@ankhorage/zora 25.8.11 → 25.8.12

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.
Files changed (221) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +2 -1
  3. package/dist/features/grid-interactions/adapters/inbound/GridInteractions.d.ts.map +1 -1
  4. package/dist/features/grid-interactions/adapters/inbound/GridInteractions.js +11 -2
  5. package/dist/features/grid-interactions/adapters/inbound/GridInteractions.js.map +1 -1
  6. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.d.ts +2 -0
  7. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.d.ts.map +1 -0
  8. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.js +2 -0
  9. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.js.map +1 -0
  10. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.d.ts +4 -0
  11. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.d.ts.map +1 -0
  12. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.js +11 -0
  13. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.js.map +1 -0
  14. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.d.ts +4 -0
  15. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.d.ts.map +1 -0
  16. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.js +9 -0
  17. package/dist/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.js.map +1 -0
  18. package/dist/features/grid-interactions/application/createGridInteractionScrollLock.d.ts +5 -0
  19. package/dist/features/grid-interactions/application/createGridInteractionScrollLock.d.ts.map +1 -0
  20. package/dist/features/grid-interactions/application/createGridInteractionScrollLock.js +14 -0
  21. package/dist/features/grid-interactions/application/createGridInteractionScrollLock.js.map +1 -0
  22. package/dist/features/grid-view/adapters/inbound/GridView.d.ts.map +1 -1
  23. package/dist/features/grid-view/adapters/inbound/GridView.js +34 -30
  24. package/dist/features/grid-view/adapters/inbound/GridView.js.map +1 -1
  25. package/dist/features/grid-view/application/createGridScrollSync.d.ts +7 -0
  26. package/dist/features/grid-view/application/createGridScrollSync.d.ts.map +1 -0
  27. package/dist/features/grid-view/application/createGridScrollSync.js +141 -0
  28. package/dist/features/grid-view/application/createGridScrollSync.js.map +1 -0
  29. package/dist/features/grid-view/application/resolveScrollEventSource.d.ts +4 -0
  30. package/dist/features/grid-view/application/resolveScrollEventSource.d.ts.map +1 -0
  31. package/dist/features/grid-view/application/resolveScrollEventSource.js +8 -0
  32. package/dist/features/grid-view/application/resolveScrollEventSource.js.map +1 -0
  33. package/dist/features/grid-view/constants/scroll.d.ts +7 -0
  34. package/dist/features/grid-view/constants/scroll.d.ts.map +1 -0
  35. package/dist/features/grid-view/constants/scroll.js +7 -0
  36. package/dist/features/grid-view/constants/scroll.js.map +1 -0
  37. package/dist/features/layout/adapters/inbound/ScrollGestureLockContext.d.ts +5 -0
  38. package/dist/features/layout/adapters/inbound/ScrollGestureLockContext.d.ts.map +1 -0
  39. package/dist/features/layout/adapters/inbound/ScrollGestureLockContext.js +4 -0
  40. package/dist/features/layout/adapters/inbound/ScrollGestureLockContext.js.map +1 -0
  41. package/dist/features/layout/adapters/inbound/ScrollView.d.ts.map +1 -1
  42. package/dist/features/layout/adapters/inbound/ScrollView.js +11 -3
  43. package/dist/features/layout/adapters/inbound/ScrollView.js.map +1 -1
  44. package/dist/features/layout/adapters/inbound/useScrollGestureLock.d.ts +4 -0
  45. package/dist/features/layout/adapters/inbound/useScrollGestureLock.d.ts.map +1 -0
  46. package/dist/features/layout/adapters/inbound/useScrollGestureLock.js +8 -0
  47. package/dist/features/layout/adapters/inbound/useScrollGestureLock.js.map +1 -0
  48. package/dist/features/layout/public.d.ts +2 -1
  49. package/dist/features/layout/public.d.ts.map +1 -1
  50. package/dist/features/layout/public.js +1 -0
  51. package/dist/features/layout/public.js.map +1 -1
  52. package/dist/features/layout/utils/createScrollGestureLock.d.ts +4 -0
  53. package/dist/features/layout/utils/createScrollGestureLock.d.ts.map +1 -0
  54. package/dist/features/layout/utils/createScrollGestureLock.js +18 -0
  55. package/dist/features/layout/utils/createScrollGestureLock.js.map +1 -0
  56. package/dist/types/grid-interactions.d.ts +5 -0
  57. package/dist/types/grid-interactions.d.ts.map +1 -1
  58. package/dist/types/grid-interactions.js.map +1 -1
  59. package/dist/types/grid-view.d.ts +40 -0
  60. package/dist/types/grid-view.d.ts.map +1 -1
  61. package/dist/types/grid-view.js.map +1 -1
  62. package/dist/types/layout.d.ts +5 -0
  63. package/dist/types/layout.d.ts.map +1 -1
  64. package/dist/types/layout.js.map +1 -1
  65. package/package.json +2 -2
  66. package/src/features/grid-interactions/adapters/inbound/GridInteractions.scrollLock.test.tsx +265 -0
  67. package/src/features/grid-interactions/adapters/inbound/GridInteractions.test.tsx +64 -0
  68. package/src/features/grid-interactions/adapters/inbound/GridInteractions.tsx +12 -4
  69. package/src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.ts +17 -0
  70. package/src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.ts +1 -0
  71. package/src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.ts +11 -0
  72. package/src/features/grid-interactions/application/createGridInteractionScrollLock.test.ts +41 -0
  73. package/src/features/grid-interactions/application/createGridInteractionScrollLock.ts +18 -0
  74. package/src/features/grid-view/adapters/inbound/GridView.nativeScrollSync.test.tsx +186 -0
  75. package/src/features/grid-view/adapters/inbound/GridView.scrollSync.interaction.test.tsx +304 -0
  76. package/src/features/grid-view/adapters/inbound/GridView.tsx +49 -29
  77. package/src/features/grid-view/application/createGridScrollSync.test.ts +292 -0
  78. package/src/features/grid-view/application/createGridScrollSync.ts +169 -0
  79. package/src/features/grid-view/application/resolveScrollEventSource.test.ts +19 -0
  80. package/src/features/grid-view/application/resolveScrollEventSource.ts +12 -0
  81. package/src/features/grid-view/constants/scroll.ts +8 -0
  82. package/src/features/layout/adapters/inbound/ScrollGestureLockContext.ts +8 -0
  83. package/src/features/layout/adapters/inbound/ScrollView.test.tsx +234 -0
  84. package/src/features/layout/adapters/inbound/ScrollView.tsx +18 -2
  85. package/src/features/layout/adapters/inbound/useScrollGestureLock.ts +11 -0
  86. package/src/features/layout/public.ts +2 -0
  87. package/src/features/layout/utils/createScrollGestureLock.test.ts +34 -0
  88. package/src/features/layout/utils/createScrollGestureLock.ts +21 -0
  89. package/src/types/grid-interactions.ts +6 -0
  90. package/src/types/grid-view.ts +45 -0
  91. package/src/types/layout.ts +6 -0
  92. package/web-dist/chunks/{Accordion-v3rzy273.js → Accordion-11ej93t5.js} +3 -3
  93. package/web-dist/chunks/{Accordion-ddrn94v3.js → Accordion-1hbt9k69.js} +1 -1
  94. package/web-dist/chunks/{Accordion-wpk8dxqp.js → Accordion-26prtnm7.js} +1 -1
  95. package/web-dist/chunks/{Accordion-0q2wzjdd.js → Accordion-2jy53kzk.js} +2 -2
  96. package/web-dist/chunks/{Accordion-geah5s4f.js → Accordion-4yq92mxp.js} +1 -1
  97. package/web-dist/chunks/{Accordion-8pkw32q9.js → Accordion-5pr1wqe3.js} +1 -1
  98. package/web-dist/chunks/{Accordion-y3083394.js → Accordion-799z2zf6.js} +1 -1
  99. package/web-dist/chunks/{Accordion-hecpczme.js → Accordion-9aczb0k2.js} +2 -2
  100. package/web-dist/chunks/{Accordion-rctfgyfv.js → Accordion-a4pz3vjj.js} +1 -1
  101. package/web-dist/chunks/{Accordion-9jrxktne.js → Accordion-b337t2df.js} +1 -1
  102. package/web-dist/chunks/{Accordion-h4ekm5cp.js → Accordion-czcaf5x2.js} +1 -1
  103. package/web-dist/chunks/{Accordion-vbzjq3z8.js → Accordion-ep35792s.js} +44 -2
  104. package/web-dist/chunks/{Accordion-ts788t7b.js → Accordion-g08740h4.js} +1 -1
  105. package/web-dist/chunks/{Accordion-9ygakvwk.js → Accordion-g2aqhct0.js} +4 -4
  106. package/web-dist/chunks/{Accordion-p1ebrt17.js → Accordion-gn8ptzwb.js} +1 -1
  107. package/web-dist/chunks/{Accordion-sq7ya2ye.js → Accordion-h9brgsk8.js} +1 -1
  108. package/web-dist/chunks/{Accordion-ztw7zp6v.js → Accordion-m2hcc8g4.js} +2 -2
  109. package/web-dist/chunks/{Accordion-sdnzqktc.js → Accordion-m6mp8aea.js} +3 -3
  110. package/web-dist/chunks/{Accordion-vxg5sw01.js → Accordion-p7d5svfq.js} +1 -1
  111. package/web-dist/chunks/{Accordion-k9cxpg08.js → Accordion-rqhh2m5b.js} +3 -3
  112. package/web-dist/chunks/{Accordion-wcmrasqx.js → Accordion-rqr10gn4.js} +4 -4
  113. package/web-dist/chunks/{Accordion-hn43wt45.js → Accordion-t0k1cjca.js} +181 -29
  114. package/web-dist/chunks/{Accordion-w59y0jdf.js → Accordion-tyh8jj9d.js} +1 -1
  115. package/web-dist/chunks/{Accordion-dk0dtyc0.js → Accordion-vjcd5kxc.js} +1 -1
  116. package/web-dist/chunks/{Accordion-t5scffdr.js → Accordion-vkd002gw.js} +5 -5
  117. package/web-dist/chunks/{Accordion-r87xx7mg.js → Accordion-w87gvpbg.js} +1 -1
  118. package/web-dist/chunks/{Accordion-yexfbrzg.js → Accordion-wqyrrptg.js} +2 -2
  119. package/web-dist/chunks/{Accordion-c50pywj3.js → Accordion-y2pss5p0.js} +1 -1
  120. package/web-dist/components/accordion/Accordion.js +2 -2
  121. package/web-dist/components/accordion-item/AccordionItem.js +2 -2
  122. package/web-dist/components/app-bar/AppBar.js +4 -4
  123. package/web-dist/components/app-header/AppHeader.js +4 -4
  124. package/web-dist/components/app-shell/AppShell.js +1 -1
  125. package/web-dist/components/auth-screen/AuthScreen.js +6 -6
  126. package/web-dist/components/avatar/Avatar.js +2 -2
  127. package/web-dist/components/avatar-group/AvatarGroup.js +2 -2
  128. package/web-dist/components/barcode-scanner-view/BarcodeScannerView.js +6 -6
  129. package/web-dist/components/bottom-sheet/BottomSheet.js +2 -2
  130. package/web-dist/components/bottom-sheet-flat-list/BottomSheetFlatList.js +2 -2
  131. package/web-dist/components/bottom-sheet-scroll-view/BottomSheetScrollView.js +2 -2
  132. package/web-dist/components/bottom-sheet-section-list/BottomSheetSectionList.js +2 -2
  133. package/web-dist/components/bottom-sheet-view/BottomSheetView.js +2 -2
  134. package/web-dist/components/bottom-sheet-virtualized-list/BottomSheetVirtualizedList.js +2 -2
  135. package/web-dist/components/breadcrumbs/Breadcrumbs.js +2 -2
  136. package/web-dist/components/button/Button.js +2 -2
  137. package/web-dist/components/button-group/ButtonGroup.js +2 -2
  138. package/web-dist/components/camera-permission-view/CameraPermissionView.js +6 -6
  139. package/web-dist/components/card/Card.js +5 -5
  140. package/web-dist/components/chat-list-item/ChatListItem.js +3 -3
  141. package/web-dist/components/checkbox/Checkbox.js +2 -2
  142. package/web-dist/components/checkbox-group/CheckboxGroup.js +2 -2
  143. package/web-dist/components/chip/Chip.js +2 -2
  144. package/web-dist/components/chip-group/ChipGroup.js +2 -2
  145. package/web-dist/components/collection-editor/CollectionEditor.js +5 -5
  146. package/web-dist/components/content-rail/ContentRail.js +2 -2
  147. package/web-dist/components/data-table/DataTable.js +10 -10
  148. package/web-dist/components/date-picker/DatePicker.js +2 -2
  149. package/web-dist/components/dialog/Dialog.js +2 -2
  150. package/web-dist/components/divider/Divider.js +1 -1
  151. package/web-dist/components/empty-state/EmptyState.js +6 -6
  152. package/web-dist/components/explorer/Explorer.js +4 -4
  153. package/web-dist/components/field/Field.js +2 -2
  154. package/web-dist/components/file-explorer/FileExplorer.js +4 -4
  155. package/web-dist/components/flat-list/FlatList.js +3 -3
  156. package/web-dist/components/forgot-password-form/ForgotPasswordForm.js +6 -6
  157. package/web-dist/components/form/Form.js +4 -4
  158. package/web-dist/components/form-actions/FormActions.js +4 -4
  159. package/web-dist/components/form-error/FormError.js +4 -4
  160. package/web-dist/components/game/Game.js +2 -2
  161. package/web-dist/components/game-entity/GameEntity.js +2 -2
  162. package/web-dist/components/game-field/GameField.js +2 -2
  163. package/web-dist/components/game-input-zone/GameInputZone.js +2 -2
  164. package/web-dist/components/game-measurement-probe/GameMeasurementProbe.js +2 -2
  165. package/web-dist/components/game-overlay/GameOverlay.js +2 -2
  166. package/web-dist/components/gradient/Gradient.js +2 -2
  167. package/web-dist/components/gradient-renderer-provider/GradientRendererProvider.js +2 -2
  168. package/web-dist/components/grid/Grid.js +1 -1
  169. package/web-dist/components/grid-interactions/GridInteractions.js +24 -2
  170. package/web-dist/components/grid-view/GridView.js +1 -1
  171. package/web-dist/components/hero/Hero.js +5 -5
  172. package/web-dist/components/icon-button/IconButton.js +2 -2
  173. package/web-dist/components/image/Image.js +2 -2
  174. package/web-dist/components/list/List.js +3 -3
  175. package/web-dist/components/list-item/ListItem.js +3 -3
  176. package/web-dist/components/list-section/ListSection.js +3 -3
  177. package/web-dist/components/matrix-grid/MatrixGrid.js +1 -1
  178. package/web-dist/components/media-card/MediaCard.js +5 -5
  179. package/web-dist/components/media-explorer/MediaExplorer.js +4 -4
  180. package/web-dist/components/message-bubble/MessageBubble.js +3 -3
  181. package/web-dist/components/metric-card/MetricCard.js +5 -5
  182. package/web-dist/components/missing-element/MissingElement.js +1 -1
  183. package/web-dist/components/o-auth-provider-button/OAuthProviderButton.js +6 -6
  184. package/web-dist/components/o-auth-provider-list/OAuthProviderList.js +6 -6
  185. package/web-dist/components/otp-form/OtpForm.js +6 -6
  186. package/web-dist/components/pagination/Pagination.js +2 -2
  187. package/web-dist/components/palette-item/PaletteItem.js +5 -5
  188. package/web-dist/components/popover-menu/PopoverMenu.js +2 -2
  189. package/web-dist/components/post-card/PostCard.js +5 -5
  190. package/web-dist/components/product-card/ProductCard.js +5 -5
  191. package/web-dist/components/progress/Progress.js +2 -2
  192. package/web-dist/components/progress-ring/ProgressRing.js +2 -2
  193. package/web-dist/components/radio/Radio.js +2 -2
  194. package/web-dist/components/radio-group/RadioGroup.js +2 -2
  195. package/web-dist/components/rating/Rating.js +1 -1
  196. package/web-dist/components/reader/Reader.js +6 -6
  197. package/web-dist/components/scan-overlay/ScanOverlay.js +6 -6
  198. package/web-dist/components/screen/Screen.js +1 -1
  199. package/web-dist/components/screen-section/ScreenSection.js +2 -2
  200. package/web-dist/components/scroll-view/ScrollView.js +1 -1
  201. package/web-dist/components/search-input/SearchInput.js +3 -3
  202. package/web-dist/components/section-header/SectionHeader.js +2 -2
  203. package/web-dist/components/section-list/SectionList.js +3 -3
  204. package/web-dist/components/select/Select.js +2 -2
  205. package/web-dist/components/sign-in-form/SignInForm.js +6 -6
  206. package/web-dist/components/sign-up-form/SignUpForm.js +6 -6
  207. package/web-dist/components/skeleton/Skeleton.js +8 -8
  208. package/web-dist/components/skeleton-card/SkeletonCard.js +8 -8
  209. package/web-dist/components/skeleton-list/SkeletonList.js +8 -8
  210. package/web-dist/components/skeleton-text/SkeletonText.js +8 -8
  211. package/web-dist/components/spatial-grid/SpatialGrid.js +1 -1
  212. package/web-dist/components/text-input/TextInput.js +3 -3
  213. package/web-dist/components/tile-grid/TileGrid.js +1 -1
  214. package/web-dist/components/time-grid/TimeGrid.js +1 -1
  215. package/web-dist/components/time-picker/TimePicker.js +2 -2
  216. package/web-dist/components/timeline/Timeline.js +1 -1
  217. package/web-dist/components/toolbar/Toolbar.js +5 -5
  218. package/web-dist/components/tree-item/TreeItem.js +4 -4
  219. package/web-dist/components/uploader/Uploader.js +9 -9
  220. package/web-dist/components/view/View.js +1 -1
  221. package/web-dist/manifest.json +326 -326
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 25.8.12
4
+
5
+ ### Patch Changes
6
+
7
+ - fe26980: Fix native GridView and GridInteractions gesture ownership. GridView no longer treats native scroll echoes of its own animated focus reveal as user pans, which could sustain an unbounded viewport and render loop in large SpatialGrid boards. GridInteractions now refuses responder termination requests and suspends ancestor ZORA ScrollView scrolling for the duration of an active native drag.
8
+
3
9
  ## 25.8.11
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/zora
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v25.8.11](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: warnings](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v25.8.12](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: warnings](././paradox/badges/docs.svg)
7
7
 
8
8
  Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
9
9
 
@@ -65,6 +65,7 @@ This package contains 6 additional examples. See the generated documentation for
65
65
  - [createPokerTrainingTableState sequence](././paradox/diagrams/sequences/create-poker-training-table-state.mmd)
66
66
  - [createZoraThemeConfig sequence](././paradox/diagrams/sequences/create-zora-theme-config.mmd)
67
67
  - [getLegalTargets sequence](././paradox/diagrams/sequences/get-legal-targets.mmd)
68
+ - [GridInteractions sequence](././paradox/diagrams/sequences/grid-interactions.mmd)
68
69
  - [GridView sequence](././paradox/diagrams/sequences/grid-view.mmd)
69
70
  - [readChessPieces sequence](././paradox/diagrams/sequences/read-chess-pieces.mmd)
70
71
  - [resolveAvatarInitials sequence](././paradox/diagrams/sequences/resolve-avatar-initials.mmd)
@@ -1 +1 @@
1
- {"version":3,"file":"GridInteractions.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/GridInteractions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,qCAAqC,CAAC;AAM7C,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,MAAM,EACN,GAAG,KAAK,EACT,EAAE,qBAAqB,qBAmEvB"}
1
+ {"version":3,"file":"GridInteractions.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/GridInteractions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAEV,qBAAqB,EACtB,MAAM,qCAAqC,CAAC;AAO7C,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,MAAM,EACN,GAAG,KAAK,EACT,EAAE,qBAAqB,qBA0EvB"}
@@ -4,6 +4,7 @@ import { createGridInteractionsController } from '../../application/createGridIn
4
4
  import { createGridInteractionsPointerQueue } from './createGridInteractionsPointerQueue';
5
5
  import { GridInteractionsKeyboardProxy } from './GridInteractionsKeyboardProxy';
6
6
  import { resolveGridInteractionPointer } from './resolveGridInteractionPointer';
7
+ import { useGridInteractionScrollLock } from './useGridInteractionScrollLock';
7
8
  /*** Adapts native responder and keyboard events to the controlled grid interaction boundary. */
8
9
  export function GridInteractions({ children, interactionPolicy, resizeHandle, testID, ...props }) {
9
10
  const controllerProps = React.useMemo(() => ({ ...props, interactionPolicy }), [interactionPolicy, props]);
@@ -11,6 +12,7 @@ export function GridInteractions({ children, interactionPolicy, resizeHandle, te
11
12
  const surfaceRef = React.useRef(null);
12
13
  const spaceKeyRef = React.useRef(false);
13
14
  const [pointerQueue] = React.useState(() => createGridInteractionsPointerQueue());
15
+ const scrollLock = useGridInteractionScrollLock();
14
16
  React.useLayoutEffect(() => controller.update(controllerProps), [controller, controllerProps]);
15
17
  React.useLayoutEffect(() => {
16
18
  pointerQueue.activate();
@@ -32,11 +34,18 @@ export function GridInteractions({ children, interactionPolicy, resizeHandle, te
32
34
  pointerQueue.enqueue(surface, (origin) => handlePointer(resolveGridInteractionPointer(eventSnapshot, origin, modifierSnapshot)));
33
35
  };
34
36
  const enabled = interactionPolicy !== 'passive';
35
- return (<View accessible accessibilityLabel="Grid interaction surface" accessibilityRole="adjustable" ref={surfaceRef} testID={testID} onResponderGrant={(event) => withPointer(event, (pointer) => controller.begin(pointer, resizeHandle))} onResponderMove={(event) => withPointer(event, controller.move)} onResponderRelease={(event) => withPointer(event, controller.end)} onResponderTerminate={() => {
37
+ return (<View accessible accessibilityLabel="Grid interaction surface" accessibilityRole="adjustable" ref={surfaceRef} testID={testID} onResponderGrant={(event) => {
38
+ scrollLock.acquire();
39
+ withPointer(event, (pointer) => controller.begin(pointer, resizeHandle));
40
+ }} onResponderMove={(event) => withPointer(event, controller.move)} onResponderRelease={(event) => {
41
+ scrollLock.release();
42
+ withPointer(event, controller.end);
43
+ }} onResponderTerminate={() => {
44
+ scrollLock.release();
36
45
  setSpaceKey(false);
37
46
  pointerQueue.cancel();
38
47
  controller.cancel();
39
- }} onStartShouldSetResponder={() => enabled}>
48
+ }} onResponderTerminationRequest={() => false} onStartShouldSetResponder={() => enabled}>
40
49
  <GridInteractionsKeyboardProxy enabled={enabled} onKeyDown={(key, keyPointer) => {
41
50
  return controller.keyDown(key, keyPointer);
42
51
  }} onSpaceKeyChange={setSpaceKey}>
@@ -1 +1 @@
1
- {"version":3,"file":"GridInteractions.js","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/GridInteractions.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { View } from 'react-native';\n\nimport type {\n GridInteractionsController,\n GridInteractionsProps,\n} from '../../../../types/grid-interactions';\nimport { createGridInteractionsController } from '../../application/createGridInteractionsController';\nimport { createGridInteractionsPointerQueue } from './createGridInteractionsPointerQueue';\nimport { GridInteractionsKeyboardProxy } from './GridInteractionsKeyboardProxy';\nimport { resolveGridInteractionPointer } from './resolveGridInteractionPointer';\n\n/*** Adapts native responder and keyboard events to the controlled grid interaction boundary. */\nexport function GridInteractions({\n children,\n interactionPolicy,\n resizeHandle,\n testID,\n ...props\n}: GridInteractionsProps) {\n const controllerProps = React.useMemo(\n () => ({ ...props, interactionPolicy }),\n [interactionPolicy, props],\n );\n const [controller] = React.useState<GridInteractionsController>(() =>\n createGridInteractionsController(controllerProps),\n );\n const surfaceRef = React.useRef<View>(null);\n const spaceKeyRef = React.useRef(false);\n const [pointerQueue] = React.useState(() => createGridInteractionsPointerQueue());\n React.useLayoutEffect(() => controller.update(controllerProps), [controller, controllerProps]);\n React.useLayoutEffect(() => {\n pointerQueue.activate();\n return () => {\n spaceKeyRef.current = false;\n pointerQueue.dispose();\n controller.cancel();\n };\n }, [controller, pointerQueue]);\n const setSpaceKey = React.useCallback((spaceKey: boolean) => {\n spaceKeyRef.current = spaceKey;\n }, []);\n const withPointer = (\n event: Parameters<typeof resolveGridInteractionPointer>[0],\n handlePointer: (pointer: ReturnType<typeof resolveGridInteractionPointer>) => void,\n ) => {\n const surface = surfaceRef.current;\n if (!surface) return;\n const eventSnapshot = { nativeEvent: { ...event.nativeEvent } };\n const modifierSnapshot = { spaceKey: spaceKeyRef.current };\n pointerQueue.enqueue(surface, (origin) =>\n handlePointer(resolveGridInteractionPointer(eventSnapshot, origin, modifierSnapshot)),\n );\n };\n const enabled = interactionPolicy !== 'passive';\n\n return (\n <View\n accessible\n accessibilityLabel=\"Grid interaction surface\"\n accessibilityRole=\"adjustable\"\n ref={surfaceRef}\n testID={testID}\n onResponderGrant={(event) =>\n withPointer(event, (pointer) => controller.begin(pointer, resizeHandle))\n }\n onResponderMove={(event) => withPointer(event, controller.move)}\n onResponderRelease={(event) => withPointer(event, controller.end)}\n onResponderTerminate={() => {\n setSpaceKey(false);\n pointerQueue.cancel();\n controller.cancel();\n }}\n onStartShouldSetResponder={() => enabled}\n >\n <GridInteractionsKeyboardProxy\n enabled={enabled}\n onKeyDown={(key, keyPointer) => {\n return controller.keyDown(key, keyPointer);\n }}\n onSpaceKeyChange={setSpaceKey}\n >\n {children}\n </GridInteractionsKeyboardProxy>\n </View>\n );\n}\n"]}
1
+ {"version":3,"file":"GridInteractions.js","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/GridInteractions.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { View } from 'react-native';\n\nimport type {\n GridInteractionsController,\n GridInteractionsProps,\n} from '../../../../types/grid-interactions';\nimport { createGridInteractionsController } from '../../application/createGridInteractionsController';\nimport { createGridInteractionsPointerQueue } from './createGridInteractionsPointerQueue';\nimport { GridInteractionsKeyboardProxy } from './GridInteractionsKeyboardProxy';\nimport { resolveGridInteractionPointer } from './resolveGridInteractionPointer';\nimport { useGridInteractionScrollLock } from './useGridInteractionScrollLock';\n\n/*** Adapts native responder and keyboard events to the controlled grid interaction boundary. */\nexport function GridInteractions({\n children,\n interactionPolicy,\n resizeHandle,\n testID,\n ...props\n}: GridInteractionsProps) {\n const controllerProps = React.useMemo(\n () => ({ ...props, interactionPolicy }),\n [interactionPolicy, props],\n );\n const [controller] = React.useState<GridInteractionsController>(() =>\n createGridInteractionsController(controllerProps),\n );\n const surfaceRef = React.useRef<View>(null);\n const spaceKeyRef = React.useRef(false);\n const [pointerQueue] = React.useState(() => createGridInteractionsPointerQueue());\n const scrollLock = useGridInteractionScrollLock();\n React.useLayoutEffect(() => controller.update(controllerProps), [controller, controllerProps]);\n React.useLayoutEffect(() => {\n pointerQueue.activate();\n return () => {\n spaceKeyRef.current = false;\n pointerQueue.dispose();\n controller.cancel();\n };\n }, [controller, pointerQueue]);\n const setSpaceKey = React.useCallback((spaceKey: boolean) => {\n spaceKeyRef.current = spaceKey;\n }, []);\n const withPointer = (\n event: Parameters<typeof resolveGridInteractionPointer>[0],\n handlePointer: (pointer: ReturnType<typeof resolveGridInteractionPointer>) => void,\n ) => {\n const surface = surfaceRef.current;\n if (!surface) return;\n const eventSnapshot = { nativeEvent: { ...event.nativeEvent } };\n const modifierSnapshot = { spaceKey: spaceKeyRef.current };\n pointerQueue.enqueue(surface, (origin) =>\n handlePointer(resolveGridInteractionPointer(eventSnapshot, origin, modifierSnapshot)),\n );\n };\n const enabled = interactionPolicy !== 'passive';\n\n return (\n <View\n accessible\n accessibilityLabel=\"Grid interaction surface\"\n accessibilityRole=\"adjustable\"\n ref={surfaceRef}\n testID={testID}\n onResponderGrant={(event) => {\n scrollLock.acquire();\n withPointer(event, (pointer) => controller.begin(pointer, resizeHandle));\n }}\n onResponderMove={(event) => withPointer(event, controller.move)}\n onResponderRelease={(event) => {\n scrollLock.release();\n withPointer(event, controller.end);\n }}\n onResponderTerminate={() => {\n scrollLock.release();\n setSpaceKey(false);\n pointerQueue.cancel();\n controller.cancel();\n }}\n onResponderTerminationRequest={() => false}\n onStartShouldSetResponder={() => enabled}\n >\n <GridInteractionsKeyboardProxy\n enabled={enabled}\n onKeyDown={(key, keyPointer) => {\n return controller.keyDown(key, keyPointer);\n }}\n onSpaceKeyChange={setSpaceKey}\n >\n {children}\n </GridInteractionsKeyboardProxy>\n </View>\n );\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export { useGridInteractionScrollLock } from './useGridInteractionScrollLock.native';
2
+ //# sourceMappingURL=useGridInteractionScrollLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGridInteractionScrollLock.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { useGridInteractionScrollLock } from './useGridInteractionScrollLock.native';
2
+ //# sourceMappingURL=useGridInteractionScrollLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGridInteractionScrollLock.js","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC","sourcesContent":["export { useGridInteractionScrollLock } from './useGridInteractionScrollLock.native';\n"]}
@@ -0,0 +1,4 @@
1
+ import type { GridInteractionScrollLock } from '../../../../types/grid-interactions';
2
+ /*** Keeps ancestor ZORA scrolling suspended while one native responder gesture owns the surface. */
3
+ export declare function useGridInteractionScrollLock(): GridInteractionScrollLock;
4
+ //# sourceMappingURL=useGridInteractionScrollLock.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGridInteractionScrollLock.native.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAIrF,oGAAoG;AACpG,wBAAgB,4BAA4B,IAAI,yBAAyB,CASxE"}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { useScrollGestureLock } from '../../../layout/public';
3
+ import { createGridInteractionScrollLock } from '../../application/createGridInteractionScrollLock';
4
+ /*** Keeps ancestor ZORA scrolling suspended while one native responder gesture owns the surface. */
5
+ export function useGridInteractionScrollLock() {
6
+ const scrollLock = useScrollGestureLock();
7
+ const gestureLock = React.useMemo(() => createGridInteractionScrollLock(scrollLock), [scrollLock]);
8
+ React.useEffect(() => gestureLock.release, [gestureLock]);
9
+ return gestureLock;
10
+ }
11
+ //# sourceMappingURL=useGridInteractionScrollLock.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGridInteractionScrollLock.native.js","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,+BAA+B,EAAE,MAAM,mDAAmD,CAAC;AAEpG,oGAAoG;AACpG,MAAM,UAAU,4BAA4B;IAC1C,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;IAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAC/B,GAAG,EAAE,CAAC,+BAA+B,CAAC,UAAU,CAAC,EACjD,CAAC,UAAU,CAAC,CACb,CAAC;IACF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAE1D,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["import React from 'react';\n\nimport type { GridInteractionScrollLock } from '../../../../types/grid-interactions';\nimport { useScrollGestureLock } from '../../../layout/public';\nimport { createGridInteractionScrollLock } from '../../application/createGridInteractionScrollLock';\n\n/*** Keeps ancestor ZORA scrolling suspended while one native responder gesture owns the surface. */\nexport function useGridInteractionScrollLock(): GridInteractionScrollLock {\n const scrollLock = useScrollGestureLock();\n const gestureLock = React.useMemo(\n () => createGridInteractionScrollLock(scrollLock),\n [scrollLock],\n );\n React.useEffect(() => gestureLock.release, [gestureLock]);\n\n return gestureLock;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { GridInteractionScrollLock } from '../../../../types/grid-interactions';
2
+ /*** Leaves browser scrolling to the RNW responder system, which already honors termination requests. */
3
+ export declare function useGridInteractionScrollLock(): GridInteractionScrollLock;
4
+ //# sourceMappingURL=useGridInteractionScrollLock.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGridInteractionScrollLock.web.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAOrF,wGAAwG;AACxG,wBAAgB,4BAA4B,IAAI,yBAAyB,CAExE"}
@@ -0,0 +1,9 @@
1
+ const webScrollLock = {
2
+ acquire: () => undefined,
3
+ release: () => undefined,
4
+ };
5
+ /*** Leaves browser scrolling to the RNW responder system, which already honors termination requests. */
6
+ export function useGridInteractionScrollLock() {
7
+ return webScrollLock;
8
+ }
9
+ //# sourceMappingURL=useGridInteractionScrollLock.web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGridInteractionScrollLock.web.js","sourceRoot":"","sources":["../../../../../src/features/grid-interactions/adapters/inbound/useGridInteractionScrollLock.web.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAA8B;IAC/C,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;IACxB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;CACzB,CAAC;AAEF,wGAAwG;AACxG,MAAM,UAAU,4BAA4B;IAC1C,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { GridInteractionScrollLock } from '../../../../types/grid-interactions';\n\nconst webScrollLock: GridInteractionScrollLock = {\n acquire: () => undefined,\n release: () => undefined,\n};\n\n/*** Leaves browser scrolling to the RNW responder system, which already honors termination requests. */\nexport function useGridInteractionScrollLock(): GridInteractionScrollLock {\n return webScrollLock;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { GridInteractionScrollLock } from '../../../types/grid-interactions';
2
+ import type { ScrollGestureLock } from '../../../types/layout';
3
+ /*** Holds at most one ancestor scroll lock for the active responder gesture of an interaction surface. */
4
+ export declare function createGridInteractionScrollLock(scrollLock: ScrollGestureLock): GridInteractionScrollLock;
5
+ //# sourceMappingURL=createGridInteractionScrollLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createGridInteractionScrollLock.d.ts","sourceRoot":"","sources":["../../../../src/features/grid-interactions/application/createGridInteractionScrollLock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAClF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,0GAA0G;AAC1G,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,iBAAiB,GAC5B,yBAAyB,CAW3B"}
@@ -0,0 +1,14 @@
1
+ /*** Holds at most one ancestor scroll lock for the active responder gesture of an interaction surface. */
2
+ export function createGridInteractionScrollLock(scrollLock) {
3
+ let releaseScrollLock;
4
+ return {
5
+ acquire: () => {
6
+ releaseScrollLock ??= scrollLock.acquire();
7
+ },
8
+ release: () => {
9
+ releaseScrollLock?.();
10
+ releaseScrollLock = undefined;
11
+ },
12
+ };
13
+ }
14
+ //# sourceMappingURL=createGridInteractionScrollLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createGridInteractionScrollLock.js","sourceRoot":"","sources":["../../../../src/features/grid-interactions/application/createGridInteractionScrollLock.ts"],"names":[],"mappings":"AAGA,0GAA0G;AAC1G,MAAM,UAAU,+BAA+B,CAC7C,UAA6B;IAE7B,IAAI,iBAA2C,CAAC;IAChD,OAAO;QACL,OAAO,EAAE,GAAG,EAAE;YACZ,iBAAiB,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QAC7C,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACZ,iBAAiB,EAAE,EAAE,CAAC;YACtB,iBAAiB,GAAG,SAAS,CAAC;QAChC,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { GridInteractionScrollLock } from '../../../types/grid-interactions';\nimport type { ScrollGestureLock } from '../../../types/layout';\n\n/*** Holds at most one ancestor scroll lock for the active responder gesture of an interaction surface. */\nexport function createGridInteractionScrollLock(\n scrollLock: ScrollGestureLock,\n): GridInteractionScrollLock {\n let releaseScrollLock: (() => void) | undefined;\n return {\n acquire: () => {\n releaseScrollLock ??= scrollLock.acquire();\n },\n release: () => {\n releaseScrollLock?.();\n releaseScrollLock = undefined;\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"GridView.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-view/adapters/inbound/GridView.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAiBjE,8GAA8G;AAC9G,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,YAAY,EACZ,aAAa,EACb,KAAK,EACL,MAAM,EACN,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,IAAQ,EACR,cAAoB,EACpB,aAAa,EACb,mBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,MAAM,GACP,EAAE,aAAa,qBAwWf"}
1
+ {"version":3,"file":"GridView.d.ts","sourceRoot":"","sources":["../../../../../src/features/grid-view/adapters/inbound/GridView.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAkC,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAiBjG,8GAA8G;AAC9G,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,YAAY,EACZ,aAAa,EACb,KAAK,EACL,MAAM,EACN,QAAQ,EAAE,kBAAkB,EAC5B,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,IAAQ,EACR,cAAoB,EACpB,aAAa,EACb,mBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,MAAM,GACP,EAAE,aAAa,qBAiYf"}
@@ -1,13 +1,15 @@
1
1
  import { constrainViewport, getVisibleGridItems, panViewport, revealWorldRect, worldToViewport, zoomViewportAt, } from '@ankhorage/grid-view';
2
2
  import React from 'react';
3
3
  import { Pressable as NativePressable, ScrollView as NativeScrollView, Text as NativeText, View as NativeView, } from 'react-native';
4
+ import { createGridScrollSync } from '../../application/createGridScrollSync';
4
5
  /*** Renders a controlled or uncontrolled, virtualized 2D world through the canonical grid viewport engine. */
5
6
  export function GridView({ items, contentWidth, contentHeight, width, height, viewport: controlledViewport, defaultViewport, viewportConstraints, zoomLimits, zoom = 1, overscanPixels = 160, focusedItemId, revealPaddingPixels = 8, interactionPolicy, onViewportChange, onVisibleItemIdsChange, renderItem, testID, }) {
6
7
  const [uncontrolledViewport, setUncontrolledViewport] = React.useState(() => createInitialViewport(width, height, zoom, defaultViewport));
7
8
  const horizontalScrollRef = React.useRef(null);
8
9
  const verticalScrollRef = React.useRef(null);
9
10
  const gridRef = React.useRef(null);
10
- const scrollPositionRef = React.useRef({ x: 0, y: 0 });
11
+ const panRef = React.useRef(() => undefined);
12
+ const scrollSyncRef = React.useRef(undefined);
11
13
  const pinchGestureRef = React.useRef(undefined);
12
14
  const pinchMeasurementRef = React.useRef(0);
13
15
  const pinchSessionRef = React.useRef(0);
@@ -50,6 +52,32 @@ export function GridView({ items, contentWidth, contentHeight, width, height, vi
50
52
  React.useEffect(() => {
51
53
  publishRef.current = publish;
52
54
  }, [publish]);
55
+ React.useEffect(() => {
56
+ panRef.current = pan;
57
+ });
58
+ // Declared before the viewport-sync effect so the arbiter exists when that effect runs.
59
+ React.useEffect(() => {
60
+ const scrollSync = createGridScrollSync({
61
+ onProgrammaticScroll: (axis, displacement) => panRef.current(axis === 'x' ? { x: -displacement, y: 0 } : { x: 0, y: -displacement }),
62
+ onUserScroll: (axis, displacement) => panRef.current(axis === 'x' ? { x: -displacement, y: 0 } : { x: 0, y: -displacement }),
63
+ scrollTo: (axis, offset, animated) => {
64
+ if (axis === 'x')
65
+ horizontalScrollRef.current?.scrollTo({ animated, x: offset });
66
+ else
67
+ verticalScrollRef.current?.scrollTo({ animated, y: offset });
68
+ },
69
+ });
70
+ scrollSyncRef.current = scrollSync;
71
+ return () => {
72
+ scrollSync.dispose();
73
+ scrollSyncRef.current = undefined;
74
+ };
75
+ }, []);
76
+ /** Routes native scroll events to the arbiter unless a pinch owns the gesture. */
77
+ const handleNativeScroll = (axis, offset) => {
78
+ if (!pinchGestureRef.current)
79
+ scrollSyncRef.current?.scrolled(axis, offset);
80
+ };
53
81
  const refreshViewportOrigin = React.useCallback(() => {
54
82
  gridRef.current?.measureInWindow((x, y) => {
55
83
  viewportOriginRef.current = { x, y };
@@ -90,13 +118,11 @@ export function GridView({ items, contentWidth, contentHeight, width, height, vi
90
118
  x: position.horizontal.position,
91
119
  y: position.vertical.position,
92
120
  };
93
- if (areScrollPositionsEqual(scrollPositionRef.current, nextPosition))
121
+ if (scrollSyncRef.current?.isCurrent(nextPosition))
94
122
  return;
95
- scrollPositionRef.current = nextPosition;
96
123
  const animated = focusRevealViewportRef.current !== undefined &&
97
124
  areViewportsEqual(viewport, focusRevealViewportRef.current);
98
- horizontalScrollRef.current?.scrollTo({ animated, x: nextPosition.x });
99
- verticalScrollRef.current?.scrollTo({ animated, y: nextPosition.y });
125
+ scrollSyncRef.current?.request(nextPosition, animated);
100
126
  if (animated)
101
127
  focusRevealViewportRef.current = undefined;
102
128
  }, [constraints, viewport]);
@@ -151,9 +177,7 @@ export function GridView({ items, contentWidth, contentHeight, width, height, vi
151
177
  x: nextMapping.horizontal.position,
152
178
  y: nextMapping.vertical.position,
153
179
  };
154
- scrollPositionRef.current = nextPosition;
155
- horizontalScrollRef.current?.scrollTo({ animated: false, x: nextPosition.x });
156
- verticalScrollRef.current?.scrollTo({ animated: false, y: nextPosition.y });
180
+ scrollSyncRef.current?.request(nextPosition, false);
157
181
  };
158
182
  return (<NativeView ref={gridRef} accessibilityLabel="Interactive grid viewport" onLayout={refreshViewportOrigin} onTouchEnd={() => {
159
183
  const wasPinching = pinchGestureRef.current !== undefined;
@@ -190,24 +214,8 @@ export function GridView({ items, contentWidth, contentHeight, width, height, vi
190
214
  setIsPinching(pinch !== undefined);
191
215
  });
192
216
  }} style={{ height, overflow: 'hidden', width }} testID={testID}>
193
- <NativeScrollView ref={horizontalScrollRef} testID={testID ? `${testID}-horizontal-scroll` : undefined} horizontal scrollEnabled={interactive && !isPinching} scrollEventThrottle={16} showsHorizontalScrollIndicator style={{ height, width }} onScroll={(event) => {
194
- if (pinchGestureRef.current)
195
- return;
196
- const { x } = event.nativeEvent.contentOffset;
197
- const displacement = x - scrollPositionRef.current.x;
198
- scrollPositionRef.current = { ...scrollPositionRef.current, x };
199
- if (displacement !== 0)
200
- pan({ x: -displacement, y: 0 });
201
- }}>
202
- <NativeScrollView ref={verticalScrollRef} testID={testID ? `${testID}-vertical-scroll` : undefined} scrollEnabled={interactive && !isPinching} scrollEventThrottle={16} showsVerticalScrollIndicator style={{ height, width: scrollMapping.horizontal.contentSize }} onScroll={(event) => {
203
- if (pinchGestureRef.current)
204
- return;
205
- const { y } = event.nativeEvent.contentOffset;
206
- const displacement = y - scrollPositionRef.current.y;
207
- scrollPositionRef.current = { ...scrollPositionRef.current, y };
208
- if (displacement !== 0)
209
- pan({ x: 0, y: -displacement });
210
- }}>
217
+ <NativeScrollView ref={horizontalScrollRef} testID={testID ? `${testID}-horizontal-scroll` : undefined} horizontal scrollEnabled={interactive && !isPinching} scrollEventThrottle={16} showsHorizontalScrollIndicator style={{ height, width }} onMomentumScrollEnd={(event) => scrollSyncRef.current?.scrollEnded('x', event.nativeEvent.contentOffset.x)} onScroll={(event) => handleNativeScroll('x', event.nativeEvent.contentOffset.x)} onScrollBeginDrag={(event) => scrollSyncRef.current?.dragBegan('x', event.nativeEvent.contentOffset.x)}>
218
+ <NativeScrollView ref={verticalScrollRef} testID={testID ? `${testID}-vertical-scroll` : undefined} scrollEnabled={interactive && !isPinching} scrollEventThrottle={16} showsVerticalScrollIndicator style={{ height, width: scrollMapping.horizontal.contentSize }} onMomentumScrollEnd={(event) => scrollSyncRef.current?.scrollEnded('y', event.nativeEvent.contentOffset.y)} onScroll={(event) => handleNativeScroll('y', event.nativeEvent.contentOffset.y)} onScrollBeginDrag={(event) => scrollSyncRef.current?.dragBegan('y', event.nativeEvent.contentOffset.y)}>
211
219
  <NativeView style={{
212
220
  height: scrollMapping.vertical.contentSize,
213
221
  width: scrollMapping.horizontal.contentSize,
@@ -306,10 +314,6 @@ function areViewportsEqual(left, right) {
306
314
  left.pixelsPerUnitX === right.pixelsPerUnitX &&
307
315
  left.pixelsPerUnitY === right.pixelsPerUnitY);
308
316
  }
309
- /*** Avoids requesting native scrolling again when the physical position is already current. */
310
- function areScrollPositionsEqual(left, right) {
311
- return left.x === right.x && left.y === right.y;
312
- }
313
317
  /*** Skips a rejected controlled focus proposal until its focus or incoming viewport changes. */
314
318
  function isRepeatedControlledFocusRevealProposal({ controlled, focusedItemId, previous, sourceViewport, viewport, }) {
315
319
  return (controlled &&
@@ -1 +1 @@
1
- {"version":3,"file":"GridView.js","sourceRoot":"","sources":["../../../../../src/features/grid-view/adapters/inbound/GridView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n constrainViewport,\n getVisibleGridItems,\n type GridPoint,\n type GridViewport,\n type GridViewportConstraints,\n panViewport,\n revealWorldRect,\n worldToViewport,\n zoomViewportAt,\n} from '@ankhorage/grid-view';\nimport React from 'react';\nimport {\n Pressable as NativePressable,\n ScrollView as NativeScrollView,\n Text as NativeText,\n View as NativeView,\n} from 'react-native';\n\nimport type { GridViewProps } from '../../../../types/grid-view';\n\ntype ScrollPosition = Readonly<{ x: number; y: number }>;\ntype PinchGesture = Readonly<{ distance: number; focalPoint: GridPoint }>;\ntype ScrollAxisMapping = Readonly<{ contentSize: number; origin: number; position: number }>;\ntype ScrollMapping = Readonly<{\n horizontal: ScrollAxisMapping;\n vertical: ScrollAxisMapping;\n}>;\ntype ViewportOrigin = Readonly<{ x: number; y: number }>;\ntype FocusRevealProposal = Readonly<{\n focusedItemId: string;\n sourceViewport: GridViewport;\n viewport: GridViewport;\n}>;\ntype PinchTouch = Readonly<{ pageX: number; pageY: number }>;\n\n/*** Renders a controlled or uncontrolled, virtualized 2D world through the canonical grid viewport engine. */\nexport function GridView({\n items,\n contentWidth,\n contentHeight,\n width,\n height,\n viewport: controlledViewport,\n defaultViewport,\n viewportConstraints,\n zoomLimits,\n zoom = 1,\n overscanPixels = 160,\n focusedItemId,\n revealPaddingPixels = 8,\n interactionPolicy,\n onViewportChange,\n onVisibleItemIdsChange,\n renderItem,\n testID,\n}: GridViewProps) {\n const [uncontrolledViewport, setUncontrolledViewport] = React.useState(() =>\n createInitialViewport(width, height, zoom, defaultViewport),\n );\n const horizontalScrollRef = React.useRef<NativeScrollView>(null);\n const verticalScrollRef = React.useRef<NativeScrollView>(null);\n const gridRef = React.useRef<React.ComponentRef<typeof NativeView>>(null);\n const scrollPositionRef = React.useRef<ScrollPosition>({ x: 0, y: 0 });\n const pinchGestureRef = React.useRef<PinchGesture | undefined>(undefined);\n const pinchMeasurementRef = React.useRef(0);\n const pinchSessionRef = React.useRef(0);\n const viewportOriginRef = React.useRef<ViewportOrigin>({ x: 0, y: 0 });\n const focusRevealProposalRef = React.useRef<FocusRevealProposal | undefined>(undefined);\n const focusRevealViewportRef = React.useRef<GridViewport | undefined>(undefined);\n const [isPinching, setIsPinching] = React.useState(false);\n const constraints = React.useMemo(\n () => viewportConstraints ?? createContentConstraints(contentWidth, contentHeight),\n [contentHeight, contentWidth, viewportConstraints],\n );\n const sourceViewport = controlledViewport ?? uncontrolledViewport;\n const viewport = React.useMemo(\n () => constrainViewport({ ...sourceViewport, height, width }, constraints),\n [constraints, height, sourceViewport, width],\n );\n const viewportRef = React.useRef(viewport);\n const visibleItems = React.useMemo(\n () => getVisibleGridItems(items, viewport, overscanPixels),\n [items, overscanPixels, viewport],\n );\n const viewportVisibleIds = React.useMemo(\n () => getVisibleGridItems(visibleItems, viewport).map((item) => item.id),\n [viewport, visibleItems],\n );\n const focusedItem = items.find((item) => item.id === focusedItemId);\n const focusedItemHeight = focusedItem?.height;\n const focusedItemIdForReveal = focusedItem?.id;\n const focusedItemWidth = focusedItem?.width;\n const focusedItemX = focusedItem?.x;\n const focusedItemY = focusedItem?.y;\n const previousVisibleIdsRef = React.useRef<readonly string[]>([]);\n const uncontrolled = controlledViewport === undefined;\n const interactive = interactionPolicy !== 'passive';\n\n const publish = React.useCallback(\n (nextViewport: GridViewport) => {\n if (areViewportsEqual(viewportRef.current, nextViewport)) return;\n viewportRef.current = nextViewport;\n if (uncontrolled) setUncontrolledViewport(nextViewport);\n onViewportChange?.(nextViewport);\n },\n [onViewportChange, uncontrolled],\n );\n const publishRef = React.useRef(publish);\n const pan = (displacement: GridPoint) =>\n publish(panViewport(viewportRef.current, displacement, constraints));\n const zoomAt = (focalPoint: GridPoint, factor: number) =>\n publish(\n zoomViewportAt(\n viewportRef.current,\n focalPoint,\n {\n pixelsPerUnitX: viewportRef.current.pixelsPerUnitX * factor,\n pixelsPerUnitY: viewportRef.current.pixelsPerUnitY * factor,\n },\n zoomLimits,\n constraints,\n ),\n );\n\n React.useEffect(() => {\n viewportRef.current = viewport;\n }, [viewport]);\n\n React.useEffect(() => {\n publishRef.current = publish;\n }, [publish]);\n\n const refreshViewportOrigin = React.useCallback(() => {\n gridRef.current?.measureInWindow((x, y) => {\n viewportOriginRef.current = { x, y };\n });\n }, []);\n\n const measurePinchGesture = React.useCallback(\n (\n touches: readonly PinchTouch[],\n session: number,\n onMeasured: (pinch: PinchGesture | undefined) => void,\n ) => {\n const measurement = pinchMeasurementRef.current + 1;\n pinchMeasurementRef.current = measurement;\n gridRef.current?.measureInWindow((x, y) => {\n if (measurement !== pinchMeasurementRef.current || session !== pinchSessionRef.current) {\n return;\n }\n viewportOriginRef.current = { x, y };\n onMeasured(getPinchGesture(touches, width, height, { x, y }));\n });\n },\n [height, width],\n );\n\n React.useLayoutEffect(() => {\n refreshViewportOrigin();\n }, [height, refreshViewportOrigin, width]);\n\n React.useEffect(\n () => () => {\n pinchMeasurementRef.current += 1;\n pinchSessionRef.current += 1;\n },\n [],\n );\n\n React.useEffect(() => {\n if (!onVisibleItemIdsChange) return;\n const previous = previousVisibleIdsRef.current;\n if (\n previous.length === viewportVisibleIds.length &&\n previous.every((id, index) => id === viewportVisibleIds.at(index))\n ) {\n return;\n }\n previousVisibleIdsRef.current = viewportVisibleIds;\n onVisibleItemIdsChange(viewportVisibleIds);\n }, [onVisibleItemIdsChange, viewportVisibleIds]);\n\n React.useEffect(() => {\n const position = createScrollMapping(viewport, constraints);\n const nextPosition = {\n x: position.horizontal.position,\n y: position.vertical.position,\n };\n if (areScrollPositionsEqual(scrollPositionRef.current, nextPosition)) return;\n scrollPositionRef.current = nextPosition;\n const animated =\n focusRevealViewportRef.current !== undefined &&\n areViewportsEqual(viewport, focusRevealViewportRef.current);\n horizontalScrollRef.current?.scrollTo({ animated, x: nextPosition.x });\n verticalScrollRef.current?.scrollTo({ animated, y: nextPosition.y });\n if (animated) focusRevealViewportRef.current = undefined;\n }, [constraints, viewport]);\n\n React.useEffect(() => {\n if (\n focusedItemHeight === undefined ||\n focusedItemIdForReveal === undefined ||\n focusedItemWidth === undefined ||\n focusedItemX === undefined ||\n focusedItemY === undefined\n ) {\n focusRevealProposalRef.current = undefined;\n return;\n }\n const sourceViewport = viewportRef.current;\n const revealed = revealWorldRect(\n sourceViewport,\n {\n height: focusedItemHeight,\n width: focusedItemWidth,\n x: focusedItemX,\n y: focusedItemY,\n },\n revealPaddingPixels,\n constraints,\n );\n if (\n isRepeatedControlledFocusRevealProposal({\n controlled: !uncontrolled,\n focusedItemId: focusedItemIdForReveal,\n previous: focusRevealProposalRef.current,\n sourceViewport,\n viewport: revealed,\n })\n ) {\n return;\n }\n focusRevealProposalRef.current = {\n focusedItemId: focusedItemIdForReveal,\n sourceViewport,\n viewport: revealed,\n };\n focusRevealViewportRef.current = areViewportsEqual(sourceViewport, revealed)\n ? undefined\n : revealed;\n publishRef.current(revealed);\n }, [\n constraints,\n focusedItemHeight,\n focusedItemIdForReveal,\n focusedItemWidth,\n focusedItemX,\n focusedItemY,\n revealPaddingPixels,\n uncontrolled,\n ]);\n\n const scrollMapping = createScrollMapping(viewport, constraints);\n\n const syncScrollPosition = () => {\n const nextMapping = createScrollMapping(viewportRef.current, constraints);\n const nextPosition = {\n x: nextMapping.horizontal.position,\n y: nextMapping.vertical.position,\n };\n scrollPositionRef.current = nextPosition;\n horizontalScrollRef.current?.scrollTo({ animated: false, x: nextPosition.x });\n verticalScrollRef.current?.scrollTo({ animated: false, y: nextPosition.y });\n };\n\n return (\n <NativeView\n ref={gridRef}\n accessibilityLabel=\"Interactive grid viewport\"\n onLayout={refreshViewportOrigin}\n onTouchEnd={() => {\n const wasPinching = pinchGestureRef.current !== undefined;\n pinchMeasurementRef.current += 1;\n pinchSessionRef.current += 1;\n pinchGestureRef.current = undefined;\n setIsPinching(false);\n if (wasPinching) syncScrollPosition();\n }}\n onTouchCancel={() => {\n const wasPinching = pinchGestureRef.current !== undefined;\n pinchMeasurementRef.current += 1;\n pinchSessionRef.current += 1;\n pinchGestureRef.current = undefined;\n setIsPinching(false);\n if (wasPinching) syncScrollPosition();\n }}\n onTouchMove={(event) => {\n if (!interactive) return;\n measurePinchGesture([...event.nativeEvent.touches], pinchSessionRef.current, (pinch) => {\n const previous = pinchGestureRef.current;\n pinchGestureRef.current = pinch;\n setIsPinching(pinch !== undefined);\n if (!pinch || !previous) return;\n zoomAt(pinch.focalPoint, pinch.distance / previous.distance);\n });\n }}\n onTouchStart={(event) => {\n const session = pinchSessionRef.current + 1;\n pinchSessionRef.current = session;\n measurePinchGesture([...event.nativeEvent.touches], session, (pinch) => {\n pinchGestureRef.current = pinch;\n setIsPinching(pinch !== undefined);\n });\n }}\n style={{ height, overflow: 'hidden', width }}\n testID={testID}\n >\n <NativeScrollView\n ref={horizontalScrollRef}\n testID={testID ? `${testID}-horizontal-scroll` : undefined}\n horizontal\n scrollEnabled={interactive && !isPinching}\n scrollEventThrottle={16}\n showsHorizontalScrollIndicator\n style={{ height, width }}\n onScroll={(event) => {\n if (pinchGestureRef.current) return;\n const { x } = event.nativeEvent.contentOffset;\n const displacement = x - scrollPositionRef.current.x;\n scrollPositionRef.current = { ...scrollPositionRef.current, x };\n if (displacement !== 0) pan({ x: -displacement, y: 0 });\n }}\n >\n <NativeScrollView\n ref={verticalScrollRef}\n testID={testID ? `${testID}-vertical-scroll` : undefined}\n scrollEnabled={interactive && !isPinching}\n scrollEventThrottle={16}\n showsVerticalScrollIndicator\n style={{ height, width: scrollMapping.horizontal.contentSize }}\n onScroll={(event) => {\n if (pinchGestureRef.current) return;\n const { y } = event.nativeEvent.contentOffset;\n const displacement = y - scrollPositionRef.current.y;\n scrollPositionRef.current = { ...scrollPositionRef.current, y };\n if (displacement !== 0) pan({ x: 0, y: -displacement });\n }}\n >\n <NativeView\n style={{\n height: scrollMapping.vertical.contentSize,\n width: scrollMapping.horizontal.contentSize,\n }}\n >\n {visibleItems.map((item) => {\n const position = worldToViewport(\n { x: item.x, y: item.y },\n { ...viewport, offsetX: 0, offsetY: 0 },\n );\n return (\n <NativeView\n key={item.id}\n style={{\n height: item.height * viewport.pixelsPerUnitY,\n left: position.x + scrollMapping.horizontal.origin,\n position: 'absolute',\n top: position.y + scrollMapping.vertical.origin,\n width: item.width * viewport.pixelsPerUnitX,\n }}\n >\n {renderItem(item)}\n </NativeView>\n );\n })}\n </NativeView>\n </NativeScrollView>\n </NativeScrollView>\n {interactive ? (\n <NativeView accessibilityLabel=\"Viewport controls\" style={controlsStyle}>\n <NativePressable\n accessibilityLabel=\"Pan left\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: 48, y: 0 })}\n >\n <NativeText>←</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Pan right\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: -48, y: 0 })}\n >\n <NativeText>→</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Pan up\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: 0, y: 48 })}\n >\n <NativeText>↑</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Pan down\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: 0, y: -48 })}\n >\n <NativeText>↓</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Zoom in\"\n accessibilityRole=\"button\"\n onPress={() => zoomAt({ x: width / 2, y: height / 2 }, 1.2)}\n >\n <NativeText>+</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Zoom out\"\n accessibilityRole=\"button\"\n onPress={() => zoomAt({ x: width / 2, y: height / 2 }, 1 / 1.2)}\n >\n <NativeText>−</NativeText>\n </NativePressable>\n </NativeView>\n ) : null}\n </NativeView>\n );\n}\n\nconst controlsStyle = { bottom: 8, gap: 4, position: 'absolute' as const, right: 8 };\n\n/*** Builds the initial world position and independent scales for uncontrolled rendering. */\nfunction createInitialViewport(\n width: number,\n height: number,\n zoom: number,\n viewport: GridViewProps['defaultViewport'],\n): GridViewport {\n return {\n height,\n offsetX: viewport?.offsetX ?? 0,\n offsetY: viewport?.offsetY ?? 0,\n pixelsPerUnitX: viewport?.pixelsPerUnitX ?? zoom,\n pixelsPerUnitY: viewport?.pixelsPerUnitY ?? zoom,\n width,\n };\n}\n\n/*** Uses the rendered content extent as the default finite world boundary. */\nfunction createContentConstraints(\n contentWidth: number,\n contentHeight: number,\n): GridViewportConstraints {\n return { world: { height: contentHeight, width: contentWidth, x: 0, y: 0 } };\n}\n\n/*** Maps engine-constrained world offsets to nonnegative native scroll coordinates. */\nfunction createScrollMapping(\n viewport: GridViewport,\n constraints: GridViewportConstraints,\n): ScrollMapping {\n const horizontalMinimum = constrainViewport(\n { ...viewport, offsetX: -Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetX;\n const horizontalMaximum = constrainViewport(\n { ...viewport, offsetX: Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetX;\n const verticalMinimum = constrainViewport(\n { ...viewport, offsetY: -Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetY;\n const verticalMaximum = constrainViewport(\n { ...viewport, offsetY: Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetY;\n return {\n horizontal: createScrollAxisMapping({\n maximum: horizontalMaximum,\n minimum: horizontalMinimum,\n offset: viewport.offsetX,\n scale: viewport.pixelsPerUnitX,\n viewportSize: viewport.width,\n }),\n vertical: createScrollAxisMapping({\n maximum: verticalMaximum,\n minimum: verticalMinimum,\n offset: viewport.offsetY,\n scale: viewport.pixelsPerUnitY,\n viewportSize: viewport.height,\n }),\n };\n}\n\ntype ScrollAxisMappingInput = Readonly<{\n maximum: number;\n minimum: number;\n offset: number;\n scale: number;\n viewportSize: number;\n}>;\n\n/*** Derives a physical scroll axis from the published engine constraint result. */\nfunction createScrollAxisMapping({\n maximum,\n minimum,\n offset,\n scale,\n viewportSize,\n}: ScrollAxisMappingInput): ScrollAxisMapping {\n const range = (maximum - minimum) * scale;\n return {\n contentSize: viewportSize + range,\n origin: -minimum * scale,\n position: (offset - minimum) * scale,\n };\n}\n\n/*** Compares canonical viewport fields without treating equal proposals as state changes. */\nfunction areViewportsEqual(left: GridViewport, right: GridViewport): boolean {\n return (\n left.width === right.width &&\n left.height === right.height &&\n left.offsetX === right.offsetX &&\n left.offsetY === right.offsetY &&\n left.pixelsPerUnitX === right.pixelsPerUnitX &&\n left.pixelsPerUnitY === right.pixelsPerUnitY\n );\n}\n\n/*** Avoids requesting native scrolling again when the physical position is already current. */\nfunction areScrollPositionsEqual(left: ScrollPosition, right: ScrollPosition): boolean {\n return left.x === right.x && left.y === right.y;\n}\n\n/*** Skips a rejected controlled focus proposal until its focus or incoming viewport changes. */\nfunction isRepeatedControlledFocusRevealProposal({\n controlled,\n focusedItemId,\n previous,\n sourceViewport,\n viewport,\n}: Readonly<{\n controlled: boolean;\n focusedItemId: string | undefined;\n previous: FocusRevealProposal | undefined;\n sourceViewport: GridViewport;\n viewport: GridViewport;\n}>): boolean {\n return (\n controlled &&\n focusedItemId !== undefined &&\n previous?.focusedItemId === focusedItemId &&\n areViewportsEqual(previous.sourceViewport, sourceViewport) &&\n areViewportsEqual(previous.viewport, viewport)\n );\n}\n\n/*** Extracts a stable two-finger focal point in the measured outer viewport coordinate space. */\nfunction getPinchGesture(\n touches: readonly Readonly<{\n pageX: number;\n pageY: number;\n }>[],\n width: number,\n height: number,\n viewportOrigin: ViewportOrigin,\n): PinchGesture | undefined {\n const [first, second] = touches;\n if (!first || !second) return undefined;\n const deltaX = second.pageX - first.pageX;\n const deltaY = second.pageY - first.pageY;\n const distance = Math.hypot(deltaX, deltaY);\n if (!Number.isFinite(distance) || distance === 0) return undefined;\n return {\n distance,\n focalPoint: {\n x: Math.min(width, Math.max(0, (first.pageX + second.pageX) / 2 - viewportOrigin.x)),\n y: Math.min(height, Math.max(0, (first.pageY + second.pageY) / 2 - viewportOrigin.y)),\n },\n };\n}\n"]}
1
+ {"version":3,"file":"GridView.js","sourceRoot":"","sources":["../../../../../src/features/grid-view/adapters/inbound/GridView.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n constrainViewport,\n getVisibleGridItems,\n type GridPoint,\n type GridViewport,\n type GridViewportConstraints,\n panViewport,\n revealWorldRect,\n worldToViewport,\n zoomViewportAt,\n} from '@ankhorage/grid-view';\nimport React from 'react';\nimport {\n Pressable as NativePressable,\n ScrollView as NativeScrollView,\n Text as NativeText,\n View as NativeView,\n} from 'react-native';\n\nimport type { GridScrollAxis, GridScrollSync, GridViewProps } from '../../../../types/grid-view';\nimport { createGridScrollSync } from '../../application/createGridScrollSync';\n\ntype PinchGesture = Readonly<{ distance: number; focalPoint: GridPoint }>;\ntype ScrollAxisMapping = Readonly<{ contentSize: number; origin: number; position: number }>;\ntype ScrollMapping = Readonly<{\n horizontal: ScrollAxisMapping;\n vertical: ScrollAxisMapping;\n}>;\ntype ViewportOrigin = Readonly<{ x: number; y: number }>;\ntype FocusRevealProposal = Readonly<{\n focusedItemId: string;\n sourceViewport: GridViewport;\n viewport: GridViewport;\n}>;\ntype PinchTouch = Readonly<{ pageX: number; pageY: number }>;\n\n/*** Renders a controlled or uncontrolled, virtualized 2D world through the canonical grid viewport engine. */\nexport function GridView({\n items,\n contentWidth,\n contentHeight,\n width,\n height,\n viewport: controlledViewport,\n defaultViewport,\n viewportConstraints,\n zoomLimits,\n zoom = 1,\n overscanPixels = 160,\n focusedItemId,\n revealPaddingPixels = 8,\n interactionPolicy,\n onViewportChange,\n onVisibleItemIdsChange,\n renderItem,\n testID,\n}: GridViewProps) {\n const [uncontrolledViewport, setUncontrolledViewport] = React.useState(() =>\n createInitialViewport(width, height, zoom, defaultViewport),\n );\n const horizontalScrollRef = React.useRef<NativeScrollView>(null);\n const verticalScrollRef = React.useRef<NativeScrollView>(null);\n const gridRef = React.useRef<React.ComponentRef<typeof NativeView>>(null);\n const panRef = React.useRef<(displacement: GridPoint) => void>(() => undefined);\n const scrollSyncRef = React.useRef<GridScrollSync | undefined>(undefined);\n const pinchGestureRef = React.useRef<PinchGesture | undefined>(undefined);\n const pinchMeasurementRef = React.useRef(0);\n const pinchSessionRef = React.useRef(0);\n const viewportOriginRef = React.useRef<ViewportOrigin>({ x: 0, y: 0 });\n const focusRevealProposalRef = React.useRef<FocusRevealProposal | undefined>(undefined);\n const focusRevealViewportRef = React.useRef<GridViewport | undefined>(undefined);\n const [isPinching, setIsPinching] = React.useState(false);\n const constraints = React.useMemo(\n () => viewportConstraints ?? createContentConstraints(contentWidth, contentHeight),\n [contentHeight, contentWidth, viewportConstraints],\n );\n const sourceViewport = controlledViewport ?? uncontrolledViewport;\n const viewport = React.useMemo(\n () => constrainViewport({ ...sourceViewport, height, width }, constraints),\n [constraints, height, sourceViewport, width],\n );\n const viewportRef = React.useRef(viewport);\n const visibleItems = React.useMemo(\n () => getVisibleGridItems(items, viewport, overscanPixels),\n [items, overscanPixels, viewport],\n );\n const viewportVisibleIds = React.useMemo(\n () => getVisibleGridItems(visibleItems, viewport).map((item) => item.id),\n [viewport, visibleItems],\n );\n const focusedItem = items.find((item) => item.id === focusedItemId);\n const focusedItemHeight = focusedItem?.height;\n const focusedItemIdForReveal = focusedItem?.id;\n const focusedItemWidth = focusedItem?.width;\n const focusedItemX = focusedItem?.x;\n const focusedItemY = focusedItem?.y;\n const previousVisibleIdsRef = React.useRef<readonly string[]>([]);\n const uncontrolled = controlledViewport === undefined;\n const interactive = interactionPolicy !== 'passive';\n\n const publish = React.useCallback(\n (nextViewport: GridViewport) => {\n if (areViewportsEqual(viewportRef.current, nextViewport)) return;\n viewportRef.current = nextViewport;\n if (uncontrolled) setUncontrolledViewport(nextViewport);\n onViewportChange?.(nextViewport);\n },\n [onViewportChange, uncontrolled],\n );\n const publishRef = React.useRef(publish);\n const pan = (displacement: GridPoint) =>\n publish(panViewport(viewportRef.current, displacement, constraints));\n const zoomAt = (focalPoint: GridPoint, factor: number) =>\n publish(\n zoomViewportAt(\n viewportRef.current,\n focalPoint,\n {\n pixelsPerUnitX: viewportRef.current.pixelsPerUnitX * factor,\n pixelsPerUnitY: viewportRef.current.pixelsPerUnitY * factor,\n },\n zoomLimits,\n constraints,\n ),\n );\n\n React.useEffect(() => {\n viewportRef.current = viewport;\n }, [viewport]);\n\n React.useEffect(() => {\n publishRef.current = publish;\n }, [publish]);\n\n React.useEffect(() => {\n panRef.current = pan;\n });\n\n // Declared before the viewport-sync effect so the arbiter exists when that effect runs.\n React.useEffect(() => {\n const scrollSync = createGridScrollSync({\n onProgrammaticScroll: (axis, displacement) =>\n panRef.current(axis === 'x' ? { x: -displacement, y: 0 } : { x: 0, y: -displacement }),\n onUserScroll: (axis, displacement) =>\n panRef.current(axis === 'x' ? { x: -displacement, y: 0 } : { x: 0, y: -displacement }),\n scrollTo: (axis, offset, animated) => {\n if (axis === 'x') horizontalScrollRef.current?.scrollTo({ animated, x: offset });\n else verticalScrollRef.current?.scrollTo({ animated, y: offset });\n },\n });\n scrollSyncRef.current = scrollSync;\n return () => {\n scrollSync.dispose();\n scrollSyncRef.current = undefined;\n };\n }, []);\n\n /** Routes native scroll events to the arbiter unless a pinch owns the gesture. */\n const handleNativeScroll = (axis: GridScrollAxis, offset: number) => {\n if (!pinchGestureRef.current) scrollSyncRef.current?.scrolled(axis, offset);\n };\n\n const refreshViewportOrigin = React.useCallback(() => {\n gridRef.current?.measureInWindow((x, y) => {\n viewportOriginRef.current = { x, y };\n });\n }, []);\n\n const measurePinchGesture = React.useCallback(\n (\n touches: readonly PinchTouch[],\n session: number,\n onMeasured: (pinch: PinchGesture | undefined) => void,\n ) => {\n const measurement = pinchMeasurementRef.current + 1;\n pinchMeasurementRef.current = measurement;\n gridRef.current?.measureInWindow((x, y) => {\n if (measurement !== pinchMeasurementRef.current || session !== pinchSessionRef.current) {\n return;\n }\n viewportOriginRef.current = { x, y };\n onMeasured(getPinchGesture(touches, width, height, { x, y }));\n });\n },\n [height, width],\n );\n\n React.useLayoutEffect(() => {\n refreshViewportOrigin();\n }, [height, refreshViewportOrigin, width]);\n\n React.useEffect(\n () => () => {\n pinchMeasurementRef.current += 1;\n pinchSessionRef.current += 1;\n },\n [],\n );\n\n React.useEffect(() => {\n if (!onVisibleItemIdsChange) return;\n const previous = previousVisibleIdsRef.current;\n if (\n previous.length === viewportVisibleIds.length &&\n previous.every((id, index) => id === viewportVisibleIds.at(index))\n ) {\n return;\n }\n previousVisibleIdsRef.current = viewportVisibleIds;\n onVisibleItemIdsChange(viewportVisibleIds);\n }, [onVisibleItemIdsChange, viewportVisibleIds]);\n\n React.useEffect(() => {\n const position = createScrollMapping(viewport, constraints);\n const nextPosition = {\n x: position.horizontal.position,\n y: position.vertical.position,\n };\n if (scrollSyncRef.current?.isCurrent(nextPosition)) return;\n const animated =\n focusRevealViewportRef.current !== undefined &&\n areViewportsEqual(viewport, focusRevealViewportRef.current);\n scrollSyncRef.current?.request(nextPosition, animated);\n if (animated) focusRevealViewportRef.current = undefined;\n }, [constraints, viewport]);\n\n React.useEffect(() => {\n if (\n focusedItemHeight === undefined ||\n focusedItemIdForReveal === undefined ||\n focusedItemWidth === undefined ||\n focusedItemX === undefined ||\n focusedItemY === undefined\n ) {\n focusRevealProposalRef.current = undefined;\n return;\n }\n const sourceViewport = viewportRef.current;\n const revealed = revealWorldRect(\n sourceViewport,\n {\n height: focusedItemHeight,\n width: focusedItemWidth,\n x: focusedItemX,\n y: focusedItemY,\n },\n revealPaddingPixels,\n constraints,\n );\n if (\n isRepeatedControlledFocusRevealProposal({\n controlled: !uncontrolled,\n focusedItemId: focusedItemIdForReveal,\n previous: focusRevealProposalRef.current,\n sourceViewport,\n viewport: revealed,\n })\n ) {\n return;\n }\n focusRevealProposalRef.current = {\n focusedItemId: focusedItemIdForReveal,\n sourceViewport,\n viewport: revealed,\n };\n focusRevealViewportRef.current = areViewportsEqual(sourceViewport, revealed)\n ? undefined\n : revealed;\n publishRef.current(revealed);\n }, [\n constraints,\n focusedItemHeight,\n focusedItemIdForReveal,\n focusedItemWidth,\n focusedItemX,\n focusedItemY,\n revealPaddingPixels,\n uncontrolled,\n ]);\n\n const scrollMapping = createScrollMapping(viewport, constraints);\n\n const syncScrollPosition = () => {\n const nextMapping = createScrollMapping(viewportRef.current, constraints);\n const nextPosition = {\n x: nextMapping.horizontal.position,\n y: nextMapping.vertical.position,\n };\n scrollSyncRef.current?.request(nextPosition, false);\n };\n\n return (\n <NativeView\n ref={gridRef}\n accessibilityLabel=\"Interactive grid viewport\"\n onLayout={refreshViewportOrigin}\n onTouchEnd={() => {\n const wasPinching = pinchGestureRef.current !== undefined;\n pinchMeasurementRef.current += 1;\n pinchSessionRef.current += 1;\n pinchGestureRef.current = undefined;\n setIsPinching(false);\n if (wasPinching) syncScrollPosition();\n }}\n onTouchCancel={() => {\n const wasPinching = pinchGestureRef.current !== undefined;\n pinchMeasurementRef.current += 1;\n pinchSessionRef.current += 1;\n pinchGestureRef.current = undefined;\n setIsPinching(false);\n if (wasPinching) syncScrollPosition();\n }}\n onTouchMove={(event) => {\n if (!interactive) return;\n measurePinchGesture([...event.nativeEvent.touches], pinchSessionRef.current, (pinch) => {\n const previous = pinchGestureRef.current;\n pinchGestureRef.current = pinch;\n setIsPinching(pinch !== undefined);\n if (!pinch || !previous) return;\n zoomAt(pinch.focalPoint, pinch.distance / previous.distance);\n });\n }}\n onTouchStart={(event) => {\n const session = pinchSessionRef.current + 1;\n pinchSessionRef.current = session;\n measurePinchGesture([...event.nativeEvent.touches], session, (pinch) => {\n pinchGestureRef.current = pinch;\n setIsPinching(pinch !== undefined);\n });\n }}\n style={{ height, overflow: 'hidden', width }}\n testID={testID}\n >\n <NativeScrollView\n ref={horizontalScrollRef}\n testID={testID ? `${testID}-horizontal-scroll` : undefined}\n horizontal\n scrollEnabled={interactive && !isPinching}\n scrollEventThrottle={16}\n showsHorizontalScrollIndicator\n style={{ height, width }}\n onMomentumScrollEnd={(event) =>\n scrollSyncRef.current?.scrollEnded('x', event.nativeEvent.contentOffset.x)\n }\n onScroll={(event) => handleNativeScroll('x', event.nativeEvent.contentOffset.x)}\n onScrollBeginDrag={(event) =>\n scrollSyncRef.current?.dragBegan('x', event.nativeEvent.contentOffset.x)\n }\n >\n <NativeScrollView\n ref={verticalScrollRef}\n testID={testID ? `${testID}-vertical-scroll` : undefined}\n scrollEnabled={interactive && !isPinching}\n scrollEventThrottle={16}\n showsVerticalScrollIndicator\n style={{ height, width: scrollMapping.horizontal.contentSize }}\n onMomentumScrollEnd={(event) =>\n scrollSyncRef.current?.scrollEnded('y', event.nativeEvent.contentOffset.y)\n }\n onScroll={(event) => handleNativeScroll('y', event.nativeEvent.contentOffset.y)}\n onScrollBeginDrag={(event) =>\n scrollSyncRef.current?.dragBegan('y', event.nativeEvent.contentOffset.y)\n }\n >\n <NativeView\n style={{\n height: scrollMapping.vertical.contentSize,\n width: scrollMapping.horizontal.contentSize,\n }}\n >\n {visibleItems.map((item) => {\n const position = worldToViewport(\n { x: item.x, y: item.y },\n { ...viewport, offsetX: 0, offsetY: 0 },\n );\n return (\n <NativeView\n key={item.id}\n style={{\n height: item.height * viewport.pixelsPerUnitY,\n left: position.x + scrollMapping.horizontal.origin,\n position: 'absolute',\n top: position.y + scrollMapping.vertical.origin,\n width: item.width * viewport.pixelsPerUnitX,\n }}\n >\n {renderItem(item)}\n </NativeView>\n );\n })}\n </NativeView>\n </NativeScrollView>\n </NativeScrollView>\n {interactive ? (\n <NativeView accessibilityLabel=\"Viewport controls\" style={controlsStyle}>\n <NativePressable\n accessibilityLabel=\"Pan left\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: 48, y: 0 })}\n >\n <NativeText>←</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Pan right\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: -48, y: 0 })}\n >\n <NativeText>→</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Pan up\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: 0, y: 48 })}\n >\n <NativeText>↑</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Pan down\"\n accessibilityRole=\"button\"\n onPress={() => pan({ x: 0, y: -48 })}\n >\n <NativeText>↓</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Zoom in\"\n accessibilityRole=\"button\"\n onPress={() => zoomAt({ x: width / 2, y: height / 2 }, 1.2)}\n >\n <NativeText>+</NativeText>\n </NativePressable>\n <NativePressable\n accessibilityLabel=\"Zoom out\"\n accessibilityRole=\"button\"\n onPress={() => zoomAt({ x: width / 2, y: height / 2 }, 1 / 1.2)}\n >\n <NativeText>−</NativeText>\n </NativePressable>\n </NativeView>\n ) : null}\n </NativeView>\n );\n}\n\nconst controlsStyle = { bottom: 8, gap: 4, position: 'absolute' as const, right: 8 };\n\n/*** Builds the initial world position and independent scales for uncontrolled rendering. */\nfunction createInitialViewport(\n width: number,\n height: number,\n zoom: number,\n viewport: GridViewProps['defaultViewport'],\n): GridViewport {\n return {\n height,\n offsetX: viewport?.offsetX ?? 0,\n offsetY: viewport?.offsetY ?? 0,\n pixelsPerUnitX: viewport?.pixelsPerUnitX ?? zoom,\n pixelsPerUnitY: viewport?.pixelsPerUnitY ?? zoom,\n width,\n };\n}\n\n/*** Uses the rendered content extent as the default finite world boundary. */\nfunction createContentConstraints(\n contentWidth: number,\n contentHeight: number,\n): GridViewportConstraints {\n return { world: { height: contentHeight, width: contentWidth, x: 0, y: 0 } };\n}\n\n/*** Maps engine-constrained world offsets to nonnegative native scroll coordinates. */\nfunction createScrollMapping(\n viewport: GridViewport,\n constraints: GridViewportConstraints,\n): ScrollMapping {\n const horizontalMinimum = constrainViewport(\n { ...viewport, offsetX: -Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetX;\n const horizontalMaximum = constrainViewport(\n { ...viewport, offsetX: Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetX;\n const verticalMinimum = constrainViewport(\n { ...viewport, offsetY: -Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetY;\n const verticalMaximum = constrainViewport(\n { ...viewport, offsetY: Number.MAX_SAFE_INTEGER },\n constraints,\n ).offsetY;\n return {\n horizontal: createScrollAxisMapping({\n maximum: horizontalMaximum,\n minimum: horizontalMinimum,\n offset: viewport.offsetX,\n scale: viewport.pixelsPerUnitX,\n viewportSize: viewport.width,\n }),\n vertical: createScrollAxisMapping({\n maximum: verticalMaximum,\n minimum: verticalMinimum,\n offset: viewport.offsetY,\n scale: viewport.pixelsPerUnitY,\n viewportSize: viewport.height,\n }),\n };\n}\n\ntype ScrollAxisMappingInput = Readonly<{\n maximum: number;\n minimum: number;\n offset: number;\n scale: number;\n viewportSize: number;\n}>;\n\n/*** Derives a physical scroll axis from the published engine constraint result. */\nfunction createScrollAxisMapping({\n maximum,\n minimum,\n offset,\n scale,\n viewportSize,\n}: ScrollAxisMappingInput): ScrollAxisMapping {\n const range = (maximum - minimum) * scale;\n return {\n contentSize: viewportSize + range,\n origin: -minimum * scale,\n position: (offset - minimum) * scale,\n };\n}\n\n/*** Compares canonical viewport fields without treating equal proposals as state changes. */\nfunction areViewportsEqual(left: GridViewport, right: GridViewport): boolean {\n return (\n left.width === right.width &&\n left.height === right.height &&\n left.offsetX === right.offsetX &&\n left.offsetY === right.offsetY &&\n left.pixelsPerUnitX === right.pixelsPerUnitX &&\n left.pixelsPerUnitY === right.pixelsPerUnitY\n );\n}\n\n/*** Skips a rejected controlled focus proposal until its focus or incoming viewport changes. */\nfunction isRepeatedControlledFocusRevealProposal({\n controlled,\n focusedItemId,\n previous,\n sourceViewport,\n viewport,\n}: Readonly<{\n controlled: boolean;\n focusedItemId: string | undefined;\n previous: FocusRevealProposal | undefined;\n sourceViewport: GridViewport;\n viewport: GridViewport;\n}>): boolean {\n return (\n controlled &&\n focusedItemId !== undefined &&\n previous?.focusedItemId === focusedItemId &&\n areViewportsEqual(previous.sourceViewport, sourceViewport) &&\n areViewportsEqual(previous.viewport, viewport)\n );\n}\n\n/*** Extracts a stable two-finger focal point in the measured outer viewport coordinate space. */\nfunction getPinchGesture(\n touches: readonly Readonly<{\n pageX: number;\n pageY: number;\n }>[],\n width: number,\n height: number,\n viewportOrigin: ViewportOrigin,\n): PinchGesture | undefined {\n const [first, second] = touches;\n if (!first || !second) return undefined;\n const deltaX = second.pageX - first.pageX;\n const deltaY = second.pageY - first.pageY;\n const distance = Math.hypot(deltaX, deltaY);\n if (!Number.isFinite(distance) || distance === 0) return undefined;\n return {\n distance,\n focalPoint: {\n x: Math.min(width, Math.max(0, (first.pageX + second.pageX) / 2 - viewportOrigin.x)),\n y: Math.min(height, Math.max(0, (first.pageY + second.pageY) / 2 - viewportOrigin.y)),\n },\n };\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { GridScrollSync, GridScrollSyncOptions } from '../../../types/grid-view';
2
+ /***
3
+ * Arbitrates each native scroll axis between programmatic requests and the user,
4
+ * so echoes of GridView's own scrollTo calls never become viewport pans.
5
+ */
6
+ export declare function createGridScrollSync({ scrollTo, onUserScroll, onProgrammaticScroll, now, schedule, cancel, }: GridScrollSyncOptions): GridScrollSync;
7
+ //# sourceMappingURL=createGridScrollSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createGridScrollSync.d.ts","sourceRoot":"","sources":["../../../../src/features/grid-view/application/createGridScrollSync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,cAAc,EACd,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAclC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,GAAc,EACd,QAAqB,EACrB,MAAqB,GACtB,EAAE,qBAAqB,GAAG,cAAc,CA4GxC"}