├── .eslintignore ├── .babelrc ├── playground ├── public │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── android-chrome-512x512.png │ ├── site.webmanifest │ └── safari-pinned-tab.svg ├── src │ ├── assets │ │ ├── logo.png │ │ └── Recursive_VF.woff2 │ ├── main.js │ ├── store.js │ ├── components │ │ ├── inputs │ │ │ ├── LabeledInput.vue │ │ │ ├── Button.vue │ │ │ └── SegmentedControl.vue │ │ ├── App.vue │ │ └── ui │ │ │ ├── Preview.vue │ │ │ ├── CodeSnippet.vue │ │ │ └── ConfigBar.vue │ └── styles │ │ └── global.css ├── postcss.config.js ├── vite.config.js ├── README.md ├── package.json ├── index.html ├── tailwind.config.js └── yarn.lock ├── src ├── utils │ ├── vueDragEvent.js │ ├── returnPositionString.js │ ├── moveElementTransform.js │ ├── eventListener.js │ ├── closestValueToSnap.js │ ├── isValidAxisValue.js │ ├── getTransformValue.js │ ├── updateMousePosition.js │ └── getSnappingValues.js ├── events │ ├── dragEnd.js │ ├── dragMove.js │ ├── dragStart.js │ └── dragSetup.js ├── index.js └── tests │ └── utils.test.js ├── .eslintrc.json ├── .github └── workflows │ ├── npm-publish.yml │ └── build.yml ├── LICENSE ├── package.json ├── rollup.config.js ├── .gitignore ├── dist ├── module.js ├── main.js └── browser.js └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | vue2 3 | vue3 -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } 4 | -------------------------------------------------------------------------------- /playground/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/public/favicon.ico -------------------------------------------------------------------------------- /playground/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/src/assets/logo.png -------------------------------------------------------------------------------- /playground/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/public/favicon-16x16.png -------------------------------------------------------------------------------- /playground/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/public/favicon-32x32.png -------------------------------------------------------------------------------- /playground/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/public/apple-touch-icon.png -------------------------------------------------------------------------------- /playground/src/assets/Recursive_VF.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/src/assets/Recursive_VF.woff2 -------------------------------------------------------------------------------- /playground/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /playground/public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nil/v-drag/HEAD/playground/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/utils/vueDragEvent.js: -------------------------------------------------------------------------------- 1 | // Creates an event handler that can be used in Vue code 2 | export default function (el, action) { 3 | el.dispatchEvent(new Event(`v-drag-${action}`)); 4 | } 5 | -------------------------------------------------------------------------------- /src/utils/returnPositionString.js: -------------------------------------------------------------------------------- 1 | // Return a matrix with transform and translate values 2 | export default function (matrix, a, b) { 3 | return `matrix(${matrix || '1, 0, 0, 1,'} ${a}, ${b})`; 4 | } 5 | -------------------------------------------------------------------------------- /playground/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | }); 8 | -------------------------------------------------------------------------------- /src/utils/moveElementTransform.js: -------------------------------------------------------------------------------- 1 | export default function (transform, left, top) { 2 | window.data.move.style.transform = transform; 3 | window.data.move.style.left = left; 4 | window.data.move.style.top = top; 5 | } 6 | -------------------------------------------------------------------------------- /playground/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './components/App.vue'; 3 | import store from './store'; 4 | import drag from '../../dist/module'; 5 | 6 | createApp(App).use(store).use(drag).mount('#app'); 7 | -------------------------------------------------------------------------------- /src/utils/eventListener.js: -------------------------------------------------------------------------------- 1 | // Shorthand for muliple events with the same function 2 | export default function (types, func, state = 'add') { 3 | types.forEach((type) => { 4 | document[`${state}EventListener`](type, func, false); 5 | }); 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/closestValueToSnap.js: -------------------------------------------------------------------------------- 1 | // Get the closest value posible when snaping on a grid 2 | export default function (value, axis) { 3 | const snapValue = axis === 'x' ? window.data.snapX : window.data.snapY; 4 | return Math.round(value / snapValue) * snapValue; 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/isValidAxisValue.js: -------------------------------------------------------------------------------- 1 | // Checks if the given value is a valid axis value ('x', 'y' or 'all') 2 | export default function (axis) { 3 | const acceptedValues = ['x', 'y', 'all']; 4 | 5 | if (acceptedValues.includes(axis)) { 6 | return true; 7 | } 8 | return false; 9 | } 10 | -------------------------------------------------------------------------------- /playground/src/store.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'vuex'; 2 | 3 | // Create a new store instance. 4 | const store = createStore({ 5 | state() { 6 | return { 7 | axis: 'all', 8 | }; 9 | }, 10 | 11 | mutations: { 12 | updateValue(state, n) { 13 | state[n.property] = n.value; 14 | }, 15 | }, 16 | }); 17 | 18 | export default store; 19 | -------------------------------------------------------------------------------- /playground/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-512x512.png", 7 | "sizes": "512x512", 8 | "type": "image/png" 9 | } 10 | ], 11 | "theme_color": "#15803D", 12 | "background_color": "#ffffff", 13 | "display": "standalone" 14 | } 15 | -------------------------------------------------------------------------------- /playground/src/components/inputs/LabeledInput.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /playground/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Vite 2 | 3 | This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` 9 | 10 | 18 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "@carbon/icons-vue": "^10.49.1", 12 | "@vitejs/plugin-vue": "^2.3.3", 13 | "vite": "^2.9.13", 14 | "vue": "^3.2.25", 15 | "vuex": "^4.0.2" 16 | }, 17 | "devDependencies": { 18 | "autoprefixer": "^10.4.7", 19 | "postcss": "^8.4.14", 20 | "tailwindcss": "^3.0.24" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /playground/src/components/ui/Preview.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 26 | -------------------------------------------------------------------------------- /src/utils/getTransformValue.js: -------------------------------------------------------------------------------- 1 | // Return element's left or top position 2 | export default function (str, dir) { 3 | // Get top or left position, without translate 4 | let pos = Number(window.getComputedStyle(window.data.move)[dir].replace('px', '')); 5 | 6 | // Only consider translation when matrix is defined 7 | if (str !== 'none') { 8 | // Get all matrix's values 9 | const itemsArray = str.match(/[0-9.-]+/g); 10 | 11 | // Get matrix translate value, based on the x + y = 8 equation 12 | pos += Number(itemsArray[8 - dir.length]); 13 | } 14 | 15 | return pos; 16 | } 17 | -------------------------------------------------------------------------------- /playground/src/components/inputs/Button.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 34 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb-base", 4 | "plugin:vue/vue3-recommended" 5 | ], 6 | "env": { 7 | "browser": true, 8 | "node": true, 9 | "jest": true 10 | }, 11 | "rules": { 12 | "func-names": 0, 13 | "prefer-destructuring": 0, 14 | "max-len": ["error", { 15 | "code": 150, 16 | "ignoreStrings": true, 17 | "ignoreTemplateLiterals": true, 18 | "ignorePattern": "class=\"" 19 | }], 20 | "import/no-unresolved": ["error", { "ignore": [ "@theme" ] }], 21 | "no-param-reassign": ["error", { "props": false }], 22 | "no-console": ["error", { "allow": ["warn", "error"] }], 23 | "vue/multi-word-component-names": 0, 24 | "vue/max-attributes-per-line": 0, 25 | "vue/require-default-prop": 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /playground/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | v-drag — playground 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: npm package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | publish-npm: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 16 18 | registry-url: https://registry.npmjs.org/ 19 | - run: npm install 20 | - run: npm ci 21 | - run: npm run build 22 | - run: npm run test 23 | - run: npm publish 24 | env: 25 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 26 | -------------------------------------------------------------------------------- /src/utils/updateMousePosition.js: -------------------------------------------------------------------------------- 1 | export default function (e) { 2 | e.preventDefault(); 3 | 4 | // Update value of the mouse position 5 | window.data.mouseX = (e.pageX || e.touches[0].pageX) - window.data.initialX; 6 | window.data.mouseY = (e.pageY || e.touches[0].pageY) - window.data.initialY; 7 | 8 | // Scroll page if dragging over the edges, 9 | // but only if mouse is static for some time 10 | window.setTimeout(() => { 11 | if ((e.clientY || e.touches[0].clientY) > window.innerHeight * 0.8) { 12 | document.documentElement.scrollTop += 10; 13 | } 14 | 15 | if ((e.clientY || e.touches[0].clientY) < window.innerHeight * 0.2) { 16 | document.documentElement.scrollTop -= 10; 17 | } 18 | 19 | if ((e.clientX || e.touches[0].clientX) > window.innerWidth * 0.8) { 20 | document.documentElement.scrollLeft += 10; 21 | } 22 | 23 | if ((e.clientX || e.touches[0].clientX) < window.innerWidth * 0.2) { 24 | document.documentElement.scrollLeft -= 10; 25 | } 26 | }, 100); 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Build 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [12.x, 14.x, 16.x] 19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | cache: 'npm' 28 | - run: npm install 29 | - run: npm ci 30 | - run: npm run build --if-present 31 | - run: npm run test 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Nil Vila 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. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "v-drag", 3 | "version": "3.0.9", 4 | "description": "The simplest way to integrate drag on Vue.js", 5 | "scripts": { 6 | "build": "rollup --config", 7 | "test": "jest" 8 | }, 9 | "main": "dist/main.js", 10 | "module": "dist/module.js", 11 | "unpkg": "dist/browser.js", 12 | "keywords": [ 13 | "vue", 14 | "vuejs", 15 | "vue2", 16 | "vue3", 17 | "drag", 18 | "draggable", 19 | "dragging" 20 | ], 21 | "homepage": "https://github.com/nil/v-drag", 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/nil/v-drag.git" 25 | }, 26 | "license": "MIT", 27 | "author": "Nil Vila", 28 | "bugs": { 29 | "url": "https://github.com/nil/v-drag/issues" 30 | }, 31 | "devDependencies": { 32 | "@babel/preset-env": "^7.18.2", 33 | "eslint": "^7.2.0", 34 | "eslint-config-airbnb-base": "^14.1.0", 35 | "eslint-plugin-import": "^2.16.0", 36 | "eslint-plugin-vue": "^8.5.0", 37 | "jest": "^28.1.1", 38 | "rollup": "^2.9.0", 39 | "rollup-plugin-commonjs": "^10.1.0", 40 | "rollup-plugin-node-resolve": "^5.2.0", 41 | "rollup-plugin-terser": "^6.1.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import { terser } from 'rollup-plugin-terser'; 2 | import commonjs from 'rollup-plugin-commonjs'; 3 | import nodeResolve from 'rollup-plugin-node-resolve'; 4 | import info from './package.json'; 5 | 6 | const bannerText = `/*! 7 | * ${info.name} v${info.version} 8 | * by ${info.author} and contributors 9 | */`; 10 | 11 | const pluginsList = [ 12 | nodeResolve(), 13 | commonjs(), 14 | terser({ 15 | output: { 16 | comments: /^!/, 17 | }, 18 | }), 19 | ]; 20 | 21 | export default [ 22 | { 23 | input: 'src/index.js', 24 | output: { 25 | file: info.main, 26 | name: 'vdrag', 27 | format: 'cjs', 28 | exports: 'default', 29 | banner: bannerText, 30 | }, 31 | plugins: pluginsList, 32 | }, 33 | { 34 | input: 'src/index.js', 35 | output: { 36 | file: info.module, 37 | name: 'vdrag', 38 | format: 'esm', 39 | exports: 'default', 40 | banner: bannerText, 41 | }, 42 | plugins: pluginsList, 43 | }, 44 | { 45 | input: 'src/index.js', 46 | output: { 47 | file: info.unpkg, 48 | name: 'vdrag', 49 | format: 'iife', 50 | exports: 'default', 51 | banner: bannerText, 52 | }, 53 | plugins: pluginsList, 54 | }, 55 | ]; 56 | -------------------------------------------------------------------------------- /src/events/dragEnd.js: -------------------------------------------------------------------------------- 1 | import dragMove from './dragMove'; 2 | 3 | import eventListener from '../utils/eventListener'; 4 | import moveElementTransform from '../utils/moveElementTransform'; 5 | import returnPositionString from '../utils/returnPositionString'; 6 | import updateMousePosition from '../utils/updateMousePosition'; 7 | import vueDragEvent from '../utils/vueDragEvent'; 8 | import closestValueToSnap from '../utils/closestValueToSnap'; 9 | 10 | export default function () { 11 | // Prevent TypeError from showing 12 | if (!(window.data.grab && window.data.move)) return; 13 | 14 | // Stop move animation 15 | cancelAnimationFrame(window.data.posAnimation); 16 | 17 | // Remove setUpMovement() if mouse/touch hasn't moved 18 | eventListener(['mousemove', 'touchmove'], dragMove, 'remove'); 19 | 20 | // Replace transform properties with left and top 21 | moveElementTransform( 22 | window.data.matrix ? returnPositionString(window.data.matrix, 0, 0) : 'none', 23 | `${window.data.matrixX + closestValueToSnap(window.data.relativeX, 'x')}px`, 24 | `${window.data.matrixY + closestValueToSnap(window.data.relativeY, 'y')}px`, 25 | ); 26 | 27 | // Remove CSS classes 28 | window.data.grab.classList.remove(window.data.class.down); 29 | window.data.move.classList.remove(window.data.class.move); 30 | 31 | // Vue event on drag end 32 | vueDragEvent(window.data.move, 'end'); 33 | 34 | // Stop updating mouse position 35 | eventListener(['mousemove', 'touchmove'], updateMousePosition, 'remove'); 36 | } 37 | -------------------------------------------------------------------------------- /src/utils/getSnappingValues.js: -------------------------------------------------------------------------------- 1 | // Return object even if it's a string (with or without units), 2 | // set 'force' to true to never return an undefined value 3 | function toNumber(input, force) { 4 | const value = typeof input === 'string' ? parseInt(input.replace(/px/g, ''), 10) : input; 5 | return (value === 0 || Number.isNaN(value) || (force && value === undefined)) ? 1 : value; 6 | } 7 | 8 | // Return many options to an object with x and y values 9 | export default function (value) { 10 | // If value is given as a string, eg. '20px' 11 | if (typeof value === 'string') { 12 | const valueArray = value.split(','); 13 | 14 | return { 15 | x: toNumber(valueArray[0]), 16 | y: toNumber(valueArray[1]) !== undefined ? toNumber(valueArray[1]) : toNumber(valueArray[0]), 17 | }; 18 | } 19 | 20 | // If value is given as a number, eg. 20 21 | if (typeof value === 'number') { 22 | return { 23 | x: toNumber(value), 24 | y: toNumber(value), 25 | }; 26 | } 27 | 28 | // If value is given as an object, eg. {x: 20, y: 10} 29 | if (value instanceof Object && (value.x || value.y)) { 30 | return { 31 | x: toNumber(value.x) || 1, 32 | y: toNumber(value.y) || 1, 33 | }; 34 | } 35 | 36 | // If value is given as an array, eg. [20, 10] 37 | if (Array.isArray(value)) { 38 | return { 39 | x: toNumber(value[0]) || 1, 40 | y: toNumber(value[1]) !== undefined ? toNumber(value[1], true) : toNumber(value[0], true), 41 | }; 42 | } 43 | 44 | return { 45 | x: 1, 46 | y: 1, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /src/events/dragMove.js: -------------------------------------------------------------------------------- 1 | import closestValueToSnap from '../utils/closestValueToSnap'; 2 | import eventListener from '../utils/eventListener'; 3 | import returnPositionString from '../utils/returnPositionString'; 4 | import vueDragEvent from '../utils/vueDragEvent'; 5 | 6 | export function updatePosition(x, y) { 7 | // Store relative coordinates 8 | window.data.relativeX = window.data.mouseX * x; 9 | window.data.relativeY = window.data.mouseY * y; 10 | 11 | // Apply transformation to move element 12 | window.data.move.style.transform = returnPositionString( 13 | window.data.matrix, 14 | window.data.matrixX + closestValueToSnap(window.data.relativeX, 'x'), 15 | window.data.matrixY + closestValueToSnap(window.data.relativeY, 'y'), 16 | ); 17 | 18 | // Vue event on drag moving 19 | vueDragEvent(window.data.move, 'moving'); 20 | 21 | // Remove text selection while dragging 22 | (window.getSelection ? window.getSelection() : document.selection).empty(); 23 | } 24 | 25 | export const callPositionUpdate = { 26 | x() { updatePosition(true, false); }, 27 | y() { updatePosition(false, true); }, 28 | all() { updatePosition(true, true); }, 29 | }; 30 | 31 | export function repeatRaf() { 32 | callPositionUpdate[window.data.axis](window.data); 33 | window.data.posAnimation = requestAnimationFrame(repeatRaf); 34 | } 35 | 36 | export default function setUpMovement() { 37 | // Apply CSS class to move element 38 | window.data.move.classList.add(window.data.class.move); 39 | 40 | // Begin moving animation 41 | window.data.posAnimation = requestAnimationFrame(repeatRaf); 42 | 43 | // Avoid this function to fire another time 44 | eventListener(['mousemove', 'touchmove'], setUpMovement, 'remove'); 45 | } 46 | -------------------------------------------------------------------------------- /playground/src/styles/global.css: -------------------------------------------------------------------------------- 1 | /* --- Tailwind ------------------ */ 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | 6 | 7 | /* --- Fonts ------------------ */ 8 | @font-face { 9 | font-family: 'Recursive'; 10 | font-style: normal; 11 | font-weight: 300 800; 12 | font-display: swap; 13 | src: url('src/assets/Recursive_VF.woff2') format('woff2'); 14 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 15 | } 16 | 17 | .font-sans { 18 | font-family: 'Recursive', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Helvetica', 'Ubuntu', 'Roboto', 'Noto', 'Arial', 'sans-serif'; 19 | font-variation-settings: "wght" 380, "MONO" 0, "CASL" 0.15, "slnt" 0, "CRSV" 0.5; 20 | /* TODO: font alternates are not working */ 21 | font-feature-settings: 'zero' on, 'ss02' on, 'ss03' on, 'ss08' on; 22 | } 23 | 24 | .font-mono { 25 | font-family: 'Recursive', monospace; 26 | font-variation-settings: "wght" 380, "MONO" 1, "CASL" 0.25, "slnt" 0, "CRSV" 0.5; 27 | font-feature-settings: 'zero' on, 'ss02' on, 'ss03' on, 'ss08' on; 28 | } 29 | 30 | .font-bold { 31 | font-variation-settings: "wght" 750; 32 | } 33 | 34 | button, input, optgroup, select, textarea { 35 | font-variation-settings: "wght" 380, "MONO" 0, "CASL" 0.15, "slnt" 0, "CRSV" 0.5; 36 | } 37 | 38 | 39 | /* --- Global ------------------ */ 40 | * { 41 | box-sizing: border-box; 42 | transition: all 100ms cubic-bezier(0.25, 1, 0.5, 1), border-width 0s, padding-left 0s, padding-right 0s; 43 | } 44 | 45 | @media (prefers-reduced-motion) { 46 | * { 47 | transition: none; 48 | } 49 | } 50 | 51 | html { 52 | font-size: 20px; 53 | } 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ############################ 2 | # OS X 3 | ############################ 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | Icon 9 | .Spotlight-V100 10 | .Trashes 11 | ._* 12 | 13 | 14 | ############################ 15 | # Linux 16 | ############################ 17 | 18 | *~ 19 | 20 | 21 | ############################ 22 | # Windows 23 | ############################ 24 | 25 | Thumbs.db 26 | ehthumbs.db 27 | Desktop.ini 28 | $RECYCLE.BIN/ 29 | *.cab 30 | *.msi 31 | *.msm 32 | *.msp 33 | 34 | 35 | ############################ 36 | # Packages 37 | ############################ 38 | 39 | *.7z 40 | *.csv 41 | *.dat 42 | *.dmg 43 | *.gz 44 | *.iso 45 | *.jar 46 | *.rar 47 | *.tar 48 | *.zip 49 | *.com 50 | *.class 51 | *.dll 52 | *.exe 53 | *.o 54 | *.seed 55 | *.so 56 | *.swo 57 | *.swp 58 | *.swn 59 | *.swm 60 | *.out 61 | *.pid 62 | 63 | 64 | ############################ 65 | # Logs and databases 66 | ############################ 67 | 68 | .tmp 69 | *.log 70 | *.sql 71 | *.sqlite 72 | *.sqlite3 73 | 74 | 75 | ############################ 76 | # Misc. 77 | ############################ 78 | 79 | *# 80 | ssl 81 | .idea 82 | nbproject 83 | public/uploads/* 84 | !public/uploads/.gitkeep 85 | 86 | ############################ 87 | # Node.js 88 | ############################ 89 | 90 | lib-cov 91 | lcov.info 92 | pids 93 | logs 94 | results 95 | node_modules 96 | .node_history 97 | package-lock.json 98 | 99 | ############################ 100 | # Tests 101 | ############################ 102 | 103 | testApp 104 | coverage 105 | 106 | ############################ 107 | # Strapi 108 | ############################ 109 | 110 | .env 111 | license.txt 112 | exports 113 | *.cache 114 | build 115 | .strapi-updater.json 116 | -------------------------------------------------------------------------------- /playground/src/components/inputs/SegmentedControl.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 72 | -------------------------------------------------------------------------------- /src/events/dragStart.js: -------------------------------------------------------------------------------- 1 | import dragMove from './dragMove'; 2 | 3 | import getTransformValue from '../utils/getTransformValue'; 4 | import moveElementTransform from '../utils/moveElementTransform'; 5 | import returnPositionString from '../utils/returnPositionString'; 6 | import eventListener from '../utils/eventListener'; 7 | import updateMousePosition from '../utils/updateMousePosition'; 8 | import vueDragEvent from '../utils/vueDragEvent'; 9 | 10 | export default function (grabElement, moveElement, axis, snap, e) { 11 | e.preventDefault(); 12 | 13 | // Store elements 14 | window.data.grab = grabElement; 15 | window.data.move = moveElement; 16 | 17 | // Store axis 18 | window.data.axis = axis; 19 | 20 | // Store current mouse or touch position 21 | window.data.initialX = e.pageX || e.touches[0].pageX; 22 | window.data.initialY = e.pageY || e.touches[0].pageY; 23 | 24 | // Reset relative coordinates 25 | window.data.relativeX = 0; 26 | window.data.relativeY = 0; 27 | 28 | // Store snapping values 29 | window.data.snapX = snap.x; 30 | window.data.snapY = snap.y; 31 | 32 | // Get transform string of the move element 33 | const matrix = window.getComputedStyle(window.data.move).transform; 34 | 35 | // Store matrix value 36 | if (matrix === 'none') { 37 | window.data.matrix = false; 38 | } else { 39 | window.data.matrix = matrix.match(/\d([^,]*,){4}/g); 40 | } 41 | 42 | // Apply transform to the move element 43 | const left = getTransformValue(matrix, 'left'); 44 | const top = getTransformValue(matrix, 'top'); 45 | 46 | // Replace left and top properties with transform 47 | moveElementTransform( 48 | returnPositionString(window.data.matrix, left, top), 49 | 0, 50 | 0, 51 | ); 52 | 53 | window.data.matrixX = left; 54 | window.data.matrixY = top; 55 | 56 | // Apply CSS class to grab element 57 | window.data.grab.classList.add(window.data.class.down); 58 | 59 | // Vue event on drag down 60 | vueDragEvent(moveElement, 'down'); 61 | vueDragEvent(moveElement, 'start'); 62 | 63 | // Add events to move drag 64 | eventListener(['mousemove', 'touchmove'], updateMousePosition); 65 | eventListener(['mousemove', 'touchmove'], dragMove); 66 | } 67 | -------------------------------------------------------------------------------- /playground/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | './index.html', 4 | './src/**/*.{vue,js,ts,jsx,tsx}', 5 | ], 6 | theme: { 7 | fontSize: { 8 | '7xl': ['5.25rem', { 9 | letterSpacing: '-0.05em', 10 | lineHeight: '1', 11 | }], 12 | '6xl': ['4.4rem', { 13 | letterSpacing: '-0.05em', 14 | lineHeight: '1', 15 | }], 16 | '5xl': ['3.65rem', { 17 | letterSpacing: '-0.05em', 18 | lineHeight: '1.1', 19 | }], 20 | '4xl': ['3.05rem', { 21 | letterSpacing: '-0.04em', 22 | lineHeight: ' 1.1', 23 | }], 24 | '3xl': ['2.1rem', { 25 | letterSpacing: '-0.04em', 26 | lineHeight: '1.1', 27 | }], 28 | '2xl': ['1.75rem', { 29 | letterSpacing: '-0.04em', 30 | lineHeight: '1.2', 31 | }], 32 | xl: ['1.45rem', { 33 | letterSpacing: '-0.04em', 34 | lineHeight: '1.25', 35 | }], 36 | l: ['1.2rem', { 37 | letterSpacing: '-0.03em', 38 | lineHeight: '1.3', 39 | }], 40 | m: ['1rem', { 41 | letterSpacing: '-0.02em', 42 | lineHeight: '1.4', 43 | }], 44 | s: ['0.85rem', { 45 | letterSpacing: '-0.02em', 46 | lineHeight: '1.4', 47 | }], 48 | xs: ['0.7rem', { 49 | letterSpacing: '-0.02em', 50 | lineHeight: '1.4', 51 | }], 52 | }, 53 | boxShadow: { 54 | outer: '0px 1px 0px #F1F5F9', 55 | DEFAULT: '0px 1px 0px #F1F5F9, inset 0px 1px 0px #F8FAFC', 56 | accent: '0px 1px 0px #F1F5F9, inset 0px 1px 0px #ECFCCB', 57 | lg: '0px 100px 80px rgba(15, 23, 42, 0.06), 0px 34.67px 24.12px rgba(15, 23, 42, 0.038), 0px 16.87px 10.02px rgba(15, 23, 42, 0.02), 0px 7.21px 3.62px rgba(15, 23, 42, 0.02)', 58 | }, 59 | borderRadius: { 60 | DEFAULT: '5px', 61 | lg: '8px', 62 | }, 63 | extend: { 64 | spacing: { 65 | '2xs': '0.4rem', 66 | xs: '0.8rem', 67 | s: '1.6rem', 68 | m: '2.4rem', 69 | l: '4rem', 70 | xl: '6.4rem', 71 | '2xl': '10.4rem', 72 | '3xl': '16.8rem', 73 | '4xl': '27.2rem', 74 | }, 75 | }, 76 | }, 77 | plugins: [], 78 | }; 79 | -------------------------------------------------------------------------------- /src/events/dragSetup.js: -------------------------------------------------------------------------------- 1 | import dragStart from './dragStart'; 2 | import dragEnd from './dragEnd'; 3 | 4 | import getSnappingValues from '../utils/getSnappingValues'; 5 | import isValidAxisValue from '../utils/isValidAxisValue'; 6 | import eventListener from '../utils/eventListener'; 7 | import vueDragEvent from '../utils/vueDragEvent'; 8 | 9 | export default function (el, binding) { 10 | const value = binding.value || {}; 11 | const handleSelector = value instanceof Object ? value.handle : value; 12 | const snap = getSnappingValues(value.snap); 13 | const handleArray = []; 14 | let axis; 15 | 16 | // Update axis value 17 | if (value instanceof Object && value.axis && isValidAxisValue(value.axis)) { 18 | axis = value.axis; 19 | } else if (isValidAxisValue(binding.arg)) { 20 | axis = binding.arg; 21 | } else { 22 | axis = 'all'; 23 | } 24 | 25 | // Store all the DOM elements that will be used as handles. 26 | // They can be declared using a string with a CSS tag, class or id, or using Vue refs. 27 | if (handleSelector instanceof HTMLElement) { 28 | handleArray.push(handleSelector); 29 | } else { 30 | // handleArray.push(document.querySelectorAll(handleSelector)); 31 | document.querySelectorAll(handleSelector).forEach((child) => { 32 | handleArray.push(child); 33 | }); 34 | } 35 | 36 | if (handleArray.length !== 0) { 37 | // Define move element and apply CSS class 38 | el.classList.add(window.data.class.usesHandle); 39 | 40 | handleArray.forEach((grabElement) => { 41 | // Apply CSS class to each grab element 42 | grabElement.classList.add(window.data.class.handle); 43 | 44 | // Add events to start drag with handle 45 | grabElement.onmousedown = (e) => dragStart(grabElement, el, axis, snap, e); 46 | grabElement.ontouchstart = (e) => dragStart(grabElement, el, axis, snap, e); 47 | }); 48 | } else { 49 | // Add events to start drag without handle 50 | el.onmousedown = (e) => dragStart(el, el, axis, snap, e); 51 | el.ontouchstart = (e) => dragStart(el, el, axis, snap, e); 52 | } 53 | 54 | // Apply CSS classes to the element 55 | el.classList.add(window.data.class.initial); 56 | 57 | // Vue event on setup 58 | vueDragEvent(el, 'setup'); 59 | 60 | // Add event to end drag 61 | eventListener(['mouseup', 'touchend'], dragEnd); 62 | } 63 | -------------------------------------------------------------------------------- /playground/public/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 35 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /playground/src/components/ui/CodeSnippet.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 101 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import dragSetup from './events/dragSetup'; 2 | 3 | import vueDragEvent from './utils/vueDragEvent'; 4 | 5 | // Add draggable configuration to element for the first time 6 | const mountedHook = (el, binding) => { 7 | dragSetup(el, binding); 8 | }; 9 | 10 | // Update the drag configuration 11 | const updatedHook = (el, binding) => { 12 | // Remove events from updated element 13 | el.onmousedown = null; 14 | el.ontouchstart = null; 15 | 16 | const handle = typeof binding.oldValue === 'object' 17 | ? binding.oldValue.handle 18 | : binding.oldValue; 19 | 20 | const oldHandleArray = document.querySelectorAll(handle); 21 | 22 | oldHandleArray.forEach((oldHandle) => { 23 | // Remove events from the old handle 24 | oldHandle.onmousedown = null; 25 | oldHandle.ontouchstart = null; 26 | 27 | // Remove CSS classes related to the old handle 28 | oldHandle.classList.remove(window.data.class.handle); 29 | el.classList.remove(window.data.class.usesHandle); 30 | }); 31 | 32 | // Vue event if anything is updated 33 | if (binding.oldValue) { 34 | Object.keys(binding.oldValue).forEach((key) => { 35 | vueDragEvent(el, `update-${key}`); 36 | }); 37 | } 38 | 39 | // Add draggable configuration to element 40 | dragSetup(el, binding); 41 | }; 42 | 43 | // Create custom directive 44 | export default { 45 | install(Vue, options) { 46 | // Initialize 'data' object 47 | window.data = {}; 48 | 49 | // Store default event classes 50 | window.data.class = { 51 | initial: 'drag-draggable', 52 | usesHandle: 'drag-uses-handle', 53 | handle: 'drag-handle', 54 | down: 'drag-down', 55 | move: 'drag-move', 56 | }; 57 | 58 | let removeTransition = true; 59 | 60 | // Replace default event classes with custom ones 61 | if (options) { 62 | if (options.eventClass) { 63 | const classes = options.eventClass; 64 | 65 | Object.keys(classes).forEach((key) => { 66 | if (classes[key]) { 67 | window.data.class[key] = classes[key]; 68 | } 69 | }); 70 | } 71 | 72 | if (typeof options.removeTransition === 'boolean') { 73 | removeTransition = options.removeTransition; 74 | } 75 | } 76 | 77 | // Create stylesheet with basic styling (position, z-index and cursors) 78 | const styleElement = document.createElement('style'); 79 | styleElement.innerHTML = `.${window.data.class.initial}{position:relative;}.${window.data.class.initial}:not(.${window.data.class.usesHandle}),.${window.data.class.handle}{cursor:move;cursor:grab;cursor:-webkit-grab;}.${window.data.class.handle}.${window.data.class.down},.${window.data.class.initial}:not(.${window.data.class.usesHandle}).${window.data.class.down}{z-index:999;cursor:grabbing;cursor:-webkit-grabbing;}`; 80 | styleElement.innerHTML += removeTransition === true ? `.${window.data.class.move}{transition:none;}` : ''; 81 | document.body.appendChild(styleElement); 82 | 83 | // Register 'v-drag' directive 84 | Vue.directive('drag', { 85 | // Hooks for Vue3 86 | mounted(el, binding) { 87 | mountedHook(el, binding); 88 | }, 89 | 90 | updated(el, binding) { 91 | updatedHook(el, binding); 92 | }, 93 | 94 | // Hooks for Vue2 95 | inserted(el, binding) { 96 | mountedHook(el, binding); 97 | }, 98 | 99 | update(el, binding) { 100 | updatedHook(el, binding); 101 | }, 102 | }); 103 | }, 104 | }; 105 | -------------------------------------------------------------------------------- /src/tests/utils.test.js: -------------------------------------------------------------------------------- 1 | import isValidAxisValue from '../utils/isValidAxisValue'; 2 | import returnPositionString from '../utils/returnPositionString'; 3 | import getSnappingValues from '../utils/getSnappingValues'; 4 | 5 | describe('Utils', () => { 6 | describe('getSnappingValues', () => { 7 | test('Declare value with number', () => { 8 | expect(getSnappingValues(10)).toStrictEqual({ x: 10, y: 10 }); 9 | }); 10 | test('Declare value with number 0', () => { 11 | expect(getSnappingValues(0)).toStrictEqual({ x: 1, y: 1 }); 12 | }); 13 | test('Declare value with string, without units', () => { 14 | expect(getSnappingValues('10')).toStrictEqual({ x: 10, y: 10 }); 15 | }); 16 | test('Declare value with string, with units', () => { 17 | expect(getSnappingValues('10px')).toStrictEqual({ x: 10, y: 10 }); 18 | }); 19 | test('Declare value with empty string', () => { 20 | expect(getSnappingValues('')).toStrictEqual({ x: 1, y: 1 }); 21 | }); 22 | test('Declare value with array of numbers of length 1', () => { 23 | expect(getSnappingValues([10])).toStrictEqual({ x: 10, y: 10 }); 24 | }); 25 | test('Declare value with array of numbers of length 2', () => { 26 | expect(getSnappingValues([10, 20])).toStrictEqual({ x: 10, y: 20 }); 27 | }); 28 | test('Declare value with array of numbers of length 3', () => { 29 | expect(getSnappingValues([10, 20, 30])).toStrictEqual({ x: 10, y: 20 }); 30 | }); 31 | test('Declare value with empty array', () => { 32 | expect(getSnappingValues([])).toStrictEqual({ x: 1, y: 1 }); 33 | }); 34 | test('Declare value with array of strings of length 1', () => { 35 | expect(getSnappingValues(['10'])).toStrictEqual({ x: 10, y: 10 }); 36 | }); 37 | test('Declare value with array of strings of length 2', () => { 38 | expect(getSnappingValues(['10', '20px'])).toStrictEqual({ x: 10, y: 20 }); 39 | }); 40 | test('Declare value with array of strings of length 3', () => { 41 | expect(getSnappingValues(['10px', '20', '30px'])).toStrictEqual({ x: 10, y: 20 }); 42 | }); 43 | test('Declare value with object', () => { 44 | expect(getSnappingValues({ x: 10, y: '20' })).toStrictEqual({ x: 10, y: 20 }); 45 | }); 46 | test('Declare value with object missing one value', () => { 47 | expect(getSnappingValues({ x: '10px' })).toStrictEqual({ x: 10, y: 1 }); 48 | }); 49 | test('Declare value with empty object', () => { 50 | expect(getSnappingValues({})).toStrictEqual({ x: 1, y: 1 }); 51 | }); 52 | test("Declare value with boolean 'true'", () => { 53 | expect(getSnappingValues(true)).toStrictEqual({ x: 1, y: 1 }); 54 | }); 55 | test("Declare value with boolean 'false'", () => { 56 | expect(getSnappingValues(false)).toStrictEqual({ x: 1, y: 1 }); 57 | }); 58 | test('Empty declaration', () => { 59 | expect(getSnappingValues()).toStrictEqual({ x: 1, y: 1 }); 60 | }); 61 | }); 62 | 63 | describe('isValidAxisValue', () => { 64 | test("Validate axis when the value is 'x'", () => { 65 | expect(isValidAxisValue('x')).toBeTruthy(); 66 | }); 67 | test("Validate axis when the value is 'y'", () => { 68 | expect(isValidAxisValue('y')).toBeTruthy(); 69 | }); 70 | test("Validate axis when the value is 'all'", () => { 71 | expect(isValidAxisValue('all')).toBeTruthy(); 72 | }); 73 | test('Validate axis when the value is another one', () => { 74 | expect(isValidAxisValue('fall')).toBeFalsy(); 75 | }); 76 | test('Validate axis when the value is empty', () => { 77 | expect(isValidAxisValue('')).toBeFalsy(); 78 | }); 79 | }); 80 | 81 | describe('returnPositionString', () => { 82 | test('Return string when matrix is defined', () => { 83 | const data = ['1, 2, 3, 4,']; 84 | expect(returnPositionString(data, 20, 30)).toBe('matrix(1, 2, 3, 4, 20, 30)'); 85 | }); 86 | test('Return string when matrix is not defined', () => { 87 | const data = false; 88 | expect(returnPositionString(data, 20, 30)).toBe('matrix(1, 0, 0, 1, 20, 30)'); 89 | }); 90 | }); 91 | }); 92 | -------------------------------------------------------------------------------- /dist/module.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * v-drag v3.0.9 3 | * by Nil Vila and contributors 4 | */ 5 | function a(a,t){const n="x"===t?window.data.snapX:window.data.snapY;return Math.round(a/n)*n}function t(a,t,n="add"){a.forEach(a=>{document[n+"EventListener"](a,t,!1)})}function n(a,t,n){return`matrix(${a||"1, 0, 0, 1,"} ${t}, ${n})`}function o(a,t){a.dispatchEvent(new Event("v-drag-"+t))}function e(t,e){window.data.relativeX=window.data.mouseX*t,window.data.relativeY=window.data.mouseY*e,window.data.move.style.transform=n(window.data.matrix,window.data.matrixX+a(window.data.relativeX,"x"),window.data.matrixY+a(window.data.relativeY,"y")),o(window.data.move,"moving"),(window.getSelection?window.getSelection():document.selection).empty()}const d={x(){e(!0,!1)},y(){e(!1,!0)},all(){e(!0,!0)}};function i(){d[window.data.axis](window.data),window.data.posAnimation=requestAnimationFrame(i)}function s(){window.data.move.classList.add(window.data.class.move),window.data.posAnimation=requestAnimationFrame(i),t(["mousemove","touchmove"],s,"remove")}function w(a,t){let n=Number(window.getComputedStyle(window.data.move)[t].replace("px",""));if("none"!==a){const o=a.match(/[0-9.-]+/g);n+=Number(o[8-t.length])}return n}function l(a,t,n){window.data.move.style.transform=a,window.data.move.style.left=t,window.data.move.style.top=n}function c(a){a.preventDefault(),window.data.mouseX=(a.pageX||a.touches[0].pageX)-window.data.initialX,window.data.mouseY=(a.pageY||a.touches[0].pageY)-window.data.initialY,window.setTimeout(()=>{(a.clientY||a.touches[0].clientY)>.8*window.innerHeight&&(document.documentElement.scrollTop+=10),(a.clientY||a.touches[0].clientY)<.2*window.innerHeight&&(document.documentElement.scrollTop-=10),(a.clientX||a.touches[0].clientX)>.8*window.innerWidth&&(document.documentElement.scrollLeft+=10),(a.clientX||a.touches[0].clientX)<.2*window.innerWidth&&(document.documentElement.scrollLeft-=10)},100)}function r(a,e,d,i,r){r.preventDefault(),window.data.grab=a,window.data.move=e,window.data.axis=d,window.data.initialX=r.pageX||r.touches[0].pageX,window.data.initialY=r.pageY||r.touches[0].pageY,window.data.relativeX=0,window.data.relativeY=0,window.data.snapX=i.x,window.data.snapY=i.y;const u=window.getComputedStyle(window.data.move).transform;window.data.matrix="none"!==u&&u.match(/\d([^,]*,){4}/g);const m=w(u,"left"),v=w(u,"top");l(n(window.data.matrix,m,v),0,0),window.data.matrixX=m,window.data.matrixY=v,window.data.grab.classList.add(window.data.class.down),o(e,"down"),o(e,"start"),t(["mousemove","touchmove"],c),t(["mousemove","touchmove"],s)}function u(){window.data.grab&&window.data.move&&(cancelAnimationFrame(window.data.posAnimation),t(["mousemove","touchmove"],s,"remove"),l(window.data.matrix?n(window.data.matrix,0,0):"none",window.data.matrixX+a(window.data.relativeX,"x")+"px",window.data.matrixY+a(window.data.relativeY,"y")+"px"),window.data.grab.classList.remove(window.data.class.down),window.data.move.classList.remove(window.data.class.move),o(window.data.move,"end"),t(["mousemove","touchmove"],c,"remove"))}function m(a,t){const n="string"==typeof a?parseInt(a.replace(/px/g,""),10):a;return 0===n||Number.isNaN(n)||t&&void 0===n?1:n}function v(a){return!!["x","y","all"].includes(a)}function p(a,n){const e=n.value||{},d=e instanceof Object?e.handle:e,i=function(a){if("string"==typeof a){const t=a.split(",");return{x:m(t[0]),y:void 0!==m(t[1])?m(t[1]):m(t[0])}}return"number"==typeof a?{x:m(a),y:m(a)}:a instanceof Object&&(a.x||a.y)?{x:m(a.x)||1,y:m(a.y)||1}:Array.isArray(a)?{x:m(a[0])||1,y:void 0!==m(a[1])?m(a[1],!0):m(a[0],!0)}:{x:1,y:1}}(e.snap),s=[];let w;w=e instanceof Object&&e.axis&&v(e.axis)?e.axis:v(n.arg)?n.arg:"all",d instanceof HTMLElement?s.push(d):document.querySelectorAll(d).forEach(a=>{s.push(a)}),0!==s.length?(a.classList.add(window.data.class.usesHandle),s.forEach(t=>{t.classList.add(window.data.class.handle),t.onmousedown=n=>r(t,a,w,i,n),t.ontouchstart=n=>r(t,a,w,i,n)})):(a.onmousedown=t=>r(a,a,w,i,t),a.ontouchstart=t=>r(a,a,w,i,t)),a.classList.add(window.data.class.initial),o(a,"setup"),t(["mouseup","touchend"],u)}const h=(a,t)=>{p(a,t)},f=(a,t)=>{a.onmousedown=null,a.ontouchstart=null;const n="object"==typeof t.oldValue?t.oldValue.handle:t.oldValue;document.querySelectorAll(n).forEach(t=>{t.onmousedown=null,t.ontouchstart=null,t.classList.remove(window.data.class.handle),a.classList.remove(window.data.class.usesHandle)}),t.oldValue&&Object.keys(t.oldValue).forEach(t=>{o(a,"update-"+t)}),p(a,t)};var g={install(a,t){window.data={},window.data.class={initial:"drag-draggable",usesHandle:"drag-uses-handle",handle:"drag-handle",down:"drag-down",move:"drag-move"};let n=!0;if(t){if(t.eventClass){const a=t.eventClass;Object.keys(a).forEach(t=>{a[t]&&(window.data.class[t]=a[t])})}"boolean"==typeof t.removeTransition&&(n=t.removeTransition)}const o=document.createElement("style");o.innerHTML=`.${window.data.class.initial}{position:relative;}.${window.data.class.initial}:not(.${window.data.class.usesHandle}),.${window.data.class.handle}{cursor:move;cursor:grab;cursor:-webkit-grab;}.${window.data.class.handle}.${window.data.class.down},.${window.data.class.initial}:not(.${window.data.class.usesHandle}).${window.data.class.down}{z-index:999;cursor:grabbing;cursor:-webkit-grabbing;}`,o.innerHTML+=!0===n?`.${window.data.class.move}{transition:none;}`:"",document.body.appendChild(o),a.directive("drag",{mounted(a,t){h(a,t)},updated(a,t){f(a,t)},inserted(a,t){h(a,t)},update(a,t){f(a,t)}})}};export{g as default}; 6 | -------------------------------------------------------------------------------- /dist/main.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * v-drag v3.0.9 3 | * by Nil Vila and contributors 4 | */ 5 | "use strict";function a(a,t){const n="x"===t?window.data.snapX:window.data.snapY;return Math.round(a/n)*n}function t(a,t,n="add"){a.forEach(a=>{document[n+"EventListener"](a,t,!1)})}function n(a,t,n){return`matrix(${a||"1, 0, 0, 1,"} ${t}, ${n})`}function o(a,t){a.dispatchEvent(new Event("v-drag-"+t))}function e(t,e){window.data.relativeX=window.data.mouseX*t,window.data.relativeY=window.data.mouseY*e,window.data.move.style.transform=n(window.data.matrix,window.data.matrixX+a(window.data.relativeX,"x"),window.data.matrixY+a(window.data.relativeY,"y")),o(window.data.move,"moving"),(window.getSelection?window.getSelection():document.selection).empty()}const d={x(){e(!0,!1)},y(){e(!1,!0)},all(){e(!0,!0)}};function i(){d[window.data.axis](window.data),window.data.posAnimation=requestAnimationFrame(i)}function s(){window.data.move.classList.add(window.data.class.move),window.data.posAnimation=requestAnimationFrame(i),t(["mousemove","touchmove"],s,"remove")}function w(a,t){let n=Number(window.getComputedStyle(window.data.move)[t].replace("px",""));if("none"!==a){const o=a.match(/[0-9.-]+/g);n+=Number(o[8-t.length])}return n}function l(a,t,n){window.data.move.style.transform=a,window.data.move.style.left=t,window.data.move.style.top=n}function c(a){a.preventDefault(),window.data.mouseX=(a.pageX||a.touches[0].pageX)-window.data.initialX,window.data.mouseY=(a.pageY||a.touches[0].pageY)-window.data.initialY,window.setTimeout(()=>{(a.clientY||a.touches[0].clientY)>.8*window.innerHeight&&(document.documentElement.scrollTop+=10),(a.clientY||a.touches[0].clientY)<.2*window.innerHeight&&(document.documentElement.scrollTop-=10),(a.clientX||a.touches[0].clientX)>.8*window.innerWidth&&(document.documentElement.scrollLeft+=10),(a.clientX||a.touches[0].clientX)<.2*window.innerWidth&&(document.documentElement.scrollLeft-=10)},100)}function r(a,e,d,i,r){r.preventDefault(),window.data.grab=a,window.data.move=e,window.data.axis=d,window.data.initialX=r.pageX||r.touches[0].pageX,window.data.initialY=r.pageY||r.touches[0].pageY,window.data.relativeX=0,window.data.relativeY=0,window.data.snapX=i.x,window.data.snapY=i.y;const u=window.getComputedStyle(window.data.move).transform;window.data.matrix="none"!==u&&u.match(/\d([^,]*,){4}/g);const m=w(u,"left"),v=w(u,"top");l(n(window.data.matrix,m,v),0,0),window.data.matrixX=m,window.data.matrixY=v,window.data.grab.classList.add(window.data.class.down),o(e,"down"),o(e,"start"),t(["mousemove","touchmove"],c),t(["mousemove","touchmove"],s)}function u(){window.data.grab&&window.data.move&&(cancelAnimationFrame(window.data.posAnimation),t(["mousemove","touchmove"],s,"remove"),l(window.data.matrix?n(window.data.matrix,0,0):"none",window.data.matrixX+a(window.data.relativeX,"x")+"px",window.data.matrixY+a(window.data.relativeY,"y")+"px"),window.data.grab.classList.remove(window.data.class.down),window.data.move.classList.remove(window.data.class.move),o(window.data.move,"end"),t(["mousemove","touchmove"],c,"remove"))}function m(a,t){const n="string"==typeof a?parseInt(a.replace(/px/g,""),10):a;return 0===n||Number.isNaN(n)||t&&void 0===n?1:n}function v(a){return!!["x","y","all"].includes(a)}function p(a,n){const e=n.value||{},d=e instanceof Object?e.handle:e,i=function(a){if("string"==typeof a){const t=a.split(",");return{x:m(t[0]),y:void 0!==m(t[1])?m(t[1]):m(t[0])}}return"number"==typeof a?{x:m(a),y:m(a)}:a instanceof Object&&(a.x||a.y)?{x:m(a.x)||1,y:m(a.y)||1}:Array.isArray(a)?{x:m(a[0])||1,y:void 0!==m(a[1])?m(a[1],!0):m(a[0],!0)}:{x:1,y:1}}(e.snap),s=[];let w;w=e instanceof Object&&e.axis&&v(e.axis)?e.axis:v(n.arg)?n.arg:"all",d instanceof HTMLElement?s.push(d):document.querySelectorAll(d).forEach(a=>{s.push(a)}),0!==s.length?(a.classList.add(window.data.class.usesHandle),s.forEach(t=>{t.classList.add(window.data.class.handle),t.onmousedown=n=>r(t,a,w,i,n),t.ontouchstart=n=>r(t,a,w,i,n)})):(a.onmousedown=t=>r(a,a,w,i,t),a.ontouchstart=t=>r(a,a,w,i,t)),a.classList.add(window.data.class.initial),o(a,"setup"),t(["mouseup","touchend"],u)}const h=(a,t)=>{p(a,t)},f=(a,t)=>{a.onmousedown=null,a.ontouchstart=null;const n="object"==typeof t.oldValue?t.oldValue.handle:t.oldValue;document.querySelectorAll(n).forEach(t=>{t.onmousedown=null,t.ontouchstart=null,t.classList.remove(window.data.class.handle),a.classList.remove(window.data.class.usesHandle)}),t.oldValue&&Object.keys(t.oldValue).forEach(t=>{o(a,"update-"+t)}),p(a,t)};var g={install(a,t){window.data={},window.data.class={initial:"drag-draggable",usesHandle:"drag-uses-handle",handle:"drag-handle",down:"drag-down",move:"drag-move"};let n=!0;if(t){if(t.eventClass){const a=t.eventClass;Object.keys(a).forEach(t=>{a[t]&&(window.data.class[t]=a[t])})}"boolean"==typeof t.removeTransition&&(n=t.removeTransition)}const o=document.createElement("style");o.innerHTML=`.${window.data.class.initial}{position:relative;}.${window.data.class.initial}:not(.${window.data.class.usesHandle}),.${window.data.class.handle}{cursor:move;cursor:grab;cursor:-webkit-grab;}.${window.data.class.handle}.${window.data.class.down},.${window.data.class.initial}:not(.${window.data.class.usesHandle}).${window.data.class.down}{z-index:999;cursor:grabbing;cursor:-webkit-grabbing;}`,o.innerHTML+=!0===n?`.${window.data.class.move}{transition:none;}`:"",document.body.appendChild(o),a.directive("drag",{mounted(a,t){h(a,t)},updated(a,t){f(a,t)},inserted(a,t){h(a,t)},update(a,t){f(a,t)}})}};module.exports=g; 6 | -------------------------------------------------------------------------------- /dist/browser.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * v-drag v3.0.9 3 | * by Nil Vila and contributors 4 | */ 5 | var vdrag=function(){"use strict";function a(a,t){const n="x"===t?window.data.snapX:window.data.snapY;return Math.round(a/n)*n}function t(a,t,n="add"){a.forEach(a=>{document[n+"EventListener"](a,t,!1)})}function n(a,t,n){return`matrix(${a||"1, 0, 0, 1,"} ${t}, ${n})`}function o(a,t){a.dispatchEvent(new Event("v-drag-"+t))}function e(t,e){window.data.relativeX=window.data.mouseX*t,window.data.relativeY=window.data.mouseY*e,window.data.move.style.transform=n(window.data.matrix,window.data.matrixX+a(window.data.relativeX,"x"),window.data.matrixY+a(window.data.relativeY,"y")),o(window.data.move,"moving"),(window.getSelection?window.getSelection():document.selection).empty()}const d={x(){e(!0,!1)},y(){e(!1,!0)},all(){e(!0,!0)}};function i(){d[window.data.axis](window.data),window.data.posAnimation=requestAnimationFrame(i)}function s(){window.data.move.classList.add(window.data.class.move),window.data.posAnimation=requestAnimationFrame(i),t(["mousemove","touchmove"],s,"remove")}function w(a,t){let n=Number(window.getComputedStyle(window.data.move)[t].replace("px",""));if("none"!==a){const o=a.match(/[0-9.-]+/g);n+=Number(o[8-t.length])}return n}function l(a,t,n){window.data.move.style.transform=a,window.data.move.style.left=t,window.data.move.style.top=n}function c(a){a.preventDefault(),window.data.mouseX=(a.pageX||a.touches[0].pageX)-window.data.initialX,window.data.mouseY=(a.pageY||a.touches[0].pageY)-window.data.initialY,window.setTimeout(()=>{(a.clientY||a.touches[0].clientY)>.8*window.innerHeight&&(document.documentElement.scrollTop+=10),(a.clientY||a.touches[0].clientY)<.2*window.innerHeight&&(document.documentElement.scrollTop-=10),(a.clientX||a.touches[0].clientX)>.8*window.innerWidth&&(document.documentElement.scrollLeft+=10),(a.clientX||a.touches[0].clientX)<.2*window.innerWidth&&(document.documentElement.scrollLeft-=10)},100)}function r(a,e,d,i,r){r.preventDefault(),window.data.grab=a,window.data.move=e,window.data.axis=d,window.data.initialX=r.pageX||r.touches[0].pageX,window.data.initialY=r.pageY||r.touches[0].pageY,window.data.relativeX=0,window.data.relativeY=0,window.data.snapX=i.x,window.data.snapY=i.y;const u=window.getComputedStyle(window.data.move).transform;window.data.matrix="none"!==u&&u.match(/\d([^,]*,){4}/g);const m=w(u,"left"),v=w(u,"top");l(n(window.data.matrix,m,v),0,0),window.data.matrixX=m,window.data.matrixY=v,window.data.grab.classList.add(window.data.class.down),o(e,"down"),o(e,"start"),t(["mousemove","touchmove"],c),t(["mousemove","touchmove"],s)}function u(){window.data.grab&&window.data.move&&(cancelAnimationFrame(window.data.posAnimation),t(["mousemove","touchmove"],s,"remove"),l(window.data.matrix?n(window.data.matrix,0,0):"none",window.data.matrixX+a(window.data.relativeX,"x")+"px",window.data.matrixY+a(window.data.relativeY,"y")+"px"),window.data.grab.classList.remove(window.data.class.down),window.data.move.classList.remove(window.data.class.move),o(window.data.move,"end"),t(["mousemove","touchmove"],c,"remove"))}function m(a,t){const n="string"==typeof a?parseInt(a.replace(/px/g,""),10):a;return 0===n||Number.isNaN(n)||t&&void 0===n?1:n}function v(a){return!!["x","y","all"].includes(a)}function p(a,n){const e=n.value||{},d=e instanceof Object?e.handle:e,i=function(a){if("string"==typeof a){const t=a.split(",");return{x:m(t[0]),y:void 0!==m(t[1])?m(t[1]):m(t[0])}}return"number"==typeof a?{x:m(a),y:m(a)}:a instanceof Object&&(a.x||a.y)?{x:m(a.x)||1,y:m(a.y)||1}:Array.isArray(a)?{x:m(a[0])||1,y:void 0!==m(a[1])?m(a[1],!0):m(a[0],!0)}:{x:1,y:1}}(e.snap),s=[];let w;w=e instanceof Object&&e.axis&&v(e.axis)?e.axis:v(n.arg)?n.arg:"all",d instanceof HTMLElement?s.push(d):document.querySelectorAll(d).forEach(a=>{s.push(a)}),0!==s.length?(a.classList.add(window.data.class.usesHandle),s.forEach(t=>{t.classList.add(window.data.class.handle),t.onmousedown=n=>r(t,a,w,i,n),t.ontouchstart=n=>r(t,a,w,i,n)})):(a.onmousedown=t=>r(a,a,w,i,t),a.ontouchstart=t=>r(a,a,w,i,t)),a.classList.add(window.data.class.initial),o(a,"setup"),t(["mouseup","touchend"],u)}const h=(a,t)=>{p(a,t)},f=(a,t)=>{a.onmousedown=null,a.ontouchstart=null;const n="object"==typeof t.oldValue?t.oldValue.handle:t.oldValue;document.querySelectorAll(n).forEach(t=>{t.onmousedown=null,t.ontouchstart=null,t.classList.remove(window.data.class.handle),a.classList.remove(window.data.class.usesHandle)}),t.oldValue&&Object.keys(t.oldValue).forEach(t=>{o(a,"update-"+t)}),p(a,t)};return{install(a,t){window.data={},window.data.class={initial:"drag-draggable",usesHandle:"drag-uses-handle",handle:"drag-handle",down:"drag-down",move:"drag-move"};let n=!0;if(t){if(t.eventClass){const a=t.eventClass;Object.keys(a).forEach(t=>{a[t]&&(window.data.class[t]=a[t])})}"boolean"==typeof t.removeTransition&&(n=t.removeTransition)}const o=document.createElement("style");o.innerHTML=`.${window.data.class.initial}{position:relative;}.${window.data.class.initial}:not(.${window.data.class.usesHandle}),.${window.data.class.handle}{cursor:move;cursor:grab;cursor:-webkit-grab;}.${window.data.class.handle}.${window.data.class.down},.${window.data.class.initial}:not(.${window.data.class.usesHandle}).${window.data.class.down}{z-index:999;cursor:grabbing;cursor:-webkit-grabbing;}`,o.innerHTML+=!0===n?`.${window.data.class.move}{transition:none;}`:"",document.body.appendChild(o),a.directive("drag",{mounted(a,t){h(a,t)},updated(a,t){f(a,t)},inserted(a,t){h(a,t)},update(a,t){f(a,t)}})}}}(); 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v-drag 2 | 3 | The simplest way to integrate drag on Vue.js. 4 | 5 | Draggable elements are a common UX pattern, specially on touch screens. But as a developer, you might know how challenging it is to apply it with JavaScript. So to simplify things, v-drag was written. Its aim is to quickly integrate and customize draggable elements on projects using Vue.js. 6 | 7 | [![Build status](https://github.com/nil/v-drag/actions/workflows/build.yml/badge.svg)](https://github.com/nil/v-drag/actions/workflows/build.yml) 8 | [![npm package](https://github.com/nil/v-drag/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/nil/v-drag/actions/workflows/npm-publish.yml) 9 | [![Version](https://img.shields.io/npm/v/v-drag.svg)](https://www.npmjs.com/package/v-drag) 10 | [![License](https://img.shields.io/npm/l/v-drag.svg)](https://github.com/nil/v-drag/blob/master/LICENSE) 11 | 12 | ## Table of contents 13 | 14 | 1. [Installation](#installation) 15 | 2. [Usage](#usage) 16 | 3. [Options](#options) 17 | 1. [Axis](#axis) 18 | 2. [Snap](#snap) 19 | 3. [Handle](#handle) 20 | 4. [Vue events](#vue-events) 21 | 5. [Global configuration](#global-configuration) 22 | 1. [Event classes](#event-classes) 23 | 2. [Remove transitions](#remove-transitions) 24 | 25 | ## Installation 26 | 27 | ```sh 28 | npm install v-drag --save 29 | ``` 30 | 31 | v-drag’s source code is also available [uncompressed](https://raw.githubusercontent.com/nil/v-drag/master/src/index.js) and [minified](https://raw.githubusercontent.com/nil/v-drag/master/src/index.min.js). 32 | 33 | ## Usage 34 | 35 | Import v-drag into any file you are planning to use it: 36 | 37 | ```js 38 | import drag from "v-drag" 39 | ``` 40 | 41 | ```js 42 | const drag = require("v-drag"); 43 | ``` 44 | 45 | Then call the v-drag plugin: 46 | 47 | ```js 48 | Vue.use(drag, { 49 | // global configuration 50 | }); 51 | ``` 52 | 53 | No extra setup is necessary at this point. Add the `v-drag` attribute to any element to make it draggable: 54 | 55 | ```html 56 |
Drag me!
57 | ``` 58 | 59 | ## Options 60 | 61 | The default behavior for any element with the `v-drag` attribute is to be draggable in any direction and without a handle. However, this can be changed using an object or its equivalent shortcuts: 62 | 63 | ```html 64 |
65 |
Handle
66 |
67 | ``` 68 | 69 | Both the object and the values can be declared inline, as in the example above, or using the `data` object, computed properties, methods, props,… 70 | 71 | ### Axis 72 | 73 | Constrains the element to move only in one direction: horizontal or vertical. 74 | 75 | **Values** 76 | 77 | - `all`: all directions `default` 78 | - `x`: horizontal movement 79 | - `y`: vertical movement 80 | 81 | **Shortcut** 82 | 83 | ```html 84 |
Horizontal
85 | ``` 86 | 87 | ### Snap 88 | 89 | When dragging, the element will snap to the specified grid. You can use either a number or a string with units. 90 | 91 | ```html 92 |
Drag me in 100px increments
93 | ``` 94 | 95 | Using an array, different values can be declared for each axis: 96 | 97 | ```html 98 |
99 | Horizontal: 10px 100 | Vertical: 50px 101 |
102 | ``` 103 | 104 | ### Handle 105 | 106 | Informs that the element can only be dragged using another element, known as handle. It’s not necessary for the handle to be located inside the draggable element, and each element can have more than one handle. 107 | 108 | **Values** 109 | 110 | Handle’s name must be a selector (the same used to refer to the element in CSS) or a Ref. 111 | 112 | **Shortcut** 113 | 114 | ```html 115 |
Don’t drag me
116 |
Drag me
117 | ``` 118 | 119 | **Ref** 120 | 121 | To define handles using Refs, you must first set its value in `data` and replace it after the component is mounted: 122 | 123 | ```html 124 | 130 | 131 | 146 | ``` 147 | 148 | ## Vue events 149 | 150 | These events are emitted when the user makes the corresponding action. 151 | 152 | ```html 153 |
154 | Event on end 155 |
156 | ``` 157 | 158 | | Event | Description | 159 | |-------------------------|----------------------------------------------------------------------------| 160 | | `@v-drag-setup` | The component has completed the initial setup | 161 | | `@v-drag-start` | The user has pressed the draggable element and its mouse or finger is down | 162 | | `@v-drag-moving` | The user is moving the mouse or finger | 163 | | `@v-drag-end` | The user has released its mouse or finger | 164 | | `@v-drag-update` | Changes in the configuration of the draggable options | 165 | | `@v-drag-axis-update` | The axis has been updated | 166 | | `@v-drag-handle-update` | The handle has been updated | 167 | 168 | ## Global configuration 169 | 170 | ### Event classes 171 | 172 | v-drag uses CSS classes to add basic styling to the draggable elements. You can override one or multiple of the default classes when the plugin is called: 173 | 174 | ```js 175 | Vue.use(drag, { 176 | eventClass: { 177 | down: "is-pressed", 178 | move: "is-moving" 179 | } 180 | }); 181 | ``` 182 | 183 | This are the default classes with its values: 184 | 185 | | Name | Default value | Description | 186 | |-------------|--------------------|---------------------------------------------- | 187 | | `initial` | `drag-draggable` | The element is draggable | 188 | | `hasHandle` | `drag-uses-handle` | The element uses a handle | 189 | | `handle` | `drag-handle` | The element is the handle of another element | 190 | | `down` | `drag-down` | The user has pressed the element | 191 | | `move` | `drag-move` | The user has started to drag the element | 192 | 193 | ### Remove transitions 194 | 195 | By default, v-drag removes all transition animations to keep the dragging as smooth as possible. However, if you want to enable them, you can: 196 | 197 | ```js 198 | Vue.use(drag, { 199 | removeTransition: false // default: `true` 200 | }); 201 | ``` 202 | -------------------------------------------------------------------------------- /playground/src/components/ui/ConfigBar.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 51 | -------------------------------------------------------------------------------- /playground/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/parser@^7.16.4": 6 | version "7.18.5" 7 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.5.tgz#337062363436a893a2d22faa60be5bb37091c83c" 8 | 9 | "@carbon/icon-helpers@^10.29.0": 10 | version "10.31.0" 11 | resolved "https://registry.yarnpkg.com/@carbon/icon-helpers/-/icon-helpers-10.31.0.tgz#6b53d67164ddc8fa6770194821c4082e66de557e" 12 | 13 | "@carbon/icons-vue@^10.49.1": 14 | version "10.49.1" 15 | resolved "https://registry.yarnpkg.com/@carbon/icons-vue/-/icons-vue-10.49.1.tgz#fd6faddc7364160c5acd60c6eaf245e86a004403" 16 | dependencies: 17 | "@carbon/icon-helpers" "^10.29.0" 18 | 19 | "@nodelib/fs.scandir@2.1.5": 20 | version "2.1.5" 21 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 22 | dependencies: 23 | "@nodelib/fs.stat" "2.0.5" 24 | run-parallel "^1.1.9" 25 | 26 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 27 | version "2.0.5" 28 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 29 | 30 | "@nodelib/fs.walk@^1.2.3": 31 | version "1.2.8" 32 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 33 | dependencies: 34 | "@nodelib/fs.scandir" "2.1.5" 35 | fastq "^1.6.0" 36 | 37 | "@vitejs/plugin-vue@^2.3.3": 38 | version "2.3.3" 39 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz#fbf80cc039b82ac21a1acb0f0478de8f61fbf600" 40 | 41 | "@vue/compiler-core@3.2.37": 42 | version "3.2.37" 43 | resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.37.tgz#b3c42e04c0e0f2c496ff1784e543fbefe91e215a" 44 | dependencies: 45 | "@babel/parser" "^7.16.4" 46 | "@vue/shared" "3.2.37" 47 | estree-walker "^2.0.2" 48 | source-map "^0.6.1" 49 | 50 | "@vue/compiler-dom@3.2.37": 51 | version "3.2.37" 52 | resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5" 53 | dependencies: 54 | "@vue/compiler-core" "3.2.37" 55 | "@vue/shared" "3.2.37" 56 | 57 | "@vue/compiler-sfc@3.2.37": 58 | version "3.2.37" 59 | resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4" 60 | dependencies: 61 | "@babel/parser" "^7.16.4" 62 | "@vue/compiler-core" "3.2.37" 63 | "@vue/compiler-dom" "3.2.37" 64 | "@vue/compiler-ssr" "3.2.37" 65 | "@vue/reactivity-transform" "3.2.37" 66 | "@vue/shared" "3.2.37" 67 | estree-walker "^2.0.2" 68 | magic-string "^0.25.7" 69 | postcss "^8.1.10" 70 | source-map "^0.6.1" 71 | 72 | "@vue/compiler-ssr@3.2.37": 73 | version "3.2.37" 74 | resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz#4899d19f3a5fafd61524a9d1aee8eb0505313cff" 75 | dependencies: 76 | "@vue/compiler-dom" "3.2.37" 77 | "@vue/shared" "3.2.37" 78 | 79 | "@vue/devtools-api@^6.0.0-beta.11": 80 | version "6.1.4" 81 | resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.1.4.tgz#b4aec2f4b4599e11ba774a50c67fa378c9824e53" 82 | 83 | "@vue/reactivity-transform@3.2.37": 84 | version "3.2.37" 85 | resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz#0caa47c4344df4ae59f5a05dde2a8758829f8eca" 86 | dependencies: 87 | "@babel/parser" "^7.16.4" 88 | "@vue/compiler-core" "3.2.37" 89 | "@vue/shared" "3.2.37" 90 | estree-walker "^2.0.2" 91 | magic-string "^0.25.7" 92 | 93 | "@vue/reactivity@3.2.37": 94 | version "3.2.37" 95 | resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848" 96 | dependencies: 97 | "@vue/shared" "3.2.37" 98 | 99 | "@vue/runtime-core@3.2.37": 100 | version "3.2.37" 101 | resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz#7ba7c54bb56e5d70edfc2f05766e1ca8519966e3" 102 | dependencies: 103 | "@vue/reactivity" "3.2.37" 104 | "@vue/shared" "3.2.37" 105 | 106 | "@vue/runtime-dom@3.2.37": 107 | version "3.2.37" 108 | resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz#002bdc8228fa63949317756fb1e92cdd3f9f4bbd" 109 | dependencies: 110 | "@vue/runtime-core" "3.2.37" 111 | "@vue/shared" "3.2.37" 112 | csstype "^2.6.8" 113 | 114 | "@vue/server-renderer@3.2.37": 115 | version "3.2.37" 116 | resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.37.tgz#840a29c8dcc29bddd9b5f5ffa22b95c0e72afdfc" 117 | dependencies: 118 | "@vue/compiler-ssr" "3.2.37" 119 | "@vue/shared" "3.2.37" 120 | 121 | "@vue/shared@3.2.37": 122 | version "3.2.37" 123 | resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702" 124 | 125 | acorn-node@^1.8.2: 126 | version "1.8.2" 127 | resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" 128 | dependencies: 129 | acorn "^7.0.0" 130 | acorn-walk "^7.0.0" 131 | xtend "^4.0.2" 132 | 133 | acorn-walk@^7.0.0: 134 | version "7.2.0" 135 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" 136 | 137 | acorn@^7.0.0: 138 | version "7.4.1" 139 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" 140 | 141 | anymatch@~3.1.2: 142 | version "3.1.2" 143 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 144 | dependencies: 145 | normalize-path "^3.0.0" 146 | picomatch "^2.0.4" 147 | 148 | arg@^5.0.2: 149 | version "5.0.2" 150 | resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" 151 | 152 | autoprefixer@^10.4.7: 153 | version "10.4.7" 154 | resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.7.tgz#1db8d195f41a52ca5069b7593be167618edbbedf" 155 | dependencies: 156 | browserslist "^4.20.3" 157 | caniuse-lite "^1.0.30001335" 158 | fraction.js "^4.2.0" 159 | normalize-range "^0.1.2" 160 | picocolors "^1.0.0" 161 | postcss-value-parser "^4.2.0" 162 | 163 | binary-extensions@^2.0.0: 164 | version "2.2.0" 165 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 166 | 167 | braces@^3.0.2, braces@~3.0.2: 168 | version "3.0.2" 169 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 170 | dependencies: 171 | fill-range "^7.0.1" 172 | 173 | browserslist@^4.20.3: 174 | version "4.20.4" 175 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.4.tgz#98096c9042af689ee1e0271333dbc564b8ce4477" 176 | dependencies: 177 | caniuse-lite "^1.0.30001349" 178 | electron-to-chromium "^1.4.147" 179 | escalade "^3.1.1" 180 | node-releases "^2.0.5" 181 | picocolors "^1.0.0" 182 | 183 | camelcase-css@^2.0.1: 184 | version "2.0.1" 185 | resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" 186 | 187 | caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001349: 188 | version "1.0.30001354" 189 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001354.tgz#95c5efdb64148bb4870771749b9a619304755ce5" 190 | 191 | chokidar@^3.5.3: 192 | version "3.5.3" 193 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 194 | dependencies: 195 | anymatch "~3.1.2" 196 | braces "~3.0.2" 197 | glob-parent "~5.1.2" 198 | is-binary-path "~2.1.0" 199 | is-glob "~4.0.1" 200 | normalize-path "~3.0.0" 201 | readdirp "~3.6.0" 202 | optionalDependencies: 203 | fsevents "~2.3.2" 204 | 205 | color-name@^1.1.4: 206 | version "1.1.4" 207 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 208 | 209 | cssesc@^3.0.0: 210 | version "3.0.0" 211 | resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" 212 | 213 | csstype@^2.6.8: 214 | version "2.6.20" 215 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda" 216 | 217 | defined@^1.0.0: 218 | version "1.0.0" 219 | resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" 220 | 221 | detective@^5.2.1: 222 | version "5.2.1" 223 | resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034" 224 | dependencies: 225 | acorn-node "^1.8.2" 226 | defined "^1.0.0" 227 | minimist "^1.2.6" 228 | 229 | didyoumean@^1.2.2: 230 | version "1.2.2" 231 | resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" 232 | 233 | dlv@^1.1.3: 234 | version "1.1.3" 235 | resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" 236 | 237 | electron-to-chromium@^1.4.147: 238 | version "1.4.156" 239 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.156.tgz#fc398e1bfbe586135351ebfaf198473a82923af5" 240 | 241 | esbuild-android-64@0.14.43: 242 | version "0.14.43" 243 | resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.43.tgz#59bf3edad6863c27aa92bbb5c1d83a9a5c981495" 244 | 245 | esbuild-android-arm64@0.14.43: 246 | version "0.14.43" 247 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.43.tgz#0258704edf92ce2463af6d2900b844b5423bed63" 248 | 249 | esbuild-darwin-64@0.14.43: 250 | version "0.14.43" 251 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.43.tgz#72a47295678d4aa0656979baa8cf6d5c8c92656f" 252 | 253 | esbuild-darwin-arm64@0.14.43: 254 | version "0.14.43" 255 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.43.tgz#5f5823170b8d85b888957f0794e186caac447aca" 256 | 257 | esbuild-freebsd-64@0.14.43: 258 | version "0.14.43" 259 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.43.tgz#e4a48b08181053837e6cd9bda19ae0af94d493b0" 260 | 261 | esbuild-freebsd-arm64@0.14.43: 262 | version "0.14.43" 263 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.43.tgz#386e780d36c1dedf3a1cdab79e0bbacd873274e6" 264 | 265 | esbuild-linux-32@0.14.43: 266 | version "0.14.43" 267 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.43.tgz#040ed6b9ebf06d73acdf2acce7f1cd0c12fbc6a5" 268 | 269 | esbuild-linux-64@0.14.43: 270 | version "0.14.43" 271 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.43.tgz#8abbb7594ab6a008f2aae72d95d8a4fdc59d9000" 272 | 273 | esbuild-linux-arm64@0.14.43: 274 | version "0.14.43" 275 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.43.tgz#4e8e9ce77cbf7efec65e79e512b3d2fbd2da398f" 276 | 277 | esbuild-linux-arm@0.14.43: 278 | version "0.14.43" 279 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.43.tgz#9e41ee5e099c0ffdfd150da154330c2c0226cc96" 280 | 281 | esbuild-linux-mips64le@0.14.43: 282 | version "0.14.43" 283 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.43.tgz#4b41f465a787f91cc4fe7dffa0dcabf655935a1a" 284 | 285 | esbuild-linux-ppc64le@0.14.43: 286 | version "0.14.43" 287 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.43.tgz#ca15934f5b46728dd9ac05270e783e7feaca9eaf" 288 | 289 | esbuild-linux-riscv64@0.14.43: 290 | version "0.14.43" 291 | resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.43.tgz#70fce2b5a0605a67e58b5a357b0e00be1029836d" 292 | 293 | esbuild-linux-s390x@0.14.43: 294 | version "0.14.43" 295 | resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.43.tgz#318d03b4f4ccc7fa44ac7562121cf4a4529e477a" 296 | 297 | esbuild-netbsd-64@0.14.43: 298 | version "0.14.43" 299 | resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.43.tgz#86130ce204ef0162a96e863b55851efecc92f423" 300 | 301 | esbuild-openbsd-64@0.14.43: 302 | version "0.14.43" 303 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.43.tgz#0229dc2db2ded97b03bb93bba7646b30ffdf5d0d" 304 | 305 | esbuild-sunos-64@0.14.43: 306 | version "0.14.43" 307 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.43.tgz#17e316216eb9f1de25d52a9000356ae5b869e736" 308 | 309 | esbuild-windows-32@0.14.43: 310 | version "0.14.43" 311 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.43.tgz#a173757bc6dfd0f2656ff40b64f7f9290745778e" 312 | 313 | esbuild-windows-64@0.14.43: 314 | version "0.14.43" 315 | resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.43.tgz#c447b23126aad158c4fe6a394342cafd97926ed1" 316 | 317 | esbuild-windows-arm64@0.14.43: 318 | version "0.14.43" 319 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.43.tgz#3caed1b430d394d7a7836407b9d36c4750246e76" 320 | 321 | esbuild@^0.14.27: 322 | version "0.14.43" 323 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.43.tgz#c227d585c512d3e0f23b88f50b8e16501147f647" 324 | optionalDependencies: 325 | esbuild-android-64 "0.14.43" 326 | esbuild-android-arm64 "0.14.43" 327 | esbuild-darwin-64 "0.14.43" 328 | esbuild-darwin-arm64 "0.14.43" 329 | esbuild-freebsd-64 "0.14.43" 330 | esbuild-freebsd-arm64 "0.14.43" 331 | esbuild-linux-32 "0.14.43" 332 | esbuild-linux-64 "0.14.43" 333 | esbuild-linux-arm "0.14.43" 334 | esbuild-linux-arm64 "0.14.43" 335 | esbuild-linux-mips64le "0.14.43" 336 | esbuild-linux-ppc64le "0.14.43" 337 | esbuild-linux-riscv64 "0.14.43" 338 | esbuild-linux-s390x "0.14.43" 339 | esbuild-netbsd-64 "0.14.43" 340 | esbuild-openbsd-64 "0.14.43" 341 | esbuild-sunos-64 "0.14.43" 342 | esbuild-windows-32 "0.14.43" 343 | esbuild-windows-64 "0.14.43" 344 | esbuild-windows-arm64 "0.14.43" 345 | 346 | escalade@^3.1.1: 347 | version "3.1.1" 348 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 349 | 350 | estree-walker@^2.0.2: 351 | version "2.0.2" 352 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" 353 | 354 | fast-glob@^3.2.11: 355 | version "3.2.11" 356 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" 357 | dependencies: 358 | "@nodelib/fs.stat" "^2.0.2" 359 | "@nodelib/fs.walk" "^1.2.3" 360 | glob-parent "^5.1.2" 361 | merge2 "^1.3.0" 362 | micromatch "^4.0.4" 363 | 364 | fastq@^1.6.0: 365 | version "1.13.0" 366 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" 367 | dependencies: 368 | reusify "^1.0.4" 369 | 370 | fill-range@^7.0.1: 371 | version "7.0.1" 372 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 373 | dependencies: 374 | to-regex-range "^5.0.1" 375 | 376 | fraction.js@^4.2.0: 377 | version "4.2.0" 378 | resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" 379 | 380 | fsevents@~2.3.2: 381 | version "2.3.2" 382 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 383 | 384 | function-bind@^1.1.1: 385 | version "1.1.1" 386 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 387 | 388 | glob-parent@^5.1.2, glob-parent@~5.1.2: 389 | version "5.1.2" 390 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 391 | dependencies: 392 | is-glob "^4.0.1" 393 | 394 | glob-parent@^6.0.2: 395 | version "6.0.2" 396 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" 397 | dependencies: 398 | is-glob "^4.0.3" 399 | 400 | has@^1.0.3: 401 | version "1.0.3" 402 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 403 | dependencies: 404 | function-bind "^1.1.1" 405 | 406 | is-binary-path@~2.1.0: 407 | version "2.1.0" 408 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 409 | dependencies: 410 | binary-extensions "^2.0.0" 411 | 412 | is-core-module@^2.8.1: 413 | version "2.9.0" 414 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" 415 | dependencies: 416 | has "^1.0.3" 417 | 418 | is-extglob@^2.1.1: 419 | version "2.1.1" 420 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 421 | 422 | is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: 423 | version "4.0.3" 424 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 425 | dependencies: 426 | is-extglob "^2.1.1" 427 | 428 | is-number@^7.0.0: 429 | version "7.0.0" 430 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 431 | 432 | lilconfig@^2.0.5: 433 | version "2.0.5" 434 | resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" 435 | 436 | magic-string@^0.25.7: 437 | version "0.25.9" 438 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" 439 | dependencies: 440 | sourcemap-codec "^1.4.8" 441 | 442 | merge2@^1.3.0: 443 | version "1.4.1" 444 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 445 | 446 | micromatch@^4.0.4: 447 | version "4.0.5" 448 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" 449 | dependencies: 450 | braces "^3.0.2" 451 | picomatch "^2.3.1" 452 | 453 | minimist@^1.2.6: 454 | version "1.2.6" 455 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 456 | 457 | nanoid@^3.3.4: 458 | version "3.3.4" 459 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" 460 | 461 | node-releases@^2.0.5: 462 | version "2.0.5" 463 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" 464 | 465 | normalize-path@^3.0.0, normalize-path@~3.0.0: 466 | version "3.0.0" 467 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 468 | 469 | normalize-range@^0.1.2: 470 | version "0.1.2" 471 | resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" 472 | 473 | object-hash@^3.0.0: 474 | version "3.0.0" 475 | resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" 476 | 477 | path-parse@^1.0.7: 478 | version "1.0.7" 479 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 480 | 481 | picocolors@^1.0.0: 482 | version "1.0.0" 483 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 484 | 485 | picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: 486 | version "2.3.1" 487 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 488 | 489 | pify@^2.3.0: 490 | version "2.3.0" 491 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 492 | 493 | postcss-import@^14.1.0: 494 | version "14.1.0" 495 | resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0" 496 | dependencies: 497 | postcss-value-parser "^4.0.0" 498 | read-cache "^1.0.0" 499 | resolve "^1.1.7" 500 | 501 | postcss-js@^4.0.0: 502 | version "4.0.0" 503 | resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00" 504 | dependencies: 505 | camelcase-css "^2.0.1" 506 | 507 | postcss-load-config@^3.1.4: 508 | version "3.1.4" 509 | resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855" 510 | dependencies: 511 | lilconfig "^2.0.5" 512 | yaml "^1.10.2" 513 | 514 | postcss-nested@5.0.6: 515 | version "5.0.6" 516 | resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc" 517 | dependencies: 518 | postcss-selector-parser "^6.0.6" 519 | 520 | postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.6: 521 | version "6.0.10" 522 | resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" 523 | dependencies: 524 | cssesc "^3.0.0" 525 | util-deprecate "^1.0.2" 526 | 527 | postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: 528 | version "4.2.0" 529 | resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" 530 | 531 | postcss@^8.1.10, postcss@^8.4.13, postcss@^8.4.14: 532 | version "8.4.14" 533 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" 534 | dependencies: 535 | nanoid "^3.3.4" 536 | picocolors "^1.0.0" 537 | source-map-js "^1.0.2" 538 | 539 | queue-microtask@^1.2.2: 540 | version "1.2.3" 541 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 542 | 543 | quick-lru@^5.1.1: 544 | version "5.1.1" 545 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" 546 | 547 | read-cache@^1.0.0: 548 | version "1.0.0" 549 | resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" 550 | dependencies: 551 | pify "^2.3.0" 552 | 553 | readdirp@~3.6.0: 554 | version "3.6.0" 555 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 556 | dependencies: 557 | picomatch "^2.2.1" 558 | 559 | resolve@^1.1.7, resolve@^1.22.0: 560 | version "1.22.0" 561 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" 562 | dependencies: 563 | is-core-module "^2.8.1" 564 | path-parse "^1.0.7" 565 | supports-preserve-symlinks-flag "^1.0.0" 566 | 567 | reusify@^1.0.4: 568 | version "1.0.4" 569 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 570 | 571 | rollup@^2.59.0: 572 | version "2.75.6" 573 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.6.tgz#ac4dc8600f95942a0180f61c7c9d6200e374b439" 574 | optionalDependencies: 575 | fsevents "~2.3.2" 576 | 577 | run-parallel@^1.1.9: 578 | version "1.2.0" 579 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 580 | dependencies: 581 | queue-microtask "^1.2.2" 582 | 583 | source-map-js@^1.0.2: 584 | version "1.0.2" 585 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 586 | 587 | source-map@^0.6.1: 588 | version "0.6.1" 589 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 590 | 591 | sourcemap-codec@^1.4.8: 592 | version "1.4.8" 593 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" 594 | 595 | supports-preserve-symlinks-flag@^1.0.0: 596 | version "1.0.0" 597 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 598 | 599 | tailwindcss@^3.0.24: 600 | version "3.1.3" 601 | resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.3.tgz#b9ef2c1ae537c339679e8e89635af8e143d1c7eb" 602 | dependencies: 603 | arg "^5.0.2" 604 | chokidar "^3.5.3" 605 | color-name "^1.1.4" 606 | detective "^5.2.1" 607 | didyoumean "^1.2.2" 608 | dlv "^1.1.3" 609 | fast-glob "^3.2.11" 610 | glob-parent "^6.0.2" 611 | is-glob "^4.0.3" 612 | lilconfig "^2.0.5" 613 | normalize-path "^3.0.0" 614 | object-hash "^3.0.0" 615 | picocolors "^1.0.0" 616 | postcss "^8.4.14" 617 | postcss-import "^14.1.0" 618 | postcss-js "^4.0.0" 619 | postcss-load-config "^3.1.4" 620 | postcss-nested "5.0.6" 621 | postcss-selector-parser "^6.0.10" 622 | postcss-value-parser "^4.2.0" 623 | quick-lru "^5.1.1" 624 | resolve "^1.22.0" 625 | 626 | to-regex-range@^5.0.1: 627 | version "5.0.1" 628 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 629 | dependencies: 630 | is-number "^7.0.0" 631 | 632 | util-deprecate@^1.0.2: 633 | version "1.0.2" 634 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 635 | 636 | vite@^2.9.13: 637 | version "2.9.13" 638 | resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.13.tgz#859cb5d4c316c0d8c6ec9866045c0f7858ca6abc" 639 | dependencies: 640 | esbuild "^0.14.27" 641 | postcss "^8.4.13" 642 | resolve "^1.22.0" 643 | rollup "^2.59.0" 644 | optionalDependencies: 645 | fsevents "~2.3.2" 646 | 647 | vue@^3.2.25: 648 | version "3.2.37" 649 | resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.37.tgz#da220ccb618d78579d25b06c7c21498ca4e5452e" 650 | dependencies: 651 | "@vue/compiler-dom" "3.2.37" 652 | "@vue/compiler-sfc" "3.2.37" 653 | "@vue/runtime-dom" "3.2.37" 654 | "@vue/server-renderer" "3.2.37" 655 | "@vue/shared" "3.2.37" 656 | 657 | vuex@^4.0.2: 658 | version "4.0.2" 659 | resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.0.2.tgz#f896dbd5bf2a0e963f00c67e9b610de749ccacc9" 660 | dependencies: 661 | "@vue/devtools-api" "^6.0.0-beta.11" 662 | 663 | xtend@^4.0.2: 664 | version "4.0.2" 665 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 666 | 667 | yaml@^1.10.2: 668 | version "1.10.2" 669 | resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" 670 | --------------------------------------------------------------------------------