├── .gitattributes ├── .github └── workflows │ ├── main.yml │ └── size.yml ├── .gitignore ├── .nvmrc ├── LICENSE ├── README.md ├── dts.config.js ├── example ├── index.html ├── index.tsx ├── package.json ├── react-local-toast.scss ├── styles.scss ├── tsconfig.json ├── vite.config.js └── yarn.lock ├── package.json ├── patches └── dts-cli+2.0.4.patch ├── src ├── const.ts ├── context.ts ├── default-implementation.tsx ├── factory.ts ├── hoc.tsx ├── icons.tsx ├── index.ts ├── internals.ts ├── provider.tsx ├── styles.scss ├── target.tsx ├── types.ts └── viewport.tsx ├── tsconfig.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push] 3 | jobs: 4 | build: 5 | name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }} 6 | 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | node: ['18.x', '20.x'] 11 | os: [ubuntu-latest, windows-latest, macOS-latest] 12 | 13 | steps: 14 | - name: Checkout repo 15 | uses: actions/checkout@v3 16 | 17 | - name: Use Node ${{ matrix.node }} 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: ${{ matrix.node }} 21 | 22 | - name: Install deps and build (with cache) 23 | uses: bahmutov/npm-install@v1 24 | 25 | - name: Lint 26 | run: yarn lint 27 | 28 | - name: Test 29 | run: yarn test --ci --coverage --maxWorkers=2 30 | 31 | - name: Build 32 | run: yarn build 33 | -------------------------------------------------------------------------------- /.github/workflows/size.yml: -------------------------------------------------------------------------------- 1 | name: size 2 | on: [pull_request] 3 | jobs: 4 | size: 5 | runs-on: ubuntu-latest 6 | env: 7 | CI_JOB_NUMBER: 1 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: andresz1/size-limit-action@v1 11 | with: 12 | github_token: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | dist 6 | 7 | stats.html -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 OlegWock 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 | # react-local-toast 2 | 3 | [![npm version][npmv-image]][npmv-url] 4 | [![npm downloads][npmd-image]][npmd-url] 5 | 6 | > Local toast helps you to provide feedback related to particular components on page 7 | 8 |

9 | Demo 10 |

11 | 12 | 13 | > [!IMPORTANT] 14 | > This is v2 of react-local-toast. There weren't any changes in API, but v2 doesn't provide minified styles. 15 | 16 | 17 | ## Features 18 | 19 | * Local toasts are linked to particular component in DOM. 20 | * Toast can be displayed on right/left/top/bottom side of component. 21 | * Toast can be hidden after some timout or hidden programatically. 22 | * Component might have multiple toasts. 23 | * Multiple toasts stucks **vertically** (even if displayed on left or right side). 24 | * `info`, `success`, `warning`, `error` and `loading` toasts out of the box. 25 | * You can bring your own design. Or your own Toast component. Or your custom implementation of toasts. 26 | * WAI-ARIA support. 27 | * TypeScript! 28 | 29 | 30 | ## Documentation and showcase 31 | 32 | Can be found [here](https://react-local-toast.netlify.app/). Check it out, I spent a lot of effort making it 😅. 33 | 34 | ## Installation 35 | 36 | ``` 37 | npm install react-local-toast --save 38 | 39 | # Or if you prefer yarn 40 | yarn add react-local-toast 41 | ``` 42 | 43 | ## Basic Usage 44 | 45 | react-local-toast doesn't automatically inject its styles into DOM, you need to do that. In most cases it will be just: 46 | 47 | ```js 48 | import 'react-local-toast/dist/bundle.css'; 49 | ``` 50 | 51 | This should work fine for most of tools (Create React App included). For more specific use cases (e.g. using toasts in Shadow DOM) you might want to inject styles manually. 52 | 53 | Now you need to wrap your application in `LocalToastProvider`. 54 | 55 | ```jsx 56 | import React from 'react'; 57 | import { LocalToastProvider } from 'react-local-toast'; 58 | 59 | export default () => { 60 | return ( 61 | {/* All your components that will use local toasts should be children of this provider. */} 62 | 63 | ); 64 | }; 65 | ``` 66 | 67 | Local toasts are linked to particular components on page, so let's mark our component as target for local toast: 68 | 69 | ```jsx 70 | import React from 'react'; 71 | import { LocalToastTarget } from 'react-local-toast'; 72 | 73 | export const App = () => { 74 | return (
75 |

This component should be inside LocalToastProvider

76 | {/* Wrap your component with */} 77 | 78 | 79 | 80 |
); 81 | }; 82 | ``` 83 | 84 | Local toast uses refs to get position of component, so in case you want to use toasts with functional components – make sure they are wrapped in `React.forwardRef`. 85 | 86 | And final piece! Update your component to actually produce local toasts: 87 | 88 | ```jsx 89 | import React from 'react'; 90 | // New import here !! 91 | import { LocalToastTarget, useLocalToast } from 'react-local-toast'; 92 | 93 | export const App = () => { 94 | // Use hook to show and hide toasts 95 | const {showToast, removeToast} = useLocalToast(); 96 | 97 | return (
98 |

This component should be inside LocalToastProvider

99 | 100 | 101 | 102 |
); 103 | }; 104 | ``` 105 | 106 | In case you need to show toast from class component, you can use HOC like this: 107 | 108 | ```tsx 109 | import { LocalToastTarget, withLocalToast, LocalToastHocProps } from 'react-local-toast'; 110 | 111 | interface Props extends LocalToastHocProps { 112 | name: string 113 | } 114 | 115 | class ClassComp extends React.Component { 116 | sayHello = () => { 117 | this.props.showToast('class_comp', `Hello, ${this.props.name}!`) 118 | }; 119 | render() { 120 | return (
121 | 122 | 123 | 124 |
); 125 | } 126 | } 127 | 128 | // And later use thic component as you usually do 129 | export default withLocalToast(ClassComp); 130 | ``` 131 | 132 | This will pass toast-related functions (exactly same as in `useLocalToast` hook) as props to wrapped component. 133 | 134 | Cool, huh? 135 | 136 | ## License 137 | 138 | MIT 139 | 140 | [npmv-image]: https://img.shields.io/npm/v/react-local-toast.svg?style=flat-square 141 | [npmv-url]: https://www.npmjs.com/package/react-local-toast 142 | [npmd-image]: https://img.shields.io/npm/dm/react-local-toast.svg?style=flat-square 143 | [npmd-url]: https://www.npmjs.com/package/react-local-toast 144 | -------------------------------------------------------------------------------- /dts.config.js: -------------------------------------------------------------------------------- 1 | const defineConfig = require('dts-cli').defineConfig; 2 | const scss = require('rollup-plugin-scss'); 3 | const { visualizer } = require("rollup-plugin-visualizer"); 4 | 5 | module.exports = defineConfig({ 6 | // This function will run for each entry/format/env combination 7 | rollup: (config, options) => { 8 | 9 | config.plugins.push(scss({ fileName: 'bundle.css' })); 10 | // config.plugins.push(visualizer()); 11 | return config; // always return a config. 12 | }, 13 | }); -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Playground 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/index.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | import { LocalToastProvider, LocalToastTarget, useLocalToast } from '../.'; 3 | import '../dist/bundle.css'; 4 | import "./react-local-toast.scss"; 5 | import "./styles.scss"; 6 | import { useRef, useState } from 'react'; 7 | 8 | const App = () => { 9 | const counterRef = useRef(1); 10 | 11 | const { showToast, removeToast } = useLocalToast(); 12 | 13 | return ( 14 |
15 | 16 | 17 | 18 |
19 | ); 20 | }; 21 | 22 | const root = createRoot(document.getElementById('root')!); 23 | root.render(); 24 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "private": true, 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "vite", 9 | "build": "vite build" 10 | }, 11 | "dependencies": { 12 | "react-app-polyfill": "^3.0.0", 13 | "sass": "^1.75.0" 14 | }, 15 | "alias": { 16 | "react": "../node_modules/react", 17 | "react-dom": "../node_modules/react-dom/profiling", 18 | "scheduler/tracing": "../node_modules/scheduler/tracing-profiling" 19 | }, 20 | "devDependencies": { 21 | "@types/react": "^18.0.31", 22 | "@types/react-dom": "^18.0.11", 23 | "@vitejs/plugin-react": "latest", 24 | "typescript": "^4", 25 | "vite": "latest" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /example/react-local-toast.scss: -------------------------------------------------------------------------------- 1 | .toasts-container { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 1rem; 5 | width: 200px; 6 | align-items: stretch; 7 | } 8 | 9 | .toast { 10 | padding: 1rem; 11 | border-radius: 8px; 12 | background: white; 13 | box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 50px; 14 | 15 | animation: appear linear 0.1s; 16 | } 17 | 18 | @keyframes appear { 19 | from { 20 | opacity: 0; 21 | } 22 | to { 23 | opacity: 1; 24 | } 25 | } 26 | 27 | @keyframes rltTop { 28 | from { 29 | transform: translateY(25%) scale(1); 30 | opacity: 0; 31 | } 32 | 33 | to { 34 | transform: translate(0, 0) scale(1); 35 | opacity: 1; 36 | } 37 | } -------------------------------------------------------------------------------- /example/styles.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | font-size: 16px; 3 | } 4 | 5 | html, body { 6 | width: 100%; 7 | height: 100%; 8 | box-sizing: border-box; 9 | margin: 0; 10 | padding: 0; 11 | } 12 | 13 | body { 14 | font-family: "Work Sans", sans-serif; 15 | font-optical-sizing: auto; 16 | font-weight: 400; 17 | font-style: normal; 18 | color: #333; 19 | display: flex; 20 | justify-content: center; 21 | align-items: center; 22 | background: rgb(229, 237, 255); 23 | } 24 | 25 | #root { 26 | width: 1000px; 27 | height: 600px; 28 | padding: 2rem; 29 | border-radius: 0.5rem; 30 | background: white; 31 | display: flex; 32 | justify-content: center; 33 | align-items: center; 34 | } 35 | 36 | button { 37 | font-family: inherit; 38 | font-size: inherit; 39 | border: none; 40 | padding: 1rem 2rem; 41 | background: #eee; 42 | border-radius: 0.5rem; 43 | cursor: pointer; 44 | } 45 | 46 | .ball { 47 | width: 2rem; 48 | height: 2rem; 49 | border-radius: 9999px; 50 | background: goldenrod; 51 | } -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/vite-react/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /example/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import ReactPlugin from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [ReactPlugin({})], 7 | }); 8 | -------------------------------------------------------------------------------- /example/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@ampproject/remapping@^2.2.0": 6 | version "2.3.0" 7 | resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" 8 | integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== 9 | dependencies: 10 | "@jridgewell/gen-mapping" "^0.3.5" 11 | "@jridgewell/trace-mapping" "^0.3.24" 12 | 13 | "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.2": 14 | version "7.24.2" 15 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" 16 | integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== 17 | dependencies: 18 | "@babel/highlight" "^7.24.2" 19 | picocolors "^1.0.0" 20 | 21 | "@babel/compat-data@^7.23.5": 22 | version "7.24.4" 23 | resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" 24 | integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== 25 | 26 | "@babel/core@^7.23.5": 27 | version "7.24.5" 28 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.5.tgz#15ab5b98e101972d171aeef92ac70d8d6718f06a" 29 | integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA== 30 | dependencies: 31 | "@ampproject/remapping" "^2.2.0" 32 | "@babel/code-frame" "^7.24.2" 33 | "@babel/generator" "^7.24.5" 34 | "@babel/helper-compilation-targets" "^7.23.6" 35 | "@babel/helper-module-transforms" "^7.24.5" 36 | "@babel/helpers" "^7.24.5" 37 | "@babel/parser" "^7.24.5" 38 | "@babel/template" "^7.24.0" 39 | "@babel/traverse" "^7.24.5" 40 | "@babel/types" "^7.24.5" 41 | convert-source-map "^2.0.0" 42 | debug "^4.1.0" 43 | gensync "^1.0.0-beta.2" 44 | json5 "^2.2.3" 45 | semver "^6.3.1" 46 | 47 | "@babel/generator@^7.24.5": 48 | version "7.24.5" 49 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.5.tgz#e5afc068f932f05616b66713e28d0f04e99daeb3" 50 | integrity sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA== 51 | dependencies: 52 | "@babel/types" "^7.24.5" 53 | "@jridgewell/gen-mapping" "^0.3.5" 54 | "@jridgewell/trace-mapping" "^0.3.25" 55 | jsesc "^2.5.1" 56 | 57 | "@babel/helper-compilation-targets@^7.23.6": 58 | version "7.23.6" 59 | resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" 60 | integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== 61 | dependencies: 62 | "@babel/compat-data" "^7.23.5" 63 | "@babel/helper-validator-option" "^7.23.5" 64 | browserslist "^4.22.2" 65 | lru-cache "^5.1.1" 66 | semver "^6.3.1" 67 | 68 | "@babel/helper-environment-visitor@^7.22.20": 69 | version "7.22.20" 70 | resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" 71 | integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== 72 | 73 | "@babel/helper-function-name@^7.23.0": 74 | version "7.23.0" 75 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" 76 | integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== 77 | dependencies: 78 | "@babel/template" "^7.22.15" 79 | "@babel/types" "^7.23.0" 80 | 81 | "@babel/helper-hoist-variables@^7.22.5": 82 | version "7.22.5" 83 | resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" 84 | integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== 85 | dependencies: 86 | "@babel/types" "^7.22.5" 87 | 88 | "@babel/helper-module-imports@^7.24.3": 89 | version "7.24.3" 90 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" 91 | integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== 92 | dependencies: 93 | "@babel/types" "^7.24.0" 94 | 95 | "@babel/helper-module-transforms@^7.24.5": 96 | version "7.24.5" 97 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz#ea6c5e33f7b262a0ae762fd5986355c45f54a545" 98 | integrity sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A== 99 | dependencies: 100 | "@babel/helper-environment-visitor" "^7.22.20" 101 | "@babel/helper-module-imports" "^7.24.3" 102 | "@babel/helper-simple-access" "^7.24.5" 103 | "@babel/helper-split-export-declaration" "^7.24.5" 104 | "@babel/helper-validator-identifier" "^7.24.5" 105 | 106 | "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.24.5": 107 | version "7.24.5" 108 | resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz#a924607dd254a65695e5bd209b98b902b3b2f11a" 109 | integrity sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ== 110 | 111 | "@babel/helper-simple-access@^7.24.5": 112 | version "7.24.5" 113 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz#50da5b72f58c16b07fbd992810be6049478e85ba" 114 | integrity sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ== 115 | dependencies: 116 | "@babel/types" "^7.24.5" 117 | 118 | "@babel/helper-split-export-declaration@^7.24.5": 119 | version "7.24.5" 120 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz#b9a67f06a46b0b339323617c8c6213b9055a78b6" 121 | integrity sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q== 122 | dependencies: 123 | "@babel/types" "^7.24.5" 124 | 125 | "@babel/helper-string-parser@^7.24.1": 126 | version "7.24.1" 127 | resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" 128 | integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== 129 | 130 | "@babel/helper-validator-identifier@^7.24.5": 131 | version "7.24.5" 132 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" 133 | integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== 134 | 135 | "@babel/helper-validator-option@^7.23.5": 136 | version "7.23.5" 137 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" 138 | integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== 139 | 140 | "@babel/helpers@^7.24.5": 141 | version "7.24.5" 142 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.5.tgz#fedeb87eeafa62b621160402181ad8585a22a40a" 143 | integrity sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q== 144 | dependencies: 145 | "@babel/template" "^7.24.0" 146 | "@babel/traverse" "^7.24.5" 147 | "@babel/types" "^7.24.5" 148 | 149 | "@babel/highlight@^7.24.2": 150 | version "7.24.5" 151 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" 152 | integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw== 153 | dependencies: 154 | "@babel/helper-validator-identifier" "^7.24.5" 155 | chalk "^2.4.2" 156 | js-tokens "^4.0.0" 157 | picocolors "^1.0.0" 158 | 159 | "@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.0", "@babel/parser@^7.24.5": 160 | version "7.24.5" 161 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790" 162 | integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg== 163 | 164 | "@babel/plugin-transform-react-jsx-self@^7.23.3": 165 | version "7.24.5" 166 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.5.tgz#22cc7572947895c8e4cd034462e65d8ecf857756" 167 | integrity sha512-RtCJoUO2oYrYwFPtR1/jkoBEcFuI1ae9a9IMxeyAVa3a1Ap4AnxmyIKG2b2FaJKqkidw/0cxRbWN+HOs6ZWd1w== 168 | dependencies: 169 | "@babel/helper-plugin-utils" "^7.24.5" 170 | 171 | "@babel/plugin-transform-react-jsx-source@^7.23.3": 172 | version "7.24.1" 173 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz#a2dedb12b09532846721b5df99e52ef8dc3351d0" 174 | integrity sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA== 175 | dependencies: 176 | "@babel/helper-plugin-utils" "^7.24.0" 177 | 178 | "@babel/template@^7.22.15", "@babel/template@^7.24.0": 179 | version "7.24.0" 180 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" 181 | integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== 182 | dependencies: 183 | "@babel/code-frame" "^7.23.5" 184 | "@babel/parser" "^7.24.0" 185 | "@babel/types" "^7.24.0" 186 | 187 | "@babel/traverse@^7.24.5": 188 | version "7.24.5" 189 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.5.tgz#972aa0bc45f16983bf64aa1f877b2dd0eea7e6f8" 190 | integrity sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA== 191 | dependencies: 192 | "@babel/code-frame" "^7.24.2" 193 | "@babel/generator" "^7.24.5" 194 | "@babel/helper-environment-visitor" "^7.22.20" 195 | "@babel/helper-function-name" "^7.23.0" 196 | "@babel/helper-hoist-variables" "^7.22.5" 197 | "@babel/helper-split-export-declaration" "^7.24.5" 198 | "@babel/parser" "^7.24.5" 199 | "@babel/types" "^7.24.5" 200 | debug "^4.3.1" 201 | globals "^11.1.0" 202 | 203 | "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5": 204 | version "7.24.5" 205 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7" 206 | integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ== 207 | dependencies: 208 | "@babel/helper-string-parser" "^7.24.1" 209 | "@babel/helper-validator-identifier" "^7.24.5" 210 | to-fast-properties "^2.0.0" 211 | 212 | "@esbuild/aix-ppc64@0.20.2": 213 | version "0.20.2" 214 | resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" 215 | integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== 216 | 217 | "@esbuild/android-arm64@0.20.2": 218 | version "0.20.2" 219 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" 220 | integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== 221 | 222 | "@esbuild/android-arm@0.20.2": 223 | version "0.20.2" 224 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" 225 | integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== 226 | 227 | "@esbuild/android-x64@0.20.2": 228 | version "0.20.2" 229 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" 230 | integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== 231 | 232 | "@esbuild/darwin-arm64@0.20.2": 233 | version "0.20.2" 234 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" 235 | integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== 236 | 237 | "@esbuild/darwin-x64@0.20.2": 238 | version "0.20.2" 239 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" 240 | integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== 241 | 242 | "@esbuild/freebsd-arm64@0.20.2": 243 | version "0.20.2" 244 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" 245 | integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== 246 | 247 | "@esbuild/freebsd-x64@0.20.2": 248 | version "0.20.2" 249 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" 250 | integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== 251 | 252 | "@esbuild/linux-arm64@0.20.2": 253 | version "0.20.2" 254 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" 255 | integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== 256 | 257 | "@esbuild/linux-arm@0.20.2": 258 | version "0.20.2" 259 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" 260 | integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== 261 | 262 | "@esbuild/linux-ia32@0.20.2": 263 | version "0.20.2" 264 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" 265 | integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== 266 | 267 | "@esbuild/linux-loong64@0.20.2": 268 | version "0.20.2" 269 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" 270 | integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== 271 | 272 | "@esbuild/linux-mips64el@0.20.2": 273 | version "0.20.2" 274 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" 275 | integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== 276 | 277 | "@esbuild/linux-ppc64@0.20.2": 278 | version "0.20.2" 279 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" 280 | integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== 281 | 282 | "@esbuild/linux-riscv64@0.20.2": 283 | version "0.20.2" 284 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" 285 | integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== 286 | 287 | "@esbuild/linux-s390x@0.20.2": 288 | version "0.20.2" 289 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" 290 | integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== 291 | 292 | "@esbuild/linux-x64@0.20.2": 293 | version "0.20.2" 294 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" 295 | integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== 296 | 297 | "@esbuild/netbsd-x64@0.20.2": 298 | version "0.20.2" 299 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" 300 | integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== 301 | 302 | "@esbuild/openbsd-x64@0.20.2": 303 | version "0.20.2" 304 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" 305 | integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== 306 | 307 | "@esbuild/sunos-x64@0.20.2": 308 | version "0.20.2" 309 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" 310 | integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== 311 | 312 | "@esbuild/win32-arm64@0.20.2": 313 | version "0.20.2" 314 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" 315 | integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== 316 | 317 | "@esbuild/win32-ia32@0.20.2": 318 | version "0.20.2" 319 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" 320 | integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== 321 | 322 | "@esbuild/win32-x64@0.20.2": 323 | version "0.20.2" 324 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" 325 | integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== 326 | 327 | "@jridgewell/gen-mapping@^0.3.5": 328 | version "0.3.5" 329 | resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" 330 | integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== 331 | dependencies: 332 | "@jridgewell/set-array" "^1.2.1" 333 | "@jridgewell/sourcemap-codec" "^1.4.10" 334 | "@jridgewell/trace-mapping" "^0.3.24" 335 | 336 | "@jridgewell/resolve-uri@^3.1.0": 337 | version "3.1.2" 338 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" 339 | integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== 340 | 341 | "@jridgewell/set-array@^1.2.1": 342 | version "1.2.1" 343 | resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" 344 | integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== 345 | 346 | "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": 347 | version "1.4.15" 348 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" 349 | integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== 350 | 351 | "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": 352 | version "0.3.25" 353 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" 354 | integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== 355 | dependencies: 356 | "@jridgewell/resolve-uri" "^3.1.0" 357 | "@jridgewell/sourcemap-codec" "^1.4.14" 358 | 359 | "@rollup/rollup-android-arm-eabi@4.17.2": 360 | version "4.17.2" 361 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz#1a32112822660ee104c5dd3a7c595e26100d4c2d" 362 | integrity sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ== 363 | 364 | "@rollup/rollup-android-arm64@4.17.2": 365 | version "4.17.2" 366 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz#5aeef206d65ff4db423f3a93f71af91b28662c5b" 367 | integrity sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw== 368 | 369 | "@rollup/rollup-darwin-arm64@4.17.2": 370 | version "4.17.2" 371 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz#6b66aaf003c70454c292cd5f0236ebdc6ffbdf1a" 372 | integrity sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw== 373 | 374 | "@rollup/rollup-darwin-x64@4.17.2": 375 | version "4.17.2" 376 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz#f64fc51ed12b19f883131ccbcea59fc68cbd6c0b" 377 | integrity sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ== 378 | 379 | "@rollup/rollup-linux-arm-gnueabihf@4.17.2": 380 | version "4.17.2" 381 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz#1a7641111be67c10111f7122d1e375d1226cbf14" 382 | integrity sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A== 383 | 384 | "@rollup/rollup-linux-arm-musleabihf@4.17.2": 385 | version "4.17.2" 386 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz#c93fd632923e0fee25aacd2ae414288d0b7455bb" 387 | integrity sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg== 388 | 389 | "@rollup/rollup-linux-arm64-gnu@4.17.2": 390 | version "4.17.2" 391 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz#fa531425dd21d058a630947527b4612d9d0b4a4a" 392 | integrity sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A== 393 | 394 | "@rollup/rollup-linux-arm64-musl@4.17.2": 395 | version "4.17.2" 396 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz#8acc16f095ceea5854caf7b07e73f7d1802ac5af" 397 | integrity sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA== 398 | 399 | "@rollup/rollup-linux-powerpc64le-gnu@4.17.2": 400 | version "4.17.2" 401 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz#94e69a8499b5cf368911b83a44bb230782aeb571" 402 | integrity sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ== 403 | 404 | "@rollup/rollup-linux-riscv64-gnu@4.17.2": 405 | version "4.17.2" 406 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz#7ef1c781c7e59e85a6ce261cc95d7f1e0b56db0f" 407 | integrity sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg== 408 | 409 | "@rollup/rollup-linux-s390x-gnu@4.17.2": 410 | version "4.17.2" 411 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz#f15775841c3232fca9b78cd25a7a0512c694b354" 412 | integrity sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g== 413 | 414 | "@rollup/rollup-linux-x64-gnu@4.17.2": 415 | version "4.17.2" 416 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz#b521d271798d037ad70c9f85dd97d25f8a52e811" 417 | integrity sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ== 418 | 419 | "@rollup/rollup-linux-x64-musl@4.17.2": 420 | version "4.17.2" 421 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz#9254019cc4baac35800991315d133cc9fd1bf385" 422 | integrity sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q== 423 | 424 | "@rollup/rollup-win32-arm64-msvc@4.17.2": 425 | version "4.17.2" 426 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz#27f65a89f6f52ee9426ec11e3571038e4671790f" 427 | integrity sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA== 428 | 429 | "@rollup/rollup-win32-ia32-msvc@4.17.2": 430 | version "4.17.2" 431 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz#a2fbf8246ed0bb014f078ca34ae6b377a90cb411" 432 | integrity sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ== 433 | 434 | "@rollup/rollup-win32-x64-msvc@4.17.2": 435 | version "4.17.2" 436 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz#5a2d08b81e8064b34242d5cc9973ef8dd1e60503" 437 | integrity sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w== 438 | 439 | "@types/babel__core@^7.20.5": 440 | version "7.20.5" 441 | resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" 442 | integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== 443 | dependencies: 444 | "@babel/parser" "^7.20.7" 445 | "@babel/types" "^7.20.7" 446 | "@types/babel__generator" "*" 447 | "@types/babel__template" "*" 448 | "@types/babel__traverse" "*" 449 | 450 | "@types/babel__generator@*": 451 | version "7.6.8" 452 | resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" 453 | integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== 454 | dependencies: 455 | "@babel/types" "^7.0.0" 456 | 457 | "@types/babel__template@*": 458 | version "7.4.4" 459 | resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" 460 | integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== 461 | dependencies: 462 | "@babel/parser" "^7.1.0" 463 | "@babel/types" "^7.0.0" 464 | 465 | "@types/babel__traverse@*": 466 | version "7.20.5" 467 | resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" 468 | integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== 469 | dependencies: 470 | "@babel/types" "^7.20.7" 471 | 472 | "@types/estree@1.0.5": 473 | version "1.0.5" 474 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" 475 | integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== 476 | 477 | "@types/prop-types@*": 478 | version "15.7.12" 479 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" 480 | integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== 481 | 482 | "@types/react-dom@^18.0.11": 483 | version "18.3.0" 484 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" 485 | integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== 486 | dependencies: 487 | "@types/react" "*" 488 | 489 | "@types/react@*", "@types/react@^18.0.31": 490 | version "18.3.1" 491 | resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.1.tgz#fed43985caa834a2084d002e4771e15dfcbdbe8e" 492 | integrity sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw== 493 | dependencies: 494 | "@types/prop-types" "*" 495 | csstype "^3.0.2" 496 | 497 | "@vitejs/plugin-react@latest": 498 | version "4.2.1" 499 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz#744d8e4fcb120fc3dbaa471dadd3483f5a304bb9" 500 | integrity sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ== 501 | dependencies: 502 | "@babel/core" "^7.23.5" 503 | "@babel/plugin-transform-react-jsx-self" "^7.23.3" 504 | "@babel/plugin-transform-react-jsx-source" "^7.23.3" 505 | "@types/babel__core" "^7.20.5" 506 | react-refresh "^0.14.0" 507 | 508 | ansi-styles@^3.2.1: 509 | version "3.2.1" 510 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 511 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 512 | dependencies: 513 | color-convert "^1.9.0" 514 | 515 | anymatch@~3.1.2: 516 | version "3.1.3" 517 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 518 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 519 | dependencies: 520 | normalize-path "^3.0.0" 521 | picomatch "^2.0.4" 522 | 523 | asap@~2.0.6: 524 | version "2.0.6" 525 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 526 | integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== 527 | 528 | binary-extensions@^2.0.0: 529 | version "2.3.0" 530 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" 531 | integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== 532 | 533 | braces@~3.0.2: 534 | version "3.0.2" 535 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 536 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 537 | dependencies: 538 | fill-range "^7.0.1" 539 | 540 | browserslist@^4.22.2: 541 | version "4.23.0" 542 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" 543 | integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== 544 | dependencies: 545 | caniuse-lite "^1.0.30001587" 546 | electron-to-chromium "^1.4.668" 547 | node-releases "^2.0.14" 548 | update-browserslist-db "^1.0.13" 549 | 550 | caniuse-lite@^1.0.30001587: 551 | version "1.0.30001614" 552 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz#f894b4209376a0bf923d67d9c361d96b1dfebe39" 553 | integrity sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog== 554 | 555 | chalk@^2.4.2: 556 | version "2.4.2" 557 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 558 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 559 | dependencies: 560 | ansi-styles "^3.2.1" 561 | escape-string-regexp "^1.0.5" 562 | supports-color "^5.3.0" 563 | 564 | "chokidar@>=3.0.0 <4.0.0": 565 | version "3.6.0" 566 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" 567 | integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== 568 | dependencies: 569 | anymatch "~3.1.2" 570 | braces "~3.0.2" 571 | glob-parent "~5.1.2" 572 | is-binary-path "~2.1.0" 573 | is-glob "~4.0.1" 574 | normalize-path "~3.0.0" 575 | readdirp "~3.6.0" 576 | optionalDependencies: 577 | fsevents "~2.3.2" 578 | 579 | color-convert@^1.9.0: 580 | version "1.9.3" 581 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 582 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 583 | dependencies: 584 | color-name "1.1.3" 585 | 586 | color-name@1.1.3: 587 | version "1.1.3" 588 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 589 | integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== 590 | 591 | convert-source-map@^2.0.0: 592 | version "2.0.0" 593 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" 594 | integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== 595 | 596 | core-js@^3.19.2: 597 | version "3.37.0" 598 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.37.0.tgz#d8dde58e91d156b2547c19d8a4efd5c7f6c426bb" 599 | integrity sha512-fu5vHevQ8ZG4og+LXug8ulUtVxjOcEYvifJr7L5Bfq9GOztVqsKd9/59hUk2ZSbCrS3BqUr3EpaYGIYzq7g3Ug== 600 | 601 | csstype@^3.0.2: 602 | version "3.1.3" 603 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" 604 | integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== 605 | 606 | debug@^4.1.0, debug@^4.3.1: 607 | version "4.3.4" 608 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 609 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 610 | dependencies: 611 | ms "2.1.2" 612 | 613 | electron-to-chromium@^1.4.668: 614 | version "1.4.751" 615 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.751.tgz#b5b19742a435c589de02f60c16618150498bbd59" 616 | integrity sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw== 617 | 618 | esbuild@^0.20.1: 619 | version "0.20.2" 620 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" 621 | integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== 622 | optionalDependencies: 623 | "@esbuild/aix-ppc64" "0.20.2" 624 | "@esbuild/android-arm" "0.20.2" 625 | "@esbuild/android-arm64" "0.20.2" 626 | "@esbuild/android-x64" "0.20.2" 627 | "@esbuild/darwin-arm64" "0.20.2" 628 | "@esbuild/darwin-x64" "0.20.2" 629 | "@esbuild/freebsd-arm64" "0.20.2" 630 | "@esbuild/freebsd-x64" "0.20.2" 631 | "@esbuild/linux-arm" "0.20.2" 632 | "@esbuild/linux-arm64" "0.20.2" 633 | "@esbuild/linux-ia32" "0.20.2" 634 | "@esbuild/linux-loong64" "0.20.2" 635 | "@esbuild/linux-mips64el" "0.20.2" 636 | "@esbuild/linux-ppc64" "0.20.2" 637 | "@esbuild/linux-riscv64" "0.20.2" 638 | "@esbuild/linux-s390x" "0.20.2" 639 | "@esbuild/linux-x64" "0.20.2" 640 | "@esbuild/netbsd-x64" "0.20.2" 641 | "@esbuild/openbsd-x64" "0.20.2" 642 | "@esbuild/sunos-x64" "0.20.2" 643 | "@esbuild/win32-arm64" "0.20.2" 644 | "@esbuild/win32-ia32" "0.20.2" 645 | "@esbuild/win32-x64" "0.20.2" 646 | 647 | escalade@^3.1.1: 648 | version "3.1.2" 649 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" 650 | integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== 651 | 652 | escape-string-regexp@^1.0.5: 653 | version "1.0.5" 654 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 655 | integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== 656 | 657 | fill-range@^7.0.1: 658 | version "7.0.1" 659 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 660 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 661 | dependencies: 662 | to-regex-range "^5.0.1" 663 | 664 | fsevents@~2.3.2, fsevents@~2.3.3: 665 | version "2.3.3" 666 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 667 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 668 | 669 | gensync@^1.0.0-beta.2: 670 | version "1.0.0-beta.2" 671 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" 672 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== 673 | 674 | glob-parent@~5.1.2: 675 | version "5.1.2" 676 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 677 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 678 | dependencies: 679 | is-glob "^4.0.1" 680 | 681 | globals@^11.1.0: 682 | version "11.12.0" 683 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" 684 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 685 | 686 | has-flag@^3.0.0: 687 | version "3.0.0" 688 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 689 | integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== 690 | 691 | immutable@^4.0.0: 692 | version "4.3.5" 693 | resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" 694 | integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== 695 | 696 | is-binary-path@~2.1.0: 697 | version "2.1.0" 698 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 699 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 700 | dependencies: 701 | binary-extensions "^2.0.0" 702 | 703 | is-extglob@^2.1.1: 704 | version "2.1.1" 705 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 706 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 707 | 708 | is-glob@^4.0.1, is-glob@~4.0.1: 709 | version "4.0.3" 710 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 711 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 712 | dependencies: 713 | is-extglob "^2.1.1" 714 | 715 | is-number@^7.0.0: 716 | version "7.0.0" 717 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 718 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 719 | 720 | js-tokens@^4.0.0: 721 | version "4.0.0" 722 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 723 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 724 | 725 | jsesc@^2.5.1: 726 | version "2.5.2" 727 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" 728 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== 729 | 730 | json5@^2.2.3: 731 | version "2.2.3" 732 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" 733 | integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== 734 | 735 | lru-cache@^5.1.1: 736 | version "5.1.1" 737 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" 738 | integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== 739 | dependencies: 740 | yallist "^3.0.2" 741 | 742 | ms@2.1.2: 743 | version "2.1.2" 744 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 745 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 746 | 747 | nanoid@^3.3.7: 748 | version "3.3.7" 749 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" 750 | integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== 751 | 752 | node-releases@^2.0.14: 753 | version "2.0.14" 754 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" 755 | integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== 756 | 757 | normalize-path@^3.0.0, normalize-path@~3.0.0: 758 | version "3.0.0" 759 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 760 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 761 | 762 | object-assign@^4.1.1: 763 | version "4.1.1" 764 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 765 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 766 | 767 | performance-now@^2.1.0: 768 | version "2.1.0" 769 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 770 | integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== 771 | 772 | picocolors@^1.0.0: 773 | version "1.0.0" 774 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 775 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 776 | 777 | picomatch@^2.0.4, picomatch@^2.2.1: 778 | version "2.3.1" 779 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 780 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 781 | 782 | postcss@^8.4.38: 783 | version "8.4.38" 784 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" 785 | integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== 786 | dependencies: 787 | nanoid "^3.3.7" 788 | picocolors "^1.0.0" 789 | source-map-js "^1.2.0" 790 | 791 | promise@^8.1.0: 792 | version "8.3.0" 793 | resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" 794 | integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== 795 | dependencies: 796 | asap "~2.0.6" 797 | 798 | raf@^3.4.1: 799 | version "3.4.1" 800 | resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" 801 | integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== 802 | dependencies: 803 | performance-now "^2.1.0" 804 | 805 | react-app-polyfill@^3.0.0: 806 | version "3.0.0" 807 | resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7" 808 | integrity sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w== 809 | dependencies: 810 | core-js "^3.19.2" 811 | object-assign "^4.1.1" 812 | promise "^8.1.0" 813 | raf "^3.4.1" 814 | regenerator-runtime "^0.13.9" 815 | whatwg-fetch "^3.6.2" 816 | 817 | react-refresh@^0.14.0: 818 | version "0.14.2" 819 | resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" 820 | integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== 821 | 822 | readdirp@~3.6.0: 823 | version "3.6.0" 824 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 825 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 826 | dependencies: 827 | picomatch "^2.2.1" 828 | 829 | regenerator-runtime@^0.13.9: 830 | version "0.13.11" 831 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" 832 | integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== 833 | 834 | rollup@^4.13.0: 835 | version "4.17.2" 836 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.17.2.tgz#26d1785d0144122277fdb20ab3a24729ae68301f" 837 | integrity sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ== 838 | dependencies: 839 | "@types/estree" "1.0.5" 840 | optionalDependencies: 841 | "@rollup/rollup-android-arm-eabi" "4.17.2" 842 | "@rollup/rollup-android-arm64" "4.17.2" 843 | "@rollup/rollup-darwin-arm64" "4.17.2" 844 | "@rollup/rollup-darwin-x64" "4.17.2" 845 | "@rollup/rollup-linux-arm-gnueabihf" "4.17.2" 846 | "@rollup/rollup-linux-arm-musleabihf" "4.17.2" 847 | "@rollup/rollup-linux-arm64-gnu" "4.17.2" 848 | "@rollup/rollup-linux-arm64-musl" "4.17.2" 849 | "@rollup/rollup-linux-powerpc64le-gnu" "4.17.2" 850 | "@rollup/rollup-linux-riscv64-gnu" "4.17.2" 851 | "@rollup/rollup-linux-s390x-gnu" "4.17.2" 852 | "@rollup/rollup-linux-x64-gnu" "4.17.2" 853 | "@rollup/rollup-linux-x64-musl" "4.17.2" 854 | "@rollup/rollup-win32-arm64-msvc" "4.17.2" 855 | "@rollup/rollup-win32-ia32-msvc" "4.17.2" 856 | "@rollup/rollup-win32-x64-msvc" "4.17.2" 857 | fsevents "~2.3.2" 858 | 859 | sass@^1.75.0: 860 | version "1.75.0" 861 | resolved "https://registry.yarnpkg.com/sass/-/sass-1.75.0.tgz#91bbe87fb02dfcc34e052ddd6ab80f60d392be6c" 862 | integrity sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw== 863 | dependencies: 864 | chokidar ">=3.0.0 <4.0.0" 865 | immutable "^4.0.0" 866 | source-map-js ">=0.6.2 <2.0.0" 867 | 868 | semver@^6.3.1: 869 | version "6.3.1" 870 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" 871 | integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== 872 | 873 | "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0: 874 | version "1.2.0" 875 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" 876 | integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== 877 | 878 | supports-color@^5.3.0: 879 | version "5.5.0" 880 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 881 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 882 | dependencies: 883 | has-flag "^3.0.0" 884 | 885 | to-fast-properties@^2.0.0: 886 | version "2.0.0" 887 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 888 | integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== 889 | 890 | to-regex-range@^5.0.1: 891 | version "5.0.1" 892 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 893 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 894 | dependencies: 895 | is-number "^7.0.0" 896 | 897 | typescript@^4: 898 | version "4.9.5" 899 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" 900 | integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== 901 | 902 | update-browserslist-db@^1.0.13: 903 | version "1.0.13" 904 | resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" 905 | integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== 906 | dependencies: 907 | escalade "^3.1.1" 908 | picocolors "^1.0.0" 909 | 910 | vite@latest: 911 | version "5.2.10" 912 | resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.10.tgz#2ac927c91e99d51b376a5c73c0e4b059705f5bd7" 913 | integrity sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw== 914 | dependencies: 915 | esbuild "^0.20.1" 916 | postcss "^8.4.38" 917 | rollup "^4.13.0" 918 | optionalDependencies: 919 | fsevents "~2.3.3" 920 | 921 | whatwg-fetch@^3.6.2: 922 | version "3.6.20" 923 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" 924 | integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== 925 | 926 | yallist@^3.0.2: 927 | version "3.1.1" 928 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" 929 | integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== 930 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-local-toast", 3 | "version": "2.0.2", 4 | "license": "MIT", 5 | "author": "OlegWock", 6 | "main": "dist/index.js", 7 | "module": "dist/react-local-toast.esm.js", 8 | "typings": "dist/index.d.ts", 9 | "files": [ 10 | "dist", 11 | "src" 12 | ], 13 | "scripts": { 14 | "analyze": "size-limit --why", 15 | "build": "patch-package && dts build", 16 | "lint": "dts lint", 17 | "prepare": "patch-package && dts build", 18 | "size": "size-limit", 19 | "start": "patch-package && dts watch --format esm", 20 | "test": "patch-package && dts test --passWithNoTests", 21 | "patch": "patch-package" 22 | }, 23 | "husky": { 24 | "hooks": { 25 | "pre-commit": "dts lint" 26 | } 27 | }, 28 | "prettier": { 29 | "printWidth": 80, 30 | "semi": true, 31 | "singleQuote": true, 32 | "trailingComma": "es5" 33 | }, 34 | "jest": { 35 | "testEnvironment": "jsdom" 36 | }, 37 | "peerDependencies": { 38 | "react": ">=16" 39 | }, 40 | "engines": { 41 | "node": ">=18" 42 | }, 43 | "size-limit": [ 44 | { 45 | "path": "dist/react-local-toast.cjs.production.min.js", 46 | "limit": "10 KB" 47 | }, 48 | { 49 | "path": "dist/react-local-toast.esm.js", 50 | "limit": "10 KB" 51 | } 52 | ], 53 | "devDependencies": { 54 | "@size-limit/preset-small-lib": "^11.1.2", 55 | "@tsconfig/recommended": "^1.0.6", 56 | "@tsconfig/vite-react": "^3.0.2", 57 | "@types/react": "^18.3.1", 58 | "@types/react-dom": "^18.3.0", 59 | "@types/react-transition-group": "^4.4.10", 60 | "@types/uuid": "^9.0.8", 61 | "dts-cli": "^2.0.4", 62 | "husky": "^9.0.11", 63 | "patch-package": "^8.0.0", 64 | "postinstall-postinstall": "^2.1.0", 65 | "react": "^18.3.1", 66 | "react-dom": "^18.3.1", 67 | "rollup-plugin-scss": "^4.0.0", 68 | "rollup-plugin-visualizer": "^5.12.0", 69 | "sass": "^1.75.0", 70 | "size-limit": "^11.1.2", 71 | "tslib": "^2.6.2", 72 | "typescript": "^5.4.5" 73 | }, 74 | "dependencies": { 75 | "clsx": "^2.1.1", 76 | "react-merge-refs": "^2.1.1", 77 | "react-transition-group": "^4.4.5", 78 | "uuid": "^9.0.1" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /patches/dts-cli+2.0.4.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/dts-cli/package.json b/node_modules/dts-cli/package.json 2 | index eb9f141..657c5bb 100644 3 | --- a/node_modules/dts-cli/package.json 4 | +++ b/node_modules/dts-cli/package.json 5 | @@ -21,6 +21,7 @@ 6 | "bin": { 7 | "dts": "./dist/index.js" 8 | }, 9 | + "main": "./dist/index.js", 10 | "typings": "./dist/index.d.ts", 11 | "scripts": { 12 | "build": "tsc -p tsconfig.json", 13 | -------------------------------------------------------------------------------- /src/const.ts: -------------------------------------------------------------------------------- 1 | import { ToastPlacement } from './types'; 2 | 3 | export const DEFAULT_ANIMATION_DURATION = 80; 4 | 5 | export const DEFAULT_PLACEMENT: ToastPlacement = 'top'; 6 | -------------------------------------------------------------------------------- /src/context.ts: -------------------------------------------------------------------------------- 1 | import { Context, RefObject, createContext as createReactContext } from 'react'; 2 | import { DEFAULT_ANIMATION_DURATION, DEFAULT_PLACEMENT } from './const'; 3 | import { Action, ToastPlacement, ToastComponentType } from './types'; 4 | 5 | export interface LocalToastContextType { 6 | Component: ToastComponentType; 7 | placement: ToastPlacement; 8 | animationDuration: number; 9 | q: Action[]; 10 | setQ: (q: Action[]) => void; 11 | refs: { 12 | [name: string]: RefObject; 13 | }; 14 | 15 | registerRef: (name: string, ref: RefObject) => void; 16 | removeRef: (name: string) => void; 17 | 18 | addToast: (name: string, data: T, placement?: ToastPlacement) => string; 19 | updateToast: (id: string, newData: Partial) => void; 20 | removeToast: (id: string) => void; 21 | removeAllToastsByName: (name: string) => void; 22 | removeAllToasts: () => void; 23 | } 24 | 25 | export const createContext = (component: ToastComponentType): Context> => { 26 | return createReactContext>({ 27 | Component: component, 28 | placement: DEFAULT_PLACEMENT, 29 | animationDuration: DEFAULT_ANIMATION_DURATION, 30 | q: [], 31 | setQ: () => { }, 32 | refs: {}, 33 | addToast: () => 'noop', 34 | updateToast: () => { }, 35 | removeToast: () => { }, 36 | removeAllToasts: () => { }, 37 | removeAllToastsByName: () => { }, 38 | registerRef: () => { }, 39 | removeRef: () => { }, 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /src/default-implementation.tsx: -------------------------------------------------------------------------------- 1 | import { forwardRef, Ref, useState, useEffect } from 'react'; 2 | import { clsx } from 'clsx'; 3 | import { createCustomLocalToast } from './factory'; 4 | import { DefaultToastData, ToastPlacement, ToastComponentProps } from './types'; 5 | import { DEFAULT_PLACEMENT } from './const'; 6 | import { createHocFromHook } from './hoc'; 7 | import { AiOutlineLoading, IoCloseCircleSharp, IoIosCheckmarkCircle, IoIosInformationCircle, RiErrorWarningFill } from './icons'; 8 | 9 | const animations = { 10 | top: 'rltTop', 11 | bottom: 'rltBottom', 12 | left: 'rltLeft', 13 | right: 'rltRight', 14 | }; 15 | 16 | 17 | const iconByType = { 18 | info: IoIosInformationCircle, 19 | success: IoIosCheckmarkCircle, 20 | warning: RiErrorWarningFill, 21 | error: IoCloseCircleSharp, 22 | loading: AiOutlineLoading, 23 | }; 24 | 25 | 26 | const ToastComponent = forwardRef( 27 | (props: ToastComponentProps, ref: Ref) => { 28 | // If you enable transition and change elements position in same tick -- position change will be animated. 29 | // This codes delays enabling transition by one render 30 | const [disableTransitions, setDisableTransitions] = useState(props.animation.disableTransitions); 31 | useEffect(() => { 32 | if (props.animation.disableTransitions !== disableTransitions) { 33 | setDisableTransitions(props.animation.disableTransitions); 34 | } 35 | }); 36 | 37 | const contentIsText = ['string', 'number'].includes(typeof props.data.text); 38 | const Icon = iconByType[props.data.type]; 39 | 40 | let animation = 'none'; 41 | if (props.animation.state === 'entering') animation = `${animations[props.placement]} ${props.animation.duration}ms linear 0s 1 normal`; 42 | if (props.animation.state === 'exiting') animation = `${animations[props.placement]} ${props.animation.duration}ms linear 0s 1 reverse`; 43 | 44 | const styles = { 45 | transition: disableTransitions ? 'none' : '0.1s linear', 46 | animation, 47 | ...props.style 48 | }; 49 | 50 | return ( 51 |
} 62 | role="presentation" 63 | tabIndex={contentIsText ? -1 : 0} 64 | > 65 |
75 | ); 76 | } 77 | ); 78 | 79 | interface ShowToastOptions { 80 | type?: DefaultToastData['type']; 81 | placement?: ToastPlacement; 82 | duration?: number; 83 | } 84 | 85 | export const { Provider, Target, useCustomLocalToast } = createCustomLocalToast(ToastComponent); 86 | 87 | export const useLocalToast = () => { 88 | const { addToast, updateToast, removeToast, removeAllToastsByName, removeAllToasts } = useCustomLocalToast(); 89 | 90 | const showToast = ( 91 | name: string, 92 | text: DefaultToastData['text'], 93 | options?: ShowToastOptions 94 | ) => { 95 | const { type = 'success', placement = DEFAULT_PLACEMENT, duration = 2500 } = (options || {}); 96 | 97 | const id = addToast( 98 | name, 99 | { 100 | type, 101 | text, 102 | }, 103 | placement 104 | ); 105 | if (duration > 0) { 106 | setTimeout(() => removeToast(id), duration); 107 | } 108 | return id; 109 | }; 110 | 111 | 112 | return { showToast, updateToast, removeToast, removeAllToastsByName, removeAllToasts }; 113 | }; 114 | 115 | export const withLocalToast = createHocFromHook(useLocalToast); 116 | 117 | export type LocalToastHocProps = typeof useLocalToast extends () => infer R ? R : never; -------------------------------------------------------------------------------- /src/factory.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | import { createContext, LocalToastContextType } from './context'; 3 | import { createProvider, LocalToastProviderType } from './provider'; 4 | import { createTarget, LocalToastTargetType } from './target'; 5 | import { ToastComponentType } from './types'; 6 | 7 | interface CreateCustomLocalToastResult { 8 | Provider: LocalToastProviderType; 9 | Target: LocalToastTargetType; 10 | useCustomLocalToast: () => Pick< 11 | LocalToastContextType, 12 | 'addToast' | 'updateToast' | 'removeToast' | 'removeAllToastsByName' | 'removeAllToasts' 13 | >; 14 | } 15 | 16 | export const createCustomLocalToast = (component: ToastComponentType): CreateCustomLocalToastResult => { 17 | const Context = createContext(component); 18 | const Provider = createProvider(Context, component); 19 | const Target = createTarget(Context); 20 | 21 | const useCustomLocalToast = () => { 22 | const { addToast, updateToast, removeToast, removeAllToastsByName, removeAllToasts } = useContext(Context); 23 | return { addToast, updateToast, removeToast, removeAllToastsByName, removeAllToasts }; 24 | }; 25 | 26 | return { Provider, Target, useCustomLocalToast }; 27 | }; 28 | -------------------------------------------------------------------------------- /src/hoc.tsx: -------------------------------------------------------------------------------- 1 | import { useContext, Context, ComponentType } from "react"; 2 | import { LocalToastContextType } from "./context"; 3 | import { ToastPlacement } from "./types"; 4 | 5 | // Reference https://react-typescript-cheatsheet.netlify.app/docs/hoc/intro/ 6 | 7 | export interface WithLocalToastContextProps { 8 | addToast: (name: string, data: T, placement?: ToastPlacement) => string; 9 | updateToast: (id: string, newData: Partial) => void; 10 | removeToast: (id: string) => void; 11 | removeAllToastsByName: (name: string) => void; 12 | removeAllToasts: () => void; 13 | } 14 | 15 | export type WithHookProps = T; 16 | 17 | 18 | export const createHocFromContext = (context: Context>) =>

>( 19 | WrappedComponent: ComponentType

, 20 | ) => { 21 | 22 | const displayName = WrappedComponent.displayName || WrappedComponent.name || "Component"; 23 | const ComponentWithToast = (props: Omit>) => { 24 | const contextProps = useContext(context); 25 | return ; 26 | }; 27 | 28 | ComponentWithToast.displayName = `withLocalToast(${displayName})`; 29 | return ComponentWithToast; 30 | }; 31 | 32 | 33 | export const createHocFromHook = (hook: () => T) =>

( 34 | WrappedComponent: ComponentType

, 35 | ) => { 36 | 37 | const displayName = WrappedComponent.displayName || WrappedComponent.name || "Component"; 38 | const ComponentWithToast = (props: Omit>) => { 39 | const hookProps = hook(); 40 | return ; 41 | }; 42 | 43 | ComponentWithToast.displayName = `withLocalToast(${displayName})`; 44 | return ComponentWithToast; 45 | }; 46 | -------------------------------------------------------------------------------- /src/icons.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentProps, forwardRef } from "react"; 2 | 3 | export const IoIosCheckmarkCircle = forwardRef>((props, ref) => { 4 | return (); 5 | }); 6 | 7 | export const IoIosInformationCircle = forwardRef>((props, ref) => { 8 | return (); 9 | }); 10 | 11 | export const IoCloseCircleSharp = forwardRef>((props, ref) => { 12 | return (); 13 | }); 14 | 15 | export const RiErrorWarningFill = forwardRef>((props, ref) => { 16 | return (); 17 | }); 18 | 19 | export const AiOutlineLoading = forwardRef>((props, ref) => { 20 | return (); 21 | }); -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import './styles.scss'; 2 | export type { LocalToastProviderProps } from './provider'; 3 | export type { ToastComponentProps, ToastPlacement, DefaultToastComponentProps, DefaultToastData } from './types'; 4 | export { createCustomLocalToast } from './factory'; 5 | export { createHocFromContext, createHocFromHook } from './hoc'; 6 | export { withLocalToast, useLocalToast, Provider as LocalToastProvider, Target as LocalToastTarget } from './default-implementation'; 7 | export type { LocalToastHocProps } from './default-implementation'; 8 | 9 | -------------------------------------------------------------------------------- /src/internals.ts: -------------------------------------------------------------------------------- 1 | // TODO: need to include this in dist package 2 | export { createContext } from './context'; 3 | export type { LocalToastContextType } from './context'; 4 | export { createProvider } from './provider'; 5 | export type { LocalToastProviderType } from './provider'; 6 | export { createTarget } from './target'; 7 | export type { LocalToastTargetType } from './target'; 8 | export { createViewport } from './viewport'; 9 | -------------------------------------------------------------------------------- /src/provider.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode, Context, useState, RefObject, useEffect } from 'react'; 2 | import { v4 as uuidv4 } from 'uuid'; 3 | import { DEFAULT_ANIMATION_DURATION, DEFAULT_PLACEMENT } from './const'; 4 | import { LocalToastContextType } from './context'; 5 | import { Action, ToastPlacement, ToastComponentType } from './types'; 6 | import { createViewport } from './viewport'; 7 | 8 | export interface LocalToastProviderProps { 9 | children?: ReactNode; 10 | Component?: ToastComponentType; 11 | animationDuration?: number; 12 | defaultPlacement?: ToastPlacement; 13 | portalInto?: HTMLElement, 14 | } 15 | 16 | export type LocalToastProviderType = (props: LocalToastProviderProps) => JSX.Element; 17 | 18 | export const createProvider = ( 19 | Context: Context>, 20 | ToastComponent: ToastComponentType 21 | ): LocalToastProviderType => { 22 | const Viewport = createViewport(Context); 23 | 24 | return ({ 25 | children, 26 | Component = ToastComponent, 27 | animationDuration = DEFAULT_ANIMATION_DURATION, 28 | defaultPlacement = DEFAULT_PLACEMENT, 29 | portalInto = undefined, 30 | }: LocalToastProviderProps) => { 31 | const [refs, setRefs] = useState['refs']>({}); 32 | const [q, setQ] = useState['q']>([]); 33 | 34 | const dispatchAction = (action: Action) => { 35 | setQ((prevQ) => { 36 | return [...prevQ, action]; 37 | }); 38 | }; 39 | 40 | const registerRef = (name: string, ref: RefObject) => { 41 | setRefs((prevRefs) => ({ 42 | ...prevRefs, 43 | [name]: ref, 44 | })); 45 | }; 46 | 47 | const removeRef = (name: string) => { 48 | setRefs((prevRefs) => { 49 | const { [name]: _, ...rest } = prevRefs; 50 | return rest; 51 | }); 52 | dispatchAction({ 53 | type: 'removeAllByName', 54 | name, 55 | }); 56 | }; 57 | 58 | const addToast = (name: string, data: T, placement: ToastPlacement = defaultPlacement) => { 59 | const ref = refs[name]; 60 | if (!ref || !ref.current) { 61 | console.warn(`Tried to show toast on not mounted component '${name}'`); 62 | return ''; 63 | } 64 | 65 | const id = uuidv4(); 66 | 67 | dispatchAction({ 68 | type: 'create', 69 | descriptor: { 70 | name, 71 | id, 72 | placement, 73 | ref, 74 | data, 75 | }, 76 | }); 77 | 78 | return id; 79 | }; 80 | 81 | const updateToast = (id: string, newData: Partial) => { 82 | dispatchAction({ 83 | type: 'update', 84 | id, 85 | newData, 86 | }); 87 | }; 88 | 89 | const removeToast = (id: string) => { 90 | dispatchAction({ 91 | type: 'remove', 92 | id, 93 | }); 94 | }; 95 | 96 | const removeAllToastsByName = (name: string) => { 97 | dispatchAction({ 98 | type: 'removeAllByName', 99 | name, 100 | }); 101 | }; 102 | 103 | const removeAllToasts = () => { 104 | dispatchAction({ 105 | type: 'removeAll', 106 | }); 107 | }; 108 | 109 | // Document is unavailable in Next.js SSR, so postpone actual rendering of viewport (portal) 110 | const [mounted, setMounted] = useState(false); 111 | useEffect(() => { 112 | setMounted(true); 113 | }, []); 114 | 115 | return ( 116 | 133 | {children} 134 | {mounted && } 135 | 136 | ); 137 | }; 138 | }; 139 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | .react-local-toast-icon { 2 | pointer-events: none; 3 | margin-right: 12px; 4 | font-size: 24px; 5 | min-width: 24px; 6 | min-height: 24px; 7 | } 8 | 9 | $colors: ( 10 | "info": "#3498db", 11 | "loading": "#3498db", 12 | "success": "#2ecc71", 13 | "warning": "#fa983a", 14 | "error": "#eb2f06", 15 | ); 16 | 17 | @each $type, $color in $colors { 18 | .react-local-toast-#{$type} { 19 | border: 2px solid #{$color}; 20 | 21 | .react-local-toast-icon { 22 | color: #{$color}; 23 | } 24 | } 25 | } 26 | 27 | 28 | .react-local-toast-loading { 29 | .react-local-toast-icon { 30 | animation: rltSpin linear infinite 1.5s; 31 | } 32 | } 33 | 34 | 35 | .react-local-toast-text { 36 | line-height: 1.5; 37 | flex-grow: 1; 38 | } 39 | 40 | .react-local-toast { 41 | padding: 6px 12px; 42 | z-index: 9999; 43 | background-color: white; 44 | color: #333; 45 | font-size: 14px; 46 | box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d; 47 | border-radius: 3px; 48 | min-width: 150px; 49 | max-width: min(350px, calc(80vw - 8px)); 50 | min-height: 30px; 51 | display: flex; 52 | justify-content: center; 53 | align-items: center; 54 | } 55 | 56 | 57 | @keyframes rltTop { 58 | from { 59 | transform: translateY(25%) scale(1); 60 | opacity: 0; 61 | } 62 | 63 | to { 64 | transform: translate(0, 0) scale(1); 65 | opacity: 1; 66 | } 67 | } 68 | 69 | @keyframes rltBottom { 70 | from { 71 | transform: translateY(-25%) scale(1); 72 | opacity: 0; 73 | } 74 | 75 | to { 76 | transform: translate(0, 0) scale(1); 77 | opacity: 1; 78 | } 79 | } 80 | 81 | @keyframes rltLeft { 82 | from { 83 | transform: translateX(25%) scale(1); 84 | opacity: 0; 85 | } 86 | 87 | to { 88 | transform: translate(0, 0) scale(1); 89 | opacity: 1; 90 | } 91 | } 92 | 93 | @keyframes rltRight { 94 | from { 95 | transform: translateX(-25%) scale(1); 96 | opacity: 0; 97 | } 98 | 99 | to { 100 | transform: translate(0, 0) scale(1); 101 | opacity: 1; 102 | } 103 | } 104 | 105 | @keyframes rltSpin { 106 | from { 107 | transform: rotate(0deg); 108 | } 109 | to { 110 | transform: rotate(360deg); 111 | } 112 | } -------------------------------------------------------------------------------- /src/target.tsx: -------------------------------------------------------------------------------- 1 | import { Children, cloneElement, useMemo, forwardRef, Context, useEffect, useContext, useRef, isValidElement, Ref, ForwardedRef } from 'react'; 2 | import { LocalToastContextType } from './context'; 3 | import { mergeRefs } from 'react-merge-refs'; 4 | 5 | export interface LocalToastTargetPropsWithoutRef { 6 | name: string; 7 | children: JSX.Element; 8 | } 9 | 10 | export interface LocalToastTargetProps extends LocalToastTargetPropsWithoutRef { 11 | ref?: Ref 12 | } 13 | 14 | export type LocalToastTargetType = (props: LocalToastTargetProps) => JSX.Element; 15 | 16 | export const createTarget = (Context: Context>): LocalToastTargetType => { 17 | return forwardRef(({ name, children }: LocalToastTargetPropsWithoutRef, forwardedRef: ForwardedRef) => { 18 | const ctx = useContext(Context); 19 | const ref = useRef(null); 20 | 21 | const mergedRefs = useMemo(() => mergeRefs([forwardedRef, ref]), [forwardedRef, ref]); 22 | 23 | useEffect(() => { 24 | ctx.registerRef(name, ref); 25 | return () => { 26 | ctx.removeRef(name); 27 | }; 28 | }, []); 29 | 30 | const child = Children.only(children); 31 | if (!isValidElement<{ ref: Ref }>(child)) { 32 | throw new Error('LocalToastTarget expected single element as a children') 33 | } 34 | return cloneElement(child, { ref: mergedRefs }); 35 | }) as LocalToastTargetType; 36 | }; 37 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType, CSSProperties, RefObject, LegacyRef } from 'react'; 2 | import { TransitionStatus } from 'react-transition-group'; 3 | 4 | export type ToastPlacement = 'top' | 'right' | 'bottom' | 'left'; 5 | 6 | export type ToastComponentType = ComponentType>; 7 | 8 | type ToastDescriptor = { 9 | id: string; 10 | name: string; 11 | placement: ToastPlacement; 12 | ref: RefObject; 13 | data: T; 14 | }; 15 | 16 | type ToastAnimationProps = { 17 | state: TransitionStatus; 18 | duration: number; 19 | disableTransitions: boolean; 20 | }; 21 | 22 | export type ToastComponentProps = { 23 | style: CSSProperties; 24 | id: string; 25 | name: string; 26 | removeMe: () => void; 27 | animation: ToastAnimationProps; 28 | placement: ToastPlacement; 29 | data: T; 30 | ref: LegacyRef; 31 | }; 32 | 33 | export type ActionType = 'create' | 'remove'; 34 | 35 | interface ActionCreate { 36 | type: 'create'; 37 | descriptor: ToastDescriptor; 38 | } 39 | 40 | interface ActionUpdate { 41 | type: 'update'; 42 | id: string; 43 | newData: Partial; 44 | } 45 | 46 | interface ActionRemove { 47 | type: 'remove'; 48 | id: string; 49 | } 50 | 51 | interface ActionRemoveAllByName { 52 | type: 'removeAllByName'; 53 | name: string; 54 | } 55 | 56 | interface ActionRemoveAll { 57 | type: 'removeAll'; 58 | } 59 | 60 | export type Action = ActionCreate | ActionUpdate | ActionRemove | ActionRemoveAllByName | ActionRemoveAll; 61 | 62 | export interface DefaultToastData { 63 | text: string; 64 | type: 'info' | 'success' | 'warning' | 'error' | 'loading'; 65 | } 66 | 67 | export type DefaultToastComponentProps = ToastComponentProps; 68 | 69 | export type DefaultAction = Action; 70 | -------------------------------------------------------------------------------- /src/viewport.tsx: -------------------------------------------------------------------------------- 1 | import { Context, RefObject, Ref, useLayoutEffect, useState, useContext, CSSProperties, useEffect } from 'react'; 2 | import { createPortal } from 'react-dom'; 3 | import { Transition, TransitionGroup } from 'react-transition-group'; 4 | import { LocalToastContextType } from './context'; 5 | import { ToastPlacement } from './types'; 6 | 7 | interface ToastInfo { 8 | id: string; 9 | placement: ToastPlacement; 10 | parentName: string; 11 | parentRef: RefObject; 12 | toastRef: { current: null | HTMLElement }; 13 | attachRef: Ref; 14 | cachedSize: [number, number]; 15 | changedSizeRecently: boolean; 16 | createdAt: number; 17 | data: T; 18 | } 19 | 20 | interface ViewportProps { 21 | portalInto?: HTMLElement, 22 | } 23 | 24 | // Source: https://stackoverflow.com/questions/19014250/rerender-view-on-browser-resize-with-react 25 | const useWindowSize = () => { 26 | const [size, setSize] = useState([0, 0]); 27 | useLayoutEffect(() => { 28 | const updateSize = () => { 29 | setSize([window.innerWidth, window.innerHeight]); 30 | } 31 | window.addEventListener('resize', updateSize); 32 | updateSize(); 33 | return () => window.removeEventListener('resize', updateSize); 34 | }, []); 35 | return size; 36 | }; 37 | 38 | export const createViewport = (context: Context>) => { 39 | return ({ portalInto }: ViewportProps) => { 40 | const renderToast = (toast: ToastInfo) => { 41 | const removeMe = () => { 42 | setToasts((t) => t.filter((tst) => tst.id !== toast.id)); 43 | }; 44 | 45 | if (!toast.parentRef.current) return null; 46 | 47 | let styles: CSSProperties = {}; 48 | let disableTransitions = false; 49 | 50 | if (toast.toastRef.current) { 51 | if (toast.changedSizeRecently) { 52 | disableTransitions = true; 53 | // We don't need this to trigger re-render 54 | toast.changedSizeRecently = false; 55 | } 56 | const MARGIN = 4; 57 | 58 | const toastRect = toast.toastRef.current.getBoundingClientRect(); 59 | const parentRect = toast.parentRef.current.getBoundingClientRect(); 60 | 61 | const parentX = parentRect.left + window.pageXOffset; 62 | const parentY = parentRect.top + window.pageYOffset; 63 | const parentEndX = parentRect.right + window.pageXOffset; 64 | const parentEndY = parentRect.bottom + window.pageYOffset; 65 | 66 | const neighbourToasts = toasts.filter((t) => { 67 | return ( 68 | t.parentName === toast.parentName && 69 | t.placement === toast.placement && 70 | t.id !== toast.id && 71 | t.createdAt < toast.createdAt 72 | ); 73 | }); 74 | const neighbourToastsHeight = neighbourToasts.reduce((height, toastDetails) => { 75 | return height + toastDetails.cachedSize[1] + MARGIN; 76 | }, 0); 77 | 78 | styles = { 79 | position: 'absolute', 80 | }; 81 | if (toast.placement === 'top') { 82 | styles.top = parentY - toastRect.height - MARGIN - neighbourToastsHeight; 83 | styles.left = (parentX + parentEndX) / 2 - toastRect.width / 2; 84 | } 85 | 86 | if (toast.placement === 'bottom') { 87 | styles.top = parentEndY + MARGIN + neighbourToastsHeight; 88 | styles.left = (parentX + parentEndX) / 2 - toastRect.width / 2; 89 | } 90 | 91 | if (toast.placement === 'left') { 92 | styles.top = (parentY + parentEndY) / 2 - toastRect.height / 2 - neighbourToastsHeight; 93 | styles.left = parentX - toastRect.width - MARGIN; 94 | } 95 | 96 | if (toast.placement === 'right') { 97 | styles.top = (parentY + parentEndY) / 2 - toastRect.height / 2 - neighbourToastsHeight; 98 | styles.left = parentEndX + MARGIN; 99 | } 100 | 101 | if (styles.left && (styles.left as number) < 0) styles.left = MARGIN; 102 | if (styles.left && ((styles.left as number) + toastRect.width) > document.body.scrollWidth) styles.left = document.body.scrollWidth - toastRect.width - MARGIN; 103 | } else { 104 | // First paint 105 | // Draw offscreen to estimate tooltip size on next render 106 | disableTransitions = true; 107 | styles = { 108 | position: 'absolute', 109 | left: '-1000px', 110 | }; 111 | } 112 | 113 | return ( 114 | 115 | {(state) => ()} 125 | 126 | ); 127 | }; 128 | 129 | // We don't really need window size, but we need to re-render once window size changes 130 | const [width, height] = useWindowSize(); 131 | 132 | const { q, setQ, Component, animationDuration } = useContext(context); 133 | const [toasts, setToasts] = useState[]>([]); 134 | 135 | useEffect(() => { 136 | q.forEach((action) => { 137 | if (action.type === 'create') { 138 | setToasts((t) => { 139 | const ref: { current: null | HTMLElement } = { current: null }; 140 | return [ 141 | ...t, 142 | { 143 | id: action.descriptor.id, 144 | placement: action.descriptor.placement, 145 | parentName: action.descriptor.name, 146 | parentRef: action.descriptor.ref, 147 | toastRef: ref, 148 | cachedSize: [0, 0], 149 | changedSizeRecently: false, 150 | attachRef: (el) => { 151 | ref.current = el; 152 | }, 153 | data: action.descriptor.data, 154 | createdAt: Date.now(), 155 | }, 156 | ]; 157 | }); 158 | } else if (action.type === 'update') { 159 | setToasts((tsts) => 160 | tsts.map((t) => { 161 | if (t.id === action.id) { 162 | return { 163 | ...t, 164 | data: { 165 | ...t.data, 166 | ...action.newData, 167 | }, 168 | }; 169 | } 170 | return t; 171 | }) 172 | ); 173 | } else if (action.type === 'remove') { 174 | setToasts((t) => t.filter((toast) => toast.id !== action.id)); 175 | } else if (action.type === 'removeAll') { 176 | setToasts([]); 177 | } else if (action.type === 'removeAllByName') { 178 | setToasts((t) => t.filter((toast) => toast.parentName !== action.name)); 179 | } 180 | }); 181 | 182 | if (q.length) setQ([]); 183 | }, [q]); 184 | 185 | useLayoutEffect(() => { 186 | // If any of toasts changed their size after render -- we need to reposition it (and thus schedule one more render) 187 | const newSizes: { [id: string]: [number, number] } = {}; 188 | toasts.forEach((t) => { 189 | if (!t.toastRef.current) return; 190 | const { width, height } = t.toastRef.current.getBoundingClientRect(); 191 | if (t.cachedSize[0] !== width || t.cachedSize[1] !== height) { 192 | newSizes[t.id] = [width, height]; 193 | } 194 | }); 195 | if (Object.keys(newSizes).length) { 196 | setToasts((tsts) => 197 | tsts.map((t) => { 198 | if (newSizes[t.id]) { 199 | return { 200 | ...t, 201 | cachedSize: newSizes[t.id], 202 | changedSizeRecently: true, 203 | }; 204 | } 205 | return t; 206 | }) 207 | ); 208 | } 209 | }); 210 | 211 | return createPortal( 212 | <> 213 | {toasts.map(renderToast)} 214 | , 215 | portalInto || document.body 216 | ); 217 | }; 218 | }; 219 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "extends": "@tsconfig/vite-react/tsconfig.json", 4 | "compilerOptions": { 5 | "allowImportingTsExtensions": false, 6 | "jsx": "react-jsx", 7 | "noUnusedLocals": false, 8 | }, 9 | "include": ["src", "types"] 10 | } 11 | --------------------------------------------------------------------------------