@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.
- package/CHANGELOG.md +12 -0
- package/README.md +3 -1
- package/dist/features/grid-view/adapters/inbound/GridView.d.ts +2 -7
- package/dist/features/grid-view/adapters/inbound/GridView.d.ts.map +1 -1
- package/dist/features/grid-view/adapters/inbound/GridView.js +309 -51
- package/dist/features/grid-view/adapters/inbound/GridView.js.map +1 -1
- package/dist/features/grid-view/adapters/inbound/TileGrid.d.ts +1 -1
- package/dist/features/grid-view/adapters/inbound/TileGrid.d.ts.map +1 -1
- package/dist/features/grid-view/adapters/inbound/TileGrid.js +11 -4
- package/dist/features/grid-view/adapters/inbound/TileGrid.js.map +1 -1
- package/dist/features/registry/ZORA_COMPONENT_REGISTRY.d.ts.map +1 -1
- package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js +2 -0
- package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js.map +1 -1
- package/dist/features/registry/componentMeta.d.ts.map +1 -1
- package/dist/features/registry/componentMeta.js +2 -0
- package/dist/features/registry/componentMeta.js.map +1 -1
- package/dist/features/time-grid/adapters/inbound/TimeGrid.d.ts +5 -0
- package/dist/features/time-grid/adapters/inbound/TimeGrid.d.ts.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGrid.js +107 -0
- package/dist/features/time-grid/adapters/inbound/TimeGrid.js.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.d.ts +9 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.d.ts.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.js +5 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.js.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.d.ts +9 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.d.ts.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.js +5 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.js.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.d.ts +9 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.d.ts.map +1 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.js +10 -0
- package/dist/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.js.map +1 -0
- package/dist/features/time-grid/application/resolveTimeGridNextFocusId.d.ts +4 -0
- package/dist/features/time-grid/application/resolveTimeGridNextFocusId.d.ts.map +1 -0
- package/dist/features/time-grid/application/resolveTimeGridNextFocusId.js +31 -0
- package/dist/features/time-grid/application/resolveTimeGridNextFocusId.js.map +1 -0
- package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.d.ts +5 -0
- package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.d.ts.map +1 -0
- package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.js +6 -0
- package/dist/features/time-grid/application/resolveTimeGridVisibleIntervals.js.map +1 -0
- package/dist/features/time-grid/meta.d.ts +11 -0
- package/dist/features/time-grid/meta.d.ts.map +1 -0
- package/dist/features/time-grid/meta.js +11 -0
- package/dist/features/time-grid/meta.js.map +1 -0
- package/dist/features/time-grid/public.d.ts +5 -0
- package/dist/features/time-grid/public.d.ts.map +1 -0
- package/dist/features/time-grid/public.js +4 -0
- package/dist/features/time-grid/public.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/grid-view.d.ts +18 -1
- package/dist/types/grid-view.d.ts.map +1 -1
- package/dist/types/grid-view.js.map +1 -1
- package/dist/types/time-grid.d.ts +30 -0
- package/dist/types/time-grid.d.ts.map +1 -0
- package/dist/types/time-grid.js +2 -0
- package/dist/types/time-grid.js.map +1 -0
- package/package.json +1 -1
- package/src/features/grid-view/adapters/inbound/GridView.interaction.test.tsx +585 -0
- package/src/features/grid-view/adapters/inbound/GridView.test.tsx +74 -0
- package/src/features/grid-view/adapters/inbound/GridView.tsx +506 -77
- package/src/features/grid-view/adapters/inbound/TileGrid.tsx +26 -3
- package/src/features/registry/ZORA_COMPONENT_REGISTRY.ts +2 -0
- package/src/features/registry/componentMeta.ts +2 -0
- package/src/features/time-grid/adapters/inbound/TimeGrid.test.tsx +158 -0
- package/src/features/time-grid/adapters/inbound/TimeGrid.tsx +197 -0
- package/src/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.native.tsx +11 -0
- package/src/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.tsx +11 -0
- package/src/features/time-grid/adapters/inbound/TimeGridKeyboardProxy.web.tsx +20 -0
- package/src/features/time-grid/application/resolveTimeGridNextFocusId.test.ts +46 -0
- package/src/features/time-grid/application/resolveTimeGridNextFocusId.ts +41 -0
- package/src/features/time-grid/application/resolveTimeGridVisibleIntervals.test.ts +33 -0
- package/src/features/time-grid/application/resolveTimeGridVisibleIntervals.ts +13 -0
- package/src/features/time-grid/meta.ts +12 -0
- package/src/features/time-grid/public.ts +4 -0
- package/src/index.ts +2 -0
- package/src/types/grid-view.ts +27 -1
- package/src/types/time-grid.ts +33 -0
- package/web-dist/chunks/{Accordion-r2w86rwv.js → Accordion-ebghcyzj.js} +125 -1
- package/web-dist/chunks/{Accordion-s3d6g59s.js → Accordion-f43jba23.js} +1 -1
- package/web-dist/chunks/Accordion-q8exgc3h.js +515 -0
- package/web-dist/chunks/{Accordion-60wn9xn9.js → Accordion-szar8dt5.js} +1 -1
- package/web-dist/components/explorer/Explorer.js +2 -2
- package/web-dist/components/file-explorer/FileExplorer.js +2 -2
- package/web-dist/components/grid-line-overlay/GridLineOverlay.js +1 -1
- package/web-dist/components/grid-ruler/GridRuler.js +1 -1
- package/web-dist/components/grid-view/GridView.js +1 -1
- package/web-dist/components/media-explorer/MediaExplorer.js +2 -2
- package/web-dist/components/reader/Reader.js +1 -1
- package/web-dist/components/spatial-grid/SpatialGrid.js +1 -1
- package/web-dist/components/tile-grid/TileGrid.js +1 -1
- package/web-dist/components/time-grid/TimeGrid.d.ts +3 -0
- package/web-dist/components/time-grid/TimeGrid.js +208 -0
- package/web-dist/components/time-grid/index.d.ts +1 -0
- package/web-dist/components/time-grid/index.js +2 -0
- package/web-dist/components/uploader/Uploader.js +2 -2
- package/web-dist/manifest.json +38 -22
- 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 };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import"../../chunks/Accordion-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
7
|
+
} from "../../chunks/Accordion-szar8dt5.js";
|
|
8
8
|
import"../../chunks/Accordion-srjya6dz.js";
|
|
9
9
|
import"../../chunks/Accordion-xgpzh4wq.js";
|
|
10
10
|
export {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import"../../chunks/Accordion-
|
|
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-
|
|
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,["
|
|
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";
|