@almadar/ui 2.5.2 → 2.7.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/dist/{chunk-2UMN2BLO.js → chunk-2QM732NQ.js} +47 -4
- package/dist/{chunk-45CTDYBT.js → chunk-RPYMP7ZC.js} +137 -1
- package/dist/{chunk-AL6BLHMG.js → chunk-VJP2HCLY.js} +2952 -461
- package/dist/{chunk-GOZKH7QW.js → chunk-WGJIL4YR.js} +267 -2
- package/dist/components/index.d.ts +527 -68
- package/dist/components/index.js +226 -321
- package/dist/hooks/index.d.ts +133 -3
- package/dist/hooks/index.js +3 -3
- package/dist/lib/index.d.ts +33 -2
- package/dist/lib/index.js +1 -2
- package/dist/providers/index.js +4 -5
- package/package.json +1 -1
- package/dist/chunk-KKCVDUK7.js +0 -104
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
import { useEventBus } from './chunk-YXZM3WCF.js';
|
|
2
2
|
import { en_default } from './chunk-TSETXL2E.js';
|
|
3
|
-
import React2, { createContext,
|
|
3
|
+
import React2, { createContext, useRef, useEffect, useCallback, useContext, useState, useMemo } from 'react';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
+
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
7
|
+
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
8
|
+
const observerRef = useRef(null);
|
|
9
|
+
const callbackRef = useRef(onLoadMore);
|
|
10
|
+
callbackRef.current = onLoadMore;
|
|
11
|
+
const hasMoreRef = useRef(hasMore);
|
|
12
|
+
hasMoreRef.current = hasMore;
|
|
13
|
+
const isLoadingRef = useRef(isLoading);
|
|
14
|
+
isLoadingRef.current = isLoading;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
return () => {
|
|
17
|
+
observerRef.current?.disconnect();
|
|
18
|
+
};
|
|
19
|
+
}, []);
|
|
20
|
+
const sentinelRef = useCallback((node) => {
|
|
21
|
+
observerRef.current?.disconnect();
|
|
22
|
+
if (!node) return;
|
|
23
|
+
observerRef.current = new IntersectionObserver(
|
|
24
|
+
(entries) => {
|
|
25
|
+
const entry = entries[0];
|
|
26
|
+
if (entry.isIntersecting && hasMoreRef.current && !isLoadingRef.current) {
|
|
27
|
+
callbackRef.current();
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{ rootMargin }
|
|
31
|
+
);
|
|
32
|
+
observerRef.current.observe(node);
|
|
33
|
+
}, [rootMargin]);
|
|
34
|
+
return { sentinelRef };
|
|
35
|
+
}
|
|
6
36
|
var { $meta: _meta, ...coreMessages } = en_default;
|
|
7
37
|
var coreLocale = coreMessages;
|
|
8
38
|
var I18nContext = createContext({
|
|
@@ -93,6 +123,241 @@ function parseQueryBinding(binding) {
|
|
|
93
123
|
field: parts.length > 1 ? parts.slice(1).join(".") : void 0
|
|
94
124
|
};
|
|
95
125
|
}
|
|
126
|
+
function useLongPress(onLongPress, options = {}) {
|
|
127
|
+
const { duration = 500, moveThreshold = 10 } = options;
|
|
128
|
+
const timerRef = useRef(null);
|
|
129
|
+
const startPos = useRef({ x: 0, y: 0 });
|
|
130
|
+
const isPressedRef = useRef(false);
|
|
131
|
+
const firedRef = useRef(false);
|
|
132
|
+
const cancel = useCallback(() => {
|
|
133
|
+
if (timerRef.current) {
|
|
134
|
+
clearTimeout(timerRef.current);
|
|
135
|
+
timerRef.current = null;
|
|
136
|
+
}
|
|
137
|
+
isPressedRef.current = false;
|
|
138
|
+
}, []);
|
|
139
|
+
const onPointerDown = useCallback((e) => {
|
|
140
|
+
firedRef.current = false;
|
|
141
|
+
startPos.current = { x: e.clientX, y: e.clientY };
|
|
142
|
+
isPressedRef.current = true;
|
|
143
|
+
timerRef.current = setTimeout(() => {
|
|
144
|
+
firedRef.current = true;
|
|
145
|
+
isPressedRef.current = false;
|
|
146
|
+
onLongPress();
|
|
147
|
+
}, duration);
|
|
148
|
+
}, [duration, onLongPress]);
|
|
149
|
+
const onPointerMove = useCallback((e) => {
|
|
150
|
+
if (!isPressedRef.current) return;
|
|
151
|
+
const dx = e.clientX - startPos.current.x;
|
|
152
|
+
const dy = e.clientY - startPos.current.y;
|
|
153
|
+
if (Math.sqrt(dx * dx + dy * dy) > moveThreshold) {
|
|
154
|
+
cancel();
|
|
155
|
+
}
|
|
156
|
+
}, [moveThreshold, cancel]);
|
|
157
|
+
const onPointerUp = useCallback(() => {
|
|
158
|
+
cancel();
|
|
159
|
+
}, [cancel]);
|
|
160
|
+
const onPointerCancel = useCallback(() => {
|
|
161
|
+
cancel();
|
|
162
|
+
}, [cancel]);
|
|
163
|
+
return {
|
|
164
|
+
onPointerDown,
|
|
165
|
+
onPointerMove,
|
|
166
|
+
onPointerUp,
|
|
167
|
+
onPointerCancel,
|
|
168
|
+
isPressed: isPressedRef.current
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function useSwipeGesture(callbacks, options = {}) {
|
|
172
|
+
const { threshold = 50, velocityThreshold = 0.3, preventDefault = false } = options;
|
|
173
|
+
const startX = useRef(0);
|
|
174
|
+
const startY = useRef(0);
|
|
175
|
+
const startTime = useRef(0);
|
|
176
|
+
const currentX = useRef(0);
|
|
177
|
+
const tracking = useRef(false);
|
|
178
|
+
const offsetXRef = useRef(0);
|
|
179
|
+
const isSwipingRef = useRef(false);
|
|
180
|
+
const onPointerDown = useCallback((e) => {
|
|
181
|
+
startX.current = e.clientX;
|
|
182
|
+
startY.current = e.clientY;
|
|
183
|
+
currentX.current = e.clientX;
|
|
184
|
+
startTime.current = Date.now();
|
|
185
|
+
tracking.current = true;
|
|
186
|
+
isSwipingRef.current = false;
|
|
187
|
+
offsetXRef.current = 0;
|
|
188
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
189
|
+
}, []);
|
|
190
|
+
const onPointerMove = useCallback((e) => {
|
|
191
|
+
if (!tracking.current) return;
|
|
192
|
+
if (preventDefault) e.preventDefault();
|
|
193
|
+
currentX.current = e.clientX;
|
|
194
|
+
const dx = e.clientX - startX.current;
|
|
195
|
+
const dy = e.clientY - startY.current;
|
|
196
|
+
if (Math.abs(dx) > 10 && Math.abs(dx) > Math.abs(dy)) {
|
|
197
|
+
isSwipingRef.current = true;
|
|
198
|
+
offsetXRef.current = dx;
|
|
199
|
+
}
|
|
200
|
+
}, [preventDefault]);
|
|
201
|
+
const onPointerUp = useCallback((e) => {
|
|
202
|
+
if (!tracking.current) return;
|
|
203
|
+
tracking.current = false;
|
|
204
|
+
const dx = e.clientX - startX.current;
|
|
205
|
+
const dy = e.clientY - startY.current;
|
|
206
|
+
const elapsed = Date.now() - startTime.current;
|
|
207
|
+
const velocity = Math.abs(dx) / Math.max(elapsed, 1);
|
|
208
|
+
offsetXRef.current = 0;
|
|
209
|
+
isSwipingRef.current = false;
|
|
210
|
+
if (Math.abs(dx) < threshold && velocity < velocityThreshold) return;
|
|
211
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
212
|
+
if (dx < -threshold) callbacks.onSwipeLeft?.();
|
|
213
|
+
else if (dx > threshold) callbacks.onSwipeRight?.();
|
|
214
|
+
} else {
|
|
215
|
+
if (dy < -threshold) callbacks.onSwipeUp?.();
|
|
216
|
+
else if (dy > threshold) callbacks.onSwipeDown?.();
|
|
217
|
+
}
|
|
218
|
+
}, [threshold, velocityThreshold, callbacks]);
|
|
219
|
+
const onPointerCancel = useCallback(() => {
|
|
220
|
+
tracking.current = false;
|
|
221
|
+
offsetXRef.current = 0;
|
|
222
|
+
isSwipingRef.current = false;
|
|
223
|
+
}, []);
|
|
224
|
+
return {
|
|
225
|
+
onPointerDown,
|
|
226
|
+
onPointerMove,
|
|
227
|
+
onPointerUp,
|
|
228
|
+
onPointerCancel,
|
|
229
|
+
offsetX: offsetXRef.current,
|
|
230
|
+
isSwiping: isSwipingRef.current
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function useDragReorder(initialItems, onReorder) {
|
|
234
|
+
const [items, setItems] = useState(initialItems);
|
|
235
|
+
const [dragIndex, setDragIndex] = useState(-1);
|
|
236
|
+
const [dragOverIndex, setDragOverIndex] = useState(-1);
|
|
237
|
+
const itemsRef = useRef(initialItems);
|
|
238
|
+
if (initialItems !== itemsRef.current) {
|
|
239
|
+
itemsRef.current = initialItems;
|
|
240
|
+
setItems(initialItems);
|
|
241
|
+
}
|
|
242
|
+
const isDragging = dragIndex >= 0;
|
|
243
|
+
const handleDragStart = useCallback((index) => (e) => {
|
|
244
|
+
e.preventDefault();
|
|
245
|
+
setDragIndex(index);
|
|
246
|
+
setDragOverIndex(index);
|
|
247
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
248
|
+
}, []);
|
|
249
|
+
const handleDragMove = useCallback((index) => (e) => {
|
|
250
|
+
if (dragIndex < 0) return;
|
|
251
|
+
const target = document.elementFromPoint(e.clientX, e.clientY);
|
|
252
|
+
if (!target) return;
|
|
253
|
+
let el = target;
|
|
254
|
+
while (el && !el.dataset.dragIndex) {
|
|
255
|
+
el = el.parentElement;
|
|
256
|
+
}
|
|
257
|
+
if (el?.dataset.dragIndex) {
|
|
258
|
+
const overIndex = parseInt(el.dataset.dragIndex, 10);
|
|
259
|
+
if (!isNaN(overIndex) && overIndex !== dragOverIndex) {
|
|
260
|
+
setDragOverIndex(overIndex);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}, [dragIndex, dragOverIndex]);
|
|
264
|
+
const handleDragEnd = useCallback(() => {
|
|
265
|
+
if (dragIndex >= 0 && dragOverIndex >= 0 && dragIndex !== dragOverIndex) {
|
|
266
|
+
const newItems = [...items];
|
|
267
|
+
const [movedItem] = newItems.splice(dragIndex, 1);
|
|
268
|
+
newItems.splice(dragOverIndex, 0, movedItem);
|
|
269
|
+
setItems(newItems);
|
|
270
|
+
onReorder(dragIndex, dragOverIndex, items[dragIndex]);
|
|
271
|
+
}
|
|
272
|
+
setDragIndex(-1);
|
|
273
|
+
setDragOverIndex(-1);
|
|
274
|
+
}, [dragIndex, dragOverIndex, items, onReorder]);
|
|
275
|
+
const getDragHandleProps = useCallback((index) => ({
|
|
276
|
+
onPointerDown: handleDragStart(index),
|
|
277
|
+
style: { cursor: "grab", touchAction: "none" },
|
|
278
|
+
"aria-grabbed": dragIndex === index,
|
|
279
|
+
role: "button"
|
|
280
|
+
}), [handleDragStart, dragIndex]);
|
|
281
|
+
const getItemProps = useCallback((index) => ({
|
|
282
|
+
onPointerMove: handleDragMove(index),
|
|
283
|
+
onPointerUp: handleDragEnd,
|
|
284
|
+
"aria-dropeffect": "move",
|
|
285
|
+
"data-drag-index": String(index),
|
|
286
|
+
style: {
|
|
287
|
+
opacity: dragIndex === index ? 0.5 : 1,
|
|
288
|
+
transition: isDragging ? "transform 150ms ease" : void 0,
|
|
289
|
+
transform: isDragging && dragOverIndex >= 0 ? index === dragIndex ? "scale(1.02)" : index > dragIndex && index <= dragOverIndex ? "translateY(-100%)" : index < dragIndex && index >= dragOverIndex ? "translateY(100%)" : void 0 : void 0
|
|
290
|
+
}
|
|
291
|
+
}), [handleDragMove, handleDragEnd, dragIndex, dragOverIndex, isDragging]);
|
|
292
|
+
return {
|
|
293
|
+
items,
|
|
294
|
+
dragIndex,
|
|
295
|
+
dragOverIndex,
|
|
296
|
+
isDragging,
|
|
297
|
+
getDragHandleProps,
|
|
298
|
+
getItemProps
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function usePullToRefresh(onRefresh, options = {}) {
|
|
302
|
+
const { threshold = 60, maxPull = 120 } = options;
|
|
303
|
+
const [pullDistance, setPullDistance] = useState(0);
|
|
304
|
+
const [isPulling, setIsPulling] = useState(false);
|
|
305
|
+
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
306
|
+
const startY = useRef(0);
|
|
307
|
+
const scrollTopRef = useRef(0);
|
|
308
|
+
const onTouchStart = useCallback((e) => {
|
|
309
|
+
const container = e.currentTarget;
|
|
310
|
+
scrollTopRef.current = container.scrollTop;
|
|
311
|
+
if (scrollTopRef.current <= 0) {
|
|
312
|
+
startY.current = e.touches[0].clientY;
|
|
313
|
+
setIsPulling(true);
|
|
314
|
+
}
|
|
315
|
+
}, []);
|
|
316
|
+
const onTouchMove = useCallback((e) => {
|
|
317
|
+
if (!isPulling || isRefreshing) return;
|
|
318
|
+
const container = e.currentTarget;
|
|
319
|
+
if (container.scrollTop > 0) {
|
|
320
|
+
setPullDistance(0);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const dy = e.touches[0].clientY - startY.current;
|
|
324
|
+
if (dy > 0) {
|
|
325
|
+
const distance = Math.min(dy * 0.5, maxPull);
|
|
326
|
+
setPullDistance(distance);
|
|
327
|
+
}
|
|
328
|
+
}, [isPulling, isRefreshing, maxPull]);
|
|
329
|
+
const onTouchEnd = useCallback(() => {
|
|
330
|
+
if (!isPulling) return;
|
|
331
|
+
setIsPulling(false);
|
|
332
|
+
if (pullDistance >= threshold && !isRefreshing) {
|
|
333
|
+
setIsRefreshing(true);
|
|
334
|
+
setPullDistance(threshold);
|
|
335
|
+
onRefresh();
|
|
336
|
+
} else {
|
|
337
|
+
setPullDistance(0);
|
|
338
|
+
}
|
|
339
|
+
}, [isPulling, pullDistance, threshold, isRefreshing, onRefresh]);
|
|
340
|
+
const endRefresh = useCallback(() => {
|
|
341
|
+
setIsRefreshing(false);
|
|
342
|
+
setPullDistance(0);
|
|
343
|
+
}, []);
|
|
344
|
+
const containerProps = {
|
|
345
|
+
onTouchStart,
|
|
346
|
+
onTouchMove,
|
|
347
|
+
onTouchEnd,
|
|
348
|
+
style: {
|
|
349
|
+
transform: pullDistance > 0 ? `translateY(${pullDistance}px)` : void 0,
|
|
350
|
+
transition: isPulling ? "none" : "transform 300ms ease-out"
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
return {
|
|
354
|
+
pullDistance,
|
|
355
|
+
isPulling,
|
|
356
|
+
isRefreshing,
|
|
357
|
+
containerProps,
|
|
358
|
+
endRefresh
|
|
359
|
+
};
|
|
360
|
+
}
|
|
96
361
|
var SelectionContext = createContext(null);
|
|
97
362
|
var defaultCompareEntities = (a, b) => {
|
|
98
363
|
if (a === b) return true;
|
|
@@ -383,4 +648,4 @@ function useEntitySuspense(entity, id) {
|
|
|
383
648
|
} };
|
|
384
649
|
}
|
|
385
650
|
|
|
386
|
-
export { EntityDataProvider, I18nProvider, SelectionContext, SelectionProvider, createTranslate, entityDataKeys, parseQueryBinding, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useQuerySingleton, useSelection, useSelectionOptional, useTranslate };
|
|
651
|
+
export { EntityDataProvider, I18nProvider, SelectionContext, SelectionProvider, createTranslate, entityDataKeys, parseQueryBinding, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSelection, useSelectionOptional, useSwipeGesture, useTranslate };
|