@ai-matrx/design-system 0.86.357 → 0.86.358

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 (85) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/dist/carousel.js +6 -6
  3. package/dist/{chunk-T4D7WAV7.js → chunk-42GFQMLA.js} +2 -2
  4. package/dist/{chunk-POJ3RR3K.js → chunk-B5D3VIMC.js} +1 -1
  5. package/dist/{chunk-POJ3RR3K.js.map → chunk-B5D3VIMC.js.map} +1 -1
  6. package/dist/{chunk-FRJ4PPA2.js → chunk-CZGZV35G.js} +2 -2
  7. package/dist/{chunk-ACZALXD6.js → chunk-K3XWUACX.js} +3 -3
  8. package/dist/{chunk-TV2IDHPZ.js → chunk-K5ZQROWN.js} +4 -4
  9. package/dist/{chunk-U46XUQI7.js → chunk-KSCSH7AO.js} +16 -14
  10. package/dist/chunk-KSCSH7AO.js.map +1 -0
  11. package/dist/{chunk-MTE6N7XU.js → chunk-NFJ63LIH.js} +2 -2
  12. package/dist/{chunk-XZGYKKCE.js → chunk-OUQT72UL.js} +3 -3
  13. package/dist/{chunk-WUD23YTG.js → chunk-P56Y43RL.js} +6 -6
  14. package/dist/{chunk-GMNROZQJ.js → chunk-QTPW44IJ.js} +2 -2
  15. package/dist/{chunk-QA7EHFRX.js → chunk-T3FKFPCW.js} +5 -5
  16. package/dist/{chunk-X6ZRHJQP.js → chunk-T57DLONB.js} +20 -11
  17. package/dist/chunk-T57DLONB.js.map +1 -0
  18. package/dist/{chunk-SOCNWQMX.js → chunk-TEMAM5ET.js} +3 -3
  19. package/dist/{chunk-CH2NWSES.js → chunk-TIV6M7Q7.js} +3 -3
  20. package/dist/{chunk-6XNYYROM.js → chunk-WVEDW5VO.js} +2 -2
  21. package/dist/clipboard-fallback-dialog.js +2 -2
  22. package/dist/controls.cjs +19 -10
  23. package/dist/controls.cjs.map +1 -1
  24. package/dist/controls.js +6 -6
  25. package/dist/data-table/data-row-inspector.cjs +99 -11
  26. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  27. package/dist/data-table/data-row-inspector.js +8 -7
  28. package/dist/data-table/data-row-window.cjs +99 -11
  29. package/dist/data-table/data-row-window.cjs.map +1 -1
  30. package/dist/data-table/data-row-window.js +9 -8
  31. package/dist/data-table/drill-chart.js +1 -1
  32. package/dist/data-table/host.cjs.map +1 -1
  33. package/dist/data-table/host.d.cts +6 -2
  34. package/dist/data-table/host.d.ts +6 -2
  35. package/dist/data-table/host.js +1 -1
  36. package/dist/data-table/index.cjs +39 -37
  37. package/dist/data-table/index.cjs.map +1 -1
  38. package/dist/data-table/index.d.cts +6 -2
  39. package/dist/data-table/index.d.ts +6 -2
  40. package/dist/data-table/index.js +19 -23
  41. package/dist/data-table/index.js.map +1 -1
  42. package/dist/data-table/pagination.cjs +19 -10
  43. package/dist/data-table/pagination.cjs.map +1 -1
  44. package/dist/data-table/pagination.js +4 -4
  45. package/dist/data-table/uuid-cell.cjs +99 -11
  46. package/dist/data-table/uuid-cell.cjs.map +1 -1
  47. package/dist/data-table/uuid-cell.js +5 -4
  48. package/dist/desktop.cjs +19 -10
  49. package/dist/desktop.cjs.map +1 -1
  50. package/dist/desktop.js +12 -12
  51. package/dist/email-input-dialog.js +1 -1
  52. package/dist/index.cjs +31 -22
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.d.cts +9 -9
  55. package/dist/index.d.ts +9 -9
  56. package/dist/index.js +20 -20
  57. package/dist/item.cjs +19 -10
  58. package/dist/item.cjs.map +1 -1
  59. package/dist/item.js +5 -5
  60. package/dist/lite-table.js +3 -3
  61. package/dist/menu-look.cjs +19 -10
  62. package/dist/menu-look.cjs.map +1 -1
  63. package/dist/menu-look.js +2 -2
  64. package/dist/record-list.cjs +19 -10
  65. package/dist/record-list.cjs.map +1 -1
  66. package/dist/record-list.js +6 -6
  67. package/dist/settings.js +3 -3
  68. package/dist/swipe-deck.js +1 -1
  69. package/dist/text-input-dialog.js +1 -1
  70. package/dist/writing-field.js +3 -3
  71. package/package.json +2 -2
  72. package/dist/chunk-U46XUQI7.js.map +0 -1
  73. package/dist/chunk-X6ZRHJQP.js.map +0 -1
  74. /package/dist/{chunk-T4D7WAV7.js.map → chunk-42GFQMLA.js.map} +0 -0
  75. /package/dist/{chunk-FRJ4PPA2.js.map → chunk-CZGZV35G.js.map} +0 -0
  76. /package/dist/{chunk-ACZALXD6.js.map → chunk-K3XWUACX.js.map} +0 -0
  77. /package/dist/{chunk-TV2IDHPZ.js.map → chunk-K5ZQROWN.js.map} +0 -0
  78. /package/dist/{chunk-MTE6N7XU.js.map → chunk-NFJ63LIH.js.map} +0 -0
  79. /package/dist/{chunk-XZGYKKCE.js.map → chunk-OUQT72UL.js.map} +0 -0
  80. /package/dist/{chunk-WUD23YTG.js.map → chunk-P56Y43RL.js.map} +0 -0
  81. /package/dist/{chunk-GMNROZQJ.js.map → chunk-QTPW44IJ.js.map} +0 -0
  82. /package/dist/{chunk-QA7EHFRX.js.map → chunk-T3FKFPCW.js.map} +0 -0
  83. /package/dist/{chunk-SOCNWQMX.js.map → chunk-TEMAM5ET.js.map} +0 -0
  84. /package/dist/{chunk-CH2NWSES.js.map → chunk-TIV6M7Q7.js.map} +0 -0
  85. /package/dist/{chunk-6XNYYROM.js.map → chunk-WVEDW5VO.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,10 +1,21 @@
1
1
  # Changelog
2
2
 
3
- ## 0.86.357
3
+ ## 0.86.358
4
4
 
5
5
  UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
6
  Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/design-system/src`.
7
7
 
8
+ ## 0.86.357
9
+
10
+ SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
11
+ so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
12
+ Diff: `git diff bd77a197ad 3cc6206acf -- apps/shared/design-system/src`
13
+
14
+ Changed shipped source files (3):
15
+ - `apps/shared/design-system/src/desktop/state.tsx`
16
+ - `apps/shared/design-system/src/error-sentence.ts`
17
+ - `apps/shared/design-system/src/notice-stack.ts`
18
+
8
19
  ## 0.86.356
9
20
 
10
21
  - Slider forwards an explicitly supplied `aria-valuetext` to its focusable thumb, so controls such as PageCompare announce their formatted value. Keyboard and numeric value behavior are unchanged. Consumer action: none.
package/dist/carousel.js CHANGED
@@ -1,17 +1,16 @@
1
1
  "use client";
2
2
  import {
3
3
  IconButton
4
- } from "./chunk-ACZALXD6.js";
4
+ } from "./chunk-K3XWUACX.js";
5
5
  import "./chunk-6NOLVA4E.js";
6
6
  import "./chunk-5IR3BZOS.js";
7
7
  import "./chunk-AV5C4YLL.js";
8
8
  import "./chunk-XERGQT2M.js";
9
9
  import "./chunk-WQ2QCMMA.js";
10
10
  import "./chunk-YRF22M5S.js";
11
- import "./chunk-GMNROZQJ.js";
11
+ import "./chunk-QTPW44IJ.js";
12
12
  import "./chunk-K4XCB576.js";
13
13
  import "./chunk-5Z5GTXKL.js";
14
- import "./chunk-HS6GMHKZ.js";
15
14
  import "./chunk-DRSBLHOF.js";
16
15
  import "./chunk-TH6DDCWF.js";
17
16
  import "./chunk-2BQAHLU3.js";
@@ -21,22 +20,23 @@ import {
21
20
  import "./chunk-IMQ3RX35.js";
22
21
  import "./chunk-U24MOJWK.js";
23
22
  import "./chunk-NDTDBBMM.js";
24
- import "./chunk-MTE6N7XU.js";
23
+ import "./chunk-NFJ63LIH.js";
25
24
  import "./chunk-WFBPCMPF.js";
26
25
  import {
27
26
  Popover,
28
27
  PopoverContent,
29
28
  PopoverTrigger
30
29
  } from "./chunk-OPF265PU.js";
31
- import "./chunk-6XNYYROM.js";
30
+ import "./chunk-WVEDW5VO.js";
32
31
  import "./chunk-BD77DHUO.js";
33
32
  import "./chunk-BKCJUFD3.js";
34
33
  import {
35
34
  TooltipProvider
36
35
  } from "./chunk-PIQJULQB.js";
37
36
  import "./chunk-MOZRIHJF.js";
38
- import "./chunk-X6ZRHJQP.js";
37
+ import "./chunk-T57DLONB.js";
39
38
  import "./chunk-BNXNIN2S.js";
39
+ import "./chunk-HS6GMHKZ.js";
40
40
  import "./chunk-WFITMVDB.js";
41
41
  import "./chunk-WAT2XW7L.js";
42
42
  import "./chunk-7IOSA55D.js";
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  DropdownMenuContent,
11
11
  DropdownMenuSubContent
12
- } from "./chunk-X6ZRHJQP.js";
12
+ } from "./chunk-T57DLONB.js";
13
13
  import {
14
14
  useScrollFade
15
15
  } from "./chunk-BNXNIN2S.js";
@@ -409,4 +409,4 @@ export {
409
409
  MenuLookPanelSeparator,
410
410
  MenuLookSearch
411
411
  };
412
- //# sourceMappingURL=chunk-T4D7WAV7.js.map
412
+ //# sourceMappingURL=chunk-42GFQMLA.js.map
@@ -228,4 +228,4 @@ export {
228
228
  MatrxTableRowControlsScope,
229
229
  useMatrxTableRowControls
230
230
  };
231
- //# sourceMappingURL=chunk-POJ3RR3K.js.map
231
+ //# sourceMappingURL=chunk-B5D3VIMC.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/table-host/row-drawing.ts","../src/table-host/host.tsx"],"sourcesContent":["/**\n * A ROW IS REDRAWN WHEN WHAT IT SHOWS CHANGED — NEVER BECAUSE A FUNCTION WAS BORN AGAIN\n * (lane TABLE-RERENDER, 2026-10-03).\n *\n * Hosts write `cell`, `customActions`, `getRowId`, `rowClassName` and their handlers inline, so every\n * host render hands the table new functions. Identity cannot say whether a new function draws\n * anything new, so the table used to redraw every row: /artifacts (560 rows) spent ~2.6 s redrawing\n * 1,120 rows to open one artifact. Asking every host to stabilise its callbacks fixed one screen of\n * ~85 at a time.\n *\n * The table now ASKS the row instead. When only the host's functions changed, a row builds its\n * elements (cheap — no component runs) and compares them with what it drew last:\n * · equal → it returns the SAME element object it committed, and React does not descend into it;\n * · different → it draws, and only that row pays.\n * Handlers inside a row that was not redrawn still call the host's LATEST function: every event\n * handler (`on[A-Z]…`) and every function the table marks `lazyCallback` is handed to the DOM as a\n * stable trampoline whose target is refreshed on each comparison (the latest-ref pattern, applied\n * to every handler a row holds instead of to a list the table has to keep in sync).\n *\n * Any other function in the tree (a render prop, a formatter a child calls while it renders, a\n * component type) is compared by identity, so a new one redraws the row — exactly as before. That\n * keeps the rule honest: a row is never left showing what an old closure drew. The one exception is\n * a prop its component DECLARED a lazy data getter (`declareLazyDataProps`): it is compared by what\n * it returns.\n */\nimport { cloneElement, isValidElement, type ReactElement, type ReactNode } from \"react\";\n\nconst LAZY = Symbol.for(\"@ai-matrx/design-system/data-table/lazy-callback\");\nconst MAX_DEPTH = 32;\nconst HANDLER_KEY = /^on[A-Z]/;\n\ntype AnyFunction = (...args: never[]) => unknown;\n\n/**\n * Marks a function the table hands into a row as one that runs LATER (on a click, a copy, a menu\n * choice) and never while a child renders — so a row may keep a trampoline to it instead of\n * redrawing when only its identity changed.\n */\nexport function lazyCallback<F extends AnyFunction>(fn: F): F {\n (fn as F & { [LAZY]?: true })[LAZY] = true;\n return fn;\n}\n\nfunction isLazy(fn: unknown): boolean {\n return (fn as { [LAZY]?: true })[LAZY] === true;\n}\n\nconst LAZY_DATA_PROPS = Symbol.for(\"@ai-matrx/design-system/data-table/lazy-data-props\");\n\n/**\n * Declares the props of `component` that take a GETTER of data the component reads only later —\n * a row menu's `config={() => menu}`, resolved when the menu opens. Without it a getter is just an\n * unknown function, compared by identity, and a host that builds it inline (every row menu does)\n * redraws every row on every render of its own: /crm redrew all 25 rows on each checkbox tick.\n *\n * A declared prop is compared by what the getter RETURNS (its handlers by trampoline, everything\n * else exactly as a drawing is): the same data → the row keeps its drawing and the component is\n * handed a stable trampoline to the host's LATEST getter, so it opens with fresh items; different\n * data (a checkbox in an open menu flipped) → that row alone redraws. Declare once, on the\n * component — never per call site.\n *\n * The contract: a declared getter is PURE and CHEAP — the row calls the previous and the new one on\n * every host render to compare them. A getter that fetches, dispatches or builds something heavy\n * must not be declared.\n */\nexport function declareLazyDataProps<C extends object>(component: C, keys: readonly string[]): C {\n (component as C & { [LAZY_DATA_PROPS]?: ReadonlySet<string> })[LAZY_DATA_PROPS] = new Set(keys);\n return component;\n}\n\nfunction lazyDataKeys(type: unknown): ReadonlySet<string> | undefined {\n if ((typeof type !== \"function\" && typeof type !== \"object\") || type === null) return undefined;\n return (type as { [LAZY_DATA_PROPS]?: ReadonlySet<string> })[LAZY_DATA_PROPS];\n}\n\nconst UNRESOLVED = Symbol(\"unresolved\");\n\n/** A declared getter's data — or `UNRESOLVED` when calling it threw (the row then simply redraws). */\nfunction resolveLazyData(value: unknown): unknown {\n if (typeof value !== \"function\") return value;\n try {\n return (value as () => unknown)();\n } catch {\n return UNRESOLVED;\n }\n}\n\nfunction trampolinable(key: string, fn: unknown): boolean {\n return isLazy(fn) || HANDLER_KEY.test(key);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\ninterface Slot {\n fn: (...args: unknown[]) => unknown;\n readonly stable: (...args: unknown[]) => unknown;\n}\n\nfunction makeSlot(fn: (...args: unknown[]) => unknown): Slot {\n const slot: Slot = {\n fn,\n // A Proxy rather than a bare wrapper: a handler that carries its own members (a debounced\n // function's `cancel`) keeps them, read from the latest function.\n stable: new Proxy((() => undefined) as (...args: unknown[]) => unknown, {\n apply: (_target, thisArg, args: unknown[]) => Reflect.apply(slot.fn, thisArg, args),\n get: (_target, key) => Reflect.get(slot.fn, key),\n }),\n };\n return slot;\n}\n\ntype Updates = Array<[path: string, fn: (...args: unknown[]) => unknown]>;\n\nfunction sameEntries(\n a: Record<string, unknown>,\n b: Record<string, unknown>,\n path: string,\n depth: number,\n updates: Updates,\n lazyKeys?: ReadonlySet<string>,\n): boolean {\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) return false;\n for (const key of keys) {\n if (!Object.prototype.hasOwnProperty.call(b, key)) return false;\n // A ref is never a handler: a new callback ref must be attached by React.\n if (key === \"ref\") {\n if (!Object.is(a[key], b[key])) return false;\n continue;\n }\n if (lazyKeys?.has(key) && (typeof a[key] === \"function\" || typeof b[key] === \"function\")) {\n if (Object.is(a[key], b[key])) continue;\n // A getter that became a plain value (or the reverse) is a new drawing: the committed element\n // still holds a trampoline to the OLD getter, which nothing would re-point.\n if (typeof a[key] !== typeof b[key]) return false;\n const before = resolveLazyData(a[key]);\n const after = resolveLazyData(b[key]);\n if (before === UNRESOLVED || after === UNRESOLVED) return false;\n // Handlers inside the data are reached through the getter's own trampoline, so the ones this\n // comparison collects are dropped: the component calls the LATEST getter and gets them fresh.\n if (!sameDrawing(before, after, key, `${path}/${key}()`, depth + 1, [])) return false;\n if (typeof b[key] === \"function\") updates.push([`${path}/${key}`, b[key] as (...args: unknown[]) => unknown]);\n continue;\n }\n if (!sameDrawing(a[key], b[key], key, `${path}/${key}`, depth + 1, updates)) return false;\n }\n return true;\n}\n\n/**\n * Whether `next` draws exactly what `previous` drew. Handlers that differ only by identity are\n * collected into `updates` (by path) so the caller can point the committed trampolines at them.\n */\nfunction sameDrawing(previous: unknown, next: unknown, key: string, path: string, depth: number, updates: Updates): boolean {\n if (Object.is(previous, next)) return true;\n if (typeof previous === \"function\" && typeof next === \"function\") {\n if (trampolinable(key, previous) && trampolinable(key, next)) {\n updates.push([path, next as (...args: unknown[]) => unknown]);\n return true;\n }\n return false;\n }\n if (depth > MAX_DEPTH) return false;\n if (isValidElement(previous) && isValidElement(next)) {\n if (previous.type !== next.type || previous.key !== next.key) return false;\n return sameEntries(\n previous.props as Record<string, unknown>,\n next.props as Record<string, unknown>,\n path,\n depth,\n updates,\n lazyDataKeys(previous.type),\n );\n }\n if (Array.isArray(previous) && Array.isArray(next)) {\n if (previous.length !== next.length) return false;\n for (let i = 0; i < previous.length; i += 1) {\n if (!sameDrawing(previous[i], next[i], key, `${path}/${i}`, depth + 1, updates)) return false;\n }\n return true;\n }\n if (isPlainObject(previous) && isPlainObject(next)) return sameEntries(previous, next, path, depth, updates);\n return false;\n}\n\n/** `value` with every trampolinable function replaced by its stable trampoline. */\nfunction stabilize(value: unknown, key: string, path: string, depth: number, slots: Map<string, Slot>, reuse: Map<string, Slot> | undefined, lazyData = false): unknown {\n if (typeof value === \"function\") {\n if (!lazyData && !trampolinable(key, value)) return value;\n const fn = value as (...args: unknown[]) => unknown;\n const kept = reuse?.get(path);\n const slot = kept ?? makeSlot(fn);\n slot.fn = fn;\n slots.set(path, slot);\n return slot.stable;\n }\n if (depth > MAX_DEPTH) return value;\n if (isValidElement(value)) {\n const props = value.props as Record<string, unknown>;\n const lazyKeys = lazyDataKeys(value.type);\n let changed: Record<string, unknown> | null = null;\n for (const propKey of Object.keys(props)) {\n if (propKey === \"ref\") continue;\n const before = props[propKey];\n const after = stabilize(before, propKey, `${path}/${propKey}`, depth + 1, slots, reuse, lazyKeys?.has(propKey) ?? false);\n if (after !== before) (changed ??= {})[propKey] = after;\n }\n if (!changed) return value;\n const clone = cloneElement(value as ReactElement, changed);\n // React (dev) marks JSX's static children as key-checked on the ELEMENT; a clone starts\n // unmarked, and a clone inside a static children array would then warn about a missing key.\n const before = (value as { _store?: { validated?: unknown } })._store;\n const after = (clone as { _store?: { validated?: unknown } })._store;\n if (before && after && \"validated\" in before) {\n try { after.validated = before.validated; } catch { /* frozen in some builds: only a dev warning is at stake */ }\n }\n return clone;\n }\n if (Array.isArray(value)) {\n let out: unknown[] | null = null;\n for (let i = 0; i < value.length; i += 1) {\n const after = stabilize(value[i], key, `${path}/${i}`, depth + 1, slots, reuse);\n if (after !== value[i]) (out ??= value.slice())[i] = after;\n }\n return out ?? value;\n }\n if (isPlainObject(value)) {\n let out: Record<string, unknown> | null = null;\n for (const entryKey of Object.keys(value)) {\n const before = value[entryKey];\n const after = stabilize(before, entryKey, `${path}/${entryKey}`, depth + 1, slots, reuse);\n if (after !== before) (out ??= { ...value })[entryKey] = after;\n }\n return out ?? value;\n }\n return value;\n}\n\ninterface RowDrawing {\n /** What the host and the table built last time — compared, never rendered. */\n raw: unknown;\n /** What React was handed: `raw` with trampolines. Returned unchanged while the drawing holds. */\n out: ReactNode;\n slots: Map<string, Slot>;\n}\n\n/** One table's drawings, by row id. */\nexport class RowDrawings {\n private readonly rows = new Map<string, RowDrawing>();\n\n /**\n * The element to hand React for this row. The SAME object as last time when `raw` draws what the\n * last one drew (its handlers are re-pointed); a new one otherwise.\n */\n draw(rowId: string, raw: ReactNode, fresh = false): ReactNode {\n const previous = this.rows.get(rowId);\n // `fresh`: the row's own facts moved — what it shows may differ even when its elements match.\n if (previous && !fresh) {\n const updates: Updates = [];\n if (sameDrawing(previous.raw, raw, \"\", \"\", 0, updates) && updates.every(([path]) => previous.slots.has(path))) {\n for (const [path, fn] of updates) previous.slots.get(path)!.fn = fn;\n previous.raw = raw;\n return previous.out;\n }\n }\n const slots = new Map<string, Slot>();\n const out = stabilize(raw, \"\", \"\", 0, slots, previous?.slots) as ReactNode;\n this.rows.set(rowId, { raw, out, slots });\n return out;\n }\n\n /** Forget rows that are no longer in the table (bounded by what was ever drawn). */\n prune(liveIds: ReadonlySet<string>): void {\n for (const id of this.rows.keys()) if (!liveIds.has(id)) this.rows.delete(id);\n }\n\n get size(): number {\n return this.rows.size;\n }\n}\n","\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"../data-table/copy-types\";\nimport type { MatrxColumnDef, MatrxDataTableDensity, MatrxDataTableLook, MatrxDataTableRecordControls, TableSavedViewsProps } from \"../data-table/types\";\nimport type {\n MatrxTableMenuIconName,\n MatrxTableMenuItem,\n MatrxTableMenuPayload,\n MatrxTableMenuSectionsResolver,\n MatrxTableMenuTarget,\n} from \"../data-table/menu-targets\";\n\nexport type {\n MatrxTableMenuIconName,\n MatrxTableMenuItem,\n MatrxTableMenuSection,\n MatrxTableMenuSectionsResolver,\n} from \"../data-table/menu-targets\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n ContentTransferReference,\n CopyControlProps,\n CopyEnvelopeMeta,\n CopyExportConfig,\n TableCopyController,\n} from \"../data-table/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; /** Increments on every open request, including a repeat open of the row already shown — a host whose panel can sit in the background (a tab) brings it forward when this changes. */ openRequest?: number; 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; /** The table look the window opens from (lane mac-blockers): `\"mac\"` asks the host window for the Mac header. Absent: the default look. */ look?: MatrxDataTableLook; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; /** Opening it starts a new tab. */ openInNewTab?: boolean; /** Its open / peek buttons stay shown, not only on hover. */ alwaysShowActions?: boolean; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors {\n href?: string;\n peekKind?: string;\n canPeek?: boolean;\n /**\n * THE RECORD'S OWN MENU (lane DRILL-PARITY-LAST): what its kind offers wherever a table names it —\n * a person's admin destinations, an organization's pages — as neutral items the table draws in a\n * row's menu and on a right-click. Absent = the record has only its open and preview doors.\n */\n menu?: MatrxTableMenuItem[];\n}\n/**\n * The host's door onto the table's right-click levels.\n *\n * A canonical table registers ONE resolver per instance. The host's own menu\n * reads which of the four levels was clicked (`readMenuTarget`) and asks for\n * that level's descriptor — the package never interprets what comes back, and\n * the host never reaches into the table for the row or the range.\n */\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (target: MatrxTableMenuTarget) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps {\n label: string;\n children: ReactNode;\n /**\n * The consumer's own sections, asked per right-click. Present only when the\n * table's consumer declared `contextMenu.sections`; the host reads the level\n * off the clicked element (`readMenuTarget`), calls this, and draws what comes\n * back in its own menu. Absent, the boundary behaves exactly as before.\n */\n sections?: MatrxTableMenuSectionsResolver | undefined;\n /** The table asked for the host's designed menu (`MatrxDataTableContextMenuConfig.designedMenu`). */\n designedMenu?: boolean | undefined;\n}\n/**\n * The host's view of a failed read with NO rows to show (RC-B12 round 13):\n * its error display (with the host's actions — matrx-frontend's Alchemy Menu)\n * and a retry. Without a host port the table draws a package `ErrorBox`.\n */\nexport interface TableReadFailureProps { error: unknown; what: string; onRetry?: (() => void) | undefined; }\n/**\n * The host's notice above rows kept from an earlier read when the latest read\n * failed: the rows may be out of date. Without a host port the table draws a\n * package `ErrorBox` in warning colors.\n */\nexport interface TableStaleNoticeProps { error: unknown; what: string; onRetry?: (() => void) | undefined; }\n/** The host's glyph for a menu icon name. A host without one draws labels only. */\nexport interface TableMenuIconProps { name: MatrxTableMenuIconName; className?: string | undefined; }\n/** The host's custom-field columns for a registry token over the given organizations (lane 7 W5). */\nexport interface TableCustomFieldColumns<T> { columns: MatrxColumnDef<T>[]; }\nexport interface MatrxDataTableHost { /** A HOOK, bound once by the host: the custom-field columns of `token` (null = none) for `organizationIds`. */ useCustomFieldColumns?: <T>(token: string | null, organizationIds: readonly string[]) => TableCustomFieldColumns<T> | null; 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; createDefaultMenuContext?: (payload: MatrxTableMenuPayload) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; MenuIcon?: ComponentType<TableMenuIconProps>; /** A failed read with no rows (RC-B12 r13). */ ReadFailure?: ComponentType<TableReadFailureProps>; /** A failed refresh over kept rows (RC-B12 r13). */ StaleNotice?: ComponentType<TableStaleNoticeProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; /** Host default look (`default` | `mac`); a table's explicit `look` takes precedence. One switch turns every table under the host, and every mode built on it, to the Mac look. */ defaultLook?: MatrxDataTableLook; notify?: { success(message: string): void; error(message: string): void }; /** Client-side navigation (the app router), for `rowClick=\"page\"`. Absent: a full page load. */ navigate?: (href: 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 /** Mount Alchemy's canonical palette in the host row menu. */\n mountMenu(target: HTMLElement | null, onClose?: () => void, restoreFocus?: () => void): 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\n/** Light door for components a row draws (a row menu): declare a lazy data prop without loading the table. */\nexport { declareLazyDataProps } from \"./row-drawing\";\n"],"mappings":"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","names":["before","after"]}
1
+ {"version":3,"sources":["../src/table-host/row-drawing.ts","../src/table-host/host.tsx"],"sourcesContent":["/**\n * A ROW IS REDRAWN WHEN WHAT IT SHOWS CHANGED — NEVER BECAUSE A FUNCTION WAS BORN AGAIN\n * (lane TABLE-RERENDER, 2026-10-03).\n *\n * Hosts write `cell`, `customActions`, `getRowId`, `rowClassName` and their handlers inline, so every\n * host render hands the table new functions. Identity cannot say whether a new function draws\n * anything new, so the table used to redraw every row: /artifacts (560 rows) spent ~2.6 s redrawing\n * 1,120 rows to open one artifact. Asking every host to stabilise its callbacks fixed one screen of\n * ~85 at a time.\n *\n * The table now ASKS the row instead. When only the host's functions changed, a row builds its\n * elements (cheap — no component runs) and compares them with what it drew last:\n * · equal → it returns the SAME element object it committed, and React does not descend into it;\n * · different → it draws, and only that row pays.\n * Handlers inside a row that was not redrawn still call the host's LATEST function: every event\n * handler (`on[A-Z]…`) and every function the table marks `lazyCallback` is handed to the DOM as a\n * stable trampoline whose target is refreshed on each comparison (the latest-ref pattern, applied\n * to every handler a row holds instead of to a list the table has to keep in sync).\n *\n * Any other function in the tree (a render prop, a formatter a child calls while it renders, a\n * component type) is compared by identity, so a new one redraws the row — exactly as before. That\n * keeps the rule honest: a row is never left showing what an old closure drew. The one exception is\n * a prop its component DECLARED a lazy data getter (`declareLazyDataProps`): it is compared by what\n * it returns.\n */\nimport { cloneElement, isValidElement, type ReactElement, type ReactNode } from \"react\";\n\nconst LAZY = Symbol.for(\"@ai-matrx/design-system/data-table/lazy-callback\");\nconst MAX_DEPTH = 32;\nconst HANDLER_KEY = /^on[A-Z]/;\n\ntype AnyFunction = (...args: never[]) => unknown;\n\n/**\n * Marks a function the table hands into a row as one that runs LATER (on a click, a copy, a menu\n * choice) and never while a child renders — so a row may keep a trampoline to it instead of\n * redrawing when only its identity changed.\n */\nexport function lazyCallback<F extends AnyFunction>(fn: F): F {\n (fn as F & { [LAZY]?: true })[LAZY] = true;\n return fn;\n}\n\nfunction isLazy(fn: unknown): boolean {\n return (fn as { [LAZY]?: true })[LAZY] === true;\n}\n\nconst LAZY_DATA_PROPS = Symbol.for(\"@ai-matrx/design-system/data-table/lazy-data-props\");\n\n/**\n * Declares the props of `component` that take a GETTER of data the component reads only later —\n * a row menu's `config={() => menu}`, resolved when the menu opens. Without it a getter is just an\n * unknown function, compared by identity, and a host that builds it inline (every row menu does)\n * redraws every row on every render of its own: /crm redrew all 25 rows on each checkbox tick.\n *\n * A declared prop is compared by what the getter RETURNS (its handlers by trampoline, everything\n * else exactly as a drawing is): the same data → the row keeps its drawing and the component is\n * handed a stable trampoline to the host's LATEST getter, so it opens with fresh items; different\n * data (a checkbox in an open menu flipped) → that row alone redraws. Declare once, on the\n * component — never per call site.\n *\n * The contract: a declared getter is PURE and CHEAP — the row calls the previous and the new one on\n * every host render to compare them. A getter that fetches, dispatches or builds something heavy\n * must not be declared.\n */\nexport function declareLazyDataProps<C extends object>(component: C, keys: readonly string[]): C {\n (component as C & { [LAZY_DATA_PROPS]?: ReadonlySet<string> })[LAZY_DATA_PROPS] = new Set(keys);\n return component;\n}\n\nfunction lazyDataKeys(type: unknown): ReadonlySet<string> | undefined {\n if ((typeof type !== \"function\" && typeof type !== \"object\") || type === null) return undefined;\n return (type as { [LAZY_DATA_PROPS]?: ReadonlySet<string> })[LAZY_DATA_PROPS];\n}\n\nconst UNRESOLVED = Symbol(\"unresolved\");\n\n/** A declared getter's data — or `UNRESOLVED` when calling it threw (the row then simply redraws). */\nfunction resolveLazyData(value: unknown): unknown {\n if (typeof value !== \"function\") return value;\n try {\n return (value as () => unknown)();\n } catch {\n return UNRESOLVED;\n }\n}\n\nfunction trampolinable(key: string, fn: unknown): boolean {\n return isLazy(fn) || HANDLER_KEY.test(key);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\ninterface Slot {\n fn: (...args: unknown[]) => unknown;\n readonly stable: (...args: unknown[]) => unknown;\n}\n\nfunction makeSlot(fn: (...args: unknown[]) => unknown): Slot {\n const slot: Slot = {\n fn,\n // A Proxy rather than a bare wrapper: a handler that carries its own members (a debounced\n // function's `cancel`) keeps them, read from the latest function.\n stable: new Proxy((() => undefined) as (...args: unknown[]) => unknown, {\n apply: (_target, thisArg, args: unknown[]) => Reflect.apply(slot.fn, thisArg, args),\n get: (_target, key) => Reflect.get(slot.fn, key),\n }),\n };\n return slot;\n}\n\ntype Updates = Array<[path: string, fn: (...args: unknown[]) => unknown]>;\n\nfunction sameEntries(\n a: Record<string, unknown>,\n b: Record<string, unknown>,\n path: string,\n depth: number,\n updates: Updates,\n lazyKeys?: ReadonlySet<string>,\n): boolean {\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) return false;\n for (const key of keys) {\n if (!Object.prototype.hasOwnProperty.call(b, key)) return false;\n // A ref is never a handler: a new callback ref must be attached by React.\n if (key === \"ref\") {\n if (!Object.is(a[key], b[key])) return false;\n continue;\n }\n if (lazyKeys?.has(key) && (typeof a[key] === \"function\" || typeof b[key] === \"function\")) {\n if (Object.is(a[key], b[key])) continue;\n // A getter that became a plain value (or the reverse) is a new drawing: the committed element\n // still holds a trampoline to the OLD getter, which nothing would re-point.\n if (typeof a[key] !== typeof b[key]) return false;\n const before = resolveLazyData(a[key]);\n const after = resolveLazyData(b[key]);\n if (before === UNRESOLVED || after === UNRESOLVED) return false;\n // Handlers inside the data are reached through the getter's own trampoline, so the ones this\n // comparison collects are dropped: the component calls the LATEST getter and gets them fresh.\n if (!sameDrawing(before, after, key, `${path}/${key}()`, depth + 1, [])) return false;\n if (typeof b[key] === \"function\") updates.push([`${path}/${key}`, b[key] as (...args: unknown[]) => unknown]);\n continue;\n }\n if (!sameDrawing(a[key], b[key], key, `${path}/${key}`, depth + 1, updates)) return false;\n }\n return true;\n}\n\n/**\n * Whether `next` draws exactly what `previous` drew. Handlers that differ only by identity are\n * collected into `updates` (by path) so the caller can point the committed trampolines at them.\n */\nfunction sameDrawing(previous: unknown, next: unknown, key: string, path: string, depth: number, updates: Updates): boolean {\n if (Object.is(previous, next)) return true;\n if (typeof previous === \"function\" && typeof next === \"function\") {\n if (trampolinable(key, previous) && trampolinable(key, next)) {\n updates.push([path, next as (...args: unknown[]) => unknown]);\n return true;\n }\n return false;\n }\n if (depth > MAX_DEPTH) return false;\n if (isValidElement(previous) && isValidElement(next)) {\n if (previous.type !== next.type || previous.key !== next.key) return false;\n return sameEntries(\n previous.props as Record<string, unknown>,\n next.props as Record<string, unknown>,\n path,\n depth,\n updates,\n lazyDataKeys(previous.type),\n );\n }\n if (Array.isArray(previous) && Array.isArray(next)) {\n if (previous.length !== next.length) return false;\n for (let i = 0; i < previous.length; i += 1) {\n if (!sameDrawing(previous[i], next[i], key, `${path}/${i}`, depth + 1, updates)) return false;\n }\n return true;\n }\n if (isPlainObject(previous) && isPlainObject(next)) return sameEntries(previous, next, path, depth, updates);\n return false;\n}\n\n/** `value` with every trampolinable function replaced by its stable trampoline. */\nfunction stabilize(value: unknown, key: string, path: string, depth: number, slots: Map<string, Slot>, reuse: Map<string, Slot> | undefined, lazyData = false): unknown {\n if (typeof value === \"function\") {\n if (!lazyData && !trampolinable(key, value)) return value;\n const fn = value as (...args: unknown[]) => unknown;\n const kept = reuse?.get(path);\n const slot = kept ?? makeSlot(fn);\n slot.fn = fn;\n slots.set(path, slot);\n return slot.stable;\n }\n if (depth > MAX_DEPTH) return value;\n if (isValidElement(value)) {\n const props = value.props as Record<string, unknown>;\n const lazyKeys = lazyDataKeys(value.type);\n let changed: Record<string, unknown> | null = null;\n for (const propKey of Object.keys(props)) {\n if (propKey === \"ref\") continue;\n const before = props[propKey];\n const after = stabilize(before, propKey, `${path}/${propKey}`, depth + 1, slots, reuse, lazyKeys?.has(propKey) ?? false);\n if (after !== before) (changed ??= {})[propKey] = after;\n }\n if (!changed) return value;\n const clone = cloneElement(value as ReactElement, changed);\n // React (dev) marks JSX's static children as key-checked on the ELEMENT; a clone starts\n // unmarked, and a clone inside a static children array would then warn about a missing key.\n const before = (value as { _store?: { validated?: unknown } })._store;\n const after = (clone as { _store?: { validated?: unknown } })._store;\n if (before && after && \"validated\" in before) {\n try { after.validated = before.validated; } catch { /* frozen in some builds: only a dev warning is at stake */ }\n }\n return clone;\n }\n if (Array.isArray(value)) {\n let out: unknown[] | null = null;\n for (let i = 0; i < value.length; i += 1) {\n const after = stabilize(value[i], key, `${path}/${i}`, depth + 1, slots, reuse);\n if (after !== value[i]) (out ??= value.slice())[i] = after;\n }\n return out ?? value;\n }\n if (isPlainObject(value)) {\n let out: Record<string, unknown> | null = null;\n for (const entryKey of Object.keys(value)) {\n const before = value[entryKey];\n const after = stabilize(before, entryKey, `${path}/${entryKey}`, depth + 1, slots, reuse);\n if (after !== before) (out ??= { ...value })[entryKey] = after;\n }\n return out ?? value;\n }\n return value;\n}\n\ninterface RowDrawing {\n /** What the host and the table built last time — compared, never rendered. */\n raw: unknown;\n /** What React was handed: `raw` with trampolines. Returned unchanged while the drawing holds. */\n out: ReactNode;\n slots: Map<string, Slot>;\n}\n\n/** One table's drawings, by row id. */\nexport class RowDrawings {\n private readonly rows = new Map<string, RowDrawing>();\n\n /**\n * The element to hand React for this row. The SAME object as last time when `raw` draws what the\n * last one drew (its handlers are re-pointed); a new one otherwise.\n */\n draw(rowId: string, raw: ReactNode, fresh = false): ReactNode {\n const previous = this.rows.get(rowId);\n // `fresh`: the row's own facts moved — what it shows may differ even when its elements match.\n if (previous && !fresh) {\n const updates: Updates = [];\n if (sameDrawing(previous.raw, raw, \"\", \"\", 0, updates) && updates.every(([path]) => previous.slots.has(path))) {\n for (const [path, fn] of updates) previous.slots.get(path)!.fn = fn;\n previous.raw = raw;\n return previous.out;\n }\n }\n const slots = new Map<string, Slot>();\n const out = stabilize(raw, \"\", \"\", 0, slots, previous?.slots) as ReactNode;\n this.rows.set(rowId, { raw, out, slots });\n return out;\n }\n\n /** Forget rows that are no longer in the table (bounded by what was ever drawn). */\n prune(liveIds: ReadonlySet<string>): void {\n for (const id of this.rows.keys()) if (!liveIds.has(id)) this.rows.delete(id);\n }\n\n get size(): number {\n return this.rows.size;\n }\n}\n","\"use client\";\nimport { createContext, useContext, type Context, type ComponentType, type ReactNode, type MouseEventHandler } from \"react\";\nimport type { CopyControlProps } from \"../data-table/copy-types\";\nimport type { MatrxColumnDef, MatrxDataTableDensity, MatrxDataTableLook, MatrxDataTableRecordControls, TableSavedViewsProps } from \"../data-table/types\";\nimport type {\n MatrxTableMenuIconName,\n MatrxTableMenuItem,\n MatrxTableMenuPayload,\n MatrxTableMenuSectionsResolver,\n MatrxTableMenuTarget,\n} from \"../data-table/menu-targets\";\n\nexport type {\n MatrxTableMenuIconName,\n MatrxTableMenuItem,\n MatrxTableMenuSection,\n MatrxTableMenuSectionsResolver,\n} from \"../data-table/menu-targets\";\n\nexport type {\n AgentPayloadInput,\n AiCustomSource,\n AiVariant,\n ContentTransferReference,\n CopyControlProps,\n CopyEnvelopeMeta,\n CopyExportConfig,\n TableCopyController,\n} from \"../data-table/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; /** Increments on every open request, including a repeat open of the row already shown — a host whose panel can sit in the background (a tab) brings it forward when this changes. */ openRequest?: number; 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; /** The table look the window opens from (lane mac-blockers): `\"mac\"` asks the host window for the Mac header. Absent: the default look. */ look?: MatrxDataTableLook; }\nexport interface TableEntityRefProps { token: string; id: string; href?: string; children: ReactNode; className?: string; /** Opening it starts a new tab. */ openInNewTab?: boolean; /** Its open / peek buttons stay shown, not only on hover. */ alwaysShowActions?: boolean; }\nexport interface TablePeekProps { kind: string; id: string; href?: string; onClose: () => void; }\nexport interface TableDoors {\n href?: string;\n peekKind?: string;\n canPeek?: boolean;\n /**\n * THE RECORD'S OWN MENU (lane DRILL-PARITY-LAST): what its kind offers wherever a table names it —\n * a person's admin destinations, an organization's pages — as neutral items the table draws in a\n * row's menu and on a right-click. Absent = the record has only its open and preview doors.\n */\n menu?: MatrxTableMenuItem[];\n}\n/**\n * The host's door onto the table's right-click levels.\n *\n * A canonical table registers ONE resolver per instance. The host's own menu\n * reads which of the four levels was clicked (`readMenuTarget`) and asks for\n * that level's descriptor — the package never interprets what comes back, and\n * the host never reaches into the table for the row or the range.\n */\nexport interface TableRowContextRegistry { register(tableId: string, resolve: (target: MatrxTableMenuTarget) => unknown): () => void; }\nexport interface TableContextMenuBoundaryProps {\n label: string;\n children: ReactNode;\n /**\n * The consumer's own sections, asked per right-click. Present only when the\n * table's consumer declared `contextMenu.sections`; the host reads the level\n * off the clicked element (`readMenuTarget`), calls this, and draws what comes\n * back in its own menu. Absent, the boundary behaves exactly as before.\n */\n sections?: MatrxTableMenuSectionsResolver | undefined;\n /** The table asked for the host's designed menu (`MatrxDataTableContextMenuConfig.designedMenu`). */\n designedMenu?: boolean | undefined;\n}\n/**\n * The host's view of a failed read with NO rows to show (RC-B12 round 13):\n * its error display (with the host's actions — matrx-frontend's Alchemy Menu)\n * and a retry. Without a host port the table draws a package `ErrorBox`.\n */\nexport interface TableReadFailureProps { error: unknown; what: string; onRetry?: (() => void) | undefined; }\n/**\n * The host's notice above rows kept from an earlier read when the latest read\n * failed: the rows may be out of date. Without a host port the table draws a\n * package `ErrorBox` in warning colors.\n */\nexport interface TableStaleNoticeProps { error: unknown; what: string; onRetry?: (() => void) | undefined; }\n/** The host's glyph for a menu icon name. A host without one draws labels only. */\nexport interface TableMenuIconProps { name: MatrxTableMenuIconName; className?: string | undefined; }\n/** The host's custom-field columns for a registry token over the given organizations (lane 7 W5). */\nexport interface TableCustomFieldColumns<T> { columns: MatrxColumnDef<T>[]; }\nexport interface MatrxDataTableHost { /** A HOOK, bound once by the host: the custom-field columns of `token` (null = none) for `organizationIds`. */ useCustomFieldColumns?: <T>(token: string | null, organizationIds: readonly string[]) => TableCustomFieldColumns<T> | null; 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; createDefaultMenuContext?: (payload: MatrxTableMenuPayload) => unknown; ContextMenuBoundary?: ComponentType<TableContextMenuBoundaryProps>; MenuIcon?: ComponentType<TableMenuIconProps>; /** A failed read with no rows (RC-B12 r13). */ ReadFailure?: ComponentType<TableReadFailureProps>; /** A failed refresh over kept rows (RC-B12 r13). */ StaleNotice?: ComponentType<TableStaleNoticeProps>; /** Host default; a table's explicit density takes precedence. */ defaultDensity?: MatrxDataTableDensity; /** Host default look (`default` | `mac`); a table's explicit `look` takes precedence. One switch turns every table under the host, and every mode built on it, to the Mac look. */ defaultLook?: MatrxDataTableLook; notify?: { success(message: string, options?: { description?: string }): void; error(message: string, options?: { description?: string }): void }; /** Client-side navigation (the app router), for `rowClick=\"page\"`. Absent: a full page load. */ navigate?: (href: 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 /** Mount Alchemy's canonical palette in the host row menu. */\n mountMenu(target: HTMLElement | null, onClose?: () => void, restoreFocus?: () => void): 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\n/** Light door for components a row draws (a row menu): declare a lazy data prop without loading the table. */\nexport { declareLazyDataProps } from \"./row-drawing\";\n"],"mappings":"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","names":["before","after"]}
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-FXT7PZAF.js";
10
10
  import {
11
11
  useMatrxDataTableHost
12
- } from "./chunk-POJ3RR3K.js";
12
+ } from "./chunk-B5D3VIMC.js";
13
13
  import {
14
14
  Button
15
15
  } from "./chunk-7IOSA55D.js";
@@ -97,4 +97,4 @@ export {
97
97
  CopyButtons,
98
98
  DeferredCopyButtons
99
99
  };
100
- //# sourceMappingURL=chunk-FRJ4PPA2.js.map
100
+ //# sourceMappingURL=chunk-CZGZV35G.js.map
@@ -49,7 +49,7 @@ import {
49
49
  import {
50
50
  Button as Button2,
51
51
  Chip
52
- } from "./chunk-6XNYYROM.js";
52
+ } from "./chunk-WVEDW5VO.js";
53
53
  import {
54
54
  Tooltip,
55
55
  TooltipContent,
@@ -66,7 +66,7 @@ import {
66
66
  DropdownMenuSubContent,
67
67
  DropdownMenuSubTrigger,
68
68
  DropdownMenuTrigger
69
- } from "./chunk-X6ZRHJQP.js";
69
+ } from "./chunk-T57DLONB.js";
70
70
  import {
71
71
  Select,
72
72
  SelectChevron,
@@ -4007,4 +4007,4 @@ export {
4007
4007
  TileCard,
4008
4008
  TileCardGrid
4009
4009
  };
4010
- //# sourceMappingURL=chunk-ACZALXD6.js.map
4010
+ //# sourceMappingURL=chunk-K3XWUACX.js.map
@@ -3,13 +3,13 @@ import {
3
3
  MENU_LOOK_CLASS,
4
4
  MenuLookPanelItem,
5
5
  MenuLookRowBody
6
- } from "./chunk-T4D7WAV7.js";
6
+ } from "./chunk-42GFQMLA.js";
7
7
  import {
8
8
  ARCHIVE_LABEL
9
9
  } from "./chunk-VQQ3O7J5.js";
10
10
  import {
11
11
  ConfirmDialog
12
- } from "./chunk-GMNROZQJ.js";
12
+ } from "./chunk-QTPW44IJ.js";
13
13
  import {
14
14
  ErrorBox
15
15
  } from "./chunk-5Z5GTXKL.js";
@@ -21,7 +21,7 @@ import {
21
21
  } from "./chunk-TDMVH77G.js";
22
22
  import {
23
23
  Button
24
- } from "./chunk-6XNYYROM.js";
24
+ } from "./chunk-WVEDW5VO.js";
25
25
  import {
26
26
  Tooltip,
27
27
  TooltipContent,
@@ -778,4 +778,4 @@ export {
778
778
  CanvasLayout,
779
779
  ModeSwitch
780
780
  };
781
- //# sourceMappingURL=chunk-TV2IDHPZ.js.map
781
+ //# sourceMappingURL=chunk-K5ZQROWN.js.map
@@ -1,16 +1,19 @@
1
1
  "use client";
2
2
  import {
3
3
  Button
4
- } from "./chunk-6XNYYROM.js";
4
+ } from "./chunk-WVEDW5VO.js";
5
5
  import {
6
6
  Tooltip,
7
7
  TooltipContent,
8
8
  TooltipProvider,
9
9
  TooltipTrigger
10
10
  } from "./chunk-PIQJULQB.js";
11
+ import {
12
+ peopleErrorSentence
13
+ } from "./chunk-HS6GMHKZ.js";
11
14
  import {
12
15
  useMatrxDataTableHost
13
- } from "./chunk-POJ3RR3K.js";
16
+ } from "./chunk-B5D3VIMC.js";
14
17
  import {
15
18
  Lightbulb,
16
19
  ShieldOff
@@ -56,13 +59,14 @@ function useTableNotice() {
56
59
  const [message, setMessage] = useState(null);
57
60
  const notify = useMemo(
58
61
  () => ({
59
- success(text) {
60
- if (host.notify) host.notify.success(text);
61
- else setMessage({ text, error: false });
62
+ // A card is a short title and an optional line (NOTICE_TEXT_BUDGET); the inline fallback joins them.
63
+ success(text, options) {
64
+ if (host.notify) host.notify.success(text, options);
65
+ else setMessage({ text: options?.description ? `${text}. ${options.description}` : text, error: false });
62
66
  },
63
- error(text) {
64
- if (host.notify) host.notify.error(text);
65
- else setMessage({ text, error: true });
67
+ error(text, options) {
68
+ if (host.notify) host.notify.error(text, options);
69
+ else setMessage({ text: options?.description ? `${text}. ${options.description}` : text, error: true });
66
70
  }
67
71
  }),
68
72
  [host]
@@ -137,7 +141,7 @@ function RecordId({
137
141
  e.preventDefault();
138
142
  void copyText(value).then((ok) => {
139
143
  if (!ok) {
140
- notify?.error(`Couldn't copy ${copyLabel}`);
144
+ notify?.error("Not copied", { description: copyLabel });
141
145
  return;
142
146
  }
143
147
  setCopied(true);
@@ -153,12 +157,10 @@ function RecordId({
153
157
  try {
154
158
  const result = await onOpen(value);
155
159
  if (result === "forbidden") {
156
- notify?.error("You don't have access to open this record");
160
+ notify?.error("No access", { description: "This account can't open this record" });
157
161
  }
158
162
  } catch (err) {
159
- notify?.error(
160
- `Couldn't open: ${err instanceof Error ? err.message : String(err)}`
161
- );
163
+ notify?.error("Not opened", { description: peopleErrorSentence(err, null, { card: true }) });
162
164
  } finally {
163
165
  setOpening(false);
164
166
  }
@@ -293,4 +295,4 @@ export {
293
295
  displayId,
294
296
  RecordId
295
297
  };
296
- //# sourceMappingURL=chunk-U46XUQI7.js.map
298
+ //# sourceMappingURL=chunk-KSCSH7AO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/record-id-format.ts","../src/record-id.tsx","../src/data-table/useTableNotice.tsx"],"sourcesContent":["// THE id's formatting — what RecordId shows for an id — as plain functions with no React, so a\n// Server Component (a page title, metadata) shortens an id exactly as the component does.\n// Server-safe entry: `@ai-matrx/design-system/record-id-format`.\n\nimport { isUuidShape } from \"@ai-matrx/kit/uuid\";\n\nconst SHORT_LEN = 8;\n\nexport function shortUuid(id: string, len = SHORT_LEN): string {\n return id.slice(0, len);\n}\n\n/** Up to this many characters an id reads whole; longer ones show their start. */\nconst WHOLE_MAX = 16;\n\n/** A record id the database minted (a UUID) — what a peek shows on its own. */\nexport function isRecordUuid(id: string | null | undefined): boolean {\n return Boolean(id && isUuidShape(id));\n}\n\n/** What RecordId shows for an id: a UUID's (or any long id's) first 8 characters, a short id whole. */\nexport type RecordIdShow = \"auto\" | \"short\" | \"full\";\n\nexport function displayId(id: string, show: RecordIdShow = \"auto\"): string {\n if (show === \"full\") return id;\n if (show === \"short\" || isUuidShape(id) || id.length > WHOLE_MAX) return shortUuid(id);\n return id;\n}\n","\"use client\";\n\n/**\n * RecordId — THE way to show a record's id, anywhere (Arman, 2026-10-18: \"anything with an id …\n * we need to use a simple canonical id component that automatically handles several things,\n * including allowing for easy copy\"). Never `{row.id.slice(0, 8)}`, never a hand-built copy button.\n *\n * What it handles, once:\n * - display: a UUID shows its first 8 characters, a short id (a model id, a video id) shows whole;\n * the full id is always the tooltip;\n * - copy: one click copies the FULL id, a check confirms it, a failure says so;\n * - doors (THE DOOR LAW, \"never render an id you can't open\"): pass `token` (the entity token the\n * id points at) and the route, new tab and quick look resolve from the host registries; or pass\n * `href` / `onOpen`. `forbidden`: copyable, not openable;\n * - looks: `plain` (dense rows, tables — the default) or `chip` (headers, cards, detail panels);\n * `labelled` puts the kind of id in front (\"Agent ID\").\n * Prefer `EntityRef` when the record's NAME is on hand — this is the id itself.\n *\n * The data table's id column (`MatrxUuidCell`) is this component.\n */\n\nimport {\n useEffect,\n useRef,\n useState,\n type MouseEvent,\n type ReactNode,\n} from \"react\";\nimport { Lightbulb, ShieldOff } from \"./data-table/icons\";\nimport { CheckIcon, CopyIcon, ExternalLinkIcon, PanelRightIcon } from \"./icons\";\nimport { useTableNotice } from \"./data-table/useTableNotice\";\nimport { useMatrxDataTableHost } from \"./data-table/host\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"./tooltip\";\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { cn } from \"./cn\";\nimport { Button as ControlButton } from \"./controls/controls\";\nimport { OutboundLink } from \"@ai-matrx/kit/outbound-react\";\n\nexport { shortUuid, isRecordUuid, displayId, type RecordIdShow } from \"./record-id-format\";\nimport { displayId, type RecordIdShow } from \"./record-id-format\";\nimport { peopleErrorSentence } from \"./error-sentence\";\nexport type RecordIdLook = \"plain\" | \"chip\" | \"icon\";\n\n\nexport type RecordIdOpenResult = void | \"forbidden\";\n\nexport interface RecordIdProps {\n value: string | null | undefined;\n /** What kind of id it is (\"Agent\", \"Chat\", a column name): the tooltip, the copy label and, with `labelled`, the visible prefix. */\n label?: string | undefined;\n /** `auto` (default): a UUID or long id shows its first 8 characters, a short id shows whole. */\n show?: RecordIdShow;\n /**\n * `plain` (default): dense mono text. `chip`: a quiet bordered pill for headers, cards and panels.\n * `icon`: the copy button alone, header-sized (a record's own header, where the id is shown elsewhere);\n * the full id is its tooltip.\n */\n look?: RecordIdLook;\n /** Show the kind of id in front of it (\"Agent ID 1a2b3c4d\"). */\n labelled?: boolean;\n /** A short note added to the tooltip under the id (\"Not a member of this organization\"). */\n hint?: string;\n /**\n * Inside another control (a button, a select trigger, a door): the id as text only, full id and\n * hint as its native tooltip, no buttons of its own — the control around it owns the click.\n */\n inert?: boolean;\n /**\n * Open the referenced record in-app (prefer WindowPanel).\n * Return `\"forbidden\"` to block navigation and show a muted state.\n */\n onOpen?: (id: string) => RecordIdOpenResult | Promise<RecordIdOpenResult>;\n /** Optional real href (new tab / cmd-click). Used when navigation is allowed. */\n href?: string | null | undefined;\n /**\n * Canonical entity token this id points at (`agent`, `note`, `task`, …).\n * Supplies the route and the peek automatically — THE DOOR LAW, resolved\n * from the registries instead of wired per callsite. An explicit `href` /\n * `onOpen` still wins.\n */\n token?: string | null | undefined;\n /** Force non-navigable (still copyable). */\n forbidden?: boolean;\n className?: string;\n trailing?: ReactNode;\n}\n\nexport function RecordId({\n value,\n label,\n show = \"auto\",\n look = \"plain\",\n labelled = false,\n hint,\n inert = false,\n onOpen,\n href,\n token,\n forbidden = false,\n className,\n trailing,\n}: RecordIdProps) {\n const { resolveEntityDoors, ResourcePeek } = useMatrxDataTableHost();\n const { notify, notice } = useTableNotice();\n const [copied, setCopied] = useState(false);\n const [opening, setOpening] = useState(false);\n const [peekOpen, setPeekOpen] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current);\n },\n [],\n );\n\n if (!value) {\n return <span className=\"text-disabled-foreground\">—</span>;\n }\n\n const doors = token ? resolveEntityDoors?.(token, value, href) ?? null : null;\n const resolvedHref = doors?.href ?? href ?? null;\n const canPeek = Boolean(doors?.canPeek) && !forbidden;\n const display = displayId(value, show);\n\n // A label that already names the id (\"Execution ID\", \"run_id\", a table's \"… Id\" header) is used as\n // written; any other kind of record gains \" ID\" (\"Agent\" → \"Agent ID\").\n const named = label ? /\\b(id|uuid)$/i.test(label.trim()) || /_id$/i.test(label.trim()) : false;\n const copyLabel = label ? (named ? label.trim() : `${label} ID`) : \"ID\";\n const tip = `${label ? `${copyLabel}: ${value}` : value}${hint ? ` — ${hint}` : \"\"}`;\n if (inert) {\n return (\n <span\n data-matrx-record-id=\"\"\n title={tip}\n className={cn(\"min-w-0 truncate font-mono text-xs tabular-nums\", className)}\n >\n {labelled ? `${copyLabel} ` : \"\"}\n {display}\n </span>\n );\n }\n\n const stop = (e: MouseEvent) => {\n e.stopPropagation();\n };\n\n const onCopy = (e: MouseEvent) => {\n stop(e);\n e.preventDefault();\n void copyText(value).then((ok) => {\n if (!ok) {\n notify?.error(\"Not copied\", { description: copyLabel });\n return;\n }\n setCopied(true);\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), 1500);\n });\n };\n\n const handleOpen = async (e: MouseEvent) => {\n stop(e);\n e.preventDefault();\n if (!onOpen || forbidden || opening) return;\n setOpening(true);\n try {\n const result = await onOpen(value);\n if (result === \"forbidden\") {\n // access-errors: ok — relays the onOpen contract's explicit verdict: the caller's opener returns \"forbidden\" only after ITS OWN access check; the cell performs no read and never guesses\n notify?.error(\"No access\", { description: \"This account can't open this record\" });\n }\n } catch (err) {\n notify?.error(\"Not opened\", { description: peopleErrorSentence(err, null, { card: true }) });\n } finally {\n setOpening(false);\n }\n };\n\n const idNode = (() => {\n if (forbidden) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-1 font-mono text-xs text-disabled-foreground tabular-nums\">\n <span className=\"min-w-0 truncate\">{display}</span>\n <ShieldOff className=\"h-3 w-3 shrink-0\" aria-hidden />\n </span>\n );\n }\n\n if (onOpen) {\n return (\n <ControlButton\n type=\"button\"\n variant=\"link\"\n iconEnd={<PanelRightIcon className=\"h-3 w-3 shrink-0 text-muted-foreground\" />}\n aria-label={`Open ${label ?? \"record\"} ${display}`}\n onClick={(e) => void handleOpen(e)}\n disabled={opening}\n className=\"min-w-0 font-mono\"\n >\n <span className=\"min-w-0 truncate tabular-nums\">{display}</span>\n </ControlButton>\n );\n }\n\n if (resolvedHref) {\n return (\n <OutboundLink\n href={resolvedHref}\n aria-label={`Open ${label ?? \"record\"} ${display} in a new tab`}\n onClick={stop}\n className=\"inline-flex min-w-0 items-center gap-1 font-mono text-xs text-primary hover:underline\"\n >\n <span className=\"min-w-0 truncate tabular-nums\">{display}</span>\n <ExternalLinkIcon className=\"h-3 w-3 shrink-0 text-muted-foreground\" />\n </OutboundLink>\n );\n }\n\n return (\n <span className=\"min-w-0 truncate font-mono text-xs text-muted-foreground tabular-nums select-all\">\n {display}\n </span>\n );\n })();\n\n return (\n <TooltipProvider delayDuration={200}>\n <span\n data-matrx-cell-control\n data-matrx-record-id=\"\"\n className={cn(\n \"inline-flex min-w-0 max-w-full items-center gap-0.5 whitespace-nowrap\",\n look === \"chip\" && \"h-5 rounded border border-border bg-muted pl-1.5 pr-0.5\",\n className,\n )}\n onClick={stop}\n >\n {labelled && look !== \"icon\" ? <span className=\"mr-1 shrink-0 text-xs text-muted-foreground\">{copyLabel}</span> : null}\n {look === \"icon\" ? null : (\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex min-w-0 max-w-full items-center\">\n {idNode}\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-sm break-all font-mono\">\n {forbidden ? `No access · ${tip}` : tip}\n </TooltipContent>\n </Tooltip>\n )}\n <Tooltip>\n <TooltipTrigger asChild>\n <ControlButton\n type=\"button\"\n variant=\"quiet\"\n icon={copied ? <CheckIcon className={look === \"icon\" ? \"h-3.5 w-3.5\" : \"h-3 w-3\"} /> : <CopyIcon className={look === \"icon\" ? \"h-3.5 w-3.5\" : \"h-3 w-3\"} />}\n onClick={onCopy}\n aria-label={copied ? \"Copied\" : `Copy ${copyLabel}`}\n className=\"shrink-0\"\n />\n </TooltipTrigger>\n <TooltipContent side=\"top\">{copied ? \"Copied\" : `Copy ${copyLabel}: ${value}`}</TooltipContent>\n </Tooltip>\n {canPeek && look !== \"icon\" ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <ControlButton\n type=\"button\"\n variant=\"quiet\"\n icon={<Lightbulb className=\"h-3 w-3\" />}\n onClick={(e) => {\n stop(e);\n setPeekOpen(true);\n }}\n aria-label={`Quick look at ${label ?? \"record\"}`}\n className=\"shrink-0\"\n >\n </ControlButton>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Quick look at {label ?? \"record\"}</TooltipContent>\n </Tooltip>\n ) : null}\n {onOpen && resolvedHref && !forbidden && look !== \"icon\" ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <OutboundLink\n href={resolvedHref}\n onClick={stop}\n aria-label={`Open ${label ?? \"record\"} in a new tab`}\n className=\"inline-flex h-4 w-4 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground focus:outline-none\"\n >\n <ExternalLinkIcon className=\"h-3 w-3\" />\n </OutboundLink>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Open {label ?? \"record\"} in a new tab</TooltipContent>\n </Tooltip>\n ) : null}\n {trailing}\n {notice}\n {canPeek && peekOpen && ResourcePeek ? (\n <ResourcePeek\n kind={doors?.peekKind ?? token ?? \"record\"}\n id={value}\n onClose={() => setPeekOpen(false)}\n // Same contract as `EntityDoorControls`: forward the CALLER's raw\n // `href` so the peek's \"Open\" cannot send the user somewhere this\n // cell's own link does not go. `doors.ts` names EntityRef and this\n // cell as the two presentations that must not drift — the peek\n // override shipped on one of them first, which is exactly the drift\n // that file warns about.\n {...(href == null ? {} : { href })}\n />\n ) : null}\n </span>\n </TooltipProvider>\n );\n}\n","\"use client\";\nimport { useMemo, useState } from \"react\";\nimport { useMatrxDataTableHost } from \"./host\";\n\n/** Every portable async action has visible feedback even without a host toast system. */\nexport function useTableNotice() {\n const host = useMatrxDataTableHost();\n const [message, setMessage] = useState<{ text: string; error: boolean } | null>(null);\n // One `notify` per host, so a memoised toolbar that holds it never holds a stale one (RENDER-3).\n const notify = useMemo(\n () => ({\n // A card is a short title and an optional line (NOTICE_TEXT_BUDGET); the inline fallback joins them.\n success(text: string, options?: { description?: string }) { if (host.notify) host.notify.success(text, options); else setMessage({ text: options?.description ? `${text}. ${options.description}` : text, error: false }); },\n error(text: string, options?: { description?: string }) { if (host.notify) host.notify.error(text, options); else setMessage({ text: options?.description ? `${text}. ${options.description}` : text, error: true }); },\n }),\n [host],\n );\n const notice = message ? <span role={message.error ? \"alert\" : \"status\"} className={message.error ? \"text-xs text-destructive-ink\" : \"text-xs text-muted-foreground\"}>{message.text}<button type=\"button\" aria-label=\"Dismiss notification\" className=\"ml-2 underline\" onClick={() => setMessage(null)}>Dismiss</button></span> : null;\n return { notify, notice };\n}\n"],"mappings":"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","names":["useState","jsx","jsxs","useState"]}
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-OPF265PU.js";
7
7
  import {
8
8
  Button
9
- } from "./chunk-6XNYYROM.js";
9
+ } from "./chunk-WVEDW5VO.js";
10
10
  import {
11
11
  AlertTriangleIcon,
12
12
  ChevronDownIcon,
@@ -605,4 +605,4 @@ export {
605
605
  ConfigurationTable,
606
606
  ConfigurationTableRow
607
607
  };
608
- //# sourceMappingURL=chunk-MTE6N7XU.js.map
608
+ //# sourceMappingURL=chunk-NFJ63LIH.js.map
@@ -21,10 +21,10 @@ import {
21
21
  import {
22
22
  DataRowInspector,
23
23
  columnId
24
- } from "./chunk-WUD23YTG.js";
24
+ } from "./chunk-P56Y43RL.js";
25
25
  import {
26
26
  useMatrxDataTableHost
27
- } from "./chunk-POJ3RR3K.js";
27
+ } from "./chunk-B5D3VIMC.js";
28
28
  import {
29
29
  Eye
30
30
  } from "./chunk-4JAYMFQO.js";
@@ -305,4 +305,4 @@ export {
305
305
  withMacLookDefaults,
306
306
  DataRowWindow
307
307
  };
308
- //# sourceMappingURL=chunk-XZGYKKCE.js.map
308
+ //# sourceMappingURL=chunk-OUQT72UL.js.map
@@ -7,23 +7,23 @@ import {
7
7
  } from "./chunk-PTYKILZE.js";
8
8
  import {
9
9
  CopyButtons
10
- } from "./chunk-FRJ4PPA2.js";
10
+ } from "./chunk-CZGZV35G.js";
11
11
  import {
12
12
  PropertyRow
13
- } from "./chunk-MTE6N7XU.js";
13
+ } from "./chunk-NFJ63LIH.js";
14
14
  import {
15
15
  completeLayeredFilterRules,
16
16
  layeredFilterMatchesValue
17
17
  } from "./chunk-7ZCD4AZS.js";
18
18
  import {
19
19
  RecordId
20
- } from "./chunk-U46XUQI7.js";
20
+ } from "./chunk-KSCSH7AO.js";
21
21
  import {
22
22
  Button
23
- } from "./chunk-6XNYYROM.js";
23
+ } from "./chunk-WVEDW5VO.js";
24
24
  import {
25
25
  useMatrxDataTableHost
26
- } from "./chunk-POJ3RR3K.js";
26
+ } from "./chunk-B5D3VIMC.js";
27
27
  import {
28
28
  cn
29
29
  } from "./chunk-M6KA5EHN.js";
@@ -671,4 +671,4 @@ export {
671
671
  isUuidValue,
672
672
  DataRowInspector
673
673
  };
674
- //# sourceMappingURL=chunk-WUD23YTG.js.map
674
+ //# sourceMappingURL=chunk-P56Y43RL.js.map
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  Button,
10
10
  ControlRow
11
- } from "./chunk-6XNYYROM.js";
11
+ } from "./chunk-WVEDW5VO.js";
12
12
  import {
13
13
  buttonVariants,
14
14
  swallowClick
@@ -482,4 +482,4 @@ export {
482
482
  DangerZone,
483
483
  PromoBanner
484
484
  };
485
- //# sourceMappingURL=chunk-GMNROZQJ.js.map
485
+ //# sourceMappingURL=chunk-QTPW44IJ.js.map
@@ -19,7 +19,7 @@ import {
19
19
  MenuLookSub,
20
20
  MenuLookSubContent,
21
21
  MenuLookSubTrigger
22
- } from "./chunk-T4D7WAV7.js";
22
+ } from "./chunk-42GFQMLA.js";
23
23
  import {
24
24
  ContextMenu,
25
25
  ContextMenuTrigger
@@ -37,16 +37,16 @@ import {
37
37
  } from "./chunk-WFBPCMPF.js";
38
38
  import {
39
39
  Button
40
- } from "./chunk-6XNYYROM.js";
40
+ } from "./chunk-WVEDW5VO.js";
41
41
  import {
42
42
  DropdownMenu,
43
43
  DropdownMenuTrigger
44
- } from "./chunk-X6ZRHJQP.js";
44
+ } from "./chunk-T57DLONB.js";
45
45
  import {
46
46
  declareLazyDataProps,
47
47
  useMatrxTableRowAlchemy,
48
48
  useMatrxTableRowControls
49
- } from "./chunk-POJ3RR3K.js";
49
+ } from "./chunk-B5D3VIMC.js";
50
50
  import {
51
51
  CheckIcon,
52
52
  ChevronDownIcon,
@@ -967,4 +967,4 @@ export {
967
967
  ItemContextMenu,
968
968
  ItemRow
969
969
  };
970
- //# sourceMappingURL=chunk-QA7EHFRX.js.map
970
+ //# sourceMappingURL=chunk-T3FKFPCW.js.map
@@ -58,7 +58,7 @@ var DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...
58
58
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
59
59
  var DropdownMenuSubContent = React.forwardRef(({ className, container, surface = "default", sideOffset = 2, alignOffset = -4, collisionPadding, onFocusOutside, children, ...props }, ref) => {
60
60
  const portalContainer = usePortalContainer(container);
61
- const [bottomClearance] = React.useState(readBottomClearance);
61
+ const [bottomClearance] = React.useState(sharedBottomClearance);
62
62
  const padding = menuCollisionPadding(collisionPadding ?? 8, 0, bottomClearance);
63
63
  const nested = useNestedSubmenuPlacement(ref, padding);
64
64
  const keep = useSubmenuSurvivesParentPanelFocus(nested.ref, onFocusOutside);
@@ -80,18 +80,27 @@ var DropdownMenuSubContent = React.forwardRef(({ className, container, surface =
80
80
  ) });
81
81
  });
82
82
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
83
- function readTopClearance() {
84
- return readClearance("var(--matrx-floating-top-clearance, var(--shell-header-h, 0px))");
85
- }
86
- function readBottomClearance() {
87
- return readClearance("var(--matrx-floating-clearance, 0px)");
88
- }
89
83
  function menuCollisionPadding(caller, top, bottom, fallback = 0) {
90
84
  const side = (key) => typeof caller === "number" ? caller : caller?.[key] ?? fallback;
91
85
  return { top: Math.max(side("top"), top), right: side("right"), bottom: Math.max(side("bottom"), bottom), left: side("left") };
92
86
  }
93
- function readClearance(height) {
87
+ var CLEARANCE_REUSE_MS = 500;
88
+ var clearanceCache = /* @__PURE__ */ new Map();
89
+ var clock = () => typeof performance !== "undefined" ? performance.now() : Date.now();
90
+ function readClearance(height, shared = false) {
94
91
  if (typeof document === "undefined") return 0;
92
+ const now = clock();
93
+ const held = shared ? clearanceCache.get(height) : void 0;
94
+ if (held && now - held.at < CLEARANCE_REUSE_MS) return held.px;
95
+ const px = measureClearance(height);
96
+ clearanceCache.set(height, { px, at: now });
97
+ return px;
98
+ }
99
+ var TOP_CLEARANCE = "var(--matrx-floating-top-clearance, var(--shell-header-h, 0px))";
100
+ var BOTTOM_CLEARANCE = "var(--matrx-floating-clearance, 0px)";
101
+ var sharedTopClearance = () => readClearance(TOP_CLEARANCE, true);
102
+ var sharedBottomClearance = () => readClearance(BOTTOM_CLEARANCE, true);
103
+ function measureClearance(height) {
95
104
  const probe = document.createElement("div");
96
105
  probe.style.cssText = `position:fixed;top:0;left:0;width:0;visibility:hidden;pointer-events:none;height:${height}`;
97
106
  document.body.appendChild(probe);
@@ -101,8 +110,8 @@ function readClearance(height) {
101
110
  }
102
111
  var DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, container, surface = "default", children, onCloseAutoFocus, collisionPadding, ...props }, ref) => {
103
112
  const portalContainer = usePortalContainer(container);
104
- const [topClearance] = React.useState(readTopClearance);
105
- const [bottomClearance] = React.useState(readBottomClearance);
113
+ const [topClearance] = React.useState(sharedTopClearance);
114
+ const [bottomClearance] = React.useState(sharedBottomClearance);
106
115
  const edges = useMenuScrollEdges(ref);
107
116
  return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(
108
117
  DropdownMenuPrimitive.Content,
@@ -217,4 +226,4 @@ export {
217
226
  DropdownMenuSeparator,
218
227
  DropdownMenuShortcut
219
228
  };
220
- //# sourceMappingURL=chunk-X6ZRHJQP.js.map
229
+ //# sourceMappingURL=chunk-T57DLONB.js.map