@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import React__default, { useId, useMemo, useState, forwardRef, useEffect, Children, isValidElement, cloneElement, useRef, useImperativeHandle,
|
|
3
|
+
import React__default, { useId, useMemo, useState, forwardRef, useEffect, useCallback, useSyncExternalStore, Children, isValidElement, cloneElement, useRef, useImperativeHandle, Fragment as Fragment$1, createContext, useContext, useLayoutEffect } from 'react';
|
|
4
4
|
import { twMerge } from 'tailwind-merge';
|
|
5
5
|
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle, Menu, MenuButton, MenuItems, MenuItem, Combobox, ComboboxInput, ComboboxButton, ComboboxOptions, ComboboxOption, TabGroup, TabList, Tab, TabPanels, TabPanel, Transition } from '@headlessui/react';
|
|
6
6
|
import { FixedSizeList } from 'react-window';
|
|
@@ -321,6 +321,45 @@ var SvgX = function SvgX(props) {
|
|
|
321
321
|
})));
|
|
322
322
|
};
|
|
323
323
|
|
|
324
|
+
const BREAKPOINT_QUERIES = {
|
|
325
|
+
medium: '(min-width: 768px)',
|
|
326
|
+
expanded: '(min-width: 1024px)',
|
|
327
|
+
};
|
|
328
|
+
// jsdom and some embedded webviews have no matchMedia; treat every query as
|
|
329
|
+
// unmatched there (the compact layout) rather than throwing.
|
|
330
|
+
const hasMatchMedia = () => typeof window !== 'undefined' && typeof window.matchMedia === 'function';
|
|
331
|
+
/** Live result of a CSS media query. `false` during server rendering or without `matchMedia`. */
|
|
332
|
+
const useMediaQuery = (query) => {
|
|
333
|
+
const subscribe = useCallback((onChange) => {
|
|
334
|
+
if (!hasMatchMedia())
|
|
335
|
+
return () => { };
|
|
336
|
+
const list = window.matchMedia(query);
|
|
337
|
+
list.addEventListener('change', onChange);
|
|
338
|
+
return () => list.removeEventListener('change', onChange);
|
|
339
|
+
}, [query]);
|
|
340
|
+
return useSyncExternalStore(subscribe, () => hasMatchMedia() && window.matchMedia(query).matches, () => false);
|
|
341
|
+
};
|
|
342
|
+
/** Current layout range; `compact` during server rendering. */
|
|
343
|
+
const useBreakpoint = () => {
|
|
344
|
+
const isMedium = useMediaQuery(BREAKPOINT_QUERIES.medium);
|
|
345
|
+
const isExpanded = useMediaQuery(BREAKPOINT_QUERIES.expanded);
|
|
346
|
+
if (isExpanded)
|
|
347
|
+
return 'expanded';
|
|
348
|
+
return isMedium ? 'medium' : 'compact';
|
|
349
|
+
};
|
|
350
|
+
/** Resolves a `ResponsiveValue` for the current viewport. */
|
|
351
|
+
const useResponsiveValue = (value) => {
|
|
352
|
+
var _a, _b, _c;
|
|
353
|
+
const breakpoint = useBreakpoint();
|
|
354
|
+
if (typeof value !== 'object' || value === null || !('base' in value))
|
|
355
|
+
return value;
|
|
356
|
+
if (breakpoint === 'expanded')
|
|
357
|
+
return (_b = (_a = value.lg) !== null && _a !== void 0 ? _a : value.md) !== null && _b !== void 0 ? _b : value.base;
|
|
358
|
+
if (breakpoint === 'medium')
|
|
359
|
+
return (_c = value.md) !== null && _c !== void 0 ? _c : value.base;
|
|
360
|
+
return value.base;
|
|
361
|
+
};
|
|
362
|
+
|
|
324
363
|
const alignmentMap = {
|
|
325
364
|
center: 'items-center justify-center h-full',
|
|
326
365
|
start: 'justify-start h-full',
|
|
@@ -333,7 +372,8 @@ const panelAlignmentMap = {
|
|
|
333
372
|
start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
|
|
334
373
|
end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
|
|
335
374
|
top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
|
|
336
|
-
|
|
375
|
+
// Bottom sheets clear the home indicator on notched phones (0 elsewhere).
|
|
376
|
+
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)]',
|
|
337
377
|
};
|
|
338
378
|
const panelSizeMap = {
|
|
339
379
|
xs: 'max-w-xs',
|
|
@@ -344,7 +384,9 @@ const panelSizeMap = {
|
|
|
344
384
|
'2xl': 'max-w-2xl',
|
|
345
385
|
full: 'w-full',
|
|
346
386
|
};
|
|
347
|
-
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, }) => {
|
|
387
|
+
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, }) => {
|
|
388
|
+
const align = useResponsiveValue(alignProp);
|
|
389
|
+
const size = useResponsiveValue(sizeProp);
|
|
348
390
|
const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
|
|
349
391
|
const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
|
|
350
392
|
const [viewportHeight, setViewportHeight] = React__default.useState(null);
|
|
@@ -659,20 +701,23 @@ const BodyText = forwardRef((props, ref) => {
|
|
|
659
701
|
});
|
|
660
702
|
BodyText.displayName = 'BodyText';
|
|
661
703
|
|
|
662
|
-
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', }) {
|
|
704
|
+
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', linkAs = 'a', linkHrefProp = 'href', ariaLabel = 'Bottom Navigation', hidden = false, }) {
|
|
663
705
|
const handleTabClick = (item) => {
|
|
664
706
|
var _a;
|
|
665
707
|
if (item.disabled)
|
|
666
708
|
return;
|
|
667
709
|
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
668
|
-
onChange(item.id);
|
|
710
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(item.id);
|
|
669
711
|
};
|
|
712
|
+
// Removed from the tree, not just covered, so hidden tabs can't take focus.
|
|
713
|
+
if (hidden)
|
|
714
|
+
return null;
|
|
670
715
|
const themeStyles = {
|
|
671
716
|
light: 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',
|
|
672
717
|
dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',
|
|
673
718
|
primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',
|
|
674
719
|
}[theme];
|
|
675
|
-
return (jsx("nav", { "aria-label":
|
|
720
|
+
return (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) => {
|
|
676
721
|
const isActive = item.id === activeId;
|
|
677
722
|
const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive);
|
|
678
723
|
const activeItemColor = {
|
|
@@ -695,11 +740,17 @@ function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels
|
|
|
695
740
|
info: 'bg-blue-500 text-white',
|
|
696
741
|
success: 'bg-emerald-500 text-white',
|
|
697
742
|
}[item.badgeVariant || 'danger'];
|
|
698
|
-
|
|
743
|
+
// A disabled item stays a button: a link can't be disabled.
|
|
744
|
+
const isLink = Boolean(item.href) && !item.disabled;
|
|
745
|
+
const ItemElement = isLink ? linkAs : 'button';
|
|
746
|
+
const elementProps = isLink
|
|
747
|
+
? { [linkHrefProp]: item.href }
|
|
748
|
+
: { type: 'button', disabled: item.disabled };
|
|
749
|
+
return (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 && (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') })), jsxs("div", { className: buildClassName('relative inline-flex items-center justify-center transition-all duration-200', activeIndicatorStyle === 'pill'
|
|
699
750
|
? buildClassName('px-4 py-1 rounded-full', isActive
|
|
700
751
|
? pillActiveStyles
|
|
701
752
|
: 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40')
|
|
702
|
-
: 'px-1 py-0.5'), children: [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 && (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 && (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 && (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));
|
|
753
|
+
: 'px-1 py-0.5'), children: [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 && (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 && (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 && (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));
|
|
703
754
|
}) }));
|
|
704
755
|
}
|
|
705
756
|
BottomNavigation.displayName = 'BottomNavigation';
|
|
@@ -2343,77 +2394,165 @@ function PinInput({ length = 4, value: externalValue, onChange, onComplete, mask
|
|
|
2343
2394
|
}
|
|
2344
2395
|
PinInput.displayName = 'PinInput';
|
|
2345
2396
|
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2397
|
+
// Resistance applied to the finger's travel, so the pull feels elastic.
|
|
2398
|
+
const RESISTANCE = 0.45;
|
|
2399
|
+
// Finger travel (px) before deciding whether a gesture is a pull or a sideways swipe.
|
|
2400
|
+
const AXIS_LOCK_SLOP = 8;
|
|
2401
|
+
// Overlay badge size and the gap it rests at below the container's top edge.
|
|
2402
|
+
const BADGE_SIZE = 40;
|
|
2403
|
+
const BADGE_TOP_GAP = 10;
|
|
2404
|
+
function PullArrowIcon({ progress, className }) {
|
|
2405
|
+
return (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: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M19 14l-7 7m0 0l-7-7m7 7V3" }) }));
|
|
2349
2406
|
}
|
|
2350
|
-
function PullToRefresh({ onRefresh, pullThreshold = 70, maxPullDistance = 120, disabled = false, refreshing: externalRefreshing, pullingContent, refreshingContent, children, className = '', contentClass = '', }) {
|
|
2407
|
+
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 = '', }) {
|
|
2351
2408
|
const containerRef = useRef(null);
|
|
2352
|
-
const startYRef = useRef(0);
|
|
2353
|
-
const isPullingRef = useRef(false);
|
|
2354
2409
|
const [pullDistance, setPullDistance] = useState(0);
|
|
2410
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
2355
2411
|
const [internalRefreshing, setInternalRefreshing] = useState(false);
|
|
2412
|
+
const [announcement, setAnnouncement] = useState('');
|
|
2356
2413
|
const isRefreshing = externalRefreshing !== undefined ? externalRefreshing : internalRefreshing;
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2414
|
+
// The touch listeners are attached once, natively (see below), so they read
|
|
2415
|
+
// the latest props and state through this ref instead of stale closures.
|
|
2416
|
+
const latest = useRef({
|
|
2417
|
+
disabled,
|
|
2418
|
+
isRefreshing,
|
|
2419
|
+
pullThreshold,
|
|
2420
|
+
maxPullDistance,
|
|
2421
|
+
onRefresh,
|
|
2422
|
+
onError,
|
|
2423
|
+
refreshedLabel,
|
|
2424
|
+
});
|
|
2425
|
+
useLayoutEffect(() => {
|
|
2426
|
+
latest.current = {
|
|
2427
|
+
disabled,
|
|
2428
|
+
isRefreshing,
|
|
2429
|
+
pullThreshold,
|
|
2430
|
+
maxPullDistance,
|
|
2431
|
+
onRefresh,
|
|
2432
|
+
onError,
|
|
2433
|
+
refreshedLabel,
|
|
2434
|
+
};
|
|
2435
|
+
});
|
|
2436
|
+
useEffect(() => {
|
|
2369
2437
|
const container = containerRef.current;
|
|
2370
|
-
if (!container
|
|
2371
|
-
return;
|
|
2372
|
-
const currentY = e.touches[0].clientY;
|
|
2373
|
-
const rawDistance = currentY - startYRef.current;
|
|
2374
|
-
if (rawDistance > 0) {
|
|
2375
|
-
// Rubber-band resistance formula
|
|
2376
|
-
const dampened = Math.min(maxPullDistance, rawDistance * 0.45);
|
|
2377
|
-
setPullDistance(dampened);
|
|
2378
|
-
if (e.cancelable) {
|
|
2379
|
-
e.preventDefault();
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
else {
|
|
2383
|
-
setPullDistance(0);
|
|
2384
|
-
}
|
|
2385
|
-
}, [disabled, isRefreshing, maxPullDistance]);
|
|
2386
|
-
const handleTouchEnd = useCallback(async () => {
|
|
2387
|
-
if (!isPullingRef.current || disabled || isRefreshing)
|
|
2438
|
+
if (!container)
|
|
2388
2439
|
return;
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2440
|
+
let mounted = true;
|
|
2441
|
+
let pulling = false;
|
|
2442
|
+
let axis = 'pending';
|
|
2443
|
+
let startX = 0;
|
|
2444
|
+
let startY = 0;
|
|
2445
|
+
let distance = 0;
|
|
2446
|
+
const setDistance = (next) => {
|
|
2447
|
+
distance = next;
|
|
2448
|
+
setPullDistance(next);
|
|
2449
|
+
};
|
|
2450
|
+
// Ends a gesture without refreshing: a cancelled touch, a sideways swipe,
|
|
2451
|
+
// or content that scrolled away from the top.
|
|
2452
|
+
const reset = () => {
|
|
2453
|
+
pulling = false;
|
|
2454
|
+
setIsDragging(false);
|
|
2455
|
+
setDistance(0);
|
|
2456
|
+
};
|
|
2457
|
+
const refresh = async () => {
|
|
2458
|
+
const { pullThreshold: threshold, onRefresh: run, onError: report } = latest.current;
|
|
2459
|
+
setDistance(threshold);
|
|
2392
2460
|
setInternalRefreshing(true);
|
|
2393
2461
|
try {
|
|
2394
|
-
await
|
|
2462
|
+
await run();
|
|
2463
|
+
if (mounted)
|
|
2464
|
+
setAnnouncement(latest.current.refreshedLabel);
|
|
2465
|
+
}
|
|
2466
|
+
catch (error) {
|
|
2467
|
+
report === null || report === void 0 ? void 0 : report(error);
|
|
2395
2468
|
}
|
|
2396
2469
|
finally {
|
|
2397
|
-
|
|
2398
|
-
|
|
2470
|
+
if (mounted) {
|
|
2471
|
+
setInternalRefreshing(false);
|
|
2472
|
+
setDistance(0);
|
|
2473
|
+
}
|
|
2399
2474
|
}
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2475
|
+
};
|
|
2476
|
+
const handleTouchStart = (e) => {
|
|
2477
|
+
var _a, _b;
|
|
2478
|
+
const { disabled: isDisabled, isRefreshing: busy } = latest.current;
|
|
2479
|
+
if (isDisabled || busy || container.scrollTop > 0 || e.touches.length !== 1)
|
|
2480
|
+
return;
|
|
2481
|
+
startX = (_a = e.touches[0].clientX) !== null && _a !== void 0 ? _a : 0;
|
|
2482
|
+
startY = (_b = e.touches[0].clientY) !== null && _b !== void 0 ? _b : 0;
|
|
2483
|
+
axis = 'pending';
|
|
2484
|
+
pulling = true;
|
|
2485
|
+
setAnnouncement('');
|
|
2486
|
+
setIsDragging(true);
|
|
2487
|
+
setDistance(0);
|
|
2488
|
+
};
|
|
2489
|
+
const handleTouchMove = (e) => {
|
|
2490
|
+
var _a, _b, _c, _d;
|
|
2491
|
+
if (!pulling)
|
|
2492
|
+
return;
|
|
2493
|
+
if (latest.current.disabled || latest.current.isRefreshing || container.scrollTop > 0) {
|
|
2494
|
+
reset();
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
const dx = ((_b = (_a = e.touches[0]) === null || _a === void 0 ? void 0 : _a.clientX) !== null && _b !== void 0 ? _b : 0) - startX;
|
|
2498
|
+
const dy = ((_d = (_c = e.touches[0]) === null || _c === void 0 ? void 0 : _c.clientY) !== null && _d !== void 0 ? _d : 0) - startY;
|
|
2499
|
+
if (axis === 'pending') {
|
|
2500
|
+
if (Math.abs(dx) < AXIS_LOCK_SLOP && Math.abs(dy) < AXIS_LOCK_SLOP)
|
|
2501
|
+
return;
|
|
2502
|
+
axis = dy > 0 && Math.abs(dy) > Math.abs(dx) ? 'vertical' : 'horizontal';
|
|
2503
|
+
// A sideways swipe or an upward scroll belongs to the content, not to us.
|
|
2504
|
+
if (axis === 'horizontal') {
|
|
2505
|
+
reset();
|
|
2506
|
+
return;
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
const next = Math.min(latest.current.maxPullDistance, Math.max(0, dy) * RESISTANCE);
|
|
2510
|
+
setDistance(next);
|
|
2511
|
+
// Needs the non-passive listener: stops the browser's own pull-to-refresh/overscroll.
|
|
2512
|
+
if (next > 0 && e.cancelable)
|
|
2513
|
+
e.preventDefault();
|
|
2514
|
+
};
|
|
2515
|
+
const handleTouchEnd = () => {
|
|
2516
|
+
if (!pulling)
|
|
2517
|
+
return;
|
|
2518
|
+
pulling = false;
|
|
2519
|
+
setIsDragging(false);
|
|
2520
|
+
if (distance >= latest.current.pullThreshold)
|
|
2521
|
+
void refresh();
|
|
2522
|
+
else
|
|
2523
|
+
setDistance(0);
|
|
2524
|
+
};
|
|
2525
|
+
// React registers touch listeners as passive, where preventDefault() is
|
|
2526
|
+
// ignored, so these are attached natively with touchmove non-passive.
|
|
2527
|
+
container.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
2528
|
+
container.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
2529
|
+
container.addEventListener('touchend', handleTouchEnd);
|
|
2530
|
+
container.addEventListener('touchcancel', reset);
|
|
2531
|
+
return () => {
|
|
2532
|
+
mounted = false;
|
|
2533
|
+
container.removeEventListener('touchstart', handleTouchStart);
|
|
2534
|
+
container.removeEventListener('touchmove', handleTouchMove);
|
|
2535
|
+
container.removeEventListener('touchend', handleTouchEnd);
|
|
2536
|
+
container.removeEventListener('touchcancel', reset);
|
|
2537
|
+
};
|
|
2538
|
+
}, []);
|
|
2405
2539
|
const progress = Math.min(1, pullDistance / pullThreshold);
|
|
2406
2540
|
const isReady = pullDistance >= pullThreshold;
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2541
|
+
const offset = isRefreshing ? pullThreshold : pullDistance;
|
|
2542
|
+
// Follow the finger exactly while dragging; animate only the settle afterwards.
|
|
2543
|
+
const motionClass = isDragging
|
|
2544
|
+
? 'transition-none'
|
|
2545
|
+
: 'transition-transform duration-200 ease-out motion-reduce:transition-none';
|
|
2546
|
+
return (jsxs("div", { ref: containerRef, className: buildClassName('relative overflow-y-auto overscroll-none', className), "data-testid": "pull-to-refresh-container", children: [jsx("span", { role: "status", "aria-live": "polite", className: "sr-only", children: isRefreshing ? refreshingLabel : announcement }), variant === 'overlay' ? (jsx("div", { className: buildClassName('pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center', motionClass), style: {
|
|
2547
|
+
transform: `translateY(${offset - BADGE_SIZE + BADGE_TOP_GAP}px)`,
|
|
2548
|
+
opacity: offset > 0 ? 1 : 0,
|
|
2549
|
+
}, "aria-hidden": "true", "data-testid": "pull-to-refresh-indicator", children: jsx("div", { className: "grid size-10 place-items-center rounded-full bg-[var(--ui-primary)] text-white shadow-lg", children: isRefreshing
|
|
2550
|
+
? (refreshingContent !== null && refreshingContent !== void 0 ? refreshingContent : jsx(Loader, { size: "xs", className: "text-white" }))
|
|
2551
|
+
: (pullingContent !== null && pullingContent !== void 0 ? pullingContent : jsx(PullArrowIcon, { progress: progress, className: "size-4" })) }) })) : (
|
|
2552
|
+
// Absolutely positioned, so the content's own translate is the only shift.
|
|
2553
|
+
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: 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
|
|
2554
|
+
? (refreshingContent !== null && refreshingContent !== void 0 ? refreshingContent : (jsxs(Fragment, { children: [jsx(Loader, { size: "sm" }), jsx("span", { children: refreshingLabel })] })))
|
|
2555
|
+
: (pullingContent !== null && pullingContent !== void 0 ? pullingContent : (jsxs(Fragment, { children: [jsx(PullArrowIcon, { progress: progress, className: "size-4 text-[var(--ui-primary)] dark:text-blue-400" }), jsx("span", { children: isReady ? releaseLabel : pullLabel })] }))) }) })), jsx("div", { className: buildClassName(variant === 'push' && motionClass, contentClass), style: variant === 'push' ? { transform: `translateY(${offset}px)` } : undefined, "data-testid": "pull-to-refresh-content", children: children })] }));
|
|
2417
2556
|
}
|
|
2418
2557
|
PullToRefresh.displayName = 'PullToRefresh';
|
|
2419
2558
|
|
|
@@ -3326,12 +3465,23 @@ function ChevronLeftIcon$1() {
|
|
|
3326
3465
|
function SearchIcon$1() {
|
|
3327
3466
|
return (jsx("svg", { className: "size-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
|
|
3328
3467
|
}
|
|
3468
|
+
function MoreIcon() {
|
|
3469
|
+
return (jsxs("svg", { className: "size-5", fill: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: [jsx("circle", { cx: "12", cy: "5", r: "1.75" }), jsx("circle", { cx: "12", cy: "12", r: "1.75" }), jsx("circle", { cx: "12", cy: "19", r: "1.75" })] }));
|
|
3470
|
+
}
|
|
3329
3471
|
function ClearIcon() {
|
|
3330
3472
|
return (jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }));
|
|
3331
3473
|
}
|
|
3332
|
-
function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabel = 'Back', leading, actions, searchable = false, searchValue: externalSearchValue, onSearchChange, searchPlaceholder = 'Search...', sticky = true, transparent = false, bottomSlot, className = '', }) {
|
|
3474
|
+
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 = '', }) {
|
|
3333
3475
|
const [isSearchActive, setIsSearchActive] = useState(false);
|
|
3334
3476
|
const [internalSearchValue, setInternalSearchValue] = useState('');
|
|
3477
|
+
const [isOverflowOpen, setIsOverflowOpen] = useState(false);
|
|
3478
|
+
// The overflow button takes one of the visible slots.
|
|
3479
|
+
const allActions = actions !== null && actions !== void 0 ? actions : [];
|
|
3480
|
+
const shouldOverflow = maxVisibleActions !== undefined && allActions.length > maxVisibleActions;
|
|
3481
|
+
const visibleActions = shouldOverflow
|
|
3482
|
+
? allActions.slice(0, Math.max(maxVisibleActions - 1, 0))
|
|
3483
|
+
: allActions;
|
|
3484
|
+
const overflowActions = shouldOverflow ? allActions.slice(visibleActions.length) : [];
|
|
3335
3485
|
const searchValue = externalSearchValue !== undefined ? externalSearchValue : internalSearchValue;
|
|
3336
3486
|
const handleSearchInput = (e) => {
|
|
3337
3487
|
const val = e.target.value;
|
|
@@ -3346,14 +3496,20 @@ function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabe
|
|
|
3346
3496
|
? 'bg-white/80 dark:bg-gray-900/80 backdrop-blur-md border-b border-[var(--ui-border-muted)]'
|
|
3347
3497
|
: '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: [jsx("div", { className: "h-14 px-3.5 flex items-center justify-between gap-3 relative", children: searchable && isSearchActive ? (jsxs("div", { className: "flex-1 flex items-center gap-2", "data-testid": "mobile-header-search-container", children: [jsxs("div", { className: "relative flex-1 flex items-center", children: [jsx("span", { className: "absolute left-3 pointer-events-none", children: jsx(SearchIcon$1, {}) }), 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 && (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: jsx(ClearIcon, {}) }))] }), 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" })] })) : (jsxs(Fragment, { children: [jsx("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 z-10", children: onBack ? (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: [jsx(ChevronLeftIcon$1, {}), jsx("span", { className: "text-xs font-semibold hidden sm:inline", children: backLabel })] })) : (leading) }), jsxs("div", { className: buildClassName('flex-1 min-w-0 px-2', titleAlign === 'center'
|
|
3348
3498
|
? 'absolute inset-x-12 text-center pointer-events-none flex flex-col items-center justify-center'
|
|
3349
|
-
: 'text-left'), children: [title && (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 && (jsx("div", { className: "text-[11px] text-gray-500 dark:text-gray-400 truncate pointer-events-auto", "data-testid": "mobile-header-subtitle", children: subtitle }))] }), jsxs("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 justify-end z-10", children: [searchable && (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: jsx(SearchIcon$1, {}) })),
|
|
3499
|
+
: 'text-left'), children: [title && (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 && (jsx("div", { className: "text-[11px] text-gray-500 dark:text-gray-400 truncate pointer-events-auto", "data-testid": "mobile-header-subtitle", children: subtitle }))] }), jsxs("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 justify-end z-10", children: [searchable && (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: jsx(SearchIcon$1, {}) })), visibleActions.map((action) => {
|
|
3350
3500
|
const badgeColor = {
|
|
3351
3501
|
danger: 'bg-red-500 text-white',
|
|
3352
3502
|
info: 'bg-blue-500 text-white',
|
|
3353
3503
|
success: 'bg-emerald-500 text-white',
|
|
3354
3504
|
}[action.badgeVariant || 'danger'];
|
|
3355
3505
|
return (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: [jsx("span", { className: "text-base", children: action.icon }), action.badge !== undefined && action.badge !== null && (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));
|
|
3356
|
-
})
|
|
3506
|
+
}), overflowActions.length > 0 && (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: jsx(MoreIcon, {}) })), trailing] })] })) }), overflowActions.length > 0 && (jsx(ActionSheet, { isOpen: isOverflowOpen, onClose: () => setIsOverflowOpen(false), actions: overflowActions.map((action) => ({
|
|
3507
|
+
id: action.id,
|
|
3508
|
+
label: action.label,
|
|
3509
|
+
icon: action.icon,
|
|
3510
|
+
disabled: action.disabled,
|
|
3511
|
+
onClick: action.onClick,
|
|
3512
|
+
})) })), bottomSlot && (jsx("div", { className: "px-3 py-2 border-t border-[var(--ui-border-muted)]", "data-testid": "mobile-header-bottom-slot", children: bottomSlot }))] }));
|
|
3357
3513
|
}
|
|
3358
3514
|
MobileHeader.displayName = 'MobileHeader';
|
|
3359
3515
|
|
|
@@ -4329,14 +4485,14 @@ StatusPill.displayName = 'StatusPill';
|
|
|
4329
4485
|
|
|
4330
4486
|
const ChevronUpIcon = ({ className }) => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": "true", children: jsx("polyline", { points: "18 15 12 9 6 15" }) }));
|
|
4331
4487
|
const StickyActionBar = forwardRef((props, ref) => {
|
|
4332
|
-
const { summaryContent, actionsContent, drawerContent, drawerTitle = 'Summary Details', position = 'fixed', containerMaxWidth = 'max-w-5xl', className, ...restProps } = props;
|
|
4488
|
+
const { summaryContent, actionsContent, drawerContent, drawerTitle = 'Summary Details', position = 'fixed', containerMaxWidth = 'max-w-5xl', safeArea = true, bottomOffset, className, style, ...restProps } = props;
|
|
4333
4489
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
|
4334
4490
|
const positionClass = position === 'fixed'
|
|
4335
4491
|
? 'fixed bottom-0 left-0 right-0 z-30'
|
|
4336
4492
|
: position === 'sticky'
|
|
4337
4493
|
? 'sticky bottom-0 z-30'
|
|
4338
4494
|
: 'relative z-10';
|
|
4339
|
-
return (jsxs(Fragment, { children: [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: jsxs("div", { className: buildClassName('mx-auto flex items-center justify-between gap-3', containerMaxWidth), children: [summaryContent && (jsx("div", { className: "flex items-center gap-2", children: drawerContent ? (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: [jsx("div", { children: summaryContent }), jsx(ChevronUpIcon, { className: "size-4 text-[var(--ui-primary)] dark:text-blue-400 shrink-0" })] })) : (jsx("div", { children: summaryContent })) })), actionsContent && (jsx("div", { className: "flex items-center gap-2 shrink-0 ml-auto", "data-testid": "actions-stack", children: actionsContent }))] }) }), drawerContent && (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 }))] }));
|
|
4495
|
+
return (jsxs(Fragment, { children: [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: jsxs("div", { className: buildClassName('mx-auto flex items-center justify-between gap-3', containerMaxWidth), children: [summaryContent && (jsx("div", { className: "flex items-center gap-2", children: drawerContent ? (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: [jsx("div", { children: summaryContent }), jsx(ChevronUpIcon, { className: "size-4 text-[var(--ui-primary)] dark:text-blue-400 shrink-0" })] })) : (jsx("div", { children: summaryContent })) })), actionsContent && (jsx("div", { className: "flex items-center gap-2 shrink-0 ml-auto", "data-testid": "actions-stack", children: actionsContent }))] }) }), drawerContent && (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 }))] }));
|
|
4340
4496
|
});
|
|
4341
4497
|
StickyActionBar.displayName = 'StickyActionBar';
|
|
4342
4498
|
|
|
@@ -4929,5 +5085,5 @@ const useIsTabletOrMobile = () => {
|
|
|
4929
5085
|
return isMobile || isTablet;
|
|
4930
5086
|
};
|
|
4931
5087
|
|
|
4932
|
-
export { Accordion, ActionSheet, Alert, Badge, Banner, BodyText, BottomNavigation, Breadcrumb, Button, ButtonGroup, Card, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle, Checkbox, CheckboxGroup, DOTS, DataList, DataTable, DetailedInformation, Dot, Drawer, Dropdown, EmptyState, EmptyTableRow, Flex, FlexItem, FloatingActionButton, Grid, GridCol, HeadingText, Input, Label, Loader, MobileHeader, MobilePicker, MobileStepper, PASSWORD_PLACEHOLDER, PASSWORD_TYPE, Pagination, PasswordInput, PinInput, PullToRefresh, QuantityStepper, Radio, RadioGroup, RadioSwitch, RangeInput, RangeSlider, SegmentedControl, SelectBox, Skeleton, SortIconMap, StatusPill, StickyActionBar, SwipeableRow, SwipeableTabs, Table, TableBody, TableCell, TableFoot, TableHead, TableHeaderCell, TableRow, Tabs, TextContent, Textarea, Toast, ToastProvider, VirtualizedDataTable, WheelPicker, buildClassName, buildInputClass, evaluatePasswordStrength, get, getSortIcon, isArray, isEmpty, nextSortDirection, updateSortQuery, useDebounce, useDebounceFn, useIsMobile, useIsTablet, useIsTabletOrMobile, usePagination, useRowSelection, useToast };
|
|
5088
|
+
export { Accordion, ActionSheet, Alert, BREAKPOINT_QUERIES, Badge, Banner, BodyText, BottomNavigation, Breadcrumb, Button, ButtonGroup, Card, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle, Checkbox, CheckboxGroup, DOTS, DataList, DataTable, DetailedInformation, Dot, Drawer, Dropdown, EmptyState, EmptyTableRow, Flex, FlexItem, FloatingActionButton, Grid, GridCol, HeadingText, Input, Label, Loader, MobileHeader, MobilePicker, MobileStepper, PASSWORD_PLACEHOLDER, PASSWORD_TYPE, Pagination, PasswordInput, PinInput, PullToRefresh, QuantityStepper, Radio, RadioGroup, RadioSwitch, RangeInput, RangeSlider, SegmentedControl, SelectBox, Skeleton, SortIconMap, StatusPill, StickyActionBar, SwipeableRow, SwipeableTabs, Table, TableBody, TableCell, TableFoot, TableHead, TableHeaderCell, TableRow, Tabs, TextContent, Textarea, Toast, ToastProvider, VirtualizedDataTable, WheelPicker, buildClassName, buildInputClass, evaluatePasswordStrength, get, getSortIcon, isArray, isEmpty, nextSortDirection, updateSortQuery, useBreakpoint, useDebounce, useDebounceFn, useIsMobile, useIsTablet, useIsTabletOrMobile, useMediaQuery, usePagination, useResponsiveValue, useRowSelection, useToast };
|
|
4933
5089
|
//# sourceMappingURL=react-tailwind.es.js.map
|