@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.
- package/CHANGELOG.md +28 -2
- package/dist/auth-gate-dialog.js +4 -4
- package/dist/carousel.js +18 -18
- package/dist/{chunk-MVGMI6UZ.js → chunk-3MQMVPKO.js} +5 -5
- package/dist/{chunk-2WL2SGKL.js → chunk-677JS6TX.js} +24 -10
- package/dist/chunk-677JS6TX.js.map +1 -0
- package/dist/{chunk-TBDMTCRW.js → chunk-6YZMGSQY.js} +10 -10
- package/dist/{chunk-OFJ5LGBU.js → chunk-7NEVJKDZ.js} +8 -8
- package/dist/{chunk-XTNAKJSH.js → chunk-B3LDW3IQ.js} +2 -2
- package/dist/{chunk-VTJWQPYR.js → chunk-BM2YYBUO.js} +5 -5
- package/dist/{chunk-FTZCPGTH.js → chunk-CFCWQDGC.js} +4 -4
- package/dist/{chunk-CN7C4KQB.js → chunk-CH2NWSES.js} +2 -2
- package/dist/{chunk-CJCUD62M.js → chunk-CSSD6NS4.js} +5 -5
- package/dist/{chunk-W3QSRJ3O.js → chunk-E4GS5QH7.js} +7 -7
- package/dist/{chunk-O4KANICE.js → chunk-FRJ4PPA2.js} +5 -5
- package/dist/{chunk-4PCLJAW2.js → chunk-FXT7PZAF.js} +5 -14
- package/dist/chunk-FXT7PZAF.js.map +1 -0
- package/dist/{chunk-D45XDOJS.js → chunk-GHPUO3O7.js} +2 -2
- package/dist/{chunk-RPUC5MNH.js → chunk-GLZJ7WZK.js} +3 -3
- package/dist/{chunk-VKWQTSB6.js → chunk-HEFTQUJ5.js} +6 -6
- package/dist/{chunk-KWBYKUKP.js → chunk-J6637L6D.js} +4 -4
- package/dist/chunk-KGW373MK.js +21 -0
- package/dist/chunk-KGW373MK.js.map +1 -0
- package/dist/{chunk-5LT34PFX.js → chunk-MEJVHDYJ.js} +18 -18
- package/dist/{chunk-PPB52S7F.js → chunk-MFUNGDHO.js} +7 -7
- package/dist/{chunk-LCPHFONA.js → chunk-MIJMP4WI.js} +5 -5
- package/dist/{chunk-XREKZXAL.js → chunk-SMJGESH7.js} +6 -6
- package/dist/{chunk-SNHCBHBE.js → chunk-U24MOJWK.js} +4 -4
- package/dist/{chunk-DO6G4EKJ.js → chunk-UWTODOMD.js} +2 -2
- package/dist/{chunk-BQR4N24F.js → chunk-VLLUUOYJ.js} +4 -4
- package/dist/{chunk-FD6V6JBN.js → chunk-VV6WZTH5.js} +8 -8
- package/dist/{chunk-LVM7XZRJ.js → chunk-WQ2QCMMA.js} +4 -4
- package/dist/{chunk-57OD2WTY.js → chunk-X6ZRHJQP.js} +6 -6
- package/dist/{chunk-PLFWDUJW.js → chunk-XEXSZBXV.js} +3 -3
- package/dist/{chunk-JSXNITMG.js → chunk-YC5GAO35.js} +2 -2
- package/dist/{chunk-5TF2AFDM.js → chunk-ZCRPESQX.js} +4 -4
- package/dist/{chunk-5IKQ6RU4.js → chunk-ZOQ2XKXF.js} +9 -9
- package/dist/clipboard-fallback-dialog.js +10 -10
- package/dist/controls.js +15 -15
- package/dist/data-table/data-row-inspector.js +15 -14
- package/dist/data-table/data-row-window.js +20 -19
- package/dist/data-table/index.cjs +16 -12
- package/dist/data-table/index.cjs.map +1 -1
- package/dist/data-table/index.js +37 -36
- package/dist/data-table/index.js.map +1 -1
- package/dist/data-table/layered-filter-builder.js +4 -4
- package/dist/data-table/pagination.js +8 -8
- package/dist/data-table/uuid-cell.js +8 -8
- package/dist/desktop.js +22 -22
- package/dist/email-input-dialog.js +7 -7
- package/dist/index.cjs +590 -397
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -10
- package/dist/index.d.ts +120 -10
- package/dist/index.js +519 -348
- package/dist/index.js.map +1 -1
- package/dist/intro-stage.js +3 -3
- package/dist/item.cjs +33 -17
- package/dist/item.cjs.map +1 -1
- package/dist/item.d.cts +7 -1
- package/dist/item.d.ts +7 -1
- package/dist/item.js +32 -30
- package/dist/item.js.map +1 -1
- package/dist/lite-table.js +10 -10
- package/dist/menu-look.js +3 -3
- package/dist/record-list.cjs +16 -2
- package/dist/record-list.cjs.map +1 -1
- package/dist/record-list.d.cts +7 -1
- package/dist/record-list.d.ts +7 -1
- package/dist/record-list.js +13 -13
- package/dist/sandbox-gate-dialog.js +8 -8
- package/dist/scope-mismatch-dialog.js +7 -7
- package/dist/settings.cjs +16 -12
- package/dist/settings.cjs.map +1 -1
- package/dist/settings.js +20 -19
- package/dist/settings.js.map +1 -1
- package/dist/site-icon.js +2 -2
- package/dist/swipe-deck.js +1 -1
- package/dist/tap-shortcut.cjs +40 -0
- package/dist/tap-shortcut.cjs.map +1 -0
- package/dist/tap-shortcut.d.cts +13 -0
- package/dist/tap-shortcut.d.ts +13 -0
- package/dist/tap-shortcut.js +10 -0
- package/dist/tap-shortcut.js.map +1 -0
- package/dist/tap-target/ai-buttons.cjs +16 -12
- package/dist/tap-target/ai-buttons.cjs.map +1 -1
- package/dist/tap-target/ai-buttons.js +4 -3
- package/dist/tap-target/ai-buttons.js.map +1 -1
- package/dist/tap-target/buttons.cjs +16 -12
- package/dist/tap-target/buttons.cjs.map +1 -1
- package/dist/tap-target/buttons.d.cts +3 -5
- package/dist/tap-target/buttons.d.ts +3 -5
- package/dist/tap-target/buttons.js +4 -3
- package/dist/tap-target.cjs +16 -12
- package/dist/tap-target.cjs.map +1 -1
- package/dist/tap-target.d.cts +5 -7
- package/dist/tap-target.d.ts +5 -7
- package/dist/tap-target.js +6 -4
- package/dist/text-input-dialog.js +10 -10
- package/dist/thumbnail-grid.js +2 -2
- package/dist/transcript-scroll-nav.cjs +16 -12
- package/dist/transcript-scroll-nav.cjs.map +1 -1
- package/dist/transcript-scroll-nav.js +2 -1
- package/dist/transcript-scroll-nav.js.map +1 -1
- package/dist/value-prompts-dialog.js +5 -5
- package/dist/writing-field.cjs +16 -12
- package/dist/writing-field.cjs.map +1 -1
- package/dist/writing-field.js +21 -20
- package/dist/writing-field.js.map +1 -1
- package/package.json +12 -2
- package/dist/chunk-2WL2SGKL.js.map +0 -1
- package/dist/chunk-4PCLJAW2.js.map +0 -1
- /package/dist/{chunk-MVGMI6UZ.js.map → chunk-3MQMVPKO.js.map} +0 -0
- /package/dist/{chunk-TBDMTCRW.js.map → chunk-6YZMGSQY.js.map} +0 -0
- /package/dist/{chunk-OFJ5LGBU.js.map → chunk-7NEVJKDZ.js.map} +0 -0
- /package/dist/{chunk-XTNAKJSH.js.map → chunk-B3LDW3IQ.js.map} +0 -0
- /package/dist/{chunk-VTJWQPYR.js.map → chunk-BM2YYBUO.js.map} +0 -0
- /package/dist/{chunk-FTZCPGTH.js.map → chunk-CFCWQDGC.js.map} +0 -0
- /package/dist/{chunk-CN7C4KQB.js.map → chunk-CH2NWSES.js.map} +0 -0
- /package/dist/{chunk-CJCUD62M.js.map → chunk-CSSD6NS4.js.map} +0 -0
- /package/dist/{chunk-W3QSRJ3O.js.map → chunk-E4GS5QH7.js.map} +0 -0
- /package/dist/{chunk-O4KANICE.js.map → chunk-FRJ4PPA2.js.map} +0 -0
- /package/dist/{chunk-D45XDOJS.js.map → chunk-GHPUO3O7.js.map} +0 -0
- /package/dist/{chunk-RPUC5MNH.js.map → chunk-GLZJ7WZK.js.map} +0 -0
- /package/dist/{chunk-VKWQTSB6.js.map → chunk-HEFTQUJ5.js.map} +0 -0
- /package/dist/{chunk-KWBYKUKP.js.map → chunk-J6637L6D.js.map} +0 -0
- /package/dist/{chunk-5LT34PFX.js.map → chunk-MEJVHDYJ.js.map} +0 -0
- /package/dist/{chunk-PPB52S7F.js.map → chunk-MFUNGDHO.js.map} +0 -0
- /package/dist/{chunk-LCPHFONA.js.map → chunk-MIJMP4WI.js.map} +0 -0
- /package/dist/{chunk-XREKZXAL.js.map → chunk-SMJGESH7.js.map} +0 -0
- /package/dist/{chunk-SNHCBHBE.js.map → chunk-U24MOJWK.js.map} +0 -0
- /package/dist/{chunk-DO6G4EKJ.js.map → chunk-UWTODOMD.js.map} +0 -0
- /package/dist/{chunk-BQR4N24F.js.map → chunk-VLLUUOYJ.js.map} +0 -0
- /package/dist/{chunk-FD6V6JBN.js.map → chunk-VV6WZTH5.js.map} +0 -0
- /package/dist/{chunk-LVM7XZRJ.js.map → chunk-WQ2QCMMA.js.map} +0 -0
- /package/dist/{chunk-57OD2WTY.js.map → chunk-X6ZRHJQP.js.map} +0 -0
- /package/dist/{chunk-PLFWDUJW.js.map → chunk-XEXSZBXV.js.map} +0 -0
- /package/dist/{chunk-JSXNITMG.js.map → chunk-YC5GAO35.js.map} +0 -0
- /package/dist/{chunk-5TF2AFDM.js.map → chunk-ZCRPESQX.js.map} +0 -0
- /package/dist/{chunk-5IKQ6RU4.js.map → chunk-ZOQ2XKXF.js.map} +0 -0
|
@@ -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-
|
|
19
|
-
import "./chunk-
|
|
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";
|
package/dist/writing-field.cjs
CHANGED
|
@@ -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));
|