@pk-design/react-tailwind 1.9.0 → 1.10.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/cjs/components/BottomNavigation/BottomNavigation.js +14 -5
- package/dist/cjs/components/BottomNavigation/BottomNavigation.js.map +1 -1
- package/dist/cjs/components/Drawer/Drawer.js +6 -2
- package/dist/cjs/components/Drawer/Drawer.js.map +1 -1
- package/dist/cjs/components/MobileHeader/MobileHeader.js +21 -3
- package/dist/cjs/components/MobileHeader/MobileHeader.js.map +1 -1
- package/dist/cjs/components/PullToRefresh/PullToRefresh.js +145 -57
- package/dist/cjs/components/PullToRefresh/PullToRefresh.js.map +1 -1
- package/dist/cjs/components/StickyActionBar/StickyActionBar.js +2 -2
- package/dist/cjs/components/StickyActionBar/StickyActionBar.js.map +1 -1
- package/dist/cjs/hooks/use-breakpoint.js +48 -0
- package/dist/cjs/hooks/use-breakpoint.js.map +1 -0
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/components/BottomNavigation/BottomNavigation.js +14 -5
- package/dist/es/components/BottomNavigation/BottomNavigation.js.map +1 -1
- package/dist/es/components/Drawer/Drawer.js +6 -2
- package/dist/es/components/Drawer/Drawer.js.map +1 -1
- package/dist/es/components/MobileHeader/MobileHeader.js +21 -3
- package/dist/es/components/MobileHeader/MobileHeader.js.map +1 -1
- package/dist/es/components/PullToRefresh/PullToRefresh.js +146 -58
- package/dist/es/components/PullToRefresh/PullToRefresh.js.map +1 -1
- package/dist/es/components/StickyActionBar/StickyActionBar.js +2 -2
- package/dist/es/components/StickyActionBar/StickyActionBar.js.map +1 -1
- package/dist/es/hooks/use-breakpoint.js +43 -0
- package/dist/es/hooks/use-breakpoint.js.map +1 -0
- package/dist/es/index.js +1 -0
- package/dist/es/index.js.map +1 -1
- package/dist/react-tailwind.cjs.js +229 -69
- package/dist/react-tailwind.cjs.js.map +1 -1
- package/dist/react-tailwind.es.js +227 -71
- package/dist/react-tailwind.es.js.map +1 -1
- package/dist/types/components/BottomNavigation/BottomNavigation.d.ts +1 -1
- package/dist/types/components/BottomNavigation/BottomNavigation.types.d.ts +28 -3
- package/dist/types/components/Drawer/Drawer.types.d.ts +8 -4
- package/dist/types/components/MobileHeader/MobileHeader.d.ts +1 -1
- package/dist/types/components/MobileHeader/MobileHeader.types.d.ts +13 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.d.ts +1 -1
- package/dist/types/components/PullToRefresh/PullToRefresh.types.d.ts +45 -6
- package/dist/types/components/StickyActionBar/StickyActionBar.types.d.ts +12 -0
- package/dist/types/hooks/use-breakpoint.d.ts +27 -0
- package/dist/types/hooks/use-breakpoint.test.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/test-utils/mock-viewport.d.ts +7 -0
- package/package.json +1 -1
|
@@ -341,6 +341,45 @@ var SvgX = function SvgX(props) {
|
|
|
341
341
|
})));
|
|
342
342
|
};
|
|
343
343
|
|
|
344
|
+
const BREAKPOINT_QUERIES = {
|
|
345
|
+
medium: '(min-width: 768px)',
|
|
346
|
+
expanded: '(min-width: 1024px)',
|
|
347
|
+
};
|
|
348
|
+
// jsdom and some embedded webviews have no matchMedia; treat every query as
|
|
349
|
+
// unmatched there (the compact layout) rather than throwing.
|
|
350
|
+
const hasMatchMedia = () => typeof window !== 'undefined' && typeof window.matchMedia === 'function';
|
|
351
|
+
/** Live result of a CSS media query. `false` during server rendering or without `matchMedia`. */
|
|
352
|
+
const useMediaQuery = (query) => {
|
|
353
|
+
const subscribe = React.useCallback((onChange) => {
|
|
354
|
+
if (!hasMatchMedia())
|
|
355
|
+
return () => { };
|
|
356
|
+
const list = window.matchMedia(query);
|
|
357
|
+
list.addEventListener('change', onChange);
|
|
358
|
+
return () => list.removeEventListener('change', onChange);
|
|
359
|
+
}, [query]);
|
|
360
|
+
return React.useSyncExternalStore(subscribe, () => hasMatchMedia() && window.matchMedia(query).matches, () => false);
|
|
361
|
+
};
|
|
362
|
+
/** Current layout range; `compact` during server rendering. */
|
|
363
|
+
const useBreakpoint = () => {
|
|
364
|
+
const isMedium = useMediaQuery(BREAKPOINT_QUERIES.medium);
|
|
365
|
+
const isExpanded = useMediaQuery(BREAKPOINT_QUERIES.expanded);
|
|
366
|
+
if (isExpanded)
|
|
367
|
+
return 'expanded';
|
|
368
|
+
return isMedium ? 'medium' : 'compact';
|
|
369
|
+
};
|
|
370
|
+
/** Resolves a `ResponsiveValue` for the current viewport. */
|
|
371
|
+
const useResponsiveValue = (value) => {
|
|
372
|
+
var _a, _b, _c;
|
|
373
|
+
const breakpoint = useBreakpoint();
|
|
374
|
+
if (typeof value !== 'object' || value === null || !('base' in value))
|
|
375
|
+
return value;
|
|
376
|
+
if (breakpoint === 'expanded')
|
|
377
|
+
return (_b = (_a = value.lg) !== null && _a !== void 0 ? _a : value.md) !== null && _b !== void 0 ? _b : value.base;
|
|
378
|
+
if (breakpoint === 'medium')
|
|
379
|
+
return (_c = value.md) !== null && _c !== void 0 ? _c : value.base;
|
|
380
|
+
return value.base;
|
|
381
|
+
};
|
|
382
|
+
|
|
344
383
|
const alignmentMap = {
|
|
345
384
|
center: 'items-center justify-center h-full',
|
|
346
385
|
start: 'justify-start h-full',
|
|
@@ -353,7 +392,8 @@ const panelAlignmentMap = {
|
|
|
353
392
|
start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
|
|
354
393
|
end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
|
|
355
394
|
top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
|
|
356
|
-
|
|
395
|
+
// Bottom sheets clear the home indicator on notched phones (0 elsewhere).
|
|
396
|
+
bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh] pb-[env(safe-area-inset-bottom,0px)]',
|
|
357
397
|
};
|
|
358
398
|
const panelSizeMap = {
|
|
359
399
|
xs: 'max-w-xs',
|
|
@@ -364,7 +404,9 @@ const panelSizeMap = {
|
|
|
364
404
|
'2xl': 'max-w-2xl',
|
|
365
405
|
full: 'w-full',
|
|
366
406
|
};
|
|
367
|
-
const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align = 'end', size = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
|
|
407
|
+
const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align: alignProp = 'end', size: sizeProp = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
|
|
408
|
+
const align = useResponsiveValue(alignProp);
|
|
409
|
+
const size = useResponsiveValue(sizeProp);
|
|
368
410
|
const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
|
|
369
411
|
const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
|
|
370
412
|
const [viewportHeight, setViewportHeight] = React.useState(null);
|
|
@@ -679,20 +721,23 @@ const BodyText = React.forwardRef((props, ref) => {
|
|
|
679
721
|
});
|
|
680
722
|
BodyText.displayName = 'BodyText';
|
|
681
723
|
|
|
682
|
-
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', }) {
|
|
724
|
+
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', linkAs = 'a', linkHrefProp = 'href', ariaLabel = 'Bottom Navigation', hidden = false, }) {
|
|
683
725
|
const handleTabClick = (item) => {
|
|
684
726
|
var _a;
|
|
685
727
|
if (item.disabled)
|
|
686
728
|
return;
|
|
687
729
|
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
688
|
-
onChange(item.id);
|
|
730
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(item.id);
|
|
689
731
|
};
|
|
732
|
+
// Removed from the tree, not just covered, so hidden tabs can't take focus.
|
|
733
|
+
if (hidden)
|
|
734
|
+
return null;
|
|
690
735
|
const themeStyles = {
|
|
691
736
|
light: 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',
|
|
692
737
|
dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',
|
|
693
738
|
primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',
|
|
694
739
|
}[theme];
|
|
695
|
-
return (jsxRuntime.jsx("nav", { "aria-label":
|
|
740
|
+
return (jsxRuntime.jsx("nav", { "aria-label": ariaLabel, className: buildClassName('w-full flex items-center justify-around select-none shadow-lg transition-colors relative', fixed && 'fixed bottom-0 left-0 right-0 z-40', 'pb-[env(safe-area-inset-bottom,6px)] px-2', themeStyles, containerClass), "data-testid": "bottom-navigation", children: items.map((item) => {
|
|
696
741
|
const isActive = item.id === activeId;
|
|
697
742
|
const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive);
|
|
698
743
|
const activeItemColor = {
|
|
@@ -715,11 +760,17 @@ function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels
|
|
|
715
760
|
info: 'bg-blue-500 text-white',
|
|
716
761
|
success: 'bg-emerald-500 text-white',
|
|
717
762
|
}[item.badgeVariant || 'danger'];
|
|
718
|
-
|
|
763
|
+
// A disabled item stays a button: a link can't be disabled.
|
|
764
|
+
const isLink = Boolean(item.href) && !item.disabled;
|
|
765
|
+
const ItemElement = isLink ? linkAs : 'button';
|
|
766
|
+
const elementProps = isLink
|
|
767
|
+
? { [linkHrefProp]: item.href }
|
|
768
|
+
: { type: 'button', disabled: item.disabled };
|
|
769
|
+
return (jsxRuntime.jsxs(ItemElement, { ...elementProps, onClick: () => handleTabClick(item), className: buildClassName('flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive ? activeItemColor : inactiveItemColor, itemClass), "data-testid": `bottom-nav-item-${item.id}`, "aria-current": isActive ? 'page' : undefined, "aria-label": !showLabelText && typeof item.label === 'string' ? item.label : undefined, children: [activeIndicatorStyle === 'line' && isActive && (jsxRuntime.jsx("span", { className: buildClassName('absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') })), jsxRuntime.jsxs("div", { className: buildClassName('relative inline-flex items-center justify-center transition-all duration-200', activeIndicatorStyle === 'pill'
|
|
719
770
|
? buildClassName('px-4 py-1 rounded-full', isActive
|
|
720
771
|
? pillActiveStyles
|
|
721
772
|
: 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40')
|
|
722
|
-
: 'px-1 py-0.5'), children: [jsxRuntime.jsx("span", { className: "text-xl transition-transform duration-150 group-active:scale-95", children: isActive && item.activeIcon ? item.activeIcon : item.icon }), item.badge !== undefined && item.badge !== null && (jsxRuntime.jsx("span", { className: buildClassName('absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10', badgeColor), "data-testid": `bottom-nav-badge-${item.id}`, children: item.badge }))] }), showLabelText && (jsxRuntime.jsx("span", { className: buildClassName('text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150', isActive ? 'font-bold' : 'font-medium opacity-90'), children: item.label })), activeIndicatorStyle === 'dot' && isActive && (jsxRuntime.jsx("span", { className: buildClassName('size-1.5 rounded-full mt-1 transition-all duration-200', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') }))] }, item.id));
|
|
773
|
+
: 'px-1 py-0.5'), children: [jsxRuntime.jsx("span", { className: "text-xl transition-transform duration-150 group-active:scale-95", "aria-hidden": "true", children: isActive && item.activeIcon ? item.activeIcon : item.icon }), item.badge !== undefined && item.badge !== null && (jsxRuntime.jsx("span", { className: buildClassName('absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10', badgeColor), "data-testid": `bottom-nav-badge-${item.id}`, children: item.badge }))] }), showLabelText && (jsxRuntime.jsx("span", { className: buildClassName('text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150', isActive ? 'font-bold' : 'font-medium opacity-90'), children: item.label })), activeIndicatorStyle === 'dot' && isActive && (jsxRuntime.jsx("span", { className: buildClassName('size-1.5 rounded-full mt-1 transition-all duration-200', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') }))] }, item.id));
|
|
723
774
|
}) }));
|
|
724
775
|
}
|
|
725
776
|
BottomNavigation.displayName = 'BottomNavigation';
|
|
@@ -2363,77 +2414,165 @@ function PinInput({ length = 4, value: externalValue, onChange, onComplete, mask
|
|
|
2363
2414
|
}
|
|
2364
2415
|
PinInput.displayName = 'PinInput';
|
|
2365
2416
|
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2417
|
+
// Resistance applied to the finger's travel, so the pull feels elastic.
|
|
2418
|
+
const RESISTANCE = 0.45;
|
|
2419
|
+
// Finger travel (px) before deciding whether a gesture is a pull or a sideways swipe.
|
|
2420
|
+
const AXIS_LOCK_SLOP = 8;
|
|
2421
|
+
// Overlay badge size and the gap it rests at below the container's top edge.
|
|
2422
|
+
const BADGE_SIZE = 40;
|
|
2423
|
+
const BADGE_TOP_GAP = 10;
|
|
2424
|
+
function PullArrowIcon({ progress, className }) {
|
|
2425
|
+
return (jsxRuntime.jsx("svg", { className: className, style: { transform: `rotate(${Math.min(180, progress * 180)}deg)` }, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M19 14l-7 7m0 0l-7-7m7 7V3" }) }));
|
|
2369
2426
|
}
|
|
2370
|
-
function PullToRefresh({ onRefresh, pullThreshold = 70, maxPullDistance = 120, disabled = false, refreshing: externalRefreshing, pullingContent, refreshingContent, children, className = '', contentClass = '', }) {
|
|
2427
|
+
function PullToRefresh({ onRefresh, onError, variant = 'push', pullThreshold = 70, maxPullDistance = 120, disabled = false, refreshing: externalRefreshing, pullingContent, refreshingContent, pullLabel = 'Pull down to refresh', releaseLabel = 'Release to refresh', refreshingLabel = 'Refreshing...', refreshedLabel = 'Content refreshed', children, className = '', contentClass = '', }) {
|
|
2371
2428
|
const containerRef = React.useRef(null);
|
|
2372
|
-
const startYRef = React.useRef(0);
|
|
2373
|
-
const isPullingRef = React.useRef(false);
|
|
2374
2429
|
const [pullDistance, setPullDistance] = React.useState(0);
|
|
2430
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
2375
2431
|
const [internalRefreshing, setInternalRefreshing] = React.useState(false);
|
|
2432
|
+
const [announcement, setAnnouncement] = React.useState('');
|
|
2376
2433
|
const isRefreshing = externalRefreshing !== undefined ? externalRefreshing : internalRefreshing;
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2434
|
+
// The touch listeners are attached once, natively (see below), so they read
|
|
2435
|
+
// the latest props and state through this ref instead of stale closures.
|
|
2436
|
+
const latest = React.useRef({
|
|
2437
|
+
disabled,
|
|
2438
|
+
isRefreshing,
|
|
2439
|
+
pullThreshold,
|
|
2440
|
+
maxPullDistance,
|
|
2441
|
+
onRefresh,
|
|
2442
|
+
onError,
|
|
2443
|
+
refreshedLabel,
|
|
2444
|
+
});
|
|
2445
|
+
React.useLayoutEffect(() => {
|
|
2446
|
+
latest.current = {
|
|
2447
|
+
disabled,
|
|
2448
|
+
isRefreshing,
|
|
2449
|
+
pullThreshold,
|
|
2450
|
+
maxPullDistance,
|
|
2451
|
+
onRefresh,
|
|
2452
|
+
onError,
|
|
2453
|
+
refreshedLabel,
|
|
2454
|
+
};
|
|
2455
|
+
});
|
|
2456
|
+
React.useEffect(() => {
|
|
2389
2457
|
const container = containerRef.current;
|
|
2390
|
-
if (!container
|
|
2391
|
-
return;
|
|
2392
|
-
const currentY = e.touches[0].clientY;
|
|
2393
|
-
const rawDistance = currentY - startYRef.current;
|
|
2394
|
-
if (rawDistance > 0) {
|
|
2395
|
-
// Rubber-band resistance formula
|
|
2396
|
-
const dampened = Math.min(maxPullDistance, rawDistance * 0.45);
|
|
2397
|
-
setPullDistance(dampened);
|
|
2398
|
-
if (e.cancelable) {
|
|
2399
|
-
e.preventDefault();
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
else {
|
|
2403
|
-
setPullDistance(0);
|
|
2404
|
-
}
|
|
2405
|
-
}, [disabled, isRefreshing, maxPullDistance]);
|
|
2406
|
-
const handleTouchEnd = React.useCallback(async () => {
|
|
2407
|
-
if (!isPullingRef.current || disabled || isRefreshing)
|
|
2458
|
+
if (!container)
|
|
2408
2459
|
return;
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2460
|
+
let mounted = true;
|
|
2461
|
+
let pulling = false;
|
|
2462
|
+
let axis = 'pending';
|
|
2463
|
+
let startX = 0;
|
|
2464
|
+
let startY = 0;
|
|
2465
|
+
let distance = 0;
|
|
2466
|
+
const setDistance = (next) => {
|
|
2467
|
+
distance = next;
|
|
2468
|
+
setPullDistance(next);
|
|
2469
|
+
};
|
|
2470
|
+
// Ends a gesture without refreshing: a cancelled touch, a sideways swipe,
|
|
2471
|
+
// or content that scrolled away from the top.
|
|
2472
|
+
const reset = () => {
|
|
2473
|
+
pulling = false;
|
|
2474
|
+
setIsDragging(false);
|
|
2475
|
+
setDistance(0);
|
|
2476
|
+
};
|
|
2477
|
+
const refresh = async () => {
|
|
2478
|
+
const { pullThreshold: threshold, onRefresh: run, onError: report } = latest.current;
|
|
2479
|
+
setDistance(threshold);
|
|
2412
2480
|
setInternalRefreshing(true);
|
|
2413
2481
|
try {
|
|
2414
|
-
await
|
|
2482
|
+
await run();
|
|
2483
|
+
if (mounted)
|
|
2484
|
+
setAnnouncement(latest.current.refreshedLabel);
|
|
2485
|
+
}
|
|
2486
|
+
catch (error) {
|
|
2487
|
+
report === null || report === void 0 ? void 0 : report(error);
|
|
2415
2488
|
}
|
|
2416
2489
|
finally {
|
|
2417
|
-
|
|
2418
|
-
|
|
2490
|
+
if (mounted) {
|
|
2491
|
+
setInternalRefreshing(false);
|
|
2492
|
+
setDistance(0);
|
|
2493
|
+
}
|
|
2419
2494
|
}
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2495
|
+
};
|
|
2496
|
+
const handleTouchStart = (e) => {
|
|
2497
|
+
var _a, _b;
|
|
2498
|
+
const { disabled: isDisabled, isRefreshing: busy } = latest.current;
|
|
2499
|
+
if (isDisabled || busy || container.scrollTop > 0 || e.touches.length !== 1)
|
|
2500
|
+
return;
|
|
2501
|
+
startX = (_a = e.touches[0].clientX) !== null && _a !== void 0 ? _a : 0;
|
|
2502
|
+
startY = (_b = e.touches[0].clientY) !== null && _b !== void 0 ? _b : 0;
|
|
2503
|
+
axis = 'pending';
|
|
2504
|
+
pulling = true;
|
|
2505
|
+
setAnnouncement('');
|
|
2506
|
+
setIsDragging(true);
|
|
2507
|
+
setDistance(0);
|
|
2508
|
+
};
|
|
2509
|
+
const handleTouchMove = (e) => {
|
|
2510
|
+
var _a, _b, _c, _d;
|
|
2511
|
+
if (!pulling)
|
|
2512
|
+
return;
|
|
2513
|
+
if (latest.current.disabled || latest.current.isRefreshing || container.scrollTop > 0) {
|
|
2514
|
+
reset();
|
|
2515
|
+
return;
|
|
2516
|
+
}
|
|
2517
|
+
const dx = ((_b = (_a = e.touches[0]) === null || _a === void 0 ? void 0 : _a.clientX) !== null && _b !== void 0 ? _b : 0) - startX;
|
|
2518
|
+
const dy = ((_d = (_c = e.touches[0]) === null || _c === void 0 ? void 0 : _c.clientY) !== null && _d !== void 0 ? _d : 0) - startY;
|
|
2519
|
+
if (axis === 'pending') {
|
|
2520
|
+
if (Math.abs(dx) < AXIS_LOCK_SLOP && Math.abs(dy) < AXIS_LOCK_SLOP)
|
|
2521
|
+
return;
|
|
2522
|
+
axis = dy > 0 && Math.abs(dy) > Math.abs(dx) ? 'vertical' : 'horizontal';
|
|
2523
|
+
// A sideways swipe or an upward scroll belongs to the content, not to us.
|
|
2524
|
+
if (axis === 'horizontal') {
|
|
2525
|
+
reset();
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
const next = Math.min(latest.current.maxPullDistance, Math.max(0, dy) * RESISTANCE);
|
|
2530
|
+
setDistance(next);
|
|
2531
|
+
// Needs the non-passive listener: stops the browser's own pull-to-refresh/overscroll.
|
|
2532
|
+
if (next > 0 && e.cancelable)
|
|
2533
|
+
e.preventDefault();
|
|
2534
|
+
};
|
|
2535
|
+
const handleTouchEnd = () => {
|
|
2536
|
+
if (!pulling)
|
|
2537
|
+
return;
|
|
2538
|
+
pulling = false;
|
|
2539
|
+
setIsDragging(false);
|
|
2540
|
+
if (distance >= latest.current.pullThreshold)
|
|
2541
|
+
void refresh();
|
|
2542
|
+
else
|
|
2543
|
+
setDistance(0);
|
|
2544
|
+
};
|
|
2545
|
+
// React registers touch listeners as passive, where preventDefault() is
|
|
2546
|
+
// ignored, so these are attached natively with touchmove non-passive.
|
|
2547
|
+
container.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
2548
|
+
container.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
2549
|
+
container.addEventListener('touchend', handleTouchEnd);
|
|
2550
|
+
container.addEventListener('touchcancel', reset);
|
|
2551
|
+
return () => {
|
|
2552
|
+
mounted = false;
|
|
2553
|
+
container.removeEventListener('touchstart', handleTouchStart);
|
|
2554
|
+
container.removeEventListener('touchmove', handleTouchMove);
|
|
2555
|
+
container.removeEventListener('touchend', handleTouchEnd);
|
|
2556
|
+
container.removeEventListener('touchcancel', reset);
|
|
2557
|
+
};
|
|
2558
|
+
}, []);
|
|
2425
2559
|
const progress = Math.min(1, pullDistance / pullThreshold);
|
|
2426
2560
|
const isReady = pullDistance >= pullThreshold;
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2561
|
+
const offset = isRefreshing ? pullThreshold : pullDistance;
|
|
2562
|
+
// Follow the finger exactly while dragging; animate only the settle afterwards.
|
|
2563
|
+
const motionClass = isDragging
|
|
2564
|
+
? 'transition-none'
|
|
2565
|
+
: 'transition-transform duration-200 ease-out motion-reduce:transition-none';
|
|
2566
|
+
return (jsxRuntime.jsxs("div", { ref: containerRef, className: buildClassName('relative overflow-y-auto overscroll-none', className), "data-testid": "pull-to-refresh-container", children: [jsxRuntime.jsx("span", { role: "status", "aria-live": "polite", className: "sr-only", children: isRefreshing ? refreshingLabel : announcement }), variant === 'overlay' ? (jsxRuntime.jsx("div", { className: buildClassName('pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center', motionClass), style: {
|
|
2567
|
+
transform: `translateY(${offset - BADGE_SIZE + BADGE_TOP_GAP}px)`,
|
|
2568
|
+
opacity: offset > 0 ? 1 : 0,
|
|
2569
|
+
}, "aria-hidden": "true", "data-testid": "pull-to-refresh-indicator", children: jsxRuntime.jsx("div", { className: "grid size-10 place-items-center rounded-full bg-[var(--ui-primary)] text-white shadow-lg", children: isRefreshing
|
|
2570
|
+
? (refreshingContent !== null && refreshingContent !== void 0 ? refreshingContent : jsxRuntime.jsx(Loader, { size: "xs", className: "text-white" }))
|
|
2571
|
+
: (pullingContent !== null && pullingContent !== void 0 ? pullingContent : jsxRuntime.jsx(PullArrowIcon, { progress: progress, className: "size-4" })) }) })) : (
|
|
2572
|
+
// Absolutely positioned, so the content's own translate is the only shift.
|
|
2573
|
+
jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 z-20 flex items-center justify-center overflow-hidden", style: { height: `${offset}px`, opacity: offset > 0 ? 1 : 0 }, "aria-hidden": "true", "data-testid": "pull-to-refresh-indicator", children: jsxRuntime.jsx("div", { className: "flex items-center gap-2 px-3.5 py-1.5 rounded-full bg-white dark:bg-gray-800 border border-[var(--ui-border)] shadow-md text-xs font-semibold text-gray-700 dark:text-gray-200", children: isRefreshing
|
|
2574
|
+
? (refreshingContent !== null && refreshingContent !== void 0 ? refreshingContent : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Loader, { size: "sm" }), jsxRuntime.jsx("span", { children: refreshingLabel })] })))
|
|
2575
|
+
: (pullingContent !== null && pullingContent !== void 0 ? pullingContent : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(PullArrowIcon, { progress: progress, className: "size-4 text-[var(--ui-primary)] dark:text-blue-400" }), jsxRuntime.jsx("span", { children: isReady ? releaseLabel : pullLabel })] }))) }) })), jsxRuntime.jsx("div", { className: buildClassName(variant === 'push' && motionClass, contentClass), style: variant === 'push' ? { transform: `translateY(${offset}px)` } : undefined, "data-testid": "pull-to-refresh-content", children: children })] }));
|
|
2437
2576
|
}
|
|
2438
2577
|
PullToRefresh.displayName = 'PullToRefresh';
|
|
2439
2578
|
|
|
@@ -3346,12 +3485,23 @@ function ChevronLeftIcon$1() {
|
|
|
3346
3485
|
function SearchIcon$1() {
|
|
3347
3486
|
return (jsxRuntime.jsx("svg", { className: "size-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
|
|
3348
3487
|
}
|
|
3488
|
+
function MoreIcon() {
|
|
3489
|
+
return (jsxRuntime.jsxs("svg", { className: "size-5", fill: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "5", r: "1.75" }), jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "1.75" }), jsxRuntime.jsx("circle", { cx: "12", cy: "19", r: "1.75" })] }));
|
|
3490
|
+
}
|
|
3349
3491
|
function ClearIcon() {
|
|
3350
3492
|
return (jsxRuntime.jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }));
|
|
3351
3493
|
}
|
|
3352
|
-
function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabel = 'Back', leading, actions, searchable = false, searchValue: externalSearchValue, onSearchChange, searchPlaceholder = 'Search...', sticky = true, transparent = false, bottomSlot, className = '', }) {
|
|
3494
|
+
function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabel = 'Back', leading, actions, maxVisibleActions, overflowLabel = 'More actions', trailing, searchable = false, searchValue: externalSearchValue, onSearchChange, searchPlaceholder = 'Search...', sticky = true, transparent = false, bottomSlot, className = '', }) {
|
|
3353
3495
|
const [isSearchActive, setIsSearchActive] = React.useState(false);
|
|
3354
3496
|
const [internalSearchValue, setInternalSearchValue] = React.useState('');
|
|
3497
|
+
const [isOverflowOpen, setIsOverflowOpen] = React.useState(false);
|
|
3498
|
+
// The overflow button takes one of the visible slots.
|
|
3499
|
+
const allActions = actions !== null && actions !== void 0 ? actions : [];
|
|
3500
|
+
const shouldOverflow = maxVisibleActions !== undefined && allActions.length > maxVisibleActions;
|
|
3501
|
+
const visibleActions = shouldOverflow
|
|
3502
|
+
? allActions.slice(0, Math.max(maxVisibleActions - 1, 0))
|
|
3503
|
+
: allActions;
|
|
3504
|
+
const overflowActions = shouldOverflow ? allActions.slice(visibleActions.length) : [];
|
|
3355
3505
|
const searchValue = externalSearchValue !== undefined ? externalSearchValue : internalSearchValue;
|
|
3356
3506
|
const handleSearchInput = (e) => {
|
|
3357
3507
|
const val = e.target.value;
|
|
@@ -3366,14 +3516,20 @@ function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabe
|
|
|
3366
3516
|
? 'bg-white/80 dark:bg-gray-900/80 backdrop-blur-md border-b border-[var(--ui-border-muted)]'
|
|
3367
3517
|
: 'bg-white dark:bg-gray-900 border-b border-[var(--ui-border)] shadow-xs', 'pt-[env(safe-area-inset-top,0px)]', className), "data-testid": "mobile-header", children: [jsxRuntime.jsx("div", { className: "h-14 px-3.5 flex items-center justify-between gap-3 relative", children: searchable && isSearchActive ? (jsxRuntime.jsxs("div", { className: "flex-1 flex items-center gap-2", "data-testid": "mobile-header-search-container", children: [jsxRuntime.jsxs("div", { className: "relative flex-1 flex items-center", children: [jsxRuntime.jsx("span", { className: "absolute left-3 pointer-events-none", children: jsxRuntime.jsx(SearchIcon$1, {}) }), jsxRuntime.jsx("input", { type: "text", value: searchValue, onChange: handleSearchInput, placeholder: searchPlaceholder, autoFocus: true, className: "w-full pl-9 pr-8 py-1.5 text-xs bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white rounded-full border border-transparent focus:border-blue-500 focus:outline-hidden transition-all", "data-testid": "mobile-header-search-input" }), searchValue && (jsxRuntime.jsx("button", { type: "button", onClick: handleClearSearch, "aria-label": "Clear search", className: "absolute right-2.5 p-0.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 cursor-pointer", children: jsxRuntime.jsx(ClearIcon, {}) }))] }), jsxRuntime.jsx("button", { type: "button", onClick: () => setIsSearchActive(false), className: "text-xs font-semibold text-blue-600 dark:text-blue-400 px-2 py-1.5 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-950/40 cursor-pointer", children: "Cancel" })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 z-10", children: onBack ? (jsxRuntime.jsxs("button", { type: "button", onClick: onBack, "aria-label": backLabel, className: "flex items-center gap-0.5 text-blue-600 dark:text-blue-400 hover:text-blue-700 p-1 -ml-1 rounded-xl transition-colors cursor-pointer", "data-testid": "mobile-header-back-btn", children: [jsxRuntime.jsx(ChevronLeftIcon$1, {}), jsxRuntime.jsx("span", { className: "text-xs font-semibold hidden sm:inline", children: backLabel })] })) : (leading) }), jsxRuntime.jsxs("div", { className: buildClassName('flex-1 min-w-0 px-2', titleAlign === 'center'
|
|
3368
3518
|
? 'absolute inset-x-12 text-center pointer-events-none flex flex-col items-center justify-center'
|
|
3369
|
-
: 'text-left'), children: [title && (jsxRuntime.jsx("div", { className: "text-sm font-bold text-gray-900 dark:text-white truncate pointer-events-auto", "data-testid": "mobile-header-title", children: title })), subtitle && (jsxRuntime.jsx("div", { className: "text-[11px] text-gray-500 dark:text-gray-400 truncate pointer-events-auto", "data-testid": "mobile-header-subtitle", children: subtitle }))] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 justify-end z-10", children: [searchable && (jsxRuntime.jsx("button", { type: "button", onClick: () => setIsSearchActive(true), "aria-label": "Search", className: "p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors cursor-pointer", "data-testid": "mobile-header-search-toggle", children: jsxRuntime.jsx(SearchIcon$1, {}) })),
|
|
3519
|
+
: 'text-left'), children: [title && (jsxRuntime.jsx("div", { className: "text-sm font-bold text-gray-900 dark:text-white truncate pointer-events-auto", "data-testid": "mobile-header-title", children: title })), subtitle && (jsxRuntime.jsx("div", { className: "text-[11px] text-gray-500 dark:text-gray-400 truncate pointer-events-auto", "data-testid": "mobile-header-subtitle", children: subtitle }))] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 justify-end z-10", children: [searchable && (jsxRuntime.jsx("button", { type: "button", onClick: () => setIsSearchActive(true), "aria-label": "Search", className: "p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors cursor-pointer", "data-testid": "mobile-header-search-toggle", children: jsxRuntime.jsx(SearchIcon$1, {}) })), visibleActions.map((action) => {
|
|
3370
3520
|
const badgeColor = {
|
|
3371
3521
|
danger: 'bg-red-500 text-white',
|
|
3372
3522
|
info: 'bg-blue-500 text-white',
|
|
3373
3523
|
success: 'bg-emerald-500 text-white',
|
|
3374
3524
|
}[action.badgeVariant || 'danger'];
|
|
3375
3525
|
return (jsxRuntime.jsxs("button", { type: "button", disabled: action.disabled, onClick: action.onClick, "aria-label": action.label, className: buildClassName('p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors relative cursor-pointer', action.disabled && 'opacity-40 cursor-not-allowed pointer-events-none'), "data-testid": `mobile-header-action-${action.id}`, children: [jsxRuntime.jsx("span", { className: "text-base", children: action.icon }), action.badge !== undefined && action.badge !== null && (jsxRuntime.jsx("span", { className: buildClassName('absolute top-1 right-1 min-w-[14px] h-3.5 px-0.5 rounded-full text-[9px] font-bold flex items-center justify-center shadow-xs', badgeColor), "data-testid": `mobile-header-badge-${action.id}`, children: action.badge }))] }, action.id));
|
|
3376
|
-
})
|
|
3526
|
+
}), overflowActions.length > 0 && (jsxRuntime.jsx("button", { type: "button", onClick: () => setIsOverflowOpen(true), "aria-label": overflowLabel, "aria-haspopup": "dialog", "aria-expanded": isOverflowOpen, className: "p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors cursor-pointer", "data-testid": "mobile-header-overflow", children: jsxRuntime.jsx(MoreIcon, {}) })), trailing] })] })) }), overflowActions.length > 0 && (jsxRuntime.jsx(ActionSheet, { isOpen: isOverflowOpen, onClose: () => setIsOverflowOpen(false), actions: overflowActions.map((action) => ({
|
|
3527
|
+
id: action.id,
|
|
3528
|
+
label: action.label,
|
|
3529
|
+
icon: action.icon,
|
|
3530
|
+
disabled: action.disabled,
|
|
3531
|
+
onClick: action.onClick,
|
|
3532
|
+
})) })), bottomSlot && (jsxRuntime.jsx("div", { className: "px-3 py-2 border-t border-[var(--ui-border-muted)]", "data-testid": "mobile-header-bottom-slot", children: bottomSlot }))] }));
|
|
3377
3533
|
}
|
|
3378
3534
|
MobileHeader.displayName = 'MobileHeader';
|
|
3379
3535
|
|
|
@@ -4349,14 +4505,14 @@ StatusPill.displayName = 'StatusPill';
|
|
|
4349
4505
|
|
|
4350
4506
|
const ChevronUpIcon = ({ className }) => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": "true", children: jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" }) }));
|
|
4351
4507
|
const StickyActionBar = React.forwardRef((props, ref) => {
|
|
4352
|
-
const { summaryContent, actionsContent, drawerContent, drawerTitle = 'Summary Details', position = 'fixed', containerMaxWidth = 'max-w-5xl', className, ...restProps } = props;
|
|
4508
|
+
const { summaryContent, actionsContent, drawerContent, drawerTitle = 'Summary Details', position = 'fixed', containerMaxWidth = 'max-w-5xl', safeArea = true, bottomOffset, className, style, ...restProps } = props;
|
|
4353
4509
|
const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
|
|
4354
4510
|
const positionClass = position === 'fixed'
|
|
4355
4511
|
? 'fixed bottom-0 left-0 right-0 z-30'
|
|
4356
4512
|
: position === 'sticky'
|
|
4357
4513
|
? 'sticky bottom-0 z-30'
|
|
4358
4514
|
: 'relative z-10';
|
|
4359
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { ref: ref, className: buildClassName(positionClass, 'border-t border-[var(--ui-border)] bg-white/90 p-3.5 backdrop-blur-md shadow-lg dark:bg-gray-900/90 transition-all', className), "data-testid": "sticky-action-bar", ...restProps, children: jsxRuntime.jsxs("div", { className: buildClassName('mx-auto flex items-center justify-between gap-3', containerMaxWidth), children: [summaryContent && (jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: drawerContent ? (jsxRuntime.jsxs("button", { type: "button", onClick: () => setIsDrawerOpen(true), className: "flex items-center gap-2 text-left transition-opacity hover:opacity-80 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)] rounded-lg p-1 -m-1", "aria-label": "Expand summary details", "data-testid": "summary-trigger", children: [jsxRuntime.jsx("div", { children: summaryContent }), jsxRuntime.jsx(ChevronUpIcon, { className: "size-4 text-[var(--ui-primary)] dark:text-blue-400 shrink-0" })] })) : (jsxRuntime.jsx("div", { children: summaryContent })) })), actionsContent && (jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0 ml-auto", "data-testid": "actions-stack", children: actionsContent }))] }) }), drawerContent && (jsxRuntime.jsx(Drawer, { isOpen: isDrawerOpen, onClose: () => setIsDrawerOpen(false), align: "bottom", size: "full", title: drawerTitle, showBackButton: true, contentClass: "px-4 pb-6 max-h-[calc(100svh-6rem)] overflow-y-auto", children: drawerContent }))] }));
|
|
4515
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { ref: ref, className: buildClassName(positionClass, 'border-t border-[var(--ui-border)] bg-white/90 p-3.5 backdrop-blur-md shadow-lg dark:bg-gray-900/90 transition-all', safeArea && 'pb-[calc(0.875rem+env(safe-area-inset-bottom,0px))]', className), style: bottomOffset && position !== 'relative' ? { bottom: bottomOffset, ...style } : style, "data-testid": "sticky-action-bar", ...restProps, children: jsxRuntime.jsxs("div", { className: buildClassName('mx-auto flex items-center justify-between gap-3', containerMaxWidth), children: [summaryContent && (jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: drawerContent ? (jsxRuntime.jsxs("button", { type: "button", onClick: () => setIsDrawerOpen(true), className: "flex items-center gap-2 text-left transition-opacity hover:opacity-80 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)] rounded-lg p-1 -m-1", "aria-label": "Expand summary details", "data-testid": "summary-trigger", children: [jsxRuntime.jsx("div", { children: summaryContent }), jsxRuntime.jsx(ChevronUpIcon, { className: "size-4 text-[var(--ui-primary)] dark:text-blue-400 shrink-0" })] })) : (jsxRuntime.jsx("div", { children: summaryContent })) })), actionsContent && (jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0 ml-auto", "data-testid": "actions-stack", children: actionsContent }))] }) }), drawerContent && (jsxRuntime.jsx(Drawer, { isOpen: isDrawerOpen, onClose: () => setIsDrawerOpen(false), align: "bottom", size: "full", title: drawerTitle, showBackButton: true, contentClass: "px-4 pb-6 max-h-[calc(100svh-6rem)] overflow-y-auto", children: drawerContent }))] }));
|
|
4360
4516
|
});
|
|
4361
4517
|
StickyActionBar.displayName = 'StickyActionBar';
|
|
4362
4518
|
|
|
@@ -4952,6 +5108,7 @@ const useIsTabletOrMobile = () => {
|
|
|
4952
5108
|
exports.Accordion = Accordion;
|
|
4953
5109
|
exports.ActionSheet = ActionSheet;
|
|
4954
5110
|
exports.Alert = Alert;
|
|
5111
|
+
exports.BREAKPOINT_QUERIES = BREAKPOINT_QUERIES;
|
|
4955
5112
|
exports.Badge = Badge;
|
|
4956
5113
|
exports.Banner = Banner;
|
|
4957
5114
|
exports.BodyText = BodyText;
|
|
@@ -5032,12 +5189,15 @@ exports.isArray = isArray;
|
|
|
5032
5189
|
exports.isEmpty = isEmpty;
|
|
5033
5190
|
exports.nextSortDirection = nextSortDirection;
|
|
5034
5191
|
exports.updateSortQuery = updateSortQuery;
|
|
5192
|
+
exports.useBreakpoint = useBreakpoint;
|
|
5035
5193
|
exports.useDebounce = useDebounce;
|
|
5036
5194
|
exports.useDebounceFn = useDebounceFn;
|
|
5037
5195
|
exports.useIsMobile = useIsMobile;
|
|
5038
5196
|
exports.useIsTablet = useIsTablet;
|
|
5039
5197
|
exports.useIsTabletOrMobile = useIsTabletOrMobile;
|
|
5198
|
+
exports.useMediaQuery = useMediaQuery;
|
|
5040
5199
|
exports.usePagination = usePagination;
|
|
5200
|
+
exports.useResponsiveValue = useResponsiveValue;
|
|
5041
5201
|
exports.useRowSelection = useRowSelection;
|
|
5042
5202
|
exports.useToast = useToast;
|
|
5043
5203
|
//# sourceMappingURL=react-tailwind.cjs.js.map
|