indas-ui 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/datagrid/DataGrid.js +2 -2
- package/dist/cjs/components/datagrid/cells/CellRenderer.js +4 -4
- package/dist/cjs/components/datagrid/cells/SelectionCell.js +10 -10
- package/dist/cjs/components/datagrid/controls/PaginationControls.js +3 -3
- package/dist/cjs/components/datagrid/controls/menu/view/CardView.js +6 -6
- package/dist/cjs/components/datagrid/rows/DraggableRow.js +6 -6
- package/dist/cjs/components/datagrid/search/InlineSearchCell.js +4 -4
- package/dist/cjs/components/draft/AutoSaveIndicator.js +9 -9
- package/dist/cjs/components/draft/DraftModal.js +6 -6
- package/dist/cjs/components/forms/date-picker/DatePicker.js +7 -13
- package/dist/cjs/components/forms/date-picker/DateTimePicker.js +2 -2
- package/dist/cjs/styles/index.css +5 -5
- package/dist/components/datagrid/DataGrid.js +2 -2
- package/dist/components/datagrid/cells/CellRenderer.js +4 -4
- package/dist/components/datagrid/cells/SelectionCell.js +10 -10
- package/dist/components/datagrid/controls/PaginationControls.js +3 -3
- package/dist/components/datagrid/controls/menu/view/CardView.js +6 -6
- package/dist/components/datagrid/rows/DraggableRow.js +6 -6
- package/dist/components/datagrid/search/InlineSearchCell.js +4 -4
- package/dist/components/draft/AutoSaveIndicator.js +9 -9
- package/dist/components/draft/DraftModal.js +6 -6
- package/dist/components/forms/date-picker/DatePicker.js +7 -13
- package/dist/components/forms/date-picker/DateTimePicker.js +2 -2
- package/dist/styles/index.css +5 -5
- package/package.json +1 -1
|
@@ -525,7 +525,7 @@ enableFilterRow = false, initialColumnFilters, }) {
|
|
|
525
525
|
}
|
|
526
526
|
return rowSelection;
|
|
527
527
|
}, [enableViewToggle, viewMode, selectedRowIds, filteredData, rowSelection, getRowId, data]);
|
|
528
|
-
// Helper function to format dates as "12 Oct
|
|
528
|
+
// Helper function to format dates as "12 Oct 2025"
|
|
529
529
|
const formatDateCell = (dateString) => {
|
|
530
530
|
if (!dateString)
|
|
531
531
|
return '-';
|
|
@@ -536,7 +536,7 @@ enableFilterRow = false, initialColumnFilters, }) {
|
|
|
536
536
|
const day = date.getDate();
|
|
537
537
|
const month = date.toLocaleDateString('en-US', { month: 'short' });
|
|
538
538
|
const year = date.getFullYear();
|
|
539
|
-
return `${day} ${month}
|
|
539
|
+
return `${day} ${month} ${year}`;
|
|
540
540
|
}
|
|
541
541
|
catch {
|
|
542
542
|
return dateString;
|
|
@@ -94,10 +94,10 @@ function CellRenderer({ cell, cellIndex, row, enableBacchaSearch = false, mainCo
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
const rowId = row.original.id || row.id;
|
|
97
|
-
return ((0, jsx_runtime_1.jsx)("td", { className: `
|
|
98
|
-
px-1 py-1 text-xs text-fg-default align-middle
|
|
99
|
-
${isBadgeColumn || isPlaceholderValue ? 'text-center' : isNumericContent ? 'text-right' : 'text-left'}
|
|
100
|
-
${isCellFrozen || isPinnedRight ? 'sticky z-[5]' : ''}
|
|
97
|
+
return ((0, jsx_runtime_1.jsx)("td", { className: `
|
|
98
|
+
px-1 py-1 text-xs text-fg-default align-middle
|
|
99
|
+
${isBadgeColumn || isPlaceholderValue ? 'text-center' : isNumericContent ? 'text-right' : 'text-left'}
|
|
100
|
+
${isCellFrozen || isPinnedRight ? 'sticky z-[5]' : ''}
|
|
101
101
|
`, style: {
|
|
102
102
|
width: `${cell.column.getSize()}px`,
|
|
103
103
|
minWidth: `${cell.column.getSize()}px`,
|
|
@@ -15,13 +15,13 @@ function SelectionCell({ checked, indeterminate = false, onChange, disabled = fa
|
|
|
15
15
|
};
|
|
16
16
|
// Radio button mode (single selection) - always circular regardless of circularCheckboxes prop
|
|
17
17
|
if (mode === 'radio') {
|
|
18
|
-
return ((0, jsx_runtime_1.jsx)("div", { onClick: handleClick, className: `
|
|
19
|
-
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
20
|
-
flex items-center justify-center flex-shrink-0
|
|
21
|
-
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
18
|
+
return ((0, jsx_runtime_1.jsx)("div", { onClick: handleClick, className: `
|
|
19
|
+
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
20
|
+
flex items-center justify-center flex-shrink-0
|
|
21
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
22
22
|
${checked
|
|
23
23
|
? 'border-primary bg-white'
|
|
24
|
-
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
24
|
+
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
25
25
|
`, style: {
|
|
26
26
|
boxShadow: checked ? '0 0 0 2px rgba(59, 130, 246, 0.1)' : 'none',
|
|
27
27
|
width: '14px',
|
|
@@ -43,13 +43,13 @@ function SelectionCell({ checked, indeterminate = false, onChange, disabled = fa
|
|
|
43
43
|
: "border-[rgb(var(--bd-default))] bg-[rgb(var(--bg-surface))] hover:border-[rgb(var(--color-primary))]", disabled && "opacity-50 cursor-not-allowed"), children: [checked && !indeterminate && ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "w-3 h-3 text-white", strokeWidth: 3 })), indeterminate && ((0, jsx_runtime_1.jsx)("div", { className: "w-2 h-0.5 bg-white rounded" }))] })] }));
|
|
44
44
|
}
|
|
45
45
|
// Circular checkbox (AG Grid style, multi-select with circular prop)
|
|
46
|
-
return ((0, jsx_runtime_1.jsxs)("div", { onClick: handleClick, className: `
|
|
47
|
-
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
48
|
-
flex items-center justify-center flex-shrink-0
|
|
49
|
-
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
46
|
+
return ((0, jsx_runtime_1.jsxs)("div", { onClick: handleClick, className: `
|
|
47
|
+
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
48
|
+
flex items-center justify-center flex-shrink-0
|
|
49
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
50
50
|
${checked || indeterminate
|
|
51
51
|
? 'border-primary bg-primary'
|
|
52
|
-
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
52
|
+
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
53
53
|
`, style: {
|
|
54
54
|
boxShadow: checked || indeterminate ? '0 0 0 2px rgba(59, 130, 246, 0.1)' : 'none',
|
|
55
55
|
width: '14px',
|
|
@@ -25,11 +25,11 @@ function PaginationControls({ pageIndex, pageSize, totalRows, pageSizeOptions =
|
|
|
25
25
|
return ((0, jsx_runtime_1.jsx)("span", { className: "px-2 text-[rgb(var(--fg-muted))]", children: "..." }, `ellipsis-${index}`));
|
|
26
26
|
}
|
|
27
27
|
const isCurrentPage = page === pageIndex;
|
|
28
|
-
return ((0, jsx_runtime_1.jsx)("button", { onClick: () => onPageChange(page), className: `
|
|
29
|
-
min-w-[32px] h-8 px-2 rounded text-sm font-medium transition-colors
|
|
28
|
+
return ((0, jsx_runtime_1.jsx)("button", { onClick: () => onPageChange(page), className: `
|
|
29
|
+
min-w-[32px] h-8 px-2 rounded text-sm font-medium transition-colors
|
|
30
30
|
${isCurrentPage
|
|
31
31
|
? 'border border-[rgb(var(--color-primary))] text-[rgb(var(--color-primary))] bg-[rgb(var(--color-primary)/0.08)]'
|
|
32
|
-
: 'text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bd-default))]'}
|
|
32
|
+
: 'text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bd-default))]'}
|
|
33
33
|
`, children: page + 1 }, page));
|
|
34
34
|
}) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => onPageChange(pageIndex + 1), disabled: !hasNextPage, className: "p-1.5 rounded hover:bg-[rgb(var(--bd-default))] disabled:opacity-40 disabled:cursor-not-allowed transition-colors", "aria-label": "Next Page", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4 text-[rgb(var(--fg-muted))]" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => onPageChange(totalPages - 1), disabled: !hasNextPage, className: "p-1.5 rounded hover:bg-[rgb(var(--bd-default))] disabled:opacity-40 disabled:cursor-not-allowed transition-colors", "aria-label": "Last Page", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsRight, { className: "h-4 w-4 text-[rgb(var(--fg-muted))]" }) })] }), !isMobile && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-sm text-[rgb(var(--fg-default))] flex-shrink-0 order-2 sm:order-3", children: [(0, jsx_runtime_1.jsx)("span", { className: "hidden sm:inline", children: "Show:" }), (0, jsx_runtime_1.jsx)(components_1.Dropdown, { value: String(pageSize), onValueChange: (value) => onPageSizeChange(Number(value)), options: pageSizeOptions.map((size) => ({
|
|
35
35
|
value: String(size),
|
|
@@ -154,14 +154,14 @@ function CardView({ data, columns, onRowClick, selectedRows, onRowSelect, isLoad
|
|
|
154
154
|
return ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: "outline-none", tabIndex: 0, onKeyDown: handleKeyDown, children: [(0, jsx_runtime_1.jsx)("div", { className: cfg.pad, children: (0, jsx_runtime_1.jsx)("div", { className: `grid ${cfg.grid} ${cfg.gap}`, children: (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { initial: false, children: data.map((item, index) => {
|
|
155
155
|
const isFocused = focusedIndex === index;
|
|
156
156
|
const itemSelected = isSelected(item);
|
|
157
|
-
return ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { ref: (el) => { cardRefs.current[index] = el; }, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.12, delay: Math.min(index * 0.015, 0.15) }, className: "group/card outline-none", tabIndex: -1, onClick: () => setFocusedIndex(index), onDoubleClick: () => handleCardClick(item), children: (0, jsx_runtime_1.jsxs)("div", { className: `
|
|
158
|
-
relative rounded-lg border bg-[rgb(var(--bg-surface))] overflow-hidden h-full
|
|
159
|
-
transition-all duration-150
|
|
157
|
+
return ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { ref: (el) => { cardRefs.current[index] = el; }, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.12, delay: Math.min(index * 0.015, 0.15) }, className: "group/card outline-none", tabIndex: -1, onClick: () => setFocusedIndex(index), onDoubleClick: () => handleCardClick(item), children: (0, jsx_runtime_1.jsxs)("div", { className: `
|
|
158
|
+
relative rounded-lg border bg-[rgb(var(--bg-surface))] overflow-hidden h-full
|
|
159
|
+
transition-all duration-150
|
|
160
160
|
${itemSelected
|
|
161
161
|
? 'border-[rgb(var(--color-primary))] shadow-sm'
|
|
162
|
-
: 'border-[rgb(var(--bd-default))] hover:border-[rgb(var(--color-primary))]/40 hover:shadow-sm'}
|
|
163
|
-
${isFocused ? 'ring-2 ring-[rgb(var(--color-primary))]/30 ring-offset-1' : ''}
|
|
164
|
-
${getCardClassName?.(item) ?? ''}
|
|
162
|
+
: 'border-[rgb(var(--bd-default))] hover:border-[rgb(var(--color-primary))]/40 hover:shadow-sm'}
|
|
163
|
+
${isFocused ? 'ring-2 ring-[rgb(var(--color-primary))]/30 ring-offset-1' : ''}
|
|
164
|
+
${getCardClassName?.(item) ?? ''}
|
|
165
165
|
`, children: [(0, jsx_runtime_1.jsx)("div", { className: `absolute left-0 top-0 bottom-0 w-[2px] transition-colors duration-150 ${itemSelected ? 'bg-[rgb(var(--color-primary))]' : 'bg-transparent group-hover/card:bg-[rgb(var(--color-primary))]/30'}` }), (0, jsx_runtime_1.jsxs)("div", { className: "pl-3 pr-2.5 py-2.5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [onRowSelect && ((0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0", onClick: (e) => e.stopPropagation(), children: (0, jsx_runtime_1.jsx)(SelectionCell_1.SelectionCheckbox, { checked: itemSelected, onChange: (checked) => handleCheckboxChange(item, checked), circular: circularCheckboxes, mode: "checkbox" }) })), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0 flex items-baseline gap-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: `${cfg.titleText} font-semibold text-[rgb(var(--fg-default))] truncate leading-tight`, children: displayColumns.length > 0 && getDisplayValue(item, displayColumns[0].accessorKey) }), displayColumns.length > 1 && ((0, jsx_runtime_1.jsx)("p", { className: `${cfg.subtitleText} text-[rgb(var(--color-primary))] font-medium truncate flex-shrink-0`, children: getDisplayValue(item, displayColumns[1].accessorKey) }))] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0 opacity-0 group-hover/card:opacity-100 transition-opacity duration-150", onClick: (e) => e.stopPropagation(), children: actionsColumn && actionsColumn.cell?.({
|
|
166
166
|
row: { original: item },
|
|
167
167
|
getValue: () => null,
|
|
@@ -20,15 +20,15 @@ navigationState = {}, columnSearches = {}, isColumnSearchActive = {}, onColumnSe
|
|
|
20
20
|
transition,
|
|
21
21
|
opacity: isDragging ? 0.5 : 1,
|
|
22
22
|
};
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)("tr", { ref: setNodeRef, style: style, className: `
|
|
24
|
-
cursor-pointer group
|
|
25
|
-
transition-colors duration-150 ease-out
|
|
26
|
-
${isDragging ? 'shadow-lg z-50' : ''}
|
|
23
|
+
return ((0, jsx_runtime_1.jsxs)("tr", { ref: setNodeRef, style: style, className: `
|
|
24
|
+
cursor-pointer group
|
|
25
|
+
transition-colors duration-150 ease-out
|
|
26
|
+
${isDragging ? 'shadow-lg z-50' : ''}
|
|
27
27
|
${isHighlighted
|
|
28
28
|
? 'border-2 border-[rgb(var(--color-primary))] bg-gradient-to-r from-[rgb(var(--color-primary))]/10 to-[rgb(var(--color-primary))]/20 shadow-lg relative'
|
|
29
29
|
: isSelected
|
|
30
30
|
? 'bg-[color-mix(in_srgb,rgb(var(--color-primary))_8%,rgb(var(--bg-surface)))] shadow-sm hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_15%,rgb(var(--bg-surface)))]'
|
|
31
|
-
: 'hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_5%,rgb(var(--bg-surface)))]'}
|
|
32
|
-
${className ?? ''}
|
|
31
|
+
: 'hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_5%,rgb(var(--bg-surface)))]'}
|
|
32
|
+
${className ?? ''}
|
|
33
33
|
`, onClick: onRowClick, onDoubleClick: onRowDoubleClick, onContextMenu: onRowContextMenu, children: [showDragHandle && ((0, jsx_runtime_1.jsx)("td", { className: "text-center align-middle cursor-grab active:cursor-grabbing", style: { width: '1.875rem', minWidth: '1.875rem', maxWidth: '1.875rem' }, ...attributes, ...listeners, children: (0, jsx_runtime_1.jsx)("div", { className: "w-full h-full flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.GripVertical, { className: "h-4 w-4 text-gray-400" }) }) })), row.getVisibleCells().map((cell, cellIndex) => ((0, jsx_runtime_1.jsx)(CellRenderer_1.CellRenderer, { cell: cell, cellIndex: cellIndex, row: row, enableBacchaSearch: enableBacchaSearch, mainColumnsArray: mainColumnsArray, frozenColumnsState: frozenColumnsState, navigationState: navigationState, columnSearches: columnSearches, isColumnSearchActive: isColumnSearchActive, onColumnSearch: onColumnSearch, onClearColumnSearch: onClearColumnSearch, SearchHighlighter: SearchHighlighter, InlineSearchCell: InlineSearchCell, isSelected: isSelected }, cell.id)))] }));
|
|
34
34
|
}
|
|
@@ -89,10 +89,10 @@ function InlineSearchCell({ value, columnId, rowId, onSearch, onClearSearch, isS
|
|
|
89
89
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: parts.map((part, index) => part.toLowerCase() === highlight.toLowerCase() ? ((0, jsx_runtime_1.jsx)("mark", { className: "bg-yellow-200 text-yellow-900 px-0.5 rounded", children: part }, index)) : ((0, jsx_runtime_1.jsx)("span", { children: part }, index))) }));
|
|
90
90
|
};
|
|
91
91
|
const displayValue = value?.toString() || '';
|
|
92
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: cellRef, tabIndex: 0, className: `bacchasearch relative group cursor-pointer outline-none inline-flex items-center w-full ${className}`, onClick: handleCellClick, children: [(0, jsx_runtime_1.jsx)("span", { className: `
|
|
93
|
-
text-xs flex-1 rounded transition-colors
|
|
94
|
-
${isSearchActive ? 'bg-[rgb(var(--color-primary)/0.1)]' : 'hover:bg-[rgb(var(--color-primary)/0.05)]'}
|
|
95
|
-
${isTyping ? 'ring-1 ring-[rgb(var(--color-primary)/0.3)] bg-[rgb(var(--color-primary)/0.15)]' : ''}
|
|
92
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: cellRef, tabIndex: 0, className: `bacchasearch relative group cursor-pointer outline-none inline-flex items-center w-full ${className}`, onClick: handleCellClick, children: [(0, jsx_runtime_1.jsx)("span", { className: `
|
|
93
|
+
text-xs flex-1 rounded transition-colors
|
|
94
|
+
${isSearchActive ? 'bg-[rgb(var(--color-primary)/0.1)]' : 'hover:bg-[rgb(var(--color-primary)/0.05)]'}
|
|
95
|
+
${isTyping ? 'ring-1 ring-[rgb(var(--color-primary)/0.3)] bg-[rgb(var(--color-primary)/0.15)]' : ''}
|
|
96
96
|
`, children: isSearchActive && searchTerm ?
|
|
97
97
|
renderHighlightedText(displayValue, searchTerm) :
|
|
98
98
|
displayValue }), (0, jsx_runtime_1.jsx)(lucide_react_1.Search, { className: `h-3 w-3 text-[rgb(var(--fg-muted))] ml-0.5 flex-shrink-0 transition-opacity ${isTyping ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}` }), (isTyping || isSearchActive) && ((0, jsx_runtime_1.jsx)("div", { className: "absolute -top-0.5 -right-0.5", children: (0, jsx_runtime_1.jsx)("div", { className: `h-1.5 w-1.5 rounded-full ${isTyping ? 'bg-[rgb(var(--color-success))]' : 'bg-[rgb(var(--color-primary))]'}` }) })), isTyping && localSearchTerm && ((0, jsx_runtime_1.jsxs)("div", { className: "absolute -bottom-5 left-0 bg-[rgb(var(--bg-surface))] text-[rgb(var(--fg-default))] text-xs px-1.5 py-0.5 rounded shadow-lg border border-[rgb(var(--bd-default))] z-10 whitespace-nowrap", children: ["\"", localSearchTerm, "\""] }))] }));
|
|
@@ -57,14 +57,14 @@ function AutoSaveIndicator({ enabled, lastSaved, isDirty, isSaving, onOpenDraftM
|
|
|
57
57
|
};
|
|
58
58
|
};
|
|
59
59
|
const status = getStatus();
|
|
60
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: "Auto-save:" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => onToggleAutoSave?.(!enabled), className: `
|
|
61
|
-
relative inline-flex h-5 w-9 items-center rounded-full transition-colors
|
|
62
|
-
${enabled ? 'bg-[rgb(var(--color-primary))]' : 'bg-[rgb(var(--bg-muted))]'}
|
|
63
|
-
`, title: enabled ? 'Disable auto-save' : 'Enable auto-save', children: (0, jsx_runtime_1.jsx)("span", { className: `
|
|
64
|
-
inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform
|
|
65
|
-
${enabled ? 'translate-x-5' : 'translate-x-1'}
|
|
66
|
-
` }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-[rgb(var(--fg-default))]", children: enabled ? 'ON' : 'OFF' })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 w-px bg-[rgb(var(--bd-default))]" }), (0, jsx_runtime_1.jsxs)("button", { onClick: onOpenDraftManager, className: `
|
|
67
|
-
flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors
|
|
68
|
-
${status.bg} ${status.color} hover:opacity-80
|
|
60
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: "Auto-save:" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => onToggleAutoSave?.(!enabled), className: `
|
|
61
|
+
relative inline-flex h-5 w-9 items-center rounded-full transition-colors
|
|
62
|
+
${enabled ? 'bg-[rgb(var(--color-primary))]' : 'bg-[rgb(var(--bg-muted))]'}
|
|
63
|
+
`, title: enabled ? 'Disable auto-save' : 'Enable auto-save', children: (0, jsx_runtime_1.jsx)("span", { className: `
|
|
64
|
+
inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform
|
|
65
|
+
${enabled ? 'translate-x-5' : 'translate-x-1'}
|
|
66
|
+
` }) }), (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium text-[rgb(var(--fg-default))]", children: enabled ? 'ON' : 'OFF' })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 w-px bg-[rgb(var(--bd-default))]" }), (0, jsx_runtime_1.jsxs)("button", { onClick: onOpenDraftManager, className: `
|
|
67
|
+
flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors
|
|
68
|
+
${status.bg} ${status.color} hover:opacity-80
|
|
69
69
|
`, title: "Click to manage drafts", children: [status.icon, (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-medium", children: status.text })] })] }));
|
|
70
70
|
}
|
|
@@ -192,10 +192,10 @@ function DraftModal({ open, onClose, drafts, onLoad, onDelete, isLoading = false
|
|
|
192
192
|
// Early return after all hooks to comply with Rules of Hooks
|
|
193
193
|
if (!open)
|
|
194
194
|
return null;
|
|
195
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-[rgb(var(--bg-surface))] rounded-lg shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col", children: [(0, jsx_runtime_1.jsxs)("div", { className: "px-6 py-3 border-b border-[rgb(var(--bd-default))] flex items-center gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 flex-shrink-0", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileText, { className: "w-5 h-5 text-[rgb(var(--color-primary))]" }), (0, jsx_runtime_1.jsx)("h2", { className: "text-base font-semibold text-[rgb(var(--fg-default))]", children: "Saved Drafts" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: ["(", drafts.length, ")"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[rgb(var(--fg-muted))]" }), (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Search...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "\n w-full pl-9 pr-3 py-1.5 rounded-lg text-sm\n bg-[rgb(var(--bg-default))]\n border border-[rgb(var(--bd-default))]\n text-[rgb(var(--fg-default))]\n placeholder:text-[rgb(var(--fg-muted))]\n focus:outline-none focus:ring-2 focus:ring-[rgb(var(--color-primary))]\n " })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0 w-36", children: (0, jsx_runtime_1.jsx)(dropdown_1.Dropdown, { options: SORT_OPTIONS, value: sortBy, onValueChange: (val) => setSortBy(val), size: "sm", autoWidth: true }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onClose, className: "p-1.5 rounded-lg hover:bg-[rgb(var(--bg-muted))] text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors flex-shrink-0", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-5 h-5" }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-16", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full border-4 border-[rgb(var(--color-primary)_/_0.2)] border-t-[rgb(var(--color-primary))] animate-spin mx-auto mb-3" }), (0, jsx_runtime_1.jsx)("p", { className: "text-[rgb(var(--fg-muted))]", children: "Loading drafts..." })] }) })) : filteredAndSortedDrafts.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileText, { className: "w-16 h-16 text-[rgb(var(--fg-muted))] mb-4 opacity-50" }), (0, jsx_runtime_1.jsx)("p", { className: "text-lg font-medium text-[rgb(var(--fg-default))] mb-1", children: searchQuery ? 'No matching drafts' : 'No drafts saved yet' }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: searchQuery ? 'Try a different search term' : 'Start by clicking "Save Draft" button' })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: paginatedDrafts.map((draft) => {
|
|
195
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-[rgb(var(--bg-surface))] rounded-lg shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col", children: [(0, jsx_runtime_1.jsxs)("div", { className: "px-6 py-3 border-b border-[rgb(var(--bd-default))] flex items-center gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 flex-shrink-0", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileText, { className: "w-5 h-5 text-[rgb(var(--color-primary))]" }), (0, jsx_runtime_1.jsx)("h2", { className: "text-base font-semibold text-[rgb(var(--fg-default))]", children: "Saved Drafts" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: ["(", drafts.length, ")"] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[rgb(var(--fg-muted))]" }), (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "Search...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "\r\n w-full pl-9 pr-3 py-1.5 rounded-lg text-sm\r\n bg-[rgb(var(--bg-default))]\r\n border border-[rgb(var(--bd-default))]\r\n text-[rgb(var(--fg-default))]\r\n placeholder:text-[rgb(var(--fg-muted))]\r\n focus:outline-none focus:ring-2 focus:ring-[rgb(var(--color-primary))]\r\n " })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0 w-36", children: (0, jsx_runtime_1.jsx)(dropdown_1.Dropdown, { options: SORT_OPTIONS, value: sortBy, onValueChange: (val) => setSortBy(val), size: "sm", autoWidth: true }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onClose, className: "p-1.5 rounded-lg hover:bg-[rgb(var(--bg-muted))] text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors flex-shrink-0", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-5 h-5" }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: isLoading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center py-16", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full border-4 border-[rgb(var(--color-primary)_/_0.2)] border-t-[rgb(var(--color-primary))] animate-spin mx-auto mb-3" }), (0, jsx_runtime_1.jsx)("p", { className: "text-[rgb(var(--fg-muted))]", children: "Loading drafts..." })] }) })) : filteredAndSortedDrafts.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileText, { className: "w-16 h-16 text-[rgb(var(--fg-muted))] mb-4 opacity-50" }), (0, jsx_runtime_1.jsx)("p", { className: "text-lg font-medium text-[rgb(var(--fg-default))] mb-1", children: searchQuery ? 'No matching drafts' : 'No drafts saved yet' }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: searchQuery ? 'Try a different search term' : 'Start by clicking "Save Draft" button' })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: paginatedDrafts.map((draft) => {
|
|
196
196
|
const progress = calculateProgress(draft);
|
|
197
197
|
const preview = draft.previewData || {};
|
|
198
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "\n group relative p-3 rounded-lg\n bg-[rgb(var(--bg-default))]\n border border-[rgb(var(--bd-default))]\n hover:border-[rgb(var(--color-primary))]\n hover:shadow-lg\n transition-all duration-200\n ", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-start gap-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("h3", { className: "font-semibold text-[rgb(var(--fg-default))] truncate text-base", children: draft.draftName || 'Untitled Draft' }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mt-1 text-xs text-[rgb(var(--fg-muted))]", children: [(0, jsx_runtime_1.jsx)("span", { children: formatRelativeTime(draft.lastSaved) }), (0, jsx_runtime_1.jsxs)("span", { className: "hidden group-hover:inline", children: ["\u2022 ", formatFullDate(draft.lastSaved)] }), draft.isAutoSave && ((0, jsx_runtime_1.jsx)("span", { className: "text-[10px] px-2 py-0.5 rounded-full bg-[rgb(var(--color-primary)_/_0.1)] text-[rgb(var(--color-primary))] font-medium", children: "AUTO-SAVE" }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => handleLoad(draft.draftId), className: "\n px-4 py-2 rounded-lg text-sm font-medium\n bg-[rgb(var(--color-primary))]\n text-white\n hover:opacity-90\n transition-opacity\n flex items-center gap-2\n ", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "w-4 h-4" }), "Load"] }), (0, jsx_runtime_1.jsx)("button", { onClick: () => handleDelete(draft.draftId), disabled: deletingId === draft.draftId, className: "\n p-2 rounded-lg\n text-[rgb(var(--fg-muted))]\n hover:text-red-600\n hover:bg-red-50\n transition-colors\n disabled:opacity-50\n ", title: "Delete draft", children: deletingId === draft.draftId ? ((0, jsx_runtime_1.jsx)("div", { className: "w-4 h-4 rounded-full border-2 border-red-200 border-t-red-600 animate-spin" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Trash2, { className: "w-4 h-4" })) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-x-6 gap-y-1 mt-2 text-sm", children: [preview.jobName && ((0, jsx_runtime_1.jsx)("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.jobName }, "job")), preview.clientName && ((0, jsx_runtime_1.jsx)("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.clientName }, "client")), preview.category && ((0, jsx_runtime_1.jsx)("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.category }, "category")), preview.totalCost !== undefined && preview.totalCost > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "font-medium text-[rgb(var(--color-primary))]", children: [currencySymbol, preview.totalCost.toLocaleString('en-IN')] }, "cost"))] }), progress > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-xs text-[rgb(var(--fg-muted))] mb-1", children: [(0, jsx_runtime_1.jsx)("span", { children: "Progress" }), (0, jsx_runtime_1.jsxs)("span", { className: "font-medium", children: [progress, "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-1.5 bg-[rgb(var(--bg-muted))] rounded-full overflow-hidden", children: (0, jsx_runtime_1.jsx)("div", { className: "h-full bg-[rgb(var(--color-primary))] transition-all duration-500 rounded-full", style: { width: `${progress}%` } }) })] }))] }) }) }, draft.draftId));
|
|
198
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "\r\n group relative p-3 rounded-lg\r\n bg-[rgb(var(--bg-default))]\r\n border border-[rgb(var(--bd-default))]\r\n hover:border-[rgb(var(--color-primary))]\r\n hover:shadow-lg\r\n transition-all duration-200\r\n ", children: (0, jsx_runtime_1.jsx)("div", { className: "flex items-start gap-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("h3", { className: "font-semibold text-[rgb(var(--fg-default))] truncate text-base", children: draft.draftName || 'Untitled Draft' }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mt-1 text-xs text-[rgb(var(--fg-muted))]", children: [(0, jsx_runtime_1.jsx)("span", { children: formatRelativeTime(draft.lastSaved) }), (0, jsx_runtime_1.jsxs)("span", { className: "hidden group-hover:inline", children: ["\u2022 ", formatFullDate(draft.lastSaved)] }), draft.isAutoSave && ((0, jsx_runtime_1.jsx)("span", { className: "text-[10px] px-2 py-0.5 rounded-full bg-[rgb(var(--color-primary)_/_0.1)] text-[rgb(var(--color-primary))] font-medium", children: "AUTO-SAVE" }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => handleLoad(draft.draftId), className: "\r\n px-4 py-2 rounded-lg text-sm font-medium\r\n bg-[rgb(var(--color-primary))]\r\n text-white\r\n hover:opacity-90\r\n transition-opacity\r\n flex items-center gap-2\r\n ", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Download, { className: "w-4 h-4" }), "Load"] }), (0, jsx_runtime_1.jsx)("button", { onClick: () => handleDelete(draft.draftId), disabled: deletingId === draft.draftId, className: "\r\n p-2 rounded-lg\r\n text-[rgb(var(--fg-muted))]\r\n hover:text-red-600\r\n hover:bg-red-50\r\n transition-colors\r\n disabled:opacity-50\r\n ", title: "Delete draft", children: deletingId === draft.draftId ? ((0, jsx_runtime_1.jsx)("div", { className: "w-4 h-4 rounded-full border-2 border-red-200 border-t-red-600 animate-spin" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Trash2, { className: "w-4 h-4" })) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-x-6 gap-y-1 mt-2 text-sm", children: [preview.jobName && ((0, jsx_runtime_1.jsx)("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.jobName }, "job")), preview.clientName && ((0, jsx_runtime_1.jsx)("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.clientName }, "client")), preview.category && ((0, jsx_runtime_1.jsx)("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.category }, "category")), preview.totalCost !== undefined && preview.totalCost > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "font-medium text-[rgb(var(--color-primary))]", children: [currencySymbol, preview.totalCost.toLocaleString('en-IN')] }, "cost"))] }), progress > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mt-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-xs text-[rgb(var(--fg-muted))] mb-1", children: [(0, jsx_runtime_1.jsx)("span", { children: "Progress" }), (0, jsx_runtime_1.jsxs)("span", { className: "font-medium", children: [progress, "%"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "h-1.5 bg-[rgb(var(--bg-muted))] rounded-full overflow-hidden", children: (0, jsx_runtime_1.jsx)("div", { className: "h-full bg-[rgb(var(--color-primary))] transition-all duration-500 rounded-full", style: { width: `${progress}%` } }) })] }))] }) }) }, draft.draftId));
|
|
199
199
|
}) })) }), (0, jsx_runtime_1.jsxs)("div", { className: "px-6 py-4 border-t border-[rgb(var(--bd-default))] flex justify-between items-center bg-[rgb(var(--bg-muted)_/_0.3)]", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-sm text-[rgb(var(--fg-muted))]", children: filteredAndSortedDrafts.length > 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Showing ", ((currentPage - 1) * PAGE_SIZE) + 1, "-", Math.min(currentPage * PAGE_SIZE, filteredAndSortedDrafts.length), " of ", filteredAndSortedDrafts.length, filteredAndSortedDrafts.length !== drafts.length && ` (filtered from ${drafts.length})`] })) : (`0 of ${drafts.length} drafts`) }), totalPages > 1 && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setCurrentPage(p => Math.max(1, p - 1)), disabled: currentPage === 1, className: "p-1.5 rounded text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { className: "w-4 h-4" }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-1", children: Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
|
|
200
200
|
let pageNum;
|
|
201
201
|
if (totalPages <= 5) {
|
|
@@ -210,11 +210,11 @@ function DraftModal({ open, onClose, drafts, onLoad, onDelete, isLoading = false
|
|
|
210
210
|
else {
|
|
211
211
|
pageNum = currentPage - 2 + i;
|
|
212
212
|
}
|
|
213
|
-
return ((0, jsx_runtime_1.jsx)("button", { onClick: () => setCurrentPage(pageNum), className: `
|
|
214
|
-
w-8 h-8 rounded text-sm font-medium transition-colors
|
|
213
|
+
return ((0, jsx_runtime_1.jsx)("button", { onClick: () => setCurrentPage(pageNum), className: `
|
|
214
|
+
w-8 h-8 rounded text-sm font-medium transition-colors
|
|
215
215
|
${currentPage === pageNum
|
|
216
216
|
? 'bg-[rgb(var(--color-primary))] text-white'
|
|
217
|
-
: 'text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))]'}
|
|
217
|
+
: 'text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))]'}
|
|
218
218
|
`, children: pageNum }, pageNum));
|
|
219
|
-
}) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), disabled: currentPage === totalPages, className: "p-1.5 rounded text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "w-4 h-4" }) })] })), (0, jsx_runtime_1.jsx)("button", { onClick: onClose, className: "\n px-5 py-2 rounded-lg text-sm font-medium\n bg-[rgb(var(--bg-default))]\n text-[rgb(var(--fg-default))]\n border border-[rgb(var(--bd-default))]\n hover:bg-[rgb(var(--bg-muted))]\n transition-colors\n ", children: "Close" })] })] }) }));
|
|
219
|
+
}) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), disabled: currentPage === totalPages, className: "p-1.5 rounded text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "w-4 h-4" }) })] })), (0, jsx_runtime_1.jsx)("button", { onClick: onClose, className: "\r\n px-5 py-2 rounded-lg text-sm font-medium\r\n bg-[rgb(var(--bg-default))]\r\n text-[rgb(var(--fg-default))]\r\n border border-[rgb(var(--bd-default))]\r\n hover:bg-[rgb(var(--bg-muted))]\r\n transition-colors\r\n ", children: "Close" })] })] }) }));
|
|
220
220
|
}
|
|
@@ -129,20 +129,14 @@ function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode = 'sing
|
|
|
129
129
|
const normalizeDateToMidnight = (date) => {
|
|
130
130
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
|
|
131
131
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return `${day} ${month}, ${year}`;
|
|
137
|
-
};
|
|
132
|
+
// "1 Sep 2026": built by hand rather than with toLocaleDateString, whose en-GB and en-IN
|
|
133
|
+
// locales spell September "Sept". parseDate reads it back with or without a comma.
|
|
134
|
+
const formatDateNoYear = (date) => `${date.getDate()} ${shared_utils_1.MONTHS[date.getMonth()].slice(0, 3)}`;
|
|
135
|
+
const formatDate = (date) => `${formatDateNoYear(date)} ${date.getFullYear()}`;
|
|
138
136
|
const formatDateShort = (date) => {
|
|
139
137
|
if (!date)
|
|
140
138
|
return '--';
|
|
141
|
-
return date
|
|
142
|
-
day: '2-digit',
|
|
143
|
-
month: 'short',
|
|
144
|
-
year: 'numeric'
|
|
145
|
-
});
|
|
139
|
+
return formatDate(date);
|
|
146
140
|
};
|
|
147
141
|
const formatDisplayValue = () => {
|
|
148
142
|
if (!value)
|
|
@@ -700,9 +694,9 @@ function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode = 'sing
|
|
|
700
694
|
}
|
|
701
695
|
// Default popover mode
|
|
702
696
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('relative w-full', className), ref: containerRef, children: [label && ((0, jsx_runtime_1.jsx)("label", { className: "block text-sm font-medium text-[rgb(var(--fg-muted))] mb-2", children: label })), (0, jsx_runtime_1.jsxs)(Popover.Root, { open: !disabled && isOpen, onOpenChange: (open) => !disabled && setIsOpen(open), children: [(0, jsx_runtime_1.jsx)(Popover.Trigger, { asChild: true, disabled: disabled, children: iconOnly ? ((0, jsx_runtime_1.jsxs)("button", { type: "button", className: (0, utils_1.cn)('relative flex items-center gap-1 text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors p-0.5 flex-shrink-0', (selectedRange.from || selectedRange.to) && 'text-[rgb(var(--color-primary))]', className), title: selectedRange.from || selectedRange.to
|
|
703
|
-
? `Date filter: ${selectedRange.from ? new Date(selectedRange.from)
|
|
697
|
+
? `Date filter: ${selectedRange.from ? formatDate(new Date(selectedRange.from)) : ''}${selectedRange.to ? ` – ${formatDate(new Date(selectedRange.to))}` : ''}`
|
|
704
698
|
: 'Select date range', children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { className: "h-3.5 w-3.5 flex-shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "hidden sm:inline text-xs", children: selectedRange.from || selectedRange.to
|
|
705
|
-
? `${selectedRange.from ? new Date(selectedRange.from)
|
|
699
|
+
? `${selectedRange.from ? formatDateNoYear(new Date(selectedRange.from)) : ''}${selectedRange.to ? ` – ${formatDateNoYear(new Date(selectedRange.to))}` : ''}`
|
|
706
700
|
: 'Date' }), (selectedRange.from || selectedRange.to) && ((0, jsx_runtime_1.jsx)("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-[rgb(var(--color-primary))] ring-1 ring-[rgb(var(--bg-surface))]" }))] })) : ((0, jsx_runtime_1.jsx)("div", { className: "relative", ref: inputWrapperRef, onClick: (e) => e.preventDefault(), children: (0, jsx_runtime_1.jsx)(ui_2.Input, { id: id, "aria-label": ariaLabel, value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, placeholder: getPlaceholder(), disabled: disabled, error: error, className: (0, utils_1.cn)('pl-2 pr-9 text-xs w-full', error && 'border-red-300'), onFocus: () => !disabled && setIsOpen(true), rightIcon: lucide_react_1.Calendar, onRightIconClick: () => !disabled && setIsOpen(!isOpen) }) })) }), (0, jsx_runtime_1.jsx)(Popover.Portal, { container: typeof document !== 'undefined' ? document.body : undefined, children: (0, jsx_runtime_1.jsxs)(Popover.Content, { ref: calendarRef, className: (0, utils_1.cn)("z-[300] bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl border border-[rgb(var(--bd-default))] backdrop-blur-sm", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2", mode === 'range' ? 'w-[95vw] sm:w-auto sm:min-w-[580px] p-2' : 'w-[95vw] sm:w-auto sm:min-w-[280px] p-3', 'max-w-[calc(100vw-2rem)]'), side: "bottom", align: popoverAlign ?? (mode === 'range' ? 'end' : 'start'), sideOffset: 8, avoidCollisions: true, collisionPadding: 16, sticky: "always", onOpenAutoFocus: (e) => e.preventDefault(), onKeyDown: handleCalendarKeyDown, tabIndex: -1, onInteractOutside: (e) => {
|
|
707
701
|
// Prevent closing when interacting with nested Radix portals (like Dropdowns)
|
|
708
702
|
const target = e.target;
|
|
@@ -76,7 +76,7 @@ function DateTimePicker({ value, onChange, placeholder = 'Select date & time...'
|
|
|
76
76
|
return returnFormat === 'string' ? date.toISOString() : date;
|
|
77
77
|
};
|
|
78
78
|
const formatDisplayValue = (date) => {
|
|
79
|
-
const day = date.getDate()
|
|
79
|
+
const day = date.getDate();
|
|
80
80
|
const month = shared_utils_1.MONTHS[date.getMonth()].slice(0, 3);
|
|
81
81
|
const year = date.getFullYear();
|
|
82
82
|
let timeStr = '';
|
|
@@ -90,7 +90,7 @@ function DateTimePicker({ value, onChange, placeholder = 'Select date & time...'
|
|
|
90
90
|
else {
|
|
91
91
|
timeStr = `${hrs.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;
|
|
92
92
|
}
|
|
93
|
-
return `${day} ${month}
|
|
93
|
+
return `${day} ${month} ${year} ${timeStr}`;
|
|
94
94
|
};
|
|
95
95
|
const handleDateClick = (date) => {
|
|
96
96
|
setSelectedDate(date);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@import './tokens.css';
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@import './tokens.css';
|
|
@@ -489,7 +489,7 @@ enableFilterRow = false, initialColumnFilters, }) {
|
|
|
489
489
|
}
|
|
490
490
|
return rowSelection;
|
|
491
491
|
}, [enableViewToggle, viewMode, selectedRowIds, filteredData, rowSelection, getRowId, data]);
|
|
492
|
-
// Helper function to format dates as "12 Oct
|
|
492
|
+
// Helper function to format dates as "12 Oct 2025"
|
|
493
493
|
const formatDateCell = (dateString) => {
|
|
494
494
|
if (!dateString)
|
|
495
495
|
return '-';
|
|
@@ -500,7 +500,7 @@ enableFilterRow = false, initialColumnFilters, }) {
|
|
|
500
500
|
const day = date.getDate();
|
|
501
501
|
const month = date.toLocaleDateString('en-US', { month: 'short' });
|
|
502
502
|
const year = date.getFullYear();
|
|
503
|
-
return `${day} ${month}
|
|
503
|
+
return `${day} ${month} ${year}`;
|
|
504
504
|
}
|
|
505
505
|
catch {
|
|
506
506
|
return dateString;
|
|
@@ -91,10 +91,10 @@ export function CellRenderer({ cell, cellIndex, row, enableBacchaSearch = false,
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
const rowId = row.original.id || row.id;
|
|
94
|
-
return (_jsx("td", { className: `
|
|
95
|
-
px-1 py-1 text-xs text-fg-default align-middle
|
|
96
|
-
${isBadgeColumn || isPlaceholderValue ? 'text-center' : isNumericContent ? 'text-right' : 'text-left'}
|
|
97
|
-
${isCellFrozen || isPinnedRight ? 'sticky z-[5]' : ''}
|
|
94
|
+
return (_jsx("td", { className: `
|
|
95
|
+
px-1 py-1 text-xs text-fg-default align-middle
|
|
96
|
+
${isBadgeColumn || isPlaceholderValue ? 'text-center' : isNumericContent ? 'text-right' : 'text-left'}
|
|
97
|
+
${isCellFrozen || isPinnedRight ? 'sticky z-[5]' : ''}
|
|
98
98
|
`, style: {
|
|
99
99
|
width: `${cell.column.getSize()}px`,
|
|
100
100
|
minWidth: `${cell.column.getSize()}px`,
|
|
@@ -11,13 +11,13 @@ export function SelectionCell({ checked, indeterminate = false, onChange, disabl
|
|
|
11
11
|
};
|
|
12
12
|
// Radio button mode (single selection) - always circular regardless of circularCheckboxes prop
|
|
13
13
|
if (mode === 'radio') {
|
|
14
|
-
return (_jsx("div", { onClick: handleClick, className: `
|
|
15
|
-
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
16
|
-
flex items-center justify-center flex-shrink-0
|
|
17
|
-
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
14
|
+
return (_jsx("div", { onClick: handleClick, className: `
|
|
15
|
+
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
16
|
+
flex items-center justify-center flex-shrink-0
|
|
17
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
18
18
|
${checked
|
|
19
19
|
? 'border-primary bg-white'
|
|
20
|
-
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
20
|
+
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
21
21
|
`, style: {
|
|
22
22
|
boxShadow: checked ? '0 0 0 2px rgba(59, 130, 246, 0.1)' : 'none',
|
|
23
23
|
width: '14px',
|
|
@@ -39,13 +39,13 @@ export function SelectionCell({ checked, indeterminate = false, onChange, disabl
|
|
|
39
39
|
: "border-[rgb(var(--bd-default))] bg-[rgb(var(--bg-surface))] hover:border-[rgb(var(--color-primary))]", disabled && "opacity-50 cursor-not-allowed"), children: [checked && !indeterminate && (_jsx(Check, { className: "w-3 h-3 text-white", strokeWidth: 3 })), indeterminate && (_jsx("div", { className: "w-2 h-0.5 bg-white rounded" }))] })] }));
|
|
40
40
|
}
|
|
41
41
|
// Circular checkbox (AG Grid style, multi-select with circular prop)
|
|
42
|
-
return (_jsxs("div", { onClick: handleClick, className: `
|
|
43
|
-
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
44
|
-
flex items-center justify-center flex-shrink-0
|
|
45
|
-
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
42
|
+
return (_jsxs("div", { onClick: handleClick, className: `
|
|
43
|
+
relative rounded-full border-2 cursor-pointer transition-all duration-150
|
|
44
|
+
flex items-center justify-center flex-shrink-0
|
|
45
|
+
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
|
|
46
46
|
${checked || indeterminate
|
|
47
47
|
? 'border-primary bg-primary'
|
|
48
|
-
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
48
|
+
: 'border-gray-300 bg-white hover:border-gray-400'}
|
|
49
49
|
`, style: {
|
|
50
50
|
boxShadow: checked || indeterminate ? '0 0 0 2px rgba(59, 130, 246, 0.1)' : 'none',
|
|
51
51
|
width: '14px',
|
|
@@ -21,11 +21,11 @@ export function PaginationControls({ pageIndex, pageSize, totalRows, pageSizeOpt
|
|
|
21
21
|
return (_jsx("span", { className: "px-2 text-[rgb(var(--fg-muted))]", children: "..." }, `ellipsis-${index}`));
|
|
22
22
|
}
|
|
23
23
|
const isCurrentPage = page === pageIndex;
|
|
24
|
-
return (_jsx("button", { onClick: () => onPageChange(page), className: `
|
|
25
|
-
min-w-[32px] h-8 px-2 rounded text-sm font-medium transition-colors
|
|
24
|
+
return (_jsx("button", { onClick: () => onPageChange(page), className: `
|
|
25
|
+
min-w-[32px] h-8 px-2 rounded text-sm font-medium transition-colors
|
|
26
26
|
${isCurrentPage
|
|
27
27
|
? 'border border-[rgb(var(--color-primary))] text-[rgb(var(--color-primary))] bg-[rgb(var(--color-primary)/0.08)]'
|
|
28
|
-
: 'text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bd-default))]'}
|
|
28
|
+
: 'text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bd-default))]'}
|
|
29
29
|
`, children: page + 1 }, page));
|
|
30
30
|
}) }), _jsx("button", { onClick: () => onPageChange(pageIndex + 1), disabled: !hasNextPage, className: "p-1.5 rounded hover:bg-[rgb(var(--bd-default))] disabled:opacity-40 disabled:cursor-not-allowed transition-colors", "aria-label": "Next Page", children: _jsx(ChevronRight, { className: "h-4 w-4 text-[rgb(var(--fg-muted))]" }) }), _jsx("button", { onClick: () => onPageChange(totalPages - 1), disabled: !hasNextPage, className: "p-1.5 rounded hover:bg-[rgb(var(--bd-default))] disabled:opacity-40 disabled:cursor-not-allowed transition-colors", "aria-label": "Last Page", children: _jsx(ChevronsRight, { className: "h-4 w-4 text-[rgb(var(--fg-muted))]" }) })] }), !isMobile && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-[rgb(var(--fg-default))] flex-shrink-0 order-2 sm:order-3", children: [_jsx("span", { className: "hidden sm:inline", children: "Show:" }), _jsx(Dropdown, { value: String(pageSize), onValueChange: (value) => onPageSizeChange(Number(value)), options: pageSizeOptions.map((size) => ({
|
|
31
31
|
value: String(size),
|
|
@@ -151,14 +151,14 @@ export function CardView({ data, columns, onRowClick, selectedRows, onRowSelect,
|
|
|
151
151
|
return (_jsxs("div", { ref: containerRef, className: "outline-none", tabIndex: 0, onKeyDown: handleKeyDown, children: [_jsx("div", { className: cfg.pad, children: _jsx("div", { className: `grid ${cfg.grid} ${cfg.gap}`, children: _jsx(AnimatePresence, { initial: false, children: data.map((item, index) => {
|
|
152
152
|
const isFocused = focusedIndex === index;
|
|
153
153
|
const itemSelected = isSelected(item);
|
|
154
|
-
return (_jsx(motion.div, { ref: (el) => { cardRefs.current[index] = el; }, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.12, delay: Math.min(index * 0.015, 0.15) }, className: "group/card outline-none", tabIndex: -1, onClick: () => setFocusedIndex(index), onDoubleClick: () => handleCardClick(item), children: _jsxs("div", { className: `
|
|
155
|
-
relative rounded-lg border bg-[rgb(var(--bg-surface))] overflow-hidden h-full
|
|
156
|
-
transition-all duration-150
|
|
154
|
+
return (_jsx(motion.div, { ref: (el) => { cardRefs.current[index] = el; }, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -6 }, transition: { duration: 0.12, delay: Math.min(index * 0.015, 0.15) }, className: "group/card outline-none", tabIndex: -1, onClick: () => setFocusedIndex(index), onDoubleClick: () => handleCardClick(item), children: _jsxs("div", { className: `
|
|
155
|
+
relative rounded-lg border bg-[rgb(var(--bg-surface))] overflow-hidden h-full
|
|
156
|
+
transition-all duration-150
|
|
157
157
|
${itemSelected
|
|
158
158
|
? 'border-[rgb(var(--color-primary))] shadow-sm'
|
|
159
|
-
: 'border-[rgb(var(--bd-default))] hover:border-[rgb(var(--color-primary))]/40 hover:shadow-sm'}
|
|
160
|
-
${isFocused ? 'ring-2 ring-[rgb(var(--color-primary))]/30 ring-offset-1' : ''}
|
|
161
|
-
${getCardClassName?.(item) ?? ''}
|
|
159
|
+
: 'border-[rgb(var(--bd-default))] hover:border-[rgb(var(--color-primary))]/40 hover:shadow-sm'}
|
|
160
|
+
${isFocused ? 'ring-2 ring-[rgb(var(--color-primary))]/30 ring-offset-1' : ''}
|
|
161
|
+
${getCardClassName?.(item) ?? ''}
|
|
162
162
|
`, children: [_jsx("div", { className: `absolute left-0 top-0 bottom-0 w-[2px] transition-colors duration-150 ${itemSelected ? 'bg-[rgb(var(--color-primary))]' : 'bg-transparent group-hover/card:bg-[rgb(var(--color-primary))]/30'}` }), _jsxs("div", { className: "pl-3 pr-2.5 py-2.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [onRowSelect && (_jsx("div", { className: "flex-shrink-0", onClick: (e) => e.stopPropagation(), children: _jsx(SelectionCheckbox, { checked: itemSelected, onChange: (checked) => handleCheckboxChange(item, checked), circular: circularCheckboxes, mode: "checkbox" }) })), _jsxs("div", { className: "flex-1 min-w-0 flex items-baseline gap-1.5", children: [_jsx("p", { className: `${cfg.titleText} font-semibold text-[rgb(var(--fg-default))] truncate leading-tight`, children: displayColumns.length > 0 && getDisplayValue(item, displayColumns[0].accessorKey) }), displayColumns.length > 1 && (_jsx("p", { className: `${cfg.subtitleText} text-[rgb(var(--color-primary))] font-medium truncate flex-shrink-0`, children: getDisplayValue(item, displayColumns[1].accessorKey) }))] }), _jsx("div", { className: "flex-shrink-0 opacity-0 group-hover/card:opacity-100 transition-opacity duration-150", onClick: (e) => e.stopPropagation(), children: actionsColumn && actionsColumn.cell?.({
|
|
163
163
|
row: { original: item },
|
|
164
164
|
getValue: () => null,
|
|
@@ -17,15 +17,15 @@ navigationState = {}, columnSearches = {}, isColumnSearchActive = {}, onColumnSe
|
|
|
17
17
|
transition,
|
|
18
18
|
opacity: isDragging ? 0.5 : 1,
|
|
19
19
|
};
|
|
20
|
-
return (_jsxs("tr", { ref: setNodeRef, style: style, className: `
|
|
21
|
-
cursor-pointer group
|
|
22
|
-
transition-colors duration-150 ease-out
|
|
23
|
-
${isDragging ? 'shadow-lg z-50' : ''}
|
|
20
|
+
return (_jsxs("tr", { ref: setNodeRef, style: style, className: `
|
|
21
|
+
cursor-pointer group
|
|
22
|
+
transition-colors duration-150 ease-out
|
|
23
|
+
${isDragging ? 'shadow-lg z-50' : ''}
|
|
24
24
|
${isHighlighted
|
|
25
25
|
? 'border-2 border-[rgb(var(--color-primary))] bg-gradient-to-r from-[rgb(var(--color-primary))]/10 to-[rgb(var(--color-primary))]/20 shadow-lg relative'
|
|
26
26
|
: isSelected
|
|
27
27
|
? 'bg-[color-mix(in_srgb,rgb(var(--color-primary))_8%,rgb(var(--bg-surface)))] shadow-sm hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_15%,rgb(var(--bg-surface)))]'
|
|
28
|
-
: 'hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_5%,rgb(var(--bg-surface)))]'}
|
|
29
|
-
${className ?? ''}
|
|
28
|
+
: 'hover:bg-[color-mix(in_srgb,rgb(var(--color-primary))_5%,rgb(var(--bg-surface)))]'}
|
|
29
|
+
${className ?? ''}
|
|
30
30
|
`, onClick: onRowClick, onDoubleClick: onRowDoubleClick, onContextMenu: onRowContextMenu, children: [showDragHandle && (_jsx("td", { className: "text-center align-middle cursor-grab active:cursor-grabbing", style: { width: '1.875rem', minWidth: '1.875rem', maxWidth: '1.875rem' }, ...attributes, ...listeners, children: _jsx("div", { className: "w-full h-full flex items-center justify-center", children: _jsx(GripVertical, { className: "h-4 w-4 text-gray-400" }) }) })), row.getVisibleCells().map((cell, cellIndex) => (_jsx(CellRenderer, { cell: cell, cellIndex: cellIndex, row: row, enableBacchaSearch: enableBacchaSearch, mainColumnsArray: mainColumnsArray, frozenColumnsState: frozenColumnsState, navigationState: navigationState, columnSearches: columnSearches, isColumnSearchActive: isColumnSearchActive, onColumnSearch: onColumnSearch, onClearColumnSearch: onClearColumnSearch, SearchHighlighter: SearchHighlighter, InlineSearchCell: InlineSearchCell, isSelected: isSelected }, cell.id)))] }));
|
|
31
31
|
}
|
|
@@ -86,10 +86,10 @@ export function InlineSearchCell({ value, columnId, rowId, onSearch, onClearSear
|
|
|
86
86
|
return (_jsx(_Fragment, { children: parts.map((part, index) => part.toLowerCase() === highlight.toLowerCase() ? (_jsx("mark", { className: "bg-yellow-200 text-yellow-900 px-0.5 rounded", children: part }, index)) : (_jsx("span", { children: part }, index))) }));
|
|
87
87
|
};
|
|
88
88
|
const displayValue = value?.toString() || '';
|
|
89
|
-
return (_jsxs("div", { ref: cellRef, tabIndex: 0, className: `bacchasearch relative group cursor-pointer outline-none inline-flex items-center w-full ${className}`, onClick: handleCellClick, children: [_jsx("span", { className: `
|
|
90
|
-
text-xs flex-1 rounded transition-colors
|
|
91
|
-
${isSearchActive ? 'bg-[rgb(var(--color-primary)/0.1)]' : 'hover:bg-[rgb(var(--color-primary)/0.05)]'}
|
|
92
|
-
${isTyping ? 'ring-1 ring-[rgb(var(--color-primary)/0.3)] bg-[rgb(var(--color-primary)/0.15)]' : ''}
|
|
89
|
+
return (_jsxs("div", { ref: cellRef, tabIndex: 0, className: `bacchasearch relative group cursor-pointer outline-none inline-flex items-center w-full ${className}`, onClick: handleCellClick, children: [_jsx("span", { className: `
|
|
90
|
+
text-xs flex-1 rounded transition-colors
|
|
91
|
+
${isSearchActive ? 'bg-[rgb(var(--color-primary)/0.1)]' : 'hover:bg-[rgb(var(--color-primary)/0.05)]'}
|
|
92
|
+
${isTyping ? 'ring-1 ring-[rgb(var(--color-primary)/0.3)] bg-[rgb(var(--color-primary)/0.15)]' : ''}
|
|
93
93
|
`, children: isSearchActive && searchTerm ?
|
|
94
94
|
renderHighlightedText(displayValue, searchTerm) :
|
|
95
95
|
displayValue }), _jsx(Search, { className: `h-3 w-3 text-[rgb(var(--fg-muted))] ml-0.5 flex-shrink-0 transition-opacity ${isTyping ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}` }), (isTyping || isSearchActive) && (_jsx("div", { className: "absolute -top-0.5 -right-0.5", children: _jsx("div", { className: `h-1.5 w-1.5 rounded-full ${isTyping ? 'bg-[rgb(var(--color-success))]' : 'bg-[rgb(var(--color-primary))]'}` }) })), isTyping && localSearchTerm && (_jsxs("div", { className: "absolute -bottom-5 left-0 bg-[rgb(var(--bg-surface))] text-[rgb(var(--fg-default))] text-xs px-1.5 py-0.5 rounded shadow-lg border border-[rgb(var(--bd-default))] z-10 whitespace-nowrap", children: ["\"", localSearchTerm, "\""] }))] }));
|
|
@@ -54,14 +54,14 @@ export function AutoSaveIndicator({ enabled, lastSaved, isDirty, isSaving, onOpe
|
|
|
54
54
|
};
|
|
55
55
|
};
|
|
56
56
|
const status = getStatus();
|
|
57
|
-
return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: "Auto-save:" }), _jsx("button", { onClick: () => onToggleAutoSave?.(!enabled), className: `
|
|
58
|
-
relative inline-flex h-5 w-9 items-center rounded-full transition-colors
|
|
59
|
-
${enabled ? 'bg-[rgb(var(--color-primary))]' : 'bg-[rgb(var(--bg-muted))]'}
|
|
60
|
-
`, title: enabled ? 'Disable auto-save' : 'Enable auto-save', children: _jsx("span", { className: `
|
|
61
|
-
inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform
|
|
62
|
-
${enabled ? 'translate-x-5' : 'translate-x-1'}
|
|
63
|
-
` }) }), _jsx("span", { className: "text-xs font-medium text-[rgb(var(--fg-default))]", children: enabled ? 'ON' : 'OFF' })] }), _jsx("div", { className: "h-4 w-px bg-[rgb(var(--bd-default))]" }), _jsxs("button", { onClick: onOpenDraftManager, className: `
|
|
64
|
-
flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors
|
|
65
|
-
${status.bg} ${status.color} hover:opacity-80
|
|
57
|
+
return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: "Auto-save:" }), _jsx("button", { onClick: () => onToggleAutoSave?.(!enabled), className: `
|
|
58
|
+
relative inline-flex h-5 w-9 items-center rounded-full transition-colors
|
|
59
|
+
${enabled ? 'bg-[rgb(var(--color-primary))]' : 'bg-[rgb(var(--bg-muted))]'}
|
|
60
|
+
`, title: enabled ? 'Disable auto-save' : 'Enable auto-save', children: _jsx("span", { className: `
|
|
61
|
+
inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform
|
|
62
|
+
${enabled ? 'translate-x-5' : 'translate-x-1'}
|
|
63
|
+
` }) }), _jsx("span", { className: "text-xs font-medium text-[rgb(var(--fg-default))]", children: enabled ? 'ON' : 'OFF' })] }), _jsx("div", { className: "h-4 w-px bg-[rgb(var(--bd-default))]" }), _jsxs("button", { onClick: onOpenDraftManager, className: `
|
|
64
|
+
flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors
|
|
65
|
+
${status.bg} ${status.color} hover:opacity-80
|
|
66
66
|
`, title: "Click to manage drafts", children: [status.icon, _jsx("span", { className: "text-xs font-medium", children: status.text })] })] }));
|
|
67
67
|
}
|
|
@@ -156,10 +156,10 @@ export function DraftModal({ open, onClose, drafts, onLoad, onDelete, isLoading
|
|
|
156
156
|
// Early return after all hooks to comply with Rules of Hooks
|
|
157
157
|
if (!open)
|
|
158
158
|
return null;
|
|
159
|
-
return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: _jsxs("div", { className: "bg-[rgb(var(--bg-surface))] rounded-lg shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col", children: [_jsxs("div", { className: "px-6 py-3 border-b border-[rgb(var(--bd-default))] flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [_jsx(FileText, { className: "w-5 h-5 text-[rgb(var(--color-primary))]" }), _jsx("h2", { className: "text-base font-semibold text-[rgb(var(--fg-default))]", children: "Saved Drafts" }), _jsxs("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: ["(", drafts.length, ")"] })] }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[rgb(var(--fg-muted))]" }), _jsx("input", { type: "text", placeholder: "Search...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "\n w-full pl-9 pr-3 py-1.5 rounded-lg text-sm\n bg-[rgb(var(--bg-default))]\n border border-[rgb(var(--bd-default))]\n text-[rgb(var(--fg-default))]\n placeholder:text-[rgb(var(--fg-muted))]\n focus:outline-none focus:ring-2 focus:ring-[rgb(var(--color-primary))]\n " })] }), _jsx("div", { className: "flex-shrink-0 w-36", children: _jsx(Dropdown, { options: SORT_OPTIONS, value: sortBy, onValueChange: (val) => setSortBy(val), size: "sm", autoWidth: true }) }), _jsx("button", { onClick: onClose, className: "p-1.5 rounded-lg hover:bg-[rgb(var(--bg-muted))] text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: isLoading ? (_jsx("div", { className: "flex items-center justify-center py-16", children: _jsxs("div", { className: "text-center", children: [_jsx("div", { className: "w-12 h-12 rounded-full border-4 border-[rgb(var(--color-primary)_/_0.2)] border-t-[rgb(var(--color-primary))] animate-spin mx-auto mb-3" }), _jsx("p", { className: "text-[rgb(var(--fg-muted))]", children: "Loading drafts..." })] }) })) : filteredAndSortedDrafts.length === 0 ? (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [_jsx(FileText, { className: "w-16 h-16 text-[rgb(var(--fg-muted))] mb-4 opacity-50" }), _jsx("p", { className: "text-lg font-medium text-[rgb(var(--fg-default))] mb-1", children: searchQuery ? 'No matching drafts' : 'No drafts saved yet' }), _jsx("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: searchQuery ? 'Try a different search term' : 'Start by clicking "Save Draft" button' })] })) : (_jsx("div", { className: "space-y-3", children: paginatedDrafts.map((draft) => {
|
|
159
|
+
return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: _jsxs("div", { className: "bg-[rgb(var(--bg-surface))] rounded-lg shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col", children: [_jsxs("div", { className: "px-6 py-3 border-b border-[rgb(var(--bd-default))] flex items-center gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [_jsx(FileText, { className: "w-5 h-5 text-[rgb(var(--color-primary))]" }), _jsx("h2", { className: "text-base font-semibold text-[rgb(var(--fg-default))]", children: "Saved Drafts" }), _jsxs("span", { className: "text-xs text-[rgb(var(--fg-muted))]", children: ["(", drafts.length, ")"] })] }), _jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-[rgb(var(--fg-muted))]" }), _jsx("input", { type: "text", placeholder: "Search...", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "\r\n w-full pl-9 pr-3 py-1.5 rounded-lg text-sm\r\n bg-[rgb(var(--bg-default))]\r\n border border-[rgb(var(--bd-default))]\r\n text-[rgb(var(--fg-default))]\r\n placeholder:text-[rgb(var(--fg-muted))]\r\n focus:outline-none focus:ring-2 focus:ring-[rgb(var(--color-primary))]\r\n " })] }), _jsx("div", { className: "flex-shrink-0 w-36", children: _jsx(Dropdown, { options: SORT_OPTIONS, value: sortBy, onValueChange: (val) => setSortBy(val), size: "sm", autoWidth: true }) }), _jsx("button", { onClick: onClose, className: "p-1.5 rounded-lg hover:bg-[rgb(var(--bg-muted))] text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: isLoading ? (_jsx("div", { className: "flex items-center justify-center py-16", children: _jsxs("div", { className: "text-center", children: [_jsx("div", { className: "w-12 h-12 rounded-full border-4 border-[rgb(var(--color-primary)_/_0.2)] border-t-[rgb(var(--color-primary))] animate-spin mx-auto mb-3" }), _jsx("p", { className: "text-[rgb(var(--fg-muted))]", children: "Loading drafts..." })] }) })) : filteredAndSortedDrafts.length === 0 ? (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [_jsx(FileText, { className: "w-16 h-16 text-[rgb(var(--fg-muted))] mb-4 opacity-50" }), _jsx("p", { className: "text-lg font-medium text-[rgb(var(--fg-default))] mb-1", children: searchQuery ? 'No matching drafts' : 'No drafts saved yet' }), _jsx("p", { className: "text-sm text-[rgb(var(--fg-muted))]", children: searchQuery ? 'Try a different search term' : 'Start by clicking "Save Draft" button' })] })) : (_jsx("div", { className: "space-y-3", children: paginatedDrafts.map((draft) => {
|
|
160
160
|
const progress = calculateProgress(draft);
|
|
161
161
|
const preview = draft.previewData || {};
|
|
162
|
-
return (_jsx("div", { className: "\n group relative p-3 rounded-lg\n bg-[rgb(var(--bg-default))]\n border border-[rgb(var(--bd-default))]\n hover:border-[rgb(var(--color-primary))]\n hover:shadow-lg\n transition-all duration-200\n ", children: _jsx("div", { className: "flex items-start gap-4", children: _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-[rgb(var(--fg-default))] truncate text-base", children: draft.draftName || 'Untitled Draft' }), _jsxs("div", { className: "flex items-center gap-2 mt-1 text-xs text-[rgb(var(--fg-muted))]", children: [_jsx("span", { children: formatRelativeTime(draft.lastSaved) }), _jsxs("span", { className: "hidden group-hover:inline", children: ["\u2022 ", formatFullDate(draft.lastSaved)] }), draft.isAutoSave && (_jsx("span", { className: "text-[10px] px-2 py-0.5 rounded-full bg-[rgb(var(--color-primary)_/_0.1)] text-[rgb(var(--color-primary))] font-medium", children: "AUTO-SAVE" }))] })] }), _jsxs("div", { className: "flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity", children: [_jsxs("button", { onClick: () => handleLoad(draft.draftId), className: "\n px-4 py-2 rounded-lg text-sm font-medium\n bg-[rgb(var(--color-primary))]\n text-white\n hover:opacity-90\n transition-opacity\n flex items-center gap-2\n ", children: [_jsx(Download, { className: "w-4 h-4" }), "Load"] }), _jsx("button", { onClick: () => handleDelete(draft.draftId), disabled: deletingId === draft.draftId, className: "\n p-2 rounded-lg\n text-[rgb(var(--fg-muted))]\n hover:text-red-600\n hover:bg-red-50\n transition-colors\n disabled:opacity-50\n ", title: "Delete draft", children: deletingId === draft.draftId ? (_jsx("div", { className: "w-4 h-4 rounded-full border-2 border-red-200 border-t-red-600 animate-spin" })) : (_jsx(Trash2, { className: "w-4 h-4" })) })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-x-6 gap-y-1 mt-2 text-sm", children: [preview.jobName && (_jsx("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.jobName }, "job")), preview.clientName && (_jsx("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.clientName }, "client")), preview.category && (_jsx("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.category }, "category")), preview.totalCost !== undefined && preview.totalCost > 0 && (_jsxs("div", { className: "font-medium text-[rgb(var(--color-primary))]", children: [currencySymbol, preview.totalCost.toLocaleString('en-IN')] }, "cost"))] }), progress > 0 && (_jsxs("div", { className: "mt-2", children: [_jsxs("div", { className: "flex items-center justify-between text-xs text-[rgb(var(--fg-muted))] mb-1", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { className: "font-medium", children: [progress, "%"] })] }), _jsx("div", { className: "h-1.5 bg-[rgb(var(--bg-muted))] rounded-full overflow-hidden", children: _jsx("div", { className: "h-full bg-[rgb(var(--color-primary))] transition-all duration-500 rounded-full", style: { width: `${progress}%` } }) })] }))] }) }) }, draft.draftId));
|
|
162
|
+
return (_jsx("div", { className: "\r\n group relative p-3 rounded-lg\r\n bg-[rgb(var(--bg-default))]\r\n border border-[rgb(var(--bd-default))]\r\n hover:border-[rgb(var(--color-primary))]\r\n hover:shadow-lg\r\n transition-all duration-200\r\n ", children: _jsx("div", { className: "flex items-start gap-4", children: _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-[rgb(var(--fg-default))] truncate text-base", children: draft.draftName || 'Untitled Draft' }), _jsxs("div", { className: "flex items-center gap-2 mt-1 text-xs text-[rgb(var(--fg-muted))]", children: [_jsx("span", { children: formatRelativeTime(draft.lastSaved) }), _jsxs("span", { className: "hidden group-hover:inline", children: ["\u2022 ", formatFullDate(draft.lastSaved)] }), draft.isAutoSave && (_jsx("span", { className: "text-[10px] px-2 py-0.5 rounded-full bg-[rgb(var(--color-primary)_/_0.1)] text-[rgb(var(--color-primary))] font-medium", children: "AUTO-SAVE" }))] })] }), _jsxs("div", { className: "flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity", children: [_jsxs("button", { onClick: () => handleLoad(draft.draftId), className: "\r\n px-4 py-2 rounded-lg text-sm font-medium\r\n bg-[rgb(var(--color-primary))]\r\n text-white\r\n hover:opacity-90\r\n transition-opacity\r\n flex items-center gap-2\r\n ", children: [_jsx(Download, { className: "w-4 h-4" }), "Load"] }), _jsx("button", { onClick: () => handleDelete(draft.draftId), disabled: deletingId === draft.draftId, className: "\r\n p-2 rounded-lg\r\n text-[rgb(var(--fg-muted))]\r\n hover:text-red-600\r\n hover:bg-red-50\r\n transition-colors\r\n disabled:opacity-50\r\n ", title: "Delete draft", children: deletingId === draft.draftId ? (_jsx("div", { className: "w-4 h-4 rounded-full border-2 border-red-200 border-t-red-600 animate-spin" })) : (_jsx(Trash2, { className: "w-4 h-4" })) })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-x-6 gap-y-1 mt-2 text-sm", children: [preview.jobName && (_jsx("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.jobName }, "job")), preview.clientName && (_jsx("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.clientName }, "client")), preview.category && (_jsx("div", { className: "text-[rgb(var(--fg-muted))] truncate", children: preview.category }, "category")), preview.totalCost !== undefined && preview.totalCost > 0 && (_jsxs("div", { className: "font-medium text-[rgb(var(--color-primary))]", children: [currencySymbol, preview.totalCost.toLocaleString('en-IN')] }, "cost"))] }), progress > 0 && (_jsxs("div", { className: "mt-2", children: [_jsxs("div", { className: "flex items-center justify-between text-xs text-[rgb(var(--fg-muted))] mb-1", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { className: "font-medium", children: [progress, "%"] })] }), _jsx("div", { className: "h-1.5 bg-[rgb(var(--bg-muted))] rounded-full overflow-hidden", children: _jsx("div", { className: "h-full bg-[rgb(var(--color-primary))] transition-all duration-500 rounded-full", style: { width: `${progress}%` } }) })] }))] }) }) }, draft.draftId));
|
|
163
163
|
}) })) }), _jsxs("div", { className: "px-6 py-4 border-t border-[rgb(var(--bd-default))] flex justify-between items-center bg-[rgb(var(--bg-muted)_/_0.3)]", children: [_jsx("div", { className: "text-sm text-[rgb(var(--fg-muted))]", children: filteredAndSortedDrafts.length > 0 ? (_jsxs(_Fragment, { children: ["Showing ", ((currentPage - 1) * PAGE_SIZE) + 1, "-", Math.min(currentPage * PAGE_SIZE, filteredAndSortedDrafts.length), " of ", filteredAndSortedDrafts.length, filteredAndSortedDrafts.length !== drafts.length && ` (filtered from ${drafts.length})`] })) : (`0 of ${drafts.length} drafts`) }), totalPages > 1 && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: () => setCurrentPage(p => Math.max(1, p - 1)), disabled: currentPage === 1, className: "p-1.5 rounded text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors", children: _jsx(ChevronLeft, { className: "w-4 h-4" }) }), _jsx("div", { className: "flex items-center gap-1", children: Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
|
|
164
164
|
let pageNum;
|
|
165
165
|
if (totalPages <= 5) {
|
|
@@ -174,11 +174,11 @@ export function DraftModal({ open, onClose, drafts, onLoad, onDelete, isLoading
|
|
|
174
174
|
else {
|
|
175
175
|
pageNum = currentPage - 2 + i;
|
|
176
176
|
}
|
|
177
|
-
return (_jsx("button", { onClick: () => setCurrentPage(pageNum), className: `
|
|
178
|
-
w-8 h-8 rounded text-sm font-medium transition-colors
|
|
177
|
+
return (_jsx("button", { onClick: () => setCurrentPage(pageNum), className: `
|
|
178
|
+
w-8 h-8 rounded text-sm font-medium transition-colors
|
|
179
179
|
${currentPage === pageNum
|
|
180
180
|
? 'bg-[rgb(var(--color-primary))] text-white'
|
|
181
|
-
: 'text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))]'}
|
|
181
|
+
: 'text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))]'}
|
|
182
182
|
`, children: pageNum }, pageNum));
|
|
183
|
-
}) }), _jsx("button", { onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), disabled: currentPage === totalPages, className: "p-1.5 rounded text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors", children: _jsx(ChevronRight, { className: "w-4 h-4" }) })] })), _jsx("button", { onClick: onClose, className: "\n px-5 py-2 rounded-lg text-sm font-medium\n bg-[rgb(var(--bg-default))]\n text-[rgb(var(--fg-default))]\n border border-[rgb(var(--bd-default))]\n hover:bg-[rgb(var(--bg-muted))]\n transition-colors\n ", children: "Close" })] })] }) }));
|
|
183
|
+
}) }), _jsx("button", { onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)), disabled: currentPage === totalPages, className: "p-1.5 rounded text-[rgb(var(--fg-muted))] hover:bg-[rgb(var(--bg-default))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors", children: _jsx(ChevronRight, { className: "w-4 h-4" }) })] })), _jsx("button", { onClick: onClose, className: "\r\n px-5 py-2 rounded-lg text-sm font-medium\r\n bg-[rgb(var(--bg-default))]\r\n text-[rgb(var(--fg-default))]\r\n border border-[rgb(var(--bd-default))]\r\n hover:bg-[rgb(var(--bg-muted))]\r\n transition-colors\r\n ", children: "Close" })] })] }) }));
|
|
184
184
|
}
|
|
@@ -93,20 +93,14 @@ export function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode
|
|
|
93
93
|
const normalizeDateToMidnight = (date) => {
|
|
94
94
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
|
|
95
95
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return `${day} ${month}, ${year}`;
|
|
101
|
-
};
|
|
96
|
+
// "1 Sep 2026": built by hand rather than with toLocaleDateString, whose en-GB and en-IN
|
|
97
|
+
// locales spell September "Sept". parseDate reads it back with or without a comma.
|
|
98
|
+
const formatDateNoYear = (date) => `${date.getDate()} ${MONTHS[date.getMonth()].slice(0, 3)}`;
|
|
99
|
+
const formatDate = (date) => `${formatDateNoYear(date)} ${date.getFullYear()}`;
|
|
102
100
|
const formatDateShort = (date) => {
|
|
103
101
|
if (!date)
|
|
104
102
|
return '--';
|
|
105
|
-
return date
|
|
106
|
-
day: '2-digit',
|
|
107
|
-
month: 'short',
|
|
108
|
-
year: 'numeric'
|
|
109
|
-
});
|
|
103
|
+
return formatDate(date);
|
|
110
104
|
};
|
|
111
105
|
const formatDisplayValue = () => {
|
|
112
106
|
if (!value)
|
|
@@ -664,9 +658,9 @@ export function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode
|
|
|
664
658
|
}
|
|
665
659
|
// Default popover mode
|
|
666
660
|
return (_jsxs("div", { className: cn('relative w-full', className), ref: containerRef, children: [label && (_jsx("label", { className: "block text-sm font-medium text-[rgb(var(--fg-muted))] mb-2", children: label })), _jsxs(Popover.Root, { open: !disabled && isOpen, onOpenChange: (open) => !disabled && setIsOpen(open), children: [_jsx(Popover.Trigger, { asChild: true, disabled: disabled, children: iconOnly ? (_jsxs("button", { type: "button", className: cn('relative flex items-center gap-1 text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors p-0.5 flex-shrink-0', (selectedRange.from || selectedRange.to) && 'text-[rgb(var(--color-primary))]', className), title: selectedRange.from || selectedRange.to
|
|
667
|
-
? `Date filter: ${selectedRange.from ? new Date(selectedRange.from)
|
|
661
|
+
? `Date filter: ${selectedRange.from ? formatDate(new Date(selectedRange.from)) : ''}${selectedRange.to ? ` – ${formatDate(new Date(selectedRange.to))}` : ''}`
|
|
668
662
|
: 'Select date range', children: [_jsx(CalendarDays, { className: "h-3.5 w-3.5 flex-shrink-0" }), _jsx("span", { className: "hidden sm:inline text-xs", children: selectedRange.from || selectedRange.to
|
|
669
|
-
? `${selectedRange.from ? new Date(selectedRange.from)
|
|
663
|
+
? `${selectedRange.from ? formatDateNoYear(new Date(selectedRange.from)) : ''}${selectedRange.to ? ` – ${formatDateNoYear(new Date(selectedRange.to))}` : ''}`
|
|
670
664
|
: 'Date' }), (selectedRange.from || selectedRange.to) && (_jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-[rgb(var(--color-primary))] ring-1 ring-[rgb(var(--bg-surface))]" }))] })) : (_jsx("div", { className: "relative", ref: inputWrapperRef, onClick: (e) => e.preventDefault(), children: _jsx(Input, { id: id, "aria-label": ariaLabel, value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, placeholder: getPlaceholder(), disabled: disabled, error: error, className: cn('pl-2 pr-9 text-xs w-full', error && 'border-red-300'), onFocus: () => !disabled && setIsOpen(true), rightIcon: Calendar, onRightIconClick: () => !disabled && setIsOpen(!isOpen) }) })) }), _jsx(Popover.Portal, { container: typeof document !== 'undefined' ? document.body : undefined, children: _jsxs(Popover.Content, { ref: calendarRef, className: cn("z-[300] bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl border border-[rgb(var(--bd-default))] backdrop-blur-sm", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2", mode === 'range' ? 'w-[95vw] sm:w-auto sm:min-w-[580px] p-2' : 'w-[95vw] sm:w-auto sm:min-w-[280px] p-3', 'max-w-[calc(100vw-2rem)]'), side: "bottom", align: popoverAlign ?? (mode === 'range' ? 'end' : 'start'), sideOffset: 8, avoidCollisions: true, collisionPadding: 16, sticky: "always", onOpenAutoFocus: (e) => e.preventDefault(), onKeyDown: handleCalendarKeyDown, tabIndex: -1, onInteractOutside: (e) => {
|
|
671
665
|
// Prevent closing when interacting with nested Radix portals (like Dropdowns)
|
|
672
666
|
const target = e.target;
|
|
@@ -40,7 +40,7 @@ export function DateTimePicker({ value, onChange, placeholder = 'Select date & t
|
|
|
40
40
|
return returnFormat === 'string' ? date.toISOString() : date;
|
|
41
41
|
};
|
|
42
42
|
const formatDisplayValue = (date) => {
|
|
43
|
-
const day = date.getDate()
|
|
43
|
+
const day = date.getDate();
|
|
44
44
|
const month = MONTHS[date.getMonth()].slice(0, 3);
|
|
45
45
|
const year = date.getFullYear();
|
|
46
46
|
let timeStr = '';
|
|
@@ -54,7 +54,7 @@ export function DateTimePicker({ value, onChange, placeholder = 'Select date & t
|
|
|
54
54
|
else {
|
|
55
55
|
timeStr = `${hrs.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;
|
|
56
56
|
}
|
|
57
|
-
return `${day} ${month}
|
|
57
|
+
return `${day} ${month} ${year} ${timeStr}`;
|
|
58
58
|
};
|
|
59
59
|
const handleDateClick = (date) => {
|
|
60
60
|
setSelectedDate(date);
|
package/dist/styles/index.css
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@import './tokens.css';
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@import './tokens.css';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "indas-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Indas UI — React component library for business apps: Tailwind design tokens, Radix primitives, Lucide icons, DataGrid, dashboards and charts.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Indas Analytics Pvt Ltd",
|