├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── ci.yml │ ├── codeql-analysis.yml │ └── release.yml ├── .gitignore ├── .prettierrc.yml ├── README.md ├── build.js ├── dist ├── composables │ ├── useDraggable.d.ts │ ├── useInteractContext.d.ts │ └── useResizable.d.ts ├── index.d.ts ├── vue-interact.js └── vue-interact.umd.cjs ├── docs ├── .vuepress │ ├── client.ts │ ├── config.ts │ ├── navbar.ts │ ├── public │ │ └── assets │ │ │ └── VueInteract.svg │ ├── sidebar.ts │ └── styles │ │ └── index.scss ├── README.md └── guide │ ├── composables │ ├── components │ │ ├── DemoUseDragAndResize.vue │ │ ├── DemoUseDraggable.vue │ │ └── DemoUseResizable.vue │ ├── index.md │ ├── use_draggable.md │ └── use_resizable.md │ └── getting_started.md ├── jest.config.ts ├── package.json ├── pnpm-lock.yaml ├── src ├── composables │ ├── useDraggable.ts │ ├── useInteractContext.ts │ └── useResizable.ts ├── index.ts └── types │ ├── vue-interact.d.ts │ └── vue.d.ts ├── tsconfig.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | env: { 6 | browser: true, 7 | }, 8 | extends: [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended", 12 | "prettier", 13 | ], 14 | // required to lint *.vue files 15 | plugins: ['@typescript-eslint', 'prettier'], 16 | // add your custom rules here 17 | rules: { 18 | // allow debugger during development 19 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 20 | 'arrow-parens': 'off', 21 | 'no-param-reassign': 'off', 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ["dev", "master"] 6 | pull_request: 7 | branches: ["master", "dev"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [18.x, 20.x] 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: pnpm install 23 | - run: pnpm run test:ci 24 | - run: pnpm run build 25 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ dev, master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ dev ] 20 | schedule: 21 | - cron: '23 6 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'javascript' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Publish NPM Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: 18 15 | - run: npm ci 16 | - run: npm run build 17 | 18 | publish-npm: 19 | needs: build 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v3 23 | - uses: actions/setup-node@v3 24 | with: 25 | node-version: 18 26 | registry-url: https://registry.npmjs.org/ 27 | - run: npm ci 28 | - run: npm publish 29 | env: 30 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | *.swp 7 | .idea/ 8 | .temp/ 9 | .cache/ 10 | coverage/ 11 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | singleQuote: true 2 | semi: true 3 | tabWidth: 4 4 | trailingComma: all 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-interact 2 | 3 | > A VueJS implementation of [InteractJS](http://interactjs.io) 4 | 5 | [![Netlify Status](https://api.netlify.com/api/v1/badges/0d134e46-98be-4533-a02f-fbf9e0358879/deploy-status)](https://app.netlify.com/sites/vue-interact/deploys) 6 | 7 | :book: [Checkout the documentation](https://vue-interact.netlify.app/) 8 | 9 | ## Build Setup 10 | 11 | ```bash 12 | npm install vue-interact --save 13 | # or 14 | yarn add vue-interact 15 | ``` 16 | 17 | ## ©️ License 18 | 19 | [MIT](http://opensource.org/licenses/MIT) 20 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | require('esbuild').build({ 2 | entryPoints: ['src/index.ts'], 3 | bundle: true, 4 | minify: true, 5 | target: 'esNext', 6 | outfile: 'dist/vue-interact.min.js', 7 | external: ['interactjs', 'vue'], 8 | tsconfig: 'tsconfig.json', 9 | }); -------------------------------------------------------------------------------- /dist/composables/useDraggable.d.ts: -------------------------------------------------------------------------------- 1 | import { DraggableOptions } from '@interactjs/actions/drag/plugin'; 2 | import { InteractContext } from './useInteractContext'; 3 | export interface IPosition { 4 | x: number; 5 | y: number; 6 | } 7 | declare const useDraggable: (context: InteractContext, interactOptions?: DraggableOptions) => { 8 | init: () => void; 9 | position: import('vue').Ref; 10 | draggableOptions: import('vue').WritableComputedRef; 11 | isDragging: import('vue').Ref; 12 | }; 13 | export default useDraggable; 14 | -------------------------------------------------------------------------------- /dist/composables/useInteractContext.d.ts: -------------------------------------------------------------------------------- 1 | import { Interactable } from '@interactjs/types'; 2 | import { default as interact } from 'interactjs'; 3 | import { Ref } from 'vue'; 4 | export interface IPosition { 5 | x: number; 6 | y: number; 7 | } 8 | export interface ISizeData { 9 | width: number; 10 | height: number; 11 | } 12 | export interface InteractContext { 13 | interactable: Ref; 14 | interact: typeof interact; 15 | position: Ref; 16 | size: Ref; 17 | } 18 | declare const useInteractContext: (elRef: Ref) => InteractContext; 19 | export default useInteractContext; 20 | -------------------------------------------------------------------------------- /dist/composables/useResizable.d.ts: -------------------------------------------------------------------------------- 1 | import { ResizableOptions } from '@interactjs/actions/resize/plugin'; 2 | import { InteractContext } from './useInteractContext'; 3 | declare const useResizable: (context: InteractContext, interactOptions: ResizableOptions) => { 4 | init: () => void; 5 | resizeData: import('vue').Ref; 6 | position: import('vue').Ref; 7 | resizableOptions: import('vue').WritableComputedRef; 8 | isResizing: import('vue').Ref; 9 | }; 10 | export default useResizable; 11 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Plugin } from 'vue'; 2 | import { default as useInteractContext } from './composables/useInteractContext'; 3 | import { default as useDraggable } from './composables/useDraggable'; 4 | import { default as useResizable } from './composables/useResizable'; 5 | export interface IVueInteractOptions { 6 | installInject?: boolean; 7 | installGlobalProperty?: boolean; 8 | } 9 | declare const VueInteract: Plugin; 10 | export { useInteractContext, useDraggable, useResizable }; 11 | export default VueInteract; 12 | -------------------------------------------------------------------------------- /dist/vue-interact.umd.cjs: -------------------------------------------------------------------------------- 1 | (function($,Y){typeof exports=="object"&&typeof module<"u"?Y(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],Y):($=typeof globalThis<"u"?globalThis:$||self,Y($.VueInteract={},$.Vue))})(this,function($,Y){"use strict";var _n=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Pn(P){return P&&P.__esModule&&Object.prototype.hasOwnProperty.call(P,"default")?P.default:P}var De={exports:{}};De.exports,function(P,R){(function(j,I){P.exports=I()})(_n,function(){function j(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(t,i).enumerable})),n.push.apply(n,r)}return n}function I(t){for(var e=1;e"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}();return function(){var n,r=B(t);if(e){var i=B(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return function(o,a){if(a&&(typeof a=="object"||typeof a=="function"))return a;if(a!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return ae(o)}(this,n)}}function se(){return se=typeof Reflect<"u"&&Reflect.get?Reflect.get.bind():function(t,e,n){var r=function(o,a){for(;!Object.prototype.hasOwnProperty.call(o,a)&&(o=B(o))!==null;);return o}(t,e);if(r){var i=Object.getOwnPropertyDescriptor(r,e);return i.get?i.get.call(arguments.length<3?t:n):i.value}},se.apply(this,arguments)}function ge(t){var e=function(n,r){if(typeof n!="object"||n===null)return n;var i=n[Symbol.toPrimitive];if(i!==void 0){var o=i.call(n,r);if(typeof o!="object")return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)}(t,"string");return typeof e=="symbol"?e:e+""}var Et=function(t){return!(!t||!t.Window)&&t instanceof t.Window},Tt=void 0,ce=void 0;function St(t){Tt=t;var e=t.document.createTextNode("");e.ownerDocument!==t.document&&typeof t.wrap=="function"&&t.wrap(e)===e&&(t=t.wrap(t)),ce=t}function U(t){return Et(t)?t:(t.ownerDocument||t).defaultView||ce.window}typeof window<"u"&&window&&St(window);var Me=function(t){return!!t&&M(t)==="object"},_t=function(t){return typeof t=="function"},d={window:function(t){return t===ce||Et(t)},docFrag:function(t){return Me(t)&&t.nodeType===11},object:Me,func:_t,number:function(t){return typeof t=="number"},bool:function(t){return typeof t=="boolean"},string:function(t){return typeof t=="string"},element:function(t){if(!t||M(t)!=="object")return!1;var e=U(t)||ce;return/object|function/.test(typeof Element>"u"?"undefined":M(Element))?t instanceof Element||t instanceof e.Element:t.nodeType===1&&typeof t.nodeName=="string"},plainObject:function(t){return Me(t)&&!!t.constructor&&/function Object\b/.test(t.constructor.toString())},array:function(t){return Me(t)&&t.length!==void 0&&_t(t.splice)}};function Ue(t){var e=t.interaction;if(e.prepared.name==="drag"){var n=e.prepared.axis;n==="x"?(e.coords.cur.page.y=e.coords.start.page.y,e.coords.cur.client.y=e.coords.start.client.y,e.coords.velocity.client.y=0,e.coords.velocity.page.y=0):n==="y"&&(e.coords.cur.page.x=e.coords.start.page.x,e.coords.cur.client.x=e.coords.start.client.x,e.coords.velocity.client.x=0,e.coords.velocity.page.x=0)}}function Pt(t){var e=t.iEvent,n=t.interaction;if(n.prepared.name==="drag"){var r=n.prepared.axis;if(r==="x"||r==="y"){var i=r==="x"?"y":"x";e.page[i]=n.coords.start.page[i],e.client[i]=n.coords.start.client[i],e.delta[i]=0}}}var ze={id:"actions/drag",install:function(t){var e=t.actions,n=t.Interactable,r=t.defaults;n.prototype.draggable=ze.draggable,e.map.drag=ze,e.methodDict.drag="draggable",r.actions.drag=ze.defaults},listeners:{"interactions:before-action-move":Ue,"interactions:action-resume":Ue,"interactions:action-move":Pt,"auto-start:check":function(t){var e=t.interaction,n=t.interactable,r=t.buttons,i=n.options.drag;if(i&&i.enabled&&(!e.pointerIsDown||!/mouse|pointer/.test(e.pointerType)||r&n.options.drag.mouseButtons))return t.action={name:"drag",axis:i.lockAxis==="start"?i.startAxis:i.lockAxis},!1}},draggable:function(t){return d.object(t)?(this.options.drag.enabled=t.enabled!==!1,this.setPerAction("drag",t),this.setOnEvents("drag",t),/^(xy|x|y|start)$/.test(t.lockAxis)&&(this.options.drag.lockAxis=t.lockAxis),/^(xy|x|y)$/.test(t.startAxis)&&(this.options.drag.startAxis=t.startAxis),this):d.bool(t)?(this.options.drag.enabled=t,this):this.options.drag},beforeMove:Ue,move:Pt,defaults:{startAxis:"xy",lockAxis:"xy"},getCursor:function(){return"move"},filterEventType:function(t){return t.search("drag")===0}},Ot=ze,L={init:function(t){var e=t;L.document=e.document,L.DocumentFragment=e.DocumentFragment||de,L.SVGElement=e.SVGElement||de,L.SVGSVGElement=e.SVGSVGElement||de,L.SVGElementInstance=e.SVGElementInstance||de,L.Element=e.Element||de,L.HTMLElement=e.HTMLElement||L.Element,L.Event=e.Event,L.Touch=e.Touch||de,L.PointerEvent=e.PointerEvent||e.MSPointerEvent},document:null,DocumentFragment:null,SVGElement:null,SVGSVGElement:null,SVGElementInstance:null,Element:null,HTMLElement:null,Event:null,Touch:null,PointerEvent:null};function de(){}var A=L,q={init:function(t){var e=A.Element,n=t.navigator||{};q.supportsTouch="ontouchstart"in t||d.func(t.DocumentTouch)&&A.document instanceof t.DocumentTouch,q.supportsPointerEvent=n.pointerEnabled!==!1&&!!A.PointerEvent,q.isIOS=/iP(hone|od|ad)/.test(n.platform),q.isIOS7=/iP(hone|od|ad)/.test(n.platform)&&/OS 7[^\d]/.test(n.appVersion),q.isIe9=/MSIE 9/.test(n.userAgent),q.isOperaMobile=n.appName==="Opera"&&q.supportsTouch&&/Presto/.test(n.userAgent),q.prefixedMatchesSelector="matches"in e.prototype?"matches":"webkitMatchesSelector"in e.prototype?"webkitMatchesSelector":"mozMatchesSelector"in e.prototype?"mozMatchesSelector":"oMatchesSelector"in e.prototype?"oMatchesSelector":"msMatchesSelector",q.pEventTypes=q.supportsPointerEvent?A.PointerEvent===t.MSPointerEvent?{up:"MSPointerUp",down:"MSPointerDown",over:"mouseover",out:"mouseout",move:"MSPointerMove",cancel:"MSPointerCancel"}:{up:"pointerup",down:"pointerdown",over:"pointerover",out:"pointerout",move:"pointermove",cancel:"pointercancel"}:null,q.wheelEvent=A.document&&"onmousewheel"in A.document?"mousewheel":"wheel"},supportsTouch:null,supportsPointerEvent:null,isIOS7:null,isIOS:null,isIe9:null,isOperaMobile:null,prefixedMatchesSelector:null,pEventTypes:null,wheelEvent:null},G=q;function le(t,e){if(t.contains)return t.contains(e);for(;e;){if(e===t)return!0;e=e.parentNode}return!1}function kt(t,e){for(;d.element(t);){if(ee(t,e))return t;t=H(t)}return null}function H(t){var e=t.parentNode;if(d.docFrag(e)){for(;(e=e.host)&&d.docFrag(e););return e}return e}function ee(t,e){return ce!==Tt&&(e=e.replace(/\/deep\//g," ")),t[G.prefixedMatchesSelector](e)}var He=function(t){return t.parentNode||t.host};function Dt(t,e){for(var n,r=[],i=t;(n=He(i))&&i!==e&&n!==i.ownerDocument;)r.unshift(i),i=n;return r}function Ke(t,e,n){for(;d.element(t);){if(ee(t,e))return!0;if((t=H(t))===n)return ee(t,e)}return!1}function It(t){return t.correspondingUseElement||t}function Je(t){var e=t instanceof A.SVGElement?t.getBoundingClientRect():t.getClientRects()[0];return e&&{left:e.left,right:e.right,top:e.top,bottom:e.bottom,width:e.width||e.right-e.left,height:e.height||e.bottom-e.top}}function Qe(t){var e,n=Je(t);if(!G.isIOS7&&n){var r={x:(e=(e=U(t))||ce).scrollX||e.document.documentElement.scrollLeft,y:e.scrollY||e.document.documentElement.scrollTop};n.left+=r.x,n.right+=r.x,n.top+=r.y,n.bottom+=r.y}return n}function Mt(t){for(var e=[];t;)e.push(t),t=H(t);return e}function zt(t){return!!d.string(t)&&(A.document.querySelector(t),!0)}function x(t,e){for(var n in e)t[n]=e[n];return t}function At(t,e,n){return t==="parent"?H(n):t==="self"?e.getRect(n):kt(n,t)}function me(t,e,n,r){var i=t;return d.string(i)?i=At(i,e,n):d.func(i)&&(i=i.apply(void 0,r)),d.element(i)&&(i=Qe(i)),i}function Ae(t){return t&&{x:"x"in t?t.x:t.left,y:"y"in t?t.y:t.top}}function Ze(t){return!t||"x"in t&&"y"in t||((t=x({},t)).x=t.left||0,t.y=t.top||0,t.width=t.width||(t.right||0)-t.x,t.height=t.height||(t.bottom||0)-t.y),t}function Re(t,e,n){t.left&&(e.left+=n.x),t.right&&(e.right+=n.x),t.top&&(e.top+=n.y),t.bottom&&(e.bottom+=n.y),e.width=e.right-e.left,e.height=e.bottom-e.top}function ye(t,e,n){var r=n&&t.options[n];return Ae(me(r&&r.origin||t.options.origin,t,e,[t&&e]))||{x:0,y:0}}function ue(t,e){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:function(c){return!0},r=arguments.length>3?arguments[3]:void 0;if(r=r||{},d.string(t)&&t.search(" ")!==-1&&(t=Rt(t)),d.array(t))return t.forEach(function(c){return ue(c,e,n,r)}),r;if(d.object(t)&&(e=t,t=""),d.func(e)&&n(t))r[t]=r[t]||[],r[t].push(e);else if(d.array(e))for(var i=0,o=e;i1?Xt(e):e[0];Ft(r,t.page),function(i,o){o=o||{},G.isOperaMobile&&Ct(i)?Fe("screen",i,o):Fe("client",i,o)}(r,t.client),t.timeStamp=n}function et(t){var e=[];return d.array(t)?(e[0]=t[0],e[1]=t[1]):t.type==="touchend"?t.touches.length===1?(e[0]=t.touches[0],e[1]=t.changedTouches[0]):t.touches.length===0&&(e[0]=t.changedTouches[0],e[1]=t.changedTouches[1]):(e[0]=t.touches[0],e[1]=t.touches[1]),e}function Xt(t){for(var e={pageX:0,pageY:0,clientX:0,clientY:0,screenX:0,screenY:0},n=0;n=(parseInt(U(b).getComputedStyle(b).zIndex,10)||0)&&(y=_);else y=_}else y=_}return y}(a);return r.activeDrops[h]||null}function ot(t,e,n){var r=t.dropState,i={enter:null,leave:null,activate:null,deactivate:null,move:null,drop:null};return n.type==="dragstart"&&(i.activate=new he(r,n,"dropactivate"),i.activate.target=null,i.activate.dropzone=null),n.type==="dragend"&&(i.deactivate=new he(r,n,"dropdeactivate"),i.deactivate.target=null,i.deactivate.dropzone=null),r.rejected||(r.cur.element!==r.prev.element&&(r.prev.dropzone&&(i.leave=new he(r,n,"dragleave"),n.dragLeave=i.leave.target=r.prev.element,n.prevDropzone=i.leave.dropzone=r.prev.dropzone),r.cur.dropzone&&(i.enter=new he(r,n,"dragenter"),n.dragEnter=r.cur.element,n.dropzone=r.cur.dropzone)),n.type==="dragend"&&r.cur.dropzone&&(i.drop=new he(r,n,"drop"),n.dropzone=r.cur.dropzone,n.relatedTarget=r.cur.element),n.type==="dragmove"&&r.cur.dropzone&&(i.move=new he(r,n,"dropmove"),n.dropzone=r.cur.dropzone)),i}function at(t,e){var n=t.dropState,r=n.activeDrops,i=n.cur,o=n.prev;e.leave&&o.dropzone.fire(e.leave),e.enter&&i.dropzone.fire(e.enter),e.move&&i.dropzone.fire(e.move),e.drop&&i.dropzone.fire(e.drop),e.deactivate&&Bt(r,e.deactivate),n.prev.dropzone=i.dropzone,n.prev.element=i.element}function Wt(t,e){var n=t.interaction,r=t.iEvent,i=t.event;if(r.type==="dragmove"||r.type==="dragend"){var o=n.dropState;e.dynamicDrop&&(o.activeDrops=it(e,n.element));var a=r,s=Gt(n,a,i);o.rejected=o.rejected&&!!s&&s.dropzone===o.cur.dropzone&&s.element===o.cur.element,o.cur.dropzone=s&&s.dropzone,o.cur.element=s&&s.element,o.events=ot(n,0,a)}}var $t={id:"actions/drop",install:function(t){var e=t.actions,n=t.interactStatic,r=t.Interactable,i=t.defaults;t.usePlugin(Ot),r.prototype.dropzone=function(o){return function(a,s){if(d.object(s)){if(a.options.drop.enabled=s.enabled!==!1,s.listeners){var c=ue(s.listeners),u=Object.keys(c).reduce(function(p,f){return p[/^(enter|leave)/.test(f)?"drag".concat(f):/^(activate|deactivate|move)/.test(f)?"drop".concat(f):f]=c[f],p},{}),l=a.options.drop.listeners;l&&a.off(l),a.on(u),a.options.drop.listeners=u}return d.func(s.ondrop)&&a.on("drop",s.ondrop),d.func(s.ondropactivate)&&a.on("dropactivate",s.ondropactivate),d.func(s.ondropdeactivate)&&a.on("dropdeactivate",s.ondropdeactivate),d.func(s.ondragenter)&&a.on("dragenter",s.ondragenter),d.func(s.ondragleave)&&a.on("dragleave",s.ondragleave),d.func(s.ondropmove)&&a.on("dropmove",s.ondropmove),/^(pointer|center)$/.test(s.overlap)?a.options.drop.overlap=s.overlap:d.number(s.overlap)&&(a.options.drop.overlap=Math.max(Math.min(1,s.overlap),0)),"accept"in s&&(a.options.drop.accept=s.accept),"checker"in s&&(a.options.drop.checker=s.checker),a}return d.bool(s)?(a.options.drop.enabled=s,a):a.options.drop}(this,o)},r.prototype.dropCheck=function(o,a,s,c,u,l){return function(p,f,v,h,g,y,m){var b=!1;if(!(m=m||p.getRect(y)))return!!p.options.drop.checker&&p.options.drop.checker(f,v,b,p,y,h,g);var T=p.options.drop.overlap;if(T==="pointer"){var _=ye(h,g,"drag"),w=Ft(f);w.x+=_.x,w.y+=_.y;var S=w.x>m.left&&w.xm.top&&w.y=m.left&&V<=m.right&&W>=m.top&&W<=m.bottom}return D&&d.number(T)&&(b=Math.max(0,Math.min(m.right,D.right)-Math.max(m.left,D.left))*Math.max(0,Math.min(m.bottom,D.bottom)-Math.max(m.top,D.top))/(D.width*D.height)>=T),p.options.drop.checker&&(b=p.options.drop.checker(f,v,b,p,y,h,g)),b}(this,o,a,s,c,u,l)},n.dynamicDrop=function(o){return d.bool(o)?(t.dynamicDrop=o,n):t.dynamicDrop},x(e.phaselessTypes,{dragenter:!0,dragleave:!0,dropactivate:!0,dropdeactivate:!0,dropmove:!0,drop:!0}),e.methodDict.drop="dropzone",t.dynamicDrop=!1,i.actions.drop=$t.defaults},listeners:{"interactions:before-action-start":function(t){var e=t.interaction;e.prepared.name==="drag"&&(e.dropState={cur:{dropzone:null,element:null},prev:{dropzone:null,element:null},rejected:null,events:null,activeDrops:[]})},"interactions:after-action-start":function(t,e){var n=t.interaction,r=(t.event,t.iEvent);if(n.prepared.name==="drag"){var i=n.dropState;i.activeDrops=[],i.events={},i.activeDrops=it(e,n.element),i.events=ot(n,0,r),i.events.activate&&(Bt(i.activeDrops,i.events.activate),e.fire("actions/drop:start",{interaction:n,dragEvent:r}))}},"interactions:action-move":Wt,"interactions:after-action-move":function(t,e){var n=t.interaction,r=t.iEvent;if(n.prepared.name==="drag"){var i=n.dropState;at(n,i.events),e.fire("actions/drop:move",{interaction:n,dragEvent:r}),i.events={}}},"interactions:action-end":function(t,e){if(t.interaction.prepared.name==="drag"){var n=t.interaction,r=t.iEvent;Wt(t,e),at(n,n.dropState.events),e.fire("actions/drop:end",{interaction:n,dragEvent:r})}},"interactions:stop":function(t){var e=t.interaction;if(e.prepared.name==="drag"){var n=e.dropState;n&&(n.activeDrops=null,n.events=null,n.cur.dropzone=null,n.cur.element=null,n.prev.dropzone=null,n.prev.element=null,n.rejected=!1)}}},getActiveDrops:it,getDrop:Gt,getDropEvents:ot,fireDropEvents:at,filterEventType:function(t){return t.search("drag")===0||t.search("drop")===0},defaults:{enabled:!1,accept:null,overlap:"pointer"}},Rn=$t;function st(t){var e=t.interaction,n=t.iEvent,r=t.phase;if(e.prepared.name==="gesture"){var i=e.pointers.map(function(u){return u.pointer}),o=r==="start",a=r==="end",s=e.interactable.options.deltaSource;if(n.touches=[i[0],i[1]],o)n.distance=nt(i,s),n.box=tt(i),n.scale=1,n.ds=0,n.angle=rt(i,s),n.da=0,e.gesture.startDistance=n.distance,e.gesture.startAngle=n.angle;else if(a||e.pointers.length<2){var c=e.prevEvent;n.distance=c.distance,n.box=c.box,n.scale=c.scale,n.ds=0,n.angle=c.angle,n.da=0}else n.distance=nt(i,s),n.box=tt(i),n.scale=n.distance/e.gesture.startDistance,n.angle=rt(i,s),n.ds=n.scale-e.gesture.scale,n.da=n.angle-e.gesture.angle;e.gesture.distance=n.distance,e.gesture.angle=n.angle,d.number(n.scale)&&n.scale!==1/0&&!isNaN(n.scale)&&(e.gesture.scale=n.scale)}}var ct={id:"actions/gesture",before:["actions/drag","actions/resize"],install:function(t){var e=t.actions,n=t.Interactable,r=t.defaults;n.prototype.gesturable=function(i){return d.object(i)?(this.options.gesture.enabled=i.enabled!==!1,this.setPerAction("gesture",i),this.setOnEvents("gesture",i),this):d.bool(i)?(this.options.gesture.enabled=i,this):this.options.gesture},e.map.gesture=ct,e.methodDict.gesture="gesturable",r.actions.gesture=ct.defaults},listeners:{"interactions:action-start":st,"interactions:action-move":st,"interactions:action-end":st,"interactions:new":function(t){t.interaction.gesture={angle:0,distance:0,scale:1,startAngle:0,startDistance:0}},"auto-start:check":function(t){if(!(t.interaction.pointers.length<2)){var e=t.interactable.options.gesture;if(e&&e.enabled)return t.action={name:"gesture"},!1}}},defaults:{},getCursor:function(){return""},filterEventType:function(t){return t.search("gesture")===0}},jn=ct;function Cn(t,e,n,r,i,o,a){if(!e)return!1;if(e===!0){var s=d.number(o.width)?o.width:o.right-o.left,c=d.number(o.height)?o.height:o.bottom-o.top;if(a=Math.min(a,Math.abs((t==="left"||t==="right"?s:c)/2)),s<0&&(t==="left"?t="right":t==="right"&&(t="left")),c<0&&(t==="top"?t="bottom":t==="bottom"&&(t="top")),t==="left"){var u=s>=0?o.left:o.right;return n.x=0?o.top:o.bottom;return n.y(s>=0?o.right:o.left)-a;if(t==="bottom")return n.y>(c>=0?o.bottom:o.top)-a}return!!d.element(r)&&(d.element(e)?e===r:Ke(r,e,i))}function Nt(t){var e=t.iEvent,n=t.interaction;if(n.prepared.name==="resize"&&n.resizeAxes){var r=e;n.interactable.options.resize.square?(n.resizeAxes==="y"?r.delta.x=r.delta.y:r.delta.y=r.delta.x,r.axes="xy"):(r.axes=n.resizeAxes,n.resizeAxes==="x"?r.delta.y=0:n.resizeAxes==="y"&&(r.delta.x=0))}}var K,pe,J={id:"actions/resize",before:["actions/drag"],install:function(t){var e=t.actions,n=t.browser,r=t.Interactable,i=t.defaults;J.cursors=function(o){return o.isIe9?{x:"e-resize",y:"s-resize",xy:"se-resize",top:"n-resize",left:"w-resize",bottom:"s-resize",right:"e-resize",topleft:"se-resize",bottomright:"se-resize",topright:"ne-resize",bottomleft:"ne-resize"}:{x:"ew-resize",y:"ns-resize",xy:"nwse-resize",top:"ns-resize",left:"ew-resize",bottom:"ns-resize",right:"ew-resize",topleft:"nwse-resize",bottomright:"nwse-resize",topright:"nesw-resize",bottomleft:"nesw-resize"}}(n),J.defaultMargin=n.supportsTouch||n.supportsPointerEvent?20:10,r.prototype.resizable=function(o){return function(a,s,c){return d.object(s)?(a.options.resize.enabled=s.enabled!==!1,a.setPerAction("resize",s),a.setOnEvents("resize",s),d.string(s.axis)&&/^x$|^y$|^xy$/.test(s.axis)?a.options.resize.axis=s.axis:s.axis===null&&(a.options.resize.axis=c.defaults.actions.resize.axis),d.bool(s.preserveAspectRatio)?a.options.resize.preserveAspectRatio=s.preserveAspectRatio:d.bool(s.square)&&(a.options.resize.square=s.square),a):d.bool(s)?(a.options.resize.enabled=s,a):a.options.resize}(this,o,t)},e.map.resize=J,e.methodDict.resize="resizable",i.actions.resize=J.defaults},listeners:{"interactions:new":function(t){t.interaction.resizeAxes="xy"},"interactions:action-start":function(t){(function(e){var n=e.iEvent,r=e.interaction;if(r.prepared.name==="resize"&&r.prepared.edges){var i=n,o=r.rect;r._rects={start:x({},o),corrected:x({},o),previous:x({},o),delta:{left:0,right:0,width:0,top:0,bottom:0,height:0}},i.edges=r.prepared.edges,i.rect=r._rects.corrected,i.deltaRect=r._rects.delta}})(t),Nt(t)},"interactions:action-move":function(t){(function(e){var n=e.iEvent,r=e.interaction;if(r.prepared.name==="resize"&&r.prepared.edges){var i=n,o=r.interactable.options.resize.invert,a=o==="reposition"||o==="negate",s=r.rect,c=r._rects,u=c.start,l=c.corrected,p=c.delta,f=c.previous;if(x(f,l),a){if(x(l,s),o==="reposition"){if(l.top>l.bottom){var v=l.top;l.top=l.bottom,l.bottom=v}if(l.left>l.right){var h=l.left;l.left=l.right,l.right=h}}}else l.top=Math.min(s.top,u.bottom),l.bottom=Math.max(s.bottom,u.top),l.left=Math.min(s.left,u.right),l.right=Math.max(s.right,u.left);for(var g in l.width=l.right-l.left,l.height=l.bottom-l.top,l)p[g]=l[g]-f[g];i.edges=r.prepared.edges,i.rect=l,i.deltaRect=p}})(t),Nt(t)},"interactions:action-end":function(t){var e=t.iEvent,n=t.interaction;if(n.prepared.name==="resize"&&n.prepared.edges){var r=e;r.edges=n.prepared.edges,r.rect=n._rects.corrected,r.deltaRect=n._rects.delta}},"auto-start:check":function(t){var e=t.interaction,n=t.interactable,r=t.element,i=t.rect,o=t.buttons;if(i){var a=x({},e.coords.cur.page),s=n.options.resize;if(s&&s.enabled&&(!e.pointerIsDown||!/mouse|pointer/.test(e.pointerType)||o&s.mouseButtons)){if(d.object(s.edges)){var c={left:!1,right:!1,top:!1,bottom:!1};for(var u in c)c[u]=Cn(u,s.edges[u],a,e._latestPointer.eventTarget,r,i,s.margin||J.defaultMargin);c.left=c.left&&!c.right,c.top=c.top&&!c.bottom,(c.left||c.right||c.top||c.bottom)&&(t.action={name:"resize",edges:c})}else{var l=s.axis!=="y"&&a.x>i.right-J.defaultMargin,p=s.axis!=="x"&&a.y>i.bottom-J.defaultMargin;(l||p)&&(t.action={name:"resize",axes:(l?"x":"")+(p?"y":"")})}return!t.action&&void 0}}}},defaults:{square:!1,preserveAspectRatio:!1,axis:"xy",margin:NaN,edges:null,invert:"none"},cursors:null,getCursor:function(t){var e=t.edges,n=t.axis,r=t.name,i=J.cursors,o=null;if(n)o=i[r+n];else if(e){for(var a="",s=0,c=["top","bottom","left","right"];s=1){var u={x:E.x*c,y:E.y*c};if(u.x||u.y){var l=Kt(o);d.window(o)?o.scrollBy(u.x,u.y):o&&(o.scrollLeft+=u.x,o.scrollTop+=u.y);var p=Kt(o),f={x:p.x-l.x,y:p.y-l.y};(f.x||f.y)&&e.fire({type:"autoscroll",target:n,interactable:e,delta:f,interaction:t,container:o})}E.prevTime=a}E.isScrolling&&(te.cancel(E.i),E.i=te.request(E.scroll))},check:function(t,e){var n;return(n=t.options[e].autoScroll)==null?void 0:n.enabled},onInteractionMove:function(t){var e=t.interaction,n=t.pointer;if(e.interacting()&&E.check(e.interactable,e.prepared.name))if(e.simulation)E.x=E.y=0;else{var r,i,o,a,s=e.interactable,c=e.element,u=e.prepared.name,l=s.options[u].autoScroll,p=Ht(l.container,s,c);if(d.window(p))a=n.clientXp.innerWidth-E.margin,o=n.clientY>p.innerHeight-E.margin;else{var f=Je(p);a=n.clientXf.right-E.margin,o=n.clientY>f.bottom-E.margin}E.x=i?1:a?-1:0,E.y=o?1:r?-1:0,E.isScrolling||(E.margin=l.margin,E.speed=l.speed,E.start(e))}}};function Ht(t,e,n){return(d.string(t)?At(t,e,n):t)||U(n)}function Kt(t){return d.window(t)&&(t=window.document.body),{x:t.scrollLeft,y:t.scrollTop}}var Yn={id:"auto-scroll",install:function(t){var e=t.defaults,n=t.actions;t.autoScroll=E,E.now=function(){return t.now()},n.phaselessTypes.autoscroll=!0,e.perAction.autoScroll=E.defaults},listeners:{"interactions:new":function(t){t.interaction.autoScroll=null},"interactions:destroy":function(t){t.interaction.autoScroll=null,E.stop(),E.interaction&&(E.interaction=null)},"interactions:stop":E.stop,"interactions:action-move":function(t){return E.onInteractionMove(t)}}},Vn=Yn;function Te(t,e){var n=!1;return function(){return n||(ce.console.warn(e),n=!0),t.apply(this,arguments)}}function lt(t,e){return t.name=e.name,t.axis=e.axis,t.edges=e.edges,t}function Ln(t){return d.bool(t)?(this.options.styleCursor=t,this):t===null?(delete this.options.styleCursor,this):this.options.styleCursor}function qn(t){return d.func(t)?(this.options.actionChecker=t,this):t===null?(delete this.options.actionChecker,this):this.options.actionChecker}var Bn={id:"auto-start/interactableMethods",install:function(t){var e=t.Interactable;e.prototype.getAction=function(n,r,i,o){var a=function(s,c,u,l,p){var f=s.getRect(l),v=c.buttons||{0:1,1:4,3:8,4:16}[c.button],h={action:null,interactable:s,interaction:u,element:l,rect:f,buttons:v};return p.fire("auto-start:check",h),h.action}(this,r,i,o,t);return this.options.actionChecker?this.options.actionChecker(n,r,a,this,o,i):a},e.prototype.ignoreFrom=Te(function(n){return this._backCompatOption("ignoreFrom",n)},"Interactable.ignoreFrom() has been deprecated. Use Interactble.draggable({ignoreFrom: newValue})."),e.prototype.allowFrom=Te(function(n){return this._backCompatOption("allowFrom",n)},"Interactable.allowFrom() has been deprecated. Use Interactble.draggable({allowFrom: newValue})."),e.prototype.actionChecker=qn,e.prototype.styleCursor=Ln}};function Jt(t,e,n,r,i){return e.testIgnoreAllow(e.options[t.name],n,r)&&e.options[t.name].enabled&&Ye(e,n,t,i)?t:null}function Gn(t,e,n,r,i,o,a){for(var s=0,c=r.length;s=s||v.interactable===t&&((u+=h===n.name?1:0)>=o||v.element===e&&(l++,h===n.name&&l>=a))))return!1}return s>0}function en(t,e){return d.number(t)?(e.autoStart.maxInteractions=t,this):e.autoStart.maxInteractions}function ut(t,e,n){var r=n.autoStart.cursorElement;r&&r!==t&&(r.style.cursor=""),t.ownerDocument.documentElement.style.cursor=e,t.style.cursor=e,n.autoStart.cursorElement=e?t:null}function tn(t,e){var n=t.interactable,r=t.element,i=t.prepared;if(t.pointerType==="mouse"&&n&&n.options.styleCursor){var o="";if(i.name){var a=n.options[i.name].cursorChecker;o=d.func(a)?a(i,n,r,t._interacting):e.actions.map[i.name].getCursor(i)}ut(t.element,o||"",e)}else e.autoStart.cursorElement&&ut(e.autoStart.cursorElement,"",e)}var Wn={id:"auto-start/base",before:["actions"],install:function(t){var e=t.interactStatic,n=t.defaults;t.usePlugin(Bn),n.base.actionChecker=null,n.base.styleCursor=!0,x(n.perAction,{manualStart:!1,max:1/0,maxPerElement:1,allowFrom:null,ignoreFrom:null,mouseButtons:1}),e.maxInteractions=function(r){return en(r,t)},t.autoStart={maxInteractions:1/0,withinInteractionLimit:Ye,cursorElement:null}},listeners:{"interactions:down":function(t,e){var n=t.interaction,r=t.pointer,i=t.event,o=t.eventTarget;n.interacting()||Zt(n,Qt(n,r,i,o,e),e)},"interactions:move":function(t,e){(function(n,r){var i=n.interaction,o=n.pointer,a=n.event,s=n.eventTarget;i.pointerType!=="mouse"||i.pointerIsDown||i.interacting()||Zt(i,Qt(i,o,a,s,r),r)})(t,e),function(n,r){var i=n.interaction;if(i.pointerIsDown&&!i.interacting()&&i.pointerWasMoved&&i.prepared.name){r.fire("autoStart:before-start",n);var o=i.interactable,a=i.prepared.name;a&&o&&(o.options[a].manualStart||!Ye(o,i.element,i.prepared,r)?i.stop():(i.start(i.prepared,o,i.element),tn(i,r)))}}(t,e)},"interactions:stop":function(t,e){var n=t.interaction,r=n.interactable;r&&r.options.styleCursor&&ut(n.element,"",e)}},maxInteractions:en,withinInteractionLimit:Ye,validateAction:Jt},pt=Wn,$n={id:"auto-start/dragAxis",listeners:{"autoStart:before-start":function(t,e){var n=t.interaction,r=t.eventTarget,i=t.dx,o=t.dy;if(n.prepared.name==="drag"){var a=Math.abs(i),s=Math.abs(o),c=n.interactable.options.drag,u=c.startAxis,l=a>s?"x":a0&&(e.autoStartHoldTimer=setTimeout(function(){e.start(e.prepared,e.interactable,e.element)},n))},"interactions:move":function(t){var e=t.interaction,n=t.duplicate;e.autoStartHoldTimer&&e.pointerWasMoved&&!n&&(clearTimeout(e.autoStartHoldTimer),e.autoStartHoldTimer=null)},"autoStart:before-start":function(t){var e=t.interaction;ft(e)>0&&(e.prepared.name=null)}},getHoldDuration:ft},Un=Nn,Hn={id:"auto-start",install:function(t){t.usePlugin(pt),t.usePlugin(Un),t.usePlugin($n)}},Kn=function(t){return/^(always|never|auto)$/.test(t)?(this.options.preventDefault=t,this):d.bool(t)?(this.options.preventDefault=t?"always":"never",this):this.options.preventDefault};function Jn(t){var e=t.interaction,n=t.event;e.interactable&&e.interactable.checkAndPreventDefault(n)}var nn={id:"core/interactablePreventDefault",install:function(t){var e=t.Interactable;e.prototype.preventDefault=Kn,e.prototype.checkAndPreventDefault=function(n){return function(r,i,o){var a=r.options.preventDefault;if(a!=="never")if(a!=="always"){if(i.events.supportsPassive&&/^touch(start|move)$/.test(o.type)){var s=U(o.target).document,c=i.getDocOptions(s);if(!c||!c.events||c.events.passive!==!1)return}/^(mouse|pointer|touch)*(down|start)/i.test(o.type)||d.element(o.target)&&ee(o.target,"input,select,textarea,[contenteditable=true],[contenteditable=true] *")||o.preventDefault()}else o.preventDefault()}(this,t,n)},t.interactions.docEvents.push({type:"dragstart",listener:function(n){for(var r=0,i=t.interactions.list;r150)return null;var i=180*Math.atan2(r.prevEvent.velocityY,r.prevEvent.velocityX)/Math.PI;i<0&&(i+=360);var o=112.5<=i&&i<247.5,a=202.5<=i&&i<337.5;return{up:a,down:!a&&22.5<=i&&i<157.5,left:o,right:!o&&(292.5<=i||i<67.5),angle:i,speed:r.prevEvent.speed,velocity:{x:r.prevEvent.velocityX,y:r.prevEvent.velocityY}}}},{key:"preventDefault",value:function(){}},{key:"stopImmediatePropagation",value:function(){this.immediatePropagationStopped=this.propagationStopped=!0}},{key:"stopPropagation",value:function(){this.propagationStopped=!0}}]),n}(Xe);Object.defineProperties(ht.prototype,{pageX:{get:function(){return this.page.x},set:function(t){this.page.x=t}},pageY:{get:function(){return this.page.y},set:function(t){this.page.y=t}},clientX:{get:function(){return this.client.x},set:function(t){this.client.x=t}},clientY:{get:function(){return this.client.y},set:function(t){this.client.y=t}},dx:{get:function(){return this.delta.x},set:function(t){this.delta.x=t}},dy:{get:function(){return this.delta.y},set:function(t){this.delta.y=t}},velocityX:{get:function(){return this.velocity.x},set:function(t){this.velocity.x=t}},velocityY:{get:function(){return this.velocity.y},set:function(t){this.velocity.y=t}}});var Zn=O(function t(e,n,r,i,o){k(this,t),this.id=void 0,this.pointer=void 0,this.event=void 0,this.downTime=void 0,this.downTarget=void 0,this.id=e,this.pointer=n,this.event=r,this.downTime=i,this.downTarget=o}),er=function(t){return t.interactable="",t.element="",t.prepared="",t.pointerIsDown="",t.pointerWasMoved="",t._proxy="",t}({}),an=function(t){return t.start="",t.move="",t.end="",t.stop="",t.interacting="",t}({}),tr=0,nr=function(){function t(e){var n=this,r=e.pointerType,i=e.scopeFire;k(this,t),this.interactable=null,this.element=null,this.rect=null,this._rects=void 0,this.edges=null,this._scopeFire=void 0,this.prepared={name:null,axis:null,edges:null},this.pointerType=void 0,this.pointers=[],this.downEvent=null,this.downPointer={},this._latestPointer={pointer:null,event:null,eventTarget:null},this.prevEvent=null,this.pointerIsDown=!1,this.pointerWasMoved=!1,this._interacting=!1,this._ending=!1,this._stopped=!0,this._proxy=void 0,this.simulation=null,this.doMove=Te(function(l){this.move(l)},"The interaction.doMove() method has been renamed to interaction.move()"),this.coords={start:{page:{x:0,y:0},client:{x:0,y:0},timeStamp:0},prev:{page:{x:0,y:0},client:{x:0,y:0},timeStamp:0},cur:{page:{x:0,y:0},client:{x:0,y:0},timeStamp:0},delta:{page:{x:0,y:0},client:{x:0,y:0},timeStamp:0},velocity:{page:{x:0,y:0},client:{x:0,y:0},timeStamp:0}},this._id=tr++,this._scopeFire=i,this.pointerType=r;var o=this;this._proxy={};var a=function(l){Object.defineProperty(n._proxy,l,{get:function(){return o[l]}})};for(var s in er)a(s);var c=function(l){Object.defineProperty(n._proxy,l,{value:function(){return o[l].apply(o,arguments)}})};for(var u in an)c(u);this._scopeFire("interactions:new",{interaction:this})}return O(t,[{key:"pointerMoveTolerance",get:function(){return 1}},{key:"pointerDown",value:function(e,n,r){var i=this.updatePointer(e,n,r,!0),o=this.pointers[i];this._scopeFire("interactions:down",{pointer:e,event:n,eventTarget:r,pointerIndex:i,pointerInfo:o,type:"down",interaction:this})}},{key:"start",value:function(e,n,r){return!(this.interacting()||!this.pointerIsDown||this.pointers.length<(e.name==="gesture"?2:1)||!n.options[e.name].enabled)&&(lt(this.prepared,e),this.interactable=n,this.element=r,this.rect=n.getRect(r),this.edges=this.prepared.edges?x({},this.prepared.edges):{left:!0,right:!0,top:!0,bottom:!0},this._stopped=!1,this._interacting=this._doPhase({interaction:this,event:this.downEvent,phase:"start"})&&!this._stopped,this._interacting)}},{key:"pointerMove",value:function(e,n,r){this.simulation||this.modification&&this.modification.endResult||this.updatePointer(e,n,r,!1);var i,o,a=this.coords.cur.page.x===this.coords.prev.page.x&&this.coords.cur.page.y===this.coords.prev.page.y&&this.coords.cur.client.x===this.coords.prev.client.x&&this.coords.cur.client.y===this.coords.prev.client.y;this.pointerIsDown&&!this.pointerWasMoved&&(i=this.coords.cur.client.x-this.coords.start.client.x,o=this.coords.cur.client.y-this.coords.start.client.y,this.pointerWasMoved=be(i,o)>this.pointerMoveTolerance);var s,c,u,l=this.getPointerIndex(e),p={pointer:e,pointerIndex:l,pointerInfo:this.pointers[l],event:n,type:"move",eventTarget:r,dx:i,dy:o,duplicate:a,interaction:this};a||(s=this.coords.velocity,c=this.coords.delta,u=Math.max(c.timeStamp/1e3,.001),s.page.x=c.page.x/u,s.page.y=c.page.y/u,s.client.x=c.client.x/u,s.client.y=c.client.y/u,s.timeStamp=u),this._scopeFire("interactions:move",p),a||this.simulation||(this.interacting()&&(p.type=null,this.move(p)),this.pointerWasMoved&&Ce(this.coords.prev,this.coords.cur))}},{key:"move",value:function(e){e&&e.event||jt(this.coords.delta),(e=x({pointer:this._latestPointer.pointer,event:this._latestPointer.event,eventTarget:this._latestPointer.eventTarget,interaction:this},e||{})).phase="move",this._doPhase(e)}},{key:"pointerUp",value:function(e,n,r,i){var o=this.getPointerIndex(e);o===-1&&(o=this.updatePointer(e,n,r,!1));var a=/cancel$/i.test(n.type)?"cancel":"up";this._scopeFire("interactions:".concat(a),{pointer:e,pointerIndex:o,pointerInfo:this.pointers[o],event:n,eventTarget:r,type:a,curEventTarget:i,interaction:this}),this.simulation||this.end(n),this.removePointer(e,n)}},{key:"documentBlur",value:function(e){this.end(e),this._scopeFire("interactions:blur",{event:e,type:"blur",interaction:this})}},{key:"end",value:function(e){var n;this._ending=!0,e=e||this._latestPointer.event,this.interacting()&&(n=this._doPhase({event:e,interaction:this,phase:"end"})),this._ending=!1,n===!0&&this.stop()}},{key:"currentAction",value:function(){return this._interacting?this.prepared.name:null}},{key:"interacting",value:function(){return this._interacting}},{key:"stop",value:function(){this._scopeFire("interactions:stop",{interaction:this}),this.interactable=this.element=null,this._interacting=!1,this._stopped=!0,this.prepared.name=this.prevEvent=null}},{key:"getPointerIndex",value:function(e){var n=xe(e);return this.pointerType==="mouse"||this.pointerType==="pen"?this.pointers.length-1:we(this.pointers,function(r){return r.id===n})}},{key:"getPointerInfo",value:function(e){return this.pointers[this.getPointerIndex(e)]}},{key:"updatePointer",value:function(e,n,r,i){var o,a,s,c=xe(e),u=this.getPointerIndex(e),l=this.pointers[u];return i=i!==!1&&(i||/(down|start)$/i.test(n.type)),l?l.pointer=e:(l=new Zn(c,e,n,null,null),u=this.pointers.length,this.pointers.push(l)),An(this.coords.cur,this.pointers.map(function(p){return p.pointer}),this._now()),o=this.coords.delta,a=this.coords.prev,s=this.coords.cur,o.page.x=s.page.x-a.page.x,o.page.y=s.page.y-a.page.y,o.client.x=s.client.x-a.client.x,o.client.y=s.client.y-a.client.y,o.timeStamp=s.timeStamp-a.timeStamp,i&&(this.pointerIsDown=!0,l.downTime=this.coords.cur.timeStamp,l.downTarget=r,je(this.downPointer,e),this.interacting()||(Ce(this.coords.start,this.coords.cur),Ce(this.coords.prev,this.coords.cur),this.downEvent=n,this.pointerWasMoved=!1)),this._updateLatestPointer(e,n,r),this._scopeFire("interactions:update-pointer",{pointer:e,event:n,eventTarget:r,down:i,pointerInfo:l,pointerIndex:u,interaction:this}),u}},{key:"removePointer",value:function(e,n){var r=this.getPointerIndex(e);if(r!==-1){var i=this.pointers[r];this._scopeFire("interactions:remove-pointer",{pointer:e,event:n,eventTarget:null,pointerIndex:r,pointerInfo:i,interaction:this}),this.pointers.splice(r,1),this.pointerIsDown=!1}}},{key:"_updateLatestPointer",value:function(e,n,r){this._latestPointer.pointer=e,this._latestPointer.event=n,this._latestPointer.eventTarget=r}},{key:"destroy",value:function(){this._latestPointer.pointer=null,this._latestPointer.event=null,this._latestPointer.eventTarget=null}},{key:"_createPreparedEvent",value:function(e,n,r,i){return new ht(this,e,this.prepared.name,n,this.element,r,i)}},{key:"_fireEvent",value:function(e){var n;(n=this.interactable)==null||n.fire(e),(!this.prevEvent||e.timeStamp>=this.prevEvent.timeStamp)&&(this.prevEvent=e)}},{key:"_doPhase",value:function(e){var n=e.event,r=e.phase,i=e.preEnd,o=e.type,a=this.rect;if(a&&r==="move"&&(Re(this.edges,a,this.coords.delta[this.interactable.options.deltaSource]),a.width=a.right-a.left,a.height=a.bottom-a.top),this._scopeFire("interactions:before-action-".concat(r),e)===!1)return!1;var s=e.iEvent=this._createPreparedEvent(n,r,i,o);return this._scopeFire("interactions:action-".concat(r),e),r==="start"&&(this.prevEvent=s),this._fireEvent(s),this._scopeFire("interactions:after-action-".concat(r),e),!0}},{key:"_now",value:function(){return Date.now()}}]),t}();function sn(t){cn(t.interaction)}function cn(t){if(!function(n){return!(!n.offset.pending.x&&!n.offset.pending.y)}(t))return!1;var e=t.offset.pending;return vt(t.coords.cur,e),vt(t.coords.delta,e),Re(t.edges,t.rect,e),e.x=0,e.y=0,!0}function rr(t){var e=t.x,n=t.y;this.offset.pending.x+=e,this.offset.pending.y+=n,this.offset.total.x+=e,this.offset.total.y+=n}function vt(t,e){var n=t.page,r=t.client,i=e.x,o=e.y;n.x+=i,n.y+=o,r.x+=i,r.y+=o}an.offsetBy="";var ir={id:"offset",before:["modifiers","pointer-events","actions","inertia"],install:function(t){t.Interaction.prototype.offsetBy=rr},listeners:{"interactions:new":function(t){t.interaction.offset={total:{x:0,y:0},pending:{x:0,y:0}}},"interactions:update-pointer":function(t){return function(e){e.pointerIsDown&&(vt(e.coords.cur,e.offset.total),e.offset.pending.x=0,e.offset.pending.y=0)}(t.interaction)},"interactions:before-action-start":sn,"interactions:before-action-move":sn,"interactions:before-action-end":function(t){var e=t.interaction;if(cn(e))return e.move({offset:!0}),e.end(),!1},"interactions:stop":function(t){var e=t.interaction;e.offset.total.x=0,e.offset.total.y=0,e.offset.pending.x=0,e.offset.pending.y=0}}},ln=ir,or=function(){function t(e){k(this,t),this.active=!1,this.isModified=!1,this.smoothEnd=!1,this.allowResume=!1,this.modification=void 0,this.modifierCount=0,this.modifierArg=void 0,this.startCoords=void 0,this.t0=0,this.v0=0,this.te=0,this.targetOffset=void 0,this.modifiedOffset=void 0,this.currentOffset=void 0,this.lambda_v0=0,this.one_ve_v0=0,this.timeout=void 0,this.interaction=void 0,this.interaction=e}return O(t,[{key:"start",value:function(e){var n=this.interaction,r=qe(n);if(!r||!r.enabled)return!1;var i=n.coords.velocity.client,o=be(i.x,i.y),a=this.modification||(this.modification=new dt(n));if(a.copyFrom(n.modification),this.t0=n._now(),this.allowResume=r.allowResume,this.v0=o,this.currentOffset={x:0,y:0},this.startCoords=n.coords.cur.page,this.modifierArg=a.fillArg({pageCoords:this.startCoords,preEnd:!0,phase:"inertiastart"}),this.t0-n.coords.cur.timeStamp<50&&o>r.minSpeed&&o>r.endSpeed)this.startInertia();else{if(a.result=a.setAll(this.modifierArg),!a.result.changed)return!1;this.startSmoothEnd()}return n.modification.result.rect=null,n.offsetBy(this.targetOffset),n._doPhase({interaction:n,event:e,phase:"inertiastart"}),n.offsetBy({x:-this.targetOffset.x,y:-this.targetOffset.y}),n.modification.result.rect=null,this.active=!0,n.simulation=this,!0}},{key:"startInertia",value:function(){var e=this,n=this.interaction.coords.velocity.client,r=qe(this.interaction),i=r.resistance,o=-Math.log(r.endSpeed/this.v0)/i;this.targetOffset={x:(n.x-o)/i,y:(n.y-o)/i},this.te=o,this.lambda_v0=i/this.v0,this.one_ve_v0=1-r.endSpeed/this.v0;var a=this.modification,s=this.modifierArg;s.pageCoords={x:this.startCoords.x+this.targetOffset.x,y:this.startCoords.y+this.targetOffset.y},a.result=a.setAll(s),a.result.changed&&(this.isModified=!0,this.modifiedOffset={x:this.targetOffset.x+a.result.delta.x,y:this.targetOffset.y+a.result.delta.y}),this.onNextFrame(function(){return e.inertiaTick()})}},{key:"startSmoothEnd",value:function(){var e=this;this.smoothEnd=!0,this.isModified=!0,this.targetOffset={x:this.modification.result.delta.x,y:this.modification.result.delta.y},this.onNextFrame(function(){return e.smoothEndTick()})}},{key:"onNextFrame",value:function(e){var n=this;this.timeout=te.request(function(){n.active&&e()})}},{key:"inertiaTick",value:function(){var e,n,r,i,o,a,s,c=this,u=this.interaction,l=qe(u).resistance,p=(u._now()-this.t0)/1e3;if(p=0;g--){var T=m[g];if(T.selector===l&&T.context===p){for(var _=T.listeners,w=_.length-1;w>=0;w--){var S=_[w];if(S.func===v&&Be(S.options,y)){_.splice(w,1),_.length||(m.splice(g,1),s(p,f,c),s(p,f,u,!0)),b=!0;break}}if(b)break}}},delegateListener:c,delegateUseCapture:u,delegatedEvents:r,documents:i,targets:n,supportsOptions:!1,supportsPassive:!1};function a(l,p,f,v){if(l.addEventListener){var h=_e(v),g=Ee(n,function(y){return y.eventTarget===l});g||(g={eventTarget:l,events:{}},n.push(g)),g.events[p]||(g.events[p]=[]),Ee(g.events[p],function(y){return y.func===f&&Be(y.options,h)})||(l.addEventListener(p,f,o.supportsOptions?h:h.capture),g.events[p].push({func:f,options:h}))}}function s(l,p,f,v){if(l.addEventListener&&l.removeEventListener){var h=we(n,function(X){return X.eventTarget===l}),g=n[h];if(g&&g.events)if(p!=="all"){var y=!1,m=g.events[p];if(m){if(f==="all"){for(var b=m.length-1;b>=0;b--){var T=m[b];s(l,p,T.func,T.options)}return}for(var _=_e(v),w=0;w=2)continue;if(!i.interacting()&&e===i.pointerType)return i}return null}};function hn(t,e){return t.pointers.some(function(n){return n.id===e})}var ur=gt,mt=["pointerDown","pointerMove","pointerUp","updatePointer","removePointer","windowBlur"];function vn(t,e){return function(n){var r=e.interactions.list,i=Yt(n),o=Vt(n),a=o[0],s=o[1],c=[];if(/^touch/.test(n.type)){e.prevTouchTime=e.now();for(var u=0,l=n.changedTouches;u=0;r--){var i=e.interactions.list[r];i.interactable===n&&(i.stop(),e.fire("interactions:destroy",{interaction:i}),i.destroy(),e.interactions.list.length>2&&e.interactions.list.splice(r,1))}}},onDocSignal:yt,doOnInteractions:vn,methodNames:mt},fr=pr,re=function(t){return t[t.On=0]="On",t[t.Off=1]="Off",t}(re||{}),dr=function(){function t(e,n,r,i){k(this,t),this.target=void 0,this.options=void 0,this._actions=void 0,this.events=new dn,this._context=void 0,this._win=void 0,this._doc=void 0,this._scopeEvents=void 0,this._actions=n.actions,this.target=e,this._context=n.context||r,this._win=U(zt(e)?this._context:e),this._doc=this._win.document,this._scopeEvents=i,this.set(n)}return O(t,[{key:"_defaults",get:function(){return{base:{},perAction:{},actions:{}}}},{key:"setOnEvents",value:function(e,n){return d.func(n.onstart)&&this.on("".concat(e,"start"),n.onstart),d.func(n.onmove)&&this.on("".concat(e,"move"),n.onmove),d.func(n.onend)&&this.on("".concat(e,"end"),n.onend),d.func(n.oninertiastart)&&this.on("".concat(e,"inertiastart"),n.oninertiastart),this}},{key:"updatePerActionListeners",value:function(e,n,r){var i,o=this,a=(i=this._actions.map[e])==null?void 0:i.filterEventType,s=function(c){return(a==null||a(c))&&Ve(c,o._actions)};(d.array(n)||d.object(n))&&this._onOff(re.Off,e,n,void 0,s),(d.array(r)||d.object(r))&&this._onOff(re.On,e,r,void 0,s)}},{key:"setPerAction",value:function(e,n){var r=this._defaults;for(var i in n){var o=i,a=this.options[e],s=n[o];o==="listeners"&&this.updatePerActionListeners(e,a.listeners,s),d.array(s)?a[o]=qt(s):d.plainObject(s)?(a[o]=x(a[o]||{},ve(s)),d.object(r.perAction[o])&&"enabled"in r.perAction[o]&&(a[o].enabled=s.enabled!==!1)):d.bool(s)&&d.object(r.perAction[o])?a[o].enabled=s:a[o]=s}}},{key:"getRect",value:function(e){return e=e||(d.element(this.target)?this.target:null),d.string(this.target)&&(e=e||this._context.querySelector(this.target)),Qe(e)}},{key:"rectChecker",value:function(e){var n=this;return d.func(e)?(this.getRect=function(r){var i=x({},e.apply(n,r));return"width"in i||(i.width=i.right-i.left,i.height=i.bottom-i.top),i},this):e===null?(delete this.getRect,this):this.getRect}},{key:"_backCompatOption",value:function(e,n){if(zt(n)||d.object(n)){for(var r in this.options[e]=n,this._actions.map)this.options[r][e]=n;return this}return this.options[e]}},{key:"origin",value:function(e){return this._backCompatOption("origin",e)}},{key:"deltaSource",value:function(e){return e==="page"||e==="client"?(this.options.deltaSource=e,this):this.options.deltaSource}},{key:"getAllElements",value:function(){var e=this.target;return d.string(e)?Array.from(this._context.querySelectorAll(e)):d.func(e)&&e.getAllElements?e.getAllElements():d.element(e)?[e]:[]}},{key:"context",value:function(){return this._context}},{key:"inContext",value:function(e){return this._context===e.ownerDocument||le(this._context,e)}},{key:"testIgnoreAllow",value:function(e,n,r){return!this.testIgnore(e.ignoreFrom,n,r)&&this.testAllow(e.allowFrom,n,r)}},{key:"testAllow",value:function(e,n,r){return!e||!!d.element(r)&&(d.string(e)?Ke(r,e,n):!!d.element(e)&&le(e,r))}},{key:"testIgnore",value:function(e,n,r){return!(!e||!d.element(r))&&(d.string(e)?Ke(r,e,n):!!d.element(e)&&le(e,r))}},{key:"fire",value:function(e){return this.events.fire(e),this}},{key:"_onOff",value:function(e,n,r,i,o){d.object(n)&&!d.array(n)&&(i=r,r=null);var a=ue(n,r,o);for(var s in a){s==="wheel"&&(s=G.wheelEvent);for(var c=0,u=a[s];c=0;r--){var i=n[r],o=i.selector,a=i.context,s=i.listeners;o===this.target&&a===this._context&&n.splice(r,1);for(var c=s.length-1;c>=0;c--)this._scopeEvents.removeDelegate(this.target,this._context,e,s[c][0],s[c][1])}else this._scopeEvents.remove(this.target,"all")}}]),t}(),hr=function(){function t(e){var n=this;k(this,t),this.list=[],this.selectorMap={},this.scope=void 0,this.scope=e,e.addListeners({"interactable:unset":function(r){var i=r.interactable,o=i.target,a=d.string(o)?n.selectorMap[o]:o[n.scope.id],s=we(a,function(c){return c===i});a.splice(s,1)}})}return O(t,[{key:"new",value:function(e,n){n=x(n||{},{actions:this.scope.actions});var r=new this.scope.Interactable(e,n,this.scope.document,this.scope.events);return this.scope.addDocument(r._doc),this.list.push(r),d.string(e)?(this.selectorMap[e]||(this.selectorMap[e]=[]),this.selectorMap[e].push(r)):(r.target[this.scope.id]||Object.defineProperty(e,this.scope.id,{value:[],configurable:!0}),e[this.scope.id].push(r)),this.scope.fire("interactable:new",{target:e,options:n,interactable:r,win:this.scope._win}),r}},{key:"getExisting",value:function(e,n){var r=n&&n.context||this.scope.document,i=d.string(e),o=i?this.selectorMap[e]:e[this.scope.id];if(o)return Ee(o,function(a){return a._context===r&&(i||a.inContext(e))})}},{key:"forEachMatch",value:function(e,n){for(var r=0,i=this.list;rMath.abs(u.y),c.coords,c.rect),x(r,c.coords)),c.eventProps},defaults:{ratio:"preserve",equalDelta:!1,modifiers:[],enabled:!1}};function wr(t,e,n){var r=t.startCoords,i=t.edgeSign;e?n.y=r.y+(n.x-r.x)*i.y:n.x=r.x+(n.y-r.y)*i.x}function Er(t,e,n,r){var i=t.startRect,o=t.startCoords,a=t.ratio,s=t.edgeSign;if(e){var c=r.width/a;n.y=o.y+(c-i.height)*s.y}else{var u=r.height*a;n.x=o.x+(u-i.width)*s.x}}var Tr=ne(xr,"aspectRatio"),bn=function(){};bn._defaults={};var Ge=bn;function fe(t,e,n){return d.func(t)?me(t,e.interactable,e.element,[n.x,n.y,e]):me(t,e.interactable,e.element)}var We={start:function(t){var e=t.rect,n=t.startOffset,r=t.state,i=t.interaction,o=t.pageCoords,a=r.options,s=a.elementRect,c=x({left:0,top:0,right:0,bottom:0},a.offset||{});if(e&&s){var u=fe(a.restriction,i,o);if(u){var l=u.right-u.left-e.width,p=u.bottom-u.top-e.height;l<0&&(c.left+=l,c.right+=l),p<0&&(c.top+=p,c.bottom+=p)}c.left+=n.left-e.width*s.left,c.top+=n.top-e.height*s.top,c.right+=n.right-e.width*(1-s.right),c.bottom+=n.bottom-e.height*(1-s.bottom)}r.offset=c},set:function(t){var e=t.coords,n=t.interaction,r=t.state,i=r.options,o=r.offset,a=fe(i.restriction,n,e);if(a){var s=function(c){return!c||"left"in c&&"top"in c||((c=x({},c)).left=c.x||0,c.top=c.y||0,c.right=c.right||c.left+c.width,c.bottom=c.bottom||c.top+c.height),c}(a);e.x=Math.max(Math.min(s.right-o.right,e.x),s.left+o.left),e.y=Math.max(Math.min(s.bottom-o.bottom,e.y),s.top+o.top)}},defaults:{restriction:null,elementRect:null,offset:null,endOnly:!1,enabled:!1}},Sr=ne(We,"restrict"),xn={top:1/0,left:1/0,bottom:-1/0,right:-1/0},wn={top:-1/0,left:-1/0,bottom:1/0,right:1/0};function En(t,e){for(var n=0,r=["top","left","bottom","right"];n{let R=Y.ref(null);const j=Y.ref({x:0,y:0}),I=Y.ref({width:0,height:0});return Y.watch(P,()=>{P.value&&(R.value=Ie(P.value),j.value={x:0,y:0})},{immediate:!0,deep:!0}),Y.watch(()=>j.value,M=>{var O;const{x:k,y:N}=M;((O=R.value)==null?void 0:O.target).style.transform=`translate(${k}px, ${N}px)`},{deep:!0}),Y.watch(()=>I.value,M=>{var O,oe;const{width:k,height:N}=M;((O=R.value)==null?void 0:O.target).style.width=`${k}px`,((oe=R.value)==null?void 0:oe.target).style.height=`${N}px`},{deep:!0}),{interactable:R,interact:Ie,position:j,size:I}},Dn=(P,R={})=>{const j=Y.ref(!1),I=P.position,M=Y.computed({get:()=>({listeners:{start:k,move:N,end:O},...R}),set:C=>{var B;R=C,(B=P.interactable.value)==null||B.set(C)}}),k=C=>{j.value=!0},N=C=>{I.value={x:I.value.x+C.dx,y:I.value.y+C.dy}},O=C=>{j.value=!1};return{init:()=>{if(!P.interactable.value)throw new Error("Interactable context is not set");P.interactable.value.draggable(M.value)},position:I,draggableOptions:M,isDragging:j}},In=(P,R)=>{const j=Y.ref(!1),I=P.position,M=P.size;let k;const N=Y.computed({get:()=>({edges:{left:!0,right:!0,bottom:!0,top:!0},listeners:{start:O,move:oe,end:C},...R}),set:z=>{R=z,k.set(z)}}),O=z=>{j.value=!0},oe=z=>{var se,ge;const ae=I.value.x+(((se=z.deltaRect)==null?void 0:se.left)||0),Z=I.value.y+(((ge=z.deltaRect)==null?void 0:ge.top)||0);Object.assign(z.target.style,{width:`${z.rect.width}px`,height:`${z.rect.height}px`,transform:`translate(${ae}px, ${Z}px)`}),M.value={width:z.rect.width,height:z.rect.height},I.value={x:ae,y:Z}},C=z=>{j.value=!1};return{init:()=>{if(!P.interactable.value)throw new Error("Interactable context is not set");k=P.interactable.value.resizable(N.value)},resizeData:M,position:I,resizableOptions:N,isResizing:j}},Mn={install:(P,R={installInject:!0,installGlobalProperty:!0})=>{if(!P)throw new Error("VueInteract.install requires an app instance");R.installInject&&P.provide("interact",Ie),R.installGlobalProperty&&(P.config.globalProperties.$interact=Ie)}};$.default=Mn,$.useDraggable=Dn,$.useInteractContext=kn,$.useResizable=In,Object.defineProperties($,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); 2 | -------------------------------------------------------------------------------- /docs/.vuepress/client.ts: -------------------------------------------------------------------------------- 1 | import { defineClientConfig } from 'vuepress/client'; 2 | import DemoUseDraggable from '../guide/composables/components/DemoUseDraggable.vue'; 3 | import DemoUseResizable from '../guide/composables/components/DemoUseResizable.vue'; 4 | import DemoUseDragAndResize from '../guide/composables/components/DemoUseDragAndResize.vue'; 5 | 6 | export default defineClientConfig({ 7 | enhance({ app }) { 8 | app.component('DemoUseDraggable', DemoUseDraggable); 9 | app.component('DemoUseResizable', DemoUseResizable); 10 | app.component('DemoUseDragAndResize', DemoUseDragAndResize); 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /docs/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineUserConfig } from "vuepress"; 2 | import { defaultTheme } from '@vuepress/theme-default'; 3 | import { viteBundler } from '@vuepress/bundler-vite'; 4 | import navbar from './navbar'; 5 | import sidebar from './sidebar'; 6 | 7 | export default defineUserConfig({ 8 | lang: "en-US", 9 | title: "VueInteract", 10 | description: "VueInteract is a Vue 3 wrapper for Interact.js", 11 | theme: defaultTheme({ 12 | navbar, 13 | sidebar, 14 | repo: 'https://github.com/kimuraz/vue-interact', 15 | }), 16 | bundler: viteBundler(), 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /docs/.vuepress/navbar.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { text: 'Home', link: '/' }, 3 | { text: 'Getting Started', link: '/guide/getting_started.html' }, 4 | { text: 'Composables', link: '/guide/composables/index.html' }, 5 | ]; 6 | -------------------------------------------------------------------------------- /docs/.vuepress/public/assets/VueInteract.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/.vuepress/sidebar.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | text: 'Home', 4 | link: '/' 5 | }, 6 | { 7 | text: 'Getting Started', 8 | link: '/guide/getting_started.html' 9 | }, 10 | { 11 | text: 'Composables', 12 | link: '/guide/composables/index.html', 13 | children: [ 14 | { text: 'useDraggable', link: '/guide/composables/use_draggable.html' }, 15 | { text: 'useResizable', link: '/guide/composables/use_resizable.html' }, 16 | ], 17 | }, 18 | ]; 19 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --c-brand: #29e; 3 | --c-brand-light: #51aff2; 4 | 5 | --c-bg: #ffffff; 6 | --c-bg-light: #f3f4f5; 7 | --c-bg-lighter: #eeeeee; 8 | --c-bg-dark: #ebebec; 9 | --c-bg-darker: #e6e6e6; 10 | --c-bg-navbar: var(--c-bg); 11 | --c-bg-sidebar: var(--c-bg); 12 | --c-bg-arrow: #cccccc; 13 | 14 | --c-text: #2c3e50; 15 | --c-text-accent: var(--c-brand); 16 | --c-text-light: #3a5169; 17 | --c-text-lighter: #4e6e8e; 18 | --c-text-lightest: #6a8bad; 19 | --c-text-quote: #999999; 20 | 21 | --c-border: #eaecef; 22 | --c-border-dark: #dfe2e5; 23 | 24 | --c-tip: #29e; 25 | --c-tip-bg: var(--c-bg-light); 26 | --c-tip-title: var(--c-text); 27 | --c-tip-text: var(--c-text); 28 | --c-tip-text-accent: var(--c-text-accent); 29 | --c-warning: #ffc310; 30 | --c-warning-bg: #fffae3; 31 | --c-warning-bg-light: #fff3ba; 32 | --c-warning-bg-lighter: #fff0b0; 33 | --c-warning-border-dark: #f7dc91; 34 | --c-warning-details-bg: #fff5ca; 35 | --c-warning-title: #f1b300; 36 | --c-warning-text: #746000; 37 | --c-warning-text-accent: #edb100; 38 | --c-warning-text-light: #c1971c; 39 | --c-warning-text-quote: #ccab49; 40 | --c-danger: #f11e37; 41 | --c-danger-bg: #ffe0e0; 42 | --c-danger-bg-light: #ffcfde; 43 | --c-danger-bg-lighter: #ffc9c9; 44 | --c-danger-border-dark: #f1abab; 45 | --c-danger-details-bg: #ffd4d4; 46 | --c-danger-title: #ed1e2c; 47 | --c-danger-text: #660000; 48 | --c-danger-text-accent: #bd1a1a; 49 | --c-danger-text-light: #b5474d; 50 | --c-danger-text-quote: #c15b5b; 51 | --c-details-bg: #eeeeee; 52 | 53 | --c-badge-tip: var(--c-tip); 54 | --c-badge-warning: #ecc808; 55 | --c-badge-warning-text: var(--c-bg); 56 | --c-badge-danger: #dc2626; 57 | --c-badge-danger-text: var(--c-bg); 58 | 59 | --t-color: 0.3s ease; 60 | --t-transform: 0.3s ease; 61 | 62 | --code-bg-color: #282c34; 63 | --code-hl-bg-color: rgba(0, 0, 0, 0.66); 64 | --code-ln-color: #9e9e9e; 65 | --code-ln-wrapper-width: 3.5rem; 66 | 67 | --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, 68 | Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 69 | --font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 70 | 71 | --navbar-height: 3.6rem; 72 | --navbar-padding-v: 0.7rem; 73 | --navbar-padding-h: 1.5rem; 74 | --sidebar-width: 20rem; 75 | --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82); 76 | --content-width: 740px; 77 | --homepage-width: 960px; 78 | } 79 | 80 | .back-to-top { 81 | --back-to-top-color: var(--c-brand); 82 | --back-to-top-color-hover: var(--c-brand-light); 83 | } 84 | 85 | .DocSearch { 86 | --docsearch-primary-color: var(--c-brand); 87 | --docsearch-text-color: var(--c-text); 88 | --docsearch-highlight-color: var(--c-brand); 89 | --docsearch-muted-color: var(--c-text-quote); 90 | --docsearch-container-background: rgba(9, 10, 17, 0.8); 91 | --docsearch-modal-background: var(--c-bg-light); 92 | --docsearch-searchbox-background: var(--c-bg-lighter); 93 | --docsearch-searchbox-focus-background: var(--c-bg); 94 | --docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand); 95 | --docsearch-hit-color: var(--c-text-light); 96 | --docsearch-hit-active-color: var(--c-bg); 97 | --docsearch-hit-background: var(--c-bg); 98 | --docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark); 99 | --docsearch-footer-background: var(--c-bg); 100 | } 101 | 102 | .external-link-icon { 103 | --external-link-icon-color: var(--c-text-quote); 104 | } 105 | 106 | .medium-zoom-overlay { 107 | --medium-zoom-bg-color: var(--c-bg); 108 | } 109 | 110 | #nprogress { 111 | --nprogress-color: var(--c-brand); 112 | } 113 | 114 | .pwa-popup { 115 | --pwa-popup-text-color: var(--c-text); 116 | --pwa-popup-bg-color: var(--c-bg); 117 | --pwa-popup-border-color: var(--c-brand); 118 | --pwa-popup-shadow: 0 4px 16px var(--c-brand); 119 | --pwa-popup-btn-text-color: var(--c-bg); 120 | --pwa-popup-btn-bg-color: var(--c-brand); 121 | --pwa-popup-btn-hover-bg-color: var(--c-brand-light); 122 | } 123 | 124 | .search-box { 125 | --search-bg-color: var(--c-bg); 126 | --search-accent-color: var(--c-brand); 127 | --search-text-color: var(--c-text); 128 | --search-border-color: var(--c-border); 129 | 130 | --search-item-text-color: var(--c-text-lighter); 131 | --search-item-focus-bg-color: var(--c-bg-light); 132 | } 133 | 134 | html.dark { 135 | // brand colors 136 | --c-brand: #29e; 137 | --c-brand-light: #51aff2; 138 | 139 | // background colors 140 | --c-bg: #22272e; 141 | --c-bg-light: #2b313a; 142 | --c-bg-lighter: #262c34; 143 | --c-bg-dark: #343b44; 144 | --c-bg-darker: #37404c; 145 | 146 | // text colors 147 | --c-text: #adbac7; 148 | --c-text-light: #96a7b7; 149 | --c-text-lighter: #8b9eb0; 150 | --c-text-lightest: #8094a8; 151 | 152 | // border colors 153 | --c-border: #3e4c5a; 154 | --c-border-dark: #34404c; 155 | 156 | // custom container colors 157 | --c-tip: #318a62; 158 | --c-warning: #e0ad15; 159 | --c-warning-bg: #2d2f2d; 160 | --c-warning-bg-light: #423e2a; 161 | --c-warning-bg-lighter: #44442f; 162 | --c-warning-border-dark: #957c35; 163 | --c-warning-details-bg: #39392d; 164 | --c-warning-title: #fdca31; 165 | --c-warning-text: #d8d96d; 166 | --c-warning-text-accent: #ffbf00; 167 | --c-warning-text-light: #ddb84b; 168 | --c-warning-text-quote: #ccab49; 169 | --c-danger: #fc1e38; 170 | --c-danger-bg: #39232c; 171 | --c-danger-bg-light: #4b2b35; 172 | --c-danger-bg-lighter: #553040; 173 | --c-danger-border-dark: #a25151; 174 | --c-danger-details-bg: #482936; 175 | --c-danger-title: #fc2d3b; 176 | --c-danger-text: #ea9ca0; 177 | --c-danger-text-accent: #fd3636; 178 | --c-danger-text-light: #d9777c; 179 | --c-danger-text-quote: #d56b6b; 180 | --c-details-bg: #323843; 181 | 182 | // badge component colors 183 | --c-badge-warning: var(--c-warning); 184 | --c-badge-warning-text: #3c2e05; 185 | --c-badge-danger: var(--c-danger); 186 | --c-badge-danger-text: #401416; 187 | 188 | // code blocks vars 189 | --code-hl-bg-color: #363b46; 190 | } 191 | 192 | // plugin-docsearch 193 | html.dark .DocSearch { 194 | --docsearch-logo-color: var(--c-text); 195 | --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309; 196 | --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 197 | 0 2px 2px 0 rgba(3, 4, 9, 0.3); 198 | --docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21); 199 | --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 200 | 0 -4px 8px 0 rgba(0, 0, 0, 0.2); 201 | } 202 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | lang: en-US 3 | heroImage: /assets/VueInteract.svg 4 | heroText: 5 | heroDescription: Vue Interact is a Vue.js plugin wrapping Interact.js 6 | home: true 7 | actions: 8 | - text: Get Started 9 | link: /guide/getting_started.md 10 | type: primary 11 | - text: Contribute 12 | link: /contributing.md 13 | type: secondary 14 | footer: MIT Licensed 15 | --- 16 | -------------------------------------------------------------------------------- /docs/guide/composables/components/DemoUseDragAndResize.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 35 | 36 | 50 | -------------------------------------------------------------------------------- /docs/guide/composables/components/DemoUseDraggable.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 31 | 32 | 46 | -------------------------------------------------------------------------------- /docs/guide/composables/components/DemoUseResizable.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 33 | 34 | 48 | -------------------------------------------------------------------------------- /docs/guide/composables/index.md: -------------------------------------------------------------------------------- 1 | ### Composables 2 | 3 | Currently the library provides the following composables: 4 | 5 | ```ts 6 | import { useInteractContext } from 'vue-interact'; 7 | import { useDraggable } from 'vue-interact'; 8 | import { useResizable } from 'vue-interact'; 9 | ``` 10 | 11 | :warning: **Important**: The `useInteractContext` must be used before the other composables. 12 | 13 | The `useInteractContext` is an entry point for the other composables. It provides the `interactable` object which is used by the other composables. 14 | 15 | Also it creates a single context to share among the other composables so you can use them together on the same element ref. 16 | 17 | On this example the position and the resizeData are actually refs declared on the context and redirected by `useDraggable` and `useResizable` respectively. 18 | 19 | ```ts 20 | import { nextTick, onMounted, ref } from 'vue'; 21 | import { useInteractContext, useDraggable, useResizable } from 'vue-interact'; 22 | 23 | const interactableTarget = ref(null); 24 | 25 | const context = useInteractContext(interactableTarget); 26 | 27 | const { init, position } = useDraggable(context); 28 | const { init: initResize, resizeData } = useResizable(context); 29 | 30 | onMounted(() => { 31 | nextTick(() => { 32 | init(); 33 | initResize(); 34 | }); 35 | }); 36 | ``` 37 | 38 | On template: 39 | 40 | ```html 41 |
45 | ``` 46 | 47 | **Note**: Due to the dependency of having the element on the DOM to initialize the interactable object, it is recommended to use the `onMounted` lifecycle hook to initialize the composables. 48 | 49 | #### Demo 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/guide/composables/use_draggable.md: -------------------------------------------------------------------------------- 1 | # useDraggable 2 | 3 | 4 | 5 | @[code{1-29}](./components/DemoUseDraggable.vue) 6 | -------------------------------------------------------------------------------- /docs/guide/composables/use_resizable.md: -------------------------------------------------------------------------------- 1 | # useResizable 2 | 3 | 4 | 5 | @[code](./components/DemoUseResizable.vue) 6 | -------------------------------------------------------------------------------- /docs/guide/getting_started.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | This plugin is compatible with `VueJS >= 3` 4 | 5 | The version is currently using InteractJS `1.10.x` 6 | 7 | ## Adding it to your project 8 | 9 | ```bash 10 | npm i vue-interact 11 | ``` 12 | 13 | ## Using the plugin 14 | 15 | ```ts 16 | import VueInteract from 'vue-interact'; 17 | 18 | const app = createApp(App); 19 | app.use(VueInteract, { 20 | installGlobalProperty: true, 21 | installInject: true, 22 | }); 23 | ``` 24 | 25 | ### Options 26 | 27 | ```ts 28 | export interface IVueInteractOptions { 29 | installInject?: boolean; 30 | installGlobalProperty?: boolean; 31 | } 32 | ``` 33 | 34 | When `installGlobalProperty` is `true` will register the plugin globally as `$interact`. 35 | 36 | When `installInject` is `true` will register the plugin as `interact` in the `provide/inject` system. 37 | 38 | Both instances are merely the default InteractJS instance. 39 | 40 | > Check the documentation for the InteractJS instance [here](https://interactjs.io/docs/interactjs/). 41 | 42 | > Check the documentation for composables [here](/guide/composables/use_draggable.html) 43 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verbose: true, 3 | clearMocks: true, 4 | moduleDirectories: ['node_modules'], 5 | roots: ["/src"], 6 | transform: { 7 | "^.+\\.(ts|tsx)$": ["ts-jest", { tsconfig: "tsconfig.json" }] 8 | }, 9 | transformIgnorePatterns: [ 10 | "/node_modules/(?!@foo)" 11 | ], 12 | testEnvironment: "jsdom", 13 | }; 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-interact", 3 | "description": "Interact.js wrapper for VueJS", 4 | "version": "2.0.0", 5 | "author": "Kimura ", 6 | "private": false, 7 | "main": "dist/vue-interact.umd.cjs", 8 | "type": "module", 9 | "module": "dist/vue-interact.js", 10 | "exports": { 11 | ".": { 12 | "import": "./dist/vue-interact.js", 13 | "require": "./dist/vue-interact.umd.cjs" 14 | } 15 | }, 16 | "types": "vue-interact.d.ts", 17 | "license": "MIT", 18 | "scripts": { 19 | "build": "vite build", 20 | "lint": "eslint --ext .ts src --no-fix", 21 | "lint:fix": "eslint --ext .ts src --fix", 22 | "docs:dev": "vuepress dev docs", 23 | "docs:build": "vuepress build docs", 24 | "test": "jest --coverage", 25 | "test:ci": "jest --ci --coverage" 26 | }, 27 | "dependencies": { 28 | "docs": "0.3.2-canary.0", 29 | "interactjs": "^1.10.27" 30 | }, 31 | "peerDependencies": { 32 | "interactjs": "^1.10.27", 33 | "vue": "^3" 34 | }, 35 | "devDependencies": { 36 | "@interactjs/types": "^1.10.27", 37 | "@tsconfig/recommended": "^1.0.1", 38 | "@types/jest": "^29.5.3", 39 | "@typescript-eslint/eslint-plugin": "^5.40.1", 40 | "@typescript-eslint/parser": "^5.40.1", 41 | "@vitejs/plugin-vue": "^5.1.2", 42 | "@vuepress/bundler-vite": "2.0.0-rc.15", 43 | "@vuepress/plugin-container": "2.0.0-rc.28", 44 | "@vuepress/plugin-register-components": "2.0.0-rc.37", 45 | "@vuepress/theme-default": "2.0.0-rc.41", 46 | "esbuild": "^0.18.17", 47 | "eslint": "^8.46.0", 48 | "eslint-config-prettier": "^9.0.0", 49 | "eslint-plugin-prettier": "^5.0.0", 50 | "jest": "^29.6.2", 51 | "jest-environment-jsdom": "^29.6.2", 52 | "prettier": "^3.0.1", 53 | "ts-jest": "^29.1.1", 54 | "ts-node": "^10.9.1", 55 | "typescript": "^5.1.6", 56 | "vite": "^5.4.1", 57 | "vite-plugin-dts": "^4.0.3", 58 | "vue": "^3.4.38", 59 | "vue-interact": "link:", 60 | "vuepress": "2.0.0-rc.15", 61 | "vuepress-theme-reco": "2.0.0-rc.18" 62 | }, 63 | "engines": { 64 | "node": ">= 14.0.0", 65 | "npm": ">= 3.0.0" 66 | }, 67 | "browserslist": [ 68 | "> 1%", 69 | "last 2 versions", 70 | "not ie <= 8" 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/composables/useDraggable.ts: -------------------------------------------------------------------------------- 1 | import interact from "interactjs"; 2 | import Interact from "@interactjs/types/index"; 3 | 4 | import { computed, ref, watch, onMounted } from "vue"; 5 | import { DraggableOptions } from '@interactjs/actions/drag/plugin'; 6 | import type { InteractContext } from "./useInteractContext"; 7 | 8 | export interface IPosition { 9 | x: number; 10 | y: number; 11 | } 12 | const useDraggable = (context: InteractContext, interactOptions: DraggableOptions = {}) => { 13 | const isDragging = ref(false); 14 | const position = context.position; 15 | 16 | const draggableOptions = computed({ 17 | get: () => ({ 18 | listeners: { 19 | start: onDragStart, 20 | move: onDragMove, 21 | end: onDragEnd, 22 | }, 23 | ...interactOptions, 24 | }), 25 | set: (value) => { 26 | interactOptions = value; 27 | context.interactable.value?.set(value); 28 | } 29 | }); 30 | 31 | const onDragStart = (event: Interact.DragEvent) => { 32 | isDragging.value = true; 33 | } 34 | 35 | const onDragMove = (event: Interact.DragEvent) => { 36 | position.value = { 37 | x: position.value.x + event.dx, 38 | y: position.value.y + event.dy, 39 | }; 40 | }; 41 | 42 | const onDragEnd = (event: Interact.DragEvent) => { 43 | isDragging.value = false; 44 | }; 45 | 46 | const init = () => { 47 | if (!context.interactable.value) { 48 | throw new Error('Interactable context is not set'); 49 | } 50 | context.interactable.value.draggable(draggableOptions.value); 51 | }; 52 | 53 | 54 | return { 55 | init, 56 | position, 57 | draggableOptions, 58 | isDragging, 59 | }; 60 | } 61 | 62 | export default useDraggable; 63 | -------------------------------------------------------------------------------- /src/composables/useInteractContext.ts: -------------------------------------------------------------------------------- 1 | import type { Interactable } from "@interactjs/types"; 2 | import interact from "interactjs"; 3 | import { Ref, watch, ref } from "vue"; 4 | 5 | export interface IPosition { 6 | x: number; 7 | y: number; 8 | } 9 | 10 | export interface ISizeData { 11 | width: number; 12 | height: number; 13 | } 14 | 15 | 16 | export interface InteractContext { 17 | interactable: Ref; 18 | interact: typeof interact; 19 | 20 | position: Ref; 21 | size: Ref; 22 | } 23 | 24 | const useInteractContext = (elRef: Ref) => { 25 | let interactable = ref(null); 26 | const position = ref({ x: 0, y: 0 }); 27 | const size = ref({ width: 0, height: 0 }); 28 | 29 | 30 | watch(elRef, () => { 31 | if (!elRef.value) { 32 | return; 33 | } 34 | interactable.value = interact(elRef.value); 35 | position.value = { 36 | x: 0, 37 | y: 0, 38 | }; 39 | }, { immediate: true, deep: true }); 40 | 41 | watch(() => position.value, (newPosition) => { 42 | const { x, y } = newPosition; 43 | (interactable.value?.target as HTMLElement).style.transform = `translate(${x}px, ${y}px)`; 44 | }, { deep: true }); 45 | 46 | watch(() => size.value, (newSizeData) => { 47 | const { width, height } = newSizeData; 48 | (interactable.value?.target as HTMLElement).style.width = `${width}px`; 49 | (interactable.value?.target as HTMLElement).style.height = `${height}px`; 50 | }, { deep: true }); 51 | 52 | return { 53 | interactable, 54 | interact, 55 | position, 56 | size, 57 | } as InteractContext; 58 | }; 59 | 60 | export default useInteractContext; 61 | -------------------------------------------------------------------------------- /src/composables/useResizable.ts: -------------------------------------------------------------------------------- 1 | import interact from "interactjs"; 2 | import Interact from "@interactjs/types/index"; 3 | 4 | import { computed, onMounted, ref } from "vue"; 5 | import { ResizableOptions } from '@interactjs/actions/resize/plugin'; 6 | import { InteractContext } from "./useInteractContext"; 7 | 8 | const useResizable = (context: InteractContext, interactOptions: ResizableOptions) => { 9 | const isResizing = ref(false); 10 | const position = context.position; 11 | const resizeData = context.size; 12 | let resizable: Interact.Interactable; 13 | const resizableOptions = computed({ 14 | get: () => ({ 15 | edges: { left: true, right: true, bottom: true, top: true }, 16 | listeners: { 17 | start: onResizeStart, 18 | move: onResizeMove, 19 | end: onResizeEnd, 20 | }, 21 | ...interactOptions, 22 | }), 23 | set: (value) => { 24 | interactOptions = value; 25 | resizable.set(value); 26 | } 27 | }); 28 | 29 | const onResizeStart = (event: Interact.ResizeEvent) => { 30 | isResizing.value = true; 31 | }; 32 | 33 | const onResizeMove = (event: Interact.ResizeEvent) => { 34 | const x = position.value.x + (event.deltaRect?.left || 0); 35 | const y = position.value.y + (event.deltaRect?.top || 0); 36 | 37 | Object.assign(event.target.style, { 38 | width: `${event.rect.width}px`, 39 | height: `${event.rect.height}px`, 40 | transform: `translate(${x}px, ${y}px)`, 41 | }); 42 | resizeData.value = { 43 | width: event.rect.width, 44 | height: event.rect.height, 45 | }; 46 | position.value = { 47 | x, 48 | y, 49 | }; 50 | }; 51 | 52 | const onResizeEnd = (event: Interact.ResizeEvent) => { 53 | isResizing.value = false; 54 | }; 55 | 56 | const init = () => { 57 | if (!context.interactable.value) { 58 | throw new Error('Interactable context is not set'); 59 | } 60 | resizable = context.interactable.value.resizable(resizableOptions.value); 61 | }; 62 | 63 | 64 | return { 65 | init, 66 | resizeData, 67 | position, 68 | resizableOptions, 69 | isResizing, 70 | }; 71 | } 72 | 73 | export default useResizable; 74 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { App, Plugin } from 'vue'; 2 | import interact from 'interactjs'; 3 | import useInteractContext from './composables/useInteractContext'; 4 | import useDraggable from './composables/useDraggable'; 5 | import useResizable from './composables/useResizable'; 6 | 7 | export interface IVueInteractOptions { 8 | installInject?: boolean; 9 | installGlobalProperty?: boolean; 10 | } 11 | 12 | const VueInteract: Plugin = { 13 | install: (app: App, options: IVueInteractOptions = { 14 | installInject: true, 15 | installGlobalProperty: true, 16 | }) => { 17 | if (!app) { 18 | throw new Error('VueInteract.install requires an app instance'); 19 | } 20 | if (options.installInject) { 21 | app.provide('interact', interact); 22 | } 23 | 24 | if (options.installGlobalProperty) { 25 | app.config.globalProperties.$interact = interact; 26 | } 27 | }, 28 | }; 29 | 30 | export { useInteractContext, useDraggable, useResizable }; 31 | export default VueInteract; 32 | -------------------------------------------------------------------------------- /src/types/vue-interact.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@vue-interact/types' { 2 | import type { DirectiveBinding } from 'vue'; 3 | export interface DragDirectiveBinding extends DirectiveBinding { 4 | value: { 5 | listeners?: { 6 | start?(event: InteractEvent): void; 7 | move?(event: InteractEvent): void; 8 | end?(event: InteractEvent): void; 9 | }; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/types/vue.d.ts: -------------------------------------------------------------------------------- 1 | import Interact from '@interactjs/types/index'; 2 | 3 | declare global { 4 | interface Vue { 5 | $interact: Interact.Static; 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/recommended/tsconfig.json", 3 | "compilerOptions": { 4 | "noImplicitAny": true, 5 | "removeComments": true, 6 | "preserveConstEnums": true, 7 | "allowJs": true, 8 | "typeRoots": [ 9 | "node_modules/@types", 10 | "src/types" 11 | ], 12 | }, 13 | "include": [ 14 | "src/**/*", 15 | ], 16 | "exclude": [ 17 | "node_modules", 18 | "src/__tests__/*.spec.ts", 19 | "dist/**/*" 20 | ], 21 | } 22 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import dts from 'vite-plugin-dts'; 3 | 4 | export default defineConfig({ 5 | build: { 6 | emptyOutDir: true, 7 | lib: { 8 | entry: 'src/index.ts', 9 | name: 'VueInteract', 10 | }, 11 | rollupOptions: { 12 | output: { 13 | exports: "named", 14 | globals: { 15 | vue: 'Vue', 16 | }, 17 | }, 18 | external: ['vue'], 19 | } 20 | }, 21 | plugins: [ 22 | dts({ 23 | insertTypesEntry: true, 24 | }), 25 | ], 26 | }); 27 | --------------------------------------------------------------------------------