@comitor/ui 3.0.1 → 3.2.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.
Files changed (89) hide show
  1. package/dist/components/composite/avatar-group.d.ts +10 -1
  2. package/dist/components/composite/avatar-group.js +37 -14
  3. package/dist/components/composite/avatar-group.js.map +1 -1
  4. package/dist/components/composite/confirm-dialog.js +56 -35
  5. package/dist/components/composite/confirm-dialog.js.map +1 -1
  6. package/dist/components/composite/search-filter-bar-constants.d.ts +3 -0
  7. package/dist/components/composite/search-filter-bar-constants.js.map +1 -1
  8. package/dist/components/composite/status-config.d.ts +41 -1
  9. package/dist/components/composite/status-config.js +6 -0
  10. package/dist/components/composite/status-config.js.map +1 -1
  11. package/dist/components/composite/status-pill.d.ts +4 -1
  12. package/dist/components/composite/status-pill.js +1 -1
  13. package/dist/components/composite/status-pill.js.map +1 -1
  14. package/dist/components/composite/table-pagination-constants.d.ts +3 -1
  15. package/dist/components/composite/table-pagination-constants.js.map +1 -1
  16. package/dist/components/composite/table-pagination.js +10 -2
  17. package/dist/components/composite/table-pagination.js.map +1 -1
  18. package/dist/components/composite/text-utils.d.ts +4 -23
  19. package/dist/components/composite/text-utils.js +1 -11
  20. package/dist/components/composite/text-utils.js.map +1 -1
  21. package/dist/components/ui/banner.d.ts +8 -0
  22. package/dist/components/ui/banner.js +149 -35
  23. package/dist/components/ui/banner.js.map +1 -1
  24. package/dist/components/ui/mask-input-constants.d.ts +34 -2
  25. package/dist/components/ui/mask-input-constants.js +56 -5
  26. package/dist/components/ui/mask-input-constants.js.map +1 -1
  27. package/dist/components/ui/mask-input.d.ts +6 -5
  28. package/dist/components/ui/mask-input.js +5 -1
  29. package/dist/components/ui/mask-input.js.map +1 -1
  30. package/dist/components/ui/mention.d.ts +14 -2
  31. package/dist/components/ui/mention.js +33 -6
  32. package/dist/components/ui/mention.js.map +1 -1
  33. package/dist/components/ui/phone-input.d.ts +18 -8
  34. package/dist/components/ui/phone-input.js +120 -33
  35. package/dist/components/ui/phone-input.js.map +1 -1
  36. package/dist/components/ui/scroll-spy.js +46 -31
  37. package/dist/components/ui/scroll-spy.js.map +1 -1
  38. package/dist/components/ui/stepper.js +26 -3
  39. package/dist/components/ui/stepper.js.map +1 -1
  40. package/dist/components/ui/time-picker.d.ts +24 -4
  41. package/dist/components/ui/time-picker.js +425 -162
  42. package/dist/components/ui/time-picker.js.map +1 -1
  43. package/dist/components/ui/timeline.js +45 -9
  44. package/dist/components/ui/timeline.js.map +1 -1
  45. package/dist/data-grid/data-grid-cell-variants.js +27 -9
  46. package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
  47. package/dist/data-grid/data-grid-cell-wrapper.d.ts +1 -1
  48. package/dist/data-grid/data-grid-cell-wrapper.js +6 -0
  49. package/dist/data-grid/data-grid-cell-wrapper.js.map +1 -1
  50. package/dist/data-grid/data-grid-row.js +1 -1
  51. package/dist/data-grid/data-grid-row.js.map +1 -1
  52. package/dist/data-grid/data-grid-select-column.js +6 -2
  53. package/dist/data-grid/data-grid-select-column.js.map +1 -1
  54. package/dist/data-grid/data-grid-skeleton.d.ts +5 -0
  55. package/dist/data-grid/data-grid-skeleton.js +1 -4
  56. package/dist/data-grid/data-grid-skeleton.js.map +1 -1
  57. package/dist/data-grid/data-grid.d.ts +1 -1
  58. package/dist/data-grid/data-grid.js +3 -2
  59. package/dist/data-grid/data-grid.js.map +1 -1
  60. package/dist/data-grid/filters.js +3 -2
  61. package/dist/data-grid/filters.js.map +1 -1
  62. package/dist/data-grid/types.d.ts +23 -0
  63. package/dist/data-grid/use-data-grid.d.ts +1 -0
  64. package/dist/data-grid/use-data-grid.js +70 -24
  65. package/dist/data-grid/use-data-grid.js.map +1 -1
  66. package/dist/data-grid/utils.d.ts +7 -0
  67. package/dist/data-grid/utils.js +3 -1
  68. package/dist/data-grid/utils.js.map +1 -1
  69. package/dist/i18n/namespaces/search-filter-bar.js +8 -6
  70. package/dist/i18n/namespaces/search-filter-bar.js.map +1 -1
  71. package/dist/i18n/namespaces/table-pagination.js +6 -4
  72. package/dist/i18n/namespaces/table-pagination.js.map +1 -1
  73. package/dist/index.d.ts +2 -1
  74. package/dist/lib/collect-item-elements.d.ts +47 -0
  75. package/dist/lib/collect-item-elements.js +22 -0
  76. package/dist/lib/collect-item-elements.js.map +1 -0
  77. package/dist/lib/text-search.d.ts +32 -0
  78. package/dist/lib/text-search.js +17 -0
  79. package/dist/lib/text-search.js.map +1 -0
  80. package/dist/shell/app-shell.d.ts +1 -0
  81. package/dist/shell/display-axis-provider.d.ts +1 -1
  82. package/dist/shell/index.d.ts +2 -1
  83. package/dist/shell/shell-context.d.ts +1 -0
  84. package/dist/shell/utils.d.ts +2 -1
  85. package/dist/tokens.d.ts +43 -11
  86. package/dist/tokens.js +36 -9
  87. package/dist/tokens.js.map +1 -1
  88. package/package.json +1 -1
  89. package/styles.css +73 -13
@@ -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 tableColumns = currentTable?.getAllColumns() ?? [];
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(tableColumns.map((c) => [c.id, c]));
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(tableColumns.map((c) => [c.id, c]));
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 lowerQuery = query.toLowerCase();
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 value = cell.getValue();
1139
- const stringValue = String(value ?? "").toLowerCase();
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
- columns,
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 tableColumns = currentTable?.getAllColumns() ?? [];
1923
- const columnById = new Map(tableColumns.map((c) => [c.id, c]));
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 dataGridElement = dataGridRef.current;
2288
- if (!dataGridElement) return;
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 = dataGridElement.contains(target);
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
- dataGridElement.focus();
2348
+ dataGridElement2.focus();
2305
2349
  });
2306
2350
  }
2307
2351
  return;
2308
2352
  }
2309
2353
  }
2310
- const isInDataGrid = dataGridElement.contains(target);
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 = dataGridRef.current;
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,