@ai-matrx/design-system 0.86.357 → 0.86.359
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.
- package/CHANGELOG.md +30 -2
- package/dist/carousel.js +6 -6
- package/dist/{chunk-T4D7WAV7.js → chunk-42GFQMLA.js} +2 -2
- package/dist/{chunk-POJ3RR3K.js → chunk-B5D3VIMC.js} +1 -1
- package/dist/{chunk-POJ3RR3K.js.map → chunk-B5D3VIMC.js.map} +1 -1
- package/dist/{chunk-FRJ4PPA2.js → chunk-CZGZV35G.js} +2 -2
- package/dist/{chunk-ACZALXD6.js → chunk-K3XWUACX.js} +3 -3
- package/dist/{chunk-TV2IDHPZ.js → chunk-K5ZQROWN.js} +4 -4
- package/dist/{chunk-U46XUQI7.js → chunk-KSCSH7AO.js} +16 -14
- package/dist/chunk-KSCSH7AO.js.map +1 -0
- package/dist/{chunk-MTE6N7XU.js → chunk-NFJ63LIH.js} +2 -2
- package/dist/{chunk-XZGYKKCE.js → chunk-OUQT72UL.js} +3 -3
- package/dist/{chunk-WUD23YTG.js → chunk-P56Y43RL.js} +6 -6
- package/dist/{chunk-GMNROZQJ.js → chunk-QTPW44IJ.js} +2 -2
- package/dist/{chunk-QA7EHFRX.js → chunk-T3FKFPCW.js} +5 -5
- package/dist/{chunk-X6ZRHJQP.js → chunk-T57DLONB.js} +20 -11
- package/dist/chunk-T57DLONB.js.map +1 -0
- package/dist/{chunk-SOCNWQMX.js → chunk-TEMAM5ET.js} +3 -3
- package/dist/{chunk-CH2NWSES.js → chunk-TIV6M7Q7.js} +3 -3
- package/dist/{chunk-6XNYYROM.js → chunk-WVEDW5VO.js} +2 -2
- package/dist/clipboard-fallback-dialog.js +2 -2
- package/dist/controls.cjs +19 -10
- package/dist/controls.cjs.map +1 -1
- package/dist/controls.js +6 -6
- package/dist/data-table/data-row-inspector.cjs +99 -11
- package/dist/data-table/data-row-inspector.cjs.map +1 -1
- package/dist/data-table/data-row-inspector.js +8 -7
- package/dist/data-table/data-row-window.cjs +99 -11
- package/dist/data-table/data-row-window.cjs.map +1 -1
- package/dist/data-table/data-row-window.js +9 -8
- package/dist/data-table/drill-chart.js +1 -1
- package/dist/data-table/host.cjs.map +1 -1
- package/dist/data-table/host.d.cts +6 -2
- package/dist/data-table/host.d.ts +6 -2
- package/dist/data-table/host.js +1 -1
- package/dist/data-table/index.cjs +39 -37
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.d.cts +6 -2
- package/dist/data-table/index.d.ts +6 -2
- package/dist/data-table/index.js +19 -23
- package/dist/data-table/index.js.map +1 -1
- package/dist/data-table/pagination.cjs +19 -10
- package/dist/data-table/pagination.cjs.map +1 -1
- package/dist/data-table/pagination.js +4 -4
- package/dist/data-table/uuid-cell.cjs +99 -11
- package/dist/data-table/uuid-cell.cjs.map +1 -1
- package/dist/data-table/uuid-cell.js +5 -4
- package/dist/desktop.cjs +20 -11
- package/dist/desktop.cjs.map +1 -1
- package/dist/desktop.d.cts +1 -1
- package/dist/desktop.d.ts +1 -1
- package/dist/desktop.js +13 -13
- package/dist/desktop.js.map +1 -1
- package/dist/email-input-dialog.js +1 -1
- package/dist/index.cjs +31 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +20 -20
- package/dist/item.cjs +19 -10
- package/dist/item.cjs.map +1 -1
- package/dist/item.js +5 -5
- package/dist/lite-table.js +3 -3
- package/dist/menu-look.cjs +19 -10
- package/dist/menu-look.cjs.map +1 -1
- package/dist/menu-look.js +2 -2
- package/dist/record-list.cjs +19 -10
- package/dist/record-list.cjs.map +1 -1
- package/dist/record-list.js +6 -6
- package/dist/settings.js +3 -3
- package/dist/swipe-deck.cjs +11 -2
- package/dist/swipe-deck.cjs.map +1 -1
- package/dist/swipe-deck.js +12 -3
- package/dist/swipe-deck.js.map +1 -1
- package/dist/text-input-dialog.js +1 -1
- package/dist/writing-field.js +3 -3
- package/package.json +2 -2
- package/dist/chunk-U46XUQI7.js.map +0 -1
- package/dist/chunk-X6ZRHJQP.js.map +0 -1
- /package/dist/{chunk-T4D7WAV7.js.map → chunk-42GFQMLA.js.map} +0 -0
- /package/dist/{chunk-FRJ4PPA2.js.map → chunk-CZGZV35G.js.map} +0 -0
- /package/dist/{chunk-ACZALXD6.js.map → chunk-K3XWUACX.js.map} +0 -0
- /package/dist/{chunk-TV2IDHPZ.js.map → chunk-K5ZQROWN.js.map} +0 -0
- /package/dist/{chunk-MTE6N7XU.js.map → chunk-NFJ63LIH.js.map} +0 -0
- /package/dist/{chunk-XZGYKKCE.js.map → chunk-OUQT72UL.js.map} +0 -0
- /package/dist/{chunk-WUD23YTG.js.map → chunk-P56Y43RL.js.map} +0 -0
- /package/dist/{chunk-GMNROZQJ.js.map → chunk-QTPW44IJ.js.map} +0 -0
- /package/dist/{chunk-QA7EHFRX.js.map → chunk-T3FKFPCW.js.map} +0 -0
- /package/dist/{chunk-SOCNWQMX.js.map → chunk-TEMAM5ET.js.map} +0 -0
- /package/dist/{chunk-CH2NWSES.js.map → chunk-TIV6M7Q7.js.map} +0 -0
- /package/dist/{chunk-6XNYYROM.js.map → chunk-WVEDW5VO.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.86.359
|
|
4
|
+
|
|
5
|
+
- DataTable filter bar: a bare row count ("1") is no longer drawn (a page heading already says it, so a table beside a counted heading showed the number twice). The count shows in words when the table has a `noun` ("5 processes") and as "3 of 5" while filtered. Guard: `src/desktop/table-filter.test.tsx`. Consumer action: a test that read the bare count (`data-table-filter-count`) of an unfiltered, noun-less table now finds none.
|
|
6
|
+
|
|
7
|
+
- SwipeDeck (REVIEW9 M-5): a full deck takes focus back only after an answer made in the deck, or when nothing is
|
|
8
|
+
focused — a card change the host makes (items arriving, re-sorting) never takes focus from a button or link; a
|
|
9
|
+
`contenteditable` region of any value but `false`, a combobox or a textbox keeps focus; a deck inside a dialog takes
|
|
10
|
+
focus back within that dialog. Consumer action: none.
|
|
11
|
+
|
|
12
|
+
## 0.86.358
|
|
13
|
+
|
|
14
|
+
SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
|
|
15
|
+
so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
|
|
16
|
+
Diff: `git diff 3cc6206acf ba5a7456f2 -- apps/shared/design-system/src`
|
|
17
|
+
|
|
18
|
+
Changed shipped source files (5):
|
|
19
|
+
- `apps/shared/design-system/src/data-table/MatrxDataTable.tsx`
|
|
20
|
+
- `apps/shared/design-system/src/data-table/useTableNotice.tsx`
|
|
21
|
+
- `apps/shared/design-system/src/dropdown-menu.tsx`
|
|
22
|
+
- `apps/shared/design-system/src/record-id.tsx`
|
|
23
|
+
- `apps/shared/design-system/src/table-host/host.tsx`
|
|
24
|
+
|
|
3
25
|
## 0.86.357
|
|
4
26
|
|
|
5
|
-
|
|
6
|
-
|
|
27
|
+
SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
|
|
28
|
+
so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
|
|
29
|
+
Diff: `git diff bd77a197ad 3cc6206acf -- apps/shared/design-system/src`
|
|
30
|
+
|
|
31
|
+
Changed shipped source files (3):
|
|
32
|
+
- `apps/shared/design-system/src/desktop/state.tsx`
|
|
33
|
+
- `apps/shared/design-system/src/error-sentence.ts`
|
|
34
|
+
- `apps/shared/design-system/src/notice-stack.ts`
|
|
7
35
|
|
|
8
36
|
## 0.86.356
|
|
9
37
|
|
package/dist/carousel.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
IconButton
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
412
|
+
//# sourceMappingURL=chunk-42GFQMLA.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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
781
|
+
//# sourceMappingURL=chunk-K5ZQROWN.js.map
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
Button
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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(
|
|
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("
|
|
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-
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,SAAS,mBAAmB;AAE5B,IAAM,YAAY;AAEX,SAAS,UAAU,IAAY,MAAM,WAAmB;AAC7D,SAAO,GAAG,MAAM,GAAG,GAAG;AACxB;AAGA,IAAM,YAAY;AAGX,SAAS,aAAa,IAAwC;AACnE,SAAO,QAAQ,MAAM,YAAY,EAAE,CAAC;AACtC;AAKO,SAAS,UAAU,IAAY,OAAqB,QAAgB;AACzE,MAAI,SAAS,OAAQ,QAAO;AAC5B,MAAI,SAAS,WAAW,YAAY,EAAE,KAAK,GAAG,SAAS,UAAW,QAAO,UAAU,EAAE;AACrF,SAAO;AACT;;;ACNA;AAAA,EACE;AAAA,EACA;AAAA,EACA,YAAAA;AAAA,OAGK;;;AC1BP,SAAS,SAAS,gBAAgB;AAgBP,SAA2J,KAA3J;AAZpB,SAAS,iBAAiB;AAC/B,QAAM,OAAO,sBAAsB;AACnC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkD,IAAI;AAEpF,QAAM,SAAS;AAAA,IACb,OAAO;AAAA;AAAA,MAEL,QAAQ,MAAc,SAAoC;AAAE,YAAI,KAAK,OAAQ,MAAK,OAAO,QAAQ,MAAM,OAAO;AAAA,YAAQ,YAAW,EAAE,MAAM,SAAS,cAAc,GAAG,IAAI,KAAK,QAAQ,WAAW,KAAK,MAAM,OAAO,MAAM,CAAC;AAAA,MAAG;AAAA,MAC3N,MAAM,MAAc,SAAoC;AAAE,YAAI,KAAK,OAAQ,MAAK,OAAO,MAAM,MAAM,OAAO;AAAA,YAAQ,YAAW,EAAE,MAAM,SAAS,cAAc,GAAG,IAAI,KAAK,QAAQ,WAAW,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,MAAG;AAAA,IACxN;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AACA,QAAM,SAAS,UAAU,qBAAC,UAAK,MAAM,QAAQ,QAAQ,UAAU,UAAU,WAAW,QAAQ,QAAQ,iCAAiC,iCAAkC;AAAA,YAAQ;AAAA,IAAK,oBAAC,YAAO,MAAK,UAAS,cAAW,wBAAuB,WAAU,kBAAiB,SAAS,MAAM,WAAW,IAAI,GAAG,qBAAO;AAAA,KAAS,IAAU;AAClU,SAAO,EAAE,QAAQ,OAAO;AAC1B;;;ADmBA,SAAS,gBAAgB;AAGzB,SAAS,oBAAoB;AAiFlB,gBAAAC,MAeL,QAAAC,aAfK;AA9BJ,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AACF,GAAkB;AAChB,QAAM,EAAE,oBAAoB,aAAa,IAAI,sBAAsB;AACnE,QAAM,EAAE,QAAQ,OAAO,IAAI,eAAe;AAC1C,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,QAAQ,OAA6C,IAAI;AAE/D;AAAA,IACE,MAAM,MAAM;AACV,UAAI,MAAM,QAAS,cAAa,MAAM,OAAO;AAAA,IAC/C;AAAA,IACA,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,OAAO;AACV,WAAO,gBAAAF,KAAC,UAAK,WAAU,4BAA2B,oBAAC;AAAA,EACrD;AAEA,QAAM,QAAQ,QAAQ,qBAAqB,OAAO,OAAO,IAAI,KAAK,OAAO;AACzE,QAAM,eAAe,OAAO,QAAQ,QAAQ;AAC5C,QAAM,UAAU,QAAQ,OAAO,OAAO,KAAK,CAAC;AAC5C,QAAM,UAAU,UAAU,OAAO,IAAI;AAIrC,QAAM,QAAQ,QAAQ,gBAAgB,KAAK,MAAM,KAAK,CAAC,KAAK,QAAQ,KAAK,MAAM,KAAK,CAAC,IAAI;AACzF,QAAM,YAAY,QAAS,QAAQ,MAAM,KAAK,IAAI,GAAG,KAAK,QAAS;AACnE,QAAM,MAAM,GAAG,QAAQ,GAAG,SAAS,KAAK,KAAK,KAAK,KAAK,GAAG,OAAO,WAAM,IAAI,KAAK,EAAE;AAClF,MAAI,OAAO;AACT,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,wBAAqB;AAAA,QACrB,OAAO;AAAA,QACP,WAAW,GAAG,mDAAmD,SAAS;AAAA,QAEzE;AAAA,qBAAW,GAAG,SAAS,MAAM;AAAA,UAC7B;AAAA;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,QAAM,OAAO,CAAC,MAAkB;AAC9B,MAAE,gBAAgB;AAAA,EACpB;AAEA,QAAM,SAAS,CAAC,MAAkB;AAChC,SAAK,CAAC;AACN,MAAE,eAAe;AACjB,SAAK,SAAS,KAAK,EAAE,KAAK,CAAC,OAAO;AAChC,UAAI,CAAC,IAAI;AACP,gBAAQ,MAAM,cAAc,EAAE,aAAa,UAAU,CAAC;AACtD;AAAA,MACF;AACA,gBAAU,IAAI;AACd,UAAI,MAAM,QAAS,cAAa,MAAM,OAAO;AAC7C,YAAM,UAAU,WAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AAAA,IACzD,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,OAAO,MAAkB;AAC1C,SAAK,CAAC;AACN,MAAE,eAAe;AACjB,QAAI,CAAC,UAAU,aAAa,QAAS;AACrC,eAAW,IAAI;AACf,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,KAAK;AACjC,UAAI,WAAW,aAAa;AAE1B,gBAAQ,MAAM,aAAa,EAAE,aAAa,sCAAsC,CAAC;AAAA,MACnF;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ,MAAM,cAAc,EAAE,aAAa,oBAAoB,KAAK,MAAM,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,IAC7F,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,WAAW;AACb,aACE,gBAAAA,MAAC,UAAK,WAAU,kGACd;AAAA,wBAAAD,KAAC,UAAK,WAAU,oBAAoB,mBAAQ;AAAA,QAC5C,gBAAAA,KAAC,aAAU,WAAU,oBAAmB,eAAW,MAAC;AAAA,SACtD;AAAA,IAEJ;AAEA,QAAI,QAAQ;AACV,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,SAAS,gBAAAA,KAAC,kBAAe,WAAU,0CAAyC;AAAA,UAC5E,cAAY,QAAQ,SAAS,QAAQ,IAAI,OAAO;AAAA,UAChD,SAAS,CAAC,MAAM,KAAK,WAAW,CAAC;AAAA,UACjC,UAAU;AAAA,UACV,WAAU;AAAA,UAEV,0BAAAA,KAAC,UAAK,WAAU,iCAAiC,mBAAQ;AAAA;AAAA,MAC3D;AAAA,IAEJ;AAEA,QAAI,cAAc;AAChB,aACE,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,cAAY,QAAQ,SAAS,QAAQ,IAAI,OAAO;AAAA,UAChD,SAAS;AAAA,UACT,WAAU;AAAA,UAEV;AAAA,4BAAAD,KAAC,UAAK,WAAU,iCAAiC,mBAAQ;AAAA,YACzD,gBAAAA,KAAC,oBAAiB,WAAU,0CAAyC;AAAA;AAAA;AAAA,MACvE;AAAA,IAEJ;AAEA,WACE,gBAAAA,KAAC,UAAK,WAAU,oFACb,mBACH;AAAA,EAEJ,GAAG;AAEH,SACE,gBAAAA,KAAC,mBAAgB,eAAe,KAC9B,0BAAAC;AAAA,IAAC;AAAA;AAAA,MACC,2BAAuB;AAAA,MACvB,wBAAqB;AAAA,MACrB,WAAW;AAAA,QACT;AAAA,QACA,SAAS,UAAU;AAAA,QACnB;AAAA,MACF;AAAA,MACA,SAAS;AAAA,MAER;AAAA,oBAAY,SAAS,SAAS,gBAAAD,KAAC,UAAK,WAAU,+CAA+C,qBAAU,IAAU;AAAA,QACjH,SAAS,SAAS,OACjB,gBAAAC,MAAC,WACC;AAAA,0BAAAD,KAAC,kBAAe,SAAO,MACrB,0BAAAA,KAAC,UAAK,WAAU,+CACb,kBACH,GACF;AAAA,UACA,gBAAAA,KAAC,kBAAe,MAAK,OAAM,WAAU,gCAClC,sBAAY,kBAAe,GAAG,KAAK,KACtC;AAAA,WACF;AAAA,QAEF,gBAAAC,MAAC,WACC;AAAA,0BAAAD,KAAC,kBAAe,SAAO,MACrB,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAM,SAAS,gBAAAA,KAAC,aAAU,WAAW,SAAS,SAAS,gBAAgB,WAAW,IAAK,gBAAAA,KAAC,YAAS,WAAW,SAAS,SAAS,gBAAgB,WAAW;AAAA,cACzJ,SAAS;AAAA,cACT,cAAY,SAAS,WAAW,QAAQ,SAAS;AAAA,cACjD,WAAU;AAAA;AAAA,UACZ,GACF;AAAA,UACA,gBAAAA,KAAC,kBAAe,MAAK,OAAO,mBAAS,WAAW,QAAQ,SAAS,KAAK,KAAK,IAAG;AAAA,WAChF;AAAA,QACC,WAAW,SAAS,SACnB,gBAAAC,MAAC,WACC;AAAA,0BAAAD,KAAC,kBAAe,SAAO,MACrB,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAM,gBAAAA,KAAC,aAAU,WAAU,WAAU;AAAA,cACrC,SAAS,CAAC,MAAM;AACd,qBAAK,CAAC;AACN,4BAAY,IAAI;AAAA,cAClB;AAAA,cACA,cAAY,iBAAiB,SAAS,QAAQ;AAAA,cAC9C,WAAU;AAAA;AAAA,UAEZ,GACF;AAAA,UACA,gBAAAC,MAAC,kBAAe,MAAK,OAAM;AAAA;AAAA,YAAe,SAAS;AAAA,aAAS;AAAA,WAC9D,IACE;AAAA,QACH,UAAU,gBAAgB,CAAC,aAAa,SAAS,SAChD,gBAAAA,MAAC,WACC;AAAA,0BAAAD,KAAC,kBAAe,SAAO,MACrB,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAM;AAAA,cACN,SAAS;AAAA,cACT,cAAY,QAAQ,SAAS,QAAQ;AAAA,cACrC,WAAU;AAAA,cAEV,0BAAAA,KAAC,oBAAiB,WAAU,WAAU;AAAA;AAAA,UACxC,GACF;AAAA,UACA,gBAAAC,MAAC,kBAAe,MAAK,OAAM;AAAA;AAAA,YAAM,SAAS;AAAA,YAAS;AAAA,aAAa;AAAA,WAClE,IACE;AAAA,QACH;AAAA,QACA;AAAA,QACA,WAAW,YAAY,eACtB,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,OAAO,YAAY,SAAS;AAAA,YAClC,IAAI;AAAA,YACJ,SAAS,MAAM,YAAY,KAAK;AAAA,YAO/B,GAAI,QAAQ,OAAO,CAAC,IAAI,EAAE,KAAK;AAAA;AAAA,QAClC,IACE;AAAA;AAAA;AAAA,EACN,GACF;AAEJ;","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-
|
|
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-
|
|
608
|
+
//# sourceMappingURL=chunk-NFJ63LIH.js.map
|
|
@@ -21,10 +21,10 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
DataRowInspector,
|
|
23
23
|
columnId
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-P56Y43RL.js";
|
|
25
25
|
import {
|
|
26
26
|
useMatrxDataTableHost
|
|
27
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
10
|
+
} from "./chunk-CZGZV35G.js";
|
|
11
11
|
import {
|
|
12
12
|
PropertyRow
|
|
13
|
-
} from "./chunk-
|
|
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-
|
|
20
|
+
} from "./chunk-KSCSH7AO.js";
|
|
21
21
|
import {
|
|
22
22
|
Button
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-WVEDW5VO.js";
|
|
24
24
|
import {
|
|
25
25
|
useMatrxDataTableHost
|
|
26
|
-
} from "./chunk-
|
|
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-
|
|
674
|
+
//# sourceMappingURL=chunk-P56Y43RL.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
Button,
|
|
10
10
|
ControlRow
|
|
11
|
-
} from "./chunk-
|
|
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-
|
|
485
|
+
//# sourceMappingURL=chunk-QTPW44IJ.js.map
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
MenuLookSub,
|
|
20
20
|
MenuLookSubContent,
|
|
21
21
|
MenuLookSubTrigger
|
|
22
|
-
} from "./chunk-
|
|
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-
|
|
40
|
+
} from "./chunk-WVEDW5VO.js";
|
|
41
41
|
import {
|
|
42
42
|
DropdownMenu,
|
|
43
43
|
DropdownMenuTrigger
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-T57DLONB.js";
|
|
45
45
|
import {
|
|
46
46
|
declareLazyDataProps,
|
|
47
47
|
useMatrxTableRowAlchemy,
|
|
48
48
|
useMatrxTableRowControls
|
|
49
|
-
} from "./chunk-
|
|
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-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
105
|
-
const [bottomClearance] = React.useState(
|
|
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-
|
|
229
|
+
//# sourceMappingURL=chunk-T57DLONB.js.map
|