@ai-matrx/design-system 0.42.1 → 0.44.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 (53) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/content-transfer.cjs +39 -0
  3. package/dist/content-transfer.cjs.map +1 -1
  4. package/dist/content-transfer.js +39 -0
  5. package/dist/content-transfer.js.map +1 -1
  6. package/dist/data-table/copy-helpers.d.cts +1 -1
  7. package/dist/data-table/copy-helpers.d.ts +1 -1
  8. package/dist/data-table/data-row-inspector.cjs +39 -0
  9. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  10. package/dist/data-table/data-row-inspector.js +41 -2
  11. package/dist/data-table/data-row-inspector.js.map +1 -1
  12. package/dist/data-table/data-row-window.cjs +39 -0
  13. package/dist/data-table/data-row-window.cjs.map +1 -1
  14. package/dist/data-table/data-row-window.js +43 -4
  15. package/dist/data-table/data-row-window.js.map +1 -1
  16. package/dist/data-table/filter-engine.d.cts +1 -1
  17. package/dist/data-table/filter-engine.d.ts +1 -1
  18. package/dist/data-table/host.d.cts +1 -1
  19. package/dist/data-table/host.d.ts +1 -1
  20. package/dist/data-table/index.cjs +114 -3
  21. package/dist/data-table/index.cjs.map +1 -1
  22. package/dist/data-table/index.d.cts +2 -2
  23. package/dist/data-table/index.d.ts +2 -2
  24. package/dist/data-table/index.js +151 -40
  25. package/dist/data-table/index.js.map +1 -1
  26. package/dist/data-table/infer-filter.d.cts +1 -1
  27. package/dist/data-table/infer-filter.d.ts +1 -1
  28. package/dist/data-table/layered-filters.d.cts +1 -1
  29. package/dist/data-table/layered-filters.d.ts +1 -1
  30. package/dist/data-table/query-control.d.cts +1 -1
  31. package/dist/data-table/query-control.d.ts +1 -1
  32. package/dist/data-table/spreadsheet.cjs +68 -1
  33. package/dist/data-table/spreadsheet.cjs.map +1 -1
  34. package/dist/data-table/spreadsheet.d.cts +55 -1
  35. package/dist/data-table/spreadsheet.d.ts +55 -1
  36. package/dist/data-table/spreadsheet.js +68 -1
  37. package/dist/data-table/spreadsheet.js.map +1 -1
  38. package/dist/data-table/types.cjs.map +1 -1
  39. package/dist/data-table/types.d.cts +1 -1
  40. package/dist/data-table/types.d.ts +1 -1
  41. package/dist/data-table/url-state.d.cts +1 -1
  42. package/dist/data-table/url-state.d.ts +1 -1
  43. package/dist/data-table/xlsx.d.cts +1 -1
  44. package/dist/data-table/xlsx.d.ts +1 -1
  45. package/dist/index.cjs +43 -0
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +28 -1
  48. package/dist/index.d.ts +28 -1
  49. package/dist/index.js +48 -5
  50. package/dist/index.js.map +1 -1
  51. package/dist/{types-afUz93xo.d.ts → types-CUR8Hbt5.d.ts} +12 -0
  52. package/dist/{types-q5ficDSo.d.cts → types-CqU57qk8.d.cts} +12 -0
  53. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as ColumnMarker, M as MatrxColumnDef } from '../types-q5ficDSo.cjs';
4
- export { A as AnyOfColumnSearch, k as CellEditType, l as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, m as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, n as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, o as MatrxDataTableDetailConfig, p as MatrxDataTableEditConfig, q as MatrxDataTableEmptyState, r as MatrxDataTableExpandedDetailConfig, s as MatrxDataTableFacetsConfig, t as MatrxDataTableFilterUi, u as MatrxDataTableGroupingConfig, v as MatrxDataTableHierarchyConfig, w as MatrxDataTableHierarchyMove, x as MatrxDataTableMobileCardControls, y as MatrxDataTableMultiExpandedDetailConfig, z as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, B as MatrxDataTableSelectionConfig, D as MatrxDataTableSingleExpandedDetailConfig, E as MatrxDataTableSourceProcessing, F as MatrxDataTableSpreadsheetConfig, G as MatrxDataTableStyleConfig, H as MatrxDataTableToolbar, I as MatrxDataTableUrlStateConfig, J as MatrxDataTableVirtualizeConfig, K as MatrxDataTableWindowConfig, N as MatrxTablePagination, O as SortDirection, S as SortState, P as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, Q as TableSearchRole, R as TableSearchScope, U as TableViewQuery, V as TextFilterMode, W as ToolbarFacet, X as inferTableSearchRole, Y as rankTableSearchRows, Z as resolveTableSearchScopes } from '../types-q5ficDSo.cjs';
3
+ import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as ColumnMarker, M as MatrxColumnDef } from '../types-CqU57qk8.cjs';
4
+ export { A as AnyOfColumnSearch, k as CellEditType, l as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, m as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, n as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, o as MatrxDataTableDetailConfig, p as MatrxDataTableEditConfig, q as MatrxDataTableEmptyState, r as MatrxDataTableExpandedDetailConfig, s as MatrxDataTableFacetsConfig, t as MatrxDataTableFilterUi, u as MatrxDataTableGroupingConfig, v as MatrxDataTableHierarchyConfig, w as MatrxDataTableHierarchyMove, x as MatrxDataTableMobileCardControls, y as MatrxDataTableMultiExpandedDetailConfig, z as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, B as MatrxDataTableSelectionConfig, D as MatrxDataTableSingleExpandedDetailConfig, E as MatrxDataTableSourceProcessing, F as MatrxDataTableSpreadsheetConfig, G as MatrxDataTableStyleConfig, H as MatrxDataTableToolbar, I as MatrxDataTableUrlStateConfig, J as MatrxDataTableVirtualizeConfig, K as MatrxDataTableWindowConfig, N as MatrxTablePagination, O as SortDirection, S as SortState, P as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, Q as TableSearchRole, R as TableSearchScope, U as TableViewQuery, V as TextFilterMode, W as ToolbarFacet, X as inferTableSearchRole, Y as rankTableSearchRows, Z as resolveTableSearchScopes } from '../types-CqU57qk8.cjs';
5
5
  export { MatrxDataTableHost, MatrxDataTableProvider, MatrxTableRowAlchemy, TableContextMenuBoundaryProps, TableDoors, TableEntityRefProps, TableLinkProps, TableMenuIconProps, TablePeekProps, TableSidePanelProps, TableToolbarActionProps, TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy } from './host.cjs';
6
6
  import { CopyControlProps } from './copy-types.cjs';
7
7
  export { AgentPayloadInput } from './copy-types.cjs';
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as ColumnMarker, M as MatrxColumnDef } from '../types-afUz93xo.js';
4
- export { A as AnyOfColumnSearch, k as CellEditType, l as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, m as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, n as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, o as MatrxDataTableDetailConfig, p as MatrxDataTableEditConfig, q as MatrxDataTableEmptyState, r as MatrxDataTableExpandedDetailConfig, s as MatrxDataTableFacetsConfig, t as MatrxDataTableFilterUi, u as MatrxDataTableGroupingConfig, v as MatrxDataTableHierarchyConfig, w as MatrxDataTableHierarchyMove, x as MatrxDataTableMobileCardControls, y as MatrxDataTableMultiExpandedDetailConfig, z as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, B as MatrxDataTableSelectionConfig, D as MatrxDataTableSingleExpandedDetailConfig, E as MatrxDataTableSourceProcessing, F as MatrxDataTableSpreadsheetConfig, G as MatrxDataTableStyleConfig, H as MatrxDataTableToolbar, I as MatrxDataTableUrlStateConfig, J as MatrxDataTableVirtualizeConfig, K as MatrxDataTableWindowConfig, N as MatrxTablePagination, O as SortDirection, S as SortState, P as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, Q as TableSearchRole, R as TableSearchScope, U as TableViewQuery, V as TextFilterMode, W as ToolbarFacet, X as inferTableSearchRole, Y as rankTableSearchRows, Z as resolveTableSearchScopes } from '../types-afUz93xo.js';
3
+ import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as ColumnMarker, M as MatrxColumnDef } from '../types-CUR8Hbt5.js';
4
+ export { A as AnyOfColumnSearch, k as CellEditType, l as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, m as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, n as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, o as MatrxDataTableDetailConfig, p as MatrxDataTableEditConfig, q as MatrxDataTableEmptyState, r as MatrxDataTableExpandedDetailConfig, s as MatrxDataTableFacetsConfig, t as MatrxDataTableFilterUi, u as MatrxDataTableGroupingConfig, v as MatrxDataTableHierarchyConfig, w as MatrxDataTableHierarchyMove, x as MatrxDataTableMobileCardControls, y as MatrxDataTableMultiExpandedDetailConfig, z as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, B as MatrxDataTableSelectionConfig, D as MatrxDataTableSingleExpandedDetailConfig, E as MatrxDataTableSourceProcessing, F as MatrxDataTableSpreadsheetConfig, G as MatrxDataTableStyleConfig, H as MatrxDataTableToolbar, I as MatrxDataTableUrlStateConfig, J as MatrxDataTableVirtualizeConfig, K as MatrxDataTableWindowConfig, N as MatrxTablePagination, O as SortDirection, S as SortState, P as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, Q as TableSearchRole, R as TableSearchScope, U as TableViewQuery, V as TextFilterMode, W as ToolbarFacet, X as inferTableSearchRole, Y as rankTableSearchRows, Z as resolveTableSearchScopes } from '../types-CUR8Hbt5.js';
5
5
  export { MatrxDataTableHost, MatrxDataTableProvider, MatrxTableRowAlchemy, TableContextMenuBoundaryProps, TableDoors, TableEntityRefProps, TableLinkProps, TableMenuIconProps, TablePeekProps, TableSidePanelProps, TableToolbarActionProps, TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy } from './host.js';
6
6
  import { CopyControlProps } from './copy-types.js';
7
7
  export { AgentPayloadInput } from './copy-types.js';
@@ -6,7 +6,7 @@ import {
6
6
  Fragment as Fragment7,
7
7
  isValidElement as isValidElement2,
8
8
  useCallback as useCallback8,
9
- useEffect as useEffect16,
9
+ useEffect as useEffect17,
10
10
  useId as useId2,
11
11
  useLayoutEffect as useLayoutEffect2,
12
12
  useMemo as useMemo9,
@@ -1529,6 +1529,15 @@ function useIsMobile() {
1529
1529
  return isMobile;
1530
1530
  }
1531
1531
 
1532
+ // src/layer-front.ts
1533
+ var LAYER_FRONT_EVENT = "matrx:layer-front";
1534
+ function announceLayerFront(element) {
1535
+ if (typeof document === "undefined") return;
1536
+ document.dispatchEvent(
1537
+ new CustomEvent(LAYER_FRONT_EVENT, { detail: { element } })
1538
+ );
1539
+ }
1540
+
1532
1541
  // src/dialog.tsx
1533
1542
  import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1534
1543
  var DialogWindowedByDefaultContext = React11.createContext(false);
@@ -1599,6 +1608,8 @@ var DialogContent = React11.forwardRef(
1599
1608
  dismissOnOutsideClick = false,
1600
1609
  onInteractOutside,
1601
1610
  onEscapeKeyDown,
1611
+ onPointerDownCapture,
1612
+ onFocusCapture,
1602
1613
  style,
1603
1614
  ...props
1604
1615
  }, ref) => {
@@ -1611,6 +1622,24 @@ var DialogContent = React11.forwardRef(
1611
1622
  const [containerEl, setContainerEl] = React11.useState(
1612
1623
  null
1613
1624
  );
1625
+ const stacks = windowed && windowedByDefault;
1626
+ const [behind, setBehind] = React11.useState(false);
1627
+ React11.useEffect(() => {
1628
+ if (!stacks || !containerEl) return;
1629
+ const onFront = (event) => {
1630
+ const element = event.detail?.element ?? null;
1631
+ if (element && (element === containerEl || containerEl.contains(element))) return;
1632
+ setBehind(true);
1633
+ };
1634
+ document.addEventListener(LAYER_FRONT_EVENT, onFront);
1635
+ announceLayerFront(containerEl);
1636
+ return () => document.removeEventListener(LAYER_FRONT_EVENT, onFront);
1637
+ }, [stacks, containerEl]);
1638
+ const bringToFront = () => {
1639
+ if (!stacks || !containerEl) return;
1640
+ setBehind(false);
1641
+ announceLayerFront(containerEl);
1642
+ };
1614
1643
  const [offset, setOffset] = React11.useState({ x: 0, y: 0 });
1615
1644
  const dragRef = React11.useRef(null);
1616
1645
  const handle = React11.useMemo(() => {
@@ -1669,10 +1698,20 @@ var DialogContent = React11.forwardRef(
1669
1698
  // z=1000); staying below that boundary makes a newly focused window
1670
1699
  // usable without coupling the two systems.
1671
1700
  !isModal && !windowedByDefault && "z-[900]",
1701
+ // Another layer came to the front after this window (layer-front.ts).
1702
+ stacks && behind && "z-[999]",
1672
1703
  // Without an overlay the card needs its own separation from the page.
1673
1704
  windowed && "shadow-2xl ring-1 ring-border/60"
1674
1705
  ),
1675
1706
  style: windowed && (offset.x !== 0 || offset.y !== 0) ? { ...style, translate: `${offset.x}px ${offset.y}px` } : style,
1707
+ onPointerDownCapture: (event) => {
1708
+ onPointerDownCapture?.(event);
1709
+ if (behind) bringToFront();
1710
+ },
1711
+ onFocusCapture: (event) => {
1712
+ onFocusCapture?.(event);
1713
+ if (behind) bringToFront();
1714
+ },
1676
1715
  onInteractOutside: (event) => {
1677
1716
  onInteractOutside?.(event);
1678
1717
  if (windowed && !dismissOnOutsideClick) event.preventDefault();
@@ -5710,9 +5749,9 @@ function useCopySubsetVariant() {
5710
5749
  }
5711
5750
 
5712
5751
  // src/data-table/clipping.ts
5713
- import { useEffect as useEffect6 } from "react";
5752
+ import { useEffect as useEffect7 } from "react";
5714
5753
  function useClippedContentGuard(ref, options) {
5715
- useEffect6(() => {
5754
+ useEffect7(() => {
5716
5755
  if (!options.enabled || !ref.current) return;
5717
5756
  const node = ref.current;
5718
5757
  const check = () => {
@@ -5726,7 +5765,7 @@ function useClippedContentGuard(ref, options) {
5726
5765
  }
5727
5766
 
5728
5767
  // src/data-table/url-state.ts
5729
- import { useCallback as useCallback4, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef9, useState as useState12 } from "react";
5768
+ import { useCallback as useCallback4, useEffect as useEffect8, useMemo as useMemo5, useRef as useRef9, useState as useState12 } from "react";
5730
5769
  import {
5731
5770
  commitUrlParams,
5732
5771
  useUrlSearchParams
@@ -5808,7 +5847,7 @@ function useTableUrlState(options) {
5808
5847
  const state = readState(searchParams);
5809
5848
  const lastTextWriteAt = useRef9(0);
5810
5849
  const [debouncedSearch, setDebouncedSearch] = useState12(state.search);
5811
- useEffect7(() => {
5850
+ useEffect8(() => {
5812
5851
  if (state.search === debouncedSearch) return;
5813
5852
  const timer = window.setTimeout(
5814
5853
  () => setDebouncedSearch(state.search),
@@ -5916,14 +5955,14 @@ import {
5916
5955
  } from "@ai-matrx/kit/url-state";
5917
5956
 
5918
5957
  // src/data-table/RowAlchemyLauncher.tsx
5919
- import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef10, useState as useState13 } from "react";
5958
+ import { useCallback as useCallback5, useEffect as useEffect9, useRef as useRef10, useState as useState13 } from "react";
5920
5959
  import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
5921
5960
  function MatrxTableRowAlchemyProvider({ copy, placement, controls, children }) {
5922
5961
  const controller = useRef10(null);
5923
5962
  const { CopyControls } = useMatrxDataTableHost();
5924
5963
  const [active, setActive] = useState13(false);
5925
5964
  const [fallback, setFallback] = useState13(false);
5926
- useEffect8(() => {
5965
+ useEffect9(() => {
5927
5966
  if (placement !== "menu" || active) return;
5928
5967
  const timer = window.setTimeout(() => {
5929
5968
  if (!active) {
@@ -5960,7 +5999,7 @@ function MatrxTableRowAlchemyProvider({ copy, placement, controls, children }) {
5960
5999
  // src/data-table/ColumnHeaderCell.tsx
5961
6000
  import {
5962
6001
  forwardRef as forwardRef13,
5963
- useEffect as useEffect9,
6002
+ useEffect as useEffect10,
5964
6003
  useMemo as useMemo6,
5965
6004
  useRef as useRef11,
5966
6005
  useState as useState14
@@ -6347,7 +6386,7 @@ function ColumnHeaderCell({
6347
6386
  const [filterOpen, setFilterOpen] = useState14(false);
6348
6387
  const [pendingNegation, setPendingNegation] = useState14(false);
6349
6388
  const [draftFilter, setDraftFilter] = useState14(filterValue);
6350
- useEffect9(() => {
6389
+ useEffect10(() => {
6351
6390
  if (!filterOpen) {
6352
6391
  setDraftFilter(filterValue);
6353
6392
  setPendingNegation(filterValue?.negated ?? false);
@@ -6355,7 +6394,7 @@ function ColumnHeaderCell({
6355
6394
  }, [filterOpen, filterValue]);
6356
6395
  const notifyOpen = useRef11(onFilterOpen);
6357
6396
  notifyOpen.current = onFilterOpen;
6358
- useEffect9(() => {
6397
+ useEffect10(() => {
6359
6398
  if (filterOpen) notifyOpen.current?.();
6360
6399
  }, [filterOpen]);
6361
6400
  const applyFilter = () => {
@@ -7203,7 +7242,7 @@ function parseOptionalNumber(raw) {
7203
7242
  // src/data-table/ColumnResizeHandle.tsx
7204
7243
  import {
7205
7244
  useCallback as useCallback6,
7206
- useEffect as useEffect10,
7245
+ useEffect as useEffect11,
7207
7246
  useRef as useRef12,
7208
7247
  useState as useState15
7209
7248
  } from "react";
@@ -7300,7 +7339,7 @@ function ColumnResizeHandle({
7300
7339
  handleRef.current.releasePointerCapture(active.pointerId);
7301
7340
  }
7302
7341
  }, [clearQueuedPreview, columnId2, cssVar, onResizeCancel, onResizeCommit, tableRef, writePreview]);
7303
- useEffect10(() => () => clearQueuedPreview(), [clearQueuedPreview]);
7342
+ useEffect11(() => () => clearQueuedPreview(), [clearQueuedPreview]);
7304
7343
  const onPointerDown = (event) => {
7305
7344
  if (disabled || event.button !== 0 || !event.isPrimary) return;
7306
7345
  event.preventDefault();
@@ -7841,7 +7880,7 @@ function scrollOffsetForIndex(input) {
7841
7880
  }
7842
7881
 
7843
7882
  // src/data-table/useSpreadsheetGrid.ts
7844
- import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo7, useRef as useRef13, useState as useState16 } from "react";
7883
+ import { useCallback as useCallback7, useEffect as useEffect12, useMemo as useMemo7, useRef as useRef13, useState as useState16 } from "react";
7845
7884
 
7846
7885
  // src/data-table/grid-selection.ts
7847
7886
  function rangeBounds(range, rowIds, fieldNames) {
@@ -8533,8 +8572,23 @@ function canRedo(stack) {
8533
8572
  function targetsAnEditor(target) {
8534
8573
  const element = target instanceof Element ? target : null;
8535
8574
  if (!element) return false;
8575
+ if (element.closest(`[${TYPE_CATCHER_ATTR}]`)) return false;
8536
8576
  return element.closest("input, textarea, select, [contenteditable='true']") !== null;
8537
8577
  }
8578
+ var TYPE_CATCHER_ATTR = "data-matrx-type-catcher";
8579
+ var TYPE_CATCHER_STYLE = {
8580
+ position: "fixed",
8581
+ top: 0,
8582
+ left: 0,
8583
+ width: 1,
8584
+ height: 1,
8585
+ padding: 0,
8586
+ border: 0,
8587
+ opacity: 0,
8588
+ overflow: "hidden",
8589
+ resize: "none",
8590
+ pointerEvents: "none"
8591
+ };
8538
8592
  function camePastAPortal(target, host) {
8539
8593
  if (typeof Element === "undefined") return false;
8540
8594
  const element = target instanceof Element ? target : null;
@@ -8554,6 +8608,8 @@ function useSpreadsheetGrid(options) {
8554
8608
  const [fillTarget, setFillTarget] = useState16(null);
8555
8609
  const [stack, setStack] = useState16(() => createUndoStack(options?.undoDepth ?? 100));
8556
8610
  const draggingRef = useRef13(null);
8611
+ const catcherRef = useRef13(null);
8612
+ const composingRef = useRef13(false);
8557
8613
  const optionsRef = useRef13(options);
8558
8614
  optionsRef.current = options;
8559
8615
  const rowIds = options?.rowIds ?? [];
@@ -8561,7 +8617,7 @@ function useSpreadsheetGrid(options) {
8561
8617
  () => options ? options.columnIds.filter((id) => id !== "") : [],
8562
8618
  [options]
8563
8619
  );
8564
- useEffect11(() => {
8620
+ useEffect12(() => {
8565
8621
  if (!range) return;
8566
8622
  const rowSet = new Set(rowIds);
8567
8623
  const colSet = new Set(columnIds);
@@ -8932,7 +8988,9 @@ function useSpreadsheetGrid(options) {
8932
8988
  event.preventDefault();
8933
8989
  const origin = event.currentTarget;
8934
8990
  if (typeof HTMLElement !== "undefined" && origin instanceof HTMLElement) {
8935
- origin.closest('[data-matrx-table-spreadsheet="true"]')?.focus({ preventScroll: true });
8991
+ const container = origin.closest('[data-matrx-table-spreadsheet="true"]');
8992
+ const catcher = container?.querySelector(`[${TYPE_CATCHER_ATTR}]`);
8993
+ (catcher ?? container)?.focus({ preventScroll: true });
8936
8994
  }
8937
8995
  setRange(
8938
8996
  (previous) => event.shiftKey && previous ? { anchor: previous.anchor, focus: address } : { anchor: address, focus: address }
@@ -8978,7 +9036,7 @@ function useSpreadsheetGrid(options) {
8978
9036
  fillTargetRef.current = fillTarget;
8979
9037
  const boundsRef = useRef13(null);
8980
9038
  boundsRef.current = bounds;
8981
- useEffect11(() => {
9039
+ useEffect12(() => {
8982
9040
  if (!options) return;
8983
9041
  const commit = () => {
8984
9042
  const wasDragging = draggingRef.current;
@@ -9003,11 +9061,58 @@ function useSpreadsheetGrid(options) {
9003
9061
  window.addEventListener("mouseup", commit);
9004
9062
  return () => window.removeEventListener("mouseup", commit);
9005
9063
  }, [options, fillRequestBase, applyPatches, announceSkips, screenPatches, refuseWrite]);
9064
+ const takeTypedText = useCallback7(
9065
+ (text) => {
9066
+ if (catcherRef.current) catcherRef.current.value = "";
9067
+ const current = optionsRef.current;
9068
+ const focused = range?.focus;
9069
+ if (!current || !focused || current.readOnly || !current.onEditRequest) return;
9070
+ if (text.trim() === "") return;
9071
+ current.onEditRequest(focused, text);
9072
+ },
9073
+ [range]
9074
+ );
9075
+ const typeCatcherProps = {
9076
+ ref: (element) => {
9077
+ catcherRef.current = element;
9078
+ },
9079
+ tabIndex: -1,
9080
+ "aria-label": "Type to edit the selected cell",
9081
+ inputMode: "none",
9082
+ autoComplete: "off",
9083
+ autoCorrect: "off",
9084
+ autoCapitalize: "off",
9085
+ spellCheck: false,
9086
+ rows: 1,
9087
+ [TYPE_CATCHER_ATTR]: "",
9088
+ style: TYPE_CATCHER_STYLE,
9089
+ onInput: (event) => {
9090
+ const kind = event.nativeEvent?.inputType;
9091
+ if (typeof kind === "string" && (kind.startsWith("insertFromPaste") || kind.startsWith("insertFromDrop"))) {
9092
+ event.currentTarget.value = "";
9093
+ return;
9094
+ }
9095
+ if (composingRef.current) return;
9096
+ takeTypedText(event.currentTarget.value);
9097
+ },
9098
+ onCompositionStart: () => {
9099
+ composingRef.current = true;
9100
+ },
9101
+ onCompositionEnd: (event) => {
9102
+ composingRef.current = false;
9103
+ takeTypedText(event.data || event.currentTarget.value);
9104
+ }
9105
+ };
9006
9106
  return {
9007
9107
  range,
9008
9108
  bounds,
9009
9109
  enabled: options !== null,
9110
+ typeCatcherProps,
9010
9111
  containerProps: {
9112
+ onFocus: (event) => {
9113
+ if (event.target !== event.currentTarget) return;
9114
+ catcherRef.current?.focus({ preventScroll: true });
9115
+ },
9011
9116
  tabIndex: options ? 0 : -1,
9012
9117
  onKeyDown,
9013
9118
  onCopy,
@@ -9172,7 +9277,7 @@ function rankTableSearchRows(rows, columns, query, options = {}, extraText) {
9172
9277
  }
9173
9278
 
9174
9279
  // src/data-table/ColumnManager.tsx
9175
- import { useEffect as useEffect12, useMemo as useMemo8, useState as useState17 } from "react";
9280
+ import { useEffect as useEffect13, useMemo as useMemo8, useState as useState17 } from "react";
9176
9281
  import { useDndMonitor, useDraggable as useDraggable2, useDroppable } from "@dnd-kit/core";
9177
9282
  import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
9178
9283
  function ColumnManager({
@@ -9191,7 +9296,7 @@ function ColumnManager({
9191
9296
  const [draftHidden, setDraftHidden] = useState17(() => new Set(hidden));
9192
9297
  const [draggedColumnId, setDraggedColumnId] = useState17(null);
9193
9298
  const [dropTarget, setDropTarget] = useState17(null);
9194
- useEffect12(() => {
9299
+ useEffect13(() => {
9195
9300
  if (!open) return;
9196
9301
  setDraftOrder(order);
9197
9302
  setDraftHidden(new Set(hidden));
@@ -9724,7 +9829,7 @@ function parseTableViewSnapshot(raw) {
9724
9829
 
9725
9830
  // src/data-table/MatrxUuidCell.tsx
9726
9831
  import {
9727
- useEffect as useEffect13,
9832
+ useEffect as useEffect14,
9728
9833
  useRef as useRef14,
9729
9834
  useState as useState18
9730
9835
  } from "react";
@@ -9771,7 +9876,7 @@ function MatrxUuidCell({
9771
9876
  const [opening, setOpening] = useState18(false);
9772
9877
  const [peekOpen, setPeekOpen] = useState18(false);
9773
9878
  const timer = useRef14(null);
9774
- useEffect13(
9879
+ useEffect14(
9775
9880
  () => () => {
9776
9881
  if (timer.current) clearTimeout(timer.current);
9777
9882
  },
@@ -10066,7 +10171,7 @@ function DataRowInspector({
10066
10171
  }
10067
10172
 
10068
10173
  // src/data-table/DataRowWindow.tsx
10069
- import { useEffect as useEffect14, useState as useState19 } from "react";
10174
+ import { useEffect as useEffect15, useState as useState19 } from "react";
10070
10175
  import { jsx as jsx37, jsxs as jsxs27 } from "react/jsx-runtime";
10071
10176
  function DataRowWindow({
10072
10177
  isOpen,
@@ -10088,7 +10193,7 @@ function DataRowWindow({
10088
10193
  const hasTabs = hasEdit && children == null;
10089
10194
  const initialTab = defaultTab ?? (hasEdit ? "edit" : "view");
10090
10195
  const [tab, setTab] = useState19(initialTab);
10091
- useEffect14(() => {
10196
+ useEffect15(() => {
10092
10197
  if (!isOpen) return;
10093
10198
  setTab(defaultTab ?? (hasEdit ? "edit" : "view"));
10094
10199
  }, [isOpen, windowId, hasEdit, defaultTab]);
@@ -11302,7 +11407,7 @@ function DirtySavePill({
11302
11407
  }
11303
11408
 
11304
11409
  // src/data-table/EditableTableCell.tsx
11305
- import { useEffect as useEffect15, useRef as useRef15, useState as useState20 } from "react";
11410
+ import { useEffect as useEffect16, useRef as useRef15, useState as useState20 } from "react";
11306
11411
  import { jsx as jsx40, jsxs as jsxs30 } from "react/jsx-runtime";
11307
11412
  function CellRefusal({ reason }) {
11308
11413
  return /* @__PURE__ */ jsx40(
@@ -11366,10 +11471,10 @@ function EditableTableCell({
11366
11471
  }) {
11367
11472
  const [open, setOpen] = useState20(false);
11368
11473
  const [refusal, setRefusal] = useState20(null);
11369
- useEffect15(() => {
11474
+ useEffect16(() => {
11370
11475
  if (editRequest !== void 0) setOpen(true);
11371
11476
  }, [editRequest]);
11372
- useEffect15(() => {
11477
+ useEffect16(() => {
11373
11478
  if (!open) setRefusal(null);
11374
11479
  }, [open]);
11375
11480
  const usePencil = Boolean(href) || editTrigger === "pencil";
@@ -11479,7 +11584,7 @@ function InlineStringEditor({
11479
11584
  const handledEditRequest = useRef15(void 0);
11480
11585
  const seedRef = useRef15(editSeed);
11481
11586
  seedRef.current = editSeed;
11482
- useEffect15(() => {
11587
+ useEffect16(() => {
11483
11588
  if (editRequest === void 0 || handledEditRequest.current === editRequest) return;
11484
11589
  handledEditRequest.current = editRequest;
11485
11590
  setDraft(seedRef.current ?? value);
@@ -12470,7 +12575,7 @@ function MatrxDataTableWithUrlState({
12470
12575
  ...urlState.history === void 0 ? {} : { history: urlState.history },
12471
12576
  ...urlState.textHistory === void 0 ? {} : { textHistory: urlState.textHistory }
12472
12577
  });
12473
- useEffect16(() => {
12578
+ useEffect17(() => {
12474
12579
  if (activeUrlTableIds.has(urlState.id)) {
12475
12580
  throw new Error(
12476
12581
  `Duplicate MatrxDataTable urlState.id "${urlState.id}" on one page. Give every table a unique stable id.`
@@ -12870,7 +12975,7 @@ function MatrxDataTableCore({
12870
12975
  rows: Object.entries(draft.values).map(([rowId, columns2]) => ({ rowId, columns: columns2 }))
12871
12976
  }));
12872
12977
  const selection = appendSourceChanged && selectionConfig ? { ...selectionConfig, selectedIds: [] } : selectionConfig;
12873
- useEffect16(() => {
12978
+ useEffect17(() => {
12874
12979
  const previous = committedAppendQueryKey.current;
12875
12980
  committedAppendQueryKey.current = appendQueryKey;
12876
12981
  if (previous === null || appendQueryKey === null || previous === appendQueryKey) {
@@ -12940,7 +13045,7 @@ function MatrxDataTableCore({
12940
13045
  behavior: "smooth"
12941
13046
  });
12942
13047
  };
12943
- useEffect16(() => {
13048
+ useEffect17(() => {
12944
13049
  updateScrollHint();
12945
13050
  window.addEventListener("resize", updateScrollHint);
12946
13051
  const el = scrollRef.current;
@@ -13033,7 +13138,7 @@ function MatrxDataTableCore({
13033
13138
  columnDragRaf.current = null;
13034
13139
  columnDragScrollDirection.current = 0;
13035
13140
  }, []);
13036
- useEffect16(() => () => {
13141
+ useEffect17(() => () => {
13037
13142
  columnDragActive.current = false;
13038
13143
  stopColumnDragScroll();
13039
13144
  }, [stopColumnDragScroll]);
@@ -13159,7 +13264,7 @@ function MatrxDataTableCore({
13159
13264
  }
13160
13265
  setColumnWidths(normalized);
13161
13266
  }, [columnIds, columnState, columns, measureFixedTableGeometry, measureVisibleColumnWidths]);
13162
- useEffect16(() => {
13267
+ useEffect17(() => {
13163
13268
  const ids = columns.map(columnId);
13164
13269
  if (columnState) return;
13165
13270
  const previousIds = knownColumnIds.current;
@@ -13390,7 +13495,7 @@ function MatrxDataTableCore({
13390
13495
  searchScope
13391
13496
  ]);
13392
13497
  const lastNotifiedViewRows = useRef16(null);
13393
- useEffect16(() => {
13498
+ useEffect17(() => {
13394
13499
  if (!onViewChange) {
13395
13500
  lastNotifiedViewRows.current = null;
13396
13501
  return;
@@ -13399,7 +13504,7 @@ function MatrxDataTableCore({
13399
13504
  lastNotifiedViewRows.current = processed;
13400
13505
  if (changed) onViewChange(processed);
13401
13506
  }, [processed, onViewChange]);
13402
- useEffect16(() => {
13507
+ useEffect17(() => {
13403
13508
  if (controlledQuery) return;
13404
13509
  setInternalPage(1);
13405
13510
  }, [
@@ -13581,7 +13686,7 @@ function MatrxDataTableCore({
13581
13686
  frozenRunLength
13582
13687
  ]);
13583
13688
  const metricsWanted = virtualizeActive || columnVirtualizeActive;
13584
- useEffect16(() => {
13689
+ useEffect17(() => {
13585
13690
  recomputeWindows();
13586
13691
  }, [
13587
13692
  recomputeWindows,
@@ -13593,7 +13698,7 @@ function MatrxDataTableCore({
13593
13698
  columnWindowWidth,
13594
13699
  frozenRunLength
13595
13700
  ]);
13596
- useEffect16(() => {
13701
+ useEffect17(() => {
13597
13702
  if (!metricsWanted) return;
13598
13703
  const el = scrollRef.current;
13599
13704
  if (!el) return;
@@ -13786,12 +13891,12 @@ function MatrxDataTableCore({
13786
13891
  }));
13787
13892
  });
13788
13893
  }, []);
13789
- useEffect16(() => {
13894
+ useEffect17(() => {
13790
13895
  if (!facetsEnabled) return;
13791
13896
  setFacetState({});
13792
13897
  facetRequestRef.current = /* @__PURE__ */ new Map();
13793
13898
  }, [facetsEnabled, data, searchValue]);
13794
- useEffect16(() => {
13899
+ useEffect17(() => {
13795
13900
  if (!controlledQuery || controlledQuery.state.page === safePage) return;
13796
13901
  emitControlledQueryChange({ page: safePage });
13797
13902
  }, [controlledQuery, emitControlledQueryChange, safePage]);
@@ -14002,13 +14107,17 @@ function MatrxDataTableCore({
14002
14107
  }));
14003
14108
  };
14004
14109
  const requestCellEdit = (address, seed) => {
14005
- if (!editEnabled) return false;
14110
+ if (!editEnabled && !spreadsheet?.onEditRequest) return false;
14006
14111
  const row = data.find((candidate) => getRowId(candidate) === address.rowId);
14007
14112
  if (!row) return false;
14008
14113
  const column = visibleColumns.find(
14009
14114
  (candidate) => columnId(candidate) === address.fieldName
14010
14115
  );
14011
- if (!column?.editable || !(column.editableIf?.(row) ?? true)) return false;
14116
+ if (!column?.editable) {
14117
+ const own = spreadsheet?.onEditRequest;
14118
+ return own ? own({ rowId: address.rowId, columnId: address.fieldName }, seed) : false;
14119
+ }
14120
+ if (!(column.editableIf?.(row) ?? true)) return false;
14012
14121
  const field = column.accessorKey ? String(column.accessorKey) : columnId(column);
14013
14122
  setEditRequest((current) => ({
14014
14123
  rowId: address.rowId,
@@ -14373,7 +14482,7 @@ function MatrxDataTableCore({
14373
14482
  );
14374
14483
  const resolveMenuLevelRef = useRef16(resolveMenuLevel);
14375
14484
  resolveMenuLevelRef.current = resolveMenuLevel;
14376
- useEffect16(() => {
14485
+ useEffect17(() => {
14377
14486
  if (!host.rowContextRegistry) return;
14378
14487
  return host.rowContextRegistry.register(
14379
14488
  tableContextMenuInstanceId,
@@ -15137,6 +15246,7 @@ function MatrxDataTableCore({
15137
15246
  onCopy: sheet.containerProps.onCopy,
15138
15247
  onCut: sheet.containerProps.onCut,
15139
15248
  onPaste: sheet.containerProps.onPaste,
15249
+ onFocus: sheet.containerProps.onFocus,
15140
15250
  "data-matrx-table-spreadsheet": "true"
15141
15251
  } : {},
15142
15252
  "aria-busy": isLoading || isFetching,
@@ -15147,6 +15257,7 @@ function MatrxDataTableCore({
15147
15257
  tableClassName
15148
15258
  ),
15149
15259
  children: [
15260
+ spreadsheetEnabled ? /* @__PURE__ */ jsx43("textarea", { ...sheet.typeCatcherProps }) : null,
15150
15261
  hierarchy && draggedRow ? /* @__PURE__ */ jsx43(
15151
15262
  HierarchyRootDropTarget,
15152
15263
  {