@ai-matrx/design-system 0.86.332 → 0.86.334

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 (140) hide show
  1. package/CHANGELOG.md +28 -2
  2. package/dist/auth-gate-dialog.js +4 -4
  3. package/dist/carousel.js +18 -18
  4. package/dist/{chunk-MVGMI6UZ.js → chunk-3MQMVPKO.js} +5 -5
  5. package/dist/{chunk-2WL2SGKL.js → chunk-677JS6TX.js} +24 -10
  6. package/dist/chunk-677JS6TX.js.map +1 -0
  7. package/dist/{chunk-TBDMTCRW.js → chunk-6YZMGSQY.js} +10 -10
  8. package/dist/{chunk-OFJ5LGBU.js → chunk-7NEVJKDZ.js} +8 -8
  9. package/dist/{chunk-XTNAKJSH.js → chunk-B3LDW3IQ.js} +2 -2
  10. package/dist/{chunk-VTJWQPYR.js → chunk-BM2YYBUO.js} +5 -5
  11. package/dist/{chunk-FTZCPGTH.js → chunk-CFCWQDGC.js} +4 -4
  12. package/dist/{chunk-CN7C4KQB.js → chunk-CH2NWSES.js} +2 -2
  13. package/dist/{chunk-CJCUD62M.js → chunk-CSSD6NS4.js} +5 -5
  14. package/dist/{chunk-W3QSRJ3O.js → chunk-E4GS5QH7.js} +7 -7
  15. package/dist/{chunk-O4KANICE.js → chunk-FRJ4PPA2.js} +5 -5
  16. package/dist/{chunk-4PCLJAW2.js → chunk-FXT7PZAF.js} +5 -14
  17. package/dist/chunk-FXT7PZAF.js.map +1 -0
  18. package/dist/{chunk-D45XDOJS.js → chunk-GHPUO3O7.js} +2 -2
  19. package/dist/{chunk-RPUC5MNH.js → chunk-GLZJ7WZK.js} +3 -3
  20. package/dist/{chunk-VKWQTSB6.js → chunk-HEFTQUJ5.js} +6 -6
  21. package/dist/{chunk-KWBYKUKP.js → chunk-J6637L6D.js} +4 -4
  22. package/dist/chunk-KGW373MK.js +21 -0
  23. package/dist/chunk-KGW373MK.js.map +1 -0
  24. package/dist/{chunk-5LT34PFX.js → chunk-MEJVHDYJ.js} +18 -18
  25. package/dist/{chunk-PPB52S7F.js → chunk-MFUNGDHO.js} +7 -7
  26. package/dist/{chunk-LCPHFONA.js → chunk-MIJMP4WI.js} +5 -5
  27. package/dist/{chunk-XREKZXAL.js → chunk-SMJGESH7.js} +6 -6
  28. package/dist/{chunk-SNHCBHBE.js → chunk-U24MOJWK.js} +4 -4
  29. package/dist/{chunk-DO6G4EKJ.js → chunk-UWTODOMD.js} +2 -2
  30. package/dist/{chunk-BQR4N24F.js → chunk-VLLUUOYJ.js} +4 -4
  31. package/dist/{chunk-FD6V6JBN.js → chunk-VV6WZTH5.js} +8 -8
  32. package/dist/{chunk-LVM7XZRJ.js → chunk-WQ2QCMMA.js} +4 -4
  33. package/dist/{chunk-57OD2WTY.js → chunk-X6ZRHJQP.js} +6 -6
  34. package/dist/{chunk-PLFWDUJW.js → chunk-XEXSZBXV.js} +3 -3
  35. package/dist/{chunk-JSXNITMG.js → chunk-YC5GAO35.js} +2 -2
  36. package/dist/{chunk-5TF2AFDM.js → chunk-ZCRPESQX.js} +4 -4
  37. package/dist/{chunk-5IKQ6RU4.js → chunk-ZOQ2XKXF.js} +9 -9
  38. package/dist/clipboard-fallback-dialog.js +10 -10
  39. package/dist/controls.js +15 -15
  40. package/dist/data-table/data-row-inspector.js +15 -14
  41. package/dist/data-table/data-row-window.js +20 -19
  42. package/dist/data-table/index.cjs +16 -12
  43. package/dist/data-table/index.cjs.map +1 -1
  44. package/dist/data-table/index.js +37 -36
  45. package/dist/data-table/index.js.map +1 -1
  46. package/dist/data-table/layered-filter-builder.js +4 -4
  47. package/dist/data-table/pagination.js +8 -8
  48. package/dist/data-table/uuid-cell.js +8 -8
  49. package/dist/desktop.js +22 -22
  50. package/dist/email-input-dialog.js +7 -7
  51. package/dist/index.cjs +590 -397
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +120 -10
  54. package/dist/index.d.ts +120 -10
  55. package/dist/index.js +519 -348
  56. package/dist/index.js.map +1 -1
  57. package/dist/intro-stage.js +3 -3
  58. package/dist/item.cjs +33 -17
  59. package/dist/item.cjs.map +1 -1
  60. package/dist/item.d.cts +7 -1
  61. package/dist/item.d.ts +7 -1
  62. package/dist/item.js +32 -30
  63. package/dist/item.js.map +1 -1
  64. package/dist/lite-table.js +10 -10
  65. package/dist/menu-look.js +3 -3
  66. package/dist/record-list.cjs +16 -2
  67. package/dist/record-list.cjs.map +1 -1
  68. package/dist/record-list.d.cts +7 -1
  69. package/dist/record-list.d.ts +7 -1
  70. package/dist/record-list.js +13 -13
  71. package/dist/sandbox-gate-dialog.js +8 -8
  72. package/dist/scope-mismatch-dialog.js +7 -7
  73. package/dist/settings.cjs +16 -12
  74. package/dist/settings.cjs.map +1 -1
  75. package/dist/settings.js +20 -19
  76. package/dist/settings.js.map +1 -1
  77. package/dist/site-icon.js +2 -2
  78. package/dist/swipe-deck.js +1 -1
  79. package/dist/tap-shortcut.cjs +40 -0
  80. package/dist/tap-shortcut.cjs.map +1 -0
  81. package/dist/tap-shortcut.d.cts +13 -0
  82. package/dist/tap-shortcut.d.ts +13 -0
  83. package/dist/tap-shortcut.js +10 -0
  84. package/dist/tap-shortcut.js.map +1 -0
  85. package/dist/tap-target/ai-buttons.cjs +16 -12
  86. package/dist/tap-target/ai-buttons.cjs.map +1 -1
  87. package/dist/tap-target/ai-buttons.js +4 -3
  88. package/dist/tap-target/ai-buttons.js.map +1 -1
  89. package/dist/tap-target/buttons.cjs +16 -12
  90. package/dist/tap-target/buttons.cjs.map +1 -1
  91. package/dist/tap-target/buttons.d.cts +3 -5
  92. package/dist/tap-target/buttons.d.ts +3 -5
  93. package/dist/tap-target/buttons.js +4 -3
  94. package/dist/tap-target.cjs +16 -12
  95. package/dist/tap-target.cjs.map +1 -1
  96. package/dist/tap-target.d.cts +5 -7
  97. package/dist/tap-target.d.ts +5 -7
  98. package/dist/tap-target.js +6 -4
  99. package/dist/text-input-dialog.js +10 -10
  100. package/dist/thumbnail-grid.js +2 -2
  101. package/dist/transcript-scroll-nav.cjs +16 -12
  102. package/dist/transcript-scroll-nav.cjs.map +1 -1
  103. package/dist/transcript-scroll-nav.js +2 -1
  104. package/dist/transcript-scroll-nav.js.map +1 -1
  105. package/dist/value-prompts-dialog.js +5 -5
  106. package/dist/writing-field.cjs +16 -12
  107. package/dist/writing-field.cjs.map +1 -1
  108. package/dist/writing-field.js +21 -20
  109. package/dist/writing-field.js.map +1 -1
  110. package/package.json +12 -2
  111. package/dist/chunk-2WL2SGKL.js.map +0 -1
  112. package/dist/chunk-4PCLJAW2.js.map +0 -1
  113. /package/dist/{chunk-MVGMI6UZ.js.map → chunk-3MQMVPKO.js.map} +0 -0
  114. /package/dist/{chunk-TBDMTCRW.js.map → chunk-6YZMGSQY.js.map} +0 -0
  115. /package/dist/{chunk-OFJ5LGBU.js.map → chunk-7NEVJKDZ.js.map} +0 -0
  116. /package/dist/{chunk-XTNAKJSH.js.map → chunk-B3LDW3IQ.js.map} +0 -0
  117. /package/dist/{chunk-VTJWQPYR.js.map → chunk-BM2YYBUO.js.map} +0 -0
  118. /package/dist/{chunk-FTZCPGTH.js.map → chunk-CFCWQDGC.js.map} +0 -0
  119. /package/dist/{chunk-CN7C4KQB.js.map → chunk-CH2NWSES.js.map} +0 -0
  120. /package/dist/{chunk-CJCUD62M.js.map → chunk-CSSD6NS4.js.map} +0 -0
  121. /package/dist/{chunk-W3QSRJ3O.js.map → chunk-E4GS5QH7.js.map} +0 -0
  122. /package/dist/{chunk-O4KANICE.js.map → chunk-FRJ4PPA2.js.map} +0 -0
  123. /package/dist/{chunk-D45XDOJS.js.map → chunk-GHPUO3O7.js.map} +0 -0
  124. /package/dist/{chunk-RPUC5MNH.js.map → chunk-GLZJ7WZK.js.map} +0 -0
  125. /package/dist/{chunk-VKWQTSB6.js.map → chunk-HEFTQUJ5.js.map} +0 -0
  126. /package/dist/{chunk-KWBYKUKP.js.map → chunk-J6637L6D.js.map} +0 -0
  127. /package/dist/{chunk-5LT34PFX.js.map → chunk-MEJVHDYJ.js.map} +0 -0
  128. /package/dist/{chunk-PPB52S7F.js.map → chunk-MFUNGDHO.js.map} +0 -0
  129. /package/dist/{chunk-LCPHFONA.js.map → chunk-MIJMP4WI.js.map} +0 -0
  130. /package/dist/{chunk-XREKZXAL.js.map → chunk-SMJGESH7.js.map} +0 -0
  131. /package/dist/{chunk-SNHCBHBE.js.map → chunk-U24MOJWK.js.map} +0 -0
  132. /package/dist/{chunk-DO6G4EKJ.js.map → chunk-UWTODOMD.js.map} +0 -0
  133. /package/dist/{chunk-BQR4N24F.js.map → chunk-VLLUUOYJ.js.map} +0 -0
  134. /package/dist/{chunk-FD6V6JBN.js.map → chunk-VV6WZTH5.js.map} +0 -0
  135. /package/dist/{chunk-LVM7XZRJ.js.map → chunk-WQ2QCMMA.js.map} +0 -0
  136. /package/dist/{chunk-57OD2WTY.js.map → chunk-X6ZRHJQP.js.map} +0 -0
  137. /package/dist/{chunk-PLFWDUJW.js.map → chunk-XEXSZBXV.js.map} +0 -0
  138. /package/dist/{chunk-JSXNITMG.js.map → chunk-YC5GAO35.js.map} +0 -0
  139. /package/dist/{chunk-5TF2AFDM.js.map → chunk-ZCRPESQX.js.map} +0 -0
  140. /package/dist/{chunk-5IKQ6RU4.js.map → chunk-ZOQ2XKXF.js.map} +0 -0
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
  import {
3
3
  TapTargetButton
4
- } from "./chunk-4PCLJAW2.js";
4
+ } from "./chunk-FXT7PZAF.js";
5
5
  import "./chunk-WFBPCMPF.js";
6
+ import "./chunk-KGW373MK.js";
6
7
  import {
7
8
  TooltipProvider
8
9
  } from "./chunk-PIQJULQB.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transcript-scroll-nav/transcript-scroll-nav.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE TRANSCRIPT SCROLL NAV — two floating round tap buttons over a long\n * transcript (owner, 2026-10-12).\n *\n * - DOWN scrolls to the end. Shown only when the view is more than\n * `TRANSCRIPT_BOTTOM_THRESHOLD_PX` from the bottom.\n * - UP puts the PREVIOUS real user message at the TOP of the view; pressed\n * again it goes to the one before it, until the very first. Only elements\n * matching the anchor selector count — the host tags the row that renders a\n * message a person actually typed (`data-transcript-anchor=\"user\"`), never a\n * tool, system, agent or assistant row. Hidden when no anchor lies above the\n * view top (`TRANSCRIPT_TOP_TOLERANCE_PX` lets an anchor already aligned at\n * the top count as \"current\", so the next press goes to the one before).\n * With no anchor above but the view not at the top, UP goes to the very top\n * — where a host lazy-loads older history — and hides only there.\n *\n * Placement (owner, 2026-10-15): each button sits at the EDGE it goes to —\n * UP at the top-right corner of the transcript, DOWN at the bottom-right. A\n * stacked pair at the bottom put \"go up\" at the bottom of a phone screen, the\n * farthest place from where it takes you. The host gives the scroll area's\n * PARENT `relative` and renders this beside (not inside) the scroller; a\n * `className` (e.g. a different right inset) is applied to BOTH corners. Each\n * corner is its own glass plane (`data-matrx-glass-plane`) because it floats\n * over moving content — tap placement rule 1.\n */\n\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { TapTargetButton } from \"../tap-target/tap-target-button\";\nimport { TooltipProvider } from \"../tooltip\";\n\nexport const TRANSCRIPT_USER_ANCHOR_SELECTOR = '[data-transcript-anchor=\"user\"]';\nexport const TRANSCRIPT_BOTTOM_THRESHOLD_PX = 120;\nexport const TRANSCRIPT_TOP_TOLERANCE_PX = 8;\n\n/** Each anchor's top in the scroller's content coordinates (what `scrollTop` measures). */\nexport function transcriptAnchorOffsets(scroller: HTMLElement, anchorSelector: string): number[] {\n const base = scroller.getBoundingClientRect().top - scroller.scrollTop;\n const out: number[] = [];\n scroller.querySelectorAll<HTMLElement>(anchorSelector).forEach((anchor) => {\n const rect = anchor.getBoundingClientRect();\n // A row that renders nothing (a host-authored turn, a collapsed wrapper) is not a place to go.\n if (rect.height <= 0) return;\n out.push(rect.top - base);\n });\n return out.sort((a, b) => a - b);\n}\n\n/** The top of the nearest anchor ABOVE `viewTop` (beyond the tolerance), or null. */\nexport function previousTranscriptAnchor(\n offsets: readonly number[],\n viewTop: number,\n tolerance: number = TRANSCRIPT_TOP_TOLERANCE_PX,\n): number | null {\n let found: number | null = null;\n for (const top of offsets) {\n if (top < viewTop - tolerance) found = top;\n else break;\n }\n return found;\n}\n\nexport interface TranscriptScrollNavState {\n canGoUp: boolean;\n canGoDown: boolean;\n goUp: () => void;\n goDown: () => void;\n}\n\nexport function useTranscriptScrollNav(\n scrollRef: React.RefObject<HTMLElement | null>,\n anchorSelector: string = TRANSCRIPT_USER_ANCHOR_SELECTOR,\n): TranscriptScrollNavState {\n // The ref's element can change (a landing surface swapped for the transcript),\n // so the element is mirrored into state after every render.\n const [el, setEl] = React.useState<HTMLElement | null>(null);\n React.useLayoutEffect(() => {\n if (scrollRef.current !== el) setEl(scrollRef.current);\n });\n\n const [canGoUp, setCanGoUp] = React.useState(false);\n const [canGoDown, setCanGoDown] = React.useState(false);\n // Where an in-flight smooth upward scroll is heading: a second press during\n // the animation steps past it instead of re-targeting the same message.\n const pendingUpRef = React.useRef<number | null>(null);\n\n const measure = React.useCallback(() => {\n if (!el) {\n setCanGoUp(false);\n setCanGoDown(false);\n return;\n }\n const pending = pendingUpRef.current;\n if (pending !== null && Math.abs(el.scrollTop - pending) <= 2) pendingUpRef.current = null;\n setCanGoDown(el.scrollHeight - el.scrollTop - el.clientHeight > TRANSCRIPT_BOTTOM_THRESHOLD_PX);\n // Above the first loaded anchor there may be older history a host loads\n // on reaching the top, so UP stays until the very top.\n setCanGoUp(el.scrollTop > TRANSCRIPT_TOP_TOLERANCE_PX);\n }, [el, anchorSelector]);\n\n React.useEffect(() => {\n if (!el) {\n measure();\n return undefined;\n }\n const view = el.ownerDocument.defaultView ?? window;\n let frame: number | null = null;\n const schedule = () => {\n if (frame !== null) return;\n frame = view.requestAnimationFrame(() => {\n frame = null;\n measure();\n });\n };\n measure();\n el.addEventListener(\"scroll\", schedule, { passive: true });\n\n // Transcripts stream: content grows without a scroll event.\n const resize = typeof view.ResizeObserver === \"function\" ? new view.ResizeObserver(schedule) : null;\n const observeChildren = () => {\n if (!resize) return;\n resize.observe(el);\n Array.from(el.children).forEach((child) => resize.observe(child));\n };\n observeChildren();\n const mutation =\n typeof view.MutationObserver === \"function\"\n ? new view.MutationObserver(() => {\n observeChildren();\n schedule();\n })\n : null;\n mutation?.observe(el, { childList: true, subtree: true });\n\n return () => {\n el.removeEventListener(\"scroll\", schedule);\n resize?.disconnect();\n mutation?.disconnect();\n if (frame !== null) view.cancelAnimationFrame(frame);\n };\n }, [el, measure]);\n\n const goUp = React.useCallback(() => {\n if (!el) return;\n const pending = pendingUpRef.current;\n const from = pending !== null && pending < el.scrollTop ? pending : el.scrollTop;\n // No message of mine above: go to the very top (a host loading older\n // history there then gives UP more messages to step through).\n const target = previousTranscriptAnchor(transcriptAnchorOffsets(el, anchorSelector), from) ?? 0;\n if (target >= el.scrollTop) return;\n pendingUpRef.current = target;\n el.scrollTo({ top: target, behavior: \"smooth\" });\n }, [el, anchorSelector]);\n\n const goDown = React.useCallback(() => {\n if (!el) return;\n pendingUpRef.current = null;\n el.scrollTo({ top: el.scrollHeight, behavior: \"smooth\" });\n }, [el]);\n\n return { canGoUp, canGoDown, goUp, goDown };\n}\n\nexport interface TranscriptScrollNavProps {\n /** The transcript's scrolling element. */\n scrollRef: React.RefObject<HTMLElement | null>;\n /** Which rows the UP button steps through. Default: `[data-transcript-anchor=\"user\"]`. */\n anchorSelector?: string | undefined;\n /** Placement override applied to both corners (e.g. a different right inset). Default: `right-4`, UP `top-4`, DOWN `bottom-4`. */\n className?: string | undefined;\n upLabel?: string | undefined;\n downLabel?: string | undefined;\n}\n\nexport function TranscriptScrollNav({\n scrollRef,\n anchorSelector = TRANSCRIPT_USER_ANCHOR_SELECTOR,\n className,\n upLabel = \"Previous message I sent\",\n downLabel = \"Scroll to bottom\",\n}: TranscriptScrollNavProps) {\n const { canGoUp, canGoDown, goUp, goDown } = useTranscriptScrollNav(scrollRef, anchorSelector);\n if (!canGoUp && !canGoDown) return null;\n return (\n <TooltipProvider>\n {canGoUp && (\n <div\n data-matrx-glass-plane=\"\"\n data-transcript-scroll-nav=\"up\"\n className={cn(\"absolute right-4 top-4 z-10 flex\", className)}\n >\n <TapTargetButton ariaLabel={upLabel} tooltip={upLabel} tooltipSide=\"left\" onClick={goUp}>\n {/* lucide: arrow-up */}\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </TapTargetButton>\n </div>\n )}\n {canGoDown && (\n <div\n data-matrx-glass-plane=\"\"\n data-transcript-scroll-nav=\"down\"\n className={cn(\"absolute bottom-4 right-4 z-10 flex\", className)}\n >\n <TapTargetButton ariaLabel={downLabel} tooltip={downLabel} tooltipSide=\"left\" onClick={goDown}>\n {/* lucide: arrow-down */}\n <path d=\"M12 5v14\" />\n <path d=\"m19 12-7 7-7-7\" />\n </TapTargetButton>\n </div>\n )}\n </TooltipProvider>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/transcript-scroll-nav/transcript-scroll-nav.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * THE TRANSCRIPT SCROLL NAV — two floating round tap buttons over a long\n * transcript (owner, 2026-10-12).\n *\n * - DOWN scrolls to the end. Shown only when the view is more than\n * `TRANSCRIPT_BOTTOM_THRESHOLD_PX` from the bottom.\n * - UP puts the PREVIOUS real user message at the TOP of the view; pressed\n * again it goes to the one before it, until the very first. Only elements\n * matching the anchor selector count — the host tags the row that renders a\n * message a person actually typed (`data-transcript-anchor=\"user\"`), never a\n * tool, system, agent or assistant row. Hidden when no anchor lies above the\n * view top (`TRANSCRIPT_TOP_TOLERANCE_PX` lets an anchor already aligned at\n * the top count as \"current\", so the next press goes to the one before).\n * With no anchor above but the view not at the top, UP goes to the very top\n * — where a host lazy-loads older history — and hides only there.\n *\n * Placement (owner, 2026-10-15): each button sits at the EDGE it goes to —\n * UP at the top-right corner of the transcript, DOWN at the bottom-right. A\n * stacked pair at the bottom put \"go up\" at the bottom of a phone screen, the\n * farthest place from where it takes you. The host gives the scroll area's\n * PARENT `relative` and renders this beside (not inside) the scroller; a\n * `className` (e.g. a different right inset) is applied to BOTH corners. Each\n * corner is its own glass plane (`data-matrx-glass-plane`) because it floats\n * over moving content — tap placement rule 1.\n */\n\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { TapTargetButton } from \"../tap-target/tap-target-button\";\nimport { TooltipProvider } from \"../tooltip\";\n\nexport const TRANSCRIPT_USER_ANCHOR_SELECTOR = '[data-transcript-anchor=\"user\"]';\nexport const TRANSCRIPT_BOTTOM_THRESHOLD_PX = 120;\nexport const TRANSCRIPT_TOP_TOLERANCE_PX = 8;\n\n/** Each anchor's top in the scroller's content coordinates (what `scrollTop` measures). */\nexport function transcriptAnchorOffsets(scroller: HTMLElement, anchorSelector: string): number[] {\n const base = scroller.getBoundingClientRect().top - scroller.scrollTop;\n const out: number[] = [];\n scroller.querySelectorAll<HTMLElement>(anchorSelector).forEach((anchor) => {\n const rect = anchor.getBoundingClientRect();\n // A row that renders nothing (a host-authored turn, a collapsed wrapper) is not a place to go.\n if (rect.height <= 0) return;\n out.push(rect.top - base);\n });\n return out.sort((a, b) => a - b);\n}\n\n/** The top of the nearest anchor ABOVE `viewTop` (beyond the tolerance), or null. */\nexport function previousTranscriptAnchor(\n offsets: readonly number[],\n viewTop: number,\n tolerance: number = TRANSCRIPT_TOP_TOLERANCE_PX,\n): number | null {\n let found: number | null = null;\n for (const top of offsets) {\n if (top < viewTop - tolerance) found = top;\n else break;\n }\n return found;\n}\n\nexport interface TranscriptScrollNavState {\n canGoUp: boolean;\n canGoDown: boolean;\n goUp: () => void;\n goDown: () => void;\n}\n\nexport function useTranscriptScrollNav(\n scrollRef: React.RefObject<HTMLElement | null>,\n anchorSelector: string = TRANSCRIPT_USER_ANCHOR_SELECTOR,\n): TranscriptScrollNavState {\n // The ref's element can change (a landing surface swapped for the transcript),\n // so the element is mirrored into state after every render.\n const [el, setEl] = React.useState<HTMLElement | null>(null);\n React.useLayoutEffect(() => {\n if (scrollRef.current !== el) setEl(scrollRef.current);\n });\n\n const [canGoUp, setCanGoUp] = React.useState(false);\n const [canGoDown, setCanGoDown] = React.useState(false);\n // Where an in-flight smooth upward scroll is heading: a second press during\n // the animation steps past it instead of re-targeting the same message.\n const pendingUpRef = React.useRef<number | null>(null);\n\n const measure = React.useCallback(() => {\n if (!el) {\n setCanGoUp(false);\n setCanGoDown(false);\n return;\n }\n const pending = pendingUpRef.current;\n if (pending !== null && Math.abs(el.scrollTop - pending) <= 2) pendingUpRef.current = null;\n setCanGoDown(el.scrollHeight - el.scrollTop - el.clientHeight > TRANSCRIPT_BOTTOM_THRESHOLD_PX);\n // Above the first loaded anchor there may be older history a host loads\n // on reaching the top, so UP stays until the very top.\n setCanGoUp(el.scrollTop > TRANSCRIPT_TOP_TOLERANCE_PX);\n }, [el, anchorSelector]);\n\n React.useEffect(() => {\n if (!el) {\n measure();\n return undefined;\n }\n const view = el.ownerDocument.defaultView ?? window;\n let frame: number | null = null;\n const schedule = () => {\n if (frame !== null) return;\n frame = view.requestAnimationFrame(() => {\n frame = null;\n measure();\n });\n };\n measure();\n el.addEventListener(\"scroll\", schedule, { passive: true });\n\n // Transcripts stream: content grows without a scroll event.\n const resize = typeof view.ResizeObserver === \"function\" ? new view.ResizeObserver(schedule) : null;\n const observeChildren = () => {\n if (!resize) return;\n resize.observe(el);\n Array.from(el.children).forEach((child) => resize.observe(child));\n };\n observeChildren();\n const mutation =\n typeof view.MutationObserver === \"function\"\n ? new view.MutationObserver(() => {\n observeChildren();\n schedule();\n })\n : null;\n mutation?.observe(el, { childList: true, subtree: true });\n\n return () => {\n el.removeEventListener(\"scroll\", schedule);\n resize?.disconnect();\n mutation?.disconnect();\n if (frame !== null) view.cancelAnimationFrame(frame);\n };\n }, [el, measure]);\n\n const goUp = React.useCallback(() => {\n if (!el) return;\n const pending = pendingUpRef.current;\n const from = pending !== null && pending < el.scrollTop ? pending : el.scrollTop;\n // No message of mine above: go to the very top (a host loading older\n // history there then gives UP more messages to step through).\n const target = previousTranscriptAnchor(transcriptAnchorOffsets(el, anchorSelector), from) ?? 0;\n if (target >= el.scrollTop) return;\n pendingUpRef.current = target;\n el.scrollTo({ top: target, behavior: \"smooth\" });\n }, [el, anchorSelector]);\n\n const goDown = React.useCallback(() => {\n if (!el) return;\n pendingUpRef.current = null;\n el.scrollTo({ top: el.scrollHeight, behavior: \"smooth\" });\n }, [el]);\n\n return { canGoUp, canGoDown, goUp, goDown };\n}\n\nexport interface TranscriptScrollNavProps {\n /** The transcript's scrolling element. */\n scrollRef: React.RefObject<HTMLElement | null>;\n /** Which rows the UP button steps through. Default: `[data-transcript-anchor=\"user\"]`. */\n anchorSelector?: string | undefined;\n /** Placement override applied to both corners (e.g. a different right inset). Default: `right-4`, UP `top-4`, DOWN `bottom-4`. */\n className?: string | undefined;\n upLabel?: string | undefined;\n downLabel?: string | undefined;\n}\n\nexport function TranscriptScrollNav({\n scrollRef,\n anchorSelector = TRANSCRIPT_USER_ANCHOR_SELECTOR,\n className,\n upLabel = \"Previous message I sent\",\n downLabel = \"Scroll to bottom\",\n}: TranscriptScrollNavProps) {\n const { canGoUp, canGoDown, goUp, goDown } = useTranscriptScrollNav(scrollRef, anchorSelector);\n if (!canGoUp && !canGoDown) return null;\n return (\n <TooltipProvider>\n {canGoUp && (\n <div\n data-matrx-glass-plane=\"\"\n data-transcript-scroll-nav=\"up\"\n className={cn(\"absolute right-4 top-4 z-10 flex\", className)}\n >\n <TapTargetButton ariaLabel={upLabel} tooltip={upLabel} tooltipSide=\"left\" onClick={goUp}>\n {/* lucide: arrow-up */}\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </TapTargetButton>\n </div>\n )}\n {canGoDown && (\n <div\n data-matrx-glass-plane=\"\"\n data-transcript-scroll-nav=\"down\"\n className={cn(\"absolute bottom-4 right-4 z-10 flex\", className)}\n >\n <TapTargetButton ariaLabel={downLabel} tooltip={downLabel} tooltipSide=\"left\" onClick={goDown}>\n {/* lucide: arrow-down */}\n <path d=\"M12 5v14\" />\n <path d=\"m19 12-7 7-7-7\" />\n </TapTargetButton>\n </div>\n )}\n </TooltipProvider>\n );\n}\n"],"mappings":"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","names":[]}
@@ -7,7 +7,6 @@ import {
7
7
  Label
8
8
  } from "./chunk-XERGQT2M.js";
9
9
  import "./chunk-TDMVH77G.js";
10
- import "./chunk-IMQ3RX35.js";
11
10
  import {
12
11
  Dialog,
13
12
  DialogContent,
@@ -15,21 +14,22 @@ import {
15
14
  DialogFooter,
16
15
  DialogHeader,
17
16
  DialogTitle
18
- } from "./chunk-DO6G4EKJ.js";
19
- import "./chunk-SNHCBHBE.js";
17
+ } from "./chunk-UWTODOMD.js";
18
+ import "./chunk-IMQ3RX35.js";
19
+ import "./chunk-U24MOJWK.js";
20
20
  import "./chunk-NDTDBBMM.js";
21
21
  import "./chunk-LEPD6TV7.js";
22
22
  import "./chunk-BD77DHUO.js";
23
23
  import "./chunk-MOZRIHJF.js";
24
+ import "./chunk-WAT2XW7L.js";
24
25
  import {
25
26
  Button
26
27
  } from "./chunk-7IOSA55D.js";
27
- import "./chunk-WAT2XW7L.js";
28
28
  import "./chunk-DGNHZBJY.js";
29
29
  import "./chunk-XIUVUL2Y.js";
30
+ import "./chunk-YCUFQCJW.js";
30
31
  import "./chunk-IMOOQQOO.js";
31
32
  import "./chunk-M6KA5EHN.js";
32
- import "./chunk-YCUFQCJW.js";
33
33
 
34
34
  // src/value-prompts-dialog.tsx
35
35
  import * as React from "react";
@@ -1574,6 +1574,22 @@ function useTapSurface(explicit) {
1574
1574
 
1575
1575
  // src/tap-target/tap-features.tsx
1576
1576
  var import_react4 = require("react");
1577
+
1578
+ // src/tap-shortcut.ts
1579
+ var IS_APPLE = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);
1580
+ function parseShortcut(shortcut) {
1581
+ const parts = shortcut.toLowerCase().split("+");
1582
+ const key = parts.pop() ?? "";
1583
+ return { mod: parts.includes("mod"), shift: parts.includes("shift"), alt: parts.includes("alt"), key };
1584
+ }
1585
+ function formatTapShortcut(shortcut) {
1586
+ const p = parseShortcut(shortcut);
1587
+ const key = p.key.length === 1 ? p.key.toUpperCase() : p.key[0].toUpperCase() + p.key.slice(1);
1588
+ if (IS_APPLE) return `${p.alt ? "\u2325" : ""}${p.shift ? "\u21E7" : ""}${p.mod ? "\u2318" : ""}${key}`;
1589
+ return [p.mod && "Ctrl", p.alt && "Alt", p.shift && "Shift", key].filter(Boolean).join("+");
1590
+ }
1591
+
1592
+ // src/tap-target/tap-features.tsx
1577
1593
  var import_jsx_runtime12 = require("react/jsx-runtime");
1578
1594
  var TAP_TONE_CLASS = {
1579
1595
  default: "text-foreground",
@@ -1591,18 +1607,6 @@ var TAP_SOLID_TONE = {
1591
1607
  warning: { fill: "bg-warning group-hover/tap:bg-warning/85", glyph: "text-warning-foreground" },
1592
1608
  neutral: { fill: "bg-foreground group-hover/tap:bg-foreground/85", glyph: "text-background" }
1593
1609
  };
1594
- var IS_APPLE = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);
1595
- function parseShortcut(shortcut) {
1596
- const parts = shortcut.toLowerCase().split("+");
1597
- const key = parts.pop() ?? "";
1598
- return { mod: parts.includes("mod"), shift: parts.includes("shift"), alt: parts.includes("alt"), key };
1599
- }
1600
- function formatTapShortcut(shortcut) {
1601
- const p = parseShortcut(shortcut);
1602
- const key = p.key.length === 1 ? p.key.toUpperCase() : p.key[0].toUpperCase() + p.key.slice(1);
1603
- if (IS_APPLE) return `${p.alt ? "\u2325" : ""}${p.shift ? "\u21E7" : ""}${p.mod ? "\u2318" : ""}${key}`;
1604
- return [p.mod && "Ctrl", p.alt && "Alt", p.shift && "Shift", key].filter(Boolean).join("+");
1605
- }
1606
1610
  function isTyping(target) {
1607
1611
  const el = target;
1608
1612
  return !!el && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));