@ankhorage/zora 25.4.0 → 25.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -1
  3. package/dist/features/grid-view/adapters/inbound/GridView.d.ts +2 -7
  4. package/dist/features/grid-view/adapters/inbound/GridView.d.ts.map +1 -1
  5. package/dist/features/grid-view/adapters/inbound/GridView.js +309 -51
  6. package/dist/features/grid-view/adapters/inbound/GridView.js.map +1 -1
  7. package/dist/features/grid-view/adapters/inbound/TileGrid.d.ts +1 -1
  8. package/dist/features/grid-view/adapters/inbound/TileGrid.d.ts.map +1 -1
  9. package/dist/features/grid-view/adapters/inbound/TileGrid.js +11 -4
  10. package/dist/features/grid-view/adapters/inbound/TileGrid.js.map +1 -1
  11. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.d.ts.map +1 -1
  12. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js +2 -0
  13. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js.map +1 -1
  14. package/dist/features/registry/componentMeta.d.ts.map +1 -1
  15. package/dist/features/registry/componentMeta.js +2 -0
  16. package/dist/features/registry/componentMeta.js.map +1 -1
  17. package/dist/features/time-grid/adapters/inbound/TimeGrid.d.ts +5 -0
  18. package/dist/features/time-grid/adapters/inbound/TimeGrid.d.ts.map +1 -0
  19. package/dist/features/time-grid/adapters/inbound/TimeGrid.js +107 -0
  20. package/dist/features/time-grid/adapters/inbound/TimeGrid.js.map +1 -0
  21. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.d.ts +9 -0
  22. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.d.ts.map +1 -0
  23. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.js +5 -0
  24. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.js.map +1 -0
  25. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.d.ts +9 -0
  26. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.d.ts.map +1 -0
  27. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.js +5 -0
  28. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.js.map +1 -0
  29. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.d.ts +9 -0
  30. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.d.ts.map +1 -0
  31. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.js +10 -0
  32. package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.js.map +1 -0
  33. package/dist/features/time-grid/application/resolveTimeGridNextFocusId.d.ts +4 -0
  34. package/dist/features/time-grid/application/resolveTimeGridNextFocusId.d.ts.map +1 -0
  35. package/dist/features/time-grid/application/resolveTimeGridNextFocusId.js +31 -0
  36. package/dist/features/time-grid/application/resolveTimeGridNextFocusId.js.map +1 -0
  37. package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.d.ts +5 -0
  38. package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.d.ts.map +1 -0
  39. package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.js +6 -0
  40. package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.js.map +1 -0
  41. package/dist/features/time-grid/meta.d.ts +11 -0
  42. package/dist/features/time-grid/meta.d.ts.map +1 -0
  43. package/dist/features/time-grid/meta.js +11 -0
  44. package/dist/features/time-grid/meta.js.map +1 -0
  45. package/dist/features/time-grid/public.d.ts +5 -0
  46. package/dist/features/time-grid/public.d.ts.map +1 -0
  47. package/dist/features/time-grid/public.js +4 -0
  48. package/dist/features/time-grid/public.js.map +1 -0
  49. package/dist/index.d.ts +2 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -0
  52. package/dist/index.js.map +1 -1
  53. package/dist/types/grid-view.d.ts +18 -1
  54. package/dist/types/grid-view.d.ts.map +1 -1
  55. package/dist/types/grid-view.js.map +1 -1
  56. package/dist/types/time-grid.d.ts +30 -0
  57. package/dist/types/time-grid.d.ts.map +1 -0
  58. package/dist/types/time-grid.js +2 -0
  59. package/dist/types/time-grid.js.map +1 -0
  60. package/package.json +1 -1
  61. package/src/features/grid-view/adapters/inbound/GridView.interaction.test.tsx +585 -0
  62. package/src/features/grid-view/adapters/inbound/GridView.test.tsx +74 -0
  63. package/src/features/grid-view/adapters/inbound/GridView.tsx +506 -77
  64. package/src/features/grid-view/adapters/inbound/TileGrid.tsx +26 -3
  65. package/src/features/registry/ZORA_COMPONENT_REGISTRY.ts +2 -0
  66. package/src/features/registry/componentMeta.ts +2 -0
  67. package/src/features/time-grid/adapters/inbound/TimeGrid.test.tsx +158 -0
  68. package/src/features/time-grid/adapters/inbound/TimeGrid.tsx +197 -0
  69. package/src/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.tsx +11 -0
  70. package/src/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.tsx +11 -0
  71. package/src/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.tsx +20 -0
  72. package/src/features/time-grid/application/resolveTimeGridNextFocusId.test.ts +46 -0
  73. package/src/features/time-grid/application/resolveTimeGridNextFocusId.ts +41 -0
  74. package/src/features/time-grid/application/resolveTimeGridVisibleIntervals.test.ts +33 -0
  75. package/src/features/time-grid/application/resolveTimeGridVisibleIntervals.ts +13 -0
  76. package/src/features/time-grid/meta.ts +12 -0
  77. package/src/features/time-grid/public.ts +4 -0
  78. package/src/index.ts +2 -0
  79. package/src/types/grid-view.ts +27 -1
  80. package/src/types/time-grid.ts +33 -0
  81. package/web-dist/chunks/{Accordion-r2w86rwv.js → Accordion-ebghcyzj.js} +125 -1
  82. package/web-dist/chunks/{Accordion-s3d6g59s.js → Accordion-f43jba23.js} +1 -1
  83. package/web-dist/chunks/Accordion-q8exgc3h.js +515 -0
  84. package/web-dist/chunks/{Accordion-60wn9xn9.js → Accordion-szar8dt5.js} +1 -1
  85. package/web-dist/components/explorer/Explorer.js +2 -2
  86. package/web-dist/components/file-explorer/FileExplorer.js +2 -2
  87. package/web-dist/components/grid-line-overlay/GridLineOverlay.js +1 -1
  88. package/web-dist/components/grid-ruler/GridRuler.js +1 -1
  89. package/web-dist/components/grid-view/GridView.js +1 -1
  90. package/web-dist/components/media-explorer/MediaExplorer.js +2 -2
  91. package/web-dist/components/reader/Reader.js +1 -1
  92. package/web-dist/components/spatial-grid/SpatialGrid.js +1 -1
  93. package/web-dist/components/tile-grid/TileGrid.js +1 -1
  94. package/web-dist/components/time-grid/TimeGrid.d.ts +3 -0
  95. package/web-dist/components/time-grid/TimeGrid.js +208 -0
  96. package/web-dist/components/time-grid/index.d.ts +1 -0
  97. package/web-dist/components/time-grid/index.js +2 -0
  98. package/web-dist/components/uploader/Uploader.js +2 -2
  99. package/web-dist/manifest.json +38 -22
  100. package/web-dist/chunks/Accordion-nxsda1my.js +0 -194
@@ -0,0 +1,515 @@
1
+ 'use client';
2
+ import {
3
+ getVisibleGridItems,
4
+ constrainViewport,
5
+ panViewport,
6
+ revealWorldRect,
7
+ worldToViewport,
8
+ zoomViewportAt
9
+ } from "./Accordion-ebghcyzj.js";
10
+ import {
11
+ require_cjs
12
+ } from "./Accordion-xgpzh4wq.js";
13
+ import {
14
+ __toESM
15
+ } from "./Accordion-nh0cs9hq.js";
16
+
17
+ // src/features/grid-view/adapters/inbound/GridView.tsx
18
+ var import_react_native = __toESM(require_cjs(), 1);
19
+ import React from "react";
20
+ import { jsx, jsxs } from "react/jsx-runtime";
21
+ function GridView2({
22
+ items,
23
+ contentWidth,
24
+ contentHeight,
25
+ width,
26
+ height,
27
+ viewport: controlledViewport,
28
+ defaultViewport,
29
+ viewportConstraints,
30
+ zoomLimits,
31
+ zoom = 1,
32
+ overscanPixels = 160,
33
+ focusedItemId,
34
+ revealPaddingPixels = 8,
35
+ interactionPolicy,
36
+ onViewportChange,
37
+ onVisibleItemIdsChange,
38
+ renderItem,
39
+ testID
40
+ }) {
41
+ const [uncontrolledViewport, setUncontrolledViewport] = React.useState(() => createInitialViewport(width, height, zoom, defaultViewport));
42
+ const horizontalScrollRef = React.useRef(null);
43
+ const verticalScrollRef = React.useRef(null);
44
+ const gridRef = React.useRef(null);
45
+ const scrollPositionRef = React.useRef({ x: 0, y: 0 });
46
+ const pinchGestureRef = React.useRef(undefined);
47
+ const pinchMeasurementRef = React.useRef(0);
48
+ const pinchSessionRef = React.useRef(0);
49
+ const viewportOriginRef = React.useRef({ x: 0, y: 0 });
50
+ const focusRevealProposalRef = React.useRef(undefined);
51
+ const focusRevealViewportRef = React.useRef(undefined);
52
+ const [isPinching, setIsPinching] = React.useState(false);
53
+ const constraints = React.useMemo(() => viewportConstraints ?? createContentConstraints(contentWidth, contentHeight), [contentHeight, contentWidth, viewportConstraints]);
54
+ const sourceViewport = controlledViewport ?? uncontrolledViewport;
55
+ const viewport = React.useMemo(() => constrainViewport({ ...sourceViewport, height, width }, constraints), [constraints, height, sourceViewport, width]);
56
+ const viewportRef = React.useRef(viewport);
57
+ const visibleItems = React.useMemo(() => getVisibleGridItems(items, viewport, overscanPixels), [items, overscanPixels, viewport]);
58
+ const viewportVisibleIds = React.useMemo(() => getVisibleGridItems(visibleItems, viewport).map((item) => item.id), [viewport, visibleItems]);
59
+ const focusedItem = items.find((item) => item.id === focusedItemId);
60
+ const focusedItemHeight = focusedItem?.height;
61
+ const focusedItemIdForReveal = focusedItem?.id;
62
+ const focusedItemWidth = focusedItem?.width;
63
+ const focusedItemX = focusedItem?.x;
64
+ const focusedItemY = focusedItem?.y;
65
+ const previousVisibleIdsRef = React.useRef([]);
66
+ const uncontrolled = controlledViewport === undefined;
67
+ const interactive = interactionPolicy !== "passive";
68
+ const publish = React.useCallback((nextViewport) => {
69
+ if (areViewportsEqual(viewportRef.current, nextViewport))
70
+ return;
71
+ viewportRef.current = nextViewport;
72
+ if (uncontrolled)
73
+ setUncontrolledViewport(nextViewport);
74
+ onViewportChange?.(nextViewport);
75
+ }, [onViewportChange, uncontrolled]);
76
+ const publishRef = React.useRef(publish);
77
+ const pan = (displacement) => publish(panViewport(viewportRef.current, displacement, constraints));
78
+ const zoomAt = (focalPoint, factor) => publish(zoomViewportAt(viewportRef.current, focalPoint, {
79
+ pixelsPerUnitX: viewportRef.current.pixelsPerUnitX * factor,
80
+ pixelsPerUnitY: viewportRef.current.pixelsPerUnitY * factor
81
+ }, zoomLimits, constraints));
82
+ React.useEffect(() => {
83
+ viewportRef.current = viewport;
84
+ }, [viewport]);
85
+ React.useEffect(() => {
86
+ publishRef.current = publish;
87
+ }, [publish]);
88
+ const refreshViewportOrigin = React.useCallback(() => {
89
+ gridRef.current?.measureInWindow((x, y) => {
90
+ viewportOriginRef.current = { x, y };
91
+ });
92
+ }, []);
93
+ const measurePinchGesture = React.useCallback((touches, session, onMeasured) => {
94
+ const measurement = pinchMeasurementRef.current + 1;
95
+ pinchMeasurementRef.current = measurement;
96
+ gridRef.current?.measureInWindow((x, y) => {
97
+ if (measurement !== pinchMeasurementRef.current || session !== pinchSessionRef.current) {
98
+ return;
99
+ }
100
+ viewportOriginRef.current = { x, y };
101
+ onMeasured(getPinchGesture(touches, width, height, { x, y }));
102
+ });
103
+ }, [height, width]);
104
+ React.useLayoutEffect(() => {
105
+ refreshViewportOrigin();
106
+ }, [height, refreshViewportOrigin, width]);
107
+ React.useEffect(() => () => {
108
+ pinchMeasurementRef.current += 1;
109
+ pinchSessionRef.current += 1;
110
+ }, []);
111
+ React.useEffect(() => {
112
+ if (!onVisibleItemIdsChange)
113
+ return;
114
+ const previous = previousVisibleIdsRef.current;
115
+ if (previous.length === viewportVisibleIds.length && previous.every((id, index) => id === viewportVisibleIds.at(index))) {
116
+ return;
117
+ }
118
+ previousVisibleIdsRef.current = viewportVisibleIds;
119
+ onVisibleItemIdsChange(viewportVisibleIds);
120
+ }, [onVisibleItemIdsChange, viewportVisibleIds]);
121
+ React.useEffect(() => {
122
+ const position = createScrollMapping(viewport, constraints);
123
+ const nextPosition = {
124
+ x: position.horizontal.position,
125
+ y: position.vertical.position
126
+ };
127
+ if (areScrollPositionsEqual(scrollPositionRef.current, nextPosition))
128
+ return;
129
+ scrollPositionRef.current = nextPosition;
130
+ const animated = focusRevealViewportRef.current !== undefined && areViewportsEqual(viewport, focusRevealViewportRef.current);
131
+ horizontalScrollRef.current?.scrollTo({ animated, x: nextPosition.x });
132
+ verticalScrollRef.current?.scrollTo({ animated, y: nextPosition.y });
133
+ if (animated)
134
+ focusRevealViewportRef.current = undefined;
135
+ }, [constraints, viewport]);
136
+ React.useEffect(() => {
137
+ if (focusedItemHeight === undefined || focusedItemIdForReveal === undefined || focusedItemWidth === undefined || focusedItemX === undefined || focusedItemY === undefined) {
138
+ focusRevealProposalRef.current = undefined;
139
+ return;
140
+ }
141
+ const sourceViewport = viewportRef.current;
142
+ const revealed = revealWorldRect(sourceViewport, {
143
+ height: focusedItemHeight,
144
+ width: focusedItemWidth,
145
+ x: focusedItemX,
146
+ y: focusedItemY
147
+ }, revealPaddingPixels, constraints);
148
+ if (isRepeatedControlledFocusRevealProposal({
149
+ controlled: !uncontrolled,
150
+ focusedItemId: focusedItemIdForReveal,
151
+ previous: focusRevealProposalRef.current,
152
+ sourceViewport,
153
+ viewport: revealed
154
+ })) {
155
+ return;
156
+ }
157
+ focusRevealProposalRef.current = {
158
+ focusedItemId: focusedItemIdForReveal,
159
+ sourceViewport,
160
+ viewport: revealed
161
+ };
162
+ focusRevealViewportRef.current = areViewportsEqual(sourceViewport, revealed) ? undefined : revealed;
163
+ publishRef.current(revealed);
164
+ }, [
165
+ constraints,
166
+ focusedItemHeight,
167
+ focusedItemIdForReveal,
168
+ focusedItemWidth,
169
+ focusedItemX,
170
+ focusedItemY,
171
+ revealPaddingPixels,
172
+ uncontrolled
173
+ ]);
174
+ const scrollMapping = createScrollMapping(viewport, constraints);
175
+ const syncScrollPosition = () => {
176
+ const nextMapping = createScrollMapping(viewportRef.current, constraints);
177
+ const nextPosition = {
178
+ x: nextMapping.horizontal.position,
179
+ y: nextMapping.vertical.position
180
+ };
181
+ scrollPositionRef.current = nextPosition;
182
+ horizontalScrollRef.current?.scrollTo({ animated: false, x: nextPosition.x });
183
+ verticalScrollRef.current?.scrollTo({ animated: false, y: nextPosition.y });
184
+ };
185
+ return /* @__PURE__ */ jsxs(import_react_native.View, {
186
+ ref: gridRef,
187
+ accessibilityLabel: "Interactive grid viewport",
188
+ onLayout: refreshViewportOrigin,
189
+ onTouchEnd: () => {
190
+ const wasPinching = pinchGestureRef.current !== undefined;
191
+ pinchMeasurementRef.current += 1;
192
+ pinchSessionRef.current += 1;
193
+ pinchGestureRef.current = undefined;
194
+ setIsPinching(false);
195
+ if (wasPinching)
196
+ syncScrollPosition();
197
+ },
198
+ onTouchCancel: () => {
199
+ const wasPinching = pinchGestureRef.current !== undefined;
200
+ pinchMeasurementRef.current += 1;
201
+ pinchSessionRef.current += 1;
202
+ pinchGestureRef.current = undefined;
203
+ setIsPinching(false);
204
+ if (wasPinching)
205
+ syncScrollPosition();
206
+ },
207
+ onTouchMove: (event) => {
208
+ if (!interactive)
209
+ return;
210
+ measurePinchGesture([...event.nativeEvent.touches], pinchSessionRef.current, (pinch) => {
211
+ const previous = pinchGestureRef.current;
212
+ pinchGestureRef.current = pinch;
213
+ setIsPinching(pinch !== undefined);
214
+ if (!pinch || !previous)
215
+ return;
216
+ zoomAt(pinch.focalPoint, pinch.distance / previous.distance);
217
+ });
218
+ },
219
+ onTouchStart: (event) => {
220
+ const session = pinchSessionRef.current + 1;
221
+ pinchSessionRef.current = session;
222
+ measurePinchGesture([...event.nativeEvent.touches], session, (pinch) => {
223
+ pinchGestureRef.current = pinch;
224
+ setIsPinching(pinch !== undefined);
225
+ });
226
+ },
227
+ style: { height, overflow: "hidden", width },
228
+ testID,
229
+ children: [
230
+ /* @__PURE__ */ jsx(import_react_native.ScrollView, {
231
+ ref: horizontalScrollRef,
232
+ testID: testID ? `${testID}-horizontal-scroll` : undefined,
233
+ horizontal: true,
234
+ scrollEnabled: interactive && !isPinching,
235
+ scrollEventThrottle: 16,
236
+ showsHorizontalScrollIndicator: true,
237
+ style: { height, width },
238
+ onScroll: (event) => {
239
+ if (pinchGestureRef.current)
240
+ return;
241
+ const { x } = event.nativeEvent.contentOffset;
242
+ const displacement = x - scrollPositionRef.current.x;
243
+ scrollPositionRef.current = { ...scrollPositionRef.current, x };
244
+ if (displacement !== 0)
245
+ pan({ x: -displacement, y: 0 });
246
+ },
247
+ children: /* @__PURE__ */ jsx(import_react_native.ScrollView, {
248
+ ref: verticalScrollRef,
249
+ testID: testID ? `${testID}-vertical-scroll` : undefined,
250
+ scrollEnabled: interactive && !isPinching,
251
+ scrollEventThrottle: 16,
252
+ showsVerticalScrollIndicator: true,
253
+ style: { height, width: scrollMapping.horizontal.contentSize },
254
+ onScroll: (event) => {
255
+ if (pinchGestureRef.current)
256
+ return;
257
+ const { y } = event.nativeEvent.contentOffset;
258
+ const displacement = y - scrollPositionRef.current.y;
259
+ scrollPositionRef.current = { ...scrollPositionRef.current, y };
260
+ if (displacement !== 0)
261
+ pan({ x: 0, y: -displacement });
262
+ },
263
+ children: /* @__PURE__ */ jsx(import_react_native.View, {
264
+ style: {
265
+ height: scrollMapping.vertical.contentSize,
266
+ width: scrollMapping.horizontal.contentSize
267
+ },
268
+ children: visibleItems.map((item) => {
269
+ const position = worldToViewport({ x: item.x, y: item.y }, { ...viewport, offsetX: 0, offsetY: 0 });
270
+ return /* @__PURE__ */ jsx(import_react_native.View, {
271
+ style: {
272
+ height: item.height * viewport.pixelsPerUnitY,
273
+ left: position.x + scrollMapping.horizontal.origin,
274
+ position: "absolute",
275
+ top: position.y + scrollMapping.vertical.origin,
276
+ width: item.width * viewport.pixelsPerUnitX
277
+ },
278
+ children: renderItem(item)
279
+ }, item.id);
280
+ })
281
+ })
282
+ })
283
+ }),
284
+ interactive ? /* @__PURE__ */ jsxs(import_react_native.View, {
285
+ accessibilityLabel: "Viewport controls",
286
+ style: controlsStyle,
287
+ children: [
288
+ /* @__PURE__ */ jsx(import_react_native.Pressable, {
289
+ accessibilityLabel: "Pan left",
290
+ accessibilityRole: "button",
291
+ onPress: () => pan({ x: 48, y: 0 }),
292
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
293
+ children: "←"
294
+ })
295
+ }),
296
+ /* @__PURE__ */ jsx(import_react_native.Pressable, {
297
+ accessibilityLabel: "Pan right",
298
+ accessibilityRole: "button",
299
+ onPress: () => pan({ x: -48, y: 0 }),
300
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
301
+ children: "→"
302
+ })
303
+ }),
304
+ /* @__PURE__ */ jsx(import_react_native.Pressable, {
305
+ accessibilityLabel: "Pan up",
306
+ accessibilityRole: "button",
307
+ onPress: () => pan({ x: 0, y: 48 }),
308
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
309
+ children: "↑"
310
+ })
311
+ }),
312
+ /* @__PURE__ */ jsx(import_react_native.Pressable, {
313
+ accessibilityLabel: "Pan down",
314
+ accessibilityRole: "button",
315
+ onPress: () => pan({ x: 0, y: -48 }),
316
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
317
+ children: "↓"
318
+ })
319
+ }),
320
+ /* @__PURE__ */ jsx(import_react_native.Pressable, {
321
+ accessibilityLabel: "Zoom in",
322
+ accessibilityRole: "button",
323
+ onPress: () => zoomAt({ x: width / 2, y: height / 2 }, 1.2),
324
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
325
+ children: "+"
326
+ })
327
+ }),
328
+ /* @__PURE__ */ jsx(import_react_native.Pressable, {
329
+ accessibilityLabel: "Zoom out",
330
+ accessibilityRole: "button",
331
+ onPress: () => zoomAt({ x: width / 2, y: height / 2 }, 1 / 1.2),
332
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
333
+ children: "−"
334
+ })
335
+ })
336
+ ]
337
+ }) : null
338
+ ]
339
+ });
340
+ }
341
+ var controlsStyle = { bottom: 8, gap: 4, position: "absolute", right: 8 };
342
+ function createInitialViewport(width, height, zoom, viewport) {
343
+ return {
344
+ height,
345
+ offsetX: viewport?.offsetX ?? 0,
346
+ offsetY: viewport?.offsetY ?? 0,
347
+ pixelsPerUnitX: viewport?.pixelsPerUnitX ?? zoom,
348
+ pixelsPerUnitY: viewport?.pixelsPerUnitY ?? zoom,
349
+ width
350
+ };
351
+ }
352
+ function createContentConstraints(contentWidth, contentHeight) {
353
+ return { world: { height: contentHeight, width: contentWidth, x: 0, y: 0 } };
354
+ }
355
+ function createScrollMapping(viewport, constraints) {
356
+ const horizontalMinimum = constrainViewport({ ...viewport, offsetX: -Number.MAX_SAFE_INTEGER }, constraints).offsetX;
357
+ const horizontalMaximum = constrainViewport({ ...viewport, offsetX: Number.MAX_SAFE_INTEGER }, constraints).offsetX;
358
+ const verticalMinimum = constrainViewport({ ...viewport, offsetY: -Number.MAX_SAFE_INTEGER }, constraints).offsetY;
359
+ const verticalMaximum = constrainViewport({ ...viewport, offsetY: Number.MAX_SAFE_INTEGER }, constraints).offsetY;
360
+ return {
361
+ horizontal: createScrollAxisMapping({
362
+ maximum: horizontalMaximum,
363
+ minimum: horizontalMinimum,
364
+ offset: viewport.offsetX,
365
+ scale: viewport.pixelsPerUnitX,
366
+ viewportSize: viewport.width
367
+ }),
368
+ vertical: createScrollAxisMapping({
369
+ maximum: verticalMaximum,
370
+ minimum: verticalMinimum,
371
+ offset: viewport.offsetY,
372
+ scale: viewport.pixelsPerUnitY,
373
+ viewportSize: viewport.height
374
+ })
375
+ };
376
+ }
377
+ function createScrollAxisMapping({
378
+ maximum,
379
+ minimum,
380
+ offset,
381
+ scale,
382
+ viewportSize
383
+ }) {
384
+ const range = (maximum - minimum) * scale;
385
+ return {
386
+ contentSize: viewportSize + range,
387
+ origin: -minimum * scale,
388
+ position: (offset - minimum) * scale
389
+ };
390
+ }
391
+ function areViewportsEqual(left, right) {
392
+ return left.width === right.width && left.height === right.height && left.offsetX === right.offsetX && left.offsetY === right.offsetY && left.pixelsPerUnitX === right.pixelsPerUnitX && left.pixelsPerUnitY === right.pixelsPerUnitY;
393
+ }
394
+ function areScrollPositionsEqual(left, right) {
395
+ return left.x === right.x && left.y === right.y;
396
+ }
397
+ function isRepeatedControlledFocusRevealProposal({
398
+ controlled,
399
+ focusedItemId,
400
+ previous,
401
+ sourceViewport,
402
+ viewport
403
+ }) {
404
+ return controlled && focusedItemId !== undefined && previous?.focusedItemId === focusedItemId && areViewportsEqual(previous.sourceViewport, sourceViewport) && areViewportsEqual(previous.viewport, viewport);
405
+ }
406
+ function getPinchGesture(touches, width, height, viewportOrigin) {
407
+ const [first, second] = touches;
408
+ if (!first || !second)
409
+ return;
410
+ const deltaX = second.pageX - first.pageX;
411
+ const deltaY = second.pageY - first.pageY;
412
+ const distance = Math.hypot(deltaX, deltaY);
413
+ if (!Number.isFinite(distance) || distance === 0)
414
+ return;
415
+ return {
416
+ distance,
417
+ focalPoint: {
418
+ x: Math.min(width, Math.max(0, (first.pageX + second.pageX) / 2 - viewportOrigin.x)),
419
+ y: Math.min(height, Math.max(0, (first.pageY + second.pageY) / 2 - viewportOrigin.y))
420
+ }
421
+ };
422
+ }
423
+
424
+ // src/features/grid-view/adapters/inbound/TileGrid.tsx
425
+ var import_react_native2 = __toESM(require_cjs(), 1);
426
+ import React2 from "react";
427
+
428
+ // src/features/grid-view/application/layoutTileGrid.ts
429
+ function layoutTileGrid(items, viewportWidth, tileSize, gap, zoom = 1) {
430
+ if (![viewportWidth, tileSize, gap, zoom].every(Number.isFinite) || viewportWidth < 0 || tileSize <= 0 || gap < 0 || zoom <= 0) {
431
+ throw new RangeError("Tile layout requires finite, nonnegative dimensions and positive scales.");
432
+ }
433
+ const columns = Math.max(1, Math.floor((viewportWidth / zoom + gap) / (tileSize + gap)));
434
+ const rows = Math.ceil(items.length / columns);
435
+ return {
436
+ columns,
437
+ width: columns * (tileSize + gap) - gap,
438
+ height: Math.max(0, rows * (tileSize + gap) - gap),
439
+ items: items.map((item, index) => ({
440
+ id: item.id,
441
+ x: index % columns * (tileSize + gap),
442
+ y: Math.floor(index / columns) * (tileSize + gap),
443
+ width: tileSize,
444
+ height: tileSize
445
+ }))
446
+ };
447
+ }
448
+
449
+ // src/features/grid-view/adapters/inbound/TileGrid.tsx
450
+ import { jsx as jsx2 } from "react/jsx-runtime";
451
+ function TileGrid2({
452
+ items,
453
+ width,
454
+ height = 440,
455
+ tileSize = 120,
456
+ gap = 12,
457
+ zoom = 1,
458
+ viewport,
459
+ defaultViewport,
460
+ viewportConstraints,
461
+ zoomLimits,
462
+ overscanPixels,
463
+ focusedItemId,
464
+ revealPaddingPixels,
465
+ onColumnsChange,
466
+ onViewportChange,
467
+ onVisibleItemIdsChange,
468
+ renderItem,
469
+ interactionPolicy,
470
+ testID
471
+ }) {
472
+ const [measuredWidth, setMeasuredWidth] = React2.useState(0);
473
+ const [uncontrolledPixelsPerUnitX, setUncontrolledPixelsPerUnitX] = React2.useState(() => defaultViewport?.pixelsPerUnitX ?? zoom);
474
+ const resolvedWidth = width ?? measuredWidth;
475
+ const pixelsPerUnitX = viewport?.pixelsPerUnitX ?? uncontrolledPixelsPerUnitX;
476
+ const layout = React2.useMemo(() => layoutTileGrid(items, resolvedWidth, tileSize, gap, pixelsPerUnitX), [gap, items, pixelsPerUnitX, resolvedWidth, tileSize]);
477
+ const itemLookup = React2.useMemo(() => new Map(items.map((item) => [item.id, item])), [items]);
478
+ React2.useEffect(() => {
479
+ if (resolvedWidth > 0)
480
+ onColumnsChange?.(layout.columns);
481
+ }, [layout.columns, onColumnsChange, resolvedWidth]);
482
+ const handleViewportChange = React2.useCallback((nextViewport) => {
483
+ if (viewport === undefined)
484
+ setUncontrolledPixelsPerUnitX(nextViewport.pixelsPerUnitX);
485
+ onViewportChange?.(nextViewport);
486
+ }, [onViewportChange, viewport]);
487
+ return /* @__PURE__ */ jsx2(import_react_native2.View, {
488
+ onLayout: (event) => setMeasuredWidth(event.nativeEvent.layout.width),
489
+ style: { width, height, overflow: "hidden" },
490
+ testID,
491
+ children: resolvedWidth > 0 ? /* @__PURE__ */ jsx2(GridView2, {
492
+ contentHeight: layout.height,
493
+ contentWidth: Math.max(resolvedWidth / pixelsPerUnitX, layout.width),
494
+ defaultViewport,
495
+ height,
496
+ focusedItemId,
497
+ interactionPolicy,
498
+ items: layout.items,
499
+ onVisibleItemIdsChange,
500
+ onViewportChange: handleViewportChange,
501
+ overscanPixels,
502
+ renderItem: (item) => {
503
+ const source = itemLookup.get(item.id);
504
+ return source ? renderItem(source) : null;
505
+ },
506
+ revealPaddingPixels,
507
+ width: resolvedWidth,
508
+ viewport,
509
+ viewportConstraints,
510
+ zoomLimits,
511
+ zoom
512
+ }) : null
513
+ });
514
+ }
515
+ export { GridView2, TileGrid2 };
@@ -6,7 +6,7 @@ import {
6
6
  getAxisCategoryTicks,
7
7
  getAxisTicks,
8
8
  worldToViewport
9
- } from "./Accordion-r2w86rwv.js";
9
+ } from "./Accordion-ebghcyzj.js";
10
10
  import {
11
11
  useZoraTheme2
12
12
  } from "./Accordion-srjya6dz.js";
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import"../../chunks/Accordion-nxsda1my.js";
2
+ import"../../chunks/Accordion-q8exgc3h.js";
3
3
  import"../../chunks/Accordion-bfzeab9x.js";
4
4
  import"../../chunks/Accordion-6wrr910w.js";
5
5
  import"../../chunks/Accordion-8f0nekwe.js";
@@ -14,7 +14,7 @@ import {
14
14
  Explorer2,
15
15
  FileExplorer2,
16
16
  MediaExplorer2
17
- } from "../../chunks/Accordion-s3d6g59s.js";
17
+ } from "../../chunks/Accordion-f43jba23.js";
18
18
  import"../../chunks/Accordion-bff0p3x4.js";
19
19
  import"../../chunks/Accordion-srjya6dz.js";
20
20
  import"../../chunks/Accordion-184r2r82.js";
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import"../../chunks/Accordion-nxsda1my.js";
2
+ import"../../chunks/Accordion-q8exgc3h.js";
3
3
  import"../../chunks/Accordion-bfzeab9x.js";
4
4
  import"../../chunks/Accordion-6wrr910w.js";
5
5
  import"../../chunks/Accordion-8f0nekwe.js";
@@ -14,7 +14,7 @@ import {
14
14
  Explorer2,
15
15
  FileExplorer2,
16
16
  MediaExplorer2
17
- } from "../../chunks/Accordion-s3d6g59s.js";
17
+ } from "../../chunks/Accordion-f43jba23.js";
18
18
  import"../../chunks/Accordion-bff0p3x4.js";
19
19
  import"../../chunks/Accordion-srjya6dz.js";
20
20
  import"../../chunks/Accordion-184r2r82.js";
@@ -4,7 +4,7 @@ import"../../chunks/Accordion-42jfy1a1.js";
4
4
  import {
5
5
  GridLineOverlay2,
6
6
  GridRuler2
7
- } from "../../chunks/Accordion-60wn9xn9.js";
7
+ } from "../../chunks/Accordion-szar8dt5.js";
8
8
  import"../../chunks/Accordion-srjya6dz.js";
9
9
  import"../../chunks/Accordion-xgpzh4wq.js";
10
10
  export {
@@ -4,7 +4,7 @@ import"../../chunks/Accordion-42jfy1a1.js";
4
4
  import {
5
5
  GridLineOverlay2,
6
6
  GridRuler2
7
- } from "../../chunks/Accordion-60wn9xn9.js";
7
+ } from "../../chunks/Accordion-szar8dt5.js";
8
8
  import"../../chunks/Accordion-srjya6dz.js";
9
9
  import"../../chunks/Accordion-xgpzh4wq.js";
10
10
  export {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  GridView2,
4
4
  TileGrid2
5
- } from "../../chunks/Accordion-nxsda1my.js";
5
+ } from "../../chunks/Accordion-q8exgc3h.js";
6
6
  import"../../chunks/Accordion-xgpzh4wq.js";
7
7
  export {
8
8
  GridView2 as GridView,
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import"../../chunks/Accordion-nxsda1my.js";
2
+ import"../../chunks/Accordion-q8exgc3h.js";
3
3
  import"../../chunks/Accordion-bfzeab9x.js";
4
4
  import"../../chunks/Accordion-6wrr910w.js";
5
5
  import"../../chunks/Accordion-8f0nekwe.js";
@@ -14,7 +14,7 @@ import {
14
14
  Explorer2,
15
15
  FileExplorer2,
16
16
  MediaExplorer2
17
- } from "../../chunks/Accordion-s3d6g59s.js";
17
+ } from "../../chunks/Accordion-f43jba23.js";
18
18
  import"../../chunks/Accordion-bff0p3x4.js";
19
19
  import"../../chunks/Accordion-srjya6dz.js";
20
20
  import"../../chunks/Accordion-184r2r82.js";
@@ -79,7 +79,7 @@ import {
79
79
  __preload,
80
80
  __chunks
81
81
  } from "../../chunks/Accordion-nh0cs9hq.js";
82
- __chunks(import.meta.url,["xqvqxdap","rg94gstv","z23c32jh","50yy1az9","x15y26r7","1t98py7y","m8ts96nj","8se5z2w3","mjvegqjq","8gxjy9na","2389epxb","pnpxcrwx","hszzyv5p","y8p5hk56","vgkvvdvg","ewf1zen9","09qs8gt1","z5a0tx18","6wrr910w","bfzeab9x","8f0nekwe","nnv76yff","wyxmd0n0","6rrqpb2h","42jfy1a1","7tjz25jh","6zb9d92y","be2yhfqz","mnac2z83","0gfsj9qh","fzcpm4xf","2nesr9cv","h7zsx9eg","b96evb46","9w8wg9mf","pvj5npzc","w6qedeba","eqvdv7tt","61e19g3e","ys214jt5","bff0p3x4","srjya6dz","184r2r82","fre84yaq","xgpzh4wq","nh0cs9hq","6a2hscrx","n7y08rz5","59pa0677","961ncx4e"],[["./Reader.js",14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],["../../chunks/ReadiumCSS-default.css-rg94gstv.js"],["../../chunks/ReadiumCSS-after.css-z23c32jh.js"],["../../chunks/ReadiumCSS-ebpaj_fonts_patch.css-50yy1az9.js"],["../../chunks/ReadiumCSS-after.css-x15y26r7.js"],["../../chunks/ReadiumCSS-before.css-1t98py7y.js"],["../../chunks/ReadiumCSS-default.css-m8ts96nj.js"],["../../chunks/ReadiumCSS-after.css-8se5z2w3.js"],["../../chunks/ReadiumCSS-before.css-mjvegqjq.js"],["../../chunks/ReadiumCSS-default.css-8gxjy9na.js"],["../../chunks/ReadiumCSS-after.css-2389epxb.js"],["../../chunks/ReadiumCSS-before.css-pnpxcrwx.js"],["../../chunks/ReadiumCSS-before.css-hszzyv5p.js"],["../../chunks/ReadiumCSS-default.css-y8p5hk56.js"],["../../chunks/Accordion-vgkvvdvg.js"],["../../chunks/Accordion-ewf1zen9.js",17,18,23,24,25,32,34,41,44,45],["../../chunks/Accordion-09qs8gt1.js",44,45],["../../chunks/Accordion-z5a0tx18.js",16,18,42,44,45],["../../chunks/Accordion-6wrr910w.js"],["../../chunks/Accordion-bfzeab9x.js"],["../../chunks/Accordion-8f0nekwe.js",19,18,46,43,44,45],["../../chunks/Accordion-nnv76yff.js",16,18,47,42,44,45],["../../chunks/Accordion-wyxmd0n0.js",18,47,46,44,45],["../../chunks/Accordion-6rrqpb2h.js",18,20,17,21,22,24,25,47,40,44,45],["../../chunks/Accordion-42jfy1a1.js",18,48],["../../chunks/Accordion-7tjz25jh.js",16,17,18,24,42,44,45],["../../chunks/Accordion-6zb9d92y.js"],["../../chunks/Accordion-be2yhfqz.js",26,44,45],["../../chunks/Accordion-mnac2z83.js"],["../../chunks/Accordion-0gfsj9qh.js",47],["../../chunks/Accordion-fzcpm4xf.js",28,29,44,45],["../../chunks/Accordion-2nesr9cv.js",17,18],["../../chunks/Accordion-h7zsx9eg.js",26,27,17,18,30,31,22,24,33,25,49,41,44,45],["../../chunks/Accordion-b96evb46.js",20,24],["../../chunks/Accordion-9w8wg9mf.js",16,24,40,41,44,45],["../../chunks/Accordion-pvj5npzc.js",24,25,34,41,44,45],["../../chunks/Accordion-w6qedeba.js",31,24],["../../chunks/Accordion-eqvdv7tt.js"],["../../chunks/Accordion-61e19g3e.js"],["../../chunks/Accordion-ys214jt5.js"],["../../chunks/Accordion-bff0p3x4.js",19,41],["../../chunks/Accordion-srjya6dz.js",18],["../../chunks/Accordion-184r2r82.js",16,43],["../../chunks/Accordion-fre84yaq.js"],["../../chunks/Accordion-xgpzh4wq.js",45],["../../chunks/Accordion-nh0cs9hq.js"],["../../chunks/Accordion-6a2hscrx.js"],["../../chunks/Accordion-n7y08rz5.js",46],["../../chunks/Accordion-59pa0677.js"],["../../chunks/Accordion-961ncx4e.js"]],0);
82
+ __chunks(import.meta.url,["rfa5chwq","pnpxcrwx","rg94gstv","z23c32jh","50yy1az9","y8p5hk56","x15y26r7","1t98py7y","m8ts96nj","8se5z2w3","mjvegqjq","8gxjy9na","2389epxb","hszzyv5p","vgkvvdvg","ewf1zen9","09qs8gt1","z5a0tx18","6wrr910w","bfzeab9x","8f0nekwe","nnv76yff","wyxmd0n0","6rrqpb2h","42jfy1a1","7tjz25jh","6zb9d92y","be2yhfqz","mnac2z83","0gfsj9qh","fzcpm4xf","2nesr9cv","h7zsx9eg","b96evb46","9w8wg9mf","pvj5npzc","w6qedeba","eqvdv7tt","61e19g3e","ys214jt5","bff0p3x4","srjya6dz","184r2r82","fre84yaq","xgpzh4wq","nh0cs9hq","6a2hscrx","n7y08rz5","59pa0677","961ncx4e"],[["./Reader.js",14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],["../../chunks/ReadiumCSS-before.css-pnpxcrwx.js"],["../../chunks/ReadiumCSS-default.css-rg94gstv.js"],["../../chunks/ReadiumCSS-after.css-z23c32jh.js"],["../../chunks/ReadiumCSS-ebpaj_fonts_patch.css-50yy1az9.js"],["../../chunks/ReadiumCSS-default.css-y8p5hk56.js"],["../../chunks/ReadiumCSS-after.css-x15y26r7.js"],["../../chunks/ReadiumCSS-before.css-1t98py7y.js"],["../../chunks/ReadiumCSS-default.css-m8ts96nj.js"],["../../chunks/ReadiumCSS-after.css-8se5z2w3.js"],["../../chunks/ReadiumCSS-before.css-mjvegqjq.js"],["../../chunks/ReadiumCSS-default.css-8gxjy9na.js"],["../../chunks/ReadiumCSS-after.css-2389epxb.js"],["../../chunks/ReadiumCSS-before.css-hszzyv5p.js"],["../../chunks/Accordion-vgkvvdvg.js"],["../../chunks/Accordion-ewf1zen9.js",17,18,23,24,25,32,34,41,44,45],["../../chunks/Accordion-09qs8gt1.js",44,45],["../../chunks/Accordion-z5a0tx18.js",16,18,42,44,45],["../../chunks/Accordion-6wrr910w.js"],["../../chunks/Accordion-bfzeab9x.js"],["../../chunks/Accordion-8f0nekwe.js",19,18,46,43,44,45],["../../chunks/Accordion-nnv76yff.js",16,18,47,42,44,45],["../../chunks/Accordion-wyxmd0n0.js",18,47,46,44,45],["../../chunks/Accordion-6rrqpb2h.js",18,20,17,21,22,24,25,47,40,44,45],["../../chunks/Accordion-42jfy1a1.js",18,48],["../../chunks/Accordion-7tjz25jh.js",16,17,18,24,42,44,45],["../../chunks/Accordion-6zb9d92y.js"],["../../chunks/Accordion-be2yhfqz.js",26,44,45],["../../chunks/Accordion-mnac2z83.js"],["../../chunks/Accordion-0gfsj9qh.js",47],["../../chunks/Accordion-fzcpm4xf.js",28,29,44,45],["../../chunks/Accordion-2nesr9cv.js",17,18],["../../chunks/Accordion-h7zsx9eg.js",26,27,17,18,30,31,22,24,33,25,49,41,44,45],["../../chunks/Accordion-b96evb46.js",20,24],["../../chunks/Accordion-9w8wg9mf.js",16,24,40,41,44,45],["../../chunks/Accordion-pvj5npzc.js",24,25,34,41,44,45],["../../chunks/Accordion-w6qedeba.js",31,24],["../../chunks/Accordion-eqvdv7tt.js"],["../../chunks/Accordion-61e19g3e.js"],["../../chunks/Accordion-ys214jt5.js"],["../../chunks/Accordion-bff0p3x4.js",19,41],["../../chunks/Accordion-srjya6dz.js",18],["../../chunks/Accordion-184r2r82.js",16,43],["../../chunks/Accordion-fre84yaq.js"],["../../chunks/Accordion-xgpzh4wq.js",45],["../../chunks/Accordion-nh0cs9hq.js"],["../../chunks/Accordion-6a2hscrx.js"],["../../chunks/Accordion-n7y08rz5.js",46],["../../chunks/Accordion-59pa0677.js"],["../../chunks/Accordion-961ncx4e.js"]],0);
83
83
 
84
84
  // node_modules/@ankhorage/reader/dist/features/reader/adapters/ReaderView.web.js
85
85
  import { jsx as _jsx2 } from "react/jsx-runtime";
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import {
3
3
  GridView2
4
- } from "../../chunks/Accordion-nxsda1my.js";
4
+ } from "../../chunks/Accordion-q8exgc3h.js";
5
5
  import {
6
6
  require_cjs
7
7
  } from "../../chunks/Accordion-xgpzh4wq.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  GridView2,
4
4
  TileGrid2
5
- } from "../../chunks/Accordion-nxsda1my.js";
5
+ } from "../../chunks/Accordion-q8exgc3h.js";
6
6
  import"../../chunks/Accordion-xgpzh4wq.js";
7
7
  export {
8
8
  GridView2 as GridView,
@@ -0,0 +1,3 @@
1
+ import type React from 'react';
2
+
3
+ export declare const TimeGrid: React.ComponentType<Record<string, unknown>>;