@ai-matrx/design-system 0.21.3 → 0.21.4

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 (48) hide show
  1. package/dist/data-table/copy-helpers.d.cts +1 -1
  2. package/dist/data-table/copy-helpers.d.ts +1 -1
  3. package/dist/data-table/data-row-inspector.cjs +3 -0
  4. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  5. package/dist/data-table/data-row-inspector.js +3 -0
  6. package/dist/data-table/data-row-inspector.js.map +1 -1
  7. package/dist/data-table/data-row-window.cjs +3 -0
  8. package/dist/data-table/data-row-window.cjs.map +1 -1
  9. package/dist/data-table/data-row-window.js +3 -0
  10. package/dist/data-table/data-row-window.js.map +1 -1
  11. package/dist/data-table/filter-engine.d.cts +1 -1
  12. package/dist/data-table/filter-engine.d.ts +1 -1
  13. package/dist/data-table/host.cjs +12 -1
  14. package/dist/data-table/host.cjs.map +1 -1
  15. package/dist/data-table/host.d.cts +19 -3
  16. package/dist/data-table/host.d.ts +19 -3
  17. package/dist/data-table/host.js +12 -1
  18. package/dist/data-table/host.js.map +1 -1
  19. package/dist/data-table/index.cjs +98 -34
  20. package/dist/data-table/index.cjs.map +1 -1
  21. package/dist/data-table/index.d.cts +5 -4
  22. package/dist/data-table/index.d.ts +5 -4
  23. package/dist/data-table/index.js +127 -63
  24. package/dist/data-table/index.js.map +1 -1
  25. package/dist/data-table/infer-filter.d.cts +1 -1
  26. package/dist/data-table/infer-filter.d.ts +1 -1
  27. package/dist/data-table/layered-filters.d.cts +1 -1
  28. package/dist/data-table/layered-filters.d.ts +1 -1
  29. package/dist/data-table/pagination.cjs +3 -0
  30. package/dist/data-table/pagination.cjs.map +1 -1
  31. package/dist/data-table/pagination.js +3 -0
  32. package/dist/data-table/pagination.js.map +1 -1
  33. package/dist/data-table/query-control.d.cts +1 -1
  34. package/dist/data-table/query-control.d.ts +1 -1
  35. package/dist/data-table/types.cjs.map +1 -1
  36. package/dist/data-table/types.d.cts +1 -1
  37. package/dist/data-table/types.d.ts +1 -1
  38. package/dist/data-table/url-state.d.cts +1 -1
  39. package/dist/data-table/url-state.d.ts +1 -1
  40. package/dist/data-table/uuid-cell.cjs +3 -0
  41. package/dist/data-table/uuid-cell.cjs.map +1 -1
  42. package/dist/data-table/uuid-cell.js +3 -0
  43. package/dist/data-table/uuid-cell.js.map +1 -1
  44. package/dist/data-table/xlsx.d.cts +1 -1
  45. package/dist/data-table/xlsx.d.ts +1 -1
  46. package/dist/{types-JFlsIv-0.d.ts → types-CbGNfo7r.d.ts} +10 -1
  47. package/dist/{types-BarjBFyG.d.cts → types-DRusLYrU.d.cts} +10 -1
  48. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-BarjBFyG.cjs';
1
+ import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-DRusLYrU.cjs';
2
2
  import '../content-transfer.cjs';
3
3
  import 'react';
4
4
  import '@ai-matrx/kit/content-transfer';
@@ -1,4 +1,4 @@
1
- import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-JFlsIv-0.js';
1
+ import { M as MatrxColumnDef, C as ColumnFiltersState, S as SortState, L as LayeredFilterRule, T as TableSearchMatchMode, a as ColumnFilterValue } from '../types-CbGNfo7r.js';
2
2
  import '../content-transfer.js';
3
3
  import 'react';
4
4
  import '@ai-matrx/kit/content-transfer';
@@ -24,8 +24,10 @@ var host_exports = {};
24
24
  __export(host_exports, {
25
25
  MatrxDataTableProvider: () => MatrxDataTableProvider,
26
26
  MatrxTableRowAlchemyScope: () => MatrxTableRowAlchemyScope,
27
+ MatrxTableRowControlsScope: () => MatrxTableRowControlsScope,
27
28
  useMatrxDataTableHost: () => useMatrxDataTableHost,
28
- useMatrxTableRowAlchemy: () => useMatrxTableRowAlchemy
29
+ useMatrxTableRowAlchemy: () => useMatrxTableRowAlchemy,
30
+ useMatrxTableRowControls: () => useMatrxTableRowControls
29
31
  });
30
32
  module.exports = __toCommonJS(host_exports);
31
33
  var import_react = require("react");
@@ -48,4 +50,13 @@ function MatrxTableRowAlchemyScope({ value, children }) {
48
50
  function useMatrxTableRowAlchemy() {
49
51
  return (0, import_react.useContext)(RowAlchemyContext);
50
52
  }
53
+ var ROW_CONTROLS_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.table-row-controls-context");
54
+ var rowControlsRegistry = globalThis;
55
+ var RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= (0, import_react.createContext)(null);
56
+ function MatrxTableRowControlsScope({ value, children }) {
57
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RowControlsContext.Provider, { value, children });
58
+ }
59
+ function useMatrxTableRowControls() {
60
+ return (0, import_react.useContext)(RowControlsContext);
61
+ }
51
62
  //# sourceMappingURL=host.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, TableSavedViewsProps } from \"./types\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAoH;AA8BK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,UAAM,4BAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,4CAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,aAAO,yBAAW,WAAW;AAAG;AAU9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,UAAM,4BAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,4CAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,aAAO,yBAAW,iBAAiB;AAAG;","names":[]}
1
+ {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, MatrxDataTableRecordControls, TableSavedViewsProps } from \"./types\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (rowId: string) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps { label: string; children: ReactNode; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; rowContextRegistry?: TableRowContextRegistry; createDefaultRowContext?: (row: unknown, controls: import(\"./types\").MatrxDataTableRecordControls) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n controls?: MatrxDataTableRecordControls;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n\nconst ROW_CONTROLS_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-controls-context\");\nconst rowControlsRegistry = globalThis as typeof globalThis & { [ROW_CONTROLS_SLOT]?: Context<MatrxDataTableRecordControls | null> };\nconst RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext<MatrxDataTableRecordControls | null>(null);\nexport function MatrxTableRowControlsScope({ value, children }: { value: MatrxDataTableRecordControls; children: ReactNode }) { return <RowControlsContext.Provider value={value}>{children}</RowControlsContext.Provider>; }\nexport function useMatrxTableRowControls(): MatrxDataTableRecordControls | null { return useContext(RowControlsContext); }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAoH;AAgCK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,UAAM,4BAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,4CAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,aAAO,yBAAW,WAAW;AAAG;AAW9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,UAAM,4BAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,4CAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,aAAO,yBAAW,iBAAiB;AAAG;AAE/G,IAAM,oBAAoB,uBAAO,IAAI,mDAAmD;AACxF,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB,oBAAoB,iBAAiB,UAAM,4BAAmD,IAAI;AACtH,SAAS,2BAA2B,EAAE,OAAO,SAAS,GAAiE;AAAE,SAAO,4CAAC,mBAAmB,UAAnB,EAA4B,OAAe,UAAS;AAAgC;AACrN,SAAS,2BAAgE;AAAE,aAAO,yBAAW,kBAAkB;AAAG;","names":[]}
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
+ import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-DRusLYrU.cjs';
3
4
  import { CopyControlProps } from './copy-types.cjs';
4
5
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.cjs';
5
- import { b as TableSavedViewsProps, c as MatrxDataTableDensity } from '../types-BarjBFyG.cjs';
6
6
  import '../content-transfer.cjs';
7
7
  import '@ai-matrx/kit/content-transfer';
8
8
  import '../content-transfer/icon.cjs';
@@ -69,6 +69,13 @@ interface TableDoors {
69
69
  peekKind?: string;
70
70
  canPeek?: boolean;
71
71
  }
72
+ interface TableRowContextRegistry {
73
+ register(tableId: string, resolve: (rowId: string) => unknown): () => void;
74
+ }
75
+ interface TableContextMenuBoundaryProps {
76
+ label: string;
77
+ children: ReactNode;
78
+ }
72
79
  interface MatrxDataTableHost {
73
80
  JsonViewer?: ComponentType<{
74
81
  data: object | string;
@@ -81,7 +88,10 @@ interface MatrxDataTableHost {
81
88
  EntityRef?: ComponentType<TableEntityRefProps>;
82
89
  resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null;
83
90
  ResourcePeek?: ComponentType<TablePeekProps>;
84
- SavedViews?: ComponentType<TableSavedViewsProps>; /** Host default; a table's explicit density takes precedence. */
91
+ SavedViews?: ComponentType<TableSavedViewsProps>;
92
+ rowContextRegistry?: TableRowContextRegistry;
93
+ createDefaultRowContext?: (row: unknown, controls: MatrxDataTableRecordControls) => unknown;
94
+ ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */
85
95
  defaultDensity?: MatrxDataTableDensity;
86
96
  notify?: {
87
97
  success(message: string): void;
@@ -95,6 +105,7 @@ declare function MatrxDataTableProvider({ value, children }: {
95
105
  declare function useMatrxDataTableHost(): MatrxDataTableHost;
96
106
  interface MatrxTableRowAlchemy {
97
107
  copy: CopyControlProps;
108
+ controls?: MatrxDataTableRecordControls;
98
109
  placement: "inline" | "menu";
99
110
  ready: boolean;
100
111
  activate(): void;
@@ -105,5 +116,10 @@ declare function MatrxTableRowAlchemyScope({ value, children }: {
105
116
  children: ReactNode;
106
117
  }): React.JSX.Element;
107
118
  declare function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null;
119
+ declare function MatrxTableRowControlsScope({ value, children }: {
120
+ value: MatrxDataTableRecordControls;
121
+ children: ReactNode;
122
+ }): React.JSX.Element;
123
+ declare function useMatrxTableRowControls(): MatrxDataTableRecordControls | null;
108
124
 
109
- export { CopyControlProps, type MatrxDataTableHost, MatrxDataTableProvider, type MatrxTableRowAlchemy, MatrxTableRowAlchemyScope, type TableDoors, type TableEntityRefProps, type TableLinkProps, type TablePeekProps, type TableSidePanelProps, type TableToolbarActionProps, type TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy };
125
+ export { CopyControlProps, type MatrxDataTableHost, MatrxDataTableProvider, type MatrxTableRowAlchemy, MatrxTableRowAlchemyScope, MatrxTableRowControlsScope, type TableContextMenuBoundaryProps, type TableDoors, type TableEntityRefProps, type TableLinkProps, type TablePeekProps, type TableRowContextRegistry, type TableSidePanelProps, type TableToolbarActionProps, type TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy, useMatrxTableRowControls };
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, ReactNode, MouseEventHandler } from 'react';
3
+ import { b as TableSavedViewsProps, c as MatrxDataTableRecordControls, d as MatrxDataTableDensity } from '../types-CbGNfo7r.js';
3
4
  import { CopyControlProps } from './copy-types.js';
4
5
  export { AgentPayloadInput, AiCustomSource, AiVariant, CopyExportConfig } from './copy-types.js';
5
- import { b as TableSavedViewsProps, c as MatrxDataTableDensity } from '../types-JFlsIv-0.js';
6
6
  import '../content-transfer.js';
7
7
  import '@ai-matrx/kit/content-transfer';
8
8
  import '../content-transfer/icon.js';
@@ -69,6 +69,13 @@ interface TableDoors {
69
69
  peekKind?: string;
70
70
  canPeek?: boolean;
71
71
  }
72
+ interface TableRowContextRegistry {
73
+ register(tableId: string, resolve: (rowId: string) => unknown): () => void;
74
+ }
75
+ interface TableContextMenuBoundaryProps {
76
+ label: string;
77
+ children: ReactNode;
78
+ }
72
79
  interface MatrxDataTableHost {
73
80
  JsonViewer?: ComponentType<{
74
81
  data: object | string;
@@ -81,7 +88,10 @@ interface MatrxDataTableHost {
81
88
  EntityRef?: ComponentType<TableEntityRefProps>;
82
89
  resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null;
83
90
  ResourcePeek?: ComponentType<TablePeekProps>;
84
- SavedViews?: ComponentType<TableSavedViewsProps>; /** Host default; a table's explicit density takes precedence. */
91
+ SavedViews?: ComponentType<TableSavedViewsProps>;
92
+ rowContextRegistry?: TableRowContextRegistry;
93
+ createDefaultRowContext?: (row: unknown, controls: MatrxDataTableRecordControls) => unknown;
94
+ ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */
85
95
  defaultDensity?: MatrxDataTableDensity;
86
96
  notify?: {
87
97
  success(message: string): void;
@@ -95,6 +105,7 @@ declare function MatrxDataTableProvider({ value, children }: {
95
105
  declare function useMatrxDataTableHost(): MatrxDataTableHost;
96
106
  interface MatrxTableRowAlchemy {
97
107
  copy: CopyControlProps;
108
+ controls?: MatrxDataTableRecordControls;
98
109
  placement: "inline" | "menu";
99
110
  ready: boolean;
100
111
  activate(): void;
@@ -105,5 +116,10 @@ declare function MatrxTableRowAlchemyScope({ value, children }: {
105
116
  children: ReactNode;
106
117
  }): React.JSX.Element;
107
118
  declare function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null;
119
+ declare function MatrxTableRowControlsScope({ value, children }: {
120
+ value: MatrxDataTableRecordControls;
121
+ children: ReactNode;
122
+ }): React.JSX.Element;
123
+ declare function useMatrxTableRowControls(): MatrxDataTableRecordControls | null;
108
124
 
109
- export { CopyControlProps, type MatrxDataTableHost, MatrxDataTableProvider, type MatrxTableRowAlchemy, MatrxTableRowAlchemyScope, type TableDoors, type TableEntityRefProps, type TableLinkProps, type TablePeekProps, type TableSidePanelProps, type TableToolbarActionProps, type TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy };
125
+ export { CopyControlProps, type MatrxDataTableHost, MatrxDataTableProvider, type MatrxTableRowAlchemy, MatrxTableRowAlchemyScope, MatrxTableRowControlsScope, type TableContextMenuBoundaryProps, type TableDoors, type TableEntityRefProps, type TableLinkProps, type TablePeekProps, type TableRowContextRegistry, type TableSidePanelProps, type TableToolbarActionProps, type TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy, useMatrxTableRowControls };
@@ -22,10 +22,21 @@ function MatrxTableRowAlchemyScope({ value, children }) {
22
22
  function useMatrxTableRowAlchemy() {
23
23
  return useContext(RowAlchemyContext);
24
24
  }
25
+ var ROW_CONTROLS_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.table-row-controls-context");
26
+ var rowControlsRegistry = globalThis;
27
+ var RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext(null);
28
+ function MatrxTableRowControlsScope({ value, children }) {
29
+ return /* @__PURE__ */ jsx(RowControlsContext.Provider, { value, children });
30
+ }
31
+ function useMatrxTableRowControls() {
32
+ return useContext(RowControlsContext);
33
+ }
25
34
  export {
26
35
  MatrxDataTableProvider,
27
36
  MatrxTableRowAlchemyScope,
37
+ MatrxTableRowControlsScope,
28
38
  useMatrxDataTableHost,
29
- useMatrxTableRowAlchemy
39
+ useMatrxTableRowAlchemy,
40
+ useMatrxTableRowControls
30
41
  };
31
42
  //# sourceMappingURL=host.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, TableSavedViewsProps } from \"./types\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n"],"mappings":";;;;AACA,SAAS,eAAe,kBAA4F;AA8BK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,MAAM,cAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,SAAO,WAAW,WAAW;AAAG;AAU9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,MAAM,cAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,SAAO,WAAW,iBAAiB;AAAG;","names":[]}
1
+ {"version":3,"sources":["../../src/data-table/host.tsx"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"./copy-types\";\nimport type { MatrxDataTableDensity, MatrxDataTableRecordControls, TableSavedViewsProps } from \"./types\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n CopyControlProps,\n CopyExportConfig,\n} from \"./copy-types\";\n\nexport interface TableLinkProps { href: string; children: ReactNode; className?: string; onClick?: MouseEventHandler<HTMLAnchorElement>; }\n/**\n * Host-owned toolbar affordance. The table package keeps operation state and\n * labels; an application can supply its canonical icon-button primitive\n * without making the shared package depend on an application UI package.\n */\nexport interface TableToolbarActionProps { ariaLabel: string; tooltip?: string | undefined; disabled?: boolean | undefined; busy?: boolean | undefined; /** Indicates a selected mutually-exclusive action such as the current page. */ active?: boolean | undefined; onClick: () => void; children: ReactNode; }\nexport interface TableSidePanelProps { title: string; titleNode?: ReactNode; description?: ReactNode; onClose: () => void; defaultWidth?: number; headerActions?: ReactNode; children: ReactNode; }\nexport interface TableWindowPanelProps { id: string; title: string; onClose: () => void; width?: number; height?: number; minWidth?: number; minHeight?: number; actionsRight?: ReactNode; bodyClassName?: string; sidebarDefaultSize?: number; sidebarMinSize?: number; sidebar?: ReactNode; children: ReactNode; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors { href?: string; peekKind?: string; canPeek?: boolean; }\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (rowId: string) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps { label: string; children: ReactNode; }\nexport interface MatrxDataTableHost { JsonViewer?: ComponentType<{ data: object | string }>; Link?: ComponentType<TableLinkProps>; CopyControls?: ComponentType<CopyControlProps>; ToolbarAction?: ComponentType<TableToolbarActionProps>; SidePanelSurface?: ComponentType<TableSidePanelProps>; WindowPanel?: ComponentType<TableWindowPanelProps>; EntityRef?: ComponentType<TableEntityRefProps>; resolveEntityDoors?: (token: string, id: string, href?: string | null) => TableDoors | null; ResourcePeek?: ComponentType<TablePeekProps>; SavedViews?: ComponentType<TableSavedViewsProps>; rowContextRegistry?: TableRowContextRegistry; createDefaultRowContext?: (row: unknown, controls: import(\"./types\").MatrxDataTableRecordControls) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; notify?: { success(message: string): void; error(message: string): void }; }\n// Public entrypoints are independently bundled in ESM and CJS. The context\n// identity must survive those bundle boundaries; values stay provider-scoped.\nconst HOST_SLOT = Symbol.for(\"ai-matrx.design-system.table-host-context\");\nconst hostRegistry = globalThis as typeof globalThis & { [HOST_SLOT]?: Context<MatrxDataTableHost> };\nconst HostContext = hostRegistry[HOST_SLOT] ??= createContext<MatrxDataTableHost>({});\nexport function MatrxDataTableProvider({ value, children }: { value: MatrxDataTableHost; children: ReactNode }) { return <HostContext.Provider value={value}>{children}</HostContext.Provider>; }\nexport function useMatrxDataTableHost(): MatrxDataTableHost { return useContext(HostContext); }\n\nexport interface MatrxTableRowAlchemy {\n copy: CopyControlProps;\n controls?: MatrxDataTableRecordControls;\n placement: \"inline\" | \"menu\";\n ready: boolean;\n activate(): void;\n prepare(restoreFocus?: () => void): Promise<void>;\n}\n\nconst ROW_ALCHEMY_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-alchemy-context\");\nconst rowAlchemyRegistry = globalThis as typeof globalThis & { [ROW_ALCHEMY_SLOT]?: Context<MatrxTableRowAlchemy | null> };\nconst RowAlchemyContext = rowAlchemyRegistry[ROW_ALCHEMY_SLOT] ??= createContext<MatrxTableRowAlchemy | null>(null);\n\nexport function MatrxTableRowAlchemyScope({ value, children }: { value: MatrxTableRowAlchemy; children: ReactNode }) { return <RowAlchemyContext.Provider value={value}>{children}</RowAlchemyContext.Provider>; }\n\nexport function useMatrxTableRowAlchemy(): MatrxTableRowAlchemy | null { return useContext(RowAlchemyContext); }\n\nconst ROW_CONTROLS_SLOT = Symbol.for(\"ai-matrx.design-system.table-row-controls-context\");\nconst rowControlsRegistry = globalThis as typeof globalThis & { [ROW_CONTROLS_SLOT]?: Context<MatrxDataTableRecordControls | null> };\nconst RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= createContext<MatrxDataTableRecordControls | null>(null);\nexport function MatrxTableRowControlsScope({ value, children }: { value: MatrxDataTableRecordControls; children: ReactNode }) { return <RowControlsContext.Provider value={value}>{children}</RowControlsContext.Provider>; }\nexport function useMatrxTableRowControls(): MatrxDataTableRecordControls | null { return useContext(RowControlsContext); }\n"],"mappings":";;;;AACA,SAAS,eAAe,kBAA4F;AAgCK;AAHzH,IAAM,YAAY,uBAAO,IAAI,2CAA2C;AACxE,IAAM,eAAe;AACrB,IAAM,cAAc,aAAa,SAAS,MAAM,cAAkC,CAAC,CAAC;AAC7E,SAAS,uBAAuB,EAAE,OAAO,SAAS,GAAuD;AAAE,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AAAyB;AACzL,SAAS,wBAA4C;AAAE,SAAO,WAAW,WAAW;AAAG;AAW9F,IAAM,mBAAmB,uBAAO,IAAI,kDAAkD;AACtF,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,mBAAmB,gBAAgB,MAAM,cAA2C,IAAI;AAE3G,SAAS,0BAA0B,EAAE,OAAO,SAAS,GAAyD;AAAE,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAe,UAAS;AAA+B;AAE1M,SAAS,0BAAuD;AAAE,SAAO,WAAW,iBAAiB;AAAG;AAE/G,IAAM,oBAAoB,uBAAO,IAAI,mDAAmD;AACxF,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB,oBAAoB,iBAAiB,MAAM,cAAmD,IAAI;AACtH,SAAS,2BAA2B,EAAE,OAAO,SAAS,GAAiE;AAAE,SAAO,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,UAAS;AAAgC;AACrN,SAAS,2BAAgE;AAAE,SAAO,WAAW,kBAAkB;AAAG;","names":[]}
@@ -1925,6 +1925,12 @@ function MatrxTableRowAlchemyScope({ value, children }) {
1925
1925
  function useMatrxTableRowAlchemy() {
1926
1926
  return (0, import_react5.useContext)(RowAlchemyContext);
1927
1927
  }
1928
+ var ROW_CONTROLS_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.design-system.table-row-controls-context");
1929
+ var rowControlsRegistry = globalThis;
1930
+ var RowControlsContext = rowControlsRegistry[ROW_CONTROLS_SLOT] ??= (0, import_react5.createContext)(null);
1931
+ function MatrxTableRowControlsScope({ value, children }) {
1932
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(RowControlsContext.Provider, { value, children });
1933
+ }
1928
1934
 
1929
1935
  // src/data-table/useTableNotice.tsx
1930
1936
  var import_jsx_runtime19 = require("react/jsx-runtime");
@@ -5588,7 +5594,7 @@ var import_url_state3 = require("@ai-matrx/kit/url-state");
5588
5594
  // src/data-table/RowAlchemyLauncher.tsx
5589
5595
  var import_react12 = require("react");
5590
5596
  var import_jsx_runtime29 = require("react/jsx-runtime");
5591
- function MatrxTableRowAlchemyProvider({ copy, placement, children }) {
5597
+ function MatrxTableRowAlchemyProvider({ copy, placement, controls, children }) {
5592
5598
  const controller = (0, import_react12.useRef)(null);
5593
5599
  const { CopyControls } = useMatrxDataTableHost();
5594
5600
  const [active, setActive] = (0, import_react12.useState)(false);
@@ -5605,6 +5611,7 @@ function MatrxTableRowAlchemyProvider({ copy, placement, children }) {
5605
5611
  }, [active, placement]);
5606
5612
  const value = {
5607
5613
  copy,
5614
+ controls,
5608
5615
  placement,
5609
5616
  ready: active,
5610
5617
  activate: () => setActive(true),
@@ -7471,9 +7478,13 @@ function EditableTableCell({
7471
7478
  onCommit,
7472
7479
  className,
7473
7480
  href,
7474
- editTrigger = "click"
7481
+ editTrigger = "click",
7482
+ editRequest
7475
7483
  }) {
7476
7484
  const [open, setOpen] = (0, import_react18.useState)(false);
7485
+ (0, import_react18.useEffect)(() => {
7486
+ if (editRequest !== void 0) setOpen(true);
7487
+ }, [editRequest]);
7477
7488
  const usePencil = Boolean(href) || editTrigger === "pencil";
7478
7489
  if (editType === "string") {
7479
7490
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
@@ -7485,7 +7496,8 @@ function EditableTableCell({
7485
7496
  onCommit,
7486
7497
  ...className === void 0 ? {} : { className },
7487
7498
  ...href === void 0 ? {} : { href },
7488
- usePencil
7499
+ usePencil,
7500
+ ...editRequest === void 0 ? {} : { editRequest }
7489
7501
  }
7490
7502
  );
7491
7503
  }
@@ -7560,10 +7572,18 @@ function InlineStringEditor({
7560
7572
  onCommit,
7561
7573
  className,
7562
7574
  href,
7563
- usePencil
7575
+ usePencil,
7576
+ editRequest
7564
7577
  }) {
7565
7578
  const [editing, setEditing] = (0, import_react18.useState)(false);
7566
7579
  const [draft, setDraft] = (0, import_react18.useState)(value);
7580
+ const handledEditRequest = (0, import_react18.useRef)(void 0);
7581
+ (0, import_react18.useEffect)(() => {
7582
+ if (editRequest === void 0 || handledEditRequest.current === editRequest) return;
7583
+ handledEditRequest.current = editRequest;
7584
+ setDraft(value);
7585
+ setEditing(true);
7586
+ }, [editRequest, value]);
7567
7587
  if (!editing) {
7568
7588
  if (usePencil) {
7569
7589
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
@@ -8557,6 +8577,9 @@ function MatrxDataTableWithUrlState({
8557
8577
  );
8558
8578
  }
8559
8579
  var COLUMN_REORDER_ACTIVATION_DISTANCE = 6;
8580
+ function TableContextPassthrough({ children }) {
8581
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_jsx_runtime41.Fragment, { children });
8582
+ }
8560
8583
  function MatrxDataTableCore({
8561
8584
  data: suppliedData,
8562
8585
  columns,
@@ -8583,6 +8606,7 @@ function MatrxDataTableCore({
8583
8606
  detail,
8584
8607
  window: windowConfig,
8585
8608
  copy,
8609
+ contextMenu,
8586
8610
  rowCopyPlacement = "inline",
8587
8611
  edit,
8588
8612
  hierarchy,
@@ -8618,6 +8642,7 @@ function MatrxDataTableCore({
8618
8642
  const isLoading = appendQuery ? appendQuery.pagination.loading : suppliedLoading;
8619
8643
  const isFetching = appendQuery ? appendQuery.pagination.isFetchingNextPage : suppliedFetching;
8620
8644
  const host = useMatrxDataTableHost();
8645
+ const ContextMenuBoundary = host.ContextMenuBoundary ?? TableContextPassthrough;
8621
8646
  const resolvedDensity = density ?? host.defaultDensity ?? "normal";
8622
8647
  const SavedViews = host.SavedViews;
8623
8648
  const Link = host.Link ?? DefaultTableLink;
@@ -8766,6 +8791,8 @@ function MatrxDataTableCore({
8766
8791
  const [editsByScope, setEditsByScope] = (0, import_react20.useState)({});
8767
8792
  const editRevisionRef = (0, import_react20.useRef)({});
8768
8793
  const [savingByScope, setSavingByScope] = (0, import_react20.useState)({});
8794
+ const savingScopesRef = (0, import_react20.useRef)(/* @__PURE__ */ new Set());
8795
+ const [editRequest, setEditRequest] = (0, import_react20.useState)(null);
8769
8796
  const [confirmForeignDraftDiscard, setConfirmForeignDraftDiscard] = (0, import_react20.useState)(false);
8770
8797
  const edits = editsByScope[editScopeKey]?.values ?? {};
8771
8798
  const saving = (savingByScope[editScopeKey] ?? 0) > 0;
@@ -9187,6 +9214,7 @@ function MatrxDataTableCore({
9187
9214
  [visibleColumns]
9188
9215
  );
9189
9216
  const tableCopySourceNamespace = (0, import_react20.useId)();
9217
+ const tableContextMenuInstanceId = (0, import_react20.useId)();
9190
9218
  const tableDndContextId = (0, import_react20.useId)();
9191
9219
  const defaultCopyTitle = toolbar?.title || "Table";
9192
9220
  const defaultCopy = (0, import_react20.useMemo)(() => ({
@@ -9388,13 +9416,15 @@ function MatrxDataTableCore({
9388
9416
  const showToolbarCopy = effectiveCopy !== void 0 && effectiveCopy.showToolbar !== false;
9389
9417
  const renderRowActions = (row, controls) => {
9390
9418
  const actions = rowActions?.(row, controls);
9391
- if (!effectiveCopy || !showRowCopy) return actions;
9419
+ const scopedActions = /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(MatrxTableRowControlsScope, { value: controls, children: actions });
9420
+ if (!effectiveCopy || !showRowCopy) return scopedActions;
9392
9421
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9393
9422
  MatrxTableRowAlchemyProvider,
9394
9423
  {
9395
9424
  copy: tableRowCopyProps(effectiveCopy, row, `${tableCopySourceNamespace}:row:${getRowId(row)}`, copy === void 0 ? declaredVisibleCopyColumns : void 0),
9396
9425
  placement: rowCopyInMenu ? "menu" : "inline",
9397
- children: actions
9426
+ controls,
9427
+ children: scopedActions
9398
9428
  }
9399
9429
  );
9400
9430
  };
@@ -9511,6 +9541,37 @@ function MatrxDataTableCore({
9511
9541
  return next;
9512
9542
  });
9513
9543
  };
9544
+ const beginRowEdit = (row) => {
9545
+ const column = visibleColumns.find(
9546
+ (candidate) => candidate.editable && (candidate.editableIf?.(row) ?? true)
9547
+ );
9548
+ if (!column) return;
9549
+ const field = column.accessorKey ? String(column.accessorKey) : columnId(column);
9550
+ setEditRequest((current) => ({
9551
+ rowId: getRowId(row),
9552
+ field,
9553
+ nonce: (current?.nonce ?? 0) + 1
9554
+ }));
9555
+ };
9556
+ const buildRecordControls = (row) => {
9557
+ const rowId = getRowId(row);
9558
+ const pending = edits[rowId];
9559
+ return {
9560
+ closeDetail: () => setSelectedId(null),
9561
+ openDetail: () => openDetail(row),
9562
+ openWindow: () => openWindow(row),
9563
+ closeWindow,
9564
+ hasPendingEdits: Boolean(pending),
9565
+ discardPendingEdits: () => discardRowEdits(rowId),
9566
+ ...pending ? { cancelEdits: () => discardRowEdits(rowId) } : {},
9567
+ ...pending && edit?.onSave && !edit.autoSave && !saving ? {
9568
+ saveEdits: () => handleSaveEdits(rowId)
9569
+ } : {},
9570
+ ...editEnabled && visibleColumns.some(
9571
+ (column) => column.editable && (column.editableIf?.(row) ?? true)
9572
+ ) ? { beginEdit: () => beginRowEdit(row) } : {}
9573
+ };
9574
+ };
9514
9575
  const hierarchyRows = hierarchy?.rows ?? data;
9515
9576
  const hierarchyGetParentId = hierarchy?.getParentId;
9516
9577
  const hierarchyIndex = (0, import_react20.useMemo)(() => {
@@ -9682,15 +9743,18 @@ function MatrxDataTableCore({
9682
9743
  }
9683
9744
  setDraggedRowId(null);
9684
9745
  };
9685
- const handleSaveEdits = async () => {
9746
+ const handleSaveEdits = async (rowId) => {
9686
9747
  if (!edit?.onSave || changeCount === 0) return;
9687
9748
  const scope = editScopeKey;
9749
+ if (savingScopesRef.current.has(scope)) return;
9688
9750
  const draft = editsByScope[scope];
9689
9751
  if (!draft) return;
9690
- const values = draft.values;
9691
- const revisions = draft.revisions;
9752
+ const values = rowId ? draft.values[rowId] ? { [rowId]: draft.values[rowId] } : {} : draft.values;
9753
+ if (Object.keys(values).length === 0) return;
9754
+ const revisions = rowId ? draft.revisions[rowId] ? { [rowId]: draft.revisions[rowId] } : {} : draft.revisions;
9692
9755
  const rows = appendQueryKey === null ? data : draft.rows;
9693
9756
  const save = edit.onSave;
9757
+ savingScopesRef.current.add(scope);
9694
9758
  startSaving(scope);
9695
9759
  try {
9696
9760
  await Promise.resolve().then(() => save(values, rows));
@@ -9698,16 +9762,16 @@ function MatrxDataTableCore({
9698
9762
  const currentDraft = current[scope];
9699
9763
  if (!currentDraft) return current;
9700
9764
  const nextValues = {};
9701
- for (const [rowId, rowValues] of Object.entries(currentDraft.values)) {
9702
- const savedRow = values[rowId];
9703
- const savedRevisions = revisions[rowId];
9704
- const currentRevisions = currentDraft.revisions[rowId];
9765
+ for (const [rowId2, rowValues] of Object.entries(currentDraft.values)) {
9766
+ const savedRow = values[rowId2];
9767
+ const savedRevisions = revisions[rowId2];
9768
+ const currentRevisions = currentDraft.revisions[rowId2];
9705
9769
  const remaining = Object.fromEntries(
9706
9770
  Object.entries(rowValues).filter(
9707
9771
  ([field]) => !Object.hasOwn(savedRow ?? {}, field) || currentRevisions?.[field] !== savedRevisions?.[field]
9708
9772
  )
9709
9773
  );
9710
- if (Object.keys(remaining).length > 0) nextValues[rowId] = remaining;
9774
+ if (Object.keys(remaining).length > 0) nextValues[rowId2] = remaining;
9711
9775
  }
9712
9776
  return { ...current, [scope]: { ...currentDraft, values: nextValues } };
9713
9777
  });
@@ -9717,6 +9781,7 @@ function MatrxDataTableCore({
9717
9781
  `Couldn't save: ${e instanceof Error ? e.message : String(e)}`
9718
9782
  );
9719
9783
  } finally {
9784
+ savingScopesRef.current.delete(scope);
9720
9785
  finishSaving(scope);
9721
9786
  }
9722
9787
  };
@@ -9724,6 +9789,17 @@ function MatrxDataTableCore({
9724
9789
  setEdits({});
9725
9790
  edit?.onCancel?.();
9726
9791
  };
9792
+ (0, import_react20.useEffect)(() => {
9793
+ if (!host.rowContextRegistry || !contextMenu && !host.createDefaultRowContext) return;
9794
+ return host.rowContextRegistry.register(tableContextMenuInstanceId, (rowId) => {
9795
+ const row = data.find((candidate) => getRowId(candidate) === rowId);
9796
+ if (!row) return null;
9797
+ const pending = edits[rowId];
9798
+ const displayRow = applyRowEdits(row, pending);
9799
+ const controls = buildRecordControls(displayRow);
9800
+ return contextMenu?.resolveRowContext(displayRow, controls) ?? host.createDefaultRowContext?.(displayRow, controls) ?? null;
9801
+ });
9802
+ }, [buildRecordControls, contextMenu, data, getRowId, host.createDefaultRowContext, host.rowContextRegistry, tableContextMenuInstanceId]);
9727
9803
  const showActionsCol = windowEnabled || Boolean(rowActions) || showInlineRowCopy;
9728
9804
  const selectedIdSet = (0, import_react20.useMemo)(
9729
9805
  () => new Set(selection?.selectedIds ?? []),
@@ -9804,7 +9880,8 @@ function MatrxDataTableCore({
9804
9880
  dirty: Boolean(rowEdits && field in rowEdits),
9805
9881
  onCommit: (next) => commitCell(id, field, next),
9806
9882
  ...href === void 0 ? {} : { href },
9807
- ...col.editTrigger === void 0 ? {} : { editTrigger: col.editTrigger }
9883
+ ...col.editTrigger === void 0 ? {} : { editTrigger: col.editTrigger },
9884
+ ...editRequest?.rowId === id && editRequest.field === field ? { editRequest: editRequest.nonce } : {}
9808
9885
  }
9809
9886
  );
9810
9887
  }
@@ -9914,7 +9991,7 @@ function MatrxDataTableCore({
9914
9991
  },
9915
9992
  [columns, commitColumnState, commitColumnWidths, controlledQuery, intelligentSearchEnabled, intelligentSearchScopes, toolbar]
9916
9993
  );
9917
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
9994
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ContextMenuBoundary, { label: tableId ?? "Data table", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
9918
9995
  import_core3.DndContext,
9919
9996
  {
9920
9997
  id: tableDndContextId,
@@ -10012,6 +10089,7 @@ function MatrxDataTableCore({
10012
10089
  {
10013
10090
  ref: rootRef,
10014
10091
  "data-matrx-table": true,
10092
+ "data-matrx-table-id": tableContextMenuInstanceId,
10015
10093
  "data-matrx-table-implementation": "@ai-matrx/design-system",
10016
10094
  "data-matrx-table-density": resolvedDensity,
10017
10095
  "data-url-state-table": urlState?.id,
@@ -10398,7 +10476,7 @@ function MatrxDataTableCore({
10398
10476
  const id = getRowId(row);
10399
10477
  const displayRow = applyRowEdits(row, edits[id]);
10400
10478
  const selectable = selection?.isRowSelectable?.(row) ?? Boolean(selection);
10401
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_react20.Fragment, { children: mobileCards(displayRow, index, {
10479
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { "data-row-id": id, className: "contents", children: mobileCards(displayRow, index, {
10402
10480
  renderCell: (columnKey) => {
10403
10481
  const column = columns.find((candidate) => columnId(candidate) === columnKey);
10404
10482
  return column ? renderRecordCell(row, column, index) : null;
@@ -10431,14 +10509,7 @@ function MatrxDataTableCore({
10431
10509
  ...copy === void 0 ? { defaultColumns: declaredVisibleCopyColumns } : {}
10432
10510
  }
10433
10511
  ) : null,
10434
- renderRowActions(displayRow, {
10435
- closeDetail: () => setSelectedId(null),
10436
- openDetail: () => openDetail(displayRow),
10437
- openWindow: () => openWindow(displayRow),
10438
- closeWindow,
10439
- hasPendingEdits: Boolean(edits[id]),
10440
- discardPendingEdits: () => discardRowEdits(id)
10441
- })
10512
+ renderRowActions(displayRow, buildRecordControls(displayRow))
10442
10513
  ]
10443
10514
  }
10444
10515
  ) : null
@@ -10834,14 +10905,7 @@ function MatrxDataTableCore({
10834
10905
  ...copy === void 0 ? { defaultColumns: declaredVisibleCopyColumns } : {}
10835
10906
  }
10836
10907
  ) : null,
10837
- renderRowActions(displayRow, {
10838
- closeDetail: () => setSelectedId(null),
10839
- openDetail: () => openDetail(displayRow),
10840
- openWindow: () => openWindow(displayRow),
10841
- closeWindow,
10842
- hasPendingEdits: Boolean(rowEdits),
10843
- discardPendingEdits: () => discardRowEdits(id)
10844
- }),
10908
+ renderRowActions(displayRow, buildRecordControls(displayRow)),
10845
10909
  windowEnabled ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(Tooltip, { children: [
10846
10910
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10847
10911
  Button,
@@ -11329,7 +11393,7 @@ function MatrxDataTableCore({
11329
11393
  ) : null })
11330
11394
  ]
11331
11395
  }
11332
- ) });
11396
+ ) }) });
11333
11397
  }
11334
11398
  function HierarchyDragHandle({
11335
11399
  id,