@papernote/ui 1.1.0 → 1.3.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/LICENSE +21 -21
- package/README.md +455 -455
- package/dist/components/Box.d.ts +2 -1
- package/dist/components/Box.d.ts.map +1 -1
- package/dist/components/Button.d.ts +10 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Card.d.ts +11 -2
- package/dist/components/Card.d.ts.map +1 -1
- package/dist/components/CurrencyInput.d.ts +52 -0
- package/dist/components/CurrencyInput.d.ts.map +1 -0
- package/dist/components/DataTable.d.ts +19 -3
- package/dist/components/DataTable.d.ts.map +1 -1
- package/dist/components/EmptyState.d.ts +3 -1
- package/dist/components/EmptyState.d.ts.map +1 -1
- package/dist/components/Grid.d.ts +4 -2
- package/dist/components/Grid.d.ts.map +1 -1
- package/dist/components/Input.d.ts +2 -0
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Modal.d.ts.map +1 -1
- package/dist/components/MultiSelect.d.ts +13 -1
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/Page.d.ts +2 -0
- package/dist/components/Page.d.ts.map +1 -1
- package/dist/components/PageLayout.d.ts +5 -1
- package/dist/components/PageLayout.d.ts.map +1 -1
- package/dist/components/Stack.d.ts +25 -5
- package/dist/components/Stack.d.ts.map +1 -1
- package/dist/components/Text.d.ts +20 -4
- package/dist/components/Text.d.ts.map +1 -1
- package/dist/components/Textarea.d.ts +2 -0
- package/dist/components/Textarea.d.ts.map +1 -1
- package/dist/components/index.d.ts +5 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +311 -49
- package/dist/index.esm.js +557 -224
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +555 -219
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2838 -2679
- package/dist/utils/excelExport.d.ts +143 -0
- package/dist/utils/excelExport.d.ts.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/AdminModal.css +49 -49
- package/src/components/Box.stories.tsx +377 -0
- package/src/components/Box.tsx +8 -4
- package/src/components/Button.tsx +23 -10
- package/src/components/Card.tsx +20 -5
- package/src/components/CurrencyInput.stories.tsx +290 -0
- package/src/components/CurrencyInput.tsx +193 -0
- package/src/components/DataTable.stories.tsx +36 -25
- package/src/components/DataTable.tsx +170 -16
- package/src/components/EmptyState.stories.tsx +124 -72
- package/src/components/EmptyState.tsx +10 -0
- package/src/components/Grid.stories.tsx +348 -0
- package/src/components/Grid.tsx +12 -5
- package/src/components/Input.tsx +12 -2
- package/src/components/Modal.stories.tsx +64 -0
- package/src/components/Modal.tsx +15 -2
- package/src/components/MultiSelect.tsx +41 -10
- package/src/components/Page.stories.tsx +76 -0
- package/src/components/Page.tsx +35 -3
- package/src/components/PageLayout.stories.tsx +75 -0
- package/src/components/PageLayout.tsx +28 -9
- package/src/components/RoleManager.css +10 -10
- package/src/components/Spreadsheet.css +216 -216
- package/src/components/Spreadsheet.stories.tsx +362 -362
- package/src/components/Spreadsheet.tsx +351 -351
- package/src/components/SpreadsheetSimple.stories.tsx +27 -27
- package/src/components/Stack.stories.tsx +24 -1
- package/src/components/Stack.tsx +40 -10
- package/src/components/Tabs.tsx +152 -152
- package/src/components/Text.stories.tsx +273 -0
- package/src/components/Text.tsx +33 -8
- package/src/components/Textarea.tsx +32 -21
- package/src/components/index.ts +6 -4
- package/src/styles/index.css +41 -4
- package/src/utils/excelExport.stories.tsx +535 -0
- package/src/utils/excelExport.ts +225 -0
- package/src/utils/index.ts +3 -0
- package/tailwind.config.js +253 -253
- package/dist/components/Button.stories.d.ts +0 -51
- package/dist/components/Button.stories.d.ts.map +0 -1
- package/dist/components/ChartVisualizationUI.d.ts +0 -21
- package/dist/components/ChartVisualizationUI.d.ts.map +0 -1
- package/dist/components/ChatUI.d.ts +0 -23
- package/dist/components/ChatUI.d.ts.map +0 -1
- package/dist/components/CommissionDashboardUI.d.ts +0 -25
- package/dist/components/CommissionDashboardUI.d.ts.map +0 -1
- package/dist/components/DataTable.stories.d.ts +0 -23
- package/dist/components/DataTable.stories.d.ts.map +0 -1
- package/dist/components/FormField.d.ts +0 -35
- package/dist/components/FormField.d.ts.map +0 -1
- package/dist/components/Input.stories.d.ts +0 -366
- package/dist/components/Input.stories.d.ts.map +0 -1
- package/dist/components/InsightsPanelUI.d.ts +0 -21
- package/dist/components/InsightsPanelUI.d.ts.map +0 -1
- package/dist/components/PaymentHistoryTimeline.d.ts +0 -34
- package/dist/components/PaymentHistoryTimeline.d.ts.map +0 -1
- package/dist/components/RelationshipManagerUI.d.ts +0 -60
- package/dist/components/RelationshipManagerUI.d.ts.map +0 -1
- package/dist/components/RoleManager.d.ts +0 -19
- package/dist/components/RoleManager.d.ts.map +0 -1
- package/dist/components/SplitCommissionBadge.d.ts +0 -18
- package/dist/components/SplitCommissionBadge.d.ts.map +0 -1
- package/dist/components/Spreadsheet.css +0 -216
- package/dist/components/Table.d.ts +0 -26
- package/dist/components/Table.d.ts.map +0 -1
- package/dist/components/__tests__/Button.test.d.ts +0 -2
- package/dist/components/__tests__/Button.test.d.ts.map +0 -1
- package/dist/components/__tests__/Input.test.d.ts +0 -2
- package/dist/components/__tests__/Input.test.d.ts.map +0 -1
- package/src/components/Table.tsx +0 -239
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { Loader2, X, EyeOff, Eye, AlertTriangle, CheckCircle, AlertCircle, ChevronDown, Search, Check, Minus, Star, Calendar as Calendar$1, ChevronLeft, ChevronRight, Clock, ChevronUp, Plus, TrendingUp, TrendingDown, Info, Trash2, Circle, ChevronsRight, ChevronsLeft, MoreVertical, GripVertical, Upload, Bold, Italic, Underline, List, ListOrdered, Code, Link, Home, ArrowUpDown, ArrowUp, ArrowDown, FileText, Image, File as File$1, User, Settings, LogOut, Moon, Sun, Bell, Edit, Trash, Download, Save, XCircle, Filter, BarChart3, MessageSquare } from 'lucide-react';
|
|
3
2
|
import * as React from 'react';
|
|
4
3
|
import React__default, { forwardRef, useState, useRef, useId, useImperativeHandle, useEffect, useCallback, useMemo, cloneElement, isValidElement, Component, createContext as createContext$1, useLayoutEffect, createElement, useContext, useReducer } from 'react';
|
|
4
|
+
import { Loader2, X, EyeOff, Eye, AlertTriangle, CheckCircle, AlertCircle, ChevronDown, Search, Check, Minus, Star, Calendar as Calendar$1, ChevronLeft, ChevronRight, Clock, ChevronUp, Plus, TrendingUp, TrendingDown, Info, Trash2, Circle, ChevronsRight, ChevronsLeft, MoreVertical, GripVertical, Upload, Bold, Italic, Underline, List, ListOrdered, Code, Link, Home, FileText, Image, File as File$1, User, Settings, LogOut, Moon, Sun, Bell, Edit, Trash, Download, Save, XCircle, Filter, BarChart3, MessageSquare } from 'lucide-react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { Link as Link$1 } from 'react-router-dom';
|
|
7
7
|
|
|
@@ -11,6 +11,8 @@ import { Link as Link$1 } from 'react-router-dom';
|
|
|
11
11
|
* A versatile button component that supports multiple visual styles, sizes, icons,
|
|
12
12
|
* loading states, and notification badges.
|
|
13
13
|
*
|
|
14
|
+
* Supports ref forwarding for DOM access.
|
|
15
|
+
*
|
|
14
16
|
* @example Basic usage
|
|
15
17
|
* ```tsx
|
|
16
18
|
* <Button variant="primary">Click me</Button>
|
|
@@ -37,8 +39,14 @@ import { Link as Link$1 } from 'react-router-dom';
|
|
|
37
39
|
* <Bell />
|
|
38
40
|
* </Button>
|
|
39
41
|
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example With ref
|
|
44
|
+
* ```tsx
|
|
45
|
+
* const buttonRef = useRef<HTMLButtonElement>(null);
|
|
46
|
+
* <Button ref={buttonRef}>Focusable</Button>
|
|
47
|
+
* ```
|
|
40
48
|
*/
|
|
41
|
-
|
|
49
|
+
const Button = forwardRef(({ variant = 'primary', size = 'md', loading = false, icon, iconPosition = 'left', fullWidth = false, iconOnly = false, badge, badgeVariant = 'error', children, disabled, className = '', ...props }, ref) => {
|
|
42
50
|
const baseStyles = 'inline-flex items-center justify-center font-medium rounded-lg border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-accent-400 disabled:opacity-40 disabled:cursor-not-allowed';
|
|
43
51
|
const variantStyles = {
|
|
44
52
|
primary: 'bg-accent-500 text-white border-accent-500 hover:bg-accent-600 hover:shadow-sm active:scale-[0.98]',
|
|
@@ -69,7 +77,7 @@ function Button({ variant = 'primary', size = 'md', loading = false, icon, iconP
|
|
|
69
77
|
md: 'min-w-[18px] h-[18px] text-[11px] px-1.5',
|
|
70
78
|
lg: 'min-w-[20px] h-5 text-xs px-1.5',
|
|
71
79
|
};
|
|
72
|
-
const buttonElement = (jsxs("button", { className: `
|
|
80
|
+
const buttonElement = (jsxs("button", { ref: ref, className: `
|
|
73
81
|
${baseStyles}
|
|
74
82
|
${variantStyles[variant]}
|
|
75
83
|
${sizeStyles[size]}
|
|
@@ -92,7 +100,8 @@ function Button({ variant = 'primary', size = 'md', loading = false, icon, iconP
|
|
|
92
100
|
shadow-sm
|
|
93
101
|
pointer-events-none
|
|
94
102
|
`, "aria-label": `${badgeContent} notifications`, children: badgeContent })] }));
|
|
95
|
-
}
|
|
103
|
+
});
|
|
104
|
+
Button.displayName = 'Button';
|
|
96
105
|
|
|
97
106
|
/**
|
|
98
107
|
* ButtonGroup component - Toggle button group for single or multiple selection.
|
|
@@ -239,7 +248,7 @@ function ButtonGroup({ options, value, values = [], onChange, onChangeMultiple,
|
|
|
239
248
|
* />
|
|
240
249
|
* ```
|
|
241
250
|
*/
|
|
242
|
-
const Input = forwardRef(({ label, helperText, validationState, validationMessage, icon, iconPosition = 'left', showCount = false, prefix, suffix, prefixIcon, suffixIcon, showPasswordToggle = false, clearable = false, onClear, className = '', id, type = 'text', value, maxLength, ...props }, ref) => {
|
|
251
|
+
const Input = forwardRef(({ label, helperText, validationState, validationMessage, icon, iconPosition = 'left', showCount = false, prefix, suffix, prefixIcon, suffixIcon, showPasswordToggle = false, clearable = false, onClear, loading = false, className = '', id, type = 'text', value, maxLength, ...props }, ref) => {
|
|
243
252
|
const inputId = id || `input-${Math.random().toString(36).substring(2, 9)}`;
|
|
244
253
|
const [showPassword, setShowPassword] = useState(false);
|
|
245
254
|
// Handle clear button click
|
|
@@ -311,7 +320,7 @@ const Input = forwardRef(({ label, helperText, validationState, validationMessag
|
|
|
311
320
|
${validationState && !suffix && !suffixIcon && !showPasswordToggle ? 'pr-10' : ''}
|
|
312
321
|
${(showPasswordToggle && type === 'password') || validationState || suffix || suffixIcon ? 'pr-20' : ''}
|
|
313
322
|
${className}
|
|
314
|
-
`, ...props }), suffix && (jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none text-ink-500 text-sm", children: suffix })), jsxs("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center gap-2", children: [suffixIcon && !suffix && !validationState && !showPasswordToggle && !showClearButton && (jsx("div", { className: "pointer-events-none text-ink-400", children: suffixIcon })), showClearButton && (jsx("button", { type: "button", onClick: handleClear, className: "text-ink-400 hover:text-ink-600 focus:outline-none cursor-pointer pointer-events-auto", "aria-label": "Clear input", children: jsx(X, { className: "h-4 w-4" }) })), type === 'password' && showPasswordToggle && (jsx("button", { type: "button", onClick: () => setShowPassword(!showPassword), className: "text-ink-400 hover:text-ink-600 focus:outline-none cursor-pointer pointer-events-auto", "aria-label": showPassword ? 'Hide password' : 'Show password', children: showPassword ? jsx(EyeOff, { className: "h-5 w-5" }) : jsx(Eye, { className: "h-5 w-5" }) })), validationState && (jsx("div", { className: "pointer-events-none", children: getValidationIcon() })), icon && iconPosition === 'right' && !suffix && !suffixIcon && !validationState && (jsx("div", { className: "pointer-events-none text-ink-400", children: icon }))] })] }), jsxs("div", { className: "flex justify-between items-center mt-2", children: [(helperText || validationMessage) && (jsx("p", { className: `text-xs ${validationMessage ? getValidationMessageColor() : 'text-ink-600'}`, children: validationMessage || helperText })), showCounter && (jsxs("p", { className: `text-xs ml-auto ${currentLength > maxLength ? 'text-error-600' : 'text-ink-500'}`, children: [currentLength, " / ", maxLength] }))] })] }));
|
|
323
|
+
`, ...props }), suffix && (jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none text-ink-500 text-sm", children: suffix })), jsxs("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center gap-2", children: [loading && (jsx("div", { className: "pointer-events-none text-ink-400", children: jsx(Loader2, { className: "h-5 w-5 animate-spin" }) })), suffixIcon && !suffix && !validationState && !showPasswordToggle && !showClearButton && !loading && (jsx("div", { className: "pointer-events-none text-ink-400", children: suffixIcon })), showClearButton && (jsx("button", { type: "button", onClick: handleClear, className: "text-ink-400 hover:text-ink-600 focus:outline-none cursor-pointer pointer-events-auto", "aria-label": "Clear input", children: jsx(X, { className: "h-4 w-4" }) })), type === 'password' && showPasswordToggle && (jsx("button", { type: "button", onClick: () => setShowPassword(!showPassword), className: "text-ink-400 hover:text-ink-600 focus:outline-none cursor-pointer pointer-events-auto", "aria-label": showPassword ? 'Hide password' : 'Show password', children: showPassword ? jsx(EyeOff, { className: "h-5 w-5" }) : jsx(Eye, { className: "h-5 w-5" }) })), validationState && (jsx("div", { className: "pointer-events-none", children: getValidationIcon() })), icon && iconPosition === 'right' && !suffix && !suffixIcon && !validationState && (jsx("div", { className: "pointer-events-none text-ink-400", children: icon }))] })] }), jsxs("div", { className: "flex justify-between items-center mt-2", children: [(helperText || validationMessage) && (jsx("p", { className: `text-xs ${validationMessage ? getValidationMessageColor() : 'text-ink-600'}`, children: validationMessage || helperText })), showCounter && (jsxs("p", { className: `text-xs ml-auto ${currentLength > maxLength ? 'text-error-600' : 'text-ink-500'}`, children: [currentLength, " / ", maxLength] }))] })] }));
|
|
315
324
|
});
|
|
316
325
|
Input.displayName = 'Input';
|
|
317
326
|
|
|
@@ -518,11 +527,18 @@ const Select = forwardRef((props, ref) => {
|
|
|
518
527
|
});
|
|
519
528
|
Select.displayName = 'Select';
|
|
520
529
|
|
|
521
|
-
|
|
530
|
+
const MultiSelect = forwardRef(({ options, value = [], onChange, placeholder = 'Select options', searchable = false, disabled = false, label, helperText, error, maxHeight = 240, maxSelections, loading = false, 'aria-label': ariaLabel, }, ref) => {
|
|
522
531
|
const [isOpen, setIsOpen] = useState(false);
|
|
523
532
|
const [searchQuery, setSearchQuery] = useState('');
|
|
524
533
|
const selectRef = useRef(null);
|
|
525
534
|
const searchInputRef = useRef(null);
|
|
535
|
+
const triggerRef = useRef(null);
|
|
536
|
+
// Expose imperative methods
|
|
537
|
+
useImperativeHandle(ref, () => ({
|
|
538
|
+
focus: () => triggerRef.current?.focus(),
|
|
539
|
+
open: () => !disabled && setIsOpen(true),
|
|
540
|
+
close: () => setIsOpen(false),
|
|
541
|
+
}));
|
|
526
542
|
const selectedOptions = options.filter(opt => value.includes(opt.value));
|
|
527
543
|
const hasReachedMax = maxSelections ? value.length >= maxSelections : false;
|
|
528
544
|
const filteredOptions = searchable && searchQuery
|
|
@@ -569,11 +585,11 @@ function MultiSelect({ options, value = [], onChange, placeholder = 'Select opti
|
|
|
569
585
|
e.stopPropagation();
|
|
570
586
|
onChange?.([]);
|
|
571
587
|
};
|
|
572
|
-
return (jsxs("div", { className: "w-full", children: [label && (jsx("label", { className: "label", children: label })), jsxs("div", { ref: selectRef, className: "relative", children: [jsxs("button", { type: "button", onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, className: `
|
|
588
|
+
return (jsxs("div", { className: "w-full", children: [label && (jsx("label", { className: "label", children: label })), jsxs("div", { ref: selectRef, className: "relative", children: [jsxs("button", { ref: triggerRef, type: "button", onClick: () => !disabled && !loading && setIsOpen(!isOpen), disabled: disabled || loading, className: `
|
|
573
589
|
input w-full flex items-center justify-between min-h-[42px]
|
|
574
590
|
${error ? 'border-error-400 focus:border-error-400 focus:ring-error-400' : ''}
|
|
575
|
-
${disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
576
|
-
`, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-label": ariaLabel || label, children: [jsx("div", { className: "flex-1 flex items-center gap-2 flex-wrap", children: selectedOptions.length === 0 ? (jsx("span", { className: "text-ink-400", children: placeholder })) : (selectedOptions.map((option) => (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-1 bg-accent-100 text-accent-800 rounded text-sm", children: [option.icon && jsx("span", { className: "text-xs", children: option.icon }), option.label, jsx("button", { type: "button", onClick: (e) => handleRemove(option.value, e), className: "hover:text-accent-900", "aria-label": `Remove ${option.label}`, children: jsx(X, { className: "h-3 w-3" }) })] }, option.value)))) }), jsxs("div", { className: "flex items-center gap-2 ml-2", children: [selectedOptions.length > 0 && !disabled && (jsx("button", { type: "button", onClick: handleClearAll, className: "text-ink-400 hover:text-ink-600", "aria-label": "Clear all", children: jsx(X, { className: "h-4 w-4" }) })), jsx(ChevronDown, { className: `h-4 w-4 text-ink-500 transition-transform ${isOpen ? 'rotate-180' : ''}` })] })] }), isOpen && (jsxs("div", { className: "absolute z-50 w-full mt-2 bg-white bg-subtle-grain rounded-lg shadow-lg border border-paper-200 overflow-hidden animate-fade-in", style: { maxHeight: `${maxHeight}px` }, children: [searchable && (jsx("div", { className: "p-2 border-b border-paper-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-ink-400" }), jsx("input", { ref: searchInputRef, type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search...", className: "w-full pl-9 pr-3 py-2 text-sm border border-paper-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400" })] }) })), jsx("div", { className: "overflow-y-auto", style: { maxHeight: `${maxHeight - 60}px` }, role: "listbox", "aria-multiselectable": "true", children: filteredOptions.length === 0 ? (jsx("div", { className: "px-4 py-3 text-sm text-ink-500 text-center", children: "No options found" })) : (filteredOptions.map((option) => {
|
|
591
|
+
${disabled || loading ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
592
|
+
`, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-label": ariaLabel || label, children: [jsx("div", { className: "flex-1 flex items-center gap-2 flex-wrap", children: selectedOptions.length === 0 ? (jsx("span", { className: "text-ink-400", children: placeholder })) : (selectedOptions.map((option) => (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-1 bg-accent-100 text-accent-800 rounded text-sm", children: [option.icon && jsx("span", { className: "text-xs", children: option.icon }), option.label, jsx("button", { type: "button", onClick: (e) => handleRemove(option.value, e), className: "hover:text-accent-900", "aria-label": `Remove ${option.label}`, children: jsx(X, { className: "h-3 w-3" }) })] }, option.value)))) }), jsxs("div", { className: "flex items-center gap-2 ml-2", children: [loading && (jsx(Loader2, { className: "h-4 w-4 text-ink-400 animate-spin" })), !loading && selectedOptions.length > 0 && !disabled && (jsx("button", { type: "button", onClick: handleClearAll, className: "text-ink-400 hover:text-ink-600", "aria-label": "Clear all", children: jsx(X, { className: "h-4 w-4" }) })), !loading && (jsx(ChevronDown, { className: `h-4 w-4 text-ink-500 transition-transform ${isOpen ? 'rotate-180' : ''}` }))] })] }), isOpen && (jsxs("div", { className: "absolute z-50 w-full mt-2 bg-white bg-subtle-grain rounded-lg shadow-lg border border-paper-200 overflow-hidden animate-fade-in", style: { maxHeight: `${maxHeight}px` }, children: [searchable && (jsx("div", { className: "p-2 border-b border-paper-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-ink-400" }), jsx("input", { ref: searchInputRef, type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search...", className: "w-full pl-9 pr-3 py-2 text-sm border border-paper-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-400 focus:border-accent-400" })] }) })), jsx("div", { className: "overflow-y-auto", style: { maxHeight: `${maxHeight - 60}px` }, role: "listbox", "aria-multiselectable": "true", children: filteredOptions.length === 0 ? (jsx("div", { className: "px-4 py-3 text-sm text-ink-500 text-center", children: "No options found" })) : (filteredOptions.map((option) => {
|
|
577
593
|
const isSelected = value.includes(option.value);
|
|
578
594
|
const isDisabled = option.disabled || (hasReachedMax && !isSelected);
|
|
579
595
|
return (jsx("button", { type: "button", onClick: () => !isDisabled && handleToggle(option.value), disabled: isDisabled, className: `
|
|
@@ -585,7 +601,8 @@ function MultiSelect({ options, value = [], onChange, placeholder = 'Select opti
|
|
|
585
601
|
${isSelected ? 'bg-accent-600 border-accent-600' : 'border-paper-300'}
|
|
586
602
|
`, children: isSelected && jsx(Check, { className: "h-3 w-3 text-white" }) }), option.icon && jsx("span", { children: option.icon }), option.label] }) }, option.value));
|
|
587
603
|
})) })] }))] }), jsxs("div", { className: "flex justify-between items-center mt-2", children: [(helperText || error) && (jsx("p", { className: `text-xs ${error ? 'text-error-600' : 'text-ink-600'}`, children: error || helperText })), maxSelections && (jsxs("p", { className: `text-xs ml-auto ${hasReachedMax ? 'text-warning-600 font-medium' : 'text-ink-500'}`, children: [value.length, " / ", maxSelections, " selected"] }))] })] }));
|
|
588
|
-
}
|
|
604
|
+
});
|
|
605
|
+
MultiSelect.displayName = 'MultiSelect';
|
|
589
606
|
|
|
590
607
|
const Switch = forwardRef(({ checked, onChange, label, description, disabled = false, size = 'md', loading = false, }, ref) => {
|
|
591
608
|
// Generate unique IDs for ARIA
|
|
@@ -632,7 +649,7 @@ const Switch = forwardRef(({ checked, onChange, label, description, disabled = f
|
|
|
632
649
|
});
|
|
633
650
|
Switch.displayName = 'Switch';
|
|
634
651
|
|
|
635
|
-
const Textarea = forwardRef(({ label, helperText, validationState, validationMessage, maxLength, showCharCount = false, autoExpand = false, minRows = 2, maxRows = 10, resize = 'vertical', className = '', id, value, rows = 4, ...props }, ref) => {
|
|
652
|
+
const Textarea = forwardRef(({ label, helperText, validationState, validationMessage, maxLength, showCharCount = false, autoExpand = false, minRows = 2, maxRows = 10, resize = 'vertical', loading = false, className = '', id, value, rows = 4, ...props }, ref) => {
|
|
636
653
|
const textareaId = id || `textarea-${Math.random().toString(36).substring(2, 9)}`;
|
|
637
654
|
const currentLength = typeof value === 'string' ? value.length : 0;
|
|
638
655
|
const internalRef = useRef(null);
|
|
@@ -707,14 +724,15 @@ const Textarea = forwardRef(({ label, helperText, validationState, validationMes
|
|
|
707
724
|
return 'text-ink-600';
|
|
708
725
|
}
|
|
709
726
|
};
|
|
710
|
-
return (jsxs("div", { className: "w-full", children: [label && (jsxs("label", { htmlFor: textareaId, className: "label", children: [label, props.required && jsx("span", { className: "text-error-500 ml-1", children: "*" })] })), jsx("textarea", { ref: textareaRef, id: textareaId, value: value, maxLength: maxLength, rows: autoExpand ? minRows : rows, className: `
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
727
|
+
return (jsxs("div", { className: "w-full", children: [label && (jsxs("label", { htmlFor: textareaId, className: "label", children: [label, props.required && jsx("span", { className: "text-error-500 ml-1", children: "*" })] })), jsxs("div", { className: "relative", children: [jsx("textarea", { ref: textareaRef, id: textareaId, value: value, maxLength: maxLength, rows: autoExpand ? minRows : rows, className: `
|
|
728
|
+
block w-full px-4 py-3 border rounded-lg text-sm text-ink-800 placeholder-ink-400
|
|
729
|
+
bg-white bg-subtle-grain transition-all duration-200
|
|
730
|
+
focus:outline-none focus:ring-2 ${getResizeClass()}
|
|
731
|
+
disabled:bg-paper-100 disabled:text-ink-400 disabled:cursor-not-allowed disabled:opacity-60
|
|
732
|
+
${getValidationClasses()}
|
|
733
|
+
${loading ? 'pr-10' : ''}
|
|
734
|
+
${className}
|
|
735
|
+
`, "aria-invalid": validationState === 'error', "aria-describedby": validationMessage || helperText ? `${textareaId}-help` : undefined, "aria-required": props.required, ...props }), loading && (jsx("div", { className: "absolute top-3 right-3 pointer-events-none", children: jsx(Loader2, { className: "h-5 w-5 text-ink-400 animate-spin" }) }))] }), ((helperText || validationMessage) || (showCharCount && maxLength)) && (jsxs("div", { className: "mt-2 flex items-center justify-between", children: [jsxs("div", { className: "flex items-center gap-2", children: [validationState && getValidationIcon(), (helperText || validationMessage) && (jsx("p", { id: `${textareaId}-help`, className: `text-xs ${validationMessage ? getValidationMessageColor() : 'text-ink-600'}`, children: validationMessage || helperText }))] }), showCharCount && maxLength && (jsxs("p", { className: `text-xs ${currentLength >= maxLength ? 'text-error-600' : 'text-ink-500'}`, children: [currentLength, " / ", maxLength] }))] }))] }));
|
|
718
736
|
});
|
|
719
737
|
Textarea.displayName = 'Textarea';
|
|
720
738
|
|
|
@@ -1930,6 +1948,8 @@ function SkeletonTable({ rows = 5, columns = 4 }) {
|
|
|
1930
1948
|
/**
|
|
1931
1949
|
* Card - Container component with paper aesthetic and subtle shadow
|
|
1932
1950
|
*
|
|
1951
|
+
* Supports ref forwarding for DOM access.
|
|
1952
|
+
*
|
|
1933
1953
|
* A content container with paper texture, border, and shadow effects. Supports
|
|
1934
1954
|
* different sizes, variants (padding/shadow levels), and loading states.
|
|
1935
1955
|
*
|
|
@@ -1959,8 +1979,14 @@ function SkeletonTable({ rows = 5, columns = 4 }) {
|
|
|
1959
1979
|
* <p>Content</p>
|
|
1960
1980
|
* </Card>
|
|
1961
1981
|
* ```
|
|
1982
|
+
*
|
|
1983
|
+
* @example With ref
|
|
1984
|
+
* ```tsx
|
|
1985
|
+
* const cardRef = useRef<HTMLDivElement>(null);
|
|
1986
|
+
* <Card ref={cardRef}>Content</Card>
|
|
1987
|
+
* ```
|
|
1962
1988
|
*/
|
|
1963
|
-
|
|
1989
|
+
const Card = forwardRef(({ children, variant = 'default', width = 'auto', className = '', onClick, hoverable = false, loading = false, ...htmlProps }, ref) => {
|
|
1964
1990
|
const baseStyles = 'bg-white bg-subtle-grain border-2 border-paper-300 transition-shadow duration-200';
|
|
1965
1991
|
const variantStyles = {
|
|
1966
1992
|
default: 'rounded-xl shadow-lg p-8',
|
|
@@ -1976,8 +2002,9 @@ function Card({ children, variant = 'default', width = 'auto', className = '', o
|
|
|
1976
2002
|
full: 'w-full',
|
|
1977
2003
|
};
|
|
1978
2004
|
const interactiveStyles = onClick || hoverable ? 'cursor-pointer hover:shadow-md' : '';
|
|
1979
|
-
return (jsx("div", { className: `${baseStyles} ${variantStyles[variant]} ${widthStyles[width]} ${interactiveStyles} ${className}`, onClick: !loading ? onClick : undefined, role: onClick ? 'button' : undefined, tabIndex: onClick ? 0 : undefined, children: loading ? (jsxs("div", { className: "space-y-4", children: [jsx(Skeleton, { className: "h-6 w-3/4" }), jsx(Skeleton, { className: "h-4 w-full" }), jsx(Skeleton, { className: "h-4 w-5/6" }), jsx(Skeleton, { className: "h-4 w-4/6" })] })) : (children) }));
|
|
1980
|
-
}
|
|
2005
|
+
return (jsx("div", { ref: ref, ...htmlProps, className: `${baseStyles} ${variantStyles[variant]} ${widthStyles[width]} ${interactiveStyles} ${className}`, onClick: !loading ? onClick : undefined, role: onClick ? 'button' : undefined, tabIndex: onClick ? 0 : undefined, children: loading ? (jsxs("div", { className: "space-y-4", children: [jsx(Skeleton, { className: "h-6 w-3/4" }), jsx(Skeleton, { className: "h-4 w-full" }), jsx(Skeleton, { className: "h-4 w-5/6" }), jsx(Skeleton, { className: "h-4 w-4/6" })] })) : (children) }));
|
|
2006
|
+
});
|
|
2007
|
+
Card.displayName = 'Card';
|
|
1981
2008
|
/**
|
|
1982
2009
|
* CardHeader - Header section for Card component
|
|
1983
2010
|
*
|
|
@@ -2075,15 +2102,34 @@ function Separator({ orientation = 'horizontal', className = '', spacing = 'md',
|
|
|
2075
2102
|
/**
|
|
2076
2103
|
* Stack component for arranging children vertically or horizontally with consistent spacing.
|
|
2077
2104
|
*
|
|
2078
|
-
*
|
|
2105
|
+
* Supports ref forwarding for DOM access.
|
|
2106
|
+
*
|
|
2107
|
+
* Spacing scale (use either `spacing` or `gap` prop - they're aliases):
|
|
2079
2108
|
* - none: 0
|
|
2080
2109
|
* - xs: 0.5rem (2)
|
|
2081
2110
|
* - sm: 0.75rem (3)
|
|
2082
2111
|
* - md: 1.5rem (6)
|
|
2083
2112
|
* - lg: 2rem (8)
|
|
2084
2113
|
* - xl: 3rem (12)
|
|
2114
|
+
*
|
|
2115
|
+
* @example
|
|
2116
|
+
* ```tsx
|
|
2117
|
+
* // Using spacing prop
|
|
2118
|
+
* <Stack spacing="md">
|
|
2119
|
+
* <Card>Item 1</Card>
|
|
2120
|
+
* <Card>Item 2</Card>
|
|
2121
|
+
* </Stack>
|
|
2122
|
+
*
|
|
2123
|
+
* // Using gap prop (alias)
|
|
2124
|
+
* <Stack gap="md">
|
|
2125
|
+
* <Card>Item 1</Card>
|
|
2126
|
+
* <Card>Item 2</Card>
|
|
2127
|
+
* </Stack>
|
|
2128
|
+
* ```
|
|
2085
2129
|
*/
|
|
2086
|
-
const Stack = ({ children, direction = 'vertical', spacing
|
|
2130
|
+
const Stack = forwardRef(({ children, direction = 'vertical', spacing, gap, align = 'stretch', justify = 'start', wrap = false, className = '', ...htmlProps }, ref) => {
|
|
2131
|
+
// Use gap as alias for spacing (spacing takes precedence if both provided)
|
|
2132
|
+
const effectiveSpacing = spacing ?? gap ?? 'md';
|
|
2087
2133
|
const spacingClasses = {
|
|
2088
2134
|
vertical: {
|
|
2089
2135
|
none: '',
|
|
@@ -2115,20 +2161,23 @@ const Stack = ({ children, direction = 'vertical', spacing = 'md', align = 'stre
|
|
|
2115
2161
|
between: 'justify-between',
|
|
2116
2162
|
around: 'justify-around',
|
|
2117
2163
|
};
|
|
2118
|
-
return (jsx("div", { className: `
|
|
2164
|
+
return (jsx("div", { ref: ref, ...htmlProps, className: `
|
|
2119
2165
|
flex
|
|
2120
2166
|
${direction === 'vertical' ? 'flex-col' : 'flex-row'}
|
|
2121
2167
|
${wrap ? 'flex-wrap' : ''}
|
|
2122
|
-
${spacingClasses[direction][
|
|
2168
|
+
${spacingClasses[direction][effectiveSpacing]}
|
|
2123
2169
|
${alignClasses[align]}
|
|
2124
2170
|
${justifyClasses[justify]}
|
|
2125
2171
|
${className}
|
|
2126
2172
|
`, children: children }));
|
|
2127
|
-
};
|
|
2173
|
+
});
|
|
2174
|
+
Stack.displayName = 'Stack';
|
|
2128
2175
|
|
|
2129
2176
|
/**
|
|
2130
2177
|
* Grid component for arranging children in a CSS grid layout.
|
|
2131
2178
|
*
|
|
2179
|
+
* Supports ref forwarding for DOM access.
|
|
2180
|
+
*
|
|
2132
2181
|
* Column options: 1, 2, 3, 4, 6, 12
|
|
2133
2182
|
*
|
|
2134
2183
|
* Responsive breakpoints (mobile-first):
|
|
@@ -2153,7 +2202,7 @@ const Stack = ({ children, direction = 'vertical', spacing = 'md', align = 'stre
|
|
|
2153
2202
|
* <Card>Item 2</Card>
|
|
2154
2203
|
* </Grid>
|
|
2155
2204
|
*/
|
|
2156
|
-
const Grid = ({ children, columns = 1, sm, md, lg, xl, gap = 'md', className = '', }) => {
|
|
2205
|
+
const Grid = forwardRef(({ children, columns = 1, sm, md, lg, xl, gap = 'md', className = '', ...htmlProps }, ref) => {
|
|
2157
2206
|
// Base column classes
|
|
2158
2207
|
const baseColumnClasses = {
|
|
2159
2208
|
1: 'grid-cols-1',
|
|
@@ -2212,18 +2261,20 @@ const Grid = ({ children, columns = 1, sm, md, lg, xl, gap = 'md', className = '
|
|
|
2212
2261
|
lg ? lgColumnClasses[lg] : '',
|
|
2213
2262
|
xl ? xlColumnClasses[xl] : '',
|
|
2214
2263
|
].filter(Boolean).join(' ');
|
|
2215
|
-
return (jsx("div", { className: `
|
|
2264
|
+
return (jsx("div", { ref: ref, ...htmlProps, className: `
|
|
2216
2265
|
grid
|
|
2217
2266
|
${columnClassList}
|
|
2218
2267
|
${gapClasses[gap]}
|
|
2219
2268
|
${className}
|
|
2220
2269
|
`, children: children }));
|
|
2221
|
-
};
|
|
2270
|
+
});
|
|
2271
|
+
Grid.displayName = 'Grid';
|
|
2222
2272
|
|
|
2223
2273
|
/**
|
|
2224
2274
|
* Box component for generic containers with design system spacing and borders.
|
|
2275
|
+
* Supports ref forwarding for DOM access.
|
|
2225
2276
|
*/
|
|
2226
|
-
const Box = ({ children, padding, paddingTop, paddingBottom, paddingLeft, paddingRight, margin, marginTop, marginBottom, marginLeft, marginRight, border = 'none', borderColor = 'default', rounded, width, height, className = '', ...htmlProps }) => {
|
|
2277
|
+
const Box = forwardRef(({ children, padding, paddingTop, paddingBottom, paddingLeft, paddingRight, margin, marginTop, marginBottom, marginLeft, marginRight, border = 'none', borderColor = 'default', rounded, width, height, className = '', ...htmlProps }, ref) => {
|
|
2227
2278
|
const spacingMap = {
|
|
2228
2279
|
none: '0',
|
|
2229
2280
|
xs: '2',
|
|
@@ -2308,7 +2359,7 @@ const Box = ({ children, padding, paddingTop, paddingBottom, paddingLeft, paddin
|
|
|
2308
2359
|
};
|
|
2309
2360
|
return roundedClasses[rounded];
|
|
2310
2361
|
};
|
|
2311
|
-
return (jsx("div", { ...htmlProps, className: `
|
|
2362
|
+
return (jsx("div", { ref: ref, ...htmlProps, className: `
|
|
2312
2363
|
${getPaddingClass()}
|
|
2313
2364
|
${getMarginClass()}
|
|
2314
2365
|
${borderClasses[border]}
|
|
@@ -2318,7 +2369,8 @@ const Box = ({ children, padding, paddingTop, paddingBottom, paddingLeft, paddin
|
|
|
2318
2369
|
${getHeightClass()}
|
|
2319
2370
|
${className}
|
|
2320
2371
|
`, children: children }));
|
|
2321
|
-
};
|
|
2372
|
+
});
|
|
2373
|
+
Box.displayName = 'Box';
|
|
2322
2374
|
|
|
2323
2375
|
/**
|
|
2324
2376
|
* GridItem component for items within a Grid layout.
|
|
@@ -2363,6 +2415,8 @@ const GridItem = ({ colSpan, rowSpan, children, className = '', ...boxProps }) =
|
|
|
2363
2415
|
/**
|
|
2364
2416
|
* Text component for consistent typography across the application.
|
|
2365
2417
|
*
|
|
2418
|
+
* Supports ref forwarding for DOM access.
|
|
2419
|
+
*
|
|
2366
2420
|
* Size scale:
|
|
2367
2421
|
* - xs: 0.75rem (12px)
|
|
2368
2422
|
* - sm: 0.875rem (14px)
|
|
@@ -2370,8 +2424,21 @@ const GridItem = ({ colSpan, rowSpan, children, className = '', ...boxProps }) =
|
|
|
2370
2424
|
* - lg: 1.125rem (18px)
|
|
2371
2425
|
* - xl: 1.25rem (20px)
|
|
2372
2426
|
* - 2xl: 1.5rem (24px)
|
|
2427
|
+
*
|
|
2428
|
+
* @example
|
|
2429
|
+
* ```tsx
|
|
2430
|
+
* <Text size="lg" weight="semibold" color="primary">
|
|
2431
|
+
* Hello World
|
|
2432
|
+
* </Text>
|
|
2433
|
+
*
|
|
2434
|
+
* <Text color="warning">Warning message</Text>
|
|
2435
|
+
*
|
|
2436
|
+
* // With ref
|
|
2437
|
+
* const textRef = useRef<HTMLParagraphElement>(null);
|
|
2438
|
+
* <Text ref={textRef}>Measurable text</Text>
|
|
2439
|
+
* ```
|
|
2373
2440
|
*/
|
|
2374
|
-
const Text = ({ children, as: Component = 'p', size = 'base', weight = 'normal', color = 'primary', align = 'left', truncate = false, lineClamp, transform, className = '', }) => {
|
|
2441
|
+
const Text = forwardRef(({ children, as: Component = 'p', size = 'base', weight = 'normal', color = 'primary', align = 'left', truncate = false, lineClamp, transform, className = '', ...htmlProps }, ref) => {
|
|
2375
2442
|
const sizeClasses = {
|
|
2376
2443
|
xs: 'text-xs',
|
|
2377
2444
|
sm: 'text-sm',
|
|
@@ -2393,6 +2460,7 @@ const Text = ({ children, as: Component = 'p', size = 'base', weight = 'normal',
|
|
|
2393
2460
|
accent: 'text-primary-600',
|
|
2394
2461
|
error: 'text-error-600',
|
|
2395
2462
|
success: 'text-success-600',
|
|
2463
|
+
warning: 'text-warning-600',
|
|
2396
2464
|
};
|
|
2397
2465
|
const alignClasses = {
|
|
2398
2466
|
left: 'text-left',
|
|
@@ -2424,8 +2492,9 @@ const Text = ({ children, as: Component = 'p', size = 'base', weight = 'normal',
|
|
|
2424
2492
|
lineClamp ? lineClampClasses[lineClamp] : '',
|
|
2425
2493
|
className,
|
|
2426
2494
|
].filter(Boolean).join(' ');
|
|
2427
|
-
return (jsx(Component, { className: classes, children: children }));
|
|
2428
|
-
};
|
|
2495
|
+
return (jsx(Component, { ref: ref, className: classes, ...htmlProps, children: children }));
|
|
2496
|
+
});
|
|
2497
|
+
Text.displayName = 'Text';
|
|
2429
2498
|
|
|
2430
2499
|
const toastStyles = {
|
|
2431
2500
|
success: {
|
|
@@ -2530,6 +2599,7 @@ const sizeClasses$4 = {
|
|
|
2530
2599
|
};
|
|
2531
2600
|
function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton = true, animation = 'scale', }) {
|
|
2532
2601
|
const modalRef = useRef(null);
|
|
2602
|
+
const mouseDownOnBackdrop = useRef(false);
|
|
2533
2603
|
const titleId = useId();
|
|
2534
2604
|
// Handle escape key
|
|
2535
2605
|
useEffect(() => {
|
|
@@ -2547,11 +2617,22 @@ function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton
|
|
|
2547
2617
|
document.body.style.overflow = 'unset';
|
|
2548
2618
|
};
|
|
2549
2619
|
}, [isOpen, onClose]);
|
|
2550
|
-
//
|
|
2551
|
-
const
|
|
2620
|
+
// Track if mousedown originated on the backdrop
|
|
2621
|
+
const handleBackdropMouseDown = (e) => {
|
|
2552
2622
|
if (e.target === e.currentTarget) {
|
|
2623
|
+
mouseDownOnBackdrop.current = true;
|
|
2624
|
+
}
|
|
2625
|
+
else {
|
|
2626
|
+
mouseDownOnBackdrop.current = false;
|
|
2627
|
+
}
|
|
2628
|
+
};
|
|
2629
|
+
// Handle click outside - only close if both mousedown and click happened on backdrop
|
|
2630
|
+
const handleBackdropClick = (e) => {
|
|
2631
|
+
if (e.target === e.currentTarget && mouseDownOnBackdrop.current) {
|
|
2553
2632
|
onClose();
|
|
2554
2633
|
}
|
|
2634
|
+
// Reset the flag after handling click
|
|
2635
|
+
mouseDownOnBackdrop.current = false;
|
|
2555
2636
|
};
|
|
2556
2637
|
const getAnimationClass = () => {
|
|
2557
2638
|
switch (animation) {
|
|
@@ -2571,7 +2652,7 @@ function Modal({ isOpen, onClose, title, children, size = 'md', showCloseButton
|
|
|
2571
2652
|
};
|
|
2572
2653
|
if (!isOpen)
|
|
2573
2654
|
return null;
|
|
2574
|
-
return (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", onClick: handleBackdropClick, children: jsxs("div", { ref: modalRef, className: `${sizeClasses$4[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, children: [jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-paper-200", children: [jsx("h3", { id: titleId, className: "text-lg font-medium text-ink-900", children: title }), showCloseButton && (jsx("button", { onClick: onClose, className: "text-ink-400 hover:text-ink-600 transition-colors", "aria-label": "Close modal", children: jsx(X, { className: "h-5 w-5" }) }))] }), jsx("div", { className: "px-6 py-4", children: children })] }) }));
|
|
2655
|
+
return (jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-ink-900 bg-opacity-50 backdrop-blur-sm animate-fade-in", onMouseDown: handleBackdropMouseDown, onClick: handleBackdropClick, children: jsxs("div", { ref: modalRef, className: `${sizeClasses$4[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, children: [jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-paper-200", children: [jsx("h3", { id: titleId, className: "text-lg font-medium text-ink-900", children: title }), showCloseButton && (jsx("button", { onClick: onClose, className: "text-ink-400 hover:text-ink-600 transition-colors", "aria-label": "Close modal", children: jsx(X, { className: "h-5 w-5" }) }))] }), jsx("div", { className: "px-6 py-4", children: children })] }) }));
|
|
2575
2656
|
}
|
|
2576
2657
|
function ModalFooter({ children }) {
|
|
2577
2658
|
return (jsx("div", { className: "flex items-center justify-end gap-3 px-6 py-4 border-t border-paper-200 bg-paper-50", children: children }));
|
|
@@ -5956,19 +6037,19 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
|
|
|
5956
6037
|
spacing: orientation === 'vertical' ? 'mt-8' : 'mt-8',
|
|
5957
6038
|
},
|
|
5958
6039
|
};
|
|
5959
|
-
return (jsxs("div", { className: `w-full ${orientation === 'vertical' ? `flex ${sizeClasses[size].gap}` : ''}`, children: [jsx("div", { className: `
|
|
5960
|
-
flex ${orientation === 'vertical' ? 'flex-col' : ''}
|
|
6040
|
+
return (jsxs("div", { className: `w-full ${orientation === 'vertical' ? `flex ${sizeClasses[size].gap}` : ''}`, children: [jsx("div", { className: `
|
|
6041
|
+
flex ${orientation === 'vertical' ? 'flex-col' : ''}
|
|
5961
6042
|
${variant === 'underline'
|
|
5962
6043
|
? orientation === 'vertical'
|
|
5963
6044
|
? `border-r border-paper-200 ${sizeClasses[size].gap} pr-6`
|
|
5964
6045
|
: `border-b border-paper-200 ${sizeClasses[size].gap}`
|
|
5965
|
-
: `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
|
|
5966
|
-
${sizeClasses[size].minWidth}
|
|
6046
|
+
: `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
|
|
6047
|
+
${sizeClasses[size].minWidth}
|
|
5967
6048
|
`, role: "tablist", children: tabs.map((tab) => {
|
|
5968
6049
|
const isActive = activeTab === tab.id;
|
|
5969
|
-
return (jsxs("button", { role: "tab", "aria-selected": isActive, "aria-controls": `panel-${tab.id}`, disabled: tab.disabled, onClick: () => !tab.disabled && handleTabChange(tab.id), className: `
|
|
5970
|
-
flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
|
|
5971
|
-
${orientation === 'vertical' ? 'w-full justify-start' : ''}
|
|
6050
|
+
return (jsxs("button", { role: "tab", "aria-selected": isActive, "aria-controls": `panel-${tab.id}`, disabled: tab.disabled, onClick: () => !tab.disabled && handleTabChange(tab.id), className: `
|
|
6051
|
+
flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
|
|
6052
|
+
${orientation === 'vertical' ? 'w-full justify-start' : ''}
|
|
5972
6053
|
${variant === 'underline'
|
|
5973
6054
|
? isActive
|
|
5974
6055
|
? orientation === 'vertical'
|
|
@@ -5979,8 +6060,8 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
|
|
|
5979
6060
|
: 'text-ink-600 hover:text-ink-900 border-b-2 border-transparent'
|
|
5980
6061
|
: isActive
|
|
5981
6062
|
? 'bg-white text-accent-900 rounded-md shadow-xs'
|
|
5982
|
-
: 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
|
|
5983
|
-
${tab.disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
6063
|
+
: 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
|
|
6064
|
+
${tab.disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
5984
6065
|
`, children: [tab.icon && jsx("span", { className: `flex-shrink-0 ${sizeClasses[size].icon}`, children: tab.icon }), jsx("span", { children: tab.label })] }, tab.id));
|
|
5985
6066
|
}) }), jsx("div", { className: `${orientation === 'vertical' ? 'flex-1' : sizeClasses[size].spacing}`, children: tabs.map((tab) => (jsx("div", { id: `panel-${tab.id}`, role: "tabpanel", "aria-labelledby": tab.id, hidden: activeTab !== tab.id, className: activeTab === tab.id ? 'animate-fade-in' : '', children: activeTab === tab.id && tab.content }, tab.id))) })] }));
|
|
5986
6067
|
}
|
|
@@ -6056,99 +6137,6 @@ function StepIndicator({ steps, currentStep, variant = 'horizontal', onStepClick
|
|
|
6056
6137
|
}) }) }));
|
|
6057
6138
|
}
|
|
6058
6139
|
|
|
6059
|
-
function Table$1({ data, columns, keyExtractor, selectable = false, expandable = false, onRowSelect, renderExpandedRow, emptyState, className = '', onSort, sortColumn: externalSortColumn, sortDirection: externalSortDirection, }) {
|
|
6060
|
-
const [internalSortColumn, setInternalSortColumn] = useState(null);
|
|
6061
|
-
const [internalSortDirection, setInternalSortDirection] = useState(null);
|
|
6062
|
-
// Use external sort state if provided, otherwise use internal state
|
|
6063
|
-
const sortColumn = externalSortColumn !== undefined ? externalSortColumn : internalSortColumn;
|
|
6064
|
-
const sortDirection = externalSortDirection !== undefined ? externalSortDirection : internalSortDirection;
|
|
6065
|
-
const [selectedRows, setSelectedRows] = useState(new Set());
|
|
6066
|
-
const [expandedRows, setExpandedRows] = useState(new Set());
|
|
6067
|
-
// Handle sorting
|
|
6068
|
-
const handleSort = (columnKey) => {
|
|
6069
|
-
let newDirection;
|
|
6070
|
-
if (sortColumn === columnKey) {
|
|
6071
|
-
if (sortDirection === 'asc') {
|
|
6072
|
-
newDirection = 'desc';
|
|
6073
|
-
}
|
|
6074
|
-
else if (sortDirection === 'desc') {
|
|
6075
|
-
newDirection = null;
|
|
6076
|
-
}
|
|
6077
|
-
else {
|
|
6078
|
-
newDirection = 'asc';
|
|
6079
|
-
}
|
|
6080
|
-
}
|
|
6081
|
-
else {
|
|
6082
|
-
newDirection = 'asc';
|
|
6083
|
-
}
|
|
6084
|
-
// If using external sort control, call the callback
|
|
6085
|
-
if (onSort) {
|
|
6086
|
-
onSort(columnKey, newDirection);
|
|
6087
|
-
}
|
|
6088
|
-
else {
|
|
6089
|
-
// Otherwise update internal state
|
|
6090
|
-
setInternalSortColumn(newDirection === null ? null : columnKey);
|
|
6091
|
-
setInternalSortDirection(newDirection);
|
|
6092
|
-
}
|
|
6093
|
-
};
|
|
6094
|
-
// Handle row selection
|
|
6095
|
-
const handleRowSelect = (rowKey) => {
|
|
6096
|
-
const newSelected = new Set(selectedRows);
|
|
6097
|
-
if (newSelected.has(rowKey)) {
|
|
6098
|
-
newSelected.delete(rowKey);
|
|
6099
|
-
}
|
|
6100
|
-
else {
|
|
6101
|
-
newSelected.add(rowKey);
|
|
6102
|
-
}
|
|
6103
|
-
setSelectedRows(newSelected);
|
|
6104
|
-
onRowSelect?.(Array.from(newSelected));
|
|
6105
|
-
};
|
|
6106
|
-
// Handle select all
|
|
6107
|
-
const handleSelectAll = () => {
|
|
6108
|
-
if (selectedRows.size === data.length) {
|
|
6109
|
-
setSelectedRows(new Set());
|
|
6110
|
-
onRowSelect?.([]);
|
|
6111
|
-
}
|
|
6112
|
-
else {
|
|
6113
|
-
const allKeys = new Set(data.map(keyExtractor));
|
|
6114
|
-
setSelectedRows(allKeys);
|
|
6115
|
-
onRowSelect?.(Array.from(allKeys));
|
|
6116
|
-
}
|
|
6117
|
-
};
|
|
6118
|
-
// Handle row expansion
|
|
6119
|
-
const handleRowExpand = (rowKey) => {
|
|
6120
|
-
const newExpanded = new Set(expandedRows);
|
|
6121
|
-
if (newExpanded.has(rowKey)) {
|
|
6122
|
-
newExpanded.delete(rowKey);
|
|
6123
|
-
}
|
|
6124
|
-
else {
|
|
6125
|
-
newExpanded.add(rowKey);
|
|
6126
|
-
}
|
|
6127
|
-
setExpandedRows(newExpanded);
|
|
6128
|
-
};
|
|
6129
|
-
const getSortIcon = (columnKey) => {
|
|
6130
|
-
if (sortColumn !== columnKey) {
|
|
6131
|
-
return jsx(ArrowUpDown, { className: "h-4 w-4 text-ink-400" });
|
|
6132
|
-
}
|
|
6133
|
-
if (sortDirection === 'asc') {
|
|
6134
|
-
return jsx(ArrowUp, { className: "h-4 w-4 text-accent-600" });
|
|
6135
|
-
}
|
|
6136
|
-
if (sortDirection === 'desc') {
|
|
6137
|
-
return jsx(ArrowDown, { className: "h-4 w-4 text-accent-600" });
|
|
6138
|
-
}
|
|
6139
|
-
return jsx(ArrowUpDown, { className: "h-4 w-4 text-ink-400" });
|
|
6140
|
-
};
|
|
6141
|
-
if (data.length === 0 && emptyState) {
|
|
6142
|
-
return jsx("div", { children: emptyState });
|
|
6143
|
-
}
|
|
6144
|
-
return (jsx("div", { className: `overflow-x-auto ${className}`, children: jsxs("table", { className: "table", children: [jsx("thead", { className: "table-header", children: jsxs("tr", { children: [selectable && (jsx("th", { className: "table-header-cell w-12", children: jsx("input", { type: "checkbox", checked: selectedRows.size === data.length && data.length > 0, onChange: handleSelectAll, className: "w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400", "aria-label": "Select all rows" }) })), expandable && jsx("th", { className: "table-header-cell w-12" }), columns.map((column) => (jsx("th", { className: "table-header-cell", style: { width: column.width }, children: column.sortable ? (jsxs("button", { onClick: () => handleSort(column.key), className: "group inline-flex items-center gap-2 hover:text-ink-900 transition-colors", children: [jsx("span", { children: column.header }), getSortIcon(column.key)] })) : (column.header) }, column.key)))] }) }), jsx("tbody", { children: data.map((row) => {
|
|
6145
|
-
const rowKey = keyExtractor(row);
|
|
6146
|
-
const isSelected = selectedRows.has(rowKey);
|
|
6147
|
-
const isExpanded = expandedRows.has(rowKey);
|
|
6148
|
-
return (jsxs(React__default.Fragment, { children: [jsxs("tr", { className: `table-row ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : ''}`, children: [selectable && (jsx("td", { className: "table-cell", children: jsx("input", { type: "checkbox", checked: isSelected, onChange: () => handleRowSelect(rowKey), className: "w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400", "aria-label": `Select row ${rowKey}` }) })), expandable && (jsx("td", { className: "table-cell", children: jsx("button", { onClick: () => handleRowExpand(rowKey), className: "text-ink-500 hover:text-ink-900 transition-colors", "aria-label": isExpanded ? 'Collapse row' : 'Expand row', children: isExpanded ? (jsx(ChevronDown, { className: "h-4 w-4" })) : (jsx(ChevronRight, { className: "h-4 w-4" })) }) })), columns.map((column) => (jsx("td", { className: "table-cell", children: column.accessor ? column.accessor(row) : row[column.key] }, column.key)))] }), expandable && isExpanded && renderExpandedRow && (jsx("tr", { children: jsx("td", { colSpan: columns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0), className: "px-6 py-4 bg-paper-50", children: renderExpandedRow(row) }) }))] }, rowKey));
|
|
6149
|
-
}) })] }) }));
|
|
6150
|
-
}
|
|
6151
|
-
|
|
6152
6140
|
function Badge({ children, variant = 'neutral', size = 'md', icon, onRemove, className = '', dot = false, }) {
|
|
6153
6141
|
const variantStyles = {
|
|
6154
6142
|
success: 'bg-success-50 text-success-700 border-success-200',
|
|
@@ -6256,8 +6244,8 @@ const Avatar = ({ firstName, lastName, fallbackText = 'U', imageUrl, size = 'md'
|
|
|
6256
6244
|
`, style: { textShadow: '0 1px 2px rgba(0,0,0,0.3)' }, children: getInitials() }) }));
|
|
6257
6245
|
};
|
|
6258
6246
|
|
|
6259
|
-
function EmptyState({ icon, title, description, action, secondaryAction, }) {
|
|
6260
|
-
return (jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center", children: [icon && (jsx("div", { className: "mb-6 text-ink-400", children: icon })), jsx("h3", { className: "text-lg font-medium text-ink-900 mb-2", children: title }), jsx("p", { className: "text-sm text-ink-600 max-w-md mb-8", children: description }), (action || secondaryAction) && (jsxs("div", { className: "flex items-center gap-3", children: [action && (jsx(Button, { variant: "primary", onClick: action.onClick, children: action.label })), secondaryAction && (jsx(Button, { variant: "secondary", onClick: secondaryAction.onClick, children: secondaryAction.label }))] }))] }));
|
|
6247
|
+
function EmptyState({ icon, title, description, action, secondaryAction, children, }) {
|
|
6248
|
+
return (jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center", children: [icon && (jsx("div", { className: "mb-6 text-ink-400", children: icon })), jsx("h3", { className: "text-lg font-medium text-ink-900 mb-2", children: title }), jsx("p", { className: "text-sm text-ink-600 max-w-md mb-8", children: description }), children && (jsx("div", { className: "mb-8 w-full max-w-md", children: children })), (action || secondaryAction) && (jsxs("div", { className: "flex items-center gap-3", children: [action && (jsx(Button, { variant: "primary", onClick: action.onClick, children: action.label })), secondaryAction && (jsx(Button, { variant: "secondary", onClick: secondaryAction.onClick, children: secondaryAction.label }))] }))] }));
|
|
6261
6249
|
}
|
|
6262
6250
|
|
|
6263
6251
|
/**
|
|
@@ -6908,8 +6896,35 @@ const TwoColumnContent = ({ sidebar, children, className = '', }) => {
|
|
|
6908
6896
|
* </PageLayout>
|
|
6909
6897
|
* ```
|
|
6910
6898
|
*/
|
|
6911
|
-
const Page = ({ children, maxWidth
|
|
6912
|
-
|
|
6899
|
+
const Page = ({ children, maxWidth = '7xl', className = '', padding = 'normal', fixed = false }) => {
|
|
6900
|
+
// Max width classes
|
|
6901
|
+
const maxWidthClasses = {
|
|
6902
|
+
'4xl': 'max-w-4xl',
|
|
6903
|
+
'5xl': 'max-w-5xl',
|
|
6904
|
+
'6xl': 'max-w-6xl',
|
|
6905
|
+
'7xl': 'max-w-7xl',
|
|
6906
|
+
'full': 'max-w-full',
|
|
6907
|
+
};
|
|
6908
|
+
// Padding classes - responsive (fixed left/top, responsive right/bottom) vs all fixed
|
|
6909
|
+
const paddingClasses = {
|
|
6910
|
+
none: fixed ? 'p-0' : 'pt-0 pl-0 pr-0 pb-0',
|
|
6911
|
+
sm: fixed ? 'p-4' : 'pt-4 pl-4 pr-4 pb-4 sm:pr-6 md:pr-8 sm:pb-6 md:pb-8',
|
|
6912
|
+
normal: fixed ? 'pt-12 pl-20 pr-16 pb-12' : 'pt-12 pl-20 pr-4 pb-4 sm:pr-8 md:pr-12 lg:pr-16 sm:pb-8 md:pb-12 lg:pb-16',
|
|
6913
|
+
lg: fixed ? 'pt-16 pl-24 pr-20 pb-16' : 'pt-16 pl-24 pr-6 pb-6 sm:pr-12 md:pr-16 lg:pr-20 sm:pb-12 md:pb-16 lg:pb-20',
|
|
6914
|
+
};
|
|
6915
|
+
// Margin classes - responsive (fixed left/top, responsive right/bottom) vs all fixed
|
|
6916
|
+
const marginClasses = fixed
|
|
6917
|
+
? 'mt-4 ml-4 mr-4 mb-4'
|
|
6918
|
+
: 'mt-4 ml-4 mr-4 mb-4 sm:mr-6 md:mr-8 lg:mr-auto sm:mb-6 md:mb-8';
|
|
6919
|
+
return (jsx("div", { className: "min-h-screen bg-paper-100", children: jsx("div", { className: `
|
|
6920
|
+
bg-white bg-subtle-grain rounded-sm shadow-lg border-l-4 border-paper-300
|
|
6921
|
+
min-h-[calc(100vh-2rem)] relative
|
|
6922
|
+
notebook-margin notebook-ruled
|
|
6923
|
+
${maxWidthClasses[maxWidth]}
|
|
6924
|
+
${paddingClasses[padding]}
|
|
6925
|
+
${marginClasses}
|
|
6926
|
+
${className}
|
|
6927
|
+
`.trim().replace(/\s+/g, ' '), children: children }) }));
|
|
6913
6928
|
};
|
|
6914
6929
|
|
|
6915
6930
|
/**
|
|
@@ -7244,9 +7259,11 @@ function getColumnStyle(column, dynamicWidth) {
|
|
|
7244
7259
|
* />
|
|
7245
7260
|
* ```
|
|
7246
7261
|
*/
|
|
7247
|
-
function DataTable({ data, columns, loading = false, error = null, emptyMessage = 'No data available', loadingRows = 5, className = '', onSortChange, currentSort = null, onEdit, onDelete, actions = [], onRowClick, onRowDoubleClick, selectable = false, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable = false, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron = false,
|
|
7262
|
+
function DataTable({ data, columns, loading = false, error = null, emptyMessage = 'No data available', loadingRows = 5, className = '', onSortChange, currentSort = null, onEdit, onDelete, actions = [], enableContextMenu = true, onRowClick, onRowDoubleClick, selectable = false, selectedRows: externalSelectedRows, onRowSelect, keyExtractor, expandable = false, expandedRows: externalExpandedRows, renderExpandedRow, expandedRowConfig, showExpandChevron = false,
|
|
7248
7263
|
// Visual customization props
|
|
7249
|
-
striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, highlightedRowId, bordered = false, borderColor = 'border-paper-200', disableHover = false, hiddenColumns = [], headerClassName = '', renderEmptyState: customRenderEmptyState, resizable = false, onColumnResize, reorderable = false, onColumnReorder, virtualized = false, virtualHeight = '600px', virtualRowHeight = 60,
|
|
7264
|
+
striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, highlightedRowId, bordered = false, borderColor = 'border-paper-200', disableHover = false, hiddenColumns = [], headerClassName = '', renderEmptyState: customRenderEmptyState, resizable = false, onColumnResize, reorderable = false, onColumnReorder, virtualized = false, virtualHeight = '600px', virtualRowHeight = 60,
|
|
7265
|
+
// Pagination props
|
|
7266
|
+
paginated = false, currentPage = 1, pageSize = 10, totalItems, onPageChange, pageSizeOptions = [10, 25, 50, 100], onPageSizeChange, showPageSizeSelector = true, }) {
|
|
7250
7267
|
// Column resizing state
|
|
7251
7268
|
const [columnWidths, setColumnWidths] = useState({});
|
|
7252
7269
|
const [resizingColumn, setResizingColumn] = useState(null);
|
|
@@ -7261,6 +7278,12 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
|
|
|
7261
7278
|
const tableContainerRef = useRef(null);
|
|
7262
7279
|
// Row hover state (for coordinating primary + secondary row highlighting)
|
|
7263
7280
|
const [hoveredRowKey, setHoveredRowKey] = useState(null);
|
|
7281
|
+
// Context menu state
|
|
7282
|
+
const [contextMenuState, setContextMenuState] = useState({
|
|
7283
|
+
isOpen: false,
|
|
7284
|
+
position: { x: 0, y: 0 },
|
|
7285
|
+
item: null,
|
|
7286
|
+
});
|
|
7264
7287
|
// Filter columns based on hiddenColumns
|
|
7265
7288
|
const baseVisibleColumns = columns.filter(col => !hiddenColumns.includes(String(col.key)));
|
|
7266
7289
|
// Initialize column order on mount or when columns change
|
|
@@ -7473,16 +7496,52 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
|
|
|
7473
7496
|
}
|
|
7474
7497
|
});
|
|
7475
7498
|
}
|
|
7499
|
+
// Combine all actions: built-in first, then custom actions, then delete last
|
|
7500
|
+
// Delete is stored separately to ensure it's always last
|
|
7501
|
+
let deleteAction = null;
|
|
7476
7502
|
if (onDelete) {
|
|
7477
|
-
|
|
7503
|
+
deleteAction = {
|
|
7478
7504
|
label: 'Delete',
|
|
7479
7505
|
icon: Trash,
|
|
7480
7506
|
onClick: onDelete,
|
|
7481
7507
|
variant: 'danger',
|
|
7482
7508
|
tooltip: 'Delete item'
|
|
7483
|
-
}
|
|
7509
|
+
};
|
|
7484
7510
|
}
|
|
7485
|
-
|
|
7511
|
+
// Build final actions array with consistent ordering:
|
|
7512
|
+
// 1. Edit (first - most common action)
|
|
7513
|
+
// 2. View Details
|
|
7514
|
+
// 3. Add Related actions
|
|
7515
|
+
// 4. Manage Related actions
|
|
7516
|
+
// 5. Custom actions (from actions prop)
|
|
7517
|
+
// 6. Delete (always last - destructive action)
|
|
7518
|
+
const allActions = [
|
|
7519
|
+
...builtInActions,
|
|
7520
|
+
...actions,
|
|
7521
|
+
...(deleteAction ? [deleteAction] : [])
|
|
7522
|
+
];
|
|
7523
|
+
// Convert actions to menu items for context menu
|
|
7524
|
+
const convertActionsToMenuItems = (item) => {
|
|
7525
|
+
const visibleActions = allActions.filter(action => !action.show || action.show(item));
|
|
7526
|
+
return visibleActions.map((action, idx) => {
|
|
7527
|
+
let iconElement = null;
|
|
7528
|
+
if (action.icon) {
|
|
7529
|
+
if (React__default.isValidElement(action.icon)) {
|
|
7530
|
+
iconElement = action.icon;
|
|
7531
|
+
}
|
|
7532
|
+
else {
|
|
7533
|
+
iconElement = React__default.createElement(action.icon, { className: 'h-4 w-4' });
|
|
7534
|
+
}
|
|
7535
|
+
}
|
|
7536
|
+
return {
|
|
7537
|
+
id: `action-${idx}`,
|
|
7538
|
+
label: action.label,
|
|
7539
|
+
icon: iconElement,
|
|
7540
|
+
onClick: () => action.onClick(item),
|
|
7541
|
+
danger: action.variant === 'danger',
|
|
7542
|
+
};
|
|
7543
|
+
});
|
|
7544
|
+
};
|
|
7486
7545
|
// Selection state management
|
|
7487
7546
|
const [internalSelectedRows, setInternalSelectedRows] = useState(new Set());
|
|
7488
7547
|
// Expansion state management
|
|
@@ -7640,7 +7699,19 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
|
|
|
7640
7699
|
// Hover state for row pair (primary + secondary)
|
|
7641
7700
|
const isHovered = hoveredRowKey === rowKey;
|
|
7642
7701
|
const hoverClass = disableHover ? '' : (isHovered ? 'bg-paper-100' : '');
|
|
7643
|
-
return (jsxs(React__default.Fragment, { children: [jsxs("tr", { className: `table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} ${borderClass}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), onClick: () => onRowClick?.(item),
|
|
7702
|
+
return (jsxs(React__default.Fragment, { children: [jsxs("tr", { className: `table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} ${borderClass}`, onMouseEnter: () => !disableHover && setHoveredRowKey(rowKey), onMouseLeave: () => !disableHover && setHoveredRowKey(null), onClick: () => onRowClick?.(item), onContextMenu: (e) => {
|
|
7703
|
+
if (enableContextMenu && allActions.length > 0) {
|
|
7704
|
+
e.preventDefault();
|
|
7705
|
+
e.stopPropagation();
|
|
7706
|
+
const x = e.clientX;
|
|
7707
|
+
const y = e.clientY;
|
|
7708
|
+
setContextMenuState({
|
|
7709
|
+
isOpen: true,
|
|
7710
|
+
position: { x, y },
|
|
7711
|
+
item,
|
|
7712
|
+
});
|
|
7713
|
+
}
|
|
7714
|
+
}, onDoubleClick: () => {
|
|
7644
7715
|
// Priority 1: If there's an onEdit handler (legacy), trigger it
|
|
7645
7716
|
if (onEdit) {
|
|
7646
7717
|
onEdit(item);
|
|
@@ -7796,10 +7867,23 @@ striped = false, stripedColor, density = 'normal', rowClassName, rowHighlight, h
|
|
|
7796
7867
|
}, children: jsx("div", { className: "absolute right-0 top-0 bottom-0 w-1 bg-paper-300 group-hover:bg-accent-400 transition-colors" }) }))] }, columnKey));
|
|
7797
7868
|
})] }) }), jsx("tbody", { className: "bg-white table-loading transition-opacity duration-200", children: loading && data.length === 0 ? (renderLoadingSkeleton()) : data.length === 0 ? (renderEmptyStateContent()) : (renderDataRows()) })] })] }));
|
|
7798
7869
|
// Wrap in scrollable container if virtualized
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7870
|
+
const finalContent = virtualized ? (jsx("div", { ref: tableContainerRef, onScroll: handleScroll, style: { height: virtualHeight, overflow: 'auto' }, className: "rounded-lg", children: tableContent })) : tableContent;
|
|
7871
|
+
// Calculate pagination values
|
|
7872
|
+
const effectiveTotalItems = totalItems ?? data.length;
|
|
7873
|
+
const totalPages = Math.ceil(effectiveTotalItems / pageSize);
|
|
7874
|
+
// Page size selector options
|
|
7875
|
+
const pageSizeSelectOptions = pageSizeOptions.map(size => ({
|
|
7876
|
+
value: String(size),
|
|
7877
|
+
label: `${size} per page`,
|
|
7878
|
+
}));
|
|
7879
|
+
// Render pagination controls
|
|
7880
|
+
const renderPaginationControls = () => {
|
|
7881
|
+
if (!paginated)
|
|
7882
|
+
return null;
|
|
7883
|
+
return (jsxs("div", { className: "flex items-center justify-between mb-4 px-1", children: [jsxs("div", { className: "flex items-center gap-4", children: [showPageSizeSelector && onPageSizeChange && (jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm text-ink-600", children: "Show:" }), jsx(Select, { options: pageSizeSelectOptions, value: String(pageSize), onChange: (value) => onPageSizeChange?.(Number(value)) })] })), jsx("span", { className: "text-sm text-ink-600", children: effectiveTotalItems > 0 ? (jsxs(Fragment, { children: ["Showing ", ((currentPage - 1) * pageSize) + 1, " - ", Math.min(currentPage * pageSize, effectiveTotalItems), " of ", effectiveTotalItems] })) : ('No items') })] }), totalPages > 1 && onPageChange && (jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: onPageChange }))] }));
|
|
7884
|
+
};
|
|
7885
|
+
// Render with context menu
|
|
7886
|
+
return (jsxs(Fragment, { children: [renderPaginationControls(), finalContent, contextMenuState.isOpen && contextMenuState.item && (jsx(Menu, { items: convertActionsToMenuItems(contextMenuState.item), position: contextMenuState.position, onClose: () => setContextMenuState({ isOpen: false, position: { x: 0, y: 0 }, item: null }) }))] }));
|
|
7803
7887
|
}
|
|
7804
7888
|
|
|
7805
7889
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
@@ -11611,12 +11695,12 @@ var bessel$1 = {};
|
|
|
11611
11695
|
|
|
11612
11696
|
/* bessel.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
|
11613
11697
|
|
|
11614
|
-
(function (exports) {
|
|
11698
|
+
(function (exports$1) {
|
|
11615
11699
|
(function (factory) {
|
|
11616
11700
|
/*jshint ignore:start */
|
|
11617
11701
|
if(typeof DO_NOT_EXPORT_BESSEL === 'undefined') {
|
|
11618
11702
|
{
|
|
11619
|
-
factory(exports);
|
|
11703
|
+
factory(exports$1);
|
|
11620
11704
|
}
|
|
11621
11705
|
} else {
|
|
11622
11706
|
factory({});
|
|
@@ -11850,7 +11934,7 @@ var bessel$1 = {};
|
|
|
11850
11934
|
|
|
11851
11935
|
var jstat = {exports: {}};
|
|
11852
11936
|
|
|
11853
|
-
(function (module, exports) {
|
|
11937
|
+
(function (module, exports$1) {
|
|
11854
11938
|
(function (window, factory) {
|
|
11855
11939
|
{
|
|
11856
11940
|
module.exports = factory();
|
|
@@ -30467,7 +30551,7 @@ var hooks = {
|
|
|
30467
30551
|
DepParser: DepParser$1,
|
|
30468
30552
|
};
|
|
30469
30553
|
|
|
30470
|
-
const {FormulaParser} = hooks$1;
|
|
30554
|
+
const {FormulaParser: FormulaParser$1} = hooks$1;
|
|
30471
30555
|
const {DepParser} = hooks;
|
|
30472
30556
|
const SSF = ssf$1;
|
|
30473
30557
|
const FormulaError = requireError();
|
|
@@ -30477,16 +30561,16 @@ const FormulaError = requireError();
|
|
|
30477
30561
|
// `\nTotal: ${funs.length}/477, ${funs.length/477*100}% implemented.`);
|
|
30478
30562
|
|
|
30479
30563
|
|
|
30480
|
-
Object.assign(FormulaParser, {
|
|
30564
|
+
Object.assign(FormulaParser$1, {
|
|
30481
30565
|
MAX_ROW: 1048576,
|
|
30482
30566
|
MAX_COLUMN: 16384,
|
|
30483
30567
|
SSF,
|
|
30484
30568
|
DepParser,
|
|
30485
30569
|
FormulaError, ...requireHelpers()
|
|
30486
30570
|
});
|
|
30487
|
-
var fastFormulaParser = FormulaParser;
|
|
30571
|
+
var fastFormulaParser = FormulaParser$1;
|
|
30488
30572
|
|
|
30489
|
-
var FormulaParser
|
|
30573
|
+
var FormulaParser = /*@__PURE__*/getDefaultExportFromCjs(fastFormulaParser);
|
|
30490
30574
|
|
|
30491
30575
|
var scheduler = {exports: {}};
|
|
30492
30576
|
|
|
@@ -30507,7 +30591,7 @@ var hasRequiredScheduler_production;
|
|
|
30507
30591
|
function requireScheduler_production () {
|
|
30508
30592
|
if (hasRequiredScheduler_production) return scheduler_production;
|
|
30509
30593
|
hasRequiredScheduler_production = 1;
|
|
30510
|
-
(function (exports) {
|
|
30594
|
+
(function (exports$1) {
|
|
30511
30595
|
function push(heap, node) {
|
|
30512
30596
|
var index = heap.length;
|
|
30513
30597
|
heap.push(node);
|
|
@@ -30556,16 +30640,16 @@ function requireScheduler_production () {
|
|
|
30556
30640
|
var diff = a.sortIndex - b.sortIndex;
|
|
30557
30641
|
return 0 !== diff ? diff : a.id - b.id;
|
|
30558
30642
|
}
|
|
30559
|
-
exports.unstable_now = void 0;
|
|
30643
|
+
exports$1.unstable_now = void 0;
|
|
30560
30644
|
if ("object" === typeof performance && "function" === typeof performance.now) {
|
|
30561
30645
|
var localPerformance = performance;
|
|
30562
|
-
exports.unstable_now = function () {
|
|
30646
|
+
exports$1.unstable_now = function () {
|
|
30563
30647
|
return localPerformance.now();
|
|
30564
30648
|
};
|
|
30565
30649
|
} else {
|
|
30566
30650
|
var localDate = Date,
|
|
30567
30651
|
initialTime = localDate.now();
|
|
30568
|
-
exports.unstable_now = function () {
|
|
30652
|
+
exports$1.unstable_now = function () {
|
|
30569
30653
|
return localDate.now() - initialTime;
|
|
30570
30654
|
};
|
|
30571
30655
|
}
|
|
@@ -30613,14 +30697,14 @@ function requireScheduler_production () {
|
|
|
30613
30697
|
function shouldYieldToHost() {
|
|
30614
30698
|
return needsPaint
|
|
30615
30699
|
? true
|
|
30616
|
-
: exports.unstable_now() - startTime < frameInterval
|
|
30700
|
+
: exports$1.unstable_now() - startTime < frameInterval
|
|
30617
30701
|
? false
|
|
30618
30702
|
: true;
|
|
30619
30703
|
}
|
|
30620
30704
|
function performWorkUntilDeadline() {
|
|
30621
30705
|
needsPaint = false;
|
|
30622
30706
|
if (isMessageLoopRunning) {
|
|
30623
|
-
var currentTime = exports.unstable_now();
|
|
30707
|
+
var currentTime = exports$1.unstable_now();
|
|
30624
30708
|
startTime = currentTime;
|
|
30625
30709
|
var hasMoreWork = true;
|
|
30626
30710
|
try {
|
|
@@ -30650,7 +30734,7 @@ function requireScheduler_production () {
|
|
|
30650
30734
|
var continuationCallback = callback(
|
|
30651
30735
|
currentTask.expirationTime <= currentTime
|
|
30652
30736
|
);
|
|
30653
|
-
currentTime = exports.unstable_now();
|
|
30737
|
+
currentTime = exports$1.unstable_now();
|
|
30654
30738
|
if ("function" === typeof continuationCallback) {
|
|
30655
30739
|
currentTask.callback = continuationCallback;
|
|
30656
30740
|
advanceTimers(currentTime);
|
|
@@ -30706,29 +30790,29 @@ function requireScheduler_production () {
|
|
|
30706
30790
|
};
|
|
30707
30791
|
function requestHostTimeout(callback, ms) {
|
|
30708
30792
|
taskTimeoutID = localSetTimeout(function () {
|
|
30709
|
-
callback(exports.unstable_now());
|
|
30793
|
+
callback(exports$1.unstable_now());
|
|
30710
30794
|
}, ms);
|
|
30711
30795
|
}
|
|
30712
|
-
exports.unstable_IdlePriority = 5;
|
|
30713
|
-
exports.unstable_ImmediatePriority = 1;
|
|
30714
|
-
exports.unstable_LowPriority = 4;
|
|
30715
|
-
exports.unstable_NormalPriority = 3;
|
|
30716
|
-
exports.unstable_Profiling = null;
|
|
30717
|
-
exports.unstable_UserBlockingPriority = 2;
|
|
30718
|
-
exports.unstable_cancelCallback = function (task) {
|
|
30796
|
+
exports$1.unstable_IdlePriority = 5;
|
|
30797
|
+
exports$1.unstable_ImmediatePriority = 1;
|
|
30798
|
+
exports$1.unstable_LowPriority = 4;
|
|
30799
|
+
exports$1.unstable_NormalPriority = 3;
|
|
30800
|
+
exports$1.unstable_Profiling = null;
|
|
30801
|
+
exports$1.unstable_UserBlockingPriority = 2;
|
|
30802
|
+
exports$1.unstable_cancelCallback = function (task) {
|
|
30719
30803
|
task.callback = null;
|
|
30720
30804
|
};
|
|
30721
|
-
exports.unstable_forceFrameRate = function (fps) {
|
|
30805
|
+
exports$1.unstable_forceFrameRate = function (fps) {
|
|
30722
30806
|
0 > fps || 125 < fps
|
|
30723
30807
|
? console.error(
|
|
30724
30808
|
"forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"
|
|
30725
30809
|
)
|
|
30726
30810
|
: (frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5);
|
|
30727
30811
|
};
|
|
30728
|
-
exports.unstable_getCurrentPriorityLevel = function () {
|
|
30812
|
+
exports$1.unstable_getCurrentPriorityLevel = function () {
|
|
30729
30813
|
return currentPriorityLevel;
|
|
30730
30814
|
};
|
|
30731
|
-
exports.unstable_next = function (eventHandler) {
|
|
30815
|
+
exports$1.unstable_next = function (eventHandler) {
|
|
30732
30816
|
switch (currentPriorityLevel) {
|
|
30733
30817
|
case 1:
|
|
30734
30818
|
case 2:
|
|
@@ -30746,10 +30830,10 @@ function requireScheduler_production () {
|
|
|
30746
30830
|
currentPriorityLevel = previousPriorityLevel;
|
|
30747
30831
|
}
|
|
30748
30832
|
};
|
|
30749
|
-
exports.unstable_requestPaint = function () {
|
|
30833
|
+
exports$1.unstable_requestPaint = function () {
|
|
30750
30834
|
needsPaint = true;
|
|
30751
30835
|
};
|
|
30752
|
-
exports.unstable_runWithPriority = function (priorityLevel, eventHandler) {
|
|
30836
|
+
exports$1.unstable_runWithPriority = function (priorityLevel, eventHandler) {
|
|
30753
30837
|
switch (priorityLevel) {
|
|
30754
30838
|
case 1:
|
|
30755
30839
|
case 2:
|
|
@@ -30768,12 +30852,12 @@ function requireScheduler_production () {
|
|
|
30768
30852
|
currentPriorityLevel = previousPriorityLevel;
|
|
30769
30853
|
}
|
|
30770
30854
|
};
|
|
30771
|
-
exports.unstable_scheduleCallback = function (
|
|
30855
|
+
exports$1.unstable_scheduleCallback = function (
|
|
30772
30856
|
priorityLevel,
|
|
30773
30857
|
callback,
|
|
30774
30858
|
options
|
|
30775
30859
|
) {
|
|
30776
|
-
var currentTime = exports.unstable_now();
|
|
30860
|
+
var currentTime = exports$1.unstable_now();
|
|
30777
30861
|
"object" === typeof options && null !== options
|
|
30778
30862
|
? ((options = options.delay),
|
|
30779
30863
|
(options =
|
|
@@ -30824,8 +30908,8 @@ function requireScheduler_production () {
|
|
|
30824
30908
|
((isMessageLoopRunning = true), schedulePerformWorkUntilDeadline())));
|
|
30825
30909
|
return priorityLevel;
|
|
30826
30910
|
};
|
|
30827
|
-
exports.unstable_shouldYield = shouldYieldToHost;
|
|
30828
|
-
exports.unstable_wrapCallback = function (callback) {
|
|
30911
|
+
exports$1.unstable_shouldYield = shouldYieldToHost;
|
|
30912
|
+
exports$1.unstable_wrapCallback = function (callback) {
|
|
30829
30913
|
var parentPriorityLevel = currentPriorityLevel;
|
|
30830
30914
|
return function () {
|
|
30831
30915
|
var previousPriorityLevel = currentPriorityLevel;
|
|
@@ -30858,13 +30942,13 @@ var hasRequiredScheduler_development;
|
|
|
30858
30942
|
function requireScheduler_development () {
|
|
30859
30943
|
if (hasRequiredScheduler_development) return scheduler_development;
|
|
30860
30944
|
hasRequiredScheduler_development = 1;
|
|
30861
|
-
(function (exports) {
|
|
30945
|
+
(function (exports$1) {
|
|
30862
30946
|
"production" !== process.env.NODE_ENV &&
|
|
30863
30947
|
(function () {
|
|
30864
30948
|
function performWorkUntilDeadline() {
|
|
30865
30949
|
needsPaint = false;
|
|
30866
30950
|
if (isMessageLoopRunning) {
|
|
30867
|
-
var currentTime = exports.unstable_now();
|
|
30951
|
+
var currentTime = exports$1.unstable_now();
|
|
30868
30952
|
startTime = currentTime;
|
|
30869
30953
|
var hasMoreWork = true;
|
|
30870
30954
|
try {
|
|
@@ -30895,7 +30979,7 @@ function requireScheduler_development () {
|
|
|
30895
30979
|
var continuationCallback = callback(
|
|
30896
30980
|
currentTask.expirationTime <= currentTime
|
|
30897
30981
|
);
|
|
30898
|
-
currentTime = exports.unstable_now();
|
|
30982
|
+
currentTime = exports$1.unstable_now();
|
|
30899
30983
|
if ("function" === typeof continuationCallback) {
|
|
30900
30984
|
currentTask.callback = continuationCallback;
|
|
30901
30985
|
advanceTimers(currentTime);
|
|
@@ -31016,32 +31100,32 @@ function requireScheduler_development () {
|
|
|
31016
31100
|
function shouldYieldToHost() {
|
|
31017
31101
|
return needsPaint
|
|
31018
31102
|
? true
|
|
31019
|
-
: exports.unstable_now() - startTime < frameInterval
|
|
31103
|
+
: exports$1.unstable_now() - startTime < frameInterval
|
|
31020
31104
|
? false
|
|
31021
31105
|
: true;
|
|
31022
31106
|
}
|
|
31023
31107
|
function requestHostTimeout(callback, ms) {
|
|
31024
31108
|
taskTimeoutID = localSetTimeout(function () {
|
|
31025
|
-
callback(exports.unstable_now());
|
|
31109
|
+
callback(exports$1.unstable_now());
|
|
31026
31110
|
}, ms);
|
|
31027
31111
|
}
|
|
31028
31112
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
|
|
31029
31113
|
"function" ===
|
|
31030
31114
|
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
|
|
31031
31115
|
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
31032
|
-
exports.unstable_now = void 0;
|
|
31116
|
+
exports$1.unstable_now = void 0;
|
|
31033
31117
|
if (
|
|
31034
31118
|
"object" === typeof performance &&
|
|
31035
31119
|
"function" === typeof performance.now
|
|
31036
31120
|
) {
|
|
31037
31121
|
var localPerformance = performance;
|
|
31038
|
-
exports.unstable_now = function () {
|
|
31122
|
+
exports$1.unstable_now = function () {
|
|
31039
31123
|
return localPerformance.now();
|
|
31040
31124
|
};
|
|
31041
31125
|
} else {
|
|
31042
31126
|
var localDate = Date,
|
|
31043
31127
|
initialTime = localDate.now();
|
|
31044
|
-
exports.unstable_now = function () {
|
|
31128
|
+
exports$1.unstable_now = function () {
|
|
31045
31129
|
return localDate.now() - initialTime;
|
|
31046
31130
|
};
|
|
31047
31131
|
}
|
|
@@ -31078,26 +31162,26 @@ function requireScheduler_development () {
|
|
|
31078
31162
|
schedulePerformWorkUntilDeadline = function () {
|
|
31079
31163
|
localSetTimeout(performWorkUntilDeadline, 0);
|
|
31080
31164
|
};
|
|
31081
|
-
exports.unstable_IdlePriority = 5;
|
|
31082
|
-
exports.unstable_ImmediatePriority = 1;
|
|
31083
|
-
exports.unstable_LowPriority = 4;
|
|
31084
|
-
exports.unstable_NormalPriority = 3;
|
|
31085
|
-
exports.unstable_Profiling = null;
|
|
31086
|
-
exports.unstable_UserBlockingPriority = 2;
|
|
31087
|
-
exports.unstable_cancelCallback = function (task) {
|
|
31165
|
+
exports$1.unstable_IdlePriority = 5;
|
|
31166
|
+
exports$1.unstable_ImmediatePriority = 1;
|
|
31167
|
+
exports$1.unstable_LowPriority = 4;
|
|
31168
|
+
exports$1.unstable_NormalPriority = 3;
|
|
31169
|
+
exports$1.unstable_Profiling = null;
|
|
31170
|
+
exports$1.unstable_UserBlockingPriority = 2;
|
|
31171
|
+
exports$1.unstable_cancelCallback = function (task) {
|
|
31088
31172
|
task.callback = null;
|
|
31089
31173
|
};
|
|
31090
|
-
exports.unstable_forceFrameRate = function (fps) {
|
|
31174
|
+
exports$1.unstable_forceFrameRate = function (fps) {
|
|
31091
31175
|
0 > fps || 125 < fps
|
|
31092
31176
|
? console.error(
|
|
31093
31177
|
"forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"
|
|
31094
31178
|
)
|
|
31095
31179
|
: (frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5);
|
|
31096
31180
|
};
|
|
31097
|
-
exports.unstable_getCurrentPriorityLevel = function () {
|
|
31181
|
+
exports$1.unstable_getCurrentPriorityLevel = function () {
|
|
31098
31182
|
return currentPriorityLevel;
|
|
31099
31183
|
};
|
|
31100
|
-
exports.unstable_next = function (eventHandler) {
|
|
31184
|
+
exports$1.unstable_next = function (eventHandler) {
|
|
31101
31185
|
switch (currentPriorityLevel) {
|
|
31102
31186
|
case 1:
|
|
31103
31187
|
case 2:
|
|
@@ -31115,10 +31199,10 @@ function requireScheduler_development () {
|
|
|
31115
31199
|
currentPriorityLevel = previousPriorityLevel;
|
|
31116
31200
|
}
|
|
31117
31201
|
};
|
|
31118
|
-
exports.unstable_requestPaint = function () {
|
|
31202
|
+
exports$1.unstable_requestPaint = function () {
|
|
31119
31203
|
needsPaint = true;
|
|
31120
31204
|
};
|
|
31121
|
-
exports.unstable_runWithPriority = function (priorityLevel, eventHandler) {
|
|
31205
|
+
exports$1.unstable_runWithPriority = function (priorityLevel, eventHandler) {
|
|
31122
31206
|
switch (priorityLevel) {
|
|
31123
31207
|
case 1:
|
|
31124
31208
|
case 2:
|
|
@@ -31137,12 +31221,12 @@ function requireScheduler_development () {
|
|
|
31137
31221
|
currentPriorityLevel = previousPriorityLevel;
|
|
31138
31222
|
}
|
|
31139
31223
|
};
|
|
31140
|
-
exports.unstable_scheduleCallback = function (
|
|
31224
|
+
exports$1.unstable_scheduleCallback = function (
|
|
31141
31225
|
priorityLevel,
|
|
31142
31226
|
callback,
|
|
31143
31227
|
options
|
|
31144
31228
|
) {
|
|
31145
|
-
var currentTime = exports.unstable_now();
|
|
31229
|
+
var currentTime = exports$1.unstable_now();
|
|
31146
31230
|
"object" === typeof options && null !== options
|
|
31147
31231
|
? ((options = options.delay),
|
|
31148
31232
|
(options =
|
|
@@ -31194,8 +31278,8 @@ function requireScheduler_development () {
|
|
|
31194
31278
|
schedulePerformWorkUntilDeadline())));
|
|
31195
31279
|
return priorityLevel;
|
|
31196
31280
|
};
|
|
31197
|
-
exports.unstable_shouldYield = shouldYieldToHost;
|
|
31198
|
-
exports.unstable_wrapCallback = function (callback) {
|
|
31281
|
+
exports$1.unstable_shouldYield = shouldYieldToHost;
|
|
31282
|
+
exports$1.unstable_wrapCallback = function (callback) {
|
|
31199
31283
|
var parentPriorityLevel = currentPriorityLevel;
|
|
31200
31284
|
return function () {
|
|
31201
31285
|
var previousPriorityLevel = currentPriorityLevel;
|
|
@@ -32450,7 +32534,7 @@ function extractFormula(value) {
|
|
|
32450
32534
|
return value.slice(1);
|
|
32451
32535
|
}
|
|
32452
32536
|
function createFormulaParser(data, config) {
|
|
32453
|
-
return new FormulaParser
|
|
32537
|
+
return new FormulaParser(__assign(__assign({}, config), { onCell: function (ref) {
|
|
32454
32538
|
var point = {
|
|
32455
32539
|
row: ref.row - 1,
|
|
32456
32540
|
column: ref.col - 1,
|
|
@@ -35456,8 +35540,8 @@ return CRC32;
|
|
|
35456
35540
|
})();
|
|
35457
35541
|
/* [MS-CFB] v20171201 */
|
|
35458
35542
|
var CFB = /*#__PURE__*/(function _CFB(){
|
|
35459
|
-
var exports = {};
|
|
35460
|
-
exports.version = '1.2.1';
|
|
35543
|
+
var exports$1 = {};
|
|
35544
|
+
exports$1.version = '1.2.1';
|
|
35461
35545
|
/* [MS-CFB] 2.6.4 */
|
|
35462
35546
|
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
|
|
35463
35547
|
var L = l.split("/"), R = r.split("/");
|
|
@@ -37129,12 +37213,12 @@ function cfb_mov(cfb/*:CFBContainer*/, old_name/*:string*/, new_name/*:string*/)
|
|
|
37129
37213
|
|
|
37130
37214
|
function cfb_gc(cfb/*:CFBContainer*/)/*:void*/ { rebuild_cfb(cfb, true); }
|
|
37131
37215
|
|
|
37132
|
-
exports.find = find;
|
|
37133
|
-
exports.read = read;
|
|
37134
|
-
exports.parse = parse;
|
|
37135
|
-
exports.write = write;
|
|
37136
|
-
exports.writeFile = write_file;
|
|
37137
|
-
exports.utils = {
|
|
37216
|
+
exports$1.find = find;
|
|
37217
|
+
exports$1.read = read;
|
|
37218
|
+
exports$1.parse = parse;
|
|
37219
|
+
exports$1.write = write;
|
|
37220
|
+
exports$1.writeFile = write_file;
|
|
37221
|
+
exports$1.utils = {
|
|
37138
37222
|
cfb_new: cfb_new,
|
|
37139
37223
|
cfb_add: cfb_add,
|
|
37140
37224
|
cfb_del: cfb_del,
|
|
@@ -37150,7 +37234,7 @@ exports.utils = {
|
|
|
37150
37234
|
consts: consts
|
|
37151
37235
|
};
|
|
37152
37236
|
|
|
37153
|
-
return exports;
|
|
37237
|
+
return exports$1;
|
|
37154
37238
|
})();
|
|
37155
37239
|
|
|
37156
37240
|
/* normalize data for blob ctor */
|
|
@@ -58613,6 +58697,137 @@ function CurrencyDisplay({ amount, currency = 'USD', locale = 'en-US', className
|
|
|
58613
58697
|
return (jsx("span", { className: combinedClasses, title: `${currency} ${safeAmount.toFixed(precision)}`, children: displayValue }));
|
|
58614
58698
|
}
|
|
58615
58699
|
|
|
58700
|
+
/**
|
|
58701
|
+
* CurrencyInput - Specialized input for monetary values
|
|
58702
|
+
*
|
|
58703
|
+
* Automatically formats currency values with proper symbols and thousands separators.
|
|
58704
|
+
* Handles parsing and validation of numeric currency input.
|
|
58705
|
+
*
|
|
58706
|
+
* @example Basic usage
|
|
58707
|
+
* ```tsx
|
|
58708
|
+
* <CurrencyInput
|
|
58709
|
+
* label="Price"
|
|
58710
|
+
* value={price}
|
|
58711
|
+
* onChange={setPrice}
|
|
58712
|
+
* currency="USD"
|
|
58713
|
+
* />
|
|
58714
|
+
* ```
|
|
58715
|
+
*
|
|
58716
|
+
* @example With validation
|
|
58717
|
+
* ```tsx
|
|
58718
|
+
* <CurrencyInput
|
|
58719
|
+
* label="Budget"
|
|
58720
|
+
* value={budget}
|
|
58721
|
+
* onChange={setBudget}
|
|
58722
|
+
* min={0}
|
|
58723
|
+
* max={10000}
|
|
58724
|
+
* validationState={budget > 10000 ? 'error' : null}
|
|
58725
|
+
* validationMessage={budget > 10000 ? 'Exceeds maximum budget' : ''}
|
|
58726
|
+
* />
|
|
58727
|
+
* ```
|
|
58728
|
+
*/
|
|
58729
|
+
const CurrencyInput = forwardRef(({ value, onChange, currency = 'USD', locale = 'en-US', precision = 2, allowNegative = false, min, max, onBlur, onFocus, ...props }, ref) => {
|
|
58730
|
+
const [displayValue, setDisplayValue] = useState('');
|
|
58731
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
58732
|
+
// Get currency symbol
|
|
58733
|
+
const getCurrencySymbol = () => {
|
|
58734
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
58735
|
+
style: 'currency',
|
|
58736
|
+
currency,
|
|
58737
|
+
});
|
|
58738
|
+
const parts = formatter.formatToParts(0);
|
|
58739
|
+
const symbolPart = parts.find(part => part.type === 'currency');
|
|
58740
|
+
return symbolPart?.value || '$';
|
|
58741
|
+
};
|
|
58742
|
+
const currencySymbol = getCurrencySymbol();
|
|
58743
|
+
// Format number as currency
|
|
58744
|
+
const formatCurrency = (num) => {
|
|
58745
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
58746
|
+
minimumFractionDigits: isFocused ? 0 : precision,
|
|
58747
|
+
maximumFractionDigits: precision,
|
|
58748
|
+
});
|
|
58749
|
+
return formatter.format(num);
|
|
58750
|
+
};
|
|
58751
|
+
// Parse display value to number
|
|
58752
|
+
const parseValue = (str) => {
|
|
58753
|
+
if (!str || str === '')
|
|
58754
|
+
return null;
|
|
58755
|
+
// Remove all non-numeric characters except decimal point and minus sign
|
|
58756
|
+
let cleaned = str.replace(/[^\d.-]/g, '');
|
|
58757
|
+
// Handle multiple decimal points
|
|
58758
|
+
const parts = cleaned.split('.');
|
|
58759
|
+
if (parts.length > 2) {
|
|
58760
|
+
cleaned = parts[0] + '.' + parts.slice(1).join('');
|
|
58761
|
+
}
|
|
58762
|
+
// Handle multiple minus signs (keep only first)
|
|
58763
|
+
const minusCount = (cleaned.match(/-/g) || []).length;
|
|
58764
|
+
if (minusCount > 1) {
|
|
58765
|
+
const hasLeadingMinus = cleaned.startsWith('-');
|
|
58766
|
+
cleaned = cleaned.replace(/-/g, '');
|
|
58767
|
+
if (hasLeadingMinus)
|
|
58768
|
+
cleaned = '-' + cleaned;
|
|
58769
|
+
}
|
|
58770
|
+
// Parse to float
|
|
58771
|
+
const num = parseFloat(cleaned);
|
|
58772
|
+
if (isNaN(num))
|
|
58773
|
+
return null;
|
|
58774
|
+
// Apply precision
|
|
58775
|
+
return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
|
|
58776
|
+
};
|
|
58777
|
+
// Update display value when external value changes
|
|
58778
|
+
useEffect(() => {
|
|
58779
|
+
if (value === undefined || value === null || value === '') {
|
|
58780
|
+
setDisplayValue('');
|
|
58781
|
+
}
|
|
58782
|
+
else {
|
|
58783
|
+
const numValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
58784
|
+
if (!isNaN(numValue)) {
|
|
58785
|
+
setDisplayValue(formatCurrency(numValue));
|
|
58786
|
+
}
|
|
58787
|
+
}
|
|
58788
|
+
}, [value, isFocused]);
|
|
58789
|
+
const handleChange = (e) => {
|
|
58790
|
+
const inputValue = e.target.value;
|
|
58791
|
+
setDisplayValue(inputValue);
|
|
58792
|
+
const numValue = parseValue(inputValue);
|
|
58793
|
+
// Validate constraints
|
|
58794
|
+
if (numValue !== null) {
|
|
58795
|
+
if (!allowNegative && numValue < 0)
|
|
58796
|
+
return;
|
|
58797
|
+
if (min !== undefined && numValue < min)
|
|
58798
|
+
return;
|
|
58799
|
+
if (max !== undefined && numValue > max)
|
|
58800
|
+
return;
|
|
58801
|
+
}
|
|
58802
|
+
onChange?.(numValue);
|
|
58803
|
+
};
|
|
58804
|
+
const handleFocus = (e) => {
|
|
58805
|
+
setIsFocused(true);
|
|
58806
|
+
// Remove formatting when focused for easier editing
|
|
58807
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
58808
|
+
const numValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
58809
|
+
if (!isNaN(numValue)) {
|
|
58810
|
+
setDisplayValue(numValue.toString());
|
|
58811
|
+
}
|
|
58812
|
+
}
|
|
58813
|
+
onFocus?.(e);
|
|
58814
|
+
};
|
|
58815
|
+
const handleBlur = (e) => {
|
|
58816
|
+
setIsFocused(false);
|
|
58817
|
+
// Reformat on blur
|
|
58818
|
+
const numValue = parseValue(displayValue);
|
|
58819
|
+
if (numValue !== null) {
|
|
58820
|
+
setDisplayValue(formatCurrency(numValue));
|
|
58821
|
+
}
|
|
58822
|
+
else if (displayValue === '') {
|
|
58823
|
+
setDisplayValue('');
|
|
58824
|
+
}
|
|
58825
|
+
onBlur?.(e);
|
|
58826
|
+
};
|
|
58827
|
+
return (jsx(Input, { ref: ref, type: "text", value: displayValue, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, prefix: currencySymbol, ...props }));
|
|
58828
|
+
});
|
|
58829
|
+
CurrencyInput.displayName = 'CurrencyInput';
|
|
58830
|
+
|
|
58616
58831
|
const formatOptions = {
|
|
58617
58832
|
short: {
|
|
58618
58833
|
year: 'numeric',
|
|
@@ -59523,8 +59738,19 @@ const AppLayout = ({ children, toolbarSections = [], className = '', showToolbar
|
|
|
59523
59738
|
* </Layout>
|
|
59524
59739
|
* ```
|
|
59525
59740
|
*/
|
|
59526
|
-
function PageLayout({ title, description, children, className = '', headerContent }) {
|
|
59527
|
-
|
|
59741
|
+
function PageLayout({ title, description, children, className = '', headerContent, maxWidth = '7xl', fixed = false }) {
|
|
59742
|
+
// Responsive padding classes - fixed left/top, responsive right/bottom
|
|
59743
|
+
const paddingClasses = fixed
|
|
59744
|
+
? 'p-6 pb-20'
|
|
59745
|
+
: 'pt-6 pl-6 pr-2 pb-8 sm:pr-4 md:pr-6 sm:pb-12 md:pb-16 lg:pb-20';
|
|
59746
|
+
const maxWidthClasses = {
|
|
59747
|
+
'4xl': 'max-w-4xl',
|
|
59748
|
+
'5xl': 'max-w-5xl',
|
|
59749
|
+
'6xl': 'max-w-6xl',
|
|
59750
|
+
'7xl': 'max-w-7xl',
|
|
59751
|
+
'full': 'max-w-full',
|
|
59752
|
+
};
|
|
59753
|
+
return (jsxs(Page, { padding: "none", maxWidth: maxWidth, fixed: fixed, children: [headerContent, jsxs("div", { className: `${paddingClasses} ${maxWidthClasses[maxWidth]} mx-auto ${className}`, children: [jsxs("div", { className: "mb-8", children: [jsx("h1", { className: "text-3xl font-bold text-ink-900 mb-2", children: title }), description && (jsx("p", { className: "text-ink-600", children: description }))] }), children] })] }));
|
|
59528
59754
|
}
|
|
59529
59755
|
|
|
59530
59756
|
const sizeClasses = {
|
|
@@ -59896,6 +60122,113 @@ function loadColumnOrder(tableId) {
|
|
|
59896
60122
|
}
|
|
59897
60123
|
}
|
|
59898
60124
|
|
|
60125
|
+
/**
|
|
60126
|
+
* Export data to Excel file
|
|
60127
|
+
*
|
|
60128
|
+
* A standalone utility for exporting any data array to Excel format.
|
|
60129
|
+
* Works independently of the Spreadsheet component.
|
|
60130
|
+
*
|
|
60131
|
+
* **Features:**
|
|
60132
|
+
* - Export arrays of objects to Excel
|
|
60133
|
+
* - Custom column headers and ordering
|
|
60134
|
+
* - Value formatting with custom functions
|
|
60135
|
+
* - Multi-sheet support
|
|
60136
|
+
* - Automatic type handling
|
|
60137
|
+
*
|
|
60138
|
+
* @example
|
|
60139
|
+
* ```typescript
|
|
60140
|
+
* // Simple export - uses object keys as headers
|
|
60141
|
+
* const data = [
|
|
60142
|
+
* { id: 1, name: 'Product A', price: 29.99 },
|
|
60143
|
+
* { id: 2, name: 'Product B', price: 49.99 },
|
|
60144
|
+
* ];
|
|
60145
|
+
* exportToExcel({ data, filename: 'products.xlsx' });
|
|
60146
|
+
*
|
|
60147
|
+
* // Custom columns with formatting
|
|
60148
|
+
* exportToExcel({
|
|
60149
|
+
* data: users,
|
|
60150
|
+
* filename: 'users.xlsx',
|
|
60151
|
+
* columns: [
|
|
60152
|
+
* { key: 'id', label: 'ID' },
|
|
60153
|
+
* { key: 'name', label: 'Full Name' },
|
|
60154
|
+
* { key: 'email', label: 'Email Address' },
|
|
60155
|
+
* { key: 'createdAt', label: 'Joined', format: (date) => new Date(date).toLocaleDateString() },
|
|
60156
|
+
* { key: 'isActive', label: 'Status', format: (active) => active ? 'Active' : 'Inactive' },
|
|
60157
|
+
* ],
|
|
60158
|
+
* });
|
|
60159
|
+
*
|
|
60160
|
+
* // Multi-sheet export
|
|
60161
|
+
* const wb = utils.book_new();
|
|
60162
|
+
* exportToExcel({ data: products, sheetName: 'Products', workbook: wb });
|
|
60163
|
+
* exportToExcel({ data: orders, sheetName: 'Orders', workbook: wb });
|
|
60164
|
+
* writeFile(wb, 'multi-sheet.xlsx');
|
|
60165
|
+
* ```
|
|
60166
|
+
*
|
|
60167
|
+
* @param options - Export configuration options
|
|
60168
|
+
* @returns WorkBook if workbook option provided, otherwise void (auto-downloads)
|
|
60169
|
+
*/
|
|
60170
|
+
function exportToExcel({ data, filename = 'export.xlsx', sheetName = 'Sheet1', columns, includeHeaders = true, workbook, }) {
|
|
60171
|
+
if (!data || data.length === 0) {
|
|
60172
|
+
throw new Error('No data provided for export');
|
|
60173
|
+
}
|
|
60174
|
+
let worksheetData;
|
|
60175
|
+
if (columns) {
|
|
60176
|
+
// Use custom columns with specific ordering and formatting
|
|
60177
|
+
const headers = columns.map((col) => col.label);
|
|
60178
|
+
const rows = data.map((row) => columns.map((col) => {
|
|
60179
|
+
const value = row[col.key];
|
|
60180
|
+
return col.format ? col.format(value) : value ?? '';
|
|
60181
|
+
}));
|
|
60182
|
+
worksheetData = includeHeaders ? [headers, ...rows] : rows;
|
|
60183
|
+
}
|
|
60184
|
+
else {
|
|
60185
|
+
// Auto-generate from object keys
|
|
60186
|
+
if (includeHeaders) {
|
|
60187
|
+
const headers = Object.keys(data[0]);
|
|
60188
|
+
const rows = data.map((row) => headers.map((key) => row[key] ?? ''));
|
|
60189
|
+
worksheetData = [headers, ...rows];
|
|
60190
|
+
}
|
|
60191
|
+
else {
|
|
60192
|
+
const headers = Object.keys(data[0]);
|
|
60193
|
+
worksheetData = data.map((row) => headers.map((key) => row[key] ?? ''));
|
|
60194
|
+
}
|
|
60195
|
+
}
|
|
60196
|
+
const worksheet = utils.aoa_to_sheet(worksheetData);
|
|
60197
|
+
// If workbook provided, add sheet and return (for multi-sheet exports)
|
|
60198
|
+
if (workbook) {
|
|
60199
|
+
utils.book_append_sheet(workbook, worksheet, sheetName);
|
|
60200
|
+
return workbook;
|
|
60201
|
+
}
|
|
60202
|
+
// Otherwise, create workbook and download
|
|
60203
|
+
const newWorkbook = utils.book_new();
|
|
60204
|
+
utils.book_append_sheet(newWorkbook, worksheet, sheetName);
|
|
60205
|
+
writeFileSync(newWorkbook, filename);
|
|
60206
|
+
}
|
|
60207
|
+
function exportDataTableToExcel({ data, columns, filename = 'export.xlsx', sheetName = 'Sheet1', }) {
|
|
60208
|
+
const excelColumns = columns.map((col) => ({
|
|
60209
|
+
key: col.key,
|
|
60210
|
+
label: col.header,
|
|
60211
|
+
}));
|
|
60212
|
+
exportToExcel({
|
|
60213
|
+
data,
|
|
60214
|
+
columns: excelColumns,
|
|
60215
|
+
filename,
|
|
60216
|
+
sheetName,
|
|
60217
|
+
});
|
|
60218
|
+
}
|
|
60219
|
+
function createMultiSheetExcel({ filename, sheets }) {
|
|
60220
|
+
const workbook = utils.book_new();
|
|
60221
|
+
sheets.forEach((sheet) => {
|
|
60222
|
+
exportToExcel({
|
|
60223
|
+
data: sheet.data,
|
|
60224
|
+
sheetName: sheet.name,
|
|
60225
|
+
columns: sheet.columns,
|
|
60226
|
+
workbook,
|
|
60227
|
+
});
|
|
60228
|
+
});
|
|
60229
|
+
writeFileSync(workbook, filename);
|
|
60230
|
+
}
|
|
60231
|
+
|
|
59899
60232
|
function useColumnResize(options = {}) {
|
|
59900
60233
|
const { tableId, persist = false } = options;
|
|
59901
60234
|
const [columnWidths, setColumnWidths] = useState({});
|
|
@@ -60012,5 +60345,5 @@ function useColumnReorder(initialColumns, options = {}) {
|
|
|
60012
60345
|
};
|
|
60013
60346
|
}
|
|
60014
60347
|
|
|
60015
|
-
export { Accordion, ActionButton, AdminModal, Alert, AlertDialog, AppLayout, Autocomplete, Avatar, Badge, BottomSheet, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, Checkbox, Chip, Collapsible, ColorPicker, Combobox, ComingSoon, CommandPalette, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, Dashboard, DashboardContent, DashboardHeader, DataTable, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, ErrorBoundary, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, Form, FormContext, FormControl, FormWizard, Grid, GridItem, Hide, HoverCard, InfiniteScroll, Input, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, Menu, MenuDivider, Modal, ModalFooter, MultiSelect, NotificationBar, NotificationIndicator, NumberInput, Page, PageLayout, PageNavigation, Pagination, PasswordInput, Popover, Progress, QueryTransparency, RadioGroup, Rating, RichTextEditor, SearchBar, Select, Separator, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard, SkeletonTable, Slider, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, Switch,
|
|
60348
|
+
export { Accordion, ActionButton, AdminModal, Alert, AlertDialog, AppLayout, Autocomplete, Avatar, Badge, BottomSheet, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, Checkbox, Chip, Collapsible, ColorPicker, Combobox, ComingSoon, CommandPalette, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataTable, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, ErrorBoundary, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, Form, FormContext, FormControl, FormWizard, Grid, GridItem, Hide, HoverCard, InfiniteScroll, Input, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, Menu, MenuDivider, Modal, ModalFooter, MultiSelect, NotificationBar, NotificationIndicator, NumberInput, Page, PageLayout, PageNavigation, Pagination, PasswordInput, Popover, Progress, QueryTransparency, RadioGroup, Rating, RichTextEditor, SearchBar, Select, Separator, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard, SkeletonTable, Slider, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, Switch, Tabs, Text, Textarea, ThemeToggle, TimePicker, Timeline, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, statusManager, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useFormContext, useMediaQuery };
|
|
60016
60349
|
//# sourceMappingURL=index.esm.js.map
|