gridsmith-ui 0.30.2 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +71 -1
  2. package/dist/charts.d.ts +114 -1
  3. package/dist/charts.js +1113 -206
  4. package/dist/charts.js.map +1 -1
  5. package/dist/chat.js +20 -12
  6. package/dist/chat.js.map +1 -1
  7. package/dist/{chunk-HVGHGBKV.js → chunk-2TCCSKL3.js} +6 -7
  8. package/dist/chunk-2TCCSKL3.js.map +1 -0
  9. package/dist/{chunk-L6HWACK7.js → chunk-53F7GVBQ.js} +6 -3
  10. package/dist/chunk-53F7GVBQ.js.map +1 -0
  11. package/dist/chunk-BHTAVJIG.js +285 -0
  12. package/dist/chunk-BHTAVJIG.js.map +1 -0
  13. package/dist/{chunk-WWN6CQKI.js → chunk-DR6WEI3A.js} +60 -7
  14. package/dist/chunk-DR6WEI3A.js.map +1 -0
  15. package/dist/{chunk-4HJDOZ2M.js → chunk-EZ3ZGFGA.js} +203 -34
  16. package/dist/chunk-EZ3ZGFGA.js.map +1 -0
  17. package/dist/{chunk-MIUSSYVE.js → chunk-HQFTP7Y5.js} +27 -52
  18. package/dist/chunk-HQFTP7Y5.js.map +1 -0
  19. package/dist/{chunk-SIWERRP2.js → chunk-I6JJ7KKP.js} +14 -15
  20. package/dist/chunk-I6JJ7KKP.js.map +1 -0
  21. package/dist/chunk-IOHGE4EW.js +755 -0
  22. package/dist/chunk-IOHGE4EW.js.map +1 -0
  23. package/dist/{chunk-USHW523V.js → chunk-IZW5XHKA.js} +73 -699
  24. package/dist/chunk-IZW5XHKA.js.map +1 -0
  25. package/dist/{chunk-ZASGFL5D.js → chunk-K3NAFQ4S.js} +3 -4
  26. package/dist/chunk-K3NAFQ4S.js.map +1 -0
  27. package/dist/{chunk-ACLKDE5W.js → chunk-KSJTMSYA.js} +23 -11
  28. package/dist/chunk-KSJTMSYA.js.map +1 -0
  29. package/dist/{chunk-SQHKC4HA.js → chunk-NDL2JGQ7.js} +8 -7
  30. package/dist/chunk-NDL2JGQ7.js.map +1 -0
  31. package/dist/{chunk-TYNDXMBV.js → chunk-QOMP4D6V.js} +3 -3
  32. package/dist/{chunk-TYNDXMBV.js.map → chunk-QOMP4D6V.js.map} +1 -1
  33. package/dist/{chunk-BZRZENBS.js → chunk-SLGGZ3MU.js} +6 -6
  34. package/dist/{chunk-BZRZENBS.js.map → chunk-SLGGZ3MU.js.map} +1 -1
  35. package/dist/{chunk-K6IDOCGE.js → chunk-TH272DIC.js} +10 -10
  36. package/dist/{chunk-K6IDOCGE.js.map → chunk-TH272DIC.js.map} +1 -1
  37. package/dist/chunk-V73LHNRL.js +51 -0
  38. package/dist/chunk-V73LHNRL.js.map +1 -0
  39. package/dist/{chunk-ZCDA74RQ.js → chunk-W3GY5ROH.js} +3 -3
  40. package/dist/{chunk-ZCDA74RQ.js.map → chunk-W3GY5ROH.js.map} +1 -1
  41. package/dist/data-grid.js +11 -12
  42. package/dist/data-grid.js.map +1 -1
  43. package/dist/editor-mentions.js +2 -3
  44. package/dist/editor-mentions.js.map +1 -1
  45. package/dist/editor.js +4 -6
  46. package/dist/editor.js.map +1 -1
  47. package/dist/icons.js +1 -1
  48. package/dist/index.d.ts +100 -16
  49. package/dist/index.js +1177 -660
  50. package/dist/index.js.map +1 -1
  51. package/dist/kanban.js +10 -11
  52. package/dist/kanban.js.map +1 -1
  53. package/dist/resizable.js +10 -11
  54. package/dist/resizable.js.map +1 -1
  55. package/dist/virtualized.js +11 -12
  56. package/dist/virtualized.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/chunk-4HJDOZ2M.js.map +0 -1
  59. package/dist/chunk-6C2IUMY7.js +0 -46
  60. package/dist/chunk-6C2IUMY7.js.map +0 -1
  61. package/dist/chunk-7Q46JXSK.js +0 -51
  62. package/dist/chunk-7Q46JXSK.js.map +0 -1
  63. package/dist/chunk-ACLKDE5W.js.map +0 -1
  64. package/dist/chunk-HVGHGBKV.js.map +0 -1
  65. package/dist/chunk-L6HWACK7.js.map +0 -1
  66. package/dist/chunk-MIUSSYVE.js.map +0 -1
  67. package/dist/chunk-NKUCS67T.js +0 -13
  68. package/dist/chunk-NKUCS67T.js.map +0 -1
  69. package/dist/chunk-SIWERRP2.js.map +0 -1
  70. package/dist/chunk-SQHKC4HA.js.map +0 -1
  71. package/dist/chunk-USHW523V.js.map +0 -1
  72. package/dist/chunk-WWN6CQKI.js.map +0 -1
  73. package/dist/chunk-YL5KD5RC.js +0 -49
  74. package/dist/chunk-YL5KD5RC.js.map +0 -1
  75. package/dist/chunk-ZASGFL5D.js.map +0 -1
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { createContext, createElement, useContext, useLayoutEffect } from 'react';
3
+
4
+ // ../../showcase/src/lib/page-actions.ts
5
+ var PageActionsCtx = createContext(null);
6
+ var CardSurfaceCtx = createContext(false);
7
+ var SplitPaneCtx = createContext(false);
8
+ var TableCardCtx = createContext(false);
9
+ var RowsCtx = createContext(false);
10
+ var SplitListFramerCtx = createContext(null);
11
+ function useReportToList(kind) {
12
+ const report = useContext(SplitListFramerCtx);
13
+ useLayoutEffect(() => {
14
+ if (!report) return;
15
+ report(kind, true);
16
+ return () => report(kind, false);
17
+ }, [report, kind]);
18
+ }
19
+ function useFramesItself() {
20
+ useReportToList("framed");
21
+ }
22
+ function useScrollsInside() {
23
+ useReportToList("scrolls");
24
+ }
25
+ function SurfaceBoundary({ children, pane = false, framer = null }) {
26
+ return createElement(
27
+ CardSurfaceCtx,
28
+ { value: false },
29
+ createElement(
30
+ SplitPaneCtx,
31
+ { value: pane },
32
+ createElement(
33
+ TableCardCtx,
34
+ { value: false },
35
+ createElement(
36
+ RowsCtx,
37
+ { value: false },
38
+ createElement(
39
+ PageActionsCtx,
40
+ { value: null },
41
+ createElement(SplitListFramerCtx, { value: framer }, children)
42
+ )
43
+ )
44
+ )
45
+ )
46
+ );
47
+ }
48
+
49
+ export { CardSurfaceCtx, PageActionsCtx, RowsCtx, SplitPaneCtx, SurfaceBoundary, TableCardCtx, useFramesItself, useScrollsInside };
50
+ //# sourceMappingURL=chunk-V73LHNRL.js.map
51
+ //# sourceMappingURL=chunk-V73LHNRL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../showcase/src/lib/page-actions.ts","../../../showcase/src/lib/surface-context.ts"],"names":["createContext"],"mappings":";;;;AAwBO,IAAM,cAAA,GAAiB,cAAsC,IAAI;AClBjE,IAAM,cAAA,GAAiBA,cAAc,KAAK;AAS1C,IAAM,YAAA,GAAeA,cAA6B,KAAK;AAOvD,IAAM,YAAA,GAAeA,cAAc,KAAK;AAUxC,IAAM,OAAA,GAAUA,cAAc,KAAK;AAWnC,IAAM,kBAAA,GAAqBA,cAAsC,IAAI,CAAA;AAE5E,SAAS,gBAAgB,IAAA,EAA4B;AACnD,EAAA,MAAM,MAAA,GAAS,WAAW,kBAAkB,CAAA;AAC5C,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAA,CAAO,MAAM,IAAI,CAAA;AACjB,IAAA,OAAO,MAAM,MAAA,CAAO,IAAA,EAAM,KAAK,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAI,CAAC,CAAA;AACnB;AAGO,SAAS,eAAA,GAAkB;AAChC,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAC1B;AAGO,SAAS,gBAAA,GAAmB;AACjC,EAAA,eAAA,CAAgB,SAAS,CAAA;AAC3B;AASO,SAAS,gBAAgB,EAAE,QAAA,EAAU,OAAO,KAAA,EAAO,MAAA,GAAS,MAAK,EAAmF;AAGzJ,EAAA,OAAO,aAAA;AAAA,IAAc,cAAA;AAAA,IAAgB,EAAE,OAAO,KAAA,EAAM;AAAA,IAClD,aAAA;AAAA,MAAc,YAAA;AAAA,MAAc,EAAE,OAAO,IAAA,EAAK;AAAA,MACxC,aAAA;AAAA,QAAc,YAAA;AAAA,QAAc,EAAE,OAAO,KAAA,EAAM;AAAA,QACzC,aAAA;AAAA,UAAc,OAAA;AAAA,UAAS,EAAE,OAAO,KAAA,EAAM;AAAA,UACpC,aAAA;AAAA,YAAc,cAAA;AAAA,YAAgB,EAAE,OAAO,IAAA,EAAK;AAAA,YAC1C,cAAc,kBAAA,EAAoB,EAAE,KAAA,EAAO,MAAA,IAAU,QAAQ;AAAA;AAAC;AAAC;AAAC;AAAC,GAAC;AAC9E","file":"chunk-V73LHNRL.js","sourcesContent":["import { createContext } from \"react\";\nimport type { ControlSize } from \"../components/Button\";\n\n/**\n * Sprint 25.16 A4 (R28-7): the slot in a page's own PageHeader for its actions (PageActions). PageContainer provides it,\n * its header draws it while a page asks, and the page's PageActions render into it. The review of 1 October:\n * - content that starts afresh (an overlay's body, a SplitView's pane: SurfaceBoundary) has no slot, so a header there\n * (a message's own header, a drawer's) never takes the page's actions;\n * - the page's header is the first slot in the page, so a second header that comes and goes hands nothing on;\n * - a container with no header of its own (a page that wraps itself in one under an area layout) passes its page's\n * actions to the container around it;\n * - the actions take the header's control size (a minimal or snapping header draws its own actions small).\n */\nexport interface PageActionsSlot {\n /** A page below asks for the slot: a PageActions is drawn. */\n wanted: boolean;\n /** Where the actions go: the slot of the page's header, at the size its controls are drawn. */\n target: { el: HTMLElement; size: ControlSize | null } | null;\n /** A header's slot, while drawn, with its controls' size; returns its release. */\n register: (el: HTMLElement, size: ControlSize | null) => () => void;\n /** A PageActions asks for the slot while drawn; returns its release. */\n add: () => () => void;\n}\n\nexport const PageActionsCtx = createContext<PageActionsSlot | null>(null);\n","import { createContext, createElement, useContext, useLayoutEffect, type ReactNode } from \"react\";\nimport { PageActionsCtx } from \"./page-actions\";\n\n/**\n * True inside a Card's surface. A StackedList reads it to inset its rows to the card's header (px-ds-5).\n */\nexport const CardSurfaceCtx = createContext(false);\n\n/**\n * The SplitView pane content sits in (\"list\", \"detail\", \"aside\"), false outside one. A StackedList reads it to take its\n * inset from the pane (Sprint 25.4 C-5): rows keep their padding so the selection rail sits at the pane's edge and never\n * touches content. A pane header (SectionHeading variant=\"pane\") in the detail insets at the page's gutter, as the item's\n * path above it does, and in the list at its rows' inset (the owner's review of 1 October).\n */\nexport type SplitPaneKind = false | \"list\" | \"detail\" | \"aside\";\nexport const SplitPaneCtx = createContext<SplitPaneKind>(false);\n\n/**\n * True inside a Table or DataGrid card (the phone layout below mobileBreakpoint). An EntityCell reads it to keep\n * the avatar beside the text and align to the value column (Sprint 25.4, round 7: the stacked cell made the card\n * three lines taller than it needed to be).\n */\nexport const TableCardCtx = createContext(false);\n\n/**\n * True among a collection's rows: a Table's or a DataGrid's rows and their phone cards, a StackedList's rows, a Timeline's\n * items, a NotificationCenter's rows. Something\n * with a Tab stop of its own adds a stop to every row there, which makes the collection hard to cross: a RelativeTime\n * drops its own, its full timestamp in its name and on hover (Sprint 25.17 A29). A DataList is one record's fields, not\n * rows, so it doesn't set it (the second review). Inside a control (a card or a row that is a button, a link) the time\n * finds that for itself, from the page. Overlays reset it: SurfaceBoundary, a Popover, a HoverCard.\n */\nexport const RowsCtx = createContext(false);\n\n/**\n * Sprint 25.14 A44: what a SplitView's list pane holds, as its content reports it while mounted. \"framed\": content that\n * draws its own frame or cards (a KanbanBoard, a CardGrid, a Table, a DataGrid). \"scrolls\": content with no frame of its\n * own that scrolls inside the pane (a StackedList, a Gantt, a VirtualizedList), which the view's hairline frames. The\n * view drops its frame and surface when the pane holds framed content and nothing that scrolls (P32: no frame around\n * what frames itself; a hairline around what scrolls inside). Here, not in SplitView, so a board or a card grid never\n * imports the resizable panels. Null outside a list pane: overlays and the view's other panes reset it (SurfaceBoundary).\n */\nexport type SplitListReport = (kind: \"framed\" | \"scrolls\", present: boolean) => void;\nexport const SplitListFramerCtx = createContext<SplitListReport | null>(null);\n\nfunction useReportToList(kind: \"framed\" | \"scrolls\") {\n const report = useContext(SplitListFramerCtx);\n useLayoutEffect(() => {\n if (!report) return;\n report(kind, true);\n return () => report(kind, false);\n }, [report, kind]);\n}\n\n/** Tell a SplitView whose list pane this sits in that it draws its own frame or cards (A44). */\nexport function useFramesItself() {\n useReportToList(\"framed\");\n}\n\n/** Tell a SplitView whose list pane this sits in that it scrolls inside the pane with no frame of its own (A44). */\nexport function useScrollsInside() {\n useReportToList(\"scrolls\");\n}\n\n/**\n * Where content starts afresh: an overlay's body, an opened table row's panel, a SplitView's pane. What a Card, a pane\n * or a table card told the content around it stops here (the review of 30 September: a StackedList in a Drawer opened\n * from a Card took the card's inset, and one in a Dialog declared in a list pane the pane's, so neither lined up with\n * the overlay's gutter), and so does the page's actions slot. A pane passes `pane` (which pane its content is in) and\n * the list pane its `framer`.\n */\nexport function SurfaceBoundary({ children, pane = false, framer = null }: { children: ReactNode; pane?: SplitPaneKind; framer?: SplitListReport | null }) {\n // the page's actions belong to the page's own header (Sprint 25.16's review): a header in a pane or an overlay never\n // takes them, and PageActions there renders nothing\n return createElement(CardSurfaceCtx, { value: false },\n createElement(SplitPaneCtx, { value: pane },\n createElement(TableCardCtx, { value: false },\n createElement(RowsCtx, { value: false },\n createElement(PageActionsCtx, { value: null },\n createElement(SplitListFramerCtx, { value: framer }, children))))));\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { useLatest } from './chunk-4HJDOZ2M.js';
2
+ import { useLatest } from './chunk-EZ3ZGFGA.js';
3
3
  import { useState, useRef, useCallback, useEffect } from 'react';
4
4
 
5
5
  var registry = /* @__PURE__ */ new WeakMap();
@@ -106,5 +106,5 @@ function useTextOverflow(options = {}) {
106
106
  }
107
107
 
108
108
  export { useTextOverflow };
109
- //# sourceMappingURL=chunk-ZCDA74RQ.js.map
110
- //# sourceMappingURL=chunk-ZCDA74RQ.js.map
109
+ //# sourceMappingURL=chunk-W3GY5ROH.js.map
110
+ //# sourceMappingURL=chunk-W3GY5ROH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/use-text-overflow.ts"],"names":[],"mappings":"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","file":"chunk-ZCDA74RQ.js","sourcesContent":["import { useState, useCallback, useRef, useEffect } from \"react\";\nimport { useLatest } from \"./use-latest\";\n\n// ─── Shared ResizeObserver (singleton per document) ────────────────────────────\n// All useTextOverflow instances share a single ResizeObserver. This avoids the\n// performance cost of 80+ independent observers on pages with many truncated elements.\n\ntype OverflowCallback = () => void;\n\nconst registry = new WeakMap<Element, Set<OverflowCallback>>();\nlet sharedObserver: ResizeObserver | null = null;\nlet rafId: number | null = null;\nconst pendingElements = new Set<Element>();\n\nfunction getSharedObserver(): ResizeObserver {\n if (sharedObserver) return sharedObserver;\n sharedObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n pendingElements.add(entry.target);\n }\n if (rafId === null) {\n rafId = requestAnimationFrame(flush);\n }\n });\n return sharedObserver;\n}\n\nfunction flush() {\n rafId = null;\n for (const el of pendingElements) {\n const callbacks = registry.get(el);\n if (callbacks) {\n for (const cb of callbacks) cb();\n }\n }\n pendingElements.clear();\n}\n\nfunction observe(el: Element, callback: OverflowCallback) {\n let set = registry.get(el);\n if (!set) {\n set = new Set();\n registry.set(el, set);\n }\n set.add(callback);\n if (set.size === 1) {\n getSharedObserver().observe(el);\n }\n}\n\nfunction unobserve(el: Element, callback: OverflowCallback) {\n const set = registry.get(el);\n if (!set) return;\n set.delete(callback);\n if (set.size === 0) {\n registry.delete(el);\n getSharedObserver().unobserve(el);\n }\n}\n\n// ─── Overflow detection ────────────────────────────────────────────────────────\n\nconst TOLERANCE = 1; // px — accounts for integer rounding in scrollWidth/clientWidth\n\nfunction checkOverflow(el: HTMLElement, lines: number): boolean {\n if (lines <= 1) {\n return el.scrollWidth - el.clientWidth > TOLERANCE;\n }\n return el.scrollHeight - el.clientHeight > TOLERANCE;\n}\n\n// ─── Hook ──────────────────────────────────────────────────────────────────────\n\nexport interface UseTextOverflowOptions {\n /** Number of visible lines before truncation. 1 = single-line ellipsis, >1 = line-clamp. */\n lines?: number;\n /** Disable overflow detection (e.g. when component is hidden) */\n disabled?: boolean;\n /** Content key — triggers re-check when this value changes (use for dynamic text content) */\n content?: unknown;\n}\n\nexport interface UseTextOverflowResult {\n /** Callback ref — attach to the element that has truncation CSS applied */\n ref: (node: HTMLElement | null) => void;\n /** True when the element's text is currently overflowing/truncated */\n isTruncated: boolean;\n}\n\n/**\n * Detects whether an element's text content is overflowing (truncated).\n * Uses a single shared ResizeObserver for all instances on the page.\n *\n * @example\n * const { ref, isTruncated } = useTextOverflow({ lines: 1 });\n * return (\n * <Tooltip content={fullText} disabled={!isTruncated}>\n * <span ref={ref} className=\"truncate\">{fullText}</span>\n * </Tooltip>\n * );\n */\nexport function useTextOverflow(options: UseTextOverflowOptions = {}): UseTextOverflowResult {\n const { lines = 1, disabled = false, content } = options;\n const [isTruncated, setIsTruncated] = useState(false);\n const elementRef = useRef<HTMLElement | null>(null);\n // The observer-registered wrapper delegates to the latest check logic via checkRef.\n const registeredRef = useRef<OverflowCallback | null>(null);\n\n const doCheck = useCallback(() => {\n if (!elementRef.current || disabled) {\n setIsTruncated(false);\n return;\n }\n const next = checkOverflow(elementRef.current, lines);\n setIsTruncated((prev) => (prev !== next ? next : prev));\n }, [lines, disabled]);\n\n // Latest check logic, updated in a layout effect so the stable wrapper never runs a stale closure.\n const checkRef = useLatest<OverflowCallback>(doCheck);\n\n // Re-check when content changes (handles dynamic text like Dropdown selection)\n // or when disabled state changes\n // Measures the committed DOM, so it must stay a post-layout effect.\n /* eslint-disable react-hooks/set-state-in-effect -- overflow is a layout measurement */\n useEffect(() => {\n if (disabled) {\n setIsTruncated(false);\n } else if (elementRef.current) {\n const next = checkOverflow(elementRef.current, lines);\n setIsTruncated((prev) => (prev !== next ? next : prev));\n }\n }, [content, lines, disabled]);\n /* eslint-enable react-hooks/set-state-in-effect */\n\n const ref = useCallback(\n (node: HTMLElement | null) => {\n const prev = elementRef.current;\n\n // Unregister previous element using the SAME function we registered with\n if (prev && registeredRef.current) {\n unobserve(prev, registeredRef.current);\n registeredRef.current = null;\n }\n\n elementRef.current = node;\n\n if (node && !disabled) {\n // Stable wrapper that delegates to the latest check logic\n const wrapper: OverflowCallback = () => checkRef.current?.();\n registeredRef.current = wrapper;\n observe(node, wrapper);\n // Initial check on mount\n const initial = checkOverflow(node, lines);\n setIsTruncated(initial);\n }\n },\n [lines, disabled, checkRef],\n );\n\n // Cleanup on unmount — uses the registered wrapper, not the check function\n useEffect(() => {\n return () => {\n if (elementRef.current && registeredRef.current) {\n unobserve(elementRef.current, registeredRef.current);\n }\n };\n }, []);\n\n return { ref, isTruncated };\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/lib/use-text-overflow.ts"],"names":[],"mappings":"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","file":"chunk-W3GY5ROH.js","sourcesContent":["import { useState, useCallback, useRef, useEffect } from \"react\";\nimport { useLatest } from \"./use-latest\";\n\n// ─── Shared ResizeObserver (singleton per document) ────────────────────────────\n// All useTextOverflow instances share a single ResizeObserver. This avoids the\n// performance cost of 80+ independent observers on pages with many truncated elements.\n\ntype OverflowCallback = () => void;\n\nconst registry = new WeakMap<Element, Set<OverflowCallback>>();\nlet sharedObserver: ResizeObserver | null = null;\nlet rafId: number | null = null;\nconst pendingElements = new Set<Element>();\n\nfunction getSharedObserver(): ResizeObserver {\n if (sharedObserver) return sharedObserver;\n sharedObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n pendingElements.add(entry.target);\n }\n if (rafId === null) {\n rafId = requestAnimationFrame(flush);\n }\n });\n return sharedObserver;\n}\n\nfunction flush() {\n rafId = null;\n for (const el of pendingElements) {\n const callbacks = registry.get(el);\n if (callbacks) {\n for (const cb of callbacks) cb();\n }\n }\n pendingElements.clear();\n}\n\nfunction observe(el: Element, callback: OverflowCallback) {\n let set = registry.get(el);\n if (!set) {\n set = new Set();\n registry.set(el, set);\n }\n set.add(callback);\n if (set.size === 1) {\n getSharedObserver().observe(el);\n }\n}\n\nfunction unobserve(el: Element, callback: OverflowCallback) {\n const set = registry.get(el);\n if (!set) return;\n set.delete(callback);\n if (set.size === 0) {\n registry.delete(el);\n getSharedObserver().unobserve(el);\n }\n}\n\n// ─── Overflow detection ────────────────────────────────────────────────────────\n\nconst TOLERANCE = 1; // px — accounts for integer rounding in scrollWidth/clientWidth\n\nfunction checkOverflow(el: HTMLElement, lines: number): boolean {\n if (lines <= 1) {\n return el.scrollWidth - el.clientWidth > TOLERANCE;\n }\n return el.scrollHeight - el.clientHeight > TOLERANCE;\n}\n\n// ─── Hook ──────────────────────────────────────────────────────────────────────\n\nexport interface UseTextOverflowOptions {\n /** Number of visible lines before truncation. 1 = single-line ellipsis, >1 = line-clamp. */\n lines?: number;\n /** Disable overflow detection (e.g. when component is hidden) */\n disabled?: boolean;\n /** Content key — triggers re-check when this value changes (use for dynamic text content) */\n content?: unknown;\n}\n\nexport interface UseTextOverflowResult {\n /** Callback ref — attach to the element that has truncation CSS applied */\n ref: (node: HTMLElement | null) => void;\n /** True when the element's text is currently overflowing/truncated */\n isTruncated: boolean;\n}\n\n/**\n * Detects whether an element's text content is overflowing (truncated).\n * Uses a single shared ResizeObserver for all instances on the page.\n *\n * @example\n * const { ref, isTruncated } = useTextOverflow({ lines: 1 });\n * return (\n * <Tooltip content={fullText} disabled={!isTruncated}>\n * <span ref={ref} className=\"truncate\">{fullText}</span>\n * </Tooltip>\n * );\n */\nexport function useTextOverflow(options: UseTextOverflowOptions = {}): UseTextOverflowResult {\n const { lines = 1, disabled = false, content } = options;\n const [isTruncated, setIsTruncated] = useState(false);\n const elementRef = useRef<HTMLElement | null>(null);\n // The observer-registered wrapper delegates to the latest check logic via checkRef.\n const registeredRef = useRef<OverflowCallback | null>(null);\n\n const doCheck = useCallback(() => {\n if (!elementRef.current || disabled) {\n setIsTruncated(false);\n return;\n }\n const next = checkOverflow(elementRef.current, lines);\n setIsTruncated((prev) => (prev !== next ? next : prev));\n }, [lines, disabled]);\n\n // Latest check logic, updated in a layout effect so the stable wrapper never runs a stale closure.\n const checkRef = useLatest<OverflowCallback>(doCheck);\n\n // Re-check when content changes (handles dynamic text like Dropdown selection)\n // or when disabled state changes\n // Measures the committed DOM, so it must stay a post-layout effect.\n /* eslint-disable react-hooks/set-state-in-effect -- overflow is a layout measurement */\n useEffect(() => {\n if (disabled) {\n setIsTruncated(false);\n } else if (elementRef.current) {\n const next = checkOverflow(elementRef.current, lines);\n setIsTruncated((prev) => (prev !== next ? next : prev));\n }\n }, [content, lines, disabled]);\n /* eslint-enable react-hooks/set-state-in-effect */\n\n const ref = useCallback(\n (node: HTMLElement | null) => {\n const prev = elementRef.current;\n\n // Unregister previous element using the SAME function we registered with\n if (prev && registeredRef.current) {\n unobserve(prev, registeredRef.current);\n registeredRef.current = null;\n }\n\n elementRef.current = node;\n\n if (node && !disabled) {\n // Stable wrapper that delegates to the latest check logic\n const wrapper: OverflowCallback = () => checkRef.current?.();\n registeredRef.current = wrapper;\n observe(node, wrapper);\n // Initial check on mount\n const initial = checkOverflow(node, lines);\n setIsTruncated(initial);\n }\n },\n [lines, disabled, checkRef],\n );\n\n // Cleanup on unmount — uses the registered wrapper, not the check function\n useEffect(() => {\n return () => {\n if (elementRef.current && registeredRef.current) {\n unobserve(elementRef.current, registeredRef.current);\n }\n };\n }, []);\n\n return { ref, isTruncated };\n}\n"]}
package/dist/data-grid.js CHANGED
@@ -1,20 +1,19 @@
1
1
  "use client";
2
- import { useCardsSwitch, CARDS_BELOW, inferColumnKinds, CardValue, SortIndicator, CutCell, CutEmail, dayKey, DatePicker, Checkbox } from './chunk-SIWERRP2.js';
3
- import { usePagination, useWholeListCheck, pagerPart, Pagination, Dropdown, Field, NumberInput, Input } from './chunk-USHW523V.js';
4
- import { useShellPreferences } from './chunk-TYNDXMBV.js';
2
+ import { useCardsSwitch, CARDS_BELOW, inferColumnKinds, CardValue, SortIndicator, CutCell, CutEmail, dayKey, DatePicker, Checkbox } from './chunk-I6JJ7KKP.js';
3
+ import { usePagination, useWholeListCheck, pagerPart, Pagination, NumberInput } from './chunk-IOHGE4EW.js';
4
+ import { useShellPreferences } from './chunk-QOMP4D6V.js';
5
5
  import './chunk-LJYSVZMI.js';
6
+ import { Dropdown, Field, Input } from './chunk-IZW5XHKA.js';
6
7
  import './chunk-7QLXYRPD.js';
7
- import './chunk-7RKC5C7G.js';
8
8
  import { FormChangeCtx } from './chunk-72SDAX54.js';
9
- import { useFramesItself, TableCardCtx, RowsCtx } from './chunk-MIUSSYVE.js';
10
- import './chunk-NKUCS67T.js';
9
+ import { useFramesItself, TableCardCtx, RowsCtx } from './chunk-V73LHNRL.js';
10
+ import './chunk-HQFTP7Y5.js';
11
11
  import { useBreakpoint } from './chunk-ZHUVLBCC.js';
12
- import './chunk-ZCDA74RQ.js';
13
- import { useRevealFocus } from './chunk-WWN6CQKI.js';
14
- import { Icon, warnOnce } from './chunk-L6HWACK7.js';
15
- import './chunk-7Q46JXSK.js';
16
- import { useGridKeyboard, useFocusLeave, focusInitial } from './chunk-4HJDOZ2M.js';
17
- import { cn, FOCUS_INSET, FOCUS_RING } from './chunk-YL5KD5RC.js';
12
+ import './chunk-7RKC5C7G.js';
13
+ import './chunk-W3GY5ROH.js';
14
+ import { useRevealFocus } from './chunk-DR6WEI3A.js';
15
+ import { Icon, warnOnce } from './chunk-53F7GVBQ.js';
16
+ import { cn, useGridKeyboard, FOCUS_INSET, FOCUS_RING, useFocusLeave, focusInitial } from './chunk-EZ3ZGFGA.js';
18
17
  import { useState, useMemo, useCallback, useRef, useEffect, useLayoutEffect } from 'react';
19
18
  import { useReactTable, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
20
19
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/components/DataGrid.tsx"],"names":[],"mappings":"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","file":"data-grid.js","sourcesContent":["import { useState, useCallback, useEffect, useLayoutEffect, useMemo, useRef, type ReactElement, type ReactNode, type SyntheticEvent, type KeyboardEvent as ReactKeyboardEvent } from \"react\";\nimport { useShellPreferences } from \"../lib/preferences\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n flexRender,\n type CellContext,\n type ColumnDef,\n type Header,\n type SortingState,\n} from \"@tanstack/react-table\";\nimport { cn, FOCUS_INSET, FOCUS_RING } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { CutCell, CutEmail } from \"./TextOverflow\";\nimport { Input } from \"./Input\";\nimport { NumberInput } from \"./NumberInput\";\nimport { DatePicker } from \"./DatePicker\";\nimport { Dropdown } from \"./Dropdown\";\nimport { Checkbox } from \"./Checkbox\";\nimport { Field } from \"./Field\";\nimport { Pagination } from \"./Pagination\";\nimport { useBreakpoint, type BreakpointKey } from \"../lib/use-breakpoint\";\nimport { useRevealFocus } from \"../lib/reveal-focus\";\nimport { inferColumnKinds, type ColumnKind } from \"../lib/table-utils\";\nimport { CardValue } from \"../lib/card-cell\";\nimport { TableCardCtx, RowsCtx, useFramesItself } from \"../lib/surface-context\";\nimport { FormChangeCtx } from \"../lib/form-context\";\nimport { focusInitial, useFocusLeave, useGridKeyboard } from \"../lib/focus\";\nimport { dayKey } from \"../lib/date-grid\";\nimport { SortIndicator } from \"../lib/sort-indicator\";\nimport { warnOnce } from \"../lib/dev-warn\";\nimport { usePagination, pagerPart, useWholeListCheck, type Pager } from \"../lib/use-pagination\";\nimport { CARDS_BELOW, useCardsSwitch } from \"../lib/use-cards-switch\";\n\n/** One of a choice column's options: the value its cells hold, and the words shown for it. */\nexport interface DataGridOption {\n value: string | number;\n label: string;\n}\n\n/** Column meta for opt-in truncation. Set on ColumnDef.meta. */\nexport interface DataGridColumnMeta {\n /** true = single-line, or { lines: N } for multi-line clamp. */\n truncate?: boolean | { lines: number };\n /** CSS max-width for the column. */\n maxWidth?: string;\n /** CSS width for the column — sibling grids that share a column set line up when their columns carry the same widths (round 14). */\n width?: string;\n /** CSS min-width for the column. */\n minWidth?: string;\n /**\n * Explicit column kind. When omitted the DataGrid infers it from data values (a yes or no too; never a choice). In an\n * editable grid it chooses the editor, where the control can hold the cell's value: \"number\" a NumberInput for a\n * number, \"date\" a DatePicker for a Date or an ISO date (\"2026-10-14\"), \"choice\" a Dropdown of `options`, \"boolean\" a\n * Checkbox; any other kind, and a number or a date written as text (\"18 KB\", \"12 Jan 2026\"), a text Input.\n */\n kind?: ColumnKind;\n /** Horizontal alignment of the header and the cells; a block element (a Checkbox, a Button) is laid out with flex so it follows too (round 14). Default: numbers right, everything else left. */\n align?: \"left\" | \"center\" | \"right\";\n /**\n * In an editable grid, whether this column's cells edit (default true); false for a column that shows (a status, a\n * calculated value, actions): its cells show no edit cue, and assistive tech hears them as read-only.\n */\n editable?: boolean;\n /**\n * A choice column's options (with `kind: \"choice\"`): its cells edit with a Dropdown of them, and a save gives the\n * option's `value`. Give the column a `cell` that shows the option's label.\n */\n options?: readonly DataGridOption[];\n /**\n * In an editable grid, the value onCellEdit gets from what was typed in a text cell, or in a number cell as its text\n * (default the text itself, or the number): a price written as text, `(text) => Number(text.replace(/[$,]/g, \"\"))`.\n * A date, a choice and a yes or no are given as their own values.\n */\n parse?: (text: string) => unknown;\n}\n\n/** The control a cell edits with (Sprint 25.8.7 item 19): its column's kind, where that control can hold the cell's value. */\ntype CellEditorKind = \"text\" | \"number\" | \"date\" | \"choice\" | \"boolean\";\n\n/** What an edit starts from: its control, the control's value, and how a saved value goes back in the cell's own form. */\ninterface EditorSetup {\n editor: CellEditorKind;\n value: unknown;\n out: (value: unknown) => unknown;\n}\n\nconst isEmpty = (v: unknown) => v === null || v === undefined || v === \"\";\nconst isDate = (v: unknown): v is Date => v instanceof Date && !Number.isNaN(v.getTime());\n/** An ISO date's text (\"2026-10-14\") as the local day it names, else null; the date grid's day key is the same text. */\nfunction isoDay(v: unknown): Date | null {\n const m = typeof v === \"string\" ? /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(v) : null;\n if (!m) return null;\n const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));\n return dayKey(d) === v ? d : null;\n}\n/** Two of an editor's values are one: a date by its time, anything else by itself. */\nconst sameValue = (a: unknown, b: unknown) => (isDate(a) && isDate(b) ? a.getTime() === b.getTime() : Object.is(a, b));\n\n/**\n * The editor for a cell. A control edits only a value it can hold: a NumberInput holds no empty cell and no \"18 KB\", a\n * DatePicker gives back no \"12 Jan 2026\", so those keep the text Input. A date goes back in the form it came: a Date,\n * keeping its time of day, or an ISO date's text; an empty cell's, as the column's first date is (a Date when it has\n * none).\n */\nfunction editorFor(kind: ColumnKind | undefined, raw: unknown, meta: DataGridColumnMeta | undefined, firstOfColumn: () => unknown): EditorSetup {\n const parse = meta?.parse;\n if (kind === \"choice\" && meta?.options?.length) return { editor: \"choice\", value: raw ?? null, out: (v) => v };\n if (kind === \"boolean\" && (typeof raw === \"boolean\" || isEmpty(raw))) return { editor: \"boolean\", value: raw === true, out: (v) => v };\n if (kind === \"number\" && typeof raw === \"number\" && Number.isFinite(raw)) return { editor: \"number\", value: raw, out: (v) => (parse ? parse(String(v)) : v) };\n if (kind === \"date\") {\n const was = isEmpty(raw) ? firstOfColumn() : raw;\n if (isDate(raw)) {\n return { editor: \"date\", value: raw, out: (v) => (isDate(v) ? new Date(v.getFullYear(), v.getMonth(), v.getDate(), raw.getHours(), raw.getMinutes(), raw.getSeconds(), raw.getMilliseconds()) : null) };\n }\n if (isoDay(was)) return { editor: \"date\", value: isoDay(raw), out: (v) => (isDate(v) ? dayKey(v) : null) };\n if (isEmpty(was) || isDate(was)) return { editor: \"date\", value: null, out: (v) => (isDate(v) ? v : null) };\n }\n return { editor: \"text\", value: String(raw ?? \"\"), out: (v) => (parse ? parse(v as string) : v) };\n}\n\n/**\n * A cell's editor (Sprint 25.8.7 item 19): the library's control for its column's kind, named for the column by a\n * hidden Field label. What is typed (text, a number, a date's parts) saves with Enter or by leaving the editor; a value\n * picked by a press (an option, a calendar's day, the box) is the edit, and saves at once; Escape, in the field or in\n * its popup, leaves the cell as it was. Leaving is the Field's own check (lib/focus.ts, useFocusLeave): focus moving\n * into the editor's popup, the Dropdown's list or the DatePicker's calendar, is not leaving it.\n */\nfunction CellEditor({ editor, value, name, options, onChange, onEnd }: {\n editor: CellEditorKind;\n value: unknown;\n name: string;\n options?: readonly DataGridOption[];\n onChange: (value: unknown) => void;\n onEnd: (save: boolean, focusBack: boolean, picked?: { value: unknown }) => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n // leaving the editor saves it and lets focus go where it went (the review of 30 September: it pulled focus back, and\n // the next keys were lost)\n const leave = useFocusLeave(() => onEnd(true, false));\n // a value chosen in a popup (the calendar's day, by a click or by Enter) is the edit itself. React passes the popup's\n // events up through its portal, so a key or a press from outside this editor's own box came from there. The flag is\n // where the latest one came from, never reset by a timer: Chrome runs a capture handler and the bubbling handler that\n // changes the value as separate listeners, with a microtask checkpoint between them\n const fromPopup = useRef(false);\n const markPopupEvent = (e: SyntheticEvent) => { fromPopup.current = !ref.current?.contains(e.target as Node); };\n const opened = useRef(false);\n useLayoutEffect(() => {\n const root = ref.current;\n if (!root) return;\n focusInitial(root);\n const el = document.activeElement;\n // the value opens selected: typing replaces it, an arrow key keeps it\n if (el instanceof HTMLInputElement && el.type === \"text\") el.select();\n // a choice opens on its list, the edit itself; once, though a development build runs this twice\n if (editor === \"choice\" && !opened.current && el instanceof HTMLButtonElement && root.contains(el)) {\n opened.current = true;\n el.click();\n }\n }, [editor]);\n // a choice and the box change only when picked, and a pick saves at once; what is typed or stepped (text, a number, a\n // date's parts) waits for Enter or for leaving the editor\n const picks = editor === \"choice\" || editor === \"boolean\";\n const change = (v: unknown) => (picks || fromPopup.current ? onEnd(true, true, { value: v }) : onChange(v));\n let control: ReactElement;\n if (editor === \"number\") control = <NumberInput size=\"sm\" value={value as number} allowDecimals onChange={change} />;\n else if (editor === \"date\") control = <DatePicker size=\"sm\" value={value as Date | null} onChange={change} />;\n else if (editor === \"boolean\") control = <Checkbox checked={value === true} onChange={(checked) => change(checked)} />;\n else if (editor === \"choice\" && options) {\n control = (\n <Dropdown\n size=\"sm\"\n options={options.map((o) => ({ id: String(o.value), label: o.label }))}\n value={value === null || value === undefined ? \"\" : String(value)}\n onChange={(id) => change(options.find((o) => String(o.value) === id)?.value ?? id)}\n />\n );\n } else control = <Input size=\"sm\" value={value as string} onChange={(e) => change(e.target.value)} />;\n return (\n <div\n ref={ref}\n data-cell-editor=\"\"\n {...leave}\n onClickCapture={markPopupEvent}\n onKeyDownCapture={markPopupEvent}\n onKeyDown={(e) => {\n // Escape, in the field or its popup, leaves the cell as it was, and goes no further: a Drawer round the grid stays\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n onEnd(false, true);\n return;\n }\n // Enter saves what was typed; on a button (the Dropdown's, the calendar's) it is the button's, which opens its\n // popup, and in the popup it picks\n if (e.key === \"Enter\" && e.currentTarget.contains(e.target as Node) && !(e.target instanceof HTMLButtonElement)) {\n e.preventDefault();\n onEnd(true, true);\n }\n }}\n >\n {/* a grid saves as you go, so its editor never marks a form around it; the cells' own controls still do (the\n review of 30 September: the whole grid opted out, and a Drawer closed on a changed checkbox unasked) */}\n <FormChangeCtx value={null}>\n <Field label={name} hideLabel>{control}</Field>\n </FormChangeCtx>\n </div>\n );\n}\n\n/**\n * Sprint 25.8.7 item 19 (collections-5): an editable cell says so before it is tried, a pencil shown while the cell is\n * hovered or focused (focused too: a touch screen has no hover); a calculated or locked cell shows none. It sits in room\n * an editable column keeps at its cells' end, header too, so a value never moves and a number stays under its header.\n */\nconst EDIT_CUE_ROOM = \"pr-[calc(var(--ds-space-4)+var(--ds-space-1)+12px)]\";\n\n/** How wide an editor sits over its cell: the cell's width inside its padding, and never less than its control needs. */\nconst EDITOR_WIDTH: Record<CellEditorKind, string> = {\n text: \"w-[max(calc(100%-var(--ds-space-4)),12rem)]\",\n number: \"w-[max(calc(100%-var(--ds-space-4)),8rem)]\",\n date: \"w-[max(calc(100%-var(--ds-space-4)),10.5rem)]\",\n choice: \"w-[max(calc(100%-var(--ds-space-4)),9rem)]\",\n boolean: \"w-auto\",\n};\n/**\n * The least an editable column of numbers, dates or choices is wide, at rest too: its editor's room and the cell's\n * padding, so the editor fits in its own cell and never covers the next one (a text column is wide by its words, and\n * a text editor may run over). A page's own width or min-width for the column wins.\n */\nconst EDITABLE_MIN_WIDTH: Partial<Record<CellEditorKind, string>> = { number: \"9rem\", date: \"11.5rem\", choice: \"10rem\" };\nfunction editableMinWidth(kind: ColumnKind | undefined, meta: DataGridColumnMeta | undefined): string | undefined {\n if (meta?.width || meta?.minWidth) return undefined;\n const editor: CellEditorKind | null = kind === \"number\" ? \"number\" : kind === \"date\" ? \"date\" : kind === \"choice\" && meta?.options?.length ? \"choice\" : null;\n return editor ? EDITABLE_MIN_WIDTH[editor] : undefined;\n}\nconst EDIT_CUE = (\n <span\n data-edit-cue=\"\"\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none absolute top-1/2 -translate-y-1/2 right-ds-4 flex\",\n \"text-[var(--ds-text-muted)] opacity-0 transition-opacity duration-[var(--ds-transition-speed)]\",\n \"group-hover/cell:opacity-100 group-focus/cell:opacity-100\",\n )}\n >\n <Icon name=\"edit\" size={12} />\n </span>\n);\n\n\nexport interface DataGridProps<T> {\n data: T[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- public API: columns may carry any value type\n columns: ColumnDef<T, any>[];\n /**\n * Rows a page, over the project's (dataDisplay.itemsPerPage), for a grid the user asked to page differently. Leave it\n * out: the grid pages as the project says, with the project's control (Sprint 25.13 A5; it was 10).\n */\n pageSize?: number;\n /**\n * Cells edit in place, as the APG's grid (Sprint 25.13 A5): the grid is one Tab stop and the arrow keys move between\n * cells; Enter or F2 (or a double-click) opens a cell's editor, Enter or leaving it saves and Escape cancels, and a\n * brief tick, announced as \"Saved\", shows the save. A grid saves as you go, so it never marks a form around it.\n */\n editable?: boolean;\n /**\n * A saved edit: the row's index in `data`, the column's id and the new value (the text typed, or the column's\n * `meta.parse` of it). Called only when the value changed. Return a promise to have the tick and \"Saved\" wait for it:\n * a rejection is announced as \"Not saved\", and the page says why and keeps the old value.\n */\n onCellEdit?: (rowIndex: number, columnId: string, value: unknown) => void | Promise<unknown>;\n /** The screen width below which the grid shows cards: the project's responsive.tableToCardsBreakpoint, else \"md\". */\n mobileBreakpoint?: BreakpointKey;\n /**\n * The grid's own width below which it shows cards when it doesn't fit, in px (Sprint 25.13 A35): about a phone's; 0\n * never switches by width. An editable grid never shows cards: it stays the APG's grid, scrolling sideways.\n */\n cardsBelow?: number;\n /**\n * The list's pager (Sprint 25.13 A3), from `usePagination(data)` over the same rows: pass it when the page also shows\n * the count (TableToolbar). Without it the grid pages itself the same way.\n */\n pager?: Pager<unknown>;\n /** The grid's name for assistive tech. */\n \"aria-label\"?: string;\n className?: string;\n}\n\n/** A cell of an editable grid: its row among those drawn (-1 for the header) and its column. */\ninterface CellAt { r: number; c: number }\nconst cellKey = (p: CellAt) => (p.r < 0 ? `h:${p.c}` : `${p.r}:${p.c}`);\n/** A cell by its row's id (null for the header), which a sort or a save that re-sorts never moves to another row. */\ninterface CellId { row: string | null; c: number }\n/** How long the saved tick shows, in ms (A5). */\nconst SAVED_TICK_MS = 1500;\n\nexport function DataGrid<T>({\n data,\n columns,\n pageSize,\n editable = false,\n onCellEdit,\n mobileBreakpoint: mobileBreakpointProp,\n cardsBelow = CARDS_BELOW,\n pager: pagerProp,\n \"aria-label\": ariaLabel,\n className,\n}: DataGridProps<T>) {\n // Sprint 25.14 A44: a grid draws its own frame, so a SplitView's list pane draws none around it\n useFramesItself();\n // Sprint 25.6 (B9): responsive.tableToCardsBreakpoint reaches the table through the shell; a prop wins; md outside any shell.\n const preferences = useShellPreferences();\n const mobileBreakpoint: BreakpointKey = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? \"md\";\n const narrowScreen = useBreakpoint(mobileBreakpoint);\n // A35: cards only on a narrow screen or where the grid's own width is a phone's. An editable grid stays the APG's grid\n // at every width, scrolling sideways: its cards have no editor (the review of 30 September: in a default Drawer, whose\n // body is 359 px, the grid went to cards and could no longer be edited).\n const { cards: isMobile, rootRef } = useCardsSwitch(editable ? false : narrowScreen, editable ? 0 : cardsBelow);\n const [sorting, setSorting] = useState<SortingState>([]);\n // the scroll area: a header or a cell the keyboard reaches is scrolled in whole, with its outline (Sprint 30, P3)\n const [scrollArea, setScrollArea] = useState<HTMLDivElement | null>(null);\n useRevealFocus(scrollArea);\n // the open editor (Sprint 25.8.7 item 19): its control, its value as the control holds it, and how a save gives it back\n const [editing, setEditing] = useState<(CellId & { editor: CellEditorKind; value: unknown; was: unknown; out: (value: unknown) => unknown }) | null>(null);\n\n /* ── Column kind inference ─────────────────────────────────────────── */\n const columnKeys = useMemo(() => columns.map((c) => c.id ?? (\"accessorKey\" in c ? String(c.accessorKey) : \"\")).filter(Boolean), [columns]);\n const inferredKinds = useMemo(\n () => inferColumnKinds(data as Record<string, unknown>[], columnKeys),\n [data, columnKeys],\n );\n const kindOf = useCallback(\n (colId: string, meta: DataGridColumnMeta | undefined) => meta?.kind ?? inferredKinds.get(colId),\n [inferredKinds],\n );\n\n // TanStack Table returns functions the React Compiler cannot memoise; the\n // compiler would skip this component, which is fine — the project does not\n // use it. The note is informational, not a defect.\n // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table is not compiler-compatible\n const table = useReactTable({\n data,\n columns,\n state: { sorting },\n onSortingChange: (updater) => { setSorting(updater); pagerProp?.setPage(1); },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n });\n\n // ── A5 / A3: the project's page size and list style, through the pager, over every row sorted ──\n const sortedRows = table.getRowModel().rows;\n const ownPager = usePagination(sortedRows, { pageSize, resetOn: sorting });\n const pager = pagerProp ?? ownPager;\n useWholeListCheck(\"DataGrid\", data.length, pagerProp);\n const rows = pagerPart(sortedRows, pager);\n const leafColumns = table.getVisibleLeafColumns();\n const headerText = (id: string) => {\n const header = leafColumns.find((c) => c.id === id)?.columnDef.header;\n return typeof header === \"string\" ? header : id;\n };\n // a column's kind chooses its editor: a choice needs its options, and options alone choose nothing (told in development)\n if (editable) {\n for (const column of leafColumns) {\n const meta = column.columnDef.meta as DataGridColumnMeta | undefined;\n if (meta?.kind === \"choice\" && !meta.options?.length) warnOnce(\"DataGrid\", `column \"${column.id}\" is a choice with no options, so it edits as text: give its meta the options its cells take.`);\n else if (meta?.options?.length && meta.kind !== \"choice\") warnOnce(\"DataGrid\", `column \"${column.id}\" has options but not the choice kind, so they go unused: give its meta kind \"choice\" to edit it with a Dropdown.`);\n }\n }\n\n // ── A5: the grid's keyboard (the APG's grid), when editable ──\n // The Tab stop, the editor and the saved tick are kept by the row's id, so a sort, or a save that re-sorts the rows,\n // keeps each on its row (the review of 30 September: the tick and the Tab stop went to the row now in the old place).\n const gridRef = useRef<HTMLTableElement>(null);\n const [activeId, setActiveId] = useState<CellId>({ row: null, c: 0 });\n const lastRow = rows.length - 1;\n const rowAt = (id: string | null) => (id === null ? -1 : rows.findIndex((row) => row.id === id));\n const idAt = (p: CellAt): CellId => ({ row: p.r < 0 ? null : rows[p.r]?.id ?? null, c: p.c });\n const current: CellAt = { r: Math.min(rowAt(activeId.row), lastRow), c: Math.min(activeId.c, Math.max(0, leafColumns.length - 1)) };\n const setActive = (p: CellAt) => setActiveId(idAt(p));\n const move = (p: CellAt, e: ReactKeyboardEvent): CellAt | null => {\n // Alt with an arrow is the browser's (Back, Forward), and Ctrl or ⌘ with one too; Ctrl or ⌘ with Home or End goes to\n // the grid's first or last cell (the APG's grid)\n if (e.altKey) return null;\n const toCorner = e.ctrlKey || e.metaKey;\n switch (e.key) {\n case \"ArrowRight\": return !toCorner && p.c < leafColumns.length - 1 ? { ...p, c: p.c + 1 } : null;\n case \"ArrowLeft\": return !toCorner && p.c > 0 ? { ...p, c: p.c - 1 } : null;\n case \"ArrowDown\": return !toCorner && p.r < lastRow ? { ...p, r: p.r + 1 } : null;\n case \"ArrowUp\": return !toCorner && p.r > -1 ? { ...p, r: p.r - 1 } : null;\n case \"Home\": return toCorner ? { r: -1, c: 0 } : { ...p, c: 0 };\n case \"End\": return toCorner ? { r: lastRow, c: leafColumns.length - 1 } : { ...p, c: leafColumns.length - 1 };\n default: return null;\n }\n };\n // an edit ends once: Enter saves and unmounts the editor, whose blur must not save it again\n const ended = useRef(false);\n const startEdit = (p: CellAt) => {\n const row = rows[p.r];\n const column = leafColumns[p.c];\n if (!row || !column || (column.columnDef.meta as DataGridColumnMeta | undefined)?.editable === false) return;\n // another cell's edit still open (its leave is told a moment after its blur) is left now, and saves\n if (editing && !(editing.row === row.id && editing.c === p.c)) finishEdit(true, false);\n ended.current = false;\n setActive(p);\n const meta = column.columnDef.meta as DataGridColumnMeta | undefined;\n // an empty date cell edits as the column's dates are held: the first of them, read only if it's needed\n const firstOfColumn = () => rows.map((x) => x.getValue(column.id)).find((v) => !isEmpty(v));\n const setup = editorFor(kindOf(column.id, meta), row.getValue(column.id), meta, firstOfColumn);\n setEditing({ row: row.id, c: p.c, editor: setup.editor, value: setup.value, was: setup.value, out: setup.out });\n };\n const grid = useGridKeyboard<CellAt>({\n container: gridRef,\n active: current,\n setActive,\n keyOf: cellKey,\n move,\n onActivate: (p, e) => {\n if (p.r < 0) { if (leafColumns[p.c]?.getCanSort()) leafColumns[p.c].toggleSorting(); }\n else if (e.key === \"Enter\") startEdit(p);\n },\n modifierKeys: true,\n });\n const onGridKeyDown = (e: ReactKeyboardEvent) => {\n // while a cell is edited its keys are its editor's, a button's arrows too: they never move to another cell (the\n // APG's grid, editing within a cell)\n if (e.target instanceof Element && e.target.closest(\"[data-cell-editor]\")) return;\n // F2 opens the cell's editor too (the APG's grid)\n if (e.key === \"F2\" && !editing && current.r >= 0 && e.target instanceof HTMLElement && e.target.getAttribute(\"data-grid-key\") === cellKey(current)) {\n e.preventDefault();\n startEdit(current);\n return;\n }\n grid.onKeyDown(e);\n };\n // the Tab stop follows focus, however it got there: a click, a screen reader's command, a double-click (the hook's\n // contract; the review of 30 September: a clicked cell took no Enter, and ArrowDown went from the header)\n const onGridFocus = (e: React.FocusEvent) => {\n const key = e.target instanceof HTMLElement ? e.target.getAttribute(\"data-grid-key\") : null;\n if (!key) return;\n const [r, c] = key.startsWith(\"h:\") ? [-1, Number(key.slice(2))] : key.split(\":\").map(Number);\n if (Number.isFinite(r) && Number.isFinite(c) && cellKey(current) !== key) setActive({ r, c });\n };\n\n // ── A5: the save, its tick and its announcement ──\n const [saved, setSaved] = useState<{ row: string; c: number; n: number; ok: boolean } | null>(null);\n useEffect(() => {\n if (!saved) return;\n const t = setTimeout(() => setSaved((s) => (s && s.n === saved.n ? null : s)), SAVED_TICK_MS);\n return () => clearTimeout(t);\n }, [saved]);\n const heard = useRef(0);\n // after Enter or Escape focus comes back to the cell, on its row wherever a save that re-sorts puts it: its page first\n const refocus = useRef<CellId | null>(null);\n useLayoutEffect(() => {\n const want = refocus.current;\n if (!want) return;\n const r = rowAt(want.row);\n if (r < 0) {\n const all = sortedRows.findIndex((row) => row.id === want.row);\n if (all >= 0 && pager.style === \"pagination\") { const page = Math.floor(all / pager.pageSize) + 1; if (page !== pager.page) { pager.setPage(page); return; } }\n refocus.current = null;\n return;\n }\n refocus.current = null;\n grid.focus({ r, c: want.c });\n });\n // `picked`: a value chosen by a press (an option, a day, the box), which is the edit itself and saves at once\n const finishEdit = (commit: boolean, focusBack: boolean, picked?: { value: unknown }) => {\n if (!editing || ended.current) return;\n ended.current = true;\n const r = rowAt(editing.row);\n const row = rows[r];\n const column = leafColumns[editing.c];\n const cell = { row: editing.row, c: editing.c };\n setEditing(null);\n // leaving the editor (a click elsewhere, Tab) saves and lets focus go where it went (the review of 30 September:\n // it pulled focus back, and the next keys were lost)\n if (focusBack) { setActiveId(cell); refocus.current = cell; }\n // a save that changes nothing isn't one\n const value = picked ? picked.value : editing.value;\n if (!commit || !row || !column || sameValue(value, editing.was)) return;\n const done = (ok: boolean) => { heard.current += 1; setSaved({ ...cell, row: editing.row!, n: heard.current, ok }); };\n const result = onCellEdit?.(row.index, column.id, editing.out(value));\n if (result && typeof (result as Promise<unknown>).then === \"function\") (result as Promise<unknown>).then(() => done(true), () => done(false));\n else done(true);\n };\n\n // A3: the grid and its control are one element, as in 0.21, which takes the className: in a grid or a flex row they\n // stay one item (the review of 30 September: the control became an item of its own beside the grid)\n const control = data.length > 0 ? <Pagination {...pager.props} /> : null;\n const setRoot = (node: HTMLDivElement | null) => { rootRef.current = node; };\n const withControl = (list: ReactNode) => <div ref={setRoot} data-gs-paged=\"\" className={cn(\"flex flex-col min-w-0\", className)}>{list}{control}</div>;\n\n if (isMobile) {\n return withControl(\n <div data-ds-list=\"\" className=\"space-y-ds-3\">\n <TableCardCtx value={true}><RowsCtx value={true}>\n <div className=\"flex flex-col gap-ds-3\">\n {rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]\",\n \"p-ds-4 space-y-ds-3\",\n )}\n >\n {row.getVisibleCells().map((cell) => (\n <div key={cell.id} className=\"flex justify-between gap-ds-2 text-sm\">\n <span className=\"shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider\">\n {typeof cell.column.columnDef.header === \"string\"\n ? cell.column.columnDef.header\n : cell.column.id}\n </span>\n <CardValue value={flexRender(cell.column.columnDef.cell, cell.getContext())} />\n </div>\n ))}\n </div>\n ))}\n </div>\n </RowsCtx></TableCardCtx>\n </div>\n );\n }\n\n const headerCell = (header: Header<T, unknown>, c: number) => {\n const canSort = header.column.getCanSort();\n const sorted = header.column.getIsSorted();\n const meta = header.column.columnDef.meta as DataGridColumnMeta | undefined;\n const headerKind = kindOf(header.column.id, meta);\n const headerAlign = meta?.align ?? (headerKind === \"number\" ? \"right\" : \"left\");\n const shrink = (headerKind === \"number\" || headerKind === \"date\") && !meta?.maxWidth;\n const at = { r: -1, c };\n const label = flexRender(header.column.columnDef.header, header.getContext());\n // A47: a sortable header holds a button: a Tab stop in a read-only grid, a cell the arrows reach in an editable one\n const inside = canSort ? (\n <button\n type=\"button\"\n onClick={header.column.getToggleSortingHandler()}\n {...(editable ? { \"data-grid-key\": cellKey(at), tabIndex: grid.tabIndexOf(at) } : {})}\n className={cn(\n \"inline-flex items-center gap-ds-1 uppercase tracking-wider cursor-pointer select-none [font:inherit] text-inherit\",\n \"hover:text-[var(--ds-text-primary)] rounded-[var(--ds-radius-sm)]\",\n // in a right-aligned column the indicator goes before the label, so the label ends where the column's values\n // end; the sorted column's label in full colour (the owner's choice at the look check, 14 October)\n headerAlign === \"right\" && \"flex-row-reverse\",\n sorted && \"text-[var(--ds-text-primary)]\",\n FOCUS_RING,\n )}\n >\n {label}\n <SortIndicator sorted={sorted} />\n </button>\n ) : label;\n return (\n <th\n key={header.id}\n role={editable ? \"columnheader\" : undefined}\n aria-sort={sorted === \"asc\" ? \"ascending\" : sorted === \"desc\" ? \"descending\" : undefined}\n {...(editable && !canSort ? { \"data-grid-key\": cellKey(at), tabIndex: grid.tabIndexOf(at) } : {})}\n className={cn(\n \"px-ds-4 py-ds-3 text-xs font-[var(--ds-weight-heading)] uppercase tracking-wider\",\n headerAlign === \"right\" ? \"text-right\" : headerAlign === \"center\" ? \"text-center\" : \"text-left\",\n shrink && \"w-px whitespace-nowrap\",\n \"text-[var(--ds-text-secondary)]\",\n FOCUS_INSET,\n // an editable column's cells keep room for their cue at their end (item 19): its header keeps the same\n editable && meta?.editable !== false && EDIT_CUE_ROOM,\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth } : undefined}\n >\n <span className={cn(\"flex items-center gap-ds-1\", headerAlign === \"right\" && \"justify-end\", headerAlign === \"center\" && \"justify-center\")}>\n {inside}\n </span>\n </th>\n );\n };\n\n return withControl(\n <div data-ds-list=\"\" className=\"min-w-0\">\n <div\n ref={setScrollArea}\n // the scroll area the width switch reads (A35), as the Table's\n data-table-scroll=\"\"\n className={cn(\n \"relative w-full overflow-auto scroll-p-[4px] rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"shadow-[var(--ds-shadow-card)]\",\n \"bg-[var(--ds-bg-surface)]\",\n )}\n >\n <table\n ref={gridRef}\n role={editable ? \"grid\" : undefined}\n aria-label={ariaLabel}\n onKeyDown={editable ? onGridKeyDown : undefined}\n onFocus={editable ? onGridFocus : undefined}\n className=\"w-full text-sm\"\n >\n <thead className=\"bg-[var(--ds-bg-muted)]\">\n {table.getHeaderGroups().map((hg) => (\n <tr key={hg.id} role={editable ? \"row\" : undefined} className=\"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {hg.headers.map((header, c) => headerCell(header, c))}\n </tr>\n ))}\n </thead>\n <tbody><RowsCtx value={true}>\n {rows.map((row, r) => (\n <tr\n key={row.id}\n role={editable ? \"row\" : undefined}\n className={cn(\n \"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0\",\n \"hover:bg-[var(--ds-bg-muted)] transition-colors\",\n )}\n >\n {row.getVisibleCells().map((cell, c) => {\n const meta = cell.column.columnDef.meta as DataGridColumnMeta | undefined;\n const truncLines = meta?.truncate === true ? 1 : meta?.truncate ? meta.truncate.lines : 0;\n const kind = kindOf(cell.column.id, meta);\n const rendered = flexRender(cell.column.columnDef.cell, cell.getContext() as CellContext<T, unknown>);\n const at = { r, c };\n const isEditing = editable && editing?.row === row.id && editing.c === c;\n\n const shrink = (kind === \"number\" || kind === \"date\") && !meta?.maxWidth;\n // Round 14 (50.2): a centred or right-aligned column lays a block element out with flex — text-align moves inline content only.\n const align = meta?.align ?? (kind === \"number\" ? \"right\" : \"left\");\n let inner: ReactNode;\n if (isEditing) {\n // the library's control for the column's kind, named for its column (CellEditor). The cell keeps its\n // size while it is edited: its value holds the room, unseen, and the editor sits over it, from the\n // cell's start (its end, in a right-aligned column), as wide as its control needs. So no column moves\n // and the row keeps its height (the look check's second round: a number's field had no room in its\n // narrow column, and a date's widened every column)\n inner = (\n <>\n <span aria-hidden=\"true\" className=\"invisible\">{rendered}</span>\n <div className={cn(\n \"absolute inset-y-0 z-30 flex items-center\", EDITOR_WIDTH[editing.editor],\n // from the cell's end in a right-aligned column, and in the last column, where an editor wider\n // than its cell would run past the grid's edge; over the cell before, it stays in view\n align === \"right\" || c === row.getVisibleCells().length - 1 ? \"right-ds-2\" : \"left-ds-2\",\n )}>\n <CellEditor\n editor={editing.editor}\n value={editing.value}\n name={headerText(cell.column.id)}\n options={meta?.options}\n onChange={(v) => setEditing({ ...editing, value: v })}\n onEnd={finishEdit}\n />\n </div>\n </>\n );\n } else if (truncLines > 0) {\n inner = <CutCell lines={truncLines}>{rendered}</CutCell>;\n } else if (kind === \"email\") {\n inner = <CutEmail>{rendered}</CutEmail>;\n } else {\n inner = rendered;\n }\n const value = cell.getValue();\n if (!isEditing && align !== \"left\" && typeof value !== \"string\" && typeof value !== \"number\" && value !== null && value !== undefined) {\n inner = <div className={cn(\"flex items-center\", align === \"center\" ? \"justify-center\" : \"justify-end\")}>{inner}</div>;\n }\n const tick = editable && saved?.ok && saved.row === row.id && saved.c === c\n ? <Icon name=\"check\" size={14} className=\"ml-ds-1 inline-block align-middle text-[var(--ds-status-success)]\" />\n : null;\n\n // item 19: an editable cell says so before it is tried; a calculated or locked one is read-only\n const edits = editable && meta?.editable !== false;\n const least = edits ? editableMinWidth(kind, meta) : undefined;\n return (\n <td\n key={cell.id}\n // a double-click in the open editor selects a word, and never reopens it over what was typed\n {...(editable ? { role: \"gridcell\", \"data-grid-key\": cellKey(at), tabIndex: grid.tabIndexOf(at), onDoubleClick: () => { if (!isEditing) startEdit(at); } } : {})}\n aria-readonly={editable && !edits ? true : undefined}\n className={cn(\n \"px-ds-4 py-ds-3 text-[var(--ds-text-primary)]\",\n align === \"right\" && \"text-right\",\n align === \"center\" && \"text-center\",\n shrink && \"w-px whitespace-nowrap\",\n editable && FOCUS_INSET,\n edits && cn(\"group/cell relative\", EDIT_CUE_ROOM),\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth || least ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth ?? least } : undefined}\n >\n {inner}\n {tick}\n {edits && !isEditing && EDIT_CUE}\n </td>\n );\n })}\n </tr>\n ))}\n </RowsCtx></tbody>\n </table>\n </div>\n {/* A5: a save is heard, politely (WCAG 4.1.3); each one is a new line, so two saves are heard twice */}\n {editable && <div role=\"status\" className=\"sr-only\"><span key={saved?.n ?? 0}>{saved ? (saved.ok ? \"Saved\" : \"Not saved\") : \"\"}</span></div>}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/components/DataGrid.tsx"],"names":[],"mappings":"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","file":"data-grid.js","sourcesContent":["import { useState, useCallback, useEffect, useLayoutEffect, useMemo, useRef, type ReactElement, type ReactNode, type SyntheticEvent, type KeyboardEvent as ReactKeyboardEvent } from \"react\";\nimport { useShellPreferences } from \"../lib/preferences\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n flexRender,\n type CellContext,\n type ColumnDef,\n type Header,\n type SortingState,\n} from \"@tanstack/react-table\";\nimport { cn, FOCUS_INSET, FOCUS_RING } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { CutCell, CutEmail } from \"./TextOverflow\";\nimport { Input } from \"./Input\";\nimport { NumberInput } from \"./NumberInput\";\nimport { DatePicker } from \"./DatePicker\";\nimport { Dropdown } from \"./Dropdown\";\nimport { Checkbox } from \"./Checkbox\";\nimport { Field } from \"./Field\";\nimport { Pagination } from \"./Pagination\";\nimport { useBreakpoint, type BreakpointKey } from \"../lib/use-breakpoint\";\nimport { useRevealFocus } from \"../lib/reveal-focus\";\nimport { inferColumnKinds, type ColumnKind } from \"../lib/table-utils\";\nimport { CardValue } from \"../lib/card-cell\";\nimport { TableCardCtx, RowsCtx, useFramesItself } from \"../lib/surface-context\";\nimport { FormChangeCtx } from \"../lib/form-context\";\nimport { focusInitial, useFocusLeave, useGridKeyboard } from \"../lib/focus\";\nimport { dayKey } from \"../lib/date-grid\";\nimport { SortIndicator } from \"../lib/sort-indicator\";\nimport { warnOnce } from \"../lib/dev-warn\";\nimport { usePagination, pagerPart, useWholeListCheck, type Pager } from \"../lib/use-pagination\";\nimport { CARDS_BELOW, useCardsSwitch } from \"../lib/use-cards-switch\";\n\n/** One of a choice column's options: the value its cells hold, and the words shown for it. */\nexport interface DataGridOption {\n value: string | number;\n label: string;\n}\n\n/** Column meta for opt-in truncation. Set on ColumnDef.meta. */\nexport interface DataGridColumnMeta {\n /** true = single-line, or { lines: N } for multi-line clamp. */\n truncate?: boolean | { lines: number };\n /** CSS max-width for the column. */\n maxWidth?: string;\n /** CSS width for the column — sibling grids that share a column set line up when their columns carry the same widths (round 14). */\n width?: string;\n /** CSS min-width for the column. */\n minWidth?: string;\n /**\n * Explicit column kind. When omitted the DataGrid infers it from data values (a yes or no too; never a choice). In an\n * editable grid it chooses the editor, where the control can hold the cell's value: \"number\" a NumberInput for a\n * number, \"date\" a DatePicker for a Date or an ISO date (\"2026-10-14\"), \"choice\" a Dropdown of `options`, \"boolean\" a\n * Checkbox; any other kind, and a number or a date written as text (\"18 KB\", \"12 Jan 2026\"), a text Input.\n */\n kind?: ColumnKind;\n /** Horizontal alignment of the header and the cells; a block element (a Checkbox, a Button) is laid out with flex so it follows too (round 14). Default: numbers right, everything else left. */\n align?: \"left\" | \"center\" | \"right\";\n /**\n * In an editable grid, whether this column's cells edit (default true); false for a column that shows (a status, a\n * calculated value, actions): its cells show no edit cue, and assistive tech hears them as read-only.\n */\n editable?: boolean;\n /**\n * A choice column's options (with `kind: \"choice\"`): its cells edit with a Dropdown of them, and a save gives the\n * option's `value`. Give the column a `cell` that shows the option's label.\n */\n options?: readonly DataGridOption[];\n /**\n * In an editable grid, the value onCellEdit gets from what was typed in a text cell, or in a number cell as its text\n * (default the text itself, or the number): a price written as text, `(text) => Number(text.replace(/[$,]/g, \"\"))`.\n * A date, a choice and a yes or no are given as their own values.\n */\n parse?: (text: string) => unknown;\n}\n\n/** The control a cell edits with (Sprint 25.8.7 item 19): its column's kind, where that control can hold the cell's value. */\ntype CellEditorKind = \"text\" | \"number\" | \"date\" | \"choice\" | \"boolean\";\n\n/** What an edit starts from: its control, the control's value, and how a saved value goes back in the cell's own form. */\ninterface EditorSetup {\n editor: CellEditorKind;\n value: unknown;\n out: (value: unknown) => unknown;\n}\n\nconst isEmpty = (v: unknown) => v === null || v === undefined || v === \"\";\nconst isDate = (v: unknown): v is Date => v instanceof Date && !Number.isNaN(v.getTime());\n/** An ISO date's text (\"2026-10-14\") as the local day it names, else null; the date grid's day key is the same text. */\nfunction isoDay(v: unknown): Date | null {\n const m = typeof v === \"string\" ? /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(v) : null;\n if (!m) return null;\n const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));\n return dayKey(d) === v ? d : null;\n}\n/** Two of an editor's values are one: a date by its time, anything else by itself. */\nconst sameValue = (a: unknown, b: unknown) => (isDate(a) && isDate(b) ? a.getTime() === b.getTime() : Object.is(a, b));\n\n/**\n * The editor for a cell. A control edits only a value it can hold: a NumberInput holds no empty cell and no \"18 KB\", a\n * DatePicker gives back no \"12 Jan 2026\", so those keep the text Input. A date goes back in the form it came: a Date,\n * keeping its time of day, or an ISO date's text; an empty cell's, as the column's first date is (a Date when it has\n * none).\n */\nfunction editorFor(kind: ColumnKind | undefined, raw: unknown, meta: DataGridColumnMeta | undefined, firstOfColumn: () => unknown): EditorSetup {\n const parse = meta?.parse;\n if (kind === \"choice\" && meta?.options?.length) return { editor: \"choice\", value: raw ?? null, out: (v) => v };\n if (kind === \"boolean\" && (typeof raw === \"boolean\" || isEmpty(raw))) return { editor: \"boolean\", value: raw === true, out: (v) => v };\n if (kind === \"number\" && typeof raw === \"number\" && Number.isFinite(raw)) return { editor: \"number\", value: raw, out: (v) => (parse ? parse(String(v)) : v) };\n if (kind === \"date\") {\n const was = isEmpty(raw) ? firstOfColumn() : raw;\n if (isDate(raw)) {\n return { editor: \"date\", value: raw, out: (v) => (isDate(v) ? new Date(v.getFullYear(), v.getMonth(), v.getDate(), raw.getHours(), raw.getMinutes(), raw.getSeconds(), raw.getMilliseconds()) : null) };\n }\n if (isoDay(was)) return { editor: \"date\", value: isoDay(raw), out: (v) => (isDate(v) ? dayKey(v) : null) };\n if (isEmpty(was) || isDate(was)) return { editor: \"date\", value: null, out: (v) => (isDate(v) ? v : null) };\n }\n return { editor: \"text\", value: String(raw ?? \"\"), out: (v) => (parse ? parse(v as string) : v) };\n}\n\n/**\n * A cell's editor (Sprint 25.8.7 item 19): the library's control for its column's kind, named for the column by a\n * hidden Field label. What is typed (text, a number, a date's parts) saves with Enter or by leaving the editor; a value\n * picked by a press (an option, a calendar's day, the box) is the edit, and saves at once; Escape, in the field or in\n * its popup, leaves the cell as it was. Leaving is the Field's own check (lib/focus.ts, useFocusLeave): focus moving\n * into the editor's popup, the Dropdown's list or the DatePicker's calendar, is not leaving it.\n */\nfunction CellEditor({ editor, value, name, options, onChange, onEnd }: {\n editor: CellEditorKind;\n value: unknown;\n name: string;\n options?: readonly DataGridOption[];\n onChange: (value: unknown) => void;\n onEnd: (save: boolean, focusBack: boolean, picked?: { value: unknown }) => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n // leaving the editor saves it and lets focus go where it went (the review of 30 September: it pulled focus back, and\n // the next keys were lost)\n const leave = useFocusLeave(() => onEnd(true, false));\n // a value chosen in a popup (the calendar's day, by a click or by Enter) is the edit itself. React passes the popup's\n // events up through its portal, so a key or a press from outside this editor's own box came from there. The flag is\n // where the latest one came from, never reset by a timer: Chrome runs a capture handler and the bubbling handler that\n // changes the value as separate listeners, with a microtask checkpoint between them\n const fromPopup = useRef(false);\n const markPopupEvent = (e: SyntheticEvent) => { fromPopup.current = !ref.current?.contains(e.target as Node); };\n const opened = useRef(false);\n useLayoutEffect(() => {\n const root = ref.current;\n if (!root) return;\n focusInitial(root);\n const el = document.activeElement;\n // the value opens selected: typing replaces it, an arrow key keeps it\n if (el instanceof HTMLInputElement && el.type === \"text\") el.select();\n // a choice opens on its list, the edit itself; once, though a development build runs this twice\n if (editor === \"choice\" && !opened.current && el instanceof HTMLButtonElement && root.contains(el)) {\n opened.current = true;\n el.click();\n }\n }, [editor]);\n // a choice and the box change only when picked, and a pick saves at once; what is typed or stepped (text, a number, a\n // date's parts) waits for Enter or for leaving the editor\n const picks = editor === \"choice\" || editor === \"boolean\";\n const change = (v: unknown) => (picks || fromPopup.current ? onEnd(true, true, { value: v }) : onChange(v));\n let control: ReactElement;\n if (editor === \"number\") control = <NumberInput size=\"sm\" value={value as number} allowDecimals onChange={change} />;\n else if (editor === \"date\") control = <DatePicker size=\"sm\" value={value as Date | null} onChange={change} />;\n else if (editor === \"boolean\") control = <Checkbox checked={value === true} onChange={(checked) => change(checked)} />;\n else if (editor === \"choice\" && options) {\n control = (\n <Dropdown\n size=\"sm\"\n options={options.map((o) => ({ id: String(o.value), label: o.label }))}\n value={value === null || value === undefined ? \"\" : String(value)}\n onChange={(id) => change(options.find((o) => String(o.value) === id)?.value ?? id)}\n />\n );\n } else control = <Input size=\"sm\" value={value as string} onChange={(e) => change(e.target.value)} />;\n return (\n <div\n ref={ref}\n data-cell-editor=\"\"\n {...leave}\n onClickCapture={markPopupEvent}\n onKeyDownCapture={markPopupEvent}\n onKeyDown={(e) => {\n // Escape, in the field or its popup, leaves the cell as it was, and goes no further: a Drawer round the grid stays\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n onEnd(false, true);\n return;\n }\n // Enter saves what was typed; on a button (the Dropdown's, the calendar's) it is the button's, which opens its\n // popup, and in the popup it picks\n if (e.key === \"Enter\" && e.currentTarget.contains(e.target as Node) && !(e.target instanceof HTMLButtonElement)) {\n e.preventDefault();\n onEnd(true, true);\n }\n }}\n >\n {/* a grid saves as you go, so its editor never marks a form around it; the cells' own controls still do (the\n review of 30 September: the whole grid opted out, and a Drawer closed on a changed checkbox unasked) */}\n <FormChangeCtx value={null}>\n <Field label={name} hideLabel>{control}</Field>\n </FormChangeCtx>\n </div>\n );\n}\n\n/**\n * Sprint 25.8.7 item 19 (collections-5): an editable cell says so before it is tried, a pencil shown while the cell is\n * hovered or focused (focused too: a touch screen has no hover); a calculated or locked cell shows none. It sits in room\n * an editable column keeps at its cells' end, header too, so a value never moves and a number stays under its header.\n */\nconst EDIT_CUE_ROOM = \"pr-[calc(var(--ds-space-4)+var(--ds-space-1)+12px)]\";\n\n/** How wide an editor sits over its cell: the cell's width inside its padding, and never less than its control needs. */\nconst EDITOR_WIDTH: Record<CellEditorKind, string> = {\n text: \"w-[max(calc(100%-var(--ds-space-4)),12rem)]\",\n number: \"w-[max(calc(100%-var(--ds-space-4)),8rem)]\",\n date: \"w-[max(calc(100%-var(--ds-space-4)),10.5rem)]\",\n choice: \"w-[max(calc(100%-var(--ds-space-4)),9rem)]\",\n boolean: \"w-auto\",\n};\n/**\n * The least an editable column of numbers, dates or choices is wide, at rest too: its editor's room and the cell's\n * padding, so the editor fits in its own cell and never covers the next one (a text column is wide by its words, and\n * a text editor may run over). A page's own width or min-width for the column wins.\n */\nconst EDITABLE_MIN_WIDTH: Partial<Record<CellEditorKind, string>> = { number: \"9rem\", date: \"11.5rem\", choice: \"10rem\" };\nfunction editableMinWidth(kind: ColumnKind | undefined, meta: DataGridColumnMeta | undefined): string | undefined {\n if (meta?.width || meta?.minWidth) return undefined;\n const editor: CellEditorKind | null = kind === \"number\" ? \"number\" : kind === \"date\" ? \"date\" : kind === \"choice\" && meta?.options?.length ? \"choice\" : null;\n return editor ? EDITABLE_MIN_WIDTH[editor] : undefined;\n}\nconst EDIT_CUE = (\n <span\n data-edit-cue=\"\"\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none absolute top-1/2 -translate-y-1/2 right-ds-4 flex\",\n \"text-[var(--ds-text-muted)] opacity-0 transition-opacity duration-[var(--ds-transition-speed)]\",\n \"group-hover/cell:opacity-100 group-focus/cell:opacity-100\",\n )}\n >\n <Icon name=\"edit\" size={12} />\n </span>\n);\n\n\nexport interface DataGridProps<T> {\n data: T[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- public API: columns may carry any value type\n columns: ColumnDef<T, any>[];\n /**\n * Rows a page, over the project's (dataDisplay.itemsPerPage), for a grid the user asked to page differently. Leave it\n * out: the grid pages as the project says, with the project's control (Sprint 25.13 A5; it was 10).\n */\n pageSize?: number;\n /**\n * Cells edit in place, as the APG's grid (Sprint 25.13 A5): the grid is one Tab stop and the arrow keys move between\n * cells; Enter or F2 (or a double-click) opens a cell's editor, Enter or leaving it saves and Escape cancels, and a\n * brief tick, announced as \"Saved\", shows the save. A grid saves as you go, so it never marks a form around it.\n */\n editable?: boolean;\n /**\n * A saved edit: the row's index in `data`, the column's id and the new value (the text typed, or the column's\n * `meta.parse` of it). Called only when the value changed. Return a promise to have the tick and \"Saved\" wait for it:\n * a rejection is announced as \"Not saved\", and the page says why and keeps the old value.\n */\n onCellEdit?: (rowIndex: number, columnId: string, value: unknown) => void | Promise<unknown>;\n /** The screen width below which the grid shows cards: the project's responsive.tableToCardsBreakpoint, else \"md\". */\n mobileBreakpoint?: BreakpointKey;\n /**\n * The grid's own width below which it shows cards when it doesn't fit, in px (Sprint 25.13 A35): about a phone's; 0\n * never switches by width. An editable grid never shows cards: it stays the APG's grid, scrolling sideways.\n */\n cardsBelow?: number;\n /**\n * The list's pager (Sprint 25.13 A3), from `usePagination(data)` over the same rows: pass it when the page also shows\n * the count (TableToolbar). Without it the grid pages itself the same way.\n */\n pager?: Pager<unknown>;\n /** The grid's name for assistive tech. */\n \"aria-label\"?: string;\n className?: string;\n}\n\n/** A cell of an editable grid: its row among those drawn (-1 for the header) and its column. */\ninterface CellAt { r: number; c: number }\nconst cellKey = (p: CellAt) => (p.r < 0 ? `h:${p.c}` : `${p.r}:${p.c}`);\n/** A cell by its row's id (null for the header), which a sort or a save that re-sorts never moves to another row. */\ninterface CellId { row: string | null; c: number }\n/** How long the saved tick shows, in ms (A5). */\nconst SAVED_TICK_MS = 1500;\n\nexport function DataGrid<T>({\n data,\n columns,\n pageSize,\n editable = false,\n onCellEdit,\n mobileBreakpoint: mobileBreakpointProp,\n cardsBelow = CARDS_BELOW,\n pager: pagerProp,\n \"aria-label\": ariaLabel,\n className,\n}: DataGridProps<T>) {\n // Sprint 25.14 A44: a grid draws its own frame, so a SplitView's list pane draws none around it\n useFramesItself();\n // Sprint 25.6 (B9): responsive.tableToCardsBreakpoint reaches the table through the shell; a prop wins; md outside any shell.\n const preferences = useShellPreferences();\n const mobileBreakpoint: BreakpointKey = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? \"md\";\n const narrowScreen = useBreakpoint(mobileBreakpoint);\n // A35: cards only on a narrow screen or where the grid's own width is a phone's. An editable grid stays the APG's grid\n // at every width, scrolling sideways: its cards have no editor (the review of 30 September: in a default Drawer, whose\n // body is 359 px, the grid went to cards and could no longer be edited).\n const { cards: isMobile, rootRef } = useCardsSwitch(editable ? false : narrowScreen, editable ? 0 : cardsBelow);\n const [sorting, setSorting] = useState<SortingState>([]);\n // the scroll area: a header or a cell the keyboard reaches is scrolled in whole, with its outline (Sprint 30, P3)\n const [scrollArea, setScrollArea] = useState<HTMLDivElement | null>(null);\n useRevealFocus(scrollArea);\n // the open editor (Sprint 25.8.7 item 19): its control, its value as the control holds it, and how a save gives it back\n const [editing, setEditing] = useState<(CellId & { editor: CellEditorKind; value: unknown; was: unknown; out: (value: unknown) => unknown }) | null>(null);\n\n /* ── Column kind inference ─────────────────────────────────────────── */\n const columnKeys = useMemo(() => columns.map((c) => c.id ?? (\"accessorKey\" in c ? String(c.accessorKey) : \"\")).filter(Boolean), [columns]);\n const inferredKinds = useMemo(\n () => inferColumnKinds(data as Record<string, unknown>[], columnKeys),\n [data, columnKeys],\n );\n const kindOf = useCallback(\n (colId: string, meta: DataGridColumnMeta | undefined) => meta?.kind ?? inferredKinds.get(colId),\n [inferredKinds],\n );\n\n // TanStack Table returns functions the React Compiler cannot memoise; the\n // compiler would skip this component, which is fine — the project does not\n // use it. The note is informational, not a defect.\n // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table is not compiler-compatible\n const table = useReactTable({\n data,\n columns,\n state: { sorting },\n onSortingChange: (updater) => { setSorting(updater); pagerProp?.setPage(1); },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n });\n\n // ── A5 / A3: the project's page size and list style, through the pager, over every row sorted ──\n const sortedRows = table.getRowModel().rows;\n const ownPager = usePagination(sortedRows, { pageSize, resetOn: sorting });\n const pager = pagerProp ?? ownPager;\n useWholeListCheck(\"DataGrid\", data.length, pagerProp);\n const rows = pagerPart(sortedRows, pager);\n const leafColumns = table.getVisibleLeafColumns();\n const headerText = (id: string) => {\n const header = leafColumns.find((c) => c.id === id)?.columnDef.header;\n return typeof header === \"string\" ? header : id;\n };\n // a column's kind chooses its editor: a choice needs its options, and options alone choose nothing (told in development)\n if (editable) {\n for (const column of leafColumns) {\n const meta = column.columnDef.meta as DataGridColumnMeta | undefined;\n if (meta?.kind === \"choice\" && !meta.options?.length) warnOnce(\"DataGrid\", `column \"${column.id}\" is a choice with no options, so it edits as text: give its meta the options its cells take.`);\n else if (meta?.options?.length && meta.kind !== \"choice\") warnOnce(\"DataGrid\", `column \"${column.id}\" has options but not the choice kind, so they go unused: give its meta kind \"choice\" to edit it with a Dropdown.`);\n }\n }\n\n // ── A5: the grid's keyboard (the APG's grid), when editable ──\n // The Tab stop, the editor and the saved tick are kept by the row's id, so a sort, or a save that re-sorts the rows,\n // keeps each on its row (the review of 30 September: the tick and the Tab stop went to the row now in the old place).\n const gridRef = useRef<HTMLTableElement>(null);\n const [activeId, setActiveId] = useState<CellId>({ row: null, c: 0 });\n const lastRow = rows.length - 1;\n const rowAt = (id: string | null) => (id === null ? -1 : rows.findIndex((row) => row.id === id));\n const idAt = (p: CellAt): CellId => ({ row: p.r < 0 ? null : rows[p.r]?.id ?? null, c: p.c });\n const current: CellAt = { r: Math.min(rowAt(activeId.row), lastRow), c: Math.min(activeId.c, Math.max(0, leafColumns.length - 1)) };\n const setActive = (p: CellAt) => setActiveId(idAt(p));\n const move = (p: CellAt, e: ReactKeyboardEvent): CellAt | null => {\n // Alt with an arrow is the browser's (Back, Forward), and Ctrl or ⌘ with one too; Ctrl or ⌘ with Home or End goes to\n // the grid's first or last cell (the APG's grid)\n if (e.altKey) return null;\n const toCorner = e.ctrlKey || e.metaKey;\n switch (e.key) {\n case \"ArrowRight\": return !toCorner && p.c < leafColumns.length - 1 ? { ...p, c: p.c + 1 } : null;\n case \"ArrowLeft\": return !toCorner && p.c > 0 ? { ...p, c: p.c - 1 } : null;\n case \"ArrowDown\": return !toCorner && p.r < lastRow ? { ...p, r: p.r + 1 } : null;\n case \"ArrowUp\": return !toCorner && p.r > -1 ? { ...p, r: p.r - 1 } : null;\n case \"Home\": return toCorner ? { r: -1, c: 0 } : { ...p, c: 0 };\n case \"End\": return toCorner ? { r: lastRow, c: leafColumns.length - 1 } : { ...p, c: leafColumns.length - 1 };\n default: return null;\n }\n };\n // an edit ends once: Enter saves and unmounts the editor, whose blur must not save it again\n const ended = useRef(false);\n const startEdit = (p: CellAt) => {\n const row = rows[p.r];\n const column = leafColumns[p.c];\n if (!row || !column || (column.columnDef.meta as DataGridColumnMeta | undefined)?.editable === false) return;\n // another cell's edit still open (its leave is told a moment after its blur) is left now, and saves\n if (editing && !(editing.row === row.id && editing.c === p.c)) finishEdit(true, false);\n ended.current = false;\n setActive(p);\n const meta = column.columnDef.meta as DataGridColumnMeta | undefined;\n // an empty date cell edits as the column's dates are held: the first of them, read only if it's needed\n const firstOfColumn = () => rows.map((x) => x.getValue(column.id)).find((v) => !isEmpty(v));\n const setup = editorFor(kindOf(column.id, meta), row.getValue(column.id), meta, firstOfColumn);\n setEditing({ row: row.id, c: p.c, editor: setup.editor, value: setup.value, was: setup.value, out: setup.out });\n };\n const grid = useGridKeyboard<CellAt>({\n container: gridRef,\n active: current,\n setActive,\n keyOf: cellKey,\n move,\n onActivate: (p, e) => {\n if (p.r < 0) { if (leafColumns[p.c]?.getCanSort()) leafColumns[p.c].toggleSorting(); }\n else if (e.key === \"Enter\") startEdit(p);\n },\n modifierKeys: true,\n });\n const onGridKeyDown = (e: ReactKeyboardEvent) => {\n // while a cell is edited its keys are its editor's, a button's arrows too: they never move to another cell (the\n // APG's grid, editing within a cell)\n if (e.target instanceof Element && e.target.closest(\"[data-cell-editor]\")) return;\n // F2 opens the cell's editor too (the APG's grid)\n if (e.key === \"F2\" && !editing && current.r >= 0 && e.target instanceof HTMLElement && e.target.getAttribute(\"data-grid-key\") === cellKey(current)) {\n e.preventDefault();\n startEdit(current);\n return;\n }\n grid.onKeyDown(e);\n };\n // the Tab stop follows focus, however it got there: a click, a screen reader's command, a double-click (the hook's\n // contract; the review of 30 September: a clicked cell took no Enter, and ArrowDown went from the header)\n const onGridFocus = (e: React.FocusEvent) => {\n const key = e.target instanceof HTMLElement ? e.target.getAttribute(\"data-grid-key\") : null;\n if (!key) return;\n const [r, c] = key.startsWith(\"h:\") ? [-1, Number(key.slice(2))] : key.split(\":\").map(Number);\n if (Number.isFinite(r) && Number.isFinite(c) && cellKey(current) !== key) setActive({ r, c });\n };\n\n // ── A5: the save, its tick and its announcement ──\n const [saved, setSaved] = useState<{ row: string; c: number; n: number; ok: boolean } | null>(null);\n useEffect(() => {\n if (!saved) return;\n const t = setTimeout(() => setSaved((s) => (s && s.n === saved.n ? null : s)), SAVED_TICK_MS);\n return () => clearTimeout(t);\n }, [saved]);\n const heard = useRef(0);\n // after Enter or Escape focus comes back to the cell, on its row wherever a save that re-sorts puts it: its page first\n const refocus = useRef<CellId | null>(null);\n useLayoutEffect(() => {\n const want = refocus.current;\n if (!want) return;\n const r = rowAt(want.row);\n if (r < 0) {\n const all = sortedRows.findIndex((row) => row.id === want.row);\n if (all >= 0 && pager.style === \"pagination\") { const page = Math.floor(all / pager.pageSize) + 1; if (page !== pager.page) { pager.setPage(page); return; } }\n refocus.current = null;\n return;\n }\n refocus.current = null;\n grid.focus({ r, c: want.c });\n });\n // `picked`: a value chosen by a press (an option, a day, the box), which is the edit itself and saves at once\n const finishEdit = (commit: boolean, focusBack: boolean, picked?: { value: unknown }) => {\n if (!editing || ended.current) return;\n ended.current = true;\n const r = rowAt(editing.row);\n const row = rows[r];\n const column = leafColumns[editing.c];\n const cell = { row: editing.row, c: editing.c };\n setEditing(null);\n // leaving the editor (a click elsewhere, Tab) saves and lets focus go where it went (the review of 30 September:\n // it pulled focus back, and the next keys were lost)\n if (focusBack) { setActiveId(cell); refocus.current = cell; }\n // a save that changes nothing isn't one\n const value = picked ? picked.value : editing.value;\n if (!commit || !row || !column || sameValue(value, editing.was)) return;\n const done = (ok: boolean) => { heard.current += 1; setSaved({ ...cell, row: editing.row!, n: heard.current, ok }); };\n const result = onCellEdit?.(row.index, column.id, editing.out(value));\n if (result && typeof (result as Promise<unknown>).then === \"function\") (result as Promise<unknown>).then(() => done(true), () => done(false));\n else done(true);\n };\n\n // A3: the grid and its control are one element, as in 0.21, which takes the className: in a grid or a flex row they\n // stay one item (the review of 30 September: the control became an item of its own beside the grid)\n const control = data.length > 0 ? <Pagination {...pager.props} /> : null;\n const setRoot = (node: HTMLDivElement | null) => { rootRef.current = node; };\n const withControl = (list: ReactNode) => <div ref={setRoot} data-gs-paged=\"\" className={cn(\"flex flex-col min-w-0\", className)}>{list}{control}</div>;\n\n if (isMobile) {\n return withControl(\n <div data-ds-list=\"\" className=\"space-y-ds-3\">\n <TableCardCtx value={true}><RowsCtx value={true}>\n <div className=\"flex flex-col gap-ds-3\">\n {rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]\",\n \"p-ds-4 space-y-ds-3\",\n )}\n >\n {row.getVisibleCells().map((cell) => (\n <div key={cell.id} className=\"flex justify-between gap-ds-2 text-sm\">\n <span className=\"shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider\">\n {typeof cell.column.columnDef.header === \"string\"\n ? cell.column.columnDef.header\n : cell.column.id}\n </span>\n <CardValue value={flexRender(cell.column.columnDef.cell, cell.getContext())} />\n </div>\n ))}\n </div>\n ))}\n </div>\n </RowsCtx></TableCardCtx>\n </div>\n );\n }\n\n const headerCell = (header: Header<T, unknown>, c: number) => {\n const canSort = header.column.getCanSort();\n const sorted = header.column.getIsSorted();\n const meta = header.column.columnDef.meta as DataGridColumnMeta | undefined;\n const headerKind = kindOf(header.column.id, meta);\n const headerAlign = meta?.align ?? (headerKind === \"number\" ? \"right\" : \"left\");\n const shrink = (headerKind === \"number\" || headerKind === \"date\") && !meta?.maxWidth;\n const at = { r: -1, c };\n const label = flexRender(header.column.columnDef.header, header.getContext());\n // A47: a sortable header holds a button: a Tab stop in a read-only grid, a cell the arrows reach in an editable one\n const inside = canSort ? (\n <button\n type=\"button\"\n onClick={header.column.getToggleSortingHandler()}\n {...(editable ? { \"data-grid-key\": cellKey(at), tabIndex: grid.tabIndexOf(at) } : {})}\n className={cn(\n \"inline-flex items-center gap-ds-1 uppercase tracking-wider cursor-pointer select-none [font:inherit] text-inherit\",\n \"hover:text-[var(--ds-text-primary)] rounded-[var(--ds-radius-sm)]\",\n // in a right-aligned column the indicator goes before the label, so the label ends where the column's values\n // end; the sorted column's label in full colour (the owner's choice at the look check, 14 October)\n headerAlign === \"right\" && \"flex-row-reverse\",\n sorted && \"text-[var(--ds-text-primary)]\",\n FOCUS_RING,\n )}\n >\n {label}\n <SortIndicator sorted={sorted} />\n </button>\n ) : label;\n return (\n <th\n key={header.id}\n role={editable ? \"columnheader\" : undefined}\n aria-sort={sorted === \"asc\" ? \"ascending\" : sorted === \"desc\" ? \"descending\" : undefined}\n {...(editable && !canSort ? { \"data-grid-key\": cellKey(at), tabIndex: grid.tabIndexOf(at) } : {})}\n className={cn(\n \"px-ds-4 py-ds-3 text-xs font-[var(--ds-weight-heading)] uppercase tracking-wider\",\n headerAlign === \"right\" ? \"text-right\" : headerAlign === \"center\" ? \"text-center\" : \"text-left\",\n shrink && \"w-px whitespace-nowrap\",\n \"text-[var(--ds-text-secondary)]\",\n FOCUS_INSET,\n // an editable column's cells keep room for their cue at their end (item 19): its header keeps the same\n editable && meta?.editable !== false && EDIT_CUE_ROOM,\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth } : undefined}\n >\n <span className={cn(\"flex items-center gap-ds-1\", headerAlign === \"right\" && \"justify-end\", headerAlign === \"center\" && \"justify-center\")}>\n {inside}\n </span>\n </th>\n );\n };\n\n return withControl(\n <div data-ds-list=\"\" className=\"min-w-0\">\n <div\n ref={setScrollArea}\n // the scroll area the width switch reads (A35), as the Table's\n data-table-scroll=\"\"\n className={cn(\n \"relative w-full overflow-auto scroll-p-[4px] rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"shadow-[var(--ds-shadow-card)]\",\n \"bg-[var(--ds-bg-surface)]\",\n )}\n >\n <table\n ref={gridRef}\n role={editable ? \"grid\" : undefined}\n aria-label={ariaLabel}\n onKeyDown={editable ? onGridKeyDown : undefined}\n onFocus={editable ? onGridFocus : undefined}\n className=\"w-full text-sm\"\n >\n <thead className=\"bg-[var(--ds-bg-muted)]\">\n {table.getHeaderGroups().map((hg) => (\n <tr key={hg.id} role={editable ? \"row\" : undefined} className=\"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {hg.headers.map((header, c) => headerCell(header, c))}\n </tr>\n ))}\n </thead>\n <tbody><RowsCtx value={true}>\n {rows.map((row, r) => (\n <tr\n key={row.id}\n role={editable ? \"row\" : undefined}\n className={cn(\n \"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0\",\n \"hover:bg-[var(--ds-bg-muted)] transition-colors\",\n )}\n >\n {row.getVisibleCells().map((cell, c) => {\n const meta = cell.column.columnDef.meta as DataGridColumnMeta | undefined;\n const truncLines = meta?.truncate === true ? 1 : meta?.truncate ? meta.truncate.lines : 0;\n const kind = kindOf(cell.column.id, meta);\n const rendered = flexRender(cell.column.columnDef.cell, cell.getContext() as CellContext<T, unknown>);\n const at = { r, c };\n const isEditing = editable && editing?.row === row.id && editing.c === c;\n\n const shrink = (kind === \"number\" || kind === \"date\") && !meta?.maxWidth;\n // Round 14 (50.2): a centred or right-aligned column lays a block element out with flex — text-align moves inline content only.\n const align = meta?.align ?? (kind === \"number\" ? \"right\" : \"left\");\n let inner: ReactNode;\n if (isEditing) {\n // the library's control for the column's kind, named for its column (CellEditor). The cell keeps its\n // size while it is edited: its value holds the room, unseen, and the editor sits over it, from the\n // cell's start (its end, in a right-aligned column), as wide as its control needs. So no column moves\n // and the row keeps its height (the look check's second round: a number's field had no room in its\n // narrow column, and a date's widened every column)\n inner = (\n <>\n <span aria-hidden=\"true\" className=\"invisible\">{rendered}</span>\n <div className={cn(\n \"absolute inset-y-0 z-30 flex items-center\", EDITOR_WIDTH[editing.editor],\n // from the cell's end in a right-aligned column, and in the last column, where an editor wider\n // than its cell would run past the grid's edge; over the cell before, it stays in view\n align === \"right\" || c === row.getVisibleCells().length - 1 ? \"right-ds-2\" : \"left-ds-2\",\n )}>\n <CellEditor\n editor={editing.editor}\n value={editing.value}\n name={headerText(cell.column.id)}\n options={meta?.options}\n onChange={(v) => setEditing({ ...editing, value: v })}\n onEnd={finishEdit}\n />\n </div>\n </>\n );\n } else if (truncLines > 0) {\n inner = <CutCell lines={truncLines}>{rendered}</CutCell>;\n } else if (kind === \"email\") {\n inner = <CutEmail>{rendered}</CutEmail>;\n } else {\n inner = rendered;\n }\n const value = cell.getValue();\n if (!isEditing && align !== \"left\" && typeof value !== \"string\" && typeof value !== \"number\" && value !== null && value !== undefined) {\n inner = <div className={cn(\"flex items-center\", align === \"center\" ? \"justify-center\" : \"justify-end\")}>{inner}</div>;\n }\n const tick = editable && saved?.ok && saved.row === row.id && saved.c === c\n ? <Icon name=\"check\" size={14} className=\"ml-ds-1 inline-block align-middle text-[var(--ds-status-success)]\" />\n : null;\n\n // item 19: an editable cell says so before it is tried; a calculated or locked one is read-only\n const edits = editable && meta?.editable !== false;\n const least = edits ? editableMinWidth(kind, meta) : undefined;\n return (\n <td\n key={cell.id}\n // a double-click in the open editor selects a word, and never reopens it over what was typed\n {...(editable ? { role: \"gridcell\", \"data-grid-key\": cellKey(at), tabIndex: grid.tabIndexOf(at), onDoubleClick: () => { if (!isEditing) startEdit(at); } } : {})}\n aria-readonly={editable && !edits ? true : undefined}\n className={cn(\n \"px-ds-4 py-ds-3 text-[var(--ds-text-primary)]\",\n align === \"right\" && \"text-right\",\n align === \"center\" && \"text-center\",\n shrink && \"w-px whitespace-nowrap\",\n editable && FOCUS_INSET,\n edits && cn(\"group/cell relative\", EDIT_CUE_ROOM),\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth || least ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth ?? least } : undefined}\n >\n {inner}\n {tick}\n {edits && !isEditing && EDIT_CUE}\n </td>\n );\n })}\n </tr>\n ))}\n </RowsCtx></tbody>\n </table>\n </div>\n {/* A5: a save is heard, politely (WCAG 4.1.3); each one is a new line, so two saves are heard twice */}\n {editable && <div role=\"status\" className=\"sr-only\"><span key={saved?.n ?? 0}>{saved ? (saved.ok ? \"Saved\" : \"Not saved\") : \"\"}</span></div>}\n </div>\n );\n}\n"]}
@@ -1,7 +1,6 @@
1
1
  "use client";
2
- import { matchMentions, shownMentions, mentionOptionId, MentionList } from './chunk-ZASGFL5D.js';
3
- import { useLatest, useOverlayLayer } from './chunk-4HJDOZ2M.js';
4
- import './chunk-YL5KD5RC.js';
2
+ import { matchMentions, shownMentions, mentionOptionId, MentionList } from './chunk-K3NAFQ4S.js';
3
+ import { useLatest, useOverlayLayer } from './chunk-EZ3ZGFGA.js';
5
4
  import { useState, useSyncExternalStore, useId, useRef, useEffect } from 'react';
6
5
  import Mention from '@tiptap/extension-mention';
7
6
  import { exitSuggestion } from '@tiptap/suggestion';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/use-mentions.tsx"],"names":[],"mappings":"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","file":"editor-mentions.js","sourcesContent":["import { useEffect, useId, useRef, useState, useSyncExternalStore, type RefObject } from \"react\";\nimport type { Editor } from \"@tiptap/react\";\nimport Mention from \"@tiptap/extension-mention\";\nimport { exitSuggestion, type SuggestionProps } from \"@tiptap/suggestion\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { useOverlayLayer } from \"./focus\";\nimport { useLatest } from \"./use-latest\";\nimport { MentionList, matchMentions, mentionOptionId, shownMentions, type MentionSuggestion } from \"../components/MentionList\";\nimport type { RichTextEditorMentions } from \"../components/RichTextEditor\";\n\nexport type UseMentionsOptions =\n /** The people to mention: each offered when its name or description matches what follows \"@\". */\n | { people: MentionSuggestion[]; search?: undefined }\n /** For a large team: the people matching what follows \"@\", looked up as it's typed. An answer to an older query is dropped. */\n | { search: (query: string) => MentionSuggestion[] | Promise<MentionSuggestion[]>; people?: undefined };\n\ninterface ListState {\n /** A mention is being typed. */\n open: boolean;\n /** Focus left the editor while one was being typed: the list waits for the next keystroke in it. */\n hidden: boolean;\n /** The people shown: the best matches, at most a list's limit. */\n items: MentionSuggestion[];\n /** How many more match than are shown. */\n more: number;\n activeIndex: number;\n /** The editor the mention is typed in: one result passed to two editors draws its list in that one alone. */\n owner: Editor | null;\n}\n\nconst CLOSED: ListState = { open: false, hidden: false, items: [], more: 0, activeIndex: 0, owner: null };\n\nfunction createStore(initial: ListState) {\n let state = initial;\n const listeners = new Set<() => void>();\n return {\n get: () => state,\n set(patch: Partial<ListState>) {\n state = { ...state, ...patch };\n for (const listener of listeners) listener();\n },\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n };\n}\n\nfunction createMentions(options: RefObject<UseMentionsOptions>): RichTextEditorMentions {\n const store = createStore(CLOSED);\n const pluginKey = new PluginKey(\"gridsmith-mentions\");\n let pick: ((item: MentionSuggestion) => void) | null = null;\n let anchor: (() => DOMRect | null) | null = null;\n /** The newest query looked up, and its answer once it has come: an answer to an older query is never shown. */\n let asked: string | null = null;\n let answer: MentionSuggestion[] | null = null;\n const shown = () => { const s = store.get(); return s.open && !s.hidden && s.items.length > 0; };\n\n // Before each lookup answers (Sprint 25.17's review: a slow search): the range and the caret are the mention as typed\n // now, so Enter replaces all of it, and the people shown stay until the new answer comes, with no blink between keys\n const typed = (props: SuggestionProps<MentionSuggestion>) => {\n pick = (item) => props.command({ id: item.id, label: item.label });\n anchor = props.clientRect ?? null;\n store.set({ open: true, hidden: false, owner: props.editor as Editor });\n };\n // A lookup answered. tiptap hands every callback the newest props, whose items may still be an older lookup's or\n // none: the list shows the newest query's own answer, when it has come.\n const answered = (props: SuggestionProps<MentionSuggestion>) => {\n if (props.query !== asked || answer === null) return;\n typed(props);\n store.set({ ...shownMentions(answer), activeIndex: 0 });\n };\n\n // Escape closes the list; with no list shown (no one matches, or focus left and came back), the mention typed so far\n // stays as text and the Escape is the page's, so an enclosing Dialog closes, as with MentionInput. tiptap's suggestion\n // takes every Escape while a mention is typed, so this runs before it and ends the mention first.\n const escape = new Plugin({\n props: {\n handleKeyDown(view, event) {\n if ((event.key === \"Escape\" || event.key === \"Esc\") && !shown() && pluginKey.getState(view.state)?.active) exitSuggestion(view, pluginKey);\n return false;\n },\n },\n });\n\n const extension = Mention.extend({\n addProseMirrorPlugins() {\n return [escape, ...(this.parent?.() ?? [])];\n },\n }).configure({\n // one token: Backspace deletes the whole mention, where tiptap's default leaves the \"@\" and offers the list again\n deleteTriggerWithBackspace: true,\n HTMLAttributes: { class: \"rte-mention\" },\n suggestion: {\n pluginKey,\n items: async ({ query }) => {\n asked = query;\n answer = null;\n const o = options.current;\n let found: MentionSuggestion[];\n try {\n found = o.search ? await o.search(query) : matchMentions(o.people ?? [], query);\n } catch {\n found = [];\n }\n if (query === asked) answer = found;\n return found;\n },\n render: () => ({\n onBeforeStart: typed,\n onBeforeUpdate: typed,\n onStart: answered,\n onUpdate: answered,\n onExit: () => {\n pick = null;\n asked = null;\n answer = null;\n store.set(CLOSED);\n },\n // MentionInput's keys: the arrows move round the list, Enter or Tab inserts, Escape closes (the suggestion ends\n // it); with no list shown every key is the editor's\n onKeyDown: ({ event }) => {\n if (!shown()) return false;\n const { items, activeIndex } = store.get();\n if (event.key === \"ArrowDown\") store.set({ activeIndex: (activeIndex + 1) % items.length });\n else if (event.key === \"ArrowUp\") store.set({ activeIndex: (activeIndex - 1 + items.length) % items.length });\n else if (event.key === \"Enter\" || (event.key === \"Tab\" && !event.shiftKey)) pick?.(items[activeIndex]);\n else return event.key === \"Escape\";\n return true;\n },\n }),\n },\n });\n\n function List({ editor }: { editor: Editor }) {\n const state = useSyncExternalStore(store.subscribe, store.get, store.get);\n const id = useId();\n const listRef = useRef<HTMLDivElement>(null);\n const visible = state.open && !state.hidden && state.items.length > 0 && state.owner === editor;\n // the top layer while it shows, so an enclosing overlay's trap stands aside for it\n useOverlayLayer(visible);\n\n // while it shows, the editable area names the list it controls and the active option (aria-activedescendant)\n useEffect(() => {\n if (!visible) return;\n const dom = editor.view.dom;\n dom.setAttribute(\"aria-controls\", id);\n dom.setAttribute(\"aria-activedescendant\", mentionOptionId(id, state.activeIndex));\n return () => {\n dom.removeAttribute(\"aria-controls\");\n dom.removeAttribute(\"aria-activedescendant\");\n };\n }, [editor, visible, id, state.activeIndex]);\n\n // focus leaving the editor hides the list; typing on in the mention shows it again\n useEffect(() => {\n const onBlur = ({ event }: { event: FocusEvent }) => {\n const next = event.relatedTarget as Node | null;\n if (next && listRef.current?.contains(next)) return;\n if (store.get().open) store.set({ hidden: true });\n };\n editor.on(\"blur\", onBlur);\n return () => { editor.off(\"blur\", onBlur); };\n }, [editor]);\n\n if (!visible) return null;\n return (\n <MentionList\n id={id}\n label=\"People\"\n items={state.items}\n more={state.more}\n activeIndex={state.activeIndex}\n onActiveIndexChange={(i) => store.set({ activeIndex: i })}\n onPick={(item) => pick?.(item)}\n anchorRect={() => anchor?.() ?? null}\n listRef={listRef}\n />\n );\n }\n\n return { extension, List };\n}\n\n/**\n * @mentions for RichTextEditor (Sprint 25.17 A17, R28-32): pass the result as the editor's `mentions`, from the first\n * render. Typing \"@\" offers the people whose name (or description) matches what follows, in MentionInput's list, at the\n * caret; the arrows move, Enter or Tab inserts, Escape closes. A mention is one token, read by its name, deleted whole,\n * and carried in onChange's HTML with the person's id (`<span data-type=\"mention\" data-id=\"…\" data-label=\"…\">`), so\n * the page can notify them. `people` can change from render to render; for a large team, `search` looks them up.\n *\n * const mentions = useMentions({ people: members.map((m) => ({ id: m.id, label: m.name, avatar: m.photo })) })\n * <RichTextEditor content={doc} onChange={save} mentions={mentions} />\n */\nexport function useMentions(options: UseMentionsOptions): RichTextEditorMentions {\n const latest = useLatest(options);\n const [mentions] = useState(() => createMentions(latest));\n return mentions;\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/lib/use-mentions.tsx"],"names":[],"mappings":"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","file":"editor-mentions.js","sourcesContent":["import { useEffect, useId, useRef, useState, useSyncExternalStore, type RefObject } from \"react\";\nimport type { Editor } from \"@tiptap/react\";\nimport Mention from \"@tiptap/extension-mention\";\nimport { exitSuggestion, type SuggestionProps } from \"@tiptap/suggestion\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport { useOverlayLayer } from \"./focus\";\nimport { useLatest } from \"./use-latest\";\nimport { MentionList, matchMentions, mentionOptionId, shownMentions, type MentionSuggestion } from \"../components/MentionList\";\nimport type { RichTextEditorMentions } from \"../components/RichTextEditor\";\n\nexport type UseMentionsOptions =\n /** The people to mention: each offered when its name or description matches what follows \"@\". */\n | { people: MentionSuggestion[]; search?: undefined }\n /** For a large team: the people matching what follows \"@\", looked up as it's typed. An answer to an older query is dropped. */\n | { search: (query: string) => MentionSuggestion[] | Promise<MentionSuggestion[]>; people?: undefined };\n\ninterface ListState {\n /** A mention is being typed. */\n open: boolean;\n /** Focus left the editor while one was being typed: the list waits for the next keystroke in it. */\n hidden: boolean;\n /** The people shown: the best matches, at most a list's limit. */\n items: MentionSuggestion[];\n /** How many more match than are shown. */\n more: number;\n activeIndex: number;\n /** The editor the mention is typed in: one result passed to two editors draws its list in that one alone. */\n owner: Editor | null;\n}\n\nconst CLOSED: ListState = { open: false, hidden: false, items: [], more: 0, activeIndex: 0, owner: null };\n\nfunction createStore(initial: ListState) {\n let state = initial;\n const listeners = new Set<() => void>();\n return {\n get: () => state,\n set(patch: Partial<ListState>) {\n state = { ...state, ...patch };\n for (const listener of listeners) listener();\n },\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n };\n}\n\nfunction createMentions(options: RefObject<UseMentionsOptions>): RichTextEditorMentions {\n const store = createStore(CLOSED);\n const pluginKey = new PluginKey(\"gridsmith-mentions\");\n let pick: ((item: MentionSuggestion) => void) | null = null;\n let anchor: (() => DOMRect | null) | null = null;\n /** The newest query looked up, and its answer once it has come: an answer to an older query is never shown. */\n let asked: string | null = null;\n let answer: MentionSuggestion[] | null = null;\n const shown = () => { const s = store.get(); return s.open && !s.hidden && s.items.length > 0; };\n\n // Before each lookup answers (Sprint 25.17's review: a slow search): the range and the caret are the mention as typed\n // now, so Enter replaces all of it, and the people shown stay until the new answer comes, with no blink between keys\n const typed = (props: SuggestionProps<MentionSuggestion>) => {\n pick = (item) => props.command({ id: item.id, label: item.label });\n anchor = props.clientRect ?? null;\n store.set({ open: true, hidden: false, owner: props.editor as Editor });\n };\n // A lookup answered. tiptap hands every callback the newest props, whose items may still be an older lookup's or\n // none: the list shows the newest query's own answer, when it has come.\n const answered = (props: SuggestionProps<MentionSuggestion>) => {\n if (props.query !== asked || answer === null) return;\n typed(props);\n store.set({ ...shownMentions(answer), activeIndex: 0 });\n };\n\n // Escape closes the list; with no list shown (no one matches, or focus left and came back), the mention typed so far\n // stays as text and the Escape is the page's, so an enclosing Dialog closes, as with MentionInput. tiptap's suggestion\n // takes every Escape while a mention is typed, so this runs before it and ends the mention first.\n const escape = new Plugin({\n props: {\n handleKeyDown(view, event) {\n if ((event.key === \"Escape\" || event.key === \"Esc\") && !shown() && pluginKey.getState(view.state)?.active) exitSuggestion(view, pluginKey);\n return false;\n },\n },\n });\n\n const extension = Mention.extend({\n addProseMirrorPlugins() {\n return [escape, ...(this.parent?.() ?? [])];\n },\n }).configure({\n // one token: Backspace deletes the whole mention, where tiptap's default leaves the \"@\" and offers the list again\n deleteTriggerWithBackspace: true,\n HTMLAttributes: { class: \"rte-mention\" },\n suggestion: {\n pluginKey,\n items: async ({ query }) => {\n asked = query;\n answer = null;\n const o = options.current;\n let found: MentionSuggestion[];\n try {\n found = o.search ? await o.search(query) : matchMentions(o.people ?? [], query);\n } catch {\n found = [];\n }\n if (query === asked) answer = found;\n return found;\n },\n render: () => ({\n onBeforeStart: typed,\n onBeforeUpdate: typed,\n onStart: answered,\n onUpdate: answered,\n onExit: () => {\n pick = null;\n asked = null;\n answer = null;\n store.set(CLOSED);\n },\n // MentionInput's keys: the arrows move round the list, Enter or Tab inserts, Escape closes (the suggestion ends\n // it); with no list shown every key is the editor's\n onKeyDown: ({ event }) => {\n if (!shown()) return false;\n const { items, activeIndex } = store.get();\n if (event.key === \"ArrowDown\") store.set({ activeIndex: (activeIndex + 1) % items.length });\n else if (event.key === \"ArrowUp\") store.set({ activeIndex: (activeIndex - 1 + items.length) % items.length });\n else if (event.key === \"Enter\" || (event.key === \"Tab\" && !event.shiftKey)) pick?.(items[activeIndex]);\n else return event.key === \"Escape\";\n return true;\n },\n }),\n },\n });\n\n function List({ editor }: { editor: Editor }) {\n const state = useSyncExternalStore(store.subscribe, store.get, store.get);\n const id = useId();\n const listRef = useRef<HTMLDivElement>(null);\n const visible = state.open && !state.hidden && state.items.length > 0 && state.owner === editor;\n // the top layer while it shows, so an enclosing overlay's trap stands aside for it\n useOverlayLayer(visible);\n\n // while it shows, the editable area names the list it controls and the active option (aria-activedescendant)\n useEffect(() => {\n if (!visible) return;\n const dom = editor.view.dom;\n dom.setAttribute(\"aria-controls\", id);\n dom.setAttribute(\"aria-activedescendant\", mentionOptionId(id, state.activeIndex));\n return () => {\n dom.removeAttribute(\"aria-controls\");\n dom.removeAttribute(\"aria-activedescendant\");\n };\n }, [editor, visible, id, state.activeIndex]);\n\n // focus leaving the editor hides the list; typing on in the mention shows it again\n useEffect(() => {\n const onBlur = ({ event }: { event: FocusEvent }) => {\n const next = event.relatedTarget as Node | null;\n if (next && listRef.current?.contains(next)) return;\n if (store.get().open) store.set({ hidden: true });\n };\n editor.on(\"blur\", onBlur);\n return () => { editor.off(\"blur\", onBlur); };\n }, [editor]);\n\n if (!visible) return null;\n return (\n <MentionList\n id={id}\n label=\"People\"\n items={state.items}\n more={state.more}\n activeIndex={state.activeIndex}\n onActiveIndexChange={(i) => store.set({ activeIndex: i })}\n onPick={(item) => pick?.(item)}\n anchorRect={() => anchor?.() ?? null}\n listRef={listRef}\n />\n );\n }\n\n return { extension, List };\n}\n\n/**\n * @mentions for RichTextEditor (Sprint 25.17 A17, R28-32): pass the result as the editor's `mentions`, from the first\n * render. Typing \"@\" offers the people whose name (or description) matches what follows, in MentionInput's list, at the\n * caret; the arrows move, Enter or Tab inserts, Escape closes. A mention is one token, read by its name, deleted whole,\n * and carried in onChange's HTML with the person's id (`<span data-type=\"mention\" data-id=\"…\" data-label=\"…\">`), so\n * the page can notify them. `people` can change from render to render; for a large team, `search` looks them up.\n *\n * const mentions = useMentions({ people: members.map((m) => ({ id: m.id, label: m.name, avatar: m.photo })) })\n * <RichTextEditor content={doc} onChange={save} mentions={mentions} />\n */\nexport function useMentions(options: UseMentionsOptions): RichTextEditorMentions {\n const latest = useLatest(options);\n const [mentions] = useState(() => createMentions(latest));\n return mentions;\n}\n"]}
package/dist/editor.js CHANGED
@@ -1,13 +1,11 @@
1
1
  "use client";
2
2
  import { useScrollEdges } from './chunk-3BRQRKDO.js';
3
- import { useInputModality } from './chunk-7RKC5C7G.js';
4
3
  import { FormChangeCtx } from './chunk-72SDAX54.js';
5
4
  import { useBreakpoint } from './chunk-ZHUVLBCC.js';
6
- import { useRevealFocus, AutoTooltip } from './chunk-WWN6CQKI.js';
7
- import { warnOnce, Icon } from './chunk-L6HWACK7.js';
8
- import './chunk-7Q46JXSK.js';
9
- import { useLatest, useOverlayLayer, useCloseOnFocusOut } from './chunk-4HJDOZ2M.js';
10
- import { cn, FIELD_FOCUS_WITHIN_RING, FOCUS_RING, FIELD_FOCUS_RING } from './chunk-YL5KD5RC.js';
5
+ import { useInputModality } from './chunk-7RKC5C7G.js';
6
+ import { useRevealFocus, AutoTooltip } from './chunk-DR6WEI3A.js';
7
+ import { warnOnce, Icon } from './chunk-53F7GVBQ.js';
8
+ import { useLatest, cn, FIELD_FOCUS_WITHIN_RING, useOverlayLayer, useCloseOnFocusOut, FOCUS_RING, FIELD_FOCUS_RING } from './chunk-EZ3ZGFGA.js';
11
9
  import { useState, useCallback, useContext, useRef, useEffect, useImperativeHandle } from 'react';
12
10
  import { Extension, Node, mergeAttributes, useEditor, EditorContent, createDocument } from '@tiptap/react';
13
11
  import { Plugin } from '@tiptap/pm/state';