react-restyle-components 0.4.65 → 0.4.66
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/lib/src/core-components/src/components/Table/Table.js +105 -16
- package/lib/src/core-components/src/components/Table/filters.d.ts +24 -12
- package/lib/src/core-components/src/components/Table/filters.js +65 -39
- package/lib/src/core-components/src/components/Table/index.d.ts +1 -1
- package/lib/src/core-components/src/components/Table/index.js +1 -1
- package/lib/src/core-components/src/components/Table/types.d.ts +12 -2
- package/lib/src/core-components/src/tc.global.css +7 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import React, { forwardRef, useState, useCallback, useMemo, useEffect, useRef, } from 'react';
|
|
4
4
|
import { TableRoot, Toolbar, ToolbarGroup, SearchInput, ToolbarButton, TableWrapper, StyledTable, TableHeader, HeaderRow, HeaderCell, TableBody, TableRow, TableCell, TableCellContent, Checkbox, ExpandButton, ExpandedRow, ExpandedCell, TableFooter, FooterRow, FooterCell, PaginationWrapper, PaginationInfo, PaginationControls, PageButton, PageSizeInputWrapper, PageSizeInput, PageSizeDropdownIcon, PageSizeDropdown, PageSizeDropdownItem, QuickJumper, EmptyState, LoadingOverlay, LoadingSpinner, EditableCell, CellEditor, ColumnTogglePanel, ColumnToggleHeader, ColumnToggleSearch, ColumnToggleList, ColumnToggleItem, ColumnToggleDragHandle, SelectionIndicator, SelectionCount, SelectSortButton, } from './elements';
|
|
5
5
|
import { useSortState, useFilterState, usePaginationState, useRowSelection, useRowExpansion, useColumnVisibility, useTableDebounce, sortData, filterData, paginateData, getNestedValue, exportToCSV, exportToExcel, } from './hooks';
|
|
6
|
-
import { getFilterComponent } from './filters';
|
|
6
|
+
import { getFilterComponent, createCallableFilterHandle } from './filters';
|
|
7
7
|
import { Tooltip } from '../Tooltip';
|
|
8
8
|
import { LoadingAnimateSpin } from '../Loader/loader.component';
|
|
9
9
|
import { useColumnResize, getColumnStyle } from './columnResize';
|
|
@@ -54,6 +54,31 @@ const RefreshIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", st
|
|
|
54
54
|
const PrintIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M6 9V2h12v7M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("rect", { x: "6", y: "14", width: "12", height: "8" })] }));
|
|
55
55
|
const ErrorIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M12 8v4M12 16h.01", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
56
56
|
const tableFilterCache = new Map();
|
|
57
|
+
/** Reads `getFilter` from TextFilter / NumberFilter / CustomFilter / DateFilter / SelectFilter factory `.props`. */
|
|
58
|
+
function getColumnFilterGetFilterCallback(filter) {
|
|
59
|
+
if (typeof filter !== 'function')
|
|
60
|
+
return undefined;
|
|
61
|
+
const props = filter.props;
|
|
62
|
+
return typeof props?.getFilter === 'function' ? props.getFilter : undefined;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* When using `filterRenderer`, the factory `filter` component does not mount, so its `getFilter`
|
|
66
|
+
* never runs. Registers the same callable imperative API as built-in filters (via table state).
|
|
67
|
+
*/
|
|
68
|
+
function FilterRendererGetFilterBridge({ getFilter, dataField, filters, handleFilterChange, }) {
|
|
69
|
+
const applyRef = useRef(() => { });
|
|
70
|
+
applyRef.current = (v) => handleFilterChange(dataField, v);
|
|
71
|
+
const getValueRef = useRef(() => filters[dataField]);
|
|
72
|
+
getValueRef.current = () => filters[dataField];
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
getFilter(createCallableFilterHandle({
|
|
75
|
+
getValue: () => getValueRef.current(),
|
|
76
|
+
setValue: (value) => applyRef.current(value),
|
|
77
|
+
clear: () => applyRef.current(null),
|
|
78
|
+
}));
|
|
79
|
+
}, [getFilter]);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
57
82
|
export const Table = forwardRef(function TableComponent(props, ref) {
|
|
58
83
|
const { id, data, columns, keyField = '_id', loading = false, loadingIndicator, isLoading = false, pagination = true, paginationConfig, totalSize, remote = true, defaultSort, sort: controlledSort, filterable = false, defaultFilters, filters: controlledFilters, defaultShowFilters = true, showFilters: controlledShowFilters, onShowFiltersChange, showFilterToggle = true, searchable = true, searchPlaceholder = 'Search...', defaultSearchValue = '', searchValue: controlledSearchValue, searchDebounce = 300, rowSelection, expandable, editMode = 'dblclick', showEditIcon = false, onCellEdit, exportable = true, exportFileName = 'table_export', exportFormat = 'excel', exportSheetName, exportHeaderStyle, exportExtraSheets, exportSummaryRows, exportCharts, columnToggle = false, isFieldSelector = true, bordered = true, striped = false, hover = true, compact = false, cellPadding, stickyHeader = false, maxHeight, rowClassName, rowStyle, classNames = {}, styles = {}, className, style, emptyText = 'No data available', onChange, onPageChange, onSortChange, onFilterChange, onSearch, onRowClick, onRowDoubleClick, onClearFilters, toolbar, hideToolbar = false, showFooter = false, caption,
|
|
59
84
|
// Quick configuration props
|
|
@@ -466,6 +491,28 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
466
491
|
// Reset the flag after processing to prevent duplicate calls
|
|
467
492
|
shouldCallOnFilter.current = false;
|
|
468
493
|
}, [debouncedSearchValue, filters, page, pageSize]);
|
|
494
|
+
/** When remote filtering is used, pagination must re-send current criteria + new page/size. */
|
|
495
|
+
const getActiveRemoteFilterCallArgs = useCallback(() => {
|
|
496
|
+
const cleanFilters = {};
|
|
497
|
+
Object.keys(filters).forEach((key) => {
|
|
498
|
+
const value = filters[key];
|
|
499
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
500
|
+
cleanFilters[key] = value;
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
const hasColumnFilters = Object.keys(cleanFilters).length > 0;
|
|
504
|
+
const hasSearch = Boolean(debouncedSearchValue);
|
|
505
|
+
if (!hasColumnFilters && !hasSearch)
|
|
506
|
+
return null;
|
|
507
|
+
const filterData = { ...cleanFilters };
|
|
508
|
+
if (hasSearch) {
|
|
509
|
+
filterData.srText = debouncedSearchValue;
|
|
510
|
+
}
|
|
511
|
+
const type = hasColumnFilters
|
|
512
|
+
? 'filter'
|
|
513
|
+
: 'search';
|
|
514
|
+
return { type, filterData };
|
|
515
|
+
}, [filters, debouncedSearchValue]);
|
|
469
516
|
// Track selection count changes for animation
|
|
470
517
|
useEffect(() => {
|
|
471
518
|
const currentCount = selectedKeys.size;
|
|
@@ -607,6 +654,15 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
607
654
|
lastOnFilterCallRef.current = null;
|
|
608
655
|
// Clear the cache so remounts also start fresh
|
|
609
656
|
tableFilterCache.delete(id);
|
|
657
|
+
// Remote tables: clear-all must notify like column-filter clears. Search uses debounce and
|
|
658
|
+
// never sets shouldCallOnFilter here, so invoke onFilter immediately with empty criteria.
|
|
659
|
+
if (onFilter) {
|
|
660
|
+
prevSearchRef.current = '';
|
|
661
|
+
prevFiltersRef.current = JSON.stringify({});
|
|
662
|
+
shouldCallOnFilter.current = false;
|
|
663
|
+
filterTypeRef.current = 'filter';
|
|
664
|
+
onFilterRef.current?.('filter', {}, page + 1, pageSize);
|
|
665
|
+
}
|
|
610
666
|
}, [
|
|
611
667
|
id,
|
|
612
668
|
clearFilters,
|
|
@@ -614,6 +670,9 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
614
670
|
onFilterChange,
|
|
615
671
|
onChange,
|
|
616
672
|
resetEditingState,
|
|
673
|
+
onFilter,
|
|
674
|
+
page,
|
|
675
|
+
pageSize,
|
|
617
676
|
]);
|
|
618
677
|
// Handle page change
|
|
619
678
|
const handlePageChange = useCallback((newPage) => {
|
|
@@ -621,13 +680,24 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
621
680
|
goToPage(newPage);
|
|
622
681
|
// Pass 1-indexed page number to callbacks (user-friendly)
|
|
623
682
|
const displayPage = newPage + 1;
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
683
|
+
const filterArgs = onFilter ? getActiveRemoteFilterCallArgs() : null;
|
|
684
|
+
// With active remote criteria, only onFilter should run (avoids double fetch vs onPageSizeChange)
|
|
685
|
+
if (filterArgs) {
|
|
686
|
+
onFilterRef.current?.(filterArgs.type, filterArgs.filterData, displayPage, pageSize);
|
|
687
|
+
// Keep onChange pagination for URL/sync; avoid duplicate fetch callbacks (onPageSizeChange / onPageChange)
|
|
688
|
+
onChange?.({
|
|
689
|
+
type: 'pagination',
|
|
690
|
+
pagination: { page: displayPage, pageSize },
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
onPageSizeChange?.(displayPage, pageSize);
|
|
695
|
+
onPageChange?.(displayPage, pageSize);
|
|
696
|
+
onChange?.({
|
|
697
|
+
type: 'pagination',
|
|
698
|
+
pagination: { page: displayPage, pageSize },
|
|
699
|
+
});
|
|
700
|
+
}
|
|
631
701
|
}, [
|
|
632
702
|
goToPage,
|
|
633
703
|
pageSize,
|
|
@@ -635,24 +705,37 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
635
705
|
onPageChange,
|
|
636
706
|
onChange,
|
|
637
707
|
resetEditingState,
|
|
708
|
+
onFilter,
|
|
709
|
+
getActiveRemoteFilterCallArgs,
|
|
638
710
|
]);
|
|
639
711
|
// Handle page size change
|
|
640
712
|
const handlePageSizeChange = useCallback((newSize) => {
|
|
641
713
|
resetEditingState();
|
|
642
714
|
changePageSize(newSize);
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
715
|
+
const filterArgs = onFilter ? getActiveRemoteFilterCallArgs() : null;
|
|
716
|
+
if (filterArgs) {
|
|
717
|
+
onFilterRef.current?.(filterArgs.type, filterArgs.filterData, 1, newSize);
|
|
718
|
+
onChange?.({
|
|
719
|
+
type: 'pagination',
|
|
720
|
+
pagination: { page: 1, pageSize: newSize },
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
else {
|
|
724
|
+
onPageSizeChange?.(1, newSize);
|
|
725
|
+
onPageChange?.(1, newSize);
|
|
726
|
+
onChange?.({
|
|
727
|
+
type: 'pagination',
|
|
728
|
+
pagination: { page: 1, pageSize: newSize },
|
|
729
|
+
});
|
|
730
|
+
}
|
|
650
731
|
}, [
|
|
651
732
|
changePageSize,
|
|
652
733
|
onPageSizeChange,
|
|
653
734
|
onPageChange,
|
|
654
735
|
onChange,
|
|
655
736
|
resetEditingState,
|
|
737
|
+
onFilter,
|
|
738
|
+
getActiveRemoteFilterCallArgs,
|
|
656
739
|
]);
|
|
657
740
|
// Handle row click
|
|
658
741
|
const handleRowClick = useCallback((row, rowIndex, e) => {
|
|
@@ -1474,6 +1557,9 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
1474
1557
|
// Non-null reference for JSX rendering (guarded by showFilter check below)
|
|
1475
1558
|
const ResolvedFilter = FilterComponent;
|
|
1476
1559
|
const onFilter = (value) => handleFilterChange(column.dataField, value);
|
|
1560
|
+
const factoryGetFilter = column.filterRenderer
|
|
1561
|
+
? getColumnFilterGetFilterCallback(column.filter)
|
|
1562
|
+
: undefined;
|
|
1477
1563
|
// Get resized column style
|
|
1478
1564
|
const resizeStyle = resizable
|
|
1479
1565
|
? getColumnStyle(column, columnWidths, resizable, isResizing)
|
|
@@ -1598,7 +1684,10 @@ export const Table = forwardRef(function TableComponent(props, ref) {
|
|
|
1598
1684
|
display: 'flex',
|
|
1599
1685
|
alignItems: 'center',
|
|
1600
1686
|
overflow: 'hidden',
|
|
1601
|
-
}, onClick: (e) => e.stopPropagation(), children: column.filterRenderer ? (
|
|
1687
|
+
}, onClick: (e) => e.stopPropagation(), children: column.filterRenderer ? (_jsxs(_Fragment, { children: [factoryGetFilter ? (_jsx(FilterRendererGetFilterBridge, { getFilter: factoryGetFilter, dataField: column.dataField, filters: filters, handleFilterChange: handleFilterChange })) : null, column.filterRenderer(onFilter, column, {
|
|
1688
|
+
value: filters[column.dataField],
|
|
1689
|
+
onClear: () => handleFilterChange(column.dataField, null),
|
|
1690
|
+
})] })) : (_jsx("div", { onFocusCapture: () => {
|
|
1602
1691
|
focusedFilterFieldRef.current =
|
|
1603
1692
|
column.dataField;
|
|
1604
1693
|
saveFilterCache({
|
|
@@ -175,6 +175,18 @@ export interface DateFilterInstance {
|
|
|
175
175
|
/** Clear the filter */
|
|
176
176
|
clear: () => void;
|
|
177
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Wraps `getFilter` instances so they are callable: `fn()`, `fn('')`, `fn(null)` clear;
|
|
180
|
+
* `fn(value)` sets. Still exposes `.value`, `.setValue`, and `.clear` like TextFilterInstance.
|
|
181
|
+
*/
|
|
182
|
+
export declare function createCallableFilterHandle({ getValue, setValue, clear, }: {
|
|
183
|
+
getValue: () => any;
|
|
184
|
+
setValue: (value: any) => void;
|
|
185
|
+
clear: () => void;
|
|
186
|
+
}): ((v?: any) => void) & {
|
|
187
|
+
setValue: (value: any) => void;
|
|
188
|
+
clear: () => void;
|
|
189
|
+
};
|
|
178
190
|
/**
|
|
179
191
|
* Text filter - can be used as a component or factory function
|
|
180
192
|
*
|
|
@@ -335,21 +347,21 @@ export interface CustomFilterInstance<T = any> {
|
|
|
335
347
|
* })
|
|
336
348
|
*
|
|
337
349
|
* @example
|
|
338
|
-
* //
|
|
339
|
-
* //
|
|
350
|
+
* // With filterRenderer, mount the same factory component as `filter` so getFilter runs.
|
|
351
|
+
* // CustomFilter’s getFilter is not called if you only render a different component in filterRenderer.
|
|
352
|
+
* const PictureFilter = NumberFilter({
|
|
353
|
+
* placeholder: 'Picture',
|
|
354
|
+
* getFilter: (f) => {
|
|
355
|
+
* pictureFilterRef.current = f;
|
|
356
|
+
* },
|
|
357
|
+
* });
|
|
340
358
|
* {
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
* placeholder: 'Picture',
|
|
345
|
-
* getFilter: (filter) => {
|
|
346
|
-
* pictureFilterRef.current = filter;
|
|
347
|
-
* },
|
|
348
|
-
* }),
|
|
349
|
-
* filterRenderer: (onFilter, column) => (
|
|
350
|
-
* <NumberFilter onFilter={onFilter} column={column} />
|
|
359
|
+
* filter: PictureFilter,
|
|
360
|
+
* filterRenderer: (onFilter, column, {value, onClear}) => (
|
|
361
|
+
* <PictureFilter column={column} value={value} onChange={onFilter} />
|
|
351
362
|
* ),
|
|
352
363
|
* }
|
|
364
|
+
* // clearAllFilter: () => pictureFilterRef.current?.clear()
|
|
353
365
|
*
|
|
354
366
|
* @example
|
|
355
367
|
* // Custom range filter
|
|
@@ -10,6 +10,33 @@ const filterSelectClass = cn(s['leading-4'], s['p-1'], s['focus:outline-none'],
|
|
|
10
10
|
const comparatorSelectClass = cn(s['leading-4'], s['p-1'], s['focus:outline-none'], s['focus:ring'], s['shadow-sm'], s['text-xs'], s['font-normal'], s['border'], s['border-gray-300'], s['rounded-md'], s['text-black'], s['bg-white'], s['cursor-pointer'], s['w-12']);
|
|
11
11
|
const dateInputClass = cn(s['leading-4'], s['p-1'], s['focus:outline-none'], s['focus:ring'], s['shadow-sm'], s['text-xs'], s['font-normal'], s['border'], s['border-gray-300'], s['rounded-md'], s['text-black'], s['bg-white'], s['flex-1'], s['transition-all']);
|
|
12
12
|
const filterContainerClass = cn(s['flex'], s['flex-row'], s['gap-1'], s['items-center'], s['w-full']);
|
|
13
|
+
/**
|
|
14
|
+
* Wraps `getFilter` instances so they are callable: `fn()`, `fn('')`, `fn(null)` clear;
|
|
15
|
+
* `fn(value)` sets. Still exposes `.value`, `.setValue`, and `.clear` like TextFilterInstance.
|
|
16
|
+
*/
|
|
17
|
+
export function createCallableFilterHandle({ getValue, setValue, clear, }) {
|
|
18
|
+
const handle = Object.assign(function callFilter(v) {
|
|
19
|
+
if (arguments.length === 0 ||
|
|
20
|
+
v === '' ||
|
|
21
|
+
(typeof v === 'string' && v.trim() === '') ||
|
|
22
|
+
v == null) {
|
|
23
|
+
clear();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
setValue(v);
|
|
27
|
+
}, {
|
|
28
|
+
setValue,
|
|
29
|
+
clear,
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(handle, 'value', {
|
|
32
|
+
get() {
|
|
33
|
+
return getValue();
|
|
34
|
+
},
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
});
|
|
38
|
+
return handle;
|
|
39
|
+
}
|
|
13
40
|
/**
|
|
14
41
|
* Internal Text filter component with options support
|
|
15
42
|
*/
|
|
@@ -57,10 +84,8 @@ const TextFilterComponent = ({ column, value, onChange, onFilter: onFilterProp,
|
|
|
57
84
|
// Provide filter instance via getFilter callback - only on mount
|
|
58
85
|
useEffect(() => {
|
|
59
86
|
if (getFilter) {
|
|
60
|
-
getFilter({
|
|
61
|
-
|
|
62
|
-
return internalValueRef.current;
|
|
63
|
-
},
|
|
87
|
+
getFilter(createCallableFilterHandle({
|
|
88
|
+
getValue: () => internalValueRef.current,
|
|
64
89
|
setValue: (newValue) => {
|
|
65
90
|
setInternalValue(newValue);
|
|
66
91
|
onChangeRef.current(newValue || null);
|
|
@@ -71,7 +96,7 @@ const TextFilterComponent = ({ column, value, onChange, onFilter: onFilterProp,
|
|
|
71
96
|
onChangeRef.current(null);
|
|
72
97
|
onFilterRef.current?.('');
|
|
73
98
|
},
|
|
74
|
-
});
|
|
99
|
+
}));
|
|
75
100
|
}
|
|
76
101
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
77
102
|
}, [getFilter]);
|
|
@@ -178,16 +203,21 @@ const NumberFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
178
203
|
// Provide filter instance via getFilter callback - only on mount
|
|
179
204
|
useEffect(() => {
|
|
180
205
|
if (getFilter) {
|
|
181
|
-
getFilter({
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
:
|
|
186
|
-
|
|
206
|
+
getFilter(createCallableFilterHandle({
|
|
207
|
+
getValue: () => numberRef.current
|
|
208
|
+
? {
|
|
209
|
+
number: numberRef.current,
|
|
210
|
+
comparator: comparatorRef.current,
|
|
211
|
+
}
|
|
212
|
+
: null,
|
|
187
213
|
setValue: (newValue) => {
|
|
188
214
|
if (newValue !== null && newValue !== undefined) {
|
|
189
|
-
const num = typeof newValue === 'object'
|
|
190
|
-
|
|
215
|
+
const num = typeof newValue === 'object'
|
|
216
|
+
? newValue.number
|
|
217
|
+
: String(newValue);
|
|
218
|
+
const comp = typeof newValue === 'object'
|
|
219
|
+
? newValue.comparator
|
|
220
|
+
: comparatorRef.current;
|
|
191
221
|
setNumber(num);
|
|
192
222
|
setComparator(comp);
|
|
193
223
|
onChangeRef.current({ number: num, comparator: comp });
|
|
@@ -205,7 +235,7 @@ const NumberFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
205
235
|
onChangeRef.current(null);
|
|
206
236
|
onFilterRef.current?.(null);
|
|
207
237
|
},
|
|
208
|
-
});
|
|
238
|
+
}));
|
|
209
239
|
}
|
|
210
240
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
211
241
|
}, [getFilter]);
|
|
@@ -353,8 +383,8 @@ const DateFilterComponent = ({ column, value, onChange, onFilter: onFilterProp,
|
|
|
353
383
|
// Provide filter instance via getFilter callback - only on mount
|
|
354
384
|
useEffect(() => {
|
|
355
385
|
if (getFilter) {
|
|
356
|
-
getFilter({
|
|
357
|
-
|
|
386
|
+
getFilter(createCallableFilterHandle({
|
|
387
|
+
getValue: () => {
|
|
358
388
|
const { startDate: s, endDate: e, diffFlag: d, comparator: c, } = stateRef.current;
|
|
359
389
|
return s || e
|
|
360
390
|
? { startDate: s, endDate: e, diffFlag: d, comparator: c }
|
|
@@ -384,7 +414,7 @@ const DateFilterComponent = ({ column, value, onChange, onFilter: onFilterProp,
|
|
|
384
414
|
onChangeRef.current(null);
|
|
385
415
|
onFilterRef.current?.(null);
|
|
386
416
|
},
|
|
387
|
-
});
|
|
417
|
+
}));
|
|
388
418
|
}
|
|
389
419
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
390
420
|
}, [getFilter]);
|
|
@@ -479,10 +509,8 @@ const SelectFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
479
509
|
// Provide filter instance via getFilter callback - only on mount
|
|
480
510
|
useEffect(() => {
|
|
481
511
|
if (getFilter) {
|
|
482
|
-
getFilter({
|
|
483
|
-
|
|
484
|
-
return selectedValueRef.current || null;
|
|
485
|
-
},
|
|
512
|
+
getFilter(createCallableFilterHandle({
|
|
513
|
+
getValue: () => selectedValueRef.current || null,
|
|
486
514
|
setValue: (newValue) => {
|
|
487
515
|
setSelectedValue(newValue || '');
|
|
488
516
|
onChangeRef.current(newValue);
|
|
@@ -493,7 +521,7 @@ const SelectFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
493
521
|
onChangeRef.current(null);
|
|
494
522
|
onFilterRef.current?.(null);
|
|
495
523
|
},
|
|
496
|
-
});
|
|
524
|
+
}));
|
|
497
525
|
}
|
|
498
526
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
499
527
|
}, [getFilter]);
|
|
@@ -564,10 +592,8 @@ const CustomFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
564
592
|
// Provide filter instance via getFilter callback - only on mount
|
|
565
593
|
useEffect(() => {
|
|
566
594
|
if (getFilter) {
|
|
567
|
-
getFilter({
|
|
568
|
-
|
|
569
|
-
return filterValueRef.current;
|
|
570
|
-
},
|
|
595
|
+
getFilter(createCallableFilterHandle({
|
|
596
|
+
getValue: () => filterValueRef.current,
|
|
571
597
|
setValue: (newValue) => {
|
|
572
598
|
setFilterValue(newValue);
|
|
573
599
|
onChangeRef.current(newValue);
|
|
@@ -578,7 +604,7 @@ const CustomFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
578
604
|
onChangeRef.current(null);
|
|
579
605
|
onFilterRef.current?.(null);
|
|
580
606
|
},
|
|
581
|
-
});
|
|
607
|
+
}));
|
|
582
608
|
}
|
|
583
609
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
584
610
|
}, [getFilter]);
|
|
@@ -643,21 +669,21 @@ const CustomFilterComponent = ({ column, value, onChange, onFilter: onFilterProp
|
|
|
643
669
|
* })
|
|
644
670
|
*
|
|
645
671
|
* @example
|
|
646
|
-
* //
|
|
647
|
-
* //
|
|
672
|
+
* // With filterRenderer, mount the same factory component as `filter` so getFilter runs.
|
|
673
|
+
* // CustomFilter’s getFilter is not called if you only render a different component in filterRenderer.
|
|
674
|
+
* const PictureFilter = NumberFilter({
|
|
675
|
+
* placeholder: 'Picture',
|
|
676
|
+
* getFilter: (f) => {
|
|
677
|
+
* pictureFilterRef.current = f;
|
|
678
|
+
* },
|
|
679
|
+
* });
|
|
648
680
|
* {
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
* placeholder: 'Picture',
|
|
653
|
-
* getFilter: (filter) => {
|
|
654
|
-
* pictureFilterRef.current = filter;
|
|
655
|
-
* },
|
|
656
|
-
* }),
|
|
657
|
-
* filterRenderer: (onFilter, column) => (
|
|
658
|
-
* <NumberFilter onFilter={onFilter} column={column} />
|
|
681
|
+
* filter: PictureFilter,
|
|
682
|
+
* filterRenderer: (onFilter, column, {value, onClear}) => (
|
|
683
|
+
* <PictureFilter column={column} value={value} onChange={onFilter} />
|
|
659
684
|
* ),
|
|
660
685
|
* }
|
|
686
|
+
* // clearAllFilter: () => pictureFilterRef.current?.clear()
|
|
661
687
|
*
|
|
662
688
|
* @example
|
|
663
689
|
* // Custom range filter
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Table, default } from './Table';
|
|
2
2
|
export * from './types';
|
|
3
3
|
export { useSortState, useFilterState, usePaginationState, useRowSelection, useRowExpansion, useColumnVisibility, useTableDebounce, sortData, filterData, paginateData, getNestedValue, exportToCSV, exportToExcel, } from './hooks';
|
|
4
|
-
export { TextFilter, NumberFilter, DateFilter, SelectFilter, CustomFilter, getFilterComponent, } from './filters';
|
|
4
|
+
export { TextFilter, NumberFilter, DateFilter, SelectFilter, CustomFilter, getFilterComponent, createCallableFilterHandle, } from './filters';
|
|
5
5
|
export type { TextFilterOptions, TextFilterInstance, NumberFilterOptions, NumberFilterInstance, SelectFilterOptions, SelectFilterInstance, DateFilterOptions, DateFilterInstance, CustomFilterOptions, CustomFilterRenderProps, CustomFilterInstance, } from './filters';
|
|
6
6
|
export { useColumnResize, getColumnStyle, ResizeHandle, ResizeLine, ResizableHeaderCell, } from './columnResize';
|
|
7
7
|
export type { ColumnResizeConfig, UseColumnResizeReturn } from './columnResize';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Table, default } from './Table';
|
|
2
2
|
export * from './types';
|
|
3
3
|
export { useSortState, useFilterState, usePaginationState, useRowSelection, useRowExpansion, useColumnVisibility, useTableDebounce, sortData, filterData, paginateData, getNestedValue, exportToCSV, exportToExcel, } from './hooks';
|
|
4
|
-
export { TextFilter, NumberFilter, DateFilter, SelectFilter, CustomFilter, getFilterComponent, } from './filters';
|
|
4
|
+
export { TextFilter, NumberFilter, DateFilter, SelectFilter, CustomFilter, getFilterComponent, createCallableFilterHandle, } from './filters';
|
|
5
5
|
export { useColumnResize, getColumnStyle, ResizeHandle, ResizeLine, ResizableHeaderCell, } from './columnResize';
|
|
6
6
|
export { useColumnReorder, DragGhost, DropIndicator, DraggableHeader, ColumnReorderGhost, ColumnDropIndicator, getReorderableHeaderProps, } from './columnReorder';
|
|
@@ -155,6 +155,16 @@ export interface FieldConfig<T = any> {
|
|
|
155
155
|
/** Field type configuration for dynamic rendering */
|
|
156
156
|
export type FieldTypeConfig<T = any> = Record<string, FieldConfig<T>>;
|
|
157
157
|
/** Column definition */
|
|
158
|
+
/**
|
|
159
|
+
* Passed as the third argument to {@link TableColumn.filterRenderer} so custom
|
|
160
|
+
* filters stay controlled with table state (including clear-all).
|
|
161
|
+
*/
|
|
162
|
+
export interface TableFilterRendererContext {
|
|
163
|
+
/** Current value for this column from the table filter state */
|
|
164
|
+
value: any;
|
|
165
|
+
/** Clear this column’s filter only */
|
|
166
|
+
onClear: () => void;
|
|
167
|
+
}
|
|
158
168
|
export interface TableColumn<T = any> {
|
|
159
169
|
/** Unique field key */
|
|
160
170
|
dataField: string;
|
|
@@ -193,8 +203,8 @@ export interface TableColumn<T = any> {
|
|
|
193
203
|
}>;
|
|
194
204
|
/** Custom filter component (alias for filter when using component) */
|
|
195
205
|
filterComponent?: React.ComponentType<TableFilterProps>;
|
|
196
|
-
/** Custom filter renderer */
|
|
197
|
-
filterRenderer?: (onFilter: (value: any) => void, column: TableColumn<T
|
|
206
|
+
/** Custom filter renderer (third arg is always passed when provided by Table; optional in signature for backward compatibility) */
|
|
207
|
+
filterRenderer?: (onFilter: (value: any) => void, column: TableColumn<T>, context?: TableFilterRendererContext) => React.ReactNode;
|
|
198
208
|
/** Filter placeholder */
|
|
199
209
|
filterPlaceholder?: string;
|
|
200
210
|
/** Whether column is editable - boolean or function returning boolean/custom editor */
|
|
@@ -75,4 +75,11 @@
|
|
|
75
75
|
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
76
76
|
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
77
77
|
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
78
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
79
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
80
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
81
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
82
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
83
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
84
|
+
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/
|
|
78
85
|
/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/.\!filter,.backdrop-blur-sm,.blur,.ring,.ring-2,.shadow,.shadow-inner,body{font-family:Arima Regular;font-size:14px}.dark\:bg-black:is(.dark *),.dark\:border-gray-600:is(.dark *){--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/fieldset,legend{padding:0}.container{width:100%}@media (min-width:0px){.container{max-width:0}}@media (min-width:20rem){.container{max-width:20rem}}@media (min-width:23.4375rem){.container{max-width:23.4375rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:90rem){.container{max-width:90rem}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.form-input,.form-input::-webkit-datetime-edit,.form-input::-webkit-datetime-edit-day-field,.form-input::-webkit-datetime-edit-hour-field,.form-input::-webkit-datetime-edit-meridiem-field,.form-input::-webkit-datetime-edit-millisecond-field,.form-input::-webkit-datetime-edit-minute-field,.form-input::-webkit-datetime-edit-month-field,.form-input::-webkit-datetime-edit-second-field,.form-input::placeholder,.form-input:focus,.form-multiselect,.form-multiselect:focus,.form-select,.form-select:focus,table{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}table:is(.dark *){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}table tr:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}select:is(.dark *){--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.\!visible{visibility:visible!important}.top-1\/2{top:50%}.-translate-x-1\/2,.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity,1))}.divide-teal-50>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(240 253 250/var(--tw-divide-opacity,1))}.bg-purple-900\/50{background-color:#581c8780}.p-0\.5{padding:.125rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.\!filter,.blur,.ring,.ring-2,.shadow,.shadow-inner,.backdrop-blur-sm,body{font-family:Arima Regular;font-size:14px}.hover\:bg-white\/20:hover{background-color:#fff3}.dark\:border-gray-600:is(.dark *),.dark\:bg-black:is(.dark *){--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.dark\:bg-boxdark:is(.dark *){--tw-bg-opacity:1;background-color:rgb(36 48 63/var(--tw-bg-opacity,1))}.dark\:bg-gray-700:is(.dark *){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.dark\:text-black:is(.dark *){--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.dark\:text-gray-100:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.dark\:text-gray-400:is(.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.dark\:text-gray-500:is(.dark *){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.dark\:text-white:is(.dark *){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.dark\:placeholder-gray-400:is(.dark *)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity,1))}.dark\:ring-offset-gray-800:is(.dark *){--tw-ring-offset-color:#1f2937}.dark\:hover\:bg-blue-900:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(30 58 138/var(--tw-bg-opacity,1))}.dark\:hover\:bg-gray-600:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:focus\:ring-blue-600:focus:is(.dark *){--tw-ring-opacity:1;--tw-ring-color:rgb(37 99 235/var(--tw-ring-opacity,1))}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{-webkit-text-size-adjust:100%;font-feature-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-variation-settings:normal;line-height:1.5;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]:where(:not([hidden=until-found])){display:none}@font-face{font-family:ArimaRegular;src:url(library/assets/fonts/arima/arima-regular.ttf)}.container{width:100%}@media (min-width:0px){.container{max-width:0}}@media (min-width:20rem){.container{max-width:20rem}}@media (min-width:23.4375rem){.container{max-width:23.4375rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:90rem){.container{max-width:90rem}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.form-input,.form-multiselect,.form-select,.form-input:focus,.form-multiselect:focus,.form-select:focus,.form-input::placeholder,.form-input::-webkit-datetime-edit,.form-input::-webkit-datetime-edit-day-field,.form-input::-webkit-datetime-edit-hour-field,.form-input::-webkit-datetime-edit-meridiem-field,.form-input::-webkit-datetime-edit-millisecond-field,.form-input::-webkit-datetime-edit-minute-field,.form-input::-webkit-datetime-edit-month-field,.form-input::-webkit-datetime-edit-second-field,table{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}table:is(.dark *){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}table tr:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}select:is(.dark *){--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.\!visible{visibility:visible!important}.top-1\/2{top:50%}.flex-grow,.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}@keyframes pulse{50%{opacity:.5}}@keyframes spin{to{transform:rotate(1turn)}}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity,1))}.divide-teal-50>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(240 253 250/var(--tw-divide-opacity,1))}.bg-purple-900\/50{background-color:#581c8780}.p-0\.5{padding:.125rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.shadow,.shadow-inner,.shadow-md,.ring,.ring-2,.blur,.\!filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.backdrop-blur-sm,body{font-family:Arima Regular;font-size:14px}.menu ul{list-style:none;margin:0;padding:0}.menu li{border-bottom:1px solid #ddd;padding:10px}.menu li:last-child{border-bottom:none}.hover\:bg-white\/20:hover{background-color:#fff3}.focus\:ring-0:focus,.dark\:border-gray-600:is(.dark *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.dark\:bg-black:is(.dark *){--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.dark\:bg-boxdark:is(.dark *){--tw-bg-opacity:1;background-color:rgb(36 48 63/var(--tw-bg-opacity,1))}.dark\:bg-gray-700:is(.dark *){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.dark\:text-black:is(.dark *){--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.dark\:text-gray-100:is(.dark *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity,1))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.dark\:text-gray-400:is(.dark *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.dark\:text-gray-500:is(.dark *){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.dark\:text-white:is(.dark *){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.dark\:placeholder-gray-400:is(.dark *)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity,1))}.dark\:ring-offset-gray-800:is(.dark *){--tw-ring-offset-color:#1f2937}.dark\:hover\:bg-blue-900:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(30 58 138/var(--tw-bg-opacity,1))}.dark\:hover\:bg-gray-600:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:focus\:ring-blue-600:focus:is(.dark *){--tw-ring-opacity:1;--tw-ring-color:rgb(37 99 235/var(--tw-ring-opacity,1))}@media (min-width:0px) and (max-width:767px){}
|