sygnal 5.3.7 → 6.0.0
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/CHANGELOG.md +646 -0
- package/README.md +77 -47
- package/dist/astro/client.cjs.js +33 -8114
- package/dist/astro/client.cjs.js.map +1 -0
- package/dist/astro/client.mjs +33 -8114
- package/dist/astro/client.mjs.map +1 -0
- package/dist/astro/index.cjs.js +1039 -9
- package/dist/astro/index.cjs.js.map +1 -0
- package/dist/astro/index.mjs +1038 -9
- package/dist/astro/index.mjs.map +1 -0
- package/dist/astro/server.cjs.js +3400 -166
- package/dist/astro/server.cjs.js.map +1 -0
- package/dist/astro/server.mjs +3400 -166
- package/dist/astro/server.mjs.map +1 -0
- package/dist/devtools.cjs.js +1431 -0
- package/dist/devtools.cjs.js.map +1 -0
- package/dist/devtools.esm.js +1419 -0
- package/dist/devtools.esm.js.map +1 -0
- package/dist/diagnostics.cjs.js +4033 -0
- package/dist/diagnostics.cjs.js.map +1 -0
- package/dist/diagnostics.esm.js +4003 -0
- package/dist/diagnostics.esm.js.map +1 -0
- package/dist/element.cjs.js +230 -0
- package/dist/element.cjs.js.map +1 -0
- package/dist/element.esm.js +228 -0
- package/dist/element.esm.js.map +1 -0
- package/dist/guide/accessibility.md +257 -0
- package/dist/guide/adapters.md +221 -0
- package/dist/guide/behaviors.md +312 -0
- package/dist/guide/browser-sources.md +203 -0
- package/dist/guide/drag-and-drop.md +342 -0
- package/dist/guide/element-commands.md +306 -0
- package/dist/guide/error-boundaries.md +169 -0
- package/dist/guide/forms-reference.md +381 -0
- package/dist/guide/forms.md +250 -0
- package/dist/guide/http.md +299 -0
- package/dist/guide/inputs.md +173 -0
- package/dist/guide/persistence.md +245 -0
- package/dist/guide/recipes/carousel.md +155 -0
- package/dist/guide/recipes/charts.md +177 -0
- package/dist/guide/recipes/code-editor.md +135 -0
- package/dist/guide/recipes/data-grid.md +155 -0
- package/dist/guide/recipes/data-table.md +196 -0
- package/dist/guide/recipes/i18n.md +222 -0
- package/dist/guide/recipes/icons.md +115 -0
- package/dist/guide/recipes/overview.md +33 -0
- package/dist/guide/recipes/rich-text.md +154 -0
- package/dist/guide/resources.md +471 -0
- package/dist/guide/ssr.md +255 -0
- package/dist/guide/timers.md +178 -0
- package/dist/guide/ui/accordion.md +93 -0
- package/dist/guide/ui/combobox.md +144 -0
- package/dist/guide/ui/dialog.md +124 -0
- package/dist/guide/ui/disclosure.md +60 -0
- package/dist/guide/ui/menu.md +125 -0
- package/dist/guide/ui/overview.md +166 -0
- package/dist/guide/ui/popover.md +101 -0
- package/dist/guide/ui/select.md +114 -0
- package/dist/guide/ui/tabs.md +161 -0
- package/dist/guide/ui/toaster.md +152 -0
- package/dist/guide/ui/tooltip.md +103 -0
- package/dist/guide/undo.md +178 -0
- package/dist/guide/virtual-collections.md +183 -0
- package/dist/guide/web-components.md +179 -0
- package/dist/guide/widgets.md +217 -0
- package/dist/index.cjs.js +15283 -6279
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +3739 -370
- package/dist/index.esm.js +15230 -6274
- package/dist/index.esm.js.map +1 -0
- package/dist/jsx-dev-runtime.cjs.js +27 -329
- package/dist/jsx-dev-runtime.cjs.js.map +1 -0
- package/dist/jsx-dev-runtime.esm.js +20 -322
- package/dist/jsx-dev-runtime.esm.js.map +1 -0
- package/dist/jsx-runtime.cjs.js +27 -329
- package/dist/jsx-runtime.cjs.js.map +1 -0
- package/dist/jsx-runtime.esm.js +20 -322
- package/dist/jsx-runtime.esm.js.map +1 -0
- package/dist/jsx.cjs.js +11 -309
- package/dist/jsx.cjs.js.map +1 -0
- package/dist/jsx.esm.js +9 -310
- package/dist/jsx.esm.js.map +1 -0
- package/dist/react.cjs.js +117 -0
- package/dist/react.cjs.js.map +1 -0
- package/dist/react.esm.js +115 -0
- package/dist/react.esm.js.map +1 -0
- package/dist/shims/globalthis.cjs +20 -0
- package/dist/sygnal.min.js +2 -1
- package/dist/sygnal.min.js.map +1 -0
- package/dist/ui-combobox.cjs.js +169 -0
- package/dist/ui-combobox.cjs.js.map +1 -0
- package/dist/ui-combobox.esm.js +148 -0
- package/dist/ui-combobox.esm.js.map +1 -0
- package/dist/ui-menu.cjs.js +87 -0
- package/dist/ui-menu.cjs.js.map +1 -0
- package/dist/ui-menu.esm.js +66 -0
- package/dist/ui-menu.esm.js.map +1 -0
- package/dist/ui-select.cjs.js +104 -0
- package/dist/ui-select.cjs.js.map +1 -0
- package/dist/ui-select.esm.js +83 -0
- package/dist/ui-select.esm.js.map +1 -0
- package/dist/ui.cjs.js +738 -0
- package/dist/ui.cjs.js.map +1 -0
- package/dist/ui.esm.js +727 -0
- package/dist/ui.esm.js.map +1 -0
- package/dist/vike/ClientOnly.cjs.js +5 -14
- package/dist/vike/ClientOnly.cjs.js.map +1 -0
- package/dist/vike/ClientOnly.mjs +5 -14
- package/dist/vike/ClientOnly.mjs.map +1 -0
- package/dist/vike/{+config.js → config/+config.js} +10 -1
- package/dist/vike/config/+config.js.map +1 -0
- package/dist/vike/config/package.json +6 -0
- package/dist/vike/onRenderClient.cjs.js +166 -95
- package/dist/vike/onRenderClient.cjs.js.map +1 -0
- package/dist/vike/onRenderClient.mjs +166 -95
- package/dist/vike/onRenderClient.mjs.map +1 -0
- package/dist/vike/onRenderHtml.cjs.js +60 -24
- package/dist/vike/onRenderHtml.cjs.js.map +1 -0
- package/dist/vike/onRenderHtml.mjs +61 -25
- package/dist/vike/onRenderHtml.mjs.map +1 -0
- package/dist/vite/plugin.cjs.js +926 -65
- package/dist/vite/plugin.cjs.js.map +1 -0
- package/dist/vite/plugin.mjs +925 -65
- package/dist/vite/plugin.mjs.map +1 -0
- package/dist/zag.cjs.js +408 -0
- package/dist/zag.cjs.js.map +1 -0
- package/dist/zag.esm.js +405 -0
- package/dist/zag.esm.js.map +1 -0
- package/llms.txt +313 -0
- package/package.json +109 -16
- package/src/astro/client.ts +40 -18
- package/src/astro/index.d.ts +48 -1
- package/src/astro/index.ts +106 -9
- package/src/astro/server.ts +11 -3
- package/src/collection.ts +6 -90
- package/src/core/actions.ts +134 -0
- package/src/core/cell.ts +202 -0
- package/src/core/debug.ts +23 -0
- package/src/core/define.ts +242 -0
- package/src/core/hooks.ts +314 -0
- package/src/core/hosts/collection.ts +325 -0
- package/src/core/hosts/switchable.ts +146 -0
- package/src/core/instance.ts +592 -0
- package/src/core/markers/clientonly.ts +13 -0
- package/src/core/markers/lazy.ts +40 -0
- package/src/core/markers/portal.ts +96 -0
- package/src/core/markers/suspense.ts +41 -0
- package/src/core/markers/transition.ts +70 -0
- package/src/core/registry.ts +25 -0
- package/src/core/runtime.ts +573 -0
- package/src/core/statics.ts +104 -0
- package/src/core/teardown.ts +60 -0
- package/src/core/view.ts +37 -0
- package/src/cycle/dom/DocumentDOMSource.ts +13 -8
- package/src/cycle/dom/ElementFinder.ts +7 -9
- package/src/cycle/dom/EventDelegator.ts +174 -223
- package/src/cycle/dom/IsolateModule.ts +65 -35
- package/src/cycle/dom/MainDOMSource.ts +13 -2
- package/src/cycle/dom/PriorityQueue.ts +4 -2
- package/src/cycle/dom/SymbolTree.ts +18 -47
- package/src/cycle/dom/classNameModule.ts +76 -0
- package/src/cycle/dom/controlledInputModule.ts +50 -0
- package/src/cycle/dom/enrichEventStream.ts +29 -45
- package/src/cycle/dom/fragment.ts +7 -0
- package/src/cycle/dom/isolate.ts +30 -27
- package/src/cycle/dom/makeDOMDriver.ts +115 -57
- package/src/cycle/dom/mockDOMSource.ts +83 -9
- package/src/cycle/dom/modules.ts +21 -4
- package/src/cycle/dom/propsModule.ts +65 -0
- package/src/cycle/dom/selectModule.ts +22 -17
- package/src/cycle/dom/snabbdom.ts +1 -6
- package/src/cycle/dom/thunk.ts +3 -0
- package/src/cycle/dom/utils.ts +98 -0
- package/src/cycle/dom/viewTransition.ts +43 -0
- package/src/cycle/state/StateSource.ts +20 -4
- package/src/cycle/state/objIsEqual.ts +50 -0
- package/src/cycle/state/types.ts +0 -10
- package/src/defineComponent.ts +34 -0
- package/src/devtools.d.ts +151 -0
- package/src/devtools.ts +34 -0
- package/src/element.d.ts +59 -0
- package/src/element.ts +235 -0
- package/src/extra/backoff.ts +9 -0
- package/src/extra/behaviors.ts +169 -0
- package/src/extra/browserSignals.ts +23 -0
- package/src/extra/browserSources.ts +326 -0
- package/src/extra/command.ts +3 -3
- package/src/extra/controls.ts +47 -0
- package/src/extra/copyAsTest.ts +286 -0
- package/src/extra/devtools.ts +109 -31
- package/src/extra/devtoolsActions.ts +379 -0
- package/src/extra/devtoolsHook.ts +9 -0
- package/src/extra/devtoolsNext.ts +83 -0
- package/src/extra/diagnostics/checks/actionLog.ts +108 -0
- package/src/extra/diagnostics/checks/behaviors.ts +49 -0
- package/src/extra/diagnostics/checks/browserSources.ts +96 -0
- package/src/extra/diagnostics/checks/collections.ts +67 -0
- package/src/extra/diagnostics/checks/controls.ts +148 -0
- package/src/extra/diagnostics/checks/dataset.ts +57 -0
- package/src/extra/diagnostics/checks/dom.ts +250 -0
- package/src/extra/diagnostics/checks/elementCommands.ts +175 -0
- package/src/extra/diagnostics/checks/events.ts +83 -0
- package/src/extra/diagnostics/checks/fetch.ts +135 -0
- package/src/extra/diagnostics/checks/forms.ts +163 -0
- package/src/extra/diagnostics/checks/index.ts +202 -0
- package/src/extra/diagnostics/checks/inspect.ts +427 -0
- package/src/extra/diagnostics/checks/next.ts +417 -0
- package/src/extra/diagnostics/checks/persist.ts +54 -0
- package/src/extra/diagnostics/checks/props.ts +56 -0
- package/src/extra/diagnostics/checks/public.d.ts +302 -0
- package/src/extra/diagnostics/checks/replies.ts +128 -0
- package/src/extra/diagnostics/checks/router.ts +100 -0
- package/src/extra/diagnostics/checks/rxjsHints.ts +88 -0
- package/src/extra/diagnostics/checks/shared.ts +203 -0
- package/src/extra/diagnostics/checks/shorthand.ts +115 -0
- package/src/extra/diagnostics/checks/sortable.ts +129 -0
- package/src/extra/diagnostics/checks/state.ts +148 -0
- package/src/extra/diagnostics/checks/statics.ts +48 -0
- package/src/extra/diagnostics/checks/strict.ts +55 -0
- package/src/extra/diagnostics/checks/timers.ts +80 -0
- package/src/extra/diagnostics/checks/viewTransitions.ts +47 -0
- package/src/extra/diagnostics/checks/virtual.ts +73 -0
- package/src/extra/diagnostics/checks/widgets.ts +109 -0
- package/src/extra/diagnostics/checks/wiring.ts +121 -0
- package/src/extra/diagnostics/codes.ts +477 -0
- package/src/extra/diagnostics/index.ts +353 -0
- package/src/extra/diagnostics/legacy.ts +76 -0
- package/src/extra/driverFactories.ts +172 -60
- package/src/extra/elementCommands.ts +53 -0
- package/src/extra/eventDriver.ts +4 -0
- package/src/extra/fetchDriver.ts +519 -0
- package/src/extra/flatten.ts +75 -0
- package/src/extra/focusWithin.ts +27 -0
- package/src/extra/form.ts +268 -0
- package/src/extra/formHelpers.ts +139 -0
- package/src/extra/head.ts +106 -0
- package/src/extra/hmr.ts +2 -3
- package/src/extra/owned.ts +24 -0
- package/src/extra/pager.ts +50 -0
- package/src/extra/persist.ts +133 -0
- package/src/extra/pwa.ts +1 -1
- package/src/extra/queryCache.ts +107 -0
- package/src/extra/reducers.ts +13 -6
- package/src/extra/reduxDevtools.ts +92 -0
- package/src/extra/replies.ts +54 -0
- package/src/extra/router.ts +323 -0
- package/src/extra/run.ts +94 -210
- package/src/extra/selection.ts +76 -0
- package/src/extra/socketDriver.ts +265 -0
- package/src/extra/sortable.ts +377 -0
- package/src/extra/ssr.ts +427 -160
- package/src/extra/standardSchema.ts +27 -0
- package/src/extra/testing.ts +3158 -190
- package/src/extra/timers.ts +95 -0
- package/src/extra/undo.ts +261 -0
- package/src/extra/viewTransitions.ts +38 -0
- package/src/extra/virtual.ts +513 -0
- package/src/extra/widget.ts +201 -0
- package/src/extra/xstreamExtras.ts +269 -0
- package/src/index.d.ts +3012 -87
- package/src/index.ts +32 -10
- package/src/jsx-runtime.ts +15 -1
- package/src/jsx.ts +2 -1
- package/src/lazy.ts +50 -7
- package/src/portal.ts +3 -1
- package/src/pragma/index.ts +262 -134
- package/src/react-peers.d.ts +5 -0
- package/src/react.d.ts +43 -0
- package/src/react.ts +110 -0
- package/src/shared.ts +48 -0
- package/src/slot.ts +1 -1
- package/src/suspense.ts +3 -1
- package/src/switchable.ts +6 -119
- package/src/transition.ts +3 -1
- package/src/ui/accordion.ts +64 -0
- package/src/ui/dialog.ts +129 -0
- package/src/ui/disclosure.ts +35 -0
- package/src/ui/popover.ts +45 -0
- package/src/ui/shared.ts +94 -0
- package/src/ui/tabs.ts +82 -0
- package/src/ui/toaster.ts +198 -0
- package/src/ui/tooltip.ts +70 -0
- package/src/ui/zag/combobox.ts +115 -0
- package/src/ui/zag/menu.ts +40 -0
- package/src/ui/zag/select.ts +54 -0
- package/src/ui/zag/shared.ts +43 -0
- package/src/ui-combobox.d.ts +20 -0
- package/src/ui-combobox.ts +6 -0
- package/src/ui-menu.d.ts +30 -0
- package/src/ui-menu.ts +6 -0
- package/src/ui-select.d.ts +17 -0
- package/src/ui-select.ts +6 -0
- package/src/ui-zag-types.d.ts +42 -0
- package/src/ui.d.ts +208 -0
- package/src/ui.ts +15 -0
- package/src/vike/+config.ts +9 -1
- package/src/vike/ClientOnly.ts +1 -1
- package/src/vike/onRenderClient.ts +144 -96
- package/src/vike/onRenderHtml.ts +69 -26
- package/src/vike/types.ts +27 -4
- package/src/vite/globalthis-shim.ts +18 -0
- package/src/vite/globalthis.ts +56 -0
- package/src/vite/plugin.d.ts +114 -2
- package/src/vite/plugin.ts +920 -56
- package/src/zag.d.ts +64 -0
- package/src/zag.ts +238 -0
- package/dist/astro/astro/client.d.ts +0 -5
- package/dist/astro/astro/index.d.ts +0 -16
- package/dist/astro/astro/server.d.ts +0 -12
- package/dist/astro/client.d.ts +0 -5
- package/dist/astro/client.esm.js +0 -4665
- package/dist/astro/collection.d.ts +0 -12
- package/dist/astro/component.d.ts +0 -22
- package/dist/astro/cycle/dom/BodyDOMSource.d.ts +0 -10
- package/dist/astro/cycle/dom/DOMSource.d.ts +0 -11
- package/dist/astro/cycle/dom/DocumentDOMSource.d.ts +0 -12
- package/dist/astro/cycle/dom/ElementFinder.d.ts +0 -8
- package/dist/astro/cycle/dom/EventDelegator.d.ts +0 -34
- package/dist/astro/cycle/dom/IsolateModule.d.ts +0 -23
- package/dist/astro/cycle/dom/MainDOMSource.d.ts +0 -32
- package/dist/astro/cycle/dom/PriorityQueue.d.ts +0 -7
- package/dist/astro/cycle/dom/ScopeChecker.d.ts +0 -9
- package/dist/astro/cycle/dom/SymbolTree.d.ts +0 -9
- package/dist/astro/cycle/dom/VNodeWrapper.d.ts +0 -8
- package/dist/astro/cycle/dom/enrichEventStream.d.ts +0 -24
- package/dist/astro/cycle/dom/fromEvent.d.ts +0 -6
- package/dist/astro/cycle/dom/index.d.ts +0 -8
- package/dist/astro/cycle/dom/isolate.d.ts +0 -9
- package/dist/astro/cycle/dom/makeDOMDriver.d.ts +0 -11
- package/dist/astro/cycle/dom/mockDOMSource.d.ts +0 -17
- package/dist/astro/cycle/dom/modules.d.ts +0 -5
- package/dist/astro/cycle/dom/snabbdom.d.ts +0 -22
- package/dist/astro/cycle/dom/styleModule.d.ts +0 -13
- package/dist/astro/cycle/dom/thunk.d.ts +0 -11
- package/dist/astro/cycle/dom/utils.d.ts +0 -8
- package/dist/astro/cycle/isolate/index.d.ts +0 -42
- package/dist/astro/cycle/run/adapt.d.ts +0 -6
- package/dist/astro/cycle/run/index.d.ts +0 -36
- package/dist/astro/cycle/run/internals.d.ts +0 -8
- package/dist/astro/cycle/run/types.d.ts +0 -49
- package/dist/astro/cycle/state/Collection.d.ts +0 -29
- package/dist/astro/cycle/state/StateSource.d.ts +0 -20
- package/dist/astro/cycle/state/index.d.ts +0 -5
- package/dist/astro/cycle/state/pickCombine.d.ts +0 -3
- package/dist/astro/cycle/state/pickMerge.d.ts +0 -3
- package/dist/astro/cycle/state/types.d.ts +0 -18
- package/dist/astro/cycle/state/withState.d.ts +0 -17
- package/dist/astro/extra/classes.d.ts +0 -7
- package/dist/astro/extra/devtools.d.ts +0 -78
- package/dist/astro/extra/dragDriver.d.ts +0 -20
- package/dist/astro/extra/driverFactories.d.ts +0 -12
- package/dist/astro/extra/eventDriver.d.ts +0 -9
- package/dist/astro/extra/exactState.d.ts +0 -1
- package/dist/astro/extra/hmr.d.ts +0 -17
- package/dist/astro/extra/logDriver.d.ts +0 -2
- package/dist/astro/extra/processDrag.d.ts +0 -19
- package/dist/astro/extra/processForm.d.ts +0 -15
- package/dist/astro/extra/run.d.ts +0 -13
- package/dist/astro/extra/xstreamCompat.d.ts +0 -5
- package/dist/astro/index.d.ts +0 -19
- package/dist/astro/index.esm.js +0 -27
- package/dist/astro/jsx-dev-runtime.d.ts +0 -1
- package/dist/astro/jsx-runtime.d.ts +0 -4
- package/dist/astro/jsx.d.ts +0 -2
- package/dist/astro/pragma/fn.d.ts +0 -7
- package/dist/astro/pragma/index.d.ts +0 -7
- package/dist/astro/pragma/is.d.ts +0 -10
- package/dist/astro/server.d.ts +0 -12
- package/dist/astro/server.esm.js +0 -25
- package/dist/astro/switchable.d.ts +0 -7
- package/dist/collection.d.ts +0 -12
- package/dist/component.d.ts +0 -22
- package/dist/cycle/dom/BodyDOMSource.d.ts +0 -10
- package/dist/cycle/dom/DOMSource.d.ts +0 -11
- package/dist/cycle/dom/DocumentDOMSource.d.ts +0 -12
- package/dist/cycle/dom/ElementFinder.d.ts +0 -8
- package/dist/cycle/dom/EventDelegator.d.ts +0 -34
- package/dist/cycle/dom/IsolateModule.d.ts +0 -23
- package/dist/cycle/dom/MainDOMSource.d.ts +0 -32
- package/dist/cycle/dom/PriorityQueue.d.ts +0 -7
- package/dist/cycle/dom/ScopeChecker.d.ts +0 -9
- package/dist/cycle/dom/SymbolTree.d.ts +0 -9
- package/dist/cycle/dom/VNodeWrapper.d.ts +0 -8
- package/dist/cycle/dom/enrichEventStream.d.ts +0 -24
- package/dist/cycle/dom/fromEvent.d.ts +0 -6
- package/dist/cycle/dom/index.d.ts +0 -8
- package/dist/cycle/dom/isolate.d.ts +0 -9
- package/dist/cycle/dom/makeDOMDriver.d.ts +0 -11
- package/dist/cycle/dom/mockDOMSource.d.ts +0 -17
- package/dist/cycle/dom/modules.d.ts +0 -5
- package/dist/cycle/dom/snabbdom.d.ts +0 -22
- package/dist/cycle/dom/styleModule.d.ts +0 -13
- package/dist/cycle/dom/thunk.d.ts +0 -11
- package/dist/cycle/dom/utils.d.ts +0 -8
- package/dist/cycle/isolate/index.d.ts +0 -42
- package/dist/cycle/run/adapt.d.ts +0 -6
- package/dist/cycle/run/index.d.ts +0 -36
- package/dist/cycle/run/internals.d.ts +0 -8
- package/dist/cycle/run/types.d.ts +0 -49
- package/dist/cycle/state/Collection.d.ts +0 -29
- package/dist/cycle/state/StateSource.d.ts +0 -20
- package/dist/cycle/state/index.d.ts +0 -5
- package/dist/cycle/state/pickCombine.d.ts +0 -3
- package/dist/cycle/state/pickMerge.d.ts +0 -3
- package/dist/cycle/state/types.d.ts +0 -18
- package/dist/cycle/state/withState.d.ts +0 -17
- package/dist/extra/classes.d.ts +0 -7
- package/dist/extra/devtools.d.ts +0 -78
- package/dist/extra/dragDriver.d.ts +0 -20
- package/dist/extra/driverFactories.d.ts +0 -12
- package/dist/extra/eventDriver.d.ts +0 -9
- package/dist/extra/exactState.d.ts +0 -1
- package/dist/extra/hmr.d.ts +0 -17
- package/dist/extra/logDriver.d.ts +0 -2
- package/dist/extra/processDrag.d.ts +0 -19
- package/dist/extra/processForm.d.ts +0 -15
- package/dist/extra/run.d.ts +0 -13
- package/dist/extra/xstreamCompat.d.ts +0 -5
- package/dist/jsx-dev-runtime.d.ts +0 -1
- package/dist/jsx-dev-runtime.js +0 -224
- package/dist/jsx-runtime.d.ts +0 -4
- package/dist/jsx-runtime.js +0 -224
- package/dist/jsx.d.ts +0 -2
- package/dist/pragma/fn.d.ts +0 -7
- package/dist/pragma/index.d.ts +0 -7
- package/dist/pragma/is.d.ts +0 -10
- package/dist/switchable.d.ts +0 -7
- package/dist/vike/+config.cjs.js +0 -65
- package/src/component.ts +0 -2256
- package/src/cycle/isolate/index.ts +0 -196
- package/src/cycle/run/index.ts +0 -151
- package/src/cycle/run/internals.ts +0 -143
- package/src/cycle/state/Collection.ts +0 -174
- package/src/cycle/state/index.ts +0 -5
- package/src/cycle/state/pickCombine.ts +0 -167
- package/src/cycle/state/pickMerge.ts +0 -122
- package/src/cycle/state/withState.ts +0 -47
- package/src/pragma/fn.ts +0 -55
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PLAN-5 B-1 (3-D): the `sortable` behavior, drag-and-drop reordering of a host's list by pointer
|
|
3
|
+
* (mouse, pen, touch) and keyboard. Spike 0-S5, rebuilt on D197 (HOST reducers, the key in the
|
|
4
|
+
* handlers) and D194 (focusWithin).
|
|
5
|
+
*
|
|
6
|
+
* List.uses = { sort: sortable({ from: 'tasks', item: '.task', handle: '.grip' }) }
|
|
7
|
+
* List.context = { sort: (state) => state.sort } // items read the drag state
|
|
8
|
+
* List.model = { 'sort.DROPPED': { EFFECT: … } } // save the order
|
|
9
|
+
* <ul><Collection of={Task} from="tasks" /></ul>
|
|
10
|
+
* <p role="status" aria-live="assertive">{state.sort.message}</p>
|
|
11
|
+
* // Task: <li className="task" data-id={state.id}>
|
|
12
|
+
* // <button className="grip" aria-label={…} aria-describedby={context.sort.helpId}>⠿</button>…
|
|
13
|
+
*
|
|
14
|
+
* Slice (state.sort): { dragging, over, after, list, mode, press, origin, message, helpId }
|
|
15
|
+
* dragging the id (a string) of the item being moved, or null
|
|
16
|
+
* over the id the pointer is over (pointer mode; null over a gap or outside the list)
|
|
17
|
+
* after true: the item lands after `over`, false: before it
|
|
18
|
+
* list the `from` key the item would land in (pointer: `over`'s list, or a `data-list`
|
|
19
|
+
* container; keyboard: unused)
|
|
20
|
+
* mode 'pointer' | 'keyboard' | null
|
|
21
|
+
* message the text for an ARIA live region (lift / move / drop / cancel)
|
|
22
|
+
* helpId a uid() id for the instructions element the handles' aria-describedby names:
|
|
23
|
+
* unique per host instance, null until the first focus, press or key inside the
|
|
24
|
+
* host (G-448: nothing is written at startup). The server renders none, nor does
|
|
25
|
+
* the client's first render, so hydration matches (G-453); a focused handle has it
|
|
26
|
+
* press, origin: internal (the pointer press before the threshold; where the item started)
|
|
27
|
+
* Actions: sort.PRESS, MOVE, UP, CANCEL (pointer), KEY (keyboard), INIT (the start), HELP, END
|
|
28
|
+
* (unmounted: a drag in progress is cancelled; INIT and a press or key over drag state another
|
|
29
|
+
* instance started do the same, G-475), and sort.DROPPED ({ id, list, index, fromList, fromIndex })
|
|
30
|
+
* once per completed move: the host adds an entry for it to save the order.
|
|
31
|
+
*
|
|
32
|
+
* A keyboard drag that ends without a drop (Escape, END, INIT, `live`) restores (D219, 3-P) only
|
|
33
|
+
* when the lists are exactly the arrays its last step made (identity, kept in `drags` under the
|
|
34
|
+
* drag's `origin` object, never in the state): it puts back the lists it lifted from (no index
|
|
35
|
+
* math). Anything else that changed them (undo, an edit, an ADD, new data, a restored or synced
|
|
36
|
+
* slice: its `origin` is another object) leaves the item where it is, and the drag just ends. The
|
|
37
|
+
* slice such an end leaves is marked (`ended`), as is a keyboard drop where the item started (no
|
|
38
|
+
* DROPPED, 3-W G-535): undo() reads it through `undoEnd` (internal) and settles the gesture's
|
|
39
|
+
* pending base (G-510).
|
|
40
|
+
*
|
|
41
|
+
* Pointer feedback is an indicator (over / after) while the pointer moves; the list is reordered
|
|
42
|
+
* on the drop. Keyboard moves reorder live (the arrow keys), and Escape puts the item back.
|
|
43
|
+
*
|
|
44
|
+
* Collection items are isolated, so the behavior listens on the host's ROOT (`DOM.events`), which
|
|
45
|
+
* hears the events that bubble out of the items (G-145), and reads the item from
|
|
46
|
+
* `target.closest(item)` and its id from `attr`. Pointer moves, the release, Escape, `selectstart`
|
|
47
|
+
* and `dragstart` (no text selection, no native drag while pressed) are document listeners, subscribed only while
|
|
48
|
+
* a press or a drag is active. The item under the pointer comes from `elementFromPoint` (a touch
|
|
49
|
+
* pointer is implicitly captured by the pressed element, so its events keep that target); no
|
|
50
|
+
* pointer capture.
|
|
51
|
+
*
|
|
52
|
+
* Nested sortables: an event is claimed by the first (innermost) sortable host it bubbles
|
|
53
|
+
* through, so an outer sortable ignores the items of an inner one. A host's own items are the
|
|
54
|
+
* item elements below its root that aren't inside another item below it (an item inside an item
|
|
55
|
+
* belongs to a nested list, whose ids may repeat this host's: G-444/G-445): the press, key, the
|
|
56
|
+
* item under the pointer (the outermost one there) and the focus target are resolved among them.
|
|
57
|
+
*
|
|
58
|
+
* Focus: each keyboard step (but Tab) sends `{ focus: <target> }`, a focusWithin-style target
|
|
59
|
+
* (D194: `within` '<item>[<attr>="<id>"] <handle>', the first match among this host's own items):
|
|
60
|
+
* the keyed Collection may move the focused node when the list reorders. A keyboard
|
|
61
|
+
* drag drops at its current position when focus moves to another element (Tab, a click
|
|
62
|
+
* elsewhere: focusout with a relatedTarget) or on any pointer press (a press on a handle then
|
|
63
|
+
* starts a pointer press at once, G-451); focus lost to nothing (the window, a node move) keeps
|
|
64
|
+
* the drag.
|
|
65
|
+
*
|
|
66
|
+
* Dev diagnostics through the core bridge's `sortable` hook (checks/sortable.ts): SYG145 an item
|
|
67
|
+
* without `attr`, SYG146 `item` / `handle` matching nothing under the host at the first
|
|
68
|
+
* interaction, SYG147 a `from` key that isn't an array in the host state, SYG435 (3-H) a list
|
|
69
|
+
* shown in another order than its array's (a Collection's sort / filter).
|
|
70
|
+
*/
|
|
71
|
+
import {defineBehavior} from './behaviors'
|
|
72
|
+
import {ABORT, isAbort} from '../shared'
|
|
73
|
+
import xs from './xstreamCompat'
|
|
74
|
+
import {dropRepeats} from './xstreamExtras'
|
|
75
|
+
|
|
76
|
+
const dev = (...a: any[]): any => (globalThis as any).__SYGNAL_DIAGNOSTICS__?.sortable?.(...a)
|
|
77
|
+
const LIFT = /^( |Enter|Spacebar)$/
|
|
78
|
+
const KEYS = /^(Arrow(Up|Down|Left|Right)|Home|End|Escape|Tab)$/
|
|
79
|
+
const S = String
|
|
80
|
+
const FIELDS = 'button,a,input,select,textarea,label,[contenteditable]'
|
|
81
|
+
// the events a sortable host has taken: an outer (nested) sortable leaves them alone
|
|
82
|
+
const claimed = new WeakSet<any>()
|
|
83
|
+
// a selector usable as one compound (`.task`, `li[data-x]`), else wrapped in :is()
|
|
84
|
+
const one = (s: string) => /^[\w.#\-[\]="']+$/.test(s) ? s : `:is(${s})`
|
|
85
|
+
// D219: a keyboard drag's lists at lift (`snap`) and after its last step (`made`), under its
|
|
86
|
+
// origin object; the slices a drag ended in without a drop (for undo(): G-510). 3-U G-532: the
|
|
87
|
+
// reducers write it (lift, each step): bookkeeping outside the state, so a reducer replayed or run
|
|
88
|
+
// twice for one action (a dev double-invoke, a devtools replay) can leave `made` one step ahead of
|
|
89
|
+
// the lists, and that drag's Escape / END then "stays" (never a wrong restore: a miss is a stay)
|
|
90
|
+
const drags = new WeakMap<any, any>(), ended = new WeakSet<any>()
|
|
91
|
+
|
|
92
|
+
const defaults = {
|
|
93
|
+
lift: (l: string, n: number, m: number, kb: boolean) => `Picked up ${l}, position ${n} of ${m}.` +
|
|
94
|
+
(kb ? ' Use the arrow keys to move, Space to drop, Escape to cancel.' : ''),
|
|
95
|
+
move: (l: string, n: number, m: number, list?: string) => `${l}: ${list ? list + ', ' : ''}position ${n} of ${m}.`,
|
|
96
|
+
drop: (l: string, n: number, m: number, list?: string) => `Dropped ${l} at ${list ? list + ', ' : ''}position ${n} of ${m}.`,
|
|
97
|
+
cancel: (l: string, n: number, m: number) => `Reorder cancelled. ${l} is back at position ${n} of ${m}.`,
|
|
98
|
+
stay: (l: string, n: number, m: number, list?: string) => `Reorder cancelled. The list changed, so ${l} stays at ${list ? list + ', ' : ''}position ${n} of ${m}.`,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const idle = {dragging: null, over: null, after: false, list: null, mode: null, press: null, origin: null, message: ''}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Drag-and-drop reordering of `state[from]` (GS-1 behavior). Options: `from` (required: the host
|
|
105
|
+
* state key of the list, or an array of keys for moves between lists, each container marked
|
|
106
|
+
* `data-list="<key>"`), `item` (each item's element, carrying its id in `attr`; default
|
|
107
|
+
* `[data-id]`), `handle` (the part that starts a drag and takes keyboard focus; default: the
|
|
108
|
+
* item), `axis` ('y' | 'x': the arrow keys that move), `threshold` (px a pointer moves before a
|
|
109
|
+
* drag starts, 4), `attr` ('data-id'), `idField` ('id'), `label` (item → its name in
|
|
110
|
+
* announcements), `messages` ({ lift, move, drop, cancel, stay }: (label, position, count, extra) =>
|
|
111
|
+
* text; `stay`: Escape after something else changed the list, the item stays where it is).
|
|
112
|
+
*/
|
|
113
|
+
export const sortable = (options: any = {}): any => {
|
|
114
|
+
const {from, handle, axis = 'y', threshold = 4, attr = 'data-id', idField = 'id'} = options
|
|
115
|
+
const item = options.item || `[${attr}]`, lists: string[] = [].concat(from), grip = handle || item
|
|
116
|
+
const label = options.label || ((i: any) => S(i?.title ?? i?.name ?? i?.label ?? i?.[idField]))
|
|
117
|
+
const msg = {...defaults, ...options.messages}
|
|
118
|
+
const [prevKey, nextKey] = axis == 'x' ? ['ArrowLeft', 'ArrowRight'] : ['ArrowUp', 'ArrowDown']
|
|
119
|
+
// an element's id attribute (dataset: the event targets of renderComponent's mock DOM)
|
|
120
|
+
const idOf = (el: any) => el?.getAttribute?.(attr) ?? el?.dataset?.[attr.slice(5).replace(/-(\w)/g, (_: any, c: string) => c.toUpperCase())] ?? null
|
|
121
|
+
|
|
122
|
+
// where an id is: { list, index, item, size }
|
|
123
|
+
const find = (st: any, id: any) => {
|
|
124
|
+
for (const l of lists) {
|
|
125
|
+
const a = st?.[l], i = id != null && Array.isArray(a) ? a.findIndex((x: any) => S(x?.[idField]) === S(id)) : -1
|
|
126
|
+
if (i >= 0) return {list: l, index: i, item: a[i], size: a.length}
|
|
127
|
+
}
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
// move the item at `f` to list `l` at index `to` (the index it ends at)
|
|
131
|
+
const move = (st: any, f: any, l: string, to: number) => {
|
|
132
|
+
const out = {...st}, src = [...st[f.list]]
|
|
133
|
+
src.splice(f.index, 1)
|
|
134
|
+
const dst = l == f.list ? src : [...(st[l] || [])]
|
|
135
|
+
dst.splice(Math.max(0, Math.min(to, dst.length)), 0, f.item)
|
|
136
|
+
out[f.list] = src
|
|
137
|
+
out[l] = dst
|
|
138
|
+
return out
|
|
139
|
+
}
|
|
140
|
+
const put = (st: any, k: string, s: any) => ({...st, [k]: {...st[k], ...s}})
|
|
141
|
+
const pick = (st: any) => { const o: any = {}; for (const l of lists) o[l] = st[l]; return o }
|
|
142
|
+
// the slice of a drag that ended without a drop (undo() settles its base)
|
|
143
|
+
const stop = (st: any, k: string, s: any) => { const r = put(st, k, s); ended.add(r[k]); return r }
|
|
144
|
+
// a drag ended without a drop (Escape; unmounted; drag state this instance didn't start:
|
|
145
|
+
// restored, synced, a host made again): a keyboard drag's lists go back to the ones it lifted
|
|
146
|
+
// from when they are exactly the arrays its last step made (D219), else the item stays where it
|
|
147
|
+
// is; `say`: announce it
|
|
148
|
+
const back = (st: any, k: string, say?: any) => {
|
|
149
|
+
const s = st[k], o = s.origin, d = s.mode == 'keyboard' && drags.get(o)
|
|
150
|
+
const own = d && lists.every(l => st[l] === d.made[l]), out = own ? {...st, ...d.snap} : st, f = say && s.mode == 'keyboard' && find(out, s.dragging)
|
|
151
|
+
return stop(out, k, {...idle, message: !f ? '' : own ? msg.cancel(label(f.item), f.index + 1, f.size) : msg.stay(label(f.item), f.index + 1, f.size, where(o, f))})
|
|
152
|
+
}
|
|
153
|
+
// where a pointer drop would land: over an item (in its own list: before it, after it when
|
|
154
|
+
// moving down; from another list: before or after it by the pointer's half, `low`: G-454), or
|
|
155
|
+
// at the end of another list's container
|
|
156
|
+
const landing = (st: any, f: any, o: any, list: any, low?: any) =>
|
|
157
|
+
o ? o.list == f.list ? {list: o.list, to: o.index, after: f.index < o.index} : {list: o.list, to: o.index + (low ? 1 : 0), after: !!low}
|
|
158
|
+
: list && lists.includes(list) && list != f.list ? {list, to: (st[list] || []).length, after: true}
|
|
159
|
+
: null
|
|
160
|
+
const where = (f: any, n: any) => n.list != f.list ? n.list : undefined
|
|
161
|
+
// a keyboard drag ends where the item is (DROPPED when it moved; 3-W G-535: else the slice is
|
|
162
|
+
// marked ended, so undo() settles the gesture: moved back after another change, it is a step)
|
|
163
|
+
const drop = (st: any, k: string, next: any) => {
|
|
164
|
+
const s = st[k], f = find(st, s.dragging), o = s.origin, m = f && (o.list != f.list || o.index != f.index)
|
|
165
|
+
if (m) next('DROPPED', {id: s.dragging, list: f.list, index: f.index, fromList: o.list, fromIndex: o.index}, 0)
|
|
166
|
+
return (m ? put : stop)(st, k, f ? {...idle, message: msg.drop(label(f.item), f.index + 1, f.size, where(o, f))} : idle)
|
|
167
|
+
}
|
|
168
|
+
// an element below the host's root `r` (the root is an item of an outer sortable; in
|
|
169
|
+
// renderComponent's mock DOM, where the event's target is the root, it counts)
|
|
170
|
+
const inside = (el: any, r: any) => el !== r ? !r?.contains || r.contains(el) : !r.nodeType
|
|
171
|
+
// one of this host's own items: below the root and not inside another item below it (that one
|
|
172
|
+
// is a nested list's, whose ids may repeat this host's: G-444)
|
|
173
|
+
const own = (it: any, r: any) => {
|
|
174
|
+
if (!it || !inside(it, r)) return false
|
|
175
|
+
const up = it.parentElement?.closest?.(item)
|
|
176
|
+
return !(up && inside(up, r))
|
|
177
|
+
}
|
|
178
|
+
// focus the moved item's handle: a focusWithin target (D194: the sender's root, a `focus` spec
|
|
179
|
+
// command) that keeps to this host's own items (G-445)
|
|
180
|
+
const focus = (_s: any, d: any) => {
|
|
181
|
+
if (d.key == 'Tab' || d.id == null) return ABORT
|
|
182
|
+
const sel = ':scope ' + one(item) + `[${attr}="${S(d.id).replace(/["\\]/g, '\\$&')}"]` + (handle ? ' ' + one(handle) : '')
|
|
183
|
+
return {focus: {within: sel, toString: () => '', spec: {commands: {focus: (root: any, o: any) => {
|
|
184
|
+
for (const el of root.querySelectorAll?.(sel) || []) if (own(handle ? el.closest(item) : el, root)) return el.focus(o)
|
|
185
|
+
}}}}}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// dev: SYG435, the list shown in another order than the array's (G-449)
|
|
189
|
+
const check = (st: any, seen: any, k: string) => seen && dev(435, seen, st, lists, idField, k)
|
|
190
|
+
// a press or key handler: drag state this instance didn't start (its token `n` isn't the
|
|
191
|
+
// event's: restored, synced) is dropped first (G-452)
|
|
192
|
+
const live = (h: any) => (st: any, d: any, next: any, _p: any, _o: any, k: string) => {
|
|
193
|
+
const s = st[k], c = (s.press || s.dragging) && (s.press || s.origin)?.n !== d.n ? back(st, k, 1) : st, r = h(c, d, next, k)
|
|
194
|
+
// the slice it leaves says a drag ended (a new lift on top: still, for undo())
|
|
195
|
+
return isAbort(r) ? c === st ? r : c : (c !== st && ended.add(r[k]), r)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const def = {
|
|
199
|
+
initialState: {...idle, helpId: null},
|
|
200
|
+
// drag state is UI state: persist() leaves this slice out (G-452)
|
|
201
|
+
persist: false,
|
|
202
|
+
// with undo(): a drag is one undo step, recorded at its drop (G-447)
|
|
203
|
+
undoStep: ['DROPPED'],
|
|
204
|
+
// internal (not public API): the slice an action left ended a drag without a drop (G-510)
|
|
205
|
+
undoEnd: (s: any) => ended.has(s),
|
|
206
|
+
intent: ({DOM, STATE, dispose$}: any, _o: any, key: string) => {
|
|
207
|
+
// `me`: this instance's token in the press / drag it starts (G-452): drag state it didn't
|
|
208
|
+
// start (restored by persist, synced, written by devtools) arms no document listener
|
|
209
|
+
const doc = DOM.select('document'), slice$ = STATE.stream, me = Math.random()
|
|
210
|
+
let root: any, checked: any // this host's root element (from its last press); SYG146 done
|
|
211
|
+
const on = (f: (s: any) => any, s$: () => any) =>
|
|
212
|
+
slice$.map(f).compose(dropRepeats()).map((a: any) => a ? s$() : xs.empty()).flatten()
|
|
213
|
+
const pressed = (s: any) => s.press?.n === me
|
|
214
|
+
// the pointer's position and what it is over: the id of this host's item around the
|
|
215
|
+
// element there (the outermost item below the root: G-444), and the data-list container
|
|
216
|
+
const pt = (e: any) => {
|
|
217
|
+
const x = e.clientX, y = e.clientY, d = typeof document != 'undefined' ? document : null
|
|
218
|
+
const el = (typeof x == 'number' && d?.elementFromPoint?.(x, y)) || e.target
|
|
219
|
+
let o: any
|
|
220
|
+
for (let it = el?.closest?.(item); it && inside(it, root); it = it.parentElement?.closest?.(item)) o = it
|
|
221
|
+
// over the item's second half (along the axis): an item from another list lands after it
|
|
222
|
+
const box = lists.length > 1 && el?.closest?.('[data-list]'), b = o?.getBoundingClientRect?.()
|
|
223
|
+
return {x: x || 0, y: y || 0, over: o ? idOf(o) : null, list: box && inside(box, root) ? box.getAttribute?.('data-list') : null,
|
|
224
|
+
low: !!b?.height && (axis == 'x' ? x > b.left + b.width / 2 : y > b.top + b.height / 2)}
|
|
225
|
+
}
|
|
226
|
+
// the id of the item whose handle (or the item itself) the event happened on; `self`: the
|
|
227
|
+
// handle must be the event's own target (keys)
|
|
228
|
+
const gripOf = (e: any, self?: boolean) => {
|
|
229
|
+
const t = e.target, r = e.ownerTarget || e.currentTarget
|
|
230
|
+
if (!checked) checked = dev(146, r, item, handle, attr)
|
|
231
|
+
const g = !claimed.has(e) && t?.closest?.(grip)
|
|
232
|
+
if (!g || self && g !== t) return null
|
|
233
|
+
// no handle: a press or key on a button, link or field inside the item is its own
|
|
234
|
+
const inner = !handle && t !== g && t.closest?.(FIELDS)
|
|
235
|
+
if (inner && inner !== g && (!g.contains || g.contains(inner))) return null
|
|
236
|
+
// one of this host's own items (not its root, not a nested list's item)
|
|
237
|
+
const it = handle ? g.closest?.(item) : g
|
|
238
|
+
if (!own(it, r)) return null
|
|
239
|
+
const id = idOf(it)
|
|
240
|
+
if (id == null) dev(145, it, item, attr)
|
|
241
|
+
return id
|
|
242
|
+
}
|
|
243
|
+
const keyed = (keys: RegExp, kb?: any) => (e: any) => keys.test(e.key) && (kb || e.key != 'Tab') && gripOf(e, true) != null
|
|
244
|
+
const lift = keyed(LIFT), step = keyed(KEYS, 1)
|
|
245
|
+
// dev (SYG435): this host's own items' ids in the order they're shown (computed by the
|
|
246
|
+
// diagnostics entry only)
|
|
247
|
+
const shown = (e: any) => dev(435, () => {
|
|
248
|
+
const r = e.ownerTarget || e.currentTarget
|
|
249
|
+
return [[...r.querySelectorAll(item)].filter((it: any) => own(it, r)), r]
|
|
250
|
+
}, key, lists, idOf)
|
|
251
|
+
const take = (e: any) => {
|
|
252
|
+
const id = gripOf(e, true)
|
|
253
|
+
claimed.add(e)
|
|
254
|
+
return {key: e.key == 'Spacebar' ? ' ' : e.key, id, n: me, seen: LIFT.test(e.key) && shown(e)}
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
INIT: xs.of(0),
|
|
258
|
+
// the host is unmounted (its state may live on in a parent's)
|
|
259
|
+
END: dispose$.mapTo(0),
|
|
260
|
+
// the first focus, press or key inside the host sets the instructions id (G-448: no
|
|
261
|
+
// write at startup, so a Collection-item host's parent data stays clean until it is used)
|
|
262
|
+
HELP: on((s: any) => !s.helpId, () => xs.merge(DOM.events('focusin'), DOM.events('pointerdown'), DOM.events('keydown')).mapTo(0)),
|
|
263
|
+
PRESS: DOM.events('pointerdown')
|
|
264
|
+
.filter((e: any) => e.isPrimary !== false && !e.button)
|
|
265
|
+
.map((e: any) => {
|
|
266
|
+
const id = gripOf(e)
|
|
267
|
+
if (id == null) return null
|
|
268
|
+
claimed.add(e)
|
|
269
|
+
root = e.ownerTarget || e.currentTarget
|
|
270
|
+
return {id, x: e.clientX || 0, y: e.clientY || 0, n: me, seen: shown(e)}
|
|
271
|
+
})
|
|
272
|
+
.filter((d: any) => d != null),
|
|
273
|
+
// no text selection and no native drag (an image or link in the item: its dragstart
|
|
274
|
+
// would cancel the pointer, G-450) while a pointer is pressed (the listeners only filter)
|
|
275
|
+
MOVE: on(pressed, () => xs.merge(
|
|
276
|
+
doc.events('pointermove').map(pt),
|
|
277
|
+
xs.merge(doc.events('selectstart', {preventDefault: true}), doc.events('dragstart', {preventDefault: true})).filter(() => false))),
|
|
278
|
+
UP: on(pressed, () => doc.events('pointerup').map(pt)),
|
|
279
|
+
CANCEL: on(pressed, () => xs.merge(
|
|
280
|
+
doc.events('pointercancel'),
|
|
281
|
+
doc.events('keydown', {preventDefault: (e: any) => e.key == 'Escape'}).filter((e: any) => e.key == 'Escape'))),
|
|
282
|
+
KEY: xs.merge(
|
|
283
|
+
// a held Space / Enter (auto-repeat) neither drops nor lifts again (G-446)
|
|
284
|
+
DOM.events('keydown', {preventDefault: lift}).filter((e: any) => !e.repeat && lift(e)).map(take),
|
|
285
|
+
on((s: any) => s.mode == 'keyboard' && s.origin?.n === me, () => xs.merge(
|
|
286
|
+
DOM.events('keydown', {preventDefault: keyed(KEYS)}).filter(step).map(take),
|
|
287
|
+
// focus moved to another element, or a pointer press anywhere: drop where it is
|
|
288
|
+
DOM.events('focusout').filter((e: any) => e.relatedTarget),
|
|
289
|
+
doc.events('pointerdown')).map((d: any) => d.key ? d : {key: 'Tab', n: me}))),
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
model: {
|
|
293
|
+
// SYG147 (dev); drag state the host starts with (restored with a parent's data, a host made
|
|
294
|
+
// again by HMR, a second host of the slice) is reset, as at END
|
|
295
|
+
INIT: {HOST: (st: any, _d: any, _n: any, _p: any, _o: any, k: string) => {
|
|
296
|
+
for (const l of lists) Array.isArray(st?.[l]) || dev(147, l, st, k)
|
|
297
|
+
return st[k].press || st[k].dragging ? back(st, k) : ABORT
|
|
298
|
+
}},
|
|
299
|
+
// unmounted mid-drag: the drag is cancelled (no DROPPED; a keyboard drag's item goes back
|
|
300
|
+
// where it started), so data that outlives the host isn't left half-moved or stuck
|
|
301
|
+
END: {HOST: (st: any, _d: any, _n: any, _p: any, _o: any, k: string) => {
|
|
302
|
+
const s = st[k]
|
|
303
|
+
return s.press || s.dragging ? back(st, k) : ABORT
|
|
304
|
+
}},
|
|
305
|
+
// the instructions id: a uid() of the host (unique per host instance)
|
|
306
|
+
HELP: {HOST: (st: any, _d: any, _n: any, p: any, _o: any, k: string) =>
|
|
307
|
+
st[k].helpId || !p?.uid ? ABORT : put(st, k, {helpId: p.uid(k + '-help')})},
|
|
308
|
+
PRESS: {HOST: live((st: any, {seen, ...d}: any, next: any, k: string) => {
|
|
309
|
+
const s = st[k]
|
|
310
|
+
if (s.mode == 'pointer' || !find(st, d.id)) return ABORT
|
|
311
|
+
check(st, seen, k)
|
|
312
|
+
// during a keyboard drag: it drops where it is, and the press starts (G-451)
|
|
313
|
+
return put(s.mode == 'keyboard' ? drop(st, k, next) : st, k, {press: d})
|
|
314
|
+
})},
|
|
315
|
+
MOVE: {HOST: (st: any, d: any, _n: any, _p: any, _o: any, k: string) => {
|
|
316
|
+
const s = st[k], p = s.press, f = p && find(st, p.id)
|
|
317
|
+
if (!f) return ABORT
|
|
318
|
+
// past the threshold: the drag starts
|
|
319
|
+
const start = !s.dragging && {dragging: S(p.id), mode: 'pointer', origin: {list: f.list, index: f.index}, message: msg.lift(label(f.item), f.index + 1, f.size, false)}
|
|
320
|
+
if (!s.dragging && Math.hypot(d.x - p.x, d.y - p.y) < threshold) return ABORT
|
|
321
|
+
const o = find(st, d.over), L = landing(st, f, o, d.list, d.low)
|
|
322
|
+
const next = {...start, over: o ? S(o.item[idField]) : null, list: L?.list ?? null, after: !!L?.after}
|
|
323
|
+
return !start && next.over === s.over && next.list === s.list && next.after === s.after ? ABORT : put(st, k, next)
|
|
324
|
+
}},
|
|
325
|
+
UP: {HOST: (st: any, d: any, next: any, _p: any, _o: any, k: string) => {
|
|
326
|
+
const s = st[k]
|
|
327
|
+
if (!s.dragging) return s.press ? put(st, k, idle) : ABORT
|
|
328
|
+
const f = find(st, s.dragging)
|
|
329
|
+
// the release point decides (a last move may not have been rendered)
|
|
330
|
+
const L = f && landing(st, f, find(st, d.over), d.list, d.low)
|
|
331
|
+
if (!f || !L || L.list == f.list && L.to == f.index) return put(st, k, {...idle, message: f ? msg.cancel(label(f.item), f.index + 1, f.size) : ''})
|
|
332
|
+
const out = move(st, f, L.list, L.to), n = find(out, s.dragging)!
|
|
333
|
+
next('DROPPED', {id: s.dragging, list: n.list, index: n.index, fromList: f.list, fromIndex: f.index}, 0)
|
|
334
|
+
return put(out, k, {...idle, message: msg.drop(label(f.item), n.index + 1, n.size, where(f, n))})
|
|
335
|
+
}},
|
|
336
|
+
CANCEL: {HOST: (st: any, _d: any, _n: any, _p: any, _o: any, k: string) => {
|
|
337
|
+
const s = st[k], f = s.dragging && find(st, s.dragging)
|
|
338
|
+
return s.press ? put(st, k, {...idle, message: f ? msg.cancel(label(f.item), f.index + 1, f.size) : ''}) : ABORT
|
|
339
|
+
}},
|
|
340
|
+
KEY: {
|
|
341
|
+
HOST: live((st: any, {key, id, n: me, seen}: any, next: any, k: string) => {
|
|
342
|
+
const s = st[k], f = find(st, s.dragging ?? id)
|
|
343
|
+
if (s.mode == 'pointer' || s.press) return ABORT
|
|
344
|
+
// the lifted item left the list (removed by another action): the drag ends
|
|
345
|
+
if (!f) return s.dragging ? stop(st, k, idle) : ABORT
|
|
346
|
+
const l = label(f.item), o = s.origin
|
|
347
|
+
if (!s.dragging) {
|
|
348
|
+
if (!LIFT.test(key)) return ABORT
|
|
349
|
+
check(st, seen, k)
|
|
350
|
+
// the drag's lists at lift (D219: also the ones its last step made, so far)
|
|
351
|
+
const origin = {list: f.list, index: f.index, n: me}
|
|
352
|
+
drags.set(origin, {snap: pick(st), made: pick(st)})
|
|
353
|
+
return put(st, k, {...idle, dragging: S(id), mode: 'keyboard', origin, message: msg.lift(l, f.index + 1, f.size, true)})
|
|
354
|
+
}
|
|
355
|
+
if (LIFT.test(key) || key == 'Tab') return drop(st, k, next)
|
|
356
|
+
if (key == 'Escape') return back(st, k, 1)
|
|
357
|
+
// a step: the lists it made (D219)
|
|
358
|
+
const step = (out: any, m: string) => { const d = drags.get(o); if (d) d.made = pick(out); return put(out, k, {message: m}) }
|
|
359
|
+
// the cross axis moves between lists (from: [a, b]): to the same index, clamped
|
|
360
|
+
const side = ({ArrowUp: -1, ArrowDown: 1, ArrowLeft: -1, ArrowRight: 1} as any)[key]
|
|
361
|
+
if (side && key != prevKey && key != nextKey) {
|
|
362
|
+
const to = lists[lists.indexOf(f.list) + side]
|
|
363
|
+
if (!to) return ABORT
|
|
364
|
+
const out = move(st, f, to, f.index), n = find(out, s.dragging)!
|
|
365
|
+
return step(out, msg.move(l, n.index + 1, n.size, to))
|
|
366
|
+
}
|
|
367
|
+
const to = key == prevKey ? f.index - 1 : key == nextKey ? f.index + 1 : key == 'Home' ? 0 : key == 'End' ? f.size - 1 : -1
|
|
368
|
+
return to < 0 || to >= f.size || to == f.index ? ABORT : step(move(st, f, f.list, to), msg.move(l, to + 1, f.size))
|
|
369
|
+
}),
|
|
370
|
+
// keep focus on the moved item's handle (its node may move or be re-created)
|
|
371
|
+
ELEMENT: focus,
|
|
372
|
+
},
|
|
373
|
+
DROPPED: ABORT,
|
|
374
|
+
},
|
|
375
|
+
}
|
|
376
|
+
return defineBehavior(def)(options)
|
|
377
|
+
}
|