@ai-matrx/design-system 0.41.0 → 0.42.1

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 (57) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/data-table/copy-helpers.d.cts +2 -1
  3. package/dist/data-table/copy-helpers.d.ts +2 -1
  4. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  5. package/dist/data-table/data-row-inspector.js.map +1 -1
  6. package/dist/data-table/data-row-window.cjs.map +1 -1
  7. package/dist/data-table/data-row-window.js.map +1 -1
  8. package/dist/data-table/filter-engine.d.cts +2 -1
  9. package/dist/data-table/filter-engine.d.ts +2 -1
  10. package/dist/data-table/host.cjs.map +1 -1
  11. package/dist/data-table/host.d.cts +18 -4
  12. package/dist/data-table/host.d.ts +18 -4
  13. package/dist/data-table/host.js.map +1 -1
  14. package/dist/data-table/index.cjs +2990 -2778
  15. package/dist/data-table/index.cjs.map +1 -1
  16. package/dist/data-table/index.d.cts +4 -4
  17. package/dist/data-table/index.d.ts +4 -4
  18. package/dist/data-table/index.js +2999 -2787
  19. package/dist/data-table/index.js.map +1 -1
  20. package/dist/data-table/infer-filter.d.cts +2 -1
  21. package/dist/data-table/infer-filter.d.ts +2 -1
  22. package/dist/data-table/layered-filters.d.cts +2 -1
  23. package/dist/data-table/layered-filters.d.ts +2 -1
  24. package/dist/data-table/menu-targets.cjs +27 -0
  25. package/dist/data-table/menu-targets.cjs.map +1 -1
  26. package/dist/data-table/menu-targets.d.cts +49 -1
  27. package/dist/data-table/menu-targets.d.ts +49 -1
  28. package/dist/data-table/menu-targets.js +27 -0
  29. package/dist/data-table/menu-targets.js.map +1 -1
  30. package/dist/data-table/pagination.cjs.map +1 -1
  31. package/dist/data-table/pagination.js.map +1 -1
  32. package/dist/data-table/query-control.d.cts +2 -1
  33. package/dist/data-table/query-control.d.ts +2 -1
  34. package/dist/data-table/spreadsheet.cjs +24 -8
  35. package/dist/data-table/spreadsheet.cjs.map +1 -1
  36. package/dist/data-table/spreadsheet.d.cts +20 -3
  37. package/dist/data-table/spreadsheet.d.ts +20 -3
  38. package/dist/data-table/spreadsheet.js +24 -8
  39. package/dist/data-table/spreadsheet.js.map +1 -1
  40. package/dist/data-table/types.cjs.map +1 -1
  41. package/dist/data-table/types.d.cts +2 -1
  42. package/dist/data-table/types.d.ts +2 -1
  43. package/dist/data-table/url-state.d.cts +2 -1
  44. package/dist/data-table/url-state.d.ts +2 -1
  45. package/dist/data-table/uuid-cell.cjs.map +1 -1
  46. package/dist/data-table/uuid-cell.js.map +1 -1
  47. package/dist/data-table/xlsx.d.cts +2 -1
  48. package/dist/data-table/xlsx.d.ts +2 -1
  49. package/dist/index.cjs +534 -468
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +67 -1
  52. package/dist/index.d.ts +67 -1
  53. package/dist/index.js +541 -475
  54. package/dist/index.js.map +1 -1
  55. package/dist/{types-Dx5hJgCi.d.ts → types-afUz93xo.d.ts} +33 -1
  56. package/dist/{types-DNkbHRVK.d.cts → types-q5ficDSo.d.cts} +33 -1
  57. package/package.json +1 -1
@@ -84,8 +84,23 @@ interface SpreadsheetGridOptions {
84
84
  isColumnWritable: (columnId: string) => boolean;
85
85
  /** Why a column refuses, as a sentence. Used in the skip list. */
86
86
  columnRefusal?: ((columnId: string) => string | undefined) | undefined;
87
- /** Applies a batch of writes. The consumer owns the door. */
88
- onPatch: (patches: CellPatch[], intent: SpreadsheetIntent) => void | Promise<void>;
87
+ /**
88
+ * Applies a batch of writes. The consumer owns the door. Optional only for a
89
+ * `readOnly` grid, which never writes; a writable grid without it refuses
90
+ * every write out loud rather than dropping it.
91
+ */
92
+ onPatch?: ((patches: CellPatch[], intent: SpreadsheetIntent) => void | Promise<void>) | undefined;
93
+ /**
94
+ * SELECT AND COPY, NEVER CHANGE. A reader gets the whole range cursor — click,
95
+ * drag, shift-click, arrows, select-all, Cmd-C — and no gesture that writes:
96
+ * no fill handle, and cut, paste, clear, fill-down, undo and redo each say
97
+ * `readOnlyReason` instead of doing anything. Separate from editing on
98
+ * purpose: whether a person may CHANGE a table is not whether they may COPY
99
+ * a range out of it.
100
+ */
101
+ readOnly?: boolean | undefined;
102
+ /** The sentence a refused write says on a read-only grid. */
103
+ readOnlyReason?: string | undefined;
89
104
  /** 0 turns undo off. */
90
105
  undoDepth?: number | undefined;
91
106
  /** The little square at the corner of a selection. */
@@ -198,6 +213,8 @@ interface SpreadsheetClipboardEvent {
198
213
  preventDefault: () => void;
199
214
  }
200
215
  declare const NOTHING: CellPatch[];
216
+ /** What a refused write says on a read-only grid when the consumer names nothing better. */
217
+ declare const READ_ONLY_REASON = "This table is view-only \u2014 you can select and copy, but not change cells.";
201
218
  declare function useSpreadsheetGrid(options: SpreadsheetGridOptions | null): SpreadsheetGrid;
202
219
 
203
- export { NOTHING as NO_PATCHES, type PasteRefusal, type SpreadsheetCellProps, type SpreadsheetClipboardEvent, type SpreadsheetGrid, type SpreadsheetGridOptions, type SpreadsheetIntent, type SpreadsheetKeyEvent, type SpreadsheetPastePlan, useSpreadsheetGrid };
220
+ export { NOTHING as NO_PATCHES, type PasteRefusal, READ_ONLY_REASON, type SpreadsheetCellProps, type SpreadsheetClipboardEvent, type SpreadsheetGrid, type SpreadsheetGridOptions, type SpreadsheetIntent, type SpreadsheetKeyEvent, type SpreadsheetPastePlan, useSpreadsheetGrid };
@@ -624,6 +624,7 @@ function camePastAPortalIntoTheContainer(target) {
624
624
  return element.closest('[data-matrx-table-spreadsheet="true"]') === null;
625
625
  }
626
626
  var NOTHING = [];
627
+ var READ_ONLY_REASON = "This table is view-only \u2014 you can select and copy, but not change cells.";
627
628
  function useSpreadsheetGrid(options) {
628
629
  const [range, setRange] = useState(null);
629
630
  const [fillTarget, setFillTarget] = useState(null);
@@ -690,10 +691,18 @@ function useSpreadsheetGrid(options) {
690
691
  }));
691
692
  setStack((previous) => pushUndo(previous, undoEntryFor(before, patches, label)));
692
693
  }
694
+ if (!current.onPatch) return;
693
695
  await current.onPatch(patches, intent);
694
696
  },
695
697
  []
696
698
  );
699
+ const refuseWrite = useCallback(() => {
700
+ const current = optionsRef.current;
701
+ if (!current) return true;
702
+ if (!current.readOnly && current.onPatch) return false;
703
+ current.notify?.(current.readOnlyReason ?? READ_ONLY_REASON);
704
+ return true;
705
+ }, []);
697
706
  const readValueAt = useCallback((rowIndex, columnIndex) => {
698
707
  const current = optionsRef.current;
699
708
  const rowId = current?.rowIds[rowIndex];
@@ -727,6 +736,7 @@ function useSpreadsheetGrid(options) {
727
736
  []
728
737
  );
729
738
  const doFillDown = useCallback(async () => {
739
+ if (refuseWrite()) return;
730
740
  const base = fillRequestBase();
731
741
  if (!base || !bounds) return;
732
742
  const result = fillDown({
@@ -736,8 +746,9 @@ function useSpreadsheetGrid(options) {
736
746
  const screened = screenPatches(result.patches);
737
747
  await applyPatches(screened.accepted, "fill-down", "Filled down");
738
748
  announceSkips([...result.skipped, ...screened.refusals], result.summary);
739
- }, [fillRequestBase, bounds, applyPatches, announceSkips, screenPatches]);
749
+ }, [fillRequestBase, bounds, applyPatches, announceSkips, screenPatches, refuseWrite]);
740
750
  const doClear = useCallback(async () => {
751
+ if (refuseWrite()) return;
741
752
  const current = optionsRef.current;
742
753
  if (!current || !bounds) return;
743
754
  const patches = [];
@@ -764,20 +775,22 @@ function useSpreadsheetGrid(options) {
764
775
  [...skipped, ...screened.refusals],
765
776
  `Cleared ${screened.accepted.length} cells.`
766
777
  );
767
- }, [bounds, applyPatches, announceSkips, screenPatches]);
778
+ }, [bounds, applyPatches, announceSkips, screenPatches, refuseWrite]);
768
779
  const doUndo = useCallback(async () => {
780
+ if (refuseWrite()) return;
769
781
  const taken = popUndo(stack);
770
782
  if (!taken.entry) return;
771
783
  setStack(taken.stack);
772
784
  await applyPatches(taken.entry.undo, "undo", taken.entry.label);
773
785
  optionsRef.current?.notify?.(taken.entry.label);
774
- }, [stack, applyPatches]);
786
+ }, [stack, applyPatches, refuseWrite]);
775
787
  const doRedo = useCallback(async () => {
788
+ if (refuseWrite()) return;
776
789
  const taken = popRedo(stack);
777
790
  if (!taken.entry) return;
778
791
  setStack(taken.stack);
779
792
  await applyPatches(taken.entry.redo, "redo", taken.entry.label);
780
- }, [stack, applyPatches]);
793
+ }, [stack, applyPatches, refuseWrite]);
781
794
  const move = useCallback(
782
795
  (direction, extend) => {
783
796
  setRange((previous) => {
@@ -853,7 +866,7 @@ function useSpreadsheetGrid(options) {
853
866
  case "edit":
854
867
  case "editSeeded": {
855
868
  const focused = range?.focus;
856
- if (!focused || !current.onEditRequest) return;
869
+ if (!focused || !current.onEditRequest || current.readOnly) return;
857
870
  const seed = action.kind === "editSeeded" ? action.seed : null;
858
871
  if (current.onEditRequest(focused, seed)) event.preventDefault();
859
872
  return;
@@ -910,6 +923,7 @@ function useSpreadsheetGrid(options) {
910
923
  const text = event.clipboardData?.getData("text/plain") ?? "";
911
924
  if (!text) return;
912
925
  event.preventDefault();
926
+ if (refuseWrite()) return;
913
927
  const block = parseClipboardGrid(text);
914
928
  const start = range.focus;
915
929
  const startRow = rowIds.indexOf(start.rowId);
@@ -972,7 +986,7 @@ function useSpreadsheetGrid(options) {
972
986
  const tail = outside > 0 ? ` ${outside} landed past the edge of the table and were ignored.` : "";
973
987
  announceSkips(refusals, `Pasted ${screened.accepted.length} cells.${tail}`);
974
988
  },
975
- [range, rowIds, columnIds, applyPatches, announceSkips, screenPatches]
989
+ [range, rowIds, columnIds, applyPatches, announceSkips, screenPatches, refuseWrite]
976
990
  );
977
991
  const cellProps = useCallback(
978
992
  (rowId, columnId) => {
@@ -1023,7 +1037,7 @@ function useSpreadsheetGrid(options) {
1023
1037
  const isFillHandleCell = useCallback(
1024
1038
  (rowId, columnId) => {
1025
1039
  const current = optionsRef.current;
1026
- if (!current || current.fillHandle === false || !bounds) return false;
1040
+ if (!current || current.fillHandle === false || current.readOnly || !bounds) return false;
1027
1041
  return rowIds[bounds.r1] === rowId && columnIds[bounds.c1] === columnId;
1028
1042
  },
1029
1043
  [bounds, rowIds, columnIds]
@@ -1050,6 +1064,7 @@ function useSpreadsheetGrid(options) {
1050
1064
  const source = boundsRef.current;
1051
1065
  setFillTarget(null);
1052
1066
  if (!target || !source) return;
1067
+ if (refuseWrite()) return;
1053
1068
  const base = fillRequestBase();
1054
1069
  if (!base) return;
1055
1070
  const result = fillRange({
@@ -1063,7 +1078,7 @@ function useSpreadsheetGrid(options) {
1063
1078
  };
1064
1079
  window.addEventListener("mouseup", commit);
1065
1080
  return () => window.removeEventListener("mouseup", commit);
1066
- }, [options, fillRequestBase, applyPatches, announceSkips, screenPatches]);
1081
+ }, [options, fillRequestBase, applyPatches, announceSkips, screenPatches, refuseWrite]);
1067
1082
  return {
1068
1083
  range,
1069
1084
  bounds,
@@ -1086,6 +1101,7 @@ function useSpreadsheetGrid(options) {
1086
1101
  }
1087
1102
  export {
1088
1103
  NOTHING as NO_PATCHES,
1104
+ READ_ONLY_REASON,
1089
1105
  useSpreadsheetGrid
1090
1106
  };
1091
1107
  //# sourceMappingURL=spreadsheet.js.map