@ankhorage/zora 25.7.0 → 25.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/CHANGELOG.md +37 -0
- package/README.md +1 -1
- package/dist/capabilities/index.d.ts +2 -74
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +6170 -59
- package/dist/capabilities/index.js.map +119 -1
- package/dist/cli/index.d.ts +2 -74
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/features/grid-interactions/adapters/inbound/GridInteractions.d.ts +5 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractions.d.ts.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractions.js +40 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractions.js.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.d.ts +2 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.d.ts.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.js +2 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.js.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.native.d.ts +11 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.native.d.ts.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.native.js +5 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.native.js.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.web.d.ts +11 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.web.d.ts.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.web.js +20 -0
- package/dist/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.web.js.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/createGridInteractionsPointerQueue.d.ts +17 -0
- package/dist/features/grid-interactions/adapters/inbound/createGridInteractionsPointerQueue.d.ts.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/createGridInteractionsPointerQueue.js +76 -0
- package/dist/features/grid-interactions/adapters/inbound/createGridInteractionsPointerQueue.js.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/resolveGridInteractionPointer.d.ts +21 -0
- package/dist/features/grid-interactions/adapters/inbound/resolveGridInteractionPointer.d.ts.map +1 -0
- package/dist/features/grid-interactions/adapters/inbound/resolveGridInteractionPointer.js +20 -0
- package/dist/features/grid-interactions/adapters/inbound/resolveGridInteractionPointer.js.map +1 -0
- package/dist/features/grid-interactions/application/createGridInteractionsController.d.ts +4 -0
- package/dist/features/grid-interactions/application/createGridInteractionsController.d.ts.map +1 -0
- package/dist/features/grid-interactions/application/createGridInteractionsController.js +200 -0
- package/dist/features/grid-interactions/application/createGridInteractionsController.js.map +1 -0
- package/dist/features/grid-interactions/meta.d.ts +11 -0
- package/dist/features/grid-interactions/meta.d.ts.map +1 -0
- package/dist/features/grid-interactions/meta.js +11 -0
- package/dist/features/grid-interactions/meta.js.map +1 -0
- package/dist/features/grid-interactions/public.d.ts +4 -0
- package/dist/features/grid-interactions/public.d.ts.map +1 -0
- package/dist/features/grid-interactions/public.js +3 -0
- package/dist/features/grid-interactions/public.js.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.d.ts.map +1 -1
- package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.js +73 -19
- package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.js.map +1 -1
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.d.ts +9 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.d.ts.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.js +5 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.js.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.native.d.ts +9 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.native.d.ts.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.native.js +5 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.native.js.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.web.d.ts +9 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.web.d.ts.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.web.js +28 -0
- package/dist/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.web.js.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/useMatrixGridKeyboardFocus.d.ts +14 -0
- package/dist/features/matrix-grid/adapters/inbound/useMatrixGridKeyboardFocus.d.ts.map +1 -0
- package/dist/features/matrix-grid/adapters/inbound/useMatrixGridKeyboardFocus.js +50 -0
- package/dist/features/matrix-grid/adapters/inbound/useMatrixGridKeyboardFocus.js.map +1 -0
- package/dist/features/matrix-grid/application/createMatrixGridSparseIndex.d.ts +18 -0
- package/dist/features/matrix-grid/application/createMatrixGridSparseIndex.d.ts.map +1 -0
- package/dist/features/matrix-grid/application/createMatrixGridSparseIndex.js +56 -0
- package/dist/features/matrix-grid/application/createMatrixGridSparseIndex.js.map +1 -0
- package/dist/features/matrix-grid/application/getMatrixGridNextFocusId.d.ts +4 -0
- package/dist/features/matrix-grid/application/getMatrixGridNextFocusId.d.ts.map +1 -0
- package/dist/features/matrix-grid/application/getMatrixGridNextFocusId.js +65 -0
- package/dist/features/matrix-grid/application/getMatrixGridNextFocusId.js.map +1 -0
- package/dist/features/matrix-grid/application/resolveMatrixGridSelection.d.ts +8 -1
- package/dist/features/matrix-grid/application/resolveMatrixGridSelection.d.ts.map +1 -1
- package/dist/features/matrix-grid/application/resolveMatrixGridSelection.js +15 -4
- package/dist/features/matrix-grid/application/resolveMatrixGridSelection.js.map +1 -1
- package/dist/features/registry/ZORA_COMPONENT_REGISTRY.d.ts.map +1 -1
- package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js +2 -0
- package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js.map +1 -1
- package/dist/features/registry/componentMeta.d.ts.map +1 -1
- package/dist/features/registry/componentMeta.js +2 -0
- package/dist/features/registry/componentMeta.js.map +1 -1
- package/dist/features/registry/createEventCapabilities.d.ts +4 -0
- package/dist/features/registry/createEventCapabilities.d.ts.map +1 -0
- package/dist/features/registry/createEventCapabilities.js +76 -0
- package/dist/features/registry/createEventCapabilities.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/grid-interactions.d.ts +58 -0
- package/dist/types/grid-interactions.d.ts.map +1 -0
- package/dist/types/grid-interactions.js +2 -0
- package/dist/types/grid-interactions.js.map +1 -0
- package/dist/types/matrix-grid.d.ts +2 -0
- package/dist/types/matrix-grid.d.ts.map +1 -1
- package/dist/types/matrix-grid.js.map +1 -1
- package/package.json +1825 -7
- package/src/capabilities/index.test.ts +87 -15
- package/src/capabilities/index.ts +5 -2
- package/src/cli/index.test.ts +5 -3
- package/src/cli/index.ts +5 -2
- package/src/features/grid-interactions/adapters/inbound/GridInteractions.test.tsx +143 -0
- package/src/features/grid-interactions/adapters/inbound/GridInteractions.tsx +79 -0
- package/src/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.native.tsx +14 -0
- package/src/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.tsx +1 -0
- package/src/features/grid-interactions/adapters/inbound/GridInteractionsKeyboardProxy.web.tsx +41 -0
- package/src/features/grid-interactions/adapters/inbound/createGridInteractionsPointerQueue.test.ts +98 -0
- package/src/features/grid-interactions/adapters/inbound/createGridInteractionsPointerQueue.ts +94 -0
- package/src/features/grid-interactions/adapters/inbound/resolveGridInteractionPointer.test.ts +33 -0
- package/src/features/grid-interactions/adapters/inbound/resolveGridInteractionPointer.ts +45 -0
- package/src/features/grid-interactions/application/createGridInteractionsController.test.ts +229 -0
- package/src/features/grid-interactions/application/createGridInteractionsController.ts +248 -0
- package/src/features/grid-interactions/meta.ts +12 -0
- package/src/features/grid-interactions/public.ts +11 -0
- package/src/features/matrix-grid/adapters/inbound/MatrixGrid.test.tsx +280 -2
- package/src/features/matrix-grid/adapters/inbound/MatrixGrid.tsx +121 -31
- package/src/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.native.tsx +11 -0
- package/src/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.tsx +11 -0
- package/src/features/matrix-grid/adapters/inbound/MatrixGridKeyboardProxy.web.tsx +43 -0
- package/src/features/matrix-grid/adapters/inbound/useMatrixGridKeyboardFocus.ts +70 -0
- package/src/features/matrix-grid/application/createMatrixGridSparseIndex.test.ts +35 -0
- package/src/features/matrix-grid/application/createMatrixGridSparseIndex.ts +105 -0
- package/src/features/matrix-grid/application/getMatrixGridNextFocusId.test.ts +93 -0
- package/src/features/matrix-grid/application/getMatrixGridNextFocusId.ts +112 -0
- package/src/features/matrix-grid/application/resolveMatrixGridSelection.test.ts +63 -2
- package/src/features/matrix-grid/application/resolveMatrixGridSelection.ts +27 -4
- package/src/features/registry/ZORA_COMPONENT_REGISTRY.ts +2 -0
- package/src/features/registry/componentMeta.ts +2 -0
- package/src/features/registry/createEventCapabilities.ts +108 -0
- package/src/index.ts +11 -0
- package/src/structureOwnership.test.ts +5 -0
- package/src/types/grid-interactions.ts +72 -0
- package/src/types/matrix-grid.ts +2 -0
- package/web-dist/chunks/{Accordion-5g05kfmx.js → Accordion-0q2wzjdd.js} +4 -4
- package/web-dist/chunks/{Accordion-b96evb46.js → Accordion-1fsrnq73.js} +1 -1
- package/web-dist/chunks/{Accordion-h3y8qev2.js → Accordion-38ts3gnn.js} +2 -2
- package/web-dist/chunks/{Accordion-jnc315h7.js → Accordion-8pkw32q9.js} +2 -2
- package/web-dist/chunks/{Accordion-h7zsx9eg.js → Accordion-9jrxktne.js} +3 -3
- package/web-dist/chunks/{Accordion-9w8wg9mf.js → Accordion-9rnsg9pk.js} +1 -1
- package/web-dist/chunks/{Accordion-4zqd7twp.js → Accordion-9ygakvwk.js} +5 -5
- package/web-dist/chunks/{Accordion-fhnazn3n.js → Accordion-b74j4hdt.js} +1 -1
- package/web-dist/chunks/{Accordion-nssr5gep.js → Accordion-c50pywj3.js} +2 -2
- package/web-dist/chunks/{Accordion-pvj5npzc.js → Accordion-ddrn94v3.js} +3 -3
- package/web-dist/chunks/{Accordion-090y18cv.js → Accordion-dk0dtyc0.js} +3 -3
- package/web-dist/chunks/{Accordion-59pa0677.js → Accordion-fcczvwgg.js} +0 -1
- package/web-dist/chunks/{Accordion-sp4k08kw.js → Accordion-geah5s4f.js} +4 -4
- package/web-dist/chunks/{Accordion-6rrqpb2h.js → Accordion-h4ekm5cp.js} +2 -2
- package/web-dist/chunks/{Accordion-3d4wkzg7.js → Accordion-hecpczme.js} +5 -5
- package/web-dist/chunks/{Accordion-a6551mh4.js → Accordion-hn43wt45.js} +1 -1
- package/web-dist/chunks/{Accordion-sw7ep29d.js → Accordion-hnx7hx55.js} +2 -2
- package/web-dist/chunks/{Accordion-rsvphbe4.js → Accordion-j1chy29e.js} +1 -1
- package/web-dist/chunks/{Accordion-ewf1zen9.js → Accordion-k9cxpg08.js} +5 -5
- package/web-dist/chunks/{Accordion-5df6cgyf.js → Accordion-md1g54wg.js} +1 -1
- package/web-dist/chunks/{Accordion-kjtcbe09.js → Accordion-p1ebrt17.js} +3 -3
- package/web-dist/chunks/{Accordion-qn398m1x.js → Accordion-r2g18vxa.js} +1 -1
- package/web-dist/chunks/{Accordion-zt9yghdz.js → Accordion-rctfgyfv.js} +4 -4
- package/web-dist/chunks/{Accordion-88t8fgxv.js → Accordion-rfc5mdbv.js} +1 -1
- package/web-dist/chunks/{Accordion-fmzxat3v.js → Accordion-sdnzqktc.js} +4 -4
- package/web-dist/chunks/{Accordion-v0grdh6q.js → Accordion-sq7ya2ye.js} +2 -2
- package/web-dist/chunks/{Accordion-ejx5gcf9.js → Accordion-t5scffdr.js} +9 -9
- package/web-dist/chunks/{Accordion-sy1cc5my.js → Accordion-ts788t7b.js} +3 -3
- package/web-dist/chunks/{Accordion-4s68t3h7.js → Accordion-v3rzy273.js} +6 -6
- package/web-dist/chunks/{Accordion-7tjz25jh.js → Accordion-vbzjq3z8.js} +1 -1
- package/web-dist/chunks/{Accordion-jh72azm2.js → Accordion-vg337250.js} +2 -2
- package/web-dist/chunks/{Accordion-42jfy1a1.js → Accordion-vj1m2wck.js} +1 -1
- package/web-dist/chunks/{Accordion-tqpsmdrk.js → Accordion-vxg5sw01.js} +4 -4
- package/web-dist/chunks/{Accordion-61ntvh14.js → Accordion-w59y0jdf.js} +4 -4
- package/web-dist/chunks/{Accordion-fjxcn6g9.js → Accordion-wcmrasqx.js} +8 -8
- package/web-dist/chunks/{Accordion-r1cj2w9e.js → Accordion-wpk8dxqp.js} +3 -3
- package/web-dist/chunks/{Accordion-w6qedeba.js → Accordion-x055n3b3.js} +1 -1
- package/web-dist/chunks/{Accordion-dbf93gxh.js → Accordion-xcm1qc39.js} +1 -1
- package/web-dist/chunks/{Accordion-7kq500r1.js → Accordion-xgxxg1hz.js} +1 -1
- package/web-dist/chunks/{Accordion-a4cma5b6.js → Accordion-y3083394.js} +3 -3
- package/web-dist/chunks/{Accordion-40tenzcg.js → Accordion-yexfbrzg.js} +4 -4
- package/web-dist/chunks/{Accordion-2r0gqk3x.js → Accordion-ztw7zp6v.js} +5 -5
- package/web-dist/chunks/{Accordion-bz04casa.js → Accordion-zypyr9xw.js} +211 -6
- package/web-dist/components/accordion/Accordion.js +5 -5
- package/web-dist/components/accordion-item/AccordionItem.js +5 -5
- package/web-dist/components/activity-indicator/ActivityIndicator.js +1 -1
- package/web-dist/components/app-bar/AppBar.js +7 -7
- package/web-dist/components/app-header/AppHeader.js +7 -7
- package/web-dist/components/app-shell/AppShell.js +2 -2
- package/web-dist/components/auth-screen/AuthScreen.js +10 -10
- package/web-dist/components/avatar/Avatar.js +5 -5
- package/web-dist/components/avatar-group/AvatarGroup.js +5 -5
- package/web-dist/components/badge/Badge.js +2 -2
- package/web-dist/components/barcode-scanner-view/BarcodeScannerView.js +10 -10
- package/web-dist/components/bottom-sheet/BottomSheet.js +3 -3
- package/web-dist/components/bottom-sheet-flat-list/BottomSheetFlatList.js +3 -3
- package/web-dist/components/bottom-sheet-scroll-view/BottomSheetScrollView.js +3 -3
- package/web-dist/components/bottom-sheet-section-list/BottomSheetSectionList.js +3 -3
- package/web-dist/components/bottom-sheet-view/BottomSheetView.js +3 -3
- package/web-dist/components/bottom-sheet-virtualized-list/BottomSheetVirtualizedList.js +3 -3
- package/web-dist/components/breadcrumbs/Breadcrumbs.js +5 -5
- package/web-dist/components/button/Button.js +3 -3
- package/web-dist/components/button-group/ButtonGroup.js +3 -3
- package/web-dist/components/camera-permission-view/CameraPermissionView.js +10 -10
- package/web-dist/components/card/Card.js +9 -9
- package/web-dist/components/card-back/CardBack.js +2 -2
- package/web-dist/components/card-hand/CardHand.js +2 -2
- package/web-dist/components/chat-list-item/ChatListItem.js +7 -7
- package/web-dist/components/checkbox/Checkbox.js +4 -4
- package/web-dist/components/checkbox-group/CheckboxGroup.js +4 -4
- package/web-dist/components/chess-board/ChessBoard.js +2 -2
- package/web-dist/components/chip/Chip.js +5 -5
- package/web-dist/components/chip-group/ChipGroup.js +5 -5
- package/web-dist/components/collection-editor/CollectionEditor.js +9 -9
- package/web-dist/components/content-rail/ContentRail.js +4 -4
- package/web-dist/components/data-table/DataTable.js +14 -14
- package/web-dist/components/date-picker/DatePicker.js +5 -5
- package/web-dist/components/dialog/Dialog.js +4 -4
- package/web-dist/components/divider/Divider.js +2 -2
- package/web-dist/components/empty-state/EmptyState.js +10 -10
- package/web-dist/components/explorer/Explorer.js +7 -7
- package/web-dist/components/field/Field.js +4 -4
- package/web-dist/components/file-explorer/FileExplorer.js +7 -7
- package/web-dist/components/flat-list/FlatList.js +5 -5
- package/web-dist/components/forgot-password-form/ForgotPasswordForm.js +10 -10
- package/web-dist/components/form/Form.js +6 -6
- package/web-dist/components/form-actions/FormActions.js +6 -6
- package/web-dist/components/form-error/FormError.js +6 -6
- package/web-dist/components/game/Game.js +3 -3
- package/web-dist/components/game-entity/GameEntity.js +3 -3
- package/web-dist/components/game-field/GameField.js +3 -3
- package/web-dist/components/game-input-zone/GameInputZone.js +3 -3
- package/web-dist/components/game-measurement-probe/GameMeasurementProbe.js +3 -3
- package/web-dist/components/game-overlay/GameOverlay.js +3 -3
- package/web-dist/components/gradient/Gradient.js +3 -3
- package/web-dist/components/gradient-renderer-provider/GradientRendererProvider.js +3 -3
- package/web-dist/components/graph-view/GraphView.js +2 -2
- package/web-dist/components/grid/Grid.js +2 -2
- package/web-dist/components/grid-interactions/GridInteractions.d.ts +3 -0
- package/web-dist/components/grid-interactions/GridInteractions.js +379 -0
- package/web-dist/components/grid-interactions/index.d.ts +1 -0
- package/web-dist/components/grid-interactions/index.js +2 -0
- package/web-dist/components/grid-line-overlay/GridLineOverlay.js +2 -2
- package/web-dist/components/grid-ruler/GridRuler.js +2 -2
- package/web-dist/components/grid-view/GridView.js +1 -1
- package/web-dist/components/heading/Heading.js +2 -2
- package/web-dist/components/hero/Hero.js +9 -9
- package/web-dist/components/icon/Icon.js +2 -2
- package/web-dist/components/icon-button/IconButton.js +3 -3
- package/web-dist/components/image/Image.js +4 -4
- package/web-dist/components/keyboard-avoiding-view/KeyboardAvoidingView.js +2 -2
- package/web-dist/components/list/List.js +5 -5
- package/web-dist/components/list-item/ListItem.js +5 -5
- package/web-dist/components/list-section/ListSection.js +5 -5
- package/web-dist/components/matrix-grid/MatrixGrid.js +296 -47
- package/web-dist/components/media-card/MediaCard.js +9 -9
- package/web-dist/components/media-explorer/MediaExplorer.js +7 -7
- package/web-dist/components/message-bubble/MessageBubble.js +7 -7
- package/web-dist/components/metric-card/MetricCard.js +9 -9
- package/web-dist/components/missing-element/MissingElement.js +4 -4
- package/web-dist/components/o-auth-provider-button/OAuthProviderButton.js +10 -10
- package/web-dist/components/o-auth-provider-list/OAuthProviderList.js +10 -10
- package/web-dist/components/opening-book/OpeningBook.js +2 -2
- package/web-dist/components/otp-form/OtpForm.js +10 -10
- package/web-dist/components/pagination/Pagination.js +4 -4
- package/web-dist/components/palette-item/PaletteItem.js +9 -9
- package/web-dist/components/playing-card/PlayingCard.js +2 -2
- package/web-dist/components/poker-training-table/PokerTrainingTable.js +2 -2
- package/web-dist/components/popover-menu/PopoverMenu.js +4 -4
- package/web-dist/components/post-card/PostCard.js +9 -9
- package/web-dist/components/product-card/ProductCard.js +9 -9
- package/web-dist/components/progress/Progress.js +4 -4
- package/web-dist/components/progress-ring/ProgressRing.js +4 -4
- package/web-dist/components/radio/Radio.js +5 -5
- package/web-dist/components/radio-group/RadioGroup.js +5 -5
- package/web-dist/components/rating/Rating.js +3 -3
- package/web-dist/components/reader/Reader.js +10 -10
- package/web-dist/components/scan-overlay/ScanOverlay.js +10 -10
- package/web-dist/components/screen/Screen.js +2 -2
- package/web-dist/components/screen-section/ScreenSection.js +4 -4
- package/web-dist/components/scroll-view/ScrollView.js +2 -2
- package/web-dist/components/search-input/SearchInput.js +4 -4
- package/web-dist/components/section-header/SectionHeader.js +4 -4
- package/web-dist/components/section-list/SectionList.js +5 -5
- package/web-dist/components/select/Select.js +4 -4
- package/web-dist/components/selectable-item/SelectableItem.js +2 -2
- package/web-dist/components/selection-provider/SelectionProvider.js +2 -2
- package/web-dist/components/sign-in-form/SignInForm.js +10 -10
- package/web-dist/components/sign-up-form/SignUpForm.js +10 -10
- package/web-dist/components/skeleton/Skeleton.js +12 -12
- package/web-dist/components/skeleton-card/SkeletonCard.js +12 -12
- package/web-dist/components/skeleton-list/SkeletonList.js +12 -12
- package/web-dist/components/skeleton-text/SkeletonText.js +12 -12
- package/web-dist/components/spatial-grid/SpatialGrid.js +1 -1
- package/web-dist/components/surface/Surface.js +2 -2
- package/web-dist/components/switch/Switch.js +1 -1
- package/web-dist/components/tab/Tab.js +2 -2
- package/web-dist/components/tab-list/TabList.js +2 -2
- package/web-dist/components/tab-panel/TabPanel.js +2 -2
- package/web-dist/components/tabletop-table/TabletopTable.js +2 -2
- package/web-dist/components/tabs/Tabs.js +2 -2
- package/web-dist/components/text/Text.js +2 -2
- package/web-dist/components/text-input/TextInput.js +4 -4
- package/web-dist/components/tile-grid/TileGrid.js +1 -1
- package/web-dist/components/time-grid/TimeGrid.js +2 -2
- package/web-dist/components/time-picker/TimePicker.js +5 -5
- package/web-dist/components/timeline/Timeline.js +4 -4
- package/web-dist/components/toast/Toast.js +2 -2
- package/web-dist/components/toast-provider/ToastProvider.js +2 -2
- package/web-dist/components/toolbar/Toolbar.js +9 -9
- package/web-dist/components/tree-item/TreeItem.js +9 -9
- package/web-dist/components/tree-view/TreeView.js +1 -1
- package/web-dist/components/uploader/Uploader.js +12 -12
- package/web-dist/components/view/View.js +2 -2
- package/web-dist/manifest.json +787 -772
- package/web-dist/runtime/ZoraProvider.js +3 -3
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { resolveGridInteractionPointer } from './resolveGridInteractionPointer';
|
|
4
|
+
|
|
5
|
+
test('normalizes nested responder coordinates against the interaction surface origin', () => {
|
|
6
|
+
expect(
|
|
7
|
+
resolveGridInteractionPointer(
|
|
8
|
+
{
|
|
9
|
+
nativeEvent: {
|
|
10
|
+
locationX: 4,
|
|
11
|
+
locationY: 6,
|
|
12
|
+
pageX: 124,
|
|
13
|
+
pageY: 86,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{ x: 120, y: 80 },
|
|
17
|
+
),
|
|
18
|
+
).toEqual({ x: 4, y: 6 });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('uses responder-local coordinates when page coordinates are unavailable on native', () => {
|
|
22
|
+
expect(
|
|
23
|
+
resolveGridInteractionPointer(
|
|
24
|
+
{
|
|
25
|
+
nativeEvent: {
|
|
26
|
+
locationX: 4,
|
|
27
|
+
locationY: 6,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{ x: 120, y: 80 },
|
|
31
|
+
),
|
|
32
|
+
).toEqual({ x: 4, y: 6 });
|
|
33
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { GridInteractionPointer } from '../../../../types/grid-interactions';
|
|
2
|
+
|
|
3
|
+
/*** Converts a responder event into coordinates local to the interaction surface. */
|
|
4
|
+
export function resolveGridInteractionPointer(
|
|
5
|
+
event: GridInteractionNativePointerEvent,
|
|
6
|
+
surfaceOrigin: GridInteractionSurfaceOrigin,
|
|
7
|
+
): GridInteractionPointer {
|
|
8
|
+
const { nativeEvent } = event;
|
|
9
|
+
const { pageX, pageY } = nativeEvent;
|
|
10
|
+
const x =
|
|
11
|
+
typeof pageX === 'number' && Number.isFinite(pageX)
|
|
12
|
+
? pageX - surfaceOrigin.x
|
|
13
|
+
: nativeEvent.locationX;
|
|
14
|
+
const y =
|
|
15
|
+
typeof pageY === 'number' && Number.isFinite(pageY)
|
|
16
|
+
? pageY - surfaceOrigin.y
|
|
17
|
+
: nativeEvent.locationY;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
altKey: nativeEvent.altKey,
|
|
21
|
+
ctrlKey: nativeEvent.ctrlKey,
|
|
22
|
+
metaKey: nativeEvent.metaKey,
|
|
23
|
+
shiftKey: nativeEvent.shiftKey,
|
|
24
|
+
x,
|
|
25
|
+
y,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface GridInteractionNativePointerEvent {
|
|
30
|
+
readonly nativeEvent: {
|
|
31
|
+
readonly altKey?: boolean;
|
|
32
|
+
readonly ctrlKey?: boolean;
|
|
33
|
+
readonly locationX: number;
|
|
34
|
+
readonly locationY: number;
|
|
35
|
+
readonly metaKey?: boolean;
|
|
36
|
+
readonly pageX?: number;
|
|
37
|
+
readonly pageY?: number;
|
|
38
|
+
readonly shiftKey?: boolean;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface GridInteractionSurfaceOrigin {
|
|
43
|
+
readonly x: number;
|
|
44
|
+
readonly y: number;
|
|
45
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { createGridInteractionsController } from './createGridInteractionsController';
|
|
4
|
+
|
|
5
|
+
const viewport = {
|
|
6
|
+
width: 100,
|
|
7
|
+
height: 100,
|
|
8
|
+
offsetX: 0,
|
|
9
|
+
offsetY: 0,
|
|
10
|
+
pixelsPerUnitX: 2,
|
|
11
|
+
pixelsPerUnitY: 4,
|
|
12
|
+
};
|
|
13
|
+
const items = [
|
|
14
|
+
{ id: 'a', x: 1, y: 1, width: 3, height: 2 },
|
|
15
|
+
{ id: 'locked', x: 10, y: 1, width: 2, height: 2, locked: true },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
describe('createGridInteractionsController', () => {
|
|
19
|
+
test('maps independent viewport scales to a move preview without mutating items', () => {
|
|
20
|
+
const intents: unknown[] = [];
|
|
21
|
+
const controller = createGridInteractionsController({
|
|
22
|
+
viewport,
|
|
23
|
+
items,
|
|
24
|
+
onIntent: (intent) => intents.push(intent),
|
|
25
|
+
});
|
|
26
|
+
controller.begin({ x: 3, y: 5 });
|
|
27
|
+
controller.move({ x: 7, y: 13 });
|
|
28
|
+
expect(intents).toEqual([
|
|
29
|
+
{ type: 'move', itemIds: ['a'], rects: [{ id: 'a', x: 3, y: 3, width: 3, height: 2 }] },
|
|
30
|
+
]);
|
|
31
|
+
expect(items[0]).toEqual({ id: 'a', x: 1, y: 1, width: 3, height: 2 });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('normalizes negative marquee drags and protects locked items', () => {
|
|
35
|
+
const intents: unknown[] = [];
|
|
36
|
+
const controller = createGridInteractionsController({
|
|
37
|
+
viewport,
|
|
38
|
+
items,
|
|
39
|
+
marqueeMode: 'intersect',
|
|
40
|
+
onIntent: (intent) => intents.push(intent),
|
|
41
|
+
});
|
|
42
|
+
controller.begin({ x: 24, y: 12 });
|
|
43
|
+
controller.end({ x: 0, y: 0 });
|
|
44
|
+
expect(intents).toEqual([
|
|
45
|
+
{ type: 'marquee', itemIds: ['a'], marquee: { x: 0, y: 0, width: 12, height: 3 } },
|
|
46
|
+
]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('keeps an active gesture while updating controlled props after a parent rerender', () => {
|
|
50
|
+
const initialIntents: unknown[] = [];
|
|
51
|
+
const rerenderedIntents: unknown[] = [];
|
|
52
|
+
const controller = createGridInteractionsController({
|
|
53
|
+
viewport,
|
|
54
|
+
items,
|
|
55
|
+
onIntent: (intent) => initialIntents.push(intent),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
controller.begin({ x: 3, y: 5 });
|
|
59
|
+
controller.update({
|
|
60
|
+
viewport,
|
|
61
|
+
items,
|
|
62
|
+
onIntent: (intent) => rerenderedIntents.push(intent),
|
|
63
|
+
});
|
|
64
|
+
controller.end({ x: 7, y: 13 });
|
|
65
|
+
|
|
66
|
+
expect(initialIntents).toEqual([]);
|
|
67
|
+
expect(rerenderedIntents).toEqual([
|
|
68
|
+
{ type: 'move', itemIds: ['a'], rects: [{ id: 'a', x: 3, y: 3, width: 3, height: 2 }] },
|
|
69
|
+
]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('emits keyboard resize and accelerated movement only while interaction is enabled', () => {
|
|
73
|
+
const intents: unknown[] = [];
|
|
74
|
+
const controller = createGridInteractionsController({
|
|
75
|
+
viewport,
|
|
76
|
+
items,
|
|
77
|
+
onIntent: (intent) => intents.push(intent),
|
|
78
|
+
selectedIds: ['a'],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(controller.keyDown('ArrowRight', { x: 0, y: 0, altKey: true })).toBe(true);
|
|
82
|
+
expect(controller.keyDown('ArrowDown', { x: 0, y: 0, shiftKey: true })).toBe(true);
|
|
83
|
+
controller.update({
|
|
84
|
+
interactionPolicy: 'passive',
|
|
85
|
+
viewport,
|
|
86
|
+
items,
|
|
87
|
+
onIntent: (intent) => intents.push(intent),
|
|
88
|
+
selectedIds: ['a'],
|
|
89
|
+
});
|
|
90
|
+
expect(controller.keyDown('ArrowLeft', { x: 0, y: 0 })).toBe(false);
|
|
91
|
+
controller.begin({ x: 3, y: 5 });
|
|
92
|
+
controller.end({ x: 7, y: 13 });
|
|
93
|
+
|
|
94
|
+
expect(intents).toEqual([
|
|
95
|
+
{ type: 'resize', itemIds: ['a'], rects: [{ id: 'a', x: 1, y: 1, width: 4, height: 2 }] },
|
|
96
|
+
{ type: 'move', itemIds: ['a'], rects: [{ id: 'a', x: 1, y: 11, width: 3, height: 2 }] },
|
|
97
|
+
]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('emits handle-driven resize intents for a pointer gesture', () => {
|
|
101
|
+
const intents: unknown[] = [];
|
|
102
|
+
const controller = createGridInteractionsController({
|
|
103
|
+
viewport,
|
|
104
|
+
items,
|
|
105
|
+
onIntent: (intent) => intents.push(intent),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
controller.begin({ x: 3, y: 5 }, 'bottom-right');
|
|
109
|
+
controller.end({ x: 7, y: 13 });
|
|
110
|
+
|
|
111
|
+
expect(intents).toEqual([
|
|
112
|
+
{ type: 'resize', itemIds: ['a'], rects: [{ id: 'a', x: 1, y: 1, width: 5, height: 4 }] },
|
|
113
|
+
]);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('does not compound controlled move previews or reapply the release endpoint', () => {
|
|
117
|
+
const intents: unknown[] = [];
|
|
118
|
+
const initialItems = [{ id: 'a', x: 40, y: 40, width: 20, height: 20 }];
|
|
119
|
+
const controller = createGridInteractionsController({
|
|
120
|
+
viewport,
|
|
121
|
+
items: initialItems,
|
|
122
|
+
onIntent: (intent) => intents.push(intent),
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
controller.begin({ x: 80, y: 160 });
|
|
126
|
+
controller.move({ x: 100, y: 160 });
|
|
127
|
+
controller.update({
|
|
128
|
+
viewport,
|
|
129
|
+
items: [{ id: 'a', x: 50, y: 40, width: 20, height: 20 }],
|
|
130
|
+
onIntent: (intent) => intents.push(intent),
|
|
131
|
+
});
|
|
132
|
+
controller.move({ x: 120, y: 160 });
|
|
133
|
+
controller.update({
|
|
134
|
+
viewport,
|
|
135
|
+
items: [{ id: 'a', x: 60, y: 40, width: 20, height: 20 }],
|
|
136
|
+
onIntent: (intent) => intents.push(intent),
|
|
137
|
+
});
|
|
138
|
+
controller.end({ x: 120, y: 160 });
|
|
139
|
+
|
|
140
|
+
expect(intents).toEqual([
|
|
141
|
+
{ type: 'move', itemIds: ['a'], rects: [{ id: 'a', x: 50, y: 40, width: 20, height: 20 }] },
|
|
142
|
+
{ type: 'move', itemIds: ['a'], rects: [{ id: 'a', x: 60, y: 40, width: 20, height: 20 }] },
|
|
143
|
+
]);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('keeps controlled resize, negative multi-item movement, cancel, and pan non-compounding', () => {
|
|
147
|
+
const resizeIntents: unknown[] = [];
|
|
148
|
+
const resizeController = createGridInteractionsController({
|
|
149
|
+
viewport,
|
|
150
|
+
items: [{ id: 'a', x: 40, y: 40, width: 20, height: 20 }],
|
|
151
|
+
onIntent: (intent) => resizeIntents.push(intent),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
resizeController.begin({ x: 120, y: 240 }, 'bottom-right');
|
|
155
|
+
resizeController.move({ x: 140, y: 280 });
|
|
156
|
+
resizeController.update({
|
|
157
|
+
viewport,
|
|
158
|
+
items: [{ id: 'a', x: 40, y: 40, width: 30, height: 30 }],
|
|
159
|
+
onIntent: (intent) => resizeIntents.push(intent),
|
|
160
|
+
});
|
|
161
|
+
resizeController.move({ x: 160, y: 320 });
|
|
162
|
+
resizeController.update({
|
|
163
|
+
viewport,
|
|
164
|
+
items: [{ id: 'a', x: 40, y: 40, width: 40, height: 40 }],
|
|
165
|
+
onIntent: (intent) => resizeIntents.push(intent),
|
|
166
|
+
});
|
|
167
|
+
resizeController.end({ x: 160, y: 320 });
|
|
168
|
+
|
|
169
|
+
const moveIntents: unknown[] = [];
|
|
170
|
+
const moveController = createGridInteractionsController({
|
|
171
|
+
viewport,
|
|
172
|
+
items: [
|
|
173
|
+
{ id: 'a', x: 40, y: 40, width: 20, height: 20 },
|
|
174
|
+
{ id: 'b', x: 80, y: 40, width: 20, height: 20 },
|
|
175
|
+
],
|
|
176
|
+
selectedIds: ['a', 'b'],
|
|
177
|
+
onIntent: (intent) => moveIntents.push(intent),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
moveController.begin({ x: 80, y: 160 });
|
|
181
|
+
moveController.move({ x: 60, y: 120 });
|
|
182
|
+
moveController.cancel();
|
|
183
|
+
moveController.end({ x: 40, y: 80 });
|
|
184
|
+
|
|
185
|
+
const panIntents: unknown[] = [];
|
|
186
|
+
const panController = createGridInteractionsController({
|
|
187
|
+
viewport,
|
|
188
|
+
items: [],
|
|
189
|
+
onIntent: (intent) => panIntents.push(intent),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
panController.begin({ x: 20, y: 40, spaceKey: true });
|
|
193
|
+
panController.move({ x: 40, y: 80 });
|
|
194
|
+
panController.update({
|
|
195
|
+
viewport: { ...viewport, offsetX: 5, offsetY: 2.5 },
|
|
196
|
+
items: [],
|
|
197
|
+
onIntent: (intent) => panIntents.push(intent),
|
|
198
|
+
});
|
|
199
|
+
panController.move({ x: 60, y: 120 });
|
|
200
|
+
panController.end({ x: 60, y: 120 });
|
|
201
|
+
|
|
202
|
+
expect(resizeIntents).toEqual([
|
|
203
|
+
{ type: 'resize', itemIds: ['a'], rects: [{ id: 'a', x: 40, y: 40, width: 30, height: 30 }] },
|
|
204
|
+
{ type: 'resize', itemIds: ['a'], rects: [{ id: 'a', x: 40, y: 40, width: 40, height: 40 }] },
|
|
205
|
+
]);
|
|
206
|
+
expect(moveIntents).toEqual([
|
|
207
|
+
{
|
|
208
|
+
type: 'move',
|
|
209
|
+
itemIds: ['a', 'b'],
|
|
210
|
+
rects: [
|
|
211
|
+
{ id: 'a', x: 30, y: 30, width: 20, height: 20 },
|
|
212
|
+
{ id: 'b', x: 70, y: 30, width: 20, height: 20 },
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
]);
|
|
216
|
+
expect(panIntents).toEqual([
|
|
217
|
+
{
|
|
218
|
+
type: 'pan',
|
|
219
|
+
itemIds: [],
|
|
220
|
+
viewport: { ...viewport, offsetX: 5, offsetY: 2.5 },
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
type: 'pan',
|
|
224
|
+
itemIds: [],
|
|
225
|
+
viewport: { ...viewport, offsetX: 10, offsetY: 5 },
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type GridPoint,
|
|
3
|
+
type GridRect,
|
|
4
|
+
type GridResizeHandle,
|
|
5
|
+
type GridViewport,
|
|
6
|
+
hitTestWorldRects,
|
|
7
|
+
moveWorldRects,
|
|
8
|
+
panViewport,
|
|
9
|
+
resizeWorldRect,
|
|
10
|
+
resolveWorldSnapCandidate,
|
|
11
|
+
selectWorldRects,
|
|
12
|
+
viewportToWorld,
|
|
13
|
+
} from '@ankhorage/grid-view';
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
GridInteractionIntent,
|
|
17
|
+
GridInteractionItem,
|
|
18
|
+
GridInteractionPointer,
|
|
19
|
+
GridInteractionsController,
|
|
20
|
+
GridInteractionsControllerProps,
|
|
21
|
+
} from '../../../types/grid-interactions';
|
|
22
|
+
|
|
23
|
+
type InteractionState =
|
|
24
|
+
| { readonly kind: 'idle' }
|
|
25
|
+
| { readonly kind: 'marquee'; readonly start: GridPoint; readonly viewport: GridViewport }
|
|
26
|
+
| { readonly kind: 'pan'; readonly start: GridPoint; readonly viewport: GridViewport }
|
|
27
|
+
| {
|
|
28
|
+
readonly kind: 'move';
|
|
29
|
+
readonly start: GridPoint;
|
|
30
|
+
readonly viewport: GridViewport;
|
|
31
|
+
readonly itemIds: readonly string[];
|
|
32
|
+
readonly items: readonly GridInteractionItem[];
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
readonly kind: 'resize';
|
|
36
|
+
readonly start: GridPoint;
|
|
37
|
+
readonly viewport: GridViewport;
|
|
38
|
+
readonly item: GridInteractionItem;
|
|
39
|
+
readonly handle: GridResizeHandle;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/*** Create a platform-neutral controlled interaction controller using grid-view geometry only. */
|
|
43
|
+
export function createGridInteractionsController(
|
|
44
|
+
props: GridInteractionsControllerProps,
|
|
45
|
+
): GridInteractionsController {
|
|
46
|
+
let currentProps = props;
|
|
47
|
+
let state: InteractionState = { kind: 'idle' };
|
|
48
|
+
let previousIntent: GridInteractionIntent | undefined;
|
|
49
|
+
const point = (pointer: GridInteractionPointer, viewport = currentProps.viewport) =>
|
|
50
|
+
Number.isFinite(pointer.x) && Number.isFinite(pointer.y)
|
|
51
|
+
? viewportToWorld(pointer, viewport)
|
|
52
|
+
: undefined;
|
|
53
|
+
const emit = (intent: GridInteractionIntent) => {
|
|
54
|
+
if (JSON.stringify(previousIntent) === JSON.stringify(intent)) return;
|
|
55
|
+
previousIntent = intent;
|
|
56
|
+
currentProps.onIntent(intent);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
begin: (pointer, handle) => {
|
|
61
|
+
if (!canEdit(currentProps)) return;
|
|
62
|
+
const start = point(pointer);
|
|
63
|
+
if (start === undefined) return;
|
|
64
|
+
if (pointer.spaceKey === true || pointer.altKey === true) {
|
|
65
|
+
state = { kind: 'pan', start, viewport: currentProps.viewport };
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const target = hitTestWorldRects(currentProps.items, start);
|
|
69
|
+
if (target === undefined || isProtected(target)) {
|
|
70
|
+
state = { kind: 'marquee', start, viewport: currentProps.viewport };
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (handle !== undefined && target.resizable !== false) {
|
|
74
|
+
state = { kind: 'resize', start, viewport: currentProps.viewport, item: target, handle };
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const itemIds =
|
|
78
|
+
currentProps.selectedIds?.includes(target.id) === true
|
|
79
|
+
? currentProps.selectedIds
|
|
80
|
+
: [target.id];
|
|
81
|
+
state = {
|
|
82
|
+
kind: 'move',
|
|
83
|
+
start,
|
|
84
|
+
viewport: currentProps.viewport,
|
|
85
|
+
itemIds,
|
|
86
|
+
items: currentProps.items.filter((item) => itemIds.includes(item.id)),
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
move: (pointer) => {
|
|
90
|
+
if (!canEdit(currentProps)) return;
|
|
91
|
+
const current = point(pointer, viewportForState(state, currentProps.viewport));
|
|
92
|
+
if (current !== undefined) emitPreview(state, current, currentProps, emit);
|
|
93
|
+
},
|
|
94
|
+
end: (pointer) => {
|
|
95
|
+
if (!canEdit(currentProps)) {
|
|
96
|
+
state = { kind: 'idle' };
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const current = point(pointer, viewportForState(state, currentProps.viewport));
|
|
100
|
+
if (current !== undefined) emitPreview(state, current, currentProps, emit);
|
|
101
|
+
state = { kind: 'idle' };
|
|
102
|
+
},
|
|
103
|
+
cancel: () => {
|
|
104
|
+
state = { kind: 'idle' };
|
|
105
|
+
},
|
|
106
|
+
keyDown: (key, pointer = { x: 0, y: 0 }) => {
|
|
107
|
+
if (!canEdit(currentProps)) return false;
|
|
108
|
+
const focusedId = currentProps.selectedIds?.at(-1);
|
|
109
|
+
const focused = currentProps.items.find((item) => item.id === focusedId);
|
|
110
|
+
if (!focused || isProtected(focused)) return false;
|
|
111
|
+
const increment = pointer.shiftKey === true ? 10 : 1;
|
|
112
|
+
const delta = keyToDelta(key, increment);
|
|
113
|
+
if (delta === undefined) return false;
|
|
114
|
+
if (pointer.altKey === true) {
|
|
115
|
+
emit({
|
|
116
|
+
type: 'resize',
|
|
117
|
+
itemIds: [focused.id],
|
|
118
|
+
rects: [resizeWorldRect(focused, resizeHandleForDelta(delta), delta)],
|
|
119
|
+
});
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
emit({ type: 'move', itemIds: [focused.id], rects: moveWorldRects([focused], delta) });
|
|
123
|
+
return true;
|
|
124
|
+
},
|
|
125
|
+
update: (nextProps) => {
|
|
126
|
+
currentProps = nextProps;
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*** Determines whether the component-wide interaction policy permits edit intents. */
|
|
132
|
+
function canEdit(props: GridInteractionsControllerProps): boolean {
|
|
133
|
+
return props.interactionPolicy !== 'passive';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/*** Emit one controlled preview/intention without retaining or mutating caller-owned item data. */
|
|
137
|
+
function emitPreview(
|
|
138
|
+
state: InteractionState,
|
|
139
|
+
current: GridPoint,
|
|
140
|
+
props: GridInteractionsControllerProps,
|
|
141
|
+
emit: (intent: GridInteractionIntent) => void,
|
|
142
|
+
) {
|
|
143
|
+
if (state.kind === 'idle') return;
|
|
144
|
+
if (state.kind === 'pan') {
|
|
145
|
+
emit({
|
|
146
|
+
type: 'pan',
|
|
147
|
+
itemIds: [],
|
|
148
|
+
viewport: panViewport(state.viewport, {
|
|
149
|
+
x: state.start.x - current.x,
|
|
150
|
+
y: state.start.y - current.y,
|
|
151
|
+
}),
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (state.kind === 'marquee') {
|
|
156
|
+
const marquee = normalizeRect(state.start, current);
|
|
157
|
+
const itemIds = selectWorldRects(props.items, marquee, {
|
|
158
|
+
mode: props.marqueeMode ?? 'intersect',
|
|
159
|
+
}).filter((id) => {
|
|
160
|
+
const item = props.items.find((candidate) => candidate.id === id);
|
|
161
|
+
return item !== undefined && !isProtected(item);
|
|
162
|
+
});
|
|
163
|
+
emit({ type: 'marquee', itemIds, marquee });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const delta = resolveSnapDelta(state, current, props);
|
|
167
|
+
if (state.kind === 'move') {
|
|
168
|
+
emit({ type: 'move', itemIds: state.itemIds, rects: moveWorldRects(state.items, delta) });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
emit({
|
|
172
|
+
type: 'resize',
|
|
173
|
+
itemIds: [state.item.id],
|
|
174
|
+
rects: [resizeWorldRect(state.item, state.handle, delta)],
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/*** Resolve explicit per-axis candidate snapping without inventing geometry outside grid-view. */
|
|
179
|
+
function resolveSnapDelta(
|
|
180
|
+
state: InteractionState,
|
|
181
|
+
current: GridPoint,
|
|
182
|
+
props: GridInteractionsControllerProps,
|
|
183
|
+
): GridPoint {
|
|
184
|
+
if (state.kind === 'idle' || state.kind === 'marquee' || state.kind === 'pan') {
|
|
185
|
+
return { x: 0, y: 0 };
|
|
186
|
+
}
|
|
187
|
+
const raw = { x: current.x - state.start.x, y: current.y - state.start.y };
|
|
188
|
+
if (props.snap?.enabled !== true) return raw;
|
|
189
|
+
const anchor = state.kind === 'resize' ? state.item : state.items.at(0);
|
|
190
|
+
if (anchor === undefined) return raw;
|
|
191
|
+
const options = {
|
|
192
|
+
enabled: true,
|
|
193
|
+
tolerancePixels: props.snap.tolerancePixels,
|
|
194
|
+
priorities: props.snap.priorities,
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
x:
|
|
198
|
+
resolveWorldSnapCandidate(anchor.x + raw.x, props.snap.x ?? [], {
|
|
199
|
+
...options,
|
|
200
|
+
pixelsPerUnit: props.viewport.pixelsPerUnitX,
|
|
201
|
+
}) - anchor.x,
|
|
202
|
+
y:
|
|
203
|
+
resolveWorldSnapCandidate(anchor.y + raw.y, props.snap.y ?? [], {
|
|
204
|
+
...options,
|
|
205
|
+
pixelsPerUnit: props.viewport.pixelsPerUnitY,
|
|
206
|
+
}) - anchor.y,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/*** Keep pointer coordinates in the original gesture coordinate space across controlled updates. */
|
|
211
|
+
function viewportForState(state: InteractionState, fallback: GridViewport): GridViewport {
|
|
212
|
+
return state.kind === 'idle' ? fallback : state.viewport;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/*** Keep all caller-declared protected items out of selection and edit intents. */
|
|
216
|
+
function isProtected(item: GridInteractionItem): boolean {
|
|
217
|
+
return (
|
|
218
|
+
item.disabled === true ||
|
|
219
|
+
item.locked === true ||
|
|
220
|
+
item.readOnly === true ||
|
|
221
|
+
item.passive === true
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/*** Normalize an arbitrary-direction drag into the world rectangle expected by grid-view selection. */
|
|
226
|
+
function normalizeRect(start: GridPoint, end: GridPoint): GridRect {
|
|
227
|
+
return {
|
|
228
|
+
x: Math.min(start.x, end.x),
|
|
229
|
+
y: Math.min(start.y, end.y),
|
|
230
|
+
width: Math.abs(end.x - start.x),
|
|
231
|
+
height: Math.abs(end.y - start.y),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Maps accessible arrow keys to caller-controlled world-space edit increments. */
|
|
236
|
+
function keyToDelta(key: string, increment: number): GridPoint | undefined {
|
|
237
|
+
if (key === 'ArrowUp') return { x: 0, y: -increment };
|
|
238
|
+
if (key === 'ArrowRight') return { x: increment, y: 0 };
|
|
239
|
+
if (key === 'ArrowDown') return { x: 0, y: increment };
|
|
240
|
+
if (key === 'ArrowLeft') return { x: -increment, y: 0 };
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Chooses the physical edge matching an accessible resize direction. */
|
|
245
|
+
function resizeHandleForDelta(delta: GridPoint): GridResizeHandle {
|
|
246
|
+
if (delta.x < 0) return delta.y < 0 ? 'top-left' : delta.y > 0 ? 'bottom-left' : 'left';
|
|
247
|
+
return delta.y < 0 ? 'top-right' : delta.y > 0 ? 'bottom-right' : 'right';
|
|
248
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '../../types/authoring';
|
|
2
|
+
|
|
3
|
+
/** Grid input is a code composition boundary because it accepts live geometry and callbacks. */
|
|
4
|
+
export const gridInteractionsMeta = {
|
|
5
|
+
name: 'GridInteractions',
|
|
6
|
+
category: 'foundation',
|
|
7
|
+
description: 'Maps native and web input to controlled world-space grid interaction intents.',
|
|
8
|
+
directManifestNode: false,
|
|
9
|
+
note: 'Requires live viewport geometry, item data, and an executable intent callback; available through code APIs only.',
|
|
10
|
+
allowedChildren: [],
|
|
11
|
+
props: {},
|
|
12
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
GridInteractionIntent,
|
|
3
|
+
GridInteractionItem,
|
|
4
|
+
GridInteractionPointer,
|
|
5
|
+
GridInteractionsController,
|
|
6
|
+
GridInteractionsControllerProps,
|
|
7
|
+
GridInteractionSnap,
|
|
8
|
+
GridInteractionsProps,
|
|
9
|
+
} from '../../types/grid-interactions';
|
|
10
|
+
export { GridInteractions } from './adapters/inbound/GridInteractions';
|
|
11
|
+
export { createGridInteractionsController } from './application/createGridInteractionsController';
|