@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/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
- clearedValues[filter.key] = filter.type === 'text' ? '' : null;
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$b = {
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$b[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: {
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$a = {
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$a[placement][size]}
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$9 = {
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$9[size] }) }) }));
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
- return (jsxRuntime.jsxs("nav", { className: "flex items-center justify-center gap-2", "aria-label": "Pagination", 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) => {
11844
- if (page === '...') {
11845
- return (jsxRuntime.jsx("span", { className: "px-3 py-2 text-ink-500", children: "..." }, `ellipsis-${index}`));
11846
- }
11847
- const pageNum = page;
11848
- const isActive = pageNum === currentPage;
11849
- return (jsxRuntime.jsx("button", { onClick: () => onPageChange(pageNum), className: `px-3 py-2 text-sm font-medium rounded-lg transition-all ${isActive
11850
- ? 'bg-accent-500 text-white shadow-sm'
11851
- : '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));
11852
- }) })), 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" })] }))] }));
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;