├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── index.html
├── package.json
├── pnpm-lock.yaml
├── public
├── 61v-62r.jpg
├── 6v-13r-infrared.jpg
├── 6v-13r.jpg
├── 88v-89r.jpg
├── 92v-93r.jpg
├── favicon.svg
├── liber-floridus-2.jpg
└── ultramarine.jpg
├── src
├── App.tsx
├── annotations.json
├── components
│ ├── AnnotationBody.tsx
│ ├── AnnotationList.tsx
│ ├── AnnotationPanel.tsx
│ ├── CategoryList.tsx
│ ├── LayerList.tsx
│ ├── MainPanel.tsx
│ ├── PageNav.tsx
│ ├── Panels.tsx
│ └── Viewer.tsx
├── config.ts
├── data.ts
├── hooks
│ └── useAnnotations.tsx
├── main.tsx
├── pages.json
├── style.css
└── types
│ └── global.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "endOfLine": "lf",
3 | "semi": false,
4 | "singleQuote": false,
5 | "useTabs": true,
6 | "tabWidth": 2,
7 | "trailingComma": "es5",
8 | "arrowParens": "avoid"
9 | }
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | Copyright 2022 Bauke van der Laan
179 |
180 | Licensed under the Apache License, Version 2.0 (the "License");
181 | you may not use this file except in compliance with the License.
182 | You may obtain a copy of the License at
183 |
184 | http://www.apache.org/licenses/LICENSE-2.0
185 |
186 | Unless required by applicable law or agreed to in writing, software
187 | distributed under the License is distributed on an "AS IS" BASIS,
188 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189 | See the License for the specific language governing permissions and
190 | limitations under the License.
191 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Annotation demo
2 |
3 | A web application showcasing annotations in different categories in a simulated [Mirador 3](https://projectmirador.org/) environment.
4 |
5 | The app is written in TypeScript using [React](https://reactjs.org/) and [Material UI](https://mui.com/) to keep the interface as close as possible to Mirador.
6 |
7 | [Vite](https://vitejs.dev/) is used as development server and build tool.
8 |
9 | ## Installing
10 |
11 | [Node.js](https://nodejs.org/) is required to build or develop the app.
12 |
13 | Install the dependencies:
14 |
15 | ```bash
16 | npm install
17 | ```
18 |
19 | ## Developing
20 |
21 | Start a development server:
22 |
23 | ```bash
24 | npm run dev
25 | ```
26 |
27 | Fast refresh is disabled for now because of [this bug](https://github.com/vitejs/vite/issues/3301) in Vite.
28 |
29 | ## Building
30 |
31 | Build a production version of the app:
32 |
33 | ```bash
34 | npm run build
35 | ```
36 |
37 | The build output can be found in `dist`.
38 |
39 | `dist/index.html` is an example of a page with the app embedded. The app will mount a `div` with `id="annotation-demo"` and needs the linked `.css` and `.js` files as seen there.
40 |
41 | > You can preview the built app with `npm run preview`. This should _not_ be used to serve the app in production.
42 |
43 | ## Structure
44 |
45 | - [`public`](public) contains static assets like the images of the Liber Floridus used in the demo.
46 | - [`src`](src) contains the sourcecode of the
47 | - [`src/main.tsx`](src/main.tsx) is the entrypoint of the React app.
48 | - [`src/config.ts`](src/config.ts) contains the available categories, their initial state and icon.
49 | - [`src/annotations.json`](src/annotations.json) contains the annotations using the [Web Annotation Data Model](https://www.w3.org/TR/annotation-model/) with an added `category` key that maps to the `id` key found in the categories in `src/config.ts`
50 | - [`src/pages.json`](src/pages.json) contains a simplified subset of an IIIF-manifest. The `body.src` in here maps to the files in `public`. The page `id` is used as target by the annotations in `src/annotations.json`.
51 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Mmmonk Annotationdemo
8 |
9 |
10 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mmmonk-annotation-demo",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview",
10 | "check": "tsc --noEmit"
11 | },
12 | "dependencies": {
13 | "@fontsource/roboto": "^4.5.8",
14 | "@material-ui/core": "^4.12.4",
15 | "@material-ui/icons": "^4.11.3",
16 | "html-react-parser": "^3.0.1",
17 | "html-to-text": "^8.2.1",
18 | "react": "^18.2.0",
19 | "react-dom": "^18.2.0",
20 | "react-rnd": "^10.3.7"
21 | },
22 | "devDependencies": {
23 | "@types/react": "^18.0.17",
24 | "@types/react-dom": "^18.0.6",
25 | "@vitejs/plugin-react": "^2.0.1",
26 | "typescript": "^4.7.4",
27 | "vite": "^3.0.7"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.4
2 |
3 | specifiers:
4 | '@fontsource/roboto': ^4.5.8
5 | '@material-ui/core': ^4.12.4
6 | '@material-ui/icons': ^4.11.3
7 | '@types/react': ^18.0.17
8 | '@types/react-dom': ^18.0.6
9 | '@vitejs/plugin-react': ^2.0.1
10 | html-react-parser: ^3.0.1
11 | html-to-text: ^8.2.1
12 | react: ^18.2.0
13 | react-dom: ^18.2.0
14 | react-rnd: ^10.3.7
15 | typescript: ^4.7.4
16 | vite: ^3.0.7
17 |
18 | dependencies:
19 | '@fontsource/roboto': 4.5.8
20 | '@material-ui/core': 4.12.4_zxljzmqdrxwnuenbkrz77w74uy
21 | '@material-ui/icons': 4.11.3_upnjamd3tbaukgopcqqdlc7jbm
22 | html-react-parser: 3.0.1_react@18.2.0
23 | html-to-text: 8.2.1
24 | react: 18.2.0
25 | react-dom: 18.2.0_react@18.2.0
26 | react-rnd: 10.3.7_biqbaboplfbrettd7655fr4n2y
27 |
28 | devDependencies:
29 | '@types/react': 18.0.17
30 | '@types/react-dom': 18.0.6
31 | '@vitejs/plugin-react': 2.0.1_vite@3.0.7
32 | typescript: 4.7.4
33 | vite: 3.0.7
34 |
35 | packages:
36 |
37 | /@ampproject/remapping/2.2.0:
38 | resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==}
39 | engines: {node: '>=6.0.0'}
40 | dependencies:
41 | '@jridgewell/gen-mapping': 0.1.1
42 | '@jridgewell/trace-mapping': 0.3.15
43 | dev: true
44 |
45 | /@babel/code-frame/7.18.6:
46 | resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
47 | engines: {node: '>=6.9.0'}
48 | dependencies:
49 | '@babel/highlight': 7.18.6
50 | dev: true
51 |
52 | /@babel/compat-data/7.18.8:
53 | resolution: {integrity: sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==}
54 | engines: {node: '>=6.9.0'}
55 | dev: true
56 |
57 | /@babel/core/7.18.10:
58 | resolution: {integrity: sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==}
59 | engines: {node: '>=6.9.0'}
60 | dependencies:
61 | '@ampproject/remapping': 2.2.0
62 | '@babel/code-frame': 7.18.6
63 | '@babel/generator': 7.18.12
64 | '@babel/helper-compilation-targets': 7.18.9_@babel+core@7.18.10
65 | '@babel/helper-module-transforms': 7.18.9
66 | '@babel/helpers': 7.18.9
67 | '@babel/parser': 7.18.11
68 | '@babel/template': 7.18.10
69 | '@babel/traverse': 7.18.11
70 | '@babel/types': 7.18.10
71 | convert-source-map: 1.8.0
72 | debug: 4.3.4
73 | gensync: 1.0.0-beta.2
74 | json5: 2.2.1
75 | semver: 6.3.0
76 | transitivePeerDependencies:
77 | - supports-color
78 | dev: true
79 |
80 | /@babel/generator/7.18.12:
81 | resolution: {integrity: sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==}
82 | engines: {node: '>=6.9.0'}
83 | dependencies:
84 | '@babel/types': 7.18.10
85 | '@jridgewell/gen-mapping': 0.3.2
86 | jsesc: 2.5.2
87 | dev: true
88 |
89 | /@babel/helper-annotate-as-pure/7.18.6:
90 | resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==}
91 | engines: {node: '>=6.9.0'}
92 | dependencies:
93 | '@babel/types': 7.18.10
94 | dev: true
95 |
96 | /@babel/helper-compilation-targets/7.18.9_@babel+core@7.18.10:
97 | resolution: {integrity: sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==}
98 | engines: {node: '>=6.9.0'}
99 | peerDependencies:
100 | '@babel/core': ^7.0.0
101 | dependencies:
102 | '@babel/compat-data': 7.18.8
103 | '@babel/core': 7.18.10
104 | '@babel/helper-validator-option': 7.18.6
105 | browserslist: 4.21.3
106 | semver: 6.3.0
107 | dev: true
108 |
109 | /@babel/helper-environment-visitor/7.18.9:
110 | resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==}
111 | engines: {node: '>=6.9.0'}
112 | dev: true
113 |
114 | /@babel/helper-function-name/7.18.9:
115 | resolution: {integrity: sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==}
116 | engines: {node: '>=6.9.0'}
117 | dependencies:
118 | '@babel/template': 7.18.10
119 | '@babel/types': 7.18.10
120 | dev: true
121 |
122 | /@babel/helper-hoist-variables/7.18.6:
123 | resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
124 | engines: {node: '>=6.9.0'}
125 | dependencies:
126 | '@babel/types': 7.18.10
127 | dev: true
128 |
129 | /@babel/helper-module-imports/7.18.6:
130 | resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
131 | engines: {node: '>=6.9.0'}
132 | dependencies:
133 | '@babel/types': 7.18.10
134 | dev: true
135 |
136 | /@babel/helper-module-transforms/7.18.9:
137 | resolution: {integrity: sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==}
138 | engines: {node: '>=6.9.0'}
139 | dependencies:
140 | '@babel/helper-environment-visitor': 7.18.9
141 | '@babel/helper-module-imports': 7.18.6
142 | '@babel/helper-simple-access': 7.18.6
143 | '@babel/helper-split-export-declaration': 7.18.6
144 | '@babel/helper-validator-identifier': 7.18.6
145 | '@babel/template': 7.18.10
146 | '@babel/traverse': 7.18.11
147 | '@babel/types': 7.18.10
148 | transitivePeerDependencies:
149 | - supports-color
150 | dev: true
151 |
152 | /@babel/helper-plugin-utils/7.18.9:
153 | resolution: {integrity: sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==}
154 | engines: {node: '>=6.9.0'}
155 | dev: true
156 |
157 | /@babel/helper-simple-access/7.18.6:
158 | resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==}
159 | engines: {node: '>=6.9.0'}
160 | dependencies:
161 | '@babel/types': 7.18.10
162 | dev: true
163 |
164 | /@babel/helper-split-export-declaration/7.18.6:
165 | resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
166 | engines: {node: '>=6.9.0'}
167 | dependencies:
168 | '@babel/types': 7.18.10
169 | dev: true
170 |
171 | /@babel/helper-string-parser/7.18.10:
172 | resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==}
173 | engines: {node: '>=6.9.0'}
174 | dev: true
175 |
176 | /@babel/helper-validator-identifier/7.18.6:
177 | resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==}
178 | engines: {node: '>=6.9.0'}
179 | dev: true
180 |
181 | /@babel/helper-validator-option/7.18.6:
182 | resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==}
183 | engines: {node: '>=6.9.0'}
184 | dev: true
185 |
186 | /@babel/helpers/7.18.9:
187 | resolution: {integrity: sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==}
188 | engines: {node: '>=6.9.0'}
189 | dependencies:
190 | '@babel/template': 7.18.10
191 | '@babel/traverse': 7.18.11
192 | '@babel/types': 7.18.10
193 | transitivePeerDependencies:
194 | - supports-color
195 | dev: true
196 |
197 | /@babel/highlight/7.18.6:
198 | resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
199 | engines: {node: '>=6.9.0'}
200 | dependencies:
201 | '@babel/helper-validator-identifier': 7.18.6
202 | chalk: 2.4.2
203 | js-tokens: 4.0.0
204 | dev: true
205 |
206 | /@babel/parser/7.18.11:
207 | resolution: {integrity: sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==}
208 | engines: {node: '>=6.0.0'}
209 | hasBin: true
210 | dependencies:
211 | '@babel/types': 7.18.10
212 | dev: true
213 |
214 | /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.18.10:
215 | resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==}
216 | engines: {node: '>=6.9.0'}
217 | peerDependencies:
218 | '@babel/core': ^7.0.0-0
219 | dependencies:
220 | '@babel/core': 7.18.10
221 | '@babel/helper-plugin-utils': 7.18.9
222 | dev: true
223 |
224 | /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.18.10:
225 | resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==}
226 | engines: {node: '>=6.9.0'}
227 | peerDependencies:
228 | '@babel/core': ^7.0.0-0
229 | dependencies:
230 | '@babel/core': 7.18.10
231 | '@babel/plugin-transform-react-jsx': 7.18.10_@babel+core@7.18.10
232 | dev: true
233 |
234 | /@babel/plugin-transform-react-jsx-self/7.18.6_@babel+core@7.18.10:
235 | resolution: {integrity: sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==}
236 | engines: {node: '>=6.9.0'}
237 | peerDependencies:
238 | '@babel/core': ^7.0.0-0
239 | dependencies:
240 | '@babel/core': 7.18.10
241 | '@babel/helper-plugin-utils': 7.18.9
242 | dev: true
243 |
244 | /@babel/plugin-transform-react-jsx-source/7.18.6_@babel+core@7.18.10:
245 | resolution: {integrity: sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw==}
246 | engines: {node: '>=6.9.0'}
247 | peerDependencies:
248 | '@babel/core': ^7.0.0-0
249 | dependencies:
250 | '@babel/core': 7.18.10
251 | '@babel/helper-plugin-utils': 7.18.9
252 | dev: true
253 |
254 | /@babel/plugin-transform-react-jsx/7.18.10_@babel+core@7.18.10:
255 | resolution: {integrity: sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==}
256 | engines: {node: '>=6.9.0'}
257 | peerDependencies:
258 | '@babel/core': ^7.0.0-0
259 | dependencies:
260 | '@babel/core': 7.18.10
261 | '@babel/helper-annotate-as-pure': 7.18.6
262 | '@babel/helper-module-imports': 7.18.6
263 | '@babel/helper-plugin-utils': 7.18.9
264 | '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.18.10
265 | '@babel/types': 7.18.10
266 | dev: true
267 |
268 | /@babel/runtime/7.18.9:
269 | resolution: {integrity: sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==}
270 | engines: {node: '>=6.9.0'}
271 | dependencies:
272 | regenerator-runtime: 0.13.9
273 | dev: false
274 |
275 | /@babel/template/7.18.10:
276 | resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==}
277 | engines: {node: '>=6.9.0'}
278 | dependencies:
279 | '@babel/code-frame': 7.18.6
280 | '@babel/parser': 7.18.11
281 | '@babel/types': 7.18.10
282 | dev: true
283 |
284 | /@babel/traverse/7.18.11:
285 | resolution: {integrity: sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==}
286 | engines: {node: '>=6.9.0'}
287 | dependencies:
288 | '@babel/code-frame': 7.18.6
289 | '@babel/generator': 7.18.12
290 | '@babel/helper-environment-visitor': 7.18.9
291 | '@babel/helper-function-name': 7.18.9
292 | '@babel/helper-hoist-variables': 7.18.6
293 | '@babel/helper-split-export-declaration': 7.18.6
294 | '@babel/parser': 7.18.11
295 | '@babel/types': 7.18.10
296 | debug: 4.3.4
297 | globals: 11.12.0
298 | transitivePeerDependencies:
299 | - supports-color
300 | dev: true
301 |
302 | /@babel/types/7.18.10:
303 | resolution: {integrity: sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==}
304 | engines: {node: '>=6.9.0'}
305 | dependencies:
306 | '@babel/helper-string-parser': 7.18.10
307 | '@babel/helper-validator-identifier': 7.18.6
308 | to-fast-properties: 2.0.0
309 | dev: true
310 |
311 | /@emotion/hash/0.8.0:
312 | resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
313 | dev: false
314 |
315 | /@esbuild/linux-loong64/0.14.54:
316 | resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
317 | engines: {node: '>=12'}
318 | cpu: [loong64]
319 | os: [linux]
320 | requiresBuild: true
321 | dev: true
322 | optional: true
323 |
324 | /@fontsource/roboto/4.5.8:
325 | resolution: {integrity: sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA==}
326 | dev: false
327 |
328 | /@jridgewell/gen-mapping/0.1.1:
329 | resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==}
330 | engines: {node: '>=6.0.0'}
331 | dependencies:
332 | '@jridgewell/set-array': 1.1.2
333 | '@jridgewell/sourcemap-codec': 1.4.14
334 | dev: true
335 |
336 | /@jridgewell/gen-mapping/0.3.2:
337 | resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==}
338 | engines: {node: '>=6.0.0'}
339 | dependencies:
340 | '@jridgewell/set-array': 1.1.2
341 | '@jridgewell/sourcemap-codec': 1.4.14
342 | '@jridgewell/trace-mapping': 0.3.15
343 | dev: true
344 |
345 | /@jridgewell/resolve-uri/3.1.0:
346 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
347 | engines: {node: '>=6.0.0'}
348 | dev: true
349 |
350 | /@jridgewell/set-array/1.1.2:
351 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
352 | engines: {node: '>=6.0.0'}
353 | dev: true
354 |
355 | /@jridgewell/sourcemap-codec/1.4.14:
356 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
357 | dev: true
358 |
359 | /@jridgewell/trace-mapping/0.3.15:
360 | resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==}
361 | dependencies:
362 | '@jridgewell/resolve-uri': 3.1.0
363 | '@jridgewell/sourcemap-codec': 1.4.14
364 | dev: true
365 |
366 | /@material-ui/core/4.12.4_zxljzmqdrxwnuenbkrz77w74uy:
367 | resolution: {integrity: sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==}
368 | engines: {node: '>=8.0.0'}
369 | peerDependencies:
370 | '@types/react': ^16.8.6 || ^17.0.0
371 | react: ^16.8.0 || ^17.0.0
372 | react-dom: ^16.8.0 || ^17.0.0
373 | peerDependenciesMeta:
374 | '@types/react':
375 | optional: true
376 | dependencies:
377 | '@babel/runtime': 7.18.9
378 | '@material-ui/styles': 4.11.5_zxljzmqdrxwnuenbkrz77w74uy
379 | '@material-ui/system': 4.12.2_zxljzmqdrxwnuenbkrz77w74uy
380 | '@material-ui/types': 5.1.0_@types+react@18.0.17
381 | '@material-ui/utils': 4.11.3_biqbaboplfbrettd7655fr4n2y
382 | '@types/react': 18.0.17
383 | '@types/react-transition-group': 4.4.5
384 | clsx: 1.2.1
385 | hoist-non-react-statics: 3.3.2
386 | popper.js: 1.16.1-lts
387 | prop-types: 15.8.1
388 | react: 18.2.0
389 | react-dom: 18.2.0_react@18.2.0
390 | react-is: 17.0.2
391 | react-transition-group: 4.4.5_biqbaboplfbrettd7655fr4n2y
392 | dev: false
393 |
394 | /@material-ui/icons/4.11.3_upnjamd3tbaukgopcqqdlc7jbm:
395 | resolution: {integrity: sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==}
396 | engines: {node: '>=8.0.0'}
397 | peerDependencies:
398 | '@material-ui/core': ^4.0.0
399 | '@types/react': ^16.8.6 || ^17.0.0
400 | react: ^16.8.0 || ^17.0.0
401 | react-dom: ^16.8.0 || ^17.0.0
402 | peerDependenciesMeta:
403 | '@types/react':
404 | optional: true
405 | dependencies:
406 | '@babel/runtime': 7.18.9
407 | '@material-ui/core': 4.12.4_zxljzmqdrxwnuenbkrz77w74uy
408 | '@types/react': 18.0.17
409 | react: 18.2.0
410 | react-dom: 18.2.0_react@18.2.0
411 | dev: false
412 |
413 | /@material-ui/styles/4.11.5_zxljzmqdrxwnuenbkrz77w74uy:
414 | resolution: {integrity: sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==}
415 | engines: {node: '>=8.0.0'}
416 | peerDependencies:
417 | '@types/react': ^16.8.6 || ^17.0.0
418 | react: ^16.8.0 || ^17.0.0
419 | react-dom: ^16.8.0 || ^17.0.0
420 | peerDependenciesMeta:
421 | '@types/react':
422 | optional: true
423 | dependencies:
424 | '@babel/runtime': 7.18.9
425 | '@emotion/hash': 0.8.0
426 | '@material-ui/types': 5.1.0_@types+react@18.0.17
427 | '@material-ui/utils': 4.11.3_biqbaboplfbrettd7655fr4n2y
428 | '@types/react': 18.0.17
429 | clsx: 1.2.1
430 | csstype: 2.6.20
431 | hoist-non-react-statics: 3.3.2
432 | jss: 10.9.2
433 | jss-plugin-camel-case: 10.9.2
434 | jss-plugin-default-unit: 10.9.2
435 | jss-plugin-global: 10.9.2
436 | jss-plugin-nested: 10.9.2
437 | jss-plugin-props-sort: 10.9.2
438 | jss-plugin-rule-value-function: 10.9.2
439 | jss-plugin-vendor-prefixer: 10.9.2
440 | prop-types: 15.8.1
441 | react: 18.2.0
442 | react-dom: 18.2.0_react@18.2.0
443 | dev: false
444 |
445 | /@material-ui/system/4.12.2_zxljzmqdrxwnuenbkrz77w74uy:
446 | resolution: {integrity: sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==}
447 | engines: {node: '>=8.0.0'}
448 | peerDependencies:
449 | '@types/react': ^16.8.6 || ^17.0.0
450 | react: ^16.8.0 || ^17.0.0
451 | react-dom: ^16.8.0 || ^17.0.0
452 | peerDependenciesMeta:
453 | '@types/react':
454 | optional: true
455 | dependencies:
456 | '@babel/runtime': 7.18.9
457 | '@material-ui/utils': 4.11.3_biqbaboplfbrettd7655fr4n2y
458 | '@types/react': 18.0.17
459 | csstype: 2.6.20
460 | prop-types: 15.8.1
461 | react: 18.2.0
462 | react-dom: 18.2.0_react@18.2.0
463 | dev: false
464 |
465 | /@material-ui/types/5.1.0_@types+react@18.0.17:
466 | resolution: {integrity: sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==}
467 | peerDependencies:
468 | '@types/react': '*'
469 | peerDependenciesMeta:
470 | '@types/react':
471 | optional: true
472 | dependencies:
473 | '@types/react': 18.0.17
474 | dev: false
475 |
476 | /@material-ui/utils/4.11.3_biqbaboplfbrettd7655fr4n2y:
477 | resolution: {integrity: sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==}
478 | engines: {node: '>=8.0.0'}
479 | peerDependencies:
480 | react: ^16.8.0 || ^17.0.0
481 | react-dom: ^16.8.0 || ^17.0.0
482 | dependencies:
483 | '@babel/runtime': 7.18.9
484 | prop-types: 15.8.1
485 | react: 18.2.0
486 | react-dom: 18.2.0_react@18.2.0
487 | react-is: 17.0.2
488 | dev: false
489 |
490 | /@selderee/plugin-htmlparser2/0.6.0:
491 | resolution: {integrity: sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==}
492 | dependencies:
493 | domhandler: 4.3.1
494 | selderee: 0.6.0
495 | dev: false
496 |
497 | /@types/prop-types/15.7.5:
498 | resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
499 |
500 | /@types/react-dom/18.0.6:
501 | resolution: {integrity: sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==}
502 | dependencies:
503 | '@types/react': 18.0.17
504 | dev: true
505 |
506 | /@types/react-transition-group/4.4.5:
507 | resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==}
508 | dependencies:
509 | '@types/react': 18.0.17
510 | dev: false
511 |
512 | /@types/react/18.0.17:
513 | resolution: {integrity: sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==}
514 | dependencies:
515 | '@types/prop-types': 15.7.5
516 | '@types/scheduler': 0.16.2
517 | csstype: 3.1.0
518 |
519 | /@types/scheduler/0.16.2:
520 | resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
521 |
522 | /@vitejs/plugin-react/2.0.1_vite@3.0.7:
523 | resolution: {integrity: sha512-uINzNHmjrbunlFtyVkST6lY1ewSfz/XwLufG0PIqvLGnpk2nOIOa/1CACTDNcKi1/RwaCzJLmsXwm1NsUVV/NA==}
524 | engines: {node: ^14.18.0 || >=16.0.0}
525 | peerDependencies:
526 | vite: ^3.0.0
527 | dependencies:
528 | '@babel/core': 7.18.10
529 | '@babel/plugin-transform-react-jsx': 7.18.10_@babel+core@7.18.10
530 | '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.18.10
531 | '@babel/plugin-transform-react-jsx-self': 7.18.6_@babel+core@7.18.10
532 | '@babel/plugin-transform-react-jsx-source': 7.18.6_@babel+core@7.18.10
533 | magic-string: 0.26.2
534 | react-refresh: 0.14.0
535 | vite: 3.0.7
536 | transitivePeerDependencies:
537 | - supports-color
538 | dev: true
539 |
540 | /ansi-styles/3.2.1:
541 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
542 | engines: {node: '>=4'}
543 | dependencies:
544 | color-convert: 1.9.3
545 | dev: true
546 |
547 | /browserslist/4.21.3:
548 | resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==}
549 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
550 | hasBin: true
551 | dependencies:
552 | caniuse-lite: 1.0.30001375
553 | electron-to-chromium: 1.4.218
554 | node-releases: 2.0.6
555 | update-browserslist-db: 1.0.5_browserslist@4.21.3
556 | dev: true
557 |
558 | /caniuse-lite/1.0.30001375:
559 | resolution: {integrity: sha512-kWIMkNzLYxSvnjy0hL8w1NOaWNr2rn39RTAVyIwcw8juu60bZDWiF1/loOYANzjtJmy6qPgNmn38ro5Pygagdw==}
560 | dev: true
561 |
562 | /chalk/2.4.2:
563 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
564 | engines: {node: '>=4'}
565 | dependencies:
566 | ansi-styles: 3.2.1
567 | escape-string-regexp: 1.0.5
568 | supports-color: 5.5.0
569 | dev: true
570 |
571 | /clsx/1.2.1:
572 | resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==}
573 | engines: {node: '>=6'}
574 | dev: false
575 |
576 | /color-convert/1.9.3:
577 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
578 | dependencies:
579 | color-name: 1.1.3
580 | dev: true
581 |
582 | /color-name/1.1.3:
583 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
584 | dev: true
585 |
586 | /commander/2.20.3:
587 | resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
588 | dev: false
589 |
590 | /convert-source-map/1.8.0:
591 | resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==}
592 | dependencies:
593 | safe-buffer: 5.1.2
594 | dev: true
595 |
596 | /css-vendor/2.0.8:
597 | resolution: {integrity: sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==}
598 | dependencies:
599 | '@babel/runtime': 7.18.9
600 | is-in-browser: 1.1.3
601 | dev: false
602 |
603 | /csstype/2.6.20:
604 | resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==}
605 | dev: false
606 |
607 | /csstype/3.1.0:
608 | resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==}
609 |
610 | /debug/4.3.4:
611 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
612 | engines: {node: '>=6.0'}
613 | peerDependencies:
614 | supports-color: '*'
615 | peerDependenciesMeta:
616 | supports-color:
617 | optional: true
618 | dependencies:
619 | ms: 2.1.2
620 | dev: true
621 |
622 | /deepmerge/4.2.2:
623 | resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
624 | engines: {node: '>=0.10.0'}
625 | dev: false
626 |
627 | /discontinuous-range/1.0.0:
628 | resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==}
629 | dev: false
630 |
631 | /dom-helpers/5.2.1:
632 | resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
633 | dependencies:
634 | '@babel/runtime': 7.18.9
635 | csstype: 3.1.0
636 | dev: false
637 |
638 | /dom-serializer/1.4.1:
639 | resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
640 | dependencies:
641 | domelementtype: 2.3.0
642 | domhandler: 4.3.1
643 | entities: 2.2.0
644 | dev: false
645 |
646 | /dom-serializer/2.0.0:
647 | resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
648 | dependencies:
649 | domelementtype: 2.3.0
650 | domhandler: 5.0.3
651 | entities: 4.3.1
652 | dev: false
653 |
654 | /domelementtype/2.3.0:
655 | resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
656 | dev: false
657 |
658 | /domhandler/4.3.1:
659 | resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
660 | engines: {node: '>= 4'}
661 | dependencies:
662 | domelementtype: 2.3.0
663 | dev: false
664 |
665 | /domhandler/5.0.3:
666 | resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
667 | engines: {node: '>= 4'}
668 | dependencies:
669 | domelementtype: 2.3.0
670 | dev: false
671 |
672 | /domutils/2.8.0:
673 | resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
674 | dependencies:
675 | dom-serializer: 1.4.1
676 | domelementtype: 2.3.0
677 | domhandler: 4.3.1
678 | dev: false
679 |
680 | /domutils/3.0.1:
681 | resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==}
682 | dependencies:
683 | dom-serializer: 2.0.0
684 | domelementtype: 2.3.0
685 | domhandler: 5.0.3
686 | dev: false
687 |
688 | /electron-to-chromium/1.4.218:
689 | resolution: {integrity: sha512-INDylKH//YIf2w67D+IjkfVnGVrZ/D94DAU/FPPm6T4jEPbEDQvo9r2wTj0ncFdtJH8+V8BggZTaN8Rzk5wkgw==}
690 | dev: true
691 |
692 | /entities/2.2.0:
693 | resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
694 | dev: false
695 |
696 | /entities/4.3.1:
697 | resolution: {integrity: sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==}
698 | engines: {node: '>=0.12'}
699 | dev: false
700 |
701 | /esbuild-android-64/0.14.54:
702 | resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
703 | engines: {node: '>=12'}
704 | cpu: [x64]
705 | os: [android]
706 | requiresBuild: true
707 | dev: true
708 | optional: true
709 |
710 | /esbuild-android-arm64/0.14.54:
711 | resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
712 | engines: {node: '>=12'}
713 | cpu: [arm64]
714 | os: [android]
715 | requiresBuild: true
716 | dev: true
717 | optional: true
718 |
719 | /esbuild-darwin-64/0.14.54:
720 | resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
721 | engines: {node: '>=12'}
722 | cpu: [x64]
723 | os: [darwin]
724 | requiresBuild: true
725 | dev: true
726 | optional: true
727 |
728 | /esbuild-darwin-arm64/0.14.54:
729 | resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
730 | engines: {node: '>=12'}
731 | cpu: [arm64]
732 | os: [darwin]
733 | requiresBuild: true
734 | dev: true
735 | optional: true
736 |
737 | /esbuild-freebsd-64/0.14.54:
738 | resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
739 | engines: {node: '>=12'}
740 | cpu: [x64]
741 | os: [freebsd]
742 | requiresBuild: true
743 | dev: true
744 | optional: true
745 |
746 | /esbuild-freebsd-arm64/0.14.54:
747 | resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
748 | engines: {node: '>=12'}
749 | cpu: [arm64]
750 | os: [freebsd]
751 | requiresBuild: true
752 | dev: true
753 | optional: true
754 |
755 | /esbuild-linux-32/0.14.54:
756 | resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
757 | engines: {node: '>=12'}
758 | cpu: [ia32]
759 | os: [linux]
760 | requiresBuild: true
761 | dev: true
762 | optional: true
763 |
764 | /esbuild-linux-64/0.14.54:
765 | resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
766 | engines: {node: '>=12'}
767 | cpu: [x64]
768 | os: [linux]
769 | requiresBuild: true
770 | dev: true
771 | optional: true
772 |
773 | /esbuild-linux-arm/0.14.54:
774 | resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
775 | engines: {node: '>=12'}
776 | cpu: [arm]
777 | os: [linux]
778 | requiresBuild: true
779 | dev: true
780 | optional: true
781 |
782 | /esbuild-linux-arm64/0.14.54:
783 | resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
784 | engines: {node: '>=12'}
785 | cpu: [arm64]
786 | os: [linux]
787 | requiresBuild: true
788 | dev: true
789 | optional: true
790 |
791 | /esbuild-linux-mips64le/0.14.54:
792 | resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
793 | engines: {node: '>=12'}
794 | cpu: [mips64el]
795 | os: [linux]
796 | requiresBuild: true
797 | dev: true
798 | optional: true
799 |
800 | /esbuild-linux-ppc64le/0.14.54:
801 | resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
802 | engines: {node: '>=12'}
803 | cpu: [ppc64]
804 | os: [linux]
805 | requiresBuild: true
806 | dev: true
807 | optional: true
808 |
809 | /esbuild-linux-riscv64/0.14.54:
810 | resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
811 | engines: {node: '>=12'}
812 | cpu: [riscv64]
813 | os: [linux]
814 | requiresBuild: true
815 | dev: true
816 | optional: true
817 |
818 | /esbuild-linux-s390x/0.14.54:
819 | resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
820 | engines: {node: '>=12'}
821 | cpu: [s390x]
822 | os: [linux]
823 | requiresBuild: true
824 | dev: true
825 | optional: true
826 |
827 | /esbuild-netbsd-64/0.14.54:
828 | resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
829 | engines: {node: '>=12'}
830 | cpu: [x64]
831 | os: [netbsd]
832 | requiresBuild: true
833 | dev: true
834 | optional: true
835 |
836 | /esbuild-openbsd-64/0.14.54:
837 | resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
838 | engines: {node: '>=12'}
839 | cpu: [x64]
840 | os: [openbsd]
841 | requiresBuild: true
842 | dev: true
843 | optional: true
844 |
845 | /esbuild-sunos-64/0.14.54:
846 | resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
847 | engines: {node: '>=12'}
848 | cpu: [x64]
849 | os: [sunos]
850 | requiresBuild: true
851 | dev: true
852 | optional: true
853 |
854 | /esbuild-windows-32/0.14.54:
855 | resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
856 | engines: {node: '>=12'}
857 | cpu: [ia32]
858 | os: [win32]
859 | requiresBuild: true
860 | dev: true
861 | optional: true
862 |
863 | /esbuild-windows-64/0.14.54:
864 | resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
865 | engines: {node: '>=12'}
866 | cpu: [x64]
867 | os: [win32]
868 | requiresBuild: true
869 | dev: true
870 | optional: true
871 |
872 | /esbuild-windows-arm64/0.14.54:
873 | resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
874 | engines: {node: '>=12'}
875 | cpu: [arm64]
876 | os: [win32]
877 | requiresBuild: true
878 | dev: true
879 | optional: true
880 |
881 | /esbuild/0.14.54:
882 | resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==}
883 | engines: {node: '>=12'}
884 | hasBin: true
885 | requiresBuild: true
886 | optionalDependencies:
887 | '@esbuild/linux-loong64': 0.14.54
888 | esbuild-android-64: 0.14.54
889 | esbuild-android-arm64: 0.14.54
890 | esbuild-darwin-64: 0.14.54
891 | esbuild-darwin-arm64: 0.14.54
892 | esbuild-freebsd-64: 0.14.54
893 | esbuild-freebsd-arm64: 0.14.54
894 | esbuild-linux-32: 0.14.54
895 | esbuild-linux-64: 0.14.54
896 | esbuild-linux-arm: 0.14.54
897 | esbuild-linux-arm64: 0.14.54
898 | esbuild-linux-mips64le: 0.14.54
899 | esbuild-linux-ppc64le: 0.14.54
900 | esbuild-linux-riscv64: 0.14.54
901 | esbuild-linux-s390x: 0.14.54
902 | esbuild-netbsd-64: 0.14.54
903 | esbuild-openbsd-64: 0.14.54
904 | esbuild-sunos-64: 0.14.54
905 | esbuild-windows-32: 0.14.54
906 | esbuild-windows-64: 0.14.54
907 | esbuild-windows-arm64: 0.14.54
908 | dev: true
909 |
910 | /escalade/3.1.1:
911 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
912 | engines: {node: '>=6'}
913 | dev: true
914 |
915 | /escape-string-regexp/1.0.5:
916 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
917 | engines: {node: '>=0.8.0'}
918 | dev: true
919 |
920 | /fast-memoize/2.5.2:
921 | resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==}
922 | dev: false
923 |
924 | /fsevents/2.3.2:
925 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
926 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
927 | os: [darwin]
928 | requiresBuild: true
929 | dev: true
930 | optional: true
931 |
932 | /function-bind/1.1.1:
933 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
934 | dev: true
935 |
936 | /gensync/1.0.0-beta.2:
937 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
938 | engines: {node: '>=6.9.0'}
939 | dev: true
940 |
941 | /globals/11.12.0:
942 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
943 | engines: {node: '>=4'}
944 | dev: true
945 |
946 | /has-flag/3.0.0:
947 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
948 | engines: {node: '>=4'}
949 | dev: true
950 |
951 | /has/1.0.3:
952 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
953 | engines: {node: '>= 0.4.0'}
954 | dependencies:
955 | function-bind: 1.1.1
956 | dev: true
957 |
958 | /he/1.2.0:
959 | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
960 | hasBin: true
961 | dev: false
962 |
963 | /hoist-non-react-statics/3.3.2:
964 | resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
965 | dependencies:
966 | react-is: 16.13.1
967 | dev: false
968 |
969 | /html-dom-parser/3.0.1:
970 | resolution: {integrity: sha512-BtPGWyE2XGbqQFdZE+0/YMVppz319jvvkNGcMwLRmt1Mw0tLHzZOMs1TqbxtcCdVSZwS5pEOXasaD7HHD5iwkQ==}
971 | dependencies:
972 | domhandler: 5.0.3
973 | htmlparser2: 8.0.1
974 | dev: false
975 |
976 | /html-react-parser/3.0.1_react@18.2.0:
977 | resolution: {integrity: sha512-TsCwwmpqN8F2JA0EqWK/8U/cN07BfZU7agH3FY5G+RQqLs6HT2z2RNlFZI+Jp8e/nIXIsgYDvt8vqu8Dv9lr6w==}
978 | peerDependencies:
979 | react: 0.14 || 15 || 16 || 17 || 18
980 | dependencies:
981 | domhandler: 5.0.3
982 | html-dom-parser: 3.0.1
983 | react: 18.2.0
984 | react-property: 2.0.0
985 | style-to-js: 1.1.1
986 | dev: false
987 |
988 | /html-to-text/8.2.1:
989 | resolution: {integrity: sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==}
990 | engines: {node: '>=10.23.2'}
991 | hasBin: true
992 | dependencies:
993 | '@selderee/plugin-htmlparser2': 0.6.0
994 | deepmerge: 4.2.2
995 | he: 1.2.0
996 | htmlparser2: 6.1.0
997 | minimist: 1.2.6
998 | selderee: 0.6.0
999 | dev: false
1000 |
1001 | /htmlparser2/6.1.0:
1002 | resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
1003 | dependencies:
1004 | domelementtype: 2.3.0
1005 | domhandler: 4.3.1
1006 | domutils: 2.8.0
1007 | entities: 2.2.0
1008 | dev: false
1009 |
1010 | /htmlparser2/8.0.1:
1011 | resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==}
1012 | dependencies:
1013 | domelementtype: 2.3.0
1014 | domhandler: 5.0.3
1015 | domutils: 3.0.1
1016 | entities: 4.3.1
1017 | dev: false
1018 |
1019 | /hyphenate-style-name/1.0.4:
1020 | resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==}
1021 | dev: false
1022 |
1023 | /inline-style-parser/0.1.1:
1024 | resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==}
1025 | dev: false
1026 |
1027 | /is-core-module/2.10.0:
1028 | resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
1029 | dependencies:
1030 | has: 1.0.3
1031 | dev: true
1032 |
1033 | /is-in-browser/1.1.3:
1034 | resolution: {integrity: sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==}
1035 | dev: false
1036 |
1037 | /js-tokens/4.0.0:
1038 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
1039 |
1040 | /jsesc/2.5.2:
1041 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
1042 | engines: {node: '>=4'}
1043 | hasBin: true
1044 | dev: true
1045 |
1046 | /json5/2.2.1:
1047 | resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==}
1048 | engines: {node: '>=6'}
1049 | hasBin: true
1050 | dev: true
1051 |
1052 | /jss-plugin-camel-case/10.9.2:
1053 | resolution: {integrity: sha512-wgBPlL3WS0WDJ1lPJcgjux/SHnDuu7opmgQKSraKs4z8dCCyYMx9IDPFKBXQ8Q5dVYij1FFV0WdxyhuOOAXuTg==}
1054 | dependencies:
1055 | '@babel/runtime': 7.18.9
1056 | hyphenate-style-name: 1.0.4
1057 | jss: 10.9.2
1058 | dev: false
1059 |
1060 | /jss-plugin-default-unit/10.9.2:
1061 | resolution: {integrity: sha512-pYg0QX3bBEFtTnmeSI3l7ad1vtHU42YEEpgW7pmIh+9pkWNWb5dwS/4onSfAaI0kq+dOZHzz4dWe+8vWnanoSg==}
1062 | dependencies:
1063 | '@babel/runtime': 7.18.9
1064 | jss: 10.9.2
1065 | dev: false
1066 |
1067 | /jss-plugin-global/10.9.2:
1068 | resolution: {integrity: sha512-GcX0aE8Ef6AtlasVrafg1DItlL/tWHoC4cGir4r3gegbWwF5ZOBYhx04gurPvWHC8F873aEGqge7C17xpwmp2g==}
1069 | dependencies:
1070 | '@babel/runtime': 7.18.9
1071 | jss: 10.9.2
1072 | dev: false
1073 |
1074 | /jss-plugin-nested/10.9.2:
1075 | resolution: {integrity: sha512-VgiOWIC6bvgDaAL97XCxGD0BxOKM0K0zeB/ECyNaVF6FqvdGB9KBBWRdy2STYAss4VVA7i5TbxFZN+WSX1kfQA==}
1076 | dependencies:
1077 | '@babel/runtime': 7.18.9
1078 | jss: 10.9.2
1079 | tiny-warning: 1.0.3
1080 | dev: false
1081 |
1082 | /jss-plugin-props-sort/10.9.2:
1083 | resolution: {integrity: sha512-AP1AyUTbi2szylgr+O0OB7gkIxEGzySLITZ2GpsaoX72YMCGI2jYAc+WUhPfvUnZYiauF4zTnN4V4TGuvFjJlw==}
1084 | dependencies:
1085 | '@babel/runtime': 7.18.9
1086 | jss: 10.9.2
1087 | dev: false
1088 |
1089 | /jss-plugin-rule-value-function/10.9.2:
1090 | resolution: {integrity: sha512-vf5ms8zvLFMub6swbNxvzsurHfUZ5Shy5aJB2gIpY6WNA3uLinEcxYyraQXItRHi5ivXGqYciFDRM2ZoVoRZ4Q==}
1091 | dependencies:
1092 | '@babel/runtime': 7.18.9
1093 | jss: 10.9.2
1094 | tiny-warning: 1.0.3
1095 | dev: false
1096 |
1097 | /jss-plugin-vendor-prefixer/10.9.2:
1098 | resolution: {integrity: sha512-SxcEoH+Rttf9fEv6KkiPzLdXRmI6waOTcMkbbEFgdZLDYNIP9UKNHFy6thhbRKqv0XMQZdrEsbDyV464zE/dUA==}
1099 | dependencies:
1100 | '@babel/runtime': 7.18.9
1101 | css-vendor: 2.0.8
1102 | jss: 10.9.2
1103 | dev: false
1104 |
1105 | /jss/10.9.2:
1106 | resolution: {integrity: sha512-b8G6rWpYLR4teTUbGd4I4EsnWjg7MN0Q5bSsjKhVkJVjhQDy2KzkbD2AW3TuT0RYZVmZZHKIrXDn6kjU14qkUg==}
1107 | dependencies:
1108 | '@babel/runtime': 7.18.9
1109 | csstype: 3.1.0
1110 | is-in-browser: 1.1.3
1111 | tiny-warning: 1.0.3
1112 | dev: false
1113 |
1114 | /loose-envify/1.4.0:
1115 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
1116 | hasBin: true
1117 | dependencies:
1118 | js-tokens: 4.0.0
1119 | dev: false
1120 |
1121 | /magic-string/0.26.2:
1122 | resolution: {integrity: sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==}
1123 | engines: {node: '>=12'}
1124 | dependencies:
1125 | sourcemap-codec: 1.4.8
1126 | dev: true
1127 |
1128 | /minimist/1.2.6:
1129 | resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==}
1130 | dev: false
1131 |
1132 | /moo/0.5.1:
1133 | resolution: {integrity: sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==}
1134 | dev: false
1135 |
1136 | /ms/2.1.2:
1137 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
1138 | dev: true
1139 |
1140 | /nanoid/3.3.4:
1141 | resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
1142 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
1143 | hasBin: true
1144 | dev: true
1145 |
1146 | /nearley/2.20.1:
1147 | resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==}
1148 | hasBin: true
1149 | dependencies:
1150 | commander: 2.20.3
1151 | moo: 0.5.1
1152 | railroad-diagrams: 1.0.0
1153 | randexp: 0.4.6
1154 | dev: false
1155 |
1156 | /node-releases/2.0.6:
1157 | resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
1158 | dev: true
1159 |
1160 | /object-assign/4.1.1:
1161 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
1162 | engines: {node: '>=0.10.0'}
1163 | dev: false
1164 |
1165 | /parseley/0.7.0:
1166 | resolution: {integrity: sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==}
1167 | dependencies:
1168 | moo: 0.5.1
1169 | nearley: 2.20.1
1170 | dev: false
1171 |
1172 | /path-parse/1.0.7:
1173 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
1174 | dev: true
1175 |
1176 | /picocolors/1.0.0:
1177 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
1178 | dev: true
1179 |
1180 | /popper.js/1.16.1-lts:
1181 | resolution: {integrity: sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==}
1182 | dev: false
1183 |
1184 | /postcss/8.4.16:
1185 | resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==}
1186 | engines: {node: ^10 || ^12 || >=14}
1187 | dependencies:
1188 | nanoid: 3.3.4
1189 | picocolors: 1.0.0
1190 | source-map-js: 1.0.2
1191 | dev: true
1192 |
1193 | /prop-types/15.8.1:
1194 | resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
1195 | dependencies:
1196 | loose-envify: 1.4.0
1197 | object-assign: 4.1.1
1198 | react-is: 16.13.1
1199 | dev: false
1200 |
1201 | /railroad-diagrams/1.0.0:
1202 | resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==}
1203 | dev: false
1204 |
1205 | /randexp/0.4.6:
1206 | resolution: {integrity: sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==}
1207 | engines: {node: '>=0.12'}
1208 | dependencies:
1209 | discontinuous-range: 1.0.0
1210 | ret: 0.1.15
1211 | dev: false
1212 |
1213 | /re-resizable/6.9.6_biqbaboplfbrettd7655fr4n2y:
1214 | resolution: {integrity: sha512-0xYKS5+Z0zk+vICQlcZW+g54CcJTTmHluA7JUUgvERDxnKAnytylcyPsA+BSFi759s5hPlHmBRegFrwXs2FuBQ==}
1215 | peerDependencies:
1216 | react: ^16.13.1 || ^17.0.0 || ^18.0.0
1217 | react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0
1218 | dependencies:
1219 | fast-memoize: 2.5.2
1220 | react: 18.2.0
1221 | react-dom: 18.2.0_react@18.2.0
1222 | dev: false
1223 |
1224 | /react-dom/18.2.0_react@18.2.0:
1225 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
1226 | peerDependencies:
1227 | react: ^18.2.0
1228 | dependencies:
1229 | loose-envify: 1.4.0
1230 | react: 18.2.0
1231 | scheduler: 0.23.0
1232 | dev: false
1233 |
1234 | /react-draggable/4.4.4_biqbaboplfbrettd7655fr4n2y:
1235 | resolution: {integrity: sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==}
1236 | peerDependencies:
1237 | react: '>= 16.3.0'
1238 | react-dom: '>= 16.3.0'
1239 | dependencies:
1240 | clsx: 1.2.1
1241 | prop-types: 15.8.1
1242 | react: 18.2.0
1243 | react-dom: 18.2.0_react@18.2.0
1244 | dev: false
1245 |
1246 | /react-is/16.13.1:
1247 | resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
1248 | dev: false
1249 |
1250 | /react-is/17.0.2:
1251 | resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
1252 | dev: false
1253 |
1254 | /react-property/2.0.0:
1255 | resolution: {integrity: sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==}
1256 | dev: false
1257 |
1258 | /react-refresh/0.14.0:
1259 | resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
1260 | engines: {node: '>=0.10.0'}
1261 | dev: true
1262 |
1263 | /react-rnd/10.3.7_biqbaboplfbrettd7655fr4n2y:
1264 | resolution: {integrity: sha512-fYifqMI6xWzzajoRbxNNH2xpKagJT5o1zAY3a4eh4gKk+Eyy/9LGoBKA3eVX0yNOeD7JB+wznps4YmnU38v6Yw==}
1265 | peerDependencies:
1266 | react: '>=16.3.0'
1267 | react-dom: '>=16.3.0'
1268 | dependencies:
1269 | re-resizable: 6.9.6_biqbaboplfbrettd7655fr4n2y
1270 | react: 18.2.0
1271 | react-dom: 18.2.0_react@18.2.0
1272 | react-draggable: 4.4.4_biqbaboplfbrettd7655fr4n2y
1273 | tslib: 2.3.1
1274 | dev: false
1275 |
1276 | /react-transition-group/4.4.5_biqbaboplfbrettd7655fr4n2y:
1277 | resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
1278 | peerDependencies:
1279 | react: '>=16.6.0'
1280 | react-dom: '>=16.6.0'
1281 | dependencies:
1282 | '@babel/runtime': 7.18.9
1283 | dom-helpers: 5.2.1
1284 | loose-envify: 1.4.0
1285 | prop-types: 15.8.1
1286 | react: 18.2.0
1287 | react-dom: 18.2.0_react@18.2.0
1288 | dev: false
1289 |
1290 | /react/18.2.0:
1291 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
1292 | engines: {node: '>=0.10.0'}
1293 | dependencies:
1294 | loose-envify: 1.4.0
1295 | dev: false
1296 |
1297 | /regenerator-runtime/0.13.9:
1298 | resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
1299 | dev: false
1300 |
1301 | /resolve/1.22.1:
1302 | resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
1303 | hasBin: true
1304 | dependencies:
1305 | is-core-module: 2.10.0
1306 | path-parse: 1.0.7
1307 | supports-preserve-symlinks-flag: 1.0.0
1308 | dev: true
1309 |
1310 | /ret/0.1.15:
1311 | resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==}
1312 | engines: {node: '>=0.12'}
1313 | dev: false
1314 |
1315 | /rollup/2.77.3:
1316 | resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==}
1317 | engines: {node: '>=10.0.0'}
1318 | hasBin: true
1319 | optionalDependencies:
1320 | fsevents: 2.3.2
1321 | dev: true
1322 |
1323 | /safe-buffer/5.1.2:
1324 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
1325 | dev: true
1326 |
1327 | /scheduler/0.23.0:
1328 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
1329 | dependencies:
1330 | loose-envify: 1.4.0
1331 | dev: false
1332 |
1333 | /selderee/0.6.0:
1334 | resolution: {integrity: sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==}
1335 | dependencies:
1336 | parseley: 0.7.0
1337 | dev: false
1338 |
1339 | /semver/6.3.0:
1340 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
1341 | hasBin: true
1342 | dev: true
1343 |
1344 | /source-map-js/1.0.2:
1345 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
1346 | engines: {node: '>=0.10.0'}
1347 | dev: true
1348 |
1349 | /sourcemap-codec/1.4.8:
1350 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
1351 | dev: true
1352 |
1353 | /style-to-js/1.1.1:
1354 | resolution: {integrity: sha512-RJ18Z9t2B02sYhZtfWKQq5uplVctgvjTfLWT7+Eb1zjUjIrWzX5SdlkwLGQozrqarTmEzJJ/YmdNJCUNI47elg==}
1355 | dependencies:
1356 | style-to-object: 0.3.0
1357 | dev: false
1358 |
1359 | /style-to-object/0.3.0:
1360 | resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==}
1361 | dependencies:
1362 | inline-style-parser: 0.1.1
1363 | dev: false
1364 |
1365 | /supports-color/5.5.0:
1366 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
1367 | engines: {node: '>=4'}
1368 | dependencies:
1369 | has-flag: 3.0.0
1370 | dev: true
1371 |
1372 | /supports-preserve-symlinks-flag/1.0.0:
1373 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
1374 | engines: {node: '>= 0.4'}
1375 | dev: true
1376 |
1377 | /tiny-warning/1.0.3:
1378 | resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
1379 | dev: false
1380 |
1381 | /to-fast-properties/2.0.0:
1382 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
1383 | engines: {node: '>=4'}
1384 | dev: true
1385 |
1386 | /tslib/2.3.1:
1387 | resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
1388 | dev: false
1389 |
1390 | /typescript/4.7.4:
1391 | resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
1392 | engines: {node: '>=4.2.0'}
1393 | hasBin: true
1394 | dev: true
1395 |
1396 | /update-browserslist-db/1.0.5_browserslist@4.21.3:
1397 | resolution: {integrity: sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==}
1398 | hasBin: true
1399 | peerDependencies:
1400 | browserslist: '>= 4.21.0'
1401 | dependencies:
1402 | browserslist: 4.21.3
1403 | escalade: 3.1.1
1404 | picocolors: 1.0.0
1405 | dev: true
1406 |
1407 | /vite/3.0.7:
1408 | resolution: {integrity: sha512-dILhvKba1mbP1wCezVQx/qhEK7/+jVn9ciadEcyKMMhZpsuAi/eWZfJRMkmYlkSFG7Qq9NvJbgFq4XOBxugJsA==}
1409 | engines: {node: ^14.18.0 || >=16.0.0}
1410 | hasBin: true
1411 | peerDependencies:
1412 | less: '*'
1413 | sass: '*'
1414 | stylus: '*'
1415 | terser: ^5.4.0
1416 | peerDependenciesMeta:
1417 | less:
1418 | optional: true
1419 | sass:
1420 | optional: true
1421 | stylus:
1422 | optional: true
1423 | terser:
1424 | optional: true
1425 | dependencies:
1426 | esbuild: 0.14.54
1427 | postcss: 8.4.16
1428 | resolve: 1.22.1
1429 | rollup: 2.77.3
1430 | optionalDependencies:
1431 | fsevents: 2.3.2
1432 | dev: true
1433 |
--------------------------------------------------------------------------------
/public/61v-62r.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/61v-62r.jpg
--------------------------------------------------------------------------------
/public/6v-13r-infrared.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/6v-13r-infrared.jpg
--------------------------------------------------------------------------------
/public/6v-13r.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/6v-13r.jpg
--------------------------------------------------------------------------------
/public/88v-89r.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/88v-89r.jpg
--------------------------------------------------------------------------------
/public/92v-93r.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/92v-93r.jpg
--------------------------------------------------------------------------------
/public/favicon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/liber-floridus-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/liber-floridus-2.jpg
--------------------------------------------------------------------------------
/public/ultramarine.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ugent-library/mmmonk-annotation-demo/baef22305a8ea5b8ee948ccabe1ecfeace895d15/public/ultramarine.jpg
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import Paper from "@material-ui/core/Paper"
3 | import AppBar from "@material-ui/core/AppBar"
4 | import Toolbar from "@material-ui/core/Toolbar"
5 | import Typography from "@material-ui/core/Typography"
6 | import { createTheme, ThemeProvider } from "@material-ui/core"
7 | import { categoryModel } from "./config"
8 | import { hydratedAnnotations } from "./data"
9 | import pages from "./pages.json"
10 | import Panels from "./components/Panels"
11 | import Viewer from "./components/Viewer"
12 | import "@fontsource/roboto"
13 |
14 | type AnnotationContext = {
15 | activeAnnotations: AnnotationState
16 | setActiveAnnotations: React.Dispatch>
17 | }
18 |
19 | export const AnnotationContext = React.createContext(null!)
20 |
21 | const defaultCategories = categoryModel.map(category => ({
22 | ...category,
23 | enabled: category.enabledByDefault,
24 | }))
25 |
26 | const defaultView = {
27 | pageIndex: 0,
28 | layerIndex: 0,
29 | }
30 |
31 | const theme = createTheme({
32 | palette: {
33 | primary: {
34 | main: "#1976d2",
35 | },
36 | },
37 | })
38 |
39 | function App() {
40 | const [activeAnnotations, setActiveAnnotations] =
41 | React.useState([])
42 |
43 | const viewState = React.useState(defaultView)
44 | const [view] = viewState
45 | const pageId = pages.items[view.pageIndex].id
46 |
47 | const categoryState = React.useState(defaultCategories)
48 | const [enabledCategories] = categoryState
49 |
50 | const filteredAnnotations = hydratedAnnotations.filter(annotation => {
51 | const annotationIsOnCurrentCanvas = annotation.target.source === pageId
52 | const annotationIsFromEnabledCategory = enabledCategories.find(
53 | cat => cat.id === annotation.category.id
54 | )?.enabled
55 | return annotationIsOnCurrentCanvas && annotationIsFromEnabledCategory
56 | })
57 |
58 | return (
59 |
60 |
61 |
62 |
63 | Liber floridus
64 |
65 |
66 |
69 |
80 |
81 |
82 |
83 | )
84 | }
85 |
86 | export default App
87 |
--------------------------------------------------------------------------------
/src/components/AnnotationBody.tsx:
--------------------------------------------------------------------------------
1 | function AnnotationBody({
2 | body,
3 | preview = false,
4 | }: {
5 | body: AnnotationBody
6 | preview?: boolean
7 | }) {
8 | const { format, value } = body
9 | switch (format) {
10 | case "text/plain":
11 | return (
12 |
15 | )
16 | case "text/html":
17 | const html = preview
18 | ? // Remove images, links and bibliography from preview
19 | value
20 | .replace(/ /g, "")
21 | .replace(/]*>|<\/a>/g, "")
22 | .replace(/.*?<\/section>/g, "")
23 | : value
24 | return (
25 |
29 | )
30 | }
31 | }
32 |
33 | export default AnnotationBody
34 |
--------------------------------------------------------------------------------
/src/components/AnnotationList.tsx:
--------------------------------------------------------------------------------
1 | import { Grid, Typography, Divider, SvgIcon } from "@material-ui/core"
2 | import AnnotationBody from "../components/AnnotationBody"
3 | import { useAnnotations } from "../hooks/useAnnotations"
4 |
5 | function AnnotationList({
6 | annotations,
7 | categoryState,
8 | }: {
9 | annotations: HydratedAnnotation[]
10 | categoryState: CategoryState
11 | }) {
12 | const [enabledCategories] = categoryState
13 | const filteredAnnotations = annotations.filter(
14 | annotation =>
15 | enabledCategories.find(category => category.id === annotation.category.id)
16 | ?.enabled
17 | )
18 | return (
19 |
20 | {filteredAnnotations.map((annotation, i) => (
21 |
22 | ))}
23 |
24 | )
25 | }
26 | export default AnnotationList
27 |
28 | function AnnotationItem({ annotation }: { annotation: HydratedAnnotation }) {
29 | const { activeAnnotations, activateAnnotation } = useAnnotations()
30 | const isActive = activeAnnotations.find(anno => anno.id === annotation.id)
31 | return (
32 | <>
33 |
34 | !isActive && activateAnnotation(annotation.id, false)}
36 | className={
37 | isActive ? "anno-card anno-card-open" : "anno-card anno-card-closed"
38 | }
39 | >
40 |
41 |
42 |
43 |
44 |
45 |
46 |
51 |
52 |
53 |
54 | {annotation.category.name}
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
74 | {isActive ? "Opened" : "View details"}
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | >
84 | )
85 | }
86 |
--------------------------------------------------------------------------------
/src/components/AnnotationPanel.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Typography,
3 | Divider,
4 | Grid,
5 | Link,
6 | SvgIcon,
7 | IconButton,
8 | } from "@material-ui/core"
9 | import CloseIcon from "@material-ui/icons/Close"
10 | import AnnotationBody from "./AnnotationBody"
11 | import { hydratedAnnotations } from "../data"
12 | import { useAnnotations } from "../hooks/useAnnotations"
13 |
14 | function formatDate(dateString: string) {
15 | return new Date(dateString).toLocaleDateString("en-UK", {
16 | year: "numeric",
17 | month: "long",
18 | day: "numeric",
19 | })
20 | }
21 |
22 | type AnnotationPanelProps = {
23 | annotation: HydratedAnnotation
24 | }
25 |
26 | function AnnotationPanel({ annotation }: AnnotationPanelProps) {
27 | const { activeAnnotations, closeAnnotation, togglePinAnnotation } =
28 | useAnnotations()
29 |
30 | const currentPanel = activeAnnotations.find(
31 | panel => panel.id === annotation.id
32 | )
33 | const isPinned = currentPanel?.pinned
34 |
35 | return (
36 |
37 |
38 |
97 |
98 |
99 | {annotation.crossReferences?.length ? (
100 |
101 | ) : null}
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | Annotated by
112 |
113 |
114 |
115 | {annotation.creator.name}
116 |
117 |
118 |
119 |
120 |
121 | Created on
122 |
123 |
124 |
125 | {formatDate(annotation.created)}
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | )
135 | }
136 |
137 | export default AnnotationPanel
138 |
139 | function CrossReferences({ refs }: { refs: { id: string }[] }) {
140 | const { activateAnnotation } = useAnnotations()
141 | const hydratedRefs = refs.map(ref =>
142 | hydratedAnnotations.find(anno => anno.id === ref.id)
143 | )
144 | return (
145 |
146 | See also
147 |
148 | {hydratedRefs.map(ref => {
149 | if (ref === undefined) {
150 | throw new Error("Cross-reference does not exist in annotations")
151 | } else {
152 | return (
153 |
154 | activateAnnotation(ref.id)}>
155 |
161 |
162 | Annotation
163 |
164 |
165 |
166 |
170 | in {ref.category.name}
171 |
172 |
173 |
174 |
175 |
176 |
177 | )
178 | }
179 | })}
180 |
181 |
182 | )
183 | }
184 |
--------------------------------------------------------------------------------
/src/components/CategoryList.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Grid,
3 | Checkbox,
4 | Typography,
5 | SvgIcon,
6 | FormControl,
7 | FormLabel,
8 | FormGroup,
9 | FormControlLabel,
10 | } from "@material-ui/core"
11 | import { categoryModel } from "../config"
12 | import { hydratedAnnotations as allAnnotations } from "../data"
13 |
14 | type CategoryItem = Category & {
15 | occurencesInManifest: number
16 | occurencesOnPage: number
17 | }
18 |
19 | type CategoryListProps = {
20 | pageId: string
21 | categoryState: CategoryState
22 | }
23 |
24 | function CategoryList({ pageId, categoryState }: CategoryListProps) {
25 | const categories: CategoryItem[] = categoryModel.map(category => {
26 | const inManifest = allAnnotations.filter(
27 | annotation => annotation.category.id === category.id
28 | )
29 |
30 | const onPage = inManifest.filter(annotation => {
31 | return annotation.target.source === pageId
32 | })
33 |
34 | return {
35 | ...category,
36 | occurencesInManifest: inManifest.length,
37 | occurencesOnPage: onPage.length,
38 | }
39 | })
40 |
41 | const [enabledCategories, setEnabledCategories] = categoryState
42 |
43 | function toggleAllCategories() {
44 | setEnabledCategories(prev =>
45 | prev.map(category => ({
46 | ...category,
47 | enabled: allCategoriesState !== "all",
48 | }))
49 | )
50 | }
51 |
52 | function calculateAllCategoriesState() {
53 | if (enabledCategories.every(category => !category.enabled)) {
54 | return "none"
55 | } else if (enabledCategories.every(category => category.enabled)) {
56 | return "all"
57 | } else {
58 | return "some"
59 | }
60 | }
61 |
62 | const allCategoriesState = calculateAllCategoriesState()
63 |
64 | return (
65 |
66 |
67 |
68 | Categorieën
69 |
70 |
71 |
80 | }
81 | label="All categories"
82 | />
83 | {categories.map(category => (
84 |
89 | ))}
90 |
91 |
92 |
93 | )
94 | }
95 |
96 | export default CategoryList
97 |
98 | type ItemProps = {
99 | category: CategoryItem
100 | categoryState: CategoryState
101 | }
102 |
103 | function Item({ category, categoryState }: ItemProps) {
104 | const [enabledCategories, setEnabledCategories] = categoryState
105 |
106 | const isEnabled = enabledCategories.find(
107 | ({ id }) => id === category.id
108 | )?.enabled
109 |
110 | function toggleCategory() {
111 | setEnabledCategories(existingEnabledCategories =>
112 | existingEnabledCategories.map(cat =>
113 | cat.id === category.id ? { ...cat, enabled: !isEnabled } : cat
114 | )
115 | )
116 | }
117 |
118 | return (
119 |
127 | }
128 | label={
129 |
130 |
131 |
136 |
137 |
138 |
139 |
140 | {category.name}
141 |
142 |
143 |
144 | {category.occurencesOnPage}{" "}
145 |
146 | / {category.occurencesInManifest}
147 |
148 |
149 |
150 |
151 |
152 |
153 | }
154 | />
155 | )
156 | }
157 |
--------------------------------------------------------------------------------
/src/components/LayerList.tsx:
--------------------------------------------------------------------------------
1 | import Radio from "@material-ui/core/Radio"
2 | import RadioGroup from "@material-ui/core/RadioGroup"
3 | import FormControlLabel from "@material-ui/core/FormControlLabel"
4 | import FormControl from "@material-ui/core/FormControl"
5 | import pages from "../pages.json"
6 |
7 | type LayerListProps = {
8 | viewState: ViewState
9 | }
10 |
11 | function LayerList({ viewState }: LayerListProps) {
12 | const [view, setView] = viewState
13 | const layersOnThisPage = pages.items[view.pageIndex].body?.items || []
14 |
15 | if (layersOnThisPage.length) {
16 | function handleChange(value: string) {
17 | setView(prev => ({
18 | ...prev,
19 | layerIndex: parseInt(value),
20 | }))
21 | }
22 |
23 | return (
24 |
25 |
26 | handleChange(e.target.value)}
31 | >
32 | {layersOnThisPage.length ? (
33 | layersOnThisPage.map((layer, i) => (
34 | }
37 | label={layer.label.en[0]}
38 | key={layer.label.en[0]}
39 | />
40 | ))
41 | ) : (
42 | }
45 | label="Default"
46 | />
47 | )}
48 |
49 |
50 |
51 | )
52 | } else {
53 | return (
54 |
55 |
56 |
57 | }
60 | label="Default"
61 | />
62 |
63 |
64 |
65 | )
66 | }
67 | }
68 |
69 | export default LayerList
70 |
--------------------------------------------------------------------------------
/src/components/MainPanel.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode, useState } from "react"
2 | import LayerList from "./LayerList"
3 | import CategoryList from "./CategoryList"
4 | import AnnotationList from "./AnnotationList"
5 | import ExpandMoreIcon from "@material-ui/icons/ExpandMore"
6 | import { withStyles } from "@material-ui/core/styles"
7 | import { Typography } from "@material-ui/core"
8 | import MuiAccordion from "@material-ui/core/Accordion"
9 | import MuiAccordionSummary from "@material-ui/core/AccordionSummary"
10 | import AccordionDetails from "@material-ui/core/AccordionDetails"
11 |
12 | type MainPanelProps = {
13 | annotations: HydratedAnnotation[]
14 | pageId: string
15 | categoryState: CategoryState
16 | viewState: ViewState
17 | }
18 |
19 | function MainPanel({
20 | annotations,
21 | pageId,
22 | categoryState,
23 | viewState,
24 | }: MainPanelProps) {
25 | return (
26 | <>
27 |
30 |
33 |
39 | >
40 | )
41 | }
42 |
43 | export default MainPanel
44 |
45 | type SectionProps = {
46 | heading: string
47 | children: ReactNode
48 | closedByDefault?: boolean
49 | }
50 |
51 | function Section({ heading, children, closedByDefault = false }: SectionProps) {
52 | const [expanded, setExpanded] = useState(!closedByDefault)
53 | return (
54 |
55 | }
57 | onClick={() => setExpanded(!expanded)}
58 | >
59 | {heading}
60 |
61 |
62 | {children}
63 |
64 |
65 | )
66 | }
67 |
68 | const Accordion = withStyles({
69 | root: {
70 | border: "none",
71 | borderRadius: 0,
72 | boxShadow: "none",
73 | "&:not(:last-child)": {
74 | borderBottom: "1px solid rgba(0, 0, 0, .38)",
75 | },
76 | "&$expanded": {
77 | margin: "auto",
78 | },
79 | },
80 | expanded: {},
81 | })(MuiAccordion)
82 |
83 | const AccordionSummary = withStyles({
84 | root: {
85 | margin: 0,
86 | minHeight: 56,
87 | "&$expanded": {
88 | margin: 0,
89 | minHeight: 56,
90 | },
91 | },
92 | content: {
93 | "&$expanded": {
94 | margin: "0",
95 | },
96 | },
97 | expanded: {},
98 | })(MuiAccordionSummary)
99 |
--------------------------------------------------------------------------------
/src/components/PageNav.tsx:
--------------------------------------------------------------------------------
1 | import { SvgIcon, IconButton, Typography } from "@material-ui/core"
2 | import { useAnnotations } from "../hooks/useAnnotations"
3 | import pages from "../pages.json"
4 |
5 | const total = pages.items.length
6 |
7 | type PageNavProps = {
8 | viewState: ViewState
9 | }
10 |
11 | function PageNav({ viewState }: PageNavProps) {
12 | const [view, setView] = viewState
13 | const { pageIndex } = view
14 |
15 | const { closeAllExceptPinnedAnnotations } = useAnnotations()
16 |
17 | function preloadImg(src: string) {
18 | const img = new Image()
19 | img.src = src
20 | }
21 |
22 | function handleHover() {
23 | if (pageIndex + 1 < total) {
24 | const nextPage = pages.items[pageIndex + 1]
25 | const { src } = nextPage.body.items
26 | ? nextPage.body.items[view.layerIndex]
27 | : nextPage.body
28 | preloadImg(src)
29 | }
30 | }
31 |
32 | function next() {
33 | closeAllExceptPinnedAnnotations()
34 | if (pageIndex + 1 < total)
35 | setView(prev => ({
36 | pageIndex: prev.pageIndex + 1,
37 | layerIndex: 0,
38 | }))
39 | }
40 | function prev() {
41 | closeAllExceptPinnedAnnotations()
42 | if (pageIndex > 0)
43 | setView(prev => ({
44 | pageIndex: prev.pageIndex - 1,
45 | layerIndex: 0,
46 | }))
47 | }
48 | return (
49 |
50 |
51 |
56 |
57 |
58 |
59 |
60 |
= total}
62 | onClick={next}
63 | onMouseEnter={handleHover}
64 | aria-label="Next item"
65 | >
66 |
67 |
68 |
69 |
70 |
71 |
72 | {pageIndex + 1} of {total}
73 |
74 |
75 | )
76 | }
77 |
78 | export default PageNav
79 |
--------------------------------------------------------------------------------
/src/components/Panels.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Rnd } from "react-rnd"
3 | import MainPanel from "./MainPanel"
4 | import AnnotationPanel from "./AnnotationPanel"
5 | import { hydratedAnnotations } from "../data"
6 | import { useAnnotations } from "../hooks/useAnnotations"
7 |
8 | type PanelsProps = {
9 | annotations: HydratedAnnotation[]
10 | pageId: string
11 | categoryState: CategoryState
12 | viewState: ViewState
13 | }
14 |
15 | function Panels({
16 | annotations,
17 | pageId,
18 | categoryState,
19 | viewState,
20 | }: PanelsProps) {
21 | const { activeAnnotations } = useAnnotations()
22 |
23 | return (
24 |
25 |
31 | {activeAnnotations.map(activeAnnotation => {
32 | const hydratedAnnotation = hydratedAnnotations.find(
33 | ({ id }) => id === activeAnnotation.id
34 | )
35 | return hydratedAnnotation ? (
36 |
40 | ) : null
41 | })}
42 |
43 | )
44 | }
45 |
46 | function PanelArea({ children }: { children: React.ReactNode }) {
47 | const arrayChildren = React.Children.toArray(children)
48 | return (
49 |
50 | {React.Children.map(arrayChildren, child => (
51 |
52 | {React.cloneElement(child as React.ReactElement)}
53 |
54 | ))}
55 |
56 | )
57 | }
58 |
59 | export default Panels
60 |
61 | function ResizablePanel({ children }: { children: React.ReactNode }) {
62 | return (
63 |
74 | {children}
75 |
76 | )
77 | }
78 |
--------------------------------------------------------------------------------
/src/components/Viewer.tsx:
--------------------------------------------------------------------------------
1 | import parse, { domToReact, attributesToProps } from "html-react-parser"
2 | import pages from "../pages.json"
3 | import { useAnnotations } from "../hooks/useAnnotations"
4 | import PageNav from "./PageNav"
5 |
6 | type ViewerProps = {
7 | viewState: ViewState
8 | annotations: HydratedAnnotation[]
9 | }
10 |
11 | function Viewer({ viewState, annotations }: ViewerProps) {
12 | const [view] = viewState
13 | const page = pages.items[view.pageIndex]
14 | const { src, width, height } = page.body.items
15 | ? page.body.items[view.layerIndex]
16 | : page.body
17 |
18 | return (
19 |
20 |
28 |
29 |
30 |
31 |
32 |
33 | )
34 | }
35 | export default Viewer
36 |
37 | type TargetsProps = {
38 | annotations: HydratedAnnotation[]
39 | }
40 |
41 | function Targets({ annotations }: TargetsProps) {
42 | const targets = annotations.map(function (annotation) {
43 | if (annotation.target.selector.type === "SvgSelector") {
44 | return
45 | }
46 | })
47 |
48 | return <>{targets}>
49 | }
50 |
51 | type TargetProps = {
52 | annotation: HydratedAnnotation
53 | }
54 |
55 | function Target({ annotation }: TargetProps) {
56 | if (annotation.target) {
57 | const { activateAnnotation, activeAnnotations } = useAnnotations()
58 | const isActive = activeAnnotations.find(anno => anno.id === annotation.id)
59 | const options = {
60 | replace: (domNode: any) => {
61 | const isValidNode = domNode.name === "svg" && domNode.children.length
62 | if (isValidNode) {
63 | const props = attributesToProps(domNode.attribs)
64 | return (
65 | !isActive && activateAnnotation(annotation.id)}
69 | >
70 | {domToReact(domNode.children)}
71 |
72 | )
73 | }
74 | },
75 | }
76 | return <>{parse(annotation.target.selector.value, options)}>
77 | } else return null
78 | }
79 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | import PaletteIcon from "@material-ui/icons/PaletteSharp"
2 | import ImageIcon from "@material-ui/icons/ImageSharp"
3 | import TextFieldsIcon from "@material-ui/icons/TextFieldsSharp"
4 | import LayersIcon from "@material-ui/icons/LayersSharp"
5 | import TranslateIcon from "@material-ui/icons/Translate"
6 |
7 | export const categoryModel = [
8 | {
9 | id: "iconography",
10 | name: "Iconography",
11 | icon: ImageIcon,
12 | enabledByDefault: true,
13 | },
14 | {
15 | id: "pigments",
16 | name: "Pigments",
17 | icon: PaletteIcon,
18 | enabledByDefault: true,
19 | },
20 | {
21 | id: "transcriptions",
22 | name: "Transcriptions",
23 | icon: TextFieldsIcon,
24 | enabledByDefault: true,
25 | },
26 | {
27 | id: "translations",
28 | name: "Translations",
29 | icon: TranslateIcon,
30 | enabledByDefault: true,
31 | },
32 | {
33 | id: "material",
34 | name: "Material technical information",
35 | icon: LayersIcon,
36 | enabledByDefault: true,
37 | },
38 | ] as const
39 |
--------------------------------------------------------------------------------
/src/data.ts:
--------------------------------------------------------------------------------
1 | import annotationPage from "./annotations.json"
2 | import { categoryModel } from "./config"
3 |
4 | const annotations = annotationPage.items as Annotation[]
5 |
6 | export const hydratedAnnotations: HydratedAnnotation[] = annotations.map(
7 | annotation => ({
8 | ...annotation,
9 | category: categoryModel.find(cat => cat.id === annotation.category)!,
10 | })
11 | )
12 |
--------------------------------------------------------------------------------
/src/hooks/useAnnotations.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { AnnotationContext } from "../App"
3 |
4 | function useAnnotations() {
5 | const context = React.useContext(AnnotationContext)
6 |
7 | if (!context) {
8 | throw new Error("useAnnotations must be used within a AnnotationProvider")
9 | }
10 |
11 | const { activeAnnotations, setActiveAnnotations } = context
12 |
13 | function activateAnnotation(id: string, scrollToCard: boolean = true): void {
14 | if (scrollToCard) {
15 | const card = document.querySelector(`[data-annotation-id="${id}"]`)
16 | card?.scrollIntoView({ block: "center" })
17 | }
18 | setActiveAnnotations(prev => {
19 | const pinnedPanels = prev.filter(annotation => annotation.pinned)
20 | const newPanel = {
21 | id,
22 | pinned: false,
23 | }
24 | return [...pinnedPanels, newPanel]
25 | })
26 | }
27 |
28 | function closeAnnotation(id: string): void {
29 | setActiveAnnotations(prev => {
30 | const newActiveAnnotations = prev.filter(
31 | annotation => annotation.id !== id
32 | )
33 | return newActiveAnnotations
34 | })
35 | }
36 |
37 | function closeAllExceptPinnedAnnotations(): void {
38 | setActiveAnnotations(prev => {
39 | return prev.filter(annotation => annotation.pinned)
40 | })
41 | }
42 |
43 | function togglePinAnnotation(id: string): void {
44 | const current = activeAnnotations.find(annotation => annotation.id === id)
45 | const isPinned = current?.pinned
46 | setActiveAnnotations(prev => {
47 | return prev.map(annotation => {
48 | return annotation.id === id
49 | ? { ...annotation, pinned: !isPinned }
50 | : annotation
51 | })
52 | })
53 | }
54 |
55 | return {
56 | activeAnnotations,
57 | activateAnnotation,
58 | closeAnnotation,
59 | closeAllExceptPinnedAnnotations,
60 | togglePinAnnotation,
61 | }
62 | }
63 |
64 | export { useAnnotations }
65 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import ReactDOM from "react-dom/client"
3 | import App from "./App"
4 |
5 | ReactDOM.createRoot(
6 | document.getElementById("annotation-demo") as HTMLElement
7 | ).render(
8 |
9 |
10 |
11 | )
12 |
--------------------------------------------------------------------------------
/src/pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "items": [
3 | {
4 | "id": "folio-1",
5 | "body": {
6 | "type": "Choice",
7 | "items": [
8 | {
9 | "id": "folio-1-natural",
10 | "type": "Image",
11 | "src": "6v-13r.jpg",
12 | "height": 2760,
13 | "width": 3999,
14 | "label": {
15 | "en": ["Natural light"]
16 | }
17 | },
18 | {
19 | "id": "folio-1-infrared",
20 | "type": "Image",
21 | "src": "6v-13r-infrared.jpg",
22 | "height": 2760,
23 | "width": 3999,
24 | "label": {
25 | "en": ["Infrared"]
26 | }
27 | }
28 | ]
29 | }
30 | },
31 | {
32 | "id": "folio-2",
33 | "body": {
34 | "type": "Image",
35 | "src": "61v-62r.jpg",
36 | "height": 2760,
37 | "width": 4000
38 | }
39 | },
40 | {
41 | "id": "folio-3",
42 | "body": {
43 | "type": "Image",
44 | "src": "88v-89r.jpg",
45 | "height": 2760,
46 | "width": 4000
47 | }
48 | },
49 | {
50 | "id": "folio-4",
51 | "body": {
52 | "type": "Image",
53 | "src": "92v-93r.jpg",
54 | "height": 3246,
55 | "width": 4000
56 | }
57 | }
58 | ]
59 | }
60 |
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | #annotation-demo {
2 | width: 100%;
3 | height: 100%;
4 | }
5 |
6 | .app {
7 | --app-padding: 6px;
8 | --color-selector-rgb: 255, 245, 0;
9 | --color-muted: rgba(0, 0, 0, 0.4);
10 | --color-main: #1967d2;
11 | --color-focus: #e8f0ff;
12 | --window-background: #000;
13 | box-sizing: border-box;
14 | background: rgb(220, 220, 220);
15 | padding: var(--app-padding);
16 | height: 100%;
17 | }
18 |
19 | .window {
20 | background: var(--window-background) !important;
21 | height: 100% !important;
22 | }
23 |
24 | .window-content {
25 | display: flex;
26 | height: calc(100% - 50px);
27 | }
28 |
29 | .top-toolbar {
30 | border-top: 2px solid var(--color-main);
31 | background-color: #fff;
32 | }
33 |
34 | .viewport {
35 | position: relative;
36 | width: 100%;
37 | height: 100%;
38 | }
39 |
40 | .panel-area {
41 | height: 100%;
42 | background: white;
43 | display: flex;
44 | flex-direction: row-reverse;
45 | }
46 |
47 | .panel {
48 | position: relative;
49 | height: 100%;
50 | overflow: auto;
51 | border-left: 1px solid #21212114;
52 | }
53 |
54 | .anno-overline {
55 | letter-spacing: 1.5px !important;
56 | font-size: 10.5px !important;
57 | color: var(--color-muted);
58 | }
59 |
60 | .anno-icon {
61 | color: var(--color-muted);
62 | }
63 |
64 | .anno-cards {
65 | list-style: none;
66 | padding-inline: 0;
67 | padding-block: 0.5rem;
68 | margin: 0;
69 | }
70 |
71 | .anno-card {
72 | all: unset;
73 | --card-bg: white;
74 | background-color: var(--card-bg);
75 | box-sizing: border-box;
76 | width: 100%;
77 | display: flex;
78 | padding-block: 0.5rem;
79 | padding-inline: 1rem;
80 | cursor: pointer;
81 | }
82 |
83 | .anno-card:hover {
84 | --card-bg: #f7f7f7;
85 | }
86 |
87 | .anno-card-closed {
88 | border-left: 2px solid transparent;
89 | }
90 |
91 | .anno-card-open,
92 | .anno-card-open:hover {
93 | --card-bg: var(--color-focus);
94 | border-left: 2px solid var(--color-main);
95 | }
96 |
97 | .anno-card .format-html h1 {
98 | font-weight: 400;
99 | font-size: 1rem;
100 | }
101 |
102 | .anno-card .format-html p {
103 | margin: 0;
104 | }
105 |
106 | .anno-card main {
107 | max-height: 10rem;
108 | overflow: hidden;
109 | position: relative;
110 | }
111 |
112 | .anno-card main:before {
113 | content: "";
114 | width: 100%;
115 | height: 100%;
116 | position: absolute;
117 | left: 0;
118 | top: 0;
119 | background: linear-gradient(transparent 2rem, var(--card-bg) 10rem);
120 | }
121 |
122 | .anno-panel-article {
123 | display: flex;
124 | row-gap: 1rem;
125 | height: 100%;
126 | flex-direction: column;
127 | justify-content: space-between;
128 | }
129 |
130 | .anno-panel-meta {
131 | padding: 1rem;
132 | }
133 |
134 | .anno-panel-meta table {
135 | /* table-layout: fixed; */
136 | width: 100%;
137 | border-collapse: collapse;
138 | }
139 |
140 | .anno-panel-meta th {
141 | text-align: left;
142 | }
143 |
144 | .anno-panel-meta td {
145 | padding-block: 0.25rem;
146 | }
147 |
148 | .anno-panel-top {
149 | padding: 1rem;
150 | padding-top: 0.25rem;
151 | }
152 |
153 | .anno-panel .format-html h1 {
154 | font-weight: 400;
155 | font-size: 2rem;
156 | margin-bottom: 4rem;
157 | }
158 |
159 | .anno-panel section[role="doc-bibliography"],
160 | .cross-references {
161 | border-top: 1px solid var(--color-muted);
162 | margin-top: 4rem;
163 | padding-top: 0.5rem;
164 | }
165 |
166 | .anno-panel section[role="doc-bibliography"] h2,
167 | .cross-references h2 {
168 | font-size: 0.9rem;
169 | margin: 0;
170 | }
171 |
172 | .anno-panel section[role="doc-bibliography"] ul {
173 | font-size: 0.75rem;
174 | list-style: none;
175 | padding: 0;
176 | }
177 |
178 | .color-muted {
179 | color: var(--color-muted);
180 | }
181 |
182 | .layer-list,
183 | .category-list {
184 | padding: 1rem;
185 | padding-top: 0;
186 | }
187 |
188 | .canvas path,
189 | .canvas polygon,
190 | .canvas ellipse,
191 | .canvas circle,
192 | .canvas rect {
193 | pointer-events: all;
194 | transition: fill 0.15s;
195 | fill: transparent;
196 | stroke: rgb(var(--color-selector-rgb));
197 | stroke-width: 2;
198 | vector-effect: non-scaling-stroke;
199 | }
200 |
201 | .selector.highlight path,
202 | .selector.highlight polygon,
203 | .selector.highlight circle,
204 | .selector.highlight rect,
205 | .selector.highlight ellipse,
206 | .selector:hover path,
207 | .selector:hover polygon,
208 | .selector:hover circle,
209 | .selector:hover rect,
210 | .selector:hover ellipse {
211 | fill: rgba(var(--color-selector-rgb), 0.3);
212 | cursor: pointer;
213 | }
214 |
215 | @keyframes highlight {
216 | from {
217 | stroke-width: 5;
218 | }
219 | to {
220 | stroke-width: 2;
221 | }
222 | }
223 |
224 | .selector.highlight path,
225 | .selector.highlight polygon,
226 | .selector.highlight circle,
227 | .selector.highlight rect,
228 | .selector.highlight ellipse {
229 | animation: highlight 1s;
230 | }
231 |
232 | .folio-nav {
233 | width: 100%;
234 | height: 5rem;
235 | background-color: rgba(255, 255, 255, 0.5);
236 | position: absolute;
237 | bottom: 0;
238 | left: 0;
239 | display: flex;
240 | flex-direction: column;
241 | align-items: center;
242 | }
243 |
244 | .format-plain p,
245 | .format-html {
246 | font-family: "Georgia", serif;
247 | font-size: 1rem;
248 | font-weight: 400;
249 | line-height: 1.5;
250 | letter-spacing: 0.00938em;
251 | }
252 |
253 | .format-html img {
254 | max-width: 100%;
255 | }
256 |
257 | .format-html a {
258 | color: var(--color-main);
259 | }
260 |
261 | .format-plain p {
262 | margin: 0;
263 | }
264 |
265 | .format-html h1,
266 | section[role="doc-bibliography"] h2,
267 | .cross-references h2 {
268 | font-style: inherit;
269 | font-family: "Roboto", "Helvetica", "Arial", sans-serif;
270 | font-weight: 400;
271 | margin: 0;
272 | }
273 |
274 | .anno-top-meta {
275 | margin-top: 4rem;
276 | }
277 |
278 | .anno-top-meta p {
279 | font-size: 0.8rem;
280 | }
281 |
282 | .cross-references ul {
283 | list-style: none;
284 | padding-inline: 0;
285 | }
286 |
287 | .cross-references button {
288 | all: unset;
289 | --card-bg: white;
290 | background-color: var(--card-bg);
291 | box-sizing: border-box;
292 | width: 100%;
293 | display: flex;
294 | cursor: pointer;
295 | color: var(--color-main);
296 | }
297 |
--------------------------------------------------------------------------------
/src/types/global.d.ts:
--------------------------------------------------------------------------------
1 | import { categoryModel } from "../config"
2 |
3 | declare global {
4 | type View = {
5 | pageIndex: number
6 | layerIndex: number
7 | }
8 | type ViewState = [View, React.Dispatch>]
9 |
10 | type CategoryId = typeof categoryModel[number]["id"]
11 | type Category = {
12 | id: CategoryId
13 | enabled?: boolean
14 | name: string
15 | icon: any
16 | enabledByDefault: boolean
17 | }
18 | type CategoryState = [
19 | Category[],
20 | React.Dispatch>
21 | ]
22 |
23 | type AnnotationState = {
24 | id: string
25 | pinned: boolean
26 | }[]
27 |
28 | type AnnotationBody = {
29 | type: string
30 | language: string
31 | format: "text/plain" | "text/html"
32 | value: string
33 | }
34 |
35 | type Annotation = {
36 | "@context": string
37 | id: string
38 | type: "Annotation"
39 | motivation: string
40 | category: CategoryId
41 | target: {
42 | source: string
43 | selector: {
44 | type: "SvgSelector"
45 | value: string
46 | }
47 | }
48 | body: AnnotationBody
49 | created: "2015-10-13T13:00:00Z"
50 | creator: {
51 | id: string
52 | type: "Person" | "Organization"
53 | name: string
54 | }
55 | crossReferences?: { id: string }[]
56 | }
57 |
58 | type HydratedAnnotation = Omit & {
59 | category: Category
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite"
2 | import react from "@vitejs/plugin-react"
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | build: {
7 | assetsDir: "annotation-demo-assets",
8 | },
9 | plugins: [
10 | react({
11 | fastRefresh: false,
12 | }),
13 | ],
14 | })
15 |
--------------------------------------------------------------------------------