@papernote/ui 1.12.0 → 1.14.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/components/AdminModal.d.ts.map +1 -1
- 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/Sidebar.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 +36 -4
- package/dist/index.esm.js +305 -226
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +305 -224
- package/dist/index.js.map +1 -1
- package/dist/styles.css +8 -0
- package/package.json +1 -1
- package/src/components/AdminModal.tsx +1 -0
- 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/Sidebar.tsx +19 -1
- package/src/components/index.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -2719,7 +2719,18 @@ function FilterBar({ filters, values, onChange, className = '', onClear, showCle
|
|
|
2719
2719
|
// Default clear: set all values to null/empty
|
|
2720
2720
|
const clearedValues = {};
|
|
2721
2721
|
filters.forEach(filter => {
|
|
2722
|
-
|
|
2722
|
+
if (filter.type === 'text' || filter.type === 'search') {
|
|
2723
|
+
clearedValues[filter.key] = '';
|
|
2724
|
+
}
|
|
2725
|
+
else if (filter.type === 'dateRange') {
|
|
2726
|
+
clearedValues[filter.key] = { from: undefined, to: undefined };
|
|
2727
|
+
}
|
|
2728
|
+
else if (filter.type === 'multiSelect') {
|
|
2729
|
+
clearedValues[filter.key] = [];
|
|
2730
|
+
}
|
|
2731
|
+
else {
|
|
2732
|
+
clearedValues[filter.key] = null;
|
|
2733
|
+
}
|
|
2723
2734
|
});
|
|
2724
2735
|
onChange(clearedValues);
|
|
2725
2736
|
}
|
|
@@ -2751,6 +2762,38 @@ function FilterBar({ filters, values, onChange, className = '', onClear, showCle
|
|
|
2751
2762
|
];
|
|
2752
2763
|
return (jsxRuntime.jsx(Select, { options: boolOptions, value: value === null || value === undefined ? '' : String(value), onChange: (newValue) => handleFilterChange(filter.key, newValue === '' ? null : newValue === 'true') }));
|
|
2753
2764
|
}
|
|
2765
|
+
case 'search':
|
|
2766
|
+
return (jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 text-ink-400" }) }), jsxRuntime.jsx("input", { type: "text", placeholder: filter.placeholder || `Search ${filter.label}...`, value: value || '', onChange: (e) => handleFilterChange(filter.key, e.target.value), className: "input pl-9" })] }));
|
|
2767
|
+
case 'dateRange': {
|
|
2768
|
+
const rangeValue = value || {};
|
|
2769
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.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` }), jsxRuntime.jsx("span", { className: "text-ink-400 text-xs", children: "to" }), jsxRuntime.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` })] }));
|
|
2770
|
+
}
|
|
2771
|
+
case 'toggle': {
|
|
2772
|
+
const toggleOptions = [
|
|
2773
|
+
{ value: '', label: 'All' },
|
|
2774
|
+
{ value: 'true', label: 'Yes' },
|
|
2775
|
+
{ value: 'false', label: 'No' },
|
|
2776
|
+
];
|
|
2777
|
+
const currentVal = value === null || value === undefined ? '' : String(value);
|
|
2778
|
+
return (jsxRuntime.jsx("div", { className: "flex rounded-lg border border-paper-300 overflow-hidden", role: "group", children: toggleOptions.map((opt) => (jsxRuntime.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
|
|
2779
|
+
? 'bg-accent-500 text-white'
|
|
2780
|
+
: 'bg-white text-ink-600 hover:bg-paper-50'} ${opt.value !== '' ? 'border-l border-paper-300' : ''}`, children: opt.label }, opt.value))) }));
|
|
2781
|
+
}
|
|
2782
|
+
case 'multiSelect': {
|
|
2783
|
+
const selectedValues = Array.isArray(value) ? value : [];
|
|
2784
|
+
const msOptions = filter.options || [];
|
|
2785
|
+
return (jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(Select, { options: [{ value: '', label: `All ${filter.label}` }, ...msOptions.map(o => ({ value: String(o.value), label: o.label }))], value: "", onChange: (newValue) => {
|
|
2786
|
+
if (!newValue) {
|
|
2787
|
+
handleFilterChange(filter.key, []);
|
|
2788
|
+
}
|
|
2789
|
+
else if (!selectedValues.includes(newValue)) {
|
|
2790
|
+
handleFilterChange(filter.key, [...selectedValues, newValue]);
|
|
2791
|
+
}
|
|
2792
|
+
} }), selectedValues.length > 0 && (jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1 mt-1", children: selectedValues.map((sv) => {
|
|
2793
|
+
const opt = msOptions.find(o => String(o.value) === sv);
|
|
2794
|
+
return (jsxRuntime.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, jsxRuntime.jsx("button", { type: "button", onClick: () => handleFilterChange(filter.key, selectedValues.filter(v => v !== sv)), className: "hover:text-accent-900", children: jsxRuntime.jsx(lucideReact.X, { className: "h-3 w-3" }) })] }, sv));
|
|
2795
|
+
}) }))] }));
|
|
2796
|
+
}
|
|
2754
2797
|
default:
|
|
2755
2798
|
return null;
|
|
2756
2799
|
}
|
|
@@ -2760,6 +2803,237 @@ function FilterBar({ filters, values, onChange, className = '', onClear, showCle
|
|
|
2760
2803
|
return (jsxRuntime.jsx("div", { className: `bg-white bg-subtle-grain border border-paper-200 rounded-lg shadow-sm p-4 ${className}`, children: jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 flex-wrap", children: [jsxRuntime.jsx("div", { className: "flex-1 flex flex-wrap gap-4", children: filters.map((filter) => (jsxRuntime.jsxs("div", { className: "flex flex-col space-y-1 min-w-[200px]", children: [jsxRuntime.jsx("label", { className: "label", children: filter.label }), renderFilter(filter)] }, filter.key))) }), showClearButton && (jsxRuntime.jsx("div", { className: "flex items-end", children: jsxRuntime.jsx(Button, { variant: "ghost", size: "md", onClick: handleClear, icon: jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }), iconPosition: "left", children: "Clear" }) }))] }) }));
|
|
2761
2804
|
}
|
|
2762
2805
|
|
|
2806
|
+
const variantClasses$4 = {
|
|
2807
|
+
primary: {
|
|
2808
|
+
default: 'bg-primary-100 text-primary-700 border-primary-200',
|
|
2809
|
+
hover: 'hover:bg-primary-200',
|
|
2810
|
+
close: 'hover:bg-primary-300 text-primary-600',
|
|
2811
|
+
selected: 'bg-primary-200 border-primary-400 ring-2 ring-primary-300',
|
|
2812
|
+
},
|
|
2813
|
+
secondary: {
|
|
2814
|
+
default: 'bg-ink-100 text-ink-700 border-ink-200',
|
|
2815
|
+
hover: 'hover:bg-ink-200',
|
|
2816
|
+
close: 'hover:bg-ink-300 text-ink-600',
|
|
2817
|
+
selected: 'bg-ink-200 border-ink-400 ring-2 ring-ink-300',
|
|
2818
|
+
},
|
|
2819
|
+
success: {
|
|
2820
|
+
default: 'bg-success-100 text-success-700 border-success-200',
|
|
2821
|
+
hover: 'hover:bg-success-200',
|
|
2822
|
+
close: 'hover:bg-success-300 text-success-600',
|
|
2823
|
+
selected: 'bg-success-200 border-success-400 ring-2 ring-success-300',
|
|
2824
|
+
},
|
|
2825
|
+
warning: {
|
|
2826
|
+
default: 'bg-warning-100 text-warning-700 border-warning-200',
|
|
2827
|
+
hover: 'hover:bg-warning-200',
|
|
2828
|
+
close: 'hover:bg-warning-300 text-warning-600',
|
|
2829
|
+
selected: 'bg-warning-200 border-warning-400 ring-2 ring-warning-300',
|
|
2830
|
+
},
|
|
2831
|
+
error: {
|
|
2832
|
+
default: 'bg-error-100 text-error-700 border-error-200',
|
|
2833
|
+
hover: 'hover:bg-error-200',
|
|
2834
|
+
close: 'hover:bg-error-300 text-error-600',
|
|
2835
|
+
selected: 'bg-error-200 border-error-400 ring-2 ring-error-300',
|
|
2836
|
+
},
|
|
2837
|
+
info: {
|
|
2838
|
+
default: 'bg-accent-100 text-accent-700 border-accent-200',
|
|
2839
|
+
hover: 'hover:bg-accent-200',
|
|
2840
|
+
close: 'hover:bg-accent-300 text-accent-600',
|
|
2841
|
+
selected: 'bg-accent-200 border-accent-400 ring-2 ring-accent-300',
|
|
2842
|
+
},
|
|
2843
|
+
};
|
|
2844
|
+
const sizeClasses$b = {
|
|
2845
|
+
sm: {
|
|
2846
|
+
container: 'h-6 px-2 text-xs gap-1',
|
|
2847
|
+
icon: 'h-3 w-3',
|
|
2848
|
+
close: 'h-3 w-3 ml-1',
|
|
2849
|
+
},
|
|
2850
|
+
md: {
|
|
2851
|
+
container: 'h-7 px-2.5 text-sm gap-1.5',
|
|
2852
|
+
icon: 'h-3.5 w-3.5',
|
|
2853
|
+
close: 'h-3.5 w-3.5 ml-1.5',
|
|
2854
|
+
},
|
|
2855
|
+
lg: {
|
|
2856
|
+
container: 'h-8 px-3 text-base gap-2',
|
|
2857
|
+
icon: 'h-4 w-4',
|
|
2858
|
+
close: 'h-4 w-4 ml-2',
|
|
2859
|
+
},
|
|
2860
|
+
};
|
|
2861
|
+
const gapClasses = {
|
|
2862
|
+
xs: 'gap-1',
|
|
2863
|
+
sm: 'gap-1.5',
|
|
2864
|
+
md: 'gap-2',
|
|
2865
|
+
lg: 'gap-3',
|
|
2866
|
+
};
|
|
2867
|
+
/**
|
|
2868
|
+
* Chip - Compact element for displaying values with optional remove functionality
|
|
2869
|
+
*
|
|
2870
|
+
* @example Basic chip
|
|
2871
|
+
* ```tsx
|
|
2872
|
+
* <Chip>Tag Name</Chip>
|
|
2873
|
+
* ```
|
|
2874
|
+
*
|
|
2875
|
+
* @example Removable chip
|
|
2876
|
+
* ```tsx
|
|
2877
|
+
* <Chip onClose={() => removeTag(tag)}>
|
|
2878
|
+
* {tag.name}
|
|
2879
|
+
* </Chip>
|
|
2880
|
+
* ```
|
|
2881
|
+
*
|
|
2882
|
+
* @example With icon and selected state
|
|
2883
|
+
* ```tsx
|
|
2884
|
+
* <Chip
|
|
2885
|
+
* icon={<Star className="h-3 w-3" />}
|
|
2886
|
+
* selected={isSelected}
|
|
2887
|
+
* onClick={() => toggleSelection()}
|
|
2888
|
+
* >
|
|
2889
|
+
* Favorite
|
|
2890
|
+
* </Chip>
|
|
2891
|
+
* ```
|
|
2892
|
+
*/
|
|
2893
|
+
function Chip({ children, variant = 'secondary', size = 'md', onClose, icon, disabled = false, className = '', onClick, selected = false, maxWidth, chipKey, }) {
|
|
2894
|
+
const variantStyle = variantClasses$4[variant];
|
|
2895
|
+
const sizeStyle = sizeClasses$b[size];
|
|
2896
|
+
const isClickable = !disabled && (onClick || onClose);
|
|
2897
|
+
return (jsxRuntime.jsxs("div", { className: `
|
|
2898
|
+
inline-flex items-center rounded-full border font-medium
|
|
2899
|
+
transition-colors
|
|
2900
|
+
${selected ? variantStyle.selected : variantStyle.default}
|
|
2901
|
+
${isClickable && !disabled && !selected ? variantStyle.hover : ''}
|
|
2902
|
+
${sizeStyle.container}
|
|
2903
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
|
|
2904
|
+
${onClick && !disabled ? 'cursor-pointer' : ''}
|
|
2905
|
+
${className}
|
|
2906
|
+
`, 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 && (jsxRuntime.jsx("span", { className: `flex-shrink-0 ${sizeStyle.icon}`, children: icon })), jsxRuntime.jsx("span", { className: "truncate", children: children }), onClose && (jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
|
|
2907
|
+
e.stopPropagation();
|
|
2908
|
+
if (!disabled)
|
|
2909
|
+
onClose();
|
|
2910
|
+
}, disabled: disabled, className: `
|
|
2911
|
+
flex-shrink-0 rounded-full transition-colors
|
|
2912
|
+
${variantStyle.close}
|
|
2913
|
+
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
|
|
2914
|
+
${sizeStyle.close}
|
|
2915
|
+
`, "aria-label": "Remove", children: jsxRuntime.jsx(lucideReact.X, { className: "w-full h-full" }) }))] }));
|
|
2916
|
+
}
|
|
2917
|
+
/**
|
|
2918
|
+
* ChipGroup - Container for multiple chips with layout and selection support
|
|
2919
|
+
*
|
|
2920
|
+
* @example Basic group
|
|
2921
|
+
* ```tsx
|
|
2922
|
+
* <ChipGroup wrap gap="sm">
|
|
2923
|
+
* {tags.map(tag => (
|
|
2924
|
+
* <Chip key={tag.id} onClose={() => removeTag(tag)}>
|
|
2925
|
+
* {tag.name}
|
|
2926
|
+
* </Chip>
|
|
2927
|
+
* ))}
|
|
2928
|
+
* </ChipGroup>
|
|
2929
|
+
* ```
|
|
2930
|
+
*
|
|
2931
|
+
* @example Selectable group (single)
|
|
2932
|
+
* ```tsx
|
|
2933
|
+
* <ChipGroup
|
|
2934
|
+
* selectionMode="single"
|
|
2935
|
+
* selectedKeys={[selectedCategory]}
|
|
2936
|
+
* onSelectionChange={(keys) => setSelectedCategory(keys[0])}
|
|
2937
|
+
* >
|
|
2938
|
+
* <Chip chipKey="all">All</Chip>
|
|
2939
|
+
* <Chip chipKey="active">Active</Chip>
|
|
2940
|
+
* <Chip chipKey="archived">Archived</Chip>
|
|
2941
|
+
* </ChipGroup>
|
|
2942
|
+
* ```
|
|
2943
|
+
*
|
|
2944
|
+
* @example Multi-select group
|
|
2945
|
+
* ```tsx
|
|
2946
|
+
* <ChipGroup
|
|
2947
|
+
* selectionMode="multiple"
|
|
2948
|
+
* selectedKeys={selectedTags}
|
|
2949
|
+
* onSelectionChange={setSelectedTags}
|
|
2950
|
+
* wrap
|
|
2951
|
+
* >
|
|
2952
|
+
* {availableTags.map(tag => (
|
|
2953
|
+
* <Chip key={tag} chipKey={tag}>{tag}</Chip>
|
|
2954
|
+
* ))}
|
|
2955
|
+
* </ChipGroup>
|
|
2956
|
+
* ```
|
|
2957
|
+
*/
|
|
2958
|
+
function ChipGroup({ children, direction = 'horizontal', wrap = false, gap = 'sm', selectionMode = 'none', selectedKeys = [], onSelectionChange, className = '', }) {
|
|
2959
|
+
const handleChipClick = (chipKey) => {
|
|
2960
|
+
if (selectionMode === 'none' || !onSelectionChange)
|
|
2961
|
+
return;
|
|
2962
|
+
if (selectionMode === 'single') {
|
|
2963
|
+
// Toggle single selection
|
|
2964
|
+
if (selectedKeys.includes(chipKey)) {
|
|
2965
|
+
onSelectionChange([]);
|
|
2966
|
+
}
|
|
2967
|
+
else {
|
|
2968
|
+
onSelectionChange([chipKey]);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
else if (selectionMode === 'multiple') {
|
|
2972
|
+
// Toggle in array
|
|
2973
|
+
if (selectedKeys.includes(chipKey)) {
|
|
2974
|
+
onSelectionChange(selectedKeys.filter(k => k !== chipKey));
|
|
2975
|
+
}
|
|
2976
|
+
else {
|
|
2977
|
+
onSelectionChange([...selectedKeys, chipKey]);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
};
|
|
2981
|
+
// Clone children to inject selection props
|
|
2982
|
+
const enhancedChildren = React.Children.map(children, (child) => {
|
|
2983
|
+
if (!React.isValidElement(child))
|
|
2984
|
+
return child;
|
|
2985
|
+
const chipKey = child.props.chipKey;
|
|
2986
|
+
if (!chipKey || selectionMode === 'none')
|
|
2987
|
+
return child;
|
|
2988
|
+
const isSelected = selectedKeys.includes(chipKey);
|
|
2989
|
+
return React.cloneElement(child, {
|
|
2990
|
+
...child.props,
|
|
2991
|
+
selected: isSelected,
|
|
2992
|
+
onClick: () => {
|
|
2993
|
+
// Call original onClick if exists
|
|
2994
|
+
if (child.props.onClick) {
|
|
2995
|
+
child.props.onClick();
|
|
2996
|
+
}
|
|
2997
|
+
handleChipClick(chipKey);
|
|
2998
|
+
},
|
|
2999
|
+
});
|
|
3000
|
+
});
|
|
3001
|
+
return (jsxRuntime.jsx("div", { className: `
|
|
3002
|
+
flex
|
|
3003
|
+
${direction === 'vertical' ? 'flex-col' : 'flex-row'}
|
|
3004
|
+
${wrap ? 'flex-wrap' : ''}
|
|
3005
|
+
${gapClasses[gap]}
|
|
3006
|
+
${className}
|
|
3007
|
+
`, role: selectionMode !== 'none' ? 'group' : undefined, "aria-label": selectionMode !== 'none' ? 'Chip selection group' : undefined, children: enhancedChildren }));
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
function FilterPills({ pills, onRemove, onClearAll, totalCount, className = '', }) {
|
|
3011
|
+
if (pills.length === 0)
|
|
3012
|
+
return null;
|
|
3013
|
+
return (jsxRuntime.jsxs("div", { className: `flex items-center gap-2 px-4 py-2 border-b border-paper-200 bg-paper-50 ${className}`, children: [jsxRuntime.jsx(lucideReact.Filter, { className: "h-3.5 w-3.5 text-ink-400 shrink-0" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap flex-1", children: [pills.map((pill) => (jsxRuntime.jsxs(Chip, { size: "sm", variant: "primary", onClose: () => onRemove(pill.key), children: [pill.label, ": ", pill.displayValue] }, pill.key))), pills.length >= 2 && (jsxRuntime.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 && (jsxRuntime.jsxs("span", { className: "text-xs text-ink-500 shrink-0 tabular-nums", children: [totalCount.toLocaleString(), " ", totalCount === 1 ? 'record' : 'records'] }))] }));
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
const LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
|
3017
|
+
function LetterNav({ activeLetter, onChange, availableLetters, className = '', }) {
|
|
3018
|
+
const hasAvailability = availableLetters && availableLetters.length > 0;
|
|
3019
|
+
const availableSet = hasAvailability
|
|
3020
|
+
? new Set(availableLetters.map((l) => l.toUpperCase()))
|
|
3021
|
+
: null;
|
|
3022
|
+
return (jsxRuntime.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: [jsxRuntime.jsx("button", { type: "button", onClick: () => onChange(null), className: `px-2 py-1 text-xs font-medium rounded transition-colors ${activeLetter === null
|
|
3023
|
+
? 'bg-accent-500 text-white'
|
|
3024
|
+
: 'text-ink-600 hover:bg-paper-100'}`, children: "All" }), LETTERS.map((letter) => {
|
|
3025
|
+
const isActive = activeLetter === letter;
|
|
3026
|
+
const isAvailable = !availableSet || availableSet.has(letter);
|
|
3027
|
+
return (jsxRuntime.jsx("button", { type: "button", onClick: () => onChange(isActive ? null : letter), className: `w-7 h-7 text-xs font-medium rounded transition-colors ${isActive
|
|
3028
|
+
? 'bg-accent-500 text-white'
|
|
3029
|
+
: isAvailable
|
|
3030
|
+
? 'text-ink-600 hover:bg-paper-100'
|
|
3031
|
+
: 'text-ink-300'}`, children: letter }, letter));
|
|
3032
|
+
}), jsxRuntime.jsx("button", { type: "button", onClick: () => onChange(activeLetter === '#' ? null : '#'), className: `px-2 py-1 text-xs font-medium rounded transition-colors ${activeLetter === '#'
|
|
3033
|
+
? 'bg-accent-500 text-white'
|
|
3034
|
+
: 'text-ink-600 hover:bg-paper-100'}`, children: "#" })] }));
|
|
3035
|
+
}
|
|
3036
|
+
|
|
2763
3037
|
function Loading({ variant = 'spinner', size = 'md', text }) {
|
|
2764
3038
|
const sizeClasses = {
|
|
2765
3039
|
sm: 'h-4 w-4',
|
|
@@ -4610,7 +4884,7 @@ function BottomSheetActions({ children, className = '' }) {
|
|
|
4610
4884
|
|
|
4611
4885
|
// Selector for all focusable elements
|
|
4612
4886
|
const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
4613
|
-
const sizeClasses$
|
|
4887
|
+
const sizeClasses$a = {
|
|
4614
4888
|
sm: 'max-w-md',
|
|
4615
4889
|
md: 'max-w-lg',
|
|
4616
4890
|
lg: 'max-w-2xl',
|
|
@@ -4799,7 +5073,7 @@ function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton
|
|
|
4799
5073
|
return reactDom.createPortal(jsxRuntime.jsx(BottomSheet, { isOpen: isOpen, onClose: onClose, title: title, height: mobileHeight, showHandle: mobileShowHandle, showCloseButton: showCloseButton, children: children }), document.body);
|
|
4800
5074
|
}
|
|
4801
5075
|
// Render as standard modal on desktop
|
|
4802
|
-
const modalContent = (jsxRuntime.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: jsxRuntime.jsxs("div", { ref: modalRef, className: `${sizeClasses$
|
|
5076
|
+
const modalContent = (jsxRuntime.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: jsxRuntime.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: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-paper-200", children: [jsxRuntime.jsx("h3", { id: titleId, className: "text-lg font-medium text-ink-900", children: title }), showCloseButton && (jsxRuntime.jsx("button", { onClick: onClose, className: "text-ink-400 hover:text-ink-600 transition-colors", "aria-label": "Close modal", children: jsxRuntime.jsx(lucideReact.X, { className: "h-5 w-5" }) }))] }), jsxRuntime.jsx("div", { className: `px-6 py-4 ${scrollable || maxHeight ? 'overflow-y-auto' : ''}`, style: {
|
|
4803
5077
|
maxHeight: maxHeight || (scrollable ? 'calc(100vh - 200px)' : undefined),
|
|
4804
5078
|
}, children: children })] }) }));
|
|
4805
5079
|
return reactDom.createPortal(modalContent, document.body);
|
|
@@ -5870,7 +6144,7 @@ function Alert({ variant = 'info', title, children, onClose, className = '', act
|
|
|
5870
6144
|
return (jsxRuntime.jsx("div", { className: `rounded-lg border p-4 ${styles.container} ${className}`, role: "alert", children: jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [jsxRuntime.jsx("div", { className: "flex-shrink-0 mt-0.5", children: styles.icon }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [title && jsxRuntime.jsx("h4", { className: "text-sm font-medium mb-1", children: title }), jsxRuntime.jsx("div", { className: "text-sm", children: children }), actions.length > 0 && (jsxRuntime.jsx("div", { className: "flex gap-2 mt-3", children: actions.map((action, index) => (jsxRuntime.jsx("button", { onClick: action.onClick, className: getButtonStyles(action.variant), children: action.label }, index))) }))] }), onClose && (jsxRuntime.jsx("button", { onClick: onClose, className: "flex-shrink-0 text-current opacity-70 hover:opacity-100 transition-opacity", "aria-label": "Close alert", children: jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }) }))] }) }));
|
|
5871
6145
|
}
|
|
5872
6146
|
|
|
5873
|
-
const sizeClasses$
|
|
6147
|
+
const sizeClasses$9 = {
|
|
5874
6148
|
left: {
|
|
5875
6149
|
sm: 'w-64',
|
|
5876
6150
|
md: 'w-96',
|
|
@@ -5949,7 +6223,7 @@ function Drawer({ isOpen, onClose, title, children, placement = 'right', size =
|
|
|
5949
6223
|
const isHorizontal = placement === 'left' || placement === 'right';
|
|
5950
6224
|
return (jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex", children: [showOverlay && (jsxRuntime.jsx("div", { className: "fixed inset-0 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onClick: handleOverlayClick, "aria-hidden": "true" })), jsxRuntime.jsxs("div", { className: `
|
|
5951
6225
|
fixed ${placementClasses[placement]}
|
|
5952
|
-
${sizeClasses$
|
|
6226
|
+
${sizeClasses$9[placement][size]}
|
|
5953
6227
|
bg-white border-paper-200 shadow-2xl
|
|
5954
6228
|
${isHorizontal ? 'border-r' : 'border-b'}
|
|
5955
6229
|
${animationClasses[placement].enter}
|
|
@@ -6091,14 +6365,14 @@ function useConfirmDialog() {
|
|
|
6091
6365
|
};
|
|
6092
6366
|
}
|
|
6093
6367
|
|
|
6094
|
-
const sizeClasses$
|
|
6368
|
+
const sizeClasses$8 = {
|
|
6095
6369
|
sm: 'h-3.5 w-3.5',
|
|
6096
6370
|
md: 'h-4 w-4',
|
|
6097
6371
|
lg: 'h-5 w-5',
|
|
6098
6372
|
};
|
|
6099
6373
|
function HelpTooltip({ content, icon = 'help', size = 'md', position = 'top', className = '', }) {
|
|
6100
6374
|
const IconComponent = icon === 'info' ? lucideReact.Info : lucideReact.HelpCircle;
|
|
6101
|
-
return (jsxRuntime.jsx(Tooltip, { content: content, position: position, children: jsxRuntime.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: jsxRuntime.jsx(IconComponent, { className: sizeClasses$
|
|
6375
|
+
return (jsxRuntime.jsx(Tooltip, { content: content, position: position, children: jsxRuntime.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: jsxRuntime.jsx(IconComponent, { className: sizeClasses$8[size] }) }) }));
|
|
6102
6376
|
}
|
|
6103
6377
|
|
|
6104
6378
|
/**
|
|
@@ -8476,210 +8750,6 @@ function MenuDivider() {
|
|
|
8476
8750
|
return { divider: true, id: `divider-${Date.now()}`, label: '' };
|
|
8477
8751
|
}
|
|
8478
8752
|
|
|
8479
|
-
const variantClasses$4 = {
|
|
8480
|
-
primary: {
|
|
8481
|
-
default: 'bg-primary-100 text-primary-700 border-primary-200',
|
|
8482
|
-
hover: 'hover:bg-primary-200',
|
|
8483
|
-
close: 'hover:bg-primary-300 text-primary-600',
|
|
8484
|
-
selected: 'bg-primary-200 border-primary-400 ring-2 ring-primary-300',
|
|
8485
|
-
},
|
|
8486
|
-
secondary: {
|
|
8487
|
-
default: 'bg-ink-100 text-ink-700 border-ink-200',
|
|
8488
|
-
hover: 'hover:bg-ink-200',
|
|
8489
|
-
close: 'hover:bg-ink-300 text-ink-600',
|
|
8490
|
-
selected: 'bg-ink-200 border-ink-400 ring-2 ring-ink-300',
|
|
8491
|
-
},
|
|
8492
|
-
success: {
|
|
8493
|
-
default: 'bg-success-100 text-success-700 border-success-200',
|
|
8494
|
-
hover: 'hover:bg-success-200',
|
|
8495
|
-
close: 'hover:bg-success-300 text-success-600',
|
|
8496
|
-
selected: 'bg-success-200 border-success-400 ring-2 ring-success-300',
|
|
8497
|
-
},
|
|
8498
|
-
warning: {
|
|
8499
|
-
default: 'bg-warning-100 text-warning-700 border-warning-200',
|
|
8500
|
-
hover: 'hover:bg-warning-200',
|
|
8501
|
-
close: 'hover:bg-warning-300 text-warning-600',
|
|
8502
|
-
selected: 'bg-warning-200 border-warning-400 ring-2 ring-warning-300',
|
|
8503
|
-
},
|
|
8504
|
-
error: {
|
|
8505
|
-
default: 'bg-error-100 text-error-700 border-error-200',
|
|
8506
|
-
hover: 'hover:bg-error-200',
|
|
8507
|
-
close: 'hover:bg-error-300 text-error-600',
|
|
8508
|
-
selected: 'bg-error-200 border-error-400 ring-2 ring-error-300',
|
|
8509
|
-
},
|
|
8510
|
-
info: {
|
|
8511
|
-
default: 'bg-accent-100 text-accent-700 border-accent-200',
|
|
8512
|
-
hover: 'hover:bg-accent-200',
|
|
8513
|
-
close: 'hover:bg-accent-300 text-accent-600',
|
|
8514
|
-
selected: 'bg-accent-200 border-accent-400 ring-2 ring-accent-300',
|
|
8515
|
-
},
|
|
8516
|
-
};
|
|
8517
|
-
const sizeClasses$8 = {
|
|
8518
|
-
sm: {
|
|
8519
|
-
container: 'h-6 px-2 text-xs gap-1',
|
|
8520
|
-
icon: 'h-3 w-3',
|
|
8521
|
-
close: 'h-3 w-3 ml-1',
|
|
8522
|
-
},
|
|
8523
|
-
md: {
|
|
8524
|
-
container: 'h-7 px-2.5 text-sm gap-1.5',
|
|
8525
|
-
icon: 'h-3.5 w-3.5',
|
|
8526
|
-
close: 'h-3.5 w-3.5 ml-1.5',
|
|
8527
|
-
},
|
|
8528
|
-
lg: {
|
|
8529
|
-
container: 'h-8 px-3 text-base gap-2',
|
|
8530
|
-
icon: 'h-4 w-4',
|
|
8531
|
-
close: 'h-4 w-4 ml-2',
|
|
8532
|
-
},
|
|
8533
|
-
};
|
|
8534
|
-
const gapClasses = {
|
|
8535
|
-
xs: 'gap-1',
|
|
8536
|
-
sm: 'gap-1.5',
|
|
8537
|
-
md: 'gap-2',
|
|
8538
|
-
lg: 'gap-3',
|
|
8539
|
-
};
|
|
8540
|
-
/**
|
|
8541
|
-
* Chip - Compact element for displaying values with optional remove functionality
|
|
8542
|
-
*
|
|
8543
|
-
* @example Basic chip
|
|
8544
|
-
* ```tsx
|
|
8545
|
-
* <Chip>Tag Name</Chip>
|
|
8546
|
-
* ```
|
|
8547
|
-
*
|
|
8548
|
-
* @example Removable chip
|
|
8549
|
-
* ```tsx
|
|
8550
|
-
* <Chip onClose={() => removeTag(tag)}>
|
|
8551
|
-
* {tag.name}
|
|
8552
|
-
* </Chip>
|
|
8553
|
-
* ```
|
|
8554
|
-
*
|
|
8555
|
-
* @example With icon and selected state
|
|
8556
|
-
* ```tsx
|
|
8557
|
-
* <Chip
|
|
8558
|
-
* icon={<Star className="h-3 w-3" />}
|
|
8559
|
-
* selected={isSelected}
|
|
8560
|
-
* onClick={() => toggleSelection()}
|
|
8561
|
-
* >
|
|
8562
|
-
* Favorite
|
|
8563
|
-
* </Chip>
|
|
8564
|
-
* ```
|
|
8565
|
-
*/
|
|
8566
|
-
function Chip({ children, variant = 'secondary', size = 'md', onClose, icon, disabled = false, className = '', onClick, selected = false, maxWidth, chipKey, }) {
|
|
8567
|
-
const variantStyle = variantClasses$4[variant];
|
|
8568
|
-
const sizeStyle = sizeClasses$8[size];
|
|
8569
|
-
const isClickable = !disabled && (onClick || onClose);
|
|
8570
|
-
return (jsxRuntime.jsxs("div", { className: `
|
|
8571
|
-
inline-flex items-center rounded-full border font-medium
|
|
8572
|
-
transition-colors
|
|
8573
|
-
${selected ? variantStyle.selected : variantStyle.default}
|
|
8574
|
-
${isClickable && !disabled && !selected ? variantStyle.hover : ''}
|
|
8575
|
-
${sizeStyle.container}
|
|
8576
|
-
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
|
|
8577
|
-
${onClick && !disabled ? 'cursor-pointer' : ''}
|
|
8578
|
-
${className}
|
|
8579
|
-
`, 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 && (jsxRuntime.jsx("span", { className: `flex-shrink-0 ${sizeStyle.icon}`, children: icon })), jsxRuntime.jsx("span", { className: "truncate", children: children }), onClose && (jsxRuntime.jsx("button", { type: "button", onClick: (e) => {
|
|
8580
|
-
e.stopPropagation();
|
|
8581
|
-
if (!disabled)
|
|
8582
|
-
onClose();
|
|
8583
|
-
}, disabled: disabled, className: `
|
|
8584
|
-
flex-shrink-0 rounded-full transition-colors
|
|
8585
|
-
${variantStyle.close}
|
|
8586
|
-
${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
|
|
8587
|
-
${sizeStyle.close}
|
|
8588
|
-
`, "aria-label": "Remove", children: jsxRuntime.jsx(lucideReact.X, { className: "w-full h-full" }) }))] }));
|
|
8589
|
-
}
|
|
8590
|
-
/**
|
|
8591
|
-
* ChipGroup - Container for multiple chips with layout and selection support
|
|
8592
|
-
*
|
|
8593
|
-
* @example Basic group
|
|
8594
|
-
* ```tsx
|
|
8595
|
-
* <ChipGroup wrap gap="sm">
|
|
8596
|
-
* {tags.map(tag => (
|
|
8597
|
-
* <Chip key={tag.id} onClose={() => removeTag(tag)}>
|
|
8598
|
-
* {tag.name}
|
|
8599
|
-
* </Chip>
|
|
8600
|
-
* ))}
|
|
8601
|
-
* </ChipGroup>
|
|
8602
|
-
* ```
|
|
8603
|
-
*
|
|
8604
|
-
* @example Selectable group (single)
|
|
8605
|
-
* ```tsx
|
|
8606
|
-
* <ChipGroup
|
|
8607
|
-
* selectionMode="single"
|
|
8608
|
-
* selectedKeys={[selectedCategory]}
|
|
8609
|
-
* onSelectionChange={(keys) => setSelectedCategory(keys[0])}
|
|
8610
|
-
* >
|
|
8611
|
-
* <Chip chipKey="all">All</Chip>
|
|
8612
|
-
* <Chip chipKey="active">Active</Chip>
|
|
8613
|
-
* <Chip chipKey="archived">Archived</Chip>
|
|
8614
|
-
* </ChipGroup>
|
|
8615
|
-
* ```
|
|
8616
|
-
*
|
|
8617
|
-
* @example Multi-select group
|
|
8618
|
-
* ```tsx
|
|
8619
|
-
* <ChipGroup
|
|
8620
|
-
* selectionMode="multiple"
|
|
8621
|
-
* selectedKeys={selectedTags}
|
|
8622
|
-
* onSelectionChange={setSelectedTags}
|
|
8623
|
-
* wrap
|
|
8624
|
-
* >
|
|
8625
|
-
* {availableTags.map(tag => (
|
|
8626
|
-
* <Chip key={tag} chipKey={tag}>{tag}</Chip>
|
|
8627
|
-
* ))}
|
|
8628
|
-
* </ChipGroup>
|
|
8629
|
-
* ```
|
|
8630
|
-
*/
|
|
8631
|
-
function ChipGroup({ children, direction = 'horizontal', wrap = false, gap = 'sm', selectionMode = 'none', selectedKeys = [], onSelectionChange, className = '', }) {
|
|
8632
|
-
const handleChipClick = (chipKey) => {
|
|
8633
|
-
if (selectionMode === 'none' || !onSelectionChange)
|
|
8634
|
-
return;
|
|
8635
|
-
if (selectionMode === 'single') {
|
|
8636
|
-
// Toggle single selection
|
|
8637
|
-
if (selectedKeys.includes(chipKey)) {
|
|
8638
|
-
onSelectionChange([]);
|
|
8639
|
-
}
|
|
8640
|
-
else {
|
|
8641
|
-
onSelectionChange([chipKey]);
|
|
8642
|
-
}
|
|
8643
|
-
}
|
|
8644
|
-
else if (selectionMode === 'multiple') {
|
|
8645
|
-
// Toggle in array
|
|
8646
|
-
if (selectedKeys.includes(chipKey)) {
|
|
8647
|
-
onSelectionChange(selectedKeys.filter(k => k !== chipKey));
|
|
8648
|
-
}
|
|
8649
|
-
else {
|
|
8650
|
-
onSelectionChange([...selectedKeys, chipKey]);
|
|
8651
|
-
}
|
|
8652
|
-
}
|
|
8653
|
-
};
|
|
8654
|
-
// Clone children to inject selection props
|
|
8655
|
-
const enhancedChildren = React.Children.map(children, (child) => {
|
|
8656
|
-
if (!React.isValidElement(child))
|
|
8657
|
-
return child;
|
|
8658
|
-
const chipKey = child.props.chipKey;
|
|
8659
|
-
if (!chipKey || selectionMode === 'none')
|
|
8660
|
-
return child;
|
|
8661
|
-
const isSelected = selectedKeys.includes(chipKey);
|
|
8662
|
-
return React.cloneElement(child, {
|
|
8663
|
-
...child.props,
|
|
8664
|
-
selected: isSelected,
|
|
8665
|
-
onClick: () => {
|
|
8666
|
-
// Call original onClick if exists
|
|
8667
|
-
if (child.props.onClick) {
|
|
8668
|
-
child.props.onClick();
|
|
8669
|
-
}
|
|
8670
|
-
handleChipClick(chipKey);
|
|
8671
|
-
},
|
|
8672
|
-
});
|
|
8673
|
-
});
|
|
8674
|
-
return (jsxRuntime.jsx("div", { className: `
|
|
8675
|
-
flex
|
|
8676
|
-
${direction === 'vertical' ? 'flex-col' : 'flex-row'}
|
|
8677
|
-
${wrap ? 'flex-wrap' : ''}
|
|
8678
|
-
${gapClasses[gap]}
|
|
8679
|
-
${className}
|
|
8680
|
-
`, role: selectionMode !== 'none' ? 'group' : undefined, "aria-label": selectionMode !== 'none' ? 'Chip selection group' : undefined, children: enhancedChildren }));
|
|
8681
|
-
}
|
|
8682
|
-
|
|
8683
8753
|
const sizeClasses$7 = {
|
|
8684
8754
|
sm: {
|
|
8685
8755
|
item: 'py-1.5 px-2',
|
|
@@ -11799,7 +11869,7 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
|
|
|
11799
11869
|
}) })] }));
|
|
11800
11870
|
}
|
|
11801
11871
|
|
|
11802
|
-
function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = true, maxPageNumbers = 5, showPageJump = false, }) {
|
|
11872
|
+
function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = true, maxPageNumbers = 5, showPageJump = false, totalItems, pageSize, pageSizeOptions, onPageSizeChange, showRecordCount = false, }) {
|
|
11803
11873
|
const [jumpValue, setJumpValue] = React.useState('');
|
|
11804
11874
|
const getPageNumbers = () => {
|
|
11805
11875
|
const pages = [];
|
|
@@ -11840,16 +11910,20 @@ function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = t
|
|
|
11840
11910
|
setJumpValue('');
|
|
11841
11911
|
}
|
|
11842
11912
|
};
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
11913
|
+
const showLeftSection = showRecordCount && totalItems !== undefined && pageSize;
|
|
11914
|
+
const showRightSection = onPageSizeChange && pageSizeOptions && pageSizeOptions.length > 0;
|
|
11915
|
+
const rangeStart = totalItems ? (currentPage - 1) * (pageSize || 0) + 1 : 0;
|
|
11916
|
+
const rangeEnd = totalItems ? Math.min(currentPage * (pageSize || 0), totalItems) : 0;
|
|
11917
|
+
return (jsxRuntime.jsxs("nav", { className: `flex items-center gap-2 ${showLeftSection || showRightSection ? 'justify-between' : 'justify-center'}`, "aria-label": "Pagination", children: [showLeftSection ? (jsxRuntime.jsxs("span", { className: "text-sm text-ink-500 tabular-nums shrink-0", children: ["Showing ", rangeStart.toLocaleString(), "\u2013", rangeEnd.toLocaleString(), " of ", totalItems.toLocaleString()] })) : showRightSection ? jsxRuntime.jsx("div", {}) : null, jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.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: [jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Previous" })] }), showPageNumbers && (jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: pageNumbers.map((page, index) => {
|
|
11918
|
+
if (page === '...') {
|
|
11919
|
+
return (jsxRuntime.jsx("span", { className: "px-3 py-2 text-ink-500", children: "..." }, `ellipsis-${index}`));
|
|
11920
|
+
}
|
|
11921
|
+
const pageNum = page;
|
|
11922
|
+
const isActive = pageNum === currentPage;
|
|
11923
|
+
return (jsxRuntime.jsx("button", { onClick: () => onPageChange(pageNum), className: `px-3 py-2 text-sm font-medium rounded-lg transition-all ${isActive
|
|
11924
|
+
? 'bg-accent-500 text-white shadow-sm'
|
|
11925
|
+
: '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));
|
|
11926
|
+
}) })), jsxRuntime.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: [jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Next" }), jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" })] }), showPageJump && (jsxRuntime.jsxs("form", { onSubmit: handlePageJump, className: "flex items-center gap-2 ml-2", children: [jsxRuntime.jsx("span", { className: "text-sm text-ink-600 hidden sm:inline", children: "Go to:" }), jsxRuntime.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" }), jsxRuntime.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 ? (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [jsxRuntime.jsx("span", { className: "text-sm text-ink-500 hidden sm:inline", children: "Per page:" }), jsxRuntime.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) => (jsxRuntime.jsx("option", { value: size, children: size }, size))) })] })) : showLeftSection ? jsxRuntime.jsx("div", {}) : null] }));
|
|
11853
11927
|
}
|
|
11854
11928
|
|
|
11855
11929
|
function StepIndicator({ steps, currentStep, variant = 'horizontal', onStepClick, }) {
|
|
@@ -13205,8 +13279,13 @@ function Sidebar({ items, onNavigate, className = '', header, footer, currentPat
|
|
|
13205
13279
|
};
|
|
13206
13280
|
// Sidebar content (shared between desktop and mobile)
|
|
13207
13281
|
const sidebarContent = (jsxRuntime.jsxs("div", { ref: sidebarRef, className: `flex flex-col h-full bg-white border-r border-paper-300 notebook-binding ${width} ${className}`, children: [mobileOpen !== undefined && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 pt-4 md:hidden", children: [jsxRuntime.jsx("div", { className: "flex-1", children: header }), jsxRuntime.jsx("button", { onClick: onMobileClose, className: "\n flex items-center justify-center\n w-10 h-10 -mr-2\n text-ink-500 hover:text-ink-700\n hover:bg-paper-100 rounded-full\n transition-colors\n ", "aria-label": "Close sidebar", children: jsxRuntime.jsx(lucideReact.X, { className: "w-5 h-5" }) })] })), header && mobileOpen === undefined && (jsxRuntime.jsx("div", { className: "px-6 pt-6 pb-4", children: header })), header && mobileOpen !== undefined && (jsxRuntime.jsx("div", { className: "px-6 pt-2 pb-4 hidden md:block", children: header })), jsxRuntime.jsx("nav", { className: "flex-1 px-3 py-2 space-y-1 overflow-y-auto", children: items.map((item) => {
|
|
13208
|
-
// Render separator
|
|
13282
|
+
// Render separator or section header
|
|
13209
13283
|
if (item.separator) {
|
|
13284
|
+
// Section header: separator with a label
|
|
13285
|
+
if (item.label) {
|
|
13286
|
+
return (jsxRuntime.jsx("div", { className: "mt-6 mb-2 px-3", "data-testid": item.dataAttributes?.['data-testid'] || `sidebar-section-${item.id}`, ...item.dataAttributes, children: jsxRuntime.jsx("div", { className: "border-t border-paper-300 pt-3", children: jsxRuntime.jsx("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-ink-400", children: item.label }) }) }, item.id));
|
|
13287
|
+
}
|
|
13288
|
+
// Plain separator: just a line
|
|
13210
13289
|
return (jsxRuntime.jsx("div", { className: "my-4 border-t border-paper-300", "data-testid": item.dataAttributes?.['data-testid'] || `sidebar-separator-${item.id}`, ...item.dataAttributes }, item.id));
|
|
13211
13290
|
}
|
|
13212
13291
|
// Render nav item
|
|
@@ -61838,7 +61917,7 @@ function AdminModal({ isOpen, onClose, title, subtitle, onSubmit, isSaving = fal
|
|
|
61838
61917
|
};
|
|
61839
61918
|
return (jsxRuntime.jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4 admin-modal-overlay", children: jsxRuntime.jsxs("div", { className: `bg-white rounded-lg w-full ${sizeClasses[size]} flex flex-col overflow-hidden shadow-2xl admin-modal-content`, style: { height: height }, children: [jsxRuntime.jsx("div", { className: "fixed inset-0 pointer-events-none admin-modal-sidebar-placeholder" }), jsxRuntime.jsxs("div", { className: "px-6 py-4 border-b", children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold", children: title }), subtitle && jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-1", children: subtitle })] }), tabs.length > 1 && (jsxRuntime.jsx("div", { className: "border-b border-gray-200 bg-white", children: jsxRuntime.jsx("nav", { className: "-mb-px flex items-center px-6 admin-modal-tabs", "aria-label": "Tabs", children: tabs.map((tab, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: () => onTabChange(tab.id), className: `whitespace-nowrap border-b-2 py-3 px-4 text-sm font-medium transition-colors ${activeTabId === tab.id
|
|
61840
61919
|
? 'border-blue-500 text-blue-600'
|
|
61841
|
-
: 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'}`, "aria-current": activeTabId === tab.id ? 'page' : undefined, children: tab.label }), index < tabs.length - 1 && (jsxRuntime.jsx("div", { className: "admin-modal-tab-separator" }))] }, tab.id))) }) })), onSubmit ? (jsxRuntime.jsx("form", { className: "flex-1 overflow-y-auto min-h-0 h-0 px-6 py-6 admin-modal-form", onSubmit: handleFormSubmit, id: formId, children: activeTab?.content || children })) : (jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto min-h-0 h-0 px-6 py-6 admin-modal-content-area", children: activeTab?.content || children })), jsxRuntime.jsxs("div", { className: "px-6 py-4 border-t bg-gray-50 flex justify-between gap-3", children: [jsxRuntime.jsx("button", { type: "button", onClick: onClose, className: "px-4 py-2 text-sm text-gray-600 hover:text-gray-800", disabled: isSaving, children: "Cancel" }), jsxRuntime.jsxs("div", { className: "flex gap-3", children: [customFooterActions, onSubmit && (jsxRuntime.jsx("button", { type: "submit", form: formId, disabled: isSaving, className: "px-4 py-2 text-sm bg-primary-600 text-white rounded hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed", children: isSaving ? 'Saving...' : 'Save Changes' }))] })] })] }) }));
|
|
61920
|
+
: 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'}`, "aria-current": activeTabId === tab.id ? 'page' : undefined, children: tab.label }), index < tabs.length - 1 && (jsxRuntime.jsx("div", { className: "admin-modal-tab-separator" }))] }, tab.id))) }) })), onSubmit ? (jsxRuntime.jsx("form", { className: "flex-1 overflow-y-auto min-h-0 h-0 px-6 py-6 admin-modal-form", onSubmit: handleFormSubmit, id: formId, noValidate: true, children: activeTab?.content || children })) : (jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto min-h-0 h-0 px-6 py-6 admin-modal-content-area", children: activeTab?.content || children })), jsxRuntime.jsxs("div", { className: "px-6 py-4 border-t bg-gray-50 flex justify-between gap-3", children: [jsxRuntime.jsx("button", { type: "button", onClick: onClose, className: "px-4 py-2 text-sm text-gray-600 hover:text-gray-800", disabled: isSaving, children: "Cancel" }), jsxRuntime.jsxs("div", { className: "flex gap-3", children: [customFooterActions, onSubmit && (jsxRuntime.jsx("button", { type: "submit", form: formId, disabled: isSaving, className: "px-4 py-2 text-sm bg-primary-600 text-white rounded hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed", children: isSaving ? 'Saving...' : 'Save Changes' }))] })] })] }) }));
|
|
61842
61921
|
}
|
|
61843
61922
|
|
|
61844
61923
|
/**
|
|
@@ -62842,6 +62921,7 @@ exports.FieldArray = FieldArray;
|
|
|
62842
62921
|
exports.FileUpload = FileUpload;
|
|
62843
62922
|
exports.FilterBar = FilterBar;
|
|
62844
62923
|
exports.FilterControls = FilterControls;
|
|
62924
|
+
exports.FilterPills = FilterPills;
|
|
62845
62925
|
exports.FilterStatusBanner = FilterStatusBanner;
|
|
62846
62926
|
exports.FloatingActionButton = FloatingActionButton;
|
|
62847
62927
|
exports.Form = Form;
|
|
@@ -62861,6 +62941,7 @@ exports.InsightsPanelUI = InsightsPanelUI;
|
|
|
62861
62941
|
exports.InviteCard = InviteCard;
|
|
62862
62942
|
exports.KanbanBoard = KanbanBoard;
|
|
62863
62943
|
exports.Layout = Layout;
|
|
62944
|
+
exports.LetterNav = LetterNav;
|
|
62864
62945
|
exports.Loading = Loading;
|
|
62865
62946
|
exports.LoadingOverlay = LoadingOverlay;
|
|
62866
62947
|
exports.Logo = Logo;
|