├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── build.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cypress.config.ts ├── cypress ├── .gitignore ├── e2e │ ├── context-menu.spec.ts │ ├── item.spec.ts │ └── keyboard.spec.ts ├── fixtures │ └── constant.ts ├── plugins │ └── index.js ├── support │ ├── commands.ts │ ├── data-test.ts │ ├── e2e.ts │ └── is-in-viewport.ts └── tsconfig.json ├── example ├── .gitignore ├── .npmignore ├── components │ ├── App.tsx │ └── Select.tsx ├── constants.ts ├── index.css ├── index.html ├── index.tsx ├── package.json ├── tsconfig.json └── yarn.lock ├── package.json ├── scss ├── _menu.scss ├── _themes.scss ├── animations │ ├── _fade.scss │ ├── _flip.scss │ ├── _scale.scss │ └── _slide.scss └── main.scss ├── src ├── components │ ├── Arrow.tsx │ ├── Item.tsx │ ├── ItemTrackerProvider.tsx │ ├── Menu.tsx │ ├── RightSlot.tsx │ ├── Separator.tsx │ ├── Submenu.tsx │ ├── keyboardController.ts │ └── utils.ts ├── constants.ts ├── core │ ├── contextMenu.ts │ ├── eventManager.ts │ └── index.ts ├── hooks │ ├── index.ts │ ├── useContextMenu.ts │ └── useItemTracker.ts ├── index.ts └── types │ └── index.ts ├── tsconfig.json ├── tsup.config.ts └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: fkhadra 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Do you want to request a *feature* or report a *bug*?** 2 | 3 | **What is the current behavior?** 4 | 5 | **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your CodeSandbox (https://codesandbox.io/s/new) example below:** 6 | 7 | **What is the expected behavior?** 8 | 9 | **Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?** 10 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Before submitting a pull request,** please make sure the following is done: 2 | 3 | 1. Fork [the repository](https://github.com/fkhadra/react-contexify) and create your branch from `master`. 4 | 2. Run `yarn` in the repository root. 5 | 3. If you've fixed a bug or added code that should be tested, add tests! 6 | 4. Run `yarn start` in the example folder to test your changes. 7 | 5. Ensure the test suite passes (`yarn test`). It uses the example 8 | 6. Update the readme if needed or the documentation 9 | 7. Update the typescript definition is needed 10 | 8. Make sure your code lints (`yarn lint --fix`). 11 | 12 | **Learn more about contributing [here](https://github.com/fkhadra/react-contexify/blob/master/CONTRIBUTING.md)** -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: React-contexify CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Install node 12 | uses: actions/setup-node@v1 13 | with: 14 | node-version: '16.x' 15 | - name: Install example dependencies 16 | run: cd example && yarn 17 | - name: Install dependencies & build 18 | run: yarn 19 | - name: Run cypress 20 | uses: cypress-io/github-action@v4 21 | with: 22 | browser: chrome 23 | start: yarn start 24 | wait-on: 'http://localhost:1234' 25 | - uses: actions/upload-artifact@v1 26 | if: failure() 27 | with: 28 | name: cypress-screenshots 29 | path: cypress/screenshots 30 | 31 | - uses: actions/upload-artifact@v1 32 | if: always() 33 | with: 34 | name: cypress-videos 35 | path: cypress/videos 36 | 37 | 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | .sass-cache/ 4 | lib/ 5 | npm-debug.log 6 | coverage/ 7 | yarn-error.log* 8 | .DS_STORE 9 | .docz 10 | .vscode 11 | .cache 12 | dist 13 | *.log -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at fdkhadra@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | 5 | When contributing to this repository, please first discuss the change you wish to make via issue before making a change. 6 | 7 | Please note we have a code of conduct, please follow it in all your interactions with the project. 8 | 9 | ## General Guidelines 10 | 11 | - If adding a new feature, write the corresponding test 12 | - Ensure that nothing get broke. You can use the example for that 13 | - If applicable, update the [documentation](https://github.com/fkhadra/react-contexify-doc) 14 | - Use prettier before commiting 😭 15 | - When solving a bug, please provide the steps to reproduce it(codesandbox is our best friend for that) 16 | - Tchill 👌 17 | 18 | ## Setup 19 | 20 | ### Pre-requisites 21 | 22 | - *Node:* `^14.0.0` 23 | - *Yarn* 24 | 25 | ### Install 26 | 27 | Clone the repository and create a local branch: 28 | 29 | ```sh 30 | git clone https://github.com/fkhadra/react-contexify.git 31 | cd react-contexify 32 | 33 | git checkout -b my-branch 34 | ``` 35 | 36 | Install dependencies: 37 | 38 | ```sh 39 | yarn install 40 | ``` 41 | 42 | ### Project structure 43 | 44 | TO COMPLETE 45 | 46 | ## License 47 | By contributing, you agree that your contributions will be licensed under its MIT License. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Fadi Khadra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | screenshot 2018-10-31 at 13 32 57 2 | 3 | ![React-contexify CI](https://github.com/fkhadra/react-contexify/workflows/React-contexify%20CI/badge.svg) [![npm](https://img.shields.io/npm/dm/react-contexify.svg)]() [![npm](https://img.shields.io/npm/v/react-contexify.svg)]() [![license](https://img.shields.io/github/license/fkhadra/react-contexify.svg?maxAge=2592000)]() 4 | 5 |
6 | 7 | ![contexify](https://user-images.githubusercontent.com/5574267/100552409-500dfd80-3287-11eb-96ee-fc1d17ef50b8.gif) 8 | 9 |
10 | 11 | ## Features 12 | 13 | - Easy to set up for real, you can make it work in less than 10sec! 14 | - Super easy to customize thanks to css variables 💅 15 | - Custom position 16 | - Sub menu support 17 | - Does not go offscreen 18 | - Dark mode 🌒 19 | - Keyboard navigation + keyboard shortcut! 20 | - Built-in animations 21 | - Easy to test! 22 | - Written in Typescript 💪 23 | - Tiny! (3k gzipped) 24 | 25 | Check the documentation for more! 26 | 27 | 28 | ## Documentation 29 | 30 | Go [here](https://fkhadra.github.io/react-contexify). 31 | 32 | ## Installation 33 | 34 | Using yarn 35 | 36 | ```sh 37 | $ yarn add react-contexify 38 | ``` 39 | 40 | Using npm 41 | 42 | ```sh 43 | $ npm install --save react-contexify 44 | ``` 45 | 46 | ## The gist 47 | 48 | ```js 49 | import { Menu, Item, Separator, Submenu, useContextMenu } from 'react-contexify'; 50 | import 'react-contexify/ReactContexify.css'; 51 | 52 | const MENU_ID = 'blahblah'; 53 | 54 | function App() { 55 | const { show } = useContextMenu({ 56 | id: MENU_ID, 57 | }); 58 | 59 | function handleContextMenu(event){ 60 | show({ 61 | event, 62 | props: { 63 | key: 'value' 64 | } 65 | }) 66 | } 67 | 68 | // I'm using a single event handler for all items 69 | // but you don't have too :) 70 | const handleItemClick = ({ id, event, props }) => { 71 | switch (id) { 72 | case "copy": 73 | console.log(event, props) 74 | break; 75 | case "cut"; 76 | console.log(event, props); 77 | break; 78 | //etc... 79 | } 80 | } 81 | 82 | return ( 83 |
84 |

lorem ipsum blabladhasi blaghs blah

85 | 86 | Copy 87 | Cut 88 | 89 | Disabled 90 | 91 | 92 | Reload 93 | Do something else 94 | 95 | 96 |
97 | ); 98 | } 99 | ``` 100 | 101 | ## Contribute 102 | 103 | Any idea and suggestions are welcome. Please have a look at the contributing guide. 104 | 105 | ## License 106 | 107 | React Contexify is licensed under MIT. 108 | -------------------------------------------------------------------------------- /cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress' 2 | 3 | export default defineConfig({ 4 | projectId: 'fwfrp4', 5 | e2e: { 6 | // We've imported your old cypress plugins here. 7 | // You may want to clean this up later by importing these. 8 | setupNodeEvents(on, config) { 9 | return require('./cypress/plugins/index.js')(on, config) 10 | }, 11 | baseUrl: 'http://localhost:1234', 12 | specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}', 13 | }, 14 | }) 15 | -------------------------------------------------------------------------------- /cypress/.gitignore: -------------------------------------------------------------------------------- 1 | videos -------------------------------------------------------------------------------- /cypress/e2e/context-menu.spec.ts: -------------------------------------------------------------------------------- 1 | import { DATA_TEST } from '../../example/constants'; 2 | import { CssClass } from '../../src/constants'; 3 | import { animation, theme } from '../fixtures/constant'; 4 | 5 | const builtInAnimationClasses = Object.keys(animation).map(k => ({ 6 | name: k, 7 | enter: `${CssClass.animationWillEnter}${animation[k]}`, 8 | exit: `${CssClass.animationWillLeave}${animation[k]}`, 9 | })); 10 | 11 | describe('Context menu', () => { 12 | beforeEach(() => { 13 | cy.visit('/'); 14 | }); 15 | 16 | it('Should not be mounted by default', () => { 17 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 18 | }); 19 | 20 | it('Display the context menu', () => { 21 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 22 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 23 | }); 24 | 25 | it('Close on Escape', () => { 26 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 27 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 28 | cy.get('body').type('{esc}'); 29 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 30 | }); 31 | 32 | it('Close on Enter', () => { 33 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 34 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 35 | cy.get('body').type('{enter}'); 36 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 37 | }); 38 | 39 | it('Close on window resize', () => { 40 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 41 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 42 | 43 | cy.viewport(123, 456); 44 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 45 | }); 46 | 47 | it('Prevent from rendering outside of the viewport if possible', () => { 48 | cy.viewport(500, 500); 49 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(10, 170); 50 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 51 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).isWithinViewport(); 52 | }); 53 | 54 | it('Can change trigger event', () => { 55 | cy.getByDataTest(DATA_TEST.EVENT_SELECTOR).select('onClick'); 56 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 57 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 58 | 59 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).click(); 60 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 61 | 62 | cy.getByDataTest(DATA_TEST.EVENT_SELECTOR).select('onDoubleClick'); 63 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 64 | 65 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).dblclick(); 66 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 67 | }); 68 | 69 | it('Can use built-in theme', () => { 70 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 71 | 72 | // no theme selected 73 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 74 | 'have.class', 75 | `${CssClass.theme}none` 76 | ); 77 | 78 | cy.getByDataTest(DATA_TEST.THEME_SELECTOR).select(theme.light); 79 | 80 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 81 | 82 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 83 | 'have.class', 84 | `${CssClass.theme}${theme.light}` 85 | ); 86 | 87 | cy.getByDataTest(DATA_TEST.THEME_SELECTOR).select(theme.dark); 88 | 89 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 90 | 91 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 92 | 'have.class', 93 | `${CssClass.theme}${theme.dark}` 94 | ); 95 | }); 96 | 97 | it('Can use built-in animation', () => { 98 | builtInAnimationClasses.forEach(builtInAnimation => { 99 | cy.getByDataTest(DATA_TEST.ANIMATION_SELECTOR).select( 100 | builtInAnimation.name 101 | ); 102 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 103 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 104 | 'have.class', 105 | builtInAnimation.enter 106 | ); 107 | // close the menu 108 | cy.get('body').type('{esc}'); 109 | 110 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 111 | 'have.class', 112 | builtInAnimation.exit 113 | ); 114 | 115 | // wait for exit animation to complete 116 | cy.wait(500); 117 | }); 118 | }); 119 | 120 | it('Can disable animation', () => { 121 | cy.getByDataTest(DATA_TEST.ANIMATION_SELECTOR).select('none'); 122 | 123 | builtInAnimationClasses.forEach(builtInAnimation => { 124 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 125 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 126 | 'not.have.class', 127 | builtInAnimation.enter 128 | ); 129 | 130 | cy.get('body').type('{esc}'); 131 | 132 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 133 | }); 134 | }); 135 | 136 | it('Can disable enter animation only', () => { 137 | cy.getByDataTest(DATA_TEST.TOGGLE_DISABLE_ENTER_ANIMATION).check(); 138 | 139 | builtInAnimationClasses.forEach(builtInAnimation => { 140 | cy.getByDataTest(DATA_TEST.ANIMATION_SELECTOR).select( 141 | builtInAnimation.name 142 | ); 143 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 144 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 145 | 'not.have.class', 146 | builtInAnimation.enter 147 | ); 148 | // close the menu 149 | cy.get('body').type('{esc}'); 150 | 151 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 152 | 'have.class', 153 | builtInAnimation.exit 154 | ); 155 | 156 | // wait for exit animation to complete 157 | cy.wait(500); 158 | }); 159 | }); 160 | 161 | it('Can disable exit animation only', () => { 162 | cy.getByDataTest(DATA_TEST.TOGGLE_DISABLE_EXIT_ANIMATION).check(); 163 | 164 | builtInAnimationClasses.forEach(builtInAnimation => { 165 | cy.getByDataTest(DATA_TEST.ANIMATION_SELECTOR).select( 166 | builtInAnimation.name 167 | ); 168 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 169 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should( 170 | 'have.class', 171 | builtInAnimation.enter 172 | ); 173 | // close the menu 174 | cy.get('body').type('{esc}'); 175 | 176 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 177 | 178 | // wait for exit animation to complete 179 | cy.wait(500); 180 | }); 181 | }); 182 | 183 | it('Can specify a custom position', () => { 184 | cy.getByDataTest(DATA_TEST.TOGGLE_CUSTOM_POSITION).check(); 185 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 186 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 187 | 188 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).then(el => { 189 | const { x, y } = el[0].getBoundingClientRect(); 190 | 191 | expect(x).to.be.eq(0, 'x match custom coordinate'); 192 | expect(y).to.be.eq(0, 'y match custom coordinate'); 193 | }); 194 | }); 195 | 196 | it('Should not close when clicking a disabled item', () => { 197 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 198 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 199 | 200 | cy.getByDataTest(DATA_TEST.DISABLED_ITEM_VIA_BOOLEAN).click(); 201 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 202 | 203 | cy.getByDataTest(DATA_TEST.DISABLED_ITEM_VIA_FUNCTION).click(); 204 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 205 | }); 206 | 207 | it('Should not close when clicking on submenu', () => { 208 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 209 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 210 | 211 | cy.getByDataTest(DATA_TEST.SUBMENU).click(); 212 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 213 | }); 214 | 215 | it('Should close when clicking on an item', () => { 216 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 217 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('be.visible'); 218 | 219 | cy.getByDataTest(DATA_TEST.MENU_FIRST_ITEM).click(); 220 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU).should('not.exist'); 221 | }); 222 | }); 223 | -------------------------------------------------------------------------------- /cypress/e2e/item.spec.ts: -------------------------------------------------------------------------------- 1 | import { DATA_TEST } from '../../example/constants'; 2 | 3 | function showContextMenu() { 4 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 5 | } 6 | 7 | describe('Menu item', () => { 8 | beforeEach(() => { 9 | cy.visit('/'); 10 | }); 11 | 12 | it('Can be disabled by passing a boolean or a function that return a boolean', () => { 13 | showContextMenu(); 14 | 15 | cy.getByDataTest(DATA_TEST.DISABLED_ITEM_VIA_BOOLEAN).should( 16 | 'have.attr', 17 | 'aria-disabled', 18 | 'true' 19 | ); 20 | 21 | cy.getByDataTest(DATA_TEST.DISABLED_ITEM_VIA_FUNCTION).should( 22 | 'have.attr', 23 | 'aria-disabled', 24 | 'true' 25 | ); 26 | }); 27 | 28 | it('Can be hidden by passing a boolean or a function that return a boolean', () => { 29 | showContextMenu(); 30 | cy.getByDataTest(DATA_TEST.MENU_FIRST_ITEM).should('be.visible'); 31 | cy.getByDataTest(DATA_TEST.MENU_SECOND_ITEM).should('be.visible'); 32 | 33 | cy.getByDataTest(DATA_TEST.TOGGLE_HIDE_ITEMS).check(); 34 | showContextMenu(); 35 | 36 | cy.getByDataTest(DATA_TEST.MENU_FIRST_ITEM).should('not.exist'); 37 | cy.getByDataTest(DATA_TEST.MENU_SECOND_ITEM).should('not.exist'); 38 | }); 39 | 40 | it('Should pass payload when clicking on an Item', () => { 41 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 42 | 43 | cy.getByDataTest(DATA_TEST.MENU_FIRST_ITEM).click(); 44 | 45 | cy.getByDataTest(DATA_TEST.ONCLICK_PAYLOAD).then(el => { 46 | const payload = JSON.parse(el.text()); 47 | expect(payload).to.deep.include({ 48 | data: { id: 1 }, 49 | props: { key: 'value' }, 50 | }); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /cypress/e2e/keyboard.spec.ts: -------------------------------------------------------------------------------- 1 | import { DATA_TEST } from '../../example/constants'; 2 | 3 | describe('Context menu keyboard interaction', () => { 4 | beforeEach(() => { 5 | cy.visit('/'); 6 | }); 7 | 8 | it('Select first menu item when pressing arrow down', () => { 9 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 10 | cy.get('body').type('{downarrow}'); 11 | 12 | cy.focused().should('have.attr', 'data-test', DATA_TEST.MENU_FIRST_ITEM); 13 | }); 14 | 15 | it('Select the last item when pressing arrow up', () => { 16 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 17 | cy.get('body').type('{uparrow}'); 18 | 19 | cy.focused().should('have.attr', 'data-test', DATA_TEST.MENU_LAST_ITEM); 20 | }); 21 | 22 | it('Should not select disabled items', () => { 23 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 24 | 25 | //🙅‍♀️ go to item 4 and skip disabled items 26 | for (let i = 0; i < 4; i++) { 27 | cy.get('body').type('{downarrow}'); 28 | cy.focused().should('have.attr', 'aria-disabled', 'false'); 29 | } 30 | }); 31 | 32 | describe('Open submenu and focus first item', () => { 33 | for (const key of ['{enter}', ' ', '{rightarrow}']) { 34 | it(`When ${key} is pressed`, () => { 35 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 36 | 37 | //🙅‍♀️ go to submenu 38 | cy.get('body').type('{uparrow}'); 39 | cy.get('body').type('{uparrow}'); 40 | 41 | cy.focused().should('have.attr', 'data-test', DATA_TEST.SUBMENU); 42 | 43 | cy.getByDataTest(DATA_TEST.SUBMENU_FIRST_ITEM).should('not.be.visible'); 44 | cy.get('body').type(key); 45 | 46 | // wait for transition 47 | cy.wait(500); 48 | cy.focused().should( 49 | 'have.attr', 50 | 'data-test', 51 | DATA_TEST.SUBMENU_FIRST_ITEM 52 | ); 53 | }); 54 | } 55 | }); 56 | 57 | it('Close submenu on left arrow press', () => { 58 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 59 | 60 | //🙅‍♀️ go to submenu 61 | cy.get('body').type('{uparrow}'); 62 | cy.get('body').type('{uparrow}'); 63 | 64 | cy.get('body').type('{rightarrow}'); 65 | 66 | // wait for transition 67 | cy.wait(500); 68 | cy.focused().should('have.attr', 'data-test', DATA_TEST.SUBMENU_FIRST_ITEM); 69 | 70 | cy.get('body').type('{leftarrow}'); 71 | cy.focused().should('have.attr', 'data-test', DATA_TEST.SUBMENU); 72 | }); 73 | 74 | it('Should handle keyboard shortcut', () => { 75 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 76 | 77 | cy.get('body').type('{ctrl}{u}'); 78 | cy.wait(500); 79 | cy.getByDataTest(DATA_TEST.KDB_SHORTCUT).then((el) => { 80 | expect(el.text()).eq('ctrl+u'); 81 | }); 82 | 83 | // nested shortcut 84 | cy.getByDataTest(DATA_TEST.CONTEXT_MENU_TRIGGER).rightclick(); 85 | 86 | cy.get('body').type('{ctrl}{s}'); 87 | cy.wait(500); 88 | cy.getByDataTest(DATA_TEST.KDB_SHORTCUT).then((el) => { 89 | expect(el.text()).eq('ctrl+s'); 90 | }); 91 | }); 92 | }); 93 | -------------------------------------------------------------------------------- /cypress/fixtures/constant.ts: -------------------------------------------------------------------------------- 1 | export const animation = { 2 | fade: 'fade', 3 | flip: 'flip', 4 | scale: 'scale', 5 | slide: 'slide', 6 | }; 7 | 8 | export const theme = { 9 | light: 'light', 10 | dark: 'dark', 11 | }; 12 | -------------------------------------------------------------------------------- /cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | /// 2 | // *********************************************************** 3 | // This example plugins/index.js can be used to load plugins 4 | // 5 | // You can change the location of this file or turn off loading 6 | // the plugins file with the 'pluginsFile' configuration option. 7 | // 8 | // You can read more here: 9 | // https://on.cypress.io/plugins-guide 10 | // *********************************************************** 11 | 12 | // This function is called when a project is opened or re-opened (e.g. due to 13 | // the project's config changing) 14 | 15 | /** 16 | * @type {Cypress.PluginConfig} 17 | */ 18 | module.exports = (on, config) => { 19 | // `on` is used to hook into various events Cypress emits 20 | // `config` is the resolved Cypress config 21 | } 22 | -------------------------------------------------------------------------------- /cypress/support/commands.ts: -------------------------------------------------------------------------------- 1 | import './data-test'; 2 | import './is-in-viewport'; 3 | -------------------------------------------------------------------------------- /cypress/support/data-test.ts: -------------------------------------------------------------------------------- 1 | declare namespace Cypress { 2 | interface Chainable { 3 | getByDataTest: (dataTest: string) => Cypress.Chainable>; 4 | findByDataTest: ( 5 | dataTest: string 6 | ) => Cypress.Chainable>; 7 | } 8 | } 9 | 10 | Cypress.Commands.add("getByDataTest", (dataTest) => { 11 | cy.get(`[data-test="${dataTest}"]`); 12 | }); 13 | 14 | Cypress.Commands.add( 15 | "findByDataTest", 16 | { prevSubject: true }, 17 | (subject, dataTest) => subject.find(`[data-test="${dataTest}"]`) 18 | ); 19 | -------------------------------------------------------------------------------- /cypress/support/e2e.ts: -------------------------------------------------------------------------------- 1 | import './commands'; 2 | -------------------------------------------------------------------------------- /cypress/support/is-in-viewport.ts: -------------------------------------------------------------------------------- 1 | declare namespace Cypress { 2 | interface Chainable { 3 | isWithinViewport: () => Cypress.Chainable>; 4 | } 5 | } 6 | 7 | Cypress.Commands.add('isWithinViewport', { prevSubject: true }, subject => { 8 | const windowInnerWidth = Cypress.config(`viewportWidth`); 9 | const windowInnerHeight = Cypress.config(`viewportHeight`); 10 | 11 | const bounding = subject[0].getBoundingClientRect(); 12 | 13 | const rightBoundOfWindow = windowInnerWidth; 14 | const bottomBoundOfWindow = windowInnerHeight; 15 | 16 | Cypress.log({ 17 | message: 'Checking bounding client rect', 18 | }); 19 | expect(bounding.top).to.be.at.least(0); 20 | expect(bounding.left).to.be.at.least(0); 21 | expect(bounding.right).to.be.lessThan(rightBoundOfWindow); 22 | expect(bounding.bottom).to.be.lessThan(bottomBoundOfWindow); 23 | 24 | return subject; 25 | }); 26 | -------------------------------------------------------------------------------- /cypress/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["es5", "dom"], 5 | "types": ["cypress"] 6 | }, 7 | "include": [ 8 | "**/*.ts" 9 | ] 10 | } -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | .parcel-cache -------------------------------------------------------------------------------- /example/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | dist -------------------------------------------------------------------------------- /example/components/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { Select } from './Select'; 4 | import { DATA_TEST, MENU_ID } from '../constants'; 5 | 6 | import { 7 | Menu, 8 | Item, 9 | Separator, 10 | Submenu, 11 | useContextMenu, 12 | ItemParams, 13 | RightSlot, 14 | } from '../../src'; 15 | 16 | const builtInAnimation = { 17 | fade: 'fade', 18 | flip: 'flip', 19 | scale: 'scale', 20 | slide: 'slide', 21 | }; 22 | 23 | const builtInTheme = { 24 | light: 'light', 25 | dark: 'dark', 26 | }; 27 | 28 | const selector = { 29 | events: ['onContextMenu', 'onClick', 'onDoubleClick'], 30 | themes: [ 31 | 'none', 32 | ...Object.keys(builtInTheme).map( 33 | (k) => builtInTheme[k as keyof typeof builtInTheme] 34 | ), 35 | ], 36 | animations: [ 37 | 'none', 38 | ...Object.keys(builtInAnimation).map( 39 | (k) => builtInAnimation[k as keyof typeof builtInAnimation] 40 | ), 41 | ], 42 | }; 43 | 44 | interface SelectorState { 45 | theme: string; 46 | animation: string | false; 47 | event: string; 48 | hideItems: boolean; 49 | customPosition: boolean; 50 | disableEnterAnimation: boolean; 51 | disableExitAnimation: boolean; 52 | kbdShortcut: string; 53 | } 54 | 55 | function selectorReducer( 56 | state: SelectorState, 57 | nextState: Partial 58 | ) { 59 | return { ...state, ...nextState }; 60 | } 61 | 62 | function singularize(s: string) { 63 | return s.slice(0, -1); 64 | } 65 | 66 | function getDataTestSelector(key: string) { 67 | switch (key) { 68 | case 'animations': 69 | return DATA_TEST.ANIMATION_SELECTOR; 70 | case 'events': 71 | return DATA_TEST.EVENT_SELECTOR; 72 | case 'themes': 73 | return DATA_TEST.THEME_SELECTOR; 74 | } 75 | } 76 | 77 | export function App() { 78 | const [state, setState] = React.useReducer(selectorReducer, { 79 | theme: selector.themes[0], 80 | animation: false, 81 | event: selector.events[0], 82 | hideItems: false, 83 | customPosition: false, 84 | disableEnterAnimation: false, 85 | disableExitAnimation: false, 86 | kbdShortcut: '', 87 | }); 88 | const [payload, setPayload] = React.useState({ 89 | x: 0, 90 | y: 0, 91 | data: null, 92 | props: null, 93 | }); 94 | const { show } = useContextMenu({ 95 | id: MENU_ID, 96 | }); 97 | 98 | function handleSelector({ 99 | target: { name, value }, 100 | }: React.ChangeEvent) { 101 | setState({ 102 | [singularize(name)]: value === 'none' ? false : value, 103 | }); 104 | } 105 | 106 | function handleCheckboxes(e: React.ChangeEvent) { 107 | setState({ 108 | [e.target.name]: !state[e.target.name], 109 | }); 110 | } 111 | 112 | function handleContextMenu(event: React.MouseEvent) { 113 | show({ 114 | event, 115 | props: { 116 | key: 'value', 117 | }, 118 | position: state.customPosition 119 | ? { 120 | x: 0, 121 | y: 0, 122 | } 123 | : null, 124 | }); 125 | } 126 | 127 | function handleItemClick(params: ItemParams) { 128 | console.log(params.triggerEvent); 129 | 130 | setPayload({ 131 | x: params.triggerEvent.clientX, 132 | y: params.triggerEvent.clientY, 133 | data: params.data, 134 | props: params.props, 135 | }); 136 | } 137 | 138 | function getAnimation() { 139 | const { disableEnterAnimation, disableExitAnimation, animation } = state; 140 | if (!animation) { 141 | return false; 142 | } else if (disableEnterAnimation || disableExitAnimation) { 143 | return { 144 | enter: disableEnterAnimation ? false : animation, 145 | exit: disableExitAnimation ? false : animation, 146 | }; 147 | } 148 | 149 | return animation; 150 | } 151 | 152 | return ( 153 |
154 |
155 |

Settings

156 |
    157 | {Object.keys(selector).map((key) => ( 158 |
  • 159 | 160 | 180 |
  • 181 |
  • 182 | 183 | 191 |
  • 192 |
  • 193 | 196 | 204 |
  • 205 |
  • 206 | 207 | 215 |
  • 216 |
217 |
218 |
219 |

Item payload

220 |
221 | On click payload 222 | 223 | {JSON.stringify(payload, null, 2)} 224 | 225 |
226 |
227 |
228 |

Keyboard shortcut

229 |
230 | Shortcut triggered: 231 | {state.kbdShortcut} 232 |
233 |
234 |
235 |
240 | event is triggered everywhere in the box 241 |
242 |
243 | 249 | 257 | 263 | { 265 | setState({ 266 | kbdShortcut: 'ctrl+u', 267 | }); 268 | }} 269 | keyMatcher={(e: KeyboardEvent) => { 270 | return e.ctrlKey && e.key == 'u'; 271 | }} 272 | > 273 | Item 3 274 | 275 | 276 | Disabled 277 | 278 | true} 280 | data-test={DATA_TEST.DISABLED_ITEM_VIA_FUNCTION} 281 | > 282 | Disabled via function 283 | 284 | 285 | Item 4 286 | 287 | Submenu Item 1 288 | Submenu Item 2 289 | 290 | { 292 | setState({ 293 | kbdShortcut: 'ctrl+s', 294 | }); 295 | }} 296 | keyMatcher={(e: KeyboardEvent) => { 297 | return e.ctrlKey && e.key == 's'; 298 | }} 299 | > 300 | Submenu Item 3 301 | 302 | Submenu Item 4 303 | 304 | 305 | Nested submenu Item 1 306 | 307 | 308 | 309 | 310 | Item 5 311 | 312 |
313 |
314 | ); 315 | } 316 | -------------------------------------------------------------------------------- /example/components/Select.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface SelectProps extends React.HTMLAttributes { 4 | name: string; 5 | value: string; 6 | data: string[]; 7 | onChange: (e: React.ChangeEvent) => void; 8 | } 9 | 10 | export function Select({ name, value, data, onChange, ...rest }: SelectProps) { 11 | return ( 12 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /example/constants.ts: -------------------------------------------------------------------------------- 1 | export const MENU_ID = '🦄'; 2 | 3 | export const enum DATA_TEST { 4 | MOUNT_NODE = 'mount-node', 5 | TOGGLE_CUSTOM_POSITION = 'toggle-custom-position', 6 | CONTEXT_MENU_TRIGGER = 'trigger', 7 | CONTEXT_MENU = 'context-menu', 8 | THEME_SELECTOR = 'theme-selector', 9 | ANIMATION_SELECTOR = 'animation-selector', 10 | EVENT_SELECTOR = 'event-selector', 11 | TOGGLE_HIDE_ITEMS = 'hide-items', 12 | TOGGLE_DISABLE_ENTER_ANIMATION = 'disable-enter-animation', 13 | TOGGLE_DISABLE_EXIT_ANIMATION = 'disable-exit-animation', 14 | DISABLED_ITEM_VIA_BOOLEAN = 'disabled-item-boolean', 15 | DISABLED_ITEM_VIA_FUNCTION = 'disabled-item-function', 16 | SUBMENU = 'submenu', 17 | NESTED_SUBMENU = 'nested-submenu', 18 | MENU_FIRST_ITEM = 'menu-firt-item', 19 | MENU_SECOND_ITEM = 'menu-second-item', 20 | MENU_LAST_ITEM = 'menu-last-item', 21 | SUBMENU_FIRST_ITEM = 'submenu-firt-item', 22 | NESTED_SUBMENU_FIRST_ITEM = 'nested-submenu-firt-item', 23 | ONCLICK_PAYLOAD = 'item-payload', 24 | KDB_SHORTCUT = "kbd-shortcut" 25 | } 26 | -------------------------------------------------------------------------------- /example/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --display-border: 1px solid red; 3 | } 4 | 5 | body { 6 | font-family: 'Inter', sans-serif; 7 | } 8 | 9 | * { 10 | box-sizing: border-box; 11 | } 12 | 13 | canvas { 14 | border: var(--display-border); 15 | } 16 | 17 | table.grid { 18 | width: 200px; 19 | border: var(--display-border); 20 | } 21 | 22 | table.grid tr { 23 | height: 15px; 24 | } 25 | 26 | table.grid td { 27 | border: 1px solid #000000; 28 | } 29 | 30 | table.grid td:hover { 31 | background: red; 32 | } 33 | 34 | main { 35 | max-width: 1180px; 36 | margin: auto; 37 | } 38 | 39 | .boxes-container{ 40 | display: flex; 41 | } 42 | 43 | .box { 44 | border: var(--display-border); 45 | background-color: blue; 46 | width: 200px; 47 | height: 200px; 48 | color: white; 49 | text-align: center; 50 | } -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Playground 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /example/index.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | import * as React from 'react'; 3 | import { App } from './components/App'; 4 | 5 | import './index.css'; 6 | import '../scss/main.scss'; 7 | 8 | const root = createRoot(document.getElementById('root')!); 9 | 10 | root.render( 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "parcel --no-cache index.html", 8 | "build": "parcel build index.html" 9 | }, 10 | "dependencies": { 11 | "react-app-polyfill": "^3.0.0" 12 | }, 13 | "alias": { 14 | "react": "../node_modules/react", 15 | "react-dom": "../node_modules/react-dom" 16 | }, 17 | "devDependencies": { 18 | "@parcel/transformer-sass": "2.7.0", 19 | "@types/react": "^18.0.24", 20 | "@types/react-dom": "^18.0.8", 21 | "parcel": "^2.7.0", 22 | "typescript": "^4.8.4" 23 | } 24 | } -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": false, 4 | "target": "ESNext", 5 | "module": "commonjs", 6 | "jsx": "react", 7 | "moduleResolution": "node", 8 | "noImplicitAny": false, 9 | "noUnusedLocals": false, 10 | "noUnusedParameters": false, 11 | "removeComments": true, 12 | "strictNullChecks": true, 13 | "preserveConstEnums": true, 14 | "sourceMap": true, 15 | "lib": ["es2015", "es2016", "dom"], 16 | "types": ["node"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.10.4" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" 8 | integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== 9 | dependencies: 10 | "@babel/highlight" "^7.10.4" 11 | 12 | "@babel/helper-validator-identifier@^7.10.4": 13 | version "7.10.4" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" 15 | integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== 16 | 17 | "@babel/highlight@^7.10.4": 18 | version "7.10.4" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" 20 | integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.10.4" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@jridgewell/gen-mapping@^0.3.0": 27 | version "0.3.2" 28 | resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" 29 | integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== 30 | dependencies: 31 | "@jridgewell/set-array" "^1.0.1" 32 | "@jridgewell/sourcemap-codec" "^1.4.10" 33 | "@jridgewell/trace-mapping" "^0.3.9" 34 | 35 | "@jridgewell/resolve-uri@3.1.0": 36 | version "3.1.0" 37 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" 38 | integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== 39 | 40 | "@jridgewell/set-array@^1.0.1": 41 | version "1.1.2" 42 | resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" 43 | integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== 44 | 45 | "@jridgewell/source-map@^0.3.2": 46 | version "0.3.2" 47 | resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" 48 | integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== 49 | dependencies: 50 | "@jridgewell/gen-mapping" "^0.3.0" 51 | "@jridgewell/trace-mapping" "^0.3.9" 52 | 53 | "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": 54 | version "1.4.14" 55 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" 56 | integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== 57 | 58 | "@jridgewell/trace-mapping@^0.3.9": 59 | version "0.3.17" 60 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" 61 | integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== 62 | dependencies: 63 | "@jridgewell/resolve-uri" "3.1.0" 64 | "@jridgewell/sourcemap-codec" "1.4.14" 65 | 66 | "@lezer/common@^0.15.0", "@lezer/common@^0.15.7": 67 | version "0.15.12" 68 | resolved "https://registry.yarnpkg.com/@lezer/common/-/common-0.15.12.tgz#2f21aec551dd5fd7d24eb069f90f54d5bc6ee5e9" 69 | integrity sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig== 70 | 71 | "@lezer/lr@^0.15.4": 72 | version "0.15.8" 73 | resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-0.15.8.tgz#1564a911e62b0a0f75ca63794a6aa8c5dc63db21" 74 | integrity sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg== 75 | dependencies: 76 | "@lezer/common" "^0.15.0" 77 | 78 | "@lmdb/lmdb-darwin-arm64@2.5.2": 79 | version "2.5.2" 80 | resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.5.2.tgz#bc66fa43286b5c082e8fee0eacc17995806b6fbe" 81 | integrity sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A== 82 | 83 | "@lmdb/lmdb-darwin-x64@2.5.2": 84 | version "2.5.2" 85 | resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.5.2.tgz#89d8390041bce6bab24a82a20392be22faf54ffc" 86 | integrity sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA== 87 | 88 | "@lmdb/lmdb-linux-arm64@2.5.2": 89 | version "2.5.2" 90 | resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.5.2.tgz#14fe4c96c2bb1285f93797f45915fa35ee047268" 91 | integrity sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ== 92 | 93 | "@lmdb/lmdb-linux-arm@2.5.2": 94 | version "2.5.2" 95 | resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.5.2.tgz#05bde4573ab10cf21827339fe687148f2590cfa1" 96 | integrity sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw== 97 | 98 | "@lmdb/lmdb-linux-x64@2.5.2": 99 | version "2.5.2" 100 | resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.5.2.tgz#d2f85afd857d2c33d2caa5b057944574edafcfee" 101 | integrity sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q== 102 | 103 | "@lmdb/lmdb-win32-x64@2.5.2": 104 | version "2.5.2" 105 | resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.5.2.tgz#28f643fbc0bec30b07fbe95b137879b6b4d1c9c5" 106 | integrity sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA== 107 | 108 | "@mischnic/json-sourcemap@^0.1.0": 109 | version "0.1.0" 110 | resolved "https://registry.yarnpkg.com/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz#38af657be4108140a548638267d02a2ea3336507" 111 | integrity sha512-dQb3QnfNqmQNYA4nFSN/uLaByIic58gOXq4Y4XqLOWmOrw73KmJPt/HLyG0wvn1bnR6mBKs/Uwvkh+Hns1T0XA== 112 | dependencies: 113 | "@lezer/common" "^0.15.7" 114 | "@lezer/lr" "^0.15.4" 115 | json5 "^2.2.1" 116 | 117 | "@msgpackr-extract/msgpackr-extract-darwin-arm64@2.1.2": 118 | version "2.1.2" 119 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.1.2.tgz#9571b87be3a3f2c46de05585470bc4f3af2f6f00" 120 | integrity sha512-TyVLn3S/+ikMDsh0gbKv2YydKClN8HaJDDpONlaZR+LVJmsxLFUgA+O7zu59h9+f9gX1aj/ahw9wqa6rosmrYQ== 121 | 122 | "@msgpackr-extract/msgpackr-extract-darwin-x64@2.1.2": 123 | version "2.1.2" 124 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.1.2.tgz#bfbc6936ede2955218f5621a675679a5fe8e6f4c" 125 | integrity sha512-YPXtcVkhmVNoMGlqp81ZHW4dMxK09msWgnxtsDpSiZwTzUBG2N+No2bsr7WMtBKCVJMSD6mbAl7YhKUqkp/Few== 126 | 127 | "@msgpackr-extract/msgpackr-extract-linux-arm64@2.1.2": 128 | version "2.1.2" 129 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.1.2.tgz#22555e28382af2922e7450634c8a2f240bb9eb82" 130 | integrity sha512-vHZ2JiOWF2+DN9lzltGbhtQNzDo8fKFGrf37UJrgqxU0yvtERrzUugnfnX1wmVfFhSsF8OxrfqiNOUc5hko1Zg== 131 | 132 | "@msgpackr-extract/msgpackr-extract-linux-arm@2.1.2": 133 | version "2.1.2" 134 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.1.2.tgz#ffb6ae1beea7ac572b6be6bf2a8e8162ebdd8be7" 135 | integrity sha512-42R4MAFeIeNn+L98qwxAt360bwzX2Kf0ZQkBBucJ2Ircza3asoY4CDbgiu9VWklq8gWJVSJSJBwDI+c/THiWkA== 136 | 137 | "@msgpackr-extract/msgpackr-extract-linux-x64@2.1.2": 138 | version "2.1.2" 139 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.1.2.tgz#7caf62eebbfb1345de40f75e89666b3d4194755f" 140 | integrity sha512-RjRoRxg7Q3kPAdUSC5EUUPlwfMkIVhmaRTIe+cqHbKrGZ4M6TyCA/b5qMaukQ/1CHWrqYY2FbKOAU8Hg0pQFzg== 141 | 142 | "@msgpackr-extract/msgpackr-extract-win32-x64@2.1.2": 143 | version "2.1.2" 144 | resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.1.2.tgz#f2d8b9ddd8d191205ed26ce54aba3dfc5ae3e7c9" 145 | integrity sha512-rIZVR48zA8hGkHIK7ED6+ZiXsjRCcAVBJbm8o89OKAMTmEAQ2QvoOxoiu3w2isAaWwzgtQIOFIqHwvZDyLKCvw== 146 | 147 | "@parcel/bundler-default@2.7.0": 148 | version "2.7.0" 149 | resolved "https://registry.yarnpkg.com/@parcel/bundler-default/-/bundler-default-2.7.0.tgz#17d94be7185f29773aa21454063cbba3cdc03d49" 150 | integrity sha512-PU5MtWWhc+dYI9x8mguYnm9yiG6TkI7niRpxgJgtqAyGHuEyNXVBQQ0X+qyOF4D9LdankBf8uNN18g31IET2Zg== 151 | dependencies: 152 | "@parcel/diagnostic" "2.7.0" 153 | "@parcel/hash" "2.7.0" 154 | "@parcel/plugin" "2.7.0" 155 | "@parcel/utils" "2.7.0" 156 | nullthrows "^1.1.1" 157 | 158 | "@parcel/cache@2.7.0": 159 | version "2.7.0" 160 | resolved "https://registry.yarnpkg.com/@parcel/cache/-/cache-2.7.0.tgz#cc4b99685c7ff0fc20fbc321f4b6850d6e0c6811" 161 | integrity sha512-JlXNoZXcWzLKdDlfeF3dIj5Vtel5T9vtdBN72PJ+cjC4qNHk4Uwvc5sfOBELuibGN0bVu2bwY9nUgSwCiB1iIA== 162 | dependencies: 163 | "@parcel/fs" "2.7.0" 164 | "@parcel/logger" "2.7.0" 165 | "@parcel/utils" "2.7.0" 166 | lmdb "2.5.2" 167 | 168 | "@parcel/codeframe@2.7.0": 169 | version "2.7.0" 170 | resolved "https://registry.yarnpkg.com/@parcel/codeframe/-/codeframe-2.7.0.tgz#b6e4ad6100938edbed1b6c72b37f609e1abaf931" 171 | integrity sha512-UTKx0jejJmmO1dwTHSJuRgrO8N6PMlkxRT6sew8N6NC3Bgv6pu0EbO+RtlWt/jCvzcdLOPdIoTzj4MMZvgcMYg== 172 | dependencies: 173 | chalk "^4.1.0" 174 | 175 | "@parcel/compressor-raw@2.7.0": 176 | version "2.7.0" 177 | resolved "https://registry.yarnpkg.com/@parcel/compressor-raw/-/compressor-raw-2.7.0.tgz#3f8677e6371ef099cd9e4bd2a899884dc8eb571b" 178 | integrity sha512-SCXwnOOQT6EmpusBsYWNQ/RFri+2JnKuE0gMSf2dROl2xbererX45FYzeDplWALCKAdjMNDpFwU+FyMYoVZSCQ== 179 | dependencies: 180 | "@parcel/plugin" "2.7.0" 181 | 182 | "@parcel/config-default@2.7.0": 183 | version "2.7.0" 184 | resolved "https://registry.yarnpkg.com/@parcel/config-default/-/config-default-2.7.0.tgz#2f6cec9c185b89e40f343549295cad21295621a8" 185 | integrity sha512-ZzsLr97AYrz8c9k6qn3DlqPzifi3vbP7q3ynUrAFxmt0L4+K0H9N508ZkORYmCgaFjLIQ8Y3eWpwCJ0AewPNIg== 186 | dependencies: 187 | "@parcel/bundler-default" "2.7.0" 188 | "@parcel/compressor-raw" "2.7.0" 189 | "@parcel/namer-default" "2.7.0" 190 | "@parcel/optimizer-css" "2.7.0" 191 | "@parcel/optimizer-htmlnano" "2.7.0" 192 | "@parcel/optimizer-image" "2.7.0" 193 | "@parcel/optimizer-svgo" "2.7.0" 194 | "@parcel/optimizer-terser" "2.7.0" 195 | "@parcel/packager-css" "2.7.0" 196 | "@parcel/packager-html" "2.7.0" 197 | "@parcel/packager-js" "2.7.0" 198 | "@parcel/packager-raw" "2.7.0" 199 | "@parcel/packager-svg" "2.7.0" 200 | "@parcel/reporter-dev-server" "2.7.0" 201 | "@parcel/resolver-default" "2.7.0" 202 | "@parcel/runtime-browser-hmr" "2.7.0" 203 | "@parcel/runtime-js" "2.7.0" 204 | "@parcel/runtime-react-refresh" "2.7.0" 205 | "@parcel/runtime-service-worker" "2.7.0" 206 | "@parcel/transformer-babel" "2.7.0" 207 | "@parcel/transformer-css" "2.7.0" 208 | "@parcel/transformer-html" "2.7.0" 209 | "@parcel/transformer-image" "2.7.0" 210 | "@parcel/transformer-js" "2.7.0" 211 | "@parcel/transformer-json" "2.7.0" 212 | "@parcel/transformer-postcss" "2.7.0" 213 | "@parcel/transformer-posthtml" "2.7.0" 214 | "@parcel/transformer-raw" "2.7.0" 215 | "@parcel/transformer-react-refresh-wrap" "2.7.0" 216 | "@parcel/transformer-svg" "2.7.0" 217 | 218 | "@parcel/core@2.7.0": 219 | version "2.7.0" 220 | resolved "https://registry.yarnpkg.com/@parcel/core/-/core-2.7.0.tgz#3310f48230bd618735f199f159f37e6b45ed2710" 221 | integrity sha512-7yKZUdh314Q/kU/9+27ZYTfcnXS6VYHuG+iiUlIohnvUUybxLqVJhdMU9Q+z2QcPka1IdJWz4K4Xx0y6/4goyg== 222 | dependencies: 223 | "@mischnic/json-sourcemap" "^0.1.0" 224 | "@parcel/cache" "2.7.0" 225 | "@parcel/diagnostic" "2.7.0" 226 | "@parcel/events" "2.7.0" 227 | "@parcel/fs" "2.7.0" 228 | "@parcel/graph" "2.7.0" 229 | "@parcel/hash" "2.7.0" 230 | "@parcel/logger" "2.7.0" 231 | "@parcel/package-manager" "2.7.0" 232 | "@parcel/plugin" "2.7.0" 233 | "@parcel/source-map" "^2.0.0" 234 | "@parcel/types" "2.7.0" 235 | "@parcel/utils" "2.7.0" 236 | "@parcel/workers" "2.7.0" 237 | abortcontroller-polyfill "^1.1.9" 238 | base-x "^3.0.8" 239 | browserslist "^4.6.6" 240 | clone "^2.1.1" 241 | dotenv "^7.0.0" 242 | dotenv-expand "^5.1.0" 243 | json5 "^2.2.0" 244 | msgpackr "^1.5.4" 245 | nullthrows "^1.1.1" 246 | semver "^5.7.1" 247 | 248 | "@parcel/css@^1.12.2": 249 | version "1.14.0" 250 | resolved "https://registry.yarnpkg.com/@parcel/css/-/css-1.14.0.tgz#233750a1e3648b3746f27c2d8f3fd85a2290e512" 251 | integrity sha512-r5tJWe6NF6lesfPw1N3g7N7WUKpHqi2ONnw9wl5ccSGGIxkmgcPaPQxfvmhdjXvQnktSuIOR0HjQXVXu+/en/w== 252 | dependencies: 253 | lightningcss "^1.14.0" 254 | 255 | "@parcel/diagnostic@2.7.0": 256 | version "2.7.0" 257 | resolved "https://registry.yarnpkg.com/@parcel/diagnostic/-/diagnostic-2.7.0.tgz#cf2596a20ce9277334616e12bbdac98490189e99" 258 | integrity sha512-pdq/cTwVoL0n8yuDCRXFRSQHVWdmmIXPt3R3iT4KtYDYvOrMT2dLPT79IMqQkhYPANW8GuL15n/WxRngfRdkug== 259 | dependencies: 260 | "@mischnic/json-sourcemap" "^0.1.0" 261 | nullthrows "^1.1.1" 262 | 263 | "@parcel/events@2.7.0": 264 | version "2.7.0" 265 | resolved "https://registry.yarnpkg.com/@parcel/events/-/events-2.7.0.tgz#b6db8464d45626686134d412d3a36d024ffb1482" 266 | integrity sha512-kQDwMKgZ1U4M/G17qeDYF6bW5kybluN6ajYPc7mZcrWg+trEI/oXi81GMFaMX0BSUhwhbiN5+/Vb2wiG/Sn6ig== 267 | 268 | "@parcel/fs-search@2.7.0": 269 | version "2.7.0" 270 | resolved "https://registry.yarnpkg.com/@parcel/fs-search/-/fs-search-2.7.0.tgz#15e658006039ddc7b92528df5266ee2b9c47b6a4" 271 | integrity sha512-K1Hv25bnRpwQVA15RvcRuB8ZhfclnCHA8N8L6w7Ul1ncSJDxCIkIAc5hAubYNNYW3kWjCC2SOaEgFKnbvMllEQ== 272 | dependencies: 273 | detect-libc "^1.0.3" 274 | 275 | "@parcel/fs@2.7.0": 276 | version "2.7.0" 277 | resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-2.7.0.tgz#c9a0c60bdbef7101ff47f2db6b23814c3db06007" 278 | integrity sha512-PU5fo4Hh8y03LZgemgVREttc0wyHQUNmsJCybxTB7EjJie2CqJRumo+DFppArlvdchLwJdc9em03yQV/GNWrEg== 279 | dependencies: 280 | "@parcel/fs-search" "2.7.0" 281 | "@parcel/types" "2.7.0" 282 | "@parcel/utils" "2.7.0" 283 | "@parcel/watcher" "^2.0.0" 284 | "@parcel/workers" "2.7.0" 285 | 286 | "@parcel/graph@2.7.0": 287 | version "2.7.0" 288 | resolved "https://registry.yarnpkg.com/@parcel/graph/-/graph-2.7.0.tgz#2ae326c62764aaa53324b89d9c83ec0bc6ad55bf" 289 | integrity sha512-Q6E94GS6q45PtsZh+m+gvFRp/N1Qopxhu2sxjcWsGs5iBd6IWn2oYLWOH5iVzEjWuYpW2HkB08lH6J50O63uOA== 290 | dependencies: 291 | "@parcel/utils" "2.7.0" 292 | nullthrows "^1.1.1" 293 | 294 | "@parcel/hash@2.7.0": 295 | version "2.7.0" 296 | resolved "https://registry.yarnpkg.com/@parcel/hash/-/hash-2.7.0.tgz#8825cff69a0bc4816737415e6e2aa29e8671c0b1" 297 | integrity sha512-k6bSKnIlPJMPU3yjQzfgfvF9zuJZGOAlJgzpL4BbWvdbE8BTdjzLcFn0Ujrtud94EgIkiXd22sC2HpCUWoHGdA== 298 | dependencies: 299 | detect-libc "^1.0.3" 300 | xxhash-wasm "^0.4.2" 301 | 302 | "@parcel/logger@2.7.0": 303 | version "2.7.0" 304 | resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-2.7.0.tgz#1aa1de0458bdd613714ce4031134d92135aec590" 305 | integrity sha512-qjMY/bYo38+o+OiIrTRldU9CwL1E7J72t+xkTP8QIcUxLWz5LYR0YbynZUVulmBSfqsykjjxCy4a+8siVr+lPw== 306 | dependencies: 307 | "@parcel/diagnostic" "2.7.0" 308 | "@parcel/events" "2.7.0" 309 | 310 | "@parcel/markdown-ansi@2.7.0": 311 | version "2.7.0" 312 | resolved "https://registry.yarnpkg.com/@parcel/markdown-ansi/-/markdown-ansi-2.7.0.tgz#4ba70e3661ce06cd8fd2eb3f7b84028853a586e4" 313 | integrity sha512-ipOX0D6FVZFEXeb/z8MnTMq2RQEIuaILY90olVIuHEFLHHfOPEn+RK3u13HA1ChF5/9E3cMD79tu6x9JL9Kqag== 314 | dependencies: 315 | chalk "^4.1.0" 316 | 317 | "@parcel/namer-default@2.7.0": 318 | version "2.7.0" 319 | resolved "https://registry.yarnpkg.com/@parcel/namer-default/-/namer-default-2.7.0.tgz#e008097586016f16509834db11985dcc772c314c" 320 | integrity sha512-lIKMdsmi//7fepecNDYmJYzBlL91HifPsX03lJCdu1dC6q5fBs+gG0XjKKG7yPnSCw1qH/4m7drzt9+dRZYAHQ== 321 | dependencies: 322 | "@parcel/diagnostic" "2.7.0" 323 | "@parcel/plugin" "2.7.0" 324 | nullthrows "^1.1.1" 325 | 326 | "@parcel/node-resolver-core@2.7.0": 327 | version "2.7.0" 328 | resolved "https://registry.yarnpkg.com/@parcel/node-resolver-core/-/node-resolver-core-2.7.0.tgz#468074aa58a2f0026a492607153079ebb16308e3" 329 | integrity sha512-5UJQHalqMxdhJIs2hhqQzFfQpF7+NAowsRq064lYtiRvcD8wMr3OOQ9wd1iazGpFSl4JKdT7BwDU9/miDJmanQ== 330 | dependencies: 331 | "@parcel/diagnostic" "2.7.0" 332 | "@parcel/utils" "2.7.0" 333 | nullthrows "^1.1.1" 334 | semver "^5.7.1" 335 | 336 | "@parcel/optimizer-css@2.7.0": 337 | version "2.7.0" 338 | resolved "https://registry.yarnpkg.com/@parcel/optimizer-css/-/optimizer-css-2.7.0.tgz#460cde19b9ee61efed577473cb0822796b6e8b1a" 339 | integrity sha512-IfnOMACqhcAclKyOW9X9JpsknB6OShk9OVvb8EvbDTKHJhQHNNmzE88OkSI/pS3ZVZP9Zj+nWcVHguV+kvDeiQ== 340 | dependencies: 341 | "@parcel/css" "^1.12.2" 342 | "@parcel/diagnostic" "2.7.0" 343 | "@parcel/plugin" "2.7.0" 344 | "@parcel/source-map" "^2.0.0" 345 | "@parcel/utils" "2.7.0" 346 | browserslist "^4.6.6" 347 | nullthrows "^1.1.1" 348 | 349 | "@parcel/optimizer-htmlnano@2.7.0": 350 | version "2.7.0" 351 | resolved "https://registry.yarnpkg.com/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.7.0.tgz#d2e843b539a430fcca723f08efcee26f98b3d40b" 352 | integrity sha512-5QrGdWS5Hi4VXE3nQNrGqugmSXt68YIsWwKRAdarOxzyULSJS3gbCiQOXqIPRJobfZjnSIcdtkyxSiCUe1inIA== 353 | dependencies: 354 | "@parcel/plugin" "2.7.0" 355 | htmlnano "^2.0.0" 356 | nullthrows "^1.1.1" 357 | posthtml "^0.16.5" 358 | svgo "^2.4.0" 359 | 360 | "@parcel/optimizer-image@2.7.0": 361 | version "2.7.0" 362 | resolved "https://registry.yarnpkg.com/@parcel/optimizer-image/-/optimizer-image-2.7.0.tgz#180d7709e6268e0634967eb265bf901aba2471ce" 363 | integrity sha512-EnaXz5UjR67FUu0BEcqZTT9LsbB/iFAkkghCotbnbOuC5QQsloq6tw54TKU3y+R3qsjgUoMtGxPcGfVoXxZXYw== 364 | dependencies: 365 | "@parcel/diagnostic" "2.7.0" 366 | "@parcel/plugin" "2.7.0" 367 | "@parcel/utils" "2.7.0" 368 | "@parcel/workers" "2.7.0" 369 | detect-libc "^1.0.3" 370 | 371 | "@parcel/optimizer-svgo@2.7.0": 372 | version "2.7.0" 373 | resolved "https://registry.yarnpkg.com/@parcel/optimizer-svgo/-/optimizer-svgo-2.7.0.tgz#9b4ab38a9d3c99504cf399a5c7709e5d2a615e71" 374 | integrity sha512-IO1JV4NpfP3V7FrhsqCcV8pDQIHraFi1/ZvEJyssITxjH49Im/txKlwMiQuZZryAPn8Xb8g395Muawuk6AK6sg== 375 | dependencies: 376 | "@parcel/diagnostic" "2.7.0" 377 | "@parcel/plugin" "2.7.0" 378 | "@parcel/utils" "2.7.0" 379 | svgo "^2.4.0" 380 | 381 | "@parcel/optimizer-terser@2.7.0": 382 | version "2.7.0" 383 | resolved "https://registry.yarnpkg.com/@parcel/optimizer-terser/-/optimizer-terser-2.7.0.tgz#b9ef408f45714952d1502940b6a63e5ebd3f0940" 384 | integrity sha512-07VZjIO8xsl2/WmS/qHI8lI/cpu47iS9eRpqwfZEEsdk1cfz50jhWkmFudHBxiHGMfcZ//1+DdaPg9RDBWZtZA== 385 | dependencies: 386 | "@parcel/diagnostic" "2.7.0" 387 | "@parcel/plugin" "2.7.0" 388 | "@parcel/source-map" "^2.0.0" 389 | "@parcel/utils" "2.7.0" 390 | nullthrows "^1.1.1" 391 | terser "^5.2.0" 392 | 393 | "@parcel/package-manager@2.7.0": 394 | version "2.7.0" 395 | resolved "https://registry.yarnpkg.com/@parcel/package-manager/-/package-manager-2.7.0.tgz#5de1bf5c94d95330e98dffb2a66c22d1f20c4c8a" 396 | integrity sha512-wmfSX1mRrTi8MeA4KrnPk/x7zGUsILCQmTo6lA4gygzAxDbM1pGuyFN8/Kt0y0SFO2lbljARtD/4an5qdotH+Q== 397 | dependencies: 398 | "@parcel/diagnostic" "2.7.0" 399 | "@parcel/fs" "2.7.0" 400 | "@parcel/logger" "2.7.0" 401 | "@parcel/types" "2.7.0" 402 | "@parcel/utils" "2.7.0" 403 | "@parcel/workers" "2.7.0" 404 | semver "^5.7.1" 405 | 406 | "@parcel/packager-css@2.7.0": 407 | version "2.7.0" 408 | resolved "https://registry.yarnpkg.com/@parcel/packager-css/-/packager-css-2.7.0.tgz#060af8b96e5ad53620b4021610364804e26d69b2" 409 | integrity sha512-44nzZwu+ssGuiFmYM6cf/Y4iChiUZ4DUzzpegnGlhXtKJKe4NHntxThJynuRZWKN2AAf48avApDpimg2jW0KDw== 410 | dependencies: 411 | "@parcel/plugin" "2.7.0" 412 | "@parcel/source-map" "^2.0.0" 413 | "@parcel/utils" "2.7.0" 414 | nullthrows "^1.1.1" 415 | 416 | "@parcel/packager-html@2.7.0": 417 | version "2.7.0" 418 | resolved "https://registry.yarnpkg.com/@parcel/packager-html/-/packager-html-2.7.0.tgz#4f86698d05f5ec5c3ebc8b46102a6ae42c58a24a" 419 | integrity sha512-Zgqd7sdcY/UnR370GR0q2ilmEohUDXsO8A1F28QCJzIsR1iCB6KRUT74+pawfQ1IhXZLaaFLLYe0UWcfm0JeXg== 420 | dependencies: 421 | "@parcel/plugin" "2.7.0" 422 | "@parcel/types" "2.7.0" 423 | "@parcel/utils" "2.7.0" 424 | nullthrows "^1.1.1" 425 | posthtml "^0.16.5" 426 | 427 | "@parcel/packager-js@2.7.0": 428 | version "2.7.0" 429 | resolved "https://registry.yarnpkg.com/@parcel/packager-js/-/packager-js-2.7.0.tgz#e694cc731d75697e63d3d4be0bdbbe4a2ae8f1fc" 430 | integrity sha512-wTRdM81PgRVDzWGXdWmqLwguWnTYWzhEDdjXpW2n8uMOu/CjHhMtogk65aaYk3GOnq6OBL/NsrmBiV/zKPj1vA== 431 | dependencies: 432 | "@parcel/diagnostic" "2.7.0" 433 | "@parcel/hash" "2.7.0" 434 | "@parcel/plugin" "2.7.0" 435 | "@parcel/source-map" "^2.0.0" 436 | "@parcel/utils" "2.7.0" 437 | globals "^13.2.0" 438 | nullthrows "^1.1.1" 439 | 440 | "@parcel/packager-raw@2.7.0": 441 | version "2.7.0" 442 | resolved "https://registry.yarnpkg.com/@parcel/packager-raw/-/packager-raw-2.7.0.tgz#5b68de05c19bbcf438f40b4ae9f45411ba9739bd" 443 | integrity sha512-jg2Zp8dI5VpIQlaeahXDCfrPN9m/DKht1NkR9P2CylMAwqCcc1Xc1RRiF0wfwcPZpPMpq1265n+4qnB7rjGBlA== 444 | dependencies: 445 | "@parcel/plugin" "2.7.0" 446 | 447 | "@parcel/packager-svg@2.7.0": 448 | version "2.7.0" 449 | resolved "https://registry.yarnpkg.com/@parcel/packager-svg/-/packager-svg-2.7.0.tgz#e7e96503c86815eca285b9cc8908105075d9ab38" 450 | integrity sha512-EmJg3HpD6/xxKBjir/CdCKJZwI24iVfBuxRS9LUp3xHAIebOzVh1z6IN+i2Di5+NyRwfOFaLliL4uMa1zwbyCA== 451 | dependencies: 452 | "@parcel/plugin" "2.7.0" 453 | "@parcel/types" "2.7.0" 454 | "@parcel/utils" "2.7.0" 455 | posthtml "^0.16.4" 456 | 457 | "@parcel/plugin@2.7.0": 458 | version "2.7.0" 459 | resolved "https://registry.yarnpkg.com/@parcel/plugin/-/plugin-2.7.0.tgz#0211281025d02afbc5a23fba237b7aae02e34e51" 460 | integrity sha512-qqgx+nnMn6/0lRc4lKbLGmhNtBiT93S2gFNB4Eb4Pfz/SxVYoW+fmml+KdfOSiZffWOAH5L6NwhyD7N8aSikzw== 461 | dependencies: 462 | "@parcel/types" "2.7.0" 463 | 464 | "@parcel/reporter-cli@2.7.0": 465 | version "2.7.0" 466 | resolved "https://registry.yarnpkg.com/@parcel/reporter-cli/-/reporter-cli-2.7.0.tgz#86499624e258034001b64c10b14e23ae4b92f44b" 467 | integrity sha512-80gEODg8cnAmnxGVuaSVDo8JJ54P9AA2bHwSs1cIkHWlJ3BjDQb83H31bBHncJ5Kn5kQ/j+7WjlqHpTCiOR9PA== 468 | dependencies: 469 | "@parcel/plugin" "2.7.0" 470 | "@parcel/types" "2.7.0" 471 | "@parcel/utils" "2.7.0" 472 | chalk "^4.1.0" 473 | term-size "^2.2.1" 474 | 475 | "@parcel/reporter-dev-server@2.7.0": 476 | version "2.7.0" 477 | resolved "https://registry.yarnpkg.com/@parcel/reporter-dev-server/-/reporter-dev-server-2.7.0.tgz#9bd3d10f745e0cbc9ab983ec046953c2c564dcb2" 478 | integrity sha512-ySuou5addK8fGue8aXzo536BaEjMujDrEc1xkp4TasInXHVcA98b+SYX5NAZTGob5CxKvZQ5ylhg77zW30B+iA== 479 | dependencies: 480 | "@parcel/plugin" "2.7.0" 481 | "@parcel/utils" "2.7.0" 482 | 483 | "@parcel/resolver-default@2.7.0": 484 | version "2.7.0" 485 | resolved "https://registry.yarnpkg.com/@parcel/resolver-default/-/resolver-default-2.7.0.tgz#648a257b81abe2eda09700d8f36348a88ea0442e" 486 | integrity sha512-v8TvWsbLK7/q7n4gv6OrYNbW18xUx4zKbVMGZb1u4yMhzEH4HFr1D9OeoTq3jk+ximAigds8B6triQbL5exF7A== 487 | dependencies: 488 | "@parcel/node-resolver-core" "2.7.0" 489 | "@parcel/plugin" "2.7.0" 490 | 491 | "@parcel/runtime-browser-hmr@2.7.0": 492 | version "2.7.0" 493 | resolved "https://registry.yarnpkg.com/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.7.0.tgz#aed79b96c0d97021f56f2b7e35bc2d4f70869e26" 494 | integrity sha512-PLbMLdclQeYsi2LkilZVGFV1n3y55G1jaBvby4ekedUZjMw3SWdMY2tDxgSDdFWfLCnYHJXdGUQSzGGi1kPzjA== 495 | dependencies: 496 | "@parcel/plugin" "2.7.0" 497 | "@parcel/utils" "2.7.0" 498 | 499 | "@parcel/runtime-js@2.7.0": 500 | version "2.7.0" 501 | resolved "https://registry.yarnpkg.com/@parcel/runtime-js/-/runtime-js-2.7.0.tgz#63dd744e96c3554ac86778ffce1c8055e7653fce" 502 | integrity sha512-9/YUZTBNrSN2H6rbz/o1EOM0O7I3ZR/x9IDzxjJBD6Mi+0uCgCD02aedare/SNr1qgnbZZWmhpOzC+YgREcfLA== 503 | dependencies: 504 | "@parcel/plugin" "2.7.0" 505 | "@parcel/utils" "2.7.0" 506 | nullthrows "^1.1.1" 507 | 508 | "@parcel/runtime-react-refresh@2.7.0": 509 | version "2.7.0" 510 | resolved "https://registry.yarnpkg.com/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.7.0.tgz#c56b847ef1144264e918339381e040ffe811efc5" 511 | integrity sha512-vDKO0rWqRzEpmvoZ4kkYUiSsTxT5NnH904BFPFxKI0wJCl6yEmPuEifmATo73OuYhP6jIP3Qfl1R4TtiDFPJ1Q== 512 | dependencies: 513 | "@parcel/plugin" "2.7.0" 514 | "@parcel/utils" "2.7.0" 515 | react-error-overlay "6.0.9" 516 | react-refresh "^0.9.0" 517 | 518 | "@parcel/runtime-service-worker@2.7.0": 519 | version "2.7.0" 520 | resolved "https://registry.yarnpkg.com/@parcel/runtime-service-worker/-/runtime-service-worker-2.7.0.tgz#352c3722ec635eee2898d9698541e3c1f53e8906" 521 | integrity sha512-uD2pAV0yV6+e7JaWH4KVPbG+zRCrxr/OACyS9tIh+Q/R1vRmh8zGM3yhdrcoiZ7tFOnM72vd6xY11eTrUsSVig== 522 | dependencies: 523 | "@parcel/plugin" "2.7.0" 524 | "@parcel/utils" "2.7.0" 525 | nullthrows "^1.1.1" 526 | 527 | "@parcel/source-map@^2.0.0": 528 | version "2.1.1" 529 | resolved "https://registry.yarnpkg.com/@parcel/source-map/-/source-map-2.1.1.tgz#fb193b82dba6dd62cc7a76b326f57bb35000a782" 530 | integrity sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew== 531 | dependencies: 532 | detect-libc "^1.0.3" 533 | 534 | "@parcel/transformer-babel@2.7.0": 535 | version "2.7.0" 536 | resolved "https://registry.yarnpkg.com/@parcel/transformer-babel/-/transformer-babel-2.7.0.tgz#eae98d50a99cd722c3146cd57c479bfb86f537b2" 537 | integrity sha512-7iklDXXnKH1530+QbI+e4kIJ+Q1puA1ulRS10db3aUJMj5GnvXGDFwhSZ7+T1ps66QHO7cVO29VlbqiRDarH1Q== 538 | dependencies: 539 | "@parcel/diagnostic" "2.7.0" 540 | "@parcel/plugin" "2.7.0" 541 | "@parcel/source-map" "^2.0.0" 542 | "@parcel/utils" "2.7.0" 543 | browserslist "^4.6.6" 544 | json5 "^2.2.0" 545 | nullthrows "^1.1.1" 546 | semver "^5.7.0" 547 | 548 | "@parcel/transformer-css@2.7.0": 549 | version "2.7.0" 550 | resolved "https://registry.yarnpkg.com/@parcel/transformer-css/-/transformer-css-2.7.0.tgz#d0879ec04191e5ba3eadb6fc06b7ec0db3f5c3f6" 551 | integrity sha512-J4EpWK9spQpXyNCmKK8Xnane0xW/1B/EAmfp7Fiv7g+5yUjY4ODf4KUugvE+Eb2gekPkhOKNHermO2KrX0/PFA== 552 | dependencies: 553 | "@parcel/css" "^1.12.2" 554 | "@parcel/diagnostic" "2.7.0" 555 | "@parcel/plugin" "2.7.0" 556 | "@parcel/source-map" "^2.0.0" 557 | "@parcel/utils" "2.7.0" 558 | browserslist "^4.6.6" 559 | nullthrows "^1.1.1" 560 | 561 | "@parcel/transformer-html@2.7.0": 562 | version "2.7.0" 563 | resolved "https://registry.yarnpkg.com/@parcel/transformer-html/-/transformer-html-2.7.0.tgz#5397a924fea683ef2c345f36f99f67f0181d6967" 564 | integrity sha512-wYJl5rn81W+Rlk9oQwDJcjoVsWVDKyeri84FzmlGXOsg0EYgnqOiG+3MDM8GeZjfuGe5fuoum4eqZeS0WdUHXw== 565 | dependencies: 566 | "@parcel/diagnostic" "2.7.0" 567 | "@parcel/hash" "2.7.0" 568 | "@parcel/plugin" "2.7.0" 569 | nullthrows "^1.1.1" 570 | posthtml "^0.16.5" 571 | posthtml-parser "^0.10.1" 572 | posthtml-render "^3.0.0" 573 | semver "^5.7.1" 574 | 575 | "@parcel/transformer-image@2.7.0": 576 | version "2.7.0" 577 | resolved "https://registry.yarnpkg.com/@parcel/transformer-image/-/transformer-image-2.7.0.tgz#e569ffc426c6060bc4dcccc0347c526930abfba4" 578 | integrity sha512-mhi9/R5/ULhCkL2COVIKhNFoLDiZwQgprdaTJr5fnODggVxEX5o7ebFV6KNLMTEkwZUJWoB1hL0ziI0++DtoFA== 579 | dependencies: 580 | "@parcel/plugin" "2.7.0" 581 | "@parcel/utils" "2.7.0" 582 | "@parcel/workers" "2.7.0" 583 | nullthrows "^1.1.1" 584 | 585 | "@parcel/transformer-js@2.7.0": 586 | version "2.7.0" 587 | resolved "https://registry.yarnpkg.com/@parcel/transformer-js/-/transformer-js-2.7.0.tgz#1e69295a11bf70d880cdd3846cf89016a74aac50" 588 | integrity sha512-mzerR+D4rDomUSIk5RSTa2w+DXBdXUeQrpDO74WCDdpDi1lIl8ppFpqtmU7O6y6p8QsgkmS9b0g/vhcry6CJTA== 589 | dependencies: 590 | "@parcel/diagnostic" "2.7.0" 591 | "@parcel/plugin" "2.7.0" 592 | "@parcel/source-map" "^2.0.0" 593 | "@parcel/utils" "2.7.0" 594 | "@parcel/workers" "2.7.0" 595 | "@swc/helpers" "^0.4.2" 596 | browserslist "^4.6.6" 597 | detect-libc "^1.0.3" 598 | nullthrows "^1.1.1" 599 | regenerator-runtime "^0.13.7" 600 | semver "^5.7.1" 601 | 602 | "@parcel/transformer-json@2.7.0": 603 | version "2.7.0" 604 | resolved "https://registry.yarnpkg.com/@parcel/transformer-json/-/transformer-json-2.7.0.tgz#c203f74cd445ce93eb833dd88be8127d1eadc6c3" 605 | integrity sha512-RQjuxBpYOch+kr4a0zi77KJtOLTPYRM7iq4NN80zKnA0r0dwDUCxZBtaj2l0O0o3R4MMJnm+ncP+cB7XR7dZYA== 606 | dependencies: 607 | "@parcel/plugin" "2.7.0" 608 | json5 "^2.2.0" 609 | 610 | "@parcel/transformer-postcss@2.7.0": 611 | version "2.7.0" 612 | resolved "https://registry.yarnpkg.com/@parcel/transformer-postcss/-/transformer-postcss-2.7.0.tgz#66be4469ae9186c89638ff67ec5808139caaeb8e" 613 | integrity sha512-b6RskXBWf0MjpC9qjR2dQ1ZdRnlOiKYseG5CEovWCqM218RtdydFKz7jS+5Gxkb6qBtOG7zGPONXdPe+gTILcA== 614 | dependencies: 615 | "@parcel/diagnostic" "2.7.0" 616 | "@parcel/hash" "2.7.0" 617 | "@parcel/plugin" "2.7.0" 618 | "@parcel/utils" "2.7.0" 619 | clone "^2.1.1" 620 | nullthrows "^1.1.1" 621 | postcss-value-parser "^4.2.0" 622 | semver "^5.7.1" 623 | 624 | "@parcel/transformer-posthtml@2.7.0": 625 | version "2.7.0" 626 | resolved "https://registry.yarnpkg.com/@parcel/transformer-posthtml/-/transformer-posthtml-2.7.0.tgz#67d5761b895574edb771f7ab1b24ec80775f58bd" 627 | integrity sha512-cP8YOiSynWJ1ycmBlhnnHeuQb2cwmklZ+BNyLUktj5p78kDy2de7VjX+dRNRHoW4H9OgEcSF4UEfDVVz5RYIhw== 628 | dependencies: 629 | "@parcel/plugin" "2.7.0" 630 | "@parcel/utils" "2.7.0" 631 | nullthrows "^1.1.1" 632 | posthtml "^0.16.5" 633 | posthtml-parser "^0.10.1" 634 | posthtml-render "^3.0.0" 635 | semver "^5.7.1" 636 | 637 | "@parcel/transformer-raw@2.7.0": 638 | version "2.7.0" 639 | resolved "https://registry.yarnpkg.com/@parcel/transformer-raw/-/transformer-raw-2.7.0.tgz#d6d8b94d1b33efc3dbf748ec1954c8917a2e1566" 640 | integrity sha512-sDnItWCFSDez0izK1i5cgv+kXzZTbcJh4rNpVIgmE1kBLvAz608sqgcCkavb2wVJIvLesxYM+5G4p1CwkDlZ1g== 641 | dependencies: 642 | "@parcel/plugin" "2.7.0" 643 | 644 | "@parcel/transformer-react-refresh-wrap@2.7.0": 645 | version "2.7.0" 646 | resolved "https://registry.yarnpkg.com/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.7.0.tgz#e206b529d4a3444e14ba329d3323c5be3ded25d2" 647 | integrity sha512-1vRmIJzyBA1nIiXTAU6tZExq2FvJj/2F0ft6KDw8GYPv0KjmdiPo/PmaZ7JeSVOM6SdXQIQCbTmp1vkMP7DtkA== 648 | dependencies: 649 | "@parcel/plugin" "2.7.0" 650 | "@parcel/utils" "2.7.0" 651 | react-refresh "^0.9.0" 652 | 653 | "@parcel/transformer-sass@2.7.0": 654 | version "2.7.0" 655 | resolved "https://registry.yarnpkg.com/@parcel/transformer-sass/-/transformer-sass-2.7.0.tgz#651b7a88bbc1ef452ace90ccb0883c1ad8cff721" 656 | integrity sha512-6m2T6Y5eQLX7ckIeuOjXXIZbzhyovnl69AvJ2FujoWb2nA55H/kg6ZdbKjo3CfXkOfg9LyG3nVnOE5PMgMpRFQ== 657 | dependencies: 658 | "@parcel/plugin" "2.7.0" 659 | "@parcel/source-map" "^2.0.0" 660 | sass "^1.38.0" 661 | 662 | "@parcel/transformer-svg@2.7.0": 663 | version "2.7.0" 664 | resolved "https://registry.yarnpkg.com/@parcel/transformer-svg/-/transformer-svg-2.7.0.tgz#c2a7d10bdbc6aeb2ae7ef85db5b583574807071c" 665 | integrity sha512-ioER37zceuuE+K6ZrnjCyMUWEnv+63hIAFResc1OXxRhyt+7kzMz9ZqK0Mt6QMLwl1dxhkLmrU41n9IxzKZuSQ== 666 | dependencies: 667 | "@parcel/diagnostic" "2.7.0" 668 | "@parcel/hash" "2.7.0" 669 | "@parcel/plugin" "2.7.0" 670 | nullthrows "^1.1.1" 671 | posthtml "^0.16.5" 672 | posthtml-parser "^0.10.1" 673 | posthtml-render "^3.0.0" 674 | semver "^5.7.1" 675 | 676 | "@parcel/types@2.7.0": 677 | version "2.7.0" 678 | resolved "https://registry.yarnpkg.com/@parcel/types/-/types-2.7.0.tgz#c89e95964339324c1931ef7a17906a72291d6b73" 679 | integrity sha512-+dhXVUnseTCpJvBTGMp0V6X13z6O/A/+CUtwEpMGZ8XSmZ4Gk44GvaTiBOp0bJpWG4fvCKp+UmC8PYbrDiiziw== 680 | dependencies: 681 | "@parcel/cache" "2.7.0" 682 | "@parcel/diagnostic" "2.7.0" 683 | "@parcel/fs" "2.7.0" 684 | "@parcel/package-manager" "2.7.0" 685 | "@parcel/source-map" "^2.0.0" 686 | "@parcel/workers" "2.7.0" 687 | utility-types "^3.10.0" 688 | 689 | "@parcel/utils@2.7.0": 690 | version "2.7.0" 691 | resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-2.7.0.tgz#f795d0f43efdd449ab0bbfac3632cd7f3ec0e4dd" 692 | integrity sha512-jNZ5bIGg1r1RDRKi562o4kuVwnz+XJ2Ie3b0Zwrqwvgfj6AbRFIKzDd+h85dWWmcDYzKUbHp11u6VJl1u8Vapg== 693 | dependencies: 694 | "@parcel/codeframe" "2.7.0" 695 | "@parcel/diagnostic" "2.7.0" 696 | "@parcel/hash" "2.7.0" 697 | "@parcel/logger" "2.7.0" 698 | "@parcel/markdown-ansi" "2.7.0" 699 | "@parcel/source-map" "^2.0.0" 700 | chalk "^4.1.0" 701 | 702 | "@parcel/watcher@^2.0.0": 703 | version "2.0.6" 704 | resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.6.tgz#9087e44ea93b2d7e901d479bb9b0578f25b2173a" 705 | integrity sha512-6CaHXp6BNrFY5375OGQLSeaxfO8csgGWbO1U2nUqufDtUks7ZIG5wAyj/wR1zkOxRrhN0EaZWvlgSKYqo7a9lg== 706 | dependencies: 707 | node-addon-api "^3.2.1" 708 | node-gyp-build "^4.3.0" 709 | 710 | "@parcel/workers@2.7.0": 711 | version "2.7.0" 712 | resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-2.7.0.tgz#d74955d361337127227912a5ab26cb3079ebfc78" 713 | integrity sha512-99VfaOX+89+RaoTSyH9ZQtkMBFZBFMvJmVJ/GeJT6QCd2wtKBStTHlaSnQOkLD/iRjJCNwV2xpZmm8YkTwV+hg== 714 | dependencies: 715 | "@parcel/diagnostic" "2.7.0" 716 | "@parcel/logger" "2.7.0" 717 | "@parcel/types" "2.7.0" 718 | "@parcel/utils" "2.7.0" 719 | chrome-trace-event "^1.0.2" 720 | nullthrows "^1.1.1" 721 | 722 | "@swc/helpers@^0.4.2": 723 | version "0.4.12" 724 | resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.12.tgz#203243e78cff3c87c081c97ae548ab33e2503573" 725 | integrity sha512-R6RmwS9Dld5lNvwKlPn62+piU+WDG1sMfsnfJioXCciyko/gZ0DQ4Mqglhq1iGU1nQ/RcGkAwfMH+elMSkJH3Q== 726 | dependencies: 727 | tslib "^2.4.0" 728 | 729 | "@trysound/sax@0.2.0": 730 | version "0.2.0" 731 | resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" 732 | integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== 733 | 734 | "@types/parse-json@^4.0.0": 735 | version "4.0.0" 736 | resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" 737 | integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== 738 | 739 | "@types/prop-types@*": 740 | version "15.7.3" 741 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" 742 | integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== 743 | 744 | "@types/react-dom@^18.0.8": 745 | version "18.0.8" 746 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.8.tgz#d2606d855186cd42cc1b11e63a71c39525441685" 747 | integrity sha512-C3GYO0HLaOkk9dDAz3Dl4sbe4AKUGTCfFIZsz3n/82dPNN8Du533HzKatDxeUYWu24wJgMP1xICqkWk1YOLOIw== 748 | dependencies: 749 | "@types/react" "*" 750 | 751 | "@types/react@*": 752 | version "16.9.51" 753 | resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.51.tgz#f8aa51ffa9996f1387f63686696d9b59713d2b60" 754 | integrity sha512-lQa12IyO+DMlnSZ3+AGHRUiUcpK47aakMMoBG8f7HGxJT8Yfe+WE128HIXaHOHVPReAW0oDS3KAI0JI2DDe1PQ== 755 | dependencies: 756 | "@types/prop-types" "*" 757 | csstype "^3.0.2" 758 | 759 | "@types/react@^18.0.24": 760 | version "18.0.24" 761 | resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.24.tgz#2f79ed5b27f08d05107aab45c17919754cc44c20" 762 | integrity sha512-wRJWT6ouziGUy+9uX0aW4YOJxAY0bG6/AOk5AW5QSvZqI7dk6VBIbXvcVgIw/W5Jrl24f77df98GEKTJGOLx7Q== 763 | dependencies: 764 | "@types/prop-types" "*" 765 | "@types/scheduler" "*" 766 | csstype "^3.0.2" 767 | 768 | "@types/scheduler@*": 769 | version "0.16.2" 770 | resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" 771 | integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== 772 | 773 | abortcontroller-polyfill@^1.1.9: 774 | version "1.7.5" 775 | resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" 776 | integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== 777 | 778 | acorn@^8.5.0: 779 | version "8.8.1" 780 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" 781 | integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== 782 | 783 | ansi-styles@^3.2.1: 784 | version "3.2.1" 785 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 786 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 787 | dependencies: 788 | color-convert "^1.9.0" 789 | 790 | ansi-styles@^4.1.0: 791 | version "4.3.0" 792 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 793 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 794 | dependencies: 795 | color-convert "^2.0.1" 796 | 797 | anymatch@~3.1.2: 798 | version "3.1.2" 799 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 800 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 801 | dependencies: 802 | normalize-path "^3.0.0" 803 | picomatch "^2.0.4" 804 | 805 | asap@~2.0.6: 806 | version "2.0.6" 807 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 808 | integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= 809 | 810 | base-x@^3.0.8: 811 | version "3.0.9" 812 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" 813 | integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== 814 | dependencies: 815 | safe-buffer "^5.0.1" 816 | 817 | binary-extensions@^2.0.0: 818 | version "2.2.0" 819 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 820 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 821 | 822 | boolbase@^1.0.0: 823 | version "1.0.0" 824 | resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" 825 | integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= 826 | 827 | braces@~3.0.2: 828 | version "3.0.2" 829 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 830 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 831 | dependencies: 832 | fill-range "^7.0.1" 833 | 834 | browserslist@^4.6.6: 835 | version "4.21.4" 836 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" 837 | integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== 838 | dependencies: 839 | caniuse-lite "^1.0.30001400" 840 | electron-to-chromium "^1.4.251" 841 | node-releases "^2.0.6" 842 | update-browserslist-db "^1.0.9" 843 | 844 | buffer-from@^1.0.0: 845 | version "1.1.1" 846 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 847 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 848 | 849 | callsites@^3.0.0: 850 | version "3.1.0" 851 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 852 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 853 | 854 | caniuse-lite@^1.0.30001400: 855 | version "1.0.30001429" 856 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz#70cdae959096756a85713b36dd9cb82e62325639" 857 | integrity sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg== 858 | 859 | chalk@^2.0.0: 860 | version "2.4.2" 861 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 862 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 863 | dependencies: 864 | ansi-styles "^3.2.1" 865 | escape-string-regexp "^1.0.5" 866 | supports-color "^5.3.0" 867 | 868 | chalk@^4.1.0: 869 | version "4.1.2" 870 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 871 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 872 | dependencies: 873 | ansi-styles "^4.1.0" 874 | supports-color "^7.1.0" 875 | 876 | "chokidar@>=3.0.0 <4.0.0": 877 | version "3.5.3" 878 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 879 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 880 | dependencies: 881 | anymatch "~3.1.2" 882 | braces "~3.0.2" 883 | glob-parent "~5.1.2" 884 | is-binary-path "~2.1.0" 885 | is-glob "~4.0.1" 886 | normalize-path "~3.0.0" 887 | readdirp "~3.6.0" 888 | optionalDependencies: 889 | fsevents "~2.3.2" 890 | 891 | chrome-trace-event@^1.0.2: 892 | version "1.0.3" 893 | resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" 894 | integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== 895 | 896 | clone@^2.1.1: 897 | version "2.1.2" 898 | resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" 899 | integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= 900 | 901 | color-convert@^1.9.0: 902 | version "1.9.3" 903 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 904 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 905 | dependencies: 906 | color-name "1.1.3" 907 | 908 | color-convert@^2.0.1: 909 | version "2.0.1" 910 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 911 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 912 | dependencies: 913 | color-name "~1.1.4" 914 | 915 | color-name@1.1.3: 916 | version "1.1.3" 917 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 918 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 919 | 920 | color-name@~1.1.4: 921 | version "1.1.4" 922 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 923 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 924 | 925 | commander@^2.20.0: 926 | version "2.20.3" 927 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 928 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 929 | 930 | commander@^7.0.0, commander@^7.2.0: 931 | version "7.2.0" 932 | resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" 933 | integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== 934 | 935 | core-js@^3.19.2: 936 | version "3.26.0" 937 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.0.tgz#a516db0ed0811be10eac5d94f3b8463d03faccfe" 938 | integrity sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw== 939 | 940 | cosmiconfig@^7.0.1: 941 | version "7.0.1" 942 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" 943 | integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== 944 | dependencies: 945 | "@types/parse-json" "^4.0.0" 946 | import-fresh "^3.2.1" 947 | parse-json "^5.0.0" 948 | path-type "^4.0.0" 949 | yaml "^1.10.0" 950 | 951 | css-select@^4.1.3: 952 | version "4.3.0" 953 | resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" 954 | integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== 955 | dependencies: 956 | boolbase "^1.0.0" 957 | css-what "^6.0.1" 958 | domhandler "^4.3.1" 959 | domutils "^2.8.0" 960 | nth-check "^2.0.1" 961 | 962 | css-tree@^1.1.2, css-tree@^1.1.3: 963 | version "1.1.3" 964 | resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" 965 | integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== 966 | dependencies: 967 | mdn-data "2.0.14" 968 | source-map "^0.6.1" 969 | 970 | css-what@^6.0.1: 971 | version "6.1.0" 972 | resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" 973 | integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== 974 | 975 | csso@^4.2.0: 976 | version "4.2.0" 977 | resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" 978 | integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== 979 | dependencies: 980 | css-tree "^1.1.2" 981 | 982 | csstype@^3.0.2: 983 | version "3.0.3" 984 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" 985 | integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== 986 | 987 | detect-libc@^1.0.3: 988 | version "1.0.3" 989 | resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" 990 | integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== 991 | 992 | dom-serializer@^1.0.1: 993 | version "1.4.1" 994 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" 995 | integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== 996 | dependencies: 997 | domelementtype "^2.0.1" 998 | domhandler "^4.2.0" 999 | entities "^2.0.0" 1000 | 1001 | domelementtype@^2.0.1: 1002 | version "2.0.2" 1003 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" 1004 | integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== 1005 | 1006 | domelementtype@^2.2.0: 1007 | version "2.3.0" 1008 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" 1009 | integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== 1010 | 1011 | domhandler@^4.2.0, domhandler@^4.2.2, domhandler@^4.3.1: 1012 | version "4.3.1" 1013 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" 1014 | integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== 1015 | dependencies: 1016 | domelementtype "^2.2.0" 1017 | 1018 | domutils@^2.8.0: 1019 | version "2.8.0" 1020 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" 1021 | integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== 1022 | dependencies: 1023 | dom-serializer "^1.0.1" 1024 | domelementtype "^2.2.0" 1025 | domhandler "^4.2.0" 1026 | 1027 | dotenv-expand@^5.1.0: 1028 | version "5.1.0" 1029 | resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" 1030 | integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== 1031 | 1032 | dotenv@^7.0.0: 1033 | version "7.0.0" 1034 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-7.0.0.tgz#a2be3cd52736673206e8a85fb5210eea29628e7c" 1035 | integrity sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g== 1036 | 1037 | electron-to-chromium@^1.4.251: 1038 | version "1.4.284" 1039 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" 1040 | integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== 1041 | 1042 | entities@^2.0.0: 1043 | version "2.0.3" 1044 | resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" 1045 | integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== 1046 | 1047 | entities@^3.0.1: 1048 | version "3.0.1" 1049 | resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" 1050 | integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== 1051 | 1052 | error-ex@^1.3.1: 1053 | version "1.3.2" 1054 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 1055 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 1056 | dependencies: 1057 | is-arrayish "^0.2.1" 1058 | 1059 | escalade@^3.1.1: 1060 | version "3.1.1" 1061 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 1062 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 1063 | 1064 | escape-string-regexp@^1.0.5: 1065 | version "1.0.5" 1066 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 1067 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 1068 | 1069 | fill-range@^7.0.1: 1070 | version "7.0.1" 1071 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 1072 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 1073 | dependencies: 1074 | to-regex-range "^5.0.1" 1075 | 1076 | fsevents@~2.3.2: 1077 | version "2.3.2" 1078 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 1079 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 1080 | 1081 | get-port@^4.2.0: 1082 | version "4.2.0" 1083 | resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" 1084 | integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw== 1085 | 1086 | glob-parent@~5.1.2: 1087 | version "5.1.2" 1088 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 1089 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 1090 | dependencies: 1091 | is-glob "^4.0.1" 1092 | 1093 | globals@^13.2.0: 1094 | version "13.17.0" 1095 | resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" 1096 | integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== 1097 | dependencies: 1098 | type-fest "^0.20.2" 1099 | 1100 | has-flag@^3.0.0: 1101 | version "3.0.0" 1102 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 1103 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 1104 | 1105 | has-flag@^4.0.0: 1106 | version "4.0.0" 1107 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 1108 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 1109 | 1110 | htmlnano@^2.0.0: 1111 | version "2.0.2" 1112 | resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-2.0.2.tgz#3e3170941e2446a86211196d740272ebca78f878" 1113 | integrity sha512-+ZrQFS4Ub+zd+/fWwfvoYCEGNEa0/zrpys6CyXxvZDwtL7Pl+pOtRkiujyvBQ7Lmfp7/iEPxtOFgxWA16Gkj3w== 1114 | dependencies: 1115 | cosmiconfig "^7.0.1" 1116 | posthtml "^0.16.5" 1117 | timsort "^0.3.0" 1118 | 1119 | htmlparser2@^7.1.1: 1120 | version "7.2.0" 1121 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.2.0.tgz#8817cdea38bbc324392a90b1990908e81a65f5a5" 1122 | integrity sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog== 1123 | dependencies: 1124 | domelementtype "^2.0.1" 1125 | domhandler "^4.2.2" 1126 | domutils "^2.8.0" 1127 | entities "^3.0.1" 1128 | 1129 | immutable@^4.0.0: 1130 | version "4.1.0" 1131 | resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" 1132 | integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== 1133 | 1134 | import-fresh@^3.2.1: 1135 | version "3.3.0" 1136 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 1137 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 1138 | dependencies: 1139 | parent-module "^1.0.0" 1140 | resolve-from "^4.0.0" 1141 | 1142 | is-arrayish@^0.2.1: 1143 | version "0.2.1" 1144 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 1145 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 1146 | 1147 | is-binary-path@~2.1.0: 1148 | version "2.1.0" 1149 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 1150 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 1151 | dependencies: 1152 | binary-extensions "^2.0.0" 1153 | 1154 | is-extglob@^2.1.1: 1155 | version "2.1.1" 1156 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 1157 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 1158 | 1159 | is-glob@^4.0.1, is-glob@~4.0.1: 1160 | version "4.0.3" 1161 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 1162 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 1163 | dependencies: 1164 | is-extglob "^2.1.1" 1165 | 1166 | is-json@^2.0.1: 1167 | version "2.0.1" 1168 | resolved "https://registry.yarnpkg.com/is-json/-/is-json-2.0.1.tgz#6be166d144828a131d686891b983df62c39491ff" 1169 | integrity sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA== 1170 | 1171 | is-number@^7.0.0: 1172 | version "7.0.0" 1173 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 1174 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 1175 | 1176 | js-tokens@^4.0.0: 1177 | version "4.0.0" 1178 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 1179 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 1180 | 1181 | json-parse-even-better-errors@^2.3.0: 1182 | version "2.3.1" 1183 | resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 1184 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 1185 | 1186 | json5@^2.2.0, json5@^2.2.1: 1187 | version "2.2.1" 1188 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" 1189 | integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== 1190 | 1191 | lightningcss-darwin-arm64@1.16.0: 1192 | version "1.16.0" 1193 | resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.16.0.tgz#f3318a2e64ca160610977675ee1a7e611f4a3617" 1194 | integrity sha512-gIhz6eZFwsC4oVMjBGQ3QWDdLQY7vcXFyM/x91PilgHqu63B9uBa10EZA75YoTEkbKhoz0uDCqyHh/EoF1GrkQ== 1195 | 1196 | lightningcss-darwin-x64@1.16.0: 1197 | version "1.16.0" 1198 | resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.16.0.tgz#46361b701b572ce9ec29730624000b439c2184bb" 1199 | integrity sha512-kLPi+OEpDj3UGY6DC8TfjbcULJDKMP+TVKSlrEkNGn8t1YRzi2g4oy7UVTSB5AnSbT0CusUItzdVjHQ49EdoNA== 1200 | 1201 | lightningcss-linux-arm-gnueabihf@1.16.0: 1202 | version "1.16.0" 1203 | resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.16.0.tgz#5da29f465dd44d98434b00b424cc4b445ea49eff" 1204 | integrity sha512-oSwEbvXUPr//H/ainBRJXTxHerlheee/KgkTTmAQWiVnt8HV+bRohTBWWPBy5ZArgiGLwj7ogv45istgljPN2Q== 1205 | 1206 | lightningcss-linux-arm64-gnu@1.16.0: 1207 | version "1.16.0" 1208 | resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.16.0.tgz#21d139f5201c9b8bb3972c24116a5bcbb7e2c3b5" 1209 | integrity sha512-Drq9BSVIvmV9zsDJbCZWCulMvKMQWFIlYXPCKV/iwRj+ZAJ1BRngma0cNHB6uW7Wac8Jg04CJN5IA4ELE3J+cQ== 1210 | 1211 | lightningcss-linux-arm64-musl@1.16.0: 1212 | version "1.16.0" 1213 | resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.16.0.tgz#d06936e0570fb51d58cc18ef2fb8858aeecd1979" 1214 | integrity sha512-1QXWStnTEo4RFQf0mfGhRyNUeEHilCZ0NA97XgwKwrYr/M7sYKU/1HWY00dPxFJ6GITR2pfJGo9xi3ScSSBxbA== 1215 | 1216 | lightningcss-linux-x64-gnu@1.16.0: 1217 | version "1.16.0" 1218 | resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.16.0.tgz#fd9881cd839cac4676a01b713b06b0b178743f87" 1219 | integrity sha512-gD2eQYD5OFs1p83R0TcMCEc5HRyJES4lR4THmclv7khm3dc9vc+2VT0kFBPxO1L2AwlZuvXaaMan7X1Ul7uSfA== 1220 | 1221 | lightningcss-linux-x64-musl@1.16.0: 1222 | version "1.16.0" 1223 | resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.16.0.tgz#697d87448e0f6445b6fc3cf8529d89709f3bfacc" 1224 | integrity sha512-HJsKeYxloEvg2WCQhtYPqzZUliLu9JBJNeI5y9cPQeDR/7ayGGLbVhJaotPtzJkElOFL/SaXsS+FRuH4w+yafg== 1225 | 1226 | lightningcss-win32-x64-msvc@1.16.0: 1227 | version "1.16.0" 1228 | resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.16.0.tgz#e4a09c12a48534121ecd03ef0be8dadbbbbb63b6" 1229 | integrity sha512-h4ayyAlOMLUHV9NdofcIu79aEjmly93adVxcg5wDJpkvMiwDTufEN30M8G4gGcjo1JE5jFjAcyQcRpXYkYcemA== 1230 | 1231 | lightningcss@^1.14.0: 1232 | version "1.16.0" 1233 | resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.16.0.tgz#4c8e4ef8133d54488d1482a115d3758259191c52" 1234 | integrity sha512-5+ZS9h+xeADcJTF2oRCT3yNZBlDYyOgQSdrWNBCqsIwm8ucKbF061OBVv/WHP4Zk8FToNhwFklk/hMuOngqsIg== 1235 | dependencies: 1236 | detect-libc "^1.0.3" 1237 | optionalDependencies: 1238 | lightningcss-darwin-arm64 "1.16.0" 1239 | lightningcss-darwin-x64 "1.16.0" 1240 | lightningcss-linux-arm-gnueabihf "1.16.0" 1241 | lightningcss-linux-arm64-gnu "1.16.0" 1242 | lightningcss-linux-arm64-musl "1.16.0" 1243 | lightningcss-linux-x64-gnu "1.16.0" 1244 | lightningcss-linux-x64-musl "1.16.0" 1245 | lightningcss-win32-x64-msvc "1.16.0" 1246 | 1247 | lines-and-columns@^1.1.6: 1248 | version "1.2.4" 1249 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" 1250 | integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== 1251 | 1252 | lmdb@2.5.2: 1253 | version "2.5.2" 1254 | resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.5.2.tgz#37e28a9fb43405f4dc48c44cec0e13a14c4a6ff1" 1255 | integrity sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA== 1256 | dependencies: 1257 | msgpackr "^1.5.4" 1258 | node-addon-api "^4.3.0" 1259 | node-gyp-build-optional-packages "5.0.3" 1260 | ordered-binary "^1.2.4" 1261 | weak-lru-cache "^1.2.2" 1262 | optionalDependencies: 1263 | "@lmdb/lmdb-darwin-arm64" "2.5.2" 1264 | "@lmdb/lmdb-darwin-x64" "2.5.2" 1265 | "@lmdb/lmdb-linux-arm" "2.5.2" 1266 | "@lmdb/lmdb-linux-arm64" "2.5.2" 1267 | "@lmdb/lmdb-linux-x64" "2.5.2" 1268 | "@lmdb/lmdb-win32-x64" "2.5.2" 1269 | 1270 | mdn-data@2.0.14: 1271 | version "2.0.14" 1272 | resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" 1273 | integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== 1274 | 1275 | msgpackr-extract@^2.1.2: 1276 | version "2.1.2" 1277 | resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.1.2.tgz#56272030f3e163e1b51964ef8b1cd5e7240c03ed" 1278 | integrity sha512-cmrmERQFb19NX2JABOGtrKdHMyI6RUyceaPBQ2iRz9GnDkjBWFjNJC0jyyoOfZl2U/LZE3tQCCQc4dlRyA8mcA== 1279 | dependencies: 1280 | node-gyp-build-optional-packages "5.0.3" 1281 | optionalDependencies: 1282 | "@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.1.2" 1283 | "@msgpackr-extract/msgpackr-extract-darwin-x64" "2.1.2" 1284 | "@msgpackr-extract/msgpackr-extract-linux-arm" "2.1.2" 1285 | "@msgpackr-extract/msgpackr-extract-linux-arm64" "2.1.2" 1286 | "@msgpackr-extract/msgpackr-extract-linux-x64" "2.1.2" 1287 | "@msgpackr-extract/msgpackr-extract-win32-x64" "2.1.2" 1288 | 1289 | msgpackr@^1.5.4: 1290 | version "1.7.2" 1291 | resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.7.2.tgz#68d6debf5999d6b61abb6e7046a689991ebf7261" 1292 | integrity sha512-mWScyHTtG6TjivXX9vfIy2nBtRupaiAj0HQ2mtmpmYujAmqZmaaEVPaSZ1NKLMvicaMLFzEaMk0ManxMRg8rMQ== 1293 | optionalDependencies: 1294 | msgpackr-extract "^2.1.2" 1295 | 1296 | node-addon-api@^3.2.1: 1297 | version "3.2.1" 1298 | resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" 1299 | integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== 1300 | 1301 | node-addon-api@^4.3.0: 1302 | version "4.3.0" 1303 | resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" 1304 | integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== 1305 | 1306 | node-gyp-build-optional-packages@5.0.3: 1307 | version "5.0.3" 1308 | resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz#92a89d400352c44ad3975010368072b41ad66c17" 1309 | integrity sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA== 1310 | 1311 | node-gyp-build@^4.3.0: 1312 | version "4.5.0" 1313 | resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" 1314 | integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== 1315 | 1316 | node-releases@^2.0.6: 1317 | version "2.0.6" 1318 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" 1319 | integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== 1320 | 1321 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1322 | version "3.0.0" 1323 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1324 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1325 | 1326 | nth-check@^2.0.1: 1327 | version "2.1.1" 1328 | resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" 1329 | integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== 1330 | dependencies: 1331 | boolbase "^1.0.0" 1332 | 1333 | nullthrows@^1.1.1: 1334 | version "1.1.1" 1335 | resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" 1336 | integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== 1337 | 1338 | object-assign@^4.1.1: 1339 | version "4.1.1" 1340 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1341 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 1342 | 1343 | ordered-binary@^1.2.4: 1344 | version "1.4.0" 1345 | resolved "https://registry.yarnpkg.com/ordered-binary/-/ordered-binary-1.4.0.tgz#6bb53d44925f3b8afc33d1eed0fa15693b211389" 1346 | integrity sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ== 1347 | 1348 | parcel@^2.7.0: 1349 | version "2.7.0" 1350 | resolved "https://registry.yarnpkg.com/parcel/-/parcel-2.7.0.tgz#41fdd3e5c7144d4cf7f1fa3ab8d0ea0d47d31f77" 1351 | integrity sha512-pRYwnivwtNP0tip8xYSo4zCB0XhLt7/gJzP1p8OovCqkmFjG9VG+GW9TcAKqMIo0ovEa9tT+/s6gY1Qy+BONGQ== 1352 | dependencies: 1353 | "@parcel/config-default" "2.7.0" 1354 | "@parcel/core" "2.7.0" 1355 | "@parcel/diagnostic" "2.7.0" 1356 | "@parcel/events" "2.7.0" 1357 | "@parcel/fs" "2.7.0" 1358 | "@parcel/logger" "2.7.0" 1359 | "@parcel/package-manager" "2.7.0" 1360 | "@parcel/reporter-cli" "2.7.0" 1361 | "@parcel/reporter-dev-server" "2.7.0" 1362 | "@parcel/utils" "2.7.0" 1363 | chalk "^4.1.0" 1364 | commander "^7.0.0" 1365 | get-port "^4.2.0" 1366 | v8-compile-cache "^2.0.0" 1367 | 1368 | parent-module@^1.0.0: 1369 | version "1.0.1" 1370 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1371 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1372 | dependencies: 1373 | callsites "^3.0.0" 1374 | 1375 | parse-json@^5.0.0: 1376 | version "5.2.0" 1377 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" 1378 | integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== 1379 | dependencies: 1380 | "@babel/code-frame" "^7.0.0" 1381 | error-ex "^1.3.1" 1382 | json-parse-even-better-errors "^2.3.0" 1383 | lines-and-columns "^1.1.6" 1384 | 1385 | path-type@^4.0.0: 1386 | version "4.0.0" 1387 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 1388 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 1389 | 1390 | performance-now@^2.1.0: 1391 | version "2.1.0" 1392 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 1393 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 1394 | 1395 | picocolors@^1.0.0: 1396 | version "1.0.0" 1397 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 1398 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 1399 | 1400 | picomatch@^2.0.4, picomatch@^2.2.1: 1401 | version "2.3.1" 1402 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1403 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1404 | 1405 | postcss-value-parser@^4.2.0: 1406 | version "4.2.0" 1407 | resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" 1408 | integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== 1409 | 1410 | posthtml-parser@^0.10.1: 1411 | version "0.10.2" 1412 | resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.10.2.tgz#df364d7b179f2a6bf0466b56be7b98fd4e97c573" 1413 | integrity sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg== 1414 | dependencies: 1415 | htmlparser2 "^7.1.1" 1416 | 1417 | posthtml-parser@^0.11.0: 1418 | version "0.11.0" 1419 | resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.11.0.tgz#25d1c7bf811ea83559bc4c21c189a29747a24b7a" 1420 | integrity sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw== 1421 | dependencies: 1422 | htmlparser2 "^7.1.1" 1423 | 1424 | posthtml-render@^3.0.0: 1425 | version "3.0.0" 1426 | resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-3.0.0.tgz#97be44931496f495b4f07b99e903cc70ad6a3205" 1427 | integrity sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA== 1428 | dependencies: 1429 | is-json "^2.0.1" 1430 | 1431 | posthtml@^0.16.4, posthtml@^0.16.5: 1432 | version "0.16.6" 1433 | resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.16.6.tgz#e2fc407f67a64d2fa3567afe770409ffdadafe59" 1434 | integrity sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ== 1435 | dependencies: 1436 | posthtml-parser "^0.11.0" 1437 | posthtml-render "^3.0.0" 1438 | 1439 | promise@^8.1.0: 1440 | version "8.3.0" 1441 | resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" 1442 | integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== 1443 | dependencies: 1444 | asap "~2.0.6" 1445 | 1446 | raf@^3.4.1: 1447 | version "3.4.1" 1448 | resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" 1449 | integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== 1450 | dependencies: 1451 | performance-now "^2.1.0" 1452 | 1453 | react-app-polyfill@^3.0.0: 1454 | version "3.0.0" 1455 | resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7" 1456 | integrity sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w== 1457 | dependencies: 1458 | core-js "^3.19.2" 1459 | object-assign "^4.1.1" 1460 | promise "^8.1.0" 1461 | raf "^3.4.1" 1462 | regenerator-runtime "^0.13.9" 1463 | whatwg-fetch "^3.6.2" 1464 | 1465 | react-error-overlay@6.0.9: 1466 | version "6.0.9" 1467 | resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" 1468 | integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== 1469 | 1470 | react-refresh@^0.9.0: 1471 | version "0.9.0" 1472 | resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf" 1473 | integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ== 1474 | 1475 | readdirp@~3.6.0: 1476 | version "3.6.0" 1477 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1478 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1479 | dependencies: 1480 | picomatch "^2.2.1" 1481 | 1482 | regenerator-runtime@^0.13.7, regenerator-runtime@^0.13.9: 1483 | version "0.13.10" 1484 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" 1485 | integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw== 1486 | 1487 | resolve-from@^4.0.0: 1488 | version "4.0.0" 1489 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1490 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1491 | 1492 | safe-buffer@^5.0.1: 1493 | version "5.2.1" 1494 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1495 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1496 | 1497 | sass@^1.38.0: 1498 | version "1.55.0" 1499 | resolved "https://registry.yarnpkg.com/sass/-/sass-1.55.0.tgz#0c4d3c293cfe8f8a2e8d3b666e1cf1bff8065d1c" 1500 | integrity sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A== 1501 | dependencies: 1502 | chokidar ">=3.0.0 <4.0.0" 1503 | immutable "^4.0.0" 1504 | source-map-js ">=0.6.2 <2.0.0" 1505 | 1506 | semver@^5.7.0, semver@^5.7.1: 1507 | version "5.7.1" 1508 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 1509 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 1510 | 1511 | "source-map-js@>=0.6.2 <2.0.0": 1512 | version "1.0.2" 1513 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 1514 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 1515 | 1516 | source-map-support@~0.5.20: 1517 | version "0.5.21" 1518 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 1519 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1520 | dependencies: 1521 | buffer-from "^1.0.0" 1522 | source-map "^0.6.0" 1523 | 1524 | source-map@^0.6.0, source-map@^0.6.1: 1525 | version "0.6.1" 1526 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1527 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1528 | 1529 | stable@^0.1.8: 1530 | version "0.1.8" 1531 | resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" 1532 | integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== 1533 | 1534 | supports-color@^5.3.0: 1535 | version "5.5.0" 1536 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1537 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1538 | dependencies: 1539 | has-flag "^3.0.0" 1540 | 1541 | supports-color@^7.1.0: 1542 | version "7.2.0" 1543 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1544 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1545 | dependencies: 1546 | has-flag "^4.0.0" 1547 | 1548 | svgo@^2.4.0: 1549 | version "2.8.0" 1550 | resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" 1551 | integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== 1552 | dependencies: 1553 | "@trysound/sax" "0.2.0" 1554 | commander "^7.2.0" 1555 | css-select "^4.1.3" 1556 | css-tree "^1.1.3" 1557 | csso "^4.2.0" 1558 | picocolors "^1.0.0" 1559 | stable "^0.1.8" 1560 | 1561 | term-size@^2.2.1: 1562 | version "2.2.1" 1563 | resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" 1564 | integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== 1565 | 1566 | terser@^5.2.0: 1567 | version "5.15.1" 1568 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.1.tgz#8561af6e0fd6d839669c73b92bdd5777d870ed6c" 1569 | integrity sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw== 1570 | dependencies: 1571 | "@jridgewell/source-map" "^0.3.2" 1572 | acorn "^8.5.0" 1573 | commander "^2.20.0" 1574 | source-map-support "~0.5.20" 1575 | 1576 | timsort@^0.3.0: 1577 | version "0.3.0" 1578 | resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" 1579 | integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= 1580 | 1581 | to-regex-range@^5.0.1: 1582 | version "5.0.1" 1583 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1584 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1585 | dependencies: 1586 | is-number "^7.0.0" 1587 | 1588 | tslib@^2.4.0: 1589 | version "2.4.1" 1590 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" 1591 | integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== 1592 | 1593 | type-fest@^0.20.2: 1594 | version "0.20.2" 1595 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" 1596 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 1597 | 1598 | typescript@^4.8.4: 1599 | version "4.8.4" 1600 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" 1601 | integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== 1602 | 1603 | update-browserslist-db@^1.0.9: 1604 | version "1.0.10" 1605 | resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" 1606 | integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== 1607 | dependencies: 1608 | escalade "^3.1.1" 1609 | picocolors "^1.0.0" 1610 | 1611 | utility-types@^3.10.0: 1612 | version "3.10.0" 1613 | resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" 1614 | integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== 1615 | 1616 | v8-compile-cache@^2.0.0: 1617 | version "2.1.1" 1618 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" 1619 | integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== 1620 | 1621 | weak-lru-cache@^1.2.2: 1622 | version "1.2.2" 1623 | resolved "https://registry.yarnpkg.com/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz#fdbb6741f36bae9540d12f480ce8254060dccd19" 1624 | integrity sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw== 1625 | 1626 | whatwg-fetch@^3.6.2: 1627 | version "3.6.2" 1628 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" 1629 | integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== 1630 | 1631 | xxhash-wasm@^0.4.2: 1632 | version "0.4.2" 1633 | resolved "https://registry.yarnpkg.com/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz#752398c131a4dd407b5132ba62ad372029be6f79" 1634 | integrity sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA== 1635 | 1636 | yaml@^1.10.0: 1637 | version "1.10.2" 1638 | resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" 1639 | integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== 1640 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "6.0.0", 3 | "license": "MIT", 4 | "main": "dist/index.js", 5 | "module": "dist/index.mjs", 6 | "types": "dist/index.d.ts", 7 | "exports": { 8 | "./package.json": "./package.json", 9 | ".": { 10 | "types": "./dist/index.d.ts", 11 | "import": "./dist/index.mjs", 12 | "require": "./dist/index.js" 13 | }, 14 | "./scss/": "./scss/", 15 | "./inject-style": { 16 | "types": "./dist/inject-style.d.ts", 17 | "require": "./dist/inject-style.js", 18 | "import": "./dist/inject-style.esm.mjs" 19 | }, 20 | "./dist/ReactContexify.css": "./dist/ReactContexify.min.css", 21 | "./dist/ReactContexify.css.map": "./dist/ReactContexify.css.map", 22 | "./ReactContexify.css": "./dist/ReactContexify.min.css", 23 | "./ReactContexify.css.map": "./dist/ReactContexify.css.map" 24 | }, 25 | "files": [ 26 | "dist", 27 | "scss" 28 | ], 29 | "scripts": { 30 | "start": "cd example && yarn start", 31 | "build": "tsup && yarn run build:style", 32 | "test": "cypress run", 33 | "cypress:open": "cypress open", 34 | "sass": "sass scss/main.scss dist/ReactContexify.css", 35 | "postsass": "postcss dist/ReactContexify.css --use autoprefixer -m -o dist/ReactContexify.css", 36 | "build:style": "yarn run sass && cssnano dist/ReactContexify.css dist/ReactContexify.min.css --no-zindex --no-reduceIdents && yarn run style2js", 37 | "style2js": "style2js --out-dir dist dist/ReactContexify.min.css" 38 | }, 39 | "peerDependencies": { 40 | "react": ">=16", 41 | "react-dom": ">=16" 42 | }, 43 | "prettier": { 44 | "printWidth": 80, 45 | "semi": true, 46 | "singleQuote": true, 47 | "trailingComma": "es5" 48 | }, 49 | "name": "react-contexify", 50 | "author": "Fadi Khadra (https://github.com/fkhadra)", 51 | "repository": { 52 | "type": "git", 53 | "url": "git+https://github.com/fkhadra/react-contexify.git" 54 | }, 55 | "bugs": { 56 | "url": "https://github.com/fkhadra/react-contexify/issues" 57 | }, 58 | "description": "Add contextmenu to your react component with ease", 59 | "keywords": [ 60 | "react", 61 | "context menu", 62 | "react-component", 63 | "menu", 64 | "react-contextmenu", 65 | "react-contexify", 66 | "popup" 67 | ], 68 | "devDependencies": { 69 | "@types/react": "^18.0.25", 70 | "@types/react-dom": "^18.0.8", 71 | "cssnano": "^5.1.14", 72 | "cssnano-cli": "^1.0.5", 73 | "cypress": "^11.0.1", 74 | "postcss": "^8.4.18", 75 | "postcss-cli": "^10.0.0", 76 | "react": "^18.2.0", 77 | "react-dom": "^18.2.0", 78 | "sass": "^1.56.1", 79 | "style2js": "^1.0.1", 80 | "tsup": "^6.4.0", 81 | "typescript": "^4.8.4" 82 | }, 83 | "dependencies": { 84 | "clsx": "^1.2.1" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /scss/_menu.scss: -------------------------------------------------------------------------------- 1 | :root{ 2 | --contexify-zIndex: 666; 3 | --contexify-menu-minWidth: 220px; 4 | --contexify-menu-padding: 6px; 5 | --contexify-menu-radius: 6px; 6 | --contexify-menu-bgColor: #fff; 7 | --contexify-menu-shadow: 1px 2px 2px rgba(0, 0, 0, 0.1), 8 | 2px 4px 4px rgba(0, 0, 0, 0.1), 9 | 3px 6px 6px rgba(0, 0, 0, 0.1); 10 | --contexify-menu-negatePadding: var(--contexify-menu-padding); 11 | 12 | --contexify-separator-color: rgba(0, 0, 0, 0.2); 13 | --contexify-separator-margin: 5px; 14 | --contexify-itemContent-padding: 6px; 15 | --contexify-activeItem-radius: 4px; 16 | --contexify-item-color: #333; 17 | --contexify-activeItem-color: #fff; 18 | --contexify-activeItem-bgColor: #3498db; 19 | --contexify-rightSlot-color: #6f6e77; 20 | --contexify-activeRightSlot-color: #fff; 21 | --contexify-arrow-color: #6f6e77; 22 | --contexify-activeArrow-color: #fff; 23 | } 24 | 25 | 26 | @mixin focus-swag { 27 | color: var(--contexify-activeItem-color); 28 | background-color: var(--contexify-activeItem-bgColor); 29 | border-radius: var(--contexify-activeItem-radius); 30 | } 31 | 32 | @function negateMenuPadding() { 33 | @return calc(-1 * var(--contexify-menu-negatePadding)); 34 | } 35 | 36 | // triggered when user select item from the context menu 37 | @keyframes contexify_feedback { 38 | from { 39 | opacity: .4; 40 | } 41 | to { 42 | opacity: 1; 43 | } 44 | } 45 | 46 | 47 | .contexify { 48 | position: fixed; 49 | opacity: 0; 50 | user-select: none; 51 | background-color: var(--contexify-menu-bgColor); 52 | box-sizing: border-box; 53 | box-shadow:var(--contexify-menu-shadow); 54 | border-radius: var(--contexify-menu-radius); 55 | padding: var(--contexify-menu-padding); 56 | min-width: var(--contexify-menu-minWidth); 57 | z-index: var(--contexify-zIndex); 58 | 59 | &_submenu-isOpen, 60 | &_submenu-isOpen > &_itemContent { 61 | @include focus-swag; 62 | } 63 | 64 | // target submenu arrow 65 | &_submenu-isOpen > &_itemContent &_rightSlot { 66 | color: var(--contexify-activeArrow-color) 67 | } 68 | 69 | 70 | &_submenu-isOpen > &_submenu { 71 | pointer-events: initial; 72 | opacity: 1; 73 | } 74 | 75 | & &_submenu { 76 | position: absolute; 77 | pointer-events: none; 78 | transition: opacity .265s; 79 | 80 | /* Initial submenu position */ 81 | top: negateMenuPadding(); 82 | left: 100%; 83 | 84 | &-bottom{ 85 | bottom: negateMenuPadding(); 86 | top: unset; 87 | } 88 | 89 | &-right { 90 | right: 100%; 91 | left: unset; 92 | } 93 | } 94 | 95 | &_rightSlot { 96 | margin-left: auto; 97 | display: flex; 98 | color: var(--contexify-rightSlot-color) 99 | } 100 | 101 | &_separator { 102 | height: 1px; 103 | cursor: default; 104 | margin: var(--contexify-separator-margin); 105 | background-color: var(--contexify-separator-color); 106 | } 107 | 108 | &_willLeave-disabled { 109 | pointer-events: none; 110 | } 111 | 112 | &_item { 113 | cursor: pointer; 114 | position: relative; 115 | 116 | &:focus{ 117 | outline: 0; 118 | } 119 | 120 | &:not(&-disabled):hover > .contexify_itemContent .contexify_rightSlot, 121 | &:focus .contexify_rightSlot{ 122 | color: var(--contexify-activeRightSlot-color); 123 | } 124 | 125 | &:not(&-disabled)[aria-haspopup] > .contexify_itemContent .contexify_rightSlot { 126 | color: var(--contexify-arrow-color); 127 | } 128 | 129 | // triggered by keyboard navigation 130 | &[aria-haspopup]:focus > .contexify_itemContent .contexify_rightSlot, 131 | &:not(&-disabled)[aria-haspopup].contexify_submenu-isOpen > .contexify_itemContent .contexify_rightSlot, 132 | 133 | &:not(&-disabled)[aria-haspopup]:hover > .contexify_itemContent .contexify_rightSlot { 134 | color: var(--contexify-activeArrow-color); 135 | } 136 | 137 | &:not(&-disabled):hover > &Content, 138 | &:not(&-disabled):focus > &Content { 139 | @include focus-swag; 140 | } 141 | 142 | &:not(&-disabled):hover > .contexify_submenu { 143 | pointer-events: initial; 144 | opacity: 1; 145 | } 146 | 147 | &-disabled { 148 | cursor: default; 149 | opacity: .5; 150 | } 151 | &Content { 152 | padding: var(--contexify-itemContent-padding); 153 | display: flex; 154 | align-items: center; 155 | white-space: nowrap; 156 | color: var(--contexify-item-color); 157 | position: relative; 158 | } 159 | 160 | &-feedback{ 161 | animation: contexify_feedback 0.12s both; 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /scss/_themes.scss: -------------------------------------------------------------------------------- 1 | .contexify_theme-dark { 2 | --contexify-menu-bgColor: rgba(40, 40, 40, 0.98); 3 | --contexify-separator-color: #4c4c4c; 4 | --contexify-item-color: #fff; 5 | // --contexify-activeItem-bgColor: #bb86fc; 6 | } 7 | 8 | .contexify_theme-light { 9 | --contexify-separator-color: #eee; 10 | --contexify-item-color: #666; 11 | --contexify-activeItem-color: #3498db; 12 | --contexify-activeItem-bgColor: #e0eefd; 13 | --contexify-activeRightSlot-color: #3498db; 14 | --contexify-active-arrow-color: #3498db; 15 | } 16 | -------------------------------------------------------------------------------- /scss/animations/_fade.scss: -------------------------------------------------------------------------------- 1 | $delay: 0.3s; 2 | 3 | @keyframes contexify_fadeIn { 4 | from { 5 | opacity: 0; 6 | transform: translateY(10px); 7 | } 8 | to { 9 | opacity: 1; 10 | transform: translateY(0); 11 | } 12 | } 13 | 14 | @keyframes contexify_fadeOut { 15 | from { 16 | opacity: 1; 17 | transform: translateY(0); 18 | } 19 | to { 20 | opacity: 0; 21 | transform: translateY(10px); 22 | } 23 | } 24 | 25 | .contexify_willEnter-fade { 26 | animation: contexify_fadeIn $delay ease; 27 | } 28 | 29 | .contexify_willLeave-fade { 30 | animation: contexify_fadeOut $delay ease; 31 | } 32 | -------------------------------------------------------------------------------- /scss/animations/_flip.scss: -------------------------------------------------------------------------------- 1 | $delay: 0.3s; 2 | 3 | @keyframes contexify_flipInX { 4 | from { 5 | transform: perspective(800px) rotate3d(1, 0, 0, 45deg); 6 | } 7 | 8 | to { 9 | transform: perspective(800px); 10 | } 11 | } 12 | 13 | @keyframes contexify_flipOutX { 14 | from { 15 | transform: perspective(800px); 16 | } 17 | 18 | to { 19 | transform: perspective(800px) rotate3d(1, 0, 0, 45deg); 20 | opacity: 0; 21 | } 22 | } 23 | 24 | .contexify_willEnter-flip { 25 | backface-visibility: visible !important; 26 | transform-origin: top center; 27 | animation: contexify_flipInX $delay; 28 | } 29 | 30 | .contexify_willLeave-flip { 31 | transform-origin: top center; 32 | animation: contexify_flipOutX $delay; 33 | backface-visibility: visible !important; 34 | } 35 | -------------------------------------------------------------------------------- /scss/animations/_scale.scss: -------------------------------------------------------------------------------- 1 | $delay: 0.3s; 2 | 3 | @keyframes contexify_scaleIn { 4 | from { 5 | opacity: 0; 6 | transform: scale3d(0.3, 0.3, 0.3); 7 | } 8 | 9 | to { 10 | opacity: 1; 11 | } 12 | } 13 | 14 | @keyframes contexify_scaleOut { 15 | from { 16 | opacity: 1; 17 | } 18 | 19 | to { 20 | opacity: 0; 21 | transform: scale3d(0.3, 0.3, 0.3); 22 | } 23 | } 24 | 25 | .contexify_willEnter-scale { 26 | transform-origin: top left; 27 | animation: contexify_scaleIn $delay; 28 | } 29 | 30 | .contexify_willLeave-scale { 31 | transform-origin: top left; 32 | animation: contexify_scaleOut $delay; 33 | } 34 | -------------------------------------------------------------------------------- /scss/animations/_slide.scss: -------------------------------------------------------------------------------- 1 | $delay: 0.3s; 2 | 3 | @keyframes contexify_slideIn { 4 | from { 5 | opacity: 0; 6 | transform: scale3d(1, 0.3, 1); 7 | } 8 | 9 | to { 10 | opacity: 1; 11 | } 12 | } 13 | 14 | @keyframes contexify_slideOut { 15 | from { 16 | opacity: 1; 17 | } 18 | 19 | to { 20 | opacity: 0; 21 | transform: scale3d(1, 0.3, 1); 22 | } 23 | } 24 | 25 | .contexify_willEnter-slide { 26 | transform-origin: top center; 27 | animation: contexify_slideIn $delay; 28 | } 29 | 30 | .contexify_willLeave-slide { 31 | transform-origin: top center; 32 | animation: contexify_slideOut $delay; 33 | } 34 | -------------------------------------------------------------------------------- /scss/main.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | //ContextMenu,Separator,Item------------------------------------------ // 4 | @import 'menu'; 5 | 6 | //Themes ------------------------------------------------------------ // 7 | @import 'themes'; 8 | 9 | //Animations -------------------------------------------------------- // 10 | @import 'animations/scale'; 11 | @import 'animations/fade'; 12 | @import 'animations/flip'; 13 | @import 'animations/slide'; 14 | -------------------------------------------------------------------------------- /src/components/Arrow.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const Arrow = () => ( 4 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/components/Item.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode, useRef } from 'react'; 2 | import cx from 'clsx'; 3 | 4 | import { 5 | ItemParams, 6 | InternalProps, 7 | BooleanPredicate, 8 | HandlerParamsEvent, 9 | BuiltInOrString, 10 | } from '../types'; 11 | import { useItemTrackerContext } from './ItemTrackerProvider'; 12 | import { NOOP, CssClass } from '../constants'; 13 | import { getPredicateValue, isFn } from './utils'; 14 | import { contextMenu } from '../core'; 15 | 16 | export interface ItemProps 17 | extends InternalProps, 18 | Omit, 'hidden' | 'disabled' | 'onClick'> { 19 | /** 20 | * Any valid node that can be rendered 21 | */ 22 | children: ReactNode; 23 | 24 | /** 25 | * Passed to the `Item` onClick callback. Accessible via `data` 26 | */ 27 | data?: any; 28 | 29 | /** 30 | * Disable `Item`. If a function is used, a boolean must be returned 31 | * 32 | * @param id The item id, when defined 33 | * @param props The props passed when you called `show(e, {props: yourProps})` 34 | * @param data The data defined on the `Item` 35 | * @param triggerEvent The event that triggered the context menu 36 | * 37 | * 38 | * ``` 39 | * function isItemDisabled({ triggerEvent, props, data }: PredicateParams): boolean 40 | * content 41 | * ``` 42 | */ 43 | disabled?: BooleanPredicate; 44 | 45 | /** 46 | * Hide the `Item`. If a function is used, a boolean must be returned 47 | * 48 | * @param id The item id, when defined 49 | * @param props The props passed when you called `show(e, {props: yourProps})` 50 | * @param data The data defined on the `Item` 51 | * @param triggerEvent The event that triggered the context menu 52 | * 53 | * 54 | * ``` 55 | * function isItemHidden({ triggerEvent, props, data }: PredicateParams): boolean 56 | * 57 | * ``` 58 | */ 59 | hidden?: BooleanPredicate; 60 | 61 | /** 62 | * Callback when the `Item` is clicked. 63 | * 64 | * @param id The item id, when defined 65 | * @param event The event that occured on the Item node 66 | * @param props The props passed when you called `show(e, {props: yourProps})` 67 | * @param data The data defined on the `Item` 68 | * @param triggerEvent The event that triggered the context menu 69 | * 70 | * ``` 71 | * function handleItemClick({ id, triggerEvent, event, props, data }: ItemParams){ 72 | * // retrieve the id of the Item 73 | * console.log(id) // item-id 74 | * 75 | * // access any other dom attribute 76 | * console.log(event.currentTarget.dataset.foo) // 123 77 | * 78 | * // access the props and the data 79 | * console.log(props, data); 80 | * 81 | * // access the coordinate of the mouse when the menu has been displayed 82 | * const { clientX, clientY } = triggerEvent; 83 | * } 84 | * 85 | * Something 86 | * ``` 87 | */ 88 | onClick?: (args: ItemParams) => void; 89 | 90 | /** 91 | * Let you implement keyboard shortcut for the menu item. It will trigger the 92 | * `onClick` hander if the given callback returns `true` 93 | * 94 | * example: 95 | * 96 | * ``` 97 | * function handleShortcut(e: React.KeyboardEvent){ 98 | * // let's say we want to match ⌘ + c 99 | * return e.metaKey && e.key === "c"; 100 | * } 101 | * 102 | * Copy ⌘ C 103 | * ``` 104 | */ 105 | keyMatcher?: (e: KeyboardEvent) => boolean; 106 | 107 | /** 108 | * Useful when using form input inside the Menu 109 | * 110 | * default: `true` 111 | */ 112 | closeOnClick?: boolean; 113 | 114 | /** 115 | * Let you specify another event for the `onClick` handler 116 | * 117 | * default: `onClick` 118 | */ 119 | handlerEvent?: BuiltInOrString<'onClick' | 'onMouseDown' | 'onMouseUp'>; 120 | } 121 | 122 | export const Item: React.FC = ({ 123 | id, 124 | children, 125 | className, 126 | style, 127 | triggerEvent, 128 | data, 129 | propsFromTrigger, 130 | keyMatcher, 131 | onClick = NOOP, 132 | disabled = false, 133 | hidden = false, 134 | closeOnClick = true, 135 | handlerEvent = 'onClick', 136 | ...rest 137 | }) => { 138 | const itemNode = useRef(); 139 | const itemTracker = useItemTrackerContext(); 140 | const handlerParams = { 141 | id, 142 | data, 143 | triggerEvent: triggerEvent as HandlerParamsEvent, 144 | props: propsFromTrigger, 145 | } as ItemParams; 146 | const isDisabled = getPredicateValue(disabled, handlerParams); 147 | const isHidden = getPredicateValue(hidden, handlerParams); 148 | 149 | function handleClick(e: React.MouseEvent) { 150 | handlerParams.event = e; 151 | e.stopPropagation(); 152 | 153 | if (!isDisabled) { 154 | !closeOnClick ? onClick(handlerParams) : dispatchUserHanlder(); 155 | } 156 | } 157 | 158 | // provide a feedback to the user that the item has been clicked before closing the menu 159 | function dispatchUserHanlder() { 160 | const node = itemNode.current!; 161 | node.focus(); 162 | node.addEventListener( 163 | 'animationend', 164 | // defer, required for react 17 165 | () => setTimeout(contextMenu.hideAll), 166 | { once: true } 167 | ); 168 | node.classList.add(CssClass.itemClickedFeedback); 169 | onClick(handlerParams); 170 | } 171 | 172 | function registerItem(node: HTMLElement | null) { 173 | if (node && !isDisabled) { 174 | itemNode.current = node; 175 | itemTracker.set(node, { 176 | node, 177 | isSubmenu: false, 178 | keyMatcher: 179 | !isDisabled && 180 | isFn(keyMatcher) && 181 | ((e: KeyboardEvent) => { 182 | if (keyMatcher(e)) { 183 | e.stopPropagation(); 184 | e.preventDefault(); 185 | handlerParams.event = e; 186 | dispatchUserHanlder(); 187 | } 188 | }), 189 | }); 190 | } 191 | } 192 | 193 | function handleKeyDown(e: React.KeyboardEvent) { 194 | if (e.key === 'Enter' || e.key === ' ') { 195 | e.stopPropagation(); 196 | handlerParams.event = e; 197 | dispatchUserHanlder(); 198 | } 199 | } 200 | 201 | if (isHidden) return null; 202 | 203 | return ( 204 |
216 |
{children}
217 |
218 | ); 219 | }; 220 | -------------------------------------------------------------------------------- /src/components/ItemTrackerProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, createContext } from 'react'; 2 | import { ItemTracker } from '../hooks'; 3 | 4 | const Context = createContext({} as ItemTracker); 5 | 6 | export const useItemTrackerContext = () => useContext(Context); 7 | 8 | export interface ItemTrackerProviderProps { 9 | value: ItemTracker; 10 | children?: React.ReactNode; 11 | } 12 | 13 | export const ItemTrackerProvider: React.FC = ( 14 | props 15 | ) => ; 16 | -------------------------------------------------------------------------------- /src/components/Menu.tsx: -------------------------------------------------------------------------------- 1 | import React, { 2 | ReactNode, 3 | useEffect, 4 | useReducer, 5 | useRef, 6 | useState, 7 | } from 'react'; 8 | import cx from 'clsx'; 9 | 10 | import { ItemTrackerProvider } from './ItemTrackerProvider'; 11 | 12 | import { eventManager } from '../core/eventManager'; 13 | import { TriggerEvent, MenuId, MenuAnimation, Theme } from '../types'; 14 | import { useItemTracker } from '../hooks'; 15 | import { createKeyboardController } from './keyboardController'; 16 | import { CssClass, EVENT, hideOnEvents } from '../constants'; 17 | import { cloneItems, getMousePosition, isFn, isStr } from './utils'; 18 | import { flushSync } from 'react-dom'; 19 | import { ShowContextMenuParams } from '../core'; 20 | 21 | export interface MenuProps 22 | extends Omit, 'id'> { 23 | /** 24 | * Unique id to identify the menu. Use to Trigger the corresponding menu 25 | */ 26 | id: MenuId; 27 | 28 | /** 29 | * Any valid node that can be rendered 30 | */ 31 | children: ReactNode; 32 | 33 | /** 34 | * Theme is appended to `contexify_theme-${given theme}`. 35 | * 36 | * Built-in theme are `light` and `dark` 37 | */ 38 | theme?: Theme; 39 | 40 | /** 41 | * Animation is appended to 42 | * - `.contexify_willEnter-${given animation}` 43 | * - `.contexify_willLeave-${given animation}` 44 | * 45 | * - To disable all animations you can pass `false` 46 | * - To disable only the enter or the exit animation you can provide an object `{enter: false, exit: 'exitAnimation'}` 47 | * 48 | * - default is set to `fade` 49 | */ 50 | animation?: MenuAnimation; 51 | 52 | /** 53 | * Disables menu repositioning if outside screen. 54 | * This may be neeeded in some cases when using custom position. 55 | */ 56 | disableBoundariesCheck?: boolean; 57 | 58 | /** 59 | * Prevents scrolling the window on when typing. Defaults to true. 60 | */ 61 | preventDefaultOnKeydown?: boolean; 62 | 63 | /** 64 | * Used to track menu visibility 65 | */ 66 | onVisibilityChange?: (isVisible: boolean) => void; 67 | } 68 | 69 | interface MenuState { 70 | x: number; 71 | y: number; 72 | visible: boolean; 73 | triggerEvent: TriggerEvent; 74 | propsFromTrigger: any; 75 | willLeave: boolean; 76 | } 77 | 78 | function reducer( 79 | state: MenuState, 80 | payload: Partial | ((state: MenuState) => Partial) 81 | ) { 82 | return { ...state, ...(isFn(payload) ? payload(state) : payload) }; 83 | } 84 | 85 | export const Menu: React.FC = ({ 86 | id, 87 | theme, 88 | style, 89 | className, 90 | children, 91 | animation = 'fade', 92 | preventDefaultOnKeydown = true, 93 | disableBoundariesCheck = false, 94 | onVisibilityChange, 95 | ...rest 96 | }) => { 97 | const [state, setState] = useReducer(reducer, { 98 | x: 0, 99 | y: 0, 100 | visible: false, 101 | triggerEvent: {} as TriggerEvent, 102 | propsFromTrigger: null, 103 | willLeave: false, 104 | }); 105 | const nodeRef = useRef(null); 106 | const itemTracker = useItemTracker(); 107 | const [menuController] = useState(() => createKeyboardController()); 108 | const wasVisible = useRef(); 109 | const visibilityId = useRef(); 110 | 111 | // subscribe event manager 112 | useEffect(() => { 113 | eventManager.on(id, show).on(EVENT.HIDE_ALL, hide); 114 | 115 | return () => { 116 | eventManager.off(id, show).off(EVENT.HIDE_ALL, hide); 117 | }; 118 | // hide rely on setState(dispatch), which is guaranted to be the same across render 119 | }, [id, animation, disableBoundariesCheck]); 120 | 121 | // collect menu items for keyboard navigation 122 | useEffect(() => { 123 | !state.visible ? itemTracker.clear() : menuController.init(itemTracker); 124 | }, [state.visible, menuController, itemTracker]); 125 | 126 | function checkBoundaries(x: number, y: number) { 127 | if (nodeRef.current && !disableBoundariesCheck) { 128 | const { innerWidth, innerHeight } = window; 129 | const { offsetWidth, offsetHeight } = nodeRef.current; 130 | 131 | if (x + offsetWidth > innerWidth) x -= x + offsetWidth - innerWidth; 132 | 133 | if (y + offsetHeight > innerHeight) y -= y + offsetHeight - innerHeight; 134 | } 135 | 136 | return { x, y }; 137 | } 138 | 139 | // when the menu is transitioning from not visible to visible, 140 | // the nodeRef is attached to the dom element this let us check the boundaries 141 | useEffect(() => { 142 | // state.visible and state{x,y} are updated together 143 | if (state.visible) setState(checkBoundaries(state.x, state.y)); 144 | }, [state.visible]); 145 | 146 | // subscribe dom events 147 | useEffect(() => { 148 | function preventDefault(e: KeyboardEvent) { 149 | if (preventDefaultOnKeydown) e.preventDefault(); 150 | } 151 | 152 | function handleKeyboard(e: KeyboardEvent) { 153 | switch (e.key) { 154 | case 'Enter': 155 | case ' ': 156 | if (!menuController.openSubmenu()) hide(); 157 | break; 158 | case 'Escape': 159 | hide(); 160 | break; 161 | case 'ArrowUp': 162 | preventDefault(e); 163 | menuController.moveUp(); 164 | break; 165 | case 'ArrowDown': 166 | preventDefault(e); 167 | menuController.moveDown(); 168 | break; 169 | case 'ArrowRight': 170 | preventDefault(e); 171 | menuController.openSubmenu(); 172 | break; 173 | case 'ArrowLeft': 174 | preventDefault(e); 175 | menuController.closeSubmenu(); 176 | break; 177 | default: 178 | menuController.matchKeys(e); 179 | break; 180 | } 181 | } 182 | 183 | if (state.visible) { 184 | window.addEventListener('keydown', handleKeyboard); 185 | 186 | for (const ev of hideOnEvents) window.addEventListener(ev, hide); 187 | } 188 | 189 | return () => { 190 | window.removeEventListener('keydown', handleKeyboard); 191 | 192 | for (const ev of hideOnEvents) window.removeEventListener(ev, hide); 193 | }; 194 | }, [state.visible, menuController, preventDefaultOnKeydown]); 195 | 196 | function show({ event, props, position }: ShowContextMenuParams) { 197 | event.stopPropagation(); 198 | const p = position || getMousePosition(event); 199 | // check boundaries when the menu is already visible 200 | const { x, y } = checkBoundaries(p.x, p.y); 201 | 202 | flushSync(() => { 203 | setState({ 204 | visible: true, 205 | willLeave: false, 206 | x, 207 | y, 208 | triggerEvent: event, 209 | propsFromTrigger: props, 210 | }); 211 | }); 212 | 213 | clearTimeout(visibilityId.current); 214 | if (!wasVisible.current && isFn(onVisibilityChange)) { 215 | onVisibilityChange(true); 216 | wasVisible.current = true; 217 | } 218 | } 219 | 220 | function hide(e?: Event) { 221 | type SafariEvent = KeyboardEvent & MouseEvent; 222 | 223 | if ( 224 | e != null && 225 | // Safari trigger a click event when you ctrl + trackpad 226 | ((e as SafariEvent).button === 2 || (e as SafariEvent).ctrlKey) && 227 | // Firefox trigger a click event when right click occur 228 | e.type !== 'contextmenu' 229 | ) 230 | return; 231 | 232 | animation && (isStr(animation) || ('exit' in animation && animation.exit)) 233 | ? setState((state) => ({ willLeave: state.visible })) 234 | : setState((state) => ({ 235 | visible: state.visible ? false : state.visible, 236 | })); 237 | 238 | visibilityId.current = setTimeout(() => { 239 | isFn(onVisibilityChange) && onVisibilityChange(false); 240 | wasVisible.current = false; 241 | }); 242 | } 243 | 244 | function handleAnimationEnd() { 245 | if (state.willLeave && state.visible) { 246 | flushSync(() => setState({ visible: false, willLeave: false })); 247 | } 248 | } 249 | 250 | function computeAnimationClasses() { 251 | if (isStr(animation)) { 252 | return cx({ 253 | [`${CssClass.animationWillEnter}${animation}`]: visible && !willLeave, 254 | [`${CssClass.animationWillLeave}${animation} ${CssClass.animationWillLeave}'disabled'`]: 255 | visible && willLeave, 256 | }); 257 | } else if (animation && 'enter' in animation && 'exit' in animation) { 258 | return cx({ 259 | [`${CssClass.animationWillEnter}${animation.enter}`]: 260 | animation.enter && visible && !willLeave, 261 | [`${CssClass.animationWillLeave}${animation.exit} ${CssClass.animationWillLeave}'disabled'`]: 262 | animation.exit && visible && willLeave, 263 | }); 264 | } 265 | 266 | return null; 267 | } 268 | 269 | const { visible, triggerEvent, propsFromTrigger, x, y, willLeave } = state; 270 | const cssClasses = cx( 271 | CssClass.menu, 272 | className, 273 | { [`${CssClass.theme}${theme}`]: theme }, 274 | computeAnimationClasses() 275 | ); 276 | 277 | // TODO: switch to translate instead of top left 278 | // requires an additional dom element around the menu 279 | return ( 280 | 281 | {visible && ( 282 |
295 | {cloneItems(children, { 296 | propsFromTrigger, 297 | triggerEvent, 298 | })} 299 |
300 | )} 301 |
302 | ); 303 | }; 304 | -------------------------------------------------------------------------------- /src/components/RightSlot.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cx from 'clsx'; 3 | 4 | import { CssClass } from '../constants'; 5 | 6 | export interface RightSlotProps extends React.HTMLAttributes { 7 | children: React.ReactNode; 8 | } 9 | 10 | export const RightSlot: React.FC = ({ className, ...rest }) => ( 11 |
12 | ); 13 | -------------------------------------------------------------------------------- /src/components/Separator.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { BooleanPredicate, HandlerParamsEvent, InternalProps } from '../types'; 4 | import { getPredicateValue } from './utils'; 5 | 6 | import { CssClass } from '../constants'; 7 | 8 | export interface SeparatorProps extends InternalProps { 9 | /** 10 | * Passed to the `Separator` hidden predicate. Accessible via `data` 11 | */ 12 | data?: any; 13 | 14 | /** 15 | * Hide the `Separator`. If a function is used, a boolean must be returned 16 | * 17 | * @param props The props passed when you called `show(e, {props: yourProps})` 18 | * @param data The data defined on the `Separator` 19 | * @param triggerEvent The event that triggered the context menu 20 | * 21 | * 22 | * ``` 23 | * function isSeparatorHidden({ triggerEvent, props, data }: PredicateParams): boolean 24 | *