├── dev
├── .gitignore
├── public
│ ├── favicon.png
│ ├── index.html
│ └── global.css
├── src
│ ├── main.js
│ ├── CloseIcon.svelte
│ ├── SettingsIcon.svelte
│ └── App.svelte
├── package.json
├── rollup.config.js
├── README.md
└── yarn.lock
├── .prettierignore
├── src
├── index.js
├── useDropOutside.css
├── utils
│ ├── resolveDragImage.js
│ └── __tests__
│ │ └── resolveDragImage.test.js
├── useDropOutside.js
├── DragAndDrop.js
└── __tests__
│ └── useDropOutside.test.js
├── .babelrc
├── .husky
├── commit-msg
└── pre-commit
├── assets
├── container-switch.gif
└── svelte-use-drop-outside.gif
├── commitlint.config.js
├── .gitignore
├── .github
└── workflows
│ ├── index.yml
│ └── codeql.yml
├── .prettierrc
├── rollup.config.js
├── LICENSE
├── jest
└── jest.setup.js
├── CHANGELOG.md
├── package.json
└── README.md
/dev/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /public/build/
3 |
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .husky/
2 | .idea/
3 | build/
4 | coverage/
5 | node_modules/
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export { default as useDropOutside } from './useDropOutside'
2 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env", {"targets": {"node": "current"}}]]
3 | }
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx commitlint --edit $1
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn test:ci
5 | yarn prettier
6 |
--------------------------------------------------------------------------------
/dev/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/untemps/svelte-use-drop-outside/HEAD/dev/public/favicon.png
--------------------------------------------------------------------------------
/assets/container-switch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/untemps/svelte-use-drop-outside/HEAD/assets/container-switch.gif
--------------------------------------------------------------------------------
/assets/svelte-use-drop-outside.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/untemps/svelte-use-drop-outside/HEAD/assets/svelte-use-drop-outside.gif
--------------------------------------------------------------------------------
/dev/src/main.js:
--------------------------------------------------------------------------------
1 | import App from './App.svelte'
2 |
3 | const app = new App({
4 | target: document.body,
5 | })
6 |
7 | export default app
8 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'subject-case': [2, 'always', ['sentence-case']],
5 | 'scope-case': [2, 'always', ['lower-case', 'upper-case']],
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/src/useDropOutside.css:
--------------------------------------------------------------------------------
1 | .__drag {
2 | position: absolute;
3 | z-index: 999;
4 | user-select: none;
5 | opacity: .7;
6 |
7 | --origin-x: 0px;
8 | --origin-y: 0px;
9 | }
10 |
11 | @keyframes move {
12 | 100% {
13 | left: var(--origin-x);
14 | top: var(--origin-y);
15 | }
16 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build
2 | .cache/
3 | dist/
4 | stats.html
5 |
6 | # Dependencies
7 | node_modules/
8 |
9 | # Misc
10 | .DS_STORE
11 |
12 | # NPM
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 | package-lock.json
17 | .yarn
18 |
19 | # Webstorm
20 | .idea/
21 | *.iml
22 |
23 | # Jest
24 | coverage/
25 | __snapshots__/
--------------------------------------------------------------------------------
/dev/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Svelte app
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/utils/resolveDragImage.js:
--------------------------------------------------------------------------------
1 | import { isString } from '@untemps/utils/string/isString'
2 | import { isElement } from '@untemps/utils/dom/isElement'
3 |
4 | export const resolveDragImage = (source) => {
5 | if (!!source) {
6 | if (isElement(source)) {
7 | return source
8 | } else if (source.src || isString(source)) {
9 | const image = new Image()
10 | image.src = source.src || source
11 | source.width && (image.width = source.width)
12 | source.height && (image.height = source.height)
13 | return image
14 | }
15 | }
16 | return null
17 | }
18 |
--------------------------------------------------------------------------------
/.github/workflows/index.yml:
--------------------------------------------------------------------------------
1 | name: "deploy"
2 | on:
3 | push:
4 | branches:
5 | - main
6 | - beta
7 | jobs:
8 | release:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - uses: actions/setup-node@v1
13 | with:
14 | node-version: '16'
15 | - run: yarn install
16 | - run: yarn test:ci
17 | - run: yarn build
18 | - run: npx semantic-release
19 | env:
20 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
22 | - uses: codecov/codecov-action@v1
23 | with:
24 | file: coverage/lcov.info
--------------------------------------------------------------------------------
/dev/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "build": "rollup -c",
7 | "dev": "rollup -c -w",
8 | "start": "sirv public --no-clear"
9 | },
10 | "devDependencies": {
11 | "@rollup/plugin-commonjs": "^17.0.0",
12 | "@rollup/plugin-node-resolve": "^11.0.0",
13 | "rollup": "^2.3.4",
14 | "rollup-plugin-css-only": "^3.1.0",
15 | "rollup-plugin-livereload": "^2.0.0",
16 | "rollup-plugin-svelte": "^7.0.0",
17 | "rollup-plugin-terser": "^7.0.0",
18 | "svelte": "^3.0.0"
19 | },
20 | "dependencies": {
21 | "sirv-cli": "^1.0.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/dev/src/CloseIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
10 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "pluginSearchDirs": ["."],
3 | "printWidth": 120,
4 | "useTabs": true,
5 | "tabWidth": 4,
6 | "singleQuote": true,
7 | "semi": false,
8 | "trailingComma": "es5",
9 | "bracketSpacing": true,
10 | "overrides": [
11 | {
12 | "files": "./**/*.js",
13 | "options": {
14 | "parser": "babel"
15 | }
16 | },
17 | {
18 | "files": "./**/*.svelte",
19 | "options": {
20 | "svelteBracketNewLine": false,
21 | "svelteAllowShorthand": false,
22 | "svelteSortOrder" : "options-scripts-styles-markup",
23 | "plugins": [
24 | "prettier-plugin-svelte"
25 | ]
26 | }
27 | },
28 | {
29 | "files": "./**/*.json",
30 | "options": {
31 | "parser": "json"
32 | }
33 | },
34 | {
35 | "files": ".prettierrc",
36 | "options": {
37 | "parser": "json"
38 | }
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/src/utils/__tests__/resolveDragImage.test.js:
--------------------------------------------------------------------------------
1 | import { createElement } from '@untemps/utils/dom/createElement'
2 |
3 | import { resolveDragImage } from '../resolveDragImage'
4 |
5 | describe('resolveDragImage', () => {
6 | let img = createElement()
7 |
8 | it.each([null, undefined, 0, {}])('returns null', (source) => {
9 | expect(resolveDragImage(source)).toBeNull()
10 | })
11 |
12 | it('returns same element', () => {
13 | expect(resolveDragImage(img).isSameNode(img)).toBeTruthy()
14 | })
15 |
16 | it.each([
17 | [{ src: 'foo' }, createElement({ tag: 'img', attributes: { src: 'foo' } })],
18 | [
19 | { src: 'foo', width: 100, height: 100 },
20 | createElement({ tag: 'img', attributes: { src: 'foo', width: 100, height: 100 } }),
21 | ],
22 | ['foo', createElement({ tag: 'img', attributes: { src: 'foo' } })],
23 | ])('returns proper element', (source, expected) => {
24 | expect(resolveDragImage(source).isEqualNode(expected)).toBeTruthy()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 | schedule:
9 | - cron: "58 6 * * 5"
10 |
11 | jobs:
12 | analyze:
13 | name: Analyze
14 | runs-on: ubuntu-latest
15 | permissions:
16 | actions: read
17 | contents: read
18 | security-events: write
19 |
20 | strategy:
21 | fail-fast: false
22 | matrix:
23 | language: [ javascript ]
24 |
25 | steps:
26 | - name: Checkout
27 | uses: actions/checkout@v3
28 |
29 | - name: Initialize CodeQL
30 | uses: github/codeql-action/init@v2
31 | with:
32 | languages: ${{ matrix.language }}
33 | queries: +security-and-quality
34 |
35 | - name: Autobuild
36 | uses: github/codeql-action/autobuild@v2
37 |
38 | - name: Perform CodeQL Analysis
39 | uses: github/codeql-action/analyze@v2
40 | with:
41 | category: "/language:${{ matrix.language }}"
42 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import svelte from 'rollup-plugin-svelte'
2 | import babel from '@rollup/plugin-babel'
3 | import commonjs from '@rollup/plugin-commonjs'
4 | import postcss from 'rollup-plugin-postcss'
5 | import resolve from '@rollup/plugin-node-resolve'
6 | import { terser } from 'rollup-plugin-terser'
7 | import visualizer from 'rollup-plugin-visualizer'
8 |
9 | const production = process.env.NODE_ENV === 'production'
10 | const target = process.env.BABEL_ENV
11 |
12 | export default {
13 | input: 'src/index.js',
14 | output: {
15 | name: 'svelte-use-drop-outside',
16 | file: {
17 | cjs: 'dist/index.js',
18 | es: 'dist/index.es.js',
19 | umd: 'dist/index.umd.js',
20 | }[target],
21 | format: target,
22 | sourcemap: 'inline',
23 | },
24 | plugins: [
25 | svelte(),
26 | postcss({
27 | plugins: [],
28 | }),
29 | babel({
30 | exclude: 'node_modules/**',
31 | babelHelpers: 'bundled',
32 | }),
33 | resolve(),
34 | commonjs(),
35 | production && terser(),
36 | visualizer({
37 | sourcemap: true,
38 | }),
39 | ],
40 | }
41 |
--------------------------------------------------------------------------------
/src/useDropOutside.js:
--------------------------------------------------------------------------------
1 | import DragAndDrop from './DragAndDrop'
2 |
3 | const useDropOutside = (
4 | node,
5 | {
6 | areaSelector,
7 | dragImage,
8 | dragClassName,
9 | animate,
10 | animateOptions,
11 | dragHandleCentered,
12 | onDropOutside,
13 | onDropInside,
14 | onDragCancel,
15 | }
16 | ) => {
17 | const instance = new DragAndDrop(
18 | node,
19 | areaSelector,
20 | dragImage,
21 | dragClassName,
22 | animate,
23 | animateOptions,
24 | dragHandleCentered,
25 | onDropOutside,
26 | onDropInside,
27 | onDragCancel
28 | )
29 |
30 | return {
31 | update: ({
32 | areaSelector,
33 | dragImage,
34 | dragClassName,
35 | animate,
36 | animateOptions,
37 | dragHandleCentered,
38 | onDropOutside,
39 | onDropInside,
40 | onDragCancel,
41 | }) =>
42 | instance.update(
43 | areaSelector,
44 | dragImage,
45 | dragClassName,
46 | animate,
47 | animateOptions,
48 | dragHandleCentered,
49 | onDropOutside,
50 | onDropInside,
51 | onDragCancel
52 | ),
53 | destroy: () => instance.destroy(),
54 | }
55 | }
56 |
57 | export default useDropOutside
58 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Vincent Le Badezet
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.
22 |
--------------------------------------------------------------------------------
/dev/public/global.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html, body {
6 | position: relative;
7 | width: 100%;
8 | height: 100%;
9 | }
10 |
11 | body {
12 | color: #333;
13 | margin: 0;
14 | padding: 0;
15 | box-sizing: border-box;
16 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
17 | }
18 |
19 | a {
20 | color: rgb(0,100,200);
21 | text-decoration: none;
22 | }
23 |
24 | a:hover {
25 | text-decoration: underline;
26 | }
27 |
28 | a:visited {
29 | color: rgb(0,80,160);
30 | }
31 |
32 | label {
33 | display: block;
34 | }
35 |
36 | input, button, select, textarea {
37 | font-family: inherit;
38 | font-size: inherit;
39 | -webkit-padding: 0.4em 0;
40 | padding: 0.4em;
41 | margin: 0 0 0.5em 0;
42 | box-sizing: border-box;
43 | border: 1px solid #ccc;
44 | border-radius: 2px;
45 | }
46 |
47 | input:disabled {
48 | color: #ccc;
49 | }
50 |
51 | button {
52 | color: #333;
53 | background-color: #f4f4f4;
54 | outline: none;
55 | }
56 |
57 | button:disabled {
58 | color: #999;
59 | }
60 |
61 | button:not(:disabled):active {
62 | background-color: #ddd;
63 | }
64 |
65 | button:focus {
66 | border-color: #666;
67 | }
68 |
--------------------------------------------------------------------------------
/jest/jest.setup.js:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/extend-expect'
2 | import { fireEvent } from '@testing-library/svelte'
3 | import { toBeInTheDocument, toHaveAttribute, toHaveStyle } from '@testing-library/jest-dom/matchers'
4 | import { standby } from '@untemps/utils/async/standby'
5 |
6 | expect.extend({ toBeInTheDocument, toHaveAttribute, toHaveStyle })
7 |
8 | global._enter = async (trigger) =>
9 | new Promise(async (resolve) => {
10 | await fireEvent.mouseOver(trigger) // fireEvent.mouseEnter only works if mouseOver is triggered before
11 | await fireEvent.mouseEnter(trigger)
12 | await standby(1)
13 | resolve()
14 | })
15 |
16 | global._leave = async (trigger) =>
17 | new Promise(async (resolve) => {
18 | await fireEvent.mouseLeave(trigger)
19 | await standby(1)
20 | resolve()
21 | })
22 |
23 | global._enterAndLeave = async (trigger) =>
24 | new Promise(async (resolve) => {
25 | await _enter(trigger)
26 | await _leave(trigger)
27 | resolve()
28 | })
29 |
30 | global._focus = async (trigger) =>
31 | new Promise(async (resolve) => {
32 | await fireEvent.focusIn(trigger)
33 | await standby(1)
34 | resolve()
35 | })
36 |
37 | global._blur = async (trigger) =>
38 | new Promise(async (resolve) => {
39 | await fireEvent.focusOut(trigger)
40 | await standby(1)
41 | resolve()
42 | })
43 |
44 | global._focusAndBlur = async (trigger) =>
45 | new Promise(async (resolve) => {
46 | await _focus(trigger)
47 | await _blur(trigger)
48 | resolve()
49 | })
50 |
51 | global._keyDown = async (trigger, key) =>
52 | new Promise(async (resolve) => {
53 | await fireEvent.keyDown(trigger, key || { key: 'Escape', code: 'Escape', charCode: 27 })
54 | await standby(1)
55 | resolve()
56 | })
57 |
--------------------------------------------------------------------------------
/dev/rollup.config.js:
--------------------------------------------------------------------------------
1 | import svelte from 'rollup-plugin-svelte'
2 | import commonjs from '@rollup/plugin-commonjs'
3 | import resolve from '@rollup/plugin-node-resolve'
4 | import livereload from 'rollup-plugin-livereload'
5 | import { terser } from 'rollup-plugin-terser'
6 | import css from 'rollup-plugin-css-only'
7 |
8 | const production = !process.env.ROLLUP_WATCH
9 |
10 | function serve() {
11 | let server
12 |
13 | function toExit() {
14 | if (server) server.kill(0)
15 | }
16 |
17 | return {
18 | writeBundle() {
19 | if (server) return
20 | server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
21 | stdio: ['ignore', 'inherit', 'inherit'],
22 | shell: true,
23 | })
24 |
25 | process.on('SIGTERM', toExit)
26 | process.on('exit', toExit)
27 | },
28 | }
29 | }
30 |
31 | export default {
32 | input: 'src/main.js',
33 | output: {
34 | sourcemap: true,
35 | format: 'iife',
36 | name: 'app',
37 | file: 'public/build/bundle.js',
38 | },
39 | plugins: [
40 | svelte({
41 | compilerOptions: {
42 | // enable run-time checks when not in production
43 | dev: !production,
44 | },
45 | }),
46 | // we'll extract any component CSS out into
47 | // a separate file - better for performance
48 | css({ output: 'bundle.css' }),
49 | // If you have external dependencies installed from
50 | // npm, you'll most likely need these plugins. In
51 | // some cases you'll need additional configuration -
52 | // consult the documentation for details:
53 | // https://github.com/rollup/plugins/tree/master/packages/commonjs
54 | resolve({
55 | browser: true,
56 | dedupe: ['svelte'],
57 | }),
58 | commonjs(),
59 |
60 | // In dev mode, call `npm run start` once
61 | // the bundle has been generated
62 | !production && serve(),
63 |
64 | // Watch the `public` directory and refresh the
65 | // browser on changes when not in production
66 | !production && livereload('public'),
67 |
68 | // If we're building for production (npm run build
69 | // instead of npm run dev), minify
70 | production && terser(),
71 | ],
72 | watch: {
73 | clearScreen: false,
74 | },
75 | }
76 |
--------------------------------------------------------------------------------
/dev/src/SettingsIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
10 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [1.6.0](https://github.com/untemps/svelte-use-drop-outside/compare/v1.5.0...v1.6.0) (2022-09-12)
2 |
3 |
4 | ### Features
5 |
6 | * Add dragHandleCentered prop ([#20](https://github.com/untemps/svelte-use-drop-outside/issues/20)) ([7946033](https://github.com/untemps/svelte-use-drop-outside/commit/7946033933f27e971b010bf2314a5a18d694cbdc)), closes [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19) [#19](https://github.com/untemps/svelte-use-drop-outside/issues/19)
7 |
8 | # [1.5.0](https://github.com/untemps/svelte-use-drop-outside/compare/v1.4.0...v1.5.0) (2022-09-11)
9 |
10 |
11 | ### Features
12 |
13 | * Implement action update ([#18](https://github.com/untemps/svelte-use-drop-outside/issues/18)) ([4c88abc](https://github.com/untemps/svelte-use-drop-outside/commit/4c88abce71316502af9411f91beb0c05d8d5b35c))
14 |
15 | # [1.4.0](https://github.com/untemps/svelte-use-drop-outside/compare/v1.3.0...v1.4.0) (2022-09-06)
16 |
17 |
18 | ### Features
19 |
20 | * Animate drag cancellation and inside drop back ([#16](https://github.com/untemps/svelte-use-drop-outside/issues/16)) ([1195df8](https://github.com/untemps/svelte-use-drop-outside/commit/1195df83afddf68eef0cdd0261ee9db029471ac1))
21 |
22 | # [1.3.0](https://github.com/untemps/svelte-use-drop-outside/compare/v1.2.0...v1.3.0) (2022-08-23)
23 |
24 |
25 | ### Features
26 |
27 | * Add new dragClassName prop ([#12](https://github.com/untemps/svelte-use-drop-outside/issues/12)) ([3744468](https://github.com/untemps/svelte-use-drop-outside/commit/3744468d0a85e3018dafd87e53b6f3a33bc30db0))
28 |
29 | # [1.2.0](https://github.com/untemps/svelte-use-drop-outside/compare/v1.1.0...v1.2.0) (2022-07-31)
30 |
31 |
32 | ### Features
33 |
34 | * Add area to callbacks arguments ([#11](https://github.com/untemps/svelte-use-drop-outside/issues/11)) ([ff77cdc](https://github.com/untemps/svelte-use-drop-outside/commit/ff77cdc1fa03f6d54e9ab339b77ed233371f299e))
35 |
36 | # [1.1.0](https://github.com/untemps/svelte-use-drop-outside/compare/v1.0.1...v1.1.0) (2022-07-26)
37 |
38 |
39 | ### Features
40 |
41 | * Add callback for drag cancellation ([#5](https://github.com/untemps/svelte-use-drop-outside/issues/5)) ([1c8d62c](https://github.com/untemps/svelte-use-drop-outside/commit/1c8d62c8836d1333d9e9597785d6dcff7fadad2d))
42 |
43 | ## [1.0.1](https://github.com/untemps/svelte-use-drop-outside/compare/v1.0.0...v1.0.1) (2022-07-20)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * Trigger onDropOutside callback when target is dropped outside window boundaries ([#3](https://github.com/untemps/svelte-use-drop-outside/issues/3)) ([19497c5](https://github.com/untemps/svelte-use-drop-outside/commit/19497c56b0f1a9dc4d1833528c00404b1b7b1724))
49 |
50 | # 1.0.0 (2022-07-18)
51 |
52 |
53 | ### Features
54 |
55 | * Initial commit ([42e2b9d](https://github.com/untemps/svelte-use-drop-outside/commit/42e2b9dbdef675e79c69a19738b86be6c6e114ef))
56 |
--------------------------------------------------------------------------------
/dev/README.md:
--------------------------------------------------------------------------------
1 | *Psst — looking for a more complete solution? Check out [SvelteKit](https://kit.svelte.dev), the official framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.*
2 |
3 | *Looking for a shareable component template instead? You can [use SvelteKit for that as well](https://kit.svelte.dev/docs#packaging) or the older [sveltejs/component-template](https://github.com/sveltejs/component-template)*
4 |
5 | ---
6 |
7 | # svelte app
8 |
9 | This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
10 |
11 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
12 |
13 | ```bash
14 | npx degit sveltejs/template svelte-app
15 | cd svelte-app
16 | ```
17 |
18 | *Note that you will need to have [Node.js](https://nodejs.org) installed.*
19 |
20 |
21 | ## Get started
22 |
23 | Install the dependencies...
24 |
25 | ```bash
26 | cd svelte-app
27 | npm install
28 | ```
29 |
30 | ...then start [Rollup](https://rollupjs.org):
31 |
32 | ```bash
33 | npm run dev
34 | ```
35 |
36 | Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
37 |
38 | By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
39 |
40 | If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
41 |
42 | ## Building and running in production mode
43 |
44 | To create an optimised version of the app:
45 |
46 | ```bash
47 | npm run build
48 | ```
49 |
50 | You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
51 |
52 |
53 | ## Single-page app mode
54 |
55 | By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
56 |
57 | If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
58 |
59 | ```js
60 | "start": "sirv public --single"
61 | ```
62 |
63 | ## Using TypeScript
64 |
65 | This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
66 |
67 | ```bash
68 | node scripts/setupTypeScript.js
69 | ```
70 |
71 | Or remove the script via:
72 |
73 | ```bash
74 | rm scripts/setupTypeScript.js
75 | ```
76 |
77 | If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte).
78 |
79 | ## Deploying to the web
80 |
81 | ### With [Vercel](https://vercel.com)
82 |
83 | Install `vercel` if you haven't already:
84 |
85 | ```bash
86 | npm install -g vercel
87 | ```
88 |
89 | Then, from within your project folder:
90 |
91 | ```bash
92 | cd public
93 | vercel deploy --name my-project
94 | ```
95 |
96 | ### With [surge](https://surge.sh/)
97 |
98 | Install `surge` if you haven't already:
99 |
100 | ```bash
101 | npm install -g surge
102 | ```
103 |
104 | Then, from within your project folder:
105 |
106 | ```bash
107 | npm run build
108 | surge public my-project.surge.sh
109 | ```
110 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@untemps/svelte-use-drop-outside",
3 | "version": "1.6.0",
4 | "author": "Vincent Le Badezet ",
5 | "license": "MIT",
6 | "description": "Svelte action to drop an element outside an area",
7 | "keywords": [
8 | "drag",
9 | "drop",
10 | "dragndrop",
11 | "svelte",
12 | "svelte-action",
13 | "action",
14 | "javascript"
15 | ],
16 | "private": false,
17 | "repository": "https://github.com/untemps/svelte-use-drop-outside.git",
18 | "bugs": "https://github.com/untemps/svelte-use-drop-outside/issues",
19 | "publishConfig": {
20 | "access": "public"
21 | },
22 | "main": "dist/index.js",
23 | "module": "dist/index.es.js",
24 | "svelte": "dist/index.es.js",
25 | "files": [
26 | "dist"
27 | ],
28 | "devDependencies": {
29 | "@babel/cli": "^7.18.6",
30 | "@babel/core": "^7.18.6",
31 | "@babel/plugin-proposal-class-properties": "^7.18.6",
32 | "@babel/plugin-transform-runtime": "^7.18.6",
33 | "@babel/preset-env": "^7.18.6",
34 | "@commitlint/cli": "^17.0.3",
35 | "@commitlint/config-conventional": "^17.0.3",
36 | "@rollup/plugin-babel": "^5.3.1",
37 | "@rollup/plugin-commonjs": "^22.0.1",
38 | "@rollup/plugin-node-resolve": "^13.3.0",
39 | "@semantic-release/changelog": "^6.0.1",
40 | "@semantic-release/git": "^10.0.1",
41 | "@semantic-release/github": "^8.0.5",
42 | "@testing-library/dom": "^8.16.0",
43 | "@testing-library/jest-dom": "^5.16.4",
44 | "@testing-library/svelte": "^3.1.3",
45 | "babel-jest": "^28.1.3",
46 | "cross-env": "^7.0.3",
47 | "husky": "^8.0.1",
48 | "identity-obj-proxy": "^3.0.0",
49 | "jest": "^28.1.3",
50 | "jest-environment-jsdom": "^28.1.3",
51 | "postcss": "^8.4.16",
52 | "prettier": "^2.7.1",
53 | "prettier-plugin-svelte": "^2.7.0",
54 | "rimraf": "^3.0.2",
55 | "rollup": "^2.77.0",
56 | "rollup-plugin-postcss": "^4.0.2",
57 | "rollup-plugin-svelte": "^7.0.0",
58 | "rollup-plugin-terser": "^7.0.2",
59 | "rollup-plugin-visualizer": "^5.7.1",
60 | "semantic-release": "^19.0.3",
61 | "svelte-jester": "^2.3.2"
62 | },
63 | "dependencies": {
64 | "@untemps/dom-observer": "^2.0.0",
65 | "@untemps/utils": "^2.2.0",
66 | "svelte": "3.49.0"
67 | },
68 | "jest": {
69 | "testEnvironment": "jsdom",
70 | "transform": {
71 | "^.+\\.js$": "babel-jest",
72 | "^.+\\.svelte$": "svelte-jester"
73 | },
74 | "moduleNameMapper": {
75 | "\\.(css|less|scss)$": "identity-obj-proxy"
76 | },
77 | "moduleFileExtensions": [
78 | "js",
79 | "svelte"
80 | ],
81 | "setupFilesAfterEnv": [
82 | "/jest/jest.setup.js"
83 | ]
84 | },
85 | "release": {
86 | "branches": [
87 | "main",
88 | {
89 | "name": "beta",
90 | "prerelease": true
91 | }
92 | ],
93 | "plugins": [
94 | [
95 | "@semantic-release/commit-analyzer",
96 | {
97 | "releaseRules": [
98 | {
99 | "type": "chore",
100 | "scope": "force",
101 | "release": "patch"
102 | }
103 | ]
104 | }
105 | ],
106 | "@semantic-release/release-notes-generator",
107 | "@semantic-release/changelog",
108 | "@semantic-release/npm",
109 | "@semantic-release/git",
110 | [
111 | "@semantic-release/github",
112 | {
113 | "assets": [
114 | {
115 | "path": "dist/index.js",
116 | "label": "CJS distribution"
117 | },
118 | {
119 | "path": "dist/index.es.js",
120 | "label": "ES distribution"
121 | },
122 | {
123 | "path": "dist/index.umd.js",
124 | "label": "UMD distribution"
125 | }
126 | ]
127 | }
128 | ]
129 | ]
130 | },
131 | "scripts": {
132 | "dev": "cd dev && rimraf dist && yarn && yarn dev",
133 | "test": "jest -u --watch --coverage",
134 | "test:ci": "jest -u -b --ci --coverage",
135 | "build": "rimraf dist && yarn build:cjs && yarn build:es && yarn build:umd",
136 | "build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs rollup -c",
137 | "build:es": "cross-env NODE_ENV=production BABEL_ENV=es rollup -c",
138 | "build:umd": "cross-env NODE_ENV=production BABEL_ENV=umd rollup -c",
139 | "prettier": "prettier \"*/**/*.js\" --ignore-path ./.prettierignore --write && git add . && git status",
140 | "prepare": "husky install"
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/dev/src/App.svelte:
--------------------------------------------------------------------------------
1 |
48 |
49 |
156 |
157 |
158 | {#if showSettings}
159 |
160 | (showSettings = !showSettings)}>
161 |
162 |
163 |
182 |
183 | {/if}
184 |
185 |
186 |
(showSettings = !showSettings)}>
187 |
188 |
189 |
190 |
191 | {#each colors as color, index}
192 |
213 | {/each}
214 |
215 |
216 |
217 |
218 |
--------------------------------------------------------------------------------
/src/DragAndDrop.js:
--------------------------------------------------------------------------------
1 | import { DOMObserver } from '@untemps/dom-observer'
2 | import { doElementsOverlap } from '@untemps/utils/dom/doElementsOverlap'
3 | import { getCSSDeclaration } from '@untemps/utils/dom/getCSSDeclaration'
4 |
5 | import { resolveDragImage } from './utils/resolveDragImage'
6 |
7 | import './useDropOutside.css'
8 |
9 | class DragAndDrop {
10 | static instances = []
11 |
12 | #target = null
13 | #dragImage = null
14 | #dragClassName = null
15 | #animate = false
16 | #animateOptions = null
17 | #dragHandleCentered = false
18 | #onDropOutside = null
19 | #onDropInside = null
20 | #onDragCancel = null
21 |
22 | #observer = null
23 | #area = null
24 | #drag = null
25 | #holdX = 0
26 | #holdY = 0
27 | #dragWidth = 0
28 | #dragHeight = 0
29 |
30 | #boundMouseOverHandler = null
31 | #boundMouseOutHandler = null
32 | #boundMouseDownHandler = null
33 | #boundMouseMoveHandler = null
34 | #boundMouseUpHandler = null
35 |
36 | static destroy() {
37 | DragAndDrop.instances.forEach((instance) => {
38 | instance.destroy()
39 | })
40 | DragAndDrop.instances = []
41 | }
42 |
43 | constructor(
44 | target,
45 | areaSelector,
46 | dragImage,
47 | dragClassName,
48 | animate,
49 | animateOptions,
50 | dragHandleCentered,
51 | onDropOutside,
52 | onDropInside,
53 | onDragCancel
54 | ) {
55 | this.#target = target
56 | this.#dragImage = dragImage
57 | this.#dragClassName = dragClassName
58 | this.#animate = animate || false
59 | this.#animateOptions = { duration: 0.2, timingFunction: 'ease', ...(animateOptions || {}) }
60 | this.#dragHandleCentered = dragHandleCentered || false
61 | this.#onDropOutside = onDropOutside
62 | this.#onDropInside = onDropInside
63 | this.#onDragCancel = onDragCancel
64 |
65 | this.#area = document.querySelector(areaSelector)
66 |
67 | this.#drag = this.#createDrag()
68 |
69 | this.#boundMouseOverHandler = this.#onMouseOver.bind(this)
70 | this.#boundMouseOutHandler = this.#onMouseOut.bind(this)
71 | this.#boundMouseDownHandler = this.#onMouseDown.bind(this)
72 |
73 | this.#target.addEventListener('mouseover', this.#boundMouseOverHandler, false)
74 | this.#target.addEventListener('mouseout', this.#boundMouseOutHandler, false)
75 | this.#target.addEventListener('mousedown', this.#boundMouseDownHandler, false)
76 | this.#target.addEventListener('touchstart', this.#boundMouseDownHandler, false)
77 |
78 | DragAndDrop.instances.push(this)
79 | }
80 |
81 | update(
82 | areaSelector,
83 | dragImage,
84 | dragClassName,
85 | animate,
86 | animateOptions,
87 | dragHandleCentered,
88 | onDropOutside,
89 | onDropInside,
90 | onDragCancel
91 | ) {
92 | this.#dragImage = dragImage || this.#dragImage
93 | this.#dragClassName = dragClassName || this.#dragClassName
94 | this.#animate = animate !== undefined ? animate : this.#animate
95 | this.#animateOptions = animateOptions || this.#animateOptions
96 | this.#dragHandleCentered = dragHandleCentered !== undefined ? dragHandleCentered : this.#dragHandleCentered
97 | this.#onDropOutside = onDropOutside || this.#onDropOutside
98 | this.#onDropInside = onDropInside || this.#onDropInside
99 | this.#onDragCancel = onDragCancel || this.#onDragCancel
100 |
101 | this.#area = !!areaSelector ? document.querySelector(areaSelector) : this.#area
102 |
103 | this.#drag = this.#createDrag()
104 | }
105 |
106 | destroy() {
107 | this.#target.removeEventListener('mouseover', this.#boundMouseOverHandler)
108 | this.#target.removeEventListener('mouseout', this.#boundMouseOutHandler)
109 | this.#target.removeEventListener('mousedown', this.#boundMouseDownHandler)
110 | this.#target.removeEventListener('touchstart', this.#boundMouseDownHandler)
111 |
112 | this.#boundMouseOverHandler = null
113 | this.#boundMouseOutHandler = null
114 | this.#boundMouseDownHandler = null
115 |
116 | this.#observer?.clear()
117 | this.#observer = null
118 | }
119 |
120 | #createDrag() {
121 | const drag = this.#dragImage ? resolveDragImage(this.#dragImage) : this.#target.cloneNode(true)
122 | drag.setAttribute('draggable', false)
123 | drag.setAttribute('id', 'drag')
124 | drag.setAttribute('role', 'presentation')
125 | drag.classList.add('__drag')
126 | if (!!this.#dragClassName) {
127 | const cssText = getCSSDeclaration(this.#dragClassName, true)
128 | if (!!cssText) {
129 | drag.style.cssText = cssText
130 | }
131 | }
132 |
133 | this.#observer = new DOMObserver()
134 | this.#observer.wait(drag, null, { events: [DOMObserver.ADD] }).then(() => {
135 | const { width, height } = drag.getBoundingClientRect()
136 | this.#dragWidth = width
137 | this.#dragHeight = height
138 | })
139 |
140 | return drag
141 | }
142 |
143 | #animateBack(callback) {
144 | if (this.#animate) {
145 | const { width, height, left, top } = this.#target.getBoundingClientRect()
146 | this.#drag.style.setProperty(
147 | '--origin-x',
148 | left - (this.#dragHandleCentered ? (this.#dragWidth - width) >> 1 : 0) + 'px'
149 | )
150 | this.#drag.style.setProperty(
151 | '--origin-y',
152 | top - (this.#dragHandleCentered ? (this.#dragHeight - height) >> 1 : 0) + 'px'
153 | )
154 | this.#drag.style.animation = `move ${this.#animateOptions.duration}s ${this.#animateOptions.timingFunction}`
155 | this.#drag.addEventListener(
156 | 'animationend',
157 | () => {
158 | this.#drag.style.animation = 'none'
159 | this.#drag.remove()
160 | callback?.(this.#target, this.#area)
161 | },
162 | false
163 | )
164 | } else {
165 | this.#drag.remove()
166 | callback?.(this.#target, this.#area)
167 | }
168 | }
169 |
170 | #onMouseOver(e) {
171 | e.target.style.cursor = 'grab'
172 | }
173 |
174 | #onMouseOut(e) {
175 | e.target.style.cursor = 'default'
176 | }
177 |
178 | #onMouseMove(e) {
179 | if (this.#drag.style.visibility === 'hidden') {
180 | this.#drag.style.visibility = 'visible'
181 | }
182 |
183 | const pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX
184 | const pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY
185 |
186 | this.#drag.style.left = pageX - (this.#dragHandleCentered ? this.#dragWidth >> 1 : this.#holdX) + 'px'
187 | this.#drag.style.top = pageY - (this.#dragHandleCentered ? this.#dragHeight >> 1 : this.#holdY) + 'px'
188 | }
189 |
190 | #onMouseDown(e) {
191 | const clientX = e.type === 'touchstart' ? e.targetTouches[0].clientX : e.clientX
192 | const clientY = e.type === 'touchstart' ? e.targetTouches[0].clientY : e.clientY
193 | this.#holdX = clientX - this.#target.getBoundingClientRect().left
194 | this.#holdY = clientY - this.#target.getBoundingClientRect().top
195 |
196 | this.#drag.style.visibility = 'hidden'
197 | this.#drag.style.cursor = 'grabbing'
198 |
199 | this.#boundMouseMoveHandler = this.#onMouseMove.bind(this)
200 | this.#boundMouseUpHandler = this.#onMouseUp.bind(this)
201 |
202 | document.addEventListener('mousemove', this.#boundMouseMoveHandler, false)
203 | document.addEventListener('mouseup', this.#boundMouseUpHandler, false)
204 | document.addEventListener('touchmove', this.#boundMouseMoveHandler, false)
205 | document.addEventListener('keydown', this.#boundMouseUpHandler)
206 | this.#target.addEventListener('touchend', this.#boundMouseUpHandler, false)
207 | this.#target.addEventListener('touchcancel', this.#boundMouseUpHandler, false)
208 |
209 | this.#target.parentNode.appendChild(this.#drag)
210 | }
211 |
212 | #onMouseUp(e) {
213 | if (e.type.startsWith('key') && e.key !== 'Escape') {
214 | return
215 | }
216 |
217 | document.removeEventListener('mousemove', this.#boundMouseMoveHandler)
218 | document.removeEventListener('mouseup', this.#boundMouseUpHandler)
219 | document.removeEventListener('touchmove', this.#boundMouseMoveHandler)
220 | document.removeEventListener('keydown', this.#boundMouseUpHandler)
221 | this.#target.removeEventListener('touchend', this.#boundMouseUpHandler)
222 | this.#target.removeEventListener('touchcancel', this.#boundMouseUpHandler)
223 |
224 | this.#boundMouseMoveHandler = null
225 | this.#boundMouseUpHandler = null
226 |
227 | const doOverlap = doElementsOverlap(this.#area, this.#drag)
228 |
229 | if (e.type.startsWith('key')) {
230 | this.#animateBack(this.#onDragCancel)
231 | } else if (doOverlap) {
232 | this.#animateBack(this.#onDropInside)
233 | } else {
234 | this.#drag.remove()
235 | this.#onDropOutside?.(this.#target, this.#area)
236 | }
237 | }
238 | }
239 |
240 | export default DragAndDrop
241 |
--------------------------------------------------------------------------------
/src/__tests__/useDropOutside.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @jest-environment jsdom
3 | */
4 |
5 | import { fireEvent, screen } from '@testing-library/dom'
6 |
7 | import { createElement } from '@untemps/utils/dom/createElement'
8 | import { getElement } from '@untemps/utils/dom/getElement'
9 |
10 | import DragAndDrop from '../DragAndDrop'
11 | import useDropOutside from '../useDropOutside'
12 |
13 | const areaSize = 200
14 | const targetSize = 100
15 |
16 | const createStyle = () => {
17 | createElement({
18 | tag: 'style',
19 | textContent: `
20 | .gag {
21 | background-color: black;
22 | }
23 | .pol {
24 | background-color: red;
25 | }
26 | `,
27 | parent: document.body,
28 | })
29 | }
30 |
31 | const createArea = (id) => {
32 | const el = createElement({
33 | tag: 'div',
34 | attributes: { id, class: 'foo', style: `width: ${areaSize}; height: ${areaSize};` },
35 | parent: document.body,
36 | })
37 | el.getBoundingClientRect = () => ({
38 | width: areaSize,
39 | height: areaSize,
40 | top: 0,
41 | left: 0,
42 | right: areaSize,
43 | bottom: areaSize,
44 | })
45 | return el
46 | }
47 |
48 | const createTarget = (id, parent) => {
49 | return createElement({
50 | tag: 'div',
51 | attributes: { id, class: 'bar', style: `width: ${targetSize}; height: ${targetSize};` },
52 | parent,
53 | })
54 | }
55 |
56 | describe('useDropOutside', () => {
57 | let area,
58 | target,
59 | options = null
60 |
61 | let action = null
62 |
63 | beforeEach(() => {
64 | createStyle()
65 | area = createArea('area')
66 | target = createTarget('target', area)
67 | options = {
68 | areaSelector: '#area',
69 | }
70 | })
71 |
72 | afterEach(() => {
73 | area = null
74 | target = null
75 | options = null
76 |
77 | fireEvent.mouseUp(document)
78 |
79 | document.body.innerHTML = ''
80 |
81 | action?.destroy()
82 |
83 | DragAndDrop.destroy()
84 | })
85 |
86 | describe('init', () => {
87 | it('Sets pointer to grab on mouseover', async () => {
88 | action = useDropOutside(target, options)
89 |
90 | fireEvent.mouseOver(target)
91 |
92 | expect(target.style.cursor).toBe('grab')
93 | })
94 |
95 | it('Sets pointer to default on mouseout', async () => {
96 | action = useDropOutside(target, options)
97 |
98 | fireEvent.mouseOver(target)
99 | fireEvent.mouseOut(target)
100 |
101 | expect(target.style.cursor).toBe('default')
102 | })
103 |
104 | it('Sets pointer to grabbing on mousedown', async () => {
105 | action = useDropOutside(target, options)
106 |
107 | fireEvent.mouseDown(target)
108 | fireEvent.mouseMove(document)
109 |
110 | const drag = getElement('#drag')
111 |
112 | expect(drag.style.cursor).toBe('grabbing')
113 | })
114 |
115 | it('Removes dragged element on mouseup', async () => {
116 | action = useDropOutside(target, options)
117 |
118 | fireEvent.mouseDown(target)
119 | fireEvent.mouseMove(document)
120 |
121 | const drag = getElement('#drag')
122 |
123 | expect(drag).toBeInTheDocument()
124 |
125 | fireEvent.mouseUp(document)
126 |
127 | expect(drag).not.toBeInTheDocument()
128 | })
129 |
130 | it('Triggers onDropInside callback', async () => {
131 | const onDropInside = jest.fn()
132 | action = useDropOutside(target, { ...options, animate: true, onDropInside })
133 |
134 | fireEvent.touchStart(target, { targetTouches: [{ pageX: 10, pageY: 10 }] })
135 | fireEvent.touchMove(document, { targetTouches: [{ pageX: 10, pageY: 10 }] })
136 | fireEvent.touchMove(document, { targetTouches: [{ pageX: 10, pageY: 10 }] }) // Duplicate on purpose
137 |
138 | const drag = document.querySelector('#drag')
139 | drag.getBoundingClientRect = () => ({
140 | width: targetSize,
141 | height: targetSize,
142 | top: 0,
143 | left: 0,
144 | right: targetSize,
145 | bottom: targetSize,
146 | })
147 |
148 | fireEvent.mouseUp(document)
149 | fireEvent.animationEnd(screen.getByRole('presentation'))
150 |
151 | expect(onDropInside).toHaveBeenCalled()
152 | })
153 |
154 | it('Triggers onDropInside callback on update', async () => {
155 | const onDropInside = jest.fn()
156 | const onDropInsideRepl = jest.fn()
157 | action = useDropOutside(target, { ...options, onDropInside })
158 | action.update({ onDropInside: onDropInsideRepl })
159 |
160 | fireEvent.touchStart(target, { targetTouches: [{ pageX: 10, pageY: 10 }] })
161 | fireEvent.touchMove(document, { targetTouches: [{ pageX: 10, pageY: 10 }] })
162 | fireEvent.touchMove(document, { targetTouches: [{ pageX: 10, pageY: 10 }] }) // Duplicate on purpose
163 |
164 | const drag = document.querySelector('#drag')
165 | drag.getBoundingClientRect = () => ({
166 | width: targetSize,
167 | height: targetSize,
168 | top: 0,
169 | left: 0,
170 | right: targetSize,
171 | bottom: targetSize,
172 | })
173 |
174 | fireEvent.mouseUp(document)
175 |
176 | expect(onDropInsideRepl).toHaveBeenCalled()
177 | })
178 |
179 | it('Triggers onDropOutside callback', async () => {
180 | const onDropOutside = jest.fn()
181 | action = useDropOutside(target, { ...options, onDropOutside })
182 |
183 | fireEvent.mouseDown(target)
184 | fireEvent.mouseMove(document)
185 |
186 | const drag = document.querySelector('#drag')
187 | drag.getBoundingClientRect = () => ({
188 | width: targetSize,
189 | height: targetSize,
190 | top: areaSize + 10,
191 | left: areaSize + 10,
192 | right: areaSize + 10 + targetSize,
193 | bottom: areaSize + 10 + targetSize,
194 | })
195 |
196 | fireEvent.mouseUp(document)
197 |
198 | expect(onDropOutside).toHaveBeenCalled()
199 | })
200 |
201 | it('Triggers onDropOutside callback on update', async () => {
202 | const onDropOutside = jest.fn()
203 | const onDropOutsideRepl = jest.fn()
204 | action = useDropOutside(target, { ...options, onDropOutside })
205 | action.update({ onDropOutside: onDropOutsideRepl })
206 |
207 | fireEvent.mouseDown(target)
208 | fireEvent.mouseMove(document)
209 |
210 | const drag = document.querySelector('#drag')
211 | drag.getBoundingClientRect = () => ({
212 | width: targetSize,
213 | height: targetSize,
214 | top: areaSize + 10,
215 | left: areaSize + 10,
216 | right: areaSize + 10 + targetSize,
217 | bottom: areaSize + 10 + targetSize,
218 | })
219 |
220 | fireEvent.mouseUp(document)
221 |
222 | expect(onDropOutsideRepl).toHaveBeenCalled()
223 | })
224 |
225 | it('Triggers onDragCancel callback', async () => {
226 | const onDragCancel = jest.fn()
227 | action = useDropOutside(target, { ...options, animate: true, onDragCancel })
228 |
229 | fireEvent.mouseDown(target)
230 | fireEvent.mouseMove(document)
231 | fireEvent.keyDown(document, { key: 'A', code: 'A' })
232 | fireEvent.keyDown(document, { key: 'Escape', code: 'Esc' })
233 | fireEvent.animationEnd(screen.getByRole('presentation'))
234 |
235 | expect(onDragCancel).toHaveBeenCalled()
236 | })
237 |
238 | it('Triggers onDragCancel callback on update', async () => {
239 | const onDragCancel = jest.fn()
240 | const onDragCancelRepl = jest.fn()
241 | action = useDropOutside(target, { ...options, animate: true, onDragCancel })
242 | action.update({ animate: false, onDragCancel: onDragCancelRepl })
243 |
244 | fireEvent.mouseDown(target)
245 | fireEvent.mouseMove(document)
246 | fireEvent.keyDown(document, { key: 'A', code: 'A' })
247 | fireEvent.keyDown(document, { key: 'Escape', code: 'Esc' })
248 |
249 | expect(onDragCancelRepl).toHaveBeenCalled()
250 | })
251 |
252 | it('Sets custom class to dragged element', async () => {
253 | action = useDropOutside(target, { ...options, dragClassName: 'gag' })
254 |
255 | fireEvent.mouseDown(target)
256 | fireEvent.mouseMove(document)
257 |
258 | expect(screen.getByRole('presentation')).toBeInTheDocument()
259 | expect(screen.getByRole('presentation')).toHaveStyle('background-color: black;')
260 | })
261 |
262 | it('Sets custom class to dragged element on update', async () => {
263 | action = useDropOutside(target, { ...options, dragClassName: 'gag' })
264 | action.update({ dragClassName: 'pol' })
265 |
266 | fireEvent.mouseDown(target)
267 | fireEvent.mouseMove(document)
268 |
269 | expect(screen.getByRole('presentation')).toBeInTheDocument()
270 | expect(screen.getByRole('presentation')).toHaveStyle('background-color: red;')
271 | })
272 |
273 | it('Sets unknown custom class to dragged element', async () => {
274 | action = useDropOutside(target, { ...options, dragClassName: 'sur' })
275 |
276 | fireEvent.mouseDown(target)
277 | fireEvent.mouseMove(document)
278 |
279 | expect(screen.getByRole('presentation')).toBeInTheDocument()
280 | expect(screen.getByRole('presentation')).not.toHaveStyle('background-color: black;')
281 | expect(screen.getByRole('presentation')).not.toHaveStyle('background-color: red;')
282 | })
283 |
284 | it('Sets drag image', async () => {
285 | const dragImage = createElement({ tag: 'img', attributes: { src: 'foo', alt: 'bar' } })
286 | action = useDropOutside(target, { ...options, dragImage, dragHandleCentered: true })
287 |
288 | fireEvent.mouseDown(target)
289 | fireEvent.mouseMove(document)
290 |
291 | expect(screen.getByAltText('bar')).toBeInTheDocument()
292 | })
293 |
294 | it('Sets drag image on update', async () => {
295 | const dragImage = createElement({ tag: 'img', attributes: { src: 'foo', alt: 'bar' } })
296 | const dragImageRepl = createElement({ tag: 'img', attributes: { src: 'bar', alt: 'foo' } })
297 | action = useDropOutside(target, { ...options, dragImage })
298 | action.update({ dragImage: dragImageRepl, dragHandleCentered: false })
299 |
300 | fireEvent.mouseDown(target)
301 | fireEvent.mouseMove(document)
302 |
303 | expect(screen.getByAltText('foo')).toBeInTheDocument()
304 | })
305 |
306 | it('Stores and clears instances in static class property', async () => {
307 | useDropOutside(target, options)
308 | useDropOutside(target, options)
309 | useDropOutside(target, options)
310 |
311 | expect(DragAndDrop.instances).toHaveLength(3)
312 |
313 | DragAndDrop.destroy()
314 |
315 | expect(DragAndDrop.instances).toHaveLength(0)
316 | })
317 | })
318 | })
319 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | svelte-use-drop-outside
6 |
7 |
8 | Svelte action to drop an element outside an area and more...
9 |
10 |
11 | [](https://www.npmjs.com/package/@untemps/svelte-use-drop-outside)
12 | [](https://github.com/untemps/svelte-use-drop-outside/actions)
13 | [](https://codecov.io/gh/untemps/svelte-use-drop-outside)
14 |
15 | ## Demo
16 |
17 |
18 | :red_circle: LIVE DEMO :red_circle:
19 |
20 |
21 | ## Installation
22 |
23 | ```bash
24 | yarn add @untemps/svelte-use-drop-outside
25 | ```
26 |
27 | ## Usage
28 |
29 | ### Basic usage
30 |
31 | ```svelte
32 |
39 |
40 |
41 |
42 |
43 |
51 | Drag me outside the white area
52 |
53 |
54 |
55 |
56 |
57 |
96 | ```
97 |
98 | ## API
99 |
100 | | Props | Type | Default | Description |
101 | |----------------------|-----------------------------|------------------------------------------|----------------------------------------------------------------------------------------|
102 | | `areaSelector` | string | null | Selector of the element considered as the "inside" area. |
103 | | `dragImage` | element or object or string | null | The image used when the element is dragging. |
104 | | `dragClassName` | string | null | A class name that will be assigned to the dragged element. |
105 | | `animate` | boolean | false | A flag to enable animation back. |
106 | | `animateOptions` | object | { duration: .2, timingFunction: 'ease' } | Optional options for the animation back (see [Animation Options](#animation-options)). |
107 | | `dragHandleCentered` | boolean | false | A flag to handle the dragged element by its center. |
108 | | `onDropOutside` | function | null | Callback triggered when the dragged element is dropped outside the area. |
109 | | `onDropInside` | function | null | Callback triggered when the dragged element is dropped inside the area |
110 | | `onDragCancel` | function | null | Callback triggered when the drag is cancelled (Esc key) |
111 |
112 | ### Area Selector
113 |
114 | You can define the DOM element which will be treated as the "inside" area by passing the [selector](https://developer.mozilla.org/fr/docs/Web/API/Document/querySelector) of this element.
115 |
116 | When dropping the dragged element, the action reconciles the boundaries of this element with the boundaries of the area to assert inside/outside stuff.
117 |
118 | When pressing the `Escape` key, wherever the dragged element is, it is put back to its original position.
119 |
120 | ### Drag Image
121 |
122 | By default, the action clones the target element and sets its opacity to `0.7`.
123 |
124 | Alternately, you may use the `dragImage` prop to customize the image displayed during the drag.
125 |
126 | The `dragImage` prop may be:
127 |
128 | #### A DOM element such a ` ` or a ``:
129 |
130 | ```svelte
131 |
132 |
133 |
134 |
142 | Drag me outside the white area
143 |
144 |
145 |
146 |
147 |
148 | ```
149 |
150 | #### An object with 3 properties:
151 |
152 | | Props | Description |
153 | |----------|---------------------------------|
154 | | `src` | Path of the image. |
155 | | `width` | Width of the image (optional). |
156 | | `height` | Height of the image (optional). |
157 |
158 | ```svelte
159 |
160 |
161 |
162 |
174 | Drag me outside the white area
175 |
176 |
177 |
178 |
179 | ```
180 |
181 | #### A string as path of the image:
182 |
183 | ```svelte
184 |
185 |
186 |
187 |
195 | Drag me outside the white area
196 |
197 |
198 |
199 |
200 | ```
201 |
202 | ### Drag styles
203 |
204 | You may assign a class to the dragged element to customize its display, whether it is a clone of the target element or it is an image, by using the `dragClassName` prop.
205 |
206 | The class declaration will be parsed and set to the `style` attribute of the dragged element to avoid priority issues. Thus, you are guaranteed your custom styles override the previous values.
207 |
208 | > Please note the class has to be global
209 |
210 | ```svelte
211 |
212 |
213 |
214 |
222 | Drag me outside the white area
223 |
224 |
225 |
226 |
227 |
228 |
238 | ```
239 |
240 | ### Animation
241 |
242 | By default, when the dragged element is dropped inside the area or if the drag is cancelled, the dragged element is plainly removed.
243 |
244 | When setting the `animate` to `true`, when those events happen, the dragged element is smoothly moved back to its original position.
245 |
246 | #### Animation Options
247 |
248 | The animation can be configured through the `animateOptions` prop:
249 |
250 | | Argument | Type | Default | Description |
251 | |----------------|--------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
252 | | duration | number | .2 | Duration of the animation (in seconds). |
253 | | timingFunction | string | 'ease' | Function that defines the animation effect (see [animation-timing-function](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function)). |
254 |
255 | ### Center Drag Handle
256 |
257 | In some cases, usually when you customize the dragged element, through the `dragImage` or the `dragClassName` prop, you may want to center the dragged element under the pointer when moving to avoid weird behaviours.
258 | Same regarding the position the dragged element has to move back when it is dropped.
259 |
260 | The `dragHandleCentered` prop allows to control the way the dragged element is handled:
261 |
262 | - If `true`, the center point the dragged element will be used.
263 | - If `false`, the top left point of the dragged element will be used.
264 |
265 | ### Callbacks
266 |
267 | All callbacks are triggered with the following arguments:
268 |
269 | | Argument | Description |
270 | |----------|------------------------------------------|
271 | | [0] | Dragged element. |
272 | | [1] | Element considered as the "inside" area. |
273 |
274 | ```javascript
275 | const _onDropOutside = (node, area) => {
276 | console.log(`You\'ve just dropped #${node.id} outside the #${area.id}`)
277 | }
278 |
279 | const _onDropInside = (node, area) => {
280 | console.log(`You\'ve just dropped #${node.id} inside the #${area.id}`)
281 | }
282 |
283 | const _onDragCancel = (node, area) => {
284 | console.log(`You\'ve just cancelled the drag of #${node.id} against #${area.id} boundaries`)
285 | }
286 | ```
287 |
288 | ## Recipes
289 |
290 | ### Switching Container
291 |
292 | You may use the action to implement a classic drag and drop container switch using the `onDropInside` callback:
293 |
294 |
295 |
296 |
297 |
298 | ```svelte
299 |
306 |
307 |
308 |
309 |
310 |
318 | Drag me into the second area
319 |
320 |
321 |
322 |
323 |
324 |
325 |
364 |
365 | ```
366 |
367 | ## Development
368 |
369 | The action can be served for development purpose on `http://localhost:5000/` running:
370 |
371 | ```bash
372 | yarn dev
373 | ```
374 |
375 | ## Contributing
376 |
377 | Contributions are warmly welcomed:
378 |
379 | - Fork the repository
380 | - Create a feature branch
381 | - Develop the feature AND write the tests (or write the tests AND develop the feature)
382 | - Commit your changes
383 | using [Angular Git Commit Guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines)
384 | - Submit a Pull Request
385 |
--------------------------------------------------------------------------------
/dev/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/code-frame@^7.10.4":
6 | version "7.15.8"
7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503"
8 | integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==
9 | dependencies:
10 | "@babel/highlight" "^7.14.5"
11 |
12 | "@babel/helper-validator-identifier@^7.14.5":
13 | version "7.15.7"
14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
15 | integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
16 |
17 | "@babel/highlight@^7.14.5":
18 | version "7.14.5"
19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
20 | integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
21 | dependencies:
22 | "@babel/helper-validator-identifier" "^7.14.5"
23 | chalk "^2.0.0"
24 | js-tokens "^4.0.0"
25 |
26 | "@polka/url@^1.0.0-next.20":
27 | version "1.0.0-next.21"
28 | resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
29 | integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
30 |
31 | "@rollup/plugin-commonjs@^17.0.0":
32 | version "17.1.0"
33 | resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz#757ec88737dffa8aa913eb392fade2e45aef2a2d"
34 | integrity sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==
35 | dependencies:
36 | "@rollup/pluginutils" "^3.1.0"
37 | commondir "^1.0.1"
38 | estree-walker "^2.0.1"
39 | glob "^7.1.6"
40 | is-reference "^1.2.1"
41 | magic-string "^0.25.7"
42 | resolve "^1.17.0"
43 |
44 | "@rollup/plugin-node-resolve@^11.0.0":
45 | version "11.2.1"
46 | resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60"
47 | integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==
48 | dependencies:
49 | "@rollup/pluginutils" "^3.1.0"
50 | "@types/resolve" "1.17.1"
51 | builtin-modules "^3.1.0"
52 | deepmerge "^4.2.2"
53 | is-module "^1.0.0"
54 | resolve "^1.19.0"
55 |
56 | "@rollup/pluginutils@4":
57 | version "4.1.1"
58 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec"
59 | integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==
60 | dependencies:
61 | estree-walker "^2.0.1"
62 | picomatch "^2.2.2"
63 |
64 | "@rollup/pluginutils@^3.1.0":
65 | version "3.1.0"
66 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
67 | integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
68 | dependencies:
69 | "@types/estree" "0.0.39"
70 | estree-walker "^1.0.1"
71 | picomatch "^2.2.2"
72 |
73 | "@types/estree@*":
74 | version "0.0.50"
75 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
76 | integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
77 |
78 | "@types/estree@0.0.39":
79 | version "0.0.39"
80 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
81 | integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
82 |
83 | "@types/node@*":
84 | version "16.11.1"
85 | resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.1.tgz#2e50a649a50fc403433a14f829eface1a3443e97"
86 | integrity sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==
87 |
88 | "@types/resolve@1.17.1":
89 | version "1.17.1"
90 | resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
91 | integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
92 | dependencies:
93 | "@types/node" "*"
94 |
95 | ansi-styles@^3.2.1:
96 | version "3.2.1"
97 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
98 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
99 | dependencies:
100 | color-convert "^1.9.0"
101 |
102 | anymatch@~3.1.2:
103 | version "3.1.2"
104 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
105 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
106 | dependencies:
107 | normalize-path "^3.0.0"
108 | picomatch "^2.0.4"
109 |
110 | balanced-match@^1.0.0:
111 | version "1.0.2"
112 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
113 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
114 |
115 | binary-extensions@^2.0.0:
116 | version "2.2.0"
117 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
118 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
119 |
120 | brace-expansion@^1.1.7:
121 | version "1.1.11"
122 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
123 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
124 | dependencies:
125 | balanced-match "^1.0.0"
126 | concat-map "0.0.1"
127 |
128 | braces@~3.0.2:
129 | version "3.0.2"
130 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
131 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
132 | dependencies:
133 | fill-range "^7.0.1"
134 |
135 | buffer-from@^1.0.0:
136 | version "1.1.2"
137 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
138 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
139 |
140 | builtin-modules@^3.1.0:
141 | version "3.2.0"
142 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"
143 | integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==
144 |
145 | chalk@^2.0.0:
146 | version "2.4.2"
147 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
148 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
149 | dependencies:
150 | ansi-styles "^3.2.1"
151 | escape-string-regexp "^1.0.5"
152 | supports-color "^5.3.0"
153 |
154 | chokidar@^3.5.0:
155 | version "3.5.2"
156 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
157 | integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
158 | dependencies:
159 | anymatch "~3.1.2"
160 | braces "~3.0.2"
161 | glob-parent "~5.1.2"
162 | is-binary-path "~2.1.0"
163 | is-glob "~4.0.1"
164 | normalize-path "~3.0.0"
165 | readdirp "~3.6.0"
166 | optionalDependencies:
167 | fsevents "~2.3.2"
168 |
169 | color-convert@^1.9.0:
170 | version "1.9.3"
171 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
172 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
173 | dependencies:
174 | color-name "1.1.3"
175 |
176 | color-name@1.1.3:
177 | version "1.1.3"
178 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
179 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
180 |
181 | commander@^2.20.0:
182 | version "2.20.3"
183 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
184 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
185 |
186 | commondir@^1.0.1:
187 | version "1.0.1"
188 | resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
189 | integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
190 |
191 | concat-map@0.0.1:
192 | version "0.0.1"
193 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
194 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
195 |
196 | console-clear@^1.1.0:
197 | version "1.1.1"
198 | resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7"
199 | integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==
200 |
201 | deepmerge@^4.2.2:
202 | version "4.2.2"
203 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
204 | integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
205 |
206 | escape-string-regexp@^1.0.5:
207 | version "1.0.5"
208 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
209 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
210 |
211 | estree-walker@^0.6.1:
212 | version "0.6.1"
213 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
214 | integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
215 |
216 | estree-walker@^1.0.1:
217 | version "1.0.1"
218 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
219 | integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
220 |
221 | estree-walker@^2.0.1:
222 | version "2.0.2"
223 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
224 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
225 |
226 | fill-range@^7.0.1:
227 | version "7.0.1"
228 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
229 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
230 | dependencies:
231 | to-regex-range "^5.0.1"
232 |
233 | fs.realpath@^1.0.0:
234 | version "1.0.0"
235 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
236 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
237 |
238 | fsevents@~2.3.2:
239 | version "2.3.2"
240 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
241 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
242 |
243 | function-bind@^1.1.1:
244 | version "1.1.1"
245 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
246 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
247 |
248 | get-port@^3.2.0:
249 | version "3.2.0"
250 | resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
251 | integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=
252 |
253 | glob-parent@~5.1.2:
254 | version "5.1.2"
255 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
256 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
257 | dependencies:
258 | is-glob "^4.0.1"
259 |
260 | glob@^7.1.6:
261 | version "7.2.0"
262 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
263 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
264 | dependencies:
265 | fs.realpath "^1.0.0"
266 | inflight "^1.0.4"
267 | inherits "2"
268 | minimatch "^3.0.4"
269 | once "^1.3.0"
270 | path-is-absolute "^1.0.0"
271 |
272 | has-flag@^3.0.0:
273 | version "3.0.0"
274 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
275 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
276 |
277 | has-flag@^4.0.0:
278 | version "4.0.0"
279 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
280 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
281 |
282 | has@^1.0.3:
283 | version "1.0.3"
284 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
285 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
286 | dependencies:
287 | function-bind "^1.1.1"
288 |
289 | inflight@^1.0.4:
290 | version "1.0.6"
291 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
292 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
293 | dependencies:
294 | once "^1.3.0"
295 | wrappy "1"
296 |
297 | inherits@2:
298 | version "2.0.4"
299 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
300 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
301 |
302 | is-binary-path@~2.1.0:
303 | version "2.1.0"
304 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
305 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
306 | dependencies:
307 | binary-extensions "^2.0.0"
308 |
309 | is-core-module@^2.2.0:
310 | version "2.8.0"
311 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
312 | integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
313 | dependencies:
314 | has "^1.0.3"
315 |
316 | is-extglob@^2.1.1:
317 | version "2.1.1"
318 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
319 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
320 |
321 | is-glob@^4.0.1, is-glob@~4.0.1:
322 | version "4.0.3"
323 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
324 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
325 | dependencies:
326 | is-extglob "^2.1.1"
327 |
328 | is-module@^1.0.0:
329 | version "1.0.0"
330 | resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
331 | integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
332 |
333 | is-number@^7.0.0:
334 | version "7.0.0"
335 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
336 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
337 |
338 | is-reference@^1.2.1:
339 | version "1.2.1"
340 | resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
341 | integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
342 | dependencies:
343 | "@types/estree" "*"
344 |
345 | jest-worker@^26.2.1:
346 | version "26.6.2"
347 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
348 | integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
349 | dependencies:
350 | "@types/node" "*"
351 | merge-stream "^2.0.0"
352 | supports-color "^7.0.0"
353 |
354 | js-tokens@^4.0.0:
355 | version "4.0.0"
356 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
357 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
358 |
359 | kleur@^3.0.0:
360 | version "3.0.3"
361 | resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
362 | integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
363 |
364 | livereload-js@^3.3.1:
365 | version "3.3.2"
366 | resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.3.2.tgz#c88b009c6e466b15b91faa26fd7c99d620e12651"
367 | integrity sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==
368 |
369 | livereload@^0.9.1:
370 | version "0.9.3"
371 | resolved "https://registry.yarnpkg.com/livereload/-/livereload-0.9.3.tgz#a714816375ed52471408bede8b49b2ee6a0c55b1"
372 | integrity sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==
373 | dependencies:
374 | chokidar "^3.5.0"
375 | livereload-js "^3.3.1"
376 | opts ">= 1.2.0"
377 | ws "^7.4.3"
378 |
379 | local-access@^1.0.1:
380 | version "1.1.0"
381 | resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.1.0.tgz#e007c76ba2ca83d5877ba1a125fc8dfe23ba4798"
382 | integrity sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==
383 |
384 | magic-string@^0.25.7:
385 | version "0.25.7"
386 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
387 | integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
388 | dependencies:
389 | sourcemap-codec "^1.4.4"
390 |
391 | merge-stream@^2.0.0:
392 | version "2.0.0"
393 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
394 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
395 |
396 | mime@^2.3.1:
397 | version "2.5.2"
398 | resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
399 | integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
400 |
401 | minimatch@^3.0.4:
402 | version "3.0.4"
403 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
404 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
405 | dependencies:
406 | brace-expansion "^1.1.7"
407 |
408 | mri@^1.1.0:
409 | version "1.2.0"
410 | resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
411 | integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
412 |
413 | normalize-path@^3.0.0, normalize-path@~3.0.0:
414 | version "3.0.0"
415 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
416 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
417 |
418 | once@^1.3.0:
419 | version "1.4.0"
420 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
421 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
422 | dependencies:
423 | wrappy "1"
424 |
425 | "opts@>= 1.2.0":
426 | version "2.0.2"
427 | resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1"
428 | integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==
429 |
430 | path-is-absolute@^1.0.0:
431 | version "1.0.1"
432 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
433 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
434 |
435 | path-parse@^1.0.6:
436 | version "1.0.7"
437 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
438 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
439 |
440 | picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2:
441 | version "2.3.0"
442 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
443 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
444 |
445 | randombytes@^2.1.0:
446 | version "2.1.0"
447 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
448 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
449 | dependencies:
450 | safe-buffer "^5.1.0"
451 |
452 | readdirp@~3.6.0:
453 | version "3.6.0"
454 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
455 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
456 | dependencies:
457 | picomatch "^2.2.1"
458 |
459 | require-relative@^0.8.7:
460 | version "0.8.7"
461 | resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
462 | integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
463 |
464 | resolve@^1.17.0, resolve@^1.19.0:
465 | version "1.20.0"
466 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
467 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
468 | dependencies:
469 | is-core-module "^2.2.0"
470 | path-parse "^1.0.6"
471 |
472 | rollup-plugin-css-only@^3.1.0:
473 | version "3.1.0"
474 | resolved "https://registry.yarnpkg.com/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz#6a701cc5b051c6b3f0961e69b108a9a118e1b1df"
475 | integrity sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==
476 | dependencies:
477 | "@rollup/pluginutils" "4"
478 |
479 | rollup-plugin-livereload@^2.0.0:
480 | version "2.0.5"
481 | resolved "https://registry.yarnpkg.com/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz#4747fa292a2cceb0c972c573d71b3d66b4252b37"
482 | integrity sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==
483 | dependencies:
484 | livereload "^0.9.1"
485 |
486 | rollup-plugin-svelte@^7.0.0:
487 | version "7.1.0"
488 | resolved "https://registry.yarnpkg.com/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz#d45f2b92b1014be4eb46b55aa033fb9a9c65f04d"
489 | integrity sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==
490 | dependencies:
491 | require-relative "^0.8.7"
492 | rollup-pluginutils "^2.8.2"
493 |
494 | rollup-plugin-terser@^7.0.0:
495 | version "7.0.2"
496 | resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d"
497 | integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==
498 | dependencies:
499 | "@babel/code-frame" "^7.10.4"
500 | jest-worker "^26.2.1"
501 | serialize-javascript "^4.0.0"
502 | terser "^5.0.0"
503 |
504 | rollup-pluginutils@^2.8.2:
505 | version "2.8.2"
506 | resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
507 | integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
508 | dependencies:
509 | estree-walker "^0.6.1"
510 |
511 | rollup@^2.3.4:
512 | version "2.58.0"
513 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.58.0.tgz#a643983365e7bf7f5b7c62a8331b983b7c4c67fb"
514 | integrity sha512-NOXpusKnaRpbS7ZVSzcEXqxcLDOagN6iFS8p45RkoiMqPHDLwJm758UF05KlMoCRbLBTZsPOIa887gZJ1AiXvw==
515 | optionalDependencies:
516 | fsevents "~2.3.2"
517 |
518 | sade@^1.6.0:
519 | version "1.7.4"
520 | resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691"
521 | integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==
522 | dependencies:
523 | mri "^1.1.0"
524 |
525 | safe-buffer@^5.1.0:
526 | version "5.2.1"
527 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
528 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
529 |
530 | semiver@^1.0.0:
531 | version "1.1.0"
532 | resolved "https://registry.yarnpkg.com/semiver/-/semiver-1.1.0.tgz#9c97fb02c21c7ce4fcf1b73e2c7a24324bdddd5f"
533 | integrity sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==
534 |
535 | serialize-javascript@^4.0.0:
536 | version "4.0.0"
537 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
538 | integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
539 | dependencies:
540 | randombytes "^2.1.0"
541 |
542 | sirv-cli@^1.0.0:
543 | version "1.0.14"
544 | resolved "https://registry.yarnpkg.com/sirv-cli/-/sirv-cli-1.0.14.tgz#4bc60421b3de9caea80ccd292b5004aca4ce3c81"
545 | integrity sha512-yyUTNr984ANKDloqepkYbBSqvx3buwYg2sQKPWjSU+IBia5loaoka2If8N9CMwt8AfP179cdEl7kYJ//iWJHjQ==
546 | dependencies:
547 | console-clear "^1.1.0"
548 | get-port "^3.2.0"
549 | kleur "^3.0.0"
550 | local-access "^1.0.1"
551 | sade "^1.6.0"
552 | semiver "^1.0.0"
553 | sirv "^1.0.13"
554 | tinydate "^1.0.0"
555 |
556 | sirv@^1.0.13:
557 | version "1.0.18"
558 | resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899"
559 | integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA==
560 | dependencies:
561 | "@polka/url" "^1.0.0-next.20"
562 | mime "^2.3.1"
563 | totalist "^1.0.0"
564 |
565 | source-map-support@~0.5.20:
566 | version "0.5.20"
567 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
568 | integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
569 | dependencies:
570 | buffer-from "^1.0.0"
571 | source-map "^0.6.0"
572 |
573 | source-map@^0.6.0:
574 | version "0.6.1"
575 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
576 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
577 |
578 | source-map@~0.7.2:
579 | version "0.7.3"
580 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
581 | integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
582 |
583 | sourcemap-codec@^1.4.4:
584 | version "1.4.8"
585 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
586 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
587 |
588 | supports-color@^5.3.0:
589 | version "5.5.0"
590 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
591 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
592 | dependencies:
593 | has-flag "^3.0.0"
594 |
595 | supports-color@^7.0.0:
596 | version "7.2.0"
597 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
598 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
599 | dependencies:
600 | has-flag "^4.0.0"
601 |
602 | svelte@^3.0.0:
603 | version "3.44.0"
604 | resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.44.0.tgz#e6176cb3ad93846ddb4140e93f43098136b23f3b"
605 | integrity sha512-zWACSJBSncGiDvFfYOMFGNV5zDLOlyhftmO5yOZ0lEtQMptpElaRtl39MWz1+lYCpwUq4F3Q2lTzI9TrTL+eMA==
606 |
607 | terser@^5.0.0:
608 | version "5.9.0"
609 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351"
610 | integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==
611 | dependencies:
612 | commander "^2.20.0"
613 | source-map "~0.7.2"
614 | source-map-support "~0.5.20"
615 |
616 | tinydate@^1.0.0:
617 | version "1.3.0"
618 | resolved "https://registry.yarnpkg.com/tinydate/-/tinydate-1.3.0.tgz#e6ca8e5a22b51bb4ea1c3a2a4fd1352dbd4c57fb"
619 | integrity sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==
620 |
621 | to-regex-range@^5.0.1:
622 | version "5.0.1"
623 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
624 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
625 | dependencies:
626 | is-number "^7.0.0"
627 |
628 | totalist@^1.0.0:
629 | version "1.1.0"
630 | resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
631 | integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
632 |
633 | wrappy@1:
634 | version "1.0.2"
635 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
636 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
637 |
638 | ws@^7.4.3:
639 | version "7.5.5"
640 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
641 | integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
642 |
--------------------------------------------------------------------------------