@bquery/bquery 1.6.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +192 -18
- package/dist/a11y/announce.d.ts +43 -0
- package/dist/a11y/announce.d.ts.map +1 -0
- package/dist/a11y/audit.d.ts +42 -0
- package/dist/a11y/audit.d.ts.map +1 -0
- package/dist/a11y/index.d.ts +53 -0
- package/dist/a11y/index.d.ts.map +1 -0
- package/dist/a11y/media-preferences.d.ts +77 -0
- package/dist/a11y/media-preferences.d.ts.map +1 -0
- package/dist/a11y/roving-tab-index.d.ts +38 -0
- package/dist/a11y/roving-tab-index.d.ts.map +1 -0
- package/dist/a11y/skip-link.d.ts +37 -0
- package/dist/a11y/skip-link.d.ts.map +1 -0
- package/dist/a11y/trap-focus.d.ts +49 -0
- package/dist/a11y/trap-focus.d.ts.map +1 -0
- package/dist/a11y/types.d.ts +152 -0
- package/dist/a11y/types.d.ts.map +1 -0
- package/dist/a11y-DVBCy09c.js +421 -0
- package/dist/a11y-DVBCy09c.js.map +1 -0
- package/dist/a11y.es.mjs +14 -0
- package/dist/component/component.d.ts.map +1 -1
- package/dist/component/html.d.ts.map +1 -1
- package/dist/component/index.d.ts +2 -1
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/library.d.ts.map +1 -1
- package/dist/component/scope.d.ts +138 -0
- package/dist/component/scope.d.ts.map +1 -0
- package/dist/component/types.d.ts +53 -1
- package/dist/component/types.d.ts.map +1 -1
- package/dist/component-L3-JfOFz.js +684 -0
- package/dist/component-L3-JfOFz.js.map +1 -0
- package/dist/component.es.mjs +9 -6
- package/dist/{config-DRmZZno3.js → config-DhT9auRm.js} +4 -4
- package/dist/{config-DRmZZno3.js.map → config-DhT9auRm.js.map} +1 -1
- package/dist/constraints-D5RHQLmP.js +100 -0
- package/dist/constraints-D5RHQLmP.js.map +1 -0
- package/dist/core/collection.d.ts +134 -0
- package/dist/core/collection.d.ts.map +1 -1
- package/dist/core/element.d.ts +120 -0
- package/dist/core/element.d.ts.map +1 -1
- package/dist/core/env.d.ts +18 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/shared.d.ts +14 -0
- package/dist/core/shared.d.ts.map +1 -1
- package/dist/core/utils/index.d.ts +52 -41
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core-DdtZHzsS.js +168 -0
- package/dist/core-DdtZHzsS.js.map +1 -0
- package/dist/{core-CCEabVHl.js → core-EMYSLzaT.js} +293 -194
- package/dist/core-EMYSLzaT.js.map +1 -0
- package/dist/core.es.mjs +48 -46
- package/dist/custom-directives-Dr4C5lVV.js +9 -0
- package/dist/custom-directives-Dr4C5lVV.js.map +1 -0
- package/dist/devtools/devtools.d.ts +212 -0
- package/dist/devtools/devtools.d.ts.map +1 -0
- package/dist/devtools/index.d.ts +20 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/types.d.ts +69 -0
- package/dist/devtools/types.d.ts.map +1 -0
- package/dist/devtools-BhB2iDPT.js +122 -0
- package/dist/devtools-BhB2iDPT.js.map +1 -0
- package/dist/devtools.es.mjs +19 -0
- package/dist/dnd/draggable.d.ts +51 -0
- package/dist/dnd/draggable.d.ts.map +1 -0
- package/dist/dnd/droppable.d.ts +38 -0
- package/dist/dnd/droppable.d.ts.map +1 -0
- package/dist/dnd/index.d.ts +47 -0
- package/dist/dnd/index.d.ts.map +1 -0
- package/dist/dnd/sortable.d.ts +43 -0
- package/dist/dnd/sortable.d.ts.map +1 -0
- package/dist/dnd/types.d.ts +250 -0
- package/dist/dnd/types.d.ts.map +1 -0
- package/dist/dnd-NwZBYh4l.js +244 -0
- package/dist/dnd-NwZBYh4l.js.map +1 -0
- package/dist/dnd.es.mjs +6 -0
- package/dist/env-CTdvLaH2.js +19 -0
- package/dist/env-CTdvLaH2.js.map +1 -0
- package/dist/forms/create-form.d.ts +49 -0
- package/dist/forms/create-form.d.ts.map +1 -0
- package/dist/forms/index.d.ts +40 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/types.d.ts +185 -0
- package/dist/forms/types.d.ts.map +1 -0
- package/dist/forms/use-field.d.ts +34 -0
- package/dist/forms/use-field.d.ts.map +1 -0
- package/dist/forms/validators.d.ts +204 -0
- package/dist/forms/validators.d.ts.map +1 -0
- package/dist/forms-UcRHsYxC.js +227 -0
- package/dist/forms-UcRHsYxC.js.map +1 -0
- package/dist/forms.es.mjs +16 -0
- package/dist/full.d.ts +30 -11
- package/dist/full.d.ts.map +1 -1
- package/dist/full.es.mjs +209 -93
- package/dist/full.iife.js +47 -31
- package/dist/full.iife.js.map +1 -1
- package/dist/full.umd.js +47 -31
- package/dist/full.umd.js.map +1 -1
- package/dist/function-Cybd57JV.js +33 -0
- package/dist/function-Cybd57JV.js.map +1 -0
- package/dist/i18n/formatting.d.ts +40 -0
- package/dist/i18n/formatting.d.ts.map +1 -0
- package/dist/i18n/i18n.d.ts +48 -0
- package/dist/i18n/i18n.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +57 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/translate.d.ts +83 -0
- package/dist/i18n/translate.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +156 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n-kuF6Ekj6.js +89 -0
- package/dist/i18n-kuF6Ekj6.js.map +1 -0
- package/dist/i18n.es.mjs +6 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.mjs +257 -143
- package/dist/media/battery.d.ts +35 -0
- package/dist/media/battery.d.ts.map +1 -0
- package/dist/media/breakpoints.d.ts +51 -0
- package/dist/media/breakpoints.d.ts.map +1 -0
- package/dist/media/clipboard.d.ts +30 -0
- package/dist/media/clipboard.d.ts.map +1 -0
- package/dist/media/device-sensors.d.ts +54 -0
- package/dist/media/device-sensors.d.ts.map +1 -0
- package/dist/media/geolocation.d.ts +38 -0
- package/dist/media/geolocation.d.ts.map +1 -0
- package/dist/media/index.d.ts +42 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/media-query.d.ts +36 -0
- package/dist/media/media-query.d.ts.map +1 -0
- package/dist/media/network.d.ts +35 -0
- package/dist/media/network.d.ts.map +1 -0
- package/dist/media/types.d.ts +173 -0
- package/dist/media/types.d.ts.map +1 -0
- package/dist/media/viewport.d.ts +32 -0
- package/dist/media/viewport.d.ts.map +1 -0
- package/dist/media-i-fB5WxI.js +340 -0
- package/dist/media-i-fB5WxI.js.map +1 -0
- package/dist/media.es.mjs +12 -0
- package/dist/motion/index.d.ts +7 -3
- package/dist/motion/index.d.ts.map +1 -1
- package/dist/motion/morph.d.ts +27 -0
- package/dist/motion/morph.d.ts.map +1 -0
- package/dist/motion/parallax.d.ts +30 -0
- package/dist/motion/parallax.d.ts.map +1 -0
- package/dist/motion/reduced-motion.d.ts +36 -3
- package/dist/motion/reduced-motion.d.ts.map +1 -1
- package/dist/motion/types.d.ts +58 -0
- package/dist/motion/types.d.ts.map +1 -1
- package/dist/motion/typewriter.d.ts +31 -0
- package/dist/motion/typewriter.d.ts.map +1 -0
- package/dist/motion-BJsAuULb.js +530 -0
- package/dist/motion-BJsAuULb.js.map +1 -0
- package/dist/motion.es.mjs +27 -23
- package/dist/{view-C70lA3vf.js → mount-B4Y8bk8Z.js} +166 -160
- package/dist/mount-B4Y8bk8Z.js.map +1 -0
- package/dist/{object-qGpWr6-J.js → object-BCk-1c8T.js} +5 -4
- package/dist/{object-qGpWr6-J.js.map → object-BCk-1c8T.js.map} +1 -1
- package/dist/{platform-Dr9b6fsq.js → platform-Dw2gE3zI.js} +21 -22
- package/dist/{platform-Dr9b6fsq.js.map → platform-Dw2gE3zI.js.map} +1 -1
- package/dist/platform.es.mjs +2 -2
- package/dist/plugin/index.d.ts +22 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/registry.d.ts +108 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/types.d.ts +110 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin-C2WuC8SF.js +66 -0
- package/dist/plugin-C2WuC8SF.js.map +1 -0
- package/dist/plugin.es.mjs +9 -0
- package/dist/reactive/async-data.d.ts +28 -3
- package/dist/reactive/async-data.d.ts.map +1 -1
- package/dist/reactive/computed.d.ts +10 -0
- package/dist/reactive/computed.d.ts.map +1 -1
- package/dist/reactive/effect.d.ts +3 -0
- package/dist/reactive/effect.d.ts.map +1 -1
- package/dist/reactive/http.d.ts +194 -0
- package/dist/reactive/http.d.ts.map +1 -0
- package/dist/reactive/index.d.ts +2 -2
- package/dist/reactive/index.d.ts.map +1 -1
- package/dist/reactive/pagination.d.ts +126 -0
- package/dist/reactive/pagination.d.ts.map +1 -0
- package/dist/reactive/polling.d.ts +55 -0
- package/dist/reactive/polling.d.ts.map +1 -0
- package/dist/reactive/readonly.d.ts +20 -1
- package/dist/reactive/readonly.d.ts.map +1 -1
- package/dist/reactive/rest.d.ts +293 -0
- package/dist/reactive/rest.d.ts.map +1 -0
- package/dist/reactive/scope.d.ts +140 -0
- package/dist/reactive/scope.d.ts.map +1 -0
- package/dist/reactive/signal.d.ts +16 -2
- package/dist/reactive/signal.d.ts.map +1 -1
- package/dist/reactive/to-value.d.ts +57 -0
- package/dist/reactive/to-value.d.ts.map +1 -0
- package/dist/reactive/websocket.d.ts +285 -0
- package/dist/reactive/websocket.d.ts.map +1 -0
- package/dist/reactive-DwkhUJfP.js +1148 -0
- package/dist/reactive-DwkhUJfP.js.map +1 -0
- package/dist/reactive.es.mjs +38 -20
- package/dist/registry-B08iilIh.js +26 -0
- package/dist/registry-B08iilIh.js.map +1 -0
- package/dist/router/bq-link.d.ts +112 -0
- package/dist/router/bq-link.d.ts.map +1 -0
- package/dist/router/constraints.d.ts +9 -0
- package/dist/router/constraints.d.ts.map +1 -0
- package/dist/router/index.d.ts +15 -7
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/match.d.ts +0 -1
- package/dist/router/match.d.ts.map +1 -1
- package/dist/router/path-pattern.d.ts +14 -0
- package/dist/router/path-pattern.d.ts.map +1 -0
- package/dist/router/query.d.ts.map +1 -1
- package/dist/router/router.d.ts +3 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/state.d.ts +25 -2
- package/dist/router/state.d.ts.map +1 -1
- package/dist/router/types.d.ts +48 -4
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/use-route.d.ts +50 -0
- package/dist/router/use-route.d.ts.map +1 -0
- package/dist/router/utils.d.ts +3 -0
- package/dist/router/utils.d.ts.map +1 -1
- package/dist/router-CQikC9Ed.js +492 -0
- package/dist/router-CQikC9Ed.js.map +1 -0
- package/dist/router.es.mjs +14 -10
- package/dist/{sanitize-Bs2dkMby.js → sanitize-B1V4JswB.js} +2 -1
- package/dist/{sanitize-Bs2dkMby.js.map → sanitize-B1V4JswB.js.map} +1 -1
- package/dist/security/index.d.ts +2 -2
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security.es.mjs +1 -1
- package/dist/ssr/hydrate.d.ts +65 -0
- package/dist/ssr/hydrate.d.ts.map +1 -0
- package/dist/ssr/index.d.ts +59 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/render.d.ts +62 -0
- package/dist/ssr/render.d.ts.map +1 -0
- package/dist/ssr/serialize.d.ts +118 -0
- package/dist/ssr/serialize.d.ts.map +1 -0
- package/dist/ssr/types.d.ts +70 -0
- package/dist/ssr/types.d.ts.map +1 -0
- package/dist/ssr-_dAcGdzu.js +248 -0
- package/dist/ssr-_dAcGdzu.js.map +1 -0
- package/dist/ssr.es.mjs +9 -0
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/persisted.d.ts +38 -4
- package/dist/store/persisted.d.ts.map +1 -1
- package/dist/store/types.d.ts +138 -1
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/utils.d.ts +2 -2
- package/dist/store/utils.d.ts.map +1 -1
- package/dist/store-Cb3gPRve.js +338 -0
- package/dist/store-Cb3gPRve.js.map +1 -0
- package/dist/store.es.mjs +11 -10
- package/dist/storybook/index.d.ts.map +1 -1
- package/dist/storybook.es.mjs +1 -1
- package/dist/storybook.es.mjs.map +1 -1
- package/dist/testing/index.d.ts +23 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/testing.d.ts +156 -0
- package/dist/testing/testing.d.ts.map +1 -0
- package/dist/testing/types.d.ts +134 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing-C5Sjfsna.js +224 -0
- package/dist/testing-C5Sjfsna.js.map +1 -0
- package/dist/testing.es.mjs +9 -0
- package/dist/type-guards-BMX2c0LP.js +44 -0
- package/dist/type-guards-BMX2c0LP.js.map +1 -0
- package/dist/untrack-D0fnO5k2.js +36 -0
- package/dist/untrack-D0fnO5k2.js.map +1 -0
- package/dist/view/custom-directives.d.ts +20 -0
- package/dist/view/custom-directives.d.ts.map +1 -0
- package/dist/view/evaluate.d.ts.map +1 -1
- package/dist/view/process.d.ts.map +1 -1
- package/dist/view.es.mjs +9 -9
- package/package.json +47 -11
- package/src/a11y/announce.ts +131 -0
- package/src/a11y/audit.ts +314 -0
- package/src/a11y/index.ts +68 -0
- package/src/a11y/media-preferences.ts +255 -0
- package/src/a11y/roving-tab-index.ts +164 -0
- package/src/a11y/skip-link.ts +255 -0
- package/src/a11y/trap-focus.ts +184 -0
- package/src/a11y/types.ts +183 -0
- package/src/component/component.ts +599 -524
- package/src/component/html.ts +153 -153
- package/src/component/index.ts +52 -50
- package/src/component/library.ts +540 -518
- package/src/component/scope.ts +212 -0
- package/src/component/types.ts +310 -256
- package/src/core/collection.ts +249 -1
- package/src/core/element.ts +252 -11
- package/src/core/env.ts +60 -0
- package/src/core/index.ts +1 -0
- package/src/core/shared.ts +64 -0
- package/src/core/utils/index.ts +66 -1
- package/src/devtools/devtools.ts +410 -0
- package/src/devtools/index.ts +48 -0
- package/src/devtools/types.ts +104 -0
- package/src/dnd/draggable.ts +296 -0
- package/src/dnd/droppable.ts +228 -0
- package/src/dnd/index.ts +62 -0
- package/src/dnd/sortable.ts +307 -0
- package/src/dnd/types.ts +293 -0
- package/src/forms/create-form.ts +320 -0
- package/src/forms/index.ts +70 -0
- package/src/forms/types.ts +203 -0
- package/src/forms/use-field.ts +231 -0
- package/src/forms/validators.ts +294 -0
- package/src/full.ts +554 -229
- package/src/i18n/formatting.ts +67 -0
- package/src/i18n/i18n.ts +200 -0
- package/src/i18n/index.ts +67 -0
- package/src/i18n/translate.ts +182 -0
- package/src/i18n/types.ts +171 -0
- package/src/index.ts +72 -0
- package/src/media/battery.ts +116 -0
- package/src/media/breakpoints.ts +129 -0
- package/src/media/clipboard.ts +80 -0
- package/src/media/device-sensors.ts +158 -0
- package/src/media/geolocation.ts +119 -0
- package/src/media/index.ts +76 -0
- package/src/media/media-query.ts +92 -0
- package/src/media/network.ts +115 -0
- package/src/media/types.ts +177 -0
- package/src/media/viewport.ts +84 -0
- package/src/motion/index.ts +11 -2
- package/src/motion/morph.ts +151 -0
- package/src/motion/parallax.ts +120 -0
- package/src/motion/reduced-motion.ts +52 -3
- package/src/motion/types.ts +63 -0
- package/src/motion/typewriter.ts +164 -0
- package/src/plugin/index.ts +37 -0
- package/src/plugin/registry.ts +284 -0
- package/src/plugin/types.ts +137 -0
- package/src/reactive/async-data.ts +250 -29
- package/src/reactive/computed.ts +53 -1
- package/src/reactive/effect.ts +29 -6
- package/src/reactive/http.ts +790 -0
- package/src/reactive/index.ts +60 -0
- package/src/reactive/pagination.ts +317 -0
- package/src/reactive/polling.ts +179 -0
- package/src/reactive/readonly.ts +52 -8
- package/src/reactive/rest.ts +859 -0
- package/src/reactive/scope.ts +276 -0
- package/src/reactive/signal.ts +61 -1
- package/src/reactive/to-value.ts +71 -0
- package/src/reactive/websocket.ts +849 -0
- package/src/router/bq-link.ts +279 -0
- package/src/router/constraints.ts +204 -0
- package/src/router/index.ts +15 -7
- package/src/router/match.ts +255 -49
- package/src/router/path-pattern.ts +52 -0
- package/src/router/query.ts +3 -0
- package/src/router/router.ts +258 -48
- package/src/router/state.ts +51 -3
- package/src/router/types.ts +50 -4
- package/src/router/use-route.ts +68 -0
- package/src/router/utils.ts +44 -3
- package/src/security/index.ts +12 -17
- package/src/security/sanitize.ts +70 -70
- package/src/security/trusted-html.ts +71 -71
- package/src/ssr/hydrate.ts +84 -0
- package/src/ssr/index.ts +70 -0
- package/src/ssr/render.ts +508 -0
- package/src/ssr/serialize.ts +296 -0
- package/src/ssr/types.ts +81 -0
- package/src/store/create-store.ts +146 -8
- package/src/store/define-store.ts +49 -49
- package/src/store/index.ts +5 -0
- package/src/store/mapping.ts +74 -74
- package/src/store/persisted.ts +245 -62
- package/src/store/types.ts +247 -92
- package/src/store/utils.ts +4 -10
- package/src/store/watch.ts +53 -53
- package/src/storybook/index.ts +480 -479
- package/src/testing/index.ts +42 -0
- package/src/testing/testing.ts +593 -0
- package/src/testing/types.ts +170 -0
- package/src/view/custom-directives.ts +28 -0
- package/src/view/evaluate.ts +2 -0
- package/src/view/process.ts +19 -3
- package/dist/component-BEQgt5hl.js +0 -600
- package/dist/component-BEQgt5hl.js.map +0 -1
- package/dist/core-BGQJVw0-.js +0 -35
- package/dist/core-BGQJVw0-.js.map +0 -1
- package/dist/core-CCEabVHl.js.map +0 -1
- package/dist/effect-AFRW_Plg.js +0 -84
- package/dist/effect-AFRW_Plg.js.map +0 -1
- package/dist/motion-D9TcHxOF.js +0 -415
- package/dist/motion-D9TcHxOF.js.map +0 -1
- package/dist/reactive-DSkct0dO.js +0 -254
- package/dist/reactive-DSkct0dO.js.map +0 -1
- package/dist/router-CbDhl8rS.js +0 -188
- package/dist/router-CbDhl8rS.js.map +0 -1
- package/dist/store-BwDvI45q.js +0 -263
- package/dist/store-BwDvI45q.js.map +0 -1
- package/dist/untrack-B0rVscTc.js +0 -7
- package/dist/untrack-B0rVscTc.js.map +0 -1
- package/dist/view-C70lA3vf.js.map +0 -1
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Make an element draggable using pointer events.
|
|
3
|
+
*
|
|
4
|
+
* Uses Pointer Events (not HTML5 Drag & Drop) for reliable
|
|
5
|
+
* cross-platform behavior including touch support.
|
|
6
|
+
*
|
|
7
|
+
* @module bquery/dnd
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
BoundsRect,
|
|
12
|
+
DragBounds,
|
|
13
|
+
DragEventData,
|
|
14
|
+
DragPosition,
|
|
15
|
+
DraggableHandle,
|
|
16
|
+
DraggableOptions,
|
|
17
|
+
} from './types';
|
|
18
|
+
|
|
19
|
+
/** Global registry of active draggable elements for drop zone detection. */
|
|
20
|
+
const activeDrags = new Map<HTMLElement, { element: HTMLElement; position: DragPosition }>();
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the currently active drag state, if any.
|
|
24
|
+
* Used internally by `droppable()` to detect drag interactions.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export const getActiveDrag = (): { element: HTMLElement; position: DragPosition } | undefined => {
|
|
28
|
+
const entries = Array.from(activeDrags.values());
|
|
29
|
+
return entries[entries.length - 1];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolves a `DragBounds` value to an absolute `BoundsRect`.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
const resolveBounds = (el: HTMLElement, bounds: DragBounds): BoundsRect | null => {
|
|
37
|
+
if (typeof bounds === 'object') {
|
|
38
|
+
return bounds;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let target: HTMLElement | null = null;
|
|
42
|
+
|
|
43
|
+
if (bounds === 'parent') {
|
|
44
|
+
target = el.parentElement;
|
|
45
|
+
} else {
|
|
46
|
+
target = document.querySelector(bounds) as HTMLElement | null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!target) return null;
|
|
50
|
+
|
|
51
|
+
const rect = target.getBoundingClientRect();
|
|
52
|
+
const elRect = el.getBoundingClientRect();
|
|
53
|
+
const rawLeft = parseFloat(el.style.left || '0');
|
|
54
|
+
const rawTop = parseFloat(el.style.top || '0');
|
|
55
|
+
const leftOffset = Number.isNaN(rawLeft) ? 0 : rawLeft;
|
|
56
|
+
const topOffset = Number.isNaN(rawTop) ? 0 : rawTop;
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
left: rect.left - elRect.left + leftOffset,
|
|
60
|
+
top: rect.top - elRect.top + topOffset,
|
|
61
|
+
right: rect.right - elRect.right + leftOffset + (rect.width - elRect.width),
|
|
62
|
+
bottom: rect.bottom - elRect.bottom + topOffset + (rect.height - elRect.height),
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Clamp a position within bounds.
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
const clampPosition = (pos: DragPosition, bounds: BoundsRect | null): DragPosition => {
|
|
71
|
+
if (!bounds) return pos;
|
|
72
|
+
return {
|
|
73
|
+
x: Math.max(bounds.left, Math.min(bounds.right, pos.x)),
|
|
74
|
+
y: Math.max(bounds.top, Math.min(bounds.bottom, pos.y)),
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Makes an element draggable using pointer events.
|
|
80
|
+
*
|
|
81
|
+
* Features:
|
|
82
|
+
* - Touch and mouse support via Pointer Events
|
|
83
|
+
* - Axis locking (`x`, `y`, or `both`)
|
|
84
|
+
* - Bounds constraint (parent, selector, or explicit rect)
|
|
85
|
+
* - Optional drag handle
|
|
86
|
+
* - Ghost/clone preview during drag
|
|
87
|
+
* - Callbacks: `onDragStart`, `onDrag`, `onDragEnd`
|
|
88
|
+
*
|
|
89
|
+
* @param el - The element to make draggable
|
|
90
|
+
* @param options - Configuration options
|
|
91
|
+
* @returns A handle with `destroy()`, `disable()`, and `enable()` methods
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { draggable } from '@bquery/bquery/dnd';
|
|
96
|
+
*
|
|
97
|
+
* const handle = draggable(document.querySelector('#box'), {
|
|
98
|
+
* axis: 'both',
|
|
99
|
+
* bounds: 'parent',
|
|
100
|
+
* onDragEnd: ({ position }) => {
|
|
101
|
+
* console.log('Dropped at', position.x, position.y);
|
|
102
|
+
* },
|
|
103
|
+
* });
|
|
104
|
+
*
|
|
105
|
+
* // Later:
|
|
106
|
+
* handle.destroy();
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export const draggable = (el: HTMLElement, options: DraggableOptions = {}): DraggableHandle => {
|
|
110
|
+
const {
|
|
111
|
+
axis = 'both',
|
|
112
|
+
bounds,
|
|
113
|
+
handle,
|
|
114
|
+
ghost = false,
|
|
115
|
+
ghostClass = 'bq-drag-ghost',
|
|
116
|
+
draggingClass = 'bq-dragging',
|
|
117
|
+
onDragStart,
|
|
118
|
+
onDrag,
|
|
119
|
+
onDragEnd,
|
|
120
|
+
} = options;
|
|
121
|
+
|
|
122
|
+
let enabled = !options.disabled;
|
|
123
|
+
let isDragging = false;
|
|
124
|
+
let startPointer: DragPosition = { x: 0, y: 0 };
|
|
125
|
+
let currentPosition: DragPosition = { x: 0, y: 0 };
|
|
126
|
+
let previousPosition: DragPosition = { x: 0, y: 0 };
|
|
127
|
+
let ghostEl: HTMLElement | null = null;
|
|
128
|
+
let ghostStartPosition: DragPosition | null = null;
|
|
129
|
+
const previousTouchAction = el.style.touchAction;
|
|
130
|
+
const previousUserSelect = el.style.userSelect;
|
|
131
|
+
|
|
132
|
+
const createEventData = (event: PointerEvent): DragEventData => ({
|
|
133
|
+
element: el,
|
|
134
|
+
position: { ...currentPosition },
|
|
135
|
+
delta: {
|
|
136
|
+
x: currentPosition.x - previousPosition.x,
|
|
137
|
+
y: currentPosition.y - previousPosition.y,
|
|
138
|
+
},
|
|
139
|
+
event,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const createGhost = (): HTMLElement => {
|
|
143
|
+
const clone = el.cloneNode(true) as HTMLElement;
|
|
144
|
+
const rect = el.getBoundingClientRect();
|
|
145
|
+
clone.classList.add(ghostClass);
|
|
146
|
+
clone.style.position = 'fixed';
|
|
147
|
+
clone.style.left = `${rect.left}px`;
|
|
148
|
+
clone.style.top = `${rect.top}px`;
|
|
149
|
+
clone.style.width = `${rect.width}px`;
|
|
150
|
+
clone.style.height = `${rect.height}px`;
|
|
151
|
+
clone.style.pointerEvents = 'none';
|
|
152
|
+
clone.style.zIndex = '999999';
|
|
153
|
+
clone.style.opacity = '0.7';
|
|
154
|
+
clone.style.margin = '0';
|
|
155
|
+
document.body.appendChild(clone);
|
|
156
|
+
return clone;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const removeGhost = (): void => {
|
|
160
|
+
if (ghostEl) {
|
|
161
|
+
ghostEl.remove();
|
|
162
|
+
ghostEl = null;
|
|
163
|
+
}
|
|
164
|
+
ghostStartPosition = null;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const onPointerDown = (e: PointerEvent): void => {
|
|
168
|
+
if (!enabled) return;
|
|
169
|
+
|
|
170
|
+
// Check handle constraint
|
|
171
|
+
if (handle) {
|
|
172
|
+
const target = e.target as Element;
|
|
173
|
+
if (!target.closest(handle)) return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
e.preventDefault();
|
|
177
|
+
isDragging = true;
|
|
178
|
+
startPointer = { x: e.clientX, y: e.clientY };
|
|
179
|
+
previousPosition = { ...currentPosition };
|
|
180
|
+
|
|
181
|
+
el.classList.add(draggingClass);
|
|
182
|
+
el.setPointerCapture(e.pointerId);
|
|
183
|
+
|
|
184
|
+
if (ghost) {
|
|
185
|
+
const rect = el.getBoundingClientRect();
|
|
186
|
+
ghostStartPosition = { x: rect.left, y: rect.top };
|
|
187
|
+
ghostEl = createGhost();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Register in global active drags
|
|
191
|
+
activeDrags.set(el, { element: el, position: currentPosition });
|
|
192
|
+
|
|
193
|
+
onDragStart?.(createEventData(e));
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const onPointerMove = (e: PointerEvent): void => {
|
|
197
|
+
if (!isDragging) return;
|
|
198
|
+
|
|
199
|
+
e.preventDefault();
|
|
200
|
+
previousPosition = { ...currentPosition };
|
|
201
|
+
|
|
202
|
+
let newX = currentPosition.x + (e.clientX - startPointer.x);
|
|
203
|
+
let newY = currentPosition.y + (e.clientY - startPointer.y);
|
|
204
|
+
|
|
205
|
+
// Reset start pointer to current for delta calculation
|
|
206
|
+
startPointer = { x: e.clientX, y: e.clientY };
|
|
207
|
+
|
|
208
|
+
// Apply axis constraint
|
|
209
|
+
if (axis === 'x') newY = currentPosition.y;
|
|
210
|
+
if (axis === 'y') newX = currentPosition.x;
|
|
211
|
+
|
|
212
|
+
let newPos: DragPosition = { x: newX, y: newY };
|
|
213
|
+
|
|
214
|
+
// Apply bounds constraint
|
|
215
|
+
if (bounds) {
|
|
216
|
+
const resolvedBounds = resolveBounds(el, bounds);
|
|
217
|
+
newPos = clampPosition(newPos, resolvedBounds);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
currentPosition = newPos;
|
|
221
|
+
|
|
222
|
+
// Update active drag position
|
|
223
|
+
activeDrags.set(el, { element: el, position: currentPosition });
|
|
224
|
+
|
|
225
|
+
// Apply the position
|
|
226
|
+
if (ghost && ghostEl) {
|
|
227
|
+
const start = ghostStartPosition ?? {
|
|
228
|
+
x: el.getBoundingClientRect().left,
|
|
229
|
+
y: el.getBoundingClientRect().top,
|
|
230
|
+
};
|
|
231
|
+
ghostEl.style.left = `${start.x + currentPosition.x}px`;
|
|
232
|
+
ghostEl.style.top = `${start.y + currentPosition.y}px`;
|
|
233
|
+
} else {
|
|
234
|
+
el.style.transform = `translate(${currentPosition.x}px, ${currentPosition.y}px)`;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
onDrag?.(createEventData(e));
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const onPointerUp = (e: PointerEvent): void => {
|
|
241
|
+
if (!isDragging) return;
|
|
242
|
+
|
|
243
|
+
isDragging = false;
|
|
244
|
+
el.classList.remove(draggingClass);
|
|
245
|
+
try {
|
|
246
|
+
if (
|
|
247
|
+
typeof el.releasePointerCapture === 'function' &&
|
|
248
|
+
(typeof el.hasPointerCapture !== 'function' || el.hasPointerCapture(e.pointerId))
|
|
249
|
+
) {
|
|
250
|
+
el.releasePointerCapture(e.pointerId);
|
|
251
|
+
}
|
|
252
|
+
} catch {
|
|
253
|
+
// Pointer capture may already be released in some interrupted drag flows.
|
|
254
|
+
} finally {
|
|
255
|
+
removeGhost();
|
|
256
|
+
|
|
257
|
+
// Remove from active drags
|
|
258
|
+
activeDrags.delete(el);
|
|
259
|
+
|
|
260
|
+
onDragEnd?.(createEventData(e));
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// Attach listeners
|
|
265
|
+
el.addEventListener('pointerdown', onPointerDown);
|
|
266
|
+
el.addEventListener('pointermove', onPointerMove);
|
|
267
|
+
el.addEventListener('pointerup', onPointerUp);
|
|
268
|
+
el.addEventListener('pointercancel', onPointerUp);
|
|
269
|
+
|
|
270
|
+
// Prevent default drag behavior
|
|
271
|
+
el.style.touchAction = 'none';
|
|
272
|
+
el.style.userSelect = 'none';
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
destroy: () => {
|
|
276
|
+
el.removeEventListener('pointerdown', onPointerDown);
|
|
277
|
+
el.removeEventListener('pointermove', onPointerMove);
|
|
278
|
+
el.removeEventListener('pointerup', onPointerUp);
|
|
279
|
+
el.removeEventListener('pointercancel', onPointerUp);
|
|
280
|
+
removeGhost();
|
|
281
|
+
activeDrags.delete(el);
|
|
282
|
+
el.style.touchAction = previousTouchAction;
|
|
283
|
+
el.style.userSelect = previousUserSelect;
|
|
284
|
+
el.classList.remove(draggingClass);
|
|
285
|
+
},
|
|
286
|
+
disable: () => {
|
|
287
|
+
enabled = false;
|
|
288
|
+
},
|
|
289
|
+
enable: () => {
|
|
290
|
+
enabled = true;
|
|
291
|
+
},
|
|
292
|
+
get enabled() {
|
|
293
|
+
return enabled;
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Define drop zones for draggable elements.
|
|
3
|
+
*
|
|
4
|
+
* Drop zones detect when draggable elements enter, move over,
|
|
5
|
+
* leave, or are dropped onto them using pointer event hit-testing.
|
|
6
|
+
*
|
|
7
|
+
* @module bquery/dnd
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { getActiveDrag } from './draggable';
|
|
11
|
+
import type { DropEventData, DroppableHandle, DroppableOptions } from './types';
|
|
12
|
+
|
|
13
|
+
type DroppableListener = {
|
|
14
|
+
handlePointerMove: (event: PointerEvent) => void;
|
|
15
|
+
handlePointerUp: (event: PointerEvent) => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const passivePointerMoveListenerOptions = { passive: true } as const;
|
|
19
|
+
|
|
20
|
+
const droppableListeners = new Set<DroppableListener>();
|
|
21
|
+
let queuedPointerMove: PointerEvent | null = null;
|
|
22
|
+
let pointerMoveFrame: number | null = null;
|
|
23
|
+
|
|
24
|
+
const getDroppableListenersSnapshot = (): DroppableListener[] => Array.from(droppableListeners);
|
|
25
|
+
|
|
26
|
+
const hasDroppableEnvironment = (): boolean => {
|
|
27
|
+
return (
|
|
28
|
+
typeof document !== 'undefined' &&
|
|
29
|
+
typeof document.addEventListener === 'function' &&
|
|
30
|
+
typeof document.removeEventListener === 'function' &&
|
|
31
|
+
typeof requestAnimationFrame === 'function' &&
|
|
32
|
+
typeof cancelAnimationFrame === 'function'
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const dispatchPointerMove = (event: PointerEvent): void => {
|
|
37
|
+
for (const listener of getDroppableListenersSnapshot()) {
|
|
38
|
+
listener.handlePointerMove(event);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const flushPointerMove = (): void => {
|
|
43
|
+
pointerMoveFrame = null;
|
|
44
|
+
const event = queuedPointerMove;
|
|
45
|
+
queuedPointerMove = null;
|
|
46
|
+
if (!event) return;
|
|
47
|
+
dispatchPointerMove(event);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleDocumentPointerMove = (event: PointerEvent): void => {
|
|
51
|
+
queuedPointerMove = event;
|
|
52
|
+
if (pointerMoveFrame === null) {
|
|
53
|
+
pointerMoveFrame = requestAnimationFrame(flushPointerMove);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const handleDocumentPointerUp = (event: PointerEvent): void => {
|
|
58
|
+
if (pointerMoveFrame !== null) {
|
|
59
|
+
cancelAnimationFrame(pointerMoveFrame);
|
|
60
|
+
pointerMoveFrame = null;
|
|
61
|
+
queuedPointerMove = null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const listener of getDroppableListenersSnapshot()) {
|
|
65
|
+
listener.handlePointerUp(event);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const registerDroppableListener = (listener: DroppableListener): void => {
|
|
70
|
+
if (droppableListeners.size === 0) {
|
|
71
|
+
document.addEventListener(
|
|
72
|
+
'pointermove',
|
|
73
|
+
handleDocumentPointerMove,
|
|
74
|
+
passivePointerMoveListenerOptions
|
|
75
|
+
);
|
|
76
|
+
document.addEventListener('pointerup', handleDocumentPointerUp);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
droppableListeners.add(listener);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const unregisterDroppableListener = (listener: DroppableListener): void => {
|
|
83
|
+
droppableListeners.delete(listener);
|
|
84
|
+
|
|
85
|
+
if (droppableListeners.size !== 0) return;
|
|
86
|
+
|
|
87
|
+
document.removeEventListener('pointermove', handleDocumentPointerMove);
|
|
88
|
+
document.removeEventListener('pointerup', handleDocumentPointerUp);
|
|
89
|
+
if (pointerMoveFrame !== null) {
|
|
90
|
+
cancelAnimationFrame(pointerMoveFrame);
|
|
91
|
+
pointerMoveFrame = null;
|
|
92
|
+
}
|
|
93
|
+
queuedPointerMove = null;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Checks whether a dragged element is accepted by the drop zone.
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
const isAccepted = (dragged: HTMLElement, accept: DroppableOptions['accept']): boolean => {
|
|
101
|
+
if (!accept) return true;
|
|
102
|
+
if (typeof accept === 'string') return dragged.matches(accept);
|
|
103
|
+
return accept(dragged);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Defines an element as a drop zone.
|
|
108
|
+
*
|
|
109
|
+
* Drop zones respond to draggable elements being moved over them
|
|
110
|
+
* by firing callbacks and applying CSS classes. They work with
|
|
111
|
+
* the `draggable()` function from this module.
|
|
112
|
+
*
|
|
113
|
+
* @param el - The drop zone element
|
|
114
|
+
* @param options - Configuration options
|
|
115
|
+
* @returns A handle with a `destroy()` method
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import { droppable } from '@bquery/bquery/dnd';
|
|
120
|
+
*
|
|
121
|
+
* const handle = droppable(document.querySelector('#dropzone'), {
|
|
122
|
+
* accept: '.draggable-item',
|
|
123
|
+
* overClass: 'drop-active',
|
|
124
|
+
* onDrop: ({ dragged }) => {
|
|
125
|
+
* console.log('Dropped:', dragged);
|
|
126
|
+
* },
|
|
127
|
+
* });
|
|
128
|
+
*
|
|
129
|
+
* // Later:
|
|
130
|
+
* handle.destroy();
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export const droppable = (el: HTMLElement, options: DroppableOptions = {}): DroppableHandle => {
|
|
134
|
+
const {
|
|
135
|
+
overClass = 'bq-drop-over',
|
|
136
|
+
accept,
|
|
137
|
+
onDragEnter,
|
|
138
|
+
onDragOver,
|
|
139
|
+
onDragLeave,
|
|
140
|
+
onDrop,
|
|
141
|
+
} = options;
|
|
142
|
+
|
|
143
|
+
if (!hasDroppableEnvironment()) {
|
|
144
|
+
return {
|
|
145
|
+
destroy: () => {},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let isOver = false;
|
|
150
|
+
let currentDragged: HTMLElement | null = null;
|
|
151
|
+
|
|
152
|
+
const createEventData = (dragged: HTMLElement, event: PointerEvent): DropEventData => ({
|
|
153
|
+
zone: el,
|
|
154
|
+
dragged,
|
|
155
|
+
event,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const isPointerInside = (event: PointerEvent): boolean => {
|
|
159
|
+
const rect = el.getBoundingClientRect();
|
|
160
|
+
return (
|
|
161
|
+
event.clientX >= rect.left &&
|
|
162
|
+
event.clientX <= rect.right &&
|
|
163
|
+
event.clientY >= rect.top &&
|
|
164
|
+
event.clientY <= rect.bottom
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const resolveDraggedElement = (): HTMLElement | null => {
|
|
169
|
+
return getActiveDrag()?.element ?? currentDragged;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const clearOverState = (event: PointerEvent, dragged = currentDragged): void => {
|
|
173
|
+
if (!isOver) return;
|
|
174
|
+
isOver = false;
|
|
175
|
+
el.classList.remove(overClass);
|
|
176
|
+
if (dragged) {
|
|
177
|
+
onDragLeave?.(createEventData(dragged, event));
|
|
178
|
+
}
|
|
179
|
+
currentDragged = null;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const handlePointerMove = (e: PointerEvent): void => {
|
|
183
|
+
const dragged = getActiveDrag()?.element ?? null;
|
|
184
|
+
const isInside = isPointerInside(e);
|
|
185
|
+
const acceptsDragged = dragged !== null && dragged !== el && isAccepted(dragged, accept);
|
|
186
|
+
|
|
187
|
+
if (!acceptsDragged || !isInside) {
|
|
188
|
+
clearOverState(e, dragged ?? currentDragged);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!isOver) {
|
|
193
|
+
isOver = true;
|
|
194
|
+
currentDragged = dragged;
|
|
195
|
+
el.classList.add(overClass);
|
|
196
|
+
onDragEnter?.(createEventData(dragged, e));
|
|
197
|
+
} else {
|
|
198
|
+
onDragOver?.(createEventData(dragged, e));
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const handlePointerUp = (e: PointerEvent): void => {
|
|
203
|
+
const dragged = resolveDraggedElement();
|
|
204
|
+
const isInside = isPointerInside(e);
|
|
205
|
+
const acceptsDragged = dragged !== null && dragged !== el && isAccepted(dragged, accept);
|
|
206
|
+
|
|
207
|
+
if (isInside && acceptsDragged && dragged) {
|
|
208
|
+
onDrop?.(createEventData(dragged, e));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (isOver) {
|
|
212
|
+
isOver = false;
|
|
213
|
+
el.classList.remove(overClass);
|
|
214
|
+
}
|
|
215
|
+
currentDragged = null;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const listener: DroppableListener = { handlePointerMove, handlePointerUp };
|
|
219
|
+
registerDroppableListener(listener);
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
destroy: () => {
|
|
223
|
+
unregisterDroppableListener(listener);
|
|
224
|
+
el.classList.remove(overClass);
|
|
225
|
+
currentDragged = null;
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
};
|
package/src/dnd/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bQuery Drag & Drop module.
|
|
3
|
+
*
|
|
4
|
+
* Provides pointer-event-based drag-and-drop, drop zones, and sortable
|
|
5
|
+
* lists with built-in touch support, axis locking, bounds constraints,
|
|
6
|
+
* and animated reordering.
|
|
7
|
+
*
|
|
8
|
+
* @module bquery/dnd
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { draggable, droppable, sortable } from '@bquery/bquery/dnd';
|
|
13
|
+
*
|
|
14
|
+
* // Make an element draggable
|
|
15
|
+
* const drag = draggable(document.querySelector('#box'), {
|
|
16
|
+
* axis: 'both',
|
|
17
|
+
* bounds: 'parent',
|
|
18
|
+
* ghost: true,
|
|
19
|
+
* onDragEnd: ({ position }) => console.log(position),
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Define a drop zone
|
|
23
|
+
* const drop = droppable(document.querySelector('#zone'), {
|
|
24
|
+
* accept: '.draggable',
|
|
25
|
+
* onDrop: ({ dragged }) => console.log('Dropped!', dragged),
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // Make a list sortable
|
|
29
|
+
* const sort = sortable(document.querySelector('#list'), {
|
|
30
|
+
* items: 'li',
|
|
31
|
+
* axis: 'y',
|
|
32
|
+
* onSortEnd: ({ oldIndex, newIndex }) => {
|
|
33
|
+
* console.log(`Moved from ${oldIndex} to ${newIndex}`);
|
|
34
|
+
* },
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* // Cleanup when done
|
|
38
|
+
* drag.destroy();
|
|
39
|
+
* drop.destroy();
|
|
40
|
+
* sort.destroy();
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
export { draggable } from './draggable';
|
|
45
|
+
export { droppable } from './droppable';
|
|
46
|
+
export { sortable } from './sortable';
|
|
47
|
+
|
|
48
|
+
export type {
|
|
49
|
+
BoundsRect,
|
|
50
|
+
DragAxis,
|
|
51
|
+
DragBounds,
|
|
52
|
+
DragEventData,
|
|
53
|
+
DragPosition,
|
|
54
|
+
DraggableHandle,
|
|
55
|
+
DraggableOptions,
|
|
56
|
+
DropEventData,
|
|
57
|
+
DroppableHandle,
|
|
58
|
+
DroppableOptions,
|
|
59
|
+
SortEventData,
|
|
60
|
+
SortableHandle,
|
|
61
|
+
SortableOptions,
|
|
62
|
+
} from './types';
|