[
  {
    "path": ".browserslistrc",
    "content": "defaults and fully supports es6-module\nnode >= 16"
  },
  {
    "path": ".codeclimate.yml",
    "content": "plugins:\n  eslint:\n    enabled: false\n    channel: eslint-6\n    extensions:\n      - .ts\n      - .js\n  duplication:\n    enabled: false\n    config:\n      languages:\n        - javascript\n        - typescript\n\nratings:\n  paths:\n    - \"packages/**/*.ts\"\n\nexclude_paths:\n  - \"**/examples/\"\n  - \"**/build/\"\n  - \"**/docs/\"\n  - \"**/_*\"\n  - \"**/*.spec.ts\"\n  - \"**/*.d.ts\"\n"
  },
  {
    "path": ".eslintignore",
    "content": "dist\ncoverage\n**/node_modules/**\n_angular\n"
  },
  {
    "path": ".eslintrc.cjs",
    "content": "module.exports = {\n  extends: [\n    'plugin:import/errors',\n    'plugin:import/warnings',\n    'plugin:import/typescript',\n    'plugin:react/all',\n    'standard',\n    'prettier',\n  ],\n  settings: {\n    'import/resolver': { typescript: null },\n    react: { version: '16' },\n  },\n  env: {\n    commonjs: true,\n    es6: true,\n    node: true,\n  },\n  parser: '@typescript-eslint/parser',\n  parserOptions: {\n    sourceType: 'module',\n    ecmaVersion: 2020,\n  },\n  plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc', 'markdown'],\n  globals: {\n    globalThis: false,\n  },\n  rules: {\n    'linebreak-style': ['error', 'unix'],\n    'lines-between-class-members': 'off',\n    'no-caller': 'error',\n    'no-console': 'off',\n    'no-empty': 'off',\n    'no-prototype-builtins': 'off',\n    'no-shadow': 'error',\n    'no-useless-constructor': 'off',\n    'no-var': 'error',\n    'import/no-extraneous-dependencies': ['error', { devDependencies: false }],\n    'import/order': [\n      'error',\n      {\n        alphabetize: { order: 'asc', caseInsensitive: true },\n        'newlines-between': 'always',\n        groups: ['builtin', 'external', 'internal', 'parent', 'index', 'sibling'],\n        pathGroups: [{ pattern: '@interactjs/**', group: 'internal' }],\n      },\n    ],\n    'operator-linebreak': 'off',\n    'prefer-arrow-callback': ['error', { allowNamedFunctions: true }],\n    'prefer-const': 'error',\n    'standard/array-bracket-even-spacing': 'off',\n    'standard/computed-property-even-spacing': 'off',\n    'standard/object-curly-even-spacing': 'off',\n    'tsdoc/syntax': 'warn',\n    '@typescript-eslint/array-type': ['error', { default: 'array-simple' }],\n    '@typescript-eslint/consistent-type-imports': 'error',\n    '@typescript-eslint/explicit-member-accessibility': 'off',\n    '@typescript-eslint/member-accessibility': 'off',\n    '@typescript-eslint/no-empty-interface': 'error',\n    '@typescript-eslint/no-inferrable-types': 'error',\n    '@typescript-eslint/no-use-before-define': 'off',\n  },\n  overrides: [\n    {\n      files: '*.{ts{,x},vue}',\n      rules: {\n        'import/named': 'off',\n        'import/no-named-as-default': 'off',\n        'import/no-unresolved': 'off',\n        'no-redeclare': 'off',\n        'no-shadow': 'off',\n        'no-undef': 'off',\n        'no-unused-vars': 'off',\n        'no-use-before-define': 'off',\n      },\n    },\n    {\n      files: '{,.md/}*.vue',\n      extends: ['plugin:vue/vue3-essential'],\n      parserOptions: { parser: '@typescript-eslint/parser' },\n    },\n    {\n      files: '*.spec.ts',\n      extends: ['plugin:jest/recommended', 'plugin:jest/style'],\n      rules: {\n        'array-bracket-spacing': 'off',\n        'import/no-extraneous-dependencies': 'off',\n        'jest/consistent-test-it': ['error', { fn: 'test' }],\n      },\n    },\n    { files: '**/*.md', processor: 'markdown/markdown' },\n    {\n      files: '**/*.md/*.{{ts,js}{,x},vue}',\n      rules: {\n        'arrow-parens': 'off',\n        'import/no-named-as-default': 'off',\n        'import/no-unresolved': 'off',\n        'no-console': 'off',\n        'no-redeclare': 'off',\n        'no-shadow': 'off',\n        'no-undef': 'off',\n        'no-unused-vars': 'off',\n        'no-use-before-define': 'off',\n        'no-var': 'off',\n        'prefer-arrow-callback': 'off',\n      },\n    },\n  ],\n}\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 14\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 7\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - pinned\n  - security\nonly: issues\n# Label to use when marking an issue as stale\nstaleLabel: stale\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: false\nexemptProjects: true\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "on:\n  push:\n    branches:\n      - main\n      - next\n\njobs:\n  test:\n    uses: ./.github/workflows/test.yml\n\n  publish-npm:\n    name: '📦 Build and Publish 🚀'\n    needs: [test]\n    runs-on: ubuntu-latest\n    environment: production\n    steps:\n      - uses: actions/checkout@v3\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: '.nvmrc'\n          registry-url: https://registry.npmjs.org/\n          cache: yarn\n      - name: ⚙ bootstrap\n        run: 'npm run bootstrap && git fetch --tags'\n      - name: 📦 build and publish 🚀\n        run: npx _release\n        env:\n          NODE_AUTH_TOKEN: ${{secrets.npm_token}}\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "on:\n  pull_request:\n  workflow_dispatch:\n  workflow_call:\n\njobs:\n  test:\n    name: '🧪 Test'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - uses: ianwalter/playwright-container@43940dfa7d309fe3569b9df407ae9e84dcbf2e7f\n      - name: ⚙ bootstrap\n        run: 'npm run bootstrap && npx _check_deps && npx _add_plugin_indexes'\n      - name: 📐 types\n        run: npx tsc -b -f\n      - name: 🔍 lint\n        run: npx _lint\n      - name: 🧪 tests\n        run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": "*.d.ts\n*.d.ts.map\n!interactjs/index.d.ts\n!shims.d.ts\npackages/@interactjs/**/index.ts\npackages/@interactjs/*/use/**/*.ts\n!packages/@interactjs/types/index.ts\n!packages/@interactjs/interact/index.ts\n!packages/@interactjs/interactjs/index.ts\n!packages/@interactjs/rebound/index.ts\npackages/**/*.js\npackages/**/*.js.map\n!packages/@interactjs/dev-tools/babel-plugin-prod.js\nnode_modules\n!test/fixtures/**/node_modules\ndist\n.projectroot\n.env\n.envrc\n.nyc_output\nyarn-error.log\n.yarn-cache\n.pnpm-store\nnpm-debug.log\npnpm-debug.log\ncoverage\ncc-test-reporter\nlerna-debug.log\n.vim\n.cjsescache"
  },
  {
    "path": ".husky/.gitignore",
    "content": "_\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nyarn lint-staged\n"
  },
  {
    "path": ".npmignore",
    "content": "*.ts\n!*.d.ts\n*.map.*\n*.spec.ts\n*.spec.js\ndist/docs\nguide\n"
  },
  {
    "path": ".npmrc",
    "content": "link-workspace-packages = true\nshared-workspace-lockfile = true\nprefer-frozen-lockfile = true\n"
  },
  {
    "path": ".nvmrc",
    "content": "v20.10.0\n"
  },
  {
    "path": ".prettierignore",
    "content": "dist\ncoverage\nnode_modules\n"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"printWidth\": 110,\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}\n"
  },
  {
    "path": ".stylelintrc.cjs",
    "content": "module.exports = {\n  extends: ['stylelint-config-standard', 'stylelint-config-recess-order', 'stylelint-config-css-modules'],\n  ignoreFiles: ['dist/**/*', 'coverage/**/*'],\n}\n"
  },
  {
    "path": ".yarnrc",
    "content": "registry \"https://registry.npmjs.org\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## v1.10.27\n\n- fix(types): fix issues with `skipLibCheck: false`\n\n## v1.10.26\n\n- fix: improve build; check output for ES2018 compatibility\n\n## v1.10.25\n\n- fix: bundle to ES5 syntax\n\n## v1.10.24\n\n- chore: generate api docs\n\n## v1.10.23\n\n- fix: transform nullish coalescing; fix symbol-tree build\n\n## v1.10.22\n\n- fix(actions/gesture): fix error when inertia is enabled for gestures #995\n\n## v1.10.21\n\n- fix(actions/drop): fix regression with drop event targets #1016\n\n## v1.10.20\n\n- fix(types): import plugins for module augmentations #933\n\n## v1.10.19\n\n- fix(core/scope): remove duplicate Interactable super.unset\n- fix(utils/pointerExtend): skip all vendor-prefixed props. Close #978\n\n## v1.10.18\n\n- fix(interact): remove types dependency\n- fix: set \"type\": \"module\" for scoped packages\n- fix(modifiers): allow toggling aspectRatio modifier during interaction\n- fix(types): import plugins for module augmentations\n- fix(interactjs): don't assign module.exports in esm package\n\n## v1.10.17\n\n- fixed missing typings when only the `@interactjs/interactjs` package is\n  installed and imported\n- added index to vue package for installing with side effect import\n\n## v1.10.16\n\n- remove vue and react deps fron pro `@interactjs/interactjs` package\n\n## v1.10.15\n\n- fixed an issue with broken `@interactjs/types` #972\n\n## v1.10.14\n\n- fixed an issue with iframes on Webkit #942. Thanks, @tulps, for PR #943\n- fixed top-right and bottom-left resizing with aspectRatio with sub-modifiers #944. Thanks again, @tulps, for PR #963\n- fixed typings for `@itneractjs/` scoped module packages #933\n- added `doubletap.double === true` event prop for consistency with `tap.double`\n- fixed a bug with calling `interactable.unset()` in a `drop` listener #919\n\n## v1.10.13\n\n- Added `.d.ts` files to all `@interactjs/*` packages\n\n## v1.10.12\n\n- fixed incorrect behaviour when `interactable.unset()` is called multiple\n  times\n\n## v1.10.11\n\n- fixed incorrect \"module\" field in package.json https://github.com/taye/interact.js/issues/894#issuecomment-811046898\n\n## v1.10.10\n\n- fixed issue with unresolved stub files #894\n- fixed commonjs import of `interactjs` package\n\n## v1.10.9\n\n- improved support for SSR environments\n\n## v1.10.8\n\n- fixed imports of missing modules #891\n\n## v1.10.7\n\n- correctly replace `process.env.npm_package_version` in min bundle #890\n\n## v1.10.6\n\n- fix packaging error\n\n## v1.10.5\n\n- fix packaging error\n\n## v1.10.4\n\n- fix NPE in indexOfDeepestElement if first element has no parent #887\n- improve babel-plugin-prod on windows #885\n\n## v1.10.3\n\n- fixed issue with TS strict null checks #882\n- fixed issue with type imports being emitted in JS modules #881\n\n## v1.10.2\n\n- marked interact.{on,off} methods as deprecated\n\n## v1.10.1\n\n- fixed mouseButtons option typings #865\n- removed plugin index module warnings\n\n## v1.10.0\n\n- changed production files extension from '.min.js' to '.prod.js' #857\n- added experimental `@interactjs/dev-tools/babel-plugin-prod` babel plugin to\n  change `@interactjs/*` imports to production versions\n- added `sideEffects` fields to package.json files\n\n## v1.9.22\n\n- fixed inertia issue with arbitrary plugin order #834\n- fixed inertia regression #853\n\n## v1.9.21\n\n- used findIndex polyfill to support 1E11 #852\n- fixed issue where resize reflow increased element size #817\n- fixed drop event order: fire `dropmove` after `dragenter` #841 and final\n  drop events before `dragend` #842\n- updated docs #844 #829\n\n## v1.9.20\n\n- fixed ordering of plugins\n\n## v1.9.19\n\n- exposed `DropEvent` type\n\n## v1.9.18\n\n- fixed further issues with types\n\n## v1.9.17\n\n- fixed missing types for interactjs package\n\n## v1.9.16\n\n- fixed missing types for interactjs package\n\n## v1.9.15\n\n- fixed missing types for interactjs package\n\n## v1.9.15\n\n- fixed further regression breaking typescript builds #816\n\n## v1.9.14\n\n- fixed regression breaking typescript builds #816\n\n## v1.9.13\n\n- fixed regression breaking es5 compatibility of .min.js bundle #814\n\n## v1.9.12\n\n- fixed regression breaking commonjs imports withotu .default\n\n## v1.9.11\n\n- fixed issue with missing width/height on rectChecker result\n- fixed resize checker with negative sizes\n- moved generated plugin use modules to @interactjs/_/{use/,}_/index.ts #800\n- changed snap function args to provide interaction proxy\n- restored dev-tools helpers in development bundle\n\n## v1.9.10\n\n- fixed issue with uninitialized scope in non browser env #803\n\n## v1.9.9\n\n- fixed typescript issue #807\n\n## v1.9.8\n\n- fixed minified bundle #802\n- fixed issue with removing delegated events #801\n\n## v1.9.7\n\n- fixed typing issues\n\n## v1.9.6\n\n- improved package dependencies\n\n## v1.9.5\n\n- made `core` and `utils` packages dependencies of `interact`\n\n## v1.9.4\n\n- restored `@interactjs/*/use/*.js*` builds\n\n## v1.9.2\n\n- fixed imports within generated modules\n\n## v1.9.1\n\n- added `@interactjs/*/use/*.min.js` builds\n- fixed issue with webpack minifier #800\n- fixed typescript issues\n\n## v1.9.0\n\n- added various `@interactjs/*/use` packages for simpler selective imports\n  #800\n- fixed endOnly modifiers without inertia\n\n## v1.8.5\n\n- fixed a but causing incorrect modifications after resuming inertia #790\n\n## v1.8.4\n\n- fixed bug when calling interaction.move() from start event #791\n\n## v1.8.3\n\n- fixed bug when calling interaction.move() from start event #791\n- fixed invalid non-array argument spread types #789\n- fixed missing typescript definition of some interactable methods #788\n- disabled `.d.ts.map` files output since the `.ts` source files are not\n  published\n- fixed typings for modifiers\n\n## v1.8.2\n\n- enabled `.d.ts.map` files output\n- added license field to @interactjs/interact package.json\n\n## v1.8.1\n\n- fixed an issue causing flickering a cursor on Firefox for Windows #781\n\n## v1.8.0\n\nChanges from prerelease versions listed below. See\nhttps://github.com/taye/interact.js/projects/4#column-7093512 for a list of\nissues and pull requests.\n\n## v1.8.0-rc.3\n\n- fixed incorrect publish\n\n## v1.8.0-rc.2\n\n- refactoring\n\n## v1.8.0-rc.1\n\n- fixed `interact.snappers.grid` arg typings\n  (https://twitter.com/ksumarine/status/1204457347856424960)\n- removed \"?\" from definitions for interact.{modifiers,snappers,createSnapGrid}\n\n## v1.8.0-rc.0\n\n- fixed `modifiers.restrictSize` #779\n- fixed option types in typescript and fixed devTools options #776\n\n## v1.8.0-alpha.7\n\n- reverted to typescript@3.6 to avoid backwards compatibility issues #775\n\n## v1.8.0-alpha.6\n\n- fixed dev scripts\n\n## v1.8.0-alpha.5\n\n- moved `interact.dynamicDrop` definition in order to avoid compilation errors\n\n## v1.8.0-alpha.4\n\n- added `main` field to interactjs package.json #774\n- removed baseUrl from project tsconfig to avoid relative imports in generated\n  declarations\n\n## v1.8.0-alpha.3\n\n- added missing typescript declaration files\n\n## v1.8.0-alpha.2\n\n- used non relative imports in .ts files with correct config for\n  babel-plugin-bare-import-rewrite\n\n## v1.8.0-alpha.1\n\n- added `event.modifiers` array #772\n\n## v1.8.0-alpha.0\n\n- added `aspectRatio` modifier #638\n\n## v1.7.4\n\n- fixed `interact.snappers.grid` arg typings\n  (https://twitter.com/ksumarine/status/1204457347856424960)\n- removed \"?\" from definitions for interact.{modifiers,snappers,createSnapGrid}\n\n## v1.7.3\n\n- fixed interactjs package main and browser fields #774\n- reverted to typescript@3.6 to avoid backwards compatibility issues #775\n\n## v1.7.2\n\n- fixed typescript definition files #771\n\n## v1.7.1\n\n- reorganized modules for esnext resolution\n\n## v1.7.0\n\n- fixed hold repeat `event.count`\n- added esnext js builds #769\n\n## v1.6.3\n\n- fixed issue with inertia resume with `endOnly: false` #765\n\n## v1.6.2\n\n- @mlucool added license field to package.json of sub modules #755\n- added `rect`, `deltaRect` and `edges` to resizestart and resizeend events #754\n\n## v1.6.1\n\n- fixed resize without invert\n\n## v1.6.0\n\n- avoided accessing deprecated event.mozPressure #751\n- changed typings to use `HTMLElement | SVGElement` for `event.target` #747\n- added `interacting` arg to cursorChecker #739\n- added zIndex compare for sibling dropzones\n\n## v1.5.4\n\n- fixed broken modifiers #746\n\n## v1.5.3\n\n- fixed issues with old modifiers API\n\n## v1.5.2\n\n- fixed null restriction issue #737\n- improved typings for modifiers\n\n## v1.5.1\n\n- fixed typing issues #738\n\n## v1.5.0\n\n- added `cursorChecker` option for drag and resize #736\n- allowed restrictions larger than the target element #735\n- added `interact.modifiers.restrictRect` with pre-set elementRect #735\n\n## v1.4.14\n\n- fixed issue with string restriction values that don't resolve to a rect\n  #731\n- changed plugin order so that `pointer-events` is installed before `inertia`\n\n## v1.4.13\n\n- fixed restrictSize min and max function restrictions\n\n## v1.4.12\n\n- fixed errors from calling `interaction.stop()` in start event #725\n\n## v1.4.11\n\n- fixed hold events #730\n\n## v1.4.10\n\n- fixed regression of preventing native drag behaviour #729\n\n## v1.4.9\n\n- fixed modifiers with inertia action-resume #728\n- fixed docs for snap grid limits #717\n\n## v1.4.8\n\n- fixed exports in generated typings #727\n\n## v1.4.7\n\n- fixed exports in generated typings #726\n\n## v1.4.6\n\n- fixed pointerEvents currentTarget\n\n## v1.4.5\n\n- @0xflotus fixed typos in docs #724\n- fixed error on iOS #682\n\n## v1.4.4\n\n- fixed an issue with interactions lingering on removed elements #723\n\n## v1.4.3\n\n- destroy only relevant interactions on interactable.unset()\n\n## v1.4.2\n\n- @jf-m fixed memory leaks and a bug on interactions stop [PR #715](https://github.com/taye/interact.js/pull/715)\n- fixed dropzones in shadow DOM [PR #722](https://github.com/taye/interact.js/pull/722)\n\n## v1.4.1\n\n- fixed scripts to run bundle optimizations and fix issues with browserify\n\n# v1.4.0\n\nMost notablly:\n\n- `interactable.reflow(action)` to re-run modifiers, drop, etc [PR #610](https://github.com/taye/interact.js/pull/610)\n- `dropEvent.reject()` [PR #613](https://github.com/taye/interact.js/pull/613)\n- snapEdges modifier [PR #620](https://github.com/taye/interact.js/pull/620)\n- per-action modifiers array [PR #625](https://github.com/taye/interact.js/pull/625)\n- autoStart set cursor on both target and &lt;html&gt; [PR #639](https://github.com/taye/interact.js/pull/639)\n- inertia: rename resume event to `${action}resume`\n- `interactable.reflow(action)` to re-run modifiers, drop, etc [PR #610](https://github.com/taye/interact.js/pull/610)\n- added `options.listeners` array/object for actions\n- `snapEdges` modifier [PR #620](https://github.com/taye/interact.js/pull/620)\n- fixed iOS preventDefault passive event issue ([issue #631](https://github.com/taye/interact.js/issues/631))\n- added `console.warn` messages for common, easily detected issues\n- improved docs\n- various fixes\n\nFull list of [changes on Github](https://github.com/taye/interact.js/compare/1.3.4...v1.4.0).\n\n## v1.3.3\n\n- fixed issues with action options ([PR #567](https://github.com/taye/interact.js/pull/567), [issue #570](https://github.com/taye/interact.js/issues/570))\n\n## v1.3.2\n\n- fixed iOS preventDefault passive event issue ([issue #561](https://github.com/taye/interact.js/issues/561))\n\n## v1.3.1\n\n- allowed calling `draggable.unset()` during `dragend` and `drop` event\n  listeners ([issue #560](https://github.com/taye/interact.js/issues/560))\n- allowed snap to be enabled with falsey targets value [issue #562](https://github.com/taye/interact.js/issues/562)\n\n## v1.3.0\n\nMost notably:\n\n- changed the npm and bower package names to \"interactjs\" ([issue\n  #399](https://github.com/taye/interact.js/issues/399)\n- major refactor with [PR #231](https://github.com/taye/interact.js/pull/231).\n- removed deprecated methods:\n  - `Interactable`: `squareResize`, `snap`, `restrict`, `inertia`,\n    `autoScroll`, `accept`\n  - `interact`: `enabbleDragging`, `enableResizing`, `enableGesturing`,\n    `margin`\n- new `hold` option for starting actions\n- new `interaction.end()` method\n  ([df963b0](https://github.com/taye/interact.js/commit/df963b0))\n- `snap.offset` `self` option ([issue\n  #204](https://github.com/taye/interact.js/issues/204/#issuecomment-154879052))\n- `interaction.doMove()`\n  ([3489ee1](https://github.com/taye/interact.js/commit/3489ee1))\n  ([c5c658a](https://github.com/taye/interact.js/commit/c5c658a))\n- snap grid limits\n  ([d549672](https://github.com/taye/interact.js/commit/d549672))\n- improved iframe support ([PR\n  #313](https://github.com/taye/interact.js/pull/313))\n- `actionend` event dx/dy are now `0`, not the difference between start and\n  end coords ([cbfaf00](https://github.com/taye/interact.js/commit/cbfaf00))\n- replaced drag `axis` option with `startAxis` and `lockAxis`\n- added pointerEvents options:\n  - `holdDuration`\n    ([1c58f92](https://github.com/taye/interact.js/commit/1c58f927)),\n  - `ignoreFrom` and `allowFrom`\n    ([6cbaad6](https://github.com/taye/interact.js/commit/6cbaad6d))\n  - `origin` ([7823bb9](https://github.com/taye/interact.js/commit/7823bb95))\n- action events set with action method options (eg.\n  `target.draggable({onmove})` are removed when that action is disabled with a\n  method call ([cca4e26](https://github.com/taye/interact.js/commit/cca4e260))\n- `context` option now works for Element targets\n  ([8f64a7a](https://github.com/taye/interact.js/commit/8f64a7a4))\n- added an action `mouseButtons` option and allowed actions only with the left\n  mouse button by default\n  ([54ebdc3](https://github.com/taye/interact.js/commit/54ebdc3e))\n- added repeating `hold` events\n  ([fe11a8e](https://github.com/taye/interact.js/commit/fe11a8e5))\n- fixed `Interactable.off` ([PR\n  #477](https://github.com/taye/interact.js/pull/477))\n- added `restrictEdges`, `restrictSize` and `snapSize` resize modifiers ([PR\n  #455](https://github.com/taye/interact.js/pull/455))\n\nFull list of [changes on Github](https://github.com/taye/interact.js/compare/v1.2.6...v1.3.0).\n\n## 1.2.6\n\n### resize.preserveAspectRatio\n\n```javascript\ninteract(target).resizable({ preserveAspectRatio: true })\n```\n\nSee [PR #260](https://github.com/taye/interact.js/pull/260).\n\n### Deprecated\n\n- `interact.margin(number)` - Use `interact(target).resizable({ margin: number });` instead\n\n### Fixed\n\n- incorrect coordinates of the first movement of every action ([5e5a040](https://github.com/taye/interact.js/commit/5e5a040))\n- warning about deprecated \"webkitForce\" event property ([0943290](https://github.com/taye/interact.js/commit/0943290))\n- bugs with multiple concurrent interactions ([ed53aee](http://github.com/taye/interact.js/commit/ed53aee))\n- iPad 1, iOS 5.1.1 error \"undefined is not a function\" when autoScroll is set\n  to true ([PR #194](https://github.com/taye/interact.js/pull/194))\n\nFull list of [changes on Github](https://github.com/taye/interact.js/compare/v1.2.5...v1.2.6)\n\n## 1.2.5\n\n### Changed parameters to actionChecker and drop.checker\n\n- Added `event` as the first argument to actionCheckers. See commit [88dc583](https://github.com/taye/interact.js/commit/88dc583)\n- Added `dragEvent` as the first parameter to drop.checker functions. See\n  commits [16d74d4](https://github.com/taye/interact.js/commit/16d74d4) and [d0c4b69](https://github.com/taye/interact.js/commit/d0c4b69)\n\n### Deprecated methods\n\ninteractable.accept - instead, use:\n\n```javascript\ninteract(target).dropzone({ accept: stringOrElement })\n```\n\ninteractable.dropChecker - instead, use:\n\n```javascript\ninteract(target).dropzone({ checker: function () {} })\n```\n\n### Added resize.margin\n\nSee https://github.com/taye/interact.js/issues/166#issuecomment-91234390\n\n### Fixes\n\n- touch coords on Presto Opera Mobile - see commits [886e54c](https://github.com/taye/interact.js/commit/886e54c) and [5a3a850](https://github.com/taye/interact.js/commit/5a3a850)\n- bug with multiple pointers - see commit [64882d3](https://github.com/taye/interact.js/commit/64882d3)\n- accessing certain recently deprecated event properties in Blink - see\n  commits [e91fbc6](https://github.com/taye/interact.js/commit/e91fbc6) and [195cfe9](https://github.com/taye/interact.js/commit/195cfe9)\n- dropzones with `accept: 'pointer'` in scrolled pages on iOS6 and lower - see\n  commit [0b94aac](https://github.com/taye/interact.js/commit/0b94aac)\n- setting styleCursor through Interactable options object - see [PR\n  #270](https://github.com/taye/interact.js/pull/270)\n- one missed interaction element on stop triggered - see [PR\n  #258](https://github.com/taye/interact.js/pull/258)\n- pointer dt on touchscreen devices - see [PR\n  #215](https://github.com/taye/interact.js/pull/215)\n- autoScroll with containers with fixed position - see commit [3635840](https://github.com/taye/interact.js/commit/3635840)\n- autoScroll for mobile - see #180\n- preventDefault - see commits [1984c80](https://github.com/taye/interact.js/commit/1984c80) and [6913959](https://github.com/taye/interact.js/commit/6913959)\n- occasional error - see [issue\n  #183](https://github.com/taye/interact.js/issue/183)\n- Interactable#unset - see [PR\n  #178](https://github.com/taye/interact.js/pull/178)\n- coords of start event after manual start - see commit [fec73b2](https://github.com/taye/interact.js/commit/fec73b2)\n- bug with touch and selector interactables - see commit [d8df3de](https://github.com/taye/interact.js/commit/d8df3de)\n- touch doubletap bug - see [273f461](https://github.com/taye/interact.js/commit/273f461)\n- event x0/y0 with origin - see [PR\n  #167](https://github.com/taye/interact.js/pull/167)\n\n## 1.2.4\n\n### Resizing from all edges\n\nWith the new [resize edges API](https://github.com/taye/interact.js/pull/145),\nyou can resize from the top and left edges of an element in addition to the\nbottom and right. It also allows you to specify CSS selectors, regions or\nelements as the resize handles.\n\n### Better `dropChecker` arguments\n\nThe arguments to `dropChecker` functions have been expanded to include the\nvalue of the default drop check and some other useful objects. See [PR\n161](https://github.com/taye/interact.js/pull/161)\n\n### Improved `preventDefault('auto')`\n\nIf manuanStart is `true`, default prevention will happen only while\ninteracting. Related to [Issue\n138](https://github.com/taye/interact.js/issues/138).\n\n### Fixed inaccurate snapping\n\nThis removes a small inaccuracy when snapping with one or more\n`relativeOffsets`.\n\n### Fixed bugs with multiple pointers\n\n## 1.2.3\n\n### ShadowDOM\n\nBasic support for ShadowDOM was implemented in [PR\n143](https://github.com/taye/interact.js/pull/143)\n\n### Fixed some issues with events\n\nFixed Interactable#on({ type: listener }). b8a5e89\n\nAdded a `double` property to tap events. `tap.double === true` if the tap will\nbe followed by a `doubletap` event. See [issue\n155](https://github.com/taye/interact.js/issues/155#issuecomment-71202352).\n\nFixed [issue 150](https://github.com/taye/interact.js/issues/150).\n\n## 1.2.2\n\n### Fixed DOM event removal\n\nSee [issue 149](https://github.com/taye/interact.js/issues/149).\n\n## 1.2.1\n\n### Fixed Gestures\n\nGestures were completely [broken in\nv1.2.0](https://github.com/taye/interact.js/issues/146). They're fixed now.\n\n### Restriction\n\nFixed restriction to an element when the element doesn't have a rect (`display: none`, not in DOM, etc.). [Issue\n144](https://github.com/taye/interact.js/issues/144).\n\n## 1.2.0\n\n### Multiple interactions\n\nMultiple interactions have been enabled by default. For example:\n\n```javascript\ninteract('.drag-element').draggable({\n  enabled: true,\n  // max          : Infinity,  // default\n  // maxPerElement: 1,         // default\n})\n```\n\nwill allow multiple `.drag-element` to be dragged simultaneously without having\nto explicitly set <code>max:&nbsp;integerGreaterThan1</code>. The default\n`maxPerElement` value is still 1 so only one drag would be able to happen on\neach `.drag-element` unless the `maxPerElement` is changed.\n\nIf you don't want multiple interactions, call `interact.maxInteractions(1)`.\n\n### Snapping\n\n#### Unified snap modes\n\nSnap modes have been\n[unified](https://github.com/taye/interact.js/pull/127). A `targets` array\nnow holds all the snap objects and functions for snapping.\n`interact.createSnapGrid(gridObject)` returns a function that snaps to the\ndimensions of the given grid.\n\n#### `relativePoints` and `origin`\n\n```javascript\ninteract(target).draggable({\n  snap: {\n    targets: [{ x: 300, y: 300 }],\n    relativePoints: [\n      { x: 0, y: 0 }, // snap relative to the top left of the element\n      { x: 1, y: 1 }, // and also to the bottom right\n    ],\n\n    // offset the snap target coordinates\n    // can be an object with x/y or 'startCoords'\n    offset: { x: 50, y: 50 },\n  },\n})\n```\n\n#### snap function interaction arg\n\nThe current `Interaction` is now passed as the third parameter to snap functions.\n\n```js\ninteract(target).draggable({\n  snap: {\n    targets: [\n      function (x, y, interaction) {\n        if (!interaction.dropTarget) {\n          return { x: 0, y: 0 }\n        }\n      },\n    ],\n  },\n})\n```\n\n#### snap.relativePoints and offset\n\nThe `snap.relativePoints` array succeeds the snap.elementOriign object. But\nbackwards compatibility with `elementOrigin` and the old snapping interface is\nmaintained.\n\n`snap.offset` lets you offset all snap target coords.\n\nSee [this PR](https://github.com/taye/interact.js/pull/133) for more info.\n\n#### slight change to snap range calculation\n\nSnapping now occurs if the distance to the snap target is [less than or\nequal](https://github.com/taye/interact.js/commit/430c28c) to the target's\nrange.\n\n### Inertia\n\n`inertia.zeroResumeDelta` is now `true` by default.\n\n### Per-action settings\n\nSnap, restrict, inertia, autoScroll can be different for drag, restrict and\ngesture. See [PR 115](https://github.com/taye/interact.js/pull/115).\n\nMethods for these settings on the `interact` object (`interact.snap()`,\n`interact.autoScroll()`, etc.) have been removed.\n\n### Space-separated string and array event list and eventType:listener object\n\n```javascript\nfunction logEventType(event) {\n  console.log(event.type, event.target)\n}\n\ninteract(target).on('down tap dragstart gestureend', logEventType)\n\ninteract(target).on(['move', 'resizestart'], logEventType)\n\ninteract(target).on({\n  dragmove: logEvent,\n  keydown: logEvent,\n})\n```\n\n### Interactable actionChecker\n\nThe expected return value from an action checker has changed from a string to\nan object. The object should have a `name` and can also have an `axis`\nproperty. For example, to resize horizontally:\n\n```javascript\ninteract(target)\n  .resizeable(true)\n  .actionChecker(function (pointer, defaultAction, interactable, element) {\n    return {\n      name: 'resize',\n      axis: 'x',\n    }\n  })\n```\n\n### Plain drop event objects\n\nAll drop-related events are [now plain\nobjects](https://github.com/taye/interact.js/issues/122). The related drag\nevents are referenced in their `dragEvent` property.\n\n### Interactable.preventDefault('always' || 'never' || 'auto')\n\nThe method takes one of the above string values. It will still accept\n`true`/`false` parameters which are changed to `'always'`/`'never'`.\n\n## 1.1.3\n\n### Better Events\n\nAdding a function as a listener for an InteractEvent or pointerEvent type\nmultiple times will cause that function to be fired multiple times for the\nevent. Previously, adding the event type + function combination again had no\neffect.\n\nAdded new event types [down, move, up, cancel,\nhold](https://github.com/taye/interact.js/pull/101).\n\nTap and doubletap with multiple pointers was improved.\n\nAdded a workaround for IE8's unusual [dblclick event\nsequence](http://www.quirksmode.org/dom/events/click.html) so that doubletap\nevents are fired.\n\nFixed a [tapping issue](https://github.com/taye/interact.js/issues/104) on\nWindows Phone/RT.\n\nFixed a bug that caused the origins of all elements with tap listeners to be\nsubtracted successively as a tap event propagated.\n\n[Fixed delegated events](https://github.com/taye/interact.js/commit/e972154)\nwhen different contexts have been used.\n\n### iFrames\n\n[Added basic support](https://github.com/taye/interact.js/pull/98) for sharing\none instance of interact.js between multiplie windows/frames. There are still\nsome issues.\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "If you have questions about the [API](http://interactjs.io/api) that aren't answered in the [docs](http://interactjs.io/docs) or [FAQ](http://interactjs.io/docs/faq), try asking in the [Gitter chatroom](https://gitter.im/taye/interact.js) or on [Stackoverflow](https://stackoverflow.com/questions/tagged/interact.js).\n\nIf you've found something that looks like a bug, include a link to a minimal demo on [JSFilddle](https://jsfiddle.net), [Codepen](https://codepen.io) with instructions to reproduce the bug with and roughly follow the following issue description format:\n\n### Expected behavior\nTell us what should happen\n\n### Actual behavior\nTell us what happens instead\n\n### System configuration\n**interact.js version**:\n**Browser name and version**:\n**Operating System**:\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2012-present Taye Adeyemi <dev@taye.me>\n\nPermission is hereby granted, free of charge, to any person \nobtaining a copy of this software and associated \ndocumentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights \nto use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the \nfollowing conditions:\n\nThe above copyright notice and this permission notice shall \nbe included in all copies or substantial portions of the \nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY \nKIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR \nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR \nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "PULL_REQUEST_TEMPLATE.md",
    "content": "Make sure to include tests in your pull request.\n"
  },
  {
    "path": "README.md",
    "content": "<a href=\"http://interactjs.io\"><img alt=\"interact.js\" src=\"https://c4d6f7d727e094887e93-4ea74b676357550bd514a6a5b344c625.ssl.cf2.rackcdn.com/ijs-solid.svg\" height=\"70px\" width=\"100%\"></a>\n\n<h2>\n  JavaScript drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE9+).\n</h2>\n\n<div align=\"center\">\n<a href=\"https://gitter.im/taye/interact.js\"><img src=\"https://badges.gitter.im/taye/interact.js.svg\" alt=\"Gitter\"></a>\n<a href=\"https://www.jsdelivr.com/package/npm/interactjs\"><img src=\"https://data.jsdelivr.com/v1/package/npm/interactjs/badge\" alt=\"jsDelivr\"></a>\n<a href=\"https://github.com/taye/interact.js/actions/workflows/workflow.yml\"><img src=\"https://github.com/taye/interact.js/actions/workflows/workflow.yml/badge.svg\" alt=\"Build Status\"></a>\n<a href=\"https://codeclimate.com/github/taye/interact.js/test_coverage\"><img src=\"https://api.codeclimate.com/v1/badges/0168aeaeed781a949088/test_coverage\"/></a>\n</div>\n<br>\n\nFeatures include:\n\n- **inertia** and **snapping**\n- **multi-touch**, simultaneous interactions\n- cross browser and device, supporting the **desktop and mobile** versions of\n  Chrome, Firefox and Opera as well as **Internet Explorer 9+**\n- interaction with [**SVG**](http://interactjs.io/#use_in_svg_files) elements\n- being **standalone and customizable**\n- **not modifying the DOM** except to change the cursor (but you can disable\n  that)\n\n## Installation\n\n- [npm](https://www.npmjs.org/): `npm install interactjs`\n- [jsDelivr CDN](https://cdn.jsdelivr.net/npm/interactjs/): `<script src=\"https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js\"></script>`\n- [unpkg CDN](https://unpkg.com/interactjs/): `<script src=\"https://unpkg.com/interactjs/dist/interact.min.js\"></script>`\n- [Rails 5.1+](https://rubyonrails.org/):\n  1. `yarn add interactjs`\n  2. `//= require interactjs/interact`\n- [Webjars SBT/Play 2](https://www.webjars.org/): `libraryDependencies ++= Seq(\"org.webjars.npm\" % \"interactjs\" % version)`\n\n### Typescript definitions\n\nThe project is written in Typescript and the npm package includes the type\ndefinitions, but if you need the typings alone, you can install them with:\n\n```\nnpm install --save-dev @interactjs/types\n```\n\n## Documentation\n\nhttp://interactjs.io/docs\n\n## Example\n\n```javascript\nvar pixelSize = 16;\n\ninteract('.rainbow-pixel-canvas')\n  .origin('self')\n  .draggable({\n    modifiers: [\n      interact.modifiers.snap({\n        // snap to the corners of a grid\n        targets: [\n          interact.snappers.grid({ x: pixelSize, y: pixelSize }),\n        ],\n      })\n    ],\n    listeners: {\n      // draw colored squares on move\n      move: function (event) {\n        var context = event.target.getContext('2d'),\n            // calculate the angle of the drag direction\n            dragAngle = 180 * Math.atan2(event.dx, event.dy) / Math.PI;\n\n        // set color based on drag angle and speed\n        context.fillStyle = 'hsl(' + dragAngle + ', 86%, '\n                            + (30 + Math.min(event.speed / 1000, 1) * 50) + '%)';\n\n        // draw squares\n        context.fillRect(event.pageX - pixelSize / 2, event.pageY - pixelSize / 2,\n                         pixelSize, pixelSize);\n      }\n    }\n  })\n  // clear the canvas on doubletap\n  .on('doubletap', function (event) {\n    var context = event.target.getContext('2d');\n\n    context.clearRect(0, 0, context.canvas.width, context.canvas.height);\n  });\n\n  function resizeCanvases () {\n    [].forEach.call(document.querySelectorAll('.rainbow-pixel-canvas'), function (canvas) {\n      canvas.width = document.body.clientWidth;\n      canvas.height = window.innerHeight * 0.7;\n    });\n  }\n\n  // interact.js can also add DOM event listeners\n  interact(document).on('DOMContentLoaded', resizeCanvases);\n  interact(window).on('resize', resizeCanvases);\n```\n\nSee the above code in action at https://codepen.io/taye/pen/tCKAm\n\n## License\n\ninteract.js is released under the [MIT License](http://taye.mit-license.org).\n\n[ijs-twitter]: https://twitter.com/interactjs\n[upcoming-changes]: https://github.com/taye/interact.js/blob/main/CHANGELOG.md#upcoming-changes\n"
  },
  {
    "path": "babel.config.cjs",
    "content": "module.exports = {\n  presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'],\n}\n"
  },
  {
    "path": "bin/_add_plugin_indexes",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/add_plugin_indexes')\n"
  },
  {
    "path": "bin/_bundle",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/bundle')\n"
  },
  {
    "path": "bin/_check_deps",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/_check_deps')\n"
  },
  {
    "path": "bin/_clean",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/clean')\n"
  },
  {
    "path": "bin/_link",
    "content": "#!/bin/bash\nROOT=$(dirname $(dirname $(readlink -f $0)))\nif [ -z \"$ROOT\" ]\nthen\n    ROOT=$(dirname $(dirname $0))\nfi\n\nmodules_scope_dir=node_modules/@interactjs\nmodules_bin_dir=node_modules/.bin\n\nmkdir -p $modules_scope_dir $modules_bin_dir\n\nrm $modules_scope_dir/* 2> /dev/null\n\n# link _dev package\nln -sf $ROOT $modules_scope_dir/_dev\n\n# link all scoped packages from CWD\nfor package in $(cd packages/@interactjs && ls -d *); do\n  ln -sf ../../packages/@interactjs/$package $modules_scope_dir\ndone\n\n# link all packages from this repo\nfor package in $(cd $ROOT/packages/@interactjs && ls -d *); do\n  ln -sf $ROOT/packages/@interactjs/$package $modules_scope_dir\ndone\n\n# link all bins from this repo and from CWD\ncd node_modules/.bin && ln -sf $ROOT/bin/* ../../bin/* .\n"
  },
  {
    "path": "bin/_lint",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/lint')\n"
  },
  {
    "path": "bin/_release",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/release')\n"
  },
  {
    "path": "bin/_types",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/types')\n"
  },
  {
    "path": "bin/_version",
    "content": "#!/usr/bin/env node\nrequire('../scripts/bin/version')\n"
  },
  {
    "path": "bundle.rollup.config.cjs",
    "content": "/* eslint-disable import/no-extraneous-dependencies */\nconst { resolve } = require('path')\n\nconst babel = require('@rollup/plugin-babel')\nconst commonjs = require('@rollup/plugin-commonjs')\nconst nodeResolve = require('@rollup/plugin-node-resolve')\nconst replace = require('@rollup/plugin-replace')\nconst terser = require('@rollup/plugin-terser')\nconst { defineConfig } = require('rollup')\n\nconst headers = require('./scripts/headers')\nconst { extendBabelOptions, getModuleDirectories, isPro } = require('./scripts/utils')\n\nconst globals = {\n  react: 'React',\n  vue: 'Vue',\n}\nconst external = Object.keys(globals)\nconst INPUT_EXTENSIONS = ['.ts', '.tsx', '.vue']\n\nmodule.exports = defineConfig(async () => {\n  const variations = [\n    { env: { NODE_ENV: 'development' }, ext: '.js', minify: isPro },\n    { env: { NODE_ENV: 'production' }, ext: '.min.js', minify: true },\n  ]\n\n  return variations.map(({ minify, ext, env }) => {\n    const babelConfig = extendBabelOptions({\n      babelrc: false,\n      configFile: false,\n      browserslistConfigFile: false,\n      targets: { ie: 9 },\n      babelHelpers: 'bundled',\n      skipPreflightCheck: true,\n      extensions: INPUT_EXTENSIONS,\n      plugins: [[require.resolve('@babel/plugin-transform-runtime'), { helpers: false, regenerator: true }]],\n    })\n\n    return defineConfig({\n      input: resolve(__dirname, 'packages', 'interactjs', 'index.ts'),\n      external,\n      plugins: [\n        nodeResolve({\n          modulePaths: getModuleDirectories(),\n          extensions: INPUT_EXTENSIONS,\n        }),\n        commonjs({ include: '**/node_modules/{rebound,symbol-tree}/**' }),\n        babel(babelConfig),\n        replace({\n          preventAssignment: true,\n          values: Object.entries({\n            npm_package_version: process.env.npm_package_version,\n            IJS_BUNDLE: '1',\n            ...env,\n          }).reduce((acc, [key, value]) => {\n            acc[`process.env.${key}`] = JSON.stringify(value)\n            return acc\n          }, {}),\n        }),\n        minify &&\n          terser({\n            module: false,\n            mangle: true,\n            compress: {\n              ecma: 5,\n              unsafe: true,\n              unsafe_Function: true,\n              unsafe_arrows: false,\n              unsafe_methods: true,\n            },\n            format: {\n              preamble: headers?.min,\n            },\n          }),\n      ],\n      context: 'window',\n      moduleContext: 'window',\n      output: {\n        file: resolve(__dirname, 'packages', 'interactjs', 'dist', `interact${ext}`),\n        format: 'umd',\n        name: 'interact',\n        banner: minify ? headers.min : headers.raw,\n        minifyInternalExports: true,\n        inlineDynamicImports: true,\n        sourcemap: true,\n        globals,\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "docs/action-options.md",
    "content": "---\ntitle: Action Options\n---\n\nThe `Interactable` methods `draggable()`, `resizable()` and `gesturable()` are\nused to enable and configure actions for target elements. They all have some\ncommon options as well as some action-specific options and event properties.\n\nDrag, resizem and gesture interactions fire `InteractEvent`s which have the\nfollowing properties common to all action types:\n\n| InteractEvent property   | Description                                      |\n| ------------------------ | ------------------------------------------------ |\n| `target`                 | The element that is being interacted with        |\n| `interactable`           | The Interactable that is being interacted with   |\n| `interaction`            | The Interaction that the event belongs to        |\n| `x0`, `y0`               | Page x and y coordinates of the starting event   |\n| `clientX0`, `clientY0`   | Client x and y coordinates of the starting event |\n| `dx`, `dy`               | Change in coordinates of the mouse/touch         |\n| `velocityX`, `velocityY` | The Velocity of the pointer                      |\n| `speed`                  | The speed of the pointer                         |\n| `timeStamp`              | The time of creation of the event object         |\n\n## Common Action Options\n\nThe Interactable methods `draggable`, `resizable` and `gesturable` take either\n`true` or `false` to simply allow/disallow the action or an object with\nproperties to change certain settings.\n\n### `max`\n\n`max` is used to limit the number of concurrent interactions that can target an\ninteractable. By default, any number of interactions can target an\ninteractable.\n\n### `maxPerElement`\n\nBy default only 1 interaction can target the same interactable+element\ncombination. If you want to allow multiple interactions on the same target\nelement, set the `maxPerElement` property of your object to a value `>= 2`.\n\n### `manualStart`\n\nIf this is changed to `true` then drag, resize and gesture actions will have to\nbe started with a call to [`Interaction#start`][interaction-start] as the usual\n`down`, `move`, `<action>start`... sequence will not start an action. See\n[auto-start](/docs/auto-start).\n\n### `hold`\n\nThe action will start after the pointer is held down for the given number of milliseconds.\n\n### `inertia`\n\nChange inertia settings for drag, and resize. See [docs/inertia](/docs/inertia).\n\n### `styleCursor`\n\nIf the [auto-start](/docs/auto-start) feature is enabled, interact will style\nthe cursor of draggable and resizable elements as you hover over them.\n\n```js\ninteract(target).styleCursor(false)\n```\n\nTo disable this for all actions, set the `styleCursor` option to `false`\n\n### `cursorChecker`\n\n```js\ninteract(target)\n  .resizable({\n    edges: { left: true, right: true },\n    cursorChecker (action, interactable, element, interacting) {\n      // the library uses biderectional arrows <-> by default,\n      // but we want specific arrows (<- or ->) for each diriection\n      if (action.edges.left) { return 'w-resize' }\n      if (action.edges.right) { return 'e-resize' }\n    },\n  })\n  .draggable({\n    cursorChecker () {\n      // don't set a cursor for drag actions\n      return null\n    },\n  })\n```\n\nYou can disable default cursors with `interact(target).styleCursor(false)`, but\nthat will disable cursor styling for all actions. To disable or change the\ncursor for each action, you can set a `cursorChecker` function which takes info\nabout the current interaction and returns the CSS cursor value to set on the\ntarget element.\n\n### `autoScroll`\n\n```javascript\ninteract(element)\n  .draggable({\n    autoScroll: true,\n  })\n  .resizable({\n    autoScroll: {\n      container: document.body,\n      margin: 50,\n      distance: 5,\n      interval: 10,\n      speed: 300,\n    }\n  })\n```\n\nScroll a container (`window` or an HTMLElement) when a drag or resize move\nhappens at the edge of the container.\n\n### `allowFrom` (handle)\n\n```html\n<div class=\"movable-box\">\n  <div class=\"drag-handle\" />\n  Content\n  <div class=\"resize-handle\" />\n</div>\n```\n\n```javascript\ninteract('.movable-box')\n  .draggable({\n    allowFrom: '.drag-handle',\n  })\n  .resizable({\n    allowFrom: '.resize-handle',\n  })\n  .pointerEvents({\n    allowFrom: '*',\n  })\n```\n\nThe `allowFrom` option lets you specify a target CSS selector or Element which\nmust be the target of the pointer down event in order for the action to start.\nThis option available for drag, resize and gesture, as well as `pointerEvents`\n(down, move, hold, etc.). Using the `allowFrom` option, you may specify handles\nfor each action separately and for all your pointerEvents listeners.\n\nThe `allowFrom` elements **must** be children of the target interactable\nelement. {.notice .info}\n\n### `ignoreFrom`\n\n```html\n<div id=\"movable-box\">\n  <p class=\"content\">Selectable text</p>\n  <div no-pointer-event>Should not fire tap, hold, etc. events</div>\n</div>\n```\n\n```javascript\nvar movable = document.querySelector('#movable-box')\n\ninteract(movable)\n  .draggable({\n    ignoreFrom: '.content',\n    onmove: function (event) {\n      /* ... */\n    }\n  })\n  .pointerEvents({\n    ignoreFrom: '[no-pointer-event]',\n  })\n  .on('tap', function (event) {\n  })\n```\n\nThe compliment to `allowFrom`, `ignoreFrom` lets you specify elements within\nyour target with which to avoid starting actions. This is useful when certain\nelements need to maintain default behavior when interacted with. For example,\ndragging around a text/contentEditable, by wrapping this object with a\ndraggable element and ignoring the editable content you maintain the ability to\nhighlight text without moving the element.\n\n### `enabled`\n\nEnable the action for the Interactable. If the options object has no `enabled`\nproperty or the property value is `true` then the action is enabled. If\n`enabled` is false, the action is disabled.\n\n[interaction-start]: /docs/auto-start\n"
  },
  {
    "path": "docs/auto-start.md",
    "content": "---\ntitle: 'AutoStart (manualStart: false)'\n---\n\nThe [pre-bundled](/docs/installation) package includes the `auto-start` plugin\nwhich will start interactions when the pointer goes down and then moves on\nenabled target elements. You can disable this for an action by setting the\n`manualStart` option to `true`.\n\n```js\ninteract(target)\n  .draggable({\n    manualStart: true,\n  })\n  .on('doubletap', function (event) {\n    var interaction = event.interaction\n\n    if (!interaction.interacting()) {\n      interaction.start(\n        { name: 'drag' },\n        event.interactable,\n        event.currentTarget,\n      )\n    }\n  })\n```\n\nWith `manualStart: true`, you will need to start the action from a pointer event\nlistener by calling `event.interaction.start(actionInfo)`. Because the library\nno longer decides when to start actions, the cursor will not be set\nautomatically.\n"
  },
  {
    "path": "docs/draggable.md",
    "content": "---\ntitle: Draggable\n---\n\nDragging is the simplest action interact.js provides. To make an element\ndraggable, create an interactable with your desired target then call the\n`draggable` method with the options that you need.\n\n<LiveDemo :demoHtml=\"import('@/demos/draggable/basic.html?raw')\" :removeNext=\"3\" hide-demo-only />\n\n```html\n<div class=\"draggable\">Draggable Element</div>\n```\n\n```css\n.draggable {\n  touch-action: none;\n  user-select: none;\n}\n```\n\n```js\nconst position = { x: 0, y: 0 }\n\ninteract('.draggable').draggable({\n  listeners: {\n    start (event) {\n      console.log(event.type, event.target)\n    },\n    move (event) {\n      position.x += event.dx\n      position.y += event.dy\n\n      event.target.style.transform = `translate(${position.x}px, ${position.y}px)`\n    },\n  },\n})\n```\n\nIn addition to the common [`InteractEvent`](/docs/events#interactevents)\nproperties, `dragmove` events also have:\n\n| Drag event property | Description                                       |\n| ------------------- | ------------------------------------------------- |\n| `dragEnter`         | The dropzone this Interactable was dragged over   |\n| `dragLeave`         | The dropzone this Interactable was dragged out of |\n\nRemember to use CSS `touch-action: none` to prevent the browser from panning\nwhen the user drags with a touch pointer, and `user-select: none` to disable\ntext selection. {.notice .info}\n\n## `lockAxis` and `startAxis`\n\n```javascript\n// lock the drag to the starting direction\ninteract(singleAxisTarget).draggable({\n  startAxis: 'xy'\n  lockAxis: 'start'\n});\n\n// only drag if the drag was started horizontally\ninteract(horizontalTarget).draggable({\n  startAxis: 'x'\n  lockAxis: 'x'\n});\n```\n\nThere are two options for controlling the axis of drag actions: `startAxis` and\n`lockAxis`.\n\n`startAxis` sets the direction that the initial movement must be in for the\naction to start. Use `'x'` to require the user to start dragging horizontally or\n`'y'` to start dragging vertically.\n\n`lockAxis` causes the drag events to change only in the given axis. If a value\nof `'start'` is used, then the drag will be locked to the starting direction.\n"
  },
  {
    "path": "docs/dropzone.md",
    "content": "---\ntitle: Dropzone\n---\n\nDropzones define elements that draggable targets can be \"dropped\" into and which\nelements will be accepted. Like with drag events, drop events don't modify the\nDOM to re-parent elements. You will have to do this in your own event listeners\nif you need this.\n\n```javascript\ninteract(dropTarget)\n  .dropzone({\n    ondrop: function (event) {\n      alert(event.relatedTarget.id\n            + ' was dropped into '\n            + event.target.id)\n    }\n  })\n  .on('dropactivate', function (event) {\n    event.target.classList.add('drop-activated')\n  })\n```\n\n## Dropzone Events\n\nDropzone events are plain objects with the following properties:\n\n| Property        | Description                                     |\n| --------------- | ----------------------------------------------- |\n| `target`        | The dropzone element                            |\n| `dropzone`      | The dropzone Interactable                       |\n| `relatedTarget` | The element that's being dragged                |\n| `draggable`     | The Interactable that's being dragged           |\n| `dragEvent`     | The related drag event – `drag{start,move,end}` |\n| `timeStamp`     | Time of the event                               |\n| `type`          | The event type                                  |\n\n```javascript\ninteract('.dropzone').dropzone({\n  accept: '.drag0, .drag1',\n});\n```\n\n## `accept`\n\nThe dropzone `accept` option is a CSS selector or element which must match the\ndragged element in order for drop events to be fired.\n\n```javascript\ninteract(target).dropzone({\n  overlap: 0.25\n});\n```\n\nThe `overlap` option sets how drops are checked for. The allowed values are:\n\n- `'pointer'` – the pointer must be over the dropzone (default)\n- `'center'` – the draggable element's center must be over the dropzone\n- a number from 0-1 which is the (intersection area) / (draggable area). e.g.\n  `0.5` for drop to happen when half of the area of the draggable is over the\n  dropzone\n\n## `checker`\n\nThe `checker` option is a function that you set to additionally check if a\ndragged element can be dropped into a dropzone.\n\n```javascript\ninteract(target).dropzone({\n  checker: function (\n    dragEvent,         // related dragmove or dragend\n    event,             // Touch, Pointer or Mouse Event\n    dropped,           // bool default checker result\n    dropzone,          // dropzone Interactable\n    dropzoneElement,   // dropzone element\n    draggable,         // draggable Interactable\n    draggableElement   // draggable element\n  ) {\n\n    // only allow drops into empty dropzone elements\n    return dropped && !dropElement.hasChildNodes();\n  }\n});\n```\n\nThe checker function takes the following arguments:\n\n| Arg                | Description                                         |\n| ------------------ | --------------------------------------------------- |\n| `dragEvent`        | related dragmove or dragend event                   |\n| `event`            | The user move/up/end Event related to the dragEvent |\n| `dropped`          | The value from the default drop checker             |\n| `dropzone`         | The dropzone interactable                           |\n| `dropElement`      | The dropzone element                                |\n| `draggable`        | The Interactable being dragged                      |\n| `draggableElement` | The actual element that's being dragged             |\n"
  },
  {
    "path": "docs/events.md",
    "content": "---\ntitle: Events\n---\n\n## InteractEvents\n\n<LiveDemo :demoHtml=\"import('@/demos/events/actions.html?raw')\" :removeNext=\"3\"/>\n\n```html\n<div>Drag, resize, or perform a multi-touch gesture</div>\n```\n\n```css\n.target {\n  display: inline-block;\n  min-height: 3rem;\n  background-color: #29e;\n  color: white;\n  padding: 1rem;\n  border-radius: 0.75rem;\n}\n```\n\n```javascript\nfunction listener(event) {\n  event.target.textContent = `${event.type} at ${event.pageX}, ${event.pageY}`\n}\n\ninteract(target)\n  .on('dragstart', listener)\n  .on('dragmove dragend', listener)\n  .on(['resizemove', 'resizeend'], listener)\n  .on({\n    gesturestart: listener,\n    gestureend: listener,\n  })\n\ninteract(target).draggable({\n  onstart: listener,\n  onmove: listener,\n  onend: listener,\n})\n\ninteract(target).resizable({\n  listeners: [\n    {\n      start: function (event) {\n        console.log(event.type, event.pageX, event.pageY)\n      },\n    },\n  ],\n})\n```\n\n`InteractEvent`s are fired for different actions. The event types include:\n\n- Draggable: `dragstart`, `dragmove`, `draginertiastart`, `dragend`\n- Resizable: `resizestart`, `resizemove`, `resizeinertiastart`, `resizeend`\n- Gesturable: `gesturestart`, `gesturemove`, `gestureend`\n\nTo respond to `InteractEvent`s, you must add listeners for the event types on an\ninteractable that's configured for that action. The event object that was\ncreated is passed to these functions as the first and only parameter.\n\n`InteractEvent` properties include the usual properties of mouse/touch events\nsuch as `pageX/Y`, `clientX/Y`, modifier keys etc. but also some properties\nproviding information about the change in coordinates and event specific data.\nThe table below displays all of these events.\n\n### Common\n\n| Property                 | Description                                      |\n| ------------------------ | ------------------------------------------------ |\n| `target`                 | The element that is being interacted with        |\n| `interactable`           | The Interactable that is being interacted with   |\n| `interaction`            | The Interaction that the event belongs to        |\n| `x0`, `y0`               | Page x and y coordinates of the starting event   |\n| `clientX0`, `clientY0`   | Client x and y coordinates of the starting event |\n| `dx`, `dy`               | Change in coordinates of the mouse/touch         |\n| `velocityX`, `velocityY` | The Velocity of the pointer                      |\n| `speed`                  | The speed of the pointer                         |\n| `timeStamp`              | The time of creation of the event object         |\n\n### Drag\n\n| Property     | Description                                       |\n| ------------ | ------------------------------------------------- |\n| **dragmove** |                                                   |\n| `dragEnter`  | The dropzone this Interactable was dragged over   |\n| `dragLeave`  | The dropzone this Interactable was dragged out of |\n\n### Resize\n\n| Property    | Description                                       |\n| ----------- | ------------------------------------------------- |\n| `edges`     | The edges of the element that are being changed   |\n| `rect`      | An object with the new dimensions of the target   |\n| `deltaRect` | The change in dimensions since the previous event |\n\n### Gesture\n\n| Property   | Description                                                                       |\n| ---------- | --------------------------------------------------------------------------------- |\n| `distance` | The distance between the event's first two touches                                |\n| `angle`    | The angle of the line made by the two touches                                     |\n| `da`       | The change in angle since previous event                                          |\n| `scale`    | The ratio of the distance of the start event to the distance of the current event |\n| `ds`       | The change in scale since the previous event                                      |\n| `box`      | A box enclosing all touch points                                                  |\n\nIn gesture events, page and client coordinates are the averages of touch\ncoordinates and velocity is calculated from these averages.\n\n## Drop Events\n\n```javascript\ninteract(dropTarget)\n  .dropzone({\n    ondrop: function (event) {\n      alert(event.relatedTarget.id + ' was dropped into ' + event.target.id)\n    },\n  })\n  .on('dropactivate', function (event) {\n    event.target.classList.add('drop-activated')\n  })\n```\n\nDropzones can receive the following events: `dropactivate`, `dropdeactivate`,\n`dragenter`, `dragleave`, `dropmove`, `drop`.\n\nThe dropzone events are plain objects with the following properties:\n\n| Property        | Description                                     |\n| --------------- | ----------------------------------------------- |\n| `target`        | The dropzone element                            |\n| `dropzone`      | The dropzone Interactable                       |\n| `relatedTarget` | The element that's being dragged                |\n| `draggable`     | The Interactable that's being dragged           |\n| `dragEvent`     | The related drag event – `drag{start,move,end}` |\n| `timeStamp`     | Time of the event                               |\n| `type`          | The event type                                  |\n\n## Pointer Events\n\n```javascript\ninteract(target).on('hold', function (event) {\n  console.log(event.type, event.target)\n})\n```\n\n- `down`\n- `move`\n- `up`\n- `cancel`\n- `tap`\n- `doubletap`\n- `hold`\n\nI call these `pointerEvents` (with a lower case \"p\") because they present the\nevents roughly as the real `PointerEvent` interface does, specifically:\n\n- `event.pointerId` provides the `TouchEvent#identifier` or\n  `PointerEvent#pointerId` or `undefined` for MouseEvents\n- `event.pointerType` provides the pointer type\n- There are no simulated mouse events after touch events\n\nThe properties of the events may vary across browsers and devices depending on\nwhich event interfaces are supported. For Example, a `down` event from a\n`touchstart` will not provide tilt or pressure as specified in the\n`PointerEvent` interface. {.notice .info}\n\n### Configuring pointer events\n\n```javascript\ninteract(target).pointerEvents({\n  holdDuration: 1000,\n  ignoreFrom: '[no-pointer]',\n  allowFrom: '.handle',\n  origin: 'self',\n})\n```\n\n`pointerEvent`s are not snapped or restricted, but can be modified with the\norigin modifications. `tap` events have a `dt` property which is the time\nbetween the related `down` and `up` events. For `doubletap` `dt` is the time\nbetween the two previous taps. `dt` for `hold` events is the length of time\nthat the pointer has been held down for (around 600ms).\n\n### Fast click\n\n```javascript\n// fast click\ninteract('a[href]').on('tap', function (event) {\n  window.location.href = event.currentTarget.href\n  event.preventDefault()\n})\n```\n\n`tap` and `doubletap` don't have the delay that `click` events have on mobile\ndevices so it works great for fast buttons and anchor links. Also, unlike\nregular click events, a tap isn’t fired if the pointer is moved before being\nreleased.\n"
  },
  {
    "path": "docs/faq.md",
    "content": "---\ntitle: FAQ\n---\n\nThis page contains questions and issues that are frequently raised on [Gitter\nchat][gitter] and [Github issues][gh-issues].\n\n## Start action after hold\n\nUse the `hold` option which takes the number of milliseconds that the pointer\nmust be held down for.\n\n```javascript\ninteract(target)\n  .draggable({\n    // start dragging after the pointer is held down for 1 second\n    hold: 1000\n  })\n```\n\nIf you are having problems with default browser behaviour like scrolling,\ncontext menus, etc. have a look at the\n[`Interactable#preventDefault`][prevent-default] method and this [thread on\nGithub](https://github.com/taye/interact.js/issues/138).\n\n## Clone target draggable\n\n```html\n<div class=\"item\"></div>\n```\n\n```javascript\ninteract('.item')\n  .draggable({ manualStart: true })\n  .on('move', function (event) {\n    var interaction = event.interaction\n\n    // if the pointer was moved while being held down\n    // and an interaction hasn't started yet\n    if (interaction.pointerIsDown && !interaction.interacting()) {\n      var original = event.currentTarget,\n        // create a clone of the currentTarget element\n        clone = event.currentTarget.cloneNode(true)\n\n      // insert the clone to the page\n      // TODO: position the clone appropriately\n      document.body.appendChild(clone)\n\n      // start a drag interaction targeting the clone\n      interaction.start({ name: 'drag' }, event.interactable, clone)\n    }\n  })\n```\n\nThere's no direct API to drag a clone of the target element. However, you can\nuse [`Interaction#start`][interaction-start] to change the target of an\ninteraction to any element that you create.\n\n## Remove / destroy / release\n\n```javascript\ninteract(target).draggable(true).resizable(true)\n\ninteract.isSet(target) // true\n\ninteract(target).unset()\n\ninteract.isSet(target) // false\ninteract(target).draggable() // false\ninteract(target).resizable() // false\n```\n\nTo remove an Interactable, use `interact(target).unset()`. That should remove\nall event listeners and make interact.js forget completely about the target.\n\n## Changing dropzones while dragging\n\n```javascript\ninteract.dynamicDrop(true)\n```\n\nIf you're adding or removing dropzone elements or changing their dimensions\nwhile dragging, you may need to change the [`dynamicDrop`][dynamic-drop] setting\nto true so that the dropzones rects are recalculated after every `dragmove`.\n\n## Drag handle\n\n```html\n<div class=\"item\">\n  A draggable item\n  <div class=\"handle\">Handle</div>\n</div>\n```\n\n```javascript\ninteract('.item').draggable({\n  allowFrom: '.handle',\n})\n```\n\nTo make an element be the handle of a parent draggable, use the allowFrom\nsetting option to allow an action to start only if the element matches a\ncertain CSS selector or is a specific element.\n\n## Prevent actions on child\n\n```html\n<div class=\"resizable\">\n  A resizable item\n  <textarea></textarea>\n</div>\n```\n\n```javascript\ninteract('.item')\n  .draggable({\n    // don't drag from textarea elments\n    ignoreFrom: 'textarea',\n  });\n```\n\nUse the `ignoreFrom` option to prevent actions from starting if the pointer\nwent down on an element matching the given selector or HTMLElement.\n\n## Revert / restore / undo drag position\n\nThere's no direct API to revert a dragged element to it's position before the\ndrag. To do this, you must store the position at `dragstart` and change the\nelement's style so that it returns to the start position on `dragend`. You can\nuse CSS transitions to animate change in position.\n\n## Dragging scrolls instead\n\n```css\n.draggable, .resizable, .gesturable {\n  -ms-touch-action: none;\n  touch-action: none;\n  user-select: none;\n}\n```\n\nTo allow touch interactions without scrolling or zooming, use the [`touch-action` CSS\nproperty][touch-action].\n\n## Dragging between iFrames\n\nThere is [limited support][iframe-pr] for using interact.js across iFrames. There are\ncurrently browser inconsistencies and other issues which have yet to be\naddressed.\n\n[gitter]: https://gitter.im/taye/interact.js\n[gh-issues]: https://github.com/taye/interact.js/issues\n[manual-start]: /docs#manualstart\n[interaction-start]: /api/Interaction.html#start\n[prevent-default]: /api/Interactable.html#preventDefault\n[dynamic-drop]: /api/module-interact.html#.dynamicDrop\n[touch-action]: https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action\n[iframe-pr]: https://github.com/taye/interact.js/pull/98\n"
  },
  {
    "path": "docs/gesturable.md",
    "content": "---\ntitle: Gesturable\n---\n\n```html\n<div id=\"rotate-area\">\n  <div id=\"angle-info\">0&deg;</div>\n  <svg id=\"arrow\" viewbox=\"0 0 100 100\">\n    <polygon points=\"50,0 75,25 62.5,25 62.5,100 37.5,100 37.5,25 25,25\" fill=\"#29e\"></polygon>\n  </svg>\n</div>\n```\n\n```css\n.draggable {\n  touch-action: none;\n  user-select: none;\n}\n```\n\n```js\nvar angle = 0\n\ninteract('#rotate-area').gesturable({\n  onmove: function (event) {\n    var arrow = document.getElementById('arrow')\n\n    angle += event.da\n\n    arrow.style.webkitTransform =\n    arrow.style.transform =\n      'rotate(' + angle + 'deg)'\n\n    document.getElementById('angle-info').textContent =\n      angle.toFixed(2) + '\\u00b0'\n  },\n})\n```\n\nGesture events are triggered when two pointers go down and are moved. In\ngesture events, page and client coordinates are the averages of touch\ncoordinates and velocity is calculated from these averages. The events also have\nthe following properties:\n\n| Gesture Event property | Description                                                                       |\n| ---------------------- | --------------------------------------------------------------------------------- |\n| `distance`             | The distance between the event's first two touches                                |\n| `angle`                | The angle of the line made by the two touches                                     |\n| `da`                   | The change in angle since previous event                                          |\n| `scale`                | The ratio of the distance of the start event to the distance of the current event |\n| `ds`                   | The change in scale since the previous event                                      |\n| `box`                  | A box enclosing all touch points                                                  |\n\nRemember to use CSS `touch-action: none` to prevent the browser from panning\nwhen the user drags with a touch pointer, and `user-select: none` to disable\ntext selection. {.notice .info}\n"
  },
  {
    "path": "docs/inertia.md",
    "content": "---\ntitle: Inertia\n---\n\n```javascript\ninteract(target)\n  .draggable({\n    inertia: true\n  })\n  .resizable({\n    inertia: {\n      resistance: 30,\n      minSpeed: 200,\n      endSpeed: 100\n    }\n  })\n```\n\nInertia allows drag and resize actions to continue after the user releases the\npointer at a fast enough speed. The required launch speed, end speed and\nresistance can optionally be configured with the settings below.\n\nIf an action ends without inertia but is snapped or restricted with the\n`endOnly` option, then the the coordinates are interpolated from the end coords\nto the snapped/restricted coords.\n\n## Options\n\n- **`resistance`** is a number greater than zero which sets the rate at which\n  the action slows down. Higher values slow it down more quickly.\n\n- **`endSpeed`** is the speed (pixels per second) at which the action is\n  considered to have stopped.\n\n- **`allowResume`** is a `boolean` value which indicates whether the user\n  should be allowed to resume an action while it is in the inertia phase.\n\n- **`smoothEndDuration`** is the duration (milliseconds) of the interpolated\n  movement from the actual end coords to the modified coords with `endOnly`.\n  Set the value to `0` to disable end transitions with `endOnly` snap/restrict.\n\nWhen inertia is resumed, the difference between the start and resume coordinates\nrelative to the target's top left corner, isn't reflected in the next\n`{action}move` events. Instead, an `{action}resume` event is fired when the\npointer goes back down during inertia before regular \"{action}move\" events are\nfired again. If you need the difference in coords, you should listen to this\nevent and respond to it as you would to an `{action}move` event.\n"
  },
  {
    "path": "docs/installation.md",
    "content": "---\ntitle: Installation\n---\n\ninteract.js offers two sets of free packages that you can add to your project:\n\n1.  To get started quickly, you can use the package named `interactjs` on npm.\n    This package contains all the features of the library as an _ES5 bundled_.\n2.  If you'd like to keep your JS payload small, there are npm packages under\n    the `@interactjs/` scope which let you choose which features to include.\n    These packages are distributed as _ES6 modules_ and may need to be\n    transpiled for older browsers.\n\n### npm pre-bundled\n\n```sh\n# install pre-bundled package with all features\n$ npm install --save interactjs\n```\n\n```js\n// es6 import\nimport interact from 'interactjs'\n```\n\n```js\n// or if using commonjs or AMD\nconst interact = require('interactjs')\n```\n\nTo use the pre-bundled package with [npm](https://docs.npmjs.com/about-npm/),\ninstall the package as a dependency with `npm install interactjs` then import or\nrequire the package in your JavaScript files.\n\n### CDN pre-bundled\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js\"></script>\n<!-- or -->\n<script src=\"https://unpkg.com/interactjs/dist/interact.min.js\"></script>\n```\n\nYou can also use the [jsDelivr](https://www.jsdelivr.com/package/npm/interactjs)\nor [unpkg](https://unpkg.com/interactjs) CDNs by adding a `<script>` tag\npointing to their servers.\n\n`interact` is exposed as a CommonJS module, an AMD module, or a global variable\ndepending on what the environment supports.\n\n```sh\n# install just the type definitions\n$ npm install --save-dev @interactjs/types\n```\n\nIf you're using the library only through a CDN and want the TypeScript type\ndefinitions for development, you can install the `@interactjs/types` package as\na dev dependency.\n\n### npm streamlined\n\n```sh\n# install only the features you need\n$ npm install --save @interactjs/interact \\\n  @interactjs/auto-start \\\n  @interactjs/actions \\\n  @interactjs/modifiers \\\n  @interactjs/dev-tools\n```\n\n```js\nimport '@interactjs/auto-start'\nimport '@interactjs/actions/drag'\nimport '@interactjs/actions/resize'\nimport '@interactjs/modifiers'\nimport '@interactjs/dev-tools'\nimport interact from '@interactjs/interact'\n\ninteract('.item').draggable({\n  listeners: {\n    move (event) {\n      console.log(event.pageX, event.pageY)\n    },\n  },\n})\n```\n\nFor a more streamlined JS payload, you can install and import the package for\neach feature you need:\n\n| Package name                                           | Description                                                                                                                              |\n| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |\n| `@interactjs/interact`                                 | **(required)** provides the `interact()` method                                                                                          |\n| [`@interactjs/actions`](action-options)                | Drag, resize, gesture actions                                                                                                            |\n| [`@interactjs/auto-start`](auto-start)                 | Start actions with pointer down, move sequence                                                                                           |\n| [`@interactjs/modifiers`](modifiers)                   | Snap, restrict, etc. modifiers                                                                                                           |\n| `@interactjs/snappers`                                 | Provides `interact.snappers.grid()` utility                                                                                              |\n| [`@interactjs/inertia`](inertia)                       | Drag and resize inertia-like throwing                                                                                                    |\n| [`@interactjs/reflow`](reflow)                         | `interactable.reflow(action)` method to trigger modifiers and event listeners                                                            |\n| [`@interactjs/dev-tools`](tooling#interactjsdev-tools) | Console warnings for common mistakes (optimized out when `NODE_ENV === 'production'`) and a babel plugin for optimized production builds |\n\n### CDN streamlined\n\n```html\n<script type=\"module\">\n  import 'https://cdn.interactjs.io/v1.9.20/auto-start/index.js'\n  import 'https://cdn.interactjs.io/v1.9.20/actions/drag/index.js'\n  import 'https://cdn.interactjs.io/v1.9.20/actions/resize/index.js'\n  import 'https://cdn.interactjs.io/v1.9.20/modifiers/index.js'\n  import 'https://cdn.interactjs.io/v1.9.20/dev-tools/index.js'\n  import interact from 'https://cdn.interactjs.io/v1.9.20/interactjs/index.js'\n\n  interact('.item').draggable({\n    onmove(event) {\n      console.log(event.pageX, event.pageY)\n    },\n  })\n</script>\n```\n\nThe packages above are also available on\n`https://cdn.interactjs.io/v[VERSION]/[UNSCOPED_NAME]`. You can import them in\nmodern browser which support ES6 `import`s.\n\n### Ruby on Rails\n\n[Rails 5.1+](https://rubyonrails.org/) supports the [yarn](http://yarnpkg.com/)\npackage manager, so you can add interact.js to you app by running `yarn add interactjs`. Then require the library with:\n\n```rb\n//= require interactjs/interact\n```\n"
  },
  {
    "path": "docs/introduction.md",
    "content": "---\ntitle: Introduction\n---\n\n## What is interact.js?\n\ninteract.js is a JavaScript library for drag and drop, resizing and multi-touch\ngestures for modern browsers. Its free and open source version comes with\npowerful options like inertia and modifiers for snapping and restricting.\n\nThe library's aim is to **present pointer input data consistently** across\ndifferent browsers and devices and provide convenient ways to **pretend that the\nuser's pointer moved in a way that it wasn't really moved** (snapping, inertia,\netc.).\n\nNote that by default **interact.js doesn't move elements for you**. Styling an\nelement so that it moves while a drag happens has to be done from your own event\nlisteners. This way, you’re in control of everything that happens.\n\n<div class=\"notice\"> 🌟 If you prefer to have feedback out-of-the-box, have\na look at <a href=\"/pro\">interact.js Pro</a>. It comes with built-in hardware\naccelerated feedback, list reordering, spring physics, Vue & React components\nand more.\n\n<div class=\"has-text-centered notice-cta\">\n  <a href=\"/pro\" class=\"button is-medium is-info has-text-white\">Get Pro</a>\n</div>\n</div>\n\n## Getting Started\n\nAfter [installing the library](/docs/installation), the basic steps to setting\nup your targets and interactions are:\n\n1.  Create an `Interactable` target.\n2.  Configure it to enable actions and add [modifiers](/docs/modifiers),\n    [inertia](/docs/inertia), etc.\n3.  Add event listeners to provide visual feedback and update your app's state.\n\nFor example, here's some code for [a very simple slider\ninput](https://codepen.io/taye/pen/GgpxNq):\n\n<LiveDemo :demoHtml=\"import('@/demos/slider.html?raw')\" :removeNext=\"1\"/>\n\n```js\n// Step 1\nconst slider = interact('.slider')    // target elements with the \"slider\" class\n\nslider\n  // Step 2\n  .draggable({                        // make the element fire drag events\n    origin: 'self',                   // (0, 0) will be the element's top-left\n    inertia: true,                    // start inertial movement if thrown\n    modifiers: [\n      interact.modifiers.restrict({\n        restriction: 'self',           // keep the drag coords within the element\n      }),\n    ],\n  })\n  // Step 3\n  .on('dragmove', function (event) {  // call this listener on every dragmove\n    const sliderWidth = interact.getElementRect(event.target.parentNode).width\n    const value = event.pageX / sliderWidth\n\n    event.target.style.paddingLeft = (value * 100) + '%'\n    event.target.setAttribute('data-value', value.toFixed(2))\n  })\n```\n\nThe `interact` function takes an element or a CSS selector string and returns an\n`Interactable` object which has various methods to configure actions and event\nlisteners. Pointer interactions of down → move → up sequences begin drag,\nresize, or gesture actions. By adding event listener functions for these action,\nyou can respond to `InteractEvent`s which provide pointer coordinates, speed,\nelement size, etc.\n\n## Actions\n\ninteract.js supports 3 basic action types which are triggered by pointer down →\nmove → up sequences:\n\n- [Draggable](/docs/draggable) for moving elements or drawing on a canvas.\n  This can be combined with [dropzones](/docs/dropzone) to implement drag and\n  drop applications.\n- [Resizable](/docs/resizable) for watching the size and position of an\n  element while the pointer is used to move one or two of the element's edges.\n- [Gesturable](/docs/gesturable) for 2-finger gestures with angle, scale, etc.\n  data.\n\nPro builds on the draggable action to provide [Sortable and\nSwappable](/docs/sortable) feature for drag and drop rearranging of lists of\nelements.\n"
  },
  {
    "path": "docs/migrating.md",
    "content": "---\ntitle: Migrating from v1.2\n---\n\nThe latest versions fix several bugs, allows setting more options on a\nper-action basis, add configuration options to `pointerEvents` and add several\nnew methods and options. The [changelog][changelog] lists all the major changes.\n\n### Per-action modifiers array\n\nModifiers are now created with `interact.modifiers[modifierName](options)`\nmethods. The return values returned by these methods go into the\n`actionOptions.modifiers` array. The lets you more easily reuse modifier\nconfigurations and specify their execution order.\n\n```js\n// create a restrict modifier to prevent dragging an element out of its parent\nconst restrictToParent = interact.modifiers.restrict({\n  restriction: 'parent',\n  elementRect: { left: 0, right: 0, top: 1, bottom: 1 },\n})\n\n// create a snap modifier which changes the event coordinates to the closest\n// corner of a grid\nconst snap100x100 = interact.modifiers.snap({\n  targets: [interact.snappers.grid({ x: 100, y: 100 })],\n  relativePoints: [{ x: 0.5, y: 0.5 }],\n})\n\ninteract(target)\n  .draggable({\n    // apply the restrict and then the snap modifiers to drag events\n    modifiers: [restrictToParent, snap100x100],\n  })\n  .on('dragmove', event => console.log(event.pageX, event.pageY))\n```\n\n### Improved resize snap and restrict\n\nThere are a few new snap and restrict modifiers for resize actions:\n\n[Restrictions](/docs/restriction):\n\n- pointer coordinate-based `restrict`\n- element rect-based restriction `restrictRect`\n- element size-based `restrictSize` (resize only)\n- and element edge-based `restrictEdges` (resize only)\n\n[Snapping](/docs/snapping):\n\n- pointer coordinate-based `snap` which is best suited to drag actions,\n- `snapSize` which works only on resize actions and let's you set targets for\n  the size of the target element,\n- and `snapEdges` which is similar to `snapSize`, but let's you set the target\n  positions of the edges of the target element.\n\n```js\ninteract(target).resize({\n  edges: { bottom: true, right: true },\n\n  // sizes at fixed grid points\n  snapSize: {\n    targets: [\n      interact.snappers.grid({ x: 25, y: 25, range: Infinity }),\n    ],\n  },\n\n  // minimum size\n  restrictSize: {\n    min: { width: 100, height: 50 },\n  },\n\n  // keep the edges inside the parent\n  restrictEdges: {\n    outer: 'parent',\n    endOnly: true,\n  },\n})\n```\n\n### Resize `aspectRatio` modifier\n\nThe resize `preserveAspectRatio` and `square` options have been replaced by an\n`aspectRatio` modifier which can cooperate with other modifiers.\n\n```js\ninteract(target).resizable({\n  edges: { left: true, bottom: true },\n  modifiers: [\n    interact.modifiers.aspectRatio({\n      // ratio may be the string 'preserve' to maintain the starting aspect ratio,\n      // or any number to force a width/height ratio\n      ratio: 'preserve',\n      // To add other modifiers that respect the aspect ratio,\n      // put them in the aspectRatio.modifiers array\n      modifiers: [interact.modifiers.restrictSize({ max: 'parent' })],\n    }),\n  ],\n})\n```\n\n```js\ninteract(target).resizable({\n  modifiers: [\n    interact.modifiers.aspectRatio({\n      // The equalDelta option replaces the old resize.square option\n      equalDelta: true,\n    }),\n  ],\n})\n```\n\n### Removed Methods\n\nThe methods in the table below were removed and replaced with action method\noptions and modifier methods for the new modifiers array API:\n\n| Method                                                     | Replaced with                                          |\n| ---------------------------------------------------------- | ------------------------------------------------------ |\n| `interactable.squareResize(bool)`                          | `interact.modifiers.aspectRatio({ equalDelta: true })` |\n| `interactable.snap({ actions: ['drag'], ...snapOptions })` | `interact.modifiers.snap(snapOptions)`                 |\n| `interactable.restrict(restrictOptions)`                   | `interact.modifiers.restrict(restrictOptions)`         |\n| `interactable.inertia(true)`                               | `interactable.draggable({ inertia: true })`            |\n| `interactable.accept('.can-be-dropped')`                   | `interactable.dropzone({ accept: '.can-be-dropped' })` |\n| `interact.margin(50)`                                      | `interactable.resizable({ margin: 50 })`               |\n\n### Action end event dx/dy\n\nThe `dx` and `dy` fields on `dragend`, `resizeend` and `gestureend` events were\nformally the difference between the start and end coordinates. Now they are\nalways `0` (the difference between the end and the last move event). Use\n`event.X0` and `event.Y0` (or `event.clientX0` and `event.clientY0`) to get the\nstarting coordinates and subtract them from the end event coordinates.\n\n```js\ninteract(target).draggable({\n  onend: function (event) {\n    console.log(event.pageX - event.X0, event.pageY - event.Y0)\n  },\n})\n```\n\n### Drop events\n\n`dragend` events are now fired _before_ `drop` events. Use\n`dragendEvent.relatedTarget` to get the dropzone element if there will be a drop\nevent.\n\n### Mouse buttons\n\nBy default, only the left mouse button can start actions. The `mouseButtons`\naction option can be used to change this.\n\n[changelog]: https://github.com/taye/interact.js/blob/master/CHANGELOG.md\n"
  },
  {
    "path": "docs/modifiers.md",
    "content": "---\ntitle: Modifiers\n---\n\n```js\n// create a restrict modifier to prevent dragging an element out of its parent\nconst restrictToParent = interact.modifiers.restrict({\n  restriction: 'parent',\n  elementRect: { left: 0, right: 0, top: 1, bottom: 1 },\n})\n\n// create a snap modifier which changes the event coordinates to the closest\n// corner of a grid\nconst snap100x100 = interact.modifiers.snap({\n  targets: [interact.snappers.grid({ x: 100, y: 100 })],\n  relativePoints: [{ x: 0.5, y: 0.5 }],\n})\n\ninteract(target)\n  .draggable({\n    // apply the restrict and then the snap modifiers to drag events\n    modifiers: [restrictToParent, snap100x100],\n  })\n  .on('dragmove', event => console.log(event.pageX, event.pageY))\n```\n\n`interact`'s `modifiers` let you change the coordinates of action events. The\noptions object passed to action methods can have a `modifiers` array which will\nbe applied to events of that action type. **Modifiers in the array are applied\nsequentially** and their order may affect the final result.\n\n```js\nconst snapAtEnd = interact.modifiers.snap({\n  endOnly: true,\n  targets: [/* ... */],\n})\n```\n\nModifiers can be set to apply only to the last move event in an interaction by\nsetting their `endOnly` option to `true`. When an `endOnly` modifier is used\nwith an action that has `inertia` enabled, the event coordinates will be\nsmoothly moved from the up coords to the modified coords.\n\ninteract.js comes with a vew different types of modifiers for\n[snapping](/docs/snapping) and [restricting](/docs/restriction) elements.\n"
  },
  {
    "path": "docs/reflow.md",
    "content": "---\ntitle: Reflow\n---\n\nThe reflow method lets you trigger an action start -> move -> end sequence which\nruns modifiers and does drop calculations, etc. If your interactable target is a\nCSS selector, an interaction will be run for each matching element.\n\n<LiveDemo :demoHtml=\"import('@/demos/reflow.html?raw')\"/>\n\nIf the elements have inertia, `endOnly` modifiers and `smoothEndDuration`, then\nthe interactions may not end immediately. The reflow method returns a `Promise`\nwhich is resolved when all interactions are complete. So you can `await` or\n`.then()` multiple reflows\n\n```js\nconst interactable = interact(target).draggable({}).resizable({})\n\nasync function onWindowResize () {\n  // start a resize action and wait for inertia to finish\n  await interactable.reflow({ name: drag, axis: 'x' })\n\n  // start a drag action\n  await interactable.reflow({\n    name: 'resize',\n    edges: { left: true, bottom: true },\n  })\n}\n\nwindow.addEventListener(onWindowResize, 'resize')\n```\n"
  },
  {
    "path": "docs/resizable.md",
    "content": "---\ntitle: Resizable\n---\n\n```javascript\ninteract(target)\n  .resizable({\n    edges: {\n      top   : true,       // Use pointer coords to check for resize.\n      left  : false,      // Disable resizing from left edge.\n      bottom: '.resize-s',// Resize if pointer target matches selector\n      right : handleEl    // Resize if pointer target is the given Element\n    }\n  })\n```\n\nResize events have `rect` and `deltaRect` properties. `rect` is updated on each\n`resizemove` event and the values in `deltaRect` reflect the changes. In\n`resizestart`, `rect` will be identical to the rect returned by\n`interactable.getRect(element)` and `deltaRect` will have all-zero properties.\n\n| Resize Event property | Description                                       |\n| --------------------- | ------------------------------------------------- |\n| `edges`               | The edges of the element that are being changed   |\n| `rect`                | An object with the new dimensions of the target   |\n| `deltaRect`           | The change in dimensions since the previous event |\n\nResizable options have an `edges` property which specifies the edges of the\nelement which can be resized from (top, left, bottom or right).\n\n<LiveDemo :demoHtml=\"import('@/demos/resizable/basic.html?raw')\" :removeNext=\"2\" />\n\n```html\n<div data-x=\"0\" data-y=\"0\" class=\"resizable\">\n  <!-- top-left resize handle -->\n  <div class=\"resize-top resize-left\"></div>\n\n  <!-- bottom-right resize handle -->\n  <div class=\"resize-bottom resize-right\"></div>\n</div>\n```\n\n```js\ninteract('.resizable').resizable({\n  edges: { top: true, left: true, bottom: true, right: true },\n  listeners: {\n    move (event) {\n      let { x, y } = event.target.dataset\n\n      x = (parseFloat(x) || 0) + event.deltaRect.left\n      y = (parseFloat(y) || 0) + event.deltaRect.top\n\n      Object.assign(event.target.style, {\n        width: `${event.rect.width}px`,\n        height: `${event.rect.height}px`,\n        transform: `translate(${x}px, ${y}px)`,\n      })\n\n      Object.assign(event.target.dataset, { x, y })\n    },\n  },\n})\n```\n\nRemember to use CSS `touch-action: none` to prevent the browser from panning\nwhen the user drags with a touch pointer, `user-select: none` to disable\ntext selection, and `box-sizing: border-box` if your elements have padding and\nborders which affect their width. {.notice .info}\n\nIf you'd like an element to behave as a resize corner, let it match the\nselectors of two adjacent edges.\n\nResize handle elements must be children of the resizable element. If you need\nthe handles to be outside the target element, then you will need to use\n[`Interaction#start`](interaction-start).\n\n### `invert`\n\n```javascript\ninteract(target).resizable({\n  edges: { bottom: true, right: true },\n  invert: 'reposition'\n})\n```\n\nBy default, resize actions can't make the `event.rect` smaller than `0x0`. Use\nthe `invert` option to specify what should happen if the target would be resized\nto dimensions less than `0x0`. The possible values are:\n\n- `'none'` (default) will limit the resize rect to a minimum of `0x0`\n- `'negate'` will allow the rect to have negative width/height\n- `'reposition'` will keep the width/height positive by swapping the top and\n  bottom edges and/or swapping the left and right edges\n\n<LiveDemo :demoHtml=\"import('@/demos/resizable/invert.html?raw')\" />\n\n### Aspect ratio\n\n```js\ninteract(target).resizable({\n  modifiers: [\n    interact.modifiers.aspectRatio({\n      // make sure the width is always double the height\n      ratio: 2,\n      // also restrict the size by nesting another modifier\n      modifiers: [\n        interact.modifiers.restrictSize({ max: 'parent' }),\n      ],\n    }),\n  ],\n})\n```\n\ninteract.js comes with an `aspectRatio` modifier which can be used to force the\nresized rect to maintain a certain aspect ratio. The modifier has 3 options:\n\n| Prop         | Type                 | Description                                                                             |\n| ------------ | -------------------- | --------------------------------------------------------------------------------------- |\n| `ratio`      | number or 'preserve' | The aspect ratio to maintain or the value 'preserve' to maintain the starting ratio     |\n| `equalDelta` | boolean              | Increase edges by the same amount instead of maintaining the same ratio                 |\n| `modifiers`  | array of modifiers   | Modifiers to apply to the resize which will be made to respect the aspect ratio options |\n\nTo guarantee that the aspect ratio options are respected by other modifiers,\nthose modifiers must be in the `aspectRatio.modifiers` array option, **not** in the\nsame `resize.modifiers` array as the `aspectRatio` one.\n\n[interaction-start]: http://interactjs.io/api/#Interaction.start\n"
  },
  {
    "path": "docs/restriction.md",
    "content": "---\ntitle: Restrict\n---\n\ninteract.js has 3 restriction modifiers available through the\n`interact.modifiers` object:\n\n- pointer coordinate-based `restrict`\n- element rect-based restriction `restrictRect`\n- element size-based `restrictSize` (resize only)\n- and element edge-based `restrictEdges` (resize only)\n\n## `restrict()`\n\n```javascript\ninteract(target).draggable({\n  modifiers: [\n    interact.modifiers.restrict({\n      restriction: 'parent',\n      endOnly: true\n    })\n  ]\n})\n```\n\nThe `restriction` value specifies the area that the action will be confined to.\nThe value can be:\n\n- a rect object with `top`, `left`, `bottom` and `right` or `x`, `y`,\n  `width` and `height`,\n- an element whose dimensions will be used as the restriction area,\n- a function which takes `(x, y, element)` and returns a rect or an element\n- one of these strings:\n- `'self'` – restrict to the target element's rect\n- `'parent'` – restrict to the rect of the element's parentNode or\n- a CSS selector string – if one of the parents of the target element matches\n  this selector, it's rect will be used as the restriction area.\n\n### `restrictRect()`\n\nWith the `restrict` variant, restricting is by default relative to the pointer\ncoordinates so that the action coordinates, not the element's dimensions, will\nbe kept within the restriction area. You can use the `restrictRect` variant so\nthat the element's edges are considered while dragging.\n\n```javascript\ninteract(target).draggable({\n  modifiers: [\n    interact.modifiers.restrictRect({\n      restriction: 'parent'\n    })\n  ]\n})\n```\n\nIf the target element is larger than the restriction, then the element will be\nallowed to move around the restriction.\n\n### `elementRect`\n\n`restrictRect` is identical to `restrict`, but the `elementRect` option is set\nto a helpful default of `{ left: 0, right: 0, top: 1, bottom: 1 }`. The\n`elementRect` option specifies the area of the element to consider as its edges\nas scalar values from the top left edges to the bottom right.\n\nFor the `left` and `right` properties, `0` means the left edge of the element\nand `1` means the right edge. For `top` and `bottom`, `0 means` the top edge of\nthe element and 1 means the bottom.\n\n`{ top: 0.25, left: 0.25, bottom: 0.75, right: 0.75 }` would result in a quarter\nof the element being allowed to hang over the restriction edges.\n\n## `restrictSize()`\n\n```javascript\ninteract(target).resizable({\n  modifiers: [\n    interact.modifiers.restrictSize({\n      min: { width: 100, height: 100 },\n      max: { width: 500, height: 500 }\n    })\n  ]\n})\n```\n\n`restrictSize` lets you specify the minimum and maximum dimensions that the\ntarget element must have when resizing.\n\n## `restrictEdges()`\n\n```javascript\ninteract(target).resizable({\n  modifiers: [\n    interact.modifiers.restrictEdges({\n      inner: {\n        left: 100,  // the left edge must be <= 100\n        right: 200  // the right edge must be >= 200\n      }\n      outer: {\n        left: 0,    // the left edge must be >= 0\n        right: 300  // the right edge must be <= 300\n      }\n    })\n  ]\n})\n```\n\n`restrictEdges` lets you specify `inner` and `outer` dimensions that the target\nelement must have when resizing. You can think of `inner` as setting the minimum\nsize of the element and `outer` as the maximum size.\n"
  },
  {
    "path": "docs/snapping.md",
    "content": "---\ntitle: Snapping\n---\n\ninteract.js has 3 snap modifiers available through the `interact.modifiers`\nobject:\n\n- pointer coordinate-based `snap` which is best suited to drag actions,\n- `snapSize` which works only on resize actions and let's you set targets for\n  the size of the target element,\n- and `snapEdges` which is similar to `snapSize`, but let's you set the target\n  positions of the edges of the target element.\n\nWhen creating snap modifiers the options have an array of `targets`. The action\nevents will be snapped to the closest target of this array which is within\nrange.\n\n## `snap()`\n\nThe `snap` modifier changes the pointer coordinates to specified targets when\nthey are within range.\n\n```js\nconst mySnap = interact.modifiers.snap({\n  targets: [\n    { x: 200, y: 200 },\n    { x: 250, y: 350 },\n  ],\n})\n```\n\nUsing the `snap` modifier while dragging, The coordinates of the pointer that\nthe drag event listeners receive will be modified to meet the coordinates of the\nsnap targets. This option may also be used with resizable targets, but may not\nyield intuitive results.\n\n`snap` targets have `x` and `y` number props and an optional `range` number\nproperty.\n\n### `relativePoints`\n\n```javascript\ninteract(element).draggable({\n  modifiers: [\n    interact.modifiers.snap({\n      targets: [ { x: 300, y: 300 } ],\n      relativePoints: [\n        { x: 0  , y: 0   },   // snap relative to the element's top-left,\n        { x: 0.5, y: 0.5 },   // to the center\n        { x: 1  , y: 1   }    // and to the bottom-right\n      ]\n    })\n  ]\n})\n```\n\nIf you want to specify for `snap` (not `snapSize` or `snapEdges`) the points on\nthe element which snapping should be relative to, then use an array of\n`relativePoints`. Each item in the array should be an object with `x` and `y`\nproperties which are scalars specifying the position on the element to which\nsnapping should be relative. If no `relativePoints` array is specified or the\narray is empty then snapping is relative to the pointer coordinates (default).\n\nThere are effectively `targets.length * max( relativePoints.length, 1 )` snap\ntargets while snap calculations are done. Snap functions are called multiple\ntimes with the coordinates at each `relativePoint`.\n\n### `offset`\n\n```javascript\ninteract(element1).draggable({\n  modifiers: [\n    interact.modifiers.snap({\n      targets: [ { x: 300, y: 300 } ],\n      offset: { x: 20, y: 20 }\n    })\n  ]\n})\n\ninteract(element2).resizable({\n  modifiers: [\n    interact.modifiers.snap({\n      targets: [ { x: 300, y: 300 } ],\n      offset: 'startCoords'\n    })\n  ]\n})\n```\n\nThe `offset` option lets you shift the coordinates of the targets of a `snap`\nmodifier. The value may be:\n\n- an object with `x` and `y` properties,\n- `'startCoords'` which will then use the `pageX` and `pageY` at the start of\n  the action,\n- `'self'` which will use the target element's top-left coordinates,\n- or `'parent'` which will use the top-left coordinates of the target's parent\n  element\n\n## `snapSize()`\n\n```js\ninteract(target).resizable({\n  edges: { top: true, left: true },\n  modifiers: [\n    interact.modifiers.snapSize({\n      targets: [\n        { width: 100 },\n        interact.snappers.grid({ width: 100, height: 100 }),\n      ],\n    }),\n  ],\n})\n```\n\nThe `snapSize` modifier snaps the _dimensions_ of targets when resizing. A\n`snapSize` target is an object with `x` and `y` number props _or_ `width` and\n`height` number props as well as an optional `range`. Its targets have `x` and\n`y` number props _or_ `width` and `height` number props as well as an optional\n`range`.\n\n## `snapEdges()`\n\n```js\ninteract(target).resizable({\n  edges: { top: true, left: true },\n  modifiers: [\n    interact.modifiers.snapEdges({\n      targets: [\n        interact.snappers.grid({ top: 100, left: 100 }),\n      ],\n    }),\n  ],\n})\n```\n\nThe `snapEdges` modifier snaps the _edges_ of targets when resizing. Its targets\nhave either `x` and `y` number props to snap the left/right and top/bottom edges\nrespectively, `top`, `left`, `width` and `height` number props to snap each edge\nand an optional `range`.\n\n### `targets` option\n\nThe coordinates of action events are compared to the targets of the provided snap\nmodifiers. If multiple targets are within range, the closest target is used.\n\n```js\ninteract.modifiers.snap({\n  targets: [\n    function (\n      // the x and y page coordinates,\n      x,\n      y,\n      // the current interaction\n      interaction,\n      // the offset information with relativePoint if set\n      { x: offsetX, y: offsetY, relativePoint, index: relativePointIndex },\n      // the index of this function in the options.targets array\n      index,\n    ) {\n      return {\n        x: x,\n        y: 75 + 50 * Math.sin(x * 0.04),\n        range: 40,\n      }\n    },\n  ],\n})\n```\n\nYou can use functions in the `targets` array. If a snap target is a function,\nthen it is called and given the `x` and `y` coordinates of the event as the\nfirst two parameters and the interaction as the third parameter. The return\nvalue of the function is used as a target.\n\nIf a target omits an axis or edge prop, then the corresponding axis will not be\nchanged. For example, if a target is defined as `{ y: 100, range Infinity }`\nthen the snapped movement will be horizontal at `(100, pointerEventPageX)`.\n\n### Snap grids\n\n```javascript\nvar gridTarget = interact.snappers.grid({\n  // can be a pair of x and y, left and top,\n  // right and bottom, or width, and height\n  x: 50,\n  y: 50,\n\n  // optional\n  range: 10,\n\n  // optional\n  offset: { x: 5, y: 10 },\n\n  // optional\n  limits: {\n    top: 0,\n    left: 0,\n    bottom: 500,\n    height: 500\n  }\n})\n\ninteract(element).draggable({\n  modifiers: [\n    interact.modifiers.snap({ targets: [gridTarget] })\n  ]\n})\n```\n\nYou can use the `interact.snappers.grid()` method to create a target that snaps\nto a grid. The method takes an object describing a grid and returns a function\nthat snaps to the corners of that grid.\n\nThe properties of the grid are:\n\n- `x`, `y`: the spacing between the horizontal and vertical grid lines.\n- `range` (optional): the distance from the grid corners within which the\n  pointer coords will be snapped.\n- `offset` (optional): an object with `x` and `y` props to offset the grid\n  lines\n- `limits` (optional): an object with `top`, `left`, `bottom` and `right` props\n  to set the bounds of the grid\n\n### `range`\n\n```javascript\ninteract(element).draggable({\n  modifiers: [\n    interact.modifiers.snap({\n      targets: [\n        { x: 20, y: 450, range: 50 }\n        { x: 10, y: 0 /* use default range below */ }\n      ],\n      range: 300 // for targets that don't specify a range\n    })\n  ]\n})\n```\n\nA range can be specified in the snap modifier options and each target may\noptionally have its own range. The `range` of a snap target is the distance the\npointer must be from the target's coordinates for a snap to be possible.\n\ni.e. `inRange = distance <= range`.\n\n### Event snap info\n\n```js\ninteract(target).draggable({\n  modifiers: [\n    interact.modifiers.snap({ targets: [(x, y) => ({ x: x + 20 })] }),\n  ],\n  listeners: {\n    move (event) {\n      console.log(event.modifiers[0].target.source)\n    },\n  },\n})\n```\n\n`InteractEvent.modifiers` will be an array with info on the modifiers that have\nbeen set for the action. Snap modifiers provide an object with the closest\ntarget with the calculated offset.\n\n| Prop        | Type                      | Description                                                                   |\n| ----------- | ------------------------- | ----------------------------------------------------------------------------- |\n| `x` and `y` | number                    | The coords that were snapped to with origin, offset and relativePoint applied |\n| `source`    | target object or function | The target object or function in the targets array option                     |\n| `index`     | number                    | The index of the source in the targets array                                  |\n| `range`     | number                    | The range of the target                                                       |\n| `offset`    | object                    | The offset applied to the source                                              |\n"
  },
  {
    "path": "docs/tooling.md",
    "content": "---\ntitle: Tooling & Optimization\n---\n\n## Feature selection\n\n```sh\n# install only the features you need\n$ npm install --save @interactjs/interact \\\n  @interactjs/auto-start \\\n  @interactjs/actions \\\n  @interactjs/modifiers \\\n  @interactjs/dev-tools\n```\n\n```js\nimport '@interactjs/auto-start'\nimport '@interactjs/actions/drag'\nimport '@interactjs/actions/resize'\nimport '@interactjs/modifiers'\nimport '@interactjs/dev-tools'\nimport interact from '@interactjs/interact'\n\ninteract('.item').draggable({\n  listeners: {\n    move (event) {\n      console.log(event.pageX, event.pageY)\n    },\n  },\n})\n```\n\nAdding the unscoped `interactjs` npm package to your project is the easiest way\nto get started with the library as it includes all features already pre-bundled\nand compiled to ES5 syntax. However, this might result in a lot of unused\nfeatures increasing the size of your JS payload.\n\nFor a more streamlined build, you can add import the packages for each feature\nyou need. See the [npm streamlined installation\ndocs](/docs/installation#npm-streamlined) for more details including a list of\navailable packages.\n\n## `@interactjs/dev-tools`\n\nThe `@interactjs/dev-tools` package provides hints that can help you avoid\ncommon issues (eg. missing event handlers and useful CSS styles) while\ndeveloping your application. Although these hints can be helpful, it's best to\navoid including them in your production deployment. There are some ways to do\nthis below.\n\n## Optimizing for production\n\n### Babel plugin\n\n```json\n// babel config\n{\n  \"env\": {\n    \"production\": {\n      \"plugins\": [\n        \"@interactjs/dev-tools/babel-plugin-prod\",\n      ]\n    }\n  }\n}\n```\n\n```js\n// source file\nimport '@interactjs/actions/drag'\nimport interact from '@interactjs/interact'\n```\n\n```js\n// result\nimport '@interactjs/actions/drag/index.prod'\nimport interact from '@interactjs/interact/index.prod'\n```\n\nIf you use babel in your deployment workflow, you can simply add\n`@interactjs/dev-tools/babel-plugin-prod` to the plugins section of your\nproduction babel config and all `@interactjs/**` imports will be changed to the\noptimized, production versions with development hints optimized out.\n\n### Without build tools\n\n```js\nimport '@interactjs/actions/drag/index.prod'\nimport interact from '@interactjs/interact/index.prod'\n```\n\nIf you're not using babel, then you'll need to change your imports to include\nthe `.prod` extension. For index files of directories you'll need to add the\nfilename (eg. `@interactjs/actions -> @interactjs/actions/index.prod`).\n"
  },
  {
    "path": "esnext.rollup.config.cjs",
    "content": "/* eslint-disable import/no-extraneous-dependencies */\nconst { resolve, basename, dirname, relative, extname } = require('path')\n\nconst { transformAsync } = require('@babel/core')\nconst babel = require('@rollup/plugin-babel')\nconst commonjs = require('@rollup/plugin-commonjs')\nconst nodeResolve = require('@rollup/plugin-node-resolve')\nconst replace = require('@rollup/plugin-replace')\nconst terser = require('@rollup/plugin-terser')\nconst { glob } = require('glob')\nconst { defineConfig } = require('rollup')\n\nconst headers = require('./scripts/headers')\nconst {\n  getPackages,\n  sourcesIgnoreGlobs,\n  extendBabelOptions,\n  getEsnextBabelOptions,\n  getModuleDirectories,\n  isPro,\n} = require('./scripts/utils')\n\nconst BUNDLED_DEPS = ['rebound']\nconst INPUT_EXTENSIONS = ['.ts', '.tsx', '.vue']\nconst moduleDirectory = getModuleDirectories()\n\nmodule.exports = defineConfig(async () => {\n  const packageDirs = (await getPackages()).map((dir) => resolve(__dirname, dir))\n  return (\n    await Promise.all(\n      packageDirs.map(async (packageDir) => {\n        const packageName = `${basename(dirname(packageDir))}/${basename(packageDir)}`\n\n        const external = (id_, importer) => {\n          const id = id_.startsWith('.') ? resolve(dirname(importer), id_) : id_\n\n          // not external if it's a dependency that's intented to be bundled\n          if (BUNDLED_DEPS.some((dep) => id === dep || id.includes(`/node_modules/${dep}/`))) return false\n\n          // not external if the id is in the current package dir\n          if (\n            [packageName, packageDir].some(\n              (prefix) =>\n                id.startsWith(prefix) && (id.length === prefix.length || id.charAt(prefix.length) === '/'),\n            )\n          )\n            return false\n\n          return true\n        }\n\n        const entryFiles = await glob('**/*.{ts,tsx}', {\n          cwd: packageDir,\n          ignore: sourcesIgnoreGlobs,\n          strict: false,\n          nodir: true,\n          absolute: true,\n        })\n        const input = Object.fromEntries(\n          entryFiles.map((file) => [\n            relative(packageDir, file.slice(0, file.length - extname(file).length)),\n            file,\n          ]),\n        )\n\n        return [\n          // dev unminified\n          { env: { NODE_ENV: 'development' }, ext: '.js', minify: isPro },\n          // prod minified\n          { env: { NODE_ENV: 'production' }, ext: '.prod.js', minify: true },\n        ].map(({ env, ext, minify }) =>\n          defineConfig({\n            external,\n            input,\n            plugins: [\n              commonjs({ include: '**/node_modules/{rebound,symbol-tree}/**' }),\n              nodeResolve({\n                modulePaths: moduleDirectory,\n                extensions: INPUT_EXTENSIONS,\n              }),\n              babel(\n                extendBabelOptions(\n                  {\n                    babelrc: false,\n                    configFile: false,\n                    babelHelpers: 'bundled',\n                    skipPreflightCheck: true,\n                    extensions: INPUT_EXTENSIONS,\n                    plugins: [\n                      [\n                        require.resolve('@babel/plugin-transform-runtime'),\n                        { helpers: false, regenerator: false },\n                      ],\n                    ],\n                  },\n                  getEsnextBabelOptions(),\n                ),\n              ),\n              replace({\n                preventAssignment: true,\n                values: Object.entries({\n                  npm_package_version: process.env.npm_package_version,\n                  IJS_BUNDLE: '',\n                  ...env,\n                }).reduce((acc, [key, value]) => {\n                  acc[`process.env.${key}`] = JSON.stringify(value)\n                  return acc\n                }, {}),\n              }),\n            ],\n            context: 'window',\n            moduleContext: 'window',\n            preserveEntrySignatures: 'strict',\n            output: [\n              {\n                dir: packageDir,\n                entryFileNames: `[name]${ext}`,\n                format: 'es',\n                banner: minify ? headers?.min : headers?.raw,\n                inlineDynamicImports: false,\n                sourcemap: true,\n                plugins: [\n                  {\n                    name: '@interactjs/_dev:output-transforms',\n                    async renderChunk(code, chunk, outputOptions) {\n                      return await transformAsync(code, {\n                        babelrc: false,\n                        configFile: false,\n                        inputSourceMap: chunk.map,\n                        filename: `${packageDir}/${chunk.fileName}`,\n                        plugins: [\n                          [\n                            require.resolve('./scripts/babel/relative-imports'),\n                            { extension: ext, moduleDirectory },\n                          ],\n                          [require.resolve('@babel/plugin-transform-class-properties'), { loose: true }],\n                        ],\n                      })\n                    },\n                  },\n                  minify &&\n                    terser({\n                      module: false,\n                      mangle: true,\n                      compress: {\n                        ecma: '2019',\n                        unsafe: true,\n                        unsafe_Function: true,\n                        unsafe_arrows: false,\n                        unsafe_methods: true,\n                      },\n                      format: {\n                        preamble: headers?.min,\n                      },\n                    }),\n                ],\n              },\n            ],\n          }),\n        )\n      }),\n    )\n  ).flat()\n})\n"
  },
  {
    "path": "examples/.eslintignore",
    "content": "js\n"
  },
  {
    "path": "examples/.eslintrc.cjs",
    "content": "module.exports = {\n  extends: '../.eslintrc.cjs',\n  globals: { interact: false, _: false, $: false },\n  rules: { 'no-console': 'off', 'import/no-unresolved': 'off', 'import/no-extraneous-dependencies': 'off' },\n}\n"
  },
  {
    "path": "examples/dropzones/index.css",
    "content": "body { font-family: Helvetica, Arial, sans-serif; }\n\n.dropzone-wrapper {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    right: 0;\n}\n\n.dropzone {\n    overflow: hidden;\n    margin: .5em;\n    padding: 1em;\n    color: #666;\n    text-align: center;\n    background: #ccc;\n    line-height: 4em;\n    border: 4px dashed transparent;\n    transition: background .15s linear, border-color .15s linear;\n}\n\n.dropzone.-drop-possible { border-color: #666; }\n\n.dropzone.-drop-over {\n    background: #666;\n    color: #fff;\n}\n\n.draggable {\n    position: relative;\n    z-index: 10;\n    width: 200px;\n    margin: .25em;\n    padding: 1em 2em;\n    background-color: #29e;\n    color: #fff;\n    text-align: center;\n\n    -ms-touch-action: none;\n        touch-action: none;\n}\n\n.draggable.-drop-possible { background-color: #42bd41; }\n"
  },
  {
    "path": "examples/dropzones/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>Highlight dropzones with interact.js</title>\n    <script type=\"module\" src=\"./index.js\"></script>\n    <link rel=\"stylesheet\" href=\"./index.css\">\n</head>\n<body>\n\n<div id=\"drag1\" class=\"draggable js-drag\">Drag me…</div>\n<div id=\"drag2\" class=\"draggable js-drag\">Drag me…</div>\n<div id=\"drag3\" class=\"draggable js-drag\">Drag me…</div>\n<div id=\"drag4\" class=\"draggable js-drag\">Drag me…</div>\n\n<div class=\"dropzone-wrapper\">\n    <div id=\"drop1\" class=\"dropzone js-drop\">Dropzone</div>\n    <div id=\"drop2\" class=\"dropzone js-drop\">Dropzone</div>\n    <div id=\"drop3\" class=\"dropzone js-drop\">Dropzone</div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "examples/dropzones/index.js",
    "content": "/* eslint-disable import/no-absolute-path */\nimport interact from '@interactjs/interactjs'\n\nlet transformProp\nconst dragPositions = [1, 2, 3, 4].reduce((acc, n) => {\n  acc[`drag${n}`] = { x: 0, y: 0 }\n  return acc\n}, {})\n\ninteract.maxInteractions(Infinity)\n\n// setup draggable elements.\ninteract('.js-drag').draggable({\n  listeners: {\n    start(event) {\n      const position = dragPositions[event.target.id]\n      position.x = parseInt(event.target.getAttribute('data-x'), 10) || 0\n      position.y = parseInt(event.target.getAttribute('data-y'), 10) || 0\n    },\n    move(event) {\n      const position = dragPositions[event.target.id]\n      position.x += event.dx\n      position.y += event.dy\n\n      if (transformProp) {\n        event.target.style[transformProp] = 'translate(' + position.x + 'px, ' + position.y + 'px)'\n      } else {\n        event.target.style.left = position.x + 'px'\n        event.target.style.top = position.y + 'px'\n      }\n    },\n    end(event) {\n      const position = dragPositions[event.target.id]\n      event.target.setAttribute('data-x', position.x)\n      event.target.setAttribute('data-y', position.y)\n    },\n  },\n})\n\n// setup drop areas.\n// dropzone #1 accepts draggable #1\nsetupDropzone('#drop1', '#drag1')\n// dropzone #2 accepts draggable #1 and #2\nsetupDropzone('#drop2', '#drag1, #drag2')\n// every dropzone accepts draggable #3\nsetupDropzone('.js-drop', '#drag3')\n\n/**\n * Setup a given element as a dropzone.\n *\n * @param {HTMLElement|String} target\n * @param {String} accept\n */\nfunction setupDropzone(target, accept) {\n  interact(target)\n    .dropzone({\n      accept,\n      ondropactivate: function (event) {\n        addClass(event.relatedTarget, '-drop-possible')\n      },\n      ondropdeactivate: function (event) {\n        removeClass(event.relatedTarget, '-drop-possible')\n      },\n    })\n    .on('dropactivate', (event) => {\n      const active = event.target.getAttribute('active') | 0\n\n      // change style if it was previously not active\n      if (active === 0) {\n        addClass(event.target, '-drop-possible')\n        event.target.textContent = 'Drop me here!'\n      }\n\n      event.target.setAttribute('active', active + 1)\n    })\n    .on('dropdeactivate', (event) => {\n      const active = event.target.getAttribute('active') | 0\n\n      // change style if it was previously active\n      // but will no longer be active\n      if (active === 1) {\n        removeClass(event.target, '-drop-possible')\n        event.target.textContent = 'Dropzone'\n      }\n\n      event.target.setAttribute('active', active - 1)\n    })\n    .on('dragenter', (event) => {\n      addClass(event.target, '-drop-over')\n      event.relatedTarget.textContent = \"I'm in\"\n    })\n    .on('dragleave', (event) => {\n      removeClass(event.target, '-drop-over')\n      event.relatedTarget.textContent = 'Drag me…'\n    })\n    .on('drop', (event) => {\n      removeClass(event.target, '-drop-over')\n      event.relatedTarget.textContent = 'Dropped'\n    })\n}\n\nfunction addClass(element, className) {\n  if (element.classList) {\n    return element.classList.add(className)\n  } else {\n    element.className += ' ' + className\n  }\n}\n\nfunction removeClass(element, className) {\n  if (element.classList) {\n    return element.classList.remove(className)\n  } else {\n    element.className = element.className.replace(new RegExp(className + ' *', 'g'), '')\n  }\n}\n\n/* eslint-disable multiline-ternary */\ninteract(document).on('ready', () => {\n  transformProp =\n    'transform' in document.body.style\n      ? 'transform'\n      : 'webkitTransform' in document.body.style\n        ? 'webkitTransform'\n        : 'mozTransform' in document.body.style\n          ? 'mozTransform'\n          : 'oTransform' in document.body.style\n            ? 'oTransform'\n            : 'msTransform' in document.body.style\n              ? 'msTransform'\n              : null\n})\n/* eslint-enable multiline-ternary */\n"
  },
  {
    "path": "examples/events/index.css",
    "content": "#swipe {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n\n    margin: 0;\n    padding: 10%;\n\n    background-color: #29e;\n    color: #fff;\n\n    font-size: 8em;\n    font-size: 10vmin;\n    font-family: sans-serif;\n\n    cursor: default;\n\n    -webkit-user-select: none;\n       -moz-user-select: none;\n        -ms-user-select: none;\n         -o-user-select: none;\n            user-select: none;\n\n    -webkit-touch-action: none;\n       -moz-touch-action: none;\n        -ms-touch-action: none;\n            touch-action: none;\n}\n\n.tolerance-slider {\n    position: absolute;\n    left: 0;\n    bottom: 0;\n    width: 80%;\n    height: 5%;\n    margin: 5% 10%;\n}\n\n#tolerance-display {\n    position: absolute;\n    left: 0;\n    bottom: 0;\n    width: 100%;\n    margin: 2% 0%;\n\n    font-size: 2em;\n    font-size: 4vmin;\n    text-align: center;\n\n    color: #fff;\n}\n\n#tolerance-display::before {\n    content: \"interact.pointerMoveTolerance( \";\n}\n#tolerance-display::after {\n    content: \" )\";\n}\n"
  },
  {
    "path": "examples/events/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\" />\n        <title>interact.js events demo</title>\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n        <meta name=\"description\" content=\"Display events with interact.js\"/>\n        <meta name=\"author\" content=\"Taye Adeyemi\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n        <link rel=\"stylesheet\" href=\"./index.css\">\n        <script type=\"module\" src=\"./index.js\"></script>\n    </head>\n    <body>\n\n        <div id=\"swipe\">Tap, drag and swipe accros the screen</div>\n\n        <input class=\"tolerance-slider\" type=\"range\" value=\"1\" step=\"1\" min=\"1\" max=\"100\">\n        <pre id=\"tolerance-display\">1</pre>\n\n    </body>\n</html>\n\n"
  },
  {
    "path": "examples/events/index.js",
    "content": "/* eslint-disable import/no-absolute-path */\nimport interact from '@interactjs/interactjs'\n\nconst dirs = ['up', 'down', 'left', 'right']\n\ninteract('#swipe')\n  .draggable(true)\n  .on('dragend', (event) => {\n    if (!event.swipe) {\n      return\n    }\n\n    let str = 'swipe'\n\n    for (const dir of dirs) {\n      if (event.swipe[dir]) {\n        str += ' ' + dir\n      }\n    }\n\n    str += '<br>' + event.swipe.angle.toFixed(2) + '°' + '<br>' + event.swipe.speed.toFixed(2) + 'px/sec'\n\n    event.target.innerHTML = str\n    window.console.log(str.replace(/<br>/g, ' '))\n  })\n\nconst pointerEvents = ['tap', 'doubletap', 'hold', 'down', 'move', 'up']\n\nfunction logEvent(event) {\n  event.currentTarget.innerHTML = event.pointerType\n\n  if (/tap|up|click|down/.test(event.type) && event.interaction.prevTap) {\n    window.console.log(\n      event.type + ' -- ' + event.dt + ', ' + (new Date().getTime() - event.interaction.prevTap.timeStamp),\n    )\n  }\n\n  if (interact.supportsTouch() || interact.supportsPointerEvent()) {\n    event.target.innerHTML += ' #' + event.pointerId\n  }\n\n  const interactionIndex = interact.debug().interactions.list.indexOf(event.interaction)\n\n  event.currentTarget.innerHTML +=\n    ' ' +\n    event.type +\n    '<br>(' +\n    event.pageX +\n    ', ' +\n    event.pageY +\n    ')<br>' +\n    'interaction #' +\n    interactionIndex\n\n  // window.console.log(event.pointerType, event.pointerId, event.type, event.pageX, event.pageY, interactionIndex);\n\n  event.preventDefault()\n}\n\nfor (let i = 0; i < pointerEvents.length; i++) {\n  const eventType = pointerEvents[i]\n\n  interact('#swipe').on(eventType, logEvent)\n}\n\nfunction changeTolerance(event) {\n  const value = event.target.value | 0\n\n  interact.pointerMoveTolerance(value)\n\n  document.getElementById('tolerance-display').textContent = value\n}\n\ninteract('.tolerance-slider').on('input', changeTolerance)\ninteract('.tolerance-slider').on('change', changeTolerance)\n"
  },
  {
    "path": "examples/iframes/bottom.html",
    "content": "<meta charset=\"utf-8\">\n<link href=\"./index.css\" rel=\"stylesheet\" type=\"text/css\"/>\n\n<script type=\"module\">\nimport setInteractables from './index.js'\nwindow.interact = window.parent.interact;\n\nsetInteractables();\n</script>\n\n<div id=\"drag-me\" class=\"draggable\">\n    <p>An element in the BOTTOM frame</p>\n</div>\n"
  },
  {
    "path": "examples/iframes/index.css",
    "content": "body {\n    margin: 0;\n    padding: 5% 10%;\n    font-family: sans-serif;\n}\n\n#drag-me {\n    width: 25%;\n\n    background-color: #29e;\n    color: white;\n\n    border: solid 0.4em #666;\n    border-radius: 0.75em;\n    padding: 3%;\n    touch-action: none;\n\n    position: absolute;\n\n    top: 0;\n    left: 0;\n}\n\niframe {\n    width: 100%;\n    height: 75vh;\n}\n\n"
  },
  {
    "path": "examples/iframes/index.html",
    "content": "<meta charset=\"utf-8\">\n<link href=\"./index.css\" rel=\"stylesheet\" type=\"text/css\"/>\n\n<iframe src=\"middle.html\" style=\"border: solid 2px black\"></iframe>\n\n<script type=\"module\">\nimport setInteractables from './index.js'\n\ndocument.querySelector('iframe').onload = function (event) {\n  window.interact = frames[0].interact;\n\n  setInteractables();\n};\n</script>\n\n\n<div id=\"drag-me\" class=\"draggable\">\n    <p>An element in the TOP frame</p>\n</div>\n\n"
  },
  {
    "path": "examples/iframes/index.js",
    "content": "export default function setInteractables() {\n  interact('.draggable', { context: document }).draggable({\n    onmove: onMove,\n    inertia: { enabled: true },\n    restrict: {\n      drag: 'parent',\n      endOnly: true,\n      elementRect: { top: 0, left: 0, bottom: 1, right: 1 },\n    },\n    autoScroll: true,\n  })\n\n  function onMove(event) {\n    const target = event.target\n    const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx\n    const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy\n\n    if ('webkitTransform' in target.style || 'transform' in target.style) {\n      target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'\n    } else {\n      target.style.left = x + 'px'\n      target.style.top = y + 'px'\n    }\n\n    target.setAttribute('data-x', x)\n    target.setAttribute('data-y', y)\n  }\n}\n"
  },
  {
    "path": "examples/iframes/middle.html",
    "content": "<meta charset=\"utf-8\">\n<link href=\"index.css\" rel=\"stylesheet\" type=\"text/css\"/>\n\n<script type=\"module\">\nimport interact from '@interactjs/interactjs'\nimport setInteractables from './index.js'\n\nwindow.interact = interact\nsetInteractables();\n\ndocument.getElementById('iframe').src = 'bottom.html'\n</script>\n\n<iframe id=\"iframe\" style=\"border: solid 2px black\"></iframe>\n\n<div id=\"drag-me\" class=\"draggable\">\n    <p>An element in the MIDDLE frame</p>\n</div>\n"
  },
  {
    "path": "examples/snap/index.css",
    "content": "body {\n  margin: 0;\n  padding: 0;\n  border: 0;\n  font-family: \"Arial\", sans-serif;\n}\n\ncanvas {\n  position: absolute;\n  top: 0;\n  left: 0;\n\n  margin: 20px;\n  padding: 0;\n\n  touch-action: none;\n}\n\n#status {\n  width: 20%;\n  height: 100%;\n  position: fixed;\n  right: 0;\n  top: 0;\n\n  padding: 5px 5px;\n  border: none;\n  border-left: solid 8px #3a6bff;\n\n  background-color: rgba(0, 143, 179, 0.298);\n  text-align: center;\n  font-size: 1.4em;\n}\n\n#status h3 {\n  font-size: 1.1em;\n  margin: 3px 0px 0px 0px;\n  padding: 0;\n  line-height: 22px;\n  text-transform: capitalize;\n  font-weight: normal\n}\n\n#status input[type=radio], #status input[type=checkbox] {\n  float: right;\n}\n\n#status [type=range] {\n  margin: auto;\n  width: 90%;\n}\n\n#status [disabled] {\n  cursor: default;\n}\n\n#status label {\n  float: left;\n  cursor: pointer;\n  width: 95%;\n  text-align: left;\n}\n\n#modes,#sliders {\n  overflow: hidden;\n  width: 100%;\n  margin: auto;\n}\n\n#modes.disabled label.snap-mode {\n  cursor: default;\n  color: gray;\n}\n"
  },
  {
    "path": "examples/snap/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<title>interact.js drag snapping</title>\n<meta name=\"description\" content=\"A demonstration of interact.js drag snapping\" />\n<meta name=\"author\" content=\"Taye Adeyemi\" />\n<script type=\"module\" src=\"./index.js\"></script>\n<link rel=\"stylesheet\" href=\"./index.css\" type=\"text/css\"/>\n</head>\n<body>\n<canvas id=\"grid\"> Your browser does not support the HTML5 canvas</canvas>\n<canvas id=\"drag\"> </canvas>\n\n<div id=\"status\">\n    <div id=\"controls\">\n    <section id=\"sliders\">\n        <h3> grid spacing </h3>\n        <input id=\"grid-x\" type=\"range\" value=\"300\" min=\"20\" max=\"500\" title=\"x-axis\">\n        <input id=\"grid-y\" type=\"range\" value=\"300\" min=\"20\" max=\"500\" title=\"x-axis\">\n        <br>\n        <h3> grid offset </h3>\n        <input id=\"offset-x\" type=\"range\" value=\"100\" min=\"0\" max=\"500\" title=\"x-axis\">\n        <input id=\"offset-y\" type=\"range\" value=\"100\" min=\"0\" max=\"500\" title=\"x-axis\">\n        <br>\n        <h3> snap range </h3>\n        <input id=\"snap-range\" type=\"range\" min=\"-1\" value=\"100\" max=\"150\" title=\"snap range\">\n    </section>\n        <br>\n        <section id=\"modes\">\n        <h3> snap mode </h3>\n            <label for=\"off-mode\" class=\"snap-mode\">\n                Off\n                <input id=\"off-mode\" type=\"radio\" name=\"snap-mode\">\n            </label> <br>\n            <label for=\"grid-mode\" class=\"snap-mode\">\n                Grid Mode\n                <input id=\"grid-mode\" type=\"radio\" name=\"snap-mode\" checked=\"true\">\n            </label> <br>\n            <label for=\"anchor-mode\" class=\"snap-mode\">\n                Anchor Mode\n                <input id=\"anchor-mode\" type=\"radio\" name=\"snap-mode\">\n            </label>\n            <br>\n            <br>\n\n            <label for=\"end-only\">\n                Snap at end only\n                <input id=\"end-only\" type=\"checkbox\">\n            </label>\n\n            <label for=\"inertia\">\n                Inertia\n                <input id=\"inertia\" type=\"checkbox\">\n            </label>\n\n            <label for=\"relative\">\n                Relative to \"startCoords\"\n                <input id=\"relative\" type=\"checkbox\">\n            </label>\n            <br>\n            <br>\n\n            <label for=\"drag-anchors\" style=\"display: none\">\n                Anchor drag mode\n                <input id=\"drag-anchors\" type=\"checkbox\" >\n            </label>\n        </section>\n    </div>\n</div>\n</body>\n</html>\n\n"
  },
  {
    "path": "examples/snap/index.js",
    "content": "/* eslint-disable import/no-absolute-path */\nimport interact from '@interactjs/interactjs'\n\nwindow.interact = interact\n\nlet canvas\nlet context\nlet guidesCanvas\nlet guidesContext\nconst width = 800\nconst height = 800\nlet status\nconst blue = '#2299ee'\nconst lightBlue = '#88ccff'\nconst tango = '#ff4400'\nlet draggingAnchor = null\n\nconst snapOffset = { x: 0, y: 0 }\n\nconst snapGrid = {\n  x: 10,\n  y: 10,\n  range: 10,\n  offset: { x: 0, y: 0 },\n}\nconst gridFunc = interact.snappers.grid(snapGrid)\nconst anchors = [\n  { x: 100, y: 100, range: 200 },\n  { x: 600, y: 400, range: Infinity },\n  { x: 500, y: 150, range: Infinity },\n  { x: 250, y: 250, range: Infinity },\n]\n\nconst prevCoords = { x: 0, y: 0 }\nlet prevClosest = { target: { x: 0, y: 0 }, range: 0 }\nconst cursorRadius = 10\n\nfunction drawGrid(grid, gridOffset, range) {\n  if (!grid.x || !grid.y) return\n\n  const barLength = 16\n  const offset = {\n    x: gridOffset.x + snapOffset.x,\n    y: gridOffset.y + snapOffset.y,\n  }\n\n  guidesContext.clearRect(0, 0, width, height)\n\n  guidesContext.fillStyle = lightBlue\n\n  if (range < 0 || range === Infinity) {\n    guidesContext.fillRect(0, 0, width, height)\n  }\n\n  for (let i = -((1 + offset.x / grid.x) | 0), lenX = width / grid.x + 1; i < lenX; i++) {\n    for (let j = -((1 + offset.y / grid.y) | 0), lenY = height / grid.y + 1; j < lenY; j++) {\n      if (range > 0 && range !== Infinity) {\n        guidesContext.circle(i * grid.x + offset.x, j * grid.y + offset.y, range, blue).fill()\n      }\n\n      guidesContext.beginPath()\n      guidesContext.moveTo(i * grid.x + offset.x, j * grid.y + offset.y - barLength / 2)\n      guidesContext.lineTo(i * grid.x + offset.x, j * grid.y + offset.y + barLength / 2)\n      guidesContext.stroke()\n\n      guidesContext.beginPath()\n      guidesContext.moveTo(i * grid.x + offset.x - barLength / 2, j * grid.y + offset.y)\n      guidesContext.lineTo(i * grid.x + offset.x + barLength / 2, j * grid.y + offset.y)\n      guidesContext.stroke()\n    }\n  }\n}\n\nfunction drawAnchors(defaultRange) {\n  const barLength = 16\n\n  guidesContext.clearRect(0, 0, width, height)\n\n  if (status.range.value < 0 && status.range.value !== Infinity) {\n    guidesContext.fillStyle = lightBlue\n    guidesContext.fillRect(0, 0, width, height)\n  }\n\n  for (let i = 0, len = anchors.length; i < len; i++) {\n    const anchor = {\n      x: anchors[i].x + snapOffset.x,\n      y: anchors[i].y + snapOffset.y,\n      range: anchors[i].range,\n    }\n    const range = typeof anchor.range === 'number' ? anchor.range : defaultRange\n\n    if (range > 0 && range !== Infinity) {\n      guidesContext.circle(anchor.x, anchor.y, range, blue).fill()\n    }\n\n    guidesContext.beginPath()\n    guidesContext.moveTo(anchor.x, anchor.y - barLength / 2)\n    guidesContext.lineTo(anchor.x, anchor.y + barLength / 2)\n    guidesContext.stroke()\n\n    guidesContext.beginPath()\n    guidesContext.moveTo(anchor.x - barLength / 2, anchor.y)\n    guidesContext.lineTo(anchor.x + barLength / 2, anchor.y)\n    guidesContext.stroke()\n  }\n}\n\nfunction drawSnap(snap) {\n  context.clearRect(0, 0, width, height)\n  guidesContext.clearRect(0, 0, width, height)\n\n  if (status.gridMode.checked) {\n    drawGrid(snapGrid, snapGrid.offset, snapGrid.range)\n  } else if (status.anchorMode.checked) {\n    drawAnchors(snap.range)\n  }\n}\n\nfunction circle(x, y, radius, color) {\n  this.fillStyle = color || this.fillStyle\n  this.beginPath()\n  this.arc(x, y, radius, 0, 2 * Math.PI)\n\n  return this\n}\nwindow.CanvasRenderingContext2D.prototype.circle = circle\n\nfunction dragMove(event) {\n  const snap = event._interaction.modification.states.find((m) => m.name === 'snap')\n  const closest = snap && snap.closest\n  const rect = interact.getElementRect(canvas)\n\n  context.clearRect(\n    prevCoords.x - cursorRadius - 2,\n    prevCoords.y - cursorRadius - 2,\n    cursorRadius * 2 + 4,\n    cursorRadius * 2 + 4,\n  )\n\n  context.clearRect(\n    prevClosest.target.x - prevClosest.range - rect.left - 2,\n    prevClosest.target.y - prevClosest.range - rect.top - 2,\n    prevClosest.range * 2 + 4 + rect.left,\n    prevClosest.range * 2 + 4 + rect.top,\n  )\n\n  if (closest && closest.range !== Infinity) {\n    const closestTarget = {\n      x: closest.target.x - rect.left,\n      y: closest.target.y - rect.top,\n    }\n\n    context.circle(closestTarget.x, closestTarget.y, closest.range + 1, 'rgba(102, 225, 117, 0.8)').fill()\n  }\n\n  context.circle(event.pageX, event.pageY, cursorRadius, tango).fill()\n\n  prevCoords.x = event.pageX\n  prevCoords.y = event.pageY\n  prevClosest = closest || prevClosest\n}\n\nfunction dragEnd(event) {\n  context.clearRect(0, 0, width, height)\n  context.circle(event.pageX, event.pageY, cursorRadius, tango).fill()\n\n  prevCoords.x = event.pageX\n  prevCoords.y = event.pageY\n}\n\nfunction anchorDragStart(event) {\n  if (event.snap.locked) {\n    interact(canvas).snap(false)\n    draggingAnchor = event.snap.anchors.closest\n  }\n}\n\nfunction anchorDragMove(event) {\n  if (draggingAnchor) {\n    const snap = interact(canvas).snap().drag\n\n    draggingAnchor.x += event.dx\n    draggingAnchor.y += event.dy\n\n    drawAnchors(snap.range)\n  }\n}\n\nfunction anchorDragEnd(event) {\n  interact(canvas).draggable(true)\n  draggingAnchor = null\n}\n\nfunction sliderChange() {\n  snapGrid.x = Number(status.gridX.value)\n  snapGrid.y = Number(status.gridY.value)\n  snapGrid.range = Number(status.range.value)\n\n  snapGrid.offset.x = Number(status.offsetX.value)\n  snapGrid.offset.y = Number(status.offsetY.value)\n\n  if (snapGrid.range < 0) {\n    snapGrid.range = Infinity\n  }\n\n  drawSnap(interact(canvas).draggable().snap)\n}\n\nfunction modeChange(event) {\n  if (status.anchorDrag.checked && !status.anchorMode.checked) {\n    status.anchorMode.checked = true\n  }\n\n  if (status.anchorDrag.checked) {\n    status.anchorMode.disabled = status.offMode.disabled = status.gridMode.disabled = true\n    status.modes.className += ' disabled'\n\n    interact(canvas)\n      .off('dragstart', dragMove)\n      .off('dragmove', dragMove)\n      .off('dragend', dragEnd)\n      .on('dragstart', anchorDragStart)\n      .on('dragmove', anchorDragMove)\n      .on('dragend', anchorDragEnd)\n  } else {\n    status.anchorMode.disabled = status.offMode.disabled = status.gridMode.disabled = false\n    status.modes.className = status.modes.className.replace(/ *\\bdisabled\\b/g, '')\n\n    interact(canvas)\n      .on('dragstart', dragMove)\n      .on('dragmove', dragMove)\n      .on('dragend', dragEnd)\n      .off('dragstart', anchorDragStart)\n      .off('dragmove', anchorDragMove)\n      .off('dragend', anchorDragEnd)\n  }\n\n  interact(canvas).draggable({\n    inertia: {\n      enabled: status.inertia.checked,\n    },\n    modifiers: [\n      interact.modifiers.restrict({ restriction: 'self' }),\n      interact.modifiers.snap({\n        targets: status.gridMode.checked ? [gridFunc] : status.anchorMode.checked ? anchors : null,\n        enabled: !status.offMode.checked,\n        endOnly: status.endOnly.checked,\n        offset: status.relative.checked ? 'startCoords' : null,\n      }),\n      interact.modifiers.spring(),\n    ],\n  })\n\n  if (!status.relative.checked) {\n    snapOffset.x = snapOffset.y = 0\n  }\n\n  drawSnap(interact(canvas).draggable().snap)\n}\n\nfunction sliderInput(event) {\n  // eslint-disable-next-line no-mixed-operators\n  if (\n    (event.target.type === 'range' &&\n      // eslint-disable-next-line no-mixed-operators\n      Number(event.target.value) > Number(event.target.max)) ||\n    Number(event.target.value) < Number(event.target.min)\n  ) {\n    return\n  }\n\n  sliderChange()\n}\n\ninteract(document).on('DOMContentLoaded', () => {\n  canvas = document.getElementById('drag')\n  canvas.width = width\n  canvas.height = height\n  context = canvas.getContext('2d')\n\n  interact(canvas)\n    .on('move down', (event) => {\n      if ((event.type === 'down' || !event.interaction.pointerIsDown) && status.relative.checked) {\n        const rect = interact.getElementRect(canvas)\n\n        snapOffset.x = event.pageX - rect.left\n        snapOffset.y = event.pageY - rect.top\n\n        drawSnap(interact(canvas).draggable().snap)\n      }\n    })\n    .draggable({ origin: 'self' })\n\n  guidesCanvas = document.getElementById('grid')\n  guidesCanvas.width = width\n  guidesCanvas.height = height\n  guidesContext = guidesCanvas.getContext('2d')\n\n  status = {\n    container: document.getElementById('status'),\n\n    sliders: document.getElementById('sliders'),\n    gridX: document.getElementById('grid-x'),\n    gridY: document.getElementById('grid-y'),\n    offsetX: document.getElementById('offset-x'),\n    offsetY: document.getElementById('offset-y'),\n    range: document.getElementById('snap-range'),\n\n    modes: document.getElementById('modes'),\n    offMode: document.getElementById('off-mode'),\n    gridMode: document.getElementById('grid-mode'),\n    anchorMode: document.getElementById('anchor-mode'),\n    anchorDrag: document.getElementById('drag-anchors'),\n    endOnly: document.getElementById('end-only'),\n    inertia: document.getElementById('inertia'),\n    relative: document.getElementById('relative'),\n  }\n\n  interact('#sliders').on('change', sliderInput).on('input', sliderInput)\n\n  interact('#modes').on('change', modeChange)\n\n  sliderChange()\n  modeChange()\n})\n\nwindow.grid = {\n  drawGrid,\n}\n"
  },
  {
    "path": "examples/sortable/index.html",
    "content": "<title>interact.js Sortable and Swappable demo</title>\n\n<link rel=\"stylesheet\" href=\"./style.css\">\n\n<body>\n\n  <div id=\"react-app\"></div>\n\n  <div id=\"vue-app\">\n    <div v-for=\"list of lists\" class=\"box\" :key=\"list.title\">\n      <h1>{{ list.title }}</h1>\n\n      <pre>{{ list.items }}</pre>\n\n      <i-sortable class=\"container\" :options=\"sortableOptions\" v-model=\"list.items\">\n        <div v-for=\"(item, index) of list.items\" :key=\"index\" disabled=\"!!(index % 2)\" :id=\"`item-${index}-${item}`\" class=\"item card\">\n          <div class=\"card-content\">{{ index }}. {{ item }}</div>\n        </div>\n      </i-sortable>\n    </div>\n\n    <pre>[ {{ tags.join(', ') }} ]</pre>\n\n    <i-swappable class=\"tags\" v-model=\"tags\" :options=\"swappableOptions\">\n      <div v-for=\"tag of tags\" :id=\"'tag-' + tag\" class=\"tag is-info is-large\" :key=\"tag\">{{ tag }}</div>\n    </i-swappable>\n\n  </div>\n\n  <div id=\"no-parent\"></div>\n\n</body>\n\n<script type=\"module\" src=\"./vue.js\"></script>\n<script type=\"module\" src=\"./react.js\"></script>\n"
  },
  {
    "path": "examples/sortable/react.js",
    "content": "import '@interactjs/react'\nimport { createElement as h, useState } from 'react'\nimport { createRoot } from 'react-dom/client'\n\nimport interact from '@interactjs/interactjs'\n\nimport { getData } from './shared.js'\n\n// eslint-disable-next-line no-undef\nconst data = getData()\n\nconst { Interactable, Sortable } = interact.react.components\nconst root = createRoot(document.getElementById('react-app'))\n\nroot.render(\n  h(() => {\n    return h(\n      'div',\n      {},\n      data.lists.map((list, index) => {\n        const [items, setItems] = useState(list.items)\n\n        return h('div', { key: list.title, className: 'box' }, [\n          list.title,\n          h('pre', {}, JSON.stringify(items, null, 2)),\n          h(\n            Sortable,\n            { className: 'container', key: `list-${list.title}`, items, onUpdate: setItems },\n            items.map((item) =>\n              h(\n                Interactable,\n                { key: item, onTap: (event) => console.log(event), className: 'item card' },\n                h('div', { className: 'card-content' }, item),\n              ),\n            ),\n          ),\n        ])\n      }),\n    )\n  }),\n)\n"
  },
  {
    "path": "examples/sortable/shared.js",
    "content": "import interact from '@interactjs/interactjs'\n\nfunction sortListener(event) {\n  console.log(event.type, event.position)\n}\n\nexport function getData() {\n  return {\n    lists: [\n      {\n        title: 'Animals',\n        items: ['elephant', 'turtle', 'frog'],\n      },\n      {\n        title: 'Numbers',\n        items: ['first', 'second', 'third'],\n      },\n    ],\n    tags: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n  }\n}\n\nexport const sortableOptions = {\n  draggable: {\n    // lockAxis: 'y',\n    inertia: true,\n    autoScroll: { container: '.container' },\n    listeners: [interact.feedback.pointers()],\n    modifiers: [\n      interact.modifiers.restrict({\n        restriction: 'html',\n        elementRect: { left: 0, top: 0, right: 1, bottom: 1 },\n      }),\n      interact.modifiers.transform(),\n      interact.modifiers.spring(),\n    ],\n  },\n  _spillTo: document.getElementById('no-parent'),\n  mirror: false,\n  listeners: [\n    {\n      start: sortListener,\n      change: sortListener,\n      end: sortListener,\n    },\n  ],\n}\n\nexport const swappableOptions = {\n  draggable: {\n    // lockAxis: 'y',\n    inertia: true,\n    modifiers: [interact.modifiers.spring()],\n    listeners: interact.feedback.pointers(),\n  },\n}\n"
  },
  {
    "path": "examples/sortable/style.css",
    "content": "@import \"bulma/css/bulma.css\";\n\nbody {\n  margin: 1em;\n  _font-size: 2em;\n}\n.container {\n  max-width: 500px;\n}\n\n.item.i-sorting {\n  z-index: 1;\n}\n\n*, *::before, *::after {\n  box-sizing: border-box;\n}\n\nbody {\n  _margin: 0;\n}\n\n.box {\n  display: inline-flex;\n  flex-direction: column;\n  margin: 1em;\n}\n\n.container {\n  margin: 0;\n  transform-origin: 0 0;\n  _transform: rotate(0deg) scale(2);\n  _transform: rotate(10deg);\n  width: 50vw;\n  padding: 1em 0;\n  flex-direction: row-reverse;\n}\n\n.item {\n  margin: 1em 0;\n  background-color: #29e;\n  max-width: none;\n}\n\n.item:first-child {\n  width: 75%;\n}\n\n.item.disabled {\n  background-color: gray;\n}\n\n.container, .tags {\n  touch-action: none;\n  user-select: none;\n}\n\n.tags {\n  background-color: lightgray;\n  padding: 1em;\n}\n\n.tag {\n  font-size: 2em !important;\n}\n\n#no-parent {\n  position: absolute;\n  bottom: 2em;\n  right: 2em;\n  width: 300px;\n}\n\n.i-ghost {\n  opacity: 0.5;\n}\n\n.i-mirror {\n  z-index: 100;\n}\n\n.container {\n  height: 300px;\n  overflow: auto;\n}\n"
  },
  {
    "path": "examples/sortable/vue.js",
    "content": "import '@interactjs/vue'\nimport { createApp } from 'vue/dist/vue.esm-bundler'\n\nimport interact from '@interactjs/interactjs'\n\nimport { getData, sortableOptions, swappableOptions } from './shared.js'\n\nconst app = createApp({\n  data() {\n    return {\n      ...getData(),\n      sortableOptions,\n      swappableOptions,\n    }\n  },\n})\n\napp.use(interact.vue)\napp.mount('#vue-app')\n"
  },
  {
    "path": "examples/star/index.css",
    "content": ".point-handle {\n    cursor: -webkit-grab;\n    cursor: -moz-grab;\n    cursor: -ms-grab;\n    cursor: grab;\n\n    touch-action: none;\n}\n\n.dragging, .dragging .point-handle {\n    cursor: -webkit-grabbing;\n    cursor: -moz-grabbing;\n    cursor: -ms-grabbing;\n    cursor: grabbing;\n}\n"
  },
  {
    "path": "examples/star/index.js",
    "content": "document.addEventListener('DOMContentLoaded', () => {\n  const sns = 'http://www.w3.org/2000/svg'\n  const xns = 'http://www.w3.org/1999/xlink'\n  const root = document.getElementById('svg-edit-demo')\n  const star = document.getElementById('edit-star')\n  let rootMatrix\n  const originalPoints = []\n  let transformedPoints = []\n\n  for (let i = 0, len = star.points.numberOfItems; i < len; i++) {\n    const handle = document.createElementNS(sns, 'use')\n    const point = star.points.getItem(i)\n    const newPoint = root.createSVGPoint()\n\n    handle.setAttributeNS(xns, 'href', '#point-handle')\n    handle.setAttribute('class', 'point-handle')\n\n    handle.x.baseVal.value = newPoint.x = point.x\n    handle.y.baseVal.value = newPoint.y = point.y\n\n    handle.setAttribute('data-index', i)\n\n    originalPoints.push(newPoint)\n\n    root.appendChild(handle)\n  }\n\n  function applyTransforms(event) {\n    rootMatrix = root.getScreenCTM()\n\n    transformedPoints = originalPoints.map((point) => {\n      return point.matrixTransform(rootMatrix)\n    })\n\n    interact('.point-handle').draggable({\n      snap: {\n        targets: transformedPoints,\n        range: 20 * Math.max(rootMatrix.a, rootMatrix.d),\n      },\n    })\n  }\n\n  interact(root).on('mousedown', applyTransforms).on('touchstart', applyTransforms)\n\n  interact('.point-handle')\n    .draggable({\n      onstart: function (event) {\n        root.setAttribute('class', 'dragging')\n      },\n      onmove: function (event) {\n        const i = event.target.getAttribute('data-index') | 0\n        const point = star.points.getItem(i)\n\n        point.x += event.dx / rootMatrix.a\n        point.y += event.dy / rootMatrix.d\n\n        event.target.x.baseVal.value = point.x\n        event.target.y.baseVal.value = point.y\n      },\n      onend: function (event) {\n        root.setAttribute('class', '')\n      },\n      snap: {\n        targets: originalPoints,\n        range: 10,\n        relativePoints: [{ x: 0.5, y: 0.5 }],\n      },\n      restrict: { restriction: document.rootElement },\n    })\n    .styleCursor(false)\n\n  document.addEventListener('dragstart', (event) => {\n    event.preventDefault()\n  })\n})\n"
  },
  {
    "path": "examples/svg-editor/index.html",
    "content": "<svg>\n</svg>\n\n<label>\n  Resize invert:\n  <select id=\"invert\">\n    <option value=\"reposition\">reposition</option>\n    <option value=\"negate\">negate</option>\n    <option value=\"none\">none</option>\n  </select>\n</label>\n\n<style>\nsvg {\n  width: 100%;\n  height: 240px;\n  background-color: #2e9;\n\n  -ms-touch-action: none;\n      touch-action: none;\n}\n.edit-rectangle {\n  fill: #92e;\n  stroke: #fff;\n\n  transition: fill 0.3s, stroke 0.3s;\n}\n.edit-rectangle.neg-w {\n  fill: #f40;\n}\n.edit-rectangle.neg-h {\n  stroke: #29e;\n}\nbody { margin: 0; }\n</style>\n\n<script type=\"module\" src=\"./index.js\"></script>\n"
  },
  {
    "path": "examples/svg-editor/index.js",
    "content": "/* eslint-disable import/no-absolute-path */\nimport '@interactjs/actions'\nimport '@interactjs/modifiers'\nimport '@interactjs/inertia'\nimport '@interactjs/auto-start'\nimport '@interactjs/dev-tools'\n\nimport interact from '@interactjs/interact'\n\nconst svgCanvas = document.querySelector('svg')\nconst svgNS = 'http://www.w3.org/2000/svg'\nconst rectangles = []\n\nclass Rectangle {\n  constructor(x, y, w, h) {\n    this.x = x\n    this.y = y\n    this.w = w\n    this.h = h\n    this.scale = 1.0\n    this.stroke = 5\n    this.el = document.createElementNS(svgNS, 'rect')\n\n    this.el.setAttribute('data-index', rectangles.length)\n    this.el.setAttribute('class', 'edit-rectangle')\n    rectangles.push(this)\n\n    this.draw()\n  }\n\n  draw() {\n    let x = this.x\n    let y = this.y\n    let w = this.w\n    let h = this.h\n    let cssClass = 'edit-rectangle'\n\n    if (w < 0) {\n      x += w\n      w = Math.abs(w)\n      cssClass += ' neg-w'\n    }\n    if (h < 0) {\n      y += h\n      h = Math.abs(h)\n      cssClass += ' neg-h'\n    }\n\n    this.el.setAttribute('x', x + this.stroke / 2)\n    this.el.setAttribute('y', y + this.stroke / 2)\n    this.el.setAttribute('width', Math.max(w, 10) - this.stroke)\n    this.el.setAttribute('height', Math.max(h, 10) - this.stroke)\n    this.el.setAttribute('stroke-width', this.stroke)\n    this.el.style.transform = `scale(${this.scale})`\n\n    this.el.setAttribute('class', cssClass)\n  }\n}\n\ninteract('.edit-rectangle')\n  // change how interact gets the\n  // dimensions of '.edit-rectangle' elements\n  .rectChecker((element) => {\n    // find the Rectangle object that the element belongs to\n    const { x, y, w, h, scale } = rectangles[element.getAttribute('data-index')]\n\n    // return a suitable object for interact.js\n    const left = x * scale\n    const top = y * scale\n\n    return {\n      left,\n      top,\n      right: left + w * scale,\n      bottom: top + h * scale,\n    }\n  })\n  .draggable({\n    // inertia: true,\n    modifiers: [\n      interact.modifiers.restrictRect({\n        // restrict to a parent element that matches this CSS selector\n        restriction: 'svg',\n        // only restrict before ending the drag\n        endOnly: true,\n      }),\n      interact.modifiers.transform(),\n    ],\n    onmove: function (event) {\n      const rectangle = rectangles[event.target.getAttribute('data-index')]\n\n      rectangle.x += event.dx\n      rectangle.y += event.dy\n      rectangle.draw()\n    },\n  })\n  .resizable({\n    edges: { left: true, right: true, top: true, bottom: true },\n    invert: 'reposition',\n    modifiers: [\n      interact.modifiers.transform(),\n      interact.modifiers.restrictEdges({\n        restriction: 'svg',\n      }),\n    ],\n    listeners: {\n      move(event) {\n        const rectangle = rectangles[event.target.getAttribute('data-index')]\n\n        rectangle.x = event.rect.left\n        rectangle.y = event.rect.top\n        rectangle.w = event.rect.width\n        rectangle.h = event.rect.height\n        rectangle.draw()\n      },\n    },\n  })\n\nfor (let i = 0; i < 5; i++) {\n  const r = new Rectangle(50 + 100 * i, 80, 80, 80)\n  svgCanvas.appendChild(r.el)\n}\n\ninteract('#invert').on('input change', (event) => {\n  interact('.edit-rectangle').resizable({ invert: event.target.value })\n  console.log(event.target.value)\n})\n"
  },
  {
    "path": "examples/transform/index.html",
    "content": "<head>\n<title>interact.js transforms modifier demo</title>\n<script type=\"module\" src=\"./index.js\"></script>\n<link rel=\"stylesheet\" href=\"../../node_modules/bulma/css/bulma.css\">\n\n</head>\n<body>\n<div id=\"container\" _class=\"container box\">\n  <div id=\"item1\" class=\"item card\">\n    <div class=\"card-content\">item 1</div>\n  </div>\n  <div id=\"item2\" class=\"item card\">\n    <div class=\"card-content\">item 2</div>\n  </div>\n  <div id=\"item3\" class=\"item card\">\n    <div class=\"card-content\">item 3</div>\n  </div>\n  <div id=\"item4\" class=\"item card\">\n    <div class=\"card-content\">item 4</div>\n  </div>\n</div>\n\n<style>\n*, *::before, *::after {\n  box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n}\n\n#container {\n  margin: 0;\n  transform-origin: 0 0;\n  transform: rotate(0deg) scale(2);\n  _transform: rotate(10deg);\n  width: 25vw;\n}\n\n.item {\n  background-color: #29e;\n  max-width: none;\n  touch-action: none;\n  user-select: none;\n}\n\n#item2 {\n  width: 200px;\n  height: 200px;\n}\n\n</style>\n</body>\n"
  },
  {
    "path": "examples/transform/index.js",
    "content": "import interact from '@interactjs/interactjs'\n// import Vue from '../../node_modules/vue/dist/vue.esm.browser.js'\n\ninteract('.item')\n  .draggable({\n    origin: 'parent',\n    // inertia: true,\n    modifiers: [\n      interact.modifiers.snap({\n        // enabled: false,\n        // targets: [interact.snappers.grid({ x: 20, y: 20 })],\n        targets: [interact.snappers.elements({ targets: '.item', range: 20 })],\n        relativePoints: [{ x: 0, y: 0 }],\n      }),\n      interact.modifiers.avoid({ targets: ['.item'] }),\n      interact.modifiers.spring({ allowResume: true }),\n      interact.modifiers.transform(),\n    ],\n  })\n  .resizable({\n    enabled: true,\n    origin: 'self',\n    edges: { left: true, right: true, top: true, bottom: true },\n    modifiers: [\n      // interact.modifiers.snapSize({\n      // targets: [interact.snappers.grid({ x: 100, y: 100 })],\n      // }),\n      // interact.modifiers.aspectRatio({ ratio: 'preserve' }),\n      // interact.modifiers.restrictSize({\n      // max: { width: 350, y: 200 },\n      // }),\n      interact.modifiers.spring({ allowResume: true }),\n      // interact.modifiers.avoid({ targets: ['.item'] }),\n      interact.modifiers.transform(),\n    ],\n  })\n  .on('resizemove', (event) => {\n    console.log(event.rect.width / event.rect.height)\n  })\n  .on('resize drag', interact.feedback.dragResize())\n"
  },
  {
    "path": "jest.config.ts",
    "content": "import type { Config } from '@jest/types'\n\nimport { sourcesGlob } from './scripts/utils'\n\nconst config: Config.InitialOptions = {\n  preset: 'vijest',\n  coverageThreshold: {\n    global: {\n      statements: 59,\n      branches: 48,\n      functions: 58,\n      lines: 59,\n    },\n  },\n  // collectCoverage: true,\n  collectCoverageFrom: [sourcesGlob],\n  coveragePathIgnorePatterns: ['[\\\\\\\\/]_', '\\\\.d\\\\.ts$', '@interactjs[\\\\\\\\/](rebound|symbol-tree)[\\\\\\\\/]'],\n  coverageReporters: ['json', 'text', ['lcov', { projectRoot: 'packages/@interactjs' }]],\n}\n\nexport default config\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"version\": \"0.0.0\",\n  \"packages\": [\n    \"@interactjs/*\",\n    \"./interactjs\"\n  ]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@interactjs/_dev\",\n  \"version\": \"1.10.27\",\n  \"private\": true,\n  \"directories\": {\n    \"bin\": \"./bin\"\n  },\n  \"scripts\": {\n    \"bootstrap\": \"yarn install --pure-lockfile --prefer-offline --silent && sh bin/_link\",\n    \"start\": \"_add_plugin_indexes && vite serve\",\n    \"build\": \"yarn build:docs && yarn build:bundle && _add_plugin_indexes && yarn build:types && yarn build:esnext\",\n    \"build:docs\": \"yarn typedoc\",\n    \"build:bundle\": \"rollup -c bundle.rollup.config.cjs\",\n    \"build:types\": \"_types\",\n    \"build:esnext\": \"_add_plugin_indexes && rollup -c esnext.rollup.config.cjs\",\n    \"test\": \"jest\",\n    \"test:debug\": \"node --inspect node_modules/.bin/jest --no-cache --runInBand \",\n    \"tsc_lint_test\": \"_add_plugin_indexes && tsc -b -f && _lint && yarn test\",\n    \"prepare\": \"bin/_link; husky install\"\n  },\n  \"homepage\": \"https://interactjs.io/pro\",\n  \"description\": \"\",\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.18.2\",\n    \"@babel/plugin-proposal-export-default-from\": \"^7.17.12\",\n    \"@babel/plugin-proposal-optional-catch-binding\": \"^7.16.7\",\n    \"@babel/plugin-proposal-optional-chaining\": \"^7.17.12\",\n    \"@babel/plugin-transform-class-properties\": \"^7.23.3\",\n    \"@babel/plugin-transform-runtime\": \"^7.18.2\",\n    \"@babel/preset-env\": \"^7.18.2\",\n    \"@babel/preset-typescript\": \"^7.17.12\",\n    \"@babel/runtime\": \"^7.18.3\",\n    \"@rollup/plugin-babel\": \"^6.0.4\",\n    \"@rollup/plugin-commonjs\": \"^25.0.7\",\n    \"@rollup/plugin-node-resolve\": \"^15.2.3\",\n    \"@rollup/plugin-replace\": \"^5.0.5\",\n    \"@rollup/plugin-terser\": \"^0.4.4\",\n    \"@testing-library/dom\": \"^9.3.3\",\n    \"@testing-library/user-event\": \"^14.5.1\",\n    \"@types/jest\": \"27\",\n    \"@types/node\": \"^17.0.42\",\n    \"@types/react\": \"^18.2.43\",\n    \"@types/shelljs\": \"^0.8.11\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.13.2\",\n    \"@typescript-eslint/parser\": \"^6.13.2\",\n    \"@vitejs/plugin-vue\": \"^4.5.2\",\n    \"@vue/babel-plugin-jsx\": \"^1.1.5\",\n    \"@vue/compiler-sfc\": \"^3.3.11\",\n    \"@vue/reactivity\": \"^3.3.11\",\n    \"@vue/runtime-dom\": \"^3.3.11\",\n    \"@vue/test-utils\": \"^2.4.2\",\n    \"babel-helper-vue-jsx-merge-props\": \"^2.0.3\",\n    \"babel-plugin-syntax-jsx\": \"^6.18.0\",\n    \"bulma\": \"^0.9.4\",\n    \"del\": \"^7.1.0\",\n    \"eslint\": \"^8.17.0\",\n    \"eslint-config-prettier\": \"^9.0.0\",\n    \"eslint-config-standard\": \"^17.0.0\",\n    \"eslint-import-resolver-typescript\": \"^3.6.1\",\n    \"eslint-plugin-import\": \"^2.26.0\",\n    \"eslint-plugin-jest\": \"^27.6.0\",\n    \"eslint-plugin-markdown\": \"^3.0.1\",\n    \"eslint-plugin-n\": \"^16.3.1\",\n    \"eslint-plugin-promise\": \"^6.0.0\",\n    \"eslint-plugin-react\": \"^7.30.0\",\n    \"eslint-plugin-require-path-exists\": \"^1.1.9\",\n    \"eslint-plugin-tsdoc\": \"^0.2.17\",\n    \"eslint-plugin-vue\": \"^9.1.1\",\n    \"fs-extra\": \"^11.2.0\",\n    \"glob\": \"^10.3.10\",\n    \"hash-sum\": \"^2.0.0\",\n    \"husky\": \"8.0.3\",\n    \"jest\": \"27\",\n    \"lint-staged\": \"^15.2.0\",\n    \"mkdirp\": \"^3.0.1\",\n    \"path-browserify\": \"^1.0.1\",\n    \"prettier\": \"^3.1.1\",\n    \"promise-polyfill\": \"^8.2.3\",\n    \"react\": \"^18.1.0\",\n    \"react-dom\": \"^18.1.0\",\n    \"rebound\": \"^0.1.0\",\n    \"resolve\": \"^1.22.0\",\n    \"rollup\": \"4.7.0\",\n    \"semver\": \"^7.3.7\",\n    \"serve-index\": \"^1.9.1\",\n    \"shelljs\": \"^0.8.5\",\n    \"stylelint\": \"^16.0.1\",\n    \"stylelint-config-css-modules\": \"^4.2.0\",\n    \"stylelint-config-html\": \"^1.1.0\",\n    \"stylelint-config-recess-order\": \"^4.2.0\",\n    \"stylelint-config-standard\": \"^35.0.0\",\n    \"temp\": \"^0.9.4\",\n    \"ts-node\": \"^10.9.2\",\n    \"typedoc\": \"^0.25.4\",\n    \"typedoc-plugin-markdown\": \"^3.17.1\",\n    \"typescript\": \"^5.3.3\",\n    \"vijest\": \"^0.0.2\",\n    \"vite\": \"^5.0.7\",\n    \"vue\": \"^3.3.11\",\n    \"yargs\": \"^17.5.1\"\n  },\n  \"resolutions\": {\n    \"jackspeak\": \"2.1.1\",\n    \"query-string\": \"7.1.3\"\n  },\n  \"sideEffects\": false,\n  \"lint-staged\": {\n    \"**/*.((ts|js|cjs)?(x)|vue|md)\": \"bin/_lint --fix\",\n    \"**/*.(yaml|yml|json|css)\": \"prettier --check --write\",\n    \"**/*.css\": [\n      \"stylelint --fix\"\n    ]\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/.eslintrc.cjs",
    "content": "module.exports = {\n  extends: '../.eslintrc.cjs',\n  env: { browser: true, node: false },\n  rules: {\n    'no-console': 2,\n    strict: [2, 'never'],\n    'no-restricted-syntax': ['error', 'Generator', 'ExperimentalRestProperty', 'ExperimentalSpreadProperty'],\n  },\n  overrides: [\n    {\n      files: '**/*.spec.ts',\n      env: { browser: true, node: true },\n      rules: { 'no-restricted-syntax': 'off', 'no-console': 'off' },\n    },\n  ],\n}\n"
  },
  {
    "path": "packages/@interactjs/actions/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/actions/actions.spec.ts",
    "content": "import type { Scope } from '@interactjs/core/scope'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport type { ActionName } from '@interactjs/core/types'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport actions from './plugin'\n\ndescribe('actions integration', () => {\n  const scope: Scope = helpers.mockScope()\n  const event = pointerUtils.coordsToEvent(pointerUtils.newCoords())\n  const element = scope.document.body\n\n  scope.usePlugin(actions)\n\n  const interactable = scope.interactables.new(element)\n  // make a dropzone\n  scope.interactables.new(scope.document.documentElement).dropzone({})\n  const interaction1 = scope.interactions.new({})\n\n  interaction1.pointerDown(event, event, element)\n\n  for (const name in scope.actions.map) {\n    test(`${name} interaction starts and stops as expected`, () => {\n      interaction1.start({ name: name as ActionName }, interactable, element)\n      interaction1.stop()\n\n      expect(() => {\n        interaction1.interacting()\n      }).not.toThrow()\n\n      expect(interaction1.interacting()).toBe(false)\n    })\n  }\n\n  const actionNames = Object.keys(scope.actions.map)\n\n  for (const order of [actionNames, [...actionNames].reverse()] as ActionName[][]) {\n    const interaction2 = scope.interactions.new({})\n\n    for (const name of order) {\n      test(`${name} interaction starts, moves and ends as expected`, () => {\n        expect(() => {\n          interaction2.start({ name }, interactable, element)\n          interaction2.pointerMove(event, event, element)\n          interaction2.pointerUp(event, event, element, element)\n        }).not.toThrow()\n\n        expect(interaction2.interacting()).toBe<boolean>(false)\n      })\n    }\n  }\n})\n"
  },
  {
    "path": "packages/@interactjs/actions/drag/drag.spec.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport extend from '@interactjs/utils/extend'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport drag from './plugin'\n\ndescribe('actions/drag', () => {\n  test('drag action init', () => {\n    const scope = helpers.mockScope()\n\n    scope.usePlugin(drag)\n\n    expect(scope.actions.map.drag).toBeTruthy()\n    expect(scope.actions.methodDict.drag).toBe('draggable')\n    expect(typeof scope.Interactable.prototype.draggable).toBe('function')\n  })\n\n  describe('interactable.draggable method', () => {\n    const interactable = {\n      options: {\n        drag: {},\n      },\n      draggable: drag.draggable,\n      setPerAction: () => {\n        calledSetPerAction = true\n      },\n      setOnEvents: () => {\n        calledSetOnEvents = true\n      },\n    } as unknown as Interactable\n    let calledSetPerAction = false\n    let calledSetOnEvents = false\n\n    test('args types', () => {\n      expect(interactable.draggable()).toEqual(interactable.options.drag)\n\n      interactable.draggable(true)\n      expect(interactable.options.drag.enabled).toBe(true)\n\n      interactable.draggable(false)\n      expect(interactable.options.drag.enabled).toBe(false)\n\n      interactable.draggable({})\n      expect(interactable.options.drag.enabled).toBe(true)\n      expect(calledSetOnEvents).toBe(true)\n      expect(calledSetPerAction).toBe(true)\n\n      interactable.draggable({ enabled: false })\n      expect(interactable.options.drag.enabled).toBe(false)\n    })\n\n    const axisSettings = {\n      lockAxis: ['x', 'y', 'xy', 'start'],\n      startAxis: ['x', 'y', 'xy'],\n    }\n\n    for (const axis in axisSettings) {\n      for (const value of axisSettings[axis]) {\n        test(`\\`${axis}: ${value}\\` is set correctly`, () => {\n          interactable.draggable({ [axis]: value })\n          expect(interactable.options.drag[axis]).toBe(value)\n        })\n      }\n    }\n  })\n\n  describe('drag axis', () => {\n    const scope = helpers.mockScope()\n\n    scope.usePlugin(drag)\n\n    const interaction = scope.interactions.new({})\n    const element = {}\n    const interactable = {\n      options: {\n        drag: {},\n      },\n      target: element,\n    } as Interactable\n    const iEvent = { page: {}, client: {}, delta: {}, type: 'dragmove' } as InteractEvent\n\n    const opposites = { x: 'y', y: 'x' }\n    const eventCoords = {\n      page: { x: -1, y: -2 },\n      client: { x: -3, y: -4 },\n      delta: { x: -5, y: -6 },\n      timeStamp: 0,\n    }\n    const coords = helpers.newCoordsSet()\n\n    resetCoords()\n    interaction.prepared = { name: 'drag', axis: 'xy' }\n    interaction.interactable = interactable\n\n    test('xy (any direction)', () => {\n      scope.fire('interactions:before-action-move', { interaction } as any)\n\n      expect(interaction.coords.start).toEqual(coords.start)\n      expect(interaction.coords.delta).toEqual(coords.delta)\n\n      scope.fire('interactions:action-move', { iEvent, interaction } as any)\n\n      expect(iEvent.page).toEqual(eventCoords.page)\n      expect(iEvent.delta).toEqual(eventCoords.delta)\n    })\n\n    for (const axis in opposites) {\n      const opposite = opposites[axis]\n\n      test(`${axis}-axis`, () => {\n        resetCoords()\n        interaction.prepared.axis = axis as any\n\n        scope.fire('interactions:action-move', { iEvent, interaction } as any)\n\n        expect(iEvent.delta).toEqual({\n          [opposite]: 0,\n          [axis]: eventCoords.delta[axis],\n        })\n\n        expect(iEvent.page).toEqual({\n          [opposite]: coords.start.page[opposite],\n          [axis]: eventCoords.page[axis],\n        })\n\n        expect(iEvent.page[axis]).toBe(eventCoords.page[axis])\n\n        expect(iEvent.client[opposite]).toBe(coords.start.client[opposite])\n        expect(iEvent.client[axis]).toBe(eventCoords.client[axis])\n      })\n    }\n\n    function resetCoords() {\n      pointerUtils.copyCoords(iEvent, eventCoords)\n      extend(iEvent.delta, eventCoords.delta)\n\n      for (const prop in coords) {\n        pointerUtils.copyCoords(interaction.coords[prop], coords[prop])\n      }\n    }\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/actions/drag/plugin.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport type { PerActionDefaults } from '@interactjs/core/options'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { ListenersArg, OrBoolean } from '@interactjs/core/types'\nimport is from '@interactjs/utils/is'\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    draggable(options: Partial<OrBoolean<DraggableOptions>> | boolean): this\n    draggable(): DraggableOptions\n    /**\n     * ```js\n     * interact(element).draggable({\n     *     onstart: function (event) {},\n     *     onmove : function (event) {},\n     *     onend  : function (event) {},\n     *\n     *     // the axis in which the first movement must be\n     *     // for the drag sequence to start\n     *     // 'xy' by default - any direction\n     *     startAxis: 'x' || 'y' || 'xy',\n     *\n     *     // 'xy' by default - don't restrict to one axis (move in any direction)\n     *     // 'x' or 'y' to restrict movement to either axis\n     *     // 'start' to restrict movement to the axis the drag started in\n     *     lockAxis: 'x' || 'y' || 'xy' || 'start',\n     *\n     *     // max number of drags that can happen concurrently\n     *     // with elements of this Interactable. Infinity by default\n     *     max: Infinity,\n     *\n     *     // max number of drags that can target the same element+Interactable\n     *     // 1 by default\n     *     maxPerElement: 2\n     * })\n     *\n     * var isDraggable = interact('element').draggable(); // true\n     * ```\n     *\n     * Get or set whether drag actions can be performed on the target\n     *\n     * @param options - true/false or An object with event\n     * listeners to be fired on drag events (object makes the Interactable\n     * draggable)\n     */\n    draggable(options?: Partial<OrBoolean<DraggableOptions>> | boolean): this | DraggableOptions\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface ActionDefaults {\n    drag: DraggableOptions\n  }\n}\n\ndeclare module '@interactjs/core/types' {\n  interface ActionMap {\n    drag?: typeof drag\n  }\n}\n\nexport type DragEvent = InteractEvent<'drag'>\n\nexport interface DraggableOptions extends PerActionDefaults {\n  startAxis?: 'x' | 'y' | 'xy'\n  lockAxis?: 'x' | 'y' | 'xy' | 'start'\n  oninertiastart?: ListenersArg\n  onstart?: ListenersArg\n  onmove?: ListenersArg\n  onend?: ListenersArg\n}\n\nfunction install(scope: Scope) {\n  const { actions, Interactable, defaults } = scope\n\n  Interactable.prototype.draggable = drag.draggable\n\n  actions.map.drag = drag\n  actions.methodDict.drag = 'draggable'\n\n  defaults.actions.drag = drag.defaults\n}\n\nfunction beforeMove({ interaction }) {\n  if (interaction.prepared.name !== 'drag') return\n\n  const axis = interaction.prepared.axis\n\n  if (axis === 'x') {\n    interaction.coords.cur.page.y = interaction.coords.start.page.y\n    interaction.coords.cur.client.y = interaction.coords.start.client.y\n\n    interaction.coords.velocity.client.y = 0\n    interaction.coords.velocity.page.y = 0\n  } else if (axis === 'y') {\n    interaction.coords.cur.page.x = interaction.coords.start.page.x\n    interaction.coords.cur.client.x = interaction.coords.start.client.x\n\n    interaction.coords.velocity.client.x = 0\n    interaction.coords.velocity.page.x = 0\n  }\n}\n\nfunction move({ iEvent, interaction }) {\n  if (interaction.prepared.name !== 'drag') return\n\n  const axis = interaction.prepared.axis\n\n  if (axis === 'x' || axis === 'y') {\n    const opposite = axis === 'x' ? 'y' : 'x'\n\n    iEvent.page[opposite] = interaction.coords.start.page[opposite]\n    iEvent.client[opposite] = interaction.coords.start.client[opposite]\n    iEvent.delta[opposite] = 0\n  }\n}\n\nconst draggable: Interactable['draggable'] = function draggable(\n  this: Interactable,\n  options?: DraggableOptions | boolean,\n): any {\n  if (is.object(options)) {\n    this.options.drag.enabled = options.enabled !== false\n    this.setPerAction('drag', options)\n    this.setOnEvents('drag', options)\n\n    if (/^(xy|x|y|start)$/.test(options.lockAxis)) {\n      this.options.drag.lockAxis = options.lockAxis\n    }\n    if (/^(xy|x|y)$/.test(options.startAxis)) {\n      this.options.drag.startAxis = options.startAxis\n    }\n\n    return this\n  }\n\n  if (is.bool(options)) {\n    this.options.drag.enabled = options\n\n    return this\n  }\n\n  return this.options.drag as DraggableOptions\n}\n\nconst drag: Plugin = {\n  id: 'actions/drag',\n  install,\n  listeners: {\n    'interactions:before-action-move': beforeMove,\n    'interactions:action-resume': beforeMove,\n\n    // dragmove\n    'interactions:action-move': move,\n    'auto-start:check': (arg) => {\n      const { interaction, interactable, buttons } = arg\n      const dragOptions = interactable.options.drag\n\n      if (\n        !(dragOptions && dragOptions.enabled) ||\n        // check mouseButton setting if the pointer is down\n        (interaction.pointerIsDown &&\n          /mouse|pointer/.test(interaction.pointerType) &&\n          (buttons & interactable.options.drag.mouseButtons) === 0)\n      ) {\n        return undefined\n      }\n\n      arg.action = {\n        name: 'drag',\n        axis: dragOptions.lockAxis === 'start' ? dragOptions.startAxis : dragOptions.lockAxis,\n      }\n\n      return false\n    },\n  },\n  draggable,\n  beforeMove,\n  move,\n  defaults: {\n    startAxis: 'xy',\n    lockAxis: 'xy',\n  } as DraggableOptions,\n\n  getCursor() {\n    return 'move'\n  },\n\n  filterEventType: (type: string) => type.search('drag') === 0,\n}\n\nexport default drag\n"
  },
  {
    "path": "packages/@interactjs/actions/drop/DropEvent.spec.ts",
    "content": "import type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport extend from '@interactjs/utils/extend'\n\nimport { DropEvent } from '../drop/DropEvent'\n\nconst dz1: any = {\n  target: 'dz1',\n  fire: jest.fn(),\n}\nconst dz2: any = {\n  target: 'dz2',\n  fire: jest.fn(),\n}\nconst el1: any = Symbol('el1')\nconst el2: any = Symbol('el2')\nconst interactable: any = Symbol('interactable')\nconst dragElement: any = Symbol('drag-el')\n\ndescribe('DropEvent', () => {\n  describe('constructor', () => {\n    const interaction: any = { dropState: {} }\n    const dragEvent = Object.freeze({\n      interactable,\n      _interaction: interaction,\n      target: dragElement,\n      timeStamp: 10,\n    }) as InteractEvent\n\n    extend(interaction.dropState, {\n      activeDrops: [\n        { dropzone: dz1, element: el1 },\n        { dropzone: dz2, element: el2 },\n      ],\n      cur: { dropzone: dz1, element: el1 },\n      prev: { dropzone: dz2, element: el2 },\n      events: {},\n    })\n\n    test('dropmove target, dropzone, relatedTarget props', () => {\n      const dropmove = new DropEvent(interaction.dropState, dragEvent, 'dropmove')\n\n      expect(dropmove.target).toBe(el1)\n      expect(dropmove.dropzone).toBe(dz1)\n      expect(dropmove.relatedTarget).toBe(dragElement)\n    })\n\n    test('dragleave target, dropzone, relatedTarget props', () => {\n      const dragleave = new DropEvent(interaction.dropState, dragEvent, 'dragleave')\n\n      expect(dragleave.target).toBe(el2)\n      expect(dragleave.dropzone).toBe(dz2)\n      expect(dragleave.relatedTarget).toBe(dragElement)\n    })\n  })\n\n  describe('reject', () => {\n    const interaction: any = { dropState: {} }\n    const dragEvent = Object.freeze({\n      interactable,\n      _interaction: interaction,\n      target: dragElement,\n      timeStamp: 10,\n    }) as InteractEvent\n\n    test('dropactivate.reject()', () => {\n      extend(interaction.dropState, {\n        activeDrops: [\n          { dropzone: dz1, element: el1 },\n          { dropzone: dz2, element: el2 },\n        ],\n        cur: { dropzone: null, element: null },\n        prev: { dropzone: null, element: null },\n        events: {},\n      })\n\n      const dropactivate = new DropEvent(interaction.dropState, dragEvent, 'dropactivate')\n\n      dropactivate.dropzone = dz1\n      dropactivate.target = el1\n      dropactivate.reject()\n\n      // immediate propagation stopped on reject\n      expect(dropactivate.propagationStopped && dropactivate.immediatePropagationStopped).toBe(true)\n\n      // dropdeactivate is fired on rejected dropzone\n      expect(dz1.fire).toHaveBeenLastCalledWith(expect.objectContaining({ type: 'dropdeactivate' }))\n\n      // activeDrop of rejected dropactivate event is removed\n      expect(interaction.dropState.activeDrops).toEqual([{ dropzone: dz2, element: el2 }])\n      expect(interaction.dropState.cur).toEqual({ dropzone: null, element: null })\n    })\n\n    test('dropmove.reject()', () => {\n      extend(interaction.dropState, {\n        cur: { dropzone: dz1, element: el1 },\n        prev: { dropzone: null, element: null },\n        events: {},\n      })\n\n      const dropmove = new DropEvent(interaction.dropState, dragEvent, 'dropmove')\n\n      dropmove.reject()\n\n      // dropState.cur remains the same after rejecting non activate event,\n      expect(interaction.dropState.cur).toEqual({ dropzone: dz1, element: el1 })\n      expect(interaction.dropState.rejected).toBe(true)\n\n      // dragleave is fired on rejected dropzone\n      expect(dz1.fire).toHaveBeenLastCalledWith(expect.objectContaining({ type: 'dragleave' }))\n    })\n  })\n\n  test('stop[Immediate]Propagation()', () => {\n    const dropEvent = new DropEvent({ cur: {} } as any, {} as any, 'dragmove')\n\n    expect(dropEvent.propagationStopped || dropEvent.immediatePropagationStopped).toBe(false)\n\n    dropEvent.stopPropagation()\n    expect(dropEvent.propagationStopped).toBe(true)\n    expect(dropEvent.immediatePropagationStopped).toBe(false)\n\n    dropEvent.propagationStopped = false\n\n    dropEvent.stopImmediatePropagation()\n    expect(dropEvent.propagationStopped && dropEvent.immediatePropagationStopped).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/actions/drop/DropEvent.ts",
    "content": "import { BaseEvent } from '@interactjs/core/BaseEvent'\nimport type { Interactable } from '@interactjs/core/Interactable'\nimport type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport type { Element } from '@interactjs/core/types'\nimport * as arr from '@interactjs/utils/arr'\n\nimport type { DropState } from './plugin'\n\nexport class DropEvent extends BaseEvent<'drag'> {\n  declare target: Element\n  dropzone: Interactable\n  dragEvent: InteractEvent<'drag'>\n  relatedTarget: Element\n  draggable: Interactable\n  propagationStopped = false\n  immediatePropagationStopped = false\n\n  /**\n   * Class of events fired on dropzones during drags with acceptable targets.\n   */\n  constructor(dropState: DropState, dragEvent: InteractEvent<'drag'>, type: string) {\n    super(dragEvent._interaction)\n\n    const { element, dropzone } = type === 'dragleave' ? dropState.prev : dropState.cur\n\n    this.type = type\n    this.target = element\n    this.currentTarget = element\n    this.dropzone = dropzone\n    this.dragEvent = dragEvent\n    this.relatedTarget = dragEvent.target\n    this.draggable = dragEvent.interactable\n    this.timeStamp = dragEvent.timeStamp\n  }\n\n  /**\n   * If this is a `dropactivate` event, the dropzone element will be\n   * deactivated.\n   *\n   * If this is a `dragmove` or `dragenter`, a `dragleave` will be fired on the\n   * dropzone element and more.\n   */\n  reject() {\n    const { dropState } = this._interaction\n\n    if (\n      this.type !== 'dropactivate' &&\n      (!this.dropzone || dropState.cur.dropzone !== this.dropzone || dropState.cur.element !== this.target)\n    ) {\n      return\n    }\n\n    dropState.prev.dropzone = this.dropzone\n    dropState.prev.element = this.target\n\n    dropState.rejected = true\n    dropState.events.enter = null\n\n    this.stopImmediatePropagation()\n\n    if (this.type === 'dropactivate') {\n      const activeDrops = dropState.activeDrops\n      const index = arr.findIndex(\n        activeDrops,\n        ({ dropzone, element }) => dropzone === this.dropzone && element === this.target,\n      )\n\n      dropState.activeDrops.splice(index, 1)\n\n      const deactivateEvent = new DropEvent(dropState, this.dragEvent, 'dropdeactivate')\n\n      deactivateEvent.dropzone = this.dropzone\n      deactivateEvent.target = this.target\n\n      this.dropzone.fire(deactivateEvent)\n    } else {\n      this.dropzone.fire(new DropEvent(dropState, this.dragEvent, 'dragleave'))\n    }\n  }\n\n  preventDefault() {}\n\n  stopPropagation() {\n    this.propagationStopped = true\n  }\n\n  stopImmediatePropagation() {\n    this.immediatePropagationStopped = this.propagationStopped = true\n  }\n}\n"
  },
  {
    "path": "packages/@interactjs/actions/drop/drop.spec.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\nimport * as helpers from '@interactjs/core/tests/_helpers'\n\nimport drop from '../drop/plugin'\n\ndescribe('actions/drop', () => {\n  afterEach(() => {\n    document.body.innerHTML = ''\n  })\n\n  test('options', () => {\n    const { interactable } = helpers.testEnv({ plugins: [drop] })\n\n    const funcs = Object.freeze({\n      drop() {},\n      activate() {},\n      deactivate() {},\n      dropmove() {},\n      dragenter() {},\n      dragleave() {},\n    })\n\n    interactable.dropzone({\n      listeners: [funcs],\n    })\n\n    expect(interactable.events.types.drop[0]).toBe(funcs.drop)\n    expect(interactable.events.types.dropactivate[0]).toBe(funcs.activate)\n    expect(interactable.events.types.dropdeactivate[0]).toBe(funcs.deactivate)\n    expect(interactable.events.types.dropmove[0]).toBe(funcs.dropmove)\n    expect(interactable.events.types.dragenter[0]).toBe(funcs.dragenter)\n    expect(interactable.events.types.dragleave[0]).toBe(funcs.dragleave)\n  })\n\n  test('dynamicDrop', () => {\n    const { scope, interactable, down, start, move, interaction } = helpers.testEnv({ plugins: [drop] })\n    interactable.draggable({})\n\n    // no error with dynamicDrop === false\n    expect(() => {\n      scope.interactStatic.dynamicDrop(false)\n\n      down()\n      start({ name: 'drag' })\n      move()\n      interaction.end()\n    }).not.toThrow()\n\n    //  no error with dynamicDrop === true\n    expect(() => {\n      scope.interactStatic.dynamicDrop(true)\n      down()\n      start({ name: 'drag' })\n      move()\n      interaction.end()\n    }).not.toThrow()\n  })\n\n  test('start', () => {\n    const { scope, interactable, down, start, move, interaction } = helpers.testEnv({ plugins: [drop] })\n\n    interactable.draggable({})\n    const dropzone = scope.interactables.new('[data-drop]').dropzone({})\n\n    const [dropEl1, dropEl2, dropEl3] = ['a', 'b', 'c'].map((id) => {\n      const dropEl = scope.document.createElement('div')\n\n      dropEl.dataset.drop = id\n      scope.document.body.appendChild(dropEl)\n\n      return dropEl\n    })\n\n    // rejet imeediately on activate\n    dropzone.on('dropactivate', (event) => {\n      if (event.target === dropEl1 || event.target === dropEl2) {\n        event.reject()\n      }\n    })\n\n    const onActionsDropStart = jest.fn((arg: { interaction: Interaction }) => {\n      const activeDrops = [...arg.interaction.dropState!.activeDrops]\n      // actions/drop:start is fired with all activeDrops\n      expect(activeDrops.map((activeDrop) => activeDrop.element)).toEqual([dropEl3])\n    })\n\n    scope.addListeners({ 'actions/drop:start': onActionsDropStart })\n\n    const onDeactivate = jest.fn()\n    dropzone.on('dropdeactivate', onDeactivate)\n\n    down()\n    start({ name: 'drag' })\n    move()\n\n    expect(onActionsDropStart).toHaveBeenCalledTimes(1)\n\n    // rejected dropzones are removed from activeDrops\n    expect(interaction.dropState!.activeDrops.map((d) => d.element)).toEqual([dropEl3])\n\n    // rejected dropzones are deactivated\n    expect(onDeactivate.mock.calls.map((arg) => arg[0].target)).toEqual([dropEl1, dropEl2])\n\n    interaction.end()\n  })\n\n  test('targeting', () => {\n    const interactionTarget = document.body.appendChild(document.createElement('div'))\n    interactionTarget.id = 'target'\n    const { scope, interactable, down, start, move, up, coords } = helpers.testEnv({\n      plugins: [drop],\n      target: interactionTarget,\n    })\n\n    interactable.draggable({})\n\n    const [dropElA, dropElB, dropElC] = ['a', 'b', 'c'].map((id) => {\n      const dropEl = scope.document.createElement('div')\n\n      dropEl.dataset.drop = id\n      scope.document.body.appendChild(dropEl)\n\n      return dropEl\n    })\n\n    const onActivate = jest.fn((event) => event.target)\n    const onDeactivate = jest.fn((event) => event.target)\n    const onDragenter = jest.fn()\n    const dropzone = scope.interactables\n      .new('[data-drop]')\n      .dropzone({\n        checker: () => true,\n      })\n      .on({ dropactivate: onActivate, dropdeactivate: onDeactivate, dragenter: onDragenter })\n\n    down()\n    start({ name: 'drag' })\n    expect(onActivate.mock.results.map(({ value }) => value)).toEqual([dropElA, dropElB, dropElC])\n    expect(onDeactivate.mock.calls).toEqual([])\n    expect(onDragenter.mock.calls).toEqual([])\n\n    coords.page.x++\n    move()\n\n    expect(onDragenter.mock.calls.map(([{ target, relatedTarget }]) => [target, relatedTarget])).toEqual([\n      [dropElC, interactionTarget],\n    ])\n\n    onDragenter.mockClear()\n\n    // only b drop\n    dropzone.dropzone({\n      checker: (_dragEvent, _event, _dropped, _dropzone, dropElement) => dropElement.dataset.drop === 'b',\n    })\n\n    coords.page.x++\n    move()\n\n    expect(onDragenter.mock.calls.map((args) => [args[0].target, args[0].relatedTarget])).toEqual([\n      [dropElB, interactionTarget],\n    ])\n\n    up()\n\n    // all dropzones are deactivated\n    expect(onDeactivate.mock.results.map(({ value }) => value)).toEqual([dropElA, dropElB, dropElC])\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/actions/drop/plugin.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { EventPhase, InteractEvent } from '@interactjs/core/InteractEvent'\nimport type { Interaction, DoPhaseArg } from '@interactjs/core/Interaction'\nimport type { PerActionDefaults } from '@interactjs/core/options'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Element, PointerEventType, Rect, ListenersArg } from '@interactjs/core/types'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport getOriginXY from '@interactjs/utils/getOriginXY'\nimport is from '@interactjs/utils/is'\nimport normalizeListeners from '@interactjs/utils/normalizeListeners'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport '../drag/plugin'\n\nimport type { DragEvent } from '../drag/plugin'\nimport drag from '../drag/plugin'\n/* eslint-enable import/no-duplicates */\n\nimport { DropEvent } from './DropEvent'\n\nexport type DropFunctionChecker = (\n  dragEvent: any, // related drag operation\n  event: any, // touch or mouse EventEmitter\n  dropped: boolean, // default checker result\n  dropzone: Interactable, // dropzone interactable\n  dropElement: Element, // drop zone element\n  draggable: Interactable, // draggable's Interactable\n  draggableElement: Element, // dragged element\n) => boolean\n\nexport interface DropzoneOptions extends PerActionDefaults {\n  accept?:\n    | string\n    | Element\n    | (({ dropzone, draggableElement }: { dropzone: Interactable; draggableElement: Element }) => boolean)\n  // How the overlap is checked on the drop zone\n  overlap?: 'pointer' | 'center' | number\n  checker?: DropFunctionChecker\n\n  ondropactivate?: ListenersArg\n  ondropdeactivate?: ListenersArg\n  ondragenter?: ListenersArg\n  ondragleave?: ListenersArg\n  ondropmove?: ListenersArg\n  ondrop?: ListenersArg\n}\n\nexport interface DropzoneMethod {\n  (this: Interactable, options: DropzoneOptions | boolean): Interactable\n  (): DropzoneOptions\n}\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    /**\n     *\n     * ```js\n     * interact('.drop').dropzone({\n     *   accept: '.can-drop' || document.getElementById('single-drop'),\n     *   overlap: 'pointer' || 'center' || zeroToOne\n     * }\n     * ```\n     *\n     * Returns or sets whether draggables can be dropped onto this target to\n     * trigger drop events\n     *\n     * Dropzones can receive the following events:\n     *  - `dropactivate` and `dropdeactivate` when an acceptable drag starts and ends\n     *  - `dragenter` and `dragleave` when a draggable enters and leaves the dropzone\n     *  - `dragmove` when a draggable that has entered the dropzone is moved\n     *  - `drop` when a draggable is dropped into this dropzone\n     *\n     * Use the `accept` option to allow only elements that match the given CSS\n     * selector or element. The value can be:\n     *\n     *  - **an Element** - only that element can be dropped into this dropzone.\n     *  - **a string**, - the element being dragged must match it as a CSS selector.\n     *  - **`null`** - accept options is cleared - it accepts any element.\n     *\n     * Use the `overlap` option to set how drops are checked for. The allowed\n     * values are:\n     *\n     *   - `'pointer'`, the pointer must be over the dropzone (default)\n     *   - `'center'`, the draggable element's center must be over the dropzone\n     *   - a number from 0-1 which is the `(intersection area) / (draggable area)`.\n     *   e.g. `0.5` for drop to happen when half of the area of the draggable is\n     *   over the dropzone\n     *\n     * Use the `checker` option to specify a function to check if a dragged element\n     * is over this Interactable.\n     *\n     * @param options - The new options to be set\n     */\n    dropzone(options: DropzoneOptions | boolean): Interactable\n    /** @returns The current setting */\n    dropzone(): DropzoneOptions\n\n    /**\n     * ```js\n     * interact(target)\n     * .dropChecker(function(dragEvent,         // related dragmove or dragend event\n     *                       event,             // TouchEvent/PointerEvent/MouseEvent\n     *                       dropped,           // bool result of the default checker\n     *                       dropzone,          // dropzone Interactable\n     *                       dropElement,       // dropzone elemnt\n     *                       draggable,         // draggable Interactable\n     *                       draggableElement) {// draggable element\n     *\n     *   return dropped && event.target.hasAttribute('allow-drop')\n     * }\n     * ```\n     */\n    dropCheck(\n      dragEvent: InteractEvent,\n      event: PointerEventType,\n      draggable: Interactable,\n      draggableElement: Element,\n      dropElemen: Element,\n      rect: any,\n    ): boolean\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    dropState?: DropState\n  }\n}\n\ndeclare module '@interactjs/core/InteractEvent' {\n  interface InteractEvent {\n    /** @internal */\n    prevDropzone?: Interactable\n    dropzone?: Interactable\n    dragEnter?: Element\n    dragLeave?: Element\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface ActionDefaults {\n    drop: DropzoneOptions\n  }\n}\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    dynamicDrop?: boolean\n  }\n\n  interface SignalArgs {\n    'actions/drop:start': DropSignalArg\n    'actions/drop:move': DropSignalArg\n    'actions/drop:end': DropSignalArg\n  }\n}\n\ndeclare module '@interactjs/core/types' {\n  interface ActionMap {\n    drop?: typeof drop\n  }\n}\n\ndeclare module '@interactjs/core/InteractStatic' {\n  interface InteractStatic {\n    /**\n     * Returns or sets whether the dimensions of dropzone elements are calculated\n     * on every dragmove or only on dragstart for the default dropChecker\n     *\n     * @param {boolean} [newValue] True to check on each move. False to check only\n     * before start\n     * @return {boolean | interact} The current setting or interact\n     */\n    dynamicDrop: (newValue?: boolean) => boolean | this\n  }\n}\n\ninterface DropSignalArg {\n  interaction: Interaction<'drag'>\n  dragEvent: DragEvent\n}\n\nexport interface ActiveDrop {\n  dropzone: Interactable\n  element: Element\n  rect: Rect\n}\n\nexport interface DropState {\n  cur: {\n    // the dropzone a drag target might be dropped into\n    dropzone: Interactable\n    // the element at the time of checking\n    element: Element\n  }\n  prev: {\n    // the dropzone that was recently dragged away from\n    dropzone: Interactable\n    // the element at the time of checking\n    element: Element\n  }\n  // wheather the potential drop was rejected from a listener\n  rejected: boolean\n  // the drop events related to the current drag event\n  events: FiredDropEvents\n  activeDrops: ActiveDrop[]\n}\n\nfunction install(scope: Scope) {\n  const { actions, interactStatic: interact, Interactable, defaults } = scope\n\n  scope.usePlugin(drag)\n\n  Interactable.prototype.dropzone = function (this: Interactable, options) {\n    return dropzoneMethod(this, options)\n  } as Interactable['dropzone']\n\n  Interactable.prototype.dropCheck = function (\n    this: Interactable,\n    dragEvent,\n    event,\n    draggable,\n    draggableElement,\n    dropElement,\n    rect,\n  ) {\n    return dropCheckMethod(this, dragEvent, event, draggable, draggableElement, dropElement, rect)\n  }\n\n  interact.dynamicDrop = function (newValue?: boolean) {\n    if (is.bool(newValue)) {\n      // if (dragging && scope.dynamicDrop !== newValue && !newValue) {\n      //  calcRects(dropzones)\n      // }\n\n      scope.dynamicDrop = newValue\n\n      return interact\n    }\n    return scope.dynamicDrop!\n  }\n\n  extend(actions.phaselessTypes, {\n    dragenter: true,\n    dragleave: true,\n    dropactivate: true,\n    dropdeactivate: true,\n    dropmove: true,\n    drop: true,\n  })\n  actions.methodDict.drop = 'dropzone'\n\n  scope.dynamicDrop = false\n\n  defaults.actions.drop = drop.defaults\n}\n\nfunction collectDropzones({ interactables }: Scope, draggableElement: Element) {\n  const drops: ActiveDrop[] = []\n\n  // collect all dropzones and their elements which qualify for a drop\n  for (const dropzone of interactables.list) {\n    if (!dropzone.options.drop.enabled) {\n      continue\n    }\n\n    const accept = dropzone.options.drop.accept\n\n    // test the draggable draggableElement against the dropzone's accept setting\n    if (\n      (is.element(accept) && accept !== draggableElement) ||\n      (is.string(accept) && !domUtils.matchesSelector(draggableElement, accept)) ||\n      (is.func(accept) && !accept({ dropzone, draggableElement }))\n    ) {\n      continue\n    }\n\n    for (const dropzoneElement of dropzone.getAllElements()) {\n      if (dropzoneElement !== draggableElement) {\n        drops.push({\n          dropzone,\n          element: dropzoneElement,\n          rect: dropzone.getRect(dropzoneElement),\n        })\n      }\n    }\n  }\n\n  return drops\n}\n\nfunction fireActivationEvents(activeDrops: ActiveDrop[], event: DropEvent) {\n  // loop through all active dropzones and trigger event\n  for (const { dropzone, element } of activeDrops.slice()) {\n    event.dropzone = dropzone\n\n    // set current element as event target\n    event.target = element\n    dropzone.fire(event)\n    event.propagationStopped = event.immediatePropagationStopped = false\n  }\n}\n\n// return a new array of possible drops. getActiveDrops should always be\n// called when a drag has just started or a drag event happens while\n// dynamicDrop is true\nfunction getActiveDrops(scope: Scope, dragElement: Element) {\n  // get dropzones and their elements that could receive the draggable\n  const activeDrops = collectDropzones(scope, dragElement)\n\n  for (const activeDrop of activeDrops) {\n    activeDrop.rect = activeDrop.dropzone.getRect(activeDrop.element)\n  }\n\n  return activeDrops\n}\n\nfunction getDrop(\n  { dropState, interactable: draggable, element: dragElement }: Interaction,\n  dragEvent,\n  pointerEvent,\n) {\n  const validDrops: Element[] = []\n\n  // collect all dropzones and their elements which qualify for a drop\n  for (const { dropzone, element: dropzoneElement, rect } of dropState.activeDrops) {\n    const isValid = dropzone.dropCheck(\n      dragEvent,\n      pointerEvent,\n      draggable!,\n      dragElement!,\n      dropzoneElement,\n      rect,\n    )\n    validDrops.push(isValid ? dropzoneElement : null)\n  }\n\n  // get the most appropriate dropzone based on DOM depth and order\n  const dropIndex = domUtils.indexOfDeepestElement(validDrops)\n\n  return dropState!.activeDrops[dropIndex] || null\n}\n\nfunction getDropEvents(interaction: Interaction, _pointerEvent, dragEvent: DragEvent) {\n  const dropState = interaction.dropState!\n  const dropEvents: Record<string, DropEvent | null> = {\n    enter: null,\n    leave: null,\n    activate: null,\n    deactivate: null,\n    move: null,\n    drop: null,\n  }\n\n  if (dragEvent.type === 'dragstart') {\n    dropEvents.activate = new DropEvent(dropState, dragEvent, 'dropactivate')\n\n    dropEvents.activate.target = null as never\n    dropEvents.activate.dropzone = null as never\n  }\n  if (dragEvent.type === 'dragend') {\n    dropEvents.deactivate = new DropEvent(dropState, dragEvent, 'dropdeactivate')\n\n    dropEvents.deactivate.target = null as never\n    dropEvents.deactivate.dropzone = null as never\n  }\n\n  if (dropState.rejected) {\n    return dropEvents\n  }\n\n  if (dropState.cur.element !== dropState.prev.element) {\n    // if there was a previous dropzone, create a dragleave event\n    if (dropState.prev.dropzone) {\n      dropEvents.leave = new DropEvent(dropState, dragEvent, 'dragleave')\n\n      dragEvent.dragLeave = dropEvents.leave.target = dropState.prev.element\n      dragEvent.prevDropzone = dropEvents.leave.dropzone = dropState.prev.dropzone\n    }\n    // if dropzone is not null, create a dragenter event\n    if (dropState.cur.dropzone) {\n      dropEvents.enter = new DropEvent(dropState, dragEvent, 'dragenter')\n\n      dragEvent.dragEnter = dropState.cur.element\n      dragEvent.dropzone = dropState.cur.dropzone\n    }\n  }\n\n  if (dragEvent.type === 'dragend' && dropState.cur.dropzone) {\n    dropEvents.drop = new DropEvent(dropState, dragEvent, 'drop')\n\n    dragEvent.dropzone = dropState.cur.dropzone\n    dragEvent.relatedTarget = dropState.cur.element\n  }\n  if (dragEvent.type === 'dragmove' && dropState.cur.dropzone) {\n    dropEvents.move = new DropEvent(dropState, dragEvent, 'dropmove')\n\n    dragEvent.dropzone = dropState.cur.dropzone\n  }\n\n  return dropEvents\n}\n\ntype FiredDropEvents = Partial<\n  Record<'leave' | 'enter' | 'move' | 'drop' | 'activate' | 'deactivate', DropEvent>\n>\n\nfunction fireDropEvents(interaction: Interaction, events: FiredDropEvents) {\n  const dropState = interaction.dropState!\n  const { activeDrops, cur, prev } = dropState\n\n  if (events.leave) {\n    prev.dropzone.fire(events.leave)\n  }\n  if (events.enter) {\n    cur.dropzone.fire(events.enter)\n  }\n  if (events.move) {\n    cur.dropzone.fire(events.move)\n  }\n  if (events.drop) {\n    cur.dropzone.fire(events.drop)\n  }\n\n  if (events.deactivate) {\n    fireActivationEvents(activeDrops, events.deactivate)\n  }\n\n  dropState.prev.dropzone = cur.dropzone\n  dropState.prev.element = cur.element\n}\n\nfunction onEventCreated({ interaction, iEvent, event }: DoPhaseArg<'drag', EventPhase>, scope: Scope) {\n  if (iEvent.type !== 'dragmove' && iEvent.type !== 'dragend') {\n    return\n  }\n\n  const dropState = interaction.dropState!\n\n  if (scope.dynamicDrop) {\n    dropState.activeDrops = getActiveDrops(scope, interaction.element!)\n  }\n\n  const dragEvent = iEvent\n  const dropResult = getDrop(interaction, dragEvent, event)\n\n  // update rejected status\n  dropState.rejected =\n    dropState.rejected &&\n    !!dropResult &&\n    dropResult.dropzone === dropState.cur.dropzone &&\n    dropResult.element === dropState.cur.element\n\n  dropState.cur.dropzone = dropResult && dropResult.dropzone\n  dropState.cur.element = dropResult && dropResult.element\n\n  dropState.events = getDropEvents(interaction, event, dragEvent)\n}\n\nfunction dropzoneMethod(interactable: Interactable): DropzoneOptions\nfunction dropzoneMethod(interactable: Interactable, options: DropzoneOptions | boolean): Interactable\nfunction dropzoneMethod(interactable: Interactable, options?: DropzoneOptions | boolean) {\n  if (is.object(options)) {\n    interactable.options.drop.enabled = options.enabled !== false\n\n    if (options.listeners) {\n      const normalized = normalizeListeners(options.listeners)\n      // rename 'drop' to '' as it will be prefixed with 'drop'\n      const corrected = Object.keys(normalized).reduce((acc, type) => {\n        const correctedType = /^(enter|leave)/.test(type)\n          ? `drag${type}`\n          : /^(activate|deactivate|move)/.test(type)\n            ? `drop${type}`\n            : type\n\n        acc[correctedType] = normalized[type]\n\n        return acc\n      }, {})\n\n      const prevListeners = interactable.options.drop.listeners\n      prevListeners && interactable.off(prevListeners)\n\n      interactable.on(corrected)\n      interactable.options.drop.listeners = corrected\n    }\n\n    if (is.func(options.ondrop)) {\n      interactable.on('drop', options.ondrop)\n    }\n    if (is.func(options.ondropactivate)) {\n      interactable.on('dropactivate', options.ondropactivate)\n    }\n    if (is.func(options.ondropdeactivate)) {\n      interactable.on('dropdeactivate', options.ondropdeactivate)\n    }\n    if (is.func(options.ondragenter)) {\n      interactable.on('dragenter', options.ondragenter)\n    }\n    if (is.func(options.ondragleave)) {\n      interactable.on('dragleave', options.ondragleave)\n    }\n    if (is.func(options.ondropmove)) {\n      interactable.on('dropmove', options.ondropmove)\n    }\n\n    if (/^(pointer|center)$/.test(options.overlap as string)) {\n      interactable.options.drop.overlap = options.overlap\n    } else if (is.number(options.overlap)) {\n      interactable.options.drop.overlap = Math.max(Math.min(1, options.overlap), 0)\n    }\n    if ('accept' in options) {\n      interactable.options.drop.accept = options.accept\n    }\n    if ('checker' in options) {\n      interactable.options.drop.checker = options.checker\n    }\n\n    return interactable\n  }\n\n  if (is.bool(options)) {\n    interactable.options.drop.enabled = options\n\n    return interactable\n  }\n\n  return interactable.options.drop\n}\n\nfunction dropCheckMethod(\n  interactable: Interactable,\n  dragEvent: InteractEvent,\n  event: PointerEventType,\n  draggable: Interactable,\n  draggableElement: Element,\n  dropElement: Element,\n  rect: any,\n) {\n  let dropped = false\n\n  // if the dropzone has no rect (eg. display: none)\n  // call the custom dropChecker or just return false\n  if (!(rect = rect || interactable.getRect(dropElement))) {\n    return interactable.options.drop.checker\n      ? interactable.options.drop.checker(\n          dragEvent,\n          event,\n          dropped,\n          interactable,\n          dropElement,\n          draggable,\n          draggableElement,\n        )\n      : false\n  }\n\n  const dropOverlap = interactable.options.drop.overlap\n\n  if (dropOverlap === 'pointer') {\n    const origin = getOriginXY(draggable, draggableElement, 'drag')\n    const page = pointerUtils.getPageXY(dragEvent)\n\n    page.x += origin.x\n    page.y += origin.y\n\n    const horizontal = page.x > rect.left && page.x < rect.right\n    const vertical = page.y > rect.top && page.y < rect.bottom\n\n    dropped = horizontal && vertical\n  }\n\n  const dragRect = draggable.getRect(draggableElement)\n\n  if (dragRect && dropOverlap === 'center') {\n    const cx = dragRect.left + dragRect.width / 2\n    const cy = dragRect.top + dragRect.height / 2\n\n    dropped = cx >= rect.left && cx <= rect.right && cy >= rect.top && cy <= rect.bottom\n  }\n\n  if (dragRect && is.number(dropOverlap)) {\n    const overlapArea =\n      Math.max(0, Math.min(rect.right, dragRect.right) - Math.max(rect.left, dragRect.left)) *\n      Math.max(0, Math.min(rect.bottom, dragRect.bottom) - Math.max(rect.top, dragRect.top))\n\n    const overlapRatio = overlapArea / (dragRect.width * dragRect.height)\n\n    dropped = overlapRatio >= dropOverlap\n  }\n\n  if (interactable.options.drop.checker) {\n    dropped = interactable.options.drop.checker(\n      dragEvent,\n      event,\n      dropped,\n      interactable,\n      dropElement,\n      draggable,\n      draggableElement,\n    )\n  }\n\n  return dropped\n}\n\nconst drop: Plugin = {\n  id: 'actions/drop',\n  install,\n  listeners: {\n    'interactions:before-action-start': ({ interaction }) => {\n      if (interaction.prepared.name !== 'drag') {\n        return\n      }\n\n      interaction.dropState = {\n        cur: {\n          dropzone: null,\n          element: null,\n        },\n        prev: {\n          dropzone: null,\n          element: null,\n        },\n        rejected: null,\n        events: null,\n        activeDrops: [],\n      }\n    },\n\n    'interactions:after-action-start': (\n      { interaction, event, iEvent: dragEvent }: DoPhaseArg<'drag', EventPhase>,\n      scope,\n    ) => {\n      if (interaction.prepared.name !== 'drag') {\n        return\n      }\n\n      const dropState = interaction.dropState!\n\n      // reset active dropzones\n      dropState.activeDrops = []\n      dropState.events = {}\n      dropState.activeDrops = getActiveDrops(scope, interaction.element!)\n      dropState.events = getDropEvents(interaction, event, dragEvent)\n\n      if (dropState.events.activate) {\n        fireActivationEvents(dropState.activeDrops, dropState.events.activate)\n        scope.fire('actions/drop:start', { interaction, dragEvent })\n      }\n    },\n\n    'interactions:action-move': onEventCreated,\n\n    'interactions:after-action-move': (\n      { interaction, iEvent: dragEvent }: DoPhaseArg<'drag', EventPhase>,\n      scope,\n    ) => {\n      if (interaction.prepared.name !== 'drag') {\n        return\n      }\n\n      const dropState = interaction.dropState!\n      fireDropEvents(interaction, dropState.events)\n\n      scope.fire('actions/drop:move', { interaction, dragEvent })\n      dropState.events = {}\n    },\n\n    'interactions:action-end': (arg: DoPhaseArg<'drag', EventPhase>, scope) => {\n      if (arg.interaction.prepared.name !== 'drag') {\n        return\n      }\n\n      const { interaction, iEvent: dragEvent } = arg\n\n      onEventCreated(arg, scope)\n      fireDropEvents(interaction, interaction.dropState!.events)\n      scope.fire('actions/drop:end', { interaction, dragEvent })\n    },\n\n    'interactions:stop': ({ interaction }) => {\n      if (interaction.prepared.name !== 'drag') {\n        return\n      }\n\n      const { dropState } = interaction\n\n      if (dropState) {\n        dropState.activeDrops = null as never\n        dropState.events = null as never\n        dropState.cur.dropzone = null as never\n        dropState.cur.element = null as never\n        dropState.prev.dropzone = null as never\n        dropState.prev.element = null as never\n        dropState.rejected = false\n      }\n    },\n  },\n  getActiveDrops,\n  getDrop,\n  getDropEvents,\n  fireDropEvents,\n\n  filterEventType: (type: string) => type.search('drag') === 0 || type.search('drop') === 0,\n\n  defaults: {\n    enabled: false,\n    accept: null as never,\n    overlap: 'pointer',\n  } as DropzoneOptions,\n}\n\nexport default drop\n"
  },
  {
    "path": "packages/@interactjs/actions/gesture/gesture.spec.ts",
    "content": "import type { Scope } from '@interactjs/core/scope'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport extend from '@interactjs/utils/extend'\nimport { coordsToEvent, newCoords } from '@interactjs/utils/pointerUtils'\n\nimport type { GestureEvent } from './plugin'\nimport gesture from './plugin'\n\nfunction getGestureProps(event: GestureEvent) {\n  return helpers.getProps(event, ['type', 'angle', 'distance', 'scale', 'ds', 'da'])\n}\n\ndescribe('actions/gesture', () => {\n  test('action init', () => {\n    const scope: Scope = helpers.mockScope()\n\n    scope.usePlugin(gesture)\n\n    expect(scope.actions.map.gesture).toBeTruthy()\n    expect(scope.actions.methodDict.gesture).toBe('gesturable')\n    expect(scope.Interactable.prototype.gesturable).toBeInstanceOf(Function)\n  })\n\n  test('interactable.gesturable() method', () => {\n    const rect = Object.freeze({ top: 100, left: 200, bottom: 300, right: 400 })\n    const {\n      scope,\n      interaction,\n      interactable,\n      target: element,\n      coords,\n      down,\n      start,\n      move,\n    } = helpers.testEnv({\n      plugins: [gesture],\n      rect,\n    })\n    const events: GestureEvent[] = []\n    const event2 = coordsToEvent(newCoords())\n    event2.coords.pointerId = 2\n\n    scope.usePlugin(gesture)\n\n    interactable.rectChecker(() => ({ ...rect }))\n    interactable.gesturable(true)\n    interactable.on('gesturestart gesturemove gestureend', (event: GestureEvent) => {\n      events.push(event)\n    })\n    interaction.pointerType = 'touch'\n\n    // 0 ➡ 1\n    extend(coords.page, { x: 0, y: 0 })\n    extend(event2.coords.page, { x: 100, y: 0 })\n\n    const checkArg = {\n      action: null,\n      interactable,\n      interaction,\n      element,\n      rect,\n      buttons: 0,\n    }\n\n    down()\n\n    scope.fire('auto-start:check', checkArg)\n    // not allowed with 1 pointer\n    expect(checkArg.action).toBeFalsy()\n\n    interaction.pointerDown(event2, event2, element)\n    scope.fire('auto-start:check', checkArg)\n    // allowed with 2 pointers\n    expect(checkArg.action).toBeTruthy()\n\n    start({ name: 'gesture' })\n\n    // start interaction properties are correct,\n    expect(interaction.gesture).toEqual({\n      angle: 0,\n      distance: 100,\n      scale: 1,\n      startAngle: 0,\n      startDistance: 100,\n    })\n\n    // start event properties are correct,\n    expect(getGestureProps(events[0])).toEqual({\n      type: 'gesturestart',\n      angle: 0,\n      distance: 100,\n      scale: 1,\n      ds: 0,\n      da: 0,\n    })\n\n    // 0\n    // ⬇\n    // 1\n    extend(event2.coords.page, { x: 0, y: 50 })\n    interaction.pointerMove(event2, event2, element)\n\n    // move interaction properties are correct,\n    expect(interaction.gesture).toEqual({\n      angle: 90,\n      distance: 50,\n      scale: 0.5,\n      startAngle: 0,\n      startDistance: 100,\n    })\n\n    // move event properties are correct,\n    expect(getGestureProps(events[1])).toEqual({\n      type: 'gesturemove',\n      angle: 90,\n      distance: 50,\n      scale: 0.5,\n      ds: -0.5,\n      da: 90,\n    })\n\n    // 1 ⬅ 0\n    extend(coords.page, { x: 50, y: 50 })\n    move()\n\n    // move interaction properties are correct,\n    expect(interaction.gesture).toEqual({\n      angle: 180,\n      distance: 50,\n      scale: 0.5,\n      startAngle: 0,\n      startDistance: 100,\n    })\n\n    // move event properties are correct,\n    expect(getGestureProps(events[2])).toEqual({\n      type: 'gesturemove',\n      angle: 180,\n      distance: 50,\n      scale: 0.5,\n      ds: 0,\n      da: 90,\n    })\n\n    interaction.pointerUp(event2, event2, element, element)\n\n    // move interaction properties are correct,\n    expect(interaction.gesture).toEqual({\n      angle: 180,\n      distance: 50,\n      scale: 0.5,\n      startAngle: 0,\n      startDistance: 100,\n    })\n\n    // end event properties are correct,\n    expect(getGestureProps(events[3])).toEqual({\n      type: 'gestureend',\n      angle: 180,\n      distance: 50,\n      scale: 0.5,\n      ds: 0,\n      da: 0,\n    })\n\n    // 0\n    // ⬇\n    // 1\n    interaction.pointerDown(event2, event2, element)\n    extend(coords.page, { x: 0, y: -150 })\n    checkArg.action = null\n    scope.fire('auto-start:check', checkArg)\n    interaction.pointerMove(event2, event2, element)\n\n    // not allowed with re-added second pointers\n    expect(checkArg.action).toBeTruthy()\n\n    interaction.start({ name: 'gesture' }, interactable, element)\n\n    // move interaction properties are correct,\n    expect(interaction.gesture).toEqual({\n      angle: 90,\n      distance: 200,\n      scale: 1,\n      startAngle: 90,\n      startDistance: 200,\n    })\n\n    // second start event properties are correct,\n    expect(getGestureProps(events[4])).toEqual({\n      type: 'gesturestart',\n      angle: 90,\n      distance: 200,\n      scale: 1,\n      ds: 0,\n      da: 0,\n    })\n\n    // correct number of events fired\n    expect(events).toHaveLength(5)\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/actions/gesture/plugin.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { InteractEvent, EventPhase } from '@interactjs/core/InteractEvent'\nimport type { Interaction, DoPhaseArg } from '@interactjs/core/Interaction'\nimport type { PerActionDefaults } from '@interactjs/core/options'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Rect, PointerType, ListenersArg, OrBoolean } from '@interactjs/core/types'\nimport is from '@interactjs/utils/is'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    gesture?: {\n      angle: number // angle from first to second touch\n      distance: number\n      scale: number // gesture.distance / gesture.startDistance\n      startAngle: number // angle of line joining two touches\n      startDistance: number // distance between two touches of touchStart\n    }\n  }\n}\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    gesturable(options: Partial<OrBoolean<GesturableOptions>> | boolean): this\n    gesturable(): GesturableOptions\n    /**\n     * ```js\n     * interact(element).gesturable({\n     *     onstart: function (event) {},\n     *     onmove : function (event) {},\n     *     onend  : function (event) {},\n     *\n     *     // limit multiple gestures.\n     *     // See the explanation in {@link Interactable.draggable} example\n     *     max: Infinity,\n     *     maxPerElement: 1,\n     * })\n     *\n     * var isGestureable = interact(element).gesturable()\n     * ```\n     *\n     * Gets or sets whether multitouch gestures can be performed on the target\n     *\n     * @param options - true/false or An object with event listeners to be fired on gesture events (makes the Interactable gesturable)\n     * @returns A boolean indicating if this can be the target of gesture events, or this Interactable\n     */\n    gesturable(options?: Partial<OrBoolean<GesturableOptions>> | boolean): this | GesturableOptions\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface ActionDefaults {\n    gesture: GesturableOptions\n  }\n}\n\ndeclare module '@interactjs/core/types' {\n  interface ActionMap {\n    gesture?: typeof gesture\n  }\n}\n\nexport interface GesturableOptions extends PerActionDefaults {\n  onstart?: ListenersArg\n  onmove?: ListenersArg\n  onend?: ListenersArg\n}\n\nexport interface GestureEvent extends InteractEvent<'gesture'> {\n  distance: number\n  angle: number\n  da: number // angle change\n  scale: number // ratio of distance start to current event\n  ds: number // scale change\n  box: Rect // enclosing box of all points\n  touches: PointerType[]\n}\n\nexport interface GestureSignalArg extends DoPhaseArg<'gesture', EventPhase> {\n  iEvent: GestureEvent\n  interaction: Interaction<'gesture'>\n}\n\nfunction install(scope: Scope) {\n  const { actions, Interactable, defaults } = scope\n\n  Interactable.prototype.gesturable = function (\n    this: InstanceType<typeof Interactable>,\n    options: GesturableOptions | boolean,\n  ) {\n    if (is.object(options)) {\n      this.options.gesture.enabled = options.enabled !== false\n      this.setPerAction('gesture', options)\n      this.setOnEvents('gesture', options)\n\n      return this\n    }\n\n    if (is.bool(options)) {\n      this.options.gesture.enabled = options\n\n      return this\n    }\n\n    return this.options.gesture as GesturableOptions\n  } as Interactable['gesturable']\n\n  actions.map.gesture = gesture\n  actions.methodDict.gesture = 'gesturable'\n\n  defaults.actions.gesture = gesture.defaults\n}\n\nfunction updateGestureProps({ interaction, iEvent, phase }: GestureSignalArg) {\n  if (interaction.prepared.name !== 'gesture') return\n\n  const pointers = interaction.pointers.map((p) => p.pointer)\n  const starting = phase === 'start'\n  const ending = phase === 'end'\n  const deltaSource = interaction.interactable.options.deltaSource\n\n  iEvent.touches = [pointers[0], pointers[1]]\n\n  if (starting) {\n    iEvent.distance = pointerUtils.touchDistance(pointers, deltaSource)\n    iEvent.box = pointerUtils.touchBBox(pointers)\n    iEvent.scale = 1\n    iEvent.ds = 0\n    iEvent.angle = pointerUtils.touchAngle(pointers, deltaSource)\n    iEvent.da = 0\n\n    interaction.gesture.startDistance = iEvent.distance\n    interaction.gesture.startAngle = iEvent.angle\n  } else if (ending || interaction.pointers.length < 2) {\n    const prevEvent = interaction.prevEvent as GestureEvent\n\n    iEvent.distance = prevEvent.distance\n    iEvent.box = prevEvent.box\n    iEvent.scale = prevEvent.scale\n    iEvent.ds = 0\n    iEvent.angle = prevEvent.angle\n    iEvent.da = 0\n  } else {\n    iEvent.distance = pointerUtils.touchDistance(pointers, deltaSource)\n    iEvent.box = pointerUtils.touchBBox(pointers)\n    iEvent.scale = iEvent.distance / interaction.gesture.startDistance\n    iEvent.angle = pointerUtils.touchAngle(pointers, deltaSource)\n\n    iEvent.ds = iEvent.scale - interaction.gesture.scale\n    iEvent.da = iEvent.angle - interaction.gesture.angle\n  }\n\n  interaction.gesture.distance = iEvent.distance\n  interaction.gesture.angle = iEvent.angle\n\n  if (is.number(iEvent.scale) && iEvent.scale !== Infinity && !isNaN(iEvent.scale)) {\n    interaction.gesture.scale = iEvent.scale\n  }\n}\n\nconst gesture: Plugin = {\n  id: 'actions/gesture',\n  before: ['actions/drag', 'actions/resize'],\n  install,\n  listeners: {\n    'interactions:action-start': updateGestureProps,\n    'interactions:action-move': updateGestureProps,\n    'interactions:action-end': updateGestureProps,\n\n    'interactions:new': ({ interaction }) => {\n      interaction.gesture = {\n        angle: 0,\n        distance: 0,\n        scale: 1,\n        startAngle: 0,\n        startDistance: 0,\n      }\n    },\n\n    'auto-start:check': (arg) => {\n      if (arg.interaction.pointers.length < 2) {\n        return undefined\n      }\n\n      const gestureOptions = arg.interactable.options.gesture\n\n      if (!(gestureOptions && gestureOptions.enabled)) {\n        return undefined\n      }\n\n      arg.action = { name: 'gesture' }\n\n      return false\n    },\n  },\n\n  defaults: {},\n\n  getCursor() {\n    return ''\n  },\n\n  filterEventType: (type: string) => type.search('gesture') === 0,\n}\n\nexport default gesture\n"
  },
  {
    "path": "packages/@interactjs/actions/package.json",
    "content": "{\n  \"name\": \"@interactjs/actions\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/actions\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/actions/plugin.ts",
    "content": "import type { Scope } from '@interactjs/core/scope'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './drag/plugin'\nimport './drop/plugin'\nimport './gesture/plugin'\nimport './resize/plugin'\n\nimport drag from './drag/plugin'\nimport drop from './drop/plugin'\nimport gesture from './gesture/plugin'\nimport resize from './resize/plugin'\n/* eslint-enable import/no-duplicates */\n\nexport default {\n  id: 'actions',\n  install(scope: Scope) {\n    scope.usePlugin(gesture)\n    scope.usePlugin(resize)\n    scope.usePlugin(drag)\n    scope.usePlugin(drop)\n  },\n}\n"
  },
  {
    "path": "packages/@interactjs/actions/resize/plugin.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { EventPhase, InteractEvent } from '@interactjs/core/InteractEvent'\nimport type { Interaction } from '@interactjs/core/Interaction'\nimport type { PerActionDefaults } from '@interactjs/core/options'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type {\n  ActionName,\n  ActionProps,\n  EdgeOptions,\n  FullRect,\n  ListenersArg,\n  OrBoolean,\n  Point,\n  Rect,\n} from '@interactjs/core/types'\nimport * as dom from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\n\nexport type EdgeName = 'top' | 'left' | 'bottom' | 'right'\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    resizable(): ResizableOptions\n    resizable(options: Partial<OrBoolean<ResizableOptions>> | boolean): this\n    /**\n     * ```js\n     * interact(element).resizable({\n     *   onstart: function (event) {},\n     *   onmove : function (event) {},\n     *   onend  : function (event) {},\n     *\n     *   edges: {\n     *     top   : true,       // Use pointer coords to check for resize.\n     *     left  : false,      // Disable resizing from left edge.\n     *     bottom: '.resize-s',// Resize if pointer target matches selector\n     *     right : handleEl    // Resize if pointer target is the given Element\n     *   },\n     *\n     *   // Width and height can be adjusted independently. When `true`, width and\n     *   // height are adjusted at a 1:1 ratio.\n     *   square: false,\n     *\n     *   // Width and height can be adjusted independently. When `true`, width and\n     *   // height maintain the aspect ratio they had when resizing started.\n     *   preserveAspectRatio: false,\n     *\n     *   // a value of 'none' will limit the resize rect to a minimum of 0x0\n     *   // 'negate' will allow the rect to have negative width/height\n     *   // 'reposition' will keep the width/height positive by swapping\n     *   // the top and bottom edges and/or swapping the left and right edges\n     *   invert: 'none' || 'negate' || 'reposition'\n     *\n     *   // limit multiple resizes.\n     *   // See the explanation in the {@link Interactable.draggable} example\n     *   max: Infinity,\n     *   maxPerElement: 1,\n     * })\n     *\n     * var isResizeable = interact(element).resizable()\n     * ```\n     *\n     * Gets or sets whether resize actions can be performed on the target\n     *\n     * @param options - true/false or An object with event\n     * listeners to be fired on resize events (object makes the Interactable\n     * resizable)\n     * @returns A boolean indicating if this can be the\n     * target of resize elements, or this Interactable\n     */\n    resizable(options?: Partial<OrBoolean<ResizableOptions>> | boolean): this | ResizableOptions\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction<T extends ActionName | null = ActionName> {\n    resizeAxes: 'x' | 'y' | 'xy'\n    styleCursor(newValue: boolean): this\n    styleCursor(): boolean\n    resizeStartAspectRatio: number\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface ActionDefaults {\n    resize: ResizableOptions\n  }\n}\n\ndeclare module '@interactjs/core/types' {\n  interface ActionMap {\n    resize?: typeof resize\n  }\n}\n\nexport interface ResizableOptions extends PerActionDefaults {\n  square?: boolean\n  preserveAspectRatio?: boolean\n  edges?: EdgeOptions | null\n  axis?: 'x' | 'y' | 'xy' // deprecated\n  invert?: 'none' | 'negate' | 'reposition'\n  margin?: number\n  squareResize?: boolean\n  oninertiastart?: ListenersArg\n  onstart?: ListenersArg\n  onmove?: ListenersArg\n  onend?: ListenersArg\n}\n\nexport interface ResizeEvent<P extends EventPhase = EventPhase> extends InteractEvent<'resize', P> {\n  deltaRect?: FullRect\n  edges?: ActionProps['edges']\n}\n\nfunction install(scope: Scope) {\n  const {\n    actions,\n    browser,\n    Interactable, // tslint:disable-line no-shadowed-variable\n    defaults,\n  } = scope\n\n  // Less Precision with touch input\n\n  resize.cursors = initCursors(browser)\n  resize.defaultMargin = browser.supportsTouch || browser.supportsPointerEvent ? 20 : 10\n\n  Interactable.prototype.resizable = function (this: Interactable, options: ResizableOptions | boolean) {\n    return resizable(this, options, scope)\n  } as Interactable['resizable']\n\n  actions.map.resize = resize\n  actions.methodDict.resize = 'resizable'\n\n  defaults.actions.resize = resize.defaults\n}\n\nfunction resizeChecker(arg) {\n  const { interaction, interactable, element, rect, buttons } = arg\n\n  if (!rect) {\n    return undefined\n  }\n\n  const page = extend({}, interaction.coords.cur.page)\n  const resizeOptions = interactable.options.resize\n\n  if (\n    !(resizeOptions && resizeOptions.enabled) ||\n    // check mouseButton setting if the pointer is down\n    (interaction.pointerIsDown &&\n      /mouse|pointer/.test(interaction.pointerType) &&\n      (buttons & resizeOptions.mouseButtons) === 0)\n  ) {\n    return undefined\n  }\n\n  // if using resize.edges\n  if (is.object(resizeOptions.edges)) {\n    const resizeEdges = {\n      left: false,\n      right: false,\n      top: false,\n      bottom: false,\n    }\n\n    for (const edge in resizeEdges) {\n      resizeEdges[edge] = checkResizeEdge(\n        edge,\n        resizeOptions.edges[edge],\n        page,\n        interaction._latestPointer.eventTarget,\n        element,\n        rect,\n        resizeOptions.margin || resize.defaultMargin,\n      )\n    }\n\n    resizeEdges.left = resizeEdges.left && !resizeEdges.right\n    resizeEdges.top = resizeEdges.top && !resizeEdges.bottom\n\n    if (resizeEdges.left || resizeEdges.right || resizeEdges.top || resizeEdges.bottom) {\n      arg.action = {\n        name: 'resize',\n        edges: resizeEdges,\n      }\n    }\n  } else {\n    const right = resizeOptions.axis !== 'y' && page.x > rect.right - resize.defaultMargin\n    const bottom = resizeOptions.axis !== 'x' && page.y > rect.bottom - resize.defaultMargin\n\n    if (right || bottom) {\n      arg.action = {\n        name: 'resize',\n        axes: (right ? 'x' : '') + (bottom ? 'y' : ''),\n      }\n    }\n  }\n\n  return arg.action ? false : undefined\n}\n\nfunction resizable(interactable: Interactable, options: OrBoolean<ResizableOptions> | boolean, scope: Scope) {\n  if (is.object(options)) {\n    interactable.options.resize.enabled = options.enabled !== false\n    interactable.setPerAction('resize', options)\n    interactable.setOnEvents('resize', options)\n\n    if (is.string(options.axis) && /^x$|^y$|^xy$/.test(options.axis)) {\n      interactable.options.resize.axis = options.axis\n    } else if (options.axis === null) {\n      interactable.options.resize.axis = scope.defaults.actions.resize.axis\n    }\n\n    if (is.bool(options.preserveAspectRatio)) {\n      interactable.options.resize.preserveAspectRatio = options.preserveAspectRatio\n    } else if (is.bool(options.square)) {\n      interactable.options.resize.square = options.square\n    }\n\n    return interactable\n  }\n  if (is.bool(options)) {\n    interactable.options.resize.enabled = options\n\n    return interactable\n  }\n  return interactable.options.resize\n}\n\nfunction checkResizeEdge(\n  name: string,\n  value: any,\n  page: Point,\n  element: Node,\n  interactableElement: Element,\n  rect: Rect,\n  margin: number,\n) {\n  // false, '', undefined, null\n  if (!value) {\n    return false\n  }\n\n  // true value, use pointer coords and element rect\n  if (value === true) {\n    // if dimensions are negative, \"switch\" edges\n    const width = is.number(rect.width) ? rect.width : rect.right - rect.left\n    const height = is.number(rect.height) ? rect.height : rect.bottom - rect.top\n\n    // don't use margin greater than half the relevent dimension\n    margin = Math.min(margin, Math.abs((name === 'left' || name === 'right' ? width : height) / 2))\n\n    if (width < 0) {\n      if (name === 'left') {\n        name = 'right'\n      } else if (name === 'right') {\n        name = 'left'\n      }\n    }\n    if (height < 0) {\n      if (name === 'top') {\n        name = 'bottom'\n      } else if (name === 'bottom') {\n        name = 'top'\n      }\n    }\n\n    if (name === 'left') {\n      const edge = width >= 0 ? rect.left : rect.right\n      return page.x < edge + margin\n    }\n    if (name === 'top') {\n      const edge = height >= 0 ? rect.top : rect.bottom\n      return page.y < edge + margin\n    }\n\n    if (name === 'right') {\n      return page.x > (width >= 0 ? rect.right : rect.left) - margin\n    }\n    if (name === 'bottom') {\n      return page.y > (height >= 0 ? rect.bottom : rect.top) - margin\n    }\n  }\n\n  // the remaining checks require an element\n  if (!is.element(element)) {\n    return false\n  }\n\n  return is.element(value)\n    ? // the value is an element to use as a resize handle\n      value === element\n    : // otherwise check if element matches value as selector\n      dom.matchesUpTo(element, value, interactableElement)\n}\n\n/* eslint-disable multiline-ternary */\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\nfunction initCursors(browser: typeof import('@interactjs/utils/browser').default) {\n  return browser.isIe9\n    ? {\n        x: 'e-resize',\n        y: 's-resize',\n        xy: 'se-resize',\n\n        top: 'n-resize',\n        left: 'w-resize',\n        bottom: 's-resize',\n        right: 'e-resize',\n        topleft: 'se-resize',\n        bottomright: 'se-resize',\n        topright: 'ne-resize',\n        bottomleft: 'ne-resize',\n      }\n    : {\n        x: 'ew-resize',\n        y: 'ns-resize',\n        xy: 'nwse-resize',\n\n        top: 'ns-resize',\n        left: 'ew-resize',\n        bottom: 'ns-resize',\n        right: 'ew-resize',\n        topleft: 'nwse-resize',\n        bottomright: 'nwse-resize',\n        topright: 'nesw-resize',\n        bottomleft: 'nesw-resize',\n      }\n}\n/* eslint-enable multiline-ternary */\n\nfunction start({ iEvent, interaction }: { iEvent: InteractEvent<any, any>; interaction: Interaction }) {\n  if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) {\n    return\n  }\n\n  const resizeEvent = iEvent as ResizeEvent\n  const rect = interaction.rect\n\n  interaction._rects = {\n    start: extend({}, rect),\n    corrected: extend({}, rect),\n    previous: extend({}, rect),\n    delta: {\n      left: 0,\n      right: 0,\n      width: 0,\n      top: 0,\n      bottom: 0,\n      height: 0,\n    },\n  }\n\n  resizeEvent.edges = interaction.prepared.edges\n  resizeEvent.rect = interaction._rects.corrected\n  resizeEvent.deltaRect = interaction._rects.delta\n}\n\nfunction move({ iEvent, interaction }: { iEvent: InteractEvent<any, any>; interaction: Interaction }) {\n  if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) return\n\n  const resizeEvent = iEvent as ResizeEvent\n  const resizeOptions = interaction.interactable.options.resize\n  const invert = resizeOptions.invert\n  const invertible = invert === 'reposition' || invert === 'negate'\n\n  const current = interaction.rect\n  const { start: startRect, corrected, delta: deltaRect, previous } = interaction._rects\n\n  extend(previous, corrected)\n\n  if (invertible) {\n    // if invertible, copy the current rect\n    extend(corrected, current)\n\n    if (invert === 'reposition') {\n      // swap edge values if necessary to keep width/height positive\n      if (corrected.top > corrected.bottom) {\n        const swap = corrected.top\n\n        corrected.top = corrected.bottom\n        corrected.bottom = swap\n      }\n      if (corrected.left > corrected.right) {\n        const swap = corrected.left\n\n        corrected.left = corrected.right\n        corrected.right = swap\n      }\n    }\n  } else {\n    // if not invertible, restrict to minimum of 0x0 rect\n    corrected.top = Math.min(current.top, startRect.bottom)\n    corrected.bottom = Math.max(current.bottom, startRect.top)\n    corrected.left = Math.min(current.left, startRect.right)\n    corrected.right = Math.max(current.right, startRect.left)\n  }\n\n  corrected.width = corrected.right - corrected.left\n  corrected.height = corrected.bottom - corrected.top\n\n  for (const edge in corrected) {\n    deltaRect[edge] = corrected[edge] - previous[edge]\n  }\n\n  resizeEvent.edges = interaction.prepared.edges\n  resizeEvent.rect = corrected\n  resizeEvent.deltaRect = deltaRect\n}\n\nfunction end({ iEvent, interaction }: { iEvent: InteractEvent<any, any>; interaction: Interaction }) {\n  if (interaction.prepared.name !== 'resize' || !interaction.prepared.edges) return\n\n  const resizeEvent = iEvent as ResizeEvent\n\n  resizeEvent.edges = interaction.prepared.edges\n  resizeEvent.rect = interaction._rects.corrected\n  resizeEvent.deltaRect = interaction._rects.delta\n}\n\nfunction updateEventAxes({\n  iEvent,\n  interaction,\n}: {\n  iEvent: InteractEvent<any, any>\n  interaction: Interaction\n}) {\n  if (interaction.prepared.name !== 'resize' || !interaction.resizeAxes) return\n\n  const options = interaction.interactable.options\n  const resizeEvent = iEvent as ResizeEvent\n\n  if (options.resize.square) {\n    if (interaction.resizeAxes === 'y') {\n      resizeEvent.delta.x = resizeEvent.delta.y\n    } else {\n      resizeEvent.delta.y = resizeEvent.delta.x\n    }\n    resizeEvent.axes = 'xy'\n  } else {\n    resizeEvent.axes = interaction.resizeAxes\n\n    if (interaction.resizeAxes === 'x') {\n      resizeEvent.delta.y = 0\n    } else if (interaction.resizeAxes === 'y') {\n      resizeEvent.delta.x = 0\n    }\n  }\n}\n\nconst resize: Plugin = {\n  id: 'actions/resize',\n  before: ['actions/drag'],\n  install,\n  listeners: {\n    'interactions:new': ({ interaction }) => {\n      interaction.resizeAxes = 'xy'\n    },\n\n    'interactions:action-start': (arg) => {\n      start(arg)\n      updateEventAxes(arg)\n    },\n    'interactions:action-move': (arg) => {\n      move(arg)\n      updateEventAxes(arg)\n    },\n    'interactions:action-end': end,\n    'auto-start:check': resizeChecker,\n  },\n\n  defaults: {\n    square: false,\n    preserveAspectRatio: false,\n    axis: 'xy',\n\n    // use default margin\n    margin: NaN,\n\n    // object with props left, right, top, bottom which are\n    // true/false values to resize when the pointer is over that edge,\n    // CSS selectors to match the handles for each direction\n    // or the Elements for each handle\n    edges: null,\n\n    // a value of 'none' will limit the resize rect to a minimum of 0x0\n    // 'negate' will alow the rect to have negative width/height\n    // 'reposition' will keep the width/height positive by swapping\n    // the top and bottom edges and/or swapping the left and right edges\n    invert: 'none',\n  } as ResizableOptions,\n\n  cursors: null as ReturnType<typeof initCursors>,\n\n  getCursor({ edges, axis, name }: ActionProps) {\n    const cursors = resize.cursors\n    let result: string = null\n\n    if (axis) {\n      result = cursors[name + axis]\n    } else if (edges) {\n      let cursorKey = ''\n\n      for (const edge of ['top', 'bottom', 'left', 'right']) {\n        if (edges[edge]) {\n          cursorKey += edge\n        }\n      }\n\n      result = cursors[cursorKey]\n    }\n\n    return result\n  },\n\n  filterEventType: (type: string) => type.search('resize') === 0,\n\n  defaultMargin: null as number,\n}\n\nexport default resize\n"
  },
  {
    "path": "packages/@interactjs/actions/resize/resize.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\n\nimport type { ResizeEvent } from './plugin'\nimport resize from './plugin'\n\nconst { ltrbwh } = helpers\n\ndescribe('actions/resize', () => {\n  test('action init', () => {\n    const { scope } = helpers.testEnv({\n      plugins: [resize],\n    })\n\n    expect(scope.actions.map.resize).toBeTruthy()\n    expect(scope.actions.methodDict.resize).toBe('resizable')\n    expect(scope.Interactable.prototype.resizable).toEqual(expect.any(Function))\n  })\n\n  test('checker', () => {\n    const rect = Object.freeze({ left: 0, top: 0, right: 10, bottom: 10, width: 10, height: 10 })\n    const { scope, interactable, interaction, coords, target, down, start, move } = helpers.testEnv({\n      plugins: [resize],\n      rect,\n    })\n\n    const element = target as HTMLElement\n    const checkArg = {\n      action: null,\n      interactable,\n      interaction,\n      element,\n      rect,\n      buttons: 0,\n    }\n\n    interactable.resizable({\n      edges: { left: true, top: true, right: true, bottom: true },\n      // use margin greater than width and height\n      margin: Infinity,\n    })\n\n    // resize top left\n    down()\n    scope.fire('auto-start:check', checkArg)\n    expect(checkArg.action).toEqual({\n      name: 'resize',\n      edges: { left: true, top: true, right: false, bottom: false },\n    })\n\n    // resize top right\n    coords.page.x = 10\n    move()\n\n    scope.fire('auto-start:check', checkArg)\n    expect(checkArg.action).toEqual({\n      name: 'resize',\n      edges: { left: false, top: true, right: true, bottom: false },\n    })\n\n    // resize bottom right\n    coords.page.y = 10\n    move()\n\n    scope.fire('auto-start:check', checkArg)\n    expect(checkArg.action).toEqual({\n      name: 'resize',\n      edges: { left: false, top: false, right: true, bottom: true },\n    })\n\n    const zeroRect = { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 }\n    let resizeEvent: ResizeEvent = null\n\n    interactable.on('resizestart resizemove resizeend', (e) => {\n      resizeEvent = e\n    })\n\n    coords.page.x = rect.right\n    coords.page.y = rect.bottom\n    down()\n    start({ name: 'resize', edges: { bottom: true, right: true } })\n\n    // sets starting correct interaction._rects\n    expect(interaction._rects).toEqual({\n      start: rect,\n      corrected: rect,\n      previous: rect,\n      delta: zeroRect,\n    })\n    // sets starting correct interaction.rect\n    expect(interaction.rect).toEqual(rect)\n    // resizestart event has extra resize props\n    expect(hasResizeProps(resizeEvent)).toBe(true)\n\n    coords.page.x = -100\n    coords.page.y = -200\n    resizeEvent = null\n    move()\n\n    // `invert: 'none'` interaction._rects are correct\n    expect(interaction._rects).toEqual({\n      start: rect,\n      corrected: zeroRect,\n      previous: rect,\n      delta: ltrbwh(0, 0, -rect.width, -rect.bottom, -rect.width, -rect.height),\n    })\n    // `invert: 'none'` interaction.rect is correct\n    expect(interaction.rect).toEqual(ltrbwh(0, 0, -100, -200, -100, -200))\n    // resizemove event has extra resize props\n    expect(hasResizeProps(resizeEvent)).toBe(true)\n\n    interactable.options.resize.invert = 'reposition'\n    interaction.move()\n\n    // `invert: 'reposition'` interaction._rects\n    expect(interaction._rects).toEqual({\n      start: rect,\n      corrected: ltrbwh(-100, -200, 0, 0, 100, 200),\n      previous: interaction._rects.previous, // not testing previous\n      delta: ltrbwh(-100, -200, 0, 0, 100, 200),\n    })\n\n    interaction.move()\n    interactable.options.resize.invert = 'negate'\n    interaction.move()\n\n    // invert: 'negate' interaction._rects\n    expect(interaction._rects).toEqual({\n      start: rect,\n      corrected: ltrbwh(0, 0, -100, -200, -100, -200),\n      previous: interaction._rects.previous, // not testing previous\n      delta: ltrbwh(100, 200, -100, -200, -200, -400),\n    })\n\n    resizeEvent = null\n    interaction.end()\n    // resizeend event has extra resize props\n    expect(hasResizeProps(resizeEvent)).toBe(true)\n  })\n})\n\nfunction hasResizeProps(event: ResizeEvent) {\n  return !!(event.deltaRect && event.rect && event.edges)\n}\n"
  },
  {
    "path": "packages/@interactjs/auto-scroll/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/auto-scroll/package.json",
    "content": "{\n  \"name\": \"@interactjs/auto-scroll\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/auto-scroll\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/auto-scroll/plugin.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { ActionName, PointerType } from '@interactjs/core/types'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport is from '@interactjs/utils/is'\nimport raf from '@interactjs/utils/raf'\nimport { getStringOptionResult } from '@interactjs/utils/rect'\nimport { getWindow } from '@interactjs/utils/window'\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    autoScroll: typeof autoScroll\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    autoScroll?: typeof autoScroll\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface PerActionDefaults {\n    autoScroll?: AutoScrollOptions\n  }\n}\n\nexport interface AutoScrollOptions {\n  container?: Window | HTMLElement | string\n  margin?: number\n  distance?: number\n  interval?: number\n  speed?: number\n  enabled?: boolean\n}\n\nfunction install(scope: Scope) {\n  const { defaults, actions } = scope\n\n  scope.autoScroll = autoScroll\n  autoScroll.now = () => scope.now()\n\n  actions.phaselessTypes.autoscroll = true\n  defaults.perAction.autoScroll = autoScroll.defaults\n}\n\nconst autoScroll = {\n  defaults: {\n    enabled: false,\n    margin: 60,\n\n    // the item that is scrolled (Window or HTMLElement)\n    container: null as AutoScrollOptions['container'],\n\n    // the scroll speed in pixels per second\n    speed: 300,\n  } as AutoScrollOptions,\n\n  now: Date.now,\n\n  interaction: null as Interaction<ActionName> | null,\n  i: 0, // the handle returned by window.setInterval\n\n  // Direction each pulse is to scroll in\n  x: 0,\n  y: 0,\n\n  isScrolling: false,\n  prevTime: 0,\n  margin: 0,\n  speed: 0,\n\n  start(interaction: Interaction) {\n    autoScroll.isScrolling = true\n    raf.cancel(autoScroll.i)\n\n    interaction.autoScroll = autoScroll\n    autoScroll.interaction = interaction\n    autoScroll.prevTime = autoScroll.now()\n    autoScroll.i = raf.request(autoScroll.scroll)\n  },\n\n  stop() {\n    autoScroll.isScrolling = false\n    if (autoScroll.interaction) {\n      autoScroll.interaction.autoScroll = null\n    }\n    raf.cancel(autoScroll.i)\n  },\n\n  // scroll the window by the values in scroll.x/y\n  scroll() {\n    const { interaction } = autoScroll\n    const { interactable, element } = interaction\n    const actionName = interaction.prepared.name\n    const options = interactable.options[actionName].autoScroll\n    const container = getContainer(options.container, interactable, element)\n    const now = autoScroll.now()\n    // change in time in seconds\n    const dt = (now - autoScroll.prevTime) / 1000\n    // displacement\n    const s = options.speed * dt\n\n    if (s >= 1) {\n      const scrollBy = {\n        x: autoScroll.x * s,\n        y: autoScroll.y * s,\n      }\n\n      if (scrollBy.x || scrollBy.y) {\n        const prevScroll = getScroll(container)\n\n        if (is.window(container)) {\n          container.scrollBy(scrollBy.x, scrollBy.y)\n        } else if (container) {\n          container.scrollLeft += scrollBy.x\n          container.scrollTop += scrollBy.y\n        }\n\n        const curScroll = getScroll(container)\n        const delta = {\n          x: curScroll.x - prevScroll.x,\n          y: curScroll.y - prevScroll.y,\n        }\n\n        if (delta.x || delta.y) {\n          interactable.fire({\n            type: 'autoscroll',\n            target: element,\n            interactable,\n            delta,\n            interaction,\n            container,\n          })\n        }\n      }\n\n      autoScroll.prevTime = now\n    }\n\n    if (autoScroll.isScrolling) {\n      raf.cancel(autoScroll.i)\n      autoScroll.i = raf.request(autoScroll.scroll)\n    }\n  },\n  check(interactable: Interactable, actionName: ActionName) {\n    const options = interactable.options\n\n    return options[actionName].autoScroll?.enabled\n  },\n  onInteractionMove<T extends ActionName>({\n    interaction,\n    pointer,\n  }: {\n    interaction: Interaction<T>\n    pointer: PointerType\n  }) {\n    if (\n      !(interaction.interacting() && autoScroll.check(interaction.interactable, interaction.prepared.name))\n    ) {\n      return\n    }\n\n    if (interaction.simulation) {\n      autoScroll.x = autoScroll.y = 0\n      return\n    }\n\n    let top: boolean\n    let right: boolean\n    let bottom: boolean\n    let left: boolean\n\n    const { interactable, element } = interaction\n    const actionName = interaction.prepared.name\n    const options = interactable.options[actionName].autoScroll\n    const container = getContainer(options.container, interactable, element)\n\n    if (is.window(container)) {\n      left = pointer.clientX < autoScroll.margin\n      top = pointer.clientY < autoScroll.margin\n      right = pointer.clientX > container.innerWidth - autoScroll.margin\n      bottom = pointer.clientY > container.innerHeight - autoScroll.margin\n    } else {\n      const rect = domUtils.getElementClientRect(container)\n\n      left = pointer.clientX < rect.left + autoScroll.margin\n      top = pointer.clientY < rect.top + autoScroll.margin\n      right = pointer.clientX > rect.right - autoScroll.margin\n      bottom = pointer.clientY > rect.bottom - autoScroll.margin\n    }\n\n    autoScroll.x = right ? 1 : left ? -1 : 0\n    autoScroll.y = bottom ? 1 : top ? -1 : 0\n\n    if (!autoScroll.isScrolling) {\n      // set the autoScroll properties to those of the target\n      autoScroll.margin = options.margin\n      autoScroll.speed = options.speed\n\n      autoScroll.start(interaction)\n    }\n  },\n}\n\nexport function getContainer(value: any, interactable: Interactable, element: Element) {\n  return (\n    (is.string(value) ? getStringOptionResult(value, interactable, element) : value) || getWindow(element)\n  )\n}\n\nexport function getScroll(container: any) {\n  if (is.window(container)) {\n    container = window.document.body\n  }\n\n  return { x: container.scrollLeft, y: container.scrollTop }\n}\n\nexport function getScrollSize(container: any) {\n  if (is.window(container)) {\n    container = window.document.body\n  }\n\n  return { x: container.scrollWidth, y: container.scrollHeight }\n}\n\nexport function getScrollSizeDelta<T extends ActionName>(\n  {\n    interaction,\n    element,\n  }: {\n    interaction: Partial<Interaction<T>>\n    element: Element\n  },\n  func: any,\n) {\n  const scrollOptions = interaction && interaction.interactable.options[interaction.prepared.name].autoScroll\n\n  if (!scrollOptions || !scrollOptions.enabled) {\n    func()\n    return { x: 0, y: 0 }\n  }\n\n  const scrollContainer = getContainer(scrollOptions.container, interaction.interactable, element)\n\n  const prevSize = getScroll(scrollContainer)\n  func()\n  const curSize = getScroll(scrollContainer)\n\n  return {\n    x: curSize.x - prevSize.x,\n    y: curSize.y - prevSize.y,\n  }\n}\n\nconst autoScrollPlugin: Plugin = {\n  id: 'auto-scroll',\n  install,\n  listeners: {\n    'interactions:new': ({ interaction }) => {\n      interaction.autoScroll = null\n    },\n\n    'interactions:destroy': ({ interaction }) => {\n      interaction.autoScroll = null\n      autoScroll.stop()\n      if (autoScroll.interaction) {\n        autoScroll.interaction = null\n      }\n    },\n\n    'interactions:stop': autoScroll.stop,\n\n    'interactions:action-move': (arg: any) => autoScroll.onInteractionMove(arg),\n  },\n}\n\nexport default autoScrollPlugin\n"
  },
  {
    "path": "packages/@interactjs/auto-start/InteractableMethods.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { Interaction } from '@interactjs/core/Interaction'\nimport type { Scope } from '@interactjs/core/scope'\nimport type { ActionProps, PointerType, PointerEventType, Element } from '@interactjs/core/types'\nimport is from '@interactjs/utils/is'\nimport { warnOnce } from '@interactjs/utils/misc'\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    getAction: (\n      this: Interactable,\n      pointer: PointerType,\n      event: PointerEventType,\n      interaction: Interaction,\n      element: Element,\n    ) => ActionProps | null\n    styleCursor(newValue: boolean): this\n    styleCursor(): boolean\n    /**\n     * Returns or sets whether the the cursor should be changed depending on the\n     * action that would be performed if the mouse were pressed and dragged.\n     *\n     * @param {boolean} [newValue]\n     * @return {boolean | Interactable} The current setting or this Interactable\n     */\n    styleCursor(newValue?: boolean): boolean | this\n    actionChecker(checker: Function): Interactable\n    actionChecker(): Function\n    /**\n     * ```js\n     * interact('.resize-drag')\n     *   .resizable(true)\n     *   .draggable(true)\n     *   .actionChecker(function (pointer, event, action, interactable, element, interaction) {\n     *\n     *     if (interact.matchesSelector(event.target, '.drag-handle')) {\n     *       // force drag with handle target\n     *       action.name = drag\n     *     }\n     *     else {\n     *       // resize from the top and right edges\n     *       action.name  = 'resize'\n     *       action.edges = { top: true, right: true }\n     *     }\n     *\n     *     return action\n     * })\n     * ```\n     *\n     * Returns or sets the function used to check action to be performed on\n     * pointerDown\n     *\n     * @param checker - A function which takes a pointer event,\n     * defaultAction string, interactable, element and interaction as parameters\n     * and returns an object with name property 'drag' 'resize' or 'gesture' and\n     * optionally an `edges` object with boolean 'top', 'left', 'bottom' and right\n     * props.\n     * @returns The checker function or this Interactable\n     */\n    actionChecker(checker?: Function): Interactable | Function\n    /** @returns This interactable */\n    ignoreFrom(newValue: string | Element | null): Interactable\n    /** @returns The current ignoreFrom value */\n    ignoreFrom(): string | Element | null\n    /**\n     * If the target of the `mousedown`, `pointerdown` or `touchstart` event or any\n     * of it's parents match the given CSS selector or Element, no\n     * drag/resize/gesture is started.\n     *\n     * @deprecated\n     * Don't use this method. Instead set the `ignoreFrom` option for each action\n     * or for `pointerEvents`\n     *\n     * ```js\n     * interact(targett)\n     *   .draggable({\n     *     ignoreFrom: 'input, textarea, a[href]'',\n     *   })\n     *   .pointerEvents({\n     *     ignoreFrom: '[no-pointer]',\n     *   })\n     * ```\n     * Interactable\n     */\n    ignoreFrom(\n      /** a CSS selector string, an Element or `null` to not ignore any elements */\n      newValue?: string | Element | null,\n    ): Interactable | string | Element | null\n    allowFrom(): boolean\n    /**\n     *\n     * A drag/resize/gesture is started only If the target of the `mousedown`,\n     * `pointerdown` or `touchstart` event or any of it's parents match the given\n     * CSS selector or Element.\n     *\n     * @deprecated\n     * Don't use this method. Instead set the `allowFrom` option for each action\n     * or for `pointerEvents`\n     *\n     * ```js\n     * interact(targett)\n     *   .resizable({\n     *     allowFrom: '.resize-handle',\n     *   .pointerEvents({\n     *     allowFrom: '.handle',,\n     *   })\n     * ```\n     *\n     * @param {string | Element | null} [newValue]\n     * @return {string | Element | object} The current allowFrom value or this\n     * Interactable\n     */\n    allowFrom(\n      /** A CSS selector string, an Element or `null` to allow from any element */\n      newValue: string | Element | null,\n    ): Interactable\n  }\n}\n\nfunction install(scope: Scope) {\n  const {\n    Interactable, // tslint:disable-line no-shadowed-variable\n  } = scope\n\n  Interactable.prototype.getAction = function getAction(\n    this: Interactable,\n    pointer: PointerType,\n    event: PointerEventType,\n    interaction: Interaction,\n    element: Element,\n  ): ActionProps {\n    const action = defaultActionChecker(this, event, interaction, element, scope)\n\n    if (this.options.actionChecker) {\n      return this.options.actionChecker(pointer, event, action, this, element, interaction)\n    }\n\n    return action\n  }\n\n  Interactable.prototype.ignoreFrom = warnOnce(function (this: Interactable, newValue) {\n    return this._backCompatOption('ignoreFrom', newValue)\n  }, 'Interactable.ignoreFrom() has been deprecated. Use Interactble.draggable({ignoreFrom: newValue}).')\n\n  Interactable.prototype.allowFrom = warnOnce(function (this: Interactable, newValue) {\n    return this._backCompatOption('allowFrom', newValue)\n  }, 'Interactable.allowFrom() has been deprecated. Use Interactble.draggable({allowFrom: newValue}).')\n\n  Interactable.prototype.actionChecker = actionChecker\n\n  Interactable.prototype.styleCursor = styleCursor\n}\n\nfunction defaultActionChecker(\n  interactable: Interactable,\n  event: PointerEventType,\n  interaction: Interaction,\n  element: Element,\n  scope: Scope,\n) {\n  const rect = interactable.getRect(element)\n  const buttons =\n    (event as MouseEvent).buttons ||\n    {\n      0: 1,\n      1: 4,\n      3: 8,\n      4: 16,\n    }[(event as MouseEvent).button as 0 | 1 | 3 | 4]\n  const arg = {\n    action: null,\n    interactable,\n    interaction,\n    element,\n    rect,\n    buttons,\n  }\n\n  scope.fire('auto-start:check', arg)\n\n  return arg.action\n}\n\nfunction styleCursor(this: Interactable, newValue?: boolean) {\n  if (is.bool(newValue)) {\n    this.options.styleCursor = newValue\n\n    return this\n  }\n\n  if (newValue === null) {\n    delete this.options.styleCursor\n\n    return this\n  }\n\n  return this.options.styleCursor\n}\n\nfunction actionChecker(this: Interactable, checker?: any) {\n  if (is.func(checker)) {\n    this.options.actionChecker = checker\n\n    return this\n  }\n\n  if (checker === null) {\n    delete this.options.actionChecker\n\n    return this\n  }\n\n  return this.options.actionChecker\n}\n\nexport default {\n  id: 'auto-start/interactableMethods',\n  install,\n}\n"
  },
  {
    "path": "packages/@interactjs/auto-start/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/auto-start/autoStart.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\nimport * as helpers from '@interactjs/core/tests/_helpers'\n\nimport autoStart from './base'\n\ntest('autoStart', () => {\n  window.PointerEvent = null\n\n  document.body.innerHTML = `\n    <style>\n    #target { position: absolute; top: 100px; left: 200px; bottom: 300px; right: 400px }\n    </style>\n    <div id=target></div>\n  `\n\n  Object.assign(document.body.style)\n\n  const {\n    interaction,\n    interactable,\n    event,\n    coords,\n    target: element,\n    down,\n  } = helpers.testEnv({\n    plugins: [autoStart, drag],\n    target: document.getElementById('target'),\n  })\n\n  interactable.draggable(true)\n  interaction.pointerType = coords.pointerType = 'mouse'\n  coords.buttons = 1\n\n  down()\n\n  // prepares action\n  expect(interaction.prepared).toEqual({ name: 'drag', axis: 'xy', edges: undefined })\n\n  // set interaction.rect\n  expect(interaction.rect).toEqual(\n    helpers.getProps(element.getBoundingClientRect(), ['top', 'left', 'bottom', 'right', 'width', 'height']),\n  )\n\n  // sets drag cursor\n  expect(element.style.cursor).toBe('move')\n\n  const cursorChecker = jest.fn(() => 'pointer')\n\n  interactable.draggable({\n    cursorChecker,\n  })\n\n  interaction.pointerDown(event, event, element)\n\n  // calls cursorChecker with expected args\n  expect(cursorChecker).toHaveBeenCalledWith(\n    { name: 'drag', axis: 'xy', edges: undefined },\n    interactable,\n    element,\n    false,\n  )\n\n  interaction.pointerDown(event, event, element)\n  // uses cursorChecker value\n  expect(element.style.cursor).toBe('pointer')\n\n  coords.page.x += 10\n  coords.client.x += 10\n  interaction.pointerMove(event, event, element)\n  // down -> move starts action\n  expect(interaction._interacting).toBe(true)\n\n  // calls cursorChecker with true for interacting arg\n  expect(cursorChecker).toHaveBeenCalledWith(\n    { name: 'drag', axis: 'xy', edges: undefined },\n    interactable,\n    element,\n    true,\n  )\n})\n"
  },
  {
    "path": "packages/@interactjs/auto-start/base.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { Interaction } from '@interactjs/core/Interaction'\nimport type { Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport type {\n  CursorChecker,\n  PointerType,\n  PointerEventType,\n  Element,\n  ActionName,\n  ActionProps,\n} from '@interactjs/core/types'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport { copyAction } from '@interactjs/utils/misc'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './InteractableMethods'\nimport InteractableMethods from './InteractableMethods'\n/* eslint-enable import/no-duplicates */\n\ndeclare module '@interactjs/core/InteractStatic' {\n  export interface InteractStatic {\n    /**\n     * Returns or sets the maximum number of concurrent interactions allowed.  By\n     * default only 1 interaction is allowed at a time (for backwards\n     * compatibility). To allow multiple interactions on the same Interactables and\n     * elements, you need to enable it in the draggable, resizable and gesturable\n     * `'max'` and `'maxPerElement'` options.\n     *\n     * @param {number} [newValue] Any number. newValue <= 0 means no interactions.\n     */\n    maxInteractions: (newValue: any) => any\n  }\n}\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    autoStart: AutoStart\n  }\n\n  interface SignalArgs {\n    'autoStart:before-start': Omit<SignalArgs['interactions:move'], 'interaction'> & {\n      interaction: Interaction<ActionName>\n    }\n    'autoStart:prepared': { interaction: Interaction }\n    'auto-start:check': CheckSignalArg\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface BaseDefaults {\n    actionChecker?: any\n    cursorChecker?: any\n    styleCursor?: any\n  }\n\n  interface PerActionDefaults {\n    manualStart?: boolean\n    max?: number\n    maxPerElement?: number\n    allowFrom?: string | Element\n    ignoreFrom?: string | Element\n    cursorChecker?: CursorChecker\n\n    // only allow left button by default\n    // see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons#Return_value\n    // TODO: docst\n    mouseButtons?: 0 | 1 | 2 | 4 | 8 | 16\n  }\n}\n\ninterface CheckSignalArg {\n  interactable: Interactable\n  interaction: Interaction\n  element: Element\n  action: ActionProps<ActionName>\n  buttons: number\n}\n\nexport interface AutoStart {\n  // Allow this many interactions to happen simultaneously\n  maxInteractions: number\n  withinInteractionLimit: typeof withinInteractionLimit\n  cursorElement: Element\n}\n\nfunction install(scope: Scope) {\n  const { interactStatic: interact, defaults } = scope\n\n  scope.usePlugin(InteractableMethods)\n\n  defaults.base.actionChecker = null\n  defaults.base.styleCursor = true\n\n  extend(defaults.perAction, {\n    manualStart: false,\n    max: Infinity,\n    maxPerElement: 1,\n    allowFrom: null,\n    ignoreFrom: null,\n\n    // only allow left button by default\n    // see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons#Return_value\n    mouseButtons: 1,\n  })\n\n  interact.maxInteractions = (newValue: number) => maxInteractions(newValue, scope)\n\n  scope.autoStart = {\n    // Allow this many interactions to happen simultaneously\n    maxInteractions: Infinity,\n    withinInteractionLimit,\n    cursorElement: null,\n  }\n}\n\nfunction prepareOnDown(\n  { interaction, pointer, event, eventTarget }: SignalArgs['interactions:down'],\n  scope: Scope,\n) {\n  if (interaction.interacting()) return\n\n  const actionInfo = getActionInfo(interaction, pointer, event, eventTarget, scope)\n  prepare(interaction, actionInfo, scope)\n}\n\nfunction prepareOnMove(\n  { interaction, pointer, event, eventTarget }: SignalArgs['interactions:move'],\n  scope: Scope,\n) {\n  if (interaction.pointerType !== 'mouse' || interaction.pointerIsDown || interaction.interacting()) return\n\n  const actionInfo = getActionInfo(interaction, pointer, event, eventTarget as Element, scope)\n  prepare(interaction, actionInfo, scope)\n}\n\nfunction startOnMove(arg: SignalArgs['interactions:move'], scope: Scope) {\n  const { interaction } = arg\n\n  if (\n    !interaction.pointerIsDown ||\n    interaction.interacting() ||\n    !interaction.pointerWasMoved ||\n    !interaction.prepared.name\n  ) {\n    return\n  }\n\n  scope.fire('autoStart:before-start', arg)\n\n  const { interactable } = interaction\n  const actionName = (interaction as Interaction<ActionName>).prepared.name\n\n  if (actionName && interactable) {\n    // check manualStart and interaction limit\n    if (\n      interactable.options[actionName].manualStart ||\n      !withinInteractionLimit(interactable, interaction.element, interaction.prepared, scope)\n    ) {\n      interaction.stop()\n    } else {\n      interaction.start(interaction.prepared, interactable, interaction.element)\n      setInteractionCursor(interaction, scope)\n    }\n  }\n}\n\nfunction clearCursorOnStop({ interaction }: { interaction: Interaction }, scope: Scope) {\n  const { interactable } = interaction\n\n  if (interactable && interactable.options.styleCursor) {\n    setCursor(interaction.element, '', scope)\n  }\n}\n\n// Check if the current interactable supports the action.\n// If so, return the validated action. Otherwise, return null\nfunction validateAction<T extends ActionName>(\n  action: ActionProps<T>,\n  interactable: Interactable,\n  element: Element,\n  eventTarget: Node,\n  scope: Scope,\n) {\n  if (\n    interactable.testIgnoreAllow(interactable.options[action.name], element, eventTarget) &&\n    interactable.options[action.name].enabled &&\n    withinInteractionLimit(interactable, element, action, scope)\n  ) {\n    return action\n  }\n\n  return null\n}\n\nfunction validateMatches(\n  interaction: Interaction,\n  pointer: PointerType,\n  event: PointerEventType,\n  matches: Interactable[],\n  matchElements: Element[],\n  eventTarget: Node,\n  scope: Scope,\n) {\n  for (let i = 0, len = matches.length; i < len; i++) {\n    const match = matches[i]\n    const matchElement = matchElements[i]\n    const matchAction = match.getAction(pointer, event, interaction, matchElement)\n\n    if (!matchAction) {\n      continue\n    }\n\n    const action = validateAction<ActionName>(matchAction, match, matchElement, eventTarget, scope)\n\n    if (action) {\n      return {\n        action,\n        interactable: match,\n        element: matchElement,\n      }\n    }\n  }\n\n  return { action: null, interactable: null, element: null }\n}\n\nfunction getActionInfo(\n  interaction: Interaction,\n  pointer: PointerType,\n  event: PointerEventType,\n  eventTarget: Node,\n  scope: Scope,\n) {\n  let matches: Interactable[] = []\n  let matchElements: Element[] = []\n\n  let element = eventTarget as Element\n\n  function pushMatches(interactable: Interactable) {\n    matches.push(interactable)\n    matchElements.push(element)\n  }\n\n  while (is.element(element)) {\n    matches = []\n    matchElements = []\n\n    scope.interactables.forEachMatch(element, pushMatches)\n\n    const actionInfo = validateMatches(\n      interaction,\n      pointer,\n      event,\n      matches,\n      matchElements,\n      eventTarget,\n      scope,\n    )\n\n    if (actionInfo.action && !actionInfo.interactable.options[actionInfo.action.name].manualStart) {\n      return actionInfo\n    }\n\n    element = domUtils.parentNode(element) as Element\n  }\n\n  return { action: null, interactable: null, element: null }\n}\n\nfunction prepare(\n  interaction: Interaction,\n  {\n    action,\n    interactable,\n    element,\n  }: {\n    action: ActionProps<any>\n    interactable: Interactable\n    element: Element\n  },\n  scope: Scope,\n) {\n  action = action || { name: null }\n\n  interaction.interactable = interactable\n  interaction.element = element\n  copyAction(interaction.prepared, action)\n\n  interaction.rect = interactable && action.name ? interactable.getRect(element) : null\n\n  setInteractionCursor(interaction, scope)\n\n  scope.fire('autoStart:prepared', { interaction })\n}\n\nfunction withinInteractionLimit<T extends ActionName>(\n  interactable: Interactable,\n  element: Element,\n  action: ActionProps<T>,\n  scope: Scope,\n) {\n  const options = interactable.options\n  const maxActions = options[action.name].max\n  const maxPerElement = options[action.name].maxPerElement\n  const autoStartMax = scope.autoStart.maxInteractions\n  let activeInteractions = 0\n  let interactableCount = 0\n  let elementCount = 0\n\n  // no actions if any of these values == 0\n  if (!(maxActions && maxPerElement && autoStartMax)) {\n    return false\n  }\n\n  for (const interaction of scope.interactions.list) {\n    const otherAction = interaction.prepared.name\n\n    if (!interaction.interacting()) {\n      continue\n    }\n\n    activeInteractions++\n\n    if (activeInteractions >= autoStartMax) {\n      return false\n    }\n\n    if (interaction.interactable !== interactable) {\n      continue\n    }\n\n    interactableCount += otherAction === action.name ? 1 : 0\n\n    if (interactableCount >= maxActions) {\n      return false\n    }\n\n    if (interaction.element === element) {\n      elementCount++\n\n      if (otherAction === action.name && elementCount >= maxPerElement) {\n        return false\n      }\n    }\n  }\n\n  return autoStartMax > 0\n}\n\nfunction maxInteractions(newValue: any, scope: Scope) {\n  if (is.number(newValue)) {\n    scope.autoStart.maxInteractions = newValue\n\n    return this\n  }\n\n  return scope.autoStart.maxInteractions\n}\n\nfunction setCursor(element: Element, cursor: string, scope: Scope) {\n  const { cursorElement: prevCursorElement } = scope.autoStart\n\n  if (prevCursorElement && prevCursorElement !== element) {\n    prevCursorElement.style.cursor = ''\n  }\n\n  element.ownerDocument.documentElement.style.cursor = cursor\n  element.style.cursor = cursor\n  scope.autoStart.cursorElement = cursor ? element : null\n}\n\nfunction setInteractionCursor<T extends ActionName>(interaction: Interaction<T>, scope: Scope) {\n  const { interactable, element, prepared } = interaction\n\n  if (!(interaction.pointerType === 'mouse' && interactable && interactable.options.styleCursor)) {\n    // clear previous target element cursor\n    if (scope.autoStart.cursorElement) {\n      setCursor(scope.autoStart.cursorElement, '', scope)\n    }\n\n    return\n  }\n\n  let cursor = ''\n\n  if (prepared.name) {\n    const cursorChecker = interactable.options[prepared.name].cursorChecker\n\n    if (is.func(cursorChecker)) {\n      cursor = cursorChecker(prepared, interactable, element, interaction._interacting)\n    } else {\n      cursor = scope.actions.map[prepared.name].getCursor(prepared)\n    }\n  }\n\n  setCursor(interaction.element, cursor || '', scope)\n}\n\nconst autoStart: Plugin = {\n  id: 'auto-start/base',\n  before: ['actions'],\n  install,\n  listeners: {\n    'interactions:down': prepareOnDown,\n    'interactions:move': (arg, scope) => {\n      prepareOnMove(arg, scope)\n      startOnMove(arg, scope)\n    },\n    'interactions:stop': clearCursorOnStop,\n  },\n  maxInteractions,\n  withinInteractionLimit,\n  validateAction,\n}\n\nexport default autoStart\n"
  },
  {
    "path": "packages/@interactjs/auto-start/dragAxis.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { SignalArgs, Scope } from '@interactjs/core/scope'\nimport type { ActionName, Element } from '@interactjs/core/types'\nimport { parentNode } from '@interactjs/utils/domUtils'\nimport is from '@interactjs/utils/is'\n\nimport autoStart from './base'\n\nfunction beforeStart({ interaction, eventTarget, dx, dy }: SignalArgs['interactions:move'], scope: Scope) {\n  if (interaction.prepared.name !== 'drag') return\n\n  // check if a drag is in the correct axis\n  const absX = Math.abs(dx)\n  const absY = Math.abs(dy)\n  const targetOptions = interaction.interactable.options.drag\n  const startAxis = targetOptions.startAxis\n  const currentAxis = absX > absY ? 'x' : absX < absY ? 'y' : 'xy'\n\n  interaction.prepared.axis =\n    targetOptions.lockAxis === 'start'\n      ? (currentAxis[0] as 'x' | 'y') // always lock to one axis even if currentAxis === 'xy'\n      : targetOptions.lockAxis\n\n  // if the movement isn't in the startAxis of the interactable\n  if (currentAxis !== 'xy' && startAxis !== 'xy' && startAxis !== currentAxis) {\n    // cancel the prepared action\n    ;(interaction as Interaction<ActionName>).prepared.name = null\n\n    // then try to get a drag from another ineractable\n    let element = eventTarget as Element\n\n    const getDraggable = function (interactable: Interactable): Interactable | void {\n      if (interactable === interaction.interactable) return\n\n      const options = interaction.interactable.options.drag\n\n      if (!options.manualStart && interactable.testIgnoreAllow(options, element, eventTarget)) {\n        const action = interactable.getAction(\n          interaction.downPointer,\n          interaction.downEvent,\n          interaction,\n          element,\n        )\n\n        if (\n          action &&\n          action.name === 'drag' &&\n          checkStartAxis(currentAxis, interactable) &&\n          autoStart.validateAction(action, interactable, element, eventTarget, scope)\n        ) {\n          return interactable\n        }\n      }\n    }\n\n    // check all interactables\n    while (is.element(element)) {\n      const interactable = scope.interactables.forEachMatch(element, getDraggable)\n\n      if (interactable) {\n        ;(interaction as Interaction<ActionName>).prepared.name = 'drag'\n        interaction.interactable = interactable\n        interaction.element = element\n        break\n      }\n\n      element = parentNode(element) as Element\n    }\n  }\n}\n\nfunction checkStartAxis(startAxis: string, interactable: Interactable) {\n  if (!interactable) {\n    return false\n  }\n\n  const thisAxis = interactable.options.drag.startAxis\n\n  return startAxis === 'xy' || thisAxis === 'xy' || thisAxis === startAxis\n}\n\nexport default {\n  id: 'auto-start/dragAxis',\n  listeners: { 'autoStart:before-start': beforeStart },\n}\n"
  },
  {
    "path": "packages/@interactjs/auto-start/hold.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\n\nimport hold from './hold'\n\ntest('autoStart/hold', () => {\n  const { scope } = helpers.testEnv({ plugins: [hold] })\n\n  // sets scope.defaults.perAction.hold\n  expect(scope.defaults.perAction.hold).toBe(0)\n  // backwards compatible \"delay\" alias.\n  expect(scope.defaults.perAction.delay).toBe(0)\n\n  const holdDuration = 1000\n  const actionName = 'TEST_ACTION'\n  const interaction: any = {\n    interactable: { options: { [actionName]: { hold: holdDuration } } },\n    prepared: { name: actionName },\n  }\n\n  // gets holdDuration\n  expect(hold.getHoldDuration(interaction)).toBe(holdDuration)\n\n  const delayDuration = 500\n\n  interaction.interactable.options[actionName].delay = delayDuration\n  delete interaction.interactable.options[actionName].hold\n\n  // gets holdDuration from \"delay\" value\n  expect(hold.getHoldDuration(interaction)).toBe(delayDuration)\n})\n"
  },
  {
    "path": "packages/@interactjs/auto-start/hold.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './base'\nimport basePlugin from './base'\n/* eslint-enable */\n\ndeclare module '@interactjs/core/options' {\n  interface PerActionDefaults {\n    hold?: number\n    delay?: number\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    autoStartHoldTimer?: any\n  }\n}\n\nfunction install(scope: Scope) {\n  const { defaults } = scope\n\n  scope.usePlugin(basePlugin)\n\n  defaults.perAction.hold = 0\n  defaults.perAction.delay = 0\n}\n\nfunction getHoldDuration(interaction: Interaction) {\n  const actionName = interaction.prepared && interaction.prepared.name\n\n  if (!actionName) {\n    return null\n  }\n\n  const options = interaction.interactable.options\n\n  return options[actionName].hold || options[actionName].delay\n}\n\nconst hold: Plugin = {\n  id: 'auto-start/hold',\n  install,\n  listeners: {\n    'interactions:new': ({ interaction }) => {\n      interaction.autoStartHoldTimer = null\n    },\n\n    'autoStart:prepared': ({ interaction }) => {\n      const hold = getHoldDuration(interaction)\n\n      if (hold > 0) {\n        interaction.autoStartHoldTimer = setTimeout(() => {\n          interaction.start(interaction.prepared, interaction.interactable, interaction.element)\n        }, hold)\n      }\n    },\n\n    'interactions:move': ({ interaction, duplicate }) => {\n      if (interaction.autoStartHoldTimer && interaction.pointerWasMoved && !duplicate) {\n        clearTimeout(interaction.autoStartHoldTimer)\n        interaction.autoStartHoldTimer = null\n      }\n    },\n\n    // prevent regular down->move autoStart\n    'autoStart:before-start': ({ interaction }) => {\n      const holdDuration = getHoldDuration(interaction)\n\n      if (holdDuration > 0) {\n        interaction.prepared.name = null\n      }\n    },\n  },\n  getHoldDuration,\n}\nexport default hold\n"
  },
  {
    "path": "packages/@interactjs/auto-start/package.json",
    "content": "{\n  \"name\": \"@interactjs/auto-start\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/auto-start\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/auto-start/plugin.ts",
    "content": "import type { Scope } from '@interactjs/core/scope'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './base'\nimport './dragAxis'\nimport './hold'\n\nimport autoStart from './base'\nimport dragAxis from './dragAxis'\nimport hold from './hold'\n/* eslint-enable import/no-duplicates */\n\nexport default {\n  id: 'auto-start',\n  install(scope: Scope) {\n    scope.usePlugin(autoStart)\n    scope.usePlugin(hold)\n    scope.usePlugin(dragAxis)\n  },\n}\n"
  },
  {
    "path": "packages/@interactjs/core/BaseEvent.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { Interaction, InteractionProxy } from '@interactjs/core/Interaction'\nimport type { ActionName } from '@interactjs/core/types'\n\nexport class BaseEvent<T extends ActionName | null = never> {\n  declare type: string\n  declare target: EventTarget\n  declare currentTarget: Node\n  declare interactable: Interactable\n  /** @internal */\n  declare _interaction: Interaction<T>\n  declare timeStamp: number\n  immediatePropagationStopped = false\n  propagationStopped = false\n\n  constructor(interaction: Interaction<T>) {\n    this._interaction = interaction\n  }\n\n  preventDefault() {}\n\n  /**\n   * Don't call any other listeners (even on the current target)\n   */\n  stopPropagation() {\n    this.propagationStopped = true\n  }\n\n  /**\n   * Don't call listeners on the remaining targets\n   */\n  stopImmediatePropagation() {\n    this.immediatePropagationStopped = this.propagationStopped = true\n  }\n}\n\n// defined outside of class definition to avoid assignment of undefined during\n// construction\nexport interface BaseEvent<T extends ActionName | null = never> {\n  interaction: InteractionProxy<T>\n}\n\n// getters and setters defined here to support typescript 3.6 and below which\n// don't support getter and setters in .d.ts files\nObject.defineProperty(BaseEvent.prototype, 'interaction', {\n  get(this: BaseEvent) {\n    return this._interaction._proxy\n  },\n  set(this: BaseEvent) {},\n})\n"
  },
  {
    "path": "packages/@interactjs/core/Eventable.spec.ts",
    "content": "import { Eventable } from './Eventable'\n\ntest('core/Eventable', () => {\n  const eventable = new Eventable()\n  const type = 'TEST'\n\n  const testEvent = {\n    type,\n    immediatePropagationStopped: false,\n  }\n  let firedEvent: any\n  const listener = (event: any) => {\n    firedEvent = event\n  }\n\n  eventable.on(type, listener)\n  eventable.fire(testEvent)\n\n  // on'd listener is called\n  expect(firedEvent).toBe(testEvent)\n\n  firedEvent = undefined\n  eventable.off(type, listener)\n  eventable.fire(testEvent)\n\n  // off'd listener is not called\n  expect(firedEvent).toBeUndefined()\n\n  testEvent.immediatePropagationStopped = true\n  eventable.on(type, listener)\n  eventable.fire(testEvent)\n\n  // listener is not called with immediatePropagationStopped\n  expect(firedEvent).toBeUndefined()\n})\n"
  },
  {
    "path": "packages/@interactjs/core/Eventable.ts",
    "content": "import * as arr from '@interactjs/utils/arr'\nimport extend from '@interactjs/utils/extend'\nimport type { NormalizedListeners } from '@interactjs/utils/normalizeListeners'\nimport normalize from '@interactjs/utils/normalizeListeners'\n\nimport type { Listener, ListenersArg, Rect } from '@interactjs/core/types'\n\nfunction fireUntilImmediateStopped(event: any, listeners: Listener[]) {\n  for (const listener of listeners) {\n    if (event.immediatePropagationStopped) {\n      break\n    }\n\n    listener(event)\n  }\n}\n\nexport class Eventable {\n  options: any\n  types: NormalizedListeners = {}\n  propagationStopped = false\n  immediatePropagationStopped = false\n  global: any\n\n  constructor(options?: { [index: string]: any }) {\n    this.options = extend({}, options || {})\n  }\n\n  fire<T extends { type: string; propagationStopped?: boolean }>(event: T) {\n    let listeners: Listener[]\n    const global = this.global\n\n    // Interactable#on() listeners\n    // tslint:disable no-conditional-assignment\n    if ((listeners = this.types[event.type])) {\n      fireUntilImmediateStopped(event, listeners)\n    }\n\n    // interact.on() listeners\n    if (!event.propagationStopped && global && (listeners = global[event.type])) {\n      fireUntilImmediateStopped(event, listeners)\n    }\n  }\n\n  on(type: string, listener: ListenersArg) {\n    const listeners = normalize(type, listener)\n\n    for (type in listeners) {\n      this.types[type] = arr.merge(this.types[type] || [], listeners[type])\n    }\n  }\n\n  off(type: string, listener: ListenersArg) {\n    const listeners = normalize(type, listener)\n\n    for (type in listeners) {\n      const eventList = this.types[type]\n\n      if (!eventList || !eventList.length) {\n        continue\n      }\n\n      for (const subListener of listeners[type]) {\n        const index = eventList.indexOf(subListener)\n\n        if (index !== -1) {\n          eventList.splice(index, 1)\n        }\n      }\n    }\n  }\n\n  getRect(_element: Element): Rect {\n    return null\n  }\n}\n"
  },
  {
    "path": "packages/@interactjs/core/InteractEvent.ts",
    "content": "import extend from '@interactjs/utils/extend'\nimport getOriginXY from '@interactjs/utils/getOriginXY'\nimport hypot from '@interactjs/utils/hypot'\n\nimport type { Point, FullRect, PointerEventType, Element, ActionName } from '@interactjs/core/types'\n\nimport { BaseEvent } from './BaseEvent'\nimport type { Interaction } from './Interaction'\nimport { defaults } from './options'\n\nexport type EventPhase = keyof PhaseMap\n\nexport interface PhaseMap {\n  start: true\n  move: true\n  end: true\n}\n\n// defined outside of class definition to avoid assignment of undefined during\n// construction\nexport interface InteractEvent {\n  pageX: number\n  pageY: number\n\n  clientX: number\n  clientY: number\n\n  dx: number\n  dy: number\n\n  velocityX: number\n  velocityY: number\n}\n\nexport class InteractEvent<\n  T extends ActionName = never,\n  P extends EventPhase = EventPhase,\n> extends BaseEvent<T> {\n  declare target: Element\n  declare currentTarget: Element\n  relatedTarget: Element | null = null\n  screenX?: number\n  screenY?: number\n  button: number\n  buttons: number\n  ctrlKey: boolean\n  shiftKey: boolean\n  altKey: boolean\n  metaKey: boolean\n  page: Point\n  client: Point\n  delta: Point\n  rect: FullRect\n  x0: number\n  y0: number\n  t0: number\n  dt: number\n  duration: number\n  clientX0: number\n  clientY0: number\n  velocity: Point\n  speed: number\n  swipe: ReturnType<InteractEvent<T>['getSwipe']>\n  // resize\n  axes?: 'x' | 'y' | 'xy'\n  /** @internal */\n  preEnd?: boolean\n\n  constructor(\n    interaction: Interaction<T>,\n    event: PointerEventType,\n    actionName: T,\n    phase: P,\n    element: Element,\n    preEnd?: boolean,\n    type?: string,\n  ) {\n    super(interaction)\n\n    element = element || interaction.element\n\n    const target = interaction.interactable\n    const deltaSource = (((target && target.options) || defaults) as any).deltaSource as 'page' | 'client'\n    const origin = getOriginXY(target, element, actionName)\n    const starting = phase === 'start'\n    const ending = phase === 'end'\n    const prevEvent = starting ? this : interaction.prevEvent\n    const coords = starting\n      ? interaction.coords.start\n      : ending\n        ? { page: prevEvent.page, client: prevEvent.client, timeStamp: interaction.coords.cur.timeStamp }\n        : interaction.coords.cur\n\n    this.page = extend({}, coords.page)\n    this.client = extend({}, coords.client)\n    this.rect = extend({}, interaction.rect)\n    this.timeStamp = coords.timeStamp\n\n    if (!ending) {\n      this.page.x -= origin.x\n      this.page.y -= origin.y\n\n      this.client.x -= origin.x\n      this.client.y -= origin.y\n    }\n\n    this.ctrlKey = event.ctrlKey\n    this.altKey = event.altKey\n    this.shiftKey = event.shiftKey\n    this.metaKey = event.metaKey\n    this.button = (event as MouseEvent).button\n    this.buttons = (event as MouseEvent).buttons\n    this.target = element\n    this.currentTarget = element\n    this.preEnd = preEnd\n    this.type = type || actionName + (phase || '')\n    this.interactable = target\n\n    this.t0 = starting ? interaction.pointers[interaction.pointers.length - 1].downTime : prevEvent.t0\n\n    this.x0 = interaction.coords.start.page.x - origin.x\n    this.y0 = interaction.coords.start.page.y - origin.y\n    this.clientX0 = interaction.coords.start.client.x - origin.x\n    this.clientY0 = interaction.coords.start.client.y - origin.y\n\n    if (starting || ending) {\n      this.delta = { x: 0, y: 0 }\n    } else {\n      this.delta = {\n        x: this[deltaSource].x - prevEvent[deltaSource].x,\n        y: this[deltaSource].y - prevEvent[deltaSource].y,\n      }\n    }\n\n    this.dt = interaction.coords.delta.timeStamp\n    this.duration = this.timeStamp - this.t0\n\n    // velocity and speed in pixels per second\n    this.velocity = extend({}, interaction.coords.velocity[deltaSource])\n    this.speed = hypot(this.velocity.x, this.velocity.y)\n\n    this.swipe = ending || phase === 'inertiastart' ? this.getSwipe() : null\n  }\n\n  getSwipe() {\n    const interaction = this._interaction\n\n    if (interaction.prevEvent.speed < 600 || this.timeStamp - interaction.prevEvent.timeStamp > 150) {\n      return null\n    }\n\n    let angle = (180 * Math.atan2(interaction.prevEvent.velocityY, interaction.prevEvent.velocityX)) / Math.PI\n    const overlap = 22.5\n\n    if (angle < 0) {\n      angle += 360\n    }\n\n    const left = 135 - overlap <= angle && angle < 225 + overlap\n    const up = 225 - overlap <= angle && angle < 315 + overlap\n\n    const right = !left && (315 - overlap <= angle || angle < 45 + overlap)\n    const down = !up && 45 - overlap <= angle && angle < 135 + overlap\n\n    return {\n      up,\n      down,\n      left,\n      right,\n      angle,\n      speed: interaction.prevEvent.speed,\n      velocity: {\n        x: interaction.prevEvent.velocityX,\n        y: interaction.prevEvent.velocityY,\n      },\n    }\n  }\n\n  preventDefault() {}\n\n  /**\n   * Don't call listeners on the remaining targets\n   */\n  stopImmediatePropagation() {\n    this.immediatePropagationStopped = this.propagationStopped = true\n  }\n\n  /**\n   * Don't call any other listeners (even on the current target)\n   */\n  stopPropagation() {\n    this.propagationStopped = true\n  }\n}\n\n// getters and setters defined here to support typescript 3.6 and below which\n// don't support getter and setters in .d.ts files\nObject.defineProperties(InteractEvent.prototype, {\n  pageX: {\n    get() {\n      return this.page.x\n    },\n    set(value) {\n      this.page.x = value\n    },\n  },\n  pageY: {\n    get() {\n      return this.page.y\n    },\n    set(value) {\n      this.page.y = value\n    },\n  },\n\n  clientX: {\n    get() {\n      return this.client.x\n    },\n    set(value) {\n      this.client.x = value\n    },\n  },\n  clientY: {\n    get() {\n      return this.client.y\n    },\n    set(value) {\n      this.client.y = value\n    },\n  },\n\n  dx: {\n    get() {\n      return this.delta.x\n    },\n    set(value) {\n      this.delta.x = value\n    },\n  },\n  dy: {\n    get() {\n      return this.delta.y\n    },\n    set(value) {\n      this.delta.y = value\n    },\n  },\n\n  velocityX: {\n    get() {\n      return this.velocity.x\n    },\n    set(value) {\n      this.velocity.x = value\n    },\n  },\n  velocityY: {\n    get() {\n      return this.velocity.y\n    },\n    set(value) {\n      this.velocity.y = value\n    },\n  },\n})\n"
  },
  {
    "path": "packages/@interactjs/core/InteractStatic.ts",
    "content": "import browser from '@interactjs/utils/browser'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport is from '@interactjs/utils/is'\nimport isNonNativeEvent from '@interactjs/utils/isNonNativeEvent'\nimport { warnOnce } from '@interactjs/utils/misc'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Context, EventTypes, Listener, ListenersArg, Target } from '@interactjs/core/types'\n\nimport type { Interactable } from './Interactable'\nimport type { Options } from './options'\n\n/**\n * ```js\n * interact('#draggable').draggable(true)\n *\n * var rectables = interact('rect')\n * rectables\n *   .gesturable(true)\n *   .on('gesturemove', function (event) {\n *       // ...\n *   })\n * ```\n *\n * The methods of this variable can be used to set elements as interactables\n * and also to change various default settings.\n *\n * Calling it as a function and passing an element or a valid CSS selector\n * string returns an Interactable object which has various methods to configure\n * it.\n *\n * @param {Element | string} target The HTML or SVG Element to interact with\n * or CSS selector\n * @return {Interactable}\n */\nexport interface InteractStatic {\n  (target: Target, options?: Options): Interactable\n  getPointerAverage: typeof pointerUtils.pointerAverage\n  getTouchBBox: typeof pointerUtils.touchBBox\n  getTouchDistance: typeof pointerUtils.touchDistance\n  getTouchAngle: typeof pointerUtils.touchAngle\n  getElementRect: typeof domUtils.getElementRect\n  getElementClientRect: typeof domUtils.getElementClientRect\n  matchesSelector: typeof domUtils.matchesSelector\n  closest: typeof domUtils.closest\n  /** @internal */ globalEvents: any\n  version: string\n  /** @internal */ scope: Scope\n  /**\n   * Use a plugin\n   */\n  use(\n    plugin: Plugin,\n    options?: {\n      [key: string]: any\n    },\n  ): any\n  /**\n   * Check if an element or selector has been set with the `interact(target)`\n   * function\n   *\n   * @return {boolean} Indicates if the element or CSS selector was previously\n   * passed to interact\n   */\n  isSet(\n    /* The Element or string being searched for */\n    target: Target,\n    options?: any,\n  ): boolean\n  on(type: string | EventTypes, listener: ListenersArg, options?: object): any\n  off(type: EventTypes, listener: any, options?: object): any\n  debug(): any\n  /**\n   * Whether or not the browser supports touch input\n   */\n  supportsTouch(): boolean\n  /**\n   * Whether or not the browser supports PointerEvents\n   */\n  supportsPointerEvent(): boolean\n  /**\n   * Cancels all interactions (end events are not fired)\n   */\n  stop(): InteractStatic\n  /**\n   * Returns or sets the distance the pointer must be moved before an action\n   * sequence occurs. This also affects tolerance for tap events.\n   */\n  pointerMoveTolerance(\n    /** The movement from the start position must be greater than this value */\n    newValue?: number,\n  ): InteractStatic | number\n  addDocument(doc: Document, options?: object): void\n  removeDocument(doc: Document): void\n}\n\nexport function createInteractStatic(scope: Scope): InteractStatic {\n  const interact = ((target: Target, options: Options) => {\n    let interactable = scope.interactables.getExisting(target, options)\n\n    if (!interactable) {\n      interactable = scope.interactables.new(target, options)\n      interactable.events.global = interact.globalEvents\n    }\n\n    return interactable\n  }) as InteractStatic\n\n  // expose the functions used to calculate multi-touch properties\n  interact.getPointerAverage = pointerUtils.pointerAverage\n  interact.getTouchBBox = pointerUtils.touchBBox\n  interact.getTouchDistance = pointerUtils.touchDistance\n  interact.getTouchAngle = pointerUtils.touchAngle\n\n  interact.getElementRect = domUtils.getElementRect\n  interact.getElementClientRect = domUtils.getElementClientRect\n  interact.matchesSelector = domUtils.matchesSelector\n  interact.closest = domUtils.closest\n\n  interact.globalEvents = {} as any\n\n  // eslint-disable-next-line no-undef\n  interact.version = process.env.npm_package_version\n  interact.scope = scope\n  interact.use = function (plugin, options) {\n    this.scope.usePlugin(plugin, options)\n\n    return this\n  }\n\n  interact.isSet = function (target: Target, options?: { context?: Context }): boolean {\n    return !!this.scope.interactables.get(target, options && options.context)\n  }\n\n  interact.on = warnOnce(function on(type: string | EventTypes, listener: ListenersArg, options?: object) {\n    if (is.string(type) && type.search(' ') !== -1) {\n      type = type.trim().split(/ +/)\n    }\n\n    if (is.array(type)) {\n      for (const eventType of type as any[]) {\n        this.on(eventType, listener, options)\n      }\n\n      return this\n    }\n\n    if (is.object(type)) {\n      for (const prop in type) {\n        this.on(prop, (type as any)[prop], listener)\n      }\n\n      return this\n    }\n\n    // if it is an InteractEvent type, add listener to globalEvents\n    if (isNonNativeEvent(type, this.scope.actions)) {\n      // if this type of event was never bound\n      if (!this.globalEvents[type]) {\n        this.globalEvents[type] = [listener]\n      } else {\n        this.globalEvents[type].push(listener)\n      }\n    }\n    // If non InteractEvent type, addEventListener to document\n    else {\n      this.scope.events.add(this.scope.document, type, listener as Listener, { options })\n    }\n\n    return this\n  }, 'The interact.on() method is being deprecated')\n\n  interact.off = warnOnce(function off(type: EventTypes, listener: any, options?: object) {\n    if (is.string(type) && type.search(' ') !== -1) {\n      type = type.trim().split(/ +/)\n    }\n\n    if (is.array(type)) {\n      for (const eventType of type) {\n        this.off(eventType, listener, options)\n      }\n\n      return this\n    }\n\n    if (is.object(type)) {\n      for (const prop in type) {\n        this.off(prop, type[prop], listener)\n      }\n\n      return this\n    }\n\n    if (isNonNativeEvent(type, this.scope.actions)) {\n      let index: number\n\n      if (type in this.globalEvents && (index = this.globalEvents[type].indexOf(listener)) !== -1) {\n        this.globalEvents[type].splice(index, 1)\n      }\n    } else {\n      this.scope.events.remove(this.scope.document, type, listener, options)\n    }\n\n    return this\n  }, 'The interact.off() method is being deprecated')\n\n  interact.debug = function () {\n    return this.scope\n  }\n\n  interact.supportsTouch = function () {\n    return browser.supportsTouch\n  }\n\n  interact.supportsPointerEvent = function () {\n    return browser.supportsPointerEvent\n  }\n\n  interact.stop = function () {\n    for (const interaction of this.scope.interactions.list) {\n      interaction.stop()\n    }\n\n    return this\n  }\n\n  interact.pointerMoveTolerance = function (newValue?: number) {\n    if (is.number(newValue)) {\n      this.scope.interactions.pointerMoveTolerance = newValue\n\n      return this\n    }\n\n    return this.scope.interactions.pointerMoveTolerance\n  }\n\n  interact.addDocument = function (doc: Document, options?: object) {\n    this.scope.addDocument(doc, options)\n  }\n\n  interact.removeDocument = function (doc: Document) {\n    this.scope.removeDocument(doc)\n  }\n\n  return interact\n}\n"
  },
  {
    "path": "packages/@interactjs/core/Interactable.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\n\nimport * as helpers from './tests/_helpers'\n\ndescribe('core/Interactable', () => {\n  test('Interactable copies and extends defaults', () => {\n    const scope = helpers.mockScope() as any\n    const { defaults } = scope\n\n    scope.actions.methodDict = { test: 'testize' }\n\n    scope.Interactable.prototype.testize = function (options: any) {\n      this.setPerAction('test', options)\n    }\n\n    defaults.actions.test = {\n      fromDefault: { a: 1, b: 2 },\n      specified: { c: 1, d: 2 },\n    }\n\n    const specified = { specified: 'parent' }\n\n    const div = scope.document.createElement('div')\n    const interactable = scope.interactables.new(div, { test: specified })\n\n    // specified options are properly set\n    expect(interactable.options.test.specified).toEqual(specified.specified)\n    // default options are properly set\n    expect(interactable.options.test.fromDefault).toEqual(defaults.actions.test.fromDefault)\n    // defaults are not aliased\n    expect(interactable.options.test.fromDefault).not.toBe(defaults.actions.test.fromDefault)\n\n    defaults.actions.test.fromDefault.c = 3\n    // modifying defaults does not affect constructed interactables\n    expect('c' in interactable.options.test.fromDefault).not.toBe(true)\n    div.remove()\n  })\n\n  test('Interactable unset correctly', () => {\n    const scope = helpers.mockScope()\n\n    const div = scope.document.createElement('div')\n    const interactable = scope.interactables.new(div)\n\n    expect(div[scope.id]).toHaveLength(1)\n\n    interactable.unset()\n\n    // clears target mapping\n    expect(div[scope.id]).toHaveLength(0)\n\n    div.remove()\n  })\n\n  test('Interactable copies and extends per action defaults', () => {\n    const scope = helpers.mockScope()\n    const { defaults } = scope\n\n    scope.actions.methodDict = { test: 'testize' } as any\n    ;(scope.Interactable.prototype as any).testize = function (options: any) {\n      this.setPerAction('test', options)\n    }\n    ;(defaults.perAction as any).testOption = {\n      fromDefault: { a: 1, b: 2 },\n      specified: null,\n    }\n    ;(defaults.actions as any).test = { testOption: (defaults.perAction as any).testOption }\n\n    const div = scope.document.createElement('div')\n    const interactable = scope.interactables.new(div, {})\n    ;(interactable as any).testize({ testOption: { specified: 'parent' } })\n\n    // specified options are properly set\n    expect((interactable.options as any).test).toEqual({\n      enabled: false,\n      origin: { x: 0, y: 0 },\n\n      testOption: {\n        fromDefault: { a: 1, b: 2 },\n        specified: 'parent',\n      },\n    })\n    // default options are properly set\n    expect((interactable.options as any).test.testOption.fromDefault).toEqual(\n      (defaults.perAction as any).testOption.fromDefault,\n    )\n    // defaults are not aliased\n    expect((interactable.options as any).test.testOption.fromDefault).not.toBe(\n      (defaults.perAction as any).testOption.fromDefault,\n    )\n    ;(defaults.perAction as any).testOption.fromDefault.c = 3\n    // modifying defaults does not affect constructed interactables\n    expect('c' in (interactable.options as any).test.testOption.fromDefault).toBe(false)\n    div.remove()\n  })\n\n  test('Interactable.updatePerActionListeners', () => {\n    const scope = helpers.mockScope()\n\n    let fired: any[] = []\n    function addToFired(event: any) {\n      fired.push(event)\n    }\n\n    scope.actions.methodDict = { test: 'testize' } as any\n    ;(scope.Interactable.prototype as any).testize = function (options: any) {\n      this.setPerAction('test', options)\n    }\n    ;(scope.defaults.actions as any).test = {}\n\n    const interactable = scope.interactables.new('target')\n\n    interactable.setPerAction('test' as any, {\n      listeners: [\n        {\n          start: addToFired,\n          move: addToFired,\n          end: addToFired,\n        },\n      ],\n    })\n\n    interactable.fire({ type: 'teststart' })\n    expect(fired.map((e) => e.type)).toEqual(['teststart'])\n\n    interactable.fire({ type: 'testmove' })\n    expect(fired.map((e) => e.type)).toEqual(['teststart', 'testmove'])\n\n    interactable.fire({ type: 'testnotadded' })\n    expect(fired.map((e) => e.type)).toEqual(['teststart', 'testmove'])\n\n    interactable.fire({ type: 'testend' })\n    expect(fired.map((e) => e.type)).toEqual(['teststart', 'testmove', 'testend'])\n\n    fired = []\n    interactable.setPerAction('test' as any, {\n      listeners: [{ start: addToFired }],\n    })\n\n    interactable.fire({ type: 'teststart' })\n    interactable.fire({ type: 'testmove' })\n    interactable.fire({ type: 'testend' })\n    expect(fired.map((e) => e.type)).toEqual(['teststart'])\n\n    fired = []\n    interactable.setPerAction('test' as any, {\n      listeners: null,\n    })\n\n    interactable.fire({ type: 'teststart' })\n    interactable.fire({ type: 'testmove' })\n    interactable.fire({ type: 'testend' })\n    expect(fired).toEqual([])\n  })\n\n  test('Interactable.{on,off}', () => {\n    const { interactable: elInteractable, interact, target: element } = helpers.testEnv({ plugins: [drag] })\n\n    let fired: Array<{ type: any }> = []\n    const listener = (e: { type: any }) => fired.push(e)\n    const selectorInteractable = interact('html')\n\n    elInteractable.on('dragstart click', listener)\n    selectorInteractable.on('dragstart click change', listener)\n\n    elInteractable.fire({ type: 'dragstart' })\n    expect(fired).toHaveLength(1)\n    expect(fired[0].type).toBe('dragstart')\n\n    elInteractable.off('dragstart', listener)\n    fired = []\n    elInteractable.fire({ type: 'dragstart' })\n    expect(fired).toEqual([])\n\n    element.click()\n    expect(fired.map((e) => e.type)).toEqual(['click', 'click'])\n\n    selectorInteractable.off('click', listener)\n    fired = []\n    element.click()\n    expect(fired.map((e) => e.type)).toEqual(['click'])\n\n    fired = []\n    selectorInteractable.fire({ type: 'dragstart' })\n    expect(fired.map((e) => e.type)).toEqual(['dragstart'])\n\n    selectorInteractable.off('dragstart', listener)\n    fired = []\n    selectorInteractable.fire({ type: 'dragstart' })\n    expect(fired).toEqual([])\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/core/Interactable.ts",
    "content": "/* eslint-disable no-dupe-class-members */\nimport * as arr from '@interactjs/utils/arr'\nimport browser from '@interactjs/utils/browser'\nimport clone from '@interactjs/utils/clone'\nimport { getElementRect, matchesUpTo, nodeContains, trySelector } from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport isNonNativeEvent from '@interactjs/utils/isNonNativeEvent'\nimport normalizeListeners from '@interactjs/utils/normalizeListeners'\nimport { getWindow } from '@interactjs/utils/window'\n\nimport type { Scope } from '@interactjs/core/scope'\nimport type {\n  ActionMap,\n  ActionMethod,\n  ActionName,\n  Actions,\n  Context,\n  Element,\n  EventTypes,\n  Listeners,\n  ListenersArg,\n  OrBoolean,\n  Target,\n} from '@interactjs/core/types'\n\nimport { Eventable } from './Eventable'\nimport type { ActionDefaults, Defaults, OptionsArg, PerActionDefaults, Options } from './options'\n\ntype IgnoreValue = string | Element | boolean\ntype DeltaSource = 'page' | 'client'\n\nconst enum OnOffMethod {\n  On,\n  Off,\n}\n\n/**\n * ```ts\n * const interactable = interact('.cards')\n *   .draggable({\n *     listeners: { move: event => console.log(event.type, event.pageX, event.pageY) }\n *   })\n *   .resizable({\n *     listeners: { move: event => console.log(event.rect) },\n *     modifiers: [interact.modifiers.restrictEdges({ outer: 'parent' })]\n *   })\n * ```\n */\nexport class Interactable implements Partial<Eventable> {\n  /** @internal */ get _defaults(): Defaults {\n    return {\n      base: {},\n      perAction: {},\n      actions: {} as ActionDefaults,\n    }\n  }\n\n  readonly target: Target\n  /** @internal */ readonly options!: Required<Options>\n  /** @internal */ readonly _actions: Actions\n  /** @internal */ readonly events = new Eventable()\n  /** @internal */ readonly _context: Context\n  /** @internal */ readonly _win: Window\n  /** @internal */ readonly _doc: Document\n  /** @internal */ readonly _scopeEvents: Scope['events']\n\n  constructor(\n    target: Target,\n    options: any,\n    defaultContext: Document | Element,\n    scopeEvents: Scope['events'],\n  ) {\n    this._actions = options.actions\n    this.target = target\n    this._context = options.context || defaultContext\n    this._win = getWindow(trySelector(target) ? this._context : target)\n    this._doc = this._win.document\n    this._scopeEvents = scopeEvents\n\n    this.set(options)\n  }\n\n  setOnEvents(actionName: ActionName, phases: NonNullable<any>) {\n    if (is.func(phases.onstart)) {\n      this.on(`${actionName}start`, phases.onstart)\n    }\n    if (is.func(phases.onmove)) {\n      this.on(`${actionName}move`, phases.onmove)\n    }\n    if (is.func(phases.onend)) {\n      this.on(`${actionName}end`, phases.onend)\n    }\n    if (is.func(phases.oninertiastart)) {\n      this.on(`${actionName}inertiastart`, phases.oninertiastart)\n    }\n\n    return this\n  }\n\n  updatePerActionListeners(actionName: ActionName, prev: Listeners | undefined, cur: Listeners | undefined) {\n    const actionFilter = (this._actions.map[actionName] as { filterEventType?: (type: string) => boolean })\n      ?.filterEventType\n    const filter = (type: string) =>\n      (actionFilter == null || actionFilter(type)) && isNonNativeEvent(type, this._actions)\n\n    if (is.array(prev) || is.object(prev)) {\n      this._onOff(OnOffMethod.Off, actionName, prev, undefined, filter)\n    }\n\n    if (is.array(cur) || is.object(cur)) {\n      this._onOff(OnOffMethod.On, actionName, cur, undefined, filter)\n    }\n  }\n\n  setPerAction(actionName: ActionName, options: OrBoolean<Options>) {\n    const defaults = this._defaults\n\n    // for all the default per-action options\n    for (const optionName_ in options) {\n      const optionName = optionName_ as keyof PerActionDefaults\n      const actionOptions = this.options[actionName]\n      const optionValue: any = options[optionName]\n\n      // remove old event listeners and add new ones\n      if (optionName === 'listeners') {\n        this.updatePerActionListeners(actionName, actionOptions.listeners, optionValue as Listeners)\n      }\n\n      // if the option value is an array\n      if (is.array(optionValue)) {\n        ;(actionOptions[optionName] as any) = arr.from(optionValue)\n      }\n      // if the option value is an object\n      else if (is.plainObject(optionValue)) {\n        // copy the object\n        ;(actionOptions[optionName] as any) = extend(\n          actionOptions[optionName] || ({} as any),\n          clone(optionValue),\n        )\n\n        // set anabled field to true if it exists in the defaults\n        if (\n          is.object(defaults.perAction[optionName]) &&\n          'enabled' in (defaults.perAction[optionName] as any)\n        ) {\n          ;(actionOptions[optionName] as any).enabled = optionValue.enabled !== false\n        }\n      }\n      // if the option value is a boolean and the default is an object\n      else if (is.bool(optionValue) && is.object(defaults.perAction[optionName])) {\n        ;(actionOptions[optionName] as any).enabled = optionValue\n      }\n      // if it's anything else, do a plain assignment\n      else {\n        ;(actionOptions[optionName] as any) = optionValue\n      }\n    }\n  }\n\n  /**\n   * The default function to get an Interactables bounding rect. Can be\n   * overridden using {@link Interactable.rectChecker}.\n   *\n   * @param {Element} [element] The element to measure.\n   * @return {Rect} The object's bounding rectangle.\n   */\n  getRect(element: Element) {\n    element = element || (is.element(this.target) ? this.target : null)\n\n    if (is.string(this.target)) {\n      element = element || this._context.querySelector(this.target)\n    }\n\n    return getElementRect(element)\n  }\n\n  /**\n   * Returns or sets the function used to calculate the interactable's\n   * element's rectangle\n   *\n   * @param {function} [checker] A function which returns this Interactable's\n   * bounding rectangle. See {@link Interactable.getRect}\n   * @return {function | object} The checker function or this Interactable\n   */\n  rectChecker(): (element: Element) => any | null\n  rectChecker(checker: (element: Element) => any): this\n  rectChecker(checker?: (element: Element) => any) {\n    if (is.func(checker)) {\n      this.getRect = (element) => {\n        const rect = extend({}, checker.apply(this, element))\n\n        if (!(('width' in rect) as unknown)) {\n          rect.width = rect.right - rect.left\n          rect.height = rect.bottom - rect.top\n        }\n\n        return rect\n      }\n\n      return this\n    }\n\n    if (checker === null) {\n      delete (this as Partial<typeof this>).getRect\n\n      return this\n    }\n\n    return this.getRect\n  }\n\n  /** @internal */\n  _backCompatOption(optionName: keyof Options, newValue: any) {\n    if (trySelector(newValue) || is.object(newValue)) {\n      ;(this.options[optionName] as any) = newValue\n\n      for (const action in this._actions.map) {\n        ;(this.options[action as keyof ActionMap] as any)[optionName] = newValue\n      }\n\n      return this\n    }\n\n    return this.options[optionName]\n  }\n\n  /**\n   * Gets or sets the origin of the Interactable's element.  The x and y\n   * of the origin will be subtracted from action event coordinates.\n   *\n   * @param {Element | object | string} [origin] An HTML or SVG Element whose\n   * rect will be used, an object eg. { x: 0, y: 0 } or string 'parent', 'self'\n   * or any CSS selector\n   *\n   * @return {object} The current origin or this Interactable\n   */\n  origin(newValue: any) {\n    return this._backCompatOption('origin', newValue)\n  }\n\n  /**\n   * Returns or sets the mouse coordinate types used to calculate the\n   * movement of the pointer.\n   *\n   * @param {string} [newValue] Use 'client' if you will be scrolling while\n   * interacting; Use 'page' if you want autoScroll to work\n   * @return {string | object} The current deltaSource or this Interactable\n   */\n  deltaSource(): DeltaSource\n  deltaSource(newValue: DeltaSource): this\n  deltaSource(newValue?: DeltaSource) {\n    if (newValue === 'page' || newValue === 'client') {\n      this.options.deltaSource = newValue\n\n      return this\n    }\n\n    return this.options.deltaSource\n  }\n\n  /** @internal */\n  getAllElements(): Element[] {\n    const { target } = this\n\n    if (is.string(target)) {\n      return Array.from(this._context.querySelectorAll(target))\n    }\n\n    if (is.func(target) && (target as any).getAllElements) {\n      return (target as any).getAllElements()\n    }\n\n    return is.element(target) ? [target] : []\n  }\n\n  /**\n   * Gets the selector context Node of the Interactable. The default is\n   * `window.document`.\n   *\n   * @return {Node} The context Node of this Interactable\n   */\n  context() {\n    return this._context\n  }\n\n  inContext(element: Document | Node) {\n    return this._context === element.ownerDocument || nodeContains(this._context, element)\n  }\n\n  /** @internal */\n  testIgnoreAllow(\n    this: Interactable,\n    options: { ignoreFrom?: IgnoreValue; allowFrom?: IgnoreValue },\n    targetNode: Node,\n    eventTarget: Node,\n  ) {\n    return (\n      !this.testIgnore(options.ignoreFrom, targetNode, eventTarget) &&\n      this.testAllow(options.allowFrom, targetNode, eventTarget)\n    )\n  }\n\n  /** @internal */\n  testAllow(this: Interactable, allowFrom: IgnoreValue | undefined, targetNode: Node, element: Node) {\n    if (!allowFrom) {\n      return true\n    }\n\n    if (!is.element(element)) {\n      return false\n    }\n\n    if (is.string(allowFrom)) {\n      return matchesUpTo(element, allowFrom, targetNode)\n    } else if (is.element(allowFrom)) {\n      return nodeContains(allowFrom, element)\n    }\n\n    return false\n  }\n\n  /** @internal */\n  testIgnore(this: Interactable, ignoreFrom: IgnoreValue | undefined, targetNode: Node, element: Node) {\n    if (!ignoreFrom || !is.element(element)) {\n      return false\n    }\n\n    if (is.string(ignoreFrom)) {\n      return matchesUpTo(element, ignoreFrom, targetNode)\n    } else if (is.element(ignoreFrom)) {\n      return nodeContains(ignoreFrom, element)\n    }\n\n    return false\n  }\n\n  /**\n   * Calls listeners for the given InteractEvent type bound globally\n   * and directly to this Interactable\n   *\n   * @param {InteractEvent} iEvent The InteractEvent object to be fired on this\n   * Interactable\n   * @return {Interactable} this Interactable\n   */\n  fire<E extends { type: string }>(iEvent: E) {\n    this.events.fire(iEvent)\n\n    return this\n  }\n\n  /** @internal */\n  _onOff(\n    method: OnOffMethod,\n    typeArg: EventTypes,\n    listenerArg?: ListenersArg | null,\n    options?: any,\n    filter?: (type: string) => boolean,\n  ) {\n    if (is.object(typeArg) && !is.array(typeArg)) {\n      options = listenerArg\n      listenerArg = null\n    }\n\n    const listeners = normalizeListeners(typeArg, listenerArg, filter)\n\n    for (let type in listeners) {\n      if (type === 'wheel') {\n        type = browser.wheelEvent\n      }\n\n      for (const listener of listeners[type]) {\n        // if it is an action event type\n        if (isNonNativeEvent(type, this._actions)) {\n          this.events[method === OnOffMethod.On ? 'on' : 'off'](type, listener)\n        }\n        // delegated event\n        else if (is.string(this.target)) {\n          this._scopeEvents[method === OnOffMethod.On ? 'addDelegate' : 'removeDelegate'](\n            this.target,\n            this._context,\n            type,\n            listener,\n            options,\n          )\n        }\n        // remove listener from this Interactable's element\n        else {\n          this._scopeEvents[method === OnOffMethod.On ? 'add' : 'remove'](\n            this.target,\n            type,\n            listener,\n            options,\n          )\n        }\n      }\n    }\n\n    return this\n  }\n\n  /**\n   * Binds a listener for an InteractEvent, pointerEvent or DOM event.\n   *\n   * @param {string | array | object} types The types of events to listen\n   * for\n   * @param {function | array | object} [listener] The event listener function(s)\n   * @param {object | boolean} [options] options object or useCapture flag for\n   * addEventListener\n   * @return {Interactable} This Interactable\n   */\n  on(types: EventTypes, listener?: ListenersArg, options?: any) {\n    return this._onOff(OnOffMethod.On, types, listener, options)\n  }\n\n  /**\n   * Removes an InteractEvent, pointerEvent or DOM event listener.\n   *\n   * @param {string | array | object} types The types of events that were\n   * listened for\n   * @param {function | array | object} [listener] The event listener function(s)\n   * @param {object | boolean} [options] options object or useCapture flag for\n   * removeEventListener\n   * @return {Interactable} This Interactable\n   */\n  off(types: string | string[] | EventTypes, listener?: ListenersArg, options?: any) {\n    return this._onOff(OnOffMethod.Off, types, listener, options)\n  }\n\n  /**\n   * Reset the options of this Interactable\n   *\n   * @param {object} options The new settings to apply\n   * @return {object} This Interactable\n   */\n  set(options: OptionsArg) {\n    const defaults = this._defaults\n\n    if (!is.object(options)) {\n      options = {}\n    }\n\n    ;(this.options as Required<Options>) = clone(defaults.base) as Required<Options>\n\n    for (const actionName_ in this._actions.methodDict) {\n      const actionName = actionName_ as ActionName\n      const methodName = this._actions.methodDict[actionName]\n\n      this.options[actionName] = {}\n      this.setPerAction(actionName, extend(extend({}, defaults.perAction), defaults.actions[actionName]))\n      ;(this[methodName] as ActionMethod<unknown>)(options[actionName])\n    }\n\n    for (const setting in options) {\n      if (setting === 'getRect') {\n        this.rectChecker(options.getRect)\n        continue\n      }\n\n      if (is.func((this as any)[setting])) {\n        ;(this as any)[setting](options[setting as keyof typeof options])\n      }\n    }\n\n    return this\n  }\n\n  /**\n   * Remove this interactable from the list of interactables and remove it's\n   * action capabilities and event listeners\n   */\n  unset() {\n    if (is.string(this.target)) {\n      // remove delegated events\n      for (const type in this._scopeEvents.delegatedEvents) {\n        const delegated = this._scopeEvents.delegatedEvents[type]\n\n        for (let i = delegated.length - 1; i >= 0; i--) {\n          const { selector, context, listeners } = delegated[i]\n\n          if (selector === this.target && context === this._context) {\n            delegated.splice(i, 1)\n          }\n\n          for (let l = listeners.length - 1; l >= 0; l--) {\n            this._scopeEvents.removeDelegate(\n              this.target,\n              this._context,\n              type,\n              listeners[l][0],\n              listeners[l][1],\n            )\n          }\n        }\n      }\n    } else {\n      this._scopeEvents.remove(this.target, 'all')\n    }\n  }\n}\n"
  },
  {
    "path": "packages/@interactjs/core/InteractableSet.ts",
    "content": "import * as arr from '@interactjs/utils/arr'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\n\nimport type { Interactable } from '@interactjs/core/Interactable'\nimport type { OptionsArg, Options } from '@interactjs/core/options'\nimport type { Scope } from '@interactjs/core/scope'\nimport type { Target } from '@interactjs/core/types'\n\ndeclare module '@interactjs/core/scope' {\n  interface SignalArgs {\n    'interactable:new': {\n      interactable: Interactable\n      target: Target\n      options: OptionsArg\n      win: Window\n    }\n  }\n}\n\nexport class InteractableSet {\n  // all set interactables\n  list: Interactable[] = []\n\n  selectorMap: {\n    [selector: string]: Interactable[]\n  } = {}\n\n  scope: Scope\n\n  constructor(scope: Scope) {\n    this.scope = scope\n    scope.addListeners({\n      'interactable:unset': ({ interactable }) => {\n        const { target } = interactable\n        const interactablesOnTarget: Interactable[] = is.string(target)\n          ? this.selectorMap[target]\n          : (target as any)[this.scope.id]\n\n        const targetIndex = arr.findIndex(interactablesOnTarget, (i) => i === interactable)\n        interactablesOnTarget.splice(targetIndex, 1)\n      },\n    })\n  }\n\n  new(target: Target, options?: any): Interactable {\n    options = extend(options || {}, {\n      actions: this.scope.actions,\n    })\n    const interactable = new this.scope.Interactable(target, options, this.scope.document, this.scope.events)\n\n    this.scope.addDocument(interactable._doc)\n    this.list.push(interactable)\n\n    if (is.string(target)) {\n      if (!this.selectorMap[target]) {\n        this.selectorMap[target] = []\n      }\n      this.selectorMap[target].push(interactable)\n    } else {\n      if (!(interactable.target as any)[this.scope.id]) {\n        Object.defineProperty(target, this.scope.id, {\n          value: [],\n          configurable: true,\n        })\n      }\n\n      ;(target as any)[this.scope.id].push(interactable)\n    }\n\n    this.scope.fire('interactable:new', {\n      target,\n      options,\n      interactable,\n      win: this.scope._win,\n    })\n\n    return interactable\n  }\n\n  getExisting(target: Target, options?: Options) {\n    const context = (options && options.context) || this.scope.document\n    const isSelector = is.string(target)\n    const interactablesOnTarget: Interactable[] = isSelector\n      ? this.selectorMap[target as string]\n      : (target as any)[this.scope.id]\n\n    if (!interactablesOnTarget) return undefined\n\n    return arr.find(\n      interactablesOnTarget,\n      (interactable) =>\n        interactable._context === context && (isSelector || interactable.inContext(target as any)),\n    )\n  }\n\n  forEachMatch<T>(node: Node, callback: (interactable: Interactable) => T): T | void {\n    for (const interactable of this.list) {\n      let ret: T\n\n      if (\n        (is.string(interactable.target)\n          ? // target is a selector and the element matches\n            is.element(node) && domUtils.matchesSelector(node, interactable.target)\n          : // target is the element\n            node === interactable.target) &&\n        // the element is in context\n        interactable.inContext(node)\n      ) {\n        ret = callback(interactable)\n      }\n\n      if (ret !== undefined) {\n        return ret\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/@interactjs/core/Interaction.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\nimport drop from '@interactjs/actions/drop/plugin'\nimport autoStart from '@interactjs/auto-start/base'\nimport extend from '@interactjs/utils/extend'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport type { PointerType } from '@interactjs/core/types'\n\nimport type { EventPhase } from './InteractEvent'\nimport { InteractEvent } from './InteractEvent'\nimport { Interaction } from './Interaction'\nimport * as helpers from './tests/_helpers'\n\ndescribe('core/Interaction', () => {\n  test('constructor', () => {\n    const testType = 'test'\n    const dummyScopeFire = () => {}\n    const interaction = new Interaction({\n      pointerType: testType,\n      scopeFire: dummyScopeFire,\n    })\n    const zeroCoords = {\n      page: { x: 0, y: 0 },\n      client: { x: 0, y: 0 },\n      timeStamp: 0,\n    }\n\n    // scopeFire option is set assigned to interaction._scopeFire\n    expect(interaction._scopeFire).toBe(dummyScopeFire)\n\n    expect(interaction.prepared).toEqual(expect.any(Object))\n    expect(interaction.downPointer).toEqual(expect.any(Object))\n\n    // `interaction.coords.${coordField} set to zero`\n    expect(interaction.coords).toEqual({\n      start: zeroCoords,\n      cur: zeroCoords,\n      prev: zeroCoords,\n      delta: zeroCoords,\n      velocity: zeroCoords,\n    })\n\n    // interaction.pointerType is set\n    expect(interaction.pointerType).toBe(testType)\n    // interaction.pointers is initially an empty array\n    expect(interaction.pointers).toEqual([])\n    // false properties\n    expect(interaction).toMatchObject({ pointerIsDown: false, pointerWasMoved: false, _interacting: false })\n    expect(interaction.pointerType).not.toBe('mouse')\n  })\n\n  test('Interaction destroy', () => {\n    const { interaction } = helpers.testEnv()\n    const pointer = { pointerId: 10 } as any\n    const event = {} as any\n\n    interaction.updatePointer(pointer, event, null)\n\n    interaction.destroy()\n\n    // interaction._latestPointer.pointer is null\n    expect(interaction._latestPointer.pointer).toBeNull()\n\n    // interaction._latestPointer.event is null\n    expect(interaction._latestPointer.event).toBeNull()\n\n    // interaction._latestPointer.eventTarget is null\n    expect(interaction._latestPointer.eventTarget).toBeNull()\n  })\n\n  test('Interaction.getPointerIndex', () => {\n    const { interaction } = helpers.testEnv()\n\n    interaction.pointers = [2, 4, 5, 0, -1].map((id) => ({ id })) as any\n\n    interaction.pointers.forEach(({ id }, index) => {\n      expect(interaction.getPointerIndex({ pointerId: id } as any)).toBe(index)\n    })\n  })\n\n  describe('Interaction.updatePointer', () => {\n    test('no existing pointers', () => {\n      const { interaction } = helpers.testEnv()\n      const pointer = { pointerId: 10 } as any\n      const event = {} as any\n\n      const ret = interaction.updatePointer(pointer, event, null)\n\n      // interaction.pointers == [{ pointer, ... }]\n      expect(interaction.pointers).toEqual([\n        {\n          id: pointer.pointerId,\n          pointer,\n          event,\n          downTime: null,\n          downTarget: null,\n        },\n      ])\n      // new pointer index is returned\n      expect(ret).toBe(0)\n    })\n\n    test('new pointer with exisiting pointer', () => {\n      const { interaction } = helpers.testEnv()\n      const existing: any = { pointerId: 0 }\n      const event: any = {}\n\n      interaction.updatePointer(existing, event, null)\n\n      const newPointer: any = { pointerId: 10 }\n      const ret = interaction.updatePointer(newPointer, event, null)\n\n      // interaction.pointers == [{ pointer: existing, ... }, { pointer: newPointer, ... }]\n      expect(interaction.pointers).toEqual([\n        {\n          id: existing.pointerId,\n          pointer: existing,\n          event,\n          downTime: null,\n          downTarget: null,\n        },\n        {\n          id: newPointer.pointerId,\n          pointer: newPointer,\n          event,\n          downTime: null,\n          downTarget: null,\n        },\n      ])\n\n      // second pointer index is 1\n      expect(ret).toBe(1)\n    })\n\n    test('update existing pointers', () => {\n      const { interaction } = helpers.testEnv()\n\n      const oldPointers = [-3, 10, 2].map((pointerId) => ({ pointerId }))\n      const newPointers = oldPointers.map((pointer) => ({ ...pointer, new: true }))\n\n      oldPointers.forEach((pointer: any) => interaction.updatePointer(pointer, pointer, null))\n      newPointers.forEach((pointer: any) => interaction.updatePointer(pointer, pointer, null))\n\n      // number of pointers is unchanged\n      expect(interaction.pointers).toHaveLength(oldPointers.length)\n\n      interaction.pointers.forEach((pointerInfo, i) => {\n        // `pointer[${i}].id is the same`\n        expect(pointerInfo.id).toBe(oldPointers[i].pointerId)\n        // `new pointer ${i} !== old pointer object`\n        expect(pointerInfo.pointer).not.toBe(oldPointers[i])\n      })\n    })\n  })\n\n  test('Interaction.removePointer', () => {\n    const { interaction } = helpers.testEnv()\n    const ids = [0, 1, 2, 3]\n    const removals = [\n      { id: 0, remain: [1, 2, 3], message: 'first of 4' },\n      { id: 2, remain: [1, 3], message: 'middle of 3' },\n      { id: 3, remain: [1], message: 'last of 2' },\n      { id: 1, remain: [], message: 'final' },\n    ]\n\n    ids.forEach((pointerId) => interaction.updatePointer({ pointerId } as any, {} as any, null))\n\n    for (const removal of removals) {\n      interaction.removePointer({ pointerId: removal.id } as PointerType, null)\n\n      // `${removal.message} - remaining interaction.pointers is correct`\n      expect(interaction.pointers.map((p) => p.id)).toEqual(removal.remain)\n    }\n  })\n\n  test('Interaction.pointer{Down,Move,Up} updatePointer', () => {\n    const { scope, interaction } = helpers.testEnv()\n    const eventTarget: any = {}\n    const pointer: any = {\n      target: eventTarget,\n      pointerId: 0,\n    }\n    let info: any = {}\n\n    scope.addListeners({\n      'interactions:update-pointer': (arg) => {\n        info.updated = arg.pointerInfo\n      },\n      'interactions:remove-pointer': (arg) => {\n        info.removed = arg.pointerInfo\n      },\n    })\n\n    interaction.coords.cur.timeStamp = 0\n    const commonPointerInfo: any = {\n      id: 0,\n      pointer,\n      event: pointer,\n      downTime: null,\n      downTarget: null,\n    }\n\n    interaction.pointerDown(pointer, pointer, eventTarget)\n    // interaction.pointerDown updates pointer\n    expect(info.updated).toEqual({\n      ...commonPointerInfo,\n      downTime: interaction.coords.cur.timeStamp,\n      downTarget: eventTarget,\n    })\n    // interaction.pointerDown doesn't remove pointer\n    expect(info.removed).toBeUndefined()\n    interaction.removePointer(pointer, null)\n    info = {}\n\n    interaction.pointerMove(pointer, pointer, eventTarget)\n    // interaction.pointerMove updates pointer\n    expect(info.updated).toEqual(commonPointerInfo)\n    // interaction.pointerMove doesn't remove pointer\n    expect(info.removed).toBeUndefined()\n    info = {}\n\n    interaction.pointerUp(pointer, pointer, eventTarget, null)\n    // interaction.pointerUp doesn't update existing pointer\n    expect(info.updated).toBeUndefined()\n    info = {}\n\n    interaction.pointerUp(pointer, pointer, eventTarget, null)\n    // interaction.pointerUp updates non existing pointer\n    expect(info.updated).toEqual(commonPointerInfo)\n    // interaction.pointerUp also removes pointer\n    expect(info.removed).toEqual(commonPointerInfo)\n    info = {}\n  })\n\n  test('Interaction.pointerDown', () => {\n    const { interaction, scope, coords, event, target } = helpers.testEnv()\n    let signalArg: any\n\n    const coordsSet = helpers.newCoordsSet()\n    scope.now = () => coords.timeStamp\n\n    extend(coords, {\n      target,\n      type: 'down',\n    })\n\n    const signalListener = (arg: any) => {\n      signalArg = arg\n    }\n\n    scope.addListeners({\n      'interactions:down': signalListener,\n    })\n\n    const pointerCoords: any = { page: {}, client: {} }\n    pointerUtils.setCoords(pointerCoords, [event], event.timeStamp)\n\n    for (const prop in coordsSet) {\n      pointerUtils.copyCoords(\n        interaction.coords[prop as keyof typeof coordsSet],\n        coordsSet[prop as keyof typeof coordsSet],\n      )\n    }\n\n    // downPointer is initially empty\n    expect(interaction.downPointer).toEqual({} as any)\n\n    // test while interacting\n    interaction._interacting = true\n    interaction.pointerDown(event, event, target)\n\n    // downEvent is not updated\n    expect(interaction.downEvent).toBeNull()\n    // pointer is added\n    expect(interaction.pointers).toEqual([\n      {\n        id: event.pointerId,\n        event,\n        pointer: event,\n        downTime: 0,\n        downTarget: target,\n      },\n    ])\n\n    // downPointer is updated\n    expect(interaction.downPointer).not.toEqual({} as any)\n\n    // coords.start are not modified\n    expect(interaction.coords.start).toEqual(coordsSet.start)\n    // coords.prev  are not modified\n    expect(interaction.coords.prev).toEqual(coordsSet.prev)\n\n    // coords.cur   *are* modified\n    expect(interaction.coords.cur).toEqual(helpers.getProps(event, ['page', 'client', 'timeStamp']))\n\n    // pointerIsDown\n    expect(interaction.pointerIsDown).toBe(true)\n    // !pointerWasMoved\n    expect(interaction.pointerWasMoved).toBe(false)\n\n    // pointer      in down signal arg\n    expect(signalArg.pointer).toBe(event)\n    // event        in down signal arg\n    expect(signalArg.event).toBe(event)\n    // eventTarget  in down signal arg\n    expect(signalArg.eventTarget).toBe(target)\n    // pointerIndex in down signal arg\n    expect(signalArg.pointerIndex).toBe(0)\n\n    // test while not interacting\n    interaction._interacting = false\n    // reset pointerIsDown\n    interaction.pointerIsDown = false\n    // pretend pointer was moved\n    interaction.pointerWasMoved = true\n    // reset signalArg object\n    signalArg = undefined\n\n    interaction.removePointer(event, null)\n    interaction.pointerDown(event, event, target)\n\n    // timeStamp is assigned with new Date.getTime()\n    // don't let it cause deepEaual to fail\n    pointerCoords.timeStamp = interaction.coords.start.timeStamp\n\n    // downEvent is updated\n    expect(interaction.downEvent).toBe(event)\n\n    // interaction.pointers is updated\n    expect(interaction.pointers).toEqual([\n      {\n        id: event.pointerId,\n        event,\n        pointer: event,\n        downTime: pointerCoords.timeStamp,\n        downTarget: target,\n      },\n    ])\n\n    // coords.start are set to pointer\n    expect(interaction.coords.start).toEqual(pointerCoords)\n    // coords.cur   are set to pointer\n    expect(interaction.coords.cur).toEqual(pointerCoords)\n    // coords.prev  are set to pointer\n    expect(interaction.coords.prev).toEqual(pointerCoords)\n\n    // down signal was fired again\n    expect(signalArg).toBeInstanceOf(Object)\n    // pointerIsDown\n    expect(interaction.pointerIsDown).toBe(true)\n    // pointerWasMoved should always change to false\n    expect(interaction.pointerWasMoved).toBe(false)\n  })\n\n  test('Interaction.start', () => {\n    const {\n      interaction,\n      interactable,\n      scope,\n      event,\n      target: element,\n      down,\n      stop,\n    } = helpers.testEnv({\n      plugins: [drag],\n    })\n    const action = { name: 'drag' } as const\n\n    interaction.start(action, interactable, element)\n    // do nothing if !pointerIsDown\n    expect(interaction.prepared.name).toBeNull()\n\n    // pointers is still empty\n    interaction.pointerIsDown = true\n    interaction.start(action, interactable, element)\n    // do nothing if too few pointers are down\n    expect(interaction.prepared.name).toBeNull()\n\n    down()\n\n    interaction._interacting = true\n    interaction.start(action, interactable, element)\n    // do nothing if already interacting\n    expect(interaction.prepared.name).toBeNull()\n\n    interaction._interacting = false\n\n    interactable.options[action.name] = { enabled: false }\n    interaction.start(action, interactable, element)\n    // do nothing if action is not enabled\n    expect(interaction.prepared.name).toBeNull()\n    interactable.options[action.name] = { enabled: true }\n\n    let signalArg: any\n\n    // let interactingInStartListener\n    const signalListener = (arg: any) => {\n      signalArg = arg\n      // interactingInStartListener = arg.interaction.interacting()\n    }\n\n    scope.addListeners({\n      'interactions:action-start': signalListener,\n    })\n    interaction.start(action, interactable, element)\n\n    // action is prepared\n    expect(interaction.prepared.name).toBe(action.name)\n    // interaction.interactable is updated\n    expect(interaction.interactable).toBe(interactable)\n    // interaction.element is updated\n    expect(interaction.element).toBe(element)\n\n    // t.assert(interactingInStartListener, 'interaction is interacting during action-start signal')\n    // interaction is interacting after start method\n    expect(interaction.interacting()).toBe(true)\n    // interaction in signal arg\n    expect(signalArg.interaction).toBe(interaction)\n    // event (interaction.downEvent) in signal arg\n    expect(signalArg.event).toBe(event)\n\n    stop()\n  })\n\n  test('interaction move() and stop() from start event', () => {\n    const { interaction, interactable, target, down } = helpers.testEnv({ plugins: [drag, drop, autoStart] })\n\n    let stoppedBeforeStartFired: boolean\n\n    interactable.draggable({\n      listeners: {\n        start(event) {\n          stoppedBeforeStartFired = interaction._stopped\n\n          // interaction.move() doesn't throw from start event\n          expect(() => event.interaction.move()).not.toThrow()\n\n          // interaction.stop() doesn't throw from start event\n          expect(() => event.interaction.stop()).not.toThrow()\n        },\n      },\n    })\n\n    down()\n    interaction.start({ name: 'drag' }, interactable, target as HTMLElement)\n\n    // !interaction._stopped in start listener\n    expect(stoppedBeforeStartFired).toBe(false)\n    // interaction can be stopped from start event listener\n    expect(interaction.interacting()).toBe(false)\n    // interaction._stopped after stop() in start listener\n    expect(interaction._stopped).toBe(true)\n  })\n\n  test('Interaction createPreparedEvent', () => {\n    const { interaction, interactable, target } = helpers.testEnv()\n\n    const action = { name: 'resize' } as const\n    const phase = 'TEST_PHASE' as EventPhase\n\n    interaction.prepared = action\n    interaction.interactable = interactable\n    interaction.element = target\n    interaction.prevEvent = { page: {}, client: {}, velocity: {} } as any\n\n    const iEvent = interaction._createPreparedEvent({} as any, phase)\n\n    expect(iEvent).toBeInstanceOf(InteractEvent)\n\n    expect(iEvent.type).toBe(action.name + phase)\n\n    expect(iEvent.interactable).toBe(interactable)\n\n    expect(iEvent.target).toBe(interactable.target)\n  })\n\n  test('Interaction fireEvent', () => {\n    const { interaction, interactable } = helpers.testEnv()\n    const iEvent = {} as InteractEvent\n\n    // this method should be called from actions.firePrepared\n    interactable.fire = jest.fn()\n\n    interaction.interactable = interactable\n    interaction._fireEvent(iEvent)\n\n    // target interactable's fire method is called\n    expect(interactable.fire).toHaveBeenCalledWith(iEvent)\n\n    // interaction.prevEvent is updated\n    expect(interaction.prevEvent).toBe(iEvent)\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/core/Interaction.ts",
    "content": "import * as arr from '@interactjs/utils/arr'\nimport extend from '@interactjs/utils/extend'\nimport hypot from '@interactjs/utils/hypot'\nimport { warnOnce, copyAction } from '@interactjs/utils/misc'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport type {\n  Element,\n  EdgeOptions,\n  PointerEventType,\n  PointerType,\n  FullRect,\n  CoordsSet,\n  ActionName,\n  ActionProps,\n} from '@interactjs/core/types'\n\nimport type { Interactable } from './Interactable'\nimport type { EventPhase } from './InteractEvent'\nimport { InteractEvent } from './InteractEvent'\nimport type { ActionDefaults } from './options'\nimport { PointerInfo } from './PointerInfo'\nimport type { Scope } from './scope'\n\nexport enum _ProxyValues {\n  interactable = '',\n  element = '',\n  prepared = '',\n  pointerIsDown = '',\n  pointerWasMoved = '',\n  _proxy = '',\n}\n\nexport enum _ProxyMethods {\n  start = '',\n  move = '',\n  end = '',\n  stop = '',\n  interacting = '',\n}\n\nexport type PointerArgProps<T extends {} = {}> = {\n  pointer: PointerType\n  event: PointerEventType\n  eventTarget: Node\n  pointerIndex: number\n  pointerInfo: PointerInfo\n  interaction: Interaction<never>\n} & T\n\nexport interface DoPhaseArg<T extends ActionName, P extends EventPhase> {\n  event: PointerEventType\n  phase: EventPhase\n  interaction: Interaction<T>\n  iEvent: InteractEvent<T, P>\n  preEnd?: boolean\n  type?: string\n}\n\nexport type DoAnyPhaseArg = DoPhaseArg<ActionName, EventPhase>\n\ndeclare module '@interactjs/core/scope' {\n  interface SignalArgs {\n    'interactions:new': { interaction: Interaction<ActionName> }\n    'interactions:down': PointerArgProps<{\n      type: 'down'\n    }>\n    'interactions:move': PointerArgProps<{\n      type: 'move'\n      dx: number\n      dy: number\n      duplicate: boolean\n    }>\n    'interactions:up': PointerArgProps<{\n      type: 'up'\n      curEventTarget: EventTarget\n    }>\n    'interactions:cancel': SignalArgs['interactions:up'] & {\n      type: 'cancel'\n      curEventTarget: EventTarget\n    }\n    'interactions:update-pointer': PointerArgProps<{\n      down: boolean\n    }>\n    'interactions:remove-pointer': PointerArgProps\n    'interactions:blur': { interaction: Interaction<never>; event: Event; type: 'blur' }\n    'interactions:before-action-start': Omit<DoAnyPhaseArg, 'iEvent'>\n    'interactions:action-start': DoAnyPhaseArg\n    'interactions:after-action-start': DoAnyPhaseArg\n    'interactions:before-action-move': Omit<DoAnyPhaseArg, 'iEvent'>\n    'interactions:action-move': DoAnyPhaseArg\n    'interactions:after-action-move': DoAnyPhaseArg\n    'interactions:before-action-end': Omit<DoAnyPhaseArg, 'iEvent'>\n    'interactions:action-end': DoAnyPhaseArg\n    'interactions:after-action-end': DoAnyPhaseArg\n    'interactions:stop': { interaction: Interaction }\n  }\n}\n\nexport type InteractionProxy<T extends ActionName | null = never> = Pick<\n  Interaction<T>,\n  Exclude<keyof typeof _ProxyValues | keyof typeof _ProxyMethods, '_proxy'>\n>\n\nlet idCounter = 0\n\nexport class Interaction<T extends ActionName | null = ActionName> {\n  /** current interactable being interacted with */\n  interactable: Interactable | null = null\n\n  /** the target element of the interactable */\n  element: Element | null = null\n  rect: FullRect | null = null\n  /** @internal */\n  _rects?: {\n    start: FullRect\n    corrected: FullRect\n    previous: FullRect\n    delta: FullRect\n  }\n  /** @internal */\n  edges: EdgeOptions | null = null\n\n  /** @internal */\n  _scopeFire: Scope['fire']\n\n  // action that's ready to be fired on next move event\n  prepared: ActionProps<T> = {\n    name: null,\n    axis: null,\n    edges: null,\n  }\n\n  pointerType: string\n\n  /** @internal keep track of added pointers */\n  pointers: PointerInfo[] = []\n\n  /** @internal pointerdown/mousedown/touchstart event */\n  downEvent: PointerEventType | null = null\n\n  /** @internal */ downPointer: PointerType = {} as PointerType\n\n  /** @internal */\n  _latestPointer: {\n    pointer: PointerType\n    event: PointerEventType\n    eventTarget: Node\n  } = {\n    pointer: null,\n    event: null,\n    eventTarget: null,\n  }\n\n  /** @internal */ prevEvent: InteractEvent<T, EventPhase> = null\n\n  pointerIsDown = false\n  pointerWasMoved = false\n  /** @internal */ _interacting = false\n  /** @internal */ _ending = false\n  /** @internal */ _stopped = true\n  /** @internal */ _proxy: InteractionProxy<T>\n\n  /** @internal */ simulation = null\n\n  /** @internal */ get pointerMoveTolerance() {\n    return 1\n  }\n\n  doMove = warnOnce(function (this: Interaction, signalArg: any) {\n    this.move(signalArg)\n  }, 'The interaction.doMove() method has been renamed to interaction.move()')\n\n  coords: CoordsSet = {\n    // Starting InteractEvent pointer coordinates\n    start: pointerUtils.newCoords(),\n    // Previous native pointer move event coordinates\n    prev: pointerUtils.newCoords(),\n    // current native pointer move event coordinates\n    cur: pointerUtils.newCoords(),\n    // Change in coordinates and time of the pointer\n    delta: pointerUtils.newCoords(),\n    // pointer velocity\n    velocity: pointerUtils.newCoords(),\n  }\n\n  /** @internal */ readonly _id: number = idCounter++\n\n  constructor({ pointerType, scopeFire }: { pointerType?: string; scopeFire: Scope['fire'] }) {\n    this._scopeFire = scopeFire\n    this.pointerType = pointerType\n\n    const that = this\n\n    this._proxy = {} as InteractionProxy<T>\n\n    for (const key in _ProxyValues) {\n      Object.defineProperty(this._proxy, key, {\n        get() {\n          return that[key]\n        },\n      })\n    }\n\n    for (const key in _ProxyMethods) {\n      Object.defineProperty(this._proxy, key, {\n        value: (...args: any[]) => that[key](...args),\n      })\n    }\n\n    this._scopeFire('interactions:new', { interaction: this })\n  }\n\n  pointerDown(pointer: PointerType, event: PointerEventType, eventTarget: Node) {\n    const pointerIndex = this.updatePointer(pointer, event, eventTarget, true)\n    const pointerInfo = this.pointers[pointerIndex]\n\n    this._scopeFire('interactions:down', {\n      pointer,\n      event,\n      eventTarget,\n      pointerIndex,\n      pointerInfo,\n      type: 'down',\n      interaction: this as unknown as Interaction<never>,\n    })\n  }\n\n  /**\n   * ```js\n   * interact(target)\n   *   .draggable({\n   *     // disable the default drag start by down->move\n   *     manualStart: true\n   *   })\n   *   // start dragging after the user holds the pointer down\n   *   .on('hold', function (event) {\n   *     var interaction = event.interaction\n   *\n   *     if (!interaction.interacting()) {\n   *       interaction.start({ name: 'drag' },\n   *                         event.interactable,\n   *                         event.currentTarget)\n   *     }\n   * })\n   * ```\n   *\n   * Start an action with the given Interactable and Element as tartgets. The\n   * action must be enabled for the target Interactable and an appropriate\n   * number of pointers must be held down - 1 for drag/resize, 2 for gesture.\n   *\n   * Use it with `interactable.<action>able({ manualStart: false })` to always\n   * [start actions manually](https://github.com/taye/interact.js/issues/114)\n   *\n   * @param action - The action to be performed - drag, resize, etc.\n   * @param target - The Interactable to target\n   * @param element - The DOM Element to target\n   * @returns Whether the interaction was successfully started\n   */\n  start<A extends ActionName>(action: ActionProps<A>, interactable: Interactable, element: Element): boolean {\n    if (\n      this.interacting() ||\n      !this.pointerIsDown ||\n      this.pointers.length < (action.name === 'gesture' ? 2 : 1) ||\n      !interactable.options[action.name as keyof ActionDefaults].enabled\n    ) {\n      return false\n    }\n\n    copyAction(this.prepared, action)\n\n    this.interactable = interactable\n    this.element = element\n    this.rect = interactable.getRect(element)\n    this.edges = this.prepared.edges\n      ? extend({}, this.prepared.edges)\n      : { left: true, right: true, top: true, bottom: true }\n    this._stopped = false\n    this._interacting =\n      this._doPhase({\n        interaction: this,\n        event: this.downEvent,\n        phase: 'start',\n      }) && !this._stopped\n\n    return this._interacting\n  }\n\n  pointerMove(pointer: PointerType, event: PointerEventType, eventTarget: Node) {\n    if (!this.simulation && !(this.modification && this.modification.endResult)) {\n      this.updatePointer(pointer, event, eventTarget, false)\n    }\n\n    const duplicateMove =\n      this.coords.cur.page.x === this.coords.prev.page.x &&\n      this.coords.cur.page.y === this.coords.prev.page.y &&\n      this.coords.cur.client.x === this.coords.prev.client.x &&\n      this.coords.cur.client.y === this.coords.prev.client.y\n\n    let dx: number\n    let dy: number\n\n    // register movement greater than pointerMoveTolerance\n    if (this.pointerIsDown && !this.pointerWasMoved) {\n      dx = this.coords.cur.client.x - this.coords.start.client.x\n      dy = this.coords.cur.client.y - this.coords.start.client.y\n\n      this.pointerWasMoved = hypot(dx, dy) > this.pointerMoveTolerance\n    }\n\n    const pointerIndex = this.getPointerIndex(pointer)\n    const signalArg = {\n      pointer,\n      pointerIndex,\n      pointerInfo: this.pointers[pointerIndex],\n      event,\n      type: 'move' as const,\n      eventTarget,\n      dx,\n      dy,\n      duplicate: duplicateMove,\n      interaction: this as unknown as Interaction<never>,\n    }\n\n    if (!duplicateMove) {\n      // set pointer coordinate, time changes and velocity\n      pointerUtils.setCoordVelocity(this.coords.velocity, this.coords.delta)\n    }\n\n    this._scopeFire('interactions:move', signalArg)\n\n    if (!duplicateMove && !this.simulation) {\n      // if interacting, fire an 'action-move' signal etc\n      if (this.interacting()) {\n        signalArg.type = null\n        this.move(signalArg)\n      }\n\n      if (this.pointerWasMoved) {\n        pointerUtils.copyCoords(this.coords.prev, this.coords.cur)\n      }\n    }\n  }\n\n  /**\n   * ```js\n   * interact(target)\n   *   .draggable(true)\n   *   .on('dragmove', function (event) {\n   *     if (someCondition) {\n   *       // change the snap settings\n   *       event.interactable.draggable({ snap: { targets: [] }})\n   *       // fire another move event with re-calculated snap\n   *       event.interaction.move()\n   *     }\n   *   })\n   * ```\n   *\n   * Force a move of the current action at the same coordinates. Useful if\n   * snap/restrict has been changed and you want a movement with the new\n   * settings.\n   */\n  move(signalArg?: any) {\n    if (!signalArg || !signalArg.event) {\n      pointerUtils.setZeroCoords(this.coords.delta)\n    }\n\n    signalArg = extend(\n      {\n        pointer: this._latestPointer.pointer,\n        event: this._latestPointer.event,\n        eventTarget: this._latestPointer.eventTarget,\n        interaction: this,\n      },\n      signalArg || {},\n    )\n\n    signalArg.phase = 'move'\n\n    this._doPhase(signalArg)\n  }\n\n  /**\n   * @internal\n   * End interact move events and stop auto-scroll unless simulation is running\n   */\n  pointerUp(pointer: PointerType, event: PointerEventType, eventTarget: Node, curEventTarget: EventTarget) {\n    let pointerIndex = this.getPointerIndex(pointer)\n\n    if (pointerIndex === -1) {\n      pointerIndex = this.updatePointer(pointer, event, eventTarget, false)\n    }\n\n    const type = /cancel$/i.test(event.type) ? 'cancel' : 'up'\n\n    this._scopeFire(`interactions:${type}` as 'interactions:up' | 'interactions:cancel', {\n      pointer,\n      pointerIndex,\n      pointerInfo: this.pointers[pointerIndex],\n      event,\n      eventTarget,\n      type: type as any,\n      curEventTarget,\n      interaction: this as unknown as Interaction<never>,\n    })\n\n    if (!this.simulation) {\n      this.end(event)\n    }\n\n    this.removePointer(pointer, event)\n  }\n\n  /** @internal */\n  documentBlur(event: Event) {\n    this.end(event as any)\n    this._scopeFire('interactions:blur', {\n      event,\n      type: 'blur',\n      interaction: this as unknown as Interaction<never>,\n    })\n  }\n\n  /**\n   * ```js\n   * interact(target)\n   *   .draggable(true)\n   *   .on('move', function (event) {\n   *     if (event.pageX > 1000) {\n   *       // end the current action\n   *       event.interaction.end()\n   *       // stop all further listeners from being called\n   *       event.stopImmediatePropagation()\n   *     }\n   *   })\n   * ```\n   */\n  end(event?: PointerEventType) {\n    this._ending = true\n    event = event || this._latestPointer.event\n    let endPhaseResult: boolean\n\n    if (this.interacting()) {\n      endPhaseResult = this._doPhase({\n        event,\n        interaction: this,\n        phase: 'end',\n      })\n    }\n\n    this._ending = false\n\n    if (endPhaseResult === true) {\n      this.stop()\n    }\n  }\n\n  currentAction() {\n    return this._interacting ? this.prepared.name : null\n  }\n\n  interacting() {\n    return this._interacting\n  }\n\n  stop() {\n    this._scopeFire('interactions:stop', { interaction: this })\n\n    this.interactable = this.element = null\n\n    this._interacting = false\n    this._stopped = true\n    this.prepared.name = this.prevEvent = null\n  }\n\n  /** @internal */\n  getPointerIndex(pointer: any) {\n    const pointerId = pointerUtils.getPointerId(pointer)\n\n    // mouse and pen interactions may have only one pointer\n    return this.pointerType === 'mouse' || this.pointerType === 'pen'\n      ? this.pointers.length - 1\n      : arr.findIndex(this.pointers, (curPointer) => curPointer.id === pointerId)\n  }\n\n  /** @internal */\n  getPointerInfo(pointer: any) {\n    return this.pointers[this.getPointerIndex(pointer)]\n  }\n\n  /** @internal */\n  updatePointer(pointer: PointerType, event: PointerEventType, eventTarget: Node, down?: boolean) {\n    const id = pointerUtils.getPointerId(pointer)\n    let pointerIndex = this.getPointerIndex(pointer)\n    let pointerInfo = this.pointers[pointerIndex]\n\n    down = down === false ? false : down || /(down|start)$/i.test(event.type)\n\n    if (!pointerInfo) {\n      pointerInfo = new PointerInfo(id, pointer, event, null, null)\n\n      pointerIndex = this.pointers.length\n      this.pointers.push(pointerInfo)\n    } else {\n      pointerInfo.pointer = pointer\n    }\n\n    pointerUtils.setCoords(\n      this.coords.cur,\n      this.pointers.map((p) => p.pointer),\n      this._now(),\n    )\n    pointerUtils.setCoordDeltas(this.coords.delta, this.coords.prev, this.coords.cur)\n\n    if (down) {\n      this.pointerIsDown = true\n\n      pointerInfo.downTime = this.coords.cur.timeStamp\n      pointerInfo.downTarget = eventTarget\n      pointerUtils.pointerExtend(this.downPointer, pointer)\n\n      if (!this.interacting()) {\n        pointerUtils.copyCoords(this.coords.start, this.coords.cur)\n        pointerUtils.copyCoords(this.coords.prev, this.coords.cur)\n\n        this.downEvent = event\n        this.pointerWasMoved = false\n      }\n    }\n\n    this._updateLatestPointer(pointer, event, eventTarget)\n\n    this._scopeFire('interactions:update-pointer', {\n      pointer,\n      event,\n      eventTarget,\n      down,\n      pointerInfo,\n      pointerIndex,\n      interaction: this as unknown as Interaction<never>,\n    })\n\n    return pointerIndex\n  }\n\n  /** @internal */\n  removePointer(pointer: PointerType, event: PointerEventType) {\n    const pointerIndex = this.getPointerIndex(pointer)\n\n    if (pointerIndex === -1) return\n\n    const pointerInfo = this.pointers[pointerIndex]\n\n    this._scopeFire('interactions:remove-pointer', {\n      pointer,\n      event,\n      eventTarget: null,\n      pointerIndex,\n      pointerInfo,\n      interaction: this as unknown as Interaction<never>,\n    })\n\n    this.pointers.splice(pointerIndex, 1)\n    this.pointerIsDown = false\n  }\n\n  /** @internal */\n  _updateLatestPointer(pointer: PointerType, event: PointerEventType, eventTarget: Node) {\n    this._latestPointer.pointer = pointer\n    this._latestPointer.event = event\n    this._latestPointer.eventTarget = eventTarget\n  }\n\n  destroy() {\n    this._latestPointer.pointer = null\n    this._latestPointer.event = null\n    this._latestPointer.eventTarget = null\n  }\n\n  /** @internal */\n  _createPreparedEvent<P extends EventPhase>(\n    event: PointerEventType,\n    phase: P,\n    preEnd?: boolean,\n    type?: string,\n  ) {\n    return new InteractEvent<T, P>(this, event, this.prepared.name, phase, this.element, preEnd, type)\n  }\n\n  /** @internal */\n  _fireEvent<P extends EventPhase>(iEvent: InteractEvent<T, P>) {\n    this.interactable?.fire(iEvent)\n\n    if (!this.prevEvent || iEvent.timeStamp >= this.prevEvent.timeStamp) {\n      this.prevEvent = iEvent\n    }\n  }\n\n  /** @internal */\n  _doPhase<P extends EventPhase>(\n    signalArg: Omit<DoPhaseArg<T, P>, 'iEvent'> & { iEvent?: InteractEvent<T, P> },\n  ) {\n    const { event, phase, preEnd, type } = signalArg\n    const { rect } = this\n\n    if (rect && phase === 'move') {\n      // update the rect changes due to pointer move\n      rectUtils.addEdges(this.edges, rect, this.coords.delta[this.interactable.options.deltaSource])\n\n      rect.width = rect.right - rect.left\n      rect.height = rect.bottom - rect.top\n    }\n\n    const beforeResult = this._scopeFire(`interactions:before-action-${phase}` as any, signalArg)\n\n    if (beforeResult === false) {\n      return false\n    }\n\n    const iEvent = (signalArg.iEvent = this._createPreparedEvent(event, phase, preEnd, type))\n\n    this._scopeFire(`interactions:action-${phase}` as any, signalArg)\n\n    if (phase === 'start') {\n      this.prevEvent = iEvent\n    }\n\n    this._fireEvent(iEvent)\n\n    this._scopeFire(`interactions:after-action-${phase}` as any, signalArg)\n\n    return true\n  }\n\n  /** @internal */\n  _now() {\n    return Date.now()\n  }\n}\n\nexport default Interaction\nexport { PointerInfo }\n"
  },
  {
    "path": "packages/@interactjs/core/NativeTypes.ts",
    "content": "export const NativePointerEvent = null as unknown as InstanceType<typeof PointerEvent>\nexport type NativeEventTarget = EventTarget\nexport type NativeElement = Element\n"
  },
  {
    "path": "packages/@interactjs/core/PointerInfo.ts",
    "content": "import type { PointerEventType, PointerType } from '@interactjs/core/types'\n\nexport class PointerInfo {\n  id: number\n  pointer: PointerType\n  event: PointerEventType\n  downTime: number\n  downTarget: Node\n\n  constructor(id: number, pointer: PointerType, event: PointerEventType, downTime: number, downTarget: Node) {\n    this.id = id\n    this.pointer = pointer\n    this.event = event\n    this.downTime = downTime\n    this.downTarget = downTarget\n  }\n}\n"
  },
  {
    "path": "packages/@interactjs/core/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/core/events.ts",
    "content": "import * as arr from '@interactjs/utils/arr'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport is from '@interactjs/utils/is'\nimport pExtend from '@interactjs/utils/pointerExtend'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport type { Scope } from '@interactjs/core/scope'\nimport type { Element } from '@interactjs/core/types'\n\nimport type { NativeEventTarget } from './NativeTypes'\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    events: ReturnType<typeof install>\n  }\n}\n\ninterface EventOptions {\n  capture: boolean\n  passive: boolean\n}\n\ntype PartialEventTarget = Partial<NativeEventTarget>\n\ntype ListenerEntry = { func: (event: Event | FakeEvent) => any; options: EventOptions }\n\nfunction install(scope: Scope) {\n  const targets: Array<{\n    eventTarget: PartialEventTarget\n    events: { [type: string]: ListenerEntry[] }\n  }> = []\n\n  const delegatedEvents: {\n    [type: string]: Array<{\n      selector: string\n      context: Node\n      listeners: ListenerEntry[]\n    }>\n  } = {}\n  const documents: Document[] = []\n\n  const eventsMethods = {\n    add,\n    remove,\n\n    addDelegate,\n    removeDelegate,\n\n    delegateListener,\n    delegateUseCapture,\n    delegatedEvents,\n    documents,\n\n    targets,\n\n    supportsOptions: false,\n    supportsPassive: false,\n  }\n\n  // check if browser supports passive events and options arg\n  scope.document?.createElement('div').addEventListener('test', null, {\n    get capture() {\n      return (eventsMethods.supportsOptions = true)\n    },\n    get passive() {\n      return (eventsMethods.supportsPassive = true)\n    },\n  })\n\n  scope.events = eventsMethods\n\n  function add(\n    eventTarget: PartialEventTarget,\n    type: string,\n    listener: ListenerEntry['func'],\n    optionalArg?: boolean | EventOptions,\n  ) {\n    if (!eventTarget.addEventListener) return\n\n    const options = getOptions(optionalArg)\n    let target = arr.find(targets, (t) => t.eventTarget === eventTarget)\n\n    if (!target) {\n      target = {\n        eventTarget,\n        events: {},\n      }\n\n      targets.push(target)\n    }\n\n    if (!target.events[type]) {\n      target.events[type] = []\n    }\n\n    if (!arr.find(target.events[type], (l) => l.func === listener && optionsMatch(l.options, options))) {\n      eventTarget.addEventListener(\n        type,\n        listener as any,\n        eventsMethods.supportsOptions ? options : options.capture,\n      )\n      target.events[type].push({ func: listener, options })\n    }\n  }\n\n  function remove(\n    eventTarget: PartialEventTarget,\n    type: string,\n    listener?: 'all' | ListenerEntry['func'],\n    optionalArg?: boolean | EventOptions,\n  ) {\n    if (!eventTarget.addEventListener || !eventTarget.removeEventListener) return\n\n    const targetIndex = arr.findIndex(targets, (t) => t.eventTarget === eventTarget)\n    const target = targets[targetIndex]\n\n    if (!target || !target.events) {\n      return\n    }\n\n    if (type === 'all') {\n      for (type in target.events) {\n        if (target.events.hasOwnProperty(type)) {\n          remove(eventTarget, type, 'all')\n        }\n      }\n      return\n    }\n\n    let typeIsEmpty = false\n    const typeListeners = target.events[type]\n\n    if (typeListeners) {\n      if (listener === 'all') {\n        for (let i = typeListeners.length - 1; i >= 0; i--) {\n          const entry = typeListeners[i]\n          remove(eventTarget, type, entry.func, entry.options)\n        }\n        return\n      } else {\n        const options = getOptions(optionalArg)\n\n        for (let i = 0; i < typeListeners.length; i++) {\n          const entry = typeListeners[i]\n          if (entry.func === listener && optionsMatch(entry.options, options)) {\n            eventTarget.removeEventListener(\n              type,\n              listener as any,\n              eventsMethods.supportsOptions ? options : options.capture,\n            )\n            typeListeners.splice(i, 1)\n\n            if (typeListeners.length === 0) {\n              delete target.events[type]\n              typeIsEmpty = true\n            }\n\n            break\n          }\n        }\n      }\n    }\n\n    if (typeIsEmpty && !Object.keys(target.events).length) {\n      targets.splice(targetIndex, 1)\n    }\n  }\n\n  function addDelegate(\n    selector: string,\n    context: Node,\n    type: string,\n    listener: ListenerEntry['func'],\n    optionalArg?: any,\n  ) {\n    const options = getOptions(optionalArg)\n    if (!delegatedEvents[type]) {\n      delegatedEvents[type] = []\n\n      // add delegate listener functions\n      for (const doc of documents) {\n        add(doc, type, delegateListener)\n        add(doc, type, delegateUseCapture, true)\n      }\n    }\n\n    const delegates = delegatedEvents[type]\n    let delegate = arr.find(delegates, (d) => d.selector === selector && d.context === context)\n\n    if (!delegate) {\n      delegate = { selector, context, listeners: [] }\n      delegates.push(delegate)\n    }\n\n    delegate.listeners.push({ func: listener, options })\n  }\n\n  function removeDelegate(\n    selector: string,\n    context: Document | Element,\n    type: string,\n    listener?: ListenerEntry['func'],\n    optionalArg?: any,\n  ) {\n    const options = getOptions(optionalArg)\n    const delegates = delegatedEvents[type]\n    let matchFound = false\n    let index: number\n\n    if (!delegates) return\n\n    // count from last index of delegated to 0\n    for (index = delegates.length - 1; index >= 0; index--) {\n      const cur = delegates[index]\n      // look for matching selector and context Node\n      if (cur.selector === selector && cur.context === context) {\n        const { listeners } = cur\n\n        // each item of the listeners array is an array: [function, capture, passive]\n        for (let i = listeners.length - 1; i >= 0; i--) {\n          const entry = listeners[i]\n\n          // check if the listener functions and capture and passive flags match\n          if (entry.func === listener && optionsMatch(entry.options, options)) {\n            // remove the listener from the array of listeners\n            listeners.splice(i, 1)\n\n            // if all listeners for this target have been removed\n            // remove the target from the delegates array\n            if (!listeners.length) {\n              delegates.splice(index, 1)\n\n              // remove delegate function from context\n              remove(context, type, delegateListener)\n              remove(context, type, delegateUseCapture, true)\n            }\n\n            // only remove one listener\n            matchFound = true\n            break\n          }\n        }\n\n        if (matchFound) {\n          break\n        }\n      }\n    }\n  }\n\n  // bound to the interactable context when a DOM event\n  // listener is added to a selector interactable\n  function delegateListener(event: Event | FakeEvent, optionalArg?: any) {\n    const options = getOptions(optionalArg)\n    const fakeEvent = new FakeEvent(event as Event)\n    const delegates = delegatedEvents[event.type]\n    const [eventTarget] = pointerUtils.getEventTargets(event as Event)\n    let element: Node = eventTarget\n\n    // climb up document tree looking for selector matches\n    while (is.element(element)) {\n      for (let i = 0; i < delegates.length; i++) {\n        const cur = delegates[i]\n        const { selector, context } = cur\n\n        if (\n          domUtils.matchesSelector(element, selector) &&\n          domUtils.nodeContains(context, eventTarget) &&\n          domUtils.nodeContains(context, element)\n        ) {\n          const { listeners } = cur\n\n          fakeEvent.currentTarget = element\n\n          for (const entry of listeners) {\n            if (optionsMatch(entry.options, options)) {\n              entry.func(fakeEvent)\n            }\n          }\n        }\n      }\n\n      element = domUtils.parentNode(element)\n    }\n  }\n\n  function delegateUseCapture(this: Element, event: Event | FakeEvent) {\n    return delegateListener.call(this, event, true)\n  }\n\n  // for type inferrence\n  return eventsMethods\n}\n\nclass FakeEvent implements Partial<Event> {\n  currentTarget: Node\n  originalEvent: Event\n  type: string\n\n  constructor(originalEvent: Event) {\n    this.originalEvent = originalEvent\n    // duplicate the event so that currentTarget can be changed\n    pExtend(this, originalEvent)\n  }\n\n  preventOriginalDefault() {\n    this.originalEvent.preventDefault()\n  }\n\n  stopPropagation() {\n    this.originalEvent.stopPropagation()\n  }\n\n  stopImmediatePropagation() {\n    this.originalEvent.stopImmediatePropagation()\n  }\n}\n\nfunction getOptions(param: { [index: string]: any } | boolean): { capture: boolean; passive: boolean } {\n  if (!is.object(param)) {\n    return { capture: !!param, passive: false }\n  }\n\n  return {\n    capture: !!param.capture,\n    passive: !!param.passive,\n  }\n}\n\nfunction optionsMatch(a: Partial<EventOptions> | boolean, b: Partial<EventOptions>) {\n  if (a === b) return true\n\n  if (typeof a === 'boolean') return !!b.capture === a && !!b.passive === false\n\n  return !!a.capture === !!b.capture && !!a.passive === !!b.passive\n}\n\nexport default {\n  id: 'events',\n  install,\n}\n"
  },
  {
    "path": "packages/@interactjs/core/interactablePreventDefault.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\nimport autoStart from '@interactjs/auto-start/base'\n\nimport interactablePreventDefault from './interactablePreventDefault'\nimport * as helpers from './tests/_helpers'\n\ntest('core/interactablePreventDefault', () => {\n  window.PointerEvent = null\n\n  const { scope, interactable } = helpers.testEnv({\n    plugins: [interactablePreventDefault, autoStart, drag],\n  })\n\n  const { MouseEvent, Event } = scope.window as any\n\n  interactable.draggable({})\n\n  const mouseDown: MouseEvent = new MouseEvent('mousedown', { bubbles: true })\n  const nativeDragStart: Event = new Event('dragstart', { bubbles: true })\n\n  nativeDragStart.preventDefault = jest.fn()\n\n  scope.document.body.dispatchEvent(mouseDown)\n  scope.document.body.dispatchEvent(nativeDragStart)\n\n  // native dragstart is prevented on interactable\n  expect(nativeDragStart.preventDefault).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "packages/@interactjs/core/interactablePreventDefault.ts",
    "content": "import { matchesSelector, nodeContains } from '@interactjs/utils/domUtils'\nimport is from '@interactjs/utils/is'\nimport { getWindow } from '@interactjs/utils/window'\n\nimport type { Interactable } from '@interactjs/core/Interactable'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { Scope } from '@interactjs/core/scope'\nimport type { PointerEventType } from '@interactjs/core/types'\n\ntype PreventDefaultValue = 'always' | 'never' | 'auto'\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    preventDefault(newValue: PreventDefaultValue): this\n    preventDefault(): PreventDefaultValue\n    /**\n     * Returns or sets whether to prevent the browser's default behaviour in\n     * response to pointer events. Can be set to:\n     *  - `'always'` to always prevent\n     *  - `'never'` to never prevent\n     *  - `'auto'` to let interact.js try to determine what would be best\n     *\n     * @param newValue - `'always'`, `'never'` or `'auto'`\n     * @returns The current setting or this Interactable\n     */\n    preventDefault(newValue?: PreventDefaultValue): PreventDefaultValue | this\n    checkAndPreventDefault(event: Event): void\n  }\n}\n\nconst preventDefault = function preventDefault(this: Interactable, newValue?: PreventDefaultValue) {\n  if (/^(always|never|auto)$/.test(newValue)) {\n    this.options.preventDefault = newValue\n    return this\n  }\n\n  if (is.bool(newValue)) {\n    this.options.preventDefault = newValue ? 'always' : 'never'\n    return this\n  }\n\n  return this.options.preventDefault\n} as Interactable['preventDefault']\n\nfunction checkAndPreventDefault(interactable: Interactable, scope: Scope, event: Event) {\n  const setting = interactable.options.preventDefault\n\n  if (setting === 'never') return\n\n  if (setting === 'always') {\n    event.preventDefault()\n    return\n  }\n\n  // setting === 'auto'\n\n  // if the browser supports passive event listeners and isn't running on iOS,\n  // don't preventDefault of touch{start,move} events. CSS touch-action and\n  // user-select should be used instead of calling event.preventDefault().\n  if (scope.events.supportsPassive && /^touch(start|move)$/.test(event.type)) {\n    const doc = getWindow(event.target).document\n    const docOptions = scope.getDocOptions(doc)\n\n    if (!(docOptions && docOptions.events) || docOptions.events.passive !== false) {\n      return\n    }\n  }\n\n  // don't preventDefault of pointerdown events\n  if (/^(mouse|pointer|touch)*(down|start)/i.test(event.type)) {\n    return\n  }\n\n  // don't preventDefault on editable elements\n  if (\n    is.element(event.target) &&\n    matchesSelector(event.target, 'input,select,textarea,[contenteditable=true],[contenteditable=true] *')\n  ) {\n    return\n  }\n\n  event.preventDefault()\n}\n\nfunction onInteractionEvent({ interaction, event }: { interaction: Interaction; event: PointerEventType }) {\n  if (interaction.interactable) {\n    interaction.interactable.checkAndPreventDefault(event as Event)\n  }\n}\n\nexport function install(scope: Scope) {\n  const { Interactable } = scope\n\n  Interactable.prototype.preventDefault = preventDefault\n\n  Interactable.prototype.checkAndPreventDefault = function (event) {\n    return checkAndPreventDefault(this, scope, event)\n  }\n\n  // prevent native HTML5 drag on interact.js target elements\n  scope.interactions.docEvents.push({\n    type: 'dragstart',\n    listener(event) {\n      for (const interaction of scope.interactions.list) {\n        if (\n          interaction.element &&\n          (interaction.element === event.target || nodeContains(interaction.element, event.target))\n        ) {\n          interaction.interactable.checkAndPreventDefault(event)\n          return\n        }\n      }\n    },\n  })\n}\n\nexport default {\n  id: 'core/interactablePreventDefault',\n  install,\n  listeners: ['down', 'move', 'up', 'cancel'].reduce((acc, eventType) => {\n    acc[`interactions:${eventType}`] = onInteractionEvent\n    return acc\n  }, {} as any),\n}\n"
  },
  {
    "path": "packages/@interactjs/core/interactionFinder.spec.ts",
    "content": "import finder from './interactionFinder'\nimport * as helpers from './tests/_helpers'\n\ntest('modifiers/snap', () => {\n  const { interactable, event, coords, scope } = helpers.testEnv()\n\n  const { body } = scope.document\n\n  const { list } = scope.interactions\n  const details = {\n    pointer: event,\n    get pointerId(): number {\n      return details.pointer.pointerId\n    },\n    get pointerType(): string {\n      return details.pointer.pointerType\n    },\n    eventType: null as string,\n    eventTarget: body,\n    curEventTarget: scope.document,\n    scope,\n  }\n\n  scope.interactions.new({ pointerType: 'touch' })\n  scope.interactions.new({ pointerType: 'mouse' })\n\n  coords.pointerType = 'mouse'\n  list[0].pointerType = 'mouse'\n  list[2]._interacting = true\n\n  // [pointerType: mouse] skips inactive mouse and touch interaction\n  expect(list.indexOf(finder.search(details))).toBe(2)\n\n  list[2]._interacting = false\n\n  // [pointerType: mouse] returns first idle mouse interaction\n  expect(list.indexOf(finder.search(details))).toBe(0)\n\n  coords.pointerId = 4\n  list[1].pointerDown({ ...event } as any, { ...event } as any, body)\n  coords.pointerType = 'touch'\n\n  // [pointerType: touch] gets interaction with pointerId\n  expect(list.indexOf(finder.search(details))).toBe(1)\n\n  coords.pointerId = 5\n\n  // `[pointerType: touch] returns idle touch interaction without matching pointerId and existing touch interaction has pointer and no target`\n  expect(list.indexOf(finder.search(details))).toBe(1)\n\n  interactable.options.gesture = { enabled: false }\n  list[1].interactable = interactable\n\n  // `[pointerType: touch] no result without matching pointerId and existing touch interaction has a pointer and target not gesturable`\n  expect(list.indexOf(finder.search(details))).toBe(-1)\n\n  interactable.options.gesture = { enabled: true }\n\n  // `[pointerType: touch] returns idle touch interaction with gesturable target and existing pointer`\n  expect(list.indexOf(finder.search(details))).toBe(1)\n})\n"
  },
  {
    "path": "packages/@interactjs/core/interactionFinder.ts",
    "content": "import * as dom from '@interactjs/utils/domUtils'\n\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { Scope } from '@interactjs/core/scope'\nimport type { PointerType } from '@interactjs/core/types'\n\nexport interface SearchDetails {\n  pointer: PointerType\n  pointerId: number\n  pointerType: string\n  eventType: string\n  eventTarget: EventTarget\n  curEventTarget: EventTarget\n  scope: Scope\n}\n\nconst finder = {\n  methodOrder: ['simulationResume', 'mouseOrPen', 'hasPointer', 'idle'] as const,\n\n  search(details: SearchDetails) {\n    for (const method of finder.methodOrder) {\n      const interaction = finder[method](details)\n\n      if (interaction) {\n        return interaction\n      }\n    }\n\n    return null\n  },\n\n  // try to resume simulation with a new pointer\n  simulationResume({ pointerType, eventType, eventTarget, scope }: SearchDetails) {\n    if (!/down|start/i.test(eventType)) {\n      return null\n    }\n\n    for (const interaction of scope.interactions.list) {\n      let element = eventTarget as Node\n\n      if (\n        interaction.simulation &&\n        interaction.simulation.allowResume &&\n        interaction.pointerType === pointerType\n      ) {\n        while (element) {\n          // if the element is the interaction element\n          if (element === interaction.element) {\n            return interaction\n          }\n          element = dom.parentNode(element)\n        }\n      }\n    }\n\n    return null\n  },\n\n  // if it's a mouse or pen interaction\n  mouseOrPen({ pointerId, pointerType, eventType, scope }: SearchDetails) {\n    if (pointerType !== 'mouse' && pointerType !== 'pen') {\n      return null\n    }\n\n    let firstNonActive\n\n    for (const interaction of scope.interactions.list) {\n      if (interaction.pointerType === pointerType) {\n        // if it's a down event, skip interactions with running simulations\n        if (interaction.simulation && !hasPointerId(interaction, pointerId)) {\n          continue\n        }\n\n        // if the interaction is active, return it immediately\n        if (interaction.interacting()) {\n          return interaction\n        }\n        // otherwise save it and look for another active interaction\n        else if (!firstNonActive) {\n          firstNonActive = interaction\n        }\n      }\n    }\n\n    // if no active mouse interaction was found use the first inactive mouse\n    // interaction\n    if (firstNonActive) {\n      return firstNonActive\n    }\n\n    // find any mouse or pen interaction.\n    // ignore the interaction if the eventType is a *down, and a simulation\n    // is active\n    for (const interaction of scope.interactions.list) {\n      if (interaction.pointerType === pointerType && !(/down/i.test(eventType) && interaction.simulation)) {\n        return interaction\n      }\n    }\n\n    return null\n  },\n\n  // get interaction that has this pointer\n  hasPointer({ pointerId, scope }: SearchDetails) {\n    for (const interaction of scope.interactions.list) {\n      if (hasPointerId(interaction, pointerId)) {\n        return interaction\n      }\n    }\n\n    return null\n  },\n\n  // get first idle interaction with a matching pointerType\n  idle({ pointerType, scope }: SearchDetails) {\n    for (const interaction of scope.interactions.list) {\n      // if there's already a pointer held down\n      if (interaction.pointers.length === 1) {\n        const target = interaction.interactable\n        // don't add this pointer if there is a target interactable and it\n        // isn't gesturable\n        if (target && !(target.options.gesture && target.options.gesture.enabled)) {\n          continue\n        }\n      }\n      // maximum of 2 pointers per interaction\n      else if (interaction.pointers.length >= 2) {\n        continue\n      }\n\n      if (!interaction.interacting() && pointerType === interaction.pointerType) {\n        return interaction\n      }\n    }\n\n    return null\n  },\n}\n\nfunction hasPointerId(interaction: Interaction, pointerId: number) {\n  return interaction.pointers.some(({ id }) => id === pointerId)\n}\n\nexport default finder\n"
  },
  {
    "path": "packages/@interactjs/core/interactions.spec.ts",
    "content": "import Interaction from './Interaction'\nimport interactions from './interactions'\nimport * as helpers from './tests/_helpers'\n\ndescribe('core/interactions', () => {\n  test('interactions', () => {\n    let scope = helpers.mockScope()\n\n    const interaction = scope.interactions.new({ pointerType: 'TEST' })\n\n    // new Interaction is pushed to scope.interactions\n    expect(scope.interactions.list[0]).toBe(interaction)\n    // interactions object added to scope\n    expect(scope.interactions).toBeInstanceOf(Object)\n\n    const listeners = scope.interactions.listeners\n\n    expect(interactions.methodNames.every((m: string) => typeof listeners[m] === 'function')).toBe(true)\n\n    scope = helpers.mockScope()\n\n    const newInteraction = scope.interactions.new({})\n\n    expect(typeof scope.interactions).toBe('object')\n    expect(typeof scope.interactions.new).toBe('function')\n    expect(newInteraction instanceof Interaction).toBe(true)\n    expect(typeof newInteraction._scopeFire).toBe('function')\n\n    expect(scope.actions).toBeInstanceOf(Object)\n    expect(scope.actions.map).toEqual({})\n    expect(scope.actions.methodDict).toEqual({})\n  })\n\n  test('interactions document event options', () => {\n    const { scope } = helpers.testEnv()\n    const doc = scope.document\n\n    let options = {}\n    scope.browser = { isIOS: false } as any\n    scope.fire('scope:add-document', { doc, scope, options } as any)\n\n    // no doc options.event.passive is added when not iOS\n    expect(options).toEqual({})\n\n    options = {}\n\n    scope.browser.isIOS = true\n    scope.fire('scope:add-document', { doc, scope, options } as any)\n\n    // doc options.event.passive is set to false for iOS\n    expect(options).toEqual({ events: { passive: false } })\n  })\n\n  test('interactions removes pointers on targeting removed elements', () => {\n    const { interaction, scope } = helpers.testEnv()\n\n    const { PointerEvent } = scope.window as any\n    const div1 = scope.document.body.appendChild(scope.document.createElement('div'))\n    const div2 = scope.document.body.appendChild(scope.document.createElement('div'))\n\n    const touch1Init = { bubbles: true, pointerType: 'touch', pointerId: 1, target: div1 }\n    const touch2Init = { bubbles: true, pointerType: 'touch', pointerId: 2, target: div2 }\n\n    interaction.pointerType = 'touch'\n    div1.dispatchEvent(new PointerEvent('pointerdown', touch1Init))\n    div1.dispatchEvent(new PointerEvent('pointermove', touch1Init))\n\n    expect(scope.interactions.list).toHaveLength(1)\n\n    // down pointer added to interaction\n    expect(interaction.pointers).toHaveLength(1)\n    // _latestPointer target is down target\n    expect(interaction._latestPointer.eventTarget).toBe(div1)\n\n    div1.remove()\n\n    div2.dispatchEvent(new TouchEvent('touchstart', touch2Init))\n\n    // interaction with removed element is reused for new pointer\n    expect(scope.interactions.list).toEqual([interaction])\n\n    // pointer on removed element is removed from existing interaction and new pointerdown is added\n    expect(interaction.pointers).toHaveLength(1)\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/core/interactions.ts",
    "content": "import browser from '@interactjs/utils/browser'\nimport domObjects from '@interactjs/utils/domObjects'\nimport { nodeContains } from '@interactjs/utils/domUtils'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport type { Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport type { ActionName, Listener } from '@interactjs/core/types'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './interactablePreventDefault'\nimport interactablePreventDefault from './interactablePreventDefault'\nimport InteractionBase from './Interaction'\n/* eslint-enable import/no-duplicates */\nimport type { SearchDetails } from './interactionFinder'\nimport finder from './interactionFinder'\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    Interaction: typeof InteractionBase\n    interactions: {\n      new: <T extends ActionName>(options: any) => InteractionBase<T>\n      list: Array<InteractionBase<ActionName>>\n      listeners: { [type: string]: Listener }\n      docEvents: Array<{ type: string; listener: Listener }>\n      pointerMoveTolerance: number\n    }\n    prevTouchTime: number\n  }\n\n  interface SignalArgs {\n    'interactions:find': {\n      interaction: InteractionBase\n      searchDetails: SearchDetails\n    }\n  }\n}\n\nconst methodNames = [\n  'pointerDown',\n  'pointerMove',\n  'pointerUp',\n  'updatePointer',\n  'removePointer',\n  'windowBlur',\n]\n\nfunction install(scope: Scope) {\n  const listeners = {} as any\n\n  for (const method of methodNames) {\n    listeners[method] = doOnInteractions(method, scope)\n  }\n\n  const pEventTypes = browser.pEventTypes\n  let docEvents: typeof scope.interactions.docEvents\n\n  if (domObjects.PointerEvent) {\n    docEvents = [\n      { type: pEventTypes.down, listener: releasePointersOnRemovedEls },\n      { type: pEventTypes.down, listener: listeners.pointerDown },\n      { type: pEventTypes.move, listener: listeners.pointerMove },\n      { type: pEventTypes.up, listener: listeners.pointerUp },\n      { type: pEventTypes.cancel, listener: listeners.pointerUp },\n    ]\n  } else {\n    docEvents = [\n      { type: 'mousedown', listener: listeners.pointerDown },\n      { type: 'mousemove', listener: listeners.pointerMove },\n      { type: 'mouseup', listener: listeners.pointerUp },\n\n      { type: 'touchstart', listener: releasePointersOnRemovedEls },\n      { type: 'touchstart', listener: listeners.pointerDown },\n      { type: 'touchmove', listener: listeners.pointerMove },\n      { type: 'touchend', listener: listeners.pointerUp },\n      { type: 'touchcancel', listener: listeners.pointerUp },\n    ]\n  }\n\n  docEvents.push({\n    type: 'blur',\n    listener(event) {\n      for (const interaction of scope.interactions.list) {\n        interaction.documentBlur(event)\n      }\n    },\n  })\n\n  // for ignoring browser's simulated mouse events\n  scope.prevTouchTime = 0\n\n  scope.Interaction = class<T extends ActionName> extends InteractionBase<T> {\n    get pointerMoveTolerance() {\n      return scope.interactions.pointerMoveTolerance\n    }\n\n    set pointerMoveTolerance(value) {\n      scope.interactions.pointerMoveTolerance = value\n    }\n\n    _now() {\n      return scope.now()\n    }\n  }\n\n  scope.interactions = {\n    // all active and idle interactions\n    list: [],\n    new<T extends ActionName>(options: { pointerType?: string; scopeFire?: Scope['fire'] }) {\n      options.scopeFire = (name, arg) => scope.fire(name, arg)\n\n      const interaction = new scope.Interaction<T>(options as Required<typeof options>)\n\n      scope.interactions.list.push(interaction)\n      return interaction\n    },\n    listeners,\n    docEvents,\n    pointerMoveTolerance: 1,\n  }\n\n  function releasePointersOnRemovedEls() {\n    // for all inactive touch interactions with pointers down\n    for (const interaction of scope.interactions.list) {\n      if (!interaction.pointerIsDown || interaction.pointerType !== 'touch' || interaction._interacting) {\n        continue\n      }\n\n      // if a pointer is down on an element that is no longer in the DOM tree\n      for (const pointer of interaction.pointers) {\n        if (!scope.documents.some(({ doc }) => nodeContains(doc, pointer.downTarget))) {\n          // remove the pointer from the interaction\n          interaction.removePointer(pointer.pointer, pointer.event)\n        }\n      }\n    }\n  }\n\n  scope.usePlugin(interactablePreventDefault)\n}\n\nfunction doOnInteractions(method: string, scope: Scope) {\n  return function (event: Event) {\n    const interactions = scope.interactions.list\n\n    const pointerType = pointerUtils.getPointerType(event)\n    const [eventTarget, curEventTarget] = pointerUtils.getEventTargets(event)\n    const matches: any[] = [] // [ [pointer, interaction], ...]\n\n    if (/^touch/.test(event.type)) {\n      scope.prevTouchTime = scope.now()\n\n      // @ts-expect-error\n      for (const changedTouch of event.changedTouches) {\n        const pointer = changedTouch\n        const pointerId = pointerUtils.getPointerId(pointer)\n        const searchDetails: SearchDetails = {\n          pointer,\n          pointerId,\n          pointerType,\n          eventType: event.type,\n          eventTarget,\n          curEventTarget,\n          scope,\n        }\n        const interaction = getInteraction(searchDetails)\n\n        matches.push([\n          searchDetails.pointer,\n          searchDetails.eventTarget,\n          searchDetails.curEventTarget,\n          interaction,\n        ])\n      }\n    } else {\n      let invalidPointer = false\n\n      if (!browser.supportsPointerEvent && /mouse/.test(event.type)) {\n        // ignore mouse events while touch interactions are active\n        for (let i = 0; i < interactions.length && !invalidPointer; i++) {\n          invalidPointer = interactions[i].pointerType !== 'mouse' && interactions[i].pointerIsDown\n        }\n\n        // try to ignore mouse events that are simulated by the browser\n        // after a touch event\n        invalidPointer =\n          invalidPointer ||\n          scope.now() - scope.prevTouchTime < 500 ||\n          // on iOS and Firefox Mobile, MouseEvent.timeStamp is zero if simulated\n          event.timeStamp === 0\n      }\n\n      if (!invalidPointer) {\n        const searchDetails = {\n          pointer: event as PointerEvent,\n          pointerId: pointerUtils.getPointerId(event as PointerEvent),\n          pointerType,\n          eventType: event.type,\n          curEventTarget,\n          eventTarget,\n          scope,\n        }\n\n        const interaction = getInteraction(searchDetails)\n\n        matches.push([\n          searchDetails.pointer,\n          searchDetails.eventTarget,\n          searchDetails.curEventTarget,\n          interaction,\n        ])\n      }\n    }\n\n    // eslint-disable-next-line no-shadow\n    for (const [pointer, eventTarget, curEventTarget, interaction] of matches) {\n      interaction[method](pointer, event, eventTarget, curEventTarget)\n    }\n  }\n}\n\nfunction getInteraction(searchDetails: SearchDetails) {\n  const { pointerType, scope } = searchDetails\n\n  const foundInteraction = finder.search(searchDetails)\n  const signalArg = { interaction: foundInteraction, searchDetails }\n\n  scope.fire('interactions:find', signalArg)\n\n  return signalArg.interaction || scope.interactions.new({ pointerType })\n}\n\nfunction onDocSignal<T extends 'scope:add-document' | 'scope:remove-document'>(\n  { doc, scope, options }: SignalArgs[T],\n  eventMethodName: 'add' | 'remove',\n) {\n  const {\n    interactions: { docEvents },\n    events,\n  } = scope\n  const eventMethod = events[eventMethodName]\n\n  if (scope.browser.isIOS && !options.events) {\n    options.events = { passive: false }\n  }\n\n  // delegate event listener\n  for (const eventType in events.delegatedEvents) {\n    eventMethod(doc, eventType, events.delegateListener)\n    eventMethod(doc, eventType, events.delegateUseCapture, true)\n  }\n\n  const eventOptions = options && options.events\n\n  for (const { type, listener } of docEvents) {\n    eventMethod(doc, type, listener, eventOptions)\n  }\n}\n\nconst interactions: Plugin = {\n  id: 'core/interactions',\n  install,\n  listeners: {\n    'scope:add-document': (arg) => onDocSignal(arg, 'add'),\n    'scope:remove-document': (arg) => onDocSignal(arg, 'remove'),\n    'interactable:unset': ({ interactable }, scope) => {\n      // Stop and destroy related interactions when an Interactable is unset\n      for (let i = scope.interactions.list.length - 1; i >= 0; i--) {\n        const interaction = scope.interactions.list[i]\n\n        if (interaction.interactable !== interactable) {\n          continue\n        }\n\n        interaction.stop()\n        scope.fire('interactions:destroy', { interaction })\n        interaction.destroy()\n\n        if (scope.interactions.list.length > 2) {\n          scope.interactions.list.splice(i, 1)\n        }\n      }\n    },\n  },\n  onDocSignal,\n  doOnInteractions,\n  methodNames,\n}\n\nexport default interactions\n"
  },
  {
    "path": "packages/@interactjs/core/options.ts",
    "content": "import type { Point, Listeners, OrBoolean, Element, Rect } from '@interactjs/core/types'\n\nexport interface Defaults {\n  base: BaseDefaults\n  perAction: PerActionDefaults\n  actions: ActionDefaults\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface ActionDefaults {}\n\nexport interface BaseDefaults {\n  preventDefault?: 'always' | 'never' | 'auto'\n  deltaSource?: 'page' | 'client'\n  context?: Node\n  getRect?: (element: Element) => Rect\n}\n\nexport interface PerActionDefaults {\n  enabled?: boolean\n  origin?: Point | string | Element\n  listeners?: Listeners\n  allowFrom?: string | Element\n  ignoreFrom?: string | Element\n}\n\nexport type Options = Partial<BaseDefaults> &\n  Partial<PerActionDefaults> & {\n    [P in keyof ActionDefaults]?: Partial<ActionDefaults[P]>\n  }\n\nexport interface OptionsArg extends BaseDefaults, OrBoolean<Partial<ActionDefaults>> {}\n\nexport const defaults: Defaults = {\n  base: {\n    preventDefault: 'auto',\n    deltaSource: 'page',\n  },\n\n  perAction: {\n    enabled: false,\n    origin: { x: 0, y: 0 },\n  },\n\n  actions: {} as ActionDefaults,\n}\n"
  },
  {
    "path": "packages/@interactjs/core/package.json",
    "content": "{\n  \"name\": \"@interactjs/core\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/core\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/core/scope.spec.ts",
    "content": "import type { ActionName } from '@interactjs/core/types'\n\nimport * as helpers from './tests/_helpers'\n\ndescribe('core/scope', () => {\n  test('usePlugin', () => {\n    const { scope } = helpers.testEnv()\n\n    const plugin1 = { id: '1', listeners: {} }\n    const plugin2 = { id: '2', listeners: {} }\n    const plugin3 = { id: '3', listeners: {}, before: ['2'] }\n    const plugin4 = { id: '4', listeners: {}, before: ['2', '3'] }\n\n    const initialListeners = scope.listenerMaps.map((l) => l.id)\n\n    scope.usePlugin(plugin1)\n    scope.usePlugin(plugin2)\n    scope.usePlugin(plugin3)\n    scope.usePlugin(plugin4)\n\n    expect(scope.listenerMaps.map((l) => l.id)).toEqual([...initialListeners, '1', '4', '3', '2'])\n  })\n\n  test('interactable unset', () => {\n    const { scope, interactable, interaction, event } = helpers.testEnv()\n\n    const interactable2 = scope.interactables.new('x')\n\n    expect(scope.interactables.list).toContain(interactable)\n    expect(scope.interactables.list).toContain(interactable2)\n    ;(interactable.options as any).test = { enabled: true }\n    interaction.pointerDown(event, event, scope.document.body)\n    interaction.start({ name: 'test' as ActionName }, interactable, scope.document.body)\n\n    const started = interaction._interacting\n    interactable.unset()\n    const stopped = !interaction._interacting\n\n    expect(scope.interactables.list).not.toContain(interactable)\n    expect(scope.interactables.list).toContain(interactable2)\n\n    // interaction is stopped on interactable.unset()\n    expect(started && stopped).toBe(true)\n\n    // repeated call to unset\n    interactable.unset()\n    expect(scope.interactables.list).not.toContain(interactable)\n    expect(scope.interactables.list).toContain(interactable2)\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/core/scope.ts",
    "content": "import browser from '@interactjs/utils/browser'\nimport clone from '@interactjs/utils/clone'\nimport domObjects from '@interactjs/utils/domObjects'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport raf from '@interactjs/utils/raf'\nimport * as win from '@interactjs/utils/window'\n\nimport type Interaction from '@interactjs/core/Interaction'\n\nimport { Eventable } from './Eventable'\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './events'\nimport './interactions'\nimport events from './events'\nimport { Interactable as InteractableBase } from './Interactable'\nimport { InteractableSet } from './InteractableSet'\nimport { InteractEvent } from './InteractEvent'\nimport interactions from './interactions'\n/* eslint-enable import/no-duplicates */\nimport { createInteractStatic } from './InteractStatic'\nimport type { OptionsArg } from './options'\nimport { defaults } from './options'\nimport type { Actions } from './types'\n\nexport interface SignalArgs {\n  'scope:add-document': DocSignalArg\n  'scope:remove-document': DocSignalArg\n  'interactable:unset': { interactable: InteractableBase }\n  'interactable:set': { interactable: InteractableBase; options: OptionsArg }\n  'interactions:destroy': { interaction: Interaction }\n}\n\nexport type ListenerName = keyof SignalArgs\n\nexport type ListenerMap = {\n  [P in ListenerName]?: (arg: SignalArgs[P], scope: Scope, signalName: P) => void | boolean\n}\n\ninterface DocSignalArg {\n  doc: Document\n  window: Window\n  scope: Scope\n  options: Record<string, any>\n}\n\nexport interface Plugin {\n  [key: string]: any\n  id?: string\n  listeners?: ListenerMap\n  before?: string[]\n  install?(scope: Scope, options?: any): void\n}\n\n/** @internal */\nexport class Scope {\n  id = `__interact_scope_${Math.floor(Math.random() * 100)}`\n  isInitialized = false\n  listenerMaps: Array<{\n    map: ListenerMap\n    id?: string\n  }> = []\n\n  browser = browser\n  defaults = clone(defaults) as typeof defaults\n  Eventable = Eventable\n  actions: Actions = {\n    map: {},\n    phases: {\n      start: true,\n      move: true,\n      end: true,\n    },\n    methodDict: {} as any,\n    phaselessTypes: {},\n  }\n\n  interactStatic = createInteractStatic(this)\n  InteractEvent = InteractEvent\n  Interactable: typeof InteractableBase\n  interactables = new InteractableSet(this)\n\n  // main window\n  _win!: Window\n\n  // main document\n  document!: Document\n\n  // main window\n  window!: Window\n\n  // all documents being listened to\n  documents: Array<{ doc: Document; options: any }> = []\n\n  _plugins: {\n    list: Plugin[]\n    map: { [id: string]: Plugin }\n  } = {\n    list: [],\n    map: {},\n  }\n\n  constructor() {\n    const scope = this\n\n    this.Interactable = class extends InteractableBase {\n      get _defaults() {\n        return scope.defaults\n      }\n\n      set<T extends InteractableBase>(this: T, options: OptionsArg) {\n        super.set(options)\n\n        scope.fire('interactable:set', {\n          options,\n          interactable: this,\n        })\n\n        return this\n      }\n\n      unset(this: InteractableBase) {\n        super.unset()\n\n        const index = scope.interactables.list.indexOf(this)\n        if (index < 0) return\n\n        scope.interactables.list.splice(index, 1)\n        scope.fire('interactable:unset', { interactable: this })\n      }\n    }\n  }\n\n  addListeners(map: ListenerMap, id?: string) {\n    this.listenerMaps.push({ id, map })\n  }\n\n  fire<T extends ListenerName>(name: T, arg: SignalArgs[T]): void | false {\n    for (const {\n      map: { [name]: listener },\n    } of this.listenerMaps) {\n      if (!!listener && listener(arg as any, this, name as never) === false) {\n        return false\n      }\n    }\n  }\n\n  onWindowUnload = (event: BeforeUnloadEvent) => this.removeDocument(event.target as Document)\n\n  init(window: Window | typeof globalThis) {\n    return this.isInitialized ? this : initScope(this, window)\n  }\n\n  pluginIsInstalled(plugin: Plugin) {\n    const { id } = plugin\n    return id ? !!this._plugins.map[id] : this._plugins.list.indexOf(plugin) !== -1\n  }\n\n  usePlugin(plugin: Plugin, options?: { [key: string]: any }) {\n    if (!this.isInitialized) {\n      return this\n    }\n\n    if (this.pluginIsInstalled(plugin)) {\n      return this\n    }\n\n    if (plugin.id) {\n      this._plugins.map[plugin.id] = plugin\n    }\n    this._plugins.list.push(plugin)\n\n    if (plugin.install) {\n      plugin.install(this, options)\n    }\n\n    if (plugin.listeners && plugin.before) {\n      let index = 0\n      const len = this.listenerMaps.length\n      const before = plugin.before.reduce((acc, id) => {\n        acc[id] = true\n        acc[pluginIdRoot(id)] = true\n        return acc\n      }, {})\n\n      for (; index < len; index++) {\n        const otherId = this.listenerMaps[index].id\n\n        if (otherId && (before[otherId] || before[pluginIdRoot(otherId)])) {\n          break\n        }\n      }\n\n      this.listenerMaps.splice(index, 0, { id: plugin.id, map: plugin.listeners })\n    } else if (plugin.listeners) {\n      this.listenerMaps.push({ id: plugin.id, map: plugin.listeners })\n    }\n\n    return this\n  }\n\n  addDocument(doc: Document, options?: any): void | false {\n    // do nothing if document is already known\n    if (this.getDocIndex(doc) !== -1) {\n      return false\n    }\n\n    const window = win.getWindow(doc)\n\n    options = options ? extend({}, options) : {}\n\n    this.documents.push({ doc, options })\n    this.events.documents.push(doc)\n\n    // don't add an unload event for the main document\n    // so that the page may be cached in browser history\n    if (doc !== this.document) {\n      this.events.add(window, 'unload', this.onWindowUnload)\n    }\n\n    this.fire('scope:add-document', { doc, window, scope: this, options })\n  }\n\n  removeDocument(doc: Document) {\n    const index = this.getDocIndex(doc)\n\n    const window = win.getWindow(doc)\n    const options = this.documents[index].options\n\n    this.events.remove(window, 'unload', this.onWindowUnload)\n\n    this.documents.splice(index, 1)\n    this.events.documents.splice(index, 1)\n\n    this.fire('scope:remove-document', { doc, window, scope: this, options })\n  }\n\n  getDocIndex(doc: Document) {\n    for (let i = 0; i < this.documents.length; i++) {\n      if (this.documents[i].doc === doc) {\n        return i\n      }\n    }\n\n    return -1\n  }\n\n  getDocOptions(doc: Document) {\n    const docIndex = this.getDocIndex(doc)\n\n    return docIndex === -1 ? null : this.documents[docIndex].options\n  }\n\n  now() {\n    return (((this.window as any).Date as typeof Date) || Date).now()\n  }\n}\n\n// Keep Scope class internal, but expose minimal interface to avoid broken types when Scope is stripped out\nexport interface Scope {\n  fire<T extends ListenerName>(name: T, arg: SignalArgs[T]): void | false\n}\n\n/** @internal */\nexport function initScope(scope: Scope, window: Window | typeof globalThis) {\n  scope.isInitialized = true\n\n  if (is.window(window)) {\n    win.init(window)\n  }\n\n  domObjects.init(window)\n  browser.init(window)\n  raf.init(window)\n\n  // @ts-expect-error\n  scope.window = window\n  scope.document = window.document\n\n  scope.usePlugin(interactions)\n  scope.usePlugin(events)\n\n  return scope\n}\n\nfunction pluginIdRoot(id: string) {\n  return id && id.replace(/\\/.*$/, '')\n}\n"
  },
  {
    "path": "packages/@interactjs/core/tests/_helpers.ts",
    "content": "import extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport type { PointerType, Rect, Target, ActionName, ActionProps } from '@interactjs/core/types'\n\nimport type { Plugin } from '../scope'\nimport { Scope } from '../scope'\n\nlet counter = 0\n\nexport function unique() {\n  return counter++\n}\n\nexport function uniqueProps(obj: any) {\n  for (const prop in obj) {\n    if (!obj.hasOwnProperty(prop)) {\n      continue\n    }\n\n    if (is.object(obj)) {\n      uniqueProps(obj[prop])\n    } else {\n      obj[prop] = counter++\n    }\n  }\n}\n\nexport function newCoordsSet(n = 0) {\n  return {\n    start: {\n      page: { x: n++, y: n++ },\n      client: { x: n++, y: n++ },\n      timeStamp: n++,\n    },\n    cur: {\n      page: { x: n++, y: n++ },\n      client: { x: n++, y: n++ },\n      timeStamp: n++,\n    },\n    prev: {\n      page: { x: n++, y: n++ },\n      client: { x: n++, y: n++ },\n      timeStamp: n++,\n    },\n    delta: {\n      page: { x: n++, y: n++ },\n      client: { x: n++, y: n++ },\n      timeStamp: n++,\n    },\n    velocity: {\n      page: { x: n++, y: n++ },\n      client: { x: n++, y: n++ },\n      timeStamp: n++,\n    },\n  }\n}\n\nexport function newPointer(n = 50) {\n  return {\n    pointerId: n++,\n    pageX: n++,\n    pageY: n++,\n    clientX: n++,\n    clientY: n++,\n  } as PointerType\n}\n\nexport function mockScope({ document = window.document } = {} as any) {\n  const window = document.defaultView\n\n  const scope = new Scope().init(window)\n\n  extend(scope.actions.phaselessTypes, { teststart: true, testmove: true, testend: true })\n\n  return scope\n}\n\nexport function getProps<T extends { [key: string]: any }, K extends keyof T>(src: T, props: readonly K[]) {\n  return props.reduce(\n    (acc, prop) => {\n      if (prop in src) {\n        acc[prop] = src[prop]\n      }\n\n      return acc\n    },\n    {} as Pick<T, K>,\n  )\n}\n\nexport function testEnv<T extends Target = HTMLElement>({\n  plugins = [],\n  target,\n  rect,\n  document = window.document,\n}: {\n  plugins?: Plugin[]\n  target?: T\n  rect?: Rect\n  document?: Document\n} = {}) {\n  const scope = mockScope({ document })\n\n  for (const plugin of plugins) {\n    scope.usePlugin(plugin)\n  }\n\n  if (!target) {\n    ;(target as unknown as HTMLElement) = scope.document.body\n  }\n\n  const interaction = scope.interactions.new({})\n  const interactable = scope.interactables.new(target)\n  const coords: pointerUtils.MockCoords = pointerUtils.newCoords()\n\n  coords.target = target\n  const event = pointerUtils.coordsToEvent(coords)\n\n  if (rect) {\n    interactable.rectChecker(() => ({ ...rect }))\n  }\n\n  return {\n    scope,\n    interaction,\n    target: target as T extends undefined ? HTMLElement : T,\n    interactable,\n    coords,\n    event,\n    interact: scope.interactStatic,\n    start: <T extends ActionName>(action: ActionProps<T>) =>\n      interaction.start(action, interactable, target as HTMLElement),\n    stop: () => interaction.stop(),\n    down: () => interaction.pointerDown(event, event, target as HTMLElement),\n    move: (force?: boolean) =>\n      force ? interaction.move() : interaction.pointerMove(event, event, target as HTMLElement),\n    up: () => interaction.pointerUp(event, event, target as HTMLElement, target as HTMLElement),\n  }\n}\n\nexport function timeout(n: number) {\n  return new Promise((resolve) => setTimeout(resolve, n))\n}\n\nexport function ltrbwh(\n  left: number,\n  top: number,\n  right: number,\n  bottom: number,\n  width: number,\n  height: number,\n) {\n  return { left, top, right, bottom, width, height }\n}\n"
  },
  {
    "path": "packages/@interactjs/core/types.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\n\nimport type { Interactable } from './Interactable'\nimport type { PhaseMap, InteractEvent } from './InteractEvent'\nimport type { NativePointerEvent as NativePointerEvent_ } from './NativeTypes'\n\nexport type OrBoolean<T> = {\n  [P in keyof T]: T[P] | boolean\n}\n\nexport type Element = HTMLElement | SVGElement\nexport type Context = Document | Element\nexport type EventTarget = Window | Document | Element\nexport type Target = EventTarget | string\n\nexport interface Point {\n  x: number\n  y: number\n}\n\nexport interface Size {\n  width: number\n  height: number\n}\n\nexport interface Rect {\n  top: number\n  left: number\n  bottom: number\n  right: number\n  width?: number\n  height?: number\n}\n\nexport type FullRect = Required<Rect>\n\nexport type RectFunction<T extends any[]> = (...args: T) => Rect | Element\n\nexport type RectResolvable<T extends any[]> = Rect | string | Element | RectFunction<T>\n\nexport type Dimensions = Point & Size\n\nexport interface CoordsSetMember {\n  page: Point\n  client: Point\n  timeStamp: number\n}\n\nexport interface CoordsSet {\n  cur: CoordsSetMember\n  prev: CoordsSetMember\n  start: CoordsSetMember\n  delta: CoordsSetMember\n  velocity: CoordsSetMember\n}\n\nexport interface HasGetRect {\n  getRect(element: Element): Rect\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface ActionMap {}\n\nexport type ActionName = keyof ActionMap\n\nexport interface Actions {\n  map: ActionMap\n  phases: PhaseMap\n  methodDict: Record<ActionName, keyof Interactable>\n  phaselessTypes: { [type: string]: true }\n}\n\nexport interface ActionProps<T extends ActionName | null = never> {\n  name: T\n  axis?: 'x' | 'y' | 'xy' | null\n  edges?: EdgeOptions | null\n}\n\nexport interface InertiaOption {\n  resistance?: number\n  minSpeed?: number\n  endSpeed?: number\n  allowResume?: boolean\n  smoothEndDuration?: number\n}\nexport type InertiaOptions = InertiaOption | boolean\n\nexport interface EdgeOptions {\n  top?: boolean | string | Element\n  left?: boolean | string | Element\n  bottom?: boolean | string | Element\n  right?: boolean | string | Element\n}\n\nexport type CursorChecker = (\n  action: ActionProps<ActionName>,\n  interactable: Interactable,\n  element: Element,\n  interacting: boolean,\n) => string\n\nexport interface ActionMethod<T> {\n  (this: Interactable): T\n  (this: Interactable, options?: Partial<OrBoolean<T>> | boolean): typeof this\n}\n\nexport interface OptionMethod<T> {\n  (this: Interactable): T\n  // eslint-disable-next-line no-undef\n  (this: Interactable, options: T): typeof this\n}\n\nexport type ActionChecker = (\n  pointerEvent: any,\n  defaultAction: string,\n  interactable: Interactable,\n  element: Element,\n  interaction: Interaction,\n) => ActionProps\n\nexport type OriginFunction = (target: Element) => Rect\n\nexport interface PointerEventsOptions {\n  holdDuration?: number\n  allowFrom?: string\n  ignoreFrom?: string\n  origin?: Rect | Point | string | Element | OriginFunction\n}\n\nexport type RectChecker = (element: Element) => Rect\n\nexport type NativePointerEventType = typeof NativePointerEvent_\nexport type PointerEventType = MouseEvent | TouchEvent | Partial<NativePointerEventType> | InteractEvent\nexport type PointerType = MouseEvent | Touch | Partial<NativePointerEventType> | InteractEvent\n\nexport type EventTypes = string | ListenerMap | Array<string | ListenerMap>\n\nexport type Listener = (...args: any[]) => any\nexport type Listeners = ListenerMap | ListenerMap[]\nexport type ListenersArg = Listener | ListenerMap | Array<Listener | ListenerMap>\nexport interface ListenerMap {\n  [index: string]: ListenersArg | ListenersArg[]\n}\n\nexport type ArrayElementType<T> = T extends Array<infer P> ? P : never\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/babel-plugin-prod.js",
    "content": "/* global process, __dirname */\nconst path = require('path')\n\nconst PROD_EXT = '.prod'\n\nfunction fixImportSource ({ node: { source } }, { filename }) {\n  if (shouldIgnoreImport(source)) return\n\n  let resolvedShort = ''\n\n  try {\n    const paths = [filename && path.dirname(filename), __dirname, process.cwd()].filter((p) => !!p)\n\n    const resolved = require.resolve(source.value, { paths })\n    const resolvedWithoutScopePath = resolved.replace(/.*[\\\\/]@interactjs[\\\\/]/, '')\n\n    resolvedShort = path\n      .join('@interactjs', resolvedWithoutScopePath)\n      // windows path to posix\n      .replace(/\\\\/g, '/')\n    source.value = resolvedShort.replace(/(\\.js)?$/, PROD_EXT)\n  } catch (e) {}\n}\n\nfunction babelPluginInteractjsProd () {\n  if (process.env.NODE_ENV === 'development') {\n    // eslint-disable-next-line no-console\n    console.warn(\n      \"[@interactjs/dev-tools] You're using the production plugin in the development environment. You might lose out on some helpful hints!\",\n    )\n  }\n\n  return {\n    visitor: {\n      ImportDeclaration: fixImportSource,\n      ExportNamedDeclaration: fixImportSource,\n      ExportAllDeclaration: fixImportSource,\n      ExportDefaultSpecifier: fixImportSource,\n    },\n  }\n}\n\nfunction shouldIgnoreImport (source) {\n  return (\n    !source ||\n    // only change @interactjs scoped imports\n    !source.value.startsWith('@interactjs/') ||\n    // ignore imports of prod files\n    source.value.endsWith(PROD_EXT) ||\n    source.value.endsWith(PROD_EXT + '.js')\n  )\n}\n\nmodule.exports = babelPluginInteractjsProd\n\nObject.assign(module.exports, {\n  default: babelPluginInteractjsProd,\n  fixImportSource,\n})\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/babel-plugin-prod.spec.ts",
    "content": "/** @jest-environment node */\nimport * as babel from '@babel/core'\nimport proposalExportDefaultFrom from '@babel/plugin-proposal-export-default-from'\n\nimport babelPluginProd, { fixImportSource } from './babel-plugin-prod'\n\ndescribe('@dev-tools/prod/babel-plugin-prod', () => {\n  const filename = require.resolve('@interactjs/_dev/test/fixtures/babelPluginProject/index.js')\n\n  const cases = [\n    {\n      module: 'x',\n      expected: 'x',\n      message: 'non @interact/* package unchanged',\n    },\n    {\n      module: 'interact',\n      expected: 'interact',\n      message: 'unscoped interact import unchanged',\n    },\n    {\n      module: '@interactjs/NONEXISTENT_PACKAGE',\n      expected: '@interactjs/NONEXISTENT_PACKAGE',\n      message: 'missing package unchanged',\n    },\n    {\n      module: '@interactjs/a/NONEXISTENT_MODULE',\n      expected: '@interactjs/a/NONEXISTENT_MODULE',\n      message: 'import of missing module unchanged',\n    },\n    {\n      module: '@interactjs/a',\n      expected: '@interactjs/a/package-main-file.prod',\n      message: 'package main module',\n    },\n    {\n      module: '@interactjs/a/a',\n      expected: '@interactjs/a/a.prod',\n      message: 'package root-level non index module',\n    },\n    {\n      module: '@interactjs/a/b',\n      expected: '@interactjs/a/b/index.prod',\n      message: 'nested index module',\n    },\n    {\n      module: '@interactjs/a/b/b',\n      expected: '@interactjs/a/b/b.prod',\n      message: 'package nested non index module',\n    },\n  ]\n\n  for (const { module, expected, message } of cases) {\n    // eslint-disable-next-line jest/valid-title\n    test(message, () => {\n      const source = { value: module }\n\n      fixImportSource({ node: { source } }, { filename })\n\n      expect(source.value).toBe(expected)\n    })\n  }\n\n  test('transforms code when used in babel config', () => {\n    expect(\n      babel.transform(\n        [\n          'import \"@interactjs/a/a\";',\n          'import a, { b } from \"@interactjs/a/a\";',\n          'export b from \"@interactjs/a/a\";',\n          'export * from \"@interactjs/a/a\";',\n        ].join('\\n'),\n        {\n          babelrc: false,\n          configFile: false,\n          plugins: [babelPluginProd, [proposalExportDefaultFrom, { loose: true }]],\n          filename,\n          sourceType: 'module',\n        },\n      ).code,\n    ).toEqual(\n      [\n        'import \"@interactjs/a/a.prod\";',\n        'import a, { b } from \"@interactjs/a/a.prod\";',\n        'export { default as b } from \"@interactjs/a/a.prod\";',\n        'export * from \"@interactjs/a/a.prod\";',\n      ].join('\\n'),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/devTools.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\nimport resize from '@interactjs/actions/resize/plugin'\nimport * as helpers from '@interactjs/core/tests/_helpers'\n\nimport type { Check, Logger } from './plugin'\nimport devTools from './plugin'\n\nconst { checks, links, prefix } = devTools\nconst checkMap = checks.reduce(\n  (acc, check) => {\n    acc[check.name] = check\n    return acc\n  },\n  {} as { [name: string]: Check },\n)\n\ntest('devTools', () => {\n  const devToolsWithLogger = {\n    install: (s) =>\n      s.usePlugin(devTools, {\n        logger: {\n          warn(...args: any[]) {\n            log(args, 'warn')\n          },\n          log(...args: any[]) {\n            log(args, 'log')\n          },\n          error(...args: any[]) {\n            log(args, 'error')\n          },\n        },\n      }),\n  }\n\n  const {\n    scope,\n    interaction,\n    interactable,\n    target: element,\n    down,\n    start,\n    move,\n    stop,\n  } = helpers.testEnv({\n    plugins: [devToolsWithLogger, drag, resize],\n  })\n\n  const logs: Array<{ args: any[]; type: keyof Logger }> = []\n\n  function log(args: any, type: any) {\n    logs.push({ args, type })\n  }\n\n  scope.usePlugin(drag)\n  scope.usePlugin(resize)\n\n  interactable.draggable(true).resizable({ onmove: () => {} })\n\n  down()\n  start({ name: 'drag' })\n  // warning about missing touchAction\n  expect(logs[0]).toEqual({\n    args: [prefix + checkMap.touchAction.text, element, links.touchAction],\n    type: 'warn',\n  })\n\n  // warning about missing move listeners\n  expect(logs[1]).toEqual({ args: [prefix + checkMap.noListeners.text, 'drag', interactable], type: 'warn' })\n\n  stop()\n\n  // resolve touchAction\n  element.style.touchAction = 'none'\n  // resolve missing listeners\n  interactable.on('dragmove', () => {})\n\n  interaction.start({ name: 'resize' }, interactable, element)\n  move()\n  stop()\n\n  // warning about resizing without \"box-sizing: none\"\n  expect(logs[2]).toEqual({\n    args: [prefix + checkMap.boxSizing.text, element, links.boxSizing],\n    type: 'warn',\n  })\n\n  logs.splice(0)\n\n  interaction.start({ name: 'resize' }, interactable, element)\n  move()\n  stop()\n\n  interactable.options.devTools.ignore = { boxSizing: true }\n\n  interaction.start({ name: 'resize' }, interactable, element)\n  move()\n  stop()\n\n  // warning removed with options.devTools.ignore\n  expect(logs).toHaveLength(1)\n\n  logs.splice(0)\n\n  // resolve boxSizing\n  interactable.options.devTools.ignore = {}\n  element.style.boxSizing = 'border-box'\n\n  interaction.start({ name: 'resize' }, interactable, element)\n  move(true)\n  stop()\n\n  interaction.start({ name: 'drag' }, interactable, element)\n  move()\n  stop()\n\n  // no warnings when issues are resolved\n  expect(logs).toHaveLength(0)\n})\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/package.json",
    "content": "{\n  \"name\": \"@interactjs/dev-tools\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/dev-tools\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/modifiers\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\",\n    \"vue\": \"3\"\n  },\n  \"devDependencies\": {\n    \"vue\": \"next\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/plugin.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Element, OptionMethod } from '@interactjs/core/types'\nimport domObjects from '@interactjs/utils/domObjects'\nimport { parentNode } from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport isNonNativeEvent from '@interactjs/utils/isNonNativeEvent'\nimport normalizeListeners from '@interactjs/utils/normalizeListeners'\nimport * as win from '@interactjs/utils/window'\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    logger: Logger\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface BaseDefaults {\n    devTools?: DevToolsOptions\n  }\n}\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    devTools: OptionMethod<DevToolsOptions>\n  }\n}\n\nexport interface DevToolsOptions {\n  ignore: { [P in keyof typeof CheckName]?: boolean }\n}\n\nexport interface Logger {\n  warn: (...args: any[]) => void\n  error: (...args: any[]) => void\n  log: (...args: any[]) => void\n}\n\nexport interface Check {\n  name: CheckName\n  text: string\n  perform: (interaction: Interaction) => boolean\n  getInfo: (interaction: Interaction) => any[]\n}\n\nenum CheckName {\n  touchAction = 'touchAction',\n  boxSizing = 'boxSizing',\n  noListeners = 'noListeners',\n}\n\nconst prefix = '[interact.js] '\nconst links = {\n  touchAction: 'https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action',\n  boxSizing: 'https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing',\n}\n\n// eslint-disable-next-line no-undef\nconst isProduction = process.env.NODE_ENV === 'production'\n\nfunction install(scope: Scope, { logger }: { logger?: Logger } = {}) {\n  const { Interactable, defaults } = scope\n\n  scope.logger = logger || console\n\n  defaults.base.devTools = {\n    ignore: {},\n  }\n\n  Interactable.prototype.devTools = function (options?: object) {\n    if (options) {\n      extend(this.options.devTools, options)\n      return this\n    }\n\n    return this.options.devTools\n  }\n\n  // can't set native events on non string targets without `addEventListener` prop\n  const { _onOff } = Interactable.prototype\n  Interactable.prototype._onOff = function (method, typeArg, listenerArg, options, filter) {\n    if (is.string(this.target) || this.target.addEventListener) {\n      return _onOff.call(this, method, typeArg, listenerArg, options, filter)\n    }\n\n    if (is.object(typeArg) && !is.array(typeArg)) {\n      options = listenerArg\n      listenerArg = null\n    }\n\n    const normalizedListeners = normalizeListeners(typeArg, listenerArg, filter)\n\n    for (const type in normalizedListeners) {\n      if (isNonNativeEvent(type, scope.actions)) continue\n      scope.logger.warn(\n        prefix +\n          `Can't add native \"${type}\" event listener to target without \\`addEventListener(type, listener, options)\\` prop.`,\n      )\n    }\n\n    return _onOff.call(this, method, normalizedListeners, options)\n  }\n}\n\nconst checks: Check[] = [\n  {\n    name: CheckName.touchAction,\n    perform({ element }) {\n      return !!element && !parentHasStyle(element, 'touchAction', /pan-|pinch|none/)\n    },\n    getInfo({ element }) {\n      return [element, links.touchAction]\n    },\n    text: 'Consider adding CSS \"touch-action: none\" to this element\\n',\n  },\n\n  {\n    name: CheckName.boxSizing,\n    perform(interaction) {\n      const { element } = interaction\n\n      return (\n        interaction.prepared.name === 'resize' &&\n        element instanceof domObjects.HTMLElement &&\n        !hasStyle(element, 'boxSizing', /border-box/)\n      )\n    },\n    text: 'Consider adding CSS \"box-sizing: border-box\" to this resizable element',\n    getInfo({ element }) {\n      return [element, links.boxSizing]\n    },\n  },\n\n  {\n    name: CheckName.noListeners,\n    perform(interaction) {\n      const actionName = interaction.prepared.name\n      const moveListeners = interaction.interactable?.events.types[`${actionName}move`] || []\n\n      return !moveListeners.length\n    },\n    getInfo(interaction) {\n      return [interaction.prepared.name, interaction.interactable]\n    },\n    text: 'There are no listeners set for this action',\n  },\n]\n\nfunction hasStyle(element: HTMLElement, prop: keyof CSSStyleDeclaration, styleRe: RegExp) {\n  const value = element.style[prop] || win.window.getComputedStyle(element)[prop]\n  return styleRe.test((value || '').toString())\n}\n\nfunction parentHasStyle(element: Element, prop: keyof CSSStyleDeclaration, styleRe: RegExp) {\n  let parent = element as HTMLElement\n\n  while (is.element(parent)) {\n    if (hasStyle(parent, prop, styleRe)) {\n      return true\n    }\n\n    parent = parentNode(parent) as HTMLElement\n  }\n\n  return false\n}\n\nconst id = 'dev-tools'\nconst defaultExport: Plugin = isProduction\n  ? { id, install: () => {} }\n  : {\n      id,\n      install,\n      listeners: {\n        'interactions:action-start': ({ interaction }, scope) => {\n          for (const check of checks) {\n            const options = interaction.interactable && interaction.interactable.options\n\n            if (\n              !(options && options.devTools && options.devTools.ignore[check.name]) &&\n              check.perform(interaction)\n            ) {\n              scope.logger.warn(prefix + check.text, ...check.getInfo(interaction))\n            }\n          }\n        },\n      },\n      checks,\n      CheckName,\n      links,\n      prefix,\n    }\n\nexport default defaultExport\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/visualizer/plugin.stub.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/visualizer/plugin.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/visualizer/visualizer.spec.stub.ts",
    "content": "test.skip('visualizer', () => {})\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/visualizer/visualizer.spec.ts",
    "content": "test.skip('visualizer', () => {})\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/visualizer/vueModules.stub.ts",
    "content": "export {}\n"
  },
  {
    "path": "packages/@interactjs/dev-tools/visualizer/vueModules.ts",
    "content": "export {}\n"
  },
  {
    "path": "packages/@interactjs/inertia/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/inertia/inertia.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\nimport type { EventPhase, InteractEvent } from '@interactjs/core/InteractEvent'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport extend from '@interactjs/utils/extend'\n\nimport inertia from './plugin'\n\ntest('inertia', () => {\n  const { scope, interaction, down, start, move, up, interactable, coords } = helpers.testEnv({\n    plugins: [inertia, drag],\n    rect: { left: 0, top: 0, bottom: 100, right: 100 },\n  })\n\n  const state = interaction.inertia\n  const modifierChange = 5\n  const changeModifier = {\n    options: { endOnly: false },\n    methods: {\n      set({ coords: modifierCoords, phase }: any) {\n        modifierCoords.x = modifierChange\n        modifierCoords.y = modifierChange\n        modifierCallPhases.push(phase)\n      },\n    },\n  }\n\n  let fired: Array<InteractEvent<'drag'>> = []\n  let modifierCallPhases: EventPhase[] = []\n\n  coords.client = coords.page\n  scope.now = () => coords.timeStamp\n  interactable.draggable({ inertia: true }).on(\n    Object.keys(scope.actions.phases).map((p) => `drag${p}`),\n    (e) => fired.push(e),\n  )\n\n  // test inertia without modifiers or throw\n  downStartMoveUp({ x: 100, y: 0, dt: 1000 })\n  // { modifiers: [] } && !thrown: inertia is not activated\n  expect(state.active).toBe(false)\n\n  // test inertia without modifiers and with throw\n  downStartMoveUp({ x: 100, y: 0, dt: 10 })\n  // thrown: inertia is activated\n  expect(state.active && state.timeout).toBeTruthy()\n\n  interactable.draggable({ modifiers: [changeModifier as any] })\n\n  // test inertia with { endOnly: false } modifier and with throw\n  downStartMoveUp({ x: 100, y: 0, dt: 10 })\n  // { endOnly: false } && thrown: modifier is called from pointerUp inertia calc and phase\n  expect(modifierCallPhases).toEqual(['move', 'inertiastart', 'inertiastart'])\n  // { endOnly: false } && thrown: move, inertiastart, and end InteractEvents are modified\n  expect(fired.map(({ page, type }) => ({ ...page, type }))).toEqual([\n    { x: 0, y: 0, type: 'dragstart' },\n    { x: modifierChange, y: modifierChange, type: 'dragmove' },\n    { x: modifierChange, y: modifierChange, type: 'draginertiastart' },\n  ])\n\n  // test inertia with { endOnly: true } modifier and with throw\n  changeModifier.options.endOnly = true\n  downStartMoveUp({ x: 100, y: 0, dt: 10 })\n  // { endOnly: true } && thrown: modifier is called from pointerUp inertia calc\n  expect(modifierCallPhases).toEqual(['inertiastart'])\n  // { endOnly: true } && thrown: inertia target coords are correct\n  expect(state.modifiedOffset).toEqual({\n    // modified target minus move coords\n    x: modifierChange - 100,\n    y: modifierChange - 0,\n  })\n\n  // test smoothEnd with { endOnly: false } modifier\n  changeModifier.options.endOnly = false\n  downStartMoveUp({ x: 1, y: 0, dt: 1000 })\n  // { endOnly: false } && !thrown: inertia smoothEnd is not activated\n  expect(state.active).toBe(false)\n  // { endOnly: false } && !thrown: modifier is called from pointerUp\n  expect(modifierCallPhases).toEqual(['move', 'inertiastart'])\n\n  // test smoothEnd with { endOnly: true } modifier\n  changeModifier.options.endOnly = true\n  downStartMoveUp({ x: 1, y: 0, dt: 1000 })\n  // { endOnly: true } && !thrown: inertia smoothEnd is activated\n  expect(state.active).toBe(true)\n  // { endOnly: true } && !thrown: modifier is called from pointerUp smooth end check\n  expect(modifierCallPhases).toEqual(['inertiastart'])\n\n  interactable.draggable({\n    modifiers: [\n      {\n        options: { endOnly: true },\n        methods: {\n          set({ coords: modifiedCoords, phase }) {\n            extend(modifiedCoords, { x: 300, y: 400 })\n            modifierCallPhases.push(phase)\n          },\n        },\n        enable: null,\n        disable: null,\n      },\n    ],\n  })\n\n  downStartMoveUp({ x: 50, y: 70, dt: 1000 })\n  coords.timeStamp = 100\n  expect(state.targetOffset).toEqual({ x: 250, y: 330 })\n\n  extend(coords.page, { x: 50, y: 100 })\n  down()\n  // inertia is stopped on resume\n  expect(interaction._interacting && !state.active).toBe(true)\n  // interaction coords are updated to down coords on resume\n  expect({ coords: interaction.coords.cur.page, rect: interaction.rect }).toEqual({\n    coords: coords.page,\n    rect: { left: 50, top: 70, right: 150, bottom: 170, width: 100, height: 100 },\n  })\n  // action resume event coords are set correctly\n  expect(lastEvent().page).toEqual(coords.page)\n\n  move()\n  // interaction coords are correct on duplicate move after resume\n  expect({ coords: interaction.coords.cur.page, rect: interaction.rect }).toEqual({\n    coords: coords.page,\n    rect: { left: 50, top: 70, right: 150, bottom: 170, width: 100, height: 100 },\n  })\n  // second release inertia target is not the modified target\n  // second release inertia target is not the pointer event coords\n  // action move event coords on duplicate move after resume is correct\n  expect(lastEvent().page).toEqual(coords.page)\n\n  extend(coords.page, { x: 200, y: 250 })\n  move()\n  up()\n  expect(state.targetOffset).not.toEqual(coords.page)\n  expect(state.targetOffset).not.toEqual({ x: 300, y: 400 })\n  // inertiastart is fired at non preEnd modified coords\n  expect(helpers.getProps(lastEvent(), ['type', 'page', 'rect'] as const)).toEqual({\n    type: 'draginertiastart',\n    page: coords.page,\n    rect: { left: 200, top: 220, right: 300, bottom: 320, width: 100, height: 100 },\n  })\n\n  down()\n  extend(coords.page, { x: 150, y: 400 })\n  move()\n  // interaction coords after second resume are correct\n  expect({ coords: interaction.coords.cur.page, rect: interaction.rect }).toEqual({\n    coords: coords.page,\n    rect: { left: 150, top: 370, right: 250, bottom: 470, width: 100, height: 100 },\n  })\n  // action move event after second resume is fired at non preEnd modified coords\n  expect(helpers.getProps(lastEvent(), ['type', 'page', 'rect'] as const)).toEqual({\n    type: 'dragmove',\n    page: coords.page,\n    rect: { left: 150, top: 370, right: 250, bottom: 470, width: 100, height: 100 },\n  })\n\n  interaction.stop()\n\n  function downStartMoveUp({ x, y, dt }: any) {\n    fired = []\n    modifierCallPhases = []\n    coords.timeStamp = 0\n    interaction.stop()\n\n    Object.assign(coords.page, { x: 0, y: 0 })\n    down()\n\n    start({ name: 'drag' })\n\n    Object.assign(coords.page, { x, y })\n    coords.timeStamp = dt\n    move()\n    up()\n  }\n\n  function lastEvent() {\n    return fired[fired.length - 1]\n  }\n})\n"
  },
  {
    "path": "packages/@interactjs/inertia/package.json",
    "content": "{\n  \"name\": \"@interactjs/inertia\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/inertia\"\n  },\n  \"dependencies\": {\n    \"@interactjs/offset\": \"1.10.27\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/modifiers\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/inertia/plugin.ts",
    "content": "import type { Interaction, DoPhaseArg } from '@interactjs/core/Interaction'\nimport type { Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport type { ActionName, Point, PointerEventType } from '@interactjs/core/types'\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport '@interactjs/modifiers/base'\nimport '@interactjs/offset/plugin'\nimport * as modifiers from '@interactjs/modifiers/base'\nimport { Modification } from '@interactjs/modifiers/Modification'\nimport type { ModifierArg } from '@interactjs/modifiers/types'\nimport offset from '@interactjs/offset/plugin'\n/* eslint-enable import/no-duplicates */\nimport * as dom from '@interactjs/utils/domUtils'\nimport hypot from '@interactjs/utils/hypot'\nimport is from '@interactjs/utils/is'\nimport { copyCoords } from '@interactjs/utils/pointerUtils'\nimport raf from '@interactjs/utils/raf'\n\ndeclare module '@interactjs/core/InteractEvent' {\n  interface PhaseMap {\n    resume?: true\n    inertiastart?: true\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    inertia?: InertiaState\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface PerActionDefaults {\n    inertia?: {\n      enabled?: boolean\n      resistance?: number // the lambda in exponential decay\n      minSpeed?: number // target speed must be above this for inertia to start\n      endSpeed?: number // the speed at which inertia is slow enough to stop\n      allowResume?: true // allow resuming an action in inertia phase\n      smoothEndDuration?: number // animate to snap/restrict endOnly if there's no inertia\n    }\n  }\n}\n\ndeclare module '@interactjs/core/scope' {\n  interface SignalArgs {\n    'interactions:before-action-inertiastart': Omit<DoPhaseArg<ActionName, 'inertiastart'>, 'iEvent'>\n    'interactions:action-inertiastart': DoPhaseArg<ActionName, 'inertiastart'>\n    'interactions:after-action-inertiastart': DoPhaseArg<ActionName, 'inertiastart'>\n    'interactions:before-action-resume': Omit<DoPhaseArg<ActionName, 'resume'>, 'iEvent'>\n    'interactions:action-resume': DoPhaseArg<ActionName, 'resume'>\n    'interactions:after-action-resume': DoPhaseArg<ActionName, 'resume'>\n  }\n}\n\nfunction install(scope: Scope) {\n  const { defaults } = scope\n\n  scope.usePlugin(offset)\n  scope.usePlugin(modifiers.default)\n  scope.actions.phases.inertiastart = true\n  scope.actions.phases.resume = true\n\n  defaults.perAction.inertia = {\n    enabled: false,\n    resistance: 10, // the lambda in exponential decay\n    minSpeed: 100, // target speed must be above this for inertia to start\n    endSpeed: 10, // the speed at which inertia is slow enough to stop\n    allowResume: true, // allow resuming an action in inertia phase\n    smoothEndDuration: 300, // animate to snap/restrict endOnly if there's no inertia\n  }\n}\n\nexport class InertiaState {\n  active = false\n  isModified = false\n  smoothEnd = false\n  allowResume = false\n\n  modification!: Modification\n  modifierCount = 0\n  modifierArg!: ModifierArg\n\n  startCoords!: Point\n  t0 = 0\n  v0 = 0\n\n  te = 0\n  targetOffset!: Point\n  modifiedOffset!: Point\n  currentOffset!: Point\n\n  lambda_v0? = 0 // eslint-disable-line camelcase\n  one_ve_v0? = 0 // eslint-disable-line camelcase\n  timeout!: number\n  readonly interaction: Interaction\n\n  constructor(interaction: Interaction) {\n    this.interaction = interaction\n  }\n\n  start(event: PointerEventType) {\n    const { interaction } = this\n    const options = getOptions(interaction)\n\n    if (!options || !options.enabled) {\n      return false\n    }\n\n    const { client: velocityClient } = interaction.coords.velocity\n    const pointerSpeed = hypot(velocityClient.x, velocityClient.y)\n    const modification = this.modification || (this.modification = new Modification(interaction))\n\n    modification.copyFrom(interaction.modification)\n\n    this.t0 = interaction._now()\n    this.allowResume = options.allowResume\n    this.v0 = pointerSpeed\n    this.currentOffset = { x: 0, y: 0 }\n    this.startCoords = interaction.coords.cur.page\n\n    this.modifierArg = modification.fillArg({\n      pageCoords: this.startCoords,\n      preEnd: true,\n      phase: 'inertiastart',\n    })\n\n    const thrown =\n      this.t0 - interaction.coords.cur.timeStamp < 50 &&\n      pointerSpeed > options.minSpeed &&\n      pointerSpeed > options.endSpeed\n\n    if (thrown) {\n      this.startInertia()\n    } else {\n      modification.result = modification.setAll(this.modifierArg)\n\n      if (!modification.result.changed) {\n        return false\n      }\n\n      this.startSmoothEnd()\n    }\n\n    // force modification change\n    interaction.modification.result.rect = null\n\n    // bring inertiastart event to the target coords\n    interaction.offsetBy(this.targetOffset)\n    interaction._doPhase({\n      interaction,\n      event,\n      phase: 'inertiastart',\n    })\n    interaction.offsetBy({ x: -this.targetOffset.x, y: -this.targetOffset.y })\n    // force modification change\n    interaction.modification.result.rect = null\n\n    this.active = true\n    interaction.simulation = this\n\n    return true\n  }\n\n  startInertia() {\n    const startVelocity = this.interaction.coords.velocity.client\n    const options = getOptions(this.interaction)\n    const lambda = options.resistance\n    const inertiaDur = -Math.log(options.endSpeed / this.v0) / lambda\n\n    this.targetOffset = {\n      x: (startVelocity.x - inertiaDur) / lambda,\n      y: (startVelocity.y - inertiaDur) / lambda,\n    }\n\n    this.te = inertiaDur\n    this.lambda_v0 = lambda / this.v0\n    this.one_ve_v0 = 1 - options.endSpeed / this.v0\n\n    const { modification, modifierArg } = this\n\n    modifierArg.pageCoords = {\n      x: this.startCoords.x + this.targetOffset.x,\n      y: this.startCoords.y + this.targetOffset.y,\n    }\n\n    modification.result = modification.setAll(modifierArg)\n\n    if (modification.result.changed) {\n      this.isModified = true\n      this.modifiedOffset = {\n        x: this.targetOffset.x + modification.result.delta.x,\n        y: this.targetOffset.y + modification.result.delta.y,\n      }\n    }\n\n    this.onNextFrame(() => this.inertiaTick())\n  }\n\n  startSmoothEnd() {\n    this.smoothEnd = true\n    this.isModified = true\n    this.targetOffset = {\n      x: this.modification.result.delta.x,\n      y: this.modification.result.delta.y,\n    }\n\n    this.onNextFrame(() => this.smoothEndTick())\n  }\n\n  onNextFrame(tickFn: () => void) {\n    this.timeout = raf.request(() => {\n      if (this.active) {\n        tickFn()\n      }\n    })\n  }\n\n  inertiaTick() {\n    const { interaction } = this\n    const options = getOptions(interaction)\n    const lambda = options.resistance\n    const t = (interaction._now() - this.t0) / 1000\n\n    if (t < this.te) {\n      const progress = 1 - (Math.exp(-lambda * t) - this.lambda_v0) / this.one_ve_v0\n      let newOffset: Point\n\n      if (this.isModified) {\n        newOffset = getQuadraticCurvePoint(\n          0,\n          0,\n          this.targetOffset.x,\n          this.targetOffset.y,\n          this.modifiedOffset.x,\n          this.modifiedOffset.y,\n          progress,\n        )\n      } else {\n        newOffset = {\n          x: this.targetOffset.x * progress,\n          y: this.targetOffset.y * progress,\n        }\n      }\n\n      const delta = { x: newOffset.x - this.currentOffset.x, y: newOffset.y - this.currentOffset.y }\n\n      this.currentOffset.x += delta.x\n      this.currentOffset.y += delta.y\n\n      interaction.offsetBy(delta)\n      interaction.move()\n\n      this.onNextFrame(() => this.inertiaTick())\n    } else {\n      interaction.offsetBy({\n        x: this.modifiedOffset.x - this.currentOffset.x,\n        y: this.modifiedOffset.y - this.currentOffset.y,\n      })\n\n      this.end()\n    }\n  }\n\n  smoothEndTick() {\n    const { interaction } = this\n    const t = interaction._now() - this.t0\n    const { smoothEndDuration: duration } = getOptions(interaction)\n\n    if (t < duration) {\n      const newOffset = {\n        x: easeOutQuad(t, 0, this.targetOffset.x, duration),\n        y: easeOutQuad(t, 0, this.targetOffset.y, duration),\n      }\n      const delta = {\n        x: newOffset.x - this.currentOffset.x,\n        y: newOffset.y - this.currentOffset.y,\n      }\n\n      this.currentOffset.x += delta.x\n      this.currentOffset.y += delta.y\n\n      interaction.offsetBy(delta)\n      interaction.move({ skipModifiers: this.modifierCount })\n\n      this.onNextFrame(() => this.smoothEndTick())\n    } else {\n      interaction.offsetBy({\n        x: this.targetOffset.x - this.currentOffset.x,\n        y: this.targetOffset.y - this.currentOffset.y,\n      })\n\n      this.end()\n    }\n  }\n\n  resume({ pointer, event, eventTarget }: SignalArgs['interactions:down']) {\n    const { interaction } = this\n\n    // undo inertia changes to interaction coords\n    interaction.offsetBy({\n      x: -this.currentOffset.x,\n      y: -this.currentOffset.y,\n    })\n\n    // update pointer at pointer down position\n    interaction.updatePointer(pointer, event, eventTarget, true)\n\n    // fire resume signals and event\n    interaction._doPhase({\n      interaction,\n      event,\n      phase: 'resume',\n    })\n    copyCoords(interaction.coords.prev, interaction.coords.cur)\n\n    this.stop()\n  }\n\n  end() {\n    this.interaction.move()\n    this.interaction.end()\n    this.stop()\n  }\n\n  stop() {\n    this.active = this.smoothEnd = false\n    this.interaction.simulation = null\n    raf.cancel(this.timeout)\n  }\n}\n\nfunction start({ interaction, event }: DoPhaseArg<ActionName, 'end'>) {\n  if (!interaction._interacting || interaction.simulation) {\n    return null\n  }\n\n  const started = interaction.inertia.start(event)\n\n  // prevent action end if inertia or smoothEnd\n  return started ? false : null\n}\n\n// Check if the down event hits the current inertia target\n// control should be return to the user\nfunction resume(arg: SignalArgs['interactions:down']) {\n  const { interaction, eventTarget } = arg\n  const state = interaction.inertia\n\n  if (!state.active) return\n\n  let element = eventTarget as Node\n\n  // climb up the DOM tree from the event target\n  while (is.element(element)) {\n    // if interaction element is the current inertia target element\n    if (element === interaction.element) {\n      state.resume(arg)\n      break\n    }\n\n    element = dom.parentNode(element)\n  }\n}\n\nfunction stop({ interaction }: { interaction: Interaction }) {\n  const state = interaction.inertia\n\n  if (state.active) {\n    state.stop()\n  }\n}\n\nfunction getOptions({ interactable, prepared }: Interaction) {\n  return interactable && interactable.options && prepared.name && interactable.options[prepared.name].inertia\n}\n\nconst inertia: Plugin = {\n  id: 'inertia',\n  before: ['modifiers', 'actions'],\n  install,\n  listeners: {\n    'interactions:new': ({ interaction }) => {\n      interaction.inertia = new InertiaState(interaction)\n    },\n\n    'interactions:before-action-end': start,\n    'interactions:down': resume,\n    'interactions:stop': stop,\n\n    'interactions:before-action-resume': (arg) => {\n      const { modification } = arg.interaction\n\n      modification.stop(arg)\n      modification.start(arg, arg.interaction.coords.cur.page)\n      modification.applyToInteraction(arg)\n    },\n\n    'interactions:before-action-inertiastart': (arg) => arg.interaction.modification.setAndApply(arg),\n    'interactions:action-resume': modifiers.addEventModifiers,\n    'interactions:action-inertiastart': modifiers.addEventModifiers,\n    'interactions:after-action-inertiastart': (arg) =>\n      arg.interaction.modification.restoreInteractionCoords(arg),\n    'interactions:after-action-resume': (arg) => arg.interaction.modification.restoreInteractionCoords(arg),\n  },\n}\n\n// http://stackoverflow.com/a/5634528/2280888\nfunction _getQBezierValue(t: number, p1: number, p2: number, p3: number) {\n  const iT = 1 - t\n  return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3\n}\n\nfunction getQuadraticCurvePoint(\n  startX: number,\n  startY: number,\n  cpX: number,\n  cpY: number,\n  endX: number,\n  endY: number,\n  position: number,\n) {\n  return {\n    x: _getQBezierValue(position, startX, cpX, endX),\n    y: _getQBezierValue(position, startY, cpY, endY),\n  }\n}\n\n// http://gizma.com/easing/\nfunction easeOutQuad(t: number, b: number, c: number, d: number) {\n  t /= d\n  return -c * t * (t - 2) + b\n}\n\nexport default inertia\n"
  },
  {
    "path": "packages/@interactjs/interact/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/interact/index.ts",
    "content": "import { Scope } from '@interactjs/core/scope'\n\nconst scope = new Scope()\n\nconst interact = scope.interactStatic\n\nexport default interact\n\nconst _global = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this\nscope.init(_global)\n"
  },
  {
    "path": "packages/@interactjs/interact/interact.spec.ts",
    "content": "import { Scope } from '@interactjs/core/scope'\n\nconst makeIframeDoc = () => {\n  const iframe = document.body.appendChild(document.createElement('iframe'))\n  return iframe.contentWindow.document\n}\ntest('interact export', () => {\n  const scope = new Scope()\n  const interact = scope.interactStatic\n\n  scope.init(window)\n\n  const interactable1 = interact('selector')\n  // interact function returns Interactable instance\n  expect(interactable1).toBeInstanceOf(scope.Interactable)\n  // same interactable is returned with same target and context\n  expect(interact('selector')).toBe(interactable1)\n  // new interactables are added to list\n  expect(scope.interactables.list).toHaveLength(1)\n\n  interactable1.unset()\n  // unset interactables are removed\n  expect(scope.interactables.list).toHaveLength(0)\n  // unset interactions are removed\n  expect(scope.interactions.list).toHaveLength(0)\n\n  const doc1 = document\n  const doc2 = makeIframeDoc()\n  const results = (\n    [\n      ['repeat', doc1],\n      ['repeat', doc2],\n      [doc1, doc1],\n      [doc2.body, doc2],\n    ] as const\n  ).reduce((acc, [target, context]) => {\n    const interactable = interact(target, { context })\n\n    // unique contexts make unique interactables with identical targets\n    expect(acc.some((e) => e.interactable === interactable)).toBe(false)\n\n    acc.push({ interactable, target, context })\n    return acc\n  }, [])\n\n  for (const { interactable, target, context } of results) {\n    // interactions.get returns correct result with identical targets and different contexts\n    expect(scope.interactables.getExisting(target, { context })).toBe(interactable)\n  }\n\n  const doc3 = makeIframeDoc()\n\n  const prevDocCount = scope.documents.length\n\n  interact.addDocument(doc3, { events: { passive: false } })\n  // interact.addDocument() adds to scope with options\n  expect(scope.documents[prevDocCount]).toEqual({ doc: doc3, options: { events: { passive: false } } })\n\n  interact.removeDocument(doc3)\n  // interact.removeDocument() removes document from scope\n  expect(scope.documents).toHaveLength(prevDocCount)\n\n  scope.interactables.list.forEach((i) => i.unset())\n\n  const plugin1 = {\n    id: 'test-1',\n    install() {\n      plugin1.count++\n    },\n    count: 0,\n  }\n  const plugin2 = {\n    id: '',\n    install() {\n      plugin2.count++\n    },\n    count: 0,\n  }\n\n  interact.use(plugin1)\n  interact.use(plugin2)\n\n  // new plugin install methods are called\n  expect([plugin1.count, plugin2.count]).toEqual([1, 1])\n\n  interact.use({ ...plugin1 })\n  // different plugin object with same id not installed\n  expect([plugin1.count, plugin2.count]).toEqual([1, 1])\n\n  interact.use(plugin2)\n  // plugin without id not re-installed\n  expect([plugin1.count, plugin2.count]).toEqual([1, 1])\n})\n"
  },
  {
    "path": "packages/@interactjs/interact/package.json",
    "content": "{\n  \"name\": \"@interactjs/interact\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/interact\"\n  },\n  \"dependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/interactjs/index.stub.ts",
    "content": "/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport '@interactjs/actions/plugin'\nimport '@interactjs/auto-scroll/plugin'\nimport '@interactjs/auto-start/plugin'\nimport '@interactjs/core/interactablePreventDefault'\nimport '@interactjs/dev-tools/plugin'\nimport '@interactjs/inertia/plugin'\nimport '@interactjs/interact'\nimport '@interactjs/modifiers/plugin'\nimport '@interactjs/offset/plugin'\nimport '@interactjs/pointer-events/plugin'\nimport '@interactjs/reflow/plugin'\n\nimport actions from '@interactjs/actions/plugin'\nimport autoScroll from '@interactjs/auto-scroll/plugin'\nimport autoStart from '@interactjs/auto-start/plugin'\nimport interactablePreventDefault from '@interactjs/core/interactablePreventDefault'\nimport devTools from '@interactjs/dev-tools/plugin'\nimport inertia from '@interactjs/inertia/plugin'\nimport interact from '@interactjs/interact'\nimport modifiers from '@interactjs/modifiers/plugin'\nimport offset from '@interactjs/offset/plugin'\nimport pointerEvents from '@interactjs/pointer-events/plugin'\nimport reflow from '@interactjs/reflow/plugin'\n/* eslint-enable import/no-duplicates */\n\ninteract.use(interactablePreventDefault)\n\ninteract.use(offset)\n\n// pointerEvents\ninteract.use(pointerEvents)\n\n// inertia\ninteract.use(inertia)\n\n// snap, resize, etc.\ninteract.use(modifiers)\n\n// autoStart, hold\ninteract.use(autoStart)\n\n// drag and drop, resize, gesture\ninteract.use(actions)\n\n// autoScroll\ninteract.use(autoScroll)\n\n// reflow\ninteract.use(reflow)\n\n// eslint-disable-next-line no-undef\nif (process.env.NODE_ENV !== 'production') {\n  interact.use(devTools)\n}\n\nexport default interact\n;(interact as any).default = interact\n"
  },
  {
    "path": "packages/@interactjs/interactjs/index.ts",
    "content": "/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport '@interactjs/actions/plugin'\nimport '@interactjs/auto-scroll/plugin'\nimport '@interactjs/auto-start/plugin'\nimport '@interactjs/core/interactablePreventDefault'\nimport '@interactjs/dev-tools/plugin'\nimport '@interactjs/inertia/plugin'\nimport '@interactjs/interact'\nimport '@interactjs/modifiers/plugin'\nimport '@interactjs/offset/plugin'\nimport '@interactjs/pointer-events/plugin'\nimport '@interactjs/reflow/plugin'\n\nimport actions from '@interactjs/actions/plugin'\nimport autoScroll from '@interactjs/auto-scroll/plugin'\nimport autoStart from '@interactjs/auto-start/plugin'\nimport interactablePreventDefault from '@interactjs/core/interactablePreventDefault'\nimport devTools from '@interactjs/dev-tools/plugin'\nimport inertia from '@interactjs/inertia/plugin'\nimport interact from '@interactjs/interact'\nimport modifiers from '@interactjs/modifiers/plugin'\nimport offset from '@interactjs/offset/plugin'\nimport pointerEvents from '@interactjs/pointer-events/plugin'\nimport reflow from '@interactjs/reflow/plugin'\n/* eslint-enable import/no-duplicates */\n\ninteract.use(interactablePreventDefault)\n\ninteract.use(offset)\n\n// pointerEvents\ninteract.use(pointerEvents)\n\n// inertia\ninteract.use(inertia)\n\n// snap, resize, etc.\ninteract.use(modifiers)\n\n// autoStart, hold\ninteract.use(autoStart)\n\n// drag and drop, resize, gesture\ninteract.use(actions)\n\n// autoScroll\ninteract.use(autoScroll)\n\n// reflow\ninteract.use(reflow)\n\n// eslint-disable-next-line no-undef\nif (process.env.NODE_ENV !== 'production') {\n  interact.use(devTools)\n}\n\nexport default interact\n;(interact as any).default = interact\n"
  },
  {
    "path": "packages/@interactjs/interactjs/package.json",
    "content": "{\n  \"name\": \"@interactjs/interactjs\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\"\n  },\n  \"dependencies\": {\n    \"@interactjs/actions\": \"1.10.27\",\n    \"@interactjs/arrange\": \"1.10.27\",\n    \"@interactjs/auto-scroll\": \"1.10.27\",\n    \"@interactjs/auto-start\": \"1.10.27\",\n    \"@interactjs/clone\": \"1.10.27\",\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/dev-tools\": \"1.10.27\",\n    \"@interactjs/feedback\": \"1.10.27\",\n    \"@interactjs/inertia\": \"1.10.27\",\n    \"@interactjs/interact\": \"1.10.27\",\n    \"@interactjs/modifiers\": \"1.10.27\",\n    \"@interactjs/multi-target\": \"1.10.27\",\n    \"@interactjs/offset\": \"1.10.27\",\n    \"@interactjs/pointer-events\": \"1.10.27\",\n    \"@interactjs/react\": \"1.10.27\",\n    \"@interactjs/rebound\": \"1.10.27\",\n    \"@interactjs/symbol-tree\": \"1.10.27\",\n    \"@interactjs/reflow\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\",\n    \"@interactjs/vue\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/modifiers/Modification.ts",
    "content": "import type { EventPhase } from '@interactjs/core/InteractEvent'\nimport type { Interaction, DoAnyPhaseArg } from '@interactjs/core/Interaction'\nimport type { EdgeOptions, FullRect, Point, Rect } from '@interactjs/core/types'\nimport clone from '@interactjs/utils/clone'\nimport extend from '@interactjs/utils/extend'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport type { Modifier, ModifierArg, ModifierState } from './types'\n\nexport interface ModificationResult {\n  delta: Point\n  rectDelta: Rect\n  coords: Point\n  rect: FullRect\n  eventProps: any[]\n  changed: boolean\n}\n\ninterface MethodArg {\n  phase: EventPhase\n  pageCoords: Point\n  rect: FullRect\n  coords: Point\n  preEnd?: boolean\n  skipModifiers?: number\n}\n\nexport class Modification {\n  states: ModifierState[] = []\n  startOffset: Rect = { left: 0, right: 0, top: 0, bottom: 0 }\n  startDelta!: Point\n  result!: ModificationResult\n  endResult!: Point\n  startEdges!: EdgeOptions\n  edges: EdgeOptions\n  readonly interaction: Readonly<Interaction>\n\n  constructor(interaction: Interaction) {\n    this.interaction = interaction\n    this.result = createResult()\n    this.edges = {\n      left: false,\n      right: false,\n      top: false,\n      bottom: false,\n    }\n  }\n\n  start({ phase }: { phase: EventPhase }, pageCoords: Point) {\n    const { interaction } = this\n    const modifierList = getModifierList(interaction)\n    this.prepareStates(modifierList)\n\n    this.startEdges = extend({}, interaction.edges)\n    this.edges = extend({}, this.startEdges)\n    this.startOffset = getRectOffset(interaction.rect, pageCoords)\n    this.startDelta = { x: 0, y: 0 }\n\n    const arg = this.fillArg({\n      phase,\n      pageCoords,\n      preEnd: false,\n    })\n\n    this.result = createResult()\n    this.startAll(arg)\n\n    const result = (this.result = this.setAll(arg))\n\n    return result\n  }\n\n  fillArg(arg: Partial<ModifierArg>) {\n    const { interaction } = this\n\n    arg.interaction = interaction\n    arg.interactable = interaction.interactable\n    arg.element = interaction.element\n    arg.rect ||= interaction.rect\n    arg.edges ||= this.startEdges\n    arg.startOffset = this.startOffset\n\n    return arg as ModifierArg\n  }\n\n  startAll(arg: MethodArg & Partial<ModifierArg>) {\n    for (const state of this.states) {\n      if (state.methods.start) {\n        arg.state = state\n        state.methods.start(arg as ModifierArg)\n      }\n    }\n  }\n\n  setAll(arg: MethodArg & Partial<ModifierArg>): ModificationResult {\n    const { phase, preEnd, skipModifiers, rect: unmodifiedRect, edges: unmodifiedEdges } = arg\n\n    arg.coords = extend({}, arg.pageCoords)\n    arg.rect = extend({}, unmodifiedRect)\n    arg.edges = extend({}, unmodifiedEdges)\n\n    const states = skipModifiers ? this.states.slice(skipModifiers) : this.states\n\n    const newResult = createResult(arg.coords, arg.rect)\n\n    for (const state of states) {\n      const { options } = state\n      const lastModifierCoords = extend({}, arg.coords)\n      let returnValue = null\n\n      if (state.methods?.set && this.shouldDo(options, preEnd, phase)) {\n        arg.state = state\n        returnValue = state.methods.set(arg as ModifierArg<never>)\n\n        rectUtils.addEdges(arg.edges, arg.rect, {\n          x: arg.coords.x - lastModifierCoords.x,\n          y: arg.coords.y - lastModifierCoords.y,\n        })\n      }\n\n      newResult.eventProps.push(returnValue)\n    }\n\n    extend(this.edges, arg.edges)\n\n    newResult.delta.x = arg.coords.x - arg.pageCoords.x\n    newResult.delta.y = arg.coords.y - arg.pageCoords.y\n\n    newResult.rectDelta.left = arg.rect.left - unmodifiedRect.left\n    newResult.rectDelta.right = arg.rect.right - unmodifiedRect.right\n    newResult.rectDelta.top = arg.rect.top - unmodifiedRect.top\n    newResult.rectDelta.bottom = arg.rect.bottom - unmodifiedRect.bottom\n\n    const prevCoords = this.result.coords\n    const prevRect = this.result.rect\n\n    if (prevCoords && prevRect) {\n      const rectChanged =\n        newResult.rect.left !== prevRect.left ||\n        newResult.rect.right !== prevRect.right ||\n        newResult.rect.top !== prevRect.top ||\n        newResult.rect.bottom !== prevRect.bottom\n\n      newResult.changed =\n        rectChanged || prevCoords.x !== newResult.coords.x || prevCoords.y !== newResult.coords.y\n    }\n\n    return newResult\n  }\n\n  applyToInteraction(arg: { phase: EventPhase; rect?: Rect }) {\n    const { interaction } = this\n    const { phase } = arg\n    const curCoords = interaction.coords.cur\n    const startCoords = interaction.coords.start\n    const { result, startDelta } = this\n    const curDelta = result.delta\n\n    if (phase === 'start') {\n      extend(this.startDelta, result.delta)\n    }\n\n    for (const [coordsSet, delta] of [\n      [startCoords, startDelta],\n      [curCoords, curDelta],\n    ] as const) {\n      coordsSet.page.x += delta.x\n      coordsSet.page.y += delta.y\n      coordsSet.client.x += delta.x\n      coordsSet.client.y += delta.y\n    }\n\n    const { rectDelta } = this.result\n    const rect = arg.rect || interaction.rect\n\n    rect.left += rectDelta.left\n    rect.right += rectDelta.right\n    rect.top += rectDelta.top\n    rect.bottom += rectDelta.bottom\n\n    rect.width = rect.right - rect.left\n    rect.height = rect.bottom - rect.top\n  }\n\n  setAndApply(\n    arg: Partial<DoAnyPhaseArg> & {\n      phase: EventPhase\n      preEnd?: boolean\n      skipModifiers?: number\n      modifiedCoords?: Point\n    },\n  ): void | false {\n    const { interaction } = this\n    const { phase, preEnd, skipModifiers } = arg\n\n    const result = this.setAll(\n      this.fillArg({\n        preEnd,\n        phase,\n        pageCoords: arg.modifiedCoords || interaction.coords.cur.page,\n      }),\n    )\n\n    this.result = result\n\n    // don't fire an action move if a modifier would keep the event in the same\n    // cordinates as before\n    if (\n      !result.changed &&\n      (!skipModifiers || skipModifiers < this.states.length) &&\n      interaction.interacting()\n    ) {\n      return false\n    }\n\n    if (arg.modifiedCoords) {\n      const { page } = interaction.coords.cur\n      const adjustment = {\n        x: arg.modifiedCoords.x - page.x,\n        y: arg.modifiedCoords.y - page.y,\n      }\n\n      result.coords.x += adjustment.x\n      result.coords.y += adjustment.y\n      result.delta.x += adjustment.x\n      result.delta.y += adjustment.y\n    }\n\n    this.applyToInteraction(arg)\n  }\n\n  beforeEnd(arg: Omit<DoAnyPhaseArg, 'iEvent'> & { state?: ModifierState }): void | false {\n    const { interaction, event } = arg\n    const states = this.states\n\n    if (!states || !states.length) {\n      return\n    }\n\n    let doPreend = false\n\n    for (const state of states) {\n      arg.state = state\n      const { options, methods } = state\n\n      const endPosition = methods.beforeEnd && methods.beforeEnd(arg as unknown as ModifierArg)\n\n      if (endPosition) {\n        this.endResult = endPosition\n        return false\n      }\n\n      doPreend = doPreend || (!doPreend && this.shouldDo(options, true, arg.phase, true))\n    }\n\n    if (doPreend) {\n      // trigger a final modified move before ending\n      interaction.move({ event, preEnd: true })\n    }\n  }\n\n  stop(arg: { interaction: Interaction }) {\n    const { interaction } = arg\n\n    if (!this.states || !this.states.length) {\n      return\n    }\n\n    const modifierArg: Partial<ModifierArg> = extend(\n      {\n        states: this.states,\n        interactable: interaction.interactable,\n        element: interaction.element,\n        rect: null,\n      },\n      arg,\n    )\n\n    this.fillArg(modifierArg)\n\n    for (const state of this.states) {\n      modifierArg.state = state\n\n      if (state.methods.stop) {\n        state.methods.stop(modifierArg as ModifierArg)\n      }\n    }\n\n    this.states = null\n    this.endResult = null\n  }\n\n  prepareStates(modifierList: Modifier[]) {\n    this.states = []\n\n    for (let index = 0; index < modifierList.length; index++) {\n      const { options, methods, name } = modifierList[index]\n\n      this.states.push({\n        options,\n        methods,\n        index,\n        name,\n      })\n    }\n\n    return this.states\n  }\n\n  restoreInteractionCoords({ interaction: { coords, rect, modification } }: { interaction: Interaction }) {\n    if (!modification.result) return\n\n    const { startDelta } = modification\n    const { delta: curDelta, rectDelta } = modification.result\n\n    const coordsAndDeltas = [\n      [coords.start, startDelta],\n      [coords.cur, curDelta],\n    ]\n\n    for (const [coordsSet, delta] of coordsAndDeltas as any) {\n      coordsSet.page.x -= delta.x\n      coordsSet.page.y -= delta.y\n      coordsSet.client.x -= delta.x\n      coordsSet.client.y -= delta.y\n    }\n\n    rect.left -= rectDelta.left\n    rect.right -= rectDelta.right\n    rect.top -= rectDelta.top\n    rect.bottom -= rectDelta.bottom\n  }\n\n  shouldDo(options, preEnd?: boolean, phase?: string, requireEndOnly?: boolean) {\n    if (\n      // ignore disabled modifiers\n      !options ||\n      options.enabled === false ||\n      // check if we require endOnly option to fire move before end\n      (requireEndOnly && !options.endOnly) ||\n      // don't apply endOnly modifiers when not ending\n      (options.endOnly && !preEnd) ||\n      // check if modifier should run be applied on start\n      (phase === 'start' && !options.setStart)\n    ) {\n      return false\n    }\n\n    return true\n  }\n\n  copyFrom(other: Modification) {\n    this.startOffset = other.startOffset\n    this.startDelta = other.startDelta\n    this.startEdges = other.startEdges\n    this.edges = other.edges\n    this.states = other.states.map((s) => clone(s) as ModifierState)\n    this.result = createResult(extend({}, other.result.coords), extend({}, other.result.rect))\n  }\n\n  destroy() {\n    for (const prop in this) {\n      this[prop] = null\n    }\n  }\n}\n\nfunction createResult(coords?: Point, rect?: FullRect): ModificationResult {\n  return {\n    rect,\n    coords,\n    delta: { x: 0, y: 0 },\n    rectDelta: {\n      left: 0,\n      right: 0,\n      top: 0,\n      bottom: 0,\n    },\n    eventProps: [],\n    changed: true,\n  }\n}\n\nfunction getModifierList(interaction) {\n  const actionOptions = interaction.interactable.options[interaction.prepared.name]\n  const actionModifiers = actionOptions.modifiers\n\n  if (actionModifiers && actionModifiers.length) {\n    return actionModifiers\n  }\n\n  return ['snap', 'snapSize', 'snapEdges', 'restrict', 'restrictEdges', 'restrictSize']\n    .map((type) => {\n      const options = actionOptions[type]\n\n      return (\n        options &&\n        options.enabled && {\n          options,\n          methods: options._methods,\n        }\n      )\n    })\n    .filter((m) => !!m)\n}\n\nexport function getRectOffset(rect, coords) {\n  return rect\n    ? {\n        left: coords.x - rect.left,\n        top: coords.y - rect.top,\n        right: rect.right - coords.x,\n        bottom: rect.bottom - coords.y,\n      }\n    : {\n        left: 0,\n        top: 0,\n        right: 0,\n        bottom: 0,\n      }\n}\n"
  },
  {
    "path": "packages/@interactjs/modifiers/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/modifiers/all.ts",
    "content": "/* eslint-disable n/no-extraneous-import, import/no-unresolved */\nimport aspectRatio from './aspectRatio'\nimport avoid from './avoid/avoid'\nimport restrictEdges from './restrict/edges'\nimport restrict from './restrict/pointer'\nimport restrictRect from './restrict/rect'\nimport restrictSize from './restrict/size'\nimport rubberband from './rubberband/rubberband'\nimport snapEdges from './snap/edges'\nimport snap from './snap/pointer'\nimport snapSize from './snap/size'\nimport spring from './spring/spring'\nimport transform from './transform/transform'\n\nexport default {\n  aspectRatio,\n  restrictEdges,\n  restrict,\n  restrictRect,\n  restrictSize,\n  snapEdges,\n  snap,\n  snapSize,\n\n  spring,\n  avoid,\n  transform,\n  rubberband,\n}\n"
  },
  {
    "path": "packages/@interactjs/modifiers/aspectRatio.spec.ts",
    "content": "import resize from '@interactjs/actions/resize/plugin'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport type { FullRect, EdgeOptions } from '@interactjs/core/types'\n\nimport type { AspectRatioOptions } from './aspectRatio'\nimport aspectRatio from './aspectRatio'\nimport modifiersBase from './base'\nimport restrictSize from './restrict/size'\n\nconst { ltrbwh } = helpers\n\ntest('modifiers/aspectRatio', () => {\n  const rect = Object.freeze({ left: 0, top: 0, right: 10, bottom: 20, width: 10, height: 20 })\n  const { interactable, interaction, event, coords, target } = helpers.testEnv({\n    plugins: [modifiersBase, resize],\n    rect,\n  })\n\n  coords.client = coords.page\n\n  const options: AspectRatioOptions = {}\n  let lastRect: FullRect = null\n\n  interactable.resizable({\n    edges: { left: true, top: true, right: true, bottom: true },\n    modifiers: [aspectRatio(options)],\n    listeners: {\n      move(e) {\n        lastRect = e.rect\n      },\n    },\n  })\n\n  options.equalDelta = true\n  downStartMoveUp({ x: 2, y: 4.33, edges: { left: true, top: true } })\n  // `equalDelta: true, 1 { left: true, top: true }\n  expect(lastRect).toEqual(ltrbwh(2, 2, 10, 20, 8, 18))\n\n  downStartMoveUp({ x: 30, y: 2, edges: { bottom: true } })\n  // equalDelta: true, 2, edges: { bottom: true }\n  expect(lastRect).toEqual(ltrbwh(0, 0, 12, 22, 12, 22))\n\n  options.equalDelta = false\n  options.ratio = 2\n  downStartMoveUp({ x: -5, y: 2, edges: { left: true } })\n  // equalDelta: false, ratio: 2, edges: left\n  expect(lastRect).toEqual(ltrbwh(-5, 12.5, 10, 20, 15, 7.5))\n\n  // combine with restrictSize\n  options.modifiers = [\n    restrictSize({\n      max: { width: 20, height: 20 },\n    }),\n  ]\n  options.equalDelta = false\n  options.ratio = 2\n\n  downStartMoveUp({ x: 20, y: 0, edges: { right: true } })\n  // restrictSize with critical primary edge\n  expect(lastRect).toEqual(ltrbwh(0, 0, 20, 10, 20, 10))\n\n  downStartMoveUp({ x: 20, y: 20, edges: { bottom: true } })\n  // restrictSize with critical secondary edge\n  expect(lastRect).toEqual(ltrbwh(0, 0, 20, 10, 20, 10))\n\n  options.ratio = 0.5\n  downStartMoveUp({ x: 5, y: -5, edges: { left: true, bottom: true } })\n  // equalDelta: false, ratio: 2, edges: left & bottom\n  expect(lastRect).toEqual(ltrbwh(5, 0, 10, 10, 5, 10))\n\n  downStartMoveUp({ x: -5, y: -5, edges: { right: true, top: true } })\n  // equalDelta: false, ratio: 2, edges: right & top\n  expect(lastRect).toEqual(ltrbwh(0, 10, 5, 20, 5, 10))\n\n  function downStartMoveUp({ x, y, edges }: { x: number; y: number; edges: EdgeOptions }) {\n    coords.timeStamp = 0\n    interaction.stop()\n    lastRect = null\n\n    Object.assign(coords.page, { x: 0, y: 0 })\n    interaction.pointerDown(event, event, target)\n\n    interaction.start({ name: 'resize', edges }, interactable, target)\n\n    Object.assign(coords.page, { x, y })\n    interaction.pointerMove(event, event, target)\n    interaction.pointerMove(event, event, target)\n    interaction.pointerUp(event, event, target, target)\n  }\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/aspectRatio.ts",
    "content": "/**\n * @module modifiers/aspectRatio\n *\n * @description\n * This modifier forces elements to be resized with a specified dx/dy ratio.\n *\n * ```js\n * interact(target).resizable({\n *   modifiers: [\n *     interact.modifiers.snapSize({\n *       targets: [ interact.snappers.grid({ x: 20, y: 20 }) ],\n *     }),\n *     interact.aspectRatio({ ratio: 'preserve' }),\n *   ],\n * });\n * ```\n */\n\nimport type { Point, Rect, EdgeOptions } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\nimport { addEdges } from '@interactjs/utils/rect'\n\nimport { makeModifier } from './base'\nimport { Modification } from './Modification'\nimport type { Modifier, ModifierModule, ModifierState } from './types'\n\nexport interface AspectRatioOptions {\n  ratio?: number | 'preserve'\n  equalDelta?: boolean\n  modifiers?: Modifier[]\n  enabled?: boolean\n}\n\nexport type AspectRatioState = ModifierState<\n  AspectRatioOptions,\n  {\n    startCoords: Point\n    startRect: Rect\n    linkedEdges: EdgeOptions\n    ratio: number\n    equalDelta: boolean\n    xIsPrimaryAxis: boolean\n    edgeSign: {\n      x: number\n      y: number\n    }\n    subModification: Modification\n  }\n>\n\nconst aspectRatio: ModifierModule<AspectRatioOptions, AspectRatioState> = {\n  start(arg) {\n    const { state, rect, edges, pageCoords: coords } = arg\n    let { ratio, enabled } = state.options\n    const { equalDelta, modifiers } = state.options\n\n    if (ratio === 'preserve') {\n      ratio = rect.width / rect.height\n    }\n\n    state.startCoords = extend({}, coords)\n    state.startRect = extend({}, rect)\n    state.ratio = ratio\n    state.equalDelta = equalDelta\n\n    const linkedEdges = (state.linkedEdges = {\n      top: edges.top || (edges.left && !edges.bottom),\n      left: edges.left || (edges.top && !edges.right),\n      bottom: edges.bottom || (edges.right && !edges.top),\n      right: edges.right || (edges.bottom && !edges.left),\n    })\n\n    state.xIsPrimaryAxis = !!(edges.left || edges.right)\n\n    if (state.equalDelta) {\n      const sign = (linkedEdges.left ? 1 : -1) * (linkedEdges.top ? 1 : -1)\n      state.edgeSign = {\n        x: sign,\n        y: sign,\n      }\n    } else {\n      state.edgeSign = {\n        x: linkedEdges.left ? -1 : 1,\n        y: linkedEdges.top ? -1 : 1,\n      }\n    }\n\n    if (enabled !== false) {\n      extend(edges, linkedEdges)\n    }\n\n    if (!modifiers?.length) return\n\n    const subModification = new Modification(arg.interaction)\n\n    subModification.copyFrom(arg.interaction.modification)\n    subModification.prepareStates(modifiers)\n\n    state.subModification = subModification\n    subModification.startAll({ ...arg })\n  },\n\n  set(arg) {\n    const { state, rect, coords } = arg\n    const { linkedEdges } = state\n    const initialCoords = extend({}, coords)\n    const aspectMethod = state.equalDelta ? setEqualDelta : setRatio\n\n    extend(arg.edges, linkedEdges)\n    aspectMethod(state, state.xIsPrimaryAxis, coords, rect)\n\n    if (!state.subModification) {\n      return null\n    }\n\n    const correctedRect = extend({}, rect)\n\n    addEdges(linkedEdges, correctedRect, {\n      x: coords.x - initialCoords.x,\n      y: coords.y - initialCoords.y,\n    })\n\n    const result = state.subModification.setAll({\n      ...arg,\n      rect: correctedRect,\n      edges: linkedEdges,\n      pageCoords: coords,\n      prevCoords: coords,\n      prevRect: correctedRect,\n    })\n\n    const { delta } = result\n\n    if (result.changed) {\n      const xIsCriticalAxis = Math.abs(delta.x) > Math.abs(delta.y)\n\n      // do aspect modification again with critical edge axis as primary\n      aspectMethod(state, xIsCriticalAxis, result.coords, result.rect)\n      extend(coords, result.coords)\n    }\n\n    return result.eventProps\n  },\n\n  defaults: {\n    ratio: 'preserve',\n    equalDelta: false,\n    modifiers: [],\n    enabled: false,\n  },\n}\n\nfunction setEqualDelta({ startCoords, edgeSign }: AspectRatioState, xIsPrimaryAxis: boolean, coords: Point) {\n  if (xIsPrimaryAxis) {\n    coords.y = startCoords.y + (coords.x - startCoords.x) * edgeSign.y\n  } else {\n    coords.x = startCoords.x + (coords.y - startCoords.y) * edgeSign.x\n  }\n}\n\nfunction setRatio(\n  { startRect, startCoords, ratio, edgeSign }: AspectRatioState,\n  xIsPrimaryAxis: boolean,\n  coords: Point,\n  rect: Rect,\n) {\n  if (xIsPrimaryAxis) {\n    const newHeight = rect.width / ratio\n\n    coords.y = startCoords.y + (newHeight - startRect.height) * edgeSign.y\n  } else {\n    const newWidth = rect.height * ratio\n\n    coords.x = startCoords.x + (newWidth - startRect.width) * edgeSign.x\n  }\n}\n\nexport default makeModifier(aspectRatio, 'aspectRatio')\nexport { aspectRatio }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/avoid/avoid.stub.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/avoid/avoid.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/base.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\nimport type { ActionName, Element } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\n\nimport modifiersBase from './base'\n\ntest('modifiers/base', () => {\n  const { scope, target, interaction, interactable, coords, event } = helpers.testEnv({\n    plugins: [modifiersBase],\n  })\n\n  // modifiers prop is added new Interaction\n  expect(is.object(interaction.modification)).toBe(true)\n\n  coords.client = coords.page\n\n  const testAction = { name: 'test' as ActionName }\n  const element = target as Element\n  const startCoords = { x: 100, y: 200 }\n  const moveCoords = { x: 400, y: 500 }\n  const options: any = { target: { x: 100, y: 100 }, setStart: true }\n  let firedEvents: any[] = []\n\n  interactable.rectChecker(() => ({ top: 0, left: 0, bottom: 50, right: 50 }))\n  interactable.on('teststart testmove testend', (e) => firedEvents.push(e))\n\n  extend(coords.page, startCoords)\n  interaction.pointerDown(event, event, element)\n  ;(interactable.options as any).test = {\n    enabled: true,\n    modifiers: [\n      {\n        options,\n        methods: targetModifier,\n      },\n    ],\n  }\n\n  interaction.start(testAction, interactable, element)\n\n  // modifier methods.start() was called\n  expect(options.started).toBe(true)\n\n  // modifier methods.set() was called\n  expect(options.setted).toBe(true)\n\n  // start event coords are modified\n  expect(interaction.prevEvent.page).toEqual(options.target)\n\n  // interaction.coords.start are restored after action start phase\n  expect(interaction.coords.start.page).toEqual(startCoords)\n\n  // interaction.coords.cur are restored after action start phase\n  expect(interaction.coords.cur.page).toEqual(startCoords)\n\n  extend(coords.page, moveCoords)\n  interaction.pointerMove(event, event, element)\n\n  // interaction.coords.cur are restored after action move phase\n  expect(interaction.coords.cur.page).toEqual(moveCoords)\n\n  // interaction.coords.start are restored after action move phase\n  expect(interaction.coords.start.page).toEqual(startCoords)\n\n  // move event start coords are modified\n  expect({ x: interaction.prevEvent.x0, y: interaction.prevEvent.y0 }).toEqual({ x: 100, y: 100 })\n\n  firedEvents = []\n  scope.interactions.pointerMoveTolerance = 0\n  interaction.pointerMove(event, event, element)\n  // duplicate result coords are ignored\n  expect(firedEvents).toHaveLength(0)\n\n  interaction.stop()\n\n  // modifier methods.stop() was called\n  expect(options.stopped).toBe(true)\n\n  // don't set start\n  options.setStart = null\n  // add second modifier\n  ;(interactable.options as any).test.modifiers.push({\n    options,\n    methods: doubleModifier,\n  })\n\n  extend(coords.page, startCoords)\n  interaction.pointerDown(event, event, element)\n  interaction.start(testAction, interactable, element)\n\n  // modifier methods.set() was not called on start phase without options.setStart\n  expect(options.setted).toBeUndefined()\n\n  // start event coords are not modified without options.setStart\n  expect(interaction.prevEvent.page).toEqual({ x: 100, y: 200 })\n\n  // interaction.coords.start are not modified without options.setStart\n  expect(interaction.coords.start.page).toEqual({ x: 100, y: 200 })\n\n  extend(coords.page, moveCoords)\n  interaction.pointerMove(event, event, element)\n\n  // move event coords are modified by all modifiers\n  expect(interaction.prevEvent.page).toEqual({ x: 200, y: 200 })\n\n  interaction.pointerMove(event, event, element)\n\n  expect(() => {\n    interaction._scopeFire('interactions:action-resume', {\n      interaction,\n      phase: 'resume',\n      iEvent: {} as any,\n      event,\n    })\n  }).not.toThrow()\n\n  interaction.stop()\n\n  interaction.pointerUp(event, event, element, element)\n  // interaction coords after stopping are as expected\n  expect(interaction.coords.cur.page).toEqual(moveCoords)\n})\n\nconst targetModifier = {\n  start({ state }: any) {\n    state.options.started = true\n  },\n  set({ state, coords }: any) {\n    const { target } = state.options\n\n    coords.x = target.x\n    coords.y = target.y\n\n    state.options.setted = true\n  },\n  stop({ state }: any) {\n    state.options.stopped = true\n    delete state.options.started\n    delete state.options.setted\n  },\n}\n\nconst doubleModifier = {\n  start() {},\n  set({ coords }: any) {\n    coords.x *= 2\n    coords.y *= 2\n  },\n}\n"
  },
  {
    "path": "packages/@interactjs/modifiers/base.ts",
    "content": "import type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { Plugin } from '@interactjs/core/scope'\n\nimport { Modification } from './Modification'\nimport type { Modifier, ModifierModule, ModifierState } from './types'\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    modification?: Modification\n  }\n}\n\ndeclare module '@interactjs/core/InteractEvent' {\n  interface InteractEvent {\n    modifiers?: Array<{\n      name: string\n      [key: string]: any\n    }>\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface PerActionDefaults {\n    modifiers?: Modifier[]\n  }\n}\n\nexport function makeModifier<\n  Defaults extends { enabled?: boolean },\n  State extends ModifierState,\n  Name extends string,\n  Result,\n>(module: ModifierModule<Defaults, State, Result>, name?: Name) {\n  const { defaults } = module\n  const methods = {\n    start: module.start,\n    set: module.set,\n    beforeEnd: module.beforeEnd,\n    stop: module.stop,\n  }\n\n  const modifier = (_options?: Partial<Defaults>) => {\n    const options = (_options || {}) as Defaults\n\n    options.enabled = options.enabled !== false\n\n    // add missing defaults to options\n    for (const prop in defaults) {\n      if (!(prop in options)) {\n        ;(options as any)[prop] = defaults[prop]\n      }\n    }\n\n    const m: Modifier<Defaults, State, Name, Result> = {\n      options,\n      methods,\n      name,\n      enable: () => {\n        options.enabled = true\n        return m\n      },\n      disable: () => {\n        options.enabled = false\n        return m\n      },\n    }\n\n    return m\n  }\n\n  if (name && typeof name === 'string') {\n    // for backwrads compatibility\n    modifier._defaults = defaults\n    modifier._methods = methods\n  }\n\n  return modifier\n}\n\nexport function addEventModifiers({\n  iEvent,\n  interaction,\n}: {\n  iEvent: InteractEvent<any>\n  interaction: Interaction<any>\n}) {\n  const result = interaction.modification!.result\n\n  if (result) {\n    iEvent.modifiers = result.eventProps\n  }\n}\n\nconst modifiersBase: Plugin = {\n  id: 'modifiers/base',\n  before: ['actions'],\n  install: (scope) => {\n    scope.defaults.perAction.modifiers = []\n  },\n  listeners: {\n    'interactions:new': ({ interaction }) => {\n      interaction.modification = new Modification(interaction)\n    },\n\n    'interactions:before-action-start': (arg) => {\n      const { interaction } = arg\n      const modification = arg.interaction.modification!\n\n      modification.start(arg, interaction.coords.start.page)\n      interaction.edges = modification.edges\n      modification.applyToInteraction(arg)\n    },\n\n    'interactions:before-action-move': (arg) => {\n      const { interaction } = arg\n      const { modification } = interaction\n      const ret = modification.setAndApply(arg)\n      interaction.edges = modification.edges\n\n      return ret\n    },\n\n    'interactions:before-action-end': (arg) => {\n      const { interaction } = arg\n      const { modification } = interaction\n      const ret = modification.beforeEnd(arg)\n      interaction.edges = modification.startEdges\n\n      return ret\n    },\n\n    'interactions:action-start': addEventModifiers,\n    'interactions:action-move': addEventModifiers,\n    'interactions:action-end': addEventModifiers,\n\n    'interactions:after-action-start': (arg) => arg.interaction.modification.restoreInteractionCoords(arg),\n    'interactions:after-action-move': (arg) => arg.interaction.modification.restoreInteractionCoords(arg),\n\n    'interactions:stop': (arg) => arg.interaction.modification.stop(arg),\n  },\n}\n\nexport default modifiersBase\n"
  },
  {
    "path": "packages/@interactjs/modifiers/noop.ts",
    "content": "import type { ModifierFunction } from './types'\n\nconst noop = (() => {}) as unknown as ModifierFunction<any, any, 'noop'>\n\nnoop._defaults = {}\n\nexport default noop\n"
  },
  {
    "path": "packages/@interactjs/modifiers/package.json",
    "content": "{\n  \"name\": \"@interactjs/modifiers\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/modifiers\"\n  },\n  \"dependencies\": {\n    \"@interactjs/snappers\": \"1.10.27\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/rebound\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/modifiers/plugin.ts",
    "content": "import type { Plugin } from '@interactjs/core/scope'\nimport snappers from '@interactjs/snappers/plugin'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './all'\nimport './base'\n\nimport all from './all'\nimport base from './base'\n/* eslint-enable import/no-duplicates */\n\ndeclare module '@interactjs/core/InteractStatic' {\n  export interface InteractStatic {\n    modifiers: typeof all\n  }\n}\n\nconst modifiers: Plugin = {\n  id: 'modifiers',\n  install(scope) {\n    const { interactStatic: interact } = scope\n\n    scope.usePlugin(base)\n    scope.usePlugin(snappers)\n\n    interact.modifiers = all\n\n    // for backwrads compatibility\n    for (const type in all) {\n      const { _defaults, _methods } = all[type as keyof typeof all]\n\n      ;(_defaults as any)._methods = _methods\n      ;(scope.defaults.perAction as any)[type] = _defaults\n    }\n  },\n}\n\nexport default modifiers\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/edges.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\n\nimport { restrictEdges } from '../restrict/edges'\n\ntest('restrictEdges', () => {\n  const { interaction } = helpers.testEnv()\n  const edges = { top: true, bottom: true, left: true, right: true }\n  interaction.prepared = {} as any\n  interaction.prepared.edges = edges\n  interaction._rects = {} as any\n  interaction._rects.corrected = { x: 10, y: 20, width: 300, height: 200 } as any\n  interaction._interacting = true\n\n  const options: any = { enabled: true }\n  const coords = { x: 40, y: 40 }\n  const offset = { top: 0, left: 0, bottom: 0, right: 0 }\n  const state = { options, offset }\n  const arg = { interaction, edges, state } as any\n\n  arg.coords = { ...coords }\n\n  // outer restriction\n  options.outer = { top: 100, left: 100, bottom: 200, right: 200 }\n  restrictEdges.set(arg)\n\n  // outer restriction is applied correctly\n  expect(arg.coords).toEqual({ x: coords.y + 60, y: coords.y + 60 })\n\n  arg.coords = { ...coords }\n\n  // inner restriction\n  options.outer = null\n  options.inner = { top: 0, left: 0, bottom: 10, right: 10 }\n  restrictEdges.set(arg)\n\n  // inner restriction is applied correctly\n  expect(arg.coords).toEqual({ x: coords.x - 40, y: coords.y - 40 })\n\n  // offset\n  Object.assign(offset, {\n    top: 100,\n    left: 100,\n    bottom: 200,\n    right: 200,\n  })\n  arg.coords = { ...coords }\n\n  options.outer = { top: 100, left: 100, bottom: 200, right: 200 }\n  options.inner = null\n  restrictEdges.set(arg)\n\n  // outer restriction is applied correctly with offset\n  expect(arg.coords).toEqual({ x: coords.x + 160, y: coords.x + 160 })\n\n  // start\n  interaction.modification = {} as any\n  arg.startOffset = { top: 5, left: 10, bottom: -8, right: -16 }\n  interaction.interactable = {\n    getRect() {\n      return { top: 500, left: 900 }\n    },\n  } as any\n\n  options.offset = 'self'\n  restrictEdges.start(arg)\n\n  // start gets x/y from selector string\n  expect(arg.state.offset).toEqual({ top: 505, left: 910, bottom: 508, right: 916 })\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/edges.ts",
    "content": "// This modifier adds the options.resize.restrictEdges setting which sets min and\n// max for the top, left, bottom and right edges of the target being resized.\n//\n// interact(target).resize({\n//   edges: { top: true, left: true },\n//   restrictEdges: {\n//     inner: { top: 200, left: 200, right: 400, bottom: 400 },\n//     outer: { top:   0, left:   0, right: 600, bottom: 600 },\n//   },\n// })\n\nimport type { Point, Rect } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport { makeModifier } from '../base'\nimport type { ModifierArg, ModifierState } from '../types'\n\nimport type { RestrictOptions } from './pointer'\nimport { getRestrictionRect } from './pointer'\n\nexport interface RestrictEdgesOptions {\n  inner: RestrictOptions['restriction']\n  outer: RestrictOptions['restriction']\n  offset?: RestrictOptions['offset']\n  endOnly: boolean\n  enabled?: boolean\n}\n\nexport type RestrictEdgesState = ModifierState<\n  RestrictEdgesOptions,\n  {\n    inner: Rect\n    outer: Rect\n    offset: RestrictEdgesOptions['offset']\n  }\n>\n\nconst noInner = { top: +Infinity, left: +Infinity, bottom: -Infinity, right: -Infinity }\nconst noOuter = { top: -Infinity, left: -Infinity, bottom: +Infinity, right: +Infinity }\n\nfunction start({ interaction, startOffset, state }: ModifierArg<RestrictEdgesState>) {\n  const { options } = state\n  let offset: Point\n\n  if (options) {\n    const offsetRect = getRestrictionRect(options.offset, interaction, interaction.coords.start.page)\n\n    offset = rectUtils.rectToXY(offsetRect)\n  }\n\n  offset = offset || { x: 0, y: 0 }\n\n  state.offset = {\n    top: offset.y + startOffset.top,\n    left: offset.x + startOffset.left,\n    bottom: offset.y - startOffset.bottom,\n    right: offset.x - startOffset.right,\n  }\n}\n\nfunction set({ coords, edges, interaction, state }: ModifierArg<RestrictEdgesState>) {\n  const { offset, options } = state\n\n  if (!edges) {\n    return\n  }\n\n  const page = extend({}, coords)\n  const inner = getRestrictionRect(options.inner, interaction, page) || ({} as Rect)\n  const outer = getRestrictionRect(options.outer, interaction, page) || ({} as Rect)\n\n  fixRect(inner, noInner)\n  fixRect(outer, noOuter)\n\n  if (edges.top) {\n    coords.y = Math.min(Math.max(outer.top + offset.top, page.y), inner.top + offset.top)\n  } else if (edges.bottom) {\n    coords.y = Math.max(Math.min(outer.bottom + offset.bottom, page.y), inner.bottom + offset.bottom)\n  }\n  if (edges.left) {\n    coords.x = Math.min(Math.max(outer.left + offset.left, page.x), inner.left + offset.left)\n  } else if (edges.right) {\n    coords.x = Math.max(Math.min(outer.right + offset.right, page.x), inner.right + offset.right)\n  }\n}\n\nfunction fixRect(rect: Rect, defaults: Rect) {\n  for (const edge of ['top', 'left', 'bottom', 'right']) {\n    if (!(edge in rect)) {\n      rect[edge] = defaults[edge]\n    }\n  }\n\n  return rect\n}\n\nconst defaults: RestrictEdgesOptions = {\n  inner: null,\n  outer: null,\n  offset: null,\n  endOnly: false,\n  enabled: false,\n}\n\nconst restrictEdges = {\n  noInner,\n  noOuter,\n  start,\n  set,\n  defaults,\n}\n\nexport default makeModifier(restrictEdges, 'restrictEdges')\nexport { restrictEdges }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/pointer.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\n\nimport { restrict } from '../restrict/pointer'\n\ntest('restrict larger than restriction', () => {\n  const edges = { left: 0, top: 0, right: 200, bottom: 200 }\n  const rect = { ...edges, width: 200, height: 200 }\n  const { interaction } = helpers.testEnv({ rect })\n\n  const restriction = { left: 100, top: 50, right: 150, bottom: 150 }\n  const options = {\n    ...restrict.defaults,\n    restriction: null as any,\n    elementRect: { left: 0, top: 0, right: 1, bottom: 1 },\n  }\n  const state = { options, offset: null as any }\n  const arg: any = {\n    interaction,\n    state,\n    rect,\n    startOffset: rect,\n    coords: { x: 0, y: 0 },\n    pageCoords: { x: 0, y: 0 },\n  }\n\n  options.restriction = () => null as any\n  expect(() => {\n    restrict.start(arg as any)\n    restrict.set(arg as any)\n  }).not.toThrow()\n\n  options.restriction = restriction\n  restrict.start(arg as any)\n\n  arg.coords = { x: 0, y: 0 }\n  restrict.set(arg)\n  // allows top and left edge values to be lower than the restriction\n  expect(arg.coords).toEqual({ x: 0, y: 0 })\n\n  arg.coords = { x: restriction.left + 10, y: restriction.top + 10 }\n  restrict.set(arg)\n  // keeps the top left edge values lower than the restriction\n  expect(arg.coords).toEqual({ x: restriction.left - rect.left, y: restriction.top - rect.top })\n\n  arg.coords = { x: restriction.right - rect.right - 10, y: restriction.bottom - rect.right - 10 }\n  restrict.set(arg)\n  // keeps the bottom right edge values higher than the restriction\n  expect(arg.coords).toEqual({ x: restriction.right - rect.right, y: restriction.bottom - rect.right })\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/pointer.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\nimport type { RectResolvable, Rect, Point } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport { makeModifier } from '../base'\nimport type { ModifierArg, ModifierModule, ModifierState } from '../types'\n\nexport interface RestrictOptions {\n  // where to drag over\n  restriction: RectResolvable<[number, number, Interaction]>\n  // what part of self is allowed to drag over\n  elementRect: Rect\n  offset: Rect\n  // restrict just before the end drag\n  endOnly: boolean\n  enabled?: boolean\n}\n\nexport type RestrictState = ModifierState<\n  RestrictOptions,\n  {\n    offset: Rect\n  }\n>\n\nfunction start({ rect, startOffset, state, interaction, pageCoords }: ModifierArg<RestrictState>) {\n  const { options } = state\n  const { elementRect } = options\n  const offset: Rect = extend(\n    {\n      left: 0,\n      top: 0,\n      right: 0,\n      bottom: 0,\n    },\n    options.offset || {},\n  )\n\n  if (rect && elementRect) {\n    const restriction = getRestrictionRect(options.restriction, interaction, pageCoords)\n\n    if (restriction) {\n      const widthDiff = restriction.right - restriction.left - rect.width\n      const heightDiff = restriction.bottom - restriction.top - rect.height\n\n      if (widthDiff < 0) {\n        offset.left += widthDiff\n        offset.right += widthDiff\n      }\n      if (heightDiff < 0) {\n        offset.top += heightDiff\n        offset.bottom += heightDiff\n      }\n    }\n\n    offset.left += startOffset.left - rect.width * elementRect.left\n    offset.top += startOffset.top - rect.height * elementRect.top\n\n    offset.right += startOffset.right - rect.width * (1 - elementRect.right)\n    offset.bottom += startOffset.bottom - rect.height * (1 - elementRect.bottom)\n  }\n\n  state.offset = offset\n}\n\nfunction set({ coords, interaction, state }: ModifierArg<RestrictState>) {\n  const { options, offset } = state\n\n  const restriction = getRestrictionRect(options.restriction, interaction, coords)\n\n  if (!restriction) return\n\n  const rect = rectUtils.xywhToTlbr(restriction)\n\n  coords.x = Math.max(Math.min(rect.right - offset.right, coords.x), rect.left + offset.left)\n  coords.y = Math.max(Math.min(rect.bottom - offset.bottom, coords.y), rect.top + offset.top)\n}\n\nexport function getRestrictionRect(\n  value: RectResolvable<[number, number, Interaction]>,\n  interaction: Interaction,\n  coords?: Point,\n) {\n  if (is.func(value)) {\n    return rectUtils.resolveRectLike(value, interaction.interactable, interaction.element, [\n      coords.x,\n      coords.y,\n      interaction,\n    ])\n  } else {\n    return rectUtils.resolveRectLike(value, interaction.interactable, interaction.element)\n  }\n}\n\nconst defaults: RestrictOptions = {\n  restriction: null,\n  elementRect: null,\n  offset: null,\n  endOnly: false,\n  enabled: false,\n}\n\nconst restrict: ModifierModule<RestrictOptions, RestrictState> = {\n  start,\n  set,\n  defaults,\n}\n\nexport default makeModifier(restrict, 'restrict')\nexport { restrict }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/rect.ts",
    "content": "import extend from '@interactjs/utils/extend'\n\nimport { makeModifier } from '../base'\n\nimport { restrict } from './pointer'\n\nconst defaults = extend(\n  {\n    get elementRect() {\n      return { top: 0, left: 0, bottom: 1, right: 1 }\n    },\n    set elementRect(_) {},\n  },\n  restrict.defaults,\n)\n\nconst restrictRect = {\n  start: restrict.start,\n  set: restrict.set,\n  defaults,\n}\n\nexport default makeModifier(restrictRect, 'restrictRect')\nexport { restrictRect }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/size.spec.ts",
    "content": "import type { ResizeEvent } from '@interactjs/actions/resize/plugin'\nimport resize from '@interactjs/actions/resize/plugin'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport extend from '@interactjs/utils/extend'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport modifiersBase from '../base'\n\nimport restrictSize from './size'\n\ntest('restrictSize', () => {\n  const rect = rectUtils.xywhToTlbr({ left: 0, top: 0, right: 200, bottom: 300 })\n  const { interaction, interactable, coords, down, start, move } = helpers.testEnv({\n    plugins: [modifiersBase, resize],\n    rect,\n  })\n  const edges = { left: true, top: true }\n  const action: any = { name: 'resize', edges }\n  const options = {\n    min: { width: 60, height: 50 } as any,\n    max: { width: 300, height: 350 } as any,\n  }\n  let latestEvent: ResizeEvent = null\n\n  interactable\n    .resizable({\n      modifiers: [restrictSize(options)],\n    })\n    .on('resizestart resizemove resizeend', (e) => {\n      latestEvent = e\n    })\n\n  down()\n  start(action)\n\n  extend(coords.page, { x: -50, y: -40 })\n  move()\n  // within both min and max\n  expect(latestEvent.page).toEqual(coords.page)\n\n  extend(coords.page, { x: -200, y: -300 })\n  move()\n\n  // outside max\n  expect(latestEvent.page).toEqual({ x: -100, y: -50 })\n\n  extend(coords.page, { x: 250, y: 320 })\n  move()\n\n  // outside min\n  expect(latestEvent.page).toEqual({ x: 140, y: 250 })\n\n  // min and max function restrictions\n  let minFuncArgs: any[]\n  let maxFuncArgs: any[]\n\n  options.min = (...args: any[]) => {\n    minFuncArgs = args\n  }\n  options.max = (...args: any[]) => {\n    maxFuncArgs = args\n  }\n\n  move()\n\n  // correct args are passed to min function restriction\n  expect(minFuncArgs).toEqual([coords.page.x, coords.page.y, interaction])\n\n  // correct args are passed to max function restriction\n  expect(maxFuncArgs).toEqual([coords.page.x, coords.page.y, interaction])\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/restrict/size.ts",
    "content": "import type { Point, Rect, Size } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport { makeModifier } from '../base'\nimport type { ModifierArg, ModifierState } from '../types'\n\nimport type { RestrictEdgesState } from './edges'\nimport { restrictEdges } from './edges'\nimport type { RestrictOptions } from './pointer'\nimport { getRestrictionRect } from './pointer'\n\nconst noMin = { width: -Infinity, height: -Infinity }\nconst noMax = { width: +Infinity, height: +Infinity }\n\nexport interface RestrictSizeOptions {\n  min?: Size | Point | RestrictOptions['restriction']\n  max?: Size | Point | RestrictOptions['restriction']\n  endOnly: boolean\n  enabled?: boolean\n}\n\nfunction start(arg: ModifierArg<RestrictEdgesState>) {\n  return restrictEdges.start(arg)\n}\n\nexport type RestrictSizeState = RestrictEdgesState &\n  ModifierState<\n    RestrictSizeOptions & { inner: Rect; outer: Rect },\n    {\n      min: Rect\n      max: Rect\n    }\n  >\n\nfunction set(arg: ModifierArg<RestrictSizeState>) {\n  const { interaction, state, rect, edges } = arg\n  const { options } = state\n\n  if (!edges) {\n    return\n  }\n\n  const minSize =\n    rectUtils.tlbrToXywh(getRestrictionRect(options.min as any, interaction, arg.coords)) || noMin\n  const maxSize =\n    rectUtils.tlbrToXywh(getRestrictionRect(options.max as any, interaction, arg.coords)) || noMax\n\n  state.options = {\n    endOnly: options.endOnly,\n    inner: extend({}, restrictEdges.noInner),\n    outer: extend({}, restrictEdges.noOuter),\n  }\n\n  if (edges.top) {\n    state.options.inner.top = rect.bottom - minSize.height\n    state.options.outer.top = rect.bottom - maxSize.height\n  } else if (edges.bottom) {\n    state.options.inner.bottom = rect.top + minSize.height\n    state.options.outer.bottom = rect.top + maxSize.height\n  }\n  if (edges.left) {\n    state.options.inner.left = rect.right - minSize.width\n    state.options.outer.left = rect.right - maxSize.width\n  } else if (edges.right) {\n    state.options.inner.right = rect.left + minSize.width\n    state.options.outer.right = rect.left + maxSize.width\n  }\n\n  restrictEdges.set(arg)\n\n  state.options = options\n}\n\nconst defaults: RestrictSizeOptions = {\n  min: null,\n  max: null,\n  endOnly: false,\n  enabled: false,\n}\n\nconst restrictSize = {\n  start,\n  set,\n  defaults,\n}\n\nexport default makeModifier(restrictSize, 'restrictSize')\nexport { restrictSize }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/rubberband/rubberband.stub.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/rubberband/rubberband.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/snap/edges.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\nimport type { EdgeOptions } from '@interactjs/core/types'\n\nimport { snapEdges } from '../snap/edges'\n\ntest('modifiers/snap/edges', () => {\n  const rect = { top: 0, left: 0, bottom: 100, right: 100 }\n  const { interaction, interactable } = helpers.testEnv({ rect })\n  interaction.interactable = interactable\n  interaction._interacting = true\n\n  const target0 = Object.freeze({\n    left: 50,\n    right: 150,\n    top: 0,\n    bottom: 100,\n  })\n  const options = {\n    targets: [{ ...target0 }],\n    range: Infinity,\n  }\n  const pageCoords = Object.freeze({ x: 0, y: 0 })\n  const arg = {\n    interaction,\n    // resize from top left\n    edges: { top: true, left: true } as EdgeOptions,\n    interactable: interaction.interactable,\n    state: null as any,\n    pageCoords,\n    coords: { ...pageCoords },\n    offset: [{ x: 0, y: 0 }],\n  }\n\n  arg.state = { options }\n  snapEdges.start!(arg as any)\n  snapEdges.set!(arg as any)\n\n  // modified coords are correct\n  expect(arg.coords).toEqual({ x: target0.left, y: target0.top })\n\n  // resize from bottom right\n  arg.edges = { bottom: true, right: true }\n\n  arg.state = { options }\n  snapEdges.start!(arg as any)\n  snapEdges.set!(arg as any)\n\n  // modified coord are correct\n  expect(arg.coords).toEqual({ x: target0.right, y: target0.bottom })\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/snap/edges.ts",
    "content": "/**\n * @module modifiers/snapEdges\n *\n * @description\n * This modifier allows snapping of the edges of targets during resize\n * interactions.\n *\n * ```js\n * interact(target).resizable({\n *   snapEdges: {\n *     targets: [interact.snappers.grid({ x: 100, y: 50 })],\n *   },\n * })\n *\n * interact(target).resizable({\n *   snapEdges: {\n *     targets: [\n *       interact.snappers.grid({\n *        top: 50,\n *        left: 50,\n *        bottom: 100,\n *        right: 100,\n *       }),\n *     ],\n *   },\n * })\n * ```\n */\n\nimport clone from '@interactjs/utils/clone'\nimport extend from '@interactjs/utils/extend'\n\nimport { makeModifier } from '../base'\nimport type { ModifierArg, ModifierModule } from '../types'\n\nimport type { SnapOptions, SnapState } from './pointer'\nimport { snapSize } from './size'\n\nexport type SnapEdgesOptions = Pick<SnapOptions, 'targets' | 'range' | 'offset' | 'endOnly' | 'enabled'>\n\nfunction start(arg: ModifierArg<SnapState>) {\n  const { edges } = arg\n\n  if (!edges) {\n    return null\n  }\n\n  arg.state.targetFields = arg.state.targetFields || [\n    [edges.left ? 'left' : 'right', edges.top ? 'top' : 'bottom'],\n  ]\n\n  return snapSize.start(arg)\n}\n\nconst snapEdges: ModifierModule<SnapEdgesOptions, SnapState, ReturnType<typeof snapSize.set>> = {\n  start,\n  set: snapSize.set,\n  defaults: extend(clone(snapSize.defaults), {\n    targets: undefined,\n    range: undefined,\n    offset: { x: 0, y: 0 },\n  } as const),\n}\n\nexport default makeModifier(snapEdges, 'snapEdges')\nexport { snapEdges }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/snap/pointer.spec.ts",
    "content": "import drag from '@interactjs/actions/drag/plugin'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport type { Point } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\n\nimport modifiersBase from '../base'\nimport snap from '../snap/pointer'\n\ntest('modifiers/snap', () => {\n  const rect = helpers.ltrbwh(0, 0, 100, 100, 100, 100)\n  const { interaction, interactable, coords, down, move, start, stop } = helpers.testEnv({\n    plugins: [modifiersBase, drag],\n    rect,\n  })\n\n  coords.client = coords.page\n\n  const origin = { x: 120, y: 120 }\n  let funcArgs!: { x: number; y: number; offset: number; index: number; unexpected: unknown[] }\n\n  const target0 = Object.freeze({ x: 50, y: 100 })\n  const targetFunc = (x, y, _interaction, offset, index, ...unexpected) => {\n    funcArgs = { x, y, offset, index, unexpected }\n    return target0\n  }\n  const relativePoint = { x: 0, y: 0 }\n\n  const options = {\n    offset: undefined as Point | undefined,\n    offsetWithOrigin: true,\n    targets: [target0, targetFunc],\n    range: Infinity,\n    relativePoints: [relativePoint],\n  }\n\n  let lastEventModifiers!: any[]\n  interactable\n    .draggable({\n      origin,\n      modifiers: [snap(options)],\n    })\n    .on('dragmove dragstart dragend', (e) => {\n      lastEventModifiers = e.modifiers\n    })\n\n  down()\n  start({ name: 'drag' })\n  extend(coords.page, { x: 50, y: 50 })\n  move()\n\n  // event.modifiers entry has expected props\n  expect(Object.keys(lastEventModifiers[0]).sort()).toEqual([\n    'delta',\n    'distance',\n    'inRange',\n    'range',\n    'target',\n  ])\n\n  // snaps to target and adds origin which will be subtracted by InteractEvent\n  expect(helpers.getProps(lastEventModifiers[0].target, ['x', 'y'])).toEqual({\n    x: target0.x + origin.x,\n    y: target0.y + origin.y,\n  })\n\n  options.targets = [targetFunc]\n  down()\n  start({ name: 'drag' })\n  move(true)\n  stop()\n\n  expect(funcArgs).toEqual({\n    x: coords.page.x - origin.x,\n    y: coords.page.y - origin.y,\n    offset: {\n      x: origin.x,\n      y: origin.y,\n      relativePoint,\n      index: 0,\n    },\n    index: 0,\n    // x, y, interaction, offset, index are passed to target function; origin subtracted from x, y\n    unexpected: [],\n  })\n\n  options.offset = { x: 300, y: 300 }\n  options.offsetWithOrigin = false\n\n  down()\n  start({ name: 'drag' })\n  move(true)\n\n  const { startOffset } = interaction.modification!\n  const relativeOffset = {\n    x: options.offset.x + startOffset.left,\n    y: options.offset.y + startOffset.top,\n  }\n\n  // event.modifiers entry has source element of options.targets array, range, and offset\n  expect(helpers.getProps(lastEventModifiers[0].target, ['source', 'range', 'offset'])).toEqual({\n    source: targetFunc,\n    range: Infinity,\n    offset: { ...relativeOffset, index: 0, relativePoint },\n  })\n\n  // origin not added to target when !options.offsetWithOrigin\n  expect(helpers.getProps(lastEventModifiers[0].target, ['x', 'y'])).toEqual({\n    x: target0.x + relativeOffset.x,\n    y: target0.y + relativeOffset.y,\n  })\n\n  // origin still subtracted from function target x, y args when !options.offsetWithOrigin\n  expect({ x: funcArgs.x, y: funcArgs.y }).toEqual({\n    x: coords.page.x - origin.x - relativeOffset.x,\n    y: coords.page.y - origin.y - relativeOffset.y,\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/snap/pointer.ts",
    "content": "import type { Interaction, InteractionProxy } from '@interactjs/core/Interaction'\nimport type { ActionName, Point, RectResolvable, Element } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\nimport getOriginXY from '@interactjs/utils/getOriginXY'\nimport hypot from '@interactjs/utils/hypot'\nimport is from '@interactjs/utils/is'\nimport { resolveRectLike, rectToXY } from '@interactjs/utils/rect'\n\nimport { makeModifier } from '../base'\nimport type { ModifierArg, ModifierState } from '../types'\n\nexport interface Offset {\n  x: number\n  y: number\n  index: number\n  relativePoint?: Point | null\n}\n\nexport interface SnapPosition {\n  x?: number\n  y?: number\n  range?: number\n  offset?: Offset\n  [index: string]: any\n}\n\nexport type SnapFunction = (\n  x: number,\n  y: number,\n  interaction: InteractionProxy<ActionName>,\n  offset: Offset,\n  index: number,\n) => SnapPosition\nexport type SnapTarget = SnapPosition | SnapFunction\nexport interface SnapOptions {\n  targets?: SnapTarget[]\n  // target range\n  range?: number\n  // self points for snapping. [0,0] = top left, [1,1] = bottom right\n  relativePoints?: Point[]\n  // startCoords = offset snapping from drag start page position\n  offset?: Point | RectResolvable<[Interaction]> | 'startCoords'\n  offsetWithOrigin?: boolean\n  origin?: RectResolvable<[Element]> | Point\n  endOnly?: boolean\n  enabled?: boolean\n}\n\nexport type SnapState = ModifierState<\n  SnapOptions,\n  {\n    offsets?: Offset[]\n    closest?: any\n    targetFields?: string[][]\n  }\n>\n\nfunction start(arg: ModifierArg<SnapState>) {\n  const { interaction, interactable, element, rect, state, startOffset } = arg\n  const { options } = state\n  const origin = options.offsetWithOrigin ? getOrigin(arg) : { x: 0, y: 0 }\n\n  let snapOffset: Point\n\n  if (options.offset === 'startCoords') {\n    snapOffset = {\n      x: interaction.coords.start.page.x,\n      y: interaction.coords.start.page.y,\n    }\n  } else {\n    const offsetRect = resolveRectLike(options.offset as any, interactable, element, [interaction])\n\n    snapOffset = rectToXY(offsetRect) || { x: 0, y: 0 }\n    snapOffset.x += origin.x\n    snapOffset.y += origin.y\n  }\n\n  const { relativePoints } = options\n\n  state.offsets =\n    rect && relativePoints && relativePoints.length\n      ? relativePoints.map((relativePoint, index) => ({\n          index,\n          relativePoint,\n          x: startOffset.left - rect.width * relativePoint.x + snapOffset.x,\n          y: startOffset.top - rect.height * relativePoint.y + snapOffset.y,\n        }))\n      : [\n          {\n            index: 0,\n            relativePoint: null,\n            x: snapOffset.x,\n            y: snapOffset.y,\n          },\n        ]\n}\n\nfunction set(arg: ModifierArg<SnapState>) {\n  const { interaction, coords, state } = arg\n  const { options, offsets } = state\n\n  const origin = getOriginXY(interaction.interactable!, interaction.element!, interaction.prepared.name)\n  const page = extend({}, coords)\n  const targets: SnapPosition[] = []\n\n  if (!options.offsetWithOrigin) {\n    page.x -= origin.x\n    page.y -= origin.y\n  }\n\n  for (const offset of offsets!) {\n    const relativeX = page.x - offset.x\n    const relativeY = page.y - offset.y\n\n    for (let index = 0, len = options.targets!.length; index < len; index++) {\n      const snapTarget = options.targets![index]\n      let target: SnapPosition\n\n      if (is.func(snapTarget)) {\n        target = snapTarget(relativeX, relativeY, interaction._proxy, offset, index)\n      } else {\n        target = snapTarget\n      }\n\n      if (!target) {\n        continue\n      }\n\n      targets.push({\n        x: (is.number(target.x) ? target.x : relativeX) + offset.x,\n        y: (is.number(target.y) ? target.y : relativeY) + offset.y,\n\n        range: is.number(target.range) ? target.range : options.range,\n        source: snapTarget,\n        index,\n        offset,\n      })\n    }\n  }\n\n  const closest = {\n    target: null,\n    inRange: false,\n    distance: 0,\n    range: 0,\n    delta: { x: 0, y: 0 },\n  }\n\n  for (const target of targets) {\n    const range = target.range\n    const dx = target.x - page.x\n    const dy = target.y - page.y\n    const distance = hypot(dx, dy)\n    let inRange = distance <= range\n\n    // Infinite targets count as being out of range\n    // compared to non infinite ones that are in range\n    if (range === Infinity && closest.inRange && closest.range !== Infinity) {\n      inRange = false\n    }\n\n    if (\n      !closest.target ||\n      (inRange\n        ? // is the closest target in range?\n          closest.inRange && range !== Infinity\n          ? // the pointer is relatively deeper in this target\n            distance / range < closest.distance / closest.range\n          : // this target has Infinite range and the closest doesn't\n            (range === Infinity && closest.range !== Infinity) ||\n            // OR this target is closer that the previous closest\n            distance < closest.distance\n        : // The other is not in range and the pointer is closer to this target\n          !closest.inRange && distance < closest.distance)\n    ) {\n      closest.target = target\n      closest.distance = distance\n      closest.range = range\n      closest.inRange = inRange\n      closest.delta.x = dx\n      closest.delta.y = dy\n    }\n  }\n\n  if (closest.inRange) {\n    coords.x = closest.target.x\n    coords.y = closest.target.y\n  }\n\n  state.closest = closest\n  return closest\n}\n\nfunction getOrigin(arg: Partial<ModifierArg<SnapState>>) {\n  const { element } = arg.interaction\n  const optionsOrigin = rectToXY(resolveRectLike(arg.state.options.origin as any, null, null, [element]))\n  const origin = optionsOrigin || getOriginXY(arg.interactable, element, arg.interaction.prepared.name)\n\n  return origin\n}\n\nconst defaults: SnapOptions = {\n  range: Infinity,\n  targets: null,\n  offset: null,\n  offsetWithOrigin: true,\n  origin: null,\n  relativePoints: null,\n  endOnly: false,\n  enabled: false,\n}\nconst snap = {\n  start,\n  set,\n  defaults,\n}\n\nexport default makeModifier(snap, 'snap')\nexport { snap }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/snap/size.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\n\nimport { snapSize } from '../snap/size'\n\ntest('modifiers/snapSize', () => {\n  const { interaction, interactable } = helpers.testEnv()\n  interaction.interactable = interactable\n  interactable.getRect = () => ({ top: 0, left: 0, bottom: 100, right: 100 }) as any\n  interaction._interacting = true\n\n  const target0 = Object.freeze({ x: 50, y: 100 })\n  const options = {\n    targets: [{ ...target0 }],\n    range: Infinity,\n  }\n  const state = {\n    options,\n    delta: { x: 0, y: 0 },\n    offset: [{ x: 0, y: 0 }],\n  }\n  const pageCoords = Object.freeze({ x: 10, y: 20 })\n  const arg = {\n    interaction,\n    interactable: interaction.interactable,\n    edges: { top: true, left: true },\n    state,\n    pageCoords,\n    coords: { ...pageCoords },\n  }\n\n  snapSize.start(arg as any)\n  snapSize.set(arg)\n\n  // snapSize.set single target, zereo offset\n  expect(arg.coords).toEqual(target0)\n})\n"
  },
  {
    "path": "packages/@interactjs/modifiers/snap/size.ts",
    "content": "// This modifier allows snapping of the size of targets during resize\n// interactions.\n\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\n\nimport { makeModifier } from '../base'\nimport type { ModifierArg } from '../types'\n\nimport type { SnapOptions, SnapState } from './pointer'\nimport { snap } from './pointer'\n\nexport type SnapSizeOptions = Pick<SnapOptions, 'targets' | 'offset' | 'endOnly' | 'range' | 'enabled'>\n\nfunction start(arg: ModifierArg<SnapState>) {\n  const { state, edges } = arg\n  const { options } = state\n\n  if (!edges) {\n    return null\n  }\n\n  arg.state = {\n    options: {\n      targets: null,\n      relativePoints: [\n        {\n          x: edges.left ? 0 : 1,\n          y: edges.top ? 0 : 1,\n        },\n      ],\n      offset: options.offset || 'self',\n      origin: { x: 0, y: 0 },\n      range: options.range,\n    },\n  }\n\n  state.targetFields = state.targetFields || [\n    ['width', 'height'],\n    ['x', 'y'],\n  ]\n\n  snap.start(arg)\n  state.offsets = arg.state.offsets\n\n  arg.state = state\n}\n\nfunction set(arg) {\n  const { interaction, state, coords } = arg\n  const { options, offsets } = state\n  const relative = {\n    x: coords.x - offsets[0].x,\n    y: coords.y - offsets[0].y,\n  }\n\n  state.options = extend({}, options)\n  state.options.targets = []\n\n  for (const snapTarget of options.targets || []) {\n    let target\n\n    if (is.func(snapTarget)) {\n      target = snapTarget(relative.x, relative.y, interaction)\n    } else {\n      target = snapTarget\n    }\n\n    if (!target) {\n      continue\n    }\n\n    for (const [xField, yField] of state.targetFields) {\n      if (xField in target || yField in target) {\n        target.x = target[xField]\n        target.y = target[yField]\n\n        break\n      }\n    }\n\n    state.options.targets.push(target)\n  }\n\n  const returnValue = snap.set(arg)\n\n  state.options = options\n\n  return returnValue\n}\n\nconst defaults: SnapSizeOptions = {\n  range: Infinity,\n  targets: null,\n  offset: null,\n  endOnly: false,\n  enabled: false,\n}\n\nconst snapSize = {\n  start,\n  set,\n  defaults,\n}\n\nexport default makeModifier(snapSize, 'snapSize')\nexport { snapSize }\n"
  },
  {
    "path": "packages/@interactjs/modifiers/spring/spring.stub.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/spring/spring.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/transform/transform.stub.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/transform/transform.ts",
    "content": "export { default } from '../noop'\n"
  },
  {
    "path": "packages/@interactjs/modifiers/types.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { EventPhase } from '@interactjs/core/InteractEvent'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { EdgeOptions, FullRect, Point, Rect } from '@interactjs/core/types'\n\nexport interface Modifier<\n  Defaults = any,\n  State extends ModifierState = any,\n  Name extends string = any,\n  Result = any,\n> {\n  options: Defaults\n  methods: {\n    start?: (arg: ModifierArg<State>) => void\n    set?: (arg: ModifierArg<State>) => Result\n    beforeEnd?: (arg: ModifierArg<State>) => Point | void\n    stop?: (arg: ModifierArg<State>) => void\n  }\n  name?: Name\n  enable: () => Modifier<Defaults, State, Name, Result>\n  disable: () => Modifier<Defaults, State, Name, Result>\n}\n\nexport type ModifierState<Defaults = unknown, StateProps = unknown, Name extends string = any> = {\n  options: Defaults\n  methods?: Modifier<Defaults>['methods']\n  index?: number\n  name?: Name\n} & StateProps\n\nexport interface ModifierArg<State extends ModifierState = ModifierState> {\n  interaction: Interaction\n  interactable: Interactable\n  phase: EventPhase\n  rect: FullRect\n  edges: EdgeOptions\n  state: State\n  element: Element\n  pageCoords: Point\n  prevCoords: Point\n  prevRect?: FullRect\n  coords: Point\n  startOffset: Rect\n  preEnd?: boolean\n}\n\nexport interface ModifierModule<\n  Defaults extends { enabled?: boolean },\n  State extends ModifierState,\n  Result = unknown,\n> {\n  defaults?: Defaults\n  start?(arg: ModifierArg<State>): void\n  set?(arg: ModifierArg<State>): Result\n  beforeEnd?(arg: ModifierArg<State>): Point | void\n  stop?(arg: ModifierArg<State>): void\n}\n\nexport interface ModifierFunction<\n  Defaults extends { enabled?: boolean },\n  State extends ModifierState,\n  Name extends string,\n> {\n  (_options?: Partial<Defaults>): Modifier<Defaults, State, Name>\n  _defaults: Defaults\n  _methods: ModifierModule<Defaults, State>\n}\n"
  },
  {
    "path": "packages/@interactjs/offset/offset.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\n\nimport offset from './plugin'\n\ntest('plugins/spring', () => {\n  const { interaction, event, coords, target } = helpers.testEnv({ plugins: [offset] })\n\n  const body = target as HTMLBodyElement\n\n  interaction.pointerMove(event, event, body)\n  interaction.offsetBy({ x: 100, y: 100 })\n  interaction.pointerMove(event, event, body)\n\n  // coords are not updated when pointer is not down\n  expect(interaction.coords.cur.page).toEqual(coords.page)\n\n  interaction.pointerUp(event, event, body, body)\n  interaction.stop()\n  interaction.pointerDown(event, event, body)\n  interaction.offsetBy({ x: 100, y: 50 })\n  interaction.pointerMove(event, event, body)\n\n  // coords are not updated when pointer is not down\n  expect(interaction.coords.cur.page).toEqual({ x: coords.page.x + 100, y: coords.page.y + 50 })\n})\n"
  },
  {
    "path": "packages/@interactjs/offset/package.json",
    "content": "{\n  \"name\": \"@interactjs/offset\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/offset\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/offset/plugin.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\nimport { _ProxyMethods } from '@interactjs/core/Interaction'\nimport type { Plugin } from '@interactjs/core/scope'\nimport type { Point } from '@interactjs/core/types'\nimport * as rectUtils from '@interactjs/utils/rect'\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    offsetBy?: typeof offsetBy\n    offset: {\n      total: Point\n      pending: Point\n    }\n  }\n\n  enum _ProxyMethods {\n    offsetBy = '',\n  }\n}\n\n;(_ProxyMethods as any).offsetBy = ''\n\nexport function addTotal(interaction: Interaction) {\n  if (!interaction.pointerIsDown) {\n    return\n  }\n\n  addToCoords(interaction.coords.cur, interaction.offset.total)\n\n  interaction.offset.pending.x = 0\n  interaction.offset.pending.y = 0\n}\n\nfunction beforeAction({ interaction }: { interaction: Interaction }) {\n  applyPending(interaction)\n}\n\nfunction beforeEnd({ interaction }: { interaction: Interaction }): boolean | void {\n  const hadPending = applyPending(interaction)\n\n  if (!hadPending) return\n\n  interaction.move({ offset: true })\n  interaction.end()\n\n  return false\n}\n\nfunction end({ interaction }: { interaction: Interaction }) {\n  interaction.offset.total.x = 0\n  interaction.offset.total.y = 0\n  interaction.offset.pending.x = 0\n  interaction.offset.pending.y = 0\n}\n\nexport function applyPending(interaction: Interaction) {\n  if (!hasPending(interaction)) {\n    return false\n  }\n\n  const { pending } = interaction.offset\n\n  addToCoords(interaction.coords.cur, pending)\n  addToCoords(interaction.coords.delta, pending)\n  rectUtils.addEdges(interaction.edges, interaction.rect, pending)\n\n  pending.x = 0\n  pending.y = 0\n\n  return true\n}\n\nfunction offsetBy(this: Interaction, { x, y }: Point) {\n  this.offset.pending.x += x\n  this.offset.pending.y += y\n\n  this.offset.total.x += x\n  this.offset.total.y += y\n}\n\nfunction addToCoords({ page, client }, { x, y }: Point) {\n  page.x += x\n  page.y += y\n  client.x += x\n  client.y += y\n}\n\nfunction hasPending(interaction: Interaction) {\n  return !!(interaction.offset.pending.x || interaction.offset.pending.y)\n}\n\nconst offset: Plugin = {\n  id: 'offset',\n  before: ['modifiers', 'pointer-events', 'actions', 'inertia'],\n  install(scope) {\n    scope.Interaction.prototype.offsetBy = offsetBy\n  },\n  listeners: {\n    'interactions:new': ({ interaction }) => {\n      interaction.offset = {\n        total: { x: 0, y: 0 },\n        pending: { x: 0, y: 0 },\n      }\n    },\n    'interactions:update-pointer': ({ interaction }) => addTotal(interaction),\n    'interactions:before-action-start': beforeAction,\n    'interactions:before-action-move': beforeAction,\n    'interactions:before-action-end': beforeEnd,\n    'interactions:stop': end,\n  },\n}\n\nexport default offset\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/PointerEvent.spec.ts",
    "content": "import * as helpers from '@interactjs/core/tests/_helpers'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport { PointerEvent } from './PointerEvent'\n\ntest('PointerEvent constructor', () => {\n  const type = 'TEST_EVENT'\n  const pointerId = -100\n  const testPointerProp = ['TEST_POINTER_PROP']\n  const pointer = {\n    pointerId,\n    testPointerProp,\n    pointerType: 'TEST_POINTER_TYPE',\n  } as any\n  const testEventProp = ['TEST_EVENT_PROP']\n  const event = {\n    testEventProp,\n  } as any\n  const { interaction } = helpers.testEnv()\n  const eventTarget = {} as Element\n  const pointerEvent = new PointerEvent(type, pointer, event, eventTarget, interaction as any, 0) as any\n\n  // pointerEvent is extended form pointer\n  expect(pointerEvent.testPointerProp).toBe(testPointerProp)\n  // pointerEvent is extended form Event\n  expect(pointerEvent.testEventProp).toBe(testEventProp)\n\n  // type is set correctly\n  expect(pointerEvent.type).toBe(type)\n  // pointerType is set correctly\n  expect(pointerEvent.pointerType).toBe(pointerUtils.getPointerType(pointer))\n  // pointerId is set correctly\n  expect(pointerEvent.pointerId).toBe(pointerId)\n  // originalEvent is set correctly\n  expect(pointerEvent.originalEvent).toBe(event)\n  // interaction is set correctly\n  expect(pointerEvent.interaction).toBe(interaction._proxy)\n  // target is set correctly\n  expect(pointerEvent.target).toBe(eventTarget)\n  // currentTarget is null\n  expect(pointerEvent.currentTarget).toBeNull()\n})\n\ntest('PointerEvent methods', () => {\n  const methodContexts = {} as any\n  const event: any = ['preventDefault', 'stopPropagation', 'stopImmediatePropagation'].reduce(\n    (acc, methodName) => {\n      acc[methodName] = function () {\n        methodContexts[methodName] = this\n      }\n      return acc\n    },\n    helpers.newPointer(),\n  )\n  const pointerEvent = new PointerEvent('TEST', {} as any, event, null, {} as any, 0)\n\n  pointerEvent.preventDefault()\n  // PointerEvent.preventDefault() calls preventDefault of originalEvent\n  expect(methodContexts.preventDefault).toBe(event)\n\n  // propagationStopped is false before call to stopPropagation\n  expect(pointerEvent.propagationStopped).toBe(false)\n  pointerEvent.stopPropagation()\n  // stopPropagation sets propagationStopped to true\n  expect(pointerEvent.propagationStopped).toBe(true)\n  // PointerEvent.stopPropagation() does not call stopPropagation of originalEvent\n  // immediatePropagationStopped is false before call to stopImmediatePropagation\n  expect(methodContexts.stopPropagation).toBeUndefined()\n\n  expect(pointerEvent.immediatePropagationStopped).toBe(false)\n  pointerEvent.stopImmediatePropagation()\n  // PointerEvent.stopImmediatePropagation() does not call stopImmediatePropagation of originalEvent\n  expect(methodContexts.stopImmediatePropagation).toBeUndefined()\n  // stopImmediatePropagation sets immediatePropagationStopped to true\n  expect(pointerEvent.immediatePropagationStopped).toBe(true)\n\n  const origin = { x: 20, y: 30 }\n  pointerEvent._subtractOrigin(origin)\n\n  // subtractOrigin updates pageX correctly\n  expect(pointerEvent.pageX).toBe(event.pageX - origin.x)\n  // subtractOrigin updates pageY correctly\n  expect(pointerEvent.pageY).toBe(event.pageY - origin.y)\n  // subtractOrigin updates clientX correctly\n  expect(pointerEvent.clientX).toBe(event.clientX - origin.x)\n  // subtractOrigin updates clientY correctly\n  expect(pointerEvent.clientY).toBe(event.clientY - origin.y)\n\n  pointerEvent._addOrigin(origin)\n  // addOrigin with the subtracted origin reverts to original coordinates\n  expect(['pageX', 'pageY', 'clientX', 'clientY'].every((prop) => pointerEvent[prop] === event[prop])).toBe(\n    true,\n  )\n})\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/PointerEvent.ts",
    "content": "import { BaseEvent } from '@interactjs/core/BaseEvent'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { PointerEventType, PointerType, Point } from '@interactjs/core/types'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nexport class PointerEvent<T extends string = any> extends BaseEvent<never> {\n  declare type: T\n  declare originalEvent: PointerEventType\n  declare pointerId: number\n  declare pointerType: string\n  declare double: boolean\n  declare pageX: number\n  declare pageY: number\n  declare clientX: number\n  declare clientY: number\n  declare dt: number\n  declare eventable: any;\n  [key: string]: any\n\n  constructor(\n    type: T,\n    pointer: PointerType | PointerEvent<any>,\n    event: PointerEventType,\n    eventTarget: Node,\n    interaction: Interaction<never>,\n    timeStamp: number,\n  ) {\n    super(interaction)\n    pointerUtils.pointerExtend(this, event)\n\n    if (event !== pointer) {\n      pointerUtils.pointerExtend(this, pointer)\n    }\n\n    this.timeStamp = timeStamp\n    this.originalEvent = event\n    this.type = type\n    this.pointerId = pointerUtils.getPointerId(pointer)\n    this.pointerType = pointerUtils.getPointerType(pointer)\n    this.target = eventTarget\n    this.currentTarget = null\n\n    if (type === 'tap') {\n      const pointerIndex = interaction.getPointerIndex(pointer)\n      this.dt = this.timeStamp - interaction.pointers[pointerIndex].downTime\n\n      const interval = this.timeStamp - interaction.tapTime\n\n      this.double =\n        !!interaction.prevTap &&\n        interaction.prevTap.type !== 'doubletap' &&\n        interaction.prevTap.target === this.target &&\n        interval < 500\n    } else if (type === 'doubletap') {\n      this.dt = (pointer as PointerEvent<'tap'>).timeStamp - interaction.tapTime\n      this.double = true\n    }\n  }\n\n  _subtractOrigin({ x: originX, y: originY }: Point) {\n    this.pageX -= originX\n    this.pageY -= originY\n    this.clientX -= originX\n    this.clientY -= originY\n\n    return this\n  }\n\n  _addOrigin({ x: originX, y: originY }: Point) {\n    this.pageX += originX\n    this.pageY += originY\n    this.clientX += originX\n    this.clientY += originY\n\n    return this\n  }\n\n  /**\n   * Prevent the default behaviour of the original Event\n   */\n  preventDefault() {\n    this.originalEvent.preventDefault()\n  }\n}\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/base.spec.ts",
    "content": "import { Eventable } from '@interactjs/core/Eventable'\nimport type { Scope } from '@interactjs/core/scope'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport type { PointerEventType, PointerType } from '@interactjs/core/types'\n\nimport type { EventTargetList } from './base'\nimport pointerEvents from './base'\nimport interactableTargets from './interactableTargets'\n\ntest('pointerEvents.types', () => {\n  expect(pointerEvents.types).toEqual({\n    down: true,\n    move: true,\n    up: true,\n    cancel: true,\n    tap: true,\n    doubletap: true,\n    hold: true,\n  })\n})\n\ntest('pointerEvents.fire', () => {\n  const { scope, interaction, event, coords } = helpers.testEnv({ plugins: [pointerEvents] })\n\n  const eventable = new Eventable(pointerEvents.defaults)\n  const type = 'TEST'\n  const element = {}\n  const eventTarget = {}\n  const TEST_PROP = ['TEST_PROP']\n  let firedEvent: any\n  const targets: EventTargetList = [\n    {\n      eventable,\n      node: element as Node,\n      props: {\n        TEST_PROP,\n      },\n    },\n  ]\n\n  eventable.on(type, (e) => {\n    firedEvent = e\n  })\n\n  pointerEvents.fire(\n    {\n      type,\n      eventTarget,\n      pointer: {},\n      event: {},\n      interaction: {},\n      targets,\n    } as any,\n    scope,\n  )\n\n  // Fired event is an instance of pointerEvents.PointerEvent\n  expect(firedEvent instanceof pointerEvents.PointerEvent).toBe(true)\n  // Fired event type is correct\n  expect(firedEvent.type).toBe(type)\n  // Fired event currentTarget is correct\n  expect(firedEvent.currentTarget).toBe(element)\n  // Fired event target is correct\n  expect(firedEvent.target).toBe(eventTarget)\n  // Fired event has props from target.props\n  expect(firedEvent.TEST_PROP).toBe(TEST_PROP)\n\n  scope.now = () => coords.timeStamp\n\n  coords.timeStamp = 0\n  interaction.pointerDown(event, event, scope.document)\n  coords.timeStamp = 500\n  interaction.pointerUp(event, event, scope.document, scope.document)\n\n  // interaction.tapTime is updated\n  expect(interaction.tapTime).toBe(500)\n  // interaction.prevTap is updated\n  expect(interaction.prevTap.type).toBe('tap')\n})\n\ntest('pointerEvents.collectEventTargets', () => {\n  const { scope, interaction } = helpers.testEnv()\n\n  const type = 'TEST'\n  const TEST_PROP = ['TEST_PROP']\n  const target = {\n    node: {} as Node,\n    props: { TEST_PROP },\n    eventable: new Eventable(pointerEvents.defaults),\n  }\n  let collectedTargets: EventTargetList\n\n  function onCollect({ targets }: { targets?: EventTargetList }) {\n    targets.push(target)\n\n    collectedTargets = targets\n  }\n\n  scope.addListeners({\n    'pointerEvents:collect-targets': onCollect,\n  })\n\n  pointerEvents.collectEventTargets(\n    {\n      interaction,\n      pointer: {},\n      event: {},\n      eventTarget: {},\n      type,\n    } as any,\n    scope,\n  )\n\n  expect(collectedTargets).toEqual([target])\n})\n\ntest('pointerEvents Interaction update-pointer signal', () => {\n  const scope: Scope = helpers.mockScope()\n\n  scope.usePlugin(pointerEvents)\n\n  const interaction = scope.interactions.new({})\n  const initialHold = { duration: Infinity, timeout: null as number }\n  const event = {} as PointerEventType\n\n  interaction.updatePointer(helpers.newPointer(0), event, null, false)\n  // set hold info for move on new pointer\n  expect(interaction.pointers.map((p) => p.hold)).toEqual([initialHold])\n\n  interaction.removePointer(helpers.newPointer(0), event)\n\n  interaction.updatePointer(helpers.newPointer(0), event, null, true)\n  expect(interaction.pointers.map((p) => p.hold)).toEqual([initialHold])\n\n  interaction.updatePointer(helpers.newPointer(5), event, null, true)\n  expect(interaction.pointers.map((p) => p.hold)).toEqual([initialHold, initialHold])\n})\n\ntest('pointerEvents Interaction remove-pointer signal', () => {\n  const scope: Scope = helpers.mockScope()\n\n  scope.usePlugin(pointerEvents)\n\n  const interaction = scope.interactions.new({})\n\n  const ids = [0, 1, 2, 3]\n  const removals = [\n    { id: 0, remain: [1, 2, 3], message: 'first of 4' },\n    { id: 2, remain: [1, 3], message: 'middle of 3' },\n    { id: 3, remain: [1], message: 'last of 2' },\n    { id: 1, remain: [], message: 'final' },\n  ]\n\n  for (const id of ids) {\n    const index = interaction.updatePointer(\n      { pointerId: id } as PointerType,\n      {} as PointerEventType,\n      null,\n      true,\n    )\n    // use the ids as the pointerInfo.hold value for this test\n    interaction.pointers[index].hold = id as any\n  }\n\n  for (const removal of removals) {\n    interaction.removePointer({ pointerId: removal.id } as any, null)\n\n    // `${removal.message} - remaining interaction.pointers[i].hold are correct`\n    expect(interaction.pointers.map((p) => p.hold as unknown as number)).toEqual(removal.remain)\n  }\n})\n\ntest('pointerEvents down hold up tap', async () => {\n  const { interaction, event, interactable } = helpers.testEnv({\n    plugins: [pointerEvents, interactableTargets],\n  })\n\n  const fired: PointerEvent[] = []\n\n  for (const type in pointerEvents.types) {\n    interactable.on(type, (e) => fired.push(e))\n  }\n\n  interaction.pointerDown(event, event, event.target)\n  interaction.pointerMove(event, event, event.target)\n\n  // duplicate move event is not fired\n  expect(fired.map((e) => e.type)).toEqual(['down'])\n\n  const holdTimer = interaction.pointers[0].hold\n\n  // hold timeout is set\n  expect(holdTimer.timeout).toBeTruthy()\n\n  await helpers.timeout(holdTimer.duration)\n\n  interaction.pointerUp(event, event, event.target, event.target)\n\n  // tap event is fired after down, hold and up events\n  expect(fired.map((e) => e.type)).toEqual(['down', 'hold', 'up', 'tap'])\n})\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/base.ts",
    "content": "import type { Eventable } from '@interactjs/core/Eventable'\nimport type { Interaction } from '@interactjs/core/Interaction'\nimport type { PerActionDefaults } from '@interactjs/core/options'\nimport type { Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport type { Point, PointerType, PointerEventType, Element } from '@interactjs/core/types'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport getOriginXY from '@interactjs/utils/getOriginXY'\n\nimport { PointerEvent } from './PointerEvent'\n\nexport type EventTargetList = Array<{\n  node: Node\n  eventable: Eventable\n  props: { [key: string]: any }\n}>\n\nexport interface PointerEventOptions extends PerActionDefaults {\n  enabled?: undefined // not used\n  holdDuration?: number\n  ignoreFrom?: any\n  allowFrom?: any\n  origin?: Point | string | Element\n}\n\ndeclare module '@interactjs/core/scope' {\n  interface Scope {\n    pointerEvents: typeof pointerEvents\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    prevTap?: PointerEvent<string>\n    tapTime?: number\n  }\n}\n\ndeclare module '@interactjs/core/PointerInfo' {\n  interface PointerInfo {\n    hold?: {\n      duration: number\n      timeout: any\n    }\n  }\n}\n\ndeclare module '@interactjs/core/options' {\n  interface ActionDefaults {\n    pointerEvents: Options\n  }\n}\n\ndeclare module '@interactjs/core/scope' {\n  interface SignalArgs {\n    'pointerEvents:new': { pointerEvent: PointerEvent<any> }\n    'pointerEvents:fired': {\n      interaction: Interaction<null>\n      pointer: PointerType | PointerEvent<any>\n      event: PointerEventType | PointerEvent<any>\n      eventTarget: Node\n      pointerEvent: PointerEvent<any>\n      targets?: EventTargetList\n      type: string\n    }\n    'pointerEvents:collect-targets': {\n      interaction: Interaction<any>\n      pointer: PointerType | PointerEvent<any>\n      event: PointerEventType | PointerEvent<any>\n      eventTarget: Node\n      targets?: EventTargetList\n      type: string\n      path: Node[]\n      node: null\n    }\n  }\n}\n\nconst defaults: PointerEventOptions = {\n  holdDuration: 600,\n  ignoreFrom: null,\n  allowFrom: null,\n  origin: { x: 0, y: 0 },\n}\n\nconst pointerEvents: Plugin = {\n  id: 'pointer-events/base',\n  before: ['inertia', 'modifiers', 'auto-start', 'actions'],\n  install,\n  listeners: {\n    'interactions:new': addInteractionProps,\n    'interactions:update-pointer': addHoldInfo,\n    'interactions:move': moveAndClearHold,\n    'interactions:down': (arg, scope) => {\n      downAndStartHold(arg, scope)\n      fire(arg, scope)\n    },\n    'interactions:up': (arg, scope) => {\n      clearHold(arg)\n      fire(arg, scope)\n      tapAfterUp(arg, scope)\n    },\n    'interactions:cancel': (arg, scope) => {\n      clearHold(arg)\n      fire(arg, scope)\n    },\n  },\n  PointerEvent,\n  fire,\n  collectEventTargets,\n  defaults,\n  types: {\n    down: true,\n    move: true,\n    up: true,\n    cancel: true,\n    tap: true,\n    doubletap: true,\n    hold: true,\n  } as { [type: string]: true },\n}\n\nfunction fire<T extends string>(\n  arg: {\n    pointer: PointerType | PointerEvent<any>\n    event: PointerEventType | PointerEvent<any>\n    eventTarget: Node\n    interaction: Interaction<never>\n    type: T\n    targets?: EventTargetList\n  },\n  scope: Scope,\n) {\n  const { interaction, pointer, event, eventTarget, type, targets = collectEventTargets(arg, scope) } = arg\n\n  const pointerEvent = new PointerEvent(type, pointer, event, eventTarget, interaction, scope.now())\n\n  scope.fire('pointerEvents:new', { pointerEvent })\n\n  const signalArg = {\n    interaction,\n    pointer,\n    event,\n    eventTarget,\n    targets,\n    type,\n    pointerEvent,\n  }\n\n  for (let i = 0; i < targets.length; i++) {\n    const target = targets[i]\n\n    for (const prop in target.props || {}) {\n      ;(pointerEvent as any)[prop] = target.props[prop]\n    }\n\n    const origin = getOriginXY(target.eventable, target.node)\n\n    pointerEvent._subtractOrigin(origin)\n    pointerEvent.eventable = target.eventable\n    pointerEvent.currentTarget = target.node\n\n    target.eventable.fire(pointerEvent)\n\n    pointerEvent._addOrigin(origin)\n\n    if (\n      pointerEvent.immediatePropagationStopped ||\n      (pointerEvent.propagationStopped &&\n        i + 1 < targets.length &&\n        targets[i + 1].node !== pointerEvent.currentTarget)\n    ) {\n      break\n    }\n  }\n\n  scope.fire('pointerEvents:fired', signalArg)\n\n  if (type === 'tap') {\n    // if pointerEvent should make a double tap, create and fire a doubletap\n    // PointerEvent and use that as the prevTap\n    const prevTap = pointerEvent.double\n      ? fire(\n          {\n            interaction,\n            pointer,\n            event,\n            eventTarget,\n            type: 'doubletap',\n          },\n          scope,\n        )\n      : pointerEvent\n\n    interaction.prevTap = prevTap\n    interaction.tapTime = prevTap.timeStamp\n  }\n\n  return pointerEvent\n}\n\nfunction collectEventTargets<T extends string>(\n  {\n    interaction,\n    pointer,\n    event,\n    eventTarget,\n    type,\n  }: {\n    interaction: Interaction<any>\n    pointer: PointerType | PointerEvent<any>\n    event: PointerEventType | PointerEvent<any>\n    eventTarget: Node\n    type: T\n  },\n  scope: Scope,\n) {\n  const pointerIndex = interaction.getPointerIndex(pointer)\n  const pointerInfo = interaction.pointers[pointerIndex]\n\n  // do not fire a tap event if the pointer was moved before being lifted\n  if (\n    type === 'tap' &&\n    (interaction.pointerWasMoved ||\n      // or if the pointerup target is different to the pointerdown target\n      !(pointerInfo && pointerInfo.downTarget === eventTarget))\n  ) {\n    return []\n  }\n\n  const path = domUtils.getPath(eventTarget as Element | Document)\n  const signalArg = {\n    interaction,\n    pointer,\n    event,\n    eventTarget,\n    type,\n    path,\n    targets: [] as EventTargetList,\n    node: null,\n  }\n\n  for (const node of path) {\n    signalArg.node = node\n\n    scope.fire('pointerEvents:collect-targets', signalArg)\n  }\n\n  if (type === 'hold') {\n    signalArg.targets = signalArg.targets.filter(\n      (target) =>\n        target.eventable.options.holdDuration === interaction.pointers[pointerIndex]?.hold?.duration,\n    )\n  }\n\n  return signalArg.targets\n}\n\nfunction addInteractionProps({ interaction }) {\n  interaction.prevTap = null // the most recent tap event on this interaction\n  interaction.tapTime = 0 // time of the most recent tap event\n}\n\nfunction addHoldInfo({ down, pointerInfo }: SignalArgs['interactions:update-pointer']) {\n  if (!down && pointerInfo.hold) {\n    return\n  }\n\n  pointerInfo.hold = { duration: Infinity, timeout: null }\n}\n\nfunction clearHold({ interaction, pointerIndex }) {\n  const hold = interaction.pointers[pointerIndex].hold\n\n  if (hold && hold.timeout) {\n    clearTimeout(hold.timeout)\n    hold.timeout = null\n  }\n}\n\nfunction moveAndClearHold(arg: SignalArgs['interactions:move'], scope: Scope) {\n  const { interaction, pointer, event, eventTarget, duplicate } = arg\n\n  if (!duplicate && (!interaction.pointerIsDown || interaction.pointerWasMoved)) {\n    if (interaction.pointerIsDown) {\n      clearHold(arg)\n    }\n\n    fire(\n      {\n        interaction,\n        pointer,\n        event,\n        eventTarget: eventTarget as Element,\n        type: 'move',\n      },\n      scope,\n    )\n  }\n}\n\nfunction downAndStartHold(\n  { interaction, pointer, event, eventTarget, pointerIndex }: SignalArgs['interactions:down'],\n  scope: Scope,\n) {\n  const timer = interaction.pointers[pointerIndex].hold!\n  const path = domUtils.getPath(eventTarget as Element | Document)\n  const signalArg = {\n    interaction,\n    pointer,\n    event,\n    eventTarget,\n    type: 'hold',\n    targets: [] as EventTargetList,\n    path,\n    node: null,\n  }\n\n  for (const node of path) {\n    signalArg.node = node\n\n    scope.fire('pointerEvents:collect-targets', signalArg)\n  }\n\n  if (!signalArg.targets.length) return\n\n  let minDuration = Infinity\n\n  for (const target of signalArg.targets) {\n    const holdDuration = target.eventable.options.holdDuration\n\n    if (holdDuration < minDuration) {\n      minDuration = holdDuration\n    }\n  }\n\n  timer.duration = minDuration\n  timer.timeout = setTimeout(() => {\n    fire(\n      {\n        interaction,\n        eventTarget,\n        pointer,\n        event,\n        type: 'hold',\n      },\n      scope,\n    )\n  }, minDuration)\n}\n\nfunction tapAfterUp(\n  { interaction, pointer, event, eventTarget }: SignalArgs['interactions:up'],\n  scope: Scope,\n) {\n  if (!interaction.pointerWasMoved) {\n    fire({ interaction, eventTarget, pointer, event, type: 'tap' }, scope)\n  }\n}\n\nfunction install(scope: Scope) {\n  scope.pointerEvents = pointerEvents\n  scope.defaults.actions.pointerEvents = pointerEvents.defaults\n  extend(scope.actions.phaselessTypes, pointerEvents.types)\n}\n\nexport default pointerEvents\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/holdRepeat.spec.ts",
    "content": "import { Eventable } from '@interactjs/core/Eventable'\nimport * as helpers from '@interactjs/core/tests/_helpers'\n\nimport holdRepeat from './holdRepeat'\n\ntest('holdRepeat count', () => {\n  const pointerEvent = {\n    type: 'hold',\n    count: 0,\n  }\n\n  const { scope } = helpers.testEnv({ plugins: [holdRepeat] })\n\n  scope.fire('pointerEvents:new', { pointerEvent } as any)\n  // first hold count is 1 with count previously undefined\n  expect(pointerEvent.count).toBe(1)\n\n  const count = 20\n  pointerEvent.count = count\n  scope.fire('pointerEvents:new', { pointerEvent } as any)\n  // existing hold count is incremented\n  expect(pointerEvent.count).toBe(count + 1)\n})\n\ntest('holdRepeat onFired', () => {\n  const { scope, interaction } = helpers.testEnv({ plugins: [holdRepeat] })\n\n  const pointerEvent = {\n    type: 'hold',\n  }\n  const eventTarget = {}\n  const eventable = new Eventable(\n    Object.assign({}, scope.pointerEvents.defaults, {\n      holdRepeatInterval: 0,\n    }),\n  )\n  const signalArg = {\n    interaction,\n    pointerEvent,\n    eventTarget,\n    targets: [\n      {\n        eventable,\n      },\n    ],\n  }\n\n  scope.fire('pointerEvents:fired', signalArg as any)\n  // interaction interval handle was not saved with 0 holdRepeatInterval\n  expect('holdIntervalHandle' in interaction).toBe(false)\n\n  eventable.options.holdRepeatInterval = 10\n  scope.fire('pointerEvents:fired', signalArg as any)\n  // interaction interval handle was saved with interval > 0\n  expect('holdIntervalHandle' in interaction).toBe(true)\n\n  clearInterval(interaction.holdIntervalHandle)\n\n  pointerEvent.type = 'NOT_HOLD'\n  delete interaction.holdIntervalHandle\n  scope.fire('pointerEvents:fired', signalArg as any)\n  // interaction interval handle is not saved if pointerEvent.type is not \"hold\"\n  expect('holdIntervalHandle' in interaction).toBe(false)\n})\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/holdRepeat.ts",
    "content": "import type Interaction from '@interactjs/core/Interaction'\nimport type { ListenerMap, Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './base'\nimport basePlugin from './base'\n/* eslint-enable import/no-duplicates */\nimport { type PointerEvent } from './PointerEvent'\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    holdIntervalHandle?: any\n  }\n}\n\ndeclare module '@interactjs/pointer-events/PointerEvent' {\n  interface PointerEvent<T extends string = any> {\n    count?: number\n  }\n}\n\ndeclare module '@interactjs/pointer-events/base' {\n  interface PointerEventOptions {\n    holdRepeatInterval?: number\n  }\n}\n\nfunction install(scope: Scope) {\n  scope.usePlugin(basePlugin)\n\n  const { pointerEvents } = scope\n\n  // don't repeat by default\n  pointerEvents.defaults.holdRepeatInterval = 0\n  pointerEvents.types.holdrepeat = scope.actions.phaselessTypes.holdrepeat = true\n}\n\nfunction onNew({ pointerEvent }: { pointerEvent: PointerEvent<any> }) {\n  if (pointerEvent.type !== 'hold') return\n\n  pointerEvent.count = (pointerEvent.count || 0) + 1\n}\n\nfunction onFired(\n  { interaction, pointerEvent, eventTarget, targets }: SignalArgs['pointerEvents:fired'],\n  scope: Scope,\n) {\n  if (pointerEvent.type !== 'hold' || !targets.length) return\n\n  // get the repeat interval from the first eventable\n  const interval = targets[0].eventable.options.holdRepeatInterval\n\n  // don't repeat if the interval is 0 or less\n  if (interval <= 0) return\n\n  // set a timeout to fire the holdrepeat event\n  interaction.holdIntervalHandle = setTimeout(() => {\n    scope.pointerEvents.fire(\n      {\n        interaction,\n        eventTarget,\n        type: 'hold',\n        pointer: pointerEvent,\n        event: pointerEvent,\n      },\n      scope,\n    )\n  }, interval)\n}\n\nfunction endHoldRepeat({ interaction }: { interaction: Interaction }) {\n  // set the interaction's holdStopTime property\n  // to stop further holdRepeat events\n  if (interaction.holdIntervalHandle) {\n    clearInterval(interaction.holdIntervalHandle)\n    interaction.holdIntervalHandle = null\n  }\n}\n\nconst holdRepeat: Plugin = {\n  id: 'pointer-events/holdRepeat',\n  install,\n  listeners: ['move', 'up', 'cancel', 'endall'].reduce(\n    (acc, enderTypes) => {\n      ;(acc as any)[`pointerEvents:${enderTypes}`] = endHoldRepeat\n      return acc\n    },\n    {\n      'pointerEvents:new': onNew,\n      'pointerEvents:fired': onFired,\n    } as ListenerMap,\n  ),\n}\n\nexport default holdRepeat\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/interactableTargets.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Element } from '@interactjs/core/types'\nimport extend from '@interactjs/utils/extend'\n\nimport type { PointerEventOptions } from '@interactjs/pointer-events/base'\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    pointerEvents(options: Partial<PointerEventOptions>): this\n    /** @internal */\n    __backCompatOption: (optionName: string, newValue: any) => any\n  }\n}\n\nfunction install(scope: Scope) {\n  const { Interactable } = scope\n\n  Interactable.prototype.pointerEvents = function (\n    this: Interactable,\n    options: Partial<PointerEventOptions>,\n  ) {\n    extend(this.events.options, options)\n\n    return this\n  }\n\n  const __backCompatOption = Interactable.prototype._backCompatOption\n\n  Interactable.prototype._backCompatOption = function (optionName, newValue) {\n    const ret = __backCompatOption.call(this, optionName, newValue)\n\n    if (ret === this) {\n      this.events.options[optionName] = newValue\n    }\n\n    return ret\n  }\n}\n\nconst plugin: Plugin = {\n  id: 'pointer-events/interactableTargets',\n  install,\n  listeners: {\n    'pointerEvents:collect-targets': ({ targets, node, type, eventTarget }, scope) => {\n      scope.interactables.forEachMatch(node, (interactable: Interactable) => {\n        const eventable = interactable.events\n        const options = eventable.options\n\n        if (\n          eventable.types[type] &&\n          eventable.types[type].length &&\n          interactable.testIgnoreAllow(options, node, eventTarget)\n        ) {\n          targets.push({\n            node,\n            eventable,\n            props: { interactable },\n          })\n        }\n      })\n    },\n\n    'interactable:new': ({ interactable }) => {\n      interactable.events.getRect = function (element: Element) {\n        return interactable.getRect(element)\n      }\n    },\n\n    'interactable:set': ({ interactable, options }, scope) => {\n      extend(interactable.events.options, scope.pointerEvents.defaults)\n      extend(interactable.events.options, options.pointerEvents || {})\n    },\n  },\n}\n\nexport default plugin\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/package.json",
    "content": "{\n  \"name\": \"@interactjs/pointer-events\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/pointer-events\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/pointer-events/plugin.ts",
    "content": "import type { Plugin } from '@interactjs/core/scope'\n\n/* eslint-disable import/no-duplicates -- for typescript module augmentations */\nimport './base'\nimport './holdRepeat'\nimport './interactableTargets'\n\nimport * as pointerEvents from './base'\nimport holdRepeat from './holdRepeat'\nimport interactableTargets from './interactableTargets'\n/* eslint-enable import/no-duplicates */\n\nconst plugin: Plugin = {\n  id: 'pointer-events',\n  install(scope) {\n    scope.usePlugin(pointerEvents)\n    scope.usePlugin(holdRepeat)\n    scope.usePlugin(interactableTargets)\n  },\n}\n\nexport default plugin\n"
  },
  {
    "path": "packages/@interactjs/reflow/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/reflow/package.json",
    "content": "{\n  \"name\": \"@interactjs/reflow\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/reflow\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/reflow/plugin.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { DoAnyPhaseArg, Interaction } from '@interactjs/core/Interaction'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { ActionName, ActionProps, Element } from '@interactjs/core/types'\nimport * as arr from '@interactjs/utils/arr'\nimport { copyAction } from '@interactjs/utils/misc'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\nimport { tlbrToXywh } from '@interactjs/utils/rect'\n\ndeclare module '@interactjs/core/scope' {\n  interface SignalArgs {\n    'interactions:before-action-reflow': Omit<DoAnyPhaseArg, 'iEvent'>\n    'interactions:action-reflow': DoAnyPhaseArg\n    'interactions:after-action-reflow': DoAnyPhaseArg\n  }\n}\n\ndeclare module '@interactjs/core/Interactable' {\n  interface Interactable {\n    /**\n     * ```js\n     * const interactable = interact(target)\n     * const drag = { name: drag, axis: 'x' }\n     * const resize = { name: resize, edges: { left: true, bottom: true }\n     *\n     * interactable.reflow(drag)\n     * interactable.reflow(resize)\n     * ```\n     *\n     * Start an action sequence to re-apply modifiers, check drops, etc.\n     *\n     * @param { Object } action The action to begin\n     * @param { string } action.name The name of the action\n     * @returns { Promise } A promise that resolves to the `Interactable` when actions on all targets have ended\n     */\n    reflow<T extends ActionName>(action: ActionProps<T>): ReturnType<typeof doReflow>\n  }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n  interface Interaction {\n    _reflowPromise: Promise<void>\n    _reflowResolve: (...args: unknown[]) => void\n  }\n}\n\ndeclare module '@interactjs/core/InteractEvent' {\n  interface PhaseMap {\n    reflow?: true\n  }\n}\n\nfunction install(scope: Scope) {\n  const { Interactable } = scope\n\n  scope.actions.phases.reflow = true\n\n  Interactable.prototype.reflow = function (action: ActionProps) {\n    return doReflow(this, action, scope)\n  }\n}\n\nfunction doReflow<T extends ActionName>(\n  interactable: Interactable,\n  action: ActionProps<T>,\n  scope: Scope,\n): Promise<Interactable> {\n  const elements = interactable.getAllElements()\n\n  // tslint:disable-next-line variable-name\n  const Promise = (scope.window as any).Promise\n  const promises: Array<Promise<null>> | null = Promise ? [] : null\n\n  for (const element of elements) {\n    const rect = interactable.getRect(element as HTMLElement | SVGElement)\n\n    if (!rect) {\n      break\n    }\n\n    const runningInteraction = arr.find(scope.interactions.list, (interaction: Interaction) => {\n      return (\n        interaction.interacting() &&\n        interaction.interactable === interactable &&\n        interaction.element === element &&\n        interaction.prepared.name === action.name\n      )\n    })\n    let reflowPromise: Promise<null>\n\n    if (runningInteraction) {\n      runningInteraction.move()\n\n      if (promises) {\n        reflowPromise =\n          runningInteraction._reflowPromise ||\n          new Promise((resolve: any) => {\n            runningInteraction._reflowResolve = resolve\n          })\n      }\n    } else {\n      const xywh = tlbrToXywh(rect)\n      const coords = {\n        page: { x: xywh.x, y: xywh.y },\n        client: { x: xywh.x, y: xywh.y },\n        timeStamp: scope.now(),\n      }\n\n      const event = pointerUtils.coordsToEvent(coords)\n      reflowPromise = startReflow<T>(scope, interactable, element, action, event)\n    }\n\n    if (promises) {\n      promises.push(reflowPromise)\n    }\n  }\n\n  return promises && Promise.all(promises).then(() => interactable)\n}\n\nfunction startReflow<T extends ActionName>(\n  scope: Scope,\n  interactable: Interactable,\n  element: Element,\n  action: ActionProps<T>,\n  event: any,\n) {\n  const interaction = scope.interactions.new({ pointerType: 'reflow' })\n  const signalArg = {\n    interaction,\n    event,\n    pointer: event,\n    eventTarget: element,\n    phase: 'reflow',\n  } as const\n\n  interaction.interactable = interactable\n  interaction.element = element\n  interaction.prevEvent = event\n  interaction.updatePointer(event, event, element, true)\n  pointerUtils.setZeroCoords(interaction.coords.delta)\n\n  copyAction(interaction.prepared, action)\n  interaction._doPhase(signalArg)\n\n  const { Promise } = scope.window as unknown as { Promise: PromiseConstructor }\n  const reflowPromise = Promise\n    ? new Promise<undefined>((resolve) => {\n        interaction._reflowResolve = resolve\n      })\n    : undefined\n\n  interaction._reflowPromise = reflowPromise\n  interaction.start(action, interactable, element)\n\n  if (interaction._interacting) {\n    interaction.move(signalArg)\n    interaction.end(event)\n  } else {\n    interaction.stop()\n    interaction._reflowResolve()\n  }\n\n  interaction.removePointer(event, event)\n\n  return reflowPromise\n}\n\nconst reflow: Plugin = {\n  id: 'reflow',\n  install,\n  listeners: {\n    // remove completed reflow interactions\n    'interactions:stop': ({ interaction }, scope) => {\n      if (interaction.pointerType === 'reflow') {\n        if (interaction._reflowResolve) {\n          interaction._reflowResolve()\n        }\n\n        arr.remove(scope.interactions.list, interaction)\n      }\n    },\n  },\n}\n\nexport default reflow\n"
  },
  {
    "path": "packages/@interactjs/reflow/reflow.spec.ts",
    "content": "import type { Interactable } from '@interactjs/core/Interactable'\nimport type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport * as helpers from '@interactjs/core/tests/_helpers'\nimport type { ActionName, Point } from '@interactjs/core/types'\nimport PromisePolyfill from 'promise-polyfill'\n\nimport reflow from './plugin'\n\nconst testAction = { name: 'TEST' as ActionName }\n\nconst Promise_ = Promise\n\ndescribe('reflow', () => {\n  test('sync', () => {\n    const rect = Object.freeze({ top: 100, left: 200, bottom: 300, right: 400 })\n\n    const { scope, interactable } = helpers.testEnv({ plugins: [reflow], rect })\n\n    Object.assign(scope.actions, { TEST: {}, names: ['TEST'] })\n\n    // reflow method is added to Interactable.prototype\n    expect(scope.Interactable.prototype.reflow instanceof Function).toBe(true)\n\n    const fired: InteractEvent[] = []\n    let beforeReflowDelta: Point\n\n    interactable.fire = ((iEvent: any) => {\n      fired.push(iEvent)\n    }) as any\n    ;(interactable.options as any).TEST = { enabled: true }\n    interactable.rectChecker(() => ({ ...rect }))\n\n    // modify move coords\n    scope.addListeners({\n      'interactions:before-action-move': ({ interaction }) => {\n        interaction.coords.cur.page = {\n          x: rect.left + 100,\n          y: rect.top - 50,\n        }\n      },\n      'interactions:before-action-reflow': ({ interaction }) => {\n        beforeReflowDelta = { ...interaction.coords.delta.page }\n      },\n    })\n\n    interactable.reflow(testAction)\n\n    const phases = ['reflow', 'start', 'move', 'end']\n    expect(phases.map((_phase, index) => fired[index]?.type)).toEqual(phases.map((phase) => `TEST${phase}`))\n\n    for (const index in phases) {\n      const phase = phases[index]\n      // `event #${index} is ${phase}`\n      expect(fired[index].type).toBe(`TEST${phase}`)\n    }\n\n    const interaction = fired[0]._interaction\n\n    // uses element top left for event coords\n    expect(interaction.coords.start.page).toEqual({\n      x: rect.left,\n      y: rect.top,\n    })\n\n    const reflowMove = fired[2]\n\n    // interaction delta is zero before-action-reflow\n    expect(beforeReflowDelta!).toEqual({ x: 0, y: 0 })\n    // move delta is correct with modified interaction coords\n    expect(reflowMove.delta).toEqual({ x: 100, y: -50 })\n    // reflow pointer was lifted\n    expect(interaction.pointerIsDown).toBe(false)\n    // reflow pointer was removed from interaction\n    expect(interaction.pointers).toHaveLength(0)\n    // interaction is removed from list\n    expect(scope.interactions.list).not.toContain(interaction)\n  })\n\n  test('async', async () => {\n    const { scope } = helpers.testEnv({ plugins: [reflow] })\n\n    Object.assign(scope.actions, { TEST: {}, names: ['TEST'] })\n\n    let reflowEvent: any\n    let promise: Promise<Interactable>\n\n    const interactable = scope.interactables.new(scope.document.documentElement)\n    const rect = Object.freeze({ top: 100, left: 200, bottom: 300, right: 400 })\n    interactable.rectChecker(() => ({ ...rect }))\n    interactable.fire = ((iEvent: any) => {\n      reflowEvent = iEvent\n    }) as any\n    ;(interactable.options as any).TEST = { enabled: true }\n\n    // test with Promise implementation\n    ;(scope.window as any).Promise = PromisePolyfill\n\n    promise = interactable.reflow(testAction)\n    // method returns a Promise if available\n    expect(promise instanceof (scope.window as any).Promise).toBe(true)\n    // reflow may end synchronously\n    expect(reflowEvent.interaction.interacting()).toBe(false)\n\n    // returned Promise resolves to interactable\n    expect(await promise).toBe(interactable)\n\n    let stoppedFromTimeout: boolean\n    // block the end of the reflow interaction and stop it after a timeout\n    scope.addListeners({\n      'interactions:before-action-end': ({ interaction }) => {\n        setTimeout(() => {\n          interaction.stop()\n          stoppedFromTimeout = true\n        }, 0)\n        return false\n      },\n    })\n\n    stoppedFromTimeout = false\n    promise = interactable.reflow(testAction)\n\n    // interaction continues if end is blocked\n    expect(reflowEvent.interaction.interacting() && !stoppedFromTimeout).toBe(true)\n    await promise\n    // interaction is stopped after promise is resolved\n    expect(reflowEvent.interaction.interacting() && stoppedFromTimeout).toBe(false)\n\n    // test without Promise implementation\n    stoppedFromTimeout = false\n    ;(scope.window as any).Promise = undefined\n\n    promise = interactable.reflow(testAction)\n    // method returns null if no Proise is avilable\n    expect(promise).toBeNull()\n    // interaction continues if end is blocked without Promise\n    expect(reflowEvent.interaction.interacting() && !stoppedFromTimeout).toBe(true)\n\n    await new Promise_<void>((resolve) =>\n      setTimeout(() => {\n        // interaction is stopped after timeout without Promised\n        expect(reflowEvent.interaction.interacting() || !stoppedFromTimeout).toBe(false)\n        resolve()\n      }, 0),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/@interactjs/snappers/all.ts",
    "content": "/* eslint-disable import/no-named-as-default, import/no-unresolved */\nexport { default as edgeTarget } from './edgeTarget'\nexport { default as elements } from './elements'\nexport { default as grid } from './grid'\n"
  },
  {
    "path": "packages/@interactjs/snappers/edgeTarget.stub.ts",
    "content": "export default () => {}\n"
  },
  {
    "path": "packages/@interactjs/snappers/edgeTarget.ts",
    "content": "export default () => {}\n"
  },
  {
    "path": "packages/@interactjs/snappers/elements.stub.ts",
    "content": "export default () => {}\n"
  },
  {
    "path": "packages/@interactjs/snappers/elements.ts",
    "content": "export default () => {}\n"
  },
  {
    "path": "packages/@interactjs/snappers/grid.ts",
    "content": "import type { Rect, Point } from '@interactjs/core/types'\nimport type { SnapFunction, SnapTarget } from '@interactjs/modifiers/snap/pointer'\n\nexport interface GridOptionsBase {\n  range?: number\n  limits?: Rect\n  offset?: Point\n}\nexport interface GridOptionsXY extends GridOptionsBase {\n  x: number\n  y: number\n}\nexport interface GridOptionsTopLeft extends GridOptionsBase {\n  top?: number\n  left?: number\n}\nexport interface GridOptionsBottomRight extends GridOptionsBase {\n  bottom?: number\n  right?: number\n}\nexport interface GridOptionsWidthHeight extends GridOptionsBase {\n  width?: number\n  height?: number\n}\n\nexport type GridOptions = GridOptionsXY | GridOptionsTopLeft | GridOptionsBottomRight | GridOptionsWidthHeight\n\nexport default (grid: GridOptions) => {\n  const coordFields = (\n    [\n      ['x', 'y'],\n      ['left', 'top'],\n      ['right', 'bottom'],\n      ['width', 'height'],\n    ] as const\n  ).filter(([xField, yField]) => xField in grid || yField in grid)\n\n  const gridFunc: SnapFunction & {\n    grid: typeof grid\n    coordFields: typeof coordFields\n  } = (x, y) => {\n    const {\n      range,\n      limits = {\n        left: -Infinity,\n        right: Infinity,\n        top: -Infinity,\n        bottom: Infinity,\n      },\n      offset = { x: 0, y: 0 },\n    } = grid\n\n    const result: SnapTarget & {\n      grid: typeof grid\n    } = { range, grid, x: null as number, y: null as number }\n\n    for (const [xField, yField] of coordFields) {\n      const gridx = Math.round((x - offset.x) / (grid as any)[xField])\n      const gridy = Math.round((y - offset.y) / (grid as any)[yField])\n\n      result[xField] = Math.max(limits.left, Math.min(limits.right, gridx * (grid as any)[xField] + offset.x))\n      result[yField] = Math.max(limits.top, Math.min(limits.bottom, gridy * (grid as any)[yField] + offset.y))\n    }\n\n    return result\n  }\n\n  gridFunc.grid = grid\n  gridFunc.coordFields = coordFields\n\n  return gridFunc\n}\n"
  },
  {
    "path": "packages/@interactjs/snappers/package.json",
    "content": "{\n  \"name\": \"@interactjs/snappers\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/snappers\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"optionalDependencies\": {\n    \"@interactjs/interact\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/snappers/plugin.ts",
    "content": "import type { Plugin } from '@interactjs/core/scope'\nimport extend from '@interactjs/utils/extend'\n\nimport * as allSnappers from './all'\n\ndeclare module '@interactjs/core/InteractStatic' {\n  export interface InteractStatic {\n    snappers: typeof allSnappers\n    createSnapGrid: typeof allSnappers.grid\n  }\n}\n\nconst snappersPlugin: Plugin = {\n  id: 'snappers',\n  install(scope) {\n    const { interactStatic: interact } = scope\n\n    interact.snappers = extend(interact.snappers || {}, allSnappers)\n    interact.createSnapGrid = interact.snappers.grid\n  },\n}\n\nexport default snappersPlugin\n"
  },
  {
    "path": "packages/@interactjs/types/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/types/index.ts",
    "content": "/* eslint-disable import/no-extraneous-dependencies */\nimport type { InteractEvent as _InteractEvent, EventPhase } from '@interactjs/core/InteractEvent'\nimport type * as interaction from '@interactjs/core/Interaction'\nimport type { ActionName, ActionProps as _ActionProps } from '@interactjs/core/types'\n// import module augmentations\nimport '@interactjs/interactjs'\n\nexport * from '@interactjs/core/types'\nexport type { Plugin } from '@interactjs/core/scope'\nexport type { EventPhase } from '@interactjs/core/InteractEvent'\nexport type { Options } from '@interactjs/core/options'\nexport type { PointerEvent } from '@interactjs/pointer-events/PointerEvent'\nexport type { Interactable } from '@interactjs/core/Interactable'\nexport type { DragEvent } from '@interactjs/actions/drag/plugin'\nexport type { DropEvent } from '@interactjs/actions/drop/DropEvent'\nexport type { GestureEvent } from '@interactjs/actions/gesture/plugin'\nexport type { ResizeEvent } from '@interactjs/actions/resize/plugin'\nexport type { SnapFunction, SnapTarget } from '@interactjs/modifiers/snap/pointer'\n\nexport type ActionProps<T extends ActionName = ActionName> = _ActionProps<T>\nexport type Interaction<T extends ActionName = ActionName> = interaction.Interaction<T>\nexport type InteractionProxy<T extends ActionName = ActionName> = interaction.InteractionProxy<T>\nexport type PointerArgProps<T extends {} = {}> = interaction.PointerArgProps<T>\nexport type InteractEvent<T extends ActionName = never, P extends EventPhase = EventPhase> = _InteractEvent<\n  T,\n  P\n>\n"
  },
  {
    "path": "packages/@interactjs/types/package.json",
    "content": "{\n  \"name\": \"@interactjs/types\",\n  \"version\": \"1.10.27\",\n  \"main\": \"index\",\n  \"module\": \"index\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/types\"\n  },\n  \"typings\": \"typings.d.ts\",\n  \"devDependencies\": {\n    \"@interactjs/actions\": \"1.10.27\",\n    \"@interactjs/arrange\": \"1.10.27\",\n    \"@interactjs/auto-scroll\": \"1.10.27\",\n    \"@interactjs/auto-start\": \"1.10.27\",\n    \"@interactjs/core\": \"1.10.27\",\n    \"@interactjs/dev-tools\": \"1.10.27\",\n    \"@interactjs/inertia\": \"1.10.27\",\n    \"@interactjs/interact\": \"1.10.27\",\n    \"@interactjs/interactjs\": \"1.10.27\",\n    \"@interactjs/modifiers\": \"1.10.27\",\n    \"@interactjs/pointer-events\": \"1.10.27\",\n    \"@interactjs/reflow\": \"1.10.27\",\n    \"@interactjs/snappers\": \"1.10.27\",\n    \"@interactjs/utils\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/types/types.spec.ts",
    "content": "/** @jest-environment node */\nimport path from 'path'\n\nimport * as execTypes from '@interactjs/_dev/scripts/execTypes'\nimport { mkdirp } from 'mkdirp'\nimport * as shell from 'shelljs'\nimport temp from 'temp'\n\njest.setTimeout(15000)\n\ntest('typings', async () => {\n  shell.config.fatal = true\n\n  const tempDir = temp.track().mkdirSync('testProject')\n  const modulesDir = path.join(tempDir, 'node_modules')\n  const tempTypesDir = path.join(modulesDir, '@interactjs', 'types')\n  const interactDir = path.join(modulesDir, 'interactjs')\n\n  await mkdirp(interactDir)\n\n  // run .d.ts generation script with output to temp dir node_modules\n  await execTypes.combined(tempTypesDir)\n\n  // copy .d.ts and package.json files of deps to temp dir\n  shell.cp(path.join('packages', 'interactjs', '{*.d.ts,package.json}'), interactDir)\n  shell.cp(path.join('packages', '@interactjs', 'types', '{*.d.ts,package.json}'), tempTypesDir)\n  shell.cp('-R', path.join(process.cwd(), 'test', 'fixtures', 'dependentTsProject', '*'), tempDir)\n\n  expect(() => {\n    shell.exec(`${getBin('tsc')} -b`, { cwd: tempDir })\n  }).not.toThrow()\n  shell.config.reset()\n})\n\nconst nodeBins = path.join(process.cwd(), 'node_modules', '.bin')\nconst getBin = (name: string) => path.join(nodeBins, name)\n"
  },
  {
    "path": "packages/@interactjs/utils/ElementState.stub.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/utils/ElementState.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/utils/README.md",
    "content": "<h2>\nThis package is an internal part of <a\nhref=\"https://www.npmjs.com/package/interactjs\">interactjs</a> and is not meant\nto be used independently as each update may introduce breaking changes\n</h2>\n"
  },
  {
    "path": "packages/@interactjs/utils/arr.ts",
    "content": "type Filter<T> = (element: T, index: number, array: T[]) => boolean\n\nexport const contains = <T>(array: T[], target: T) => array.indexOf(target) !== -1\n\nexport const remove = <T>(array: T[], target: T) => array.splice(array.indexOf(target), 1)\n\nexport const merge = <T, U>(target: Array<T | U>, source: U[]) => {\n  for (const item of source) {\n    target.push(item)\n  }\n\n  return target\n}\n\nexport const from = <T = any>(source: ArrayLike<T>) => merge([] as T[], source as T[])\n\nexport const findIndex = <T>(array: T[], func: Filter<T>) => {\n  for (let i = 0; i < array.length; i++) {\n    if (func(array[i], i, array)) {\n      return i\n    }\n  }\n\n  return -1\n}\n\nexport const find = <T = any>(array: T[], func: Filter<T>): T | undefined => array[findIndex(array, func)]\n"
  },
  {
    "path": "packages/@interactjs/utils/browser.ts",
    "content": "import domObjects from './domObjects'\nimport is from './is'\n\nconst browser = {\n  init,\n  supportsTouch: null as boolean,\n  supportsPointerEvent: null as boolean,\n  isIOS7: null as boolean,\n  isIOS: null as boolean,\n  isIe9: null as boolean,\n  isOperaMobile: null as boolean,\n  prefixedMatchesSelector: null as 'matches',\n  pEventTypes: null as {\n    up: string\n    down: string\n    over: string\n    out: string\n    move: string\n    cancel: string\n  },\n  wheelEvent: null as string,\n}\n\nfunction init(window: any) {\n  const Element = domObjects.Element\n  const navigator: Partial<Navigator> = window.navigator || {}\n\n  // Does the browser support touch input?\n  browser.supportsTouch =\n    'ontouchstart' in window ||\n    (is.func(window.DocumentTouch) && domObjects.document instanceof window.DocumentTouch)\n\n  // Does the browser support PointerEvents\n  // https://github.com/taye/interact.js/issues/703#issuecomment-471570492\n  browser.supportsPointerEvent = (navigator as any).pointerEnabled !== false && !!domObjects.PointerEvent\n\n  browser.isIOS = /iP(hone|od|ad)/.test(navigator.platform)\n\n  // scrolling doesn't change the result of getClientRects on iOS 7\n  browser.isIOS7 = /iP(hone|od|ad)/.test(navigator.platform) && /OS 7[^\\d]/.test(navigator.appVersion)\n\n  browser.isIe9 = /MSIE 9/.test(navigator.userAgent)\n\n  // Opera Mobile must be handled differently\n  browser.isOperaMobile =\n    navigator.appName === 'Opera' && browser.supportsTouch && /Presto/.test(navigator.userAgent)\n\n  // prefix matchesSelector\n  browser.prefixedMatchesSelector = (\n    'matches' in Element.prototype\n      ? 'matches'\n      : 'webkitMatchesSelector' in Element.prototype\n        ? 'webkitMatchesSelector'\n        : 'mozMatchesSelector' in Element.prototype\n          ? 'mozMatchesSelector'\n          : 'oMatchesSelector' in Element.prototype\n            ? 'oMatchesSelector'\n            : 'msMatchesSelector'\n  ) as 'matches'\n\n  browser.pEventTypes = browser.supportsPointerEvent\n    ? domObjects.PointerEvent === window.MSPointerEvent\n      ? {\n          up: 'MSPointerUp',\n          down: 'MSPointerDown',\n          over: 'mouseover',\n          out: 'mouseout',\n          move: 'MSPointerMove',\n          cancel: 'MSPointerCancel',\n        }\n      : {\n          up: 'pointerup',\n          down: 'pointerdown',\n          over: 'pointerover',\n          out: 'pointerout',\n          move: 'pointermove',\n          cancel: 'pointercancel',\n        }\n    : null\n\n  // because Webkit and Opera still use 'mousewheel' event type\n  browser.wheelEvent = domObjects.document && 'onmousewheel' in domObjects.document ? 'mousewheel' : 'wheel'\n}\n\nexport default browser\n"
  },
  {
    "path": "packages/@interactjs/utils/center.ts",
    "content": "import type { Rect } from '@interactjs/core/types'\n\nexport default (rect: Rect) => ({\n  x: rect.left + (rect.right - rect.left) / 2,\n  y: rect.top + (rect.bottom - rect.top) / 2,\n})\n"
  },
  {
    "path": "packages/@interactjs/utils/clone.ts",
    "content": "import * as arr from './arr'\nimport is from './is'\n\n// tslint:disable-next-line ban-types\nexport default function clone<T extends Object>(source: T): Partial<T> {\n  const dest = {} as Partial<T>\n\n  for (const prop in source) {\n    const value = source[prop]\n\n    if (is.plainObject(value)) {\n      dest[prop] = clone(value) as any\n    } else if (is.array(value)) {\n      dest[prop] = arr.from(value) as typeof value\n    } else {\n      dest[prop] = value\n    }\n  }\n\n  return dest\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/displace.stub.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/utils/displace.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/utils/domObjects.ts",
    "content": "const domObjects: {\n  init: any\n  document: Document\n  DocumentFragment: typeof DocumentFragment\n  SVGElement: typeof SVGElement\n  SVGSVGElement: typeof SVGSVGElement\n  SVGElementInstance: any\n  Element: typeof Element\n  HTMLElement: typeof HTMLElement\n  Event: typeof Event\n  Touch: typeof Touch\n  PointerEvent: typeof PointerEvent\n} = {\n  init,\n  document: null,\n  DocumentFragment: null,\n  SVGElement: null,\n  SVGSVGElement: null,\n  SVGElementInstance: null,\n  Element: null,\n  HTMLElement: null,\n  Event: null,\n  Touch: null,\n  PointerEvent: null,\n}\n\nfunction blank() {}\n\nexport default domObjects\n\nfunction init(window: Window) {\n  const win = window as any\n\n  domObjects.document = win.document\n  domObjects.DocumentFragment = win.DocumentFragment || blank\n  domObjects.SVGElement = win.SVGElement || blank\n  domObjects.SVGSVGElement = win.SVGSVGElement || blank\n  domObjects.SVGElementInstance = win.SVGElementInstance || blank\n  domObjects.Element = win.Element || blank\n  domObjects.HTMLElement = win.HTMLElement || domObjects.Element\n\n  domObjects.Event = win.Event\n  domObjects.Touch = win.Touch || blank\n  domObjects.PointerEvent = win.PointerEvent || win.MSPointerEvent\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/domUtils.spec.ts",
    "content": "import domObjects from './domObjects'\nimport { indexOfDeepestElement } from './domUtils'\n\ninterface MockNode {\n  name: string\n  lastChild: any\n  parentNode: MockNode | null\n  ownerDocument: MockNode | null\n  host?: MockNode\n}\n\ntest('utils/domUtils/indexOfDeepestElement', () => {\n  document.body.innerHTML = `<div id=\"topDiv\">\n    <div id=\"sib0\"></div>\n    <div id=\"sib1\"></div>\n    <div id=\"sib2\"></div>\n  </div>`\n\n  domObjects.init(document)\n\n  const ownerDocument: MockNode = {\n    name: 'Owner Document',\n    lastChild: null as any,\n    parentNode: null,\n    ownerDocument: null,\n  }\n  const html: MockNode = {\n    name: 'html',\n    lastChild: null as any,\n    ownerDocument,\n    parentNode: ownerDocument,\n  }\n\n  const body: MockNode = { name: 'body', lastChild: null, ownerDocument, parentNode: html }\n  const wrapper: MockNode = { name: 'wrapper', ownerDocument, parentNode: body, lastChild: null }\n  const a: MockNode = { name: 'a', ownerDocument, parentNode: wrapper, lastChild: null }\n  const b1: MockNode = { name: 'b1', ownerDocument, parentNode: a, lastChild: null }\n  const b2: MockNode = { name: 'b2', ownerDocument, parentNode: a, lastChild: null }\n  const c1: MockNode = { name: 'c1', ownerDocument, parentNode: b1, lastChild: null }\n  const c2: MockNode = { name: 'c2', ownerDocument, parentNode: b1, lastChild: null }\n  const d1: MockNode = { name: 'd1', ownerDocument, parentNode: c1, lastChild: null }\n  const d1Comp: MockNode = { name: 'd1_comp', ownerDocument, parentNode: d1, lastChild: null }\n  const d2Shadow: MockNode = {\n    name: 'd2_shadow',\n    ownerDocument,\n    parentNode: null,\n    lastChild: null,\n    host: d1Comp,\n  }\n\n  ownerDocument.lastChild = html\n  html.lastChild = body\n  body.lastChild = wrapper\n  a.lastChild = b2\n  b1.lastChild = c2\n  b2.lastChild = null\n  c1.lastChild = d1\n  c2.lastChild = null\n  d1.lastChild = d1\n  wrapper.lastChild = a\n\n  const deepestShadow = [null, d2Shadow, c1, b1, a] as unknown as HTMLElement[]\n  expect(indexOfDeepestElement(deepestShadow)).toBe(deepestShadow.indexOf(d2Shadow as any))\n\n  const noShadow = [null, d1, c1, b1] as unknown as HTMLElement[]\n\n  // only chooses elements that are passed in\n  expect(indexOfDeepestElement(noShadow)).toBe(noShadow.indexOf(d1 as any))\n\n  const siblings: NodeListOf<HTMLElement> = document.querySelectorAll('#topDiv > *')\n\n  // last sibling is deepest with equal zIndex\n  expect(indexOfDeepestElement(siblings)).toBe(2)\n\n  siblings[0].style.zIndex = '2'\n  siblings[1].style.zIndex = '2'\n  siblings[2].style.zIndex = '1'\n\n  // works with shadow root\n  // sibling with higher z-index is selected\n  expect(indexOfDeepestElement(siblings)).toBe(1)\n\n  const nodeWithoutParent: MockNode = { name: 'd1', ownerDocument, parentNode: null, lastChild: null }\n  const brokenElementCollection = [nodeWithoutParent, d1, c2] as unknown as HTMLElement[]\n  expect(indexOfDeepestElement(brokenElementCollection)).toBe(0)\n})\n"
  },
  {
    "path": "packages/@interactjs/utils/domUtils.ts",
    "content": "import type { Rect, Target, Element } from '@interactjs/core/types'\n\nimport browser from './browser'\nimport domObjects from './domObjects'\nimport is from './is'\nimport * as win from './window'\n\nexport function nodeContains(parent: Node, child: Node) {\n  if (parent.contains) {\n    return parent.contains(child as Node)\n  }\n\n  while (child) {\n    if (child === parent) {\n      return true\n    }\n\n    child = (child as Node).parentNode\n  }\n\n  return false\n}\n\nexport function closest(element: Node, selector: string) {\n  while (is.element(element)) {\n    if (matchesSelector(element, selector)) {\n      return element\n    }\n\n    element = parentNode(element)\n  }\n\n  return null\n}\n\nexport function parentNode(node: Node | Document) {\n  let parent = node.parentNode\n\n  if (is.docFrag(parent)) {\n    // skip past #shado-root fragments\n    // tslint:disable-next-line\n    while ((parent = (parent as any).host) && is.docFrag(parent)) {\n      continue\n    }\n\n    return parent\n  }\n\n  return parent\n}\n\nexport function matchesSelector(element: Element, selector: string) {\n  // remove /deep/ from selectors if shadowDOM polyfill is used\n  if (win.window !== win.realWindow) {\n    selector = selector.replace(/\\/deep\\//g, ' ')\n  }\n\n  return element[browser.prefixedMatchesSelector](selector)\n}\n\nconst getParent = (el: Node | Document | ShadowRoot) => el.parentNode || (el as ShadowRoot).host\n\n// Test for the element that's \"above\" all other qualifiers\nexport function indexOfDeepestElement(elements: Element[] | NodeListOf<globalThis.Element>) {\n  let deepestNodeParents: Node[] = []\n  let deepestNodeIndex: number\n\n  for (let i = 0; i < elements.length; i++) {\n    const currentNode = elements[i]\n    const deepestNode: Node = elements[deepestNodeIndex]\n\n    // node may appear in elements array multiple times\n    if (!currentNode || i === deepestNodeIndex) {\n      continue\n    }\n\n    if (!deepestNode) {\n      deepestNodeIndex = i\n      continue\n    }\n\n    const currentNodeParent = getParent(currentNode)\n    const deepestNodeParent = getParent(deepestNode)\n\n    // check if the deepest or current are document.documentElement/rootElement\n    // - if the current node is, do nothing and continue\n    if (currentNodeParent === currentNode.ownerDocument) {\n      continue\n    }\n    // - if deepest is, update with the current node and continue to next\n    else if (deepestNodeParent === currentNode.ownerDocument) {\n      deepestNodeIndex = i\n      continue\n    }\n\n    // compare zIndex of siblings\n    if (currentNodeParent === deepestNodeParent) {\n      if (zIndexIsHigherThan(currentNode, deepestNode)) {\n        deepestNodeIndex = i\n      }\n\n      continue\n    }\n\n    // populate the ancestry array for the latest deepest node\n    deepestNodeParents = deepestNodeParents.length ? deepestNodeParents : getNodeParents(deepestNode)\n\n    let ancestryStart: Node\n\n    // if the deepest node is an HTMLElement and the current node is a non root svg element\n    if (\n      deepestNode instanceof domObjects.HTMLElement &&\n      currentNode instanceof domObjects.SVGElement &&\n      !(currentNode instanceof domObjects.SVGSVGElement)\n    ) {\n      // TODO: is this check necessary? Was this for HTML elements embedded in SVG?\n      if (currentNode === deepestNodeParent) {\n        continue\n      }\n\n      ancestryStart = currentNode.ownerSVGElement\n    } else {\n      ancestryStart = currentNode\n    }\n\n    const currentNodeParents = getNodeParents(ancestryStart, deepestNode.ownerDocument)\n    let commonIndex = 0\n\n    // get (position of closest common ancestor) + 1\n    while (\n      currentNodeParents[commonIndex] &&\n      currentNodeParents[commonIndex] === deepestNodeParents[commonIndex]\n    ) {\n      commonIndex++\n    }\n\n    const parents = [\n      currentNodeParents[commonIndex - 1],\n      currentNodeParents[commonIndex],\n      deepestNodeParents[commonIndex],\n    ]\n\n    if (parents[0]) {\n      let child = parents[0].lastChild\n\n      while (child) {\n        if (child === parents[1]) {\n          deepestNodeIndex = i\n          deepestNodeParents = currentNodeParents\n\n          break\n        } else if (child === parents[2]) {\n          break\n        }\n\n        child = child.previousSibling\n      }\n    }\n  }\n\n  return deepestNodeIndex\n}\n\nfunction getNodeParents(node: Node, limit?: Node) {\n  const parents: Node[] = []\n  let parent: Node = node\n  let parentParent: Node\n\n  while ((parentParent = getParent(parent)) && parent !== limit && parentParent !== parent.ownerDocument) {\n    parents.unshift(parent)\n    parent = parentParent\n  }\n\n  return parents\n}\n\nfunction zIndexIsHigherThan(higherNode: Node, lowerNode: Node) {\n  const higherIndex = parseInt(win.getWindow(higherNode).getComputedStyle(higherNode).zIndex, 10) || 0\n  const lowerIndex = parseInt(win.getWindow(lowerNode).getComputedStyle(lowerNode).zIndex, 10) || 0\n\n  return higherIndex >= lowerIndex\n}\n\nexport function matchesUpTo(element: Element, selector: string, limit: Node) {\n  while (is.element(element)) {\n    if (matchesSelector(element, selector)) {\n      return true\n    }\n\n    element = parentNode(element) as Element\n\n    if (element === limit) {\n      return matchesSelector(element, selector)\n    }\n  }\n\n  return false\n}\n\nexport function getActualElement(element: Element) {\n  return (element as any).correspondingUseElement || element\n}\n\nexport function getScrollXY(relevantWindow?: Window) {\n  relevantWindow = relevantWindow || win.window\n  return {\n    x: relevantWindow.scrollX || relevantWindow.document.documentElement.scrollLeft,\n    y: relevantWindow.scrollY || relevantWindow.document.documentElement.scrollTop,\n  }\n}\n\nexport function getElementClientRect(element: Element): Required<Rect> {\n  const clientRect =\n    element instanceof domObjects.SVGElement ? element.getBoundingClientRect() : element.getClientRects()[0]\n\n  return (\n    clientRect && {\n      left: clientRect.left,\n      right: clientRect.right,\n      top: clientRect.top,\n      bottom: clientRect.bottom,\n      width: clientRect.width || clientRect.right - clientRect.left,\n      height: clientRect.height || clientRect.bottom - clientRect.top,\n    }\n  )\n}\n\nexport function getElementRect(element: Element) {\n  const clientRect = getElementClientRect(element)\n\n  if (!browser.isIOS7 && clientRect) {\n    const scroll = getScrollXY(win.getWindow(element))\n\n    clientRect.left += scroll.x\n    clientRect.right += scroll.x\n    clientRect.top += scroll.y\n    clientRect.bottom += scroll.y\n  }\n\n  return clientRect\n}\n\nexport function getPath(node: Node | Document) {\n  const path = []\n\n  while (node) {\n    path.push(node)\n    node = parentNode(node)\n  }\n\n  return path\n}\n\nexport function trySelector(value: Target) {\n  if (!is.string(value)) {\n    return false\n  }\n\n  // an exception will be raised if it is invalid\n  domObjects.document.querySelector(value)\n  return true\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/exchange.stub.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/utils/exchange.ts",
    "content": "export default {}\n"
  },
  {
    "path": "packages/@interactjs/utils/extend.ts",
    "content": "export default function extend<T, U extends object>(dest: U & Partial<T>, source: T): T & U {\n  for (const prop in source) {\n    ;(dest as unknown as T)[prop] = source[prop]\n  }\n\n  const ret = dest as T & U\n\n  return ret\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/getOriginXY.ts",
    "content": "import type { PerActionDefaults } from '@interactjs/core/options'\nimport type { ActionName, HasGetRect } from '@interactjs/core/types'\n\nimport { rectToXY, resolveRectLike } from './rect'\n\nexport default function getOriginXY(\n  target: HasGetRect & { options: PerActionDefaults },\n  element: Node,\n  actionName?: ActionName,\n) {\n  const actionOptions = actionName && (target.options as any)[actionName]\n  const actionOrigin = actionOptions && actionOptions.origin\n  const origin = actionOrigin || target.options.origin\n\n  const originRect = resolveRectLike(origin, target, element, [target && element])\n\n  return rectToXY(originRect) || { x: 0, y: 0 }\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/hypot.ts",
    "content": "export default (x: number, y: number) => Math.sqrt(x * x + y * y)\n"
  },
  {
    "path": "packages/@interactjs/utils/is.ts",
    "content": "import isWindow from './isWindow'\nimport * as win from './window'\n\nconst window = (thing: any): thing is Window => thing === win.window || isWindow(thing)\n\nconst docFrag = (thing: any): thing is DocumentFragment => object(thing) && thing.nodeType === 11\n\nconst object = (thing: any): thing is { [index: string]: any } => !!thing && typeof thing === 'object'\n\nconst func = (thing: any): thing is (...args: any[]) => any => typeof thing === 'function'\n\nconst number = (thing: any): thing is number => typeof thing === 'number'\n\nconst bool = (thing: any): thing is boolean => typeof thing === 'boolean'\n\nconst string = (thing: any): thing is string => typeof thing === 'string'\n\nconst element = (thing: any): thing is HTMLElement | SVGElement => {\n  if (!thing || typeof thing !== 'object') {\n    return false\n  }\n\n  const _window = win.getWindow(thing) || win.window\n\n  return /object|function/.test(typeof Element)\n    ? thing instanceof Element || thing instanceof _window.Element\n    : thing.nodeType === 1 && typeof thing.nodeName === 'string'\n}\n\nconst plainObject: typeof object = (thing: any): thing is { [index: string]: any } =>\n  object(thing) && !!thing.constructor && /function Object\\b/.test(thing.constructor.toString())\n\nconst array = <T extends unknown>(thing: any): thing is T[] =>\n  object(thing) && typeof thing.length !== 'undefined' && func(thing.splice)\n\nexport default {\n  window,\n  docFrag,\n  object,\n  func,\n  number,\n  bool,\n  string,\n  element,\n  plainObject,\n  array,\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/isNonNativeEvent.ts",
    "content": "import type { Actions } from '@interactjs/core/types'\n\nexport default function isNonNativeEvent(type: string, actions: Actions) {\n  if (actions.phaselessTypes[type]) {\n    return true\n  }\n\n  for (const name in actions.map) {\n    if (type.indexOf(name) === 0 && type.substr(name.length) in actions.phases) {\n      return true\n    }\n  }\n\n  return false\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/isWindow.ts",
    "content": "export default (thing: any) => !!(thing && thing.Window) && thing instanceof thing.Window\n"
  },
  {
    "path": "packages/@interactjs/utils/misc.ts",
    "content": "import type { ActionName, ActionProps } from '@interactjs/core/types'\n\nimport { window } from './window'\n\nexport function warnOnce<T>(this: T, method: (...args: any[]) => any, message: string) {\n  let warned = false\n\n  return function (this: T) {\n    if (!warned) {\n      ;(window as any).console.warn(message)\n      warned = true\n    }\n\n    return method.apply(this, arguments)\n  }\n}\n\nexport function copyAction<T extends ActionName>(dest: ActionProps<any>, src: ActionProps<T>) {\n  dest.name = src.name\n  dest.axis = src.axis\n  dest.edges = src.edges\n\n  return dest\n}\n\nexport const sign = (n: number) => (n >= 0 ? 1 : -1)\n"
  },
  {
    "path": "packages/@interactjs/utils/normalizeListeners.spec.ts",
    "content": "import normalizeListeners from './normalizeListeners'\n\ntest('utils/normalizeListeners', () => {\n  const a = () => {}\n  const b = () => {}\n  const c = () => {}\n\n  // single type, single listener function\n  expect(normalizeListeners('type1', a)).toEqual({\n    type1: [a],\n  })\n\n  // multiple types, single listener function\n  expect(normalizeListeners('type1 type2', a)).toEqual({\n    type1: [a],\n    type2: [a],\n  })\n\n  // array of types equivalent to space separated string\n  expect(normalizeListeners('type1 type2', a)).toEqual(normalizeListeners(['type1', 'type2'], a))\n\n  // single type, multiple listener functions\n  expect(normalizeListeners('type1', [a, b])).toEqual({\n    type1: [a, b],\n  })\n\n  // single type prefix, object of { suffix: [fn, ...] }\n  expect(normalizeListeners('prefix', { _1: [a, b], _2: [b, c] })).toEqual({\n    prefix_1: [a, b],\n    prefix_2: [b, c],\n  })\n\n  // multiple type prefixes, single length array of { suffix: [fn, ...] }\n  expect(normalizeListeners('prefix1 prefix2', [{ _1: [a, b], _2: [b, c] }])).toEqual({\n    prefix1_1: [a, b],\n    prefix1_2: [b, c],\n    prefix2_1: [a, b],\n    prefix2_2: [b, c],\n  })\n\n  // object of { suffix: [fn, ...] } as type arg\n  expect(normalizeListeners({ _1: [a, b], _2: [b, c] })).toEqual({\n    _1: [a, b],\n    _2: [b, c],\n  })\n\n  // object of { \"suffix1 suffix2\": [fn, ...], ... } as type arg\n  expect(normalizeListeners({ '_1 _2': [a, b], _3: [b, c] })).toEqual({\n    _1: [a, b],\n    _2: [a, b],\n    _3: [b, c],\n  })\n\n  // single type prefix, object of { \"suffix1 suffix2\": [fn, ...], ... }\n  expect(normalizeListeners('prefix', { '_1 _2': [a, b], _3: [b, c] })).toEqual({\n    prefix_1: [a, b],\n    prefix_2: [a, b],\n    prefix_3: [b, c],\n  })\n\n  // filter\n  expect(normalizeListeners('ignore', [{ _1: a, '': b }], (type) => !type.startsWith('ignore'))).toEqual({})\n  expect(\n    normalizeListeners(\n      { ignore: { _1: a }, ig: { nore: b }, allow: { _x: c } },\n      undefined,\n      (type) => !type.startsWith('ignore'),\n    ),\n  ).toEqual({ allow_x: [c] })\n})\n"
  },
  {
    "path": "packages/@interactjs/utils/normalizeListeners.ts",
    "content": "import type { EventTypes, Listener, ListenersArg } from '@interactjs/core/types'\n\nimport is from './is'\n\nexport interface NormalizedListeners {\n  [type: string]: Listener[]\n}\n\nexport default function normalize(\n  type: EventTypes,\n  listeners?: ListenersArg | ListenersArg[] | null,\n  filter = (_typeOrPrefix: string) => true,\n  result?: NormalizedListeners,\n): NormalizedListeners {\n  result = result || {}\n\n  if (is.string(type) && type.search(' ') !== -1) {\n    type = split(type)\n  }\n\n  if (is.array(type)) {\n    type.forEach((t) => normalize(t, listeners, filter, result))\n    return result\n  }\n\n  // before:  type = [{ drag: () => {} }], listeners = undefined\n  // after:   type = ''                  , listeners = [{ drag: () => {} }]\n  if (is.object(type)) {\n    listeners = type\n    type = ''\n  }\n\n  if (is.func(listeners) && filter(type)) {\n    result[type] = result[type] || []\n    result[type].push(listeners)\n  } else if (is.array(listeners)) {\n    for (const l of listeners) {\n      normalize(type, l, filter, result)\n    }\n  } else if (is.object(listeners)) {\n    for (const prefix in listeners) {\n      const combinedTypes = split(prefix).map((p) => `${type}${p}`)\n\n      normalize(combinedTypes, listeners[prefix], filter, result)\n    }\n  }\n\n  return result as NormalizedListeners\n}\n\nfunction split(type: string) {\n  return type.trim().split(/ +/)\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/package.json",
    "content": "{\n  \"name\": \"@interactjs/utils\",\n  \"version\": \"1.10.27\",\n  \"type\": \"module\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\",\n    \"directory\": \"packages/@interactjs/utils\"\n  },\n  \"peerDependencies\": {\n    \"@interactjs/feedback\": \"1.10.27\",\n    \"@interactjs/symbol-tree\": \"1.10.27\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"sideEffects\": false,\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/pointerExtend.ts",
    "content": "const VENDOR_PREFIXES = ['webkit', 'moz']\n\nexport default function pointerExtend<T>(dest: Partial<T & { __set?: Partial<T> }>, source: T) {\n  dest.__set ||= {} as any\n\n  for (const prop in source) {\n    // skip deprecated prefixed properties\n    if (VENDOR_PREFIXES.some((prefix) => prop.indexOf(prefix) === 0)) continue\n\n    if (typeof dest[prop] !== 'function' && prop !== '__set') {\n      Object.defineProperty(dest, prop, {\n        get() {\n          if (prop in dest.__set) return dest.__set[prop]\n\n          return (dest.__set[prop] = source[prop] as any)\n        },\n        set(value: any) {\n          dest.__set[prop] = value\n        },\n        configurable: true,\n      })\n    }\n  }\n  return dest\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/pointerUtils.ts",
    "content": "import type { InteractEvent } from '@interactjs/core/InteractEvent'\nimport type { CoordsSetMember, PointerType, Point, PointerEventType, Element } from '@interactjs/core/types'\n\nimport browser from './browser'\nimport dom from './domObjects'\nimport * as domUtils from './domUtils'\nimport hypot from './hypot'\nimport is from './is'\nimport pointerExtend from './pointerExtend'\n\nexport function copyCoords(dest: CoordsSetMember, src: CoordsSetMember) {\n  dest.page = dest.page || ({} as any)\n  dest.page.x = src.page.x\n  dest.page.y = src.page.y\n\n  dest.client = dest.client || ({} as any)\n  dest.client.x = src.client.x\n  dest.client.y = src.client.y\n\n  dest.timeStamp = src.timeStamp\n}\n\nexport function setCoordDeltas(targetObj: CoordsSetMember, prev: CoordsSetMember, cur: CoordsSetMember) {\n  targetObj.page.x = cur.page.x - prev.page.x\n  targetObj.page.y = cur.page.y - prev.page.y\n  targetObj.client.x = cur.client.x - prev.client.x\n  targetObj.client.y = cur.client.y - prev.client.y\n  targetObj.timeStamp = cur.timeStamp - prev.timeStamp\n}\n\nexport function setCoordVelocity(targetObj: CoordsSetMember, delta: CoordsSetMember) {\n  const dt = Math.max(delta.timeStamp / 1000, 0.001)\n\n  targetObj.page.x = delta.page.x / dt\n  targetObj.page.y = delta.page.y / dt\n  targetObj.client.x = delta.client.x / dt\n  targetObj.client.y = delta.client.y / dt\n  targetObj.timeStamp = dt\n}\n\nexport function setZeroCoords(targetObj: CoordsSetMember) {\n  targetObj.page.x = 0\n  targetObj.page.y = 0\n  targetObj.client.x = 0\n  targetObj.client.y = 0\n}\n\nexport function isNativePointer(pointer: any) {\n  return pointer instanceof dom.Event || pointer instanceof dom.Touch\n}\n\n// Get specified X/Y coords for mouse or event.touches[0]\nexport function getXY(type: string, pointer: PointerType | InteractEvent, xy: Point) {\n  xy = xy || ({} as Point)\n  type = type || 'page'\n\n  xy.x = pointer[(type + 'X') as 'pageX']\n  xy.y = pointer[(type + 'Y') as 'pageY']\n\n  return xy\n}\n\nexport function getPageXY(pointer: PointerType | InteractEvent, page?: Point) {\n  page = page || { x: 0, y: 0 }\n\n  // Opera Mobile handles the viewport and scrolling oddly\n  if (browser.isOperaMobile && isNativePointer(pointer)) {\n    getXY('screen', pointer, page)\n\n    page.x += window.scrollX\n    page.y += window.scrollY\n  } else {\n    getXY('page', pointer, page)\n  }\n\n  return page\n}\n\nexport function getClientXY(pointer: PointerType, client: Point) {\n  client = client || ({} as any)\n\n  if (browser.isOperaMobile && isNativePointer(pointer)) {\n    // Opera Mobile handles the viewport and scrolling oddly\n    getXY('screen', pointer, client)\n  } else {\n    getXY('client', pointer, client)\n  }\n\n  return client\n}\n\nexport function getPointerId(pointer: { pointerId?: number; identifier?: number; type?: string }) {\n  return is.number(pointer.pointerId) ? pointer.pointerId! : pointer.identifier!\n}\n\nexport function setCoords(dest: CoordsSetMember, pointers: any[], timeStamp: number) {\n  const pointer = pointers.length > 1 ? pointerAverage(pointers) : pointers[0]\n\n  getPageXY(pointer, dest.page)\n  getClientXY(pointer, dest.client)\n\n  dest.timeStamp = timeStamp\n}\n\nexport function getTouchPair(event: TouchEvent | PointerType[]) {\n  const touches: PointerType[] = []\n\n  // array of touches is supplied\n  if (is.array(event)) {\n    touches[0] = event[0]\n    touches[1] = event[1]\n  }\n  // an event\n  else {\n    if (event.type === 'touchend') {\n      if (event.touches.length === 1) {\n        touches[0] = event.touches[0]\n        touches[1] = event.changedTouches[0]\n      } else if (event.touches.length === 0) {\n        touches[0] = event.changedTouches[0]\n        touches[1] = event.changedTouches[1]\n      }\n    } else {\n      touches[0] = event.touches[0]\n      touches[1] = event.touches[1]\n    }\n  }\n\n  return touches\n}\n\nexport function pointerAverage(pointers: PointerType[]) {\n  const average = {\n    pageX: 0,\n    pageY: 0,\n    clientX: 0,\n    clientY: 0,\n    screenX: 0,\n    screenY: 0,\n  }\n\n  type CoordKeys = keyof typeof average\n\n  for (const pointer of pointers) {\n    for (const prop in average) {\n      average[prop as CoordKeys] += pointer[prop as CoordKeys]\n    }\n  }\n  for (const prop in average) {\n    average[prop as CoordKeys] /= pointers.length\n  }\n\n  return average\n}\n\nexport function touchBBox(event: PointerType[]) {\n  if (!event.length) {\n    return null\n  }\n\n  const touches = getTouchPair(event)\n  const minX = Math.min(touches[0].pageX, touches[1].pageX)\n  const minY = Math.min(touches[0].pageY, touches[1].pageY)\n  const maxX = Math.max(touches[0].pageX, touches[1].pageX)\n  const maxY = Math.max(touches[0].pageY, touches[1].pageY)\n\n  return {\n    x: minX,\n    y: minY,\n    left: minX,\n    top: minY,\n    right: maxX,\n    bottom: maxY,\n    width: maxX - minX,\n    height: maxY - minY,\n  }\n}\n\nexport function touchDistance(event: PointerType[] | TouchEvent, deltaSource: string) {\n  const sourceX = (deltaSource + 'X') as 'pageX'\n  const sourceY = (deltaSource + 'Y') as 'pageY'\n  const touches = getTouchPair(event)\n\n  const dx = touches[0][sourceX] - touches[1][sourceX]\n  const dy = touches[0][sourceY] - touches[1][sourceY]\n\n  return hypot(dx, dy)\n}\n\nexport function touchAngle(event: PointerType[] | TouchEvent, deltaSource: string) {\n  const sourceX = (deltaSource + 'X') as 'pageX'\n  const sourceY = (deltaSource + 'Y') as 'pageY'\n  const touches = getTouchPair(event)\n  const dx = touches[1][sourceX] - touches[0][sourceX]\n  const dy = touches[1][sourceY] - touches[0][sourceY]\n  const angle = (180 * Math.atan2(dy, dx)) / Math.PI\n\n  return angle\n}\n\nexport function getPointerType(pointer: { pointerType?: string; identifier?: number; type?: string }) {\n  return is.string(pointer.pointerType)\n    ? pointer.pointerType\n    : is.number(pointer.pointerType)\n      ? [undefined, undefined, 'touch', 'pen', 'mouse'][pointer.pointerType]!\n      : // if the PointerEvent API isn't available, then the \"pointer\" must\n        // be either a MouseEvent, TouchEvent, or Touch object\n        /touch/.test(pointer.type || '') || pointer instanceof dom.Touch\n        ? 'touch'\n        : 'mouse'\n}\n\n// [ event.target, event.currentTarget ]\nexport function getEventTargets(event: Event) {\n  const path = is.func(event.composedPath)\n    ? (event.composedPath() as Element[])\n    : (event as unknown as { path: Element[] }).path\n\n  return [\n    domUtils.getActualElement(path ? path[0] : (event.target as Element)),\n    domUtils.getActualElement(event.currentTarget as Element),\n  ]\n}\n\nexport function newCoords(): CoordsSetMember {\n  return {\n    page: { x: 0, y: 0 },\n    client: { x: 0, y: 0 },\n    timeStamp: 0,\n  }\n}\n\nexport function coordsToEvent(coords: MockCoords) {\n  const event = {\n    coords,\n    get page() {\n      return this.coords.page\n    },\n    get client() {\n      return this.coords.client\n    },\n    get timeStamp() {\n      return this.coords.timeStamp\n    },\n    get pageX() {\n      return this.coords.page.x\n    },\n    get pageY() {\n      return this.coords.page.y\n    },\n    get clientX() {\n      return this.coords.client.x\n    },\n    get clientY() {\n      return this.coords.client.y\n    },\n    get pointerId() {\n      return this.coords.pointerId\n    },\n    get target() {\n      return this.coords.target\n    },\n    get type() {\n      return this.coords.type\n    },\n    get pointerType() {\n      return this.coords.pointerType\n    },\n    get buttons() {\n      return this.coords.buttons\n    },\n    preventDefault() {},\n  }\n\n  return event as typeof event & PointerType & PointerEventType\n}\n\nexport interface MockCoords {\n  page: Point\n  client: Point\n  timeStamp?: number\n  pointerId?: any\n  target?: any\n  type?: string\n  pointerType?: string\n  buttons?: number\n}\n\nexport { pointerExtend }\n"
  },
  {
    "path": "packages/@interactjs/utils/raf.ts",
    "content": "let lastTime = 0\nlet request: typeof requestAnimationFrame\nlet cancel: typeof cancelAnimationFrame\n\nfunction init(global: Window | typeof globalThis) {\n  request = global.requestAnimationFrame\n  cancel = global.cancelAnimationFrame\n\n  if (!request) {\n    const vendors = ['ms', 'moz', 'webkit', 'o']\n\n    for (const vendor of vendors) {\n      request = global[`${vendor}RequestAnimationFrame` as 'requestAnimationFrame']\n      cancel =\n        global[`${vendor}CancelAnimationFrame` as 'cancelAnimationFrame'] ||\n        global[`${vendor}CancelRequestAnimationFrame` as 'cancelAnimationFrame']\n    }\n  }\n\n  request = request && request.bind(global)\n  cancel = cancel && cancel.bind(global)\n\n  if (!request) {\n    request = (callback) => {\n      const currTime = Date.now()\n      const timeToCall = Math.max(0, 16 - (currTime - lastTime))\n      const token = global.setTimeout(() => {\n        // eslint-disable-next-line n/no-callback-literal\n        callback(currTime + timeToCall)\n      }, timeToCall)\n\n      lastTime = currTime + timeToCall\n      return token as any\n    }\n\n    cancel = (token) => clearTimeout(token)\n  }\n}\n\nexport default {\n  request: (callback: FrameRequestCallback) => request(callback),\n  cancel: (token: number) => cancel(token),\n  init,\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/rect.ts",
    "content": "import type {\n  HasGetRect,\n  RectResolvable,\n  Rect,\n  Element,\n  Point,\n  FullRect,\n  EdgeOptions,\n} from '@interactjs/core/types'\n\nimport { closest, getElementRect, parentNode } from './domUtils'\nimport extend from './extend'\nimport is from './is'\n\nexport function getStringOptionResult(value: any, target: HasGetRect, element: Node) {\n  if (value === 'parent') {\n    return parentNode(element)\n  }\n\n  if (value === 'self') {\n    return target.getRect(element as Element)\n  }\n\n  return closest(element, value)\n}\n\nexport function resolveRectLike<T extends any[]>(\n  value: RectResolvable<T>,\n  target?: HasGetRect,\n  element?: Node,\n  functionArgs?: T,\n) {\n  let returnValue: any = value\n  if (is.string(returnValue)) {\n    returnValue = getStringOptionResult(returnValue, target, element)\n  } else if (is.func(returnValue)) {\n    returnValue = returnValue(...functionArgs)\n  }\n\n  if (is.element(returnValue)) {\n    returnValue = getElementRect(returnValue)\n  }\n\n  return returnValue as Rect\n}\n\nexport function toFullRect(rect: Rect): FullRect {\n  const { top, left, bottom, right } = rect\n  const width = rect.width ?? rect.right - rect.left\n  const height = rect.height ?? rect.bottom - rect.top\n\n  return { top, left, bottom, right, width, height }\n}\n\nexport function rectToXY(rect: Rect | Point) {\n  return (\n    rect && {\n      x: 'x' in rect ? rect.x : rect.left,\n      y: 'y' in rect ? rect.y : rect.top,\n    }\n  )\n}\n\nexport function xywhToTlbr<T extends Partial<Rect & Point>>(rect: T) {\n  if (rect && !('left' in rect && 'top' in rect)) {\n    rect = extend({}, rect)\n\n    rect.left = rect.x || 0\n    rect.top = rect.y || 0\n    rect.right = rect.right || rect.left + rect.width\n    rect.bottom = rect.bottom || rect.top + rect.height\n  }\n\n  return rect as Rect & T\n}\n\nexport function tlbrToXywh(rect: Rect & Partial<Point>) {\n  if (rect && !('x' in rect && 'y' in rect)) {\n    rect = extend({}, rect)\n\n    rect.x = rect.left || 0\n    rect.y = rect.top || 0\n    rect.width = rect.width || (rect.right || 0) - rect.x\n    rect.height = rect.height || (rect.bottom || 0) - rect.y\n  }\n\n  return rect as FullRect & Point\n}\n\nexport function addEdges(edges: EdgeOptions, rect: Rect, delta: Point) {\n  if (edges.left) {\n    rect.left += delta.x\n  }\n  if (edges.right) {\n    rect.right += delta.x\n  }\n  if (edges.top) {\n    rect.top += delta.y\n  }\n  if (edges.bottom) {\n    rect.bottom += delta.y\n  }\n\n  rect.width = rect.right - rect.left\n  rect.height = rect.bottom - rect.top\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/shallowEqual.ts",
    "content": "export default function shallowEqual(left: any, right: any) {\n  if (left === right) {\n    return true\n  }\n\n  if (!left || !right) {\n    return false\n  }\n\n  const leftKeys = Object.keys(left)\n\n  if (leftKeys.length !== Object.keys(right).length) {\n    return false\n  }\n\n  for (const key of leftKeys) {\n    if (left[key] !== right[key]) {\n      return false\n    }\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/@interactjs/utils/window.ts",
    "content": "import isWindow from './isWindow'\n\nexport let realWindow = undefined as Window\n\nlet win = undefined as Window\nexport { win as window }\n\nexport function init(window: Window & { wrap?: (...args: any[]) => any }) {\n  // get wrapped window if using Shadow DOM polyfill\n\n  realWindow = window\n\n  // create a TextNode\n  const el = window.document.createTextNode('')\n\n  // check if it's wrapped by a polyfill\n  if (el.ownerDocument !== window.document && typeof window.wrap === 'function' && window.wrap(el) === el) {\n    // use wrapped window\n    window = window.wrap(window)\n  }\n\n  win = window\n}\n\nif (typeof window !== 'undefined' && !!window) {\n  init(window)\n}\n\nexport function getWindow(node: any) {\n  if (isWindow(node)) {\n    return node\n  }\n\n  const rootNode = node.ownerDocument || node\n\n  return rootNode.defaultView || win.window\n}\n"
  },
  {
    "path": "packages/interactjs/.npmignore",
    "content": "*.ts\n!*.d.ts\n*.spec.ts\n*.spec.js\ndist/docs\nguide\n"
  },
  {
    "path": "packages/interactjs/LICENSE",
    "content": "Copyright (c) 2012-present Taye Adeyemi <dev@taye.me>\n\nPermission is hereby granted, free of charge, to any person \nobtaining a copy of this software and associated \ndocumentation files (the \"Software\"), to deal in the Software \nwithout restriction, including without limitation the rights \nto use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to the \nfollowing conditions:\n\nThe above copyright notice and this permission notice shall \nbe included in all copies or substantial portions of the \nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY \nKIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR \nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR \nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "packages/interactjs/README.md",
    "content": "<a href=\"http://interactjs.io\"><img alt=\"interact.js\" src=\"https://c4d6f7d727e094887e93-4ea74b676357550bd514a6a5b344c625.ssl.cf2.rackcdn.com/ijs-solid.svg\" height=\"70px\" width=\"100%\"></a>\n\n<h2>\n  JavaScript drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE9+).\n</h2>\n\n<div align=\"center\">\n<a href=\"https://gitter.im/taye/interact.js\"><img src=\"https://badges.gitter.im/taye/interact.js.svg\" alt=\"Gitter\"></a>\n<a href=\"https://www.jsdelivr.com/package/npm/interactjs\"><img src=\"https://data.jsdelivr.com/v1/package/npm/interactjs/badge\" alt=\"jsDelivr\"></a>\n<a href=\"https://travis-ci.com/taye/interact.js\"><img src=\"https://travis-ci.com/taye/interact.js.svg?branch=main\" alt=\"Build Status\"></a>\n<a href=\"https://codeclimate.com/github/taye/interact.js/test_coverage\"><img src=\"https://api.codeclimate.com/v1/badges/0168aeaeed781a949088/test_coverage\"/></a>\n</div>\n<br>\n\nFeatures include:\n\n - **inertia** and **snapping**\n - **multi-touch**, simultaneous interactions\n - cross browser and device, supporting the **desktop and mobile** versions of\n   Chrome, Firefox and Opera as well as **Internet Explorer 9+**\n - interaction with [**SVG**](http://interactjs.io/#use_in_svg_files) elements\n - being **standalone and customizable**\n - **not modifying the DOM** except to change the cursor (but you can disable\n   that)\n\nInstallation\n------------\n\n* [npm](https://www.npmjs.org/): `npm install interactjs`\n* [jsDelivr CDN](https://cdn.jsdelivr.net/npm/interactjs/): `<script src=\"https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js\"></script>`\n* [unpkg CDN](https://unpkg.com/interactjs/): `<script src=\"https://unpkg.com/interactjs/dist/interact.min.js\"></script>`\n* [Rails 5.1+](https://rubyonrails.org/):\n  1. `yarn add interactjs`\n  2. `//= require interactjs/interact`\n* [Webjars SBT/Play 2](https://www.webjars.org/): `libraryDependencies ++= Seq(\"org.webjars.npm\" % \"interactjs\" % version)`\n\n### Typescript definitions\n\nThe project is written in Typescript and the npm package includes the type\ndefinitions, but if you need the typings alone, you can install them with:\n\n```\nnpm install --save-dev @interactjs/types\n```\n\nDocumentation\n-------------\n\nhttp://interactjs.io/docs\n\nExample\n-------\n\n```javascript\nvar pixelSize = 16;\n\ninteract('.rainbow-pixel-canvas')\n  .origin('self')\n  .draggable({\n    modifiers: [\n      interact.modifiers.snap({\n        // snap to the corners of a grid\n        targets: [\n          interact.snappers.grid({ x: pixelSize, y: pixelSize }),\n        ],\n      })\n    ],\n    listeners: {\n      // draw colored squares on move\n      move: function (event) {\n        var context = event.target.getContext('2d'),\n            // calculate the angle of the drag direction\n            dragAngle = 180 * Math.atan2(event.dx, event.dy) / Math.PI;\n\n        // set color based on drag angle and speed\n        context.fillStyle = 'hsl(' + dragAngle + ', 86%, '\n                            + (30 + Math.min(event.speed / 1000, 1) * 50) + '%)';\n\n        // draw squares\n        context.fillRect(event.pageX - pixelSize / 2, event.pageY - pixelSize / 2,\n                         pixelSize, pixelSize);\n      }\n    }\n  })\n  // clear the canvas on doubletap\n  .on('doubletap', function (event) {\n    var context = event.target.getContext('2d');\n\n    context.clearRect(0, 0, context.canvas.width, context.canvas.height);\n  });\n\n  function resizeCanvases () {\n    [].forEach.call(document.querySelectorAll('.rainbow-pixel-canvas'), function (canvas) {\n      canvas.width = document.body.clientWidth;\n      canvas.height = window.innerHeight * 0.7;\n    });\n  }\n\n  // interact.js can also add DOM event listeners\n  interact(document).on('DOMContentLoaded', resizeCanvases);\n  interact(window).on('resize', resizeCanvases);\n```\n\nSee the above code in action at https://codepen.io/taye/pen/tCKAm\n\nLicense\n-------\n\ninteract.js is released under the [MIT License](http://taye.mit-license.org).\n\n[ijs-twitter]: https://twitter.com/interactjs\n[upcoming-changes]: https://github.com/taye/interact.js/blob/main/CHANGELOG.md#upcoming-changes\n"
  },
  {
    "path": "packages/interactjs/bower.json",
    "content": "{\n  \"name\": \"interactjs\",\n  \"main\": \"index.js\",\n  \"license\": \"SEE LICENSE AT https://interactjs.io/license\",\n  \"description\": \"Drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE9+)\",\n  \"homepage\": \"http://interactjs.io\",\n  \"authors\": [\n    {\n      \"name\": \"Taye Adeyemi\",\n      \"email\": \"dev@taye.me\",\n      \"url\": \"http://taye.me\"\n    }\n  ],\n  \"keywords\": [\n    \"interact.js\",\n    \"draggable\",\n    \"droppable\",\n    \"drag\",\n    \"drop\",\n    \"drag and drop\",\n    \"resize\",\n    \"touch\",\n    \"multi-touch\",\n    \"gesture\",\n    \"snap\",\n    \"inertia\",\n    \"grid\",\n    \"autoscroll\",\n    \"SVG\"\n  ],\n  \"moduleType\": [\n    \"amd\",\n    \"globals\",\n    \"node\"\n  ],\n  \"ignore\": [\n    \"/*\",\n    \"!src\",\n    \"!dist\",\n    \"!LICENSE\"\n  ]\n}\n"
  },
  {
    "path": "packages/interactjs/index.ts",
    "content": "// eslint-disable-next-line import/no-extraneous-dependencies\nimport interact from '@interactjs/interactjs'\n\nexport default interact\n\nif (typeof module === 'object' && !!module) {\n  try {\n    module.exports = interact\n  } catch {}\n}\n\n;(interact as any).default = interact\n"
  },
  {
    "path": "packages/interactjs/package.json",
    "content": "{\n  \"name\": \"interactjs\",\n  \"version\": \"1.10.27\",\n  \"main\": \"dist/interact.min.js\",\n  \"typings\": \"index.d.ts\",\n  \"description\": \"Drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE9+)\",\n  \"homepage\": \"https://interactjs.io\",\n  \"authors\": [\n    {\n      \"name\": \"Taye Adeyemi\",\n      \"email\": \"dev@taye.me\",\n      \"url\": \"https://taye.me\"\n    }\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/taye/interact.js.git\"\n  },\n  \"keywords\": [\n    \"interact.js\",\n    \"draggable\",\n    \"droppable\",\n    \"drag\",\n    \"drop\",\n    \"drag and drop\",\n    \"resize\",\n    \"touch\",\n    \"multi-touch\",\n    \"gesture\",\n    \"snap\",\n    \"inertia\",\n    \"grid\",\n    \"autoscroll\",\n    \"SVG\",\n    \"interact\"\n  ],\n  \"scripts\": {\n    \"test\": \"cd ../; npm test\"\n  },\n  \"dependencies\": {\n    \"@interactjs/types\": \"1.10.27\"\n  },\n  \"sideEffects\": [\n    \"**/index.js\",\n    \"**/index.prod.js\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "scripts/.eslintrc.cjs",
    "content": "module.exports = {\n  extends: '../.eslintrc.cjs',\n  parserOptions: { sourceType: 'script', ecmaVersion: 2018 },\n  rules: { 'import/no-extraneous-dependencies': 'off' },\n}\n"
  },
  {
    "path": "scripts/addPluginIndexes.js",
    "content": "const fs = require('fs').promises\nconst path = require('path')\n\nconst { mkdirp } = require('mkdirp')\n\nmodule.exports = (plugins) => {\n  return Promise.all(\n    plugins.map(async (modulePath) => {\n      const [scopePath] = modulePath.split('/')\n      const packagePath = path.join('packages', '@interactjs', scopePath)\n      const pluginPath = path.join('packages', '@interactjs', modulePath)\n      const dest = path.join(packagePath, path.dirname(path.relative(packagePath, pluginPath)), 'index.ts')\n      const destDir = path.dirname(dest)\n\n      const pluginSpecifier = pluginPath.replace(/^packages./, '')\n\n      await mkdirp(destDir)\n\n      await fs.writeFile(\n        dest,\n        [\n          '/* eslint-disable no-console, eol-last, import/no-duplicates,  import/no-extraneous-dependencies, import/order */',\n          `import '${pluginSpecifier}'`,\n          \"import interact from '@interactjs/interact/index'\",\n          `import plugin from '${pluginSpecifier}'`,\n          'interact.use(plugin)',\n        ].join('\\n'),\n      )\n\n      console.log(`wrote ${dest}`)\n    }),\n  )\n}\n"
  },
  {
    "path": "scripts/babel/absolute-imports.js",
    "content": "const path = require('path')\n\nconst resolveSync = require('resolve').sync\n\nconst { getModuleDirectories, shouldIgnoreImport, getRelativeToRoot } = require('../utils')\n\nmodule.exports = function transformImportsToAbsolute() {\n  const fixImportSource = ({ node: { source } }, { opts, filename }) => {\n    if (!source || (opts.ignore && opts.ignore(filename, source.value))) return\n\n    const { moduleDirectory = getModuleDirectories() } = opts\n\n    if (shouldIgnoreImport(source.value)) return\n\n    const { extension = '', prefix } = opts\n    const basedir = path.dirname(filename)\n\n    let resolvedImport = ''\n\n    resolvedImport = resolveSync(source.value, {\n      extensions: ['.ts', '.tsx', '.js'],\n      basedir,\n      moduleDirectory,\n    })\n\n    try {\n      const unrootedImport = getRelativeToRoot(resolvedImport, moduleDirectory, prefix).result\n\n      source.value = extension === null ? unrootedImport : unrootedImport.replace(/\\.[jt]sx?$/, extension)\n    } catch (error) {\n      source.value = resolveSync(source.value, {\n        basedir,\n        moduleDirectory,\n      })\n    }\n  }\n\n  return {\n    name: '@interactjs/_dev:absolute-imports',\n    visitor: {\n      ImportDeclaration: fixImportSource,\n      ExportNamedDeclaration: fixImportSource,\n    },\n  }\n}\n"
  },
  {
    "path": "scripts/babel/inline-env-vars.js",
    "content": "module.exports = function transformInlineEnvironmentVariables({ types: t }) {\n  return {\n    name: '@interactjs/_dev:inline-env-vars',\n    visitor: {\n      // eslint-disable-next-line no-shadow\n      MemberExpression(path, { opts: { include, exclude, env } = {} }) {\n        if (path.get('object').matchesPattern('process.env')) {\n          const key = path.toComputedKey()\n          if (\n            t.isStringLiteral(key) &&\n            (!include || include.indexOf(key.value) !== -1) &&\n            (!exclude || exclude.indexOf(key.value) === -1)\n          ) {\n            const name = key.value\n            const value = env && name in env ? env[name] : process.env[name]\n            path.replaceWith(t.valueToNode(value))\n          }\n        }\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "scripts/babel/relative-imports.js",
    "content": "const path = require('path')\n\nconst resolveSync = require('resolve').sync\n\nconst { getModuleDirectories, shouldIgnoreImport, getRelativeToRoot } = require('../utils')\n\nmodule.exports = function transformImportsToRelative() {\n  const fixImportSource = ({ node: { source } }, { opts, filename }) => {\n    if (!source || (opts.ignore && opts.ignore(filename))) return\n\n    const { moduleDirectory = getModuleDirectories() } = opts\n\n    if (shouldIgnoreImport(source.value, filename, moduleDirectory)) return\n\n    const { extension = '.js' } = opts\n\n    const basedir = path.dirname(getRelativeToRoot(filename, moduleDirectory).result)\n    let resolvedImport = ''\n\n    for (const root of moduleDirectory) {\n      try {\n        resolvedImport = resolveSync(source.value, {\n          extensions: ['.ts', '.tsx'],\n          basedir: path.join(root, basedir),\n          moduleDirectory,\n        })\n        break\n      } catch {}\n    }\n\n    if (!resolvedImport) {\n      throw new Error(`Couldn't find module \"${source.value}\" from \"${filename}\"`)\n    }\n\n    const relativeImport = path.relative(basedir, getRelativeToRoot(resolvedImport, moduleDirectory).result)\n\n    const importWithDir = /^[./\\\\]/.test(relativeImport) ? relativeImport : `${path.sep}${relativeImport}`\n\n    source.value = importWithDir.replace(/^\\//, `.${path.sep}`).replace(/\\.tsx?$/, extension)\n  }\n\n  return {\n    name: '@interactjs/_dev:relative-imports',\n    visitor: {\n      ImportDeclaration: fixImportSource,\n      ExportNamedDeclaration: fixImportSource,\n      ExportAllDeclaration: fixImportSource,\n    },\n  }\n}\n"
  },
  {
    "path": "scripts/babel/vue-sfc.js",
    "content": "const { parse, compileScript, compileStyle } = require('@vue/compiler-sfc')\nconst hash = require('hash-sum')\n\nmodule.exports = function transformVueSfc() {\n  return {\n    name: '@interactjs/_dev:vue-sfc',\n    parserOverride(source, options, babelParse) {\n      const { sourceFileName, filename = sourceFileName } = options\n\n      if (!filename?.endsWith('.vue')) return\n\n      const { code, map } = compileSfc(source, { filename, isProd: true })\n      const newFilename = filename + '.ts'\n\n      return babelParse(code, {\n        ...options,\n        inputSourceMap: map,\n        sourceFileName: newFilename,\n        filename: newFilename,\n      })\n    },\n  }\n}\n\nfunction compileSfc(source, { filename, isProd = true }) {\n  const id = hash([filename, source].join('\\0'))\n  const { descriptor: sfc, errors: parseErrors } = parse(source, {\n    filename,\n    sourceMap: !isProd,\n  })\n\n  if (parseErrors.length) throw parseErrors\n\n  const script = compileScript(sfc, { id, inlineTemplate: true, isProd })\n  const styles = sfc.styles.map((style) =>\n    compileStyle({\n      source: style.content,\n      filename,\n      id,\n      scoped: style.attrs.scoped,\n      isProd,\n    }),\n  )\n\n  return {\n    code: `${script.content}\\n;${getStyleStatement(styles)}`,\n    map: script.map,\n  }\n}\n\nfunction getStyleStatement(styles) {\n  if (!styles.length) return ''\n\n  const css = styles.map((style) => style.code).join('\\n')\n  // TODO: minify CSS\n  const html = `<style>${css}</style>`\n\n  return ['document.head.insertAdjacentHTML(', '\"beforeEnd\",', JSON.stringify(html), ')'].join('')\n}\n\nmodule.exports.compileSfc = compileSfc\n"
  },
  {
    "path": "scripts/bin/_check_deps.js",
    "content": "const fs = require('fs/promises')\n\nconst { getPackageJsons, errorExit } = require('../utils')\n\nasync function checkDeps () {\n  const packageJsons = await getPackageJsons()\n  const pkgNames = new Set(packageJsons.map(([, pkg]) => pkg.name))\n\n  Promise.all(\n    packageJsons.map(async ([p, pkg]) => {\n      for (const depField of ['dependencies', 'peerDependencies', 'devDependencies']) {\n        const missingDeps = Object.keys(pkg[depField] || {}).filter(\n          (depName) => depName.startsWith('@interactjs/') && !pkgNames.has(depName),\n        )\n\n        for (const depName of missingDeps) {\n          delete pkg[depField][depName]\n          console.warn(`tidying ${pkg.name} ${depField} ✕ ${depName}`)\n        }\n      }\n\n      await fs.writeFile(p, JSON.stringify(pkg, null, 2) + '\\n')\n    }),\n  )\n}\n\ncheckDeps().catch(errorExit)\n"
  },
  {
    "path": "scripts/bin/add_plugin_indexes.js",
    "content": "const { isPro } = require('../utils')\n\nrequire('../addPluginIndexes')([\n  'actions/plugin',\n  'actions/drag/plugin',\n  'actions/drop/plugin',\n  'actions/resize/plugin',\n  'actions/gesture/plugin',\n  'auto-scroll/plugin',\n  'auto-start/plugin',\n  'dev-tools/plugin',\n  'inertia/plugin',\n  'modifiers/plugin',\n  'pointer-events/plugin',\n  'reflow/plugin',\n  'snappers/plugin',\n  ...(isPro\n    ? [\n      'react/plugin',\n      'vue/plugin',\n      'multi-target/plugin',\n      'feedback/plugin',\n      'clone/plugin',\n      'arrange/plugin',\n      'iframes/plugin',\n    ]\n    : []),\n])\n"
  },
  {
    "path": "scripts/bin/bundle.js",
    "content": "const path = require('path')\n\nconst bundler = require('../bundler')\nconst headers = require('../headers')\nconst { errorExit } = require('../utils')\n\nconst [, , entry = 'packages/interactjs', name = 'interact'] = process.argv\nconst entryPkgDir = path.join(process.cwd(), entry)\n\nconst options = {\n  headers,\n  entry: path.join(entryPkgDir, 'index.ts'),\n  destDir: path.join(entryPkgDir, 'dist'),\n  name,\n}\n\nprocess.stdout.write('Bundling...')\n\nbundler(options)\n  .then(async (code) => console.log(' done.'))\n  .catch(errorExit)\n"
  },
  {
    "path": "scripts/bin/clean.js",
    "content": "const fs = require('fs')\nconst path = require('path')\n\nconst shell = require('shelljs')\n\nconst { getBuiltJsFiles } = require('../utils')\n\nconsole.log('removing typescript generated files.')\nshell.exec('tsc -b types.tsconfig.json --clean')\n\nPromise.all([getBuiltJsFiles(), import('del').then((m) => m.deleteAsync)]).then(async ([filenames, del]) => {\n  console.log(`removing ${filenames.length} generated files and directories.`)\n\n  await Promise.all(\n    filenames.map((filename) => {\n      return del(filename)\n    }),\n  )\n\n  // remove empty directories\n  const directories = [...new Set(filenames.map(path.dirname))].sort().reverse()\n\n  for (const dir of directories) {\n    const files = await fs.promises.readdir(dir)\n\n    if (!files.length) {\n      await del(dir)\n    }\n  }\n})\n"
  },
  {
    "path": "scripts/bin/lint.js",
    "content": "const { existsSync, promises: fs } = require('fs')\n\nconst { ESLint } = require('eslint')\nconst { glob } = require('glob')\nconst prettier = require('prettier')\nconst yargs = require('yargs')\n\nconst { lintSourcesGlob, lintIgnoreGlobs, errorExit } = require('../utils')\n\nconst { fix, _: fileArgs } = yargs.boolean('fix').argv\nconst jsExt = /\\.js$/\nconst dtsExt = /\\.d\\.ts$/\n\nmain().catch(errorExit)\n\nasync function main() {\n  const sources = fileArgs.length ? fileArgs : await getSources()\n\n  console.log(`Linting ${sources.length} 'file${sources.length === 1 ? '' : 's'}...`)\n\n  if (fix) {\n    await Promise.all(sources.map(formatWithPrettier))\n  }\n\n  const eslint = new ESLint({\n    fix,\n    useEslintrc: true,\n  })\n  const results = await eslint.lintFiles(sources)\n  const formatter = await eslint.loadFormatter('stylish')\n\n  if (fix) {\n    await ESLint.outputFixes(results)\n  }\n\n  console.log(formatter.format(results))\n\n  const hasUnfixedError = results.some((r) => r.errorCount > (fix ? r.fixableErrorCount : 0))\n\n  if (hasUnfixedError) {\n    throw new Error('unfixed errors remain')\n  }\n}\n\nasync function formatWithPrettier(filepath) {\n  const [source, config] = await Promise.all([\n    fs.readFile(filepath).then((buffer) => buffer.toString()),\n    prettier.resolveConfig(filepath),\n  ])\n  const output = await prettier.format(source, { ...config, filepath })\n\n  if (source !== output) await fs.writeFile(filepath, output)\n}\n\nasync function getSources() {\n  const sources = await glob(lintSourcesGlob, {\n    ignore: lintIgnoreGlobs,\n    silent: true,\n  })\n\n  return sources.filter((source) => !isGenerated(source))\n}\n\nfunction isGenerated(source) {\n  return (\n    (dtsExt.test(source) && existsSync(source.replace(dtsExt, '.ts'))) ||\n    (jsExt.test(source) && existsSync(source.replace(jsExt, '.ts')))\n  )\n}\n"
  },
  {
    "path": "scripts/bin/release.js",
    "content": "const fs = require('fs').promises\nconst path = require('path')\n\nconst shell = require('shelljs')\n\nconst { getPackages, isPro, registryUrl, errorExit } = require('../utils')\n\nconst cwd = process.cwd()\n\nprocess.env.PATH = `${cwd}/bin:${cwd}/node_modules/.bin:${process.env.PATH}`\n\nshell.config.verbose = true\nshell.config.fatal = true\n\nensureCleanIndex()\n\nconst { gitTag } = checkVersion()\nlet packages\n\nmain().catch(errorExit)\n\nasync function main(ps) {\n  configGitUser()\n  gitDetatch()\n\n  clean()\n\n  packages = await getPackages()\n\n  await runBuild()\n\n  await commit()\n  await pushAndPublish()\n}\n\nfunction configGitUser() {\n  shell.exec('git config user.name \"CI\"')\n  shell.exec('git config user.email \"<>\"')\n}\n\nfunction ensureCleanIndex() {\n  // make sure the repo is clean\n  try {\n    shell.exec('git diff-index -G . HEAD --stat --exit-code')\n  } catch {\n    throw new Error('working directory must be clean')\n  }\n}\n\nfunction checkVersion() {\n  const getVersion = require('../getVersion')\n  const version = require('semver').clean(getVersion())\n\n  if (!version) {\n    throw new Error('failed to parse version')\n  }\n\n  return {\n    version,\n    gitTag: 'v' + version,\n  }\n}\n\nfunction gitDetatch() {\n  shell.exec('git checkout --detach')\n}\n\nfunction clean() {\n  shell.exec('_clean')\n}\n\nasync function runBuild() {\n  // copy README to interactjs package\n  await Promise.all(\n    packages\n      .filter((p) => p.endsWith('interactjs'))\n      .map((p) => fs.copyFile(`${cwd}/README.md`, `${p}/README.md`)),\n  )\n\n  // copy license file and npmignore to all packages\n  const licenseFilename = isPro ? 'LICENSE.md' : 'LICENSE'\n  await Promise.all(\n    packages.map(async (pkg) => {\n      await fs.copyFile(licenseFilename, path.join(pkg, licenseFilename))\n      await fs.copyFile('.npmignore', path.join(pkg, '.npmignore'))\n    }),\n  )\n\n  if (isPro) await fs.rm(path.resolve('LICENSE'))\n\n  // clean up scope deps\n  shell.exec('npx _check_deps')\n\n  if (!isPro) {\n    // bundle interactjs\n    shell.exec('npm run build:bundle')\n    // ensure that the output is valid ES5 syntax\n    shell.exec('acorn --silent --ecma5 packages/interactjs/dist/*.js')\n\n    // generate docs\n    shell.exec('npm run build:docs')\n  }\n\n  // create @interactjs/**/use/* modules\n  shell.exec('npx _add_plugin_indexes')\n\n  // generate types\n  shell.exec('npx _types')\n\n  // generate esnext .js modules\n  shell.exec('rollup -c esnext.rollup.config.cjs')\n  // ensure that the output is valid ES2018 syntax\n  shell.exec('acorn --silent --module --ecma2018 packages/**/*.js')\n\n  // set publishConfig\n  await editPackageJsons((pkg) => {\n    pkg.publishConfig = isPro ? { access: 'restricted', registry: registryUrl } : { access: 'public' }\n  })\n}\n\nfunction commit() {\n  // commit and add new version tag\n  shell.exec('git add --all .')\n  shell.exec('git add --force packages')\n  if (!isPro) shell.exec('git add --force dist/api')\n  shell.exec('git reset **/node_modules')\n  shell.exec(`git commit --no-verify -m ${gitTag}`)\n}\n\nasync function pushAndPublish() {\n  const { NPM_TAG } = process.env\n\n  try {\n    shell.exec(`git push --no-verify origin HEAD:refs/tags/${gitTag}`)\n  } catch {\n    throw new Error(`failed to push git tag ${gitTag} to origin`)\n  }\n\n  const gitHead = shell.exec('git rev-parse --short HEAD').trim()\n  await editPackageJsons((pkg) => {\n    pkg.gitHead = gitHead\n  })\n\n  const { deleteAsync } = await import('del')\n  if (isPro) await deleteAsync('packages/**/*.map')\n\n  const npmPublishCommand = 'npm publish' + (NPM_TAG ? ` --tag ${NPM_TAG}` : '')\n  const packagesToPublish = isPro ? packages.filter((p) => /@interactjs\\//.test(p)) : packages\n\n  for (const pkg of packagesToPublish) {\n    shell.exec(npmPublishCommand, { cwd: path.resolve(pkg) })\n  }\n\n  shell.exec('git checkout $(git ls-files \"**package.json\")')\n}\n\nasync function editPackageJsons(func) {\n  await Promise.all(\n    ['.', ...packages].map(async (packageDir) => {\n      const file = path.resolve(packageDir, 'package.json')\n      const pkg = JSON.parse((await fs.readFile(file)).toString())\n\n      func(pkg)\n\n      await fs.writeFile(file, `${JSON.stringify(pkg, null, 2)}\\n`)\n    }),\n  )\n}\n"
  },
  {
    "path": "scripts/bin/types.js",
    "content": "const path = require('path')\n\nconst shell = require('shelljs')\n\nconst execTypes = require('../execTypes')\nconst { errorExit } = require('../utils')\n\nshell.config.verbose = true\nshell.config.fatal = true\n\nconst typesDir = '@interactjs/types'\n\n;(async () => {\n  const modulesDir = path.resolve('packages')\n\n  execTypes.modular(modulesDir)\n  await execTypes.combined(path.join(modulesDir, typesDir))\n})().catch(errorExit)\n"
  },
  {
    "path": "scripts/bin/version.js",
    "content": "const fs = require('fs')\nconst path = require('path')\n\nconst { glob } = require('glob')\nconst semver = require('semver')\n\nconst getVersion = require('../getVersion')\n\nlet [, , cwd, versionChange, prereleaseId] = process.argv\n\nif (cwd === undefined || !cwd.startsWith('/')) {\n  ;[cwd, versionChange, prereleaseId] = [process.cwd(), cwd, versionChange]\n}\n\nconst depFields = ['dependencies', 'peerDependencies', 'devDependencies', 'optionalDependencies']\n\nlet currentVersion\n\nconst previousVersion = getVersion(cwd)\n\nif (versionChange) {\n  if (/^(major|minor|patch|premajor|preminor|prepatch|prerelease)$/.test(versionChange)) {\n    currentVersion = semver.inc(previousVersion, versionChange, prereleaseId)\n  } else {\n    currentVersion = semver.clean(versionChange)\n\n    if (currentVersion === null) {\n      throw Error(`Invalid version change \"${previousVersion}\" -> \"${versionChange}\"`)\n    }\n  }\n\n  const versionTable = []\n\n  for (const file of [\n    'package.json',\n    ...glob.sync('packages/{@interactjs/*,interactjs}/package.json', { cwd }),\n  ]) {\n    const pkg = require(path.resolve(file))\n\n    versionTable.push({ package: pkg.name, old: pkg.version, new: currentVersion })\n\n    pkg.version = currentVersion\n\n    for (const deps of depFields.map((f) => pkg[f]).filter(Boolean)) {\n      for (const name of Object.keys(deps).filter((n) => /@?interactjs\\//.test(n))) {\n        if (deps[name] === previousVersion) {\n          deps[name] = currentVersion\n        } else {\n          console.warn(`${file}: not updating \"${name}\" from \"${deps[name]}\"`)\n        }\n      }\n    }\n\n    fs.writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\\n`)\n  }\n\n  console.table(versionTable)\n}\n// if this was run with no arguments, get the current version\nelse {\n  currentVersion = previousVersion\n  console.log(currentVersion)\n}\n"
  },
  {
    "path": "scripts/execTypes.js",
    "content": "const fs = require('fs')\nconst path = require('path')\n\nconst shell = require('shelljs')\n\nmodule.exports = {\n  modular(modulesDir) {\n    shell.exec(`npx tsc -p types.tsconfig.json --outDir ${modulesDir}/@interactjs`)\n  },\n  async combined(outDir) {\n    const outFile = path.join(outDir, 'index.d.ts')\n\n    // await del(path.join(typesOutDir, outBasename))\n    shell.exec(`npx tsc -p types.tsconfig.json --rootDir packages --outFile ${outFile}`)\n\n    const namespaceDeclaration = `\nimport * as Interact from '@interactjs/types/index'\n\nexport as namespace Interact\nexport = Interact\n`.trimStart()\n\n    await fs.promises.writeFile(path.join(outDir, 'typings.d.ts'), namespaceDeclaration)\n  },\n}\n"
  },
  {
    "path": "scripts/getVersion.js",
    "content": "const path = require('path')\n\nmodule.exports = (cwd = process.cwd()) => {\n  const rootPkg = require(path.resolve(cwd, 'package.json'))\n\n  return rootPkg.version\n}\n"
  },
  {
    "path": "scripts/headers.js",
    "content": "const version = require('../scripts/getVersion')()\n\nmodule.exports =\n  process.env.INTERACTJS_TIER === 'pro'\n    ? {\n        raw: `/**\n * interact.js ${version}\n *\n * Copyright (c) 2012-present Taye Adeyemi <dev@taye.me>\n * https://interactjs.io/license\n */\\n`,\n        min: `/* interact.js ${version} | https://interactjs.io/license */\\n`,\n      }\n    : {\n        raw: `/**\n * interact.js ${version}\n *\n * Copyright (c) 2012-present Taye Adeyemi <dev@taye.me>\n * Released under the MIT License.\n * https://raw.github.com/taye/interact.js/main/LICENSE\n */\\n`,\n        min: `/* interact.js ${version} | https://raw.github.com/taye/interact.js/main/LICENSE */\\n`,\n      }\n"
  },
  {
    "path": "scripts/utils.js",
    "content": "const fs = require('fs')\nconst path = require('path')\n\nconst { glob } = require('glob')\nconst resolveSync = require('resolve').sync\n\nconst sourcesGlob = 'packages/{,@}interactjs/**/**/*{.ts,.tsx,.vue}'\nconst lintSourcesGlob = `{${sourcesGlob},{scripts,examples,docs}/**/*.{js,cjs,md},bin/**/*}`\nconst commonIgnoreGlobs = ['**/node_modules/**', '**/*_*', '**/*.d.ts', '**/dist/**', 'examples/js/**']\nconst lintIgnoreGlobs = [...commonIgnoreGlobs]\nconst sourcesIgnoreGlobs = [...commonIgnoreGlobs, '**/*.spec.ts']\nconst builtFilesGlob =\n  '{{**/dist/**,packages/{,@}interactjs/**/**/*.js{,.map}},packages/@interactjs/**/index.ts}'\nconst builtFilesIgnoreGlobs = [\n  '**/node_modules/**',\n  'packages/@interactjs/{dev-tools/babel-plugin-prod.js,{types,interact,interactjs,rebound}/index.ts}',\n]\n\nconst getSources = ({ cwd = process.cwd(), ...options } = {}) =>\n  glob(sourcesGlob, {\n    cwd,\n    ignore: sourcesIgnoreGlobs,\n    strict: false,\n    nodir: true,\n    absolute: true,\n    ...options,\n  })\n\nconst getBuiltJsFiles = ({ cwd = process.cwd() } = {}) =>\n  glob(builtFilesGlob, {\n    cwd,\n    ignore: builtFilesIgnoreGlobs,\n    strict: false,\n    nodir: true,\n  })\n\nfunction getEsnextBabelOptions(presetEnvOptions) {\n  return {\n    babelrc: false,\n    configFile: false,\n    sourceMaps: true,\n    presets: [\n      [\n        require.resolve('@babel/preset-env'),\n        {\n          shippedProposals: true,\n          ...presetEnvOptions,\n        },\n      ],\n      [\n        require.resolve('@babel/preset-typescript'),\n        { isTSX: false, onlyRemoveTypeImports: true, allExtensions: true, allowDeclareFields: true },\n      ],\n    ],\n    plugins: [\n      require.resolve('./babel/vue-sfc'),\n      require.resolve('@babel/plugin-proposal-optional-catch-binding'),\n      require.resolve('@babel/plugin-proposal-optional-chaining'),\n      require.resolve('@babel/plugin-transform-nullish-coalescing-operator'),\n      require.resolve('@babel/plugin-transform-logical-assignment-operators'),\n    ],\n    assumptions: {\n      iterableIsArray: true,\n      noDocumentAll: true,\n      noNewArrows: true,\n      setPublicClassFields: true,\n    },\n  }\n}\n\nfunction getDevPackageDir() {\n  return path.join(__dirname, '..')\n}\n\nfunction getModuleName(tsName) {\n  return tsName.replace(/\\.[jt]sx?$/, '')\n}\n\nfunction getModuleDirectories() {\n  return [path.join(__dirname, '..', 'packages'), path.join(process.cwd(), 'node_modules')]\n}\n\nasync function getPackages(options) {\n  const packageJsonPaths = await glob('packages/{@interactjs/*,interactjs}/package.json', {\n    ignore: commonIgnoreGlobs,\n    ...options,\n  })\n  const packageDirs = packageJsonPaths.map(path.dirname)\n\n  return [...new Set(packageDirs)].sort()\n}\n\nasync function getPackageJsons(packages = getPackages()) {\n  return Promise.all(\n    (await packages).map(async (p) => {\n      const jsonPath = path.resolve(p, 'package.json')\n      const pkg = JSON.parse((await fs.promises.readFile(jsonPath)).toString())\n      return [jsonPath, pkg]\n    }),\n  )\n}\n\nfunction shouldIgnoreImport(sourceValue) {\n  return !/^(\\.{1-2}|(@interactjs))[\\\\/]/.test(sourceValue)\n}\n\nconst isPro = process.env.INTERACTJS_TIER === 'pro'\nconst registryUrl = isPro ? 'https://registry.interactjs.io' : undefined\n\nfunction extendBabelOptions(\n  { ignore = [], plugins = [], presets = [], ...others },\n  base = getEsnextBabelOptions(),\n) {\n  return {\n    ...base,\n    ...others,\n    ignore: [...(base.ignore || []), ...ignore],\n    presets: [...(base.presets || []), ...presets],\n    plugins: [...(base.plugins || []), ...plugins],\n  }\n}\n\nfunction getPackageDir(filename) {\n  let packageDir = filename\n\n  while (!fs.existsSync(path.join(packageDir, 'package.json'))) {\n    packageDir = path.dirname(packageDir)\n\n    if (packageDir === path.sep) {\n      throw new Error(`Couldn't find a package for ${filename}`)\n    }\n  }\n\n  return packageDir\n}\n\nfunction getRelativeToRoot(filename, moduleDirectory, prefix = '/') {\n  filename = path.normalize(filename)\n\n  const ret = withBestRoot((root) => {\n    const valid = filename.startsWith(root)\n    const result = valid && path.join(prefix, path.relative(root, filename))\n    const priority = valid && -result.length\n\n    return { valid, result, priority }\n  }, moduleDirectory)\n\n  if (!ret.result) {\n    throw new Error(`Couldn't find module ${filename} in ${moduleDirectory.join(' or')}.`)\n  }\n\n  return ret\n}\n\n/**\n * use the result of `func` most shallow valid root\n */\nfunction withBestRoot(func, moduleDirectory) {\n  const roots = moduleDirectory.map(path.normalize)\n\n  return (\n    roots.reduce((best, root) => {\n      const { result, valid, priority } = func(root)\n\n      if (!valid) {\n        return best\n      }\n\n      if (!best || priority > best.priority) {\n        return { result, priority, root }\n      }\n\n      return best\n    }, null) || {}\n  )\n}\n\nfunction resolveImport(specifier, basedir, moduleDirectory) {\n  if (specifier.startsWith('.')) {\n    specifier = path.join(basedir, specifier)\n  }\n\n  return resolveSync(specifier, {\n    extensions: ['.ts', '.tsx'],\n    moduleDirectory,\n  })\n}\n\nfunction getShims() {\n  try {\n    return require('../scripts/shims')\n  } catch {\n    return []\n  }\n}\n\nfunction errorExit(error) {\n  console.error(error)\n  process.exit(1)\n}\n\nmodule.exports = {\n  getSources,\n  sourcesGlob,\n  lintSourcesGlob,\n  commonIgnoreGlobs,\n  sourcesIgnoreGlobs,\n  lintIgnoreGlobs,\n  getBuiltJsFiles,\n  getEsnextBabelOptions,\n  extendBabelOptions,\n  getDevPackageDir,\n  getPackages,\n  getPackageJsons,\n  getModuleName,\n  getModuleDirectories,\n  getPackageDir,\n  getRelativeToRoot,\n  withBestRoot,\n  resolveImport,\n  isPro,\n  registryUrl,\n  shouldIgnoreImport,\n  getShims,\n  errorExit,\n}\n"
  },
  {
    "path": "shims.d.ts",
    "content": "declare module '*.vue' {\n  import type { DefineComponent } from 'vue'\n  const component: ReturnType<DefineComponent<{}, {}, any>>\n  export default component\n}\n"
  },
  {
    "path": "test/.eslintrc.cjs",
    "content": "module.exports = {\n  extends: '../.eslintrc.cjs',\n  env: { browser: true },\n  rules: { 'no-console': 2, strict: [2, 'never'] },\n}\n"
  },
  {
    "path": "test/fixtures/babelPluginProject/index.js",
    "content": "// eslint-disable-next-line import/no-extraneous-dependencies\nexport * from '@interactjs/a'\n"
  },
  {
    "path": "test/fixtures/babelPluginProject/node_modules/@interactjs/a/a.js",
    "content": "export const a =  {}\nexport * from './b'\n"
  },
  {
    "path": "test/fixtures/babelPluginProject/node_modules/@interactjs/a/b/b.js",
    "content": "export const b = {}\n"
  },
  {
    "path": "test/fixtures/babelPluginProject/node_modules/@interactjs/a/b/index.js",
    "content": "export { b } from './b'\n"
  },
  {
    "path": "test/fixtures/babelPluginProject/node_modules/@interactjs/a/package-main-file.js",
    "content": "export * from './a'\n"
  },
  {
    "path": "test/fixtures/babelPluginProject/node_modules/@interactjs/a/package.json",
    "content": "{\n  \"main\": \"package-main-file.js\"\n}\n"
  },
  {
    "path": "test/fixtures/dependentTsProject/index.ts",
    "content": "/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved */\nimport interact from 'interactjs'\n\n// Interactables\ninteract(document.body)\ninteract(document)\ninteract(window)\n\ninteract('.drag-and-resize')\n  .draggable({\n    inertia: true,\n    modifiers: [\n      interact.modifiers.snap({\n        targets: [\n          { x: 100, y: 200 },\n          (x: number, y: number) => ({ x: x % 20, y }),\n          interact.snappers.grid({ x: 20, y: 0 }),\n        ],\n        offset: 'startCoords',\n        relativePoints: [{ x: 0, y: 1 }],\n        endOnly: true,\n      }),\n      interact.modifiers.snapSize({\n        targets: [\n          { x: 100, y: 200 },\n          (x: number, y: number) => ({ x: x % 20, y }),\n          interact.snappers.grid({ width: 100, height: 500 }),\n        ],\n        endOnly: true,\n      }),\n      interact.modifiers.restrictRect({\n        restriction: 'parent',\n        endOnly: true,\n      }),\n      interact.modifiers.restrict({\n        restriction: _ => ({ top: 0, left: 0, bottom: 1, right: 1 }),\n      }),\n      interact.modifiers.restrict({\n        restriction: _ => document.body,\n      }),\n      interact.modifiers.restrictSize({\n        min: document.body,\n        max: 'parent',\n      }),\n      interact.modifiers.restrictEdges({\n        inner: document.body,\n        outer: 'parent',\n      }),\n    ],\n  })\n  .resizable({\n    inertia: true,\n  })\n\n// Selector context\nconst myList = document.querySelector('#my-list') as HTMLElement | SVGElement\n\ninteract('li', {\n  context: myList,\n}).draggable({\n  /* ... */\n})\n\n// Action options\nconst target = 'li'\ninteract(target)\n  .draggable({\n    max: 1,\n    maxPerElement: 2,\n    manualStart: true,\n    modifiers: [],\n    inertia: {\n      /* ... */\n    },\n    autoScroll: {\n      /* ... */\n    },\n\n    lockAxis: 'x' || 'y' || 'start',\n    startAxis: 'x' || 'y',\n  })\n  .resizable({\n    max: 1,\n    maxPerElement: 2,\n    manualStart: true,\n    modifiers: [],\n    inertia: {\n      /* ... */\n    },\n    autoScroll: {\n      /* ... */\n    },\n    margin: 50,\n\n    square: true || false,\n    axis: 'x' || 'y',\n  })\n  .gesturable({\n    max: 1,\n    maxPerElement: 2,\n    manualStart: true,\n    modifiers: [],\n  })\n\n// autoscroll\nconst element = 'li'\ninteract(element)\n  .draggable({\n    autoScroll: true,\n  })\n  .resizable({\n    autoScroll: {\n      container: document.body,\n      margin: 50,\n      distance: 5,\n      interval: 10,\n    },\n  })\n\n// axis\ninteract(target)\n  .draggable({\n    startAxis: 'x',\n    lockAxis: 'y',\n  })\n  .draggable({\n    startAxis: 'xy',\n    lockAxis: 'x',\n  })\n\ninteract(target).resizable({\n  axis: 'x',\n})\n\nconst handleEl = 'li'\ninteract(target).resizable({\n  edges: {\n    top: true, // Use pointer coords to check for resize.\n    left: false, // Disable resizing from left edge.\n    bottom: '.resize-s', // Resize if pointer target matches selector\n    right: handleEl, // Resize if pointer target is the given Element\n  },\n})\n\n// resize invert\ninteract(target).resizable({\n  edges: { bottom: true, right: true },\n  invert: 'reposition',\n})\n\n// resize square\ninteract(target).resizable({\n  squareResize: true,\n})\n\n// dropzone  accept\ninteract(target).dropzone({\n  accept: '.drag0, .drag1',\n})\n\n// dropzone overlap\ninteract(target).dropzone({\n  overlap: 0.25,\n})\n\n// dropzone checker\ninteract(target).dropzone({\n  checker (\n    _dragEvent: Interact.Element, // related dragmove or dragend\n    _event: Event, // Touch, Pointer or Mouse Event\n    dropped: boolean, // bool default checker result\n    _dropzone: Interact.Interactable, // dropzone Interactable\n    dropElement: Interact.Element, // dropzone elemnt\n    _draggable: Interact.Interactable, // draggable Interactable\n    _draggableElement: Interact.Element,\n  ) {\n    // draggable element\n    // only allow drops into empty dropzone elements\n    return dropped && !dropElement.hasChildNodes()\n  },\n})\n\ninteract.dynamicDrop()\ninteract.dynamicDrop(false)\n\n// Events\nfunction listener (event: Interact.InteractEvent) {\n  const { type, pageX, pageY } = event\n  alert({ type, pageX, pageY })\n}\n\ninteract(target)\n  .on('dragstart', listener)\n  .on('dragmove dragend', listener)\n  .on(['resizemove', 'resizeend'], listener)\n  .on({\n    gesturestart: listener,\n    gestureend: listener,\n  })\n\ninteract.on('resize', (event: Interact.ResizeEvent) => {\n  const { rect, deltaRect } = event\n  alert(JSON.stringify({ rect, deltaRect }))\n})\n\ninteract(target).resizable({\n  listeners: [{ start: listener, move: listener }],\n})\n\ninteract(target).draggable({\n  listeners: { start: listener, end: listener },\n})\n\ninteract(target).draggable({\n  onstart: listener,\n  onmove: listener,\n  onend: listener,\n})\n\ninteract.on(['dragmove', 'resizestart'], listener)\n\n// devTools options\ninteract(target).devTools({\n  ignore: { boxSizing: true, touchAction: true },\n})\n\nconst dropTarget = 'div'\n// Drop Events\ninteract(dropTarget)\n  .dropzone({\n    ondrop (event) {\n      alert(event.relatedTarget.id + ' was dropped into ' + event.target.id)\n    },\n  })\n  .on('dropactivate', event => {\n    event.target.classList.add('drop-activated')\n  })\n\ninteract(target).on('up', _event => {})\n\n// fast click\ninteract('a[href]').on('tap', event => {\n  window.location.href = event.currentTarget.href\n\n  event.preventDefault()\n})\n"
  },
  {
    "path": "test/fixtures/dependentTsProject/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"commonjs\",\n    \"lib\": [\"dom\", \"esnext\"],\n    \"strict\": true,\n    \"skipLibCheck\": false,\n    \"esModuleInterop\": true,\n    \"noEmit\": true\n  }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"include\": [\n    \"packages\",\n    \"shims.d.ts\",\n    \"scripts\",\n    \"jsdoc\"\n  ],\n  \"exclude\": [\n    \"test/fixtures\",\n    \"_angular\",\n    \"**/dist\"\n  ],\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n\n    \"allowJs\": false,\n    \"skipLibCheck\": true,\n    \"noEmit\": true,\n\n    \"strict\": false,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"jsx\": \"preserve\",\n    \"experimentalDecorators\": true,\n\n    \"lib\": [\n      \"esnext\",\n      \"dom\"\n    ],\n\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@interactjs/_dev/*\": [\"./*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "typedoc.config.cjs",
    "content": "const { isPro } = require('./scripts/utils')\n\n/** @type {import('typedoc').TypeDocOptions} */\nconst config = {\n  name: '@interactjs',\n  entryPoints: [\n    'actions',\n    'auto-scroll',\n    'auto-start',\n    'core',\n    'dev-tools',\n    'inertia',\n    'modifiers',\n    'pointer-events',\n    'reflow',\n    'snappers',\n  ].map((pkg) => `./packages/@interactjs/${pkg}/*.ts`),\n  exclude: ['**/*.{spec,stub}.ts{,x}', '**/_*'],\n  excludeReferences: true,\n  excludeInternal: true,\n  excludeExternals: true,\n  excludePrivate: true,\n  excludeNotDocumented: true,\n  excludeNotDocumentedKinds: [\n    'Module',\n    'Variable',\n    'Function',\n    'Constructor',\n    'Method',\n    'IndexSignature',\n    'ConstructorSignature',\n    'Reference',\n  ],\n  basePath: './packages/@interactjs',\n  titleLink: '/',\n  readme: 'none',\n  disableSources: isPro,\n  plugin: ['typedoc-plugin-markdown'],\n  out: './dist/api',\n}\n\nmodule.exports = config\n"
  },
  {
    "path": "types.tsconfig.json",
    "content": "{\n  \"include\": [\"packages/@interactjs\", \"shims.d.ts\"],\n  \"exclude\": [\"**/*.spec.ts\", \"packages/@interactjs/vue\", \"packages/@interactjs/react\"],\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n\n    \"declaration\": true,\n    \"declarationMap\": false,\n    \"emitDeclarationOnly\": true,\n    \"stripInternal\": true,\n    \"skipLibCheck\": true,\n\n    \"strict\": false\n  }\n}\n"
  },
  {
    "path": "vijest.config.js",
    "content": "module.exports = {\n  launch: {\n    executablePath: 'chromium',\n    // devtools: true,\n    // slowMo: 1000,\n  },\n  shareBrowserContext: true,\n}\n"
  },
  {
    "path": "vite.config.ts",
    "content": "import path from 'path'\n\nimport vue from '@vitejs/plugin-vue'\nimport serveIndex from 'serve-index'\nimport type { Plugin } from 'vite'\nimport { defineConfig } from 'vite'\n\nconst examplesDir = path.resolve(__dirname, 'examples')\n\nexport default defineConfig({\n  root: examplesDir,\n  resolve: {\n    alias: {\n      '@interactjs/': path.resolve(__dirname, 'packages/@interactjs'),\n      interactjs: path.resolve(__dirname, 'packages/interactjs'),\n    },\n  },\n  define: {\n    ...getDefinedEnv(),\n  },\n  plugins: [vue(), dirListing()],\n  optimizeDeps: {\n    include: ['react'],\n  },\n  server: {\n    port: 8081,\n  },\n})\n\nfunction getDefinedEnv () {\n  const entries = Object.entries(process.env)\n    .filter(([key]) => /^(NODE_ENV|npm_package_version|INTERACTJS_.*)$/.test(key))\n    .map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)])\n\n  return Object.fromEntries(entries)\n}\n\nfunction dirListing (): Plugin {\n  return {\n    name: 'dir-listing',\n    configureServer (server) {\n      server.middlewares.use(serveIndex(examplesDir, { icons: true }) as any)\n    },\n  }\n}\n"
  }
]