├── .gitignore
├── LICENSE.md
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
├── fonts
│ ├── Nunito-Light.ttf
│ ├── Nunito-Regular.ttf
│ └── Nunito-SemiBold.ttf
├── images
│ ├── brand.svg
│ ├── favicon.png
│ ├── icons
│ │ └── x.svg
│ └── screenshots
│ │ └── app.png
├── scripts
│ ├── js
│ │ ├── Alert.js
│ │ ├── BookList.js
│ │ ├── BookStore.js
│ │ ├── Modal.js
│ │ ├── Search.js
│ │ ├── Shelf.js
│ │ └── index.js
│ └── ts
│ │ ├── Alert.ts
│ │ ├── BookList.ts
│ │ ├── BookStore.ts
│ │ ├── Modal.ts
│ │ ├── Search.ts
│ │ ├── Shelf.ts
│ │ └── index.ts
└── styles
│ ├── css
│ ├── index.css
│ └── index.css.map
│ └── scss
│ ├── color.scss
│ ├── components
│ ├── alert.scss
│ ├── book_list.scss
│ ├── button.scss
│ ├── checkbox.scss
│ ├── form_input.scss
│ ├── modal.scss
│ ├── search_input.scss
│ └── shelf-selector.scss
│ ├── index.scss
│ ├── main.scss
│ ├── reset.scss
│ ├── sections
│ ├── footer.scss
│ └── header.scss
│ └── typography.scss
├── tsconfig.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright: (c) 2022 Eko Susilo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
BookShelf
2 |
3 | 
4 |
5 | Demo Page
6 |
7 | BookShelf is an App to manage books that separate books to 2 Shelf (Finished Read Shelf and Unfinished Read Shelf). I create this website for Dicoding Submission in Learn to Make Frontend-Web for Beginner class.
8 |
9 | ## Technology Used
10 | - HTML
11 | - SCSS
12 | - Typescript
13 | ## Get Started
14 | Because this is use ES Module so this can't be simply run by open html file directly. You must use a local server (ex: live-server extension on VSCode or package live-server from npm),
15 |
16 | For easiest way you can follow instruction below.
17 |
18 | ```bash
19 | #Clone
20 | $ git clone https://github.com/iceboy1406/bookshelf
21 |
22 | #Install required packages
23 | $ npm install
24 |
25 | #Run project
26 | $ npm run start
27 |
28 | #Or run project and watch Typescript and SCSS files
29 | $ npm run dev
30 |
31 | ```
32 |
33 | ## Author
34 | This website created by [Eko Susilo](https://github.com/iceboy1406)
35 |
36 | ## Licence
37 | BookShelf is under MIT Licence
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Book Shelf
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
43 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | © Copyright (C) 2022. Created by Eko Susilo
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bookshelf",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "src/scripts/index.js",
6 | "scripts": {
7 | "start": "live-server",
8 | "build-ts": "concurrently \"npx rimraf src/scripts/js \" \"tsc\"",
9 | "build-scss": "sass src/styles/scss/index.scss src/styles/css/index.css",
10 | "dev": "concurrently \"npx rimraf src/scripts/js \" \"tsc --watch\" \"live-server\" \"sass --watch src/styles/scss/index.scss src/styles/css/index.css\""
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "concurrently": "^7.2.1",
16 | "live-server": "^1.2.2",
17 | "rimraf": "^3.0.2",
18 | "sass": "^1.52.2",
19 | "typescript": "^4.7.2"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/fonts/Nunito-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rei1406/bookshelf/e7ed87528497ad4cc06ef3358648801e06282857/src/fonts/Nunito-Light.ttf
--------------------------------------------------------------------------------
/src/fonts/Nunito-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rei1406/bookshelf/e7ed87528497ad4cc06ef3358648801e06282857/src/fonts/Nunito-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/Nunito-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rei1406/bookshelf/e7ed87528497ad4cc06ef3358648801e06282857/src/fonts/Nunito-SemiBold.ttf
--------------------------------------------------------------------------------
/src/images/brand.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rei1406/bookshelf/e7ed87528497ad4cc06ef3358648801e06282857/src/images/favicon.png
--------------------------------------------------------------------------------
/src/images/icons/x.svg:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/images/screenshots/app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rei1406/bookshelf/e7ed87528497ad4cc06ef3358648801e06282857/src/images/screenshots/app.png
--------------------------------------------------------------------------------
/src/scripts/js/Alert.js:
--------------------------------------------------------------------------------
1 | class Alert {
2 | #theme;
3 | #message;
4 | #alertContainer = document.getElementById('alert-container');
5 | #closeButton;
6 | constructor(theme, message) {
7 | this.#theme = theme;
8 | this.#message = message;
9 | this.#init();
10 | this.#closeButton = this.#alertContainer?.querySelector('button.close-button');
11 | this.#closeButton?.addEventListener('click', () => this.hide());
12 | }
13 | #init() {
14 | if (this.#alertContainer) {
15 | this.#alertContainer.innerHTML = `
16 |
17 |
${this.#message}
18 |
19 |
21 |
23 |
24 |
25 |
26 | `;
27 | }
28 | }
29 | launch() {
30 | if (this.#alertContainer) {
31 | this.#alertContainer.classList.remove('hidden');
32 | }
33 | }
34 | hide() {
35 | if (this.#alertContainer) {
36 | this.#alertContainer.classList.add('hidden');
37 | }
38 | }
39 | }
40 | export default Alert;
41 |
--------------------------------------------------------------------------------
/src/scripts/js/BookList.js:
--------------------------------------------------------------------------------
1 | import Modal from './Modal.js';
2 | class BookList {
3 | #books;
4 | #noBookMessage;
5 | #bookListElement = document.getElementById('book-list');
6 | constructor(books, noBookMessage) {
7 | this.#books = books;
8 | this.#noBookMessage = noBookMessage;
9 | }
10 | render() {
11 | if (this.#bookListElement) {
12 | if (this.#books.length > 0) {
13 | this.#bookListElement.classList.remove('no-book');
14 | const list = this.#books
15 | .map((book) => {
16 | return `
17 |
18 |
19 |
${book.title}
20 |
Penulis : ${book.author}
21 |
Tahun terbit : ${book.year}
22 |
23 |
24 |
25 |
26 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 |
${book.isComplete
45 | ? 'Tandai Belum Selesai Dibaca'
46 | : 'Tandai Selesai Dibaca'}
47 |
48 |
49 | `;
50 | })
51 | .join('');
52 | this.#bookListElement.innerHTML = list;
53 | this.#actionHandler();
54 | }
55 | else {
56 | this.#bookListElement.classList.add('no-book');
57 | this.#bookListElement.innerHTML = `
58 | ${this.#noBookMessage}
59 | `;
60 | }
61 | }
62 | }
63 | #actionHandler() {
64 | const bookListItems = this.#bookListElement?.querySelectorAll('.book-list-item');
65 | if (bookListItems) {
66 | for (const bookListItem of bookListItems) {
67 | const bookId = parseInt(`${bookListItem.getAttribute('data-id')}`);
68 | const editButton = bookListItem.querySelector('.edit-button');
69 | const deleteButton = bookListItem.querySelector('.delete-button');
70 | const markButton = bookListItem.querySelector('.mark-button');
71 | deleteButton?.addEventListener('click', () => {
72 | const deleteConfirmationModal = new Modal('DeleteConfirmation', bookId);
73 | deleteConfirmationModal.launch();
74 | });
75 | markButton?.addEventListener('click', () => {
76 | const markConfirmationModal = new Modal('MarkConfirmation', bookId);
77 | markConfirmationModal.launch();
78 | });
79 | editButton?.addEventListener('click', () => {
80 | const editBookModal = new Modal('EditBook', bookId);
81 | editBookModal.launch();
82 | });
83 | }
84 | }
85 | }
86 | }
87 | export default BookList;
88 |
--------------------------------------------------------------------------------
/src/scripts/js/BookStore.js:
--------------------------------------------------------------------------------
1 | class BookStore {
2 | static getAll() {
3 | const currentBooks = localStorage.getItem('books');
4 | return currentBooks == null ? [] : JSON.parse(currentBooks);
5 | }
6 | static findById(id) {
7 | const currentBooks = this.getAll();
8 | const index = currentBooks.findIndex((book) => book.id === id);
9 | if (index === -1)
10 | throw Error('Buku tidak ditemukan');
11 | return { data: currentBooks[index], index };
12 | }
13 | static findByTitle(title) {
14 | const currentBooks = this.getAll();
15 | const searchedBooks = currentBooks.filter((value) => value.title.match(new RegExp(title.trim(), 'gi')));
16 | if (title.trim().length > 0)
17 | return searchedBooks;
18 | return currentBooks;
19 | }
20 | static filterUnfinishedRead(books) {
21 | return books.filter((book) => book.isComplete === false);
22 | }
23 | static filterFinishedRead(books) {
24 | return books.filter((book) => book.isComplete === true);
25 | }
26 | static moveBookToUnfinishedShelf(id) {
27 | const currentBooks = this.getAll();
28 | const searchedBook = this.findById(id);
29 | if (searchedBook.data.isComplete === false) {
30 | throw Error(`Buku ${searchedBook.data.title} sudah berada di rak belum selesai dibaca`);
31 | }
32 | else {
33 | searchedBook.data.isComplete = false;
34 | currentBooks.splice(searchedBook.index, 1, searchedBook.data);
35 | localStorage.setItem('books', JSON.stringify(currentBooks));
36 | return `Berhasil memindahkan buku ${searchedBook.data.title} ke rak belum selesai dibaca`;
37 | }
38 | }
39 | static moveBookToFinishedShelf(id) {
40 | const currentBooks = this.getAll();
41 | const searchedBook = this.findById(id);
42 | if (searchedBook.data.isComplete === true) {
43 | throw Error(`Buku ${searchedBook.data.title} sudah berada di rak selesai dibaca`);
44 | }
45 | else {
46 | searchedBook.data.isComplete = true;
47 | currentBooks.splice(searchedBook.index, 1, searchedBook.data);
48 | localStorage.setItem('books', JSON.stringify(currentBooks));
49 | return `Berhasil memindahkan buku ${searchedBook.data.title} ke rak selesai dibaca`;
50 | }
51 | }
52 | static add(newBook) {
53 | const currentBooks = this.getAll();
54 | if (currentBooks.findIndex((currentBook) => currentBook.author === newBook.author &&
55 | currentBook.title === newBook.title &&
56 | currentBook.year === newBook.year) !== -1) {
57 | throw Error(`Buku ${newBook.title} karya ${newBook.author} dan terbit tahun ${newBook.year} sudah ada di rak. Tidak bisa diduplikat.`);
58 | }
59 | else {
60 | if (isNaN(newBook.year) || newBook.year < 1) {
61 | throw Error(`Tahun terbit harus diisi dengan angka dan harus lebih besar dari 0`);
62 | }
63 | else {
64 | localStorage.setItem('books', JSON.stringify([...currentBooks, newBook]));
65 | return `Berhasil menambahkan buku ${newBook.title}`;
66 | }
67 | }
68 | }
69 | static delete(id) {
70 | const currentBooks = this.getAll();
71 | const searchedBook = this.findById(id);
72 | currentBooks.splice(searchedBook.index, 1);
73 | localStorage.setItem('books', JSON.stringify(currentBooks));
74 | return `Berhasil menghapus buku ${searchedBook.data.title} dari rak`;
75 | }
76 | static update(id, newBook) {
77 | if (isNaN(newBook.year) || newBook.year < 1) {
78 | throw Error(`Tahun terbit harus diisi dengan angka dan harus lebih besar dari 0`);
79 | }
80 | else {
81 | const currentBooks = this.getAll();
82 | const searchedBook = this.findById(id);
83 | currentBooks.splice(searchedBook.index, 1, newBook);
84 | localStorage.setItem('books', JSON.stringify(currentBooks));
85 | return `Berhasil mengubah data buku ${searchedBook.data.title}`;
86 | }
87 | }
88 | }
89 | export default BookStore;
90 |
--------------------------------------------------------------------------------
/src/scripts/js/Modal.js:
--------------------------------------------------------------------------------
1 | import Alert from './Alert.js';
2 | import BookStore from './BookStore.js';
3 | import Search from './Search.js';
4 | class Modal {
5 | #modalContainer = document.getElementById('modal-container');
6 | #form;
7 | #cancelButton;
8 | #titleField;
9 | #authorField;
10 | #yearField;
11 | #finishedReadCheckbox;
12 | #name;
13 | #id;
14 | constructor(name, id) {
15 | this.#name = name;
16 | this.#id = id;
17 | this.#init();
18 | this.#cancelButton = this.#modalContainer.querySelector('button#cancel-button');
19 | this.#form = this.#modalContainer.querySelector('form');
20 | this.#titleField = this.#modalContainer.querySelector('#title-field');
21 | this.#authorField = this.#modalContainer.querySelector('#author-field');
22 | this.#yearField = this.#modalContainer.querySelector('#year-field');
23 | this.#finishedReadCheckbox = this.#modalContainer.querySelector('#finished-read-checkbox');
24 | }
25 | #init() {
26 | switch (this.#name) {
27 | case 'AddBook':
28 | this.#initAddBookModal();
29 | break;
30 | case 'EditBook':
31 | this.#initEditBookModal();
32 | break;
33 | case 'DeleteConfirmation':
34 | this.#initDeleteConfirmationModal();
35 | break;
36 | case 'MarkConfirmation':
37 | this.#initMarkConfirmationModal();
38 | }
39 | }
40 | launch() {
41 | this.#modalContainer?.classList.remove('hidden');
42 | this.#hideEventHandler();
43 | this.#autofocusHandler();
44 | this.#formSubmitEventHandler();
45 | }
46 | hide() {
47 | this.#modalContainer?.classList.add('hidden');
48 | }
49 | #hideEventHandler() {
50 | this.#modalContainer?.addEventListener('click', (e) => {
51 | if (e.target === this.#modalContainer)
52 | this.hide();
53 | });
54 | document.body.addEventListener('keydown', (e) => {
55 | if (e.key === 'Escape') {
56 | this.hide();
57 | }
58 | });
59 | this.#cancelButton?.addEventListener('click', () => this.hide());
60 | }
61 | #autofocusHandler() {
62 | switch (this.#name) {
63 | case 'AddBook':
64 | this.#titleField?.focus();
65 | break;
66 | case 'EditBook':
67 | this.#titleField?.focus();
68 | break;
69 | }
70 | }
71 | #formSubmitEventHandler() {
72 | this.#form?.addEventListener('submit', (e) => {
73 | switch (this.#name) {
74 | case 'AddBook':
75 | this.#addBookModalActionHandler();
76 | break;
77 | case 'EditBook':
78 | this.#editBookModalActionHandler();
79 | break;
80 | case 'DeleteConfirmation':
81 | this.#deleteConfirmationModalActionHandler();
82 | break;
83 | case 'MarkConfirmation':
84 | this.#markConfirmationModalActionHandler();
85 | }
86 | e.preventDefault();
87 | Search.renderSearchedBooks();
88 | this.hide();
89 | });
90 | }
91 | #initEditBookModal() {
92 | if (this.#id) {
93 | const currentBook = BookStore.findById(this.#id).data;
94 | this.#modalContainer.innerHTML = `
95 |
96 |
Tambah Buku
97 |
124 |
125 | `;
126 | }
127 | }
128 | #initAddBookModal() {
129 | this.#modalContainer.innerHTML = `
130 |
131 |
Tambah Buku
132 |
159 |
160 | `;
161 | }
162 | #initDeleteConfirmationModal() {
163 | if (this.#id) {
164 | const bookTitle = BookStore.findById(this.#id).data.title;
165 | this.#modalContainer.innerHTML = `
166 |
167 |
Apakah anda yakin ingin menghapus buku ${bookTitle}?
168 |
172 |
173 | `;
174 | }
175 | }
176 | #initMarkConfirmationModal() {
177 | if (this.#id) {
178 | const book = BookStore.findById(this.#id).data;
179 | this.#modalContainer.innerHTML = `
180 |
181 |
Apakah anda yakin ingin memindahkan buku ${book.title} ke rak ${book.isComplete ? 'Belum Selesai Dibaca' : 'Selesai Dibaca'}?
182 |
186 |
187 | `;
188 | }
189 | }
190 | #addBookModalActionHandler() {
191 | try {
192 | if (this.#titleField &&
193 | this.#authorField &&
194 | this.#yearField &&
195 | this.#finishedReadCheckbox) {
196 | const newBook = {
197 | id: +new Date(),
198 | title: this.#titleField.value,
199 | author: this.#authorField.value,
200 | year: parseInt(this.#yearField.value),
201 | isComplete: this.#finishedReadCheckbox.checked,
202 | };
203 | const response = BookStore.add(newBook);
204 | const successAlert = new Alert('success', response);
205 | successAlert.launch();
206 | }
207 | else {
208 | throw Error('Fields null or undefined, check again');
209 | }
210 | }
211 | catch (error) {
212 | if (error instanceof Error) {
213 | const errorAlert = new Alert('danger', error.message);
214 | errorAlert.launch();
215 | }
216 | }
217 | }
218 | #editBookModalActionHandler() {
219 | try {
220 | if (this.#titleField &&
221 | this.#authorField &&
222 | this.#yearField &&
223 | this.#finishedReadCheckbox) {
224 | const newBook = {
225 | id: +new Date(),
226 | title: this.#titleField.value,
227 | author: this.#authorField.value,
228 | year: parseInt(this.#yearField.value),
229 | isComplete: this.#finishedReadCheckbox.checked,
230 | };
231 | if (this.#id) {
232 | const response = BookStore.update(this.#id, newBook);
233 | const successAlert = new Alert('success', response);
234 | successAlert.launch();
235 | }
236 | }
237 | else {
238 | throw Error('Fields null or undefined, check again');
239 | }
240 | }
241 | catch (error) {
242 | if (error instanceof Error) {
243 | const errorAlert = new Alert('danger', error.message);
244 | errorAlert.launch();
245 | }
246 | }
247 | }
248 | #deleteConfirmationModalActionHandler() {
249 | try {
250 | if (this.#id) {
251 | const response = BookStore.delete(this.#id);
252 | const successAlert = new Alert('success', response);
253 | successAlert.launch();
254 | }
255 | }
256 | catch (error) {
257 | if (error instanceof Error) {
258 | const errorAlert = new Alert('danger', error.message);
259 | errorAlert.launch();
260 | }
261 | }
262 | }
263 | #markConfirmationModalActionHandler() {
264 | try {
265 | if (this.#id) {
266 | const bookIsComplete = BookStore.findById(this.#id).data.isComplete;
267 | const response = bookIsComplete
268 | ? BookStore.moveBookToUnfinishedShelf(this.#id)
269 | : BookStore.moveBookToFinishedShelf(this.#id);
270 | const successAlert = new Alert('success', response);
271 | successAlert.launch();
272 | }
273 | }
274 | catch (error) {
275 | if (error instanceof Error) {
276 | const errorAlert = new Alert('danger', error.message);
277 | errorAlert.launch();
278 | }
279 | }
280 | }
281 | }
282 | export default Modal;
283 |
--------------------------------------------------------------------------------
/src/scripts/js/Search.js:
--------------------------------------------------------------------------------
1 | import BookList from './BookList.js';
2 | import BookStore from './BookStore.js';
3 | import Shelf from './Shelf.js';
4 | class Search {
5 | static searchInput = document.querySelector('#search-input');
6 | static get value() {
7 | if (this.searchInput !== null)
8 | return this.searchInput?.value;
9 | return '';
10 | }
11 | static get searchedBooks() {
12 | switch (Shelf.selected) {
13 | case Shelf.type.finishedRead:
14 | return BookStore.filterFinishedRead(BookStore.findByTitle(this.value));
15 | case Shelf.type.unfinishedRead:
16 | return BookStore.filterUnfinishedRead(BookStore.findByTitle(this.value));
17 | }
18 | }
19 | static renderSearchedBooks() {
20 | const allBookOnActiveShelf = (() => {
21 | switch (Shelf.selected) {
22 | case Shelf.type.finishedRead:
23 | return BookStore.filterFinishedRead(BookStore.getAll());
24 | case Shelf.type.unfinishedRead:
25 | return BookStore.filterUnfinishedRead(BookStore.getAll());
26 | }
27 | })();
28 | if (this.searchedBooks && allBookOnActiveShelf) {
29 | const noBookMessage = allBookOnActiveShelf.length > 0
30 | ? `Buku dengan judul yang mengandung ${this.value.toLowerCase()} tidak ditemukan`
31 | : `Tidak ada buku di rak ini`;
32 | const searchedBooksList = new BookList(this?.searchedBooks, noBookMessage);
33 | searchedBooksList.render();
34 | }
35 | }
36 | static inputChangeEventHandler() {
37 | this.searchInput?.addEventListener('input', () => this.renderSearchedBooks());
38 | }
39 | static inputFocusEventHandler() {
40 | const searchInputContainer = document.querySelector('.search-input-container');
41 | if (searchInputContainer instanceof HTMLLabelElement &&
42 | this.searchInput instanceof HTMLInputElement) {
43 | this.searchInput.addEventListener('focus', () => searchInputContainer.classList.add('focused'));
44 | this.searchInput.addEventListener('blur', () => searchInputContainer.classList.remove('focused'));
45 | }
46 | }
47 | }
48 | export default Search;
49 |
--------------------------------------------------------------------------------
/src/scripts/js/Shelf.js:
--------------------------------------------------------------------------------
1 | import Search from './Search.js';
2 | class Shelf {
3 | static get type() {
4 | return {
5 | unfinishedRead: 'unfinished-read',
6 | finishedRead: 'finished-read',
7 | };
8 | }
9 | static changeEventHandler() {
10 | const shelfSelectors = document.querySelectorAll('[name=shelf-selector]');
11 | for (const shelfSelector of shelfSelectors) {
12 | shelfSelector.addEventListener('change', () => Search.renderSearchedBooks());
13 | }
14 | }
15 | static get selected() {
16 | const selectedShelf = document.querySelector('[name=shelf-selector]:checked');
17 | return selectedShelf?.id;
18 | }
19 | }
20 | export default Shelf;
21 |
--------------------------------------------------------------------------------
/src/scripts/js/index.js:
--------------------------------------------------------------------------------
1 | import Shelf from './Shelf.js';
2 | import Search from './Search.js';
3 | import Modal from './Modal.js';
4 | window.addEventListener('DOMContentLoaded', () => {
5 | Search.inputFocusEventHandler();
6 | Search.inputChangeEventHandler();
7 | Shelf.changeEventHandler();
8 | Search.renderSearchedBooks();
9 | });
10 | const addBookButton = document.getElementById('add-book-button');
11 | addBookButton.addEventListener('click', () => {
12 | const addBookModal = new Modal('AddBook');
13 | addBookModal.launch();
14 | });
15 |
--------------------------------------------------------------------------------
/src/scripts/ts/Alert.ts:
--------------------------------------------------------------------------------
1 | class Alert {
2 | #theme: string
3 | #message: string
4 | #alertContainer = document.getElementById('alert-container')
5 | #closeButton: HTMLButtonElement | null | undefined
6 | constructor(theme: 'danger' | 'success', message: string) {
7 | this.#theme = theme
8 | this.#message = message
9 | this.#init()
10 | this.#closeButton = this.#alertContainer?.querySelector(
11 | 'button.close-button'
12 | )
13 | this.#closeButton?.addEventListener('click', () => this.hide())
14 | }
15 | #init() {
16 | if (this.#alertContainer) {
17 | this.#alertContainer.innerHTML = `
18 |
19 |
${this.#message}
20 |
21 |
23 |
25 |
26 |
27 |
28 | `
29 | }
30 | }
31 | launch() {
32 | if (this.#alertContainer) {
33 | this.#alertContainer.classList.remove('hidden')
34 | }
35 | }
36 | hide() {
37 | if (this.#alertContainer) {
38 | this.#alertContainer.classList.add('hidden')
39 | }
40 | }
41 | }
42 | export default Alert
43 |
--------------------------------------------------------------------------------
/src/scripts/ts/BookList.ts:
--------------------------------------------------------------------------------
1 | import BookStore, { Book } from './BookStore.js'
2 | import Modal from './Modal.js'
3 | import Shelf from './Shelf.js'
4 |
5 | class BookList {
6 | #books: Book[]
7 | #noBookMessage?: string
8 | #bookListElement = document.getElementById('book-list')
9 | constructor(books: Book[], noBookMessage?: string) {
10 | this.#books = books
11 | this.#noBookMessage = noBookMessage
12 | }
13 | render() {
14 | if (this.#bookListElement) {
15 | if (this.#books.length > 0) {
16 | this.#bookListElement.classList.remove('no-book')
17 | const list = this.#books
18 | .map((book) => {
19 | return `
20 |
21 |
22 |
${book.title}
23 |
Penulis : ${book.author}
24 |
Tahun terbit : ${book.year}
25 |
26 |
27 |
28 |
29 |
32 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
${
48 | book.isComplete
49 | ? 'Tandai Belum Selesai Dibaca'
50 | : 'Tandai Selesai Dibaca'
51 | }
52 |
53 |
54 | `
55 | })
56 | .join('')
57 | this.#bookListElement.innerHTML = list
58 | this.#actionHandler()
59 | } else {
60 | this.#bookListElement.classList.add('no-book')
61 | this.#bookListElement.innerHTML = `
62 | ${this.#noBookMessage}
63 | `
64 | }
65 | }
66 | }
67 |
68 | #actionHandler() {
69 | const bookListItems =
70 | this.#bookListElement?.querySelectorAll('.book-list-item')
71 | if (bookListItems) {
72 | for (const bookListItem of bookListItems) {
73 | const bookId = parseInt(`${bookListItem.getAttribute('data-id')}`)
74 | const editButton = bookListItem.querySelector('.edit-button')
75 | const deleteButton = bookListItem.querySelector('.delete-button')
76 | const markButton = bookListItem.querySelector('.mark-button')
77 | deleteButton?.addEventListener('click', () => {
78 | const deleteConfirmationModal = new Modal(
79 | 'DeleteConfirmation',
80 | bookId
81 | )
82 | deleteConfirmationModal.launch()
83 | })
84 | markButton?.addEventListener('click', () => {
85 | const markConfirmationModal = new Modal(
86 | 'MarkConfirmation',
87 | bookId
88 | )
89 | markConfirmationModal.launch()
90 | })
91 | editButton?.addEventListener('click', () => {
92 | const editBookModal = new Modal(
93 | 'EditBook',
94 | bookId
95 | )
96 | editBookModal.launch()
97 | })
98 | }
99 | }
100 | }
101 |
102 | }
103 | export default BookList
104 |
--------------------------------------------------------------------------------
/src/scripts/ts/BookStore.ts:
--------------------------------------------------------------------------------
1 | interface Book {
2 | id: number
3 | title: string
4 | author: string
5 | year: number
6 | isComplete: boolean
7 | }
8 | interface DataBook {
9 | index: number
10 | data: Book
11 | }
12 | class BookStore {
13 | static getAll(): Book[] {
14 | const currentBooks = localStorage.getItem('books')
15 | return currentBooks == null ? [] : JSON.parse(currentBooks)
16 | }
17 | static findById(id: number): DataBook {
18 | const currentBooks: Book[] = this.getAll()
19 | const index = currentBooks.findIndex((book) => book.id === id)
20 | if (index === -1) throw Error('Buku tidak ditemukan')
21 | return { data: currentBooks[index], index }
22 | }
23 | static findByTitle(title: string): Book[] {
24 | const currentBooks = this.getAll()
25 | const searchedBooks = currentBooks.filter((value) =>
26 | value.title.match(new RegExp(title.trim(), 'gi'))
27 | )
28 | if (title.trim().length > 0) return searchedBooks
29 | return currentBooks
30 | }
31 |
32 | static filterUnfinishedRead(books: Book[]) {
33 | return books.filter((book) => book.isComplete === false)
34 | }
35 | static filterFinishedRead(books: Book[]) {
36 | return books.filter((book) => book.isComplete === true)
37 | }
38 | static moveBookToUnfinishedShelf(id: number): string {
39 | const currentBooks: Book[] = this.getAll()
40 | const searchedBook = this.findById(id)
41 | if (searchedBook.data.isComplete === false) {
42 | throw Error(
43 | `Buku ${searchedBook.data.title} sudah berada di rak belum selesai dibaca`
44 | )
45 | } else {
46 | searchedBook.data.isComplete = false
47 | currentBooks.splice(searchedBook.index, 1, searchedBook.data)
48 | localStorage.setItem('books', JSON.stringify(currentBooks))
49 | return `Berhasil memindahkan buku ${searchedBook.data.title} ke rak belum selesai dibaca`
50 | }
51 | }
52 | static moveBookToFinishedShelf(id: number): string {
53 | const currentBooks: Book[] = this.getAll()
54 | const searchedBook = this.findById(id)
55 | if (searchedBook.data.isComplete === true) {
56 | throw Error(
57 | `Buku ${searchedBook.data.title} sudah berada di rak selesai dibaca`
58 | )
59 | } else {
60 | searchedBook.data.isComplete = true
61 | currentBooks.splice(searchedBook.index, 1, searchedBook.data)
62 | localStorage.setItem('books', JSON.stringify(currentBooks))
63 | return `Berhasil memindahkan buku ${searchedBook.data.title} ke rak selesai dibaca`
64 | }
65 | }
66 | static add(newBook: Book): string {
67 | const currentBooks: Book[] = this.getAll()
68 | if (
69 | currentBooks.findIndex(
70 | (currentBook) =>
71 | currentBook.author === newBook.author &&
72 | currentBook.title === newBook.title &&
73 | currentBook.year === newBook.year
74 | ) !== -1
75 | ) {
76 | throw Error(
77 | `Buku ${newBook.title} karya ${newBook.author} dan terbit tahun ${newBook.year} sudah ada di rak. Tidak bisa diduplikat.`
78 | )
79 | } else {
80 | if (isNaN(newBook.year) || newBook.year < 1) {
81 | throw Error(
82 | `Tahun terbit harus diisi dengan angka dan harus lebih besar dari 0`
83 | )
84 | } else {
85 | localStorage.setItem(
86 | 'books',
87 | JSON.stringify([...currentBooks, newBook])
88 | )
89 | return `Berhasil menambahkan buku ${newBook.title}`
90 | }
91 | }
92 | }
93 | static delete(id: number): string {
94 | const currentBooks: Book[] = this.getAll()
95 | const searchedBook = this.findById(id)
96 | currentBooks.splice(searchedBook.index, 1)
97 | localStorage.setItem('books', JSON.stringify(currentBooks))
98 | return `Berhasil menghapus buku ${searchedBook.data.title} dari rak`
99 | }
100 | static update(id: number, newBook: Book): string {
101 | if (isNaN(newBook.year) || newBook.year < 1) {
102 | throw Error(
103 | `Tahun terbit harus diisi dengan angka dan harus lebih besar dari 0`
104 | )
105 | } else {
106 | const currentBooks: Book[] = this.getAll()
107 | const searchedBook = this.findById(id)
108 | currentBooks.splice(searchedBook.index, 1, newBook)
109 | localStorage.setItem('books', JSON.stringify(currentBooks))
110 | return `Berhasil mengubah data buku ${searchedBook.data.title}`
111 | }
112 | }
113 | }
114 |
115 | export default BookStore
116 | export type { DataBook as OneBook, Book }
117 |
--------------------------------------------------------------------------------
/src/scripts/ts/Modal.ts:
--------------------------------------------------------------------------------
1 | import Alert from './Alert.js'
2 | import BookStore, { Book } from './BookStore.js'
3 | import Search from './Search.js'
4 | import Shelf from './Shelf.js'
5 |
6 | class Modal {
7 | #modalContainer = document.getElementById('modal-container') as HTMLDivElement
8 | #form: HTMLFormElement | null
9 | #cancelButton: HTMLButtonElement | null
10 | #titleField: HTMLInputElement | null
11 | #authorField: HTMLInputElement | null
12 | #yearField: HTMLInputElement | null
13 | #finishedReadCheckbox: HTMLInputElement | null
14 | #name: string
15 | #id?: number
16 | constructor(
17 | name: 'AddBook' | 'EditBook' | 'DeleteConfirmation' | 'MarkConfirmation',
18 | id?: number
19 | ) {
20 | this.#name = name
21 | this.#id = id
22 | this.#init()
23 | this.#cancelButton = this.#modalContainer.querySelector(
24 | 'button#cancel-button'
25 | )
26 | this.#form = this.#modalContainer.querySelector('form')
27 | this.#titleField = this.#modalContainer.querySelector('#title-field')
28 | this.#authorField = this.#modalContainer.querySelector('#author-field')
29 | this.#yearField = this.#modalContainer.querySelector('#year-field')
30 | this.#finishedReadCheckbox = this.#modalContainer.querySelector(
31 | '#finished-read-checkbox'
32 | )
33 | }
34 | #init() {
35 | switch (this.#name) {
36 | case 'AddBook':
37 | this.#initAddBookModal()
38 | break
39 | case 'EditBook':
40 | this.#initEditBookModal()
41 | break
42 | case 'DeleteConfirmation':
43 | this.#initDeleteConfirmationModal()
44 | break
45 | case 'MarkConfirmation':
46 | this.#initMarkConfirmationModal()
47 | }
48 | }
49 |
50 | launch() {
51 | this.#modalContainer?.classList.remove('hidden')
52 | this.#hideEventHandler()
53 | this.#autofocusHandler()
54 | this.#formSubmitEventHandler()
55 | }
56 |
57 | hide() {
58 | this.#modalContainer?.classList.add('hidden')
59 | }
60 |
61 | #hideEventHandler() {
62 | this.#modalContainer?.addEventListener('click', (e) => {
63 | if (e.target === this.#modalContainer) this.hide()
64 | })
65 | document.body.addEventListener('keydown', (e) => {
66 | if (e.key === 'Escape') {
67 | this.hide()
68 | }
69 | })
70 |
71 | this.#cancelButton?.addEventListener('click', () => this.hide())
72 | }
73 |
74 | #autofocusHandler() {
75 | switch (this.#name) {
76 | case 'AddBook':
77 | this.#titleField?.focus()
78 | break
79 | case 'EditBook':
80 | this.#titleField?.focus()
81 | break
82 | }
83 | }
84 |
85 | #formSubmitEventHandler() {
86 | this.#form?.addEventListener('submit', (e) => {
87 | switch (this.#name) {
88 | case 'AddBook':
89 | this.#addBookModalActionHandler()
90 | break
91 | case 'EditBook':
92 | this.#editBookModalActionHandler()
93 | break
94 | case 'DeleteConfirmation':
95 | this.#deleteConfirmationModalActionHandler()
96 | break
97 | case 'MarkConfirmation':
98 | this.#markConfirmationModalActionHandler()
99 | }
100 | e.preventDefault()
101 | Search.renderSearchedBooks()
102 | this.hide()
103 | })
104 | }
105 |
106 | #initEditBookModal() {
107 | if (this.#id) {
108 | const currentBook = BookStore.findById(this.#id).data
109 | this.#modalContainer.innerHTML = `
110 |
111 |
Tambah Buku
112 |
147 |
148 | `
149 | }
150 | }
151 | #initAddBookModal() {
152 | this.#modalContainer.innerHTML = `
153 |
154 |
Tambah Buku
155 |
182 |
183 | `
184 | }
185 | #initDeleteConfirmationModal() {
186 | if (this.#id) {
187 | const bookTitle = BookStore.findById(this.#id).data.title
188 | this.#modalContainer.innerHTML = `
189 |
190 |
Apakah anda yakin ingin menghapus buku ${bookTitle}?
191 |
195 |
196 | `
197 | }
198 | }
199 | #initMarkConfirmationModal() {
200 | if (this.#id) {
201 | const book = BookStore.findById(this.#id).data
202 | this.#modalContainer.innerHTML = `
203 |
204 |
Apakah anda yakin ingin memindahkan buku ${
205 | book.title
206 | } ke rak ${
207 | book.isComplete ? 'Belum Selesai Dibaca' : 'Selesai Dibaca'
208 | }?
209 |
213 |
214 | `
215 | }
216 | }
217 |
218 | #addBookModalActionHandler() {
219 | try {
220 | if (
221 | this.#titleField &&
222 | this.#authorField &&
223 | this.#yearField &&
224 | this.#finishedReadCheckbox
225 | ) {
226 | const newBook: Book = {
227 | id: +new Date(),
228 | title: this.#titleField.value,
229 | author: this.#authorField.value,
230 | year: parseInt(this.#yearField.value),
231 | isComplete: this.#finishedReadCheckbox.checked,
232 | }
233 | const response = BookStore.add(newBook)
234 | const successAlert = new Alert('success', response)
235 | successAlert.launch()
236 | } else {
237 | throw Error('Fields null or undefined, check again')
238 | }
239 | } catch (error) {
240 | if (error instanceof Error) {
241 | const errorAlert = new Alert('danger', error.message)
242 | errorAlert.launch()
243 | }
244 | }
245 | }
246 | #editBookModalActionHandler() {
247 | try {
248 | if (
249 | this.#titleField &&
250 | this.#authorField &&
251 | this.#yearField &&
252 | this.#finishedReadCheckbox
253 | ) {
254 | const newBook: Book = {
255 | id: +new Date(),
256 | title: this.#titleField.value,
257 | author: this.#authorField.value,
258 | year: parseInt(this.#yearField.value),
259 | isComplete: this.#finishedReadCheckbox.checked,
260 | }
261 | if (this.#id) {
262 | const response = BookStore.update(this.#id, newBook)
263 | const successAlert = new Alert('success', response)
264 | successAlert.launch()
265 | }
266 | } else {
267 | throw Error('Fields null or undefined, check again')
268 | }
269 | } catch (error) {
270 | if (error instanceof Error) {
271 | const errorAlert = new Alert('danger', error.message)
272 | errorAlert.launch()
273 | }
274 | }
275 | }
276 |
277 | #deleteConfirmationModalActionHandler() {
278 | try {
279 | if (this.#id) {
280 | const response = BookStore.delete(this.#id)
281 | const successAlert = new Alert('success', response)
282 | successAlert.launch()
283 | }
284 | } catch (error) {
285 | if (error instanceof Error) {
286 | const errorAlert = new Alert('danger', error.message)
287 | errorAlert.launch()
288 | }
289 | }
290 | }
291 | #markConfirmationModalActionHandler() {
292 | try {
293 | if (this.#id) {
294 | const bookIsComplete = BookStore.findById(this.#id).data.isComplete
295 | const response = bookIsComplete
296 | ? BookStore.moveBookToUnfinishedShelf(this.#id)
297 | : BookStore.moveBookToFinishedShelf(this.#id)
298 | const successAlert = new Alert('success', response)
299 | successAlert.launch()
300 | }
301 | } catch (error) {
302 | if (error instanceof Error) {
303 | const errorAlert = new Alert('danger', error.message)
304 | errorAlert.launch()
305 | }
306 | }
307 | }
308 | }
309 |
310 | export default Modal
311 |
--------------------------------------------------------------------------------
/src/scripts/ts/Search.ts:
--------------------------------------------------------------------------------
1 | import BookList from './BookList.js'
2 | import BookStore from './BookStore.js'
3 | import Shelf from './Shelf.js'
4 |
5 | class Search {
6 | static searchInput: HTMLInputElement | null =
7 | document.querySelector('#search-input')
8 |
9 | static get value() {
10 | if (this.searchInput !== null) return this.searchInput?.value
11 | return ''
12 | }
13 |
14 | static get searchedBooks() {
15 | switch (Shelf.selected) {
16 | case Shelf.type.finishedRead:
17 | return BookStore.filterFinishedRead(BookStore.findByTitle(this.value))
18 | case Shelf.type.unfinishedRead:
19 | return BookStore.filterUnfinishedRead(BookStore.findByTitle(this.value))
20 | }
21 | }
22 |
23 | static renderSearchedBooks() {
24 | const allBookOnActiveShelf = (() => {
25 | switch (Shelf.selected) {
26 | case Shelf.type.finishedRead:
27 | return BookStore.filterFinishedRead(BookStore.getAll())
28 | case Shelf.type.unfinishedRead:
29 | return BookStore.filterUnfinishedRead(BookStore.getAll())
30 | }
31 | })()
32 | if (this.searchedBooks && allBookOnActiveShelf) {
33 | const noBookMessage =
34 | allBookOnActiveShelf.length > 0
35 | ? `Buku dengan judul yang mengandung ${this.value.toLowerCase()} tidak ditemukan`
36 | : `Tidak ada buku di rak ini`
37 | const searchedBooksList = new BookList(this?.searchedBooks, noBookMessage)
38 | searchedBooksList.render()
39 | }
40 | }
41 |
42 | static inputChangeEventHandler() {
43 | this.searchInput?.addEventListener('input', () =>
44 | this.renderSearchedBooks()
45 | )
46 | }
47 | static inputFocusEventHandler() {
48 | const searchInputContainer: HTMLElement | null | HTMLLabelElement =
49 | document.querySelector('.search-input-container')
50 | if (
51 | searchInputContainer instanceof HTMLLabelElement &&
52 | this.searchInput instanceof HTMLInputElement
53 | ) {
54 | this.searchInput.addEventListener('focus', () =>
55 | searchInputContainer.classList.add('focused')
56 | )
57 | this.searchInput.addEventListener('blur', () =>
58 | searchInputContainer.classList.remove('focused')
59 | )
60 | }
61 | }
62 | }
63 | export default Search
64 |
--------------------------------------------------------------------------------
/src/scripts/ts/Shelf.ts:
--------------------------------------------------------------------------------
1 | import Search from './Search.js'
2 |
3 | class Shelf {
4 | static get type() {
5 | return {
6 | unfinishedRead: 'unfinished-read',
7 | finishedRead: 'finished-read',
8 | }
9 | }
10 |
11 | static changeEventHandler() {
12 | const shelfSelectors: NodeListOf =
13 | document.querySelectorAll('[name=shelf-selector]')
14 | for (const shelfSelector of shelfSelectors) {
15 | shelfSelector.addEventListener(
16 | 'change',
17 | () => Search.renderSearchedBooks()
18 | )
19 | }
20 | }
21 |
22 | static get selected() {
23 | const selectedShelf: HTMLInputElement | null = document.querySelector(
24 | '[name=shelf-selector]:checked'
25 | )
26 | return selectedShelf?.id
27 | }
28 | }
29 | export default Shelf
30 |
--------------------------------------------------------------------------------
/src/scripts/ts/index.ts:
--------------------------------------------------------------------------------
1 | import Shelf from './Shelf.js'
2 | import Search from './Search.js'
3 | import Modal from './Modal.js'
4 | window.addEventListener('DOMContentLoaded', () => {
5 | Search.inputFocusEventHandler()
6 | Search.inputChangeEventHandler()
7 | Shelf.changeEventHandler()
8 | Search.renderSearchedBooks()
9 | })
10 | const addBookButton = document.getElementById(
11 | 'add-book-button'
12 | ) as HTMLButtonElement
13 | addBookButton.addEventListener('click', () => {
14 | const addBookModal = new Modal('AddBook')
15 | addBookModal.launch()
16 | })
17 | export {}
18 |
--------------------------------------------------------------------------------
/src/styles/css/index.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;600&display=swap");
2 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
3 | /* Document
4 | ========================================================================== */
5 | /**
6 | * 1. Correct the line height in all browsers.
7 | * 2. Prevent adjustments of font size after orientation changes in iOS.
8 | */
9 | * {
10 | margin: 0;
11 | padding: 0;
12 | word-break: break-word;
13 | }
14 |
15 | html {
16 | line-height: 1.15; /* 1 */
17 | -webkit-text-size-adjust: 100%; /* 2 */
18 | }
19 |
20 | /* Sections
21 | ========================================================================== */
22 | /**
23 | * Remove the margin in all browsers.
24 | */
25 | body {
26 | margin: 0;
27 | }
28 |
29 | /**
30 | * Render the `main` element consistently in IE.
31 | */
32 | main {
33 | display: block;
34 | }
35 |
36 | /**
37 | * Correct the font size and margin on `h1` elements within `section` and
38 | * `article` contexts in Chrome, Firefox, and Safari.
39 | */
40 | h1 {
41 | font-size: 2em;
42 | }
43 |
44 | /* Grouping content
45 | ========================================================================== */
46 | /**
47 | * 1. Add the correct box sizing in Firefox.
48 | * 2. Show the overflow in Edge and IE.
49 | */
50 | hr {
51 | box-sizing: content-box; /* 1 */
52 | height: 0; /* 1 */
53 | overflow: visible; /* 2 */
54 | }
55 |
56 | /**
57 | * 1. Correct the inheritance and scaling of font size in all browsers.
58 | * 2. Correct the odd `em` font sizing in all browsers.
59 | */
60 | pre {
61 | font-family: monospace, monospace; /* 1 */
62 | font-size: 1em; /* 2 */
63 | }
64 |
65 | /* Text-level semantics
66 | ========================================================================== */
67 | /**
68 | * Remove the gray background on active links in IE 10.
69 | */
70 | a {
71 | background-color: transparent;
72 | text-decoration: none;
73 | }
74 |
75 | /**
76 | * 1. Remove the bottom border in Chrome 57-
77 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
78 | */
79 | abbr[title] {
80 | border-bottom: none; /* 1 */
81 | text-decoration: underline; /* 2 */
82 | text-decoration: underline dotted; /* 2 */
83 | }
84 |
85 | /**
86 | * Add the correct font weight in Chrome, Edge, and Safari.
87 | */
88 | b,
89 | strong {
90 | font-weight: bolder;
91 | }
92 |
93 | /**
94 | * 1. Correct the inheritance and scaling of font size in all browsers.
95 | * 2. Correct the odd `em` font sizing in all browsers.
96 | */
97 | code,
98 | kbd,
99 | samp {
100 | font-family: monospace, monospace; /* 1 */
101 | font-size: 1em; /* 2 */
102 | }
103 |
104 | /**
105 | * Add the correct font size in all browsers.
106 | */
107 | small {
108 | font-size: 80%;
109 | }
110 |
111 | /**
112 | * Prevent `sub` and `sup` elements from affecting the line height in
113 | * all browsers.
114 | */
115 | sub,
116 | sup {
117 | font-size: 75%;
118 | line-height: 0;
119 | position: relative;
120 | vertical-align: baseline;
121 | }
122 |
123 | sub {
124 | bottom: -0.25em;
125 | }
126 |
127 | sup {
128 | top: -0.5em;
129 | }
130 |
131 | /* Embedded content
132 | ========================================================================== */
133 | /**
134 | * Remove the border on images inside links in IE 10.
135 | */
136 | img {
137 | border-style: none;
138 | }
139 |
140 | /* Forms
141 | ========================================================================== */
142 | /**
143 | * 1. Change the font styles in all browsers.
144 | * 2. Remove the margin in Firefox and Safari.
145 | */
146 | button,
147 | input,
148 | optgroup,
149 | select,
150 | textarea {
151 | font-family: inherit; /* 1 */
152 | font-size: 100%; /* 1 */
153 | line-height: 1.15; /* 1 */
154 | margin: 0; /* 2 */
155 | outline: 0;
156 | border: 0;
157 | cursor: pointer;
158 | }
159 |
160 | /**
161 | * Show the overflow in IE.
162 | * 1. Show the overflow in Edge.
163 | */
164 | button,
165 | input {
166 | /* 1 */
167 | overflow: visible;
168 | }
169 |
170 | /**
171 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
172 | * 1. Remove the inheritance of text transform in Firefox.
173 | */
174 | button,
175 | select {
176 | /* 1 */
177 | text-transform: none;
178 | }
179 |
180 | /**
181 | * Correct the inability to style clickable types in iOS and Safari.
182 | */
183 | button,
184 | [type=button],
185 | [type=reset],
186 | [type=submit] {
187 | -webkit-appearance: button;
188 | }
189 |
190 | /**
191 | * Remove the inner border and padding in Firefox.
192 | */
193 | button::-moz-focus-inner,
194 | [type=button]::-moz-focus-inner,
195 | [type=reset]::-moz-focus-inner,
196 | [type=submit]::-moz-focus-inner {
197 | border-style: none;
198 | padding: 0;
199 | }
200 |
201 | /**
202 | * Restore the focus styles unset by the previous rule.
203 | */
204 | button:-moz-focusring,
205 | [type=button]:-moz-focusring,
206 | [type=reset]:-moz-focusring,
207 | [type=submit]:-moz-focusring {
208 | outline: 1px dotted ButtonText;
209 | }
210 |
211 | /**
212 | * Correct the padding in Firefox.
213 | */
214 | fieldset {
215 | padding: 0.35em 0.75em 0.625em;
216 | }
217 |
218 | /**
219 | * 1. Correct the text wrapping in Edge and IE.
220 | * 2. Correct the color inheritance from `fieldset` elements in IE.
221 | * 3. Remove the padding so developers are not caught out when they zero out
222 | * `fieldset` elements in all browsers.
223 | */
224 | legend {
225 | box-sizing: border-box; /* 1 */
226 | color: inherit; /* 2 */
227 | display: table; /* 1 */
228 | max-width: 100%; /* 1 */
229 | padding: 0; /* 3 */
230 | white-space: normal; /* 1 */
231 | }
232 |
233 | /**
234 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
235 | */
236 | progress {
237 | vertical-align: baseline;
238 | }
239 |
240 | /**
241 | * Remove the default vertical scrollbar in IE 10+.
242 | */
243 | textarea {
244 | overflow: auto;
245 | }
246 |
247 | /**
248 | * 1. Add the correct box sizing in IE 10.
249 | * 2. Remove the padding in IE 10.
250 | */
251 | [type=checkbox],
252 | [type=radio] {
253 | box-sizing: border-box; /* 1 */
254 | padding: 0; /* 2 */
255 | }
256 |
257 | /**
258 | * Correct the cursor style of increment and decrement buttons in Chrome.
259 | */
260 | [type=number]::-webkit-inner-spin-button,
261 | [type=number]::-webkit-outer-spin-button {
262 | height: auto;
263 | }
264 |
265 | /**
266 | * 1. Correct the odd appearance in Chrome and Safari.
267 | * 2. Correct the outline style in Safari.
268 | */
269 | [type=search] {
270 | -webkit-appearance: textfield; /* 1 */
271 | outline-offset: -2px; /* 2 */
272 | }
273 |
274 | /**
275 | * Remove the inner padding in Chrome and Safari on macOS.
276 | */
277 | [type=search]::-webkit-search-decoration {
278 | -webkit-appearance: none;
279 | }
280 |
281 | /**
282 | * 1. Correct the inability to style clickable types in iOS and Safari.
283 | * 2. Change font properties to `inherit` in Safari.
284 | */
285 | ::-webkit-file-upload-button {
286 | -webkit-appearance: button; /* 1 */
287 | font: inherit; /* 2 */
288 | }
289 |
290 | /* Interactive
291 | ========================================================================== */
292 | /*
293 | * Add the correct display in Edge, IE 10+, and Firefox.
294 | */
295 | details {
296 | display: block;
297 | }
298 |
299 | /*
300 | * Add the correct display in all browsers.
301 | */
302 | summary {
303 | display: list-item;
304 | }
305 |
306 | /* Misc
307 | ========================================================================== */
308 | /**
309 | * Add the correct display in IE 10+.
310 | */
311 | template {
312 | display: none;
313 | }
314 |
315 | /**
316 | * Add the correct display in IE 10.
317 | */
318 | [hidden] {
319 | display: none;
320 | }
321 |
322 | label {
323 | cursor: pointer;
324 | user-select: none;
325 | width: fit-content;
326 | }
327 |
328 | button {
329 | width: fit-content;
330 | height: fit-content;
331 | display: block;
332 | transition: all 0.3s ease;
333 | user-select: none;
334 | }
335 |
336 | * {
337 | scroll-behavior: smooth;
338 | box-sizing: border-box;
339 | }
340 |
341 | html {
342 | font-family: "Nunito", sans-serif;
343 | }
344 |
345 | body {
346 | background: #F9FAFB;
347 | overflow: hidden;
348 | width: 100vw;
349 | display: flex;
350 | flex-direction: column;
351 | height: 100vh;
352 | gap: 16px;
353 | align-items: center;
354 | padding-top: 32px;
355 | padding-left: 28px;
356 | padding-right: 28px;
357 | }
358 |
359 | main,
360 | header,
361 | footer {
362 | width: 100%;
363 | max-width: 900px;
364 | }
365 |
366 | main {
367 | flex-grow: 1;
368 | background-color: transparent;
369 | overflow-y: auto;
370 | padding-right: 8px;
371 | /* Track */
372 | /* Handle */
373 | /* Handle on hover */
374 | }
375 | main::-webkit-scrollbar {
376 | width: 8px;
377 | }
378 | main::-webkit-scrollbar-track {
379 | background: rgba(107, 114, 128, 0.15);
380 | }
381 | main::-webkit-scrollbar-thumb {
382 | background: #6B7280;
383 | border-radius: 16px;
384 | max-height: 24px;
385 | }
386 | main::-webkit-scrollbar-thumb:hover {
387 | background: #4B5563;
388 | }
389 |
390 | .shelf-selector {
391 | display: flex;
392 | padding: 8px;
393 | border-radius: 8px;
394 | background-color: #ffffff;
395 | }
396 | .shelf-selector label [name=shelf-selector] {
397 | display: none;
398 | }
399 | .shelf-selector label div {
400 | width: 100%;
401 | padding-top: 12px;
402 | padding-bottom: 12px;
403 | color: #4B5563;
404 | text-align: center;
405 | border-radius: 8px;
406 | font-size: 14px;
407 | cursor: pointer;
408 | user-select: none;
409 | }
410 | @media screen and (min-width: 500px) {
411 | .shelf-selector label div {
412 | font-size: 16px;
413 | padding-top: 14px;
414 | padding-bottom: 14px;
415 | }
416 | }
417 | .shelf-selector label.finished-read-option {
418 | flex-basis: 41.666%;
419 | }
420 | @media screen and (min-width: 414px) {
421 | .shelf-selector label.finished-read-option {
422 | flex-basis: 50%;
423 | }
424 | }
425 | .shelf-selector label.finished-read-option [name=shelf-selector]:checked ~ div {
426 | background-color: #6366F1;
427 | color: #ffffff;
428 | }
429 | .shelf-selector label.unfinished-read-option {
430 | flex-grow: 1;
431 | }
432 | .shelf-selector label.unfinished-read-option [name=shelf-selector]:checked ~ div {
433 | background-color: #6366F1;
434 | color: #ffffff;
435 | }
436 |
437 | .button {
438 | text-align: center;
439 | padding: 12px 20px;
440 | border-radius: 4px;
441 | font-size: 14px;
442 | }
443 | @media screen and (min-width: 500px) {
444 | .button {
445 | font-size: 16px;
446 | }
447 | }
448 |
449 | .icon-button {
450 | padding: 12px;
451 | border-radius: 4px;
452 | }
453 | .icon-button svg {
454 | display: block;
455 | width: 16px;
456 | height: 16px;
457 | }
458 | @media screen and (min-width: 500px) {
459 | .icon-button svg {
460 | width: 18px;
461 | height: 18px;
462 | }
463 | }
464 |
465 | .button-primary {
466 | background-color: #6366F1;
467 | color: #ffffff;
468 | box-shadow: 0px 2px 5px rgba(99, 102, 241, 0.85);
469 | }
470 | .button-primary:hover {
471 | background-color: #575bf0;
472 | box-shadow: 0px 2px 20px rgba(99, 102, 241, 0.85);
473 | }
474 | .button-primary:active {
475 | box-shadow: none;
476 | }
477 |
478 | .button-success {
479 | background-color: #10B981;
480 | color: #ffffff;
481 | box-shadow: 0px 2px 5px rgba(16, 185, 129, 0.85);
482 | }
483 | .button-success:hover {
484 | background-color: #0fad79;
485 | box-shadow: 0px 2px 20px rgba(16, 185, 129, 0.85);
486 | }
487 | .button-success:active {
488 | box-shadow: none;
489 | }
490 |
491 | .button-danger {
492 | background-color: #EF4444;
493 | color: #ffffff;
494 | box-shadow: 0px 2px 5px rgba(239, 68, 68, 0.85);
495 | }
496 | .button-danger:hover {
497 | background-color: #ee3838;
498 | box-shadow: 0px 2px 20px rgba(239, 68, 68, 0.85);
499 | }
500 | .button-danger:active {
501 | box-shadow: none;
502 | }
503 |
504 | .button-secondary {
505 | background-color: #6B7280;
506 | color: #ffffff;
507 | box-shadow: 0px 2px 5px rgba(107, 114, 128, 0.85);
508 | }
509 | .button-secondary:hover {
510 | background-color: #656c79;
511 | box-shadow: 0px 2px 20px rgba(107, 114, 128, 0.85);
512 | }
513 | .button-secondary:active {
514 | box-shadow: none;
515 | }
516 |
517 | .search-input-container {
518 | display: flex;
519 | align-items: center;
520 | gap: 12px;
521 | padding: 12px 20px;
522 | background-color: #ffffff;
523 | border-radius: 4px;
524 | border: 1px solid transparent;
525 | transition: all 0.3s ease-in-out;
526 | width: 100%;
527 | cursor: text;
528 | }
529 | @media screen and (min-width: 640px) {
530 | .search-input-container {
531 | width: unset;
532 | }
533 | }
534 | .search-input-container.focused {
535 | border: 1px solid #6366F1;
536 | }
537 | .search-input-container input {
538 | color: #4B5563;
539 | cursor: text;
540 | font-size: 14px;
541 | flex-grow: 1;
542 | background-color: transparent;
543 | }
544 | @media screen and (min-width: 500px) {
545 | .search-input-container input {
546 | font-size: 16px;
547 | }
548 | }
549 | .search-input-container input::placeholder {
550 | color: #6B7280;
551 | }
552 | .search-input-container input::-webkit-search-cancel-button {
553 | -webkit-appearance: none;
554 | width: 12px;
555 | height: 12px;
556 | background: url(../../images/icons/x.svg) no-repeat 50% 50%;
557 | cursor: pointer;
558 | }
559 |
560 | #alert-container.hidden {
561 | display: none;
562 | }
563 |
564 | .alert {
565 | display: flex;
566 | justify-content: space-between;
567 | width: 100%;
568 | gap: 8px;
569 | padding: 12px 16px;
570 | border-left: 4px solid;
571 | border-radius: 4px;
572 | }
573 | .alert .message {
574 | font-size: 16px;
575 | font-weight: 600;
576 | line-height: 24px;
577 | }
578 | .alert .close-button {
579 | display: block;
580 | height: fit-content;
581 | color: inherit;
582 | padding: 4px;
583 | border-radius: 50%;
584 | }
585 | .alert .close-button svg {
586 | width: 16px;
587 | height: 16px;
588 | display: block;
589 | }
590 | .alert.alert-success {
591 | background-color: rgba(16, 185, 129, 0.15);
592 | border-color: #10B981;
593 | color: #10B981;
594 | }
595 | .alert.alert-success .close-button {
596 | background-color: rgba(16, 185, 129, 0.15);
597 | }
598 | .alert.alert-danger {
599 | background-color: rgba(239, 68, 68, 0.15);
600 | border-color: #EF4444;
601 | color: #EF4444;
602 | }
603 | .alert.alert-danger .close-button {
604 | background-color: rgba(239, 68, 68, 0.15);
605 | }
606 |
607 | #book-list {
608 | column-count: 1;
609 | list-style-type: none;
610 | gap: 16px;
611 | }
612 | @media screen and (min-width: 768px) {
613 | #book-list {
614 | column-count: 2;
615 | }
616 | }
617 | #book-list.no-book {
618 | display: grid;
619 | place-items: center;
620 | height: 100%;
621 | }
622 | #book-list.no-book .message {
623 | text-align: center;
624 | font-weight: 400;
625 | font-size: 16px;
626 | color: #4B5563;
627 | line-height: 22px;
628 | }
629 | #book-list.no-book .message b {
630 | color: #222933;
631 | }
632 | #book-list .book-list-item {
633 | background-color: #ffffff;
634 | border-radius: 4px;
635 | padding: 24px;
636 | display: inline-flex;
637 | flex-direction: column;
638 | gap: 16px;
639 | height: fit-content;
640 | width: 100%;
641 | margin-bottom: 16px;
642 | }
643 | #book-list .book-list-item .info {
644 | display: flex;
645 | flex-direction: column;
646 | gap: 6px;
647 | }
648 | #book-list .book-list-item .info .title {
649 | font-weight: 600;
650 | font-size: 24px;
651 | color: #374151;
652 | line-height: 32px;
653 | }
654 | #book-list .book-list-item .info .author {
655 | font-weight: 400;
656 | font-size: 18px;
657 | color: #4B5563;
658 | line-height: 24px;
659 | }
660 | #book-list .book-list-item .info .published-year {
661 | font-weight: 400;
662 | font-size: 18px;
663 | color: #4B5563;
664 | line-height: 24px;
665 | }
666 | #book-list .book-list-item .actions {
667 | display: flex;
668 | gap: 8px;
669 | flex-wrap: wrap;
670 | }
671 |
672 | #modal-container {
673 | width: 100vw;
674 | height: 100vh;
675 | background-color: rgba(0, 0, 0, 0.5);
676 | position: fixed;
677 | top: 0px;
678 | left: 0px;
679 | padding: 28px;
680 | display: flex;
681 | justify-content: center;
682 | align-items: center;
683 | }
684 | #modal-container.hidden {
685 | display: none;
686 | }
687 | #modal-container .modal {
688 | background-color: #F9FAFB;
689 | width: 100%;
690 | padding: 24px;
691 | border-radius: 8px;
692 | max-width: 400px;
693 | animation-name: slide-down;
694 | animation-duration: 0.3s;
695 | animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
696 | }
697 | #modal-container .modal .title {
698 | font-weight: 600;
699 | font-size: 24px;
700 | color: #374151;
701 | line-height: 32px;
702 | }
703 | #modal-container .modal .confirmation-message {
704 | font-weight: 400;
705 | font-size: 18px;
706 | color: #4B5563;
707 | line-height: 24px;
708 | }
709 | #modal-container .modal.add-book, #modal-container .modal.edit-book {
710 | display: flex;
711 | flex-direction: column;
712 | gap: 16px;
713 | }
714 | #modal-container .modal.add-book form, #modal-container .modal.edit-book form {
715 | display: flex;
716 | flex-direction: column;
717 | gap: 8px;
718 | }
719 | #modal-container .modal.add-book form button, #modal-container .modal.edit-book form button {
720 | width: 100%;
721 | }
722 | #modal-container .modal.delete-confirmation, #modal-container .modal.mark-confirmation {
723 | display: flex;
724 | flex-direction: column;
725 | gap: 24px;
726 | }
727 | #modal-container .modal.delete-confirmation .message, #modal-container .modal.mark-confirmation .message {
728 | font-weight: 400;
729 | font-size: 20px;
730 | color: #4B5563;
731 | line-height: 28px;
732 | }
733 | #modal-container .modal.delete-confirmation form, #modal-container .modal.mark-confirmation form {
734 | margin-left: auto;
735 | display: flex;
736 | gap: 8px;
737 | }
738 |
739 | @keyframes slide-down {
740 | 0% {
741 | transform: scale(0.85) translateY(-300px);
742 | }
743 | 100% {
744 | transform: scale(1) translateY(0px);
745 | }
746 | }
747 | .input-group {
748 | display: flex;
749 | flex-direction: column;
750 | gap: 4px;
751 | }
752 | .input-group label {
753 | font-weight: 400;
754 | font-size: 16px;
755 | color: #4B5563;
756 | line-height: 22px;
757 | }
758 | .input-group input[type=text], .input-group input[type=number] {
759 | padding: 8px 16px;
760 | border-radius: 4px;
761 | font-weight: 400;
762 | font-size: 16px;
763 | color: #4B5563;
764 | line-height: 22px;
765 | border: 1px solid transparent;
766 | cursor: text;
767 | }
768 | .input-group input[type=text]:focus, .input-group input[type=number]:focus {
769 | border: 1px solid #6366F1;
770 | }
771 |
772 | .checkbox-group {
773 | display: flex;
774 | gap: 6px;
775 | align-items: center;
776 | }
777 | .checkbox-group input[type=checkbox] {
778 | display: none;
779 | }
780 | .checkbox-group input[type=checkbox]:checked ~ .checkbox {
781 | background-color: #6366F1;
782 | border: 1px solid #6366F1;
783 | color: #ffffff;
784 | }
785 | .checkbox-group .checkbox {
786 | border: 1px solid rgba(55, 65, 81, 0.35);
787 | border-radius: 4px;
788 | padding: 2px;
789 | color: transparent;
790 | }
791 | .checkbox-group .checkbox svg {
792 | display: block;
793 | width: 12px;
794 | height: 12px;
795 | }
796 | .checkbox-group .checkbox-label {
797 | font-weight: 400;
798 | font-size: 16px;
799 | color: #4B5563;
800 | line-height: 22px;
801 | }
802 |
803 | header {
804 | display: flex;
805 | flex-direction: column;
806 | align-items: flex-start;
807 | gap: 32px;
808 | }
809 | header .actions {
810 | width: 100%;
811 | display: flex;
812 | flex-direction: column;
813 | gap: 16px;
814 | }
815 | header .actions .form {
816 | display: flex;
817 | flex-direction: column;
818 | gap: 16px;
819 | }
820 | @media screen and (min-width: 640px) {
821 | header .actions .form {
822 | flex-direction: row;
823 | }
824 | }
825 | header .actions .form .search-input-container {
826 | flex-grow: 1;
827 | }
828 | header .actions .form button {
829 | width: 100%;
830 | }
831 | @media screen and (min-width: 640px) {
832 | header .actions .form button {
833 | width: fit-content;
834 | order: 2;
835 | }
836 | }
837 |
838 | footer {
839 | text-align: center;
840 | padding-top: 16px;
841 | padding-bottom: 16px;
842 | font-weight: 400;
843 | font-size: 16px;
844 | color: #4B5563;
845 | line-height: 22px;
846 | }
847 |
848 | /*# sourceMappingURL=index.css.map */
849 |
--------------------------------------------------------------------------------
/src/styles/css/index.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../scss/main.scss","../scss/reset.scss","../scss/color.scss","../scss/components/shelf-selector.scss","../scss/components/button.scss","../scss/components/search_input.scss","../scss/components/alert.scss","../scss/components/book_list.scss","../scss/typography.scss","../scss/components/modal.scss","../scss/components/form_input.scss","../scss/components/checkbox.scss","../scss/sections/header.scss","../scss/sections/footer.scss"],"names":[],"mappings":"AACQ;ACDR;AAEA;AAAA;AAGA;AAAA;AAAA;AAAA;AAIA;EACE;EACA;EACA;;;AAEF;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;EAEE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;EAGE;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAAA;EAKE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;AAEE;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;AAEE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;EAEE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;ADpWF;EACE;EACA;;;AAGF;EACE;;;AAEF;EACE,YEpBQ;EFqBR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;AAAA;AAAA;EAGE;EACA;;;AAEF;EACE;EACA;EACA;EACA;AAKA;AAKA;AAOA;;AAhBA;EACE;;AAIF;EACE;;AAIF;EACE,YErDO;EFsDP;EACA;;AAIF;EACE,YE3DO;;;ACHX;EACI;EACA;EACA;EACA,kBDLI;;ACQA;EACI;;AAEJ;EACI;EACA;EACA;EACA,ODXD;ECYC;EACA;EACA;EACA;EACA;;AACA;EAVJ;IAWQ;IACA;IACA;;;AAGR;EACI;;AACA;EAFJ;IAGQ;;;AAEJ;EACI,kBD3BH;EC4BG,ODlCR;;ACqCA;EACI;;AACA;EACI,kBDlCH;ECmCG,ODzCR;;;AECR;EACE;EACA;EACA;EACA;;AACA;EALF;IAMI;;;;AAGJ;EACE;EACA;;AACA;EACE;EACA;EACA;;AACA;EAJF;IAKI;IACA;;;;AAYJ;EACE,kBARY;EASZ,OFjCI;EEkCJ;;AACA;EACE;EACA;;AAEF;EACE;;;AATJ;EACE,kBARY;EASZ,OFjCI;EEkCJ;;AACA;EACE;EACA;;AAEF;EACE;;;AATJ;EACE,kBARY;EASZ,OFjCI;EEkCJ;;AACA;EACE;EACA;;AAEF;EACE;;;AATJ;EACE,kBARY;EASZ,OFjCI;EEkCJ;;AACA;EACE;EACA;;AAEF;EACE;;;ACvCN;EACE;EACA;EACA;EACA;EACA,kBHNM;EGON;EACA;EACA;EACA;EAIA;;AAHA;EAVF;IAWI;;;AAGF;EACE;;AAEF;EACE,OHfO;EGgBP;EACA;EACA;EACA;;AACA;EANF;IAOI;;;AAEF;EACE,OHzBK;;AG2BP;EACE;EACA;EACA;EACA;EACA;;;AC7BJ;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAIF;EACE;EACA,cAtCS;EAuCT,OAvCS;;AAwCT;EACE;;AALJ;EACE;EACA,cAtCS;EAuCT,OAvCS;;AAwCT;EACE;;;ACxCR;EACE;EACA;EACA;;AACA;EAJF;IAKI;;;AAEF;EACE;EACA;EACA;;AACA;EACE;ECEJ;EACA;EACA,ONdS;EMeT;;ADHI;EACE;;AAIN;EACE,kBLtBI;EKuBJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACA;ECjCJ;EACA;EACA,ONCS;EMAT;;ADiCI;EChBJ;EACA;EACA,ONpBS;EMqBT;;ADgBI;ECnBJ;EACA;EACA,ONpBS;EMqBT;;ADoBE;EACE;EACA;EACA;;;AE9CN;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;;AAEJ;EACI,kBPfE;EOgBF;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EDvBN;EACA;EACA,ONCS;EMAT;;ACuBM;EDNN;EACA;EACA,ONpBS;EMqBT;;ACMM;EACI;EACA;EACA;;AACA;EACI;EACA;EACA;;AACA;EACI;;AAIZ;EACI;EACA;EACA;;AACA;EDvCV;EACA;EACA,ONPS;EMQT;;ACuCU;EACI;EACA;EACA;;;AAMhB;EACI;IACI;;EAEJ;IACI;;;AC/DR;EACE;EACA;EACA;;AACA;EFUA;EACA;EACA,ONdS;EMeT;;AEVA;EACE;EACA;EFKF;EACA;EACA,ONdS;EMeT;EENE;EACA;;AACA;EACI;;;ACdR;EACE;EACA;EACA;;AAEA;EACE;;AACA;EACE,kBTJO;ESKP;EACA,OTZE;;ASeN;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAGJ;EHVA;EACA;EACA,ONdS;EMeT;;;AInBF;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACA;EAJF;IAKI;;;AAEF;EACE;;AAEF;EACE;;AACA;EAFF;IAGI;IACA;;;;ACtBV;EACI;EACA;EACA;ELWF;EACA;EACA,ONdS;EMeT","file":"index.css"}
--------------------------------------------------------------------------------
/src/styles/scss/color.scss:
--------------------------------------------------------------------------------
1 | $white: #ffffff;
2 | $black: #000000;
3 | $gray-50: #F9FAFB;
4 | $gray-500: #6B7280;
5 | $gray-600: #4B5563;
6 | $gray-700: #374151;
7 | $indigo-500: #6366F1;
8 | $red-500: #EF4444;
9 | $emerald-500: #10B981;
--------------------------------------------------------------------------------
/src/styles/scss/components/alert.scss:
--------------------------------------------------------------------------------
1 | @use '../color.scss';
2 | $alert-themes: (
3 | success: color.$emerald-500,
4 | danger: color.$red-500,
5 | );
6 | #alert-container {
7 | &.hidden {
8 | display: none;
9 | }
10 | }
11 | .alert {
12 | display: flex;
13 | justify-content: space-between;
14 | width: 100%;
15 | gap: 8px;
16 | padding: 12px 16px;
17 | border-left: 4px solid;
18 | border-radius: 4px;
19 |
20 | .message {
21 | font-size: 16px;
22 | font-weight: 600;
23 | line-height: 24px;
24 | }
25 | .close-button {
26 | display: block;
27 | height: fit-content;
28 | color: inherit;
29 | padding: 4px;
30 | border-radius: 50%;
31 | svg {
32 | width: 16px;
33 | height: 16px;
34 | display: block;
35 | }
36 | }
37 | @each $key, $value in $alert-themes {
38 | &.alert-#{$key} {
39 | background-color: rgba($value, 0.15);
40 | border-color: $value;
41 | color: $value;
42 | .close-button {
43 | background-color: rgba($value, 0.15);
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/styles/scss/components/book_list.scss:
--------------------------------------------------------------------------------
1 | @use '../color.scss';
2 | @use '../typography.scss';
3 | #book-list {
4 | column-count: 1;
5 | list-style-type: none;
6 | gap: 16px;
7 | @media screen and (min-width: 768px) {
8 | column-count: 2;
9 | }
10 | &.no-book {
11 | display: grid;
12 | place-items: center;
13 | height: 100%;
14 | .message {
15 | text-align: center;
16 | @include typography.body_text;
17 | b {
18 | color: darken(color.$gray-700, 10%);
19 | }
20 | }
21 | }
22 | .book-list-item {
23 | background-color: color.$white;
24 | border-radius: 4px;
25 | padding: 24px;
26 | display: inline-flex;
27 | flex-direction: column;
28 | gap: 16px;
29 | height: fit-content;
30 | width: 100%;
31 | margin-bottom: 16px;
32 | .info {
33 | display: flex;
34 | flex-direction: column;
35 | gap: 6px;
36 | .title {
37 | @include typography.heading_text;
38 | }
39 | .author {
40 | @include typography.body_text_medium;
41 | }
42 | .published-year {
43 | @include typography.body_text_medium;
44 | }
45 | }
46 | .actions {
47 | display: flex;
48 | gap: 8px;
49 | flex-wrap: wrap;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/styles/scss/components/button.scss:
--------------------------------------------------------------------------------
1 | @use '../color.scss';
2 | .button {
3 | text-align: center;
4 | padding: 12px 20px;
5 | border-radius: 4px;
6 | font-size: 14px;
7 | @media screen and (min-width: 500px) {
8 | font-size: 16px;
9 | }
10 | }
11 | .icon-button {
12 | padding: 12px;
13 | border-radius: 4px;
14 | svg {
15 | display: block;
16 | width: 16px;
17 | height: 16px;
18 | @media screen and (min-width:500px) {
19 | width: 18px;
20 | height: 18px;
21 |
22 | }
23 | }
24 | }
25 | $button-themes: (
26 | primary: color.$indigo-500,
27 | success: color.$emerald-500,
28 | danger: color.$red-500,
29 | secondary: color.$gray-500
30 | );
31 | @each $key, $value in $button-themes {
32 | .button-#{$key} {
33 | background-color: $value;
34 | color: color.$white;
35 | box-shadow: 0px 2px 5px rgba($value, 0.85);
36 | &:hover {
37 | background-color: darken($value, 2.5%);
38 | box-shadow: 0px 2px 20px rgba($value, 0.85);
39 | }
40 | &:active {
41 | box-shadow: none;
42 | }
43 | }
44 | }
45 | // .button-primary {
46 | // background-color: color.$indigo-500;
47 | // color: color.$white;
48 | // box-shadow: 0px 2px 5px rgba(color.$indigo-500, 0.85);
49 | // &:hover {
50 | // background-color: darken(color.$indigo-500, 2.5%);
51 | // box-shadow: 0px 2px 20px rgba(color.$indigo-500, 0.85);
52 | // }
53 | // &:active {
54 | // box-shadow: none;
55 | // }
56 | // }
57 | // .button-danger {
58 | // background-color: color.$red-500;
59 | // color: color.$white;
60 | // box-shadow: 0px 2px 5px rgba(color.$red-500, 0.85);
61 | // &:hover {
62 | // background-color: darken(color.$red-500, 2.5%);
63 | // box-shadow: 0px 2px 20px rgba(color.$red-500, 0.85);
64 | // }
65 | // &:active {
66 | // box-shadow: none;
67 | // }
68 | // }
69 | // .button-success {
70 | // background-color: color.$emerald-500;
71 | // color: color.$white;
72 | // box-shadow: 0px 2px 5px rgba(color.$emerald-500, 0.85);
73 | // &:hover {
74 | // background-color: darken(color.$emerald-500, 2.5%);
75 | // box-shadow: 0px 2px 20px rgba(color.$emerald-500, 0.85);
76 | // }
77 | // &:active {
78 | // box-shadow: none;
79 | // }
80 | // }
81 |
--------------------------------------------------------------------------------
/src/styles/scss/components/checkbox.scss:
--------------------------------------------------------------------------------
1 | @use '../color.scss';
2 | @use '../typography.scss';
3 | .checkbox-group {
4 | display: flex;
5 | gap: 6px;
6 | align-items: center;
7 |
8 | input[type='checkbox'] {
9 | display: none;
10 | &:checked ~ .checkbox {
11 | background-color: color.$indigo-500;
12 | border: 1px solid color.$indigo-500;
13 | color: color.$white;
14 | }
15 | }
16 | .checkbox {
17 | border: 1px solid rgba(color.$gray-700, 0.35);
18 | border-radius: 4px;
19 | padding: 2px;
20 | color: transparent;
21 | svg {
22 | display: block;
23 | width: 12px;
24 | height: 12px;
25 | }
26 | }
27 | .checkbox-label {
28 | @include typography.body_text;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/styles/scss/components/form_input.scss:
--------------------------------------------------------------------------------
1 | @use '../color.scss';
2 | @use '../typography.scss';
3 | .input-group {
4 | display: flex;
5 | flex-direction: column;
6 | gap: 4px;
7 | label {
8 | @include typography.body_text;
9 | }
10 | input[type='text'], input[type='number'] {
11 | padding: 8px 16px;
12 | border-radius: 4px;
13 | @include typography.body_text;
14 | border: 1px solid transparent;
15 | cursor: text;
16 | &:focus {
17 | border: 1px solid color.$indigo-500;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/styles/scss/components/modal.scss:
--------------------------------------------------------------------------------
1 | @use "../color.scss";
2 | @use "../typography.scss";
3 | #modal-container {
4 | width: 100vw;
5 | height: 100vh;
6 | background-color: rgba(color.$black, .5);
7 | position: fixed;
8 | top: 0px;
9 | left: 0px;
10 | padding: 28px;
11 | display: flex;
12 | justify-content: center;
13 | align-items: center;
14 | &.hidden {
15 | display: none;
16 | }
17 | .modal {
18 | background-color: color.$gray-50;
19 | width: 100%;
20 | padding: 24px;
21 | border-radius: 8px;
22 | max-width: 400px;
23 | animation-name: slide-down;
24 | animation-duration: .3s;
25 | animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
26 | .title {
27 | @include typography.heading_text;
28 | }
29 | .confirmation-message {
30 | @include typography.body_text_medium;
31 | }
32 | &.add-book, &.edit-book {
33 | display: flex;
34 | flex-direction: column;
35 | gap: 16px;
36 | form {
37 | display: flex;
38 | flex-direction: column;
39 | gap: 8px;
40 | button {
41 | width: 100%;
42 | }
43 | }
44 | }
45 | &.delete-confirmation, &.mark-confirmation {
46 | display: flex;
47 | flex-direction: column;
48 | gap: 24px;
49 | .message {
50 | @include typography.body_text_big;
51 | }
52 | form {
53 | margin-left: auto;
54 | display: flex;
55 | gap: 8px;
56 | }
57 | }
58 | }
59 | }
60 |
61 | @keyframes slide-down {
62 | 0% {
63 | transform: scale(0.85) translateY(-300px);
64 | }
65 | 100% {
66 | transform: scale(1) translateY(0px);
67 | }
68 | }
--------------------------------------------------------------------------------
/src/styles/scss/components/search_input.scss:
--------------------------------------------------------------------------------
1 | @use '../color.scss';
2 | .search-input-container {
3 | display: flex;
4 | align-items: center;
5 | gap: 12px;
6 | padding: 12px 20px;
7 | background-color: color.$white;
8 | border-radius: 4px;
9 | border: 1px solid transparent;
10 | transition: all .3s ease-in-out;
11 | width: 100%;
12 | @media screen and (min-width: 640px) {
13 | width: unset;
14 | }
15 | cursor: text;
16 | &.focused {
17 | border: 1px solid color.$indigo-500;
18 | }
19 | input {
20 | color: color.$gray-600;
21 | cursor: text;
22 | font-size: 14px;
23 | flex-grow: 1;
24 | background-color: transparent;
25 | @media screen and (min-width: 500px) {
26 | font-size: 16px;
27 | }
28 | &::placeholder {
29 | color: color.$gray-500;
30 | }
31 | &::-webkit-search-cancel-button {
32 | -webkit-appearance: none;
33 | width: 12px;
34 | height: 12px;
35 | background: url(../../images/icons/x.svg) no-repeat 50% 50%;
36 | cursor: pointer;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/styles/scss/components/shelf-selector.scss:
--------------------------------------------------------------------------------
1 | @use "../color.scss";
2 | .shelf-selector {
3 | display: flex;
4 | padding: 8px;
5 | border-radius: 8px;
6 | background-color: color.$white;
7 | label {
8 |
9 | [name=shelf-selector] {
10 | display: none;
11 | }
12 | div {
13 | width: 100%;
14 | padding-top: 12px;
15 | padding-bottom: 12px;
16 | color: color.$gray-600;
17 | text-align: center;
18 | border-radius: 8px;
19 | font-size: 14px;
20 | cursor: pointer;
21 | user-select: none;
22 | @media screen and (min-width: 500px) {
23 | font-size: 16px;
24 | padding-top: 14px;
25 | padding-bottom: 14px;
26 | }
27 | }
28 | &.finished-read-option {
29 | flex-basis: 41.666%;
30 | @media screen and (min-width: 414px) {
31 | flex-basis: 50%;
32 | }
33 | [name=shelf-selector]:checked ~ div {
34 | background-color: color.$indigo-500;
35 | color: color.$white;
36 | }
37 | }
38 | &.unfinished-read-option {
39 | flex-grow: 1;
40 | [name=shelf-selector]:checked ~ div {
41 | background-color: color.$indigo-500;
42 | color: color.$white;
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/styles/scss/index.scss:
--------------------------------------------------------------------------------
1 | @use './reset.scss';
2 | @use './main.scss';
3 |
4 | @use 'components/shelf-selector.scss';
5 | @use 'components/button.scss';
6 | @use 'components/search_input.scss';
7 | @use 'components/alert.scss';
8 | @use 'components/book_list.scss';
9 | @use 'components/modal.scss';
10 | @use 'components/form_input.scss';
11 | @use 'components/checkbox.scss';
12 | @use 'sections/header.scss';
13 | @use 'sections/footer.scss';
14 |
--------------------------------------------------------------------------------
/src/styles/scss/main.scss:
--------------------------------------------------------------------------------
1 | @use 'color';
2 | @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600&display=swap');
3 | // Local font - uncomment if you want to use
4 | // @font-face {
5 | // font-family: 'Nunito';
6 | // src: url('../../fonts/Nunito-Regular.ttf');
7 | // font-weight: 400;
8 | // }
9 | // @font-face {
10 | // font-family: 'Nunito';
11 | // src: url('../../fonts/Nunito-SemiBold.ttf');
12 | // font-weight: 600;
13 | // }
14 | * {
15 | scroll-behavior: smooth;
16 | box-sizing: border-box;
17 | }
18 |
19 | html {
20 | font-family: 'Nunito', sans-serif;
21 | }
22 | body {
23 | background: color.$gray-50;
24 | overflow: hidden;
25 | width: 100vw;
26 | display: flex;
27 | flex-direction: column;
28 | height: 100vh;
29 | gap: 16px;
30 | align-items: center;
31 | padding-top: 32px;
32 | padding-left: 28px;
33 | padding-right: 28px;
34 | }
35 | main,
36 | header,
37 | footer {
38 | width: 100%;
39 | max-width: 900px;
40 | }
41 | main {
42 | flex-grow: 1;
43 | background-color: transparent;
44 | overflow-y: auto;
45 | padding-right: 8px;
46 | &::-webkit-scrollbar {
47 | width: 8px;
48 | }
49 |
50 | /* Track */
51 | &::-webkit-scrollbar-track {
52 | background: rgba(color.$gray-500, 0.15);
53 | }
54 |
55 | /* Handle */
56 | &::-webkit-scrollbar-thumb {
57 | background: color.$gray-500;
58 | border-radius: 16px;
59 | max-height: 24px;
60 | }
61 |
62 | /* Handle on hover */
63 | &::-webkit-scrollbar-thumb:hover {
64 | background: color.$gray-600;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/styles/scss/reset.scss:
--------------------------------------------------------------------------------
1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /* Document
4 | ========================================================================== */
5 |
6 | /**
7 | * 1. Correct the line height in all browsers.
8 | * 2. Prevent adjustments of font size after orientation changes in iOS.
9 | */
10 | * {
11 | margin: 0;
12 | padding: 0;
13 | word-break: break-word;
14 | }
15 | html {
16 | line-height: 1.15; /* 1 */
17 | -webkit-text-size-adjust: 100%; /* 2 */
18 | }
19 |
20 | /* Sections
21 | ========================================================================== */
22 |
23 | /**
24 | * Remove the margin in all browsers.
25 | */
26 |
27 | body {
28 | margin: 0;
29 | }
30 |
31 | /**
32 | * Render the `main` element consistently in IE.
33 | */
34 |
35 | main {
36 | display: block;
37 | }
38 |
39 | /**
40 | * Correct the font size and margin on `h1` elements within `section` and
41 | * `article` contexts in Chrome, Firefox, and Safari.
42 | */
43 |
44 | h1 {
45 | font-size: 2em;
46 | }
47 |
48 | /* Grouping content
49 | ========================================================================== */
50 |
51 | /**
52 | * 1. Add the correct box sizing in Firefox.
53 | * 2. Show the overflow in Edge and IE.
54 | */
55 |
56 | hr {
57 | box-sizing: content-box; /* 1 */
58 | height: 0; /* 1 */
59 | overflow: visible; /* 2 */
60 | }
61 |
62 | /**
63 | * 1. Correct the inheritance and scaling of font size in all browsers.
64 | * 2. Correct the odd `em` font sizing in all browsers.
65 | */
66 |
67 | pre {
68 | font-family: monospace, monospace; /* 1 */
69 | font-size: 1em; /* 2 */
70 | }
71 |
72 | /* Text-level semantics
73 | ========================================================================== */
74 |
75 | /**
76 | * Remove the gray background on active links in IE 10.
77 | */
78 |
79 | a {
80 | background-color: transparent;
81 | text-decoration: none;
82 | }
83 |
84 | /**
85 | * 1. Remove the bottom border in Chrome 57-
86 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
87 | */
88 |
89 | abbr[title] {
90 | border-bottom: none; /* 1 */
91 | text-decoration: underline; /* 2 */
92 | text-decoration: underline dotted; /* 2 */
93 | }
94 |
95 | /**
96 | * Add the correct font weight in Chrome, Edge, and Safari.
97 | */
98 |
99 | b,
100 | strong {
101 | font-weight: bolder;
102 | }
103 |
104 | /**
105 | * 1. Correct the inheritance and scaling of font size in all browsers.
106 | * 2. Correct the odd `em` font sizing in all browsers.
107 | */
108 |
109 | code,
110 | kbd,
111 | samp {
112 | font-family: monospace, monospace; /* 1 */
113 | font-size: 1em; /* 2 */
114 | }
115 |
116 | /**
117 | * Add the correct font size in all browsers.
118 | */
119 |
120 | small {
121 | font-size: 80%;
122 | }
123 |
124 | /**
125 | * Prevent `sub` and `sup` elements from affecting the line height in
126 | * all browsers.
127 | */
128 |
129 | sub,
130 | sup {
131 | font-size: 75%;
132 | line-height: 0;
133 | position: relative;
134 | vertical-align: baseline;
135 | }
136 |
137 | sub {
138 | bottom: -0.25em;
139 | }
140 |
141 | sup {
142 | top: -0.5em;
143 | }
144 |
145 | /* Embedded content
146 | ========================================================================== */
147 |
148 | /**
149 | * Remove the border on images inside links in IE 10.
150 | */
151 |
152 | img {
153 | border-style: none;
154 | }
155 |
156 | /* Forms
157 | ========================================================================== */
158 |
159 | /**
160 | * 1. Change the font styles in all browsers.
161 | * 2. Remove the margin in Firefox and Safari.
162 | */
163 |
164 | button,
165 | input,
166 | optgroup,
167 | select,
168 | textarea {
169 | font-family: inherit; /* 1 */
170 | font-size: 100%; /* 1 */
171 | line-height: 1.15; /* 1 */
172 | margin: 0; /* 2 */
173 | outline: 0;
174 | border: 0;
175 | cursor: pointer;
176 | }
177 |
178 | /**
179 | * Show the overflow in IE.
180 | * 1. Show the overflow in Edge.
181 | */
182 |
183 | button,
184 | input {
185 | /* 1 */
186 | overflow: visible;
187 | }
188 |
189 | /**
190 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
191 | * 1. Remove the inheritance of text transform in Firefox.
192 | */
193 |
194 | button,
195 | select {
196 | /* 1 */
197 | text-transform: none;
198 | }
199 |
200 | /**
201 | * Correct the inability to style clickable types in iOS and Safari.
202 | */
203 |
204 | button,
205 | [type='button'],
206 | [type='reset'],
207 | [type='submit'] {
208 | -webkit-appearance: button;
209 | }
210 |
211 | /**
212 | * Remove the inner border and padding in Firefox.
213 | */
214 |
215 | button::-moz-focus-inner,
216 | [type='button']::-moz-focus-inner,
217 | [type='reset']::-moz-focus-inner,
218 | [type='submit']::-moz-focus-inner {
219 | border-style: none;
220 | padding: 0;
221 | }
222 |
223 | /**
224 | * Restore the focus styles unset by the previous rule.
225 | */
226 |
227 | button:-moz-focusring,
228 | [type='button']:-moz-focusring,
229 | [type='reset']:-moz-focusring,
230 | [type='submit']:-moz-focusring {
231 | outline: 1px dotted ButtonText;
232 | }
233 |
234 | /**
235 | * Correct the padding in Firefox.
236 | */
237 |
238 | fieldset {
239 | padding: 0.35em 0.75em 0.625em;
240 | }
241 |
242 | /**
243 | * 1. Correct the text wrapping in Edge and IE.
244 | * 2. Correct the color inheritance from `fieldset` elements in IE.
245 | * 3. Remove the padding so developers are not caught out when they zero out
246 | * `fieldset` elements in all browsers.
247 | */
248 |
249 | legend {
250 | box-sizing: border-box; /* 1 */
251 | color: inherit; /* 2 */
252 | display: table; /* 1 */
253 | max-width: 100%; /* 1 */
254 | padding: 0; /* 3 */
255 | white-space: normal; /* 1 */
256 | }
257 |
258 | /**
259 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
260 | */
261 |
262 | progress {
263 | vertical-align: baseline;
264 | }
265 |
266 | /**
267 | * Remove the default vertical scrollbar in IE 10+.
268 | */
269 |
270 | textarea {
271 | overflow: auto;
272 | }
273 |
274 | /**
275 | * 1. Add the correct box sizing in IE 10.
276 | * 2. Remove the padding in IE 10.
277 | */
278 |
279 | [type='checkbox'],
280 | [type='radio'] {
281 | box-sizing: border-box; /* 1 */
282 | padding: 0; /* 2 */
283 | }
284 |
285 | /**
286 | * Correct the cursor style of increment and decrement buttons in Chrome.
287 | */
288 |
289 | [type='number']::-webkit-inner-spin-button,
290 | [type='number']::-webkit-outer-spin-button {
291 | height: auto;
292 | }
293 |
294 | /**
295 | * 1. Correct the odd appearance in Chrome and Safari.
296 | * 2. Correct the outline style in Safari.
297 | */
298 |
299 | [type='search'] {
300 | -webkit-appearance: textfield; /* 1 */
301 | outline-offset: -2px; /* 2 */
302 | }
303 |
304 | /**
305 | * Remove the inner padding in Chrome and Safari on macOS.
306 | */
307 |
308 | [type='search']::-webkit-search-decoration {
309 | -webkit-appearance: none;
310 | }
311 |
312 | /**
313 | * 1. Correct the inability to style clickable types in iOS and Safari.
314 | * 2. Change font properties to `inherit` in Safari.
315 | */
316 |
317 | ::-webkit-file-upload-button {
318 | -webkit-appearance: button; /* 1 */
319 | font: inherit; /* 2 */
320 | }
321 |
322 | /* Interactive
323 | ========================================================================== */
324 |
325 | /*
326 | * Add the correct display in Edge, IE 10+, and Firefox.
327 | */
328 |
329 | details {
330 | display: block;
331 | }
332 |
333 | /*
334 | * Add the correct display in all browsers.
335 | */
336 |
337 | summary {
338 | display: list-item;
339 | }
340 |
341 | /* Misc
342 | ========================================================================== */
343 |
344 | /**
345 | * Add the correct display in IE 10+.
346 | */
347 |
348 | template {
349 | display: none;
350 | }
351 |
352 | /**
353 | * Add the correct display in IE 10.
354 | */
355 |
356 | [hidden] {
357 | display: none;
358 | }
359 |
360 | label {
361 | cursor: pointer;
362 | user-select: none;
363 | width: fit-content;
364 | }
365 | button {
366 | width: fit-content;
367 | height: fit-content;
368 | display: block;
369 | transition: all 0.3s ease;
370 | user-select: none;
371 | }
372 |
--------------------------------------------------------------------------------
/src/styles/scss/sections/footer.scss:
--------------------------------------------------------------------------------
1 | @use "../color.scss";
2 | @use "../typography.scss";
3 | footer {
4 | text-align: center;
5 | padding-top: 16px;
6 | padding-bottom: 16px;
7 | @include typography.body_text;
8 | }
--------------------------------------------------------------------------------
/src/styles/scss/sections/header.scss:
--------------------------------------------------------------------------------
1 | header {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: flex-start;
5 | gap: 32px;
6 | .actions {
7 | width: 100%;
8 | display: flex;
9 | flex-direction: column;
10 | gap: 16px;
11 | .form {
12 | display: flex;
13 | flex-direction: column;
14 | gap: 16px;
15 | @media screen and (min-width: 640px) {
16 | flex-direction: row;
17 | }
18 | .search-input-container {
19 | flex-grow: 1;
20 | }
21 | button {
22 | width: 100%;
23 | @media screen and (min-width: 640px) {
24 | width: fit-content;
25 | order: 2;
26 | }
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/styles/scss/typography.scss:
--------------------------------------------------------------------------------
1 | @use 'color';
2 | @mixin heading_text {
3 | font-weight: 600;
4 | font-size: 24px;
5 | color: color.$gray-700;
6 | line-height: 32px;
7 | }
8 |
9 | @mixin body_text_big {
10 | font-weight: 400;
11 | font-size: 20px;
12 | color: color.$gray-600;
13 | line-height: 28px;
14 | }
15 |
16 | @mixin body_text {
17 | font-weight: 400;
18 | font-size: 16px;
19 | color: color.$gray-600;
20 | line-height: 22px;
21 | }
22 | @mixin body_text_medium {
23 | font-weight: 400;
24 | font-size: 18px;
25 | color: color.$gray-600;
26 | line-height: 24px;
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Enable incremental compilation */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 |
26 | /* Modules */
27 | "module": "ES2022", /* Specify what module code is generated. */
28 | "rootDir": "./src/scripts/ts", /* Specify the root folder within your source files. */
29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
36 | // "resolveJsonModule": true, /* Enable importing .json files */
37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */
38 |
39 | /* JavaScript Support */
40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
43 |
44 | /* Emit */
45 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
50 | "outDir": "./src/scripts/js", /* Specify an output folder for all emitted files. */
51 | // "removeComments": true, /* Disable emitting comments. */
52 | // "noEmit": true, /* Disable emitting files from a compilation. */
53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
61 | // "newLine": "crlf", /* Set the newline character for emitting files. */
62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
68 |
69 | /* Interop Constraints */
70 | "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
72 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
74 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
75 |
76 | /* Type Checking */
77 | "strict": true, /* Enable all strict type-checking options. */
78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
96 |
97 | /* Completeness */
98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
100 | },
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "accepts@~1.3.4":
6 | "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="
7 | "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz"
8 | "version" "1.3.8"
9 | dependencies:
10 | "mime-types" "~2.1.34"
11 | "negotiator" "0.6.3"
12 |
13 | "ansi-regex@^5.0.1":
14 | "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
15 | "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz"
16 | "version" "5.0.1"
17 |
18 | "ansi-styles@^4.0.0", "ansi-styles@^4.1.0":
19 | "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="
20 | "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
21 | "version" "4.3.0"
22 | dependencies:
23 | "color-convert" "^2.0.1"
24 |
25 | "anymatch@^2.0.0":
26 | "integrity" "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw=="
27 | "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz"
28 | "version" "2.0.0"
29 | dependencies:
30 | "micromatch" "^3.1.4"
31 | "normalize-path" "^2.1.1"
32 |
33 | "anymatch@~3.1.2":
34 | "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg=="
35 | "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz"
36 | "version" "3.1.2"
37 | dependencies:
38 | "normalize-path" "^3.0.0"
39 | "picomatch" "^2.0.4"
40 |
41 | "apache-crypt@^1.1.2":
42 | "integrity" "sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg=="
43 | "resolved" "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.5.tgz"
44 | "version" "1.2.5"
45 | dependencies:
46 | "unix-crypt-td-js" "^1.1.4"
47 |
48 | "apache-md5@^1.0.6":
49 | "integrity" "sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw=="
50 | "resolved" "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.7.tgz"
51 | "version" "1.1.7"
52 |
53 | "arr-diff@^4.0.0":
54 | "integrity" "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA=="
55 | "resolved" "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz"
56 | "version" "4.0.0"
57 |
58 | "arr-flatten@^1.1.0":
59 | "integrity" "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
60 | "resolved" "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz"
61 | "version" "1.1.0"
62 |
63 | "arr-union@^3.1.0":
64 | "integrity" "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q=="
65 | "resolved" "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz"
66 | "version" "3.1.0"
67 |
68 | "array-unique@^0.3.2":
69 | "integrity" "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ=="
70 | "resolved" "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz"
71 | "version" "0.3.2"
72 |
73 | "assign-symbols@^1.0.0":
74 | "integrity" "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="
75 | "resolved" "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz"
76 | "version" "1.0.0"
77 |
78 | "async-each@^1.0.1":
79 | "integrity" "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
80 | "resolved" "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz"
81 | "version" "1.0.3"
82 |
83 | "atob@^2.1.2":
84 | "integrity" "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
85 | "resolved" "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz"
86 | "version" "2.1.2"
87 |
88 | "balanced-match@^1.0.0":
89 | "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
90 | "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
91 | "version" "1.0.2"
92 |
93 | "base@^0.11.1":
94 | "integrity" "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg=="
95 | "resolved" "https://registry.npmjs.org/base/-/base-0.11.2.tgz"
96 | "version" "0.11.2"
97 | dependencies:
98 | "cache-base" "^1.0.1"
99 | "class-utils" "^0.3.5"
100 | "component-emitter" "^1.2.1"
101 | "define-property" "^1.0.0"
102 | "isobject" "^3.0.1"
103 | "mixin-deep" "^1.2.0"
104 | "pascalcase" "^0.1.1"
105 |
106 | "basic-auth@~2.0.1":
107 | "integrity" "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg=="
108 | "resolved" "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz"
109 | "version" "2.0.1"
110 | dependencies:
111 | "safe-buffer" "5.1.2"
112 |
113 | "batch@0.6.1":
114 | "integrity" "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw=="
115 | "resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz"
116 | "version" "0.6.1"
117 |
118 | "bcryptjs@^2.3.0":
119 | "integrity" "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
120 | "resolved" "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz"
121 | "version" "2.4.3"
122 |
123 | "binary-extensions@^1.0.0":
124 | "integrity" "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
125 | "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz"
126 | "version" "1.13.1"
127 |
128 | "binary-extensions@^2.0.0":
129 | "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
130 | "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
131 | "version" "2.2.0"
132 |
133 | "brace-expansion@^1.1.7":
134 | "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="
135 | "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
136 | "version" "1.1.11"
137 | dependencies:
138 | "balanced-match" "^1.0.0"
139 | "concat-map" "0.0.1"
140 |
141 | "braces@^2.3.1", "braces@^2.3.2":
142 | "integrity" "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w=="
143 | "resolved" "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz"
144 | "version" "2.3.2"
145 | dependencies:
146 | "arr-flatten" "^1.1.0"
147 | "array-unique" "^0.3.2"
148 | "extend-shallow" "^2.0.1"
149 | "fill-range" "^4.0.0"
150 | "isobject" "^3.0.1"
151 | "repeat-element" "^1.1.2"
152 | "snapdragon" "^0.8.1"
153 | "snapdragon-node" "^2.0.1"
154 | "split-string" "^3.0.2"
155 | "to-regex" "^3.0.1"
156 |
157 | "braces@~3.0.2":
158 | "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A=="
159 | "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
160 | "version" "3.0.2"
161 | dependencies:
162 | "fill-range" "^7.0.1"
163 |
164 | "cache-base@^1.0.1":
165 | "integrity" "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ=="
166 | "resolved" "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz"
167 | "version" "1.0.1"
168 | dependencies:
169 | "collection-visit" "^1.0.0"
170 | "component-emitter" "^1.2.1"
171 | "get-value" "^2.0.6"
172 | "has-value" "^1.0.0"
173 | "isobject" "^3.0.1"
174 | "set-value" "^2.0.0"
175 | "to-object-path" "^0.3.0"
176 | "union-value" "^1.0.0"
177 | "unset-value" "^1.0.0"
178 |
179 | "chalk@^4.1.0":
180 | "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="
181 | "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
182 | "version" "4.1.2"
183 | dependencies:
184 | "ansi-styles" "^4.1.0"
185 | "supports-color" "^7.1.0"
186 |
187 | "chokidar@^2.0.4":
188 | "integrity" "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg=="
189 | "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz"
190 | "version" "2.1.8"
191 | dependencies:
192 | "anymatch" "^2.0.0"
193 | "async-each" "^1.0.1"
194 | "braces" "^2.3.2"
195 | "glob-parent" "^3.1.0"
196 | "inherits" "^2.0.3"
197 | "is-binary-path" "^1.0.0"
198 | "is-glob" "^4.0.0"
199 | "normalize-path" "^3.0.0"
200 | "path-is-absolute" "^1.0.0"
201 | "readdirp" "^2.2.1"
202 | "upath" "^1.1.1"
203 | optionalDependencies:
204 | "fsevents" "^1.2.7"
205 |
206 | "chokidar@>=3.0.0 <4.0.0":
207 | "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw=="
208 | "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
209 | "version" "3.5.3"
210 | dependencies:
211 | "anymatch" "~3.1.2"
212 | "braces" "~3.0.2"
213 | "glob-parent" "~5.1.2"
214 | "is-binary-path" "~2.1.0"
215 | "is-glob" "~4.0.1"
216 | "normalize-path" "~3.0.0"
217 | "readdirp" "~3.6.0"
218 | optionalDependencies:
219 | "fsevents" "~2.3.2"
220 |
221 | "class-utils@^0.3.5":
222 | "integrity" "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg=="
223 | "resolved" "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz"
224 | "version" "0.3.6"
225 | dependencies:
226 | "arr-union" "^3.1.0"
227 | "define-property" "^0.2.5"
228 | "isobject" "^3.0.0"
229 | "static-extend" "^0.1.1"
230 |
231 | "cliui@^7.0.2":
232 | "integrity" "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="
233 | "resolved" "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz"
234 | "version" "7.0.4"
235 | dependencies:
236 | "string-width" "^4.2.0"
237 | "strip-ansi" "^6.0.0"
238 | "wrap-ansi" "^7.0.0"
239 |
240 | "collection-visit@^1.0.0":
241 | "integrity" "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw=="
242 | "resolved" "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz"
243 | "version" "1.0.0"
244 | dependencies:
245 | "map-visit" "^1.0.0"
246 | "object-visit" "^1.0.0"
247 |
248 | "color-convert@^2.0.1":
249 | "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="
250 | "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
251 | "version" "2.0.1"
252 | dependencies:
253 | "color-name" "~1.1.4"
254 |
255 | "color-name@~1.1.4":
256 | "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
257 | "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
258 | "version" "1.1.4"
259 |
260 | "colors@1.4.0":
261 | "integrity" "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
262 | "resolved" "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz"
263 | "version" "1.4.0"
264 |
265 | "component-emitter@^1.2.1":
266 | "integrity" "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
267 | "resolved" "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz"
268 | "version" "1.3.0"
269 |
270 | "concat-map@0.0.1":
271 | "integrity" "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
272 | "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
273 | "version" "0.0.1"
274 |
275 | "concurrently@^7.2.1":
276 | "integrity" "sha512-7cab/QyqipqghrVr9qZmoWbidu0nHsmxrpNqQ7r/67vfl1DWJElexehQnTH1p+87tDkihaAjM79xTZyBQh7HLw=="
277 | "resolved" "https://registry.npmjs.org/concurrently/-/concurrently-7.2.1.tgz"
278 | "version" "7.2.1"
279 | dependencies:
280 | "chalk" "^4.1.0"
281 | "date-fns" "^2.16.1"
282 | "lodash" "^4.17.21"
283 | "rxjs" "^6.6.3"
284 | "shell-quote" "^1.7.3"
285 | "spawn-command" "^0.0.2-1"
286 | "supports-color" "^8.1.0"
287 | "tree-kill" "^1.2.2"
288 | "yargs" "^17.3.1"
289 |
290 | "connect@^3.6.6":
291 | "integrity" "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="
292 | "resolved" "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz"
293 | "version" "3.7.0"
294 | dependencies:
295 | "debug" "2.6.9"
296 | "finalhandler" "1.1.2"
297 | "parseurl" "~1.3.3"
298 | "utils-merge" "1.0.1"
299 |
300 | "copy-descriptor@^0.1.0":
301 | "integrity" "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw=="
302 | "resolved" "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz"
303 | "version" "0.1.1"
304 |
305 | "core-util-is@~1.0.0":
306 | "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
307 | "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz"
308 | "version" "1.0.3"
309 |
310 | "cors@latest":
311 | "integrity" "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="
312 | "resolved" "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz"
313 | "version" "2.8.5"
314 | dependencies:
315 | "object-assign" "^4"
316 | "vary" "^1"
317 |
318 | "date-fns@^2.16.1":
319 | "integrity" "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw=="
320 | "resolved" "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz"
321 | "version" "2.28.0"
322 |
323 | "debug@^2.2.0", "debug@^2.3.3", "debug@2.6.9":
324 | "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="
325 | "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
326 | "version" "2.6.9"
327 | dependencies:
328 | "ms" "2.0.0"
329 |
330 | "decode-uri-component@^0.2.0":
331 | "integrity" "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og=="
332 | "resolved" "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz"
333 | "version" "0.2.0"
334 |
335 | "define-property@^0.2.5":
336 | "integrity" "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA=="
337 | "resolved" "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz"
338 | "version" "0.2.5"
339 | dependencies:
340 | "is-descriptor" "^0.1.0"
341 |
342 | "define-property@^1.0.0":
343 | "integrity" "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA=="
344 | "resolved" "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz"
345 | "version" "1.0.0"
346 | dependencies:
347 | "is-descriptor" "^1.0.0"
348 |
349 | "define-property@^2.0.2":
350 | "integrity" "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ=="
351 | "resolved" "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz"
352 | "version" "2.0.2"
353 | dependencies:
354 | "is-descriptor" "^1.0.2"
355 | "isobject" "^3.0.1"
356 |
357 | "depd@~1.1.2":
358 | "integrity" "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="
359 | "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz"
360 | "version" "1.1.2"
361 |
362 | "depd@~2.0.0", "depd@2.0.0":
363 | "integrity" "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
364 | "resolved" "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz"
365 | "version" "2.0.0"
366 |
367 | "destroy@1.2.0":
368 | "integrity" "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
369 | "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz"
370 | "version" "1.2.0"
371 |
372 | "duplexer@~0.1.1":
373 | "integrity" "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
374 | "resolved" "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
375 | "version" "0.1.2"
376 |
377 | "ee-first@1.1.1":
378 | "integrity" "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
379 | "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz"
380 | "version" "1.1.1"
381 |
382 | "emoji-regex@^8.0.0":
383 | "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
384 | "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
385 | "version" "8.0.0"
386 |
387 | "encodeurl@~1.0.2":
388 | "integrity" "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
389 | "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz"
390 | "version" "1.0.2"
391 |
392 | "escalade@^3.1.1":
393 | "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
394 | "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
395 | "version" "3.1.1"
396 |
397 | "escape-html@~1.0.3":
398 | "integrity" "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
399 | "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz"
400 | "version" "1.0.3"
401 |
402 | "etag@~1.8.1":
403 | "integrity" "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
404 | "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
405 | "version" "1.8.1"
406 |
407 | "event-stream@3.3.4":
408 | "integrity" "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g=="
409 | "resolved" "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz"
410 | "version" "3.3.4"
411 | dependencies:
412 | "duplexer" "~0.1.1"
413 | "from" "~0"
414 | "map-stream" "~0.1.0"
415 | "pause-stream" "0.0.11"
416 | "split" "0.3"
417 | "stream-combiner" "~0.0.4"
418 | "through" "~2.3.1"
419 |
420 | "expand-brackets@^2.1.4":
421 | "integrity" "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA=="
422 | "resolved" "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz"
423 | "version" "2.1.4"
424 | dependencies:
425 | "debug" "^2.3.3"
426 | "define-property" "^0.2.5"
427 | "extend-shallow" "^2.0.1"
428 | "posix-character-classes" "^0.1.0"
429 | "regex-not" "^1.0.0"
430 | "snapdragon" "^0.8.1"
431 | "to-regex" "^3.0.1"
432 |
433 | "extend-shallow@^2.0.1":
434 | "integrity" "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="
435 | "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz"
436 | "version" "2.0.1"
437 | dependencies:
438 | "is-extendable" "^0.1.0"
439 |
440 | "extend-shallow@^3.0.0":
441 | "integrity" "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q=="
442 | "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz"
443 | "version" "3.0.2"
444 | dependencies:
445 | "assign-symbols" "^1.0.0"
446 | "is-extendable" "^1.0.1"
447 |
448 | "extend-shallow@^3.0.2":
449 | "integrity" "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q=="
450 | "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz"
451 | "version" "3.0.2"
452 | dependencies:
453 | "assign-symbols" "^1.0.0"
454 | "is-extendable" "^1.0.1"
455 |
456 | "extglob@^2.0.4":
457 | "integrity" "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw=="
458 | "resolved" "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz"
459 | "version" "2.0.4"
460 | dependencies:
461 | "array-unique" "^0.3.2"
462 | "define-property" "^1.0.0"
463 | "expand-brackets" "^2.1.4"
464 | "extend-shallow" "^2.0.1"
465 | "fragment-cache" "^0.2.1"
466 | "regex-not" "^1.0.0"
467 | "snapdragon" "^0.8.1"
468 | "to-regex" "^3.0.1"
469 |
470 | "faye-websocket@0.11.x":
471 | "integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g=="
472 | "resolved" "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz"
473 | "version" "0.11.4"
474 | dependencies:
475 | "websocket-driver" ">=0.5.1"
476 |
477 | "fill-range@^4.0.0":
478 | "integrity" "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ=="
479 | "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz"
480 | "version" "4.0.0"
481 | dependencies:
482 | "extend-shallow" "^2.0.1"
483 | "is-number" "^3.0.0"
484 | "repeat-string" "^1.6.1"
485 | "to-regex-range" "^2.1.0"
486 |
487 | "fill-range@^7.0.1":
488 | "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ=="
489 | "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
490 | "version" "7.0.1"
491 | dependencies:
492 | "to-regex-range" "^5.0.1"
493 |
494 | "finalhandler@1.1.2":
495 | "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="
496 | "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz"
497 | "version" "1.1.2"
498 | dependencies:
499 | "debug" "2.6.9"
500 | "encodeurl" "~1.0.2"
501 | "escape-html" "~1.0.3"
502 | "on-finished" "~2.3.0"
503 | "parseurl" "~1.3.3"
504 | "statuses" "~1.5.0"
505 | "unpipe" "~1.0.0"
506 |
507 | "for-in@^1.0.2":
508 | "integrity" "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
509 | "resolved" "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz"
510 | "version" "1.0.2"
511 |
512 | "fragment-cache@^0.2.1":
513 | "integrity" "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA=="
514 | "resolved" "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz"
515 | "version" "0.2.1"
516 | dependencies:
517 | "map-cache" "^0.2.2"
518 |
519 | "fresh@0.5.2":
520 | "integrity" "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
521 | "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz"
522 | "version" "0.5.2"
523 |
524 | "from@~0":
525 | "integrity" "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="
526 | "resolved" "https://registry.npmjs.org/from/-/from-0.1.7.tgz"
527 | "version" "0.1.7"
528 |
529 | "fs.realpath@^1.0.0":
530 | "integrity" "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
531 | "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
532 | "version" "1.0.0"
533 |
534 | "get-caller-file@^2.0.5":
535 | "integrity" "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
536 | "resolved" "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz"
537 | "version" "2.0.5"
538 |
539 | "get-value@^2.0.3", "get-value@^2.0.6":
540 | "integrity" "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="
541 | "resolved" "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz"
542 | "version" "2.0.6"
543 |
544 | "glob-parent@^3.1.0":
545 | "integrity" "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA=="
546 | "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz"
547 | "version" "3.1.0"
548 | dependencies:
549 | "is-glob" "^3.1.0"
550 | "path-dirname" "^1.0.0"
551 |
552 | "glob-parent@~5.1.2":
553 | "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="
554 | "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
555 | "version" "5.1.2"
556 | dependencies:
557 | "is-glob" "^4.0.1"
558 |
559 | "glob@^7.1.3":
560 | "integrity" "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="
561 | "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
562 | "version" "7.2.3"
563 | dependencies:
564 | "fs.realpath" "^1.0.0"
565 | "inflight" "^1.0.4"
566 | "inherits" "2"
567 | "minimatch" "^3.1.1"
568 | "once" "^1.3.0"
569 | "path-is-absolute" "^1.0.0"
570 |
571 | "graceful-fs@^4.1.11":
572 | "integrity" "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
573 | "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz"
574 | "version" "4.2.10"
575 |
576 | "has-flag@^4.0.0":
577 | "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
578 | "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
579 | "version" "4.0.0"
580 |
581 | "has-value@^0.3.1":
582 | "integrity" "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q=="
583 | "resolved" "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz"
584 | "version" "0.3.1"
585 | dependencies:
586 | "get-value" "^2.0.3"
587 | "has-values" "^0.1.4"
588 | "isobject" "^2.0.0"
589 |
590 | "has-value@^1.0.0":
591 | "integrity" "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw=="
592 | "resolved" "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz"
593 | "version" "1.0.0"
594 | dependencies:
595 | "get-value" "^2.0.6"
596 | "has-values" "^1.0.0"
597 | "isobject" "^3.0.0"
598 |
599 | "has-values@^0.1.4":
600 | "integrity" "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="
601 | "resolved" "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz"
602 | "version" "0.1.4"
603 |
604 | "has-values@^1.0.0":
605 | "integrity" "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ=="
606 | "resolved" "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz"
607 | "version" "1.0.0"
608 | dependencies:
609 | "is-number" "^3.0.0"
610 | "kind-of" "^4.0.0"
611 |
612 | "http-auth@3.1.x":
613 | "integrity" "sha512-Jbx0+ejo2IOx+cRUYAGS1z6RGc6JfYUNkysZM4u4Sfk1uLlGv814F7/PIjQQAuThLdAWxb74JMGd5J8zex1VQg=="
614 | "resolved" "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz"
615 | "version" "3.1.3"
616 | dependencies:
617 | "apache-crypt" "^1.1.2"
618 | "apache-md5" "^1.0.6"
619 | "bcryptjs" "^2.3.0"
620 | "uuid" "^3.0.0"
621 |
622 | "http-errors@~1.6.2":
623 | "integrity" "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A=="
624 | "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz"
625 | "version" "1.6.3"
626 | dependencies:
627 | "depd" "~1.1.2"
628 | "inherits" "2.0.3"
629 | "setprototypeof" "1.1.0"
630 | "statuses" ">= 1.4.0 < 2"
631 |
632 | "http-errors@2.0.0":
633 | "integrity" "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="
634 | "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz"
635 | "version" "2.0.0"
636 | dependencies:
637 | "depd" "2.0.0"
638 | "inherits" "2.0.4"
639 | "setprototypeof" "1.2.0"
640 | "statuses" "2.0.1"
641 | "toidentifier" "1.0.1"
642 |
643 | "http-parser-js@>=0.5.1":
644 | "integrity" "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA=="
645 | "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz"
646 | "version" "0.5.6"
647 |
648 | "immutable@^4.0.0":
649 | "integrity" "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ=="
650 | "resolved" "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz"
651 | "version" "4.1.0"
652 |
653 | "inflight@^1.0.4":
654 | "integrity" "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="
655 | "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
656 | "version" "1.0.6"
657 | dependencies:
658 | "once" "^1.3.0"
659 | "wrappy" "1"
660 |
661 | "inherits@^2.0.3", "inherits@~2.0.3", "inherits@2", "inherits@2.0.4":
662 | "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
663 | "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
664 | "version" "2.0.4"
665 |
666 | "inherits@2.0.3":
667 | "integrity" "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
668 | "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
669 | "version" "2.0.3"
670 |
671 | "is-accessor-descriptor@^0.1.6":
672 | "integrity" "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A=="
673 | "resolved" "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz"
674 | "version" "0.1.6"
675 | dependencies:
676 | "kind-of" "^3.0.2"
677 |
678 | "is-accessor-descriptor@^1.0.0":
679 | "integrity" "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ=="
680 | "resolved" "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz"
681 | "version" "1.0.0"
682 | dependencies:
683 | "kind-of" "^6.0.0"
684 |
685 | "is-binary-path@^1.0.0":
686 | "integrity" "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q=="
687 | "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz"
688 | "version" "1.0.1"
689 | dependencies:
690 | "binary-extensions" "^1.0.0"
691 |
692 | "is-binary-path@~2.1.0":
693 | "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="
694 | "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz"
695 | "version" "2.1.0"
696 | dependencies:
697 | "binary-extensions" "^2.0.0"
698 |
699 | "is-buffer@^1.1.5":
700 | "integrity" "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
701 | "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz"
702 | "version" "1.1.6"
703 |
704 | "is-data-descriptor@^0.1.4":
705 | "integrity" "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg=="
706 | "resolved" "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz"
707 | "version" "0.1.4"
708 | dependencies:
709 | "kind-of" "^3.0.2"
710 |
711 | "is-data-descriptor@^1.0.0":
712 | "integrity" "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ=="
713 | "resolved" "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz"
714 | "version" "1.0.0"
715 | dependencies:
716 | "kind-of" "^6.0.0"
717 |
718 | "is-descriptor@^0.1.0":
719 | "integrity" "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg=="
720 | "resolved" "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz"
721 | "version" "0.1.6"
722 | dependencies:
723 | "is-accessor-descriptor" "^0.1.6"
724 | "is-data-descriptor" "^0.1.4"
725 | "kind-of" "^5.0.0"
726 |
727 | "is-descriptor@^1.0.0", "is-descriptor@^1.0.2":
728 | "integrity" "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg=="
729 | "resolved" "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz"
730 | "version" "1.0.2"
731 | dependencies:
732 | "is-accessor-descriptor" "^1.0.0"
733 | "is-data-descriptor" "^1.0.0"
734 | "kind-of" "^6.0.2"
735 |
736 | "is-extendable@^0.1.0", "is-extendable@^0.1.1":
737 | "integrity" "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="
738 | "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz"
739 | "version" "0.1.1"
740 |
741 | "is-extendable@^1.0.1":
742 | "integrity" "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="
743 | "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz"
744 | "version" "1.0.1"
745 | dependencies:
746 | "is-plain-object" "^2.0.4"
747 |
748 | "is-extglob@^2.1.0", "is-extglob@^2.1.1":
749 | "integrity" "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
750 | "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
751 | "version" "2.1.1"
752 |
753 | "is-fullwidth-code-point@^3.0.0":
754 | "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
755 | "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz"
756 | "version" "3.0.0"
757 |
758 | "is-glob@^3.1.0":
759 | "integrity" "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw=="
760 | "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz"
761 | "version" "3.1.0"
762 | dependencies:
763 | "is-extglob" "^2.1.0"
764 |
765 | "is-glob@^4.0.0", "is-glob@^4.0.1", "is-glob@~4.0.1":
766 | "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="
767 | "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
768 | "version" "4.0.3"
769 | dependencies:
770 | "is-extglob" "^2.1.1"
771 |
772 | "is-number@^3.0.0":
773 | "integrity" "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg=="
774 | "resolved" "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz"
775 | "version" "3.0.0"
776 | dependencies:
777 | "kind-of" "^3.0.2"
778 |
779 | "is-number@^7.0.0":
780 | "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
781 | "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
782 | "version" "7.0.0"
783 |
784 | "is-plain-object@^2.0.3", "is-plain-object@^2.0.4":
785 | "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="
786 | "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz"
787 | "version" "2.0.4"
788 | dependencies:
789 | "isobject" "^3.0.1"
790 |
791 | "is-windows@^1.0.2":
792 | "integrity" "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
793 | "resolved" "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz"
794 | "version" "1.0.2"
795 |
796 | "is-wsl@^1.1.0":
797 | "integrity" "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="
798 | "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz"
799 | "version" "1.1.0"
800 |
801 | "isarray@~1.0.0", "isarray@1.0.0":
802 | "integrity" "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
803 | "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
804 | "version" "1.0.0"
805 |
806 | "isobject@^2.0.0":
807 | "integrity" "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA=="
808 | "resolved" "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz"
809 | "version" "2.1.0"
810 | dependencies:
811 | "isarray" "1.0.0"
812 |
813 | "isobject@^3.0.0", "isobject@^3.0.1":
814 | "integrity" "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
815 | "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz"
816 | "version" "3.0.1"
817 |
818 | "kind-of@^3.0.2", "kind-of@^3.0.3", "kind-of@^3.2.0":
819 | "integrity" "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="
820 | "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
821 | "version" "3.2.2"
822 | dependencies:
823 | "is-buffer" "^1.1.5"
824 |
825 | "kind-of@^4.0.0":
826 | "integrity" "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw=="
827 | "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz"
828 | "version" "4.0.0"
829 | dependencies:
830 | "is-buffer" "^1.1.5"
831 |
832 | "kind-of@^5.0.0":
833 | "integrity" "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
834 | "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz"
835 | "version" "5.1.0"
836 |
837 | "kind-of@^6.0.0":
838 | "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
839 | "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz"
840 | "version" "6.0.3"
841 |
842 | "kind-of@^6.0.2":
843 | "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
844 | "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz"
845 | "version" "6.0.3"
846 |
847 | "live-server@^1.2.2":
848 | "integrity" "sha512-t28HXLjITRGoMSrCOv4eZ88viHaBVIjKjdI5PO92Vxlu+twbk6aE0t7dVIaz6ZWkjPilYFV6OSdMYl9ybN2B4w=="
849 | "resolved" "https://registry.npmjs.org/live-server/-/live-server-1.2.2.tgz"
850 | "version" "1.2.2"
851 | dependencies:
852 | "chokidar" "^2.0.4"
853 | "colors" "1.4.0"
854 | "connect" "^3.6.6"
855 | "cors" "latest"
856 | "event-stream" "3.3.4"
857 | "faye-websocket" "0.11.x"
858 | "http-auth" "3.1.x"
859 | "morgan" "^1.9.1"
860 | "object-assign" "latest"
861 | "opn" "latest"
862 | "proxy-middleware" "latest"
863 | "send" "latest"
864 | "serve-index" "^1.9.1"
865 |
866 | "lodash@^4.17.21":
867 | "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
868 | "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
869 | "version" "4.17.21"
870 |
871 | "map-cache@^0.2.2":
872 | "integrity" "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="
873 | "resolved" "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz"
874 | "version" "0.2.2"
875 |
876 | "map-stream@~0.1.0":
877 | "integrity" "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g=="
878 | "resolved" "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz"
879 | "version" "0.1.0"
880 |
881 | "map-visit@^1.0.0":
882 | "integrity" "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w=="
883 | "resolved" "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz"
884 | "version" "1.0.0"
885 | dependencies:
886 | "object-visit" "^1.0.0"
887 |
888 | "micromatch@^3.1.10", "micromatch@^3.1.4":
889 | "integrity" "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg=="
890 | "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz"
891 | "version" "3.1.10"
892 | dependencies:
893 | "arr-diff" "^4.0.0"
894 | "array-unique" "^0.3.2"
895 | "braces" "^2.3.1"
896 | "define-property" "^2.0.2"
897 | "extend-shallow" "^3.0.2"
898 | "extglob" "^2.0.4"
899 | "fragment-cache" "^0.2.1"
900 | "kind-of" "^6.0.2"
901 | "nanomatch" "^1.2.9"
902 | "object.pick" "^1.3.0"
903 | "regex-not" "^1.0.0"
904 | "snapdragon" "^0.8.1"
905 | "to-regex" "^3.0.2"
906 |
907 | "mime-db@1.52.0":
908 | "integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
909 | "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
910 | "version" "1.52.0"
911 |
912 | "mime-types@~2.1.17", "mime-types@~2.1.34":
913 | "integrity" "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="
914 | "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
915 | "version" "2.1.35"
916 | dependencies:
917 | "mime-db" "1.52.0"
918 |
919 | "mime@1.6.0":
920 | "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
921 | "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz"
922 | "version" "1.6.0"
923 |
924 | "minimatch@^3.1.1":
925 | "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="
926 | "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
927 | "version" "3.1.2"
928 | dependencies:
929 | "brace-expansion" "^1.1.7"
930 |
931 | "mixin-deep@^1.2.0":
932 | "integrity" "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA=="
933 | "resolved" "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz"
934 | "version" "1.3.2"
935 | dependencies:
936 | "for-in" "^1.0.2"
937 | "is-extendable" "^1.0.1"
938 |
939 | "morgan@^1.9.1":
940 | "integrity" "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ=="
941 | "resolved" "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz"
942 | "version" "1.10.0"
943 | dependencies:
944 | "basic-auth" "~2.0.1"
945 | "debug" "2.6.9"
946 | "depd" "~2.0.0"
947 | "on-finished" "~2.3.0"
948 | "on-headers" "~1.0.2"
949 |
950 | "ms@2.0.0":
951 | "integrity" "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
952 | "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
953 | "version" "2.0.0"
954 |
955 | "ms@2.1.3":
956 | "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
957 | "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
958 | "version" "2.1.3"
959 |
960 | "nanomatch@^1.2.9":
961 | "integrity" "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA=="
962 | "resolved" "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz"
963 | "version" "1.2.13"
964 | dependencies:
965 | "arr-diff" "^4.0.0"
966 | "array-unique" "^0.3.2"
967 | "define-property" "^2.0.2"
968 | "extend-shallow" "^3.0.2"
969 | "fragment-cache" "^0.2.1"
970 | "is-windows" "^1.0.2"
971 | "kind-of" "^6.0.2"
972 | "object.pick" "^1.3.0"
973 | "regex-not" "^1.0.0"
974 | "snapdragon" "^0.8.1"
975 | "to-regex" "^3.0.1"
976 |
977 | "negotiator@0.6.3":
978 | "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
979 | "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz"
980 | "version" "0.6.3"
981 |
982 | "normalize-path@^2.1.1":
983 | "integrity" "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="
984 | "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz"
985 | "version" "2.1.1"
986 | dependencies:
987 | "remove-trailing-separator" "^1.0.1"
988 |
989 | "normalize-path@^3.0.0", "normalize-path@~3.0.0":
990 | "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
991 | "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
992 | "version" "3.0.0"
993 |
994 | "object-assign@^4", "object-assign@latest":
995 | "integrity" "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
996 | "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
997 | "version" "4.1.1"
998 |
999 | "object-copy@^0.1.0":
1000 | "integrity" "sha1-fn2Fi3gb18mRpBupde04EnVOmYw= sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ=="
1001 | "resolved" "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz"
1002 | "version" "0.1.0"
1003 | dependencies:
1004 | "copy-descriptor" "^0.1.0"
1005 | "define-property" "^0.2.5"
1006 | "kind-of" "^3.0.3"
1007 |
1008 | "object-visit@^1.0.0":
1009 | "integrity" "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA=="
1010 | "resolved" "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz"
1011 | "version" "1.0.1"
1012 | dependencies:
1013 | "isobject" "^3.0.0"
1014 |
1015 | "object.pick@^1.3.0":
1016 | "integrity" "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ=="
1017 | "resolved" "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz"
1018 | "version" "1.3.0"
1019 | dependencies:
1020 | "isobject" "^3.0.1"
1021 |
1022 | "on-finished@~2.3.0":
1023 | "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="
1024 | "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz"
1025 | "version" "2.3.0"
1026 | dependencies:
1027 | "ee-first" "1.1.1"
1028 |
1029 | "on-finished@2.4.1":
1030 | "integrity" "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="
1031 | "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz"
1032 | "version" "2.4.1"
1033 | dependencies:
1034 | "ee-first" "1.1.1"
1035 |
1036 | "on-headers@~1.0.2":
1037 | "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
1038 | "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz"
1039 | "version" "1.0.2"
1040 |
1041 | "once@^1.3.0":
1042 | "integrity" "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="
1043 | "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
1044 | "version" "1.4.0"
1045 | dependencies:
1046 | "wrappy" "1"
1047 |
1048 | "opn@latest":
1049 | "integrity" "sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ=="
1050 | "resolved" "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz"
1051 | "version" "6.0.0"
1052 | dependencies:
1053 | "is-wsl" "^1.1.0"
1054 |
1055 | "parseurl@~1.3.2", "parseurl@~1.3.3":
1056 | "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
1057 | "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz"
1058 | "version" "1.3.3"
1059 |
1060 | "pascalcase@^0.1.1":
1061 | "integrity" "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="
1062 | "resolved" "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz"
1063 | "version" "0.1.1"
1064 |
1065 | "path-dirname@^1.0.0":
1066 | "integrity" "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q=="
1067 | "resolved" "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz"
1068 | "version" "1.0.2"
1069 |
1070 | "path-is-absolute@^1.0.0":
1071 | "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18= sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
1072 | "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
1073 | "version" "1.0.1"
1074 |
1075 | "pause-stream@0.0.11":
1076 | "integrity" "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A=="
1077 | "resolved" "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz"
1078 | "version" "0.0.11"
1079 | dependencies:
1080 | "through" "~2.3"
1081 |
1082 | "picomatch@^2.0.4", "picomatch@^2.2.1":
1083 | "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
1084 | "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
1085 | "version" "2.3.1"
1086 |
1087 | "posix-character-classes@^0.1.0":
1088 | "integrity" "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="
1089 | "resolved" "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz"
1090 | "version" "0.1.1"
1091 |
1092 | "process-nextick-args@~2.0.0":
1093 | "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
1094 | "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
1095 | "version" "2.0.1"
1096 |
1097 | "proxy-middleware@latest":
1098 | "integrity" "sha512-EGCG8SeoIRVMhsqHQUdDigB2i7qU7fCsWASwn54+nPutYO8n4q6EiwMzyfWlC+dzRFExP+kvcnDFdBDHoZBU7Q=="
1099 | "resolved" "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz"
1100 | "version" "0.15.0"
1101 |
1102 | "range-parser@~1.2.1":
1103 | "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1104 | "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz"
1105 | "version" "1.2.1"
1106 |
1107 | "readable-stream@^2.0.2":
1108 | "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw=="
1109 | "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz"
1110 | "version" "2.3.7"
1111 | dependencies:
1112 | "core-util-is" "~1.0.0"
1113 | "inherits" "~2.0.3"
1114 | "isarray" "~1.0.0"
1115 | "process-nextick-args" "~2.0.0"
1116 | "safe-buffer" "~5.1.1"
1117 | "string_decoder" "~1.1.1"
1118 | "util-deprecate" "~1.0.1"
1119 |
1120 | "readdirp@^2.2.1":
1121 | "integrity" "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ=="
1122 | "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz"
1123 | "version" "2.2.1"
1124 | dependencies:
1125 | "graceful-fs" "^4.1.11"
1126 | "micromatch" "^3.1.10"
1127 | "readable-stream" "^2.0.2"
1128 |
1129 | "readdirp@~3.6.0":
1130 | "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="
1131 | "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
1132 | "version" "3.6.0"
1133 | dependencies:
1134 | "picomatch" "^2.2.1"
1135 |
1136 | "regex-not@^1.0.0", "regex-not@^1.0.2":
1137 | "integrity" "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A=="
1138 | "resolved" "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz"
1139 | "version" "1.0.2"
1140 | dependencies:
1141 | "extend-shallow" "^3.0.2"
1142 | "safe-regex" "^1.1.0"
1143 |
1144 | "remove-trailing-separator@^1.0.1":
1145 | "integrity" "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
1146 | "resolved" "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz"
1147 | "version" "1.1.0"
1148 |
1149 | "repeat-element@^1.1.2":
1150 | "integrity" "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ=="
1151 | "resolved" "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz"
1152 | "version" "1.1.4"
1153 |
1154 | "repeat-string@^1.6.1":
1155 | "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
1156 | "resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz"
1157 | "version" "1.6.1"
1158 |
1159 | "require-directory@^2.1.1":
1160 | "integrity" "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
1161 | "resolved" "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz"
1162 | "version" "2.1.1"
1163 |
1164 | "resolve-url@^0.2.1":
1165 | "integrity" "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
1166 | "resolved" "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz"
1167 | "version" "0.2.1"
1168 |
1169 | "ret@~0.1.10":
1170 | "integrity" "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
1171 | "resolved" "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz"
1172 | "version" "0.1.15"
1173 |
1174 | "rimraf@^3.0.2":
1175 | "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="
1176 | "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz"
1177 | "version" "3.0.2"
1178 | dependencies:
1179 | "glob" "^7.1.3"
1180 |
1181 | "rxjs@^6.6.3":
1182 | "integrity" "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="
1183 | "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz"
1184 | "version" "6.6.7"
1185 | dependencies:
1186 | "tslib" "^1.9.0"
1187 |
1188 | "safe-buffer@>=5.1.0", "safe-buffer@~5.1.0", "safe-buffer@~5.1.1", "safe-buffer@5.1.2":
1189 | "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1190 | "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz"
1191 | "version" "5.1.2"
1192 |
1193 | "safe-regex@^1.1.0":
1194 | "integrity" "sha1-QKNmnzsHfR6UPURinhV91IAjvy4="
1195 | "resolved" "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz"
1196 | "version" "1.1.0"
1197 | dependencies:
1198 | "ret" "~0.1.10"
1199 |
1200 | "sass@^1.52.2":
1201 | "integrity" "sha512-mfHB2VSeFS7sZlPv9YohB9GB7yWIgQNTGniQwfQ04EoQN0wsQEv7SwpCwy/x48Af+Z3vDeFXz+iuXM3HK/phZQ=="
1202 | "resolved" "https://registry.npmjs.org/sass/-/sass-1.52.2.tgz"
1203 | "version" "1.52.2"
1204 | dependencies:
1205 | "chokidar" ">=3.0.0 <4.0.0"
1206 | "immutable" "^4.0.0"
1207 | "source-map-js" ">=0.6.2 <2.0.0"
1208 |
1209 | "send@latest":
1210 | "integrity" "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg=="
1211 | "resolved" "https://registry.npmjs.org/send/-/send-0.18.0.tgz"
1212 | "version" "0.18.0"
1213 | dependencies:
1214 | "debug" "2.6.9"
1215 | "depd" "2.0.0"
1216 | "destroy" "1.2.0"
1217 | "encodeurl" "~1.0.2"
1218 | "escape-html" "~1.0.3"
1219 | "etag" "~1.8.1"
1220 | "fresh" "0.5.2"
1221 | "http-errors" "2.0.0"
1222 | "mime" "1.6.0"
1223 | "ms" "2.1.3"
1224 | "on-finished" "2.4.1"
1225 | "range-parser" "~1.2.1"
1226 | "statuses" "2.0.1"
1227 |
1228 | "serve-index@^1.9.1":
1229 | "integrity" "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk="
1230 | "resolved" "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz"
1231 | "version" "1.9.1"
1232 | dependencies:
1233 | "accepts" "~1.3.4"
1234 | "batch" "0.6.1"
1235 | "debug" "2.6.9"
1236 | "escape-html" "~1.0.3"
1237 | "http-errors" "~1.6.2"
1238 | "mime-types" "~2.1.17"
1239 | "parseurl" "~1.3.2"
1240 |
1241 | "set-value@^2.0.0", "set-value@^2.0.1":
1242 | "integrity" "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw=="
1243 | "resolved" "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz"
1244 | "version" "2.0.1"
1245 | dependencies:
1246 | "extend-shallow" "^2.0.1"
1247 | "is-extendable" "^0.1.1"
1248 | "is-plain-object" "^2.0.3"
1249 | "split-string" "^3.0.1"
1250 |
1251 | "setprototypeof@1.1.0":
1252 | "integrity" "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
1253 | "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz"
1254 | "version" "1.1.0"
1255 |
1256 | "setprototypeof@1.2.0":
1257 | "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
1258 | "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz"
1259 | "version" "1.2.0"
1260 |
1261 | "shell-quote@^1.7.3":
1262 | "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw=="
1263 | "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz"
1264 | "version" "1.7.3"
1265 |
1266 | "snapdragon-node@^2.0.1":
1267 | "integrity" "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw=="
1268 | "resolved" "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz"
1269 | "version" "2.1.1"
1270 | dependencies:
1271 | "define-property" "^1.0.0"
1272 | "isobject" "^3.0.0"
1273 | "snapdragon-util" "^3.0.1"
1274 |
1275 | "snapdragon-util@^3.0.1":
1276 | "integrity" "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ=="
1277 | "resolved" "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz"
1278 | "version" "3.0.1"
1279 | dependencies:
1280 | "kind-of" "^3.2.0"
1281 |
1282 | "snapdragon@^0.8.1":
1283 | "integrity" "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg=="
1284 | "resolved" "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz"
1285 | "version" "0.8.2"
1286 | dependencies:
1287 | "base" "^0.11.1"
1288 | "debug" "^2.2.0"
1289 | "define-property" "^0.2.5"
1290 | "extend-shallow" "^2.0.1"
1291 | "map-cache" "^0.2.2"
1292 | "source-map" "^0.5.6"
1293 | "source-map-resolve" "^0.5.0"
1294 | "use" "^3.1.0"
1295 |
1296 | "source-map-js@>=0.6.2 <2.0.0":
1297 | "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
1298 | "resolved" "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
1299 | "version" "1.0.2"
1300 |
1301 | "source-map-resolve@^0.5.0":
1302 | "integrity" "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw=="
1303 | "resolved" "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz"
1304 | "version" "0.5.3"
1305 | dependencies:
1306 | "atob" "^2.1.2"
1307 | "decode-uri-component" "^0.2.0"
1308 | "resolve-url" "^0.2.1"
1309 | "source-map-url" "^0.4.0"
1310 | "urix" "^0.1.0"
1311 |
1312 | "source-map-url@^0.4.0":
1313 | "integrity" "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw=="
1314 | "resolved" "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz"
1315 | "version" "0.4.1"
1316 |
1317 | "source-map@^0.5.6":
1318 | "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
1319 | "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
1320 | "version" "0.5.7"
1321 |
1322 | "spawn-command@^0.0.2-1":
1323 | "integrity" "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A="
1324 | "resolved" "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz"
1325 | "version" "0.0.2-1"
1326 |
1327 | "split-string@^3.0.1", "split-string@^3.0.2":
1328 | "integrity" "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw=="
1329 | "resolved" "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz"
1330 | "version" "3.1.0"
1331 | dependencies:
1332 | "extend-shallow" "^3.0.0"
1333 |
1334 | "split@0.3":
1335 | "integrity" "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8="
1336 | "resolved" "https://registry.npmjs.org/split/-/split-0.3.3.tgz"
1337 | "version" "0.3.3"
1338 | dependencies:
1339 | "through" "2"
1340 |
1341 | "static-extend@^0.1.1":
1342 | "integrity" "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY="
1343 | "resolved" "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz"
1344 | "version" "0.1.2"
1345 | dependencies:
1346 | "define-property" "^0.2.5"
1347 | "object-copy" "^0.1.0"
1348 |
1349 | "statuses@>= 1.4.0 < 2", "statuses@~1.5.0":
1350 | "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1351 | "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz"
1352 | "version" "1.5.0"
1353 |
1354 | "statuses@2.0.1":
1355 | "integrity" "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
1356 | "resolved" "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz"
1357 | "version" "2.0.1"
1358 |
1359 | "stream-combiner@~0.0.4":
1360 | "integrity" "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ="
1361 | "resolved" "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz"
1362 | "version" "0.0.4"
1363 | dependencies:
1364 | "duplexer" "~0.1.1"
1365 |
1366 | "string_decoder@~1.1.1":
1367 | "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="
1368 | "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
1369 | "version" "1.1.1"
1370 | dependencies:
1371 | "safe-buffer" "~5.1.0"
1372 |
1373 | "string-width@^4.1.0", "string-width@^4.2.0", "string-width@^4.2.3":
1374 | "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="
1375 | "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
1376 | "version" "4.2.3"
1377 | dependencies:
1378 | "emoji-regex" "^8.0.0"
1379 | "is-fullwidth-code-point" "^3.0.0"
1380 | "strip-ansi" "^6.0.1"
1381 |
1382 | "strip-ansi@^6.0.0", "strip-ansi@^6.0.1":
1383 | "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="
1384 | "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
1385 | "version" "6.0.1"
1386 | dependencies:
1387 | "ansi-regex" "^5.0.1"
1388 |
1389 | "supports-color@^7.1.0":
1390 | "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="
1391 | "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
1392 | "version" "7.2.0"
1393 | dependencies:
1394 | "has-flag" "^4.0.0"
1395 |
1396 | "supports-color@^8.1.0":
1397 | "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="
1398 | "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz"
1399 | "version" "8.1.1"
1400 | dependencies:
1401 | "has-flag" "^4.0.0"
1402 |
1403 | "through@~2.3", "through@~2.3.1", "through@2":
1404 | "integrity" "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
1405 | "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
1406 | "version" "2.3.8"
1407 |
1408 | "to-object-path@^0.3.0":
1409 | "integrity" "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68="
1410 | "resolved" "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz"
1411 | "version" "0.3.0"
1412 | dependencies:
1413 | "kind-of" "^3.0.2"
1414 |
1415 | "to-regex-range@^2.1.0":
1416 | "integrity" "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg="
1417 | "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz"
1418 | "version" "2.1.1"
1419 | dependencies:
1420 | "is-number" "^3.0.0"
1421 | "repeat-string" "^1.6.1"
1422 |
1423 | "to-regex-range@^5.0.1":
1424 | "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="
1425 | "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
1426 | "version" "5.0.1"
1427 | dependencies:
1428 | "is-number" "^7.0.0"
1429 |
1430 | "to-regex@^3.0.1", "to-regex@^3.0.2":
1431 | "integrity" "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw=="
1432 | "resolved" "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz"
1433 | "version" "3.0.2"
1434 | dependencies:
1435 | "define-property" "^2.0.2"
1436 | "extend-shallow" "^3.0.2"
1437 | "regex-not" "^1.0.2"
1438 | "safe-regex" "^1.1.0"
1439 |
1440 | "toidentifier@1.0.1":
1441 | "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
1442 | "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz"
1443 | "version" "1.0.1"
1444 |
1445 | "tree-kill@^1.2.2":
1446 | "integrity" "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
1447 | "resolved" "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz"
1448 | "version" "1.2.2"
1449 |
1450 | "tslib@^1.9.0":
1451 | "integrity" "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
1452 | "resolved" "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
1453 | "version" "1.14.1"
1454 |
1455 | "typescript@^4.7.2":
1456 | "integrity" "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A=="
1457 | "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz"
1458 | "version" "4.7.2"
1459 |
1460 | "union-value@^1.0.0":
1461 | "integrity" "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg=="
1462 | "resolved" "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz"
1463 | "version" "1.0.1"
1464 | dependencies:
1465 | "arr-union" "^3.1.0"
1466 | "get-value" "^2.0.6"
1467 | "is-extendable" "^0.1.1"
1468 | "set-value" "^2.0.1"
1469 |
1470 | "unix-crypt-td-js@^1.1.4":
1471 | "integrity" "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw=="
1472 | "resolved" "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz"
1473 | "version" "1.1.4"
1474 |
1475 | "unpipe@~1.0.0":
1476 | "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1477 | "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz"
1478 | "version" "1.0.0"
1479 |
1480 | "unset-value@^1.0.0":
1481 | "integrity" "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk="
1482 | "resolved" "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz"
1483 | "version" "1.0.0"
1484 | dependencies:
1485 | "has-value" "^0.3.1"
1486 | "isobject" "^3.0.0"
1487 |
1488 | "upath@^1.1.1":
1489 | "integrity" "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
1490 | "resolved" "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz"
1491 | "version" "1.2.0"
1492 |
1493 | "urix@^0.1.0":
1494 | "integrity" "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
1495 | "resolved" "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz"
1496 | "version" "0.1.0"
1497 |
1498 | "use@^3.1.0":
1499 | "integrity" "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
1500 | "resolved" "https://registry.npmjs.org/use/-/use-3.1.1.tgz"
1501 | "version" "3.1.1"
1502 |
1503 | "util-deprecate@~1.0.1":
1504 | "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
1505 | "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
1506 | "version" "1.0.2"
1507 |
1508 | "utils-merge@1.0.1":
1509 | "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
1510 | "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz"
1511 | "version" "1.0.1"
1512 |
1513 | "uuid@^3.0.0":
1514 | "integrity" "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
1515 | "resolved" "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz"
1516 | "version" "3.4.0"
1517 |
1518 | "vary@^1":
1519 | "integrity" "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1520 | "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz"
1521 | "version" "1.1.2"
1522 |
1523 | "websocket-driver@>=0.5.1":
1524 | "integrity" "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg=="
1525 | "resolved" "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz"
1526 | "version" "0.7.4"
1527 | dependencies:
1528 | "http-parser-js" ">=0.5.1"
1529 | "safe-buffer" ">=5.1.0"
1530 | "websocket-extensions" ">=0.1.1"
1531 |
1532 | "websocket-extensions@>=0.1.1":
1533 | "integrity" "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
1534 | "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz"
1535 | "version" "0.1.4"
1536 |
1537 | "wrap-ansi@^7.0.0":
1538 | "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="
1539 | "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
1540 | "version" "7.0.0"
1541 | dependencies:
1542 | "ansi-styles" "^4.0.0"
1543 | "string-width" "^4.1.0"
1544 | "strip-ansi" "^6.0.0"
1545 |
1546 | "wrappy@1":
1547 | "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
1548 | "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
1549 | "version" "1.0.2"
1550 |
1551 | "y18n@^5.0.5":
1552 | "integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
1553 | "resolved" "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
1554 | "version" "5.0.8"
1555 |
1556 | "yargs-parser@^21.0.0":
1557 | "integrity" "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg=="
1558 | "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz"
1559 | "version" "21.0.1"
1560 |
1561 | "yargs@^17.3.1":
1562 | "integrity" "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA=="
1563 | "resolved" "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz"
1564 | "version" "17.5.1"
1565 | dependencies:
1566 | "cliui" "^7.0.2"
1567 | "escalade" "^3.1.1"
1568 | "get-caller-file" "^2.0.5"
1569 | "require-directory" "^2.1.1"
1570 | "string-width" "^4.2.3"
1571 | "y18n" "^5.0.5"
1572 | "yargs-parser" "^21.0.0"
1573 |
--------------------------------------------------------------------------------