@comitor/ui 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/components/composite/confirm-dialog.js +56 -35
- package/dist/components/composite/confirm-dialog.js.map +1 -1
- package/dist/components/composite/search-filter-bar-constants.d.ts +3 -0
- package/dist/components/composite/search-filter-bar-constants.js.map +1 -1
- package/dist/components/composite/table-pagination-constants.d.ts +3 -1
- package/dist/components/composite/table-pagination-constants.js.map +1 -1
- package/dist/components/composite/table-pagination.js +10 -2
- package/dist/components/composite/table-pagination.js.map +1 -1
- package/dist/components/composite/text-utils.d.ts +4 -23
- package/dist/components/composite/text-utils.js +1 -11
- package/dist/components/composite/text-utils.js.map +1 -1
- package/dist/components/composite/toast.d.ts +2 -1
- package/dist/components/composite/toast.js +3 -9
- package/dist/components/composite/toast.js.map +1 -1
- package/dist/components/ui/action-bar.js +45 -1
- package/dist/components/ui/action-bar.js.map +1 -1
- package/dist/components/ui/banner.d.ts +8 -0
- package/dist/components/ui/banner.js +149 -35
- package/dist/components/ui/banner.js.map +1 -1
- package/dist/components/ui/circular-progress.js +10 -2
- package/dist/components/ui/circular-progress.js.map +1 -1
- package/dist/components/ui/kanban.js +9 -3
- package/dist/components/ui/kanban.js.map +1 -1
- package/dist/components/ui/key-value.js +70 -76
- package/dist/components/ui/key-value.js.map +1 -1
- package/dist/components/ui/mask-input-constants.d.ts +34 -2
- package/dist/components/ui/mask-input-constants.js +87 -76
- package/dist/components/ui/mask-input-constants.js.map +1 -1
- package/dist/components/ui/mask-input.d.ts +6 -5
- package/dist/components/ui/mask-input.js +23 -21
- package/dist/components/ui/mask-input.js.map +1 -1
- package/dist/components/ui/mention.d.ts +14 -2
- package/dist/components/ui/mention.js +33 -6
- package/dist/components/ui/mention.js.map +1 -1
- package/dist/components/ui/phone-input.d.ts +18 -8
- package/dist/components/ui/phone-input.js +125 -35
- package/dist/components/ui/phone-input.js.map +1 -1
- package/dist/components/ui/rating.js +4 -2
- package/dist/components/ui/rating.js.map +1 -1
- package/dist/components/ui/scroll-spy.js +46 -31
- package/dist/components/ui/scroll-spy.js.map +1 -1
- package/dist/components/ui/slider.d.ts +1 -1
- package/dist/components/ui/slider.js +15 -1
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/sonner.js +2 -0
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/components/ui/stepper.js +26 -3
- package/dist/components/ui/stepper.js.map +1 -1
- package/dist/components/ui/time-picker.d.ts +24 -4
- package/dist/components/ui/time-picker.js +425 -162
- package/dist/components/ui/time-picker.js.map +1 -1
- package/dist/components/ui/timeline.js +45 -9
- package/dist/components/ui/timeline.js.map +1 -1
- package/dist/components/ui/toggle-group.js +12 -1
- package/dist/components/ui/toggle-group.js.map +1 -1
- package/dist/components/ui/tour.js +3 -2
- package/dist/components/ui/tour.js.map +1 -1
- package/dist/data-grid/data-grid-cell-variants.js +4 -4
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
- package/dist/data-grid/data-grid-cell-wrapper.d.ts +1 -1
- package/dist/data-grid/data-grid-cell-wrapper.js +6 -0
- package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -1
- package/dist/data-grid/data-grid-row.js +1 -1
- package/dist/data-grid/data-grid-row.js.map +1 -1
- package/dist/data-grid/data-grid-select-column.js +6 -2
- package/dist/data-grid/data-grid-select-column.js.map +1 -1
- package/dist/data-grid/data-grid-skeleton.d.ts +5 -0
- package/dist/data-grid/data-grid-skeleton.js +1 -4
- package/dist/data-grid/data-grid-skeleton.js.map +1 -1
- package/dist/data-grid/data-grid.d.ts +1 -1
- package/dist/data-grid/data-grid.js +3 -2
- package/dist/data-grid/data-grid.js.map +1 -1
- package/dist/data-grid/filters.js +3 -2
- package/dist/data-grid/filters.js.map +1 -1
- package/dist/data-grid/types.d.ts +7 -0
- package/dist/data-grid/use-data-grid.d.ts +1 -0
- package/dist/data-grid/use-data-grid.js +70 -24
- package/dist/data-grid/use-data-grid.js.map +1 -1
- package/dist/data-grid/utils.d.ts +7 -0
- package/dist/data-grid/utils.js +3 -1
- package/dist/data-grid/utils.js.map +1 -1
- package/dist/i18n/locale-provider.d.ts +18 -0
- package/dist/i18n/locale-provider.js.map +1 -1
- package/dist/i18n/namespaces/rating.js +2 -1
- package/dist/i18n/namespaces/rating.js.map +1 -1
- package/dist/i18n/namespaces/search-filter-bar.js +8 -6
- package/dist/i18n/namespaces/search-filter-bar.js.map +1 -1
- package/dist/i18n/namespaces/shell.d.ts +4 -0
- package/dist/i18n/namespaces/shell.js +1 -1
- package/dist/i18n/namespaces/shell.js.map +1 -1
- package/dist/i18n/namespaces/table-pagination.js +6 -4
- package/dist/i18n/namespaces/table-pagination.js.map +1 -1
- package/dist/i18n/namespaces/toast.d.ts +3 -2
- package/dist/i18n/namespaces/toast.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/lib/collect-item-elements.d.ts +47 -0
- package/dist/lib/collect-item-elements.js +22 -0
- package/dist/lib/collect-item-elements.js.map +1 -0
- package/dist/lib/text-search.d.ts +32 -0
- package/dist/lib/text-search.js +17 -0
- package/dist/lib/text-search.js.map +1 -0
- package/dist/lib/toast-language.d.ts +8 -0
- package/dist/lib/toast-language.js +19 -0
- package/dist/lib/toast-language.js.map +1 -0
- package/dist/shell/app-shell.d.ts +1 -0
- package/dist/shell/index.d.ts +2 -1
- package/dist/shell/shell-context.d.ts +1 -0
- package/dist/shell/utils.d.ts +2 -1
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "@tanstack/react-table";
|
|
9
9
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
10
10
|
import * as React from "react";
|
|
11
|
+
import { normalizeVi } from "../lib/text-search.js";
|
|
11
12
|
import { useAsRef } from "../lib/use-as-ref.js";
|
|
12
13
|
import { useIsomorphicLayoutEffect } from "../lib/use-isomorphic-layout-effect.js";
|
|
13
14
|
import { useLazyRef } from "../lib/use-lazy-ref.js";
|
|
@@ -43,6 +44,34 @@ const AUTO_SCROLL_SPEED_RAMP_ZONE = AUTO_SCROLL_EDGE_ZONE * 3;
|
|
|
43
44
|
const AUTO_SCROLL_MIN_SPEED = 8;
|
|
44
45
|
const AUTO_SCROLL_MAX_SPEED = 40;
|
|
45
46
|
const AUTO_SCROLL_SELECTION_THROTTLE_MS = 32;
|
|
47
|
+
function getIsColumnReadOnly(table, columnId) {
|
|
48
|
+
return table?.getColumn(columnId)?.columnDef.meta?.readOnly === true;
|
|
49
|
+
}
|
|
50
|
+
function getCellDisplayText(value, cellOpts) {
|
|
51
|
+
if (cellOpts?.variant === "select") {
|
|
52
|
+
return cellOpts.options.find((option) => option.value === value)?.label ?? String(value ?? "");
|
|
53
|
+
}
|
|
54
|
+
if (cellOpts?.variant === "multi-select" && Array.isArray(value)) {
|
|
55
|
+
return value.map((item) => cellOpts.options.find((option) => option.value === item)?.label ?? String(item)).join(", ");
|
|
56
|
+
}
|
|
57
|
+
return String(value ?? "");
|
|
58
|
+
}
|
|
59
|
+
function withLocaleSorting(column, collator) {
|
|
60
|
+
if (column.sortingFn !== void 0) return column;
|
|
61
|
+
if (!("accessorKey" in column) && !("accessorFn" in column)) return column;
|
|
62
|
+
const cellOpts = column.meta?.cell;
|
|
63
|
+
const variant = cellOpts?.variant ?? "short-text";
|
|
64
|
+
if (variant !== "short-text" && variant !== "long-text" && variant !== "url" && variant !== "select") {
|
|
65
|
+
return column;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
...column,
|
|
69
|
+
sortingFn: (rowA, rowB, columnId) => collator.compare(
|
|
70
|
+
getCellDisplayText(rowA.getValue(columnId), cellOpts),
|
|
71
|
+
getCellDisplayText(rowB.getValue(columnId), cellOpts)
|
|
72
|
+
)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
46
75
|
const DOMAIN_REGEX = /^[\w.-]+\.[a-z]{2,}(\/\S*)?$/i;
|
|
47
76
|
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}.*)?$/;
|
|
48
77
|
const TRUTHY_BOOLEANS = /* @__PURE__ */ new Set(["true", "1", "yes", "checked"]);
|
|
@@ -62,10 +91,26 @@ function useDataGrid({
|
|
|
62
91
|
...props
|
|
63
92
|
}) {
|
|
64
93
|
const { messages: msg, dateLocale } = useResolvedDataGridLocale(locale);
|
|
94
|
+
const collator = React.useMemo(() => {
|
|
95
|
+
try {
|
|
96
|
+
return new Intl.Collator(dateLocale.code, { numeric: true });
|
|
97
|
+
} catch {
|
|
98
|
+
return new Intl.Collator(void 0, { numeric: true });
|
|
99
|
+
}
|
|
100
|
+
}, [dateLocale]);
|
|
101
|
+
const tableColumns = React.useMemo(
|
|
102
|
+
() => columns.map((column) => withLocaleSorting(column, collator)),
|
|
103
|
+
[columns, collator]
|
|
104
|
+
);
|
|
65
105
|
const msgRef = useAsRef(msg);
|
|
66
106
|
const dateLocaleRef = useAsRef(dateLocale);
|
|
67
107
|
const dir = useDirection(dirProp);
|
|
68
108
|
const dataGridRef = React.useRef(null);
|
|
109
|
+
const [dataGridElement, setDataGridElement] = React.useState(null);
|
|
110
|
+
const dataGridElementRef = React.useCallback((node) => {
|
|
111
|
+
dataGridRef.current = node;
|
|
112
|
+
setDataGridElement(node);
|
|
113
|
+
}, []);
|
|
69
114
|
const tableRef = React.useRef(null);
|
|
70
115
|
const rowVirtualizerRef = React.useRef(null);
|
|
71
116
|
const headerRef = React.useRef(null);
|
|
@@ -240,7 +285,9 @@ function useDataGrid({
|
|
|
240
285
|
const onDataUpdate = React.useCallback(
|
|
241
286
|
(updates) => {
|
|
242
287
|
if (propsRef.current.readOnly) return;
|
|
243
|
-
const updateArray = Array.isArray(updates) ? updates : [updates]
|
|
288
|
+
const updateArray = (Array.isArray(updates) ? updates : [updates]).filter(
|
|
289
|
+
(update) => !getIsColumnReadOnly(tableRef.current, update.columnId)
|
|
290
|
+
);
|
|
244
291
|
if (updateArray.length === 0) return;
|
|
245
292
|
const currentTable = tableRef.current;
|
|
246
293
|
const currentData = propsRef.current.data;
|
|
@@ -559,7 +606,7 @@ function useDataGrid({
|
|
|
559
606
|
}
|
|
560
607
|
}
|
|
561
608
|
const updates = [];
|
|
562
|
-
const
|
|
609
|
+
const tableColumns2 = currentTable?.getAllColumns() ?? [];
|
|
563
610
|
let cellsUpdated = 0;
|
|
564
611
|
let endRowIndex = startRowIndex;
|
|
565
612
|
let endColIndex = startColIndex;
|
|
@@ -567,7 +614,7 @@ function useDataGrid({
|
|
|
567
614
|
const updatedRows = updatedTable?.getRowModel().rows;
|
|
568
615
|
const currentRowCount = updatedRows?.length ?? 0;
|
|
569
616
|
let cellsSkipped = 0;
|
|
570
|
-
const columnMap = new Map(
|
|
617
|
+
const columnMap = new Map(tableColumns2.map((c) => [c.id, c]));
|
|
571
618
|
for (let pasteRowIdx = 0; pasteRowIdx < pastedData.length; pasteRowIdx++) {
|
|
572
619
|
const pasteRow = pastedData[pasteRowIdx];
|
|
573
620
|
if (!pasteRow) continue;
|
|
@@ -748,7 +795,7 @@ function useDataGrid({
|
|
|
748
795
|
}
|
|
749
796
|
const allUpdates = [...updates];
|
|
750
797
|
if (currentState.cutCells.size > 0) {
|
|
751
|
-
const columnById = new Map(
|
|
798
|
+
const columnById = new Map(tableColumns2.map((c) => [c.id, c]));
|
|
752
799
|
for (const cellKey of currentState.cutCells) {
|
|
753
800
|
const { rowIndex, columnId } = parseCellKey(cellKey);
|
|
754
801
|
const column = columnById.get(columnId);
|
|
@@ -1052,7 +1099,7 @@ function useDataGrid({
|
|
|
1052
1099
|
);
|
|
1053
1100
|
const onCellEditingStart = React.useCallback(
|
|
1054
1101
|
(rowIndex, columnId) => {
|
|
1055
|
-
if (propsRef.current.readOnly) return;
|
|
1102
|
+
if (propsRef.current.readOnly || getIsColumnReadOnly(tableRef.current, columnId)) return;
|
|
1056
1103
|
store.batch(() => {
|
|
1057
1104
|
store.setState("focusedCell", { rowIndex, columnId });
|
|
1058
1105
|
store.setState("editingCell", { rowIndex, columnId });
|
|
@@ -1127,7 +1174,7 @@ function useDataGrid({
|
|
|
1127
1174
|
const matches = [];
|
|
1128
1175
|
const currentTable = tableRef.current;
|
|
1129
1176
|
const rows = currentTable?.getRowModel().rows ?? [];
|
|
1130
|
-
const
|
|
1177
|
+
const normalizedQuery = normalizeVi(query);
|
|
1131
1178
|
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
1132
1179
|
const row = rows[rowIndex];
|
|
1133
1180
|
if (!row) continue;
|
|
@@ -1135,9 +1182,8 @@ function useDataGrid({
|
|
|
1135
1182
|
for (const columnId of columnIds) {
|
|
1136
1183
|
const cell = cellById.get(columnId);
|
|
1137
1184
|
if (!cell) continue;
|
|
1138
|
-
const
|
|
1139
|
-
|
|
1140
|
-
if (stringValue.includes(lowerQuery)) {
|
|
1185
|
+
const text = getCellDisplayText(cell.getValue(), cell.column.columnDef.meta?.cell);
|
|
1186
|
+
if (normalizeVi(text).includes(normalizedQuery)) {
|
|
1141
1187
|
matches.push({ rowIndex, columnId });
|
|
1142
1188
|
}
|
|
1143
1189
|
}
|
|
@@ -1678,7 +1724,7 @@ function useDataGrid({
|
|
|
1678
1724
|
return {
|
|
1679
1725
|
...propsRef.current,
|
|
1680
1726
|
data,
|
|
1681
|
-
columns,
|
|
1727
|
+
columns: tableColumns,
|
|
1682
1728
|
defaultColumn,
|
|
1683
1729
|
initialState: propsRef.current.initialState,
|
|
1684
1730
|
state: tableState,
|
|
@@ -1695,7 +1741,7 @@ function useDataGrid({
|
|
|
1695
1741
|
}, [
|
|
1696
1742
|
propsRef,
|
|
1697
1743
|
data,
|
|
1698
|
-
|
|
1744
|
+
tableColumns,
|
|
1699
1745
|
defaultColumn,
|
|
1700
1746
|
tableState,
|
|
1701
1747
|
dir,
|
|
@@ -1919,8 +1965,8 @@ function useDataGrid({
|
|
|
1919
1965
|
event.preventDefault();
|
|
1920
1966
|
const updates = [];
|
|
1921
1967
|
const currentTable = tableRef.current;
|
|
1922
|
-
const
|
|
1923
|
-
const columnById = new Map(
|
|
1968
|
+
const tableColumns2 = currentTable?.getAllColumns() ?? [];
|
|
1969
|
+
const columnById = new Map(tableColumns2.map((c) => [c.id, c]));
|
|
1924
1970
|
for (const cellKey of cellsToClear) {
|
|
1925
1971
|
const { rowIndex, columnId } = parseCellKey(cellKey);
|
|
1926
1972
|
const column = columnById.get(columnId);
|
|
@@ -2258,15 +2304,13 @@ function useDataGrid({
|
|
|
2258
2304
|
onNavigateToPrevMatch
|
|
2259
2305
|
]);
|
|
2260
2306
|
React.useEffect(() => {
|
|
2261
|
-
const dataGridElement = dataGridRef.current;
|
|
2262
2307
|
if (!dataGridElement) return;
|
|
2263
2308
|
dataGridElement.addEventListener("keydown", onDataGridKeyDown);
|
|
2264
2309
|
return () => {
|
|
2265
2310
|
dataGridElement.removeEventListener("keydown", onDataGridKeyDown);
|
|
2266
2311
|
};
|
|
2267
|
-
}, [onDataGridKeyDown]);
|
|
2312
|
+
}, [dataGridElement, onDataGridKeyDown]);
|
|
2268
2313
|
React.useEffect(() => {
|
|
2269
|
-
const dataGridElement = dataGridRef.current;
|
|
2270
2314
|
if (!dataGridElement) return;
|
|
2271
2315
|
function onPaste(event) {
|
|
2272
2316
|
if (!propsRef.current.enablePaste || propsRef.current.readOnly) return;
|
|
@@ -2281,18 +2325,18 @@ function useDataGrid({
|
|
|
2281
2325
|
return () => {
|
|
2282
2326
|
dataGridElement.removeEventListener("paste", onPaste);
|
|
2283
2327
|
};
|
|
2284
|
-
}, [propsRef, store, onCellsPaste]);
|
|
2328
|
+
}, [dataGridElement, propsRef, store, onCellsPaste]);
|
|
2285
2329
|
React.useEffect(() => {
|
|
2286
2330
|
function onGlobalKeyDown(event) {
|
|
2287
|
-
const
|
|
2288
|
-
if (!
|
|
2331
|
+
const dataGridElement2 = dataGridRef.current;
|
|
2332
|
+
if (!dataGridElement2) return;
|
|
2289
2333
|
const target = event.target;
|
|
2290
2334
|
if (!(target instanceof HTMLElement)) return;
|
|
2291
2335
|
const { key, ctrlKey, metaKey, shiftKey } = event;
|
|
2292
2336
|
const isCommandPressed = ctrlKey || metaKey;
|
|
2293
2337
|
if (propsRef.current.enableSearch && isCommandPressed && !shiftKey && key === SEARCH_SHORTCUT_KEY) {
|
|
2294
2338
|
const isInInput = target.tagName === "INPUT" || target.tagName === "TEXTAREA";
|
|
2295
|
-
const isInDataGrid2 =
|
|
2339
|
+
const isInDataGrid2 = dataGridElement2.contains(target);
|
|
2296
2340
|
const isInSearchInput = target.closest('[role="search"]') !== null;
|
|
2297
2341
|
if (isInDataGrid2 || isInSearchInput || !isInInput) {
|
|
2298
2342
|
event.preventDefault();
|
|
@@ -2301,13 +2345,13 @@ function useDataGrid({
|
|
|
2301
2345
|
onSearchOpenChange(nextSearchOpen);
|
|
2302
2346
|
if (nextSearchOpen && !isInDataGrid2 && !isInSearchInput) {
|
|
2303
2347
|
requestAnimationFrame(() => {
|
|
2304
|
-
|
|
2348
|
+
dataGridElement2.focus();
|
|
2305
2349
|
});
|
|
2306
2350
|
}
|
|
2307
2351
|
return;
|
|
2308
2352
|
}
|
|
2309
2353
|
}
|
|
2310
|
-
const isInDataGrid =
|
|
2354
|
+
const isInDataGrid = dataGridElement2.contains(target);
|
|
2311
2355
|
if (!isInDataGrid) return;
|
|
2312
2356
|
if (key === "Escape") {
|
|
2313
2357
|
const currentState = store.getState();
|
|
@@ -2347,7 +2391,7 @@ function useDataGrid({
|
|
|
2347
2391
|
}
|
|
2348
2392
|
}, [store, propsRef, data, columns, navigableColumnIds, focusCell]);
|
|
2349
2393
|
React.useEffect(() => {
|
|
2350
|
-
const container =
|
|
2394
|
+
const container = dataGridElement;
|
|
2351
2395
|
if (!container) return;
|
|
2352
2396
|
function onFocusOut(event) {
|
|
2353
2397
|
if (focusGuardRef.current) return;
|
|
@@ -2376,7 +2420,7 @@ function useDataGrid({
|
|
|
2376
2420
|
return () => {
|
|
2377
2421
|
container.removeEventListener("focusout", onFocusOut);
|
|
2378
2422
|
};
|
|
2379
|
-
}, [store]);
|
|
2423
|
+
}, [dataGridElement, store]);
|
|
2380
2424
|
React.useEffect(() => {
|
|
2381
2425
|
function onOutsideClick(event) {
|
|
2382
2426
|
if (event.button === 2) {
|
|
@@ -2644,6 +2688,7 @@ function useDataGrid({
|
|
|
2644
2688
|
return React.useMemo(
|
|
2645
2689
|
() => ({
|
|
2646
2690
|
dataGridRef,
|
|
2691
|
+
dataGridElementRef,
|
|
2647
2692
|
headerRef,
|
|
2648
2693
|
rowMapRef,
|
|
2649
2694
|
footerRef,
|
|
@@ -2670,6 +2715,7 @@ function useDataGrid({
|
|
|
2670
2715
|
}),
|
|
2671
2716
|
[
|
|
2672
2717
|
hasRowAdd,
|
|
2718
|
+
dataGridElementRef,
|
|
2673
2719
|
dir,
|
|
2674
2720
|
table,
|
|
2675
2721
|
tableMeta,
|