@papernote/ui 1.13.0 → 1.14.1
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/components/FilterBar.d.ts +1 -1
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterPills.d.ts +14 -0
- package/dist/components/FilterPills.d.ts.map +1 -0
- package/dist/components/LetterNav.d.ts +8 -0
- package/dist/components/LetterNav.d.ts.map +1 -0
- package/dist/components/Pagination.d.ts +11 -1
- package/dist/components/Pagination.d.ts.map +1 -1
- package/dist/components/Select.d.ts +3 -3
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +38 -6
- package/dist/index.esm.js +446 -344
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +446 -342
- package/dist/index.js.map +1 -1
- package/dist/styles.css +4 -0
- package/package.json +1 -1
- package/src/components/FilterBar.tsx +116 -3
- package/src/components/FilterPills.tsx +58 -0
- package/src/components/LetterNav.tsx +67 -0
- package/src/components/Pagination.tsx +49 -1
- package/src/components/Select.tsx +367 -241
- package/src/components/index.ts +6 -0
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import React__default, { forwardRef, useState, useRef, useEffect, useId, useCallback, useImperativeHandle, useMemo, Children, isValidElement, cloneElement, Component, createContext as createContext$1, useContext, useLayoutEffect, createElement, useReducer } from 'react';
|
|
4
|
-
import { Loader2, Check, X, EyeOff, Eye, AlertTriangle, CheckCircle, AlertCircle, ChevronDown, Search, Minus, Star, Calendar as Calendar$1, ChevronLeft, ChevronRight, Clock, ChevronUp, Plus, TrendingUp, TrendingDown, Lightbulb, Sparkles, PartyPopper, Flame, Shield, Pencil, User, Users, Activity, Mail, Send, Info, Trash2, HelpCircle, ChevronsLeft, ChevronsRight, Circle, MoreVertical, GripVertical, Upload, Bold, Italic, Underline, List, ListOrdered, Code, Link, ExternalLink, MoreHorizontal, Home, ArrowUp, ArrowDown, RotateCcw, ArrowRight, FileText, Image, File as File$1, Menu as Menu$1, Settings, LogOut, Moon, Sun, Bell, Edit, Trash, Pin, PinOff, Download, Save, ArrowUpDown,
|
|
4
|
+
import { Loader2, Check, X, EyeOff, Eye, AlertTriangle, CheckCircle, AlertCircle, ChevronDown, Search, Minus, Star, Calendar as Calendar$1, ChevronLeft, ChevronRight, Clock, ChevronUp, Plus, Filter, TrendingUp, TrendingDown, Lightbulb, Sparkles, PartyPopper, Flame, Shield, Pencil, User, Users, Activity, Mail, Send, Info, Trash2, HelpCircle, ChevronsLeft, ChevronsRight, Circle, MoreVertical, GripVertical, Upload, Bold, Italic, Underline, List, ListOrdered, Code, Link, ExternalLink, MoreHorizontal, Home, ArrowUp, ArrowDown, RotateCcw, ArrowRight, FileText, Image, File as File$1, Menu as Menu$1, Settings, LogOut, Moon, Sun, Bell, Edit, Trash, Pin, PinOff, Download, Save, ArrowUpDown, XCircle, BarChart3, MessageSquare, Bot, RefreshCw, BrainCircuit, Target } from 'lucide-react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { Link as Link$1, useInRouterContext, useNavigate, useLocation } from 'react-router-dom';
|
|
7
7
|
|
|
@@ -705,15 +705,15 @@ function usePrefersMobile() {
|
|
|
705
705
|
|
|
706
706
|
// Size classes for trigger button
|
|
707
707
|
const sizeClasses$d = {
|
|
708
|
-
sm:
|
|
709
|
-
md:
|
|
710
|
-
lg:
|
|
708
|
+
sm: "h-8 text-sm py-1",
|
|
709
|
+
md: "h-10 text-base py-2",
|
|
710
|
+
lg: "h-12 text-base py-3 min-h-touch", // 44px touch target
|
|
711
711
|
};
|
|
712
712
|
// Size classes for options
|
|
713
713
|
const optionSizeClasses = {
|
|
714
|
-
sm:
|
|
715
|
-
md:
|
|
716
|
-
lg:
|
|
714
|
+
sm: "py-2 text-sm",
|
|
715
|
+
md: "py-2.5 text-sm",
|
|
716
|
+
lg: "py-3.5 text-base min-h-touch", // 44px touch target for mobile
|
|
717
717
|
};
|
|
718
718
|
/**
|
|
719
719
|
* Select - Dropdown select component with search, groups, virtual scrolling, and mobile support
|
|
@@ -786,9 +786,9 @@ const optionSizeClasses = {
|
|
|
786
786
|
* ```
|
|
787
787
|
*/
|
|
788
788
|
const Select = forwardRef((props, ref) => {
|
|
789
|
-
const { options = [], groups = [], value, onChange, placeholder =
|
|
789
|
+
const { options = [], groups = [], value, onChange, placeholder = "Select an option", searchable = false, disabled = false, label, helperText, error, loading = false, clearable = false, creatable = false, onCreateOption, virtualized = false, virtualHeight = "300px", virtualItemHeight = 42, size = "md", mobileMode = "auto", usePortal = true, required = false, } = props;
|
|
790
790
|
const [isOpen, setIsOpen] = useState(false);
|
|
791
|
-
const [searchQuery, setSearchQuery] = useState(
|
|
791
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
792
792
|
const [scrollTop, setScrollTop] = useState(0);
|
|
793
793
|
const [activeDescendant] = useState(undefined);
|
|
794
794
|
const [dropdownPosition, setDropdownPosition] = useState(null);
|
|
@@ -801,10 +801,10 @@ const Select = forwardRef((props, ref) => {
|
|
|
801
801
|
const nativeSelectRef = useRef(null);
|
|
802
802
|
// Detect mobile viewport
|
|
803
803
|
const isMobile = useIsMobile();
|
|
804
|
-
const useMobileSheet = mobileMode ===
|
|
805
|
-
const useNativeSelect = mobileMode ===
|
|
804
|
+
const useMobileSheet = mobileMode === "auto" && isMobile;
|
|
805
|
+
const useNativeSelect = mobileMode === "native" && isMobile;
|
|
806
806
|
// Auto-size for mobile
|
|
807
|
-
const effectiveSize = isMobile && size ===
|
|
807
|
+
const effectiveSize = isMobile && size === "md" ? "lg" : size;
|
|
808
808
|
// Generate unique IDs for ARIA
|
|
809
809
|
const labelId = useId();
|
|
810
810
|
const listboxId = useId();
|
|
@@ -818,11 +818,8 @@ const Select = forwardRef((props, ref) => {
|
|
|
818
818
|
close: () => setIsOpen(false),
|
|
819
819
|
}));
|
|
820
820
|
// Flatten all options (from both options and groups)
|
|
821
|
-
const allOptions = [
|
|
822
|
-
|
|
823
|
-
...groups.flatMap(group => group.options)
|
|
824
|
-
];
|
|
825
|
-
const selectedOption = allOptions.find(opt => opt.value === value);
|
|
821
|
+
const allOptions = [...options, ...groups.flatMap((group) => group.options)];
|
|
822
|
+
const selectedOption = allOptions.find((opt) => opt.value === value);
|
|
826
823
|
// Filter options/groups based on search
|
|
827
824
|
const getFilteredData = () => {
|
|
828
825
|
if (!searchable || !searchQuery) {
|
|
@@ -830,41 +827,58 @@ const Select = forwardRef((props, ref) => {
|
|
|
830
827
|
}
|
|
831
828
|
const query = searchQuery.toLowerCase();
|
|
832
829
|
// Filter flat options
|
|
833
|
-
const filteredOptions = options.filter(opt => opt.label.toLowerCase().includes(query));
|
|
830
|
+
const filteredOptions = options.filter((opt) => opt.label.toLowerCase().includes(query));
|
|
834
831
|
// Filter grouped options
|
|
835
832
|
const filteredGroups = groups
|
|
836
|
-
.map(group => ({
|
|
833
|
+
.map((group) => ({
|
|
837
834
|
...group,
|
|
838
|
-
options: group.options.filter(opt => opt.label.toLowerCase().includes(query))
|
|
835
|
+
options: group.options.filter((opt) => opt.label.toLowerCase().includes(query)),
|
|
839
836
|
}))
|
|
840
|
-
.filter(group => group.options.length > 0);
|
|
837
|
+
.filter((group) => group.options.length > 0);
|
|
841
838
|
return { options: filteredOptions, groups: filteredGroups };
|
|
842
839
|
};
|
|
843
840
|
const { options: filteredOptions, groups: filteredGroups } = getFilteredData();
|
|
844
841
|
// Virtual scrolling calculations
|
|
845
|
-
const totalItems = filteredOptions.length + filteredGroups.flatMap(g => g.options).length;
|
|
842
|
+
const totalItems = filteredOptions.length + filteredGroups.flatMap((g) => g.options).length;
|
|
846
843
|
const useVirtualScrolling = virtualized && totalItems > 50;
|
|
847
844
|
const visibleRangeStart = useVirtualScrolling
|
|
848
845
|
? Math.floor(scrollTop / virtualItemHeight)
|
|
849
846
|
: 0;
|
|
850
847
|
const visibleRangeEnd = useVirtualScrolling
|
|
851
|
-
? Math.min(visibleRangeStart +
|
|
848
|
+
? Math.min(visibleRangeStart +
|
|
849
|
+
Math.ceil(parseInt(virtualHeight) / virtualItemHeight) +
|
|
850
|
+
5, totalItems)
|
|
852
851
|
: totalItems;
|
|
853
852
|
// Flatten all filtered items for virtualization
|
|
854
853
|
const allFilteredItems = [
|
|
855
|
-
...filteredOptions.map((opt, idx) => ({
|
|
856
|
-
|
|
854
|
+
...filteredOptions.map((opt, idx) => ({
|
|
855
|
+
type: "option",
|
|
856
|
+
option: opt,
|
|
857
|
+
groupIndex: -1,
|
|
858
|
+
optionIndex: idx,
|
|
859
|
+
})),
|
|
860
|
+
...filteredGroups.flatMap((group, groupIdx) => group.options.map((opt, optIdx) => ({
|
|
861
|
+
type: "grouped",
|
|
862
|
+
option: opt,
|
|
863
|
+
groupIndex: groupIdx,
|
|
864
|
+
optionIndex: optIdx,
|
|
865
|
+
groupLabel: group.label,
|
|
866
|
+
}))),
|
|
857
867
|
];
|
|
858
868
|
const visibleItems = useVirtualScrolling
|
|
859
869
|
? allFilteredItems.slice(visibleRangeStart, visibleRangeEnd)
|
|
860
870
|
: allFilteredItems;
|
|
861
|
-
const offsetY = useVirtualScrolling
|
|
862
|
-
|
|
871
|
+
const offsetY = useVirtualScrolling
|
|
872
|
+
? visibleRangeStart * virtualItemHeight
|
|
873
|
+
: 0;
|
|
874
|
+
const totalHeight = useVirtualScrolling
|
|
875
|
+
? totalItems * virtualItemHeight
|
|
876
|
+
: "auto";
|
|
863
877
|
// Check if we should show "Create" option
|
|
864
878
|
const showCreateOption = creatable &&
|
|
865
|
-
searchQuery.trim() !==
|
|
866
|
-
!filteredOptions.some(opt => opt.label.toLowerCase() === searchQuery.toLowerCase()) &&
|
|
867
|
-
!filteredGroups.some(group => group.options.some(opt => opt.label.toLowerCase() === searchQuery.toLowerCase()));
|
|
879
|
+
searchQuery.trim() !== "" &&
|
|
880
|
+
!filteredOptions.some((opt) => opt.label.toLowerCase() === searchQuery.toLowerCase()) &&
|
|
881
|
+
!filteredGroups.some((group) => group.options.some((opt) => opt.label.toLowerCase() === searchQuery.toLowerCase()));
|
|
868
882
|
// Handle creating new option
|
|
869
883
|
const handleCreateOption = () => {
|
|
870
884
|
if (onCreateOption) {
|
|
@@ -874,7 +888,7 @@ const Select = forwardRef((props, ref) => {
|
|
|
874
888
|
// If no callback, just select the typed value
|
|
875
889
|
onChange?.(searchQuery.trim());
|
|
876
890
|
}
|
|
877
|
-
setSearchQuery(
|
|
891
|
+
setSearchQuery("");
|
|
878
892
|
setIsOpen(false);
|
|
879
893
|
};
|
|
880
894
|
// Handle click outside (desktop dropdown only)
|
|
@@ -888,14 +902,14 @@ const Select = forwardRef((props, ref) => {
|
|
|
888
902
|
const isOutsideDropdown = dropdownRef.current && !dropdownRef.current.contains(target);
|
|
889
903
|
if (isOutsideSelect && isOutsideDropdown) {
|
|
890
904
|
setIsOpen(false);
|
|
891
|
-
setSearchQuery(
|
|
905
|
+
setSearchQuery("");
|
|
892
906
|
}
|
|
893
907
|
};
|
|
894
908
|
if (isOpen) {
|
|
895
|
-
document.addEventListener(
|
|
909
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
896
910
|
}
|
|
897
911
|
return () => {
|
|
898
|
-
document.removeEventListener(
|
|
912
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
899
913
|
};
|
|
900
914
|
}, [isOpen, useMobileSheet]);
|
|
901
915
|
// Focus search input when opened
|
|
@@ -929,8 +943,8 @@ const Select = forwardRef((props, ref) => {
|
|
|
929
943
|
const hasSpaceBelow = spaceBelow >= dropdownHeight + gap;
|
|
930
944
|
const hasSpaceAbove = spaceAbove >= dropdownHeight + gap;
|
|
931
945
|
// Prefer bottom placement, flip to top if not enough space below but enough above
|
|
932
|
-
const placement = hasSpaceBelow || !hasSpaceAbove ?
|
|
933
|
-
const top = placement ===
|
|
946
|
+
const placement = hasSpaceBelow || !hasSpaceAbove ? "bottom" : "top";
|
|
947
|
+
const top = placement === "bottom"
|
|
934
948
|
? rect.bottom + gap
|
|
935
949
|
: rect.top - dropdownHeight - gap;
|
|
936
950
|
setDropdownPosition({
|
|
@@ -943,23 +957,23 @@ const Select = forwardRef((props, ref) => {
|
|
|
943
957
|
// Initial position calculation
|
|
944
958
|
updatePosition();
|
|
945
959
|
// Listen for scroll events on all scrollable ancestors
|
|
946
|
-
window.addEventListener(
|
|
947
|
-
window.addEventListener(
|
|
960
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
961
|
+
window.addEventListener("resize", updatePosition);
|
|
948
962
|
return () => {
|
|
949
|
-
window.removeEventListener(
|
|
950
|
-
window.removeEventListener(
|
|
963
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
964
|
+
window.removeEventListener("resize", updatePosition);
|
|
951
965
|
};
|
|
952
966
|
}, [isOpen, useMobileSheet, usePortal]);
|
|
953
967
|
// Lock body scroll when mobile sheet is open
|
|
954
968
|
useEffect(() => {
|
|
955
969
|
if (useMobileSheet && isOpen) {
|
|
956
|
-
document.body.style.overflow =
|
|
970
|
+
document.body.style.overflow = "hidden";
|
|
957
971
|
}
|
|
958
972
|
else {
|
|
959
|
-
document.body.style.overflow =
|
|
973
|
+
document.body.style.overflow = "";
|
|
960
974
|
}
|
|
961
975
|
return () => {
|
|
962
|
-
document.body.style.overflow =
|
|
976
|
+
document.body.style.overflow = "";
|
|
963
977
|
};
|
|
964
978
|
}, [isOpen, useMobileSheet]);
|
|
965
979
|
// Handle escape key for mobile sheet
|
|
@@ -967,83 +981,105 @@ const Select = forwardRef((props, ref) => {
|
|
|
967
981
|
if (!useMobileSheet || !isOpen)
|
|
968
982
|
return;
|
|
969
983
|
const handleEscape = (e) => {
|
|
970
|
-
if (e.key ===
|
|
984
|
+
if (e.key === "Escape") {
|
|
971
985
|
setIsOpen(false);
|
|
972
|
-
setSearchQuery(
|
|
986
|
+
setSearchQuery("");
|
|
973
987
|
}
|
|
974
988
|
};
|
|
975
|
-
document.addEventListener(
|
|
976
|
-
return () => document.removeEventListener(
|
|
989
|
+
document.addEventListener("keydown", handleEscape);
|
|
990
|
+
return () => document.removeEventListener("keydown", handleEscape);
|
|
977
991
|
}, [isOpen, useMobileSheet]);
|
|
978
992
|
const handleSelect = (optionValue) => {
|
|
979
993
|
onChange?.(optionValue);
|
|
980
994
|
setIsOpen(false);
|
|
981
|
-
setSearchQuery(
|
|
995
|
+
setSearchQuery("");
|
|
982
996
|
};
|
|
983
997
|
const handleClose = () => {
|
|
984
998
|
setIsOpen(false);
|
|
985
|
-
setSearchQuery(
|
|
999
|
+
setSearchQuery("");
|
|
986
1000
|
};
|
|
987
1001
|
// Render option button (shared between desktop and mobile)
|
|
988
1002
|
const renderOption = (option, isSelected, mobile = false) => (jsxs("button", { type: "button", onClick: () => !option.disabled && handleSelect(option.value), disabled: option.disabled, className: `
|
|
989
1003
|
w-full flex items-center justify-between px-4 transition-colors
|
|
990
1004
|
${mobile ? optionSizeClasses.lg : optionSizeClasses[effectiveSize]}
|
|
991
|
-
${isSelected ?
|
|
992
|
-
${option.disabled ?
|
|
993
|
-
`, role: "option", "aria-selected": isSelected, children: [jsxs("span", { className: "flex items-center gap-2", children: [option.icon && jsx("span", { children: option.icon }), option.label] }), isSelected && jsx(Check, { className: `${mobile ?
|
|
1005
|
+
${isSelected ? "bg-accent-50 text-accent-900" : "text-ink-700"}
|
|
1006
|
+
${option.disabled ? "opacity-40 cursor-not-allowed" : "hover:bg-paper-50 active:bg-paper-100 cursor-pointer"}
|
|
1007
|
+
`, role: "option", "aria-selected": isSelected, children: [jsxs("span", { className: "flex items-center gap-2", children: [option.icon && jsx("span", { children: option.icon }), option.label] }), isSelected && (jsx(Check, { className: `${mobile ? "h-5 w-5" : "h-4 w-4"} text-accent-600` }))] }, option.value));
|
|
994
1008
|
// Render options list content (shared between desktop and mobile)
|
|
995
1009
|
const renderOptionsContent = (mobile = false) => {
|
|
996
1010
|
if (loading) {
|
|
997
1011
|
return (jsxs("div", { className: "px-4 py-8 flex items-center justify-center", role: "status", "aria-live": "polite", children: [jsx(Loader2, { className: "h-5 w-5 animate-spin text-ink-500" }), jsx("span", { className: "ml-2 text-sm text-ink-500", children: "Loading..." })] }));
|
|
998
1012
|
}
|
|
999
|
-
if (filteredOptions.length === 0 &&
|
|
1013
|
+
if (filteredOptions.length === 0 &&
|
|
1014
|
+
filteredGroups.length === 0 &&
|
|
1015
|
+
!showCreateOption) {
|
|
1000
1016
|
return (jsx("div", { className: "px-4 py-3 text-sm text-ink-500 text-center", role: "status", "aria-live": "polite", children: "No options found" }));
|
|
1001
1017
|
}
|
|
1002
1018
|
return (jsxs(Fragment, { children: [showCreateOption && (jsx("button", { type: "button", onClick: handleCreateOption, className: `
|
|
1003
1019
|
w-full flex items-center px-4 text-accent-700 hover:bg-accent-50 transition-colors border-b border-paper-200
|
|
1004
|
-
${mobile ?
|
|
1005
|
-
`, children: jsxs("span", { className: "font-medium", children: ["Create \"", searchQuery, "\""] }) })), useVirtualScrolling ? (jsx("div", { style: { height: totalHeight, position:
|
|
1020
|
+
${mobile ? "py-3.5 text-base" : "py-2.5 text-sm"}
|
|
1021
|
+
`, children: jsxs("span", { className: "font-medium", children: ["Create \"", searchQuery, "\""] }) })), useVirtualScrolling ? (jsx("div", { style: { height: totalHeight, position: "relative" }, children: jsx("div", { style: { transform: `translateY(${offsetY}px)` }, children: visibleItems.map((item) => {
|
|
1006
1022
|
const option = item.option;
|
|
1007
1023
|
const isSelected = option.value === value;
|
|
1008
1024
|
const key = `${item.type}-${item.groupIndex}-${item.optionIndex}-${option.value}`;
|
|
1009
|
-
return (jsxs("button", { type: "button", onClick: () => !option.disabled && handleSelect(option.value), disabled: option.disabled, style: {
|
|
1025
|
+
return (jsxs("button", { type: "button", onClick: () => !option.disabled && handleSelect(option.value), disabled: option.disabled, style: {
|
|
1026
|
+
height: mobile ? "56px" : `${virtualItemHeight}px`,
|
|
1027
|
+
}, className: `
|
|
1010
1028
|
w-full flex items-center justify-between px-4 transition-colors
|
|
1011
|
-
${mobile ?
|
|
1012
|
-
${isSelected ?
|
|
1013
|
-
${option.disabled ?
|
|
1014
|
-
`, role: "option", "aria-selected": isSelected, children: [jsxs("span", { className: "flex items-center gap-2", children: [option.icon && jsx("span", { children: option.icon }), option.label] }), isSelected && jsx(Check, { className: `${mobile ?
|
|
1029
|
+
${mobile ? "text-base" : "text-sm"}
|
|
1030
|
+
${isSelected ? "bg-accent-50 text-accent-900" : "text-ink-700"}
|
|
1031
|
+
${option.disabled ? "opacity-40 cursor-not-allowed" : "hover:bg-paper-50 cursor-pointer"}
|
|
1032
|
+
`, role: "option", "aria-selected": isSelected, children: [jsxs("span", { className: "flex items-center gap-2", children: [option.icon && jsx("span", { children: option.icon }), option.label] }), isSelected && (jsx(Check, { className: `${mobile ? "h-5 w-5" : "h-4 w-4"} text-accent-600` }))] }, key));
|
|
1015
1033
|
}) }) })) : (jsxs(Fragment, { children: [filteredOptions.map((option) => renderOption(option, option.value === value, mobile)), filteredGroups.map((group) => (jsxs("div", { children: [jsx("div", { className: `
|
|
1016
1034
|
px-4 font-semibold text-ink-500 uppercase tracking-wider bg-paper-50 border-t border-b border-paper-200
|
|
1017
|
-
${mobile ?
|
|
1035
|
+
${mobile ? "py-2.5 text-xs" : "py-2 text-xs"}
|
|
1018
1036
|
`, children: group.label }), group.options.map((option) => renderOption(option, option.value === value, mobile))] }, group.label)))] }))] }));
|
|
1019
1037
|
};
|
|
1020
1038
|
// Native select for mobile (optional)
|
|
1021
1039
|
if (useNativeSelect) {
|
|
1022
|
-
return (jsxs("div", { className: "w-full", children: [label && (jsxs("label", { id: labelId, className: "label", children: [label, required && jsx("span", { className: "text-error-500 ml-1", children: "*" })] })), jsxs("div", { className: "relative", children: [jsxs("select", { ref: nativeSelectRef, value: value ||
|
|
1040
|
+
return (jsxs("div", { className: "w-full", children: [label && (jsxs("label", { id: labelId, className: "label", children: [label, required && jsx("span", { className: "text-error-500 ml-1", children: "*" })] })), jsxs("div", { className: "relative", children: [jsxs("select", { ref: nativeSelectRef, value: value || "", onChange: (e) => onChange?.(e.target.value), disabled: disabled, className: `
|
|
1023
1041
|
input w-full appearance-none pr-10
|
|
1024
1042
|
${sizeClasses$d[effectiveSize]}
|
|
1025
|
-
${error ?
|
|
1026
|
-
${disabled ?
|
|
1027
|
-
`, "aria-labelledby": label ? labelId : undefined, "aria-invalid": error ?
|
|
1043
|
+
${error ? "border-error-400 focus:border-error-400 focus:ring-error-400" : ""}
|
|
1044
|
+
${disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer"}
|
|
1045
|
+
`, "aria-labelledby": label ? labelId : undefined, "aria-invalid": error ? "true" : undefined, "aria-describedby": error ? errorId : helperText ? helperTextId : undefined, "aria-required": required, children: [jsx("option", { value: "", disabled: true, children: placeholder }), options.map((opt) => (jsx("option", { value: opt.value, disabled: opt.disabled, children: opt.label }, opt.value))), groups.map((group) => (jsx("optgroup", { label: group.label, children: group.options.map((opt) => (jsx("option", { value: opt.value, disabled: opt.disabled, children: opt.label }, opt.value))) }, group.label)))] }), jsx(ChevronDown, { className: "absolute right-3 top-1/2 -translate-y-1/2 h-5 w-5 text-ink-500 pointer-events-none" })] }), error && (jsx("p", { id: errorId, className: "mt-2 text-xs text-error-600", role: "alert", "aria-live": "assertive", children: error })), helperText && !error && (jsx("p", { id: helperTextId, className: "mt-2 text-xs text-ink-600", children: helperText }))] }));
|
|
1028
1046
|
}
|
|
1029
1047
|
return (jsxs("div", { className: "w-full", children: [label && (jsxs("label", { id: labelId, className: "label", children: [label, required && jsx("span", { className: "text-error-500 ml-1", children: "*" })] })), jsx("div", { ref: selectRef, className: "relative", children: jsxs("button", { ref: buttonRef, type: "button", onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, className: `
|
|
1030
1048
|
input w-full flex items-center justify-between px-3
|
|
1031
1049
|
${sizeClasses$d[effectiveSize]}
|
|
1032
|
-
${error ?
|
|
1033
|
-
${disabled ?
|
|
1034
|
-
`, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-labelledby": label ? labelId : undefined, "aria-label": !label ? placeholder : undefined, "aria-activedescendant": activeDescendant, "aria-invalid": error ?
|
|
1050
|
+
${error ? "border-error-400 focus:border-error-400 focus:ring-error-400" : ""}
|
|
1051
|
+
${disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer"}
|
|
1052
|
+
`, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-labelledby": label ? labelId : undefined, "aria-label": !label ? placeholder : undefined, "aria-activedescendant": activeDescendant, "aria-invalid": error ? "true" : undefined, "aria-describedby": error ? errorId : helperText ? helperTextId : undefined, "aria-disabled": disabled, "aria-required": required, children: [jsxs("span", { className: `flex items-center gap-2 ${selectedOption ? "text-ink-800" : "text-ink-400"}`, children: [loading && (jsx(Loader2, { className: "h-4 w-4 animate-spin text-ink-500" })), !loading && selectedOption?.icon && (jsx("span", { children: selectedOption.icon })), selectedOption ? selectedOption.label : placeholder] }), jsxs("div", { className: "flex items-center gap-1", children: [clearable && value && (jsx("span", { role: "button", tabIndex: -1, onClick: (e) => {
|
|
1035
1053
|
e.stopPropagation();
|
|
1036
|
-
onChange?.(
|
|
1054
|
+
onChange?.("");
|
|
1037
1055
|
setIsOpen(false);
|
|
1038
|
-
},
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1056
|
+
}, onKeyDown: (e) => {
|
|
1057
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1058
|
+
e.preventDefault();
|
|
1059
|
+
e.stopPropagation();
|
|
1060
|
+
onChange?.("");
|
|
1061
|
+
setIsOpen(false);
|
|
1062
|
+
}
|
|
1063
|
+
}, className: "text-ink-400 hover:text-ink-600 transition-colors p-0.5 cursor-pointer inline-flex", "aria-label": "Clear selection", children: jsx(X, { className: `${effectiveSize === "lg" ? "h-5 w-5" : "h-4 w-4"}` }) })), jsx(ChevronDown, { className: `${effectiveSize === "lg" ? "h-5 w-5" : "h-4 w-4"} text-ink-500 transition-transform ${isOpen ? "rotate-180" : ""}` })] })] }) }), isOpen &&
|
|
1064
|
+
!useMobileSheet &&
|
|
1065
|
+
(usePortal ? dropdownPosition : true) &&
|
|
1066
|
+
(usePortal ? (createPortal(jsxs("div", { ref: dropdownRef, className: `fixed z-[9999] bg-white bg-subtle-grain rounded-lg shadow-lg border border-paper-200 max-h-60 overflow-hidden animate-fade-in ${dropdownPosition?.placement === "top"
|
|
1067
|
+
? "origin-bottom"
|
|
1068
|
+
: "origin-top"}`, style: {
|
|
1069
|
+
top: dropdownPosition.top,
|
|
1070
|
+
left: dropdownPosition.left,
|
|
1071
|
+
width: dropdownPosition.width,
|
|
1072
|
+
}, children: [searchable && (jsx("div", { className: "p-2 border-b border-paper-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-ink-400" }), jsx("input", { ref: searchInputRef, type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search...", className: "w-full pl-9 pr-3 py-2 text-sm border border-paper-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400", role: "searchbox", "aria-label": "Search options", "aria-autocomplete": "list", "aria-controls": listboxId })] }) })), jsx("div", { ref: listRef, id: listboxId, className: "overflow-y-auto", style: {
|
|
1073
|
+
maxHeight: useVirtualScrolling ? virtualHeight : "12rem",
|
|
1074
|
+
}, onScroll: (e) => useVirtualScrolling && setScrollTop(e.currentTarget.scrollTop), role: "listbox", "aria-label": "Available options", "aria-multiselectable": "false", children: renderOptionsContent(false) })] }), document.body)) : (
|
|
1075
|
+
// Non-portal dropdown (inline, relative positioning)
|
|
1076
|
+
jsxs("div", { ref: dropdownRef, className: "absolute z-50 mt-1 w-full bg-white bg-subtle-grain rounded-lg shadow-lg border border-paper-200 max-h-60 overflow-hidden animate-fade-in", children: [searchable && (jsx("div", { className: "p-2 border-b border-paper-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-ink-400" }), jsx("input", { ref: searchInputRef, type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search...", className: "w-full pl-9 pr-3 py-2 text-sm border border-paper-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400", role: "searchbox", "aria-label": "Search options", "aria-autocomplete": "list", "aria-controls": listboxId })] }) })), jsx("div", { ref: listRef, id: listboxId, className: "overflow-y-auto", style: {
|
|
1077
|
+
maxHeight: useVirtualScrolling ? virtualHeight : "12rem",
|
|
1078
|
+
}, onScroll: (e) => useVirtualScrolling && setScrollTop(e.currentTarget.scrollTop), role: "listbox", "aria-label": "Available options", "aria-multiselectable": "false", children: renderOptionsContent(false) })] }))), isOpen &&
|
|
1079
|
+
useMobileSheet &&
|
|
1080
|
+
createPortal(jsxs("div", { className: "fixed inset-0 z-50 flex items-end", onClick: (e) => e.target === e.currentTarget && handleClose(), role: "dialog", "aria-modal": "true", "aria-labelledby": label ? `mobile-${labelId}` : undefined, children: [jsx("div", { className: "absolute inset-0 bg-black/50 animate-fade-in" }), jsxs("div", { className: "relative w-full bg-white rounded-t-2xl shadow-2xl animate-slide-up max-h-[85vh] flex flex-col", style: { paddingBottom: "env(safe-area-inset-bottom)" }, children: [jsx("div", { className: "py-3 cursor-grab", children: jsx("div", { className: "w-12 h-1.5 bg-ink-300 rounded-full mx-auto" }) }), jsxs("div", { className: "px-4 pb-3 border-b border-paper-200 flex items-center justify-between", children: [label && (jsx("h2", { id: `mobile-${labelId}`, className: "text-lg font-semibold text-ink-900", children: label })), !label && (jsx("h2", { className: "text-lg font-semibold text-ink-900", children: placeholder })), jsx("button", { onClick: handleClose, className: "text-ink-400 hover:text-ink-600 transition-colors p-2 -mr-2", "aria-label": "Close", children: jsx(X, { className: "h-5 w-5" }) })] }), searchable && (jsx("div", { className: "p-3 border-b border-paper-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-4 top-1/2 -translate-y-1/2 h-5 w-5 text-ink-400" }), jsx("input", { ref: mobileSearchInputRef, type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search...", inputMode: "search", enterKeyHint: "search", className: "w-full pl-12 pr-4 py-3 text-base border border-paper-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400", role: "searchbox", "aria-label": "Search options" })] }) })), jsx("div", { id: listboxId, className: "overflow-y-auto flex-1", role: "listbox", "aria-label": "Available options", "aria-multiselectable": "false", children: renderOptionsContent(true) })] })] }), document.body), error && (jsx("p", { id: errorId, className: "mt-2 text-xs text-error-600", role: "alert", "aria-live": "assertive", children: error })), helperText && !error && (jsx("p", { id: helperTextId, className: "mt-2 text-xs text-ink-600", children: helperText }))] }));
|
|
1045
1081
|
});
|
|
1046
|
-
Select.displayName =
|
|
1082
|
+
Select.displayName = "Select";
|
|
1047
1083
|
|
|
1048
1084
|
const MultiSelect = forwardRef(({ options, value = [], onChange, placeholder = 'Select options', searchable = false, disabled = false, label, helperText, error, maxHeight = 240, maxSelections, loading = false, 'aria-label': ariaLabel, }, ref) => {
|
|
1049
1085
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -2699,7 +2735,18 @@ function FilterBar({ filters, values, onChange, className = '', onClear, showCle
|
|
|
2699
2735
|
// Default clear: set all values to null/empty
|
|
2700
2736
|
const clearedValues = {};
|
|
2701
2737
|
filters.forEach(filter => {
|
|
2702
|
-
|
|
2738
|
+
if (filter.type === 'text' || filter.type === 'search') {
|
|
2739
|
+
clearedValues[filter.key] = '';
|
|
2740
|
+
}
|
|
2741
|
+
else if (filter.type === 'dateRange') {
|
|
2742
|
+
clearedValues[filter.key] = { from: undefined, to: undefined };
|
|
2743
|
+
}
|
|
2744
|
+
else if (filter.type === 'multiSelect') {
|
|
2745
|
+
clearedValues[filter.key] = [];
|
|
2746
|
+
}
|
|
2747
|
+
else {
|
|
2748
|
+
clearedValues[filter.key] = null;
|
|
2749
|
+
}
|
|
2703
2750
|
});
|
|
2704
2751
|
onChange(clearedValues);
|
|
2705
2752
|
}
|
|
@@ -2731,6 +2778,38 @@ function FilterBar({ filters, values, onChange, className = '', onClear, showCle
|
|
|
2731
2778
|
];
|
|
2732
2779
|
return (jsx(Select, { options: boolOptions, value: value === null || value === undefined ? '' : String(value), onChange: (newValue) => handleFilterChange(filter.key, newValue === '' ? null : newValue === 'true') }));
|
|
2733
2780
|
}
|
|
2781
|
+
case 'search':
|
|
2782
|
+
return (jsxs("div", { className: "relative", children: [jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: jsx(Search, { className: "h-4 w-4 text-ink-400" }) }), jsx("input", { type: "text", placeholder: filter.placeholder || `Search ${filter.label}...`, value: value || '', onChange: (e) => handleFilterChange(filter.key, e.target.value), className: "input pl-9" })] }));
|
|
2783
|
+
case 'dateRange': {
|
|
2784
|
+
const rangeValue = value || {};
|
|
2785
|
+
return (jsxs("div", { className: "flex items-center gap-2", children: [jsx("input", { type: "date", value: rangeValue.from || '', onChange: (e) => handleFilterChange(filter.key, { ...rangeValue, from: e.target.value || undefined }), className: "input text-sm", "aria-label": `${filter.label} from` }), jsx("span", { className: "text-ink-400 text-xs", children: "to" }), jsx("input", { type: "date", value: rangeValue.to || '', onChange: (e) => handleFilterChange(filter.key, { ...rangeValue, to: e.target.value || undefined }), className: "input text-sm", "aria-label": `${filter.label} to` })] }));
|
|
2786
|
+
}
|
|
2787
|
+
case 'toggle': {
|
|
2788
|
+
const toggleOptions = [
|
|
2789
|
+
{ value: '', label: 'All' },
|
|
2790
|
+
{ value: 'true', label: 'Yes' },
|
|
2791
|
+
{ value: 'false', label: 'No' },
|
|
2792
|
+
];
|
|
2793
|
+
const currentVal = value === null || value === undefined ? '' : String(value);
|
|
2794
|
+
return (jsx("div", { className: "flex rounded-lg border border-paper-300 overflow-hidden", role: "group", children: toggleOptions.map((opt) => (jsx("button", { type: "button", onClick: () => handleFilterChange(filter.key, opt.value === '' ? null : opt.value === 'true'), className: `px-3 py-1.5 text-xs font-medium transition-colors ${currentVal === opt.value
|
|
2795
|
+
? 'bg-accent-500 text-white'
|
|
2796
|
+
: 'bg-white text-ink-600 hover:bg-paper-50'} ${opt.value !== '' ? 'border-l border-paper-300' : ''}`, children: opt.label }, opt.value))) }));
|
|
2797
|
+
}
|
|
2798
|
+
case 'multiSelect': {
|
|
2799
|
+
const selectedValues = Array.isArray(value) ? value : [];
|
|
2800
|
+
const msOptions = filter.options || [];
|
|
2801
|
+
return (jsxs("div", { className: "relative", children: [jsx(Select, { options: [{ value: '', label: `All ${filter.label}` }, ...msOptions.map(o => ({ value: String(o.value), label: o.label }))], value: "", onChange: (newValue) => {
|
|
2802
|
+
if (!newValue) {
|
|
2803
|
+
handleFilterChange(filter.key, []);
|
|
2804
|
+
}
|
|
2805
|
+
else if (!selectedValues.includes(newValue)) {
|
|
2806
|
+
handleFilterChange(filter.key, [...selectedValues, newValue]);
|
|
2807
|
+
}
|
|
2808
|
+
} }), selectedValues.length > 0 && (jsx("div", { className: "flex flex-wrap gap-1 mt-1", children: selectedValues.map((sv) => {
|
|
2809
|
+
const opt = msOptions.find(o => String(o.value) === sv);
|
|
2810
|
+
return (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs bg-accent-100 text-accent-700 rounded-full", children: [opt?.label || sv, jsx("button", { type: "button", onClick: () => handleFilterChange(filter.key, selectedValues.filter(v => v !== sv)), className: "hover:text-accent-900", children: jsx(X, { className: "h-3 w-3" }) })] }, sv));
|
|
2811
|
+
}) }))] }));
|
|
2812
|
+
}
|
|
2734
2813
|
default:
|
|
2735
2814
|
return null;
|
|
2736
2815
|
}
|
|
@@ -2740,6 +2819,237 @@ function FilterBar({ filters, values, onChange, className = '', onClear, showCle
|
|
|
2740
2819
|
return (jsx("div", { className: `bg-white bg-subtle-grain border border-paper-200 rounded-lg shadow-sm p-4 ${className}`, children: jsxs("div", { className: "flex items-start justify-between gap-4 flex-wrap", children: [jsx("div", { className: "flex-1 flex flex-wrap gap-4", children: filters.map((filter) => (jsxs("div", { className: "flex flex-col space-y-1 min-w-[200px]", children: [jsx("label", { className: "label", children: filter.label }), renderFilter(filter)] }, filter.key))) }), showClearButton && (jsx("div", { className: "flex items-end", children: jsx(Button, { variant: "ghost", size: "md", onClick: handleClear, icon: jsx(X, { className: "h-4 w-4" }), iconPosition: "left", children: "Clear" }) }))] }) }));
|
|
2741
2820
|
}
|
|
2742
2821
|
|
|
2822
|
+
const variantClasses$4 = {
|
|
2823
|
+
primary: {
|
|
2824
|
+
default: 'bg-primary-100 text-primary-700 border-primary-200',
|
|
2825
|
+
hover: 'hover:bg-primary-200',
|
|
2826
|
+
close: 'hover:bg-primary-300 text-primary-600',
|
|
2827
|
+
selected: 'bg-primary-200 border-primary-400 ring-2 ring-primary-300',
|
|
2828
|
+
},
|
|
2829
|
+
secondary: {
|
|
2830
|
+
default: 'bg-ink-100 text-ink-700 border-ink-200',
|
|
2831
|
+
hover: 'hover:bg-ink-200',
|
|
2832
|
+
close: 'hover:bg-ink-300 text-ink-600',
|
|
2833
|
+
selected: 'bg-ink-200 border-ink-400 ring-2 ring-ink-300',
|
|
2834
|
+
},
|
|
2835
|
+
success: {
|
|
2836
|
+
default: 'bg-success-100 text-success-700 border-success-200',
|
|
2837
|
+
hover: 'hover:bg-success-200',
|
|
2838
|
+
close: 'hover:bg-success-300 text-success-600',
|
|
2839
|
+
selected: 'bg-success-200 border-success-400 ring-2 ring-success-300',
|
|
2840
|
+
},
|
|
2841
|
+
warning: {
|
|
2842
|
+
default: 'bg-warning-100 text-warning-700 border-warning-200',
|
|
2843
|
+
hover: 'hover:bg-warning-200',
|
|
2844
|
+
close: 'hover:bg-warning-300 text-warning-600',
|
|
2845
|
+
selected: 'bg-warning-200 border-warning-400 ring-2 ring-warning-300',
|
|
2846
|
+
},
|
|
2847
|
+
error: {
|
|
2848
|
+
default: 'bg-error-100 text-error-700 border-error-200',
|
|
2849
|
+
hover: 'hover:bg-error-200',
|
|
2850
|
+
close: 'hover:bg-error-300 text-error-600',
|
|
2851
|
+
selected: 'bg-error-200 border-error-400 ring-2 ring-error-300',
|
|
2852
|
+
},
|
|
2853
|
+
info: {
|
|
2854
|
+
default: 'bg-accent-100 text-accent-700 border-accent-200',
|
|
2855
|
+
hover: 'hover:bg-accent-200',
|
|
2856
|
+
close: 'hover:bg-accent-300 text-accent-600',
|
|
2857
|
+
selected: 'bg-accent-200 border-accent-400 ring-2 ring-accent-300',
|
|
2858
|
+
},
|
|
2859
|
+
};
|
|
2860
|
+
const sizeClasses$b = {
|
|
2861
|
+
sm: {
|
|
2862
|
+
container: 'h-6 px-2 text-xs gap-1',
|
|
2863
|
+
icon: 'h-3 w-3',
|
|
2864
|
+
close: 'h-3 w-3 ml-1',
|
|
2865
|
+
},
|
|
2866
|
+
md: {
|
|
2867
|
+
container: 'h-7 px-2.5 text-sm gap-1.5',
|
|
2868
|
+
icon: 'h-3.5 w-3.5',
|
|
2869
|
+
close: 'h-3.5 w-3.5 ml-1.5',
|
|
2870
|
+
},
|
|
2871
|
+
lg: {
|
|
2872
|
+
container: 'h-8 px-3 text-base gap-2',
|
|
2873
|
+
icon: 'h-4 w-4',
|
|
2874
|
+
close: 'h-4 w-4 ml-2',
|
|
2875
|
+
},
|
|
2876
|
+
};
|
|
2877
|
+
const gapClasses = {
|
|
2878
|
+
xs: 'gap-1',
|
|
2879
|
+
sm: 'gap-1.5',
|
|
2880
|
+
md: 'gap-2',
|
|
2881
|
+
lg: 'gap-3',
|
|
2882
|
+
};
|
|
2883
|
+
/**
|
|
2884
|
+
* Chip - Compact element for displaying values with optional remove functionality
|
|
2885
|
+
*
|
|
2886
|
+
* @example Basic chip
|
|
2887
|
+
* ```tsx
|
|
2888
|
+
* <Chip>Tag Name</Chip>
|
|
2889
|
+
* ```
|
|
2890
|
+
*
|
|
2891
|
+
* @example Removable chip
|
|
2892
|
+
* ```tsx
|
|
2893
|
+
* <Chip onClose={() => removeTag(tag)}>
|
|
2894
|
+
* {tag.name}
|
|
2895
|
+
* </Chip>
|
|
2896
|
+
* ```
|
|
2897
|
+
*
|
|
2898
|
+
* @example With icon and selected state
|
|
2899
|
+
* ```tsx
|
|
2900
|
+
* <Chip
|
|
2901
|
+
* icon={<Star className="h-3 w-3" />}
|
|
2902
|
+
* selected={isSelected}
|
|
2903
|
+
* onClick={() => toggleSelection()}
|
|
2904
|
+
* >
|
|
2905
|
+
* Favorite
|
|
2906
|
+
* </Chip>
|
|
2907
|
+
* ```
|
|
2908
|
+
*/
|
|
2909
|
+
function Chip({ children, variant = 'secondary', size = 'md', onClose, icon, disabled = false, className = '', onClick, selected = false, maxWidth, chipKey, }) {
|
|
2910
|
+
const variantStyle = variantClasses$4[variant];
|
|
2911
|
+
const sizeStyle = sizeClasses$b[size];
|
|
2912
|
+
const isClickable = !disabled && (onClick || onClose);
|
|
2913
|
+
return (jsxs("div", { className: `
|
|
2914
|
+
inline-flex items-center rounded-full border font-medium
|
|
2915
|
+
transition-colors
|
|
2916
|
+
${selected ? variantStyle.selected : variantStyle.default}
|
|
2917
|
+
${isClickable && !disabled && !selected ? variantStyle.hover : ''}
|
|
2918
|
+
${sizeStyle.container}
|
|
2919
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
|
|
2920
|
+
${onClick && !disabled ? 'cursor-pointer' : ''}
|
|
2921
|
+
${className}
|
|
2922
|
+
`, onClick: onClick && !disabled ? onClick : undefined, role: onClick ? 'button' : undefined, "aria-disabled": disabled, "aria-pressed": onClick ? selected : undefined, "data-chip-key": chipKey, style: { maxWidth: maxWidth || undefined }, children: [icon && (jsx("span", { className: `flex-shrink-0 ${sizeStyle.icon}`, children: icon })), jsx("span", { className: "truncate", children: children }), onClose && (jsx("button", { type: "button", onClick: (e) => {
|
|
2923
|
+
e.stopPropagation();
|
|
2924
|
+
if (!disabled)
|
|
2925
|
+
onClose();
|
|
2926
|
+
}, disabled: disabled, className: `
|
|
2927
|
+
flex-shrink-0 rounded-full transition-colors
|
|
2928
|
+
${variantStyle.close}
|
|
2929
|
+
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
|
|
2930
|
+
${sizeStyle.close}
|
|
2931
|
+
`, "aria-label": "Remove", children: jsx(X, { className: "w-full h-full" }) }))] }));
|
|
2932
|
+
}
|
|
2933
|
+
/**
|
|
2934
|
+
* ChipGroup - Container for multiple chips with layout and selection support
|
|
2935
|
+
*
|
|
2936
|
+
* @example Basic group
|
|
2937
|
+
* ```tsx
|
|
2938
|
+
* <ChipGroup wrap gap="sm">
|
|
2939
|
+
* {tags.map(tag => (
|
|
2940
|
+
* <Chip key={tag.id} onClose={() => removeTag(tag)}>
|
|
2941
|
+
* {tag.name}
|
|
2942
|
+
* </Chip>
|
|
2943
|
+
* ))}
|
|
2944
|
+
* </ChipGroup>
|
|
2945
|
+
* ```
|
|
2946
|
+
*
|
|
2947
|
+
* @example Selectable group (single)
|
|
2948
|
+
* ```tsx
|
|
2949
|
+
* <ChipGroup
|
|
2950
|
+
* selectionMode="single"
|
|
2951
|
+
* selectedKeys={[selectedCategory]}
|
|
2952
|
+
* onSelectionChange={(keys) => setSelectedCategory(keys[0])}
|
|
2953
|
+
* >
|
|
2954
|
+
* <Chip chipKey="all">All</Chip>
|
|
2955
|
+
* <Chip chipKey="active">Active</Chip>
|
|
2956
|
+
* <Chip chipKey="archived">Archived</Chip>
|
|
2957
|
+
* </ChipGroup>
|
|
2958
|
+
* ```
|
|
2959
|
+
*
|
|
2960
|
+
* @example Multi-select group
|
|
2961
|
+
* ```tsx
|
|
2962
|
+
* <ChipGroup
|
|
2963
|
+
* selectionMode="multiple"
|
|
2964
|
+
* selectedKeys={selectedTags}
|
|
2965
|
+
* onSelectionChange={setSelectedTags}
|
|
2966
|
+
* wrap
|
|
2967
|
+
* >
|
|
2968
|
+
* {availableTags.map(tag => (
|
|
2969
|
+
* <Chip key={tag} chipKey={tag}>{tag}</Chip>
|
|
2970
|
+
* ))}
|
|
2971
|
+
* </ChipGroup>
|
|
2972
|
+
* ```
|
|
2973
|
+
*/
|
|
2974
|
+
function ChipGroup({ children, direction = 'horizontal', wrap = false, gap = 'sm', selectionMode = 'none', selectedKeys = [], onSelectionChange, className = '', }) {
|
|
2975
|
+
const handleChipClick = (chipKey) => {
|
|
2976
|
+
if (selectionMode === 'none' || !onSelectionChange)
|
|
2977
|
+
return;
|
|
2978
|
+
if (selectionMode === 'single') {
|
|
2979
|
+
// Toggle single selection
|
|
2980
|
+
if (selectedKeys.includes(chipKey)) {
|
|
2981
|
+
onSelectionChange([]);
|
|
2982
|
+
}
|
|
2983
|
+
else {
|
|
2984
|
+
onSelectionChange([chipKey]);
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
else if (selectionMode === 'multiple') {
|
|
2988
|
+
// Toggle in array
|
|
2989
|
+
if (selectedKeys.includes(chipKey)) {
|
|
2990
|
+
onSelectionChange(selectedKeys.filter(k => k !== chipKey));
|
|
2991
|
+
}
|
|
2992
|
+
else {
|
|
2993
|
+
onSelectionChange([...selectedKeys, chipKey]);
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
// Clone children to inject selection props
|
|
2998
|
+
const enhancedChildren = Children.map(children, (child) => {
|
|
2999
|
+
if (!isValidElement(child))
|
|
3000
|
+
return child;
|
|
3001
|
+
const chipKey = child.props.chipKey;
|
|
3002
|
+
if (!chipKey || selectionMode === 'none')
|
|
3003
|
+
return child;
|
|
3004
|
+
const isSelected = selectedKeys.includes(chipKey);
|
|
3005
|
+
return cloneElement(child, {
|
|
3006
|
+
...child.props,
|
|
3007
|
+
selected: isSelected,
|
|
3008
|
+
onClick: () => {
|
|
3009
|
+
// Call original onClick if exists
|
|
3010
|
+
if (child.props.onClick) {
|
|
3011
|
+
child.props.onClick();
|
|
3012
|
+
}
|
|
3013
|
+
handleChipClick(chipKey);
|
|
3014
|
+
},
|
|
3015
|
+
});
|
|
3016
|
+
});
|
|
3017
|
+
return (jsx("div", { className: `
|
|
3018
|
+
flex
|
|
3019
|
+
${direction === 'vertical' ? 'flex-col' : 'flex-row'}
|
|
3020
|
+
${wrap ? 'flex-wrap' : ''}
|
|
3021
|
+
${gapClasses[gap]}
|
|
3022
|
+
${className}
|
|
3023
|
+
`, role: selectionMode !== 'none' ? 'group' : undefined, "aria-label": selectionMode !== 'none' ? 'Chip selection group' : undefined, children: enhancedChildren }));
|
|
3024
|
+
}
|
|
3025
|
+
|
|
3026
|
+
function FilterPills({ pills, onRemove, onClearAll, totalCount, className = '', }) {
|
|
3027
|
+
if (pills.length === 0)
|
|
3028
|
+
return null;
|
|
3029
|
+
return (jsxs("div", { className: `flex items-center gap-2 px-4 py-2 border-b border-paper-200 bg-paper-50 ${className}`, children: [jsx(Filter, { className: "h-3.5 w-3.5 text-ink-400 shrink-0" }), jsxs("div", { className: "flex items-center gap-1.5 flex-wrap flex-1", children: [pills.map((pill) => (jsxs(Chip, { size: "sm", variant: "primary", onClose: () => onRemove(pill.key), children: [pill.label, ": ", pill.displayValue] }, pill.key))), pills.length >= 2 && (jsx("button", { type: "button", onClick: onClearAll, className: "text-xs text-ink-500 hover:text-ink-700 underline underline-offset-2 ml-1", children: "Clear all" }))] }), totalCount !== undefined && (jsxs("span", { className: "text-xs text-ink-500 shrink-0 tabular-nums", children: [totalCount.toLocaleString(), " ", totalCount === 1 ? 'record' : 'records'] }))] }));
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
const LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
|
3033
|
+
function LetterNav({ activeLetter, onChange, availableLetters, className = '', }) {
|
|
3034
|
+
const hasAvailability = availableLetters && availableLetters.length > 0;
|
|
3035
|
+
const availableSet = hasAvailability
|
|
3036
|
+
? new Set(availableLetters.map((l) => l.toUpperCase()))
|
|
3037
|
+
: null;
|
|
3038
|
+
return (jsxs("div", { className: `flex items-center gap-0.5 px-4 py-1.5 border-b border-paper-200 bg-white overflow-x-auto ${className}`, children: [jsx("button", { type: "button", onClick: () => onChange(null), className: `px-2 py-1 text-xs font-medium rounded transition-colors ${activeLetter === null
|
|
3039
|
+
? 'bg-accent-500 text-white'
|
|
3040
|
+
: 'text-ink-600 hover:bg-paper-100'}`, children: "All" }), LETTERS.map((letter) => {
|
|
3041
|
+
const isActive = activeLetter === letter;
|
|
3042
|
+
const isAvailable = !availableSet || availableSet.has(letter);
|
|
3043
|
+
return (jsx("button", { type: "button", onClick: () => onChange(isActive ? null : letter), className: `w-7 h-7 text-xs font-medium rounded transition-colors ${isActive
|
|
3044
|
+
? 'bg-accent-500 text-white'
|
|
3045
|
+
: isAvailable
|
|
3046
|
+
? 'text-ink-600 hover:bg-paper-100'
|
|
3047
|
+
: 'text-ink-300'}`, children: letter }, letter));
|
|
3048
|
+
}), jsx("button", { type: "button", onClick: () => onChange(activeLetter === '#' ? null : '#'), className: `px-2 py-1 text-xs font-medium rounded transition-colors ${activeLetter === '#'
|
|
3049
|
+
? 'bg-accent-500 text-white'
|
|
3050
|
+
: 'text-ink-600 hover:bg-paper-100'}`, children: "#" })] }));
|
|
3051
|
+
}
|
|
3052
|
+
|
|
2743
3053
|
function Loading({ variant = 'spinner', size = 'md', text }) {
|
|
2744
3054
|
const sizeClasses = {
|
|
2745
3055
|
sm: 'h-4 w-4',
|
|
@@ -4590,7 +4900,7 @@ function BottomSheetActions({ children, className = '' }) {
|
|
|
4590
4900
|
|
|
4591
4901
|
// Selector for all focusable elements
|
|
4592
4902
|
const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
4593
|
-
const sizeClasses$
|
|
4903
|
+
const sizeClasses$a = {
|
|
4594
4904
|
sm: 'max-w-md',
|
|
4595
4905
|
md: 'max-w-lg',
|
|
4596
4906
|
lg: 'max-w-2xl',
|
|
@@ -4779,7 +5089,7 @@ function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton
|
|
|
4779
5089
|
return createPortal(jsx(BottomSheet, { isOpen: isOpen, onClose: onClose, title: title, height: mobileHeight, showHandle: mobileShowHandle, showCloseButton: showCloseButton, children: children }), document.body);
|
|
4780
5090
|
}
|
|
4781
5091
|
// Render as standard modal on desktop
|
|
4782
|
-
const modalContent = (jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onMouseDown: handleBackdropMouseDown, onClick: handleBackdropClick, children: jsxs("div", { ref: modalRef, className: `${sizeClasses$
|
|
5092
|
+
const modalContent = (jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onMouseDown: handleBackdropMouseDown, onClick: handleBackdropClick, children: jsxs("div", { ref: modalRef, className: `${sizeClasses$a[size]} w-full bg-white bg-subtle-grain rounded-xl shadow-2xl border border-paper-200 ${getAnimationClass()}`, role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, tabIndex: -1, children: [jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-paper-200", children: [jsx("h3", { id: titleId, className: "text-lg font-medium text-ink-900", children: title }), showCloseButton && (jsx("button", { onClick: onClose, className: "text-ink-400 hover:text-ink-600 transition-colors", "aria-label": "Close modal", children: jsx(X, { className: "h-5 w-5" }) }))] }), jsx("div", { className: `px-6 py-4 ${scrollable || maxHeight ? 'overflow-y-auto' : ''}`, style: {
|
|
4783
5093
|
maxHeight: maxHeight || (scrollable ? 'calc(100vh - 200px)' : undefined),
|
|
4784
5094
|
}, children: children })] }) }));
|
|
4785
5095
|
return createPortal(modalContent, document.body);
|
|
@@ -5850,7 +6160,7 @@ function Alert({ variant = 'info', title, children, onClose, className = '', act
|
|
|
5850
6160
|
return (jsx("div", { className: `rounded-lg border p-4 ${styles.container} ${className}`, role: "alert", children: jsxs("div", { className: "flex items-start gap-3", children: [jsx("div", { className: "flex-shrink-0 mt-0.5", children: styles.icon }), jsxs("div", { className: "flex-1 min-w-0", children: [title && jsx("h4", { className: "text-sm font-medium mb-1", children: title }), jsx("div", { className: "text-sm", children: children }), actions.length > 0 && (jsx("div", { className: "flex gap-2 mt-3", children: actions.map((action, index) => (jsx("button", { onClick: action.onClick, className: getButtonStyles(action.variant), children: action.label }, index))) }))] }), onClose && (jsx("button", { onClick: onClose, className: "flex-shrink-0 text-current opacity-70 hover:opacity-100 transition-opacity", "aria-label": "Close alert", children: jsx(X, { className: "h-4 w-4" }) }))] }) }));
|
|
5851
6161
|
}
|
|
5852
6162
|
|
|
5853
|
-
const sizeClasses$
|
|
6163
|
+
const sizeClasses$9 = {
|
|
5854
6164
|
left: {
|
|
5855
6165
|
sm: 'w-64',
|
|
5856
6166
|
md: 'w-96',
|
|
@@ -5929,7 +6239,7 @@ function Drawer({ isOpen, onClose, title, children, placement = 'right', size =
|
|
|
5929
6239
|
const isHorizontal = placement === 'left' || placement === 'right';
|
|
5930
6240
|
return (jsxs("div", { className: "fixed inset-0 z-50 flex", children: [showOverlay && (jsx("div", { className: "fixed inset-0 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onClick: handleOverlayClick, "aria-hidden": "true" })), jsxs("div", { className: `
|
|
5931
6241
|
fixed ${placementClasses[placement]}
|
|
5932
|
-
${sizeClasses$
|
|
6242
|
+
${sizeClasses$9[placement][size]}
|
|
5933
6243
|
bg-white border-paper-200 shadow-2xl
|
|
5934
6244
|
${isHorizontal ? 'border-r' : 'border-b'}
|
|
5935
6245
|
${animationClasses[placement].enter}
|
|
@@ -6071,14 +6381,14 @@ function useConfirmDialog() {
|
|
|
6071
6381
|
};
|
|
6072
6382
|
}
|
|
6073
6383
|
|
|
6074
|
-
const sizeClasses$
|
|
6384
|
+
const sizeClasses$8 = {
|
|
6075
6385
|
sm: 'h-3.5 w-3.5',
|
|
6076
6386
|
md: 'h-4 w-4',
|
|
6077
6387
|
lg: 'h-5 w-5',
|
|
6078
6388
|
};
|
|
6079
6389
|
function HelpTooltip({ content, icon = 'help', size = 'md', position = 'top', className = '', }) {
|
|
6080
6390
|
const IconComponent = icon === 'info' ? Info : HelpCircle;
|
|
6081
|
-
return (jsx(Tooltip, { content: content, position: position, children: jsx("span", { className: `inline-flex items-center justify-center text-ink-400 hover:text-ink-600 cursor-help transition-colors ${className}`, role: "button", "aria-label": "Help", tabIndex: 0, children: jsx(IconComponent, { className: sizeClasses$
|
|
6391
|
+
return (jsx(Tooltip, { content: content, position: position, children: jsx("span", { className: `inline-flex items-center justify-center text-ink-400 hover:text-ink-600 cursor-help transition-colors ${className}`, role: "button", "aria-label": "Help", tabIndex: 0, children: jsx(IconComponent, { className: sizeClasses$8[size] }) }) }));
|
|
6082
6392
|
}
|
|
6083
6393
|
|
|
6084
6394
|
/**
|
|
@@ -8456,210 +8766,6 @@ function MenuDivider() {
|
|
|
8456
8766
|
return { divider: true, id: `divider-${Date.now()}`, label: '' };
|
|
8457
8767
|
}
|
|
8458
8768
|
|
|
8459
|
-
const variantClasses$4 = {
|
|
8460
|
-
primary: {
|
|
8461
|
-
default: 'bg-primary-100 text-primary-700 border-primary-200',
|
|
8462
|
-
hover: 'hover:bg-primary-200',
|
|
8463
|
-
close: 'hover:bg-primary-300 text-primary-600',
|
|
8464
|
-
selected: 'bg-primary-200 border-primary-400 ring-2 ring-primary-300',
|
|
8465
|
-
},
|
|
8466
|
-
secondary: {
|
|
8467
|
-
default: 'bg-ink-100 text-ink-700 border-ink-200',
|
|
8468
|
-
hover: 'hover:bg-ink-200',
|
|
8469
|
-
close: 'hover:bg-ink-300 text-ink-600',
|
|
8470
|
-
selected: 'bg-ink-200 border-ink-400 ring-2 ring-ink-300',
|
|
8471
|
-
},
|
|
8472
|
-
success: {
|
|
8473
|
-
default: 'bg-success-100 text-success-700 border-success-200',
|
|
8474
|
-
hover: 'hover:bg-success-200',
|
|
8475
|
-
close: 'hover:bg-success-300 text-success-600',
|
|
8476
|
-
selected: 'bg-success-200 border-success-400 ring-2 ring-success-300',
|
|
8477
|
-
},
|
|
8478
|
-
warning: {
|
|
8479
|
-
default: 'bg-warning-100 text-warning-700 border-warning-200',
|
|
8480
|
-
hover: 'hover:bg-warning-200',
|
|
8481
|
-
close: 'hover:bg-warning-300 text-warning-600',
|
|
8482
|
-
selected: 'bg-warning-200 border-warning-400 ring-2 ring-warning-300',
|
|
8483
|
-
},
|
|
8484
|
-
error: {
|
|
8485
|
-
default: 'bg-error-100 text-error-700 border-error-200',
|
|
8486
|
-
hover: 'hover:bg-error-200',
|
|
8487
|
-
close: 'hover:bg-error-300 text-error-600',
|
|
8488
|
-
selected: 'bg-error-200 border-error-400 ring-2 ring-error-300',
|
|
8489
|
-
},
|
|
8490
|
-
info: {
|
|
8491
|
-
default: 'bg-accent-100 text-accent-700 border-accent-200',
|
|
8492
|
-
hover: 'hover:bg-accent-200',
|
|
8493
|
-
close: 'hover:bg-accent-300 text-accent-600',
|
|
8494
|
-
selected: 'bg-accent-200 border-accent-400 ring-2 ring-accent-300',
|
|
8495
|
-
},
|
|
8496
|
-
};
|
|
8497
|
-
const sizeClasses$8 = {
|
|
8498
|
-
sm: {
|
|
8499
|
-
container: 'h-6 px-2 text-xs gap-1',
|
|
8500
|
-
icon: 'h-3 w-3',
|
|
8501
|
-
close: 'h-3 w-3 ml-1',
|
|
8502
|
-
},
|
|
8503
|
-
md: {
|
|
8504
|
-
container: 'h-7 px-2.5 text-sm gap-1.5',
|
|
8505
|
-
icon: 'h-3.5 w-3.5',
|
|
8506
|
-
close: 'h-3.5 w-3.5 ml-1.5',
|
|
8507
|
-
},
|
|
8508
|
-
lg: {
|
|
8509
|
-
container: 'h-8 px-3 text-base gap-2',
|
|
8510
|
-
icon: 'h-4 w-4',
|
|
8511
|
-
close: 'h-4 w-4 ml-2',
|
|
8512
|
-
},
|
|
8513
|
-
};
|
|
8514
|
-
const gapClasses = {
|
|
8515
|
-
xs: 'gap-1',
|
|
8516
|
-
sm: 'gap-1.5',
|
|
8517
|
-
md: 'gap-2',
|
|
8518
|
-
lg: 'gap-3',
|
|
8519
|
-
};
|
|
8520
|
-
/**
|
|
8521
|
-
* Chip - Compact element for displaying values with optional remove functionality
|
|
8522
|
-
*
|
|
8523
|
-
* @example Basic chip
|
|
8524
|
-
* ```tsx
|
|
8525
|
-
* <Chip>Tag Name</Chip>
|
|
8526
|
-
* ```
|
|
8527
|
-
*
|
|
8528
|
-
* @example Removable chip
|
|
8529
|
-
* ```tsx
|
|
8530
|
-
* <Chip onClose={() => removeTag(tag)}>
|
|
8531
|
-
* {tag.name}
|
|
8532
|
-
* </Chip>
|
|
8533
|
-
* ```
|
|
8534
|
-
*
|
|
8535
|
-
* @example With icon and selected state
|
|
8536
|
-
* ```tsx
|
|
8537
|
-
* <Chip
|
|
8538
|
-
* icon={<Star className="h-3 w-3" />}
|
|
8539
|
-
* selected={isSelected}
|
|
8540
|
-
* onClick={() => toggleSelection()}
|
|
8541
|
-
* >
|
|
8542
|
-
* Favorite
|
|
8543
|
-
* </Chip>
|
|
8544
|
-
* ```
|
|
8545
|
-
*/
|
|
8546
|
-
function Chip({ children, variant = 'secondary', size = 'md', onClose, icon, disabled = false, className = '', onClick, selected = false, maxWidth, chipKey, }) {
|
|
8547
|
-
const variantStyle = variantClasses$4[variant];
|
|
8548
|
-
const sizeStyle = sizeClasses$8[size];
|
|
8549
|
-
const isClickable = !disabled && (onClick || onClose);
|
|
8550
|
-
return (jsxs("div", { className: `
|
|
8551
|
-
inline-flex items-center rounded-full border font-medium
|
|
8552
|
-
transition-colors
|
|
8553
|
-
${selected ? variantStyle.selected : variantStyle.default}
|
|
8554
|
-
${isClickable && !disabled && !selected ? variantStyle.hover : ''}
|
|
8555
|
-
${sizeStyle.container}
|
|
8556
|
-
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
|
|
8557
|
-
${onClick && !disabled ? 'cursor-pointer' : ''}
|
|
8558
|
-
${className}
|
|
8559
|
-
`, onClick: onClick && !disabled ? onClick : undefined, role: onClick ? 'button' : undefined, "aria-disabled": disabled, "aria-pressed": onClick ? selected : undefined, "data-chip-key": chipKey, style: { maxWidth: maxWidth || undefined }, children: [icon && (jsx("span", { className: `flex-shrink-0 ${sizeStyle.icon}`, children: icon })), jsx("span", { className: "truncate", children: children }), onClose && (jsx("button", { type: "button", onClick: (e) => {
|
|
8560
|
-
e.stopPropagation();
|
|
8561
|
-
if (!disabled)
|
|
8562
|
-
onClose();
|
|
8563
|
-
}, disabled: disabled, className: `
|
|
8564
|
-
flex-shrink-0 rounded-full transition-colors
|
|
8565
|
-
${variantStyle.close}
|
|
8566
|
-
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
|
|
8567
|
-
${sizeStyle.close}
|
|
8568
|
-
`, "aria-label": "Remove", children: jsx(X, { className: "w-full h-full" }) }))] }));
|
|
8569
|
-
}
|
|
8570
|
-
/**
|
|
8571
|
-
* ChipGroup - Container for multiple chips with layout and selection support
|
|
8572
|
-
*
|
|
8573
|
-
* @example Basic group
|
|
8574
|
-
* ```tsx
|
|
8575
|
-
* <ChipGroup wrap gap="sm">
|
|
8576
|
-
* {tags.map(tag => (
|
|
8577
|
-
* <Chip key={tag.id} onClose={() => removeTag(tag)}>
|
|
8578
|
-
* {tag.name}
|
|
8579
|
-
* </Chip>
|
|
8580
|
-
* ))}
|
|
8581
|
-
* </ChipGroup>
|
|
8582
|
-
* ```
|
|
8583
|
-
*
|
|
8584
|
-
* @example Selectable group (single)
|
|
8585
|
-
* ```tsx
|
|
8586
|
-
* <ChipGroup
|
|
8587
|
-
* selectionMode="single"
|
|
8588
|
-
* selectedKeys={[selectedCategory]}
|
|
8589
|
-
* onSelectionChange={(keys) => setSelectedCategory(keys[0])}
|
|
8590
|
-
* >
|
|
8591
|
-
* <Chip chipKey="all">All</Chip>
|
|
8592
|
-
* <Chip chipKey="active">Active</Chip>
|
|
8593
|
-
* <Chip chipKey="archived">Archived</Chip>
|
|
8594
|
-
* </ChipGroup>
|
|
8595
|
-
* ```
|
|
8596
|
-
*
|
|
8597
|
-
* @example Multi-select group
|
|
8598
|
-
* ```tsx
|
|
8599
|
-
* <ChipGroup
|
|
8600
|
-
* selectionMode="multiple"
|
|
8601
|
-
* selectedKeys={selectedTags}
|
|
8602
|
-
* onSelectionChange={setSelectedTags}
|
|
8603
|
-
* wrap
|
|
8604
|
-
* >
|
|
8605
|
-
* {availableTags.map(tag => (
|
|
8606
|
-
* <Chip key={tag} chipKey={tag}>{tag}</Chip>
|
|
8607
|
-
* ))}
|
|
8608
|
-
* </ChipGroup>
|
|
8609
|
-
* ```
|
|
8610
|
-
*/
|
|
8611
|
-
function ChipGroup({ children, direction = 'horizontal', wrap = false, gap = 'sm', selectionMode = 'none', selectedKeys = [], onSelectionChange, className = '', }) {
|
|
8612
|
-
const handleChipClick = (chipKey) => {
|
|
8613
|
-
if (selectionMode === 'none' || !onSelectionChange)
|
|
8614
|
-
return;
|
|
8615
|
-
if (selectionMode === 'single') {
|
|
8616
|
-
// Toggle single selection
|
|
8617
|
-
if (selectedKeys.includes(chipKey)) {
|
|
8618
|
-
onSelectionChange([]);
|
|
8619
|
-
}
|
|
8620
|
-
else {
|
|
8621
|
-
onSelectionChange([chipKey]);
|
|
8622
|
-
}
|
|
8623
|
-
}
|
|
8624
|
-
else if (selectionMode === 'multiple') {
|
|
8625
|
-
// Toggle in array
|
|
8626
|
-
if (selectedKeys.includes(chipKey)) {
|
|
8627
|
-
onSelectionChange(selectedKeys.filter(k => k !== chipKey));
|
|
8628
|
-
}
|
|
8629
|
-
else {
|
|
8630
|
-
onSelectionChange([...selectedKeys, chipKey]);
|
|
8631
|
-
}
|
|
8632
|
-
}
|
|
8633
|
-
};
|
|
8634
|
-
// Clone children to inject selection props
|
|
8635
|
-
const enhancedChildren = Children.map(children, (child) => {
|
|
8636
|
-
if (!isValidElement(child))
|
|
8637
|
-
return child;
|
|
8638
|
-
const chipKey = child.props.chipKey;
|
|
8639
|
-
if (!chipKey || selectionMode === 'none')
|
|
8640
|
-
return child;
|
|
8641
|
-
const isSelected = selectedKeys.includes(chipKey);
|
|
8642
|
-
return cloneElement(child, {
|
|
8643
|
-
...child.props,
|
|
8644
|
-
selected: isSelected,
|
|
8645
|
-
onClick: () => {
|
|
8646
|
-
// Call original onClick if exists
|
|
8647
|
-
if (child.props.onClick) {
|
|
8648
|
-
child.props.onClick();
|
|
8649
|
-
}
|
|
8650
|
-
handleChipClick(chipKey);
|
|
8651
|
-
},
|
|
8652
|
-
});
|
|
8653
|
-
});
|
|
8654
|
-
return (jsx("div", { className: `
|
|
8655
|
-
flex
|
|
8656
|
-
${direction === 'vertical' ? 'flex-col' : 'flex-row'}
|
|
8657
|
-
${wrap ? 'flex-wrap' : ''}
|
|
8658
|
-
${gapClasses[gap]}
|
|
8659
|
-
${className}
|
|
8660
|
-
`, role: selectionMode !== 'none' ? 'group' : undefined, "aria-label": selectionMode !== 'none' ? 'Chip selection group' : undefined, children: enhancedChildren }));
|
|
8661
|
-
}
|
|
8662
|
-
|
|
8663
8769
|
const sizeClasses$7 = {
|
|
8664
8770
|
sm: {
|
|
8665
8771
|
item: 'py-1.5 px-2',
|
|
@@ -11779,7 +11885,7 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
|
|
|
11779
11885
|
}) })] }));
|
|
11780
11886
|
}
|
|
11781
11887
|
|
|
11782
|
-
function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = true, maxPageNumbers = 5, showPageJump = false, }) {
|
|
11888
|
+
function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = true, maxPageNumbers = 5, showPageJump = false, totalItems, pageSize, pageSizeOptions, onPageSizeChange, showRecordCount = false, }) {
|
|
11783
11889
|
const [jumpValue, setJumpValue] = useState('');
|
|
11784
11890
|
const getPageNumbers = () => {
|
|
11785
11891
|
const pages = [];
|
|
@@ -11820,16 +11926,20 @@ function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = t
|
|
|
11820
11926
|
setJumpValue('');
|
|
11821
11927
|
}
|
|
11822
11928
|
};
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11929
|
+
const showLeftSection = showRecordCount && totalItems !== undefined && pageSize;
|
|
11930
|
+
const showRightSection = onPageSizeChange && pageSizeOptions && pageSizeOptions.length > 0;
|
|
11931
|
+
const rangeStart = totalItems ? (currentPage - 1) * (pageSize || 0) + 1 : 0;
|
|
11932
|
+
const rangeEnd = totalItems ? Math.min(currentPage * (pageSize || 0), totalItems) : 0;
|
|
11933
|
+
return (jsxs("nav", { className: `flex items-center gap-2 ${showLeftSection || showRightSection ? 'justify-between' : 'justify-center'}`, "aria-label": "Pagination", children: [showLeftSection ? (jsxs("span", { className: "text-sm text-ink-500 tabular-nums shrink-0", children: ["Showing ", rangeStart.toLocaleString(), "\u2013", rangeEnd.toLocaleString(), " of ", totalItems.toLocaleString()] })) : showRightSection ? jsx("div", {}) : null, jsxs("div", { className: "flex items-center gap-2", children: [jsxs("button", { onClick: () => onPageChange(currentPage - 1), disabled: currentPage === 1, className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-ink-700 bg-white border border-paper-300 rounded-lg hover:bg-paper-50 hover:border-paper-400 disabled:opacity-40 disabled:cursor-not-allowed transition-all shadow-xs hover:shadow-sm", "aria-label": "Previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Previous" })] }), showPageNumbers && (jsx("div", { className: "flex items-center gap-1", children: pageNumbers.map((page, index) => {
|
|
11934
|
+
if (page === '...') {
|
|
11935
|
+
return (jsx("span", { className: "px-3 py-2 text-ink-500", children: "..." }, `ellipsis-${index}`));
|
|
11936
|
+
}
|
|
11937
|
+
const pageNum = page;
|
|
11938
|
+
const isActive = pageNum === currentPage;
|
|
11939
|
+
return (jsx("button", { onClick: () => onPageChange(pageNum), className: `px-3 py-2 text-sm font-medium rounded-lg transition-all ${isActive
|
|
11940
|
+
? 'bg-accent-500 text-white shadow-sm'
|
|
11941
|
+
: 'text-ink-700 bg-white border border-paper-300 hover:bg-paper-50 hover:border-paper-400'}`, "aria-label": `Page ${pageNum}`, "aria-current": isActive ? 'page' : undefined, children: pageNum }, pageNum));
|
|
11942
|
+
}) })), jsxs("button", { onClick: () => onPageChange(currentPage + 1), disabled: currentPage === totalPages, className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-ink-700 bg-white border border-paper-300 rounded-lg hover:bg-paper-50 hover:border-paper-400 disabled:opacity-40 disabled:cursor-not-allowed transition-all shadow-xs hover:shadow-sm", "aria-label": "Next page", children: [jsx("span", { className: "hidden sm:inline", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4" })] }), showPageJump && (jsxs("form", { onSubmit: handlePageJump, className: "flex items-center gap-2 ml-2", children: [jsx("span", { className: "text-sm text-ink-600 hidden sm:inline", children: "Go to:" }), jsx("input", { type: "number", min: "1", max: totalPages, value: jumpValue, onChange: (e) => setJumpValue(e.target.value), placeholder: "#", className: "w-16 px-2 py-1.5 text-sm text-center border border-paper-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400", "aria-label": "Jump to page" }), jsx("button", { type: "submit", disabled: !jumpValue, className: "px-3 py-1.5 text-sm font-medium text-white bg-accent-500 rounded-lg hover:bg-accent-600 disabled:opacity-40 disabled:cursor-not-allowed transition-all", children: "Go" })] }))] }), showRightSection ? (jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [jsx("span", { className: "text-sm text-ink-500 hidden sm:inline", children: "Per page:" }), jsx("select", { value: pageSize || pageSizeOptions[0], onChange: (e) => onPageSizeChange(Number(e.target.value)), className: "px-2 py-1.5 text-sm border border-paper-300 rounded-lg bg-white text-ink-700 focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400 cursor-pointer", "aria-label": "Items per page", children: pageSizeOptions.map((size) => (jsx("option", { value: size, children: size }, size))) })] })) : showLeftSection ? jsx("div", {}) : null] }));
|
|
11833
11943
|
}
|
|
11834
11944
|
|
|
11835
11945
|
function StepIndicator({ steps, currentStep, variant = 'horizontal', onStepClick, }) {
|
|
@@ -15686,52 +15796,44 @@ function getAugmentedNamespace(n) {
|
|
|
15686
15796
|
* (A1, A1:C5, ...)
|
|
15687
15797
|
*/
|
|
15688
15798
|
|
|
15689
|
-
|
|
15690
|
-
var hasRequiredCollection;
|
|
15691
|
-
|
|
15692
|
-
function requireCollection () {
|
|
15693
|
-
if (hasRequiredCollection) return collection;
|
|
15694
|
-
hasRequiredCollection = 1;
|
|
15695
|
-
class Collection {
|
|
15799
|
+
let Collection$3 = class Collection {
|
|
15696
15800
|
|
|
15697
|
-
|
|
15698
|
-
|
|
15699
|
-
|
|
15700
|
-
|
|
15701
|
-
|
|
15702
|
-
|
|
15703
|
-
|
|
15704
|
-
|
|
15705
|
-
|
|
15706
|
-
|
|
15707
|
-
|
|
15801
|
+
constructor(data, refs) {
|
|
15802
|
+
if (data == null && refs == null) {
|
|
15803
|
+
this._data = [];
|
|
15804
|
+
this._refs = [];
|
|
15805
|
+
} else {
|
|
15806
|
+
if (data.length !== refs.length)
|
|
15807
|
+
throw Error('Collection: data length should match references length.');
|
|
15808
|
+
this._data = data;
|
|
15809
|
+
this._refs = refs;
|
|
15810
|
+
}
|
|
15811
|
+
}
|
|
15708
15812
|
|
|
15709
|
-
|
|
15710
|
-
|
|
15711
|
-
|
|
15813
|
+
get data() {
|
|
15814
|
+
return this._data;
|
|
15815
|
+
}
|
|
15712
15816
|
|
|
15713
|
-
|
|
15714
|
-
|
|
15715
|
-
|
|
15817
|
+
get refs() {
|
|
15818
|
+
return this._refs;
|
|
15819
|
+
}
|
|
15716
15820
|
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
|
|
15821
|
+
get length() {
|
|
15822
|
+
return this._data.length;
|
|
15823
|
+
}
|
|
15720
15824
|
|
|
15721
|
-
|
|
15722
|
-
|
|
15723
|
-
|
|
15724
|
-
|
|
15725
|
-
|
|
15726
|
-
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
|
|
15825
|
+
/**
|
|
15826
|
+
* Add data and references to this collection.
|
|
15827
|
+
* @param {{}} obj - data
|
|
15828
|
+
* @param {{}} ref - reference
|
|
15829
|
+
*/
|
|
15830
|
+
add(obj, ref) {
|
|
15831
|
+
this._data.push(obj);
|
|
15832
|
+
this._refs.push(ref);
|
|
15833
|
+
}
|
|
15834
|
+
};
|
|
15731
15835
|
|
|
15732
|
-
|
|
15733
|
-
return collection;
|
|
15734
|
-
}
|
|
15836
|
+
var collection = Collection$3;
|
|
15735
15837
|
|
|
15736
15838
|
var helpers;
|
|
15737
15839
|
var hasRequiredHelpers;
|
|
@@ -15740,7 +15842,7 @@ function requireHelpers () {
|
|
|
15740
15842
|
if (hasRequiredHelpers) return helpers;
|
|
15741
15843
|
hasRequiredHelpers = 1;
|
|
15742
15844
|
const FormulaError = requireError();
|
|
15743
|
-
const Collection =
|
|
15845
|
+
const Collection = collection;
|
|
15744
15846
|
|
|
15745
15847
|
const Types = {
|
|
15746
15848
|
NUMBER: 0,
|
|
@@ -25394,7 +25496,7 @@ var engineering = EngineeringFunctions;
|
|
|
25394
25496
|
|
|
25395
25497
|
const FormulaError$b = requireError();
|
|
25396
25498
|
const {FormulaHelpers: FormulaHelpers$8, Types: Types$6, WildCard, Address: Address$3} = requireHelpers();
|
|
25397
|
-
const Collection$2 =
|
|
25499
|
+
const Collection$2 = collection;
|
|
25398
25500
|
const H$5 = FormulaHelpers$8;
|
|
25399
25501
|
|
|
25400
25502
|
const ReferenceFunctions$1 = {
|
|
@@ -37022,7 +37124,7 @@ var parsing = {
|
|
|
37022
37124
|
const FormulaError$4 = requireError();
|
|
37023
37125
|
const {Address: Address$1} = requireHelpers();
|
|
37024
37126
|
const {Prefix: Prefix$1, Postfix: Postfix$1, Infix: Infix$1, Operators: Operators$1} = operators;
|
|
37025
|
-
const Collection$1 =
|
|
37127
|
+
const Collection$1 = collection;
|
|
37026
37128
|
const MAX_ROW$1 = 1048576, MAX_COLUMN$1 = 16384;
|
|
37027
37129
|
const {NotAllInputParsedException} = require$$4;
|
|
37028
37130
|
|
|
@@ -37784,7 +37886,7 @@ var hooks$1 = {
|
|
|
37784
37886
|
const FormulaError$2 = requireError();
|
|
37785
37887
|
const {FormulaHelpers: FormulaHelpers$1, Types, Address} = requireHelpers();
|
|
37786
37888
|
const {Prefix, Postfix, Infix, Operators} = operators;
|
|
37787
|
-
const Collection =
|
|
37889
|
+
const Collection = collection;
|
|
37788
37890
|
const MAX_ROW = 1048576, MAX_COLUMN = 16384;
|
|
37789
37891
|
|
|
37790
37892
|
let Utils$1 = class Utils {
|
|
@@ -62742,5 +62844,5 @@ const InsightsPanelUI = forwardRef(({ insights, isLoading = false, filter = 'all
|
|
|
62742
62844
|
});
|
|
62743
62845
|
InsightsPanelUI.displayName = 'InsightsPanelUI';
|
|
62744
62846
|
|
|
62745
|
-
export { Accordion, AchievementBadge, AchievementUnlock, ActionBar, ActionBarCenter, ActionBarLeft, ActionBarRight, ActionButton, ActionCard, ActivityFeed, AdminModal, Alert, AlertDialog, AnomalyBanner, AppLayout, Autocomplete, Avatar, BREAKPOINTS, Badge, BottomNavigation, BottomNavigationSpacer, BottomSheet, BottomSheetActions, BottomSheetContent, BottomSheetHeader, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, CaseQueueItem, Celebration, ChatUI, Checkbox, CheckboxList, Chip, ChipGroup, CollaboratorAvatars, Collapsible, CollapsibleSection, ColorPicker, Combobox, ComingSoon, CommandPalette, CompactStat, ConfidenceBadge, ConfidenceIndicator, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataGrid, DataTable, DataTableCardView, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, DesktopOnly, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, EntityCard, ErrorBoundary, ExpandablePanel, ExpandablePanelContainer, ExpandablePanelSpacer, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FORMULA_CATEGORIES, FORMULA_DEFINITIONS, FORMULA_NAMES, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, FloatingActionButton, Form, FormContext, FormControl, FormWizard, FunnelChart, Grid, GridItem, HelpTooltip, Hide, HorizontalScroll, HoverCard, InfiniteScroll, Input, InsightsPanelUI, InviteCard, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, MatchIndicator, Menu, MenuDivider, MobileHeader, MobileHeaderSpacer, MobileLayout, MobileOnly, MobileProvider, Modal, ModalFooter, MotivationalMessage, MultiSelect, NotificationBanner, NotificationBar, NotificationBell, NotificationIndicator, NumberInput, Page, PageHeader, PageLayout, PageNavigation, Pagination, PasswordInput, PermissionBadge, PersonaDashboard, PivotTable, Popover, PriorityAlertBanner, ProcessHealthBar, ProcessIndicator, Progress, ProgressCelebration, PullToRefresh, QueryTransparency, RadioGroup, Rating, Responsive, ReviewDecisionCard, RichTextEditor, SLAIndicator, SearchBar, SearchableList, Select, Separator, SharedBadge, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard$1 as SkeletonCard, SkeletonTable, SkipLink, Slider, SplitPane, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, StreakBadge, SuccessCheck, SummaryCard, SwipeActions, SwipeableCard, SwipeableListItem, Switch, SystemActionEntry, Tabs, TabsContent, TabsList, TabsRoot, TabsTrigger, Text, Textarea, ThemeToggle, TimePicker, Timeline, TimezoneSelector, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, VarianceDisplay, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, getFormula, getFormulasByCategory, getLocalTimezone, isValidTimezone, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, searchFormulas, statusManager, useBreadcrumbReset, useBreakpoint, useBreakpointValue, useCelebration, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useDelighters, useFABScroll, useFormContext, useIsDesktop, useIsMobile, useIsTablet, useIsTouchDevice, useMediaQuery, useMobileContext, useOrientation, usePrefersMobile, useResponsiveCallback, useSafeAreaInsets, useViewportSize, withMobileContext };
|
|
62847
|
+
export { Accordion, AchievementBadge, AchievementUnlock, ActionBar, ActionBarCenter, ActionBarLeft, ActionBarRight, ActionButton, ActionCard, ActivityFeed, AdminModal, Alert, AlertDialog, AnomalyBanner, AppLayout, Autocomplete, Avatar, BREAKPOINTS, Badge, BottomNavigation, BottomNavigationSpacer, BottomSheet, BottomSheetActions, BottomSheetContent, BottomSheetHeader, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, CaseQueueItem, Celebration, ChatUI, Checkbox, CheckboxList, Chip, ChipGroup, CollaboratorAvatars, Collapsible, CollapsibleSection, ColorPicker, Combobox, ComingSoon, CommandPalette, CompactStat, ConfidenceBadge, ConfidenceIndicator, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataGrid, DataTable, DataTableCardView, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, DesktopOnly, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, EntityCard, ErrorBoundary, ExpandablePanel, ExpandablePanelContainer, ExpandablePanelSpacer, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FORMULA_CATEGORIES, FORMULA_DEFINITIONS, FORMULA_NAMES, FieldArray, FileUpload, FilterBar, FilterControls, FilterPills, FilterStatusBanner, FloatingActionButton, Form, FormContext, FormControl, FormWizard, FunnelChart, Grid, GridItem, HelpTooltip, Hide, HorizontalScroll, HoverCard, InfiniteScroll, Input, InsightsPanelUI, InviteCard, KanbanBoard, Layout, LetterNav, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, MatchIndicator, Menu, MenuDivider, MobileHeader, MobileHeaderSpacer, MobileLayout, MobileOnly, MobileProvider, Modal, ModalFooter, MotivationalMessage, MultiSelect, NotificationBanner, NotificationBar, NotificationBell, NotificationIndicator, NumberInput, Page, PageHeader, PageLayout, PageNavigation, Pagination, PasswordInput, PermissionBadge, PersonaDashboard, PivotTable, Popover, PriorityAlertBanner, ProcessHealthBar, ProcessIndicator, Progress, ProgressCelebration, PullToRefresh, QueryTransparency, RadioGroup, Rating, Responsive, ReviewDecisionCard, RichTextEditor, SLAIndicator, SearchBar, SearchableList, Select, Separator, SharedBadge, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard$1 as SkeletonCard, SkeletonTable, SkipLink, Slider, SplitPane, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, StreakBadge, SuccessCheck, SummaryCard, SwipeActions, SwipeableCard, SwipeableListItem, Switch, SystemActionEntry, Tabs, TabsContent, TabsList, TabsRoot, TabsTrigger, Text, Textarea, ThemeToggle, TimePicker, Timeline, TimezoneSelector, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, VarianceDisplay, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, getFormula, getFormulasByCategory, getLocalTimezone, isValidTimezone, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, searchFormulas, statusManager, useBreadcrumbReset, useBreakpoint, useBreakpointValue, useCelebration, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useDelighters, useFABScroll, useFormContext, useIsDesktop, useIsMobile, useIsTablet, useIsTouchDevice, useMediaQuery, useMobileContext, useOrientation, usePrefersMobile, useResponsiveCallback, useSafeAreaInsets, useViewportSize, withMobileContext };
|
|
62746
62848
|
//# sourceMappingURL=index.esm.js.map
|