@usetheo/ui 0.13.1 → 0.13.2
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/dist/{chunk-REFY5MLN.js → chunk-2NTEJRPA.js} +5 -5
- package/dist/{chunk-REFY5MLN.js.map → chunk-2NTEJRPA.js.map} +1 -1
- package/dist/{chunk-2EUKYGH5.js → chunk-357XIC2N.js} +3 -3
- package/dist/chunk-357XIC2N.js.map +1 -0
- package/dist/{chunk-RPZMFGYI.js → chunk-3YOPTHZH.js} +3 -3
- package/dist/{chunk-RPZMFGYI.js.map → chunk-3YOPTHZH.js.map} +1 -1
- package/dist/{chunk-KFUFTZLS.js → chunk-44ZNZZUS.js} +3 -3
- package/dist/{chunk-KFUFTZLS.js.map → chunk-44ZNZZUS.js.map} +1 -1
- package/dist/{chunk-PJUP4BJD.js → chunk-47IPOYLQ.js} +3 -3
- package/dist/{chunk-PJUP4BJD.js.map → chunk-47IPOYLQ.js.map} +1 -1
- package/dist/{chunk-OJPPSJMF.js → chunk-4XYFJIRC.js} +3 -3
- package/dist/{chunk-OJPPSJMF.js.map → chunk-4XYFJIRC.js.map} +1 -1
- package/dist/{chunk-SOJW47EZ.js → chunk-5YX76GH6.js} +3 -3
- package/dist/{chunk-SOJW47EZ.js.map → chunk-5YX76GH6.js.map} +1 -1
- package/dist/{chunk-7T4NK6W6.js → chunk-65YSFZAN.js} +3 -3
- package/dist/{chunk-7T4NK6W6.js.map → chunk-65YSFZAN.js.map} +1 -1
- package/dist/{chunk-3ZXZGZOX.js → chunk-6ORS6XOE.js} +3 -3
- package/dist/{chunk-3ZXZGZOX.js.map → chunk-6ORS6XOE.js.map} +1 -1
- package/dist/{chunk-2A3E5Y72.js → chunk-6V2LQEPT.js} +3 -3
- package/dist/{chunk-2A3E5Y72.js.map → chunk-6V2LQEPT.js.map} +1 -1
- package/dist/{chunk-5XCTTXC3.js → chunk-ACZNFEOZ.js} +3 -3
- package/dist/{chunk-5XCTTXC3.js.map → chunk-ACZNFEOZ.js.map} +1 -1
- package/dist/{chunk-GLEOUWPN.js → chunk-AJ2LNQUQ.js} +3 -3
- package/dist/{chunk-GLEOUWPN.js.map → chunk-AJ2LNQUQ.js.map} +1 -1
- package/dist/{chunk-SBKVVVYY.js → chunk-AX6P3SDS.js} +3 -3
- package/dist/{chunk-SBKVVVYY.js.map → chunk-AX6P3SDS.js.map} +1 -1
- package/dist/{chunk-VB53UMAL.js → chunk-B42EOFRD.js} +3 -3
- package/dist/{chunk-VB53UMAL.js.map → chunk-B42EOFRD.js.map} +1 -1
- package/dist/{chunk-GIXHBTHH.js → chunk-CFVSXYVT.js} +3 -3
- package/dist/{chunk-GIXHBTHH.js.map → chunk-CFVSXYVT.js.map} +1 -1
- package/dist/{chunk-KDE3NYTI.js → chunk-CX54TUTT.js} +3 -3
- package/dist/{chunk-KDE3NYTI.js.map → chunk-CX54TUTT.js.map} +1 -1
- package/dist/{chunk-BP4RQSX7.js → chunk-DJK6H3FD.js} +3 -3
- package/dist/{chunk-BP4RQSX7.js.map → chunk-DJK6H3FD.js.map} +1 -1
- package/dist/{chunk-4SMYNLTA.js → chunk-EOTSD2GL.js} +3 -3
- package/dist/{chunk-4SMYNLTA.js.map → chunk-EOTSD2GL.js.map} +1 -1
- package/dist/{chunk-YUFFAWNB.js → chunk-FELH4AAQ.js} +3 -3
- package/dist/{chunk-YUFFAWNB.js.map → chunk-FELH4AAQ.js.map} +1 -1
- package/dist/{chunk-NEMXW2LB.js → chunk-FM72LBCJ.js} +3 -3
- package/dist/{chunk-NEMXW2LB.js.map → chunk-FM72LBCJ.js.map} +1 -1
- package/dist/{chunk-VHTAVROO.js → chunk-FNQASFTK.js} +3 -3
- package/dist/{chunk-VHTAVROO.js.map → chunk-FNQASFTK.js.map} +1 -1
- package/dist/{chunk-Q2BAL2PF.js → chunk-FOE3XXBJ.js} +3 -3
- package/dist/{chunk-Q2BAL2PF.js.map → chunk-FOE3XXBJ.js.map} +1 -1
- package/dist/{chunk-7BGCWJQR.js → chunk-HKVOCYTN.js} +3 -3
- package/dist/{chunk-7BGCWJQR.js.map → chunk-HKVOCYTN.js.map} +1 -1
- package/dist/{chunk-JFKBFQA5.js → chunk-HNRFBJ25.js} +3 -3
- package/dist/{chunk-JFKBFQA5.js.map → chunk-HNRFBJ25.js.map} +1 -1
- package/dist/{chunk-QCQTTOMD.js → chunk-II5Q5RIO.js} +3 -3
- package/dist/{chunk-QCQTTOMD.js.map → chunk-II5Q5RIO.js.map} +1 -1
- package/dist/{chunk-QRXIYPWP.js → chunk-ITEIRMSH.js} +3 -3
- package/dist/{chunk-QRXIYPWP.js.map → chunk-ITEIRMSH.js.map} +1 -1
- package/dist/{chunk-JQTCCKZA.js → chunk-JP3SHERK.js} +3 -3
- package/dist/{chunk-JQTCCKZA.js.map → chunk-JP3SHERK.js.map} +1 -1
- package/dist/{chunk-VBEMLZGX.js → chunk-JS5T2CRO.js} +3 -3
- package/dist/{chunk-VBEMLZGX.js.map → chunk-JS5T2CRO.js.map} +1 -1
- package/dist/{chunk-VBQFE5RV.js → chunk-KXZH7BTX.js} +3 -3
- package/dist/{chunk-VBQFE5RV.js.map → chunk-KXZH7BTX.js.map} +1 -1
- package/dist/{chunk-MXB2GVEQ.js → chunk-LB4PMLCX.js} +3 -3
- package/dist/{chunk-MXB2GVEQ.js.map → chunk-LB4PMLCX.js.map} +1 -1
- package/dist/{chunk-CED2LKHI.js → chunk-LMGE2QEO.js} +3 -3
- package/dist/{chunk-CED2LKHI.js.map → chunk-LMGE2QEO.js.map} +1 -1
- package/dist/{chunk-PVCW4O37.js → chunk-MLEPCMTF.js} +3 -3
- package/dist/{chunk-PVCW4O37.js.map → chunk-MLEPCMTF.js.map} +1 -1
- package/dist/{chunk-H5QPJNVD.js → chunk-NSZEZTDO.js} +3 -3
- package/dist/{chunk-H5QPJNVD.js.map → chunk-NSZEZTDO.js.map} +1 -1
- package/dist/{chunk-AENNHS3S.js → chunk-QBSJM4XI.js} +3 -3
- package/dist/{chunk-AENNHS3S.js.map → chunk-QBSJM4XI.js.map} +1 -1
- package/dist/{chunk-XJA4B3F5.js → chunk-QCSMJTA6.js} +3 -3
- package/dist/{chunk-XJA4B3F5.js.map → chunk-QCSMJTA6.js.map} +1 -1
- package/dist/{chunk-G2WCT6PJ.js → chunk-QTG266XU.js} +3 -3
- package/dist/{chunk-G2WCT6PJ.js.map → chunk-QTG266XU.js.map} +1 -1
- package/dist/{chunk-RLWULF5B.js → chunk-RMJYXHBX.js} +3 -3
- package/dist/{chunk-RLWULF5B.js.map → chunk-RMJYXHBX.js.map} +1 -1
- package/dist/{chunk-P44UAK45.js → chunk-SPGNNN4R.js} +3 -3
- package/dist/{chunk-P44UAK45.js.map → chunk-SPGNNN4R.js.map} +1 -1
- package/dist/{chunk-CSEGVTKO.js → chunk-T4Z7HBZR.js} +3 -3
- package/dist/{chunk-CSEGVTKO.js.map → chunk-T4Z7HBZR.js.map} +1 -1
- package/dist/{chunk-PZGUZHI7.js → chunk-TW5I37AE.js} +3 -3
- package/dist/{chunk-PZGUZHI7.js.map → chunk-TW5I37AE.js.map} +1 -1
- package/dist/{chunk-AXNJFBYX.js → chunk-UJAWV6LM.js} +3 -3
- package/dist/{chunk-AXNJFBYX.js.map → chunk-UJAWV6LM.js.map} +1 -1
- package/dist/{chunk-4DTLUBRW.js → chunk-V2WCZBVE.js} +4 -4
- package/dist/{chunk-4DTLUBRW.js.map → chunk-V2WCZBVE.js.map} +1 -1
- package/dist/{chunk-YES6SPDT.js → chunk-V4LRBYOD.js} +3 -3
- package/dist/{chunk-YES6SPDT.js.map → chunk-V4LRBYOD.js.map} +1 -1
- package/dist/{chunk-4UBFLXS3.js → chunk-VFRFUU7A.js} +3 -3
- package/dist/{chunk-4UBFLXS3.js.map → chunk-VFRFUU7A.js.map} +1 -1
- package/dist/{chunk-BWIDDAR7.js → chunk-VLNFUEOR.js} +3 -3
- package/dist/{chunk-BWIDDAR7.js.map → chunk-VLNFUEOR.js.map} +1 -1
- package/dist/{chunk-ZJXOHLQE.js → chunk-VU7XKD4G.js} +3 -3
- package/dist/{chunk-ZJXOHLQE.js.map → chunk-VU7XKD4G.js.map} +1 -1
- package/dist/{chunk-V3HFDVZ3.js → chunk-W24RR5OD.js} +3 -3
- package/dist/{chunk-V3HFDVZ3.js.map → chunk-W24RR5OD.js.map} +1 -1
- package/dist/{chunk-A3OU6ICP.js → chunk-W743ORLA.js} +3 -3
- package/dist/{chunk-A3OU6ICP.js.map → chunk-W743ORLA.js.map} +1 -1
- package/dist/{chunk-TJLULCZW.js → chunk-WQVEJJV7.js} +3 -3
- package/dist/{chunk-TJLULCZW.js.map → chunk-WQVEJJV7.js.map} +1 -1
- package/dist/{chunk-ZAMPCRFJ.js → chunk-WX4Q4DTX.js} +3 -3
- package/dist/{chunk-ZAMPCRFJ.js.map → chunk-WX4Q4DTX.js.map} +1 -1
- package/dist/{chunk-U3AEEFVB.js → chunk-Y7JTBQUQ.js} +3 -3
- package/dist/{chunk-U3AEEFVB.js.map → chunk-Y7JTBQUQ.js.map} +1 -1
- package/dist/{chunk-K72DJOXR.js → chunk-ZAP4RIUL.js} +3 -3
- package/dist/{chunk-K72DJOXR.js.map → chunk-ZAP4RIUL.js.map} +1 -1
- package/dist/{chunk-BPJ3RN3U.js → chunk-ZEDDWVBB.js} +4 -4
- package/dist/{chunk-BPJ3RN3U.js.map → chunk-ZEDDWVBB.js.map} +1 -1
- package/dist/composites/agent-composer/index.js +2 -2
- package/dist/composites/agent-stream/index.js +8 -8
- package/dist/composites/agent-tool-renderer/index.js +5 -5
- package/dist/composites/approval-card/index.js +1 -1
- package/dist/composites/chat-composer/index.js +1 -1
- package/dist/composites/chat-message/index.js +6 -6
- package/dist/composites/choice-prompt/index.js +1 -1
- package/dist/composites/command-palette/index.js +2 -2
- package/dist/composites/confirm-dialog/index.js +2 -2
- package/dist/composites/confirm-prompt/index.js +1 -1
- package/dist/composites/cron-jobs-list/index.js +2 -2
- package/dist/composites/data-table/index.js +2 -2
- package/dist/composites/domain-config/index.js +1 -1
- package/dist/composites/env-var-editor/index.js +1 -1
- package/dist/composites/mcp-server-list/index.js +2 -2
- package/dist/composites/metric-card/index.js +2 -2
- package/dist/composites/multi-select-prompt/index.js +1 -1
- package/dist/composites/page-shell/index.js +3 -3
- package/dist/composites/permission-modal/index.js +2 -2
- package/dist/composites/preview-env-card/index.js +1 -1
- package/dist/composites/preview-panel/index.js +1 -1
- package/dist/composites/project-card/index.js +1 -1
- package/dist/composites/rollback-ui/index.js +1 -1
- package/dist/composites/skills-list/index.js +2 -2
- package/dist/composites/text-prompt/index.js +1 -1
- package/dist/index.js +53 -53
- package/dist/primitives/artifact-preview/index.js +1 -1
- package/dist/primitives/build-log-stream/index.js +1 -1
- package/dist/primitives/card/index.js +1 -1
- package/dist/primitives/channel-card/index.js +1 -1
- package/dist/primitives/cost-meter/index.js +1 -1
- package/dist/primitives/cron-job-card/index.js +1 -1
- package/dist/primitives/dialog/index.js +1 -1
- package/dist/primitives/diff-viewer/index.js +1 -1
- package/dist/primitives/empty-state/index.js +1 -1
- package/dist/primitives/folder-context-card/index.js +1 -1
- package/dist/primitives/hook-config/index.js +1 -1
- package/dist/primitives/hook-event-log/index.js +1 -1
- package/dist/primitives/mcp-server-card/index.js +1 -1
- package/dist/primitives/memory-editor/index.js +1 -1
- package/dist/primitives/metrics-panel/index.js +1 -1
- package/dist/primitives/model-card/index.js +1 -1
- package/dist/primitives/permission-matrix/index.js +1 -1
- package/dist/primitives/pin-input/index.js +1 -1
- package/dist/primitives/progress-checklist/index.js +1 -1
- package/dist/primitives/recent-folders-list/index.js +1 -1
- package/dist/primitives/running-tasks-panel/index.js +1 -1
- package/dist/primitives/session-timeline/index.js +1 -1
- package/dist/primitives/skill-card/index.js +1 -1
- package/dist/primitives/system-prompt-editor/index.js +1 -1
- package/dist/primitives/task-plan/index.js +1 -1
- package/dist/primitives/terminal-panel/index.js +1 -1
- package/dist/primitives/token-usage-chart/index.js +1 -1
- package/dist/primitives/tools-list/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2EUKYGH5.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/terminal-panel/terminal-panel.tsx"],"names":["TerminalIcon"],"mappings":";;;;;;AA8BA,IAAM,SAAA,GAA+D;AAAA,EACnE,OAAA,EAAS,iBAAA;AAAA,EACT,MAAA,EAAQ,uBAAA;AAAA,EACR,MAAA,EAAQ,kBAAA;AAAA,EACR,EAAA,EAAI,cAAA;AAAA,EACJ,MAAA,EAAQ;AACV,CAAA;AASA,IAAM,aAAA,GAAgB,UAAA;AAAA,EACpB,CAAC,EAAE,SAAA,EAAW,KAAA,GAAQ,UAAA,EAAY,KAAA,EAAO,YAAA,GAAe,GAAA,EAAK,IAAA,GAAO,KAAA,EAAO,GAAG,KAAA,IAAS,GAAA,KAAQ;AAE7F,IAAA,MAAM,eAAe,eAAA,EAAgB;AACrC,IAAA,MAAM,aAAA,GAAgB,eAAe,KAAA,GAAQ,IAAA;AAC7C,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,gBAAA;AAAA,QACV,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/terminal-panel/terminal-panel.tsx"],"names":["TerminalIcon"],"mappings":";;;;;;AA8BA,IAAM,SAAA,GAA+D;AAAA,EACnE,OAAA,EAAS,iBAAA;AAAA,EACT,MAAA,EAAQ,uBAAA;AAAA,EACR,MAAA,EAAQ,kBAAA;AAAA,EACR,EAAA,EAAI,cAAA;AAAA,EACJ,MAAA,EAAQ;AACV,CAAA;AASA,IAAM,aAAA,GAAgB,UAAA;AAAA,EACpB,CAAC,EAAE,SAAA,EAAW,KAAA,GAAQ,UAAA,EAAY,KAAA,EAAO,YAAA,GAAe,GAAA,EAAK,IAAA,GAAO,KAAA,EAAO,GAAG,KAAA,IAAS,GAAA,KAAQ;AAE7F,IAAA,MAAM,eAAe,eAAA,EAAgB;AACrC,IAAA,MAAM,aAAA,GAAgB,eAAe,KAAA,GAAQ,IAAA;AAC7C,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,gBAAA;AAAA,QACV,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,yDAAA,EAA2D,SAAS,CAAA;AAAA,QACjF,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,QAAA,EAAA,EAAO,WAAU,6DAAA,EAChB,QAAA,EAAA;AAAA,4BAAA,GAAA,CAACA,QAAA,EAAA,EAAa,SAAA,EAAU,gCAAA,EAAiC,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,4BAC5E,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0EAAA,EACb,QAAA,EAAA,KAAA,EACH;AAAA,WAAA,EACF,CAAA;AAAA,0BACA,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,+CAAA;AAAA,cACV,WAAA,EAAW,aAAA;AAAA,cACX,aAAA,EAAY,OAAA;AAAA,cAEX,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AACnB,gBAAA,MAAM,IAAA,GAAO,KAAK,IAAA,IAAQ,QAAA;AAC1B,gBAAA,uBACE,GAAA,CAAC,IAAA,EAAA,EAAiB,SAAA,EAAW,EAAA,CAAG,qBAAA,EAAuB,SAAA,CAAU,IAAI,CAAC,CAAA,EACnE,QAAA,EAAA,IAAA,KAAS,SAAA,mBACR,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,kCAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,0BAAA,EAA4B,QAAA,EAAA;AAAA,oBAAA,YAAA;AAAA,oBAAa;AAAA,mBAAA,EAAC,CAAA;AAAA,kBACzD,IAAA,CAAK;AAAA,iBAAA,EACR,CAAA,GACE,IAAA,KAAS,QAAA,mBACX,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2BAAA,EAA6B,QAAA,EAAA,IAAA,CAAK,OAAA,EAAQ,CAAA,GAE1D,IAAA,CAAK,OAAA,EAAA,EATA,KAAK,EAWd,CAAA;AAAA,cAEJ,CAAC;AAAA;AAAA;AACH;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AACA,aAAA,CAAc,WAAA,GAAc,eAAA","file":"chunk-6ORS6XOE.js","sourcesContent":["import { Terminal as TerminalIcon } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { useInLiveRegion } from \"../../../lib/live-region-context.js\";\n\nexport interface TerminalLine {\n id: string;\n /**\n * Visual kind: command (prompted), stdout, stderr, ok (success), prompt (active line).\n */\n kind?: \"command\" | \"stdout\" | \"stderr\" | \"ok\" | \"prompt\";\n content: ReactNode;\n}\n\ninterface TerminalPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n title?: ReactNode;\n lines: TerminalLine[];\n /**\n * Optional prompt prefix for commands, defaults to \"$\".\n */\n promptPrefix?: string;\n /**\n * Live-region politeness for screen readers. Use `\"polite\"` when streaming\n * fresh output so assistive tech announces new lines without interrupting.\n * Default `\"off\"` for static / historical views.\n */\n live?: \"off\" | \"polite\";\n}\n\nconst kindColor: Record<NonNullable<TerminalLine[\"kind\"]>, string> = {\n command: \"text-foreground\",\n stdout: \"text-muted-foreground\",\n stderr: \"text-destructive\",\n ok: \"text-success\",\n prompt: \"text-primary\",\n};\n\n/**\n * TerminalPanel — minimal terminal output viewer.\n *\n * Visual: dark card with mono font, \"$ \" prefix on command lines, color-coded\n * stdout/stderr/success. No interactivity (read-only) — pair with your own\n * pty/xterm for live shells if needed.\n */\nconst TerminalPanel = forwardRef<HTMLDivElement, TerminalPanelProps>(\n ({ className, title = \"Terminal\", lines, promptPrefix = \"$\", live = \"off\", ...props }, ref) => {\n // T4.1 (MF-4): suppress own aria-live when nested in container live region.\n const inLiveRegion = useInLiveRegion();\n const effectiveLive = inLiveRegion ? \"off\" : live;\n return (\n <div\n data-slot=\"terminal-panel\"\n ref={ref}\n className={cn(\"overflow-hidden rounded-xl border border-border bg-card\", className)}\n {...props}\n >\n <header className=\"flex items-center gap-2 border-border/40 border-b px-3 py-2\">\n <TerminalIcon className=\"size-3.5 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"font-sans text-label-caps text-muted-foreground uppercase tracking-wider\">\n {title}\n </span>\n </header>\n <ol\n className=\"grid gap-0.5 px-3 py-2 font-mono text-code-sm\"\n aria-live={effectiveLive}\n aria-atomic=\"false\"\n >\n {lines.map((line) => {\n const kind = line.kind ?? \"stdout\";\n return (\n <li key={line.id} className={cn(\"whitespace-pre-wrap\", kindColor[kind])}>\n {kind === \"command\" ? (\n <>\n <span className=\"select-none text-primary\">{promptPrefix} </span>\n {line.content}\n </>\n ) : kind === \"prompt\" ? (\n <span className=\"motion-safe:animate-pulse\">{line.content}</span>\n ) : (\n line.content\n )}\n </li>\n );\n })}\n </ol>\n </div>\n );\n },\n);\nTerminalPanel.displayName = \"TerminalPanel\";\n\nexport { TerminalPanel };\n"]}
|
|
@@ -39,7 +39,7 @@ var PermissionMatrix = forwardRef(
|
|
|
39
39
|
{
|
|
40
40
|
"data-slot": "permission-matrix",
|
|
41
41
|
ref,
|
|
42
|
-
className: cn("rounded-xl border bg-card", className),
|
|
42
|
+
className: cn("rounded-xl border border-border bg-card", className),
|
|
43
43
|
...props,
|
|
44
44
|
children: [
|
|
45
45
|
title ? /* @__PURE__ */ jsxs("header", { className: "flex items-baseline justify-between border-border/40 border-b px-4 py-3", children: [
|
|
@@ -161,5 +161,5 @@ var PermissionMatrix = forwardRef(
|
|
|
161
161
|
PermissionMatrix.displayName = "PermissionMatrix";
|
|
162
162
|
|
|
163
163
|
export { PermissionMatrix };
|
|
164
|
-
//# sourceMappingURL=chunk-
|
|
165
|
-
//# sourceMappingURL=chunk-
|
|
164
|
+
//# sourceMappingURL=chunk-6V2LQEPT.js.map
|
|
165
|
+
//# sourceMappingURL=chunk-6V2LQEPT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/permission-matrix/permission-matrix.tsx"],"names":[],"mappings":"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","file":"chunk-2A3E5Y72.js","sourcesContent":["\"use client\";\n\nimport { Check, Lock, Plus, ShieldQuestion, Trash2 } from \"lucide-react\";\nimport { forwardRef, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\nexport type PermissionDecisionKind = \"allow\" | \"ask\" | \"deny\";\n\nexport interface PermissionRule {\n id: string;\n /** Tool the rule applies to. Use \"*\" for any. */\n tool: string;\n /** Glob path it applies to. Use \"*\" for any. */\n path: string;\n decision: PermissionDecisionKind;\n /** Optional rationale shown as helper text. */\n note?: string;\n}\n\ninterface PermissionMatrixProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n rules: PermissionRule[];\n title?: ReactNode;\n /**\n * Available tools shown in the add form. Pass `undefined` (or omit) — or an\n * empty array — to hide the add form entirely. The form only renders when\n * `onAdd` is provided AND `toolOptions` has at least one entry.\n */\n toolOptions?: string[];\n onAdd?: (rule: Omit<PermissionRule, \"id\">) => void;\n onRemove?: (id: string) => void;\n onDecisionChange?: (id: string, decision: PermissionDecisionKind) => void;\n}\n\nconst DECISION_CLASS: Record<PermissionDecisionKind, string> = {\n allow: \"bg-success/15 text-success border-success/40\",\n ask: \"bg-warning/15 text-warning border-warning/40\",\n deny: \"bg-destructive/15 text-destructive border-destructive/40\",\n};\n\nconst DECISION_ICON: Record<PermissionDecisionKind, ReactNode> = {\n allow: <Check className=\"size-3\" aria-hidden=\"true\" />,\n ask: <ShieldQuestion className=\"size-3\" aria-hidden=\"true\" />,\n deny: <Lock className=\"size-3\" aria-hidden=\"true\" />,\n};\n\nconst cycle = (cur: PermissionDecisionKind): PermissionDecisionKind =>\n cur === \"allow\" ? \"ask\" : cur === \"ask\" ? \"deny\" : \"allow\";\n\n/**\n * PermissionMatrix — tool × path × decision grid for fine-grained access\n * control. Used as the \"permissions\" tab in the agent settings.\n *\n * One PermissionRule per row. Click the decision pill to cycle Allow → Ask → Deny.\n *\n * Design decision (2026-05-14): PermissionMatrix stays in `primitives/`\n * — not `composites/` — even though it renders inputs and a select. The native\n * `<input>` / `<select>` elements use Theo design tokens directly (border-input,\n * ring, font-mono) so visual parity with `Input` / `Select` primitives is\n * preserved. Reason for keeping it primitive: a consumer installing\n * `permission-matrix` from the registry gets a single self-contained file with\n * no transitive Theo dependencies — opposite trade-off from `EnvVarEditor`\n * which is intentionally a composite. Both shapes are valid; we ship one of\n * each so consumers can pick the dependency profile that fits their app.\n */\nconst PermissionMatrix = forwardRef<HTMLDivElement, PermissionMatrixProps>(\n (\n {\n className,\n rules,\n title = \"Permissions\",\n toolOptions,\n onAdd,\n onRemove,\n onDecisionChange,\n ...props\n },\n ref,\n ) => {\n const [newTool, setNewTool] = useState(toolOptions?.[0] ?? \"*\");\n const [newPath, setNewPath] = useState(\"\");\n const [newDecision, setNewDecision] = useState<PermissionDecisionKind>(\"ask\");\n\n const submit = () => {\n if (!newPath.trim()) return;\n onAdd?.({ tool: newTool, path: newPath.trim(), decision: newDecision });\n setNewPath(\"\");\n };\n\n return (\n <section\n data-slot=\"permission-matrix\"\n ref={ref}\n className={cn(\"rounded-xl border bg-card\", className)}\n {...props}\n >\n {title ? (\n <header className=\"flex items-baseline justify-between border-border/40 border-b px-4 py-3\">\n <h3 className=\"font-display text-title-md tracking-tight\">{title}</h3>\n <span className=\"font-mono text-label text-muted-foreground\">\n {rules.length} {rules.length === 1 ? \"rule\" : \"rules\"}\n </span>\n </header>\n ) : null}\n\n {onAdd && toolOptions && toolOptions.length > 0 ? (\n <form\n className=\"grid grid-cols-[1fr_2fr_auto_auto] gap-2 border-border/40 border-b p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n submit();\n }}\n >\n <select\n value={newTool}\n onChange={(e) => setNewTool(e.target.value)}\n aria-label=\"Tool\"\n className=\"h-9 rounded-md border border-input bg-card px-2 font-mono text-code-sm\"\n >\n <option value=\"*\">* (any tool)</option>\n {toolOptions.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <input\n type=\"text\"\n value={newPath}\n onChange={(e) => setNewPath(e.target.value)}\n placeholder=\"path glob (e.g. src/**/*.ts)\"\n aria-label=\"Path\"\n className=\"h-9 rounded-md border border-input bg-card px-2 font-mono text-code-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <select\n value={newDecision}\n onChange={(e) => setNewDecision(e.target.value as PermissionDecisionKind)}\n aria-label=\"Decision\"\n className=\"h-9 rounded-md border border-input bg-card px-2 font-mono text-code-sm uppercase\"\n >\n <option value=\"allow\">allow</option>\n <option value=\"ask\">ask</option>\n <option value=\"deny\">deny</option>\n </select>\n <button\n type=\"submit\"\n className=\"inline-flex h-9 items-center gap-1 rounded-md bg-primary px-3 font-sans text-label text-primary-foreground hover:shadow-glow focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <Plus className=\"size-3.5\" /> Add\n </button>\n </form>\n ) : null}\n\n <ul className=\"divide-y divide-border/30\">\n {rules.map((rule) => (\n <li\n key={rule.id}\n className=\"grid grid-cols-[1fr_2fr_auto_auto] items-center gap-3 px-4 py-2.5\"\n >\n <span className=\"truncate font-mono text-code-sm text-foreground\">{rule.tool}</span>\n <span className=\"truncate font-mono text-code-sm text-muted-foreground\">\n {rule.path}\n </span>\n <button\n type=\"button\"\n onClick={() => onDecisionChange?.(rule.id, cycle(rule.decision))}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1\",\n \"font-mono text-label uppercase tracking-wider transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n DECISION_CLASS[rule.decision],\n !onDecisionChange && \"pointer-events-none\",\n )}\n >\n {DECISION_ICON[rule.decision]}\n {rule.decision}\n </button>\n {onRemove ? (\n <button\n type=\"button\"\n onClick={() => onRemove(rule.id)}\n aria-label={`Remove rule ${rule.tool} ${rule.path}`}\n className=\"rounded-md p-1.5 text-muted-foreground hover:bg-muted hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <Trash2 className=\"size-3.5\" />\n </button>\n ) : null}\n </li>\n ))}\n {rules.length === 0 ? (\n <li className=\"px-4 py-8 text-center font-sans text-body-sm text-muted-foreground\">\n No permission rules configured. The agent will fall back to default policy.\n </li>\n ) : null}\n </ul>\n </section>\n );\n },\n);\nPermissionMatrix.displayName = \"PermissionMatrix\";\n\nexport { PermissionMatrix };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/permission-matrix/permission-matrix.tsx"],"names":[],"mappings":"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","file":"chunk-6V2LQEPT.js","sourcesContent":["\"use client\";\n\nimport { Check, Lock, Plus, ShieldQuestion, Trash2 } from \"lucide-react\";\nimport { forwardRef, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\nexport type PermissionDecisionKind = \"allow\" | \"ask\" | \"deny\";\n\nexport interface PermissionRule {\n id: string;\n /** Tool the rule applies to. Use \"*\" for any. */\n tool: string;\n /** Glob path it applies to. Use \"*\" for any. */\n path: string;\n decision: PermissionDecisionKind;\n /** Optional rationale shown as helper text. */\n note?: string;\n}\n\ninterface PermissionMatrixProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n rules: PermissionRule[];\n title?: ReactNode;\n /**\n * Available tools shown in the add form. Pass `undefined` (or omit) — or an\n * empty array — to hide the add form entirely. The form only renders when\n * `onAdd` is provided AND `toolOptions` has at least one entry.\n */\n toolOptions?: string[];\n onAdd?: (rule: Omit<PermissionRule, \"id\">) => void;\n onRemove?: (id: string) => void;\n onDecisionChange?: (id: string, decision: PermissionDecisionKind) => void;\n}\n\nconst DECISION_CLASS: Record<PermissionDecisionKind, string> = {\n allow: \"bg-success/15 text-success border-success/40\",\n ask: \"bg-warning/15 text-warning border-warning/40\",\n deny: \"bg-destructive/15 text-destructive border-destructive/40\",\n};\n\nconst DECISION_ICON: Record<PermissionDecisionKind, ReactNode> = {\n allow: <Check className=\"size-3\" aria-hidden=\"true\" />,\n ask: <ShieldQuestion className=\"size-3\" aria-hidden=\"true\" />,\n deny: <Lock className=\"size-3\" aria-hidden=\"true\" />,\n};\n\nconst cycle = (cur: PermissionDecisionKind): PermissionDecisionKind =>\n cur === \"allow\" ? \"ask\" : cur === \"ask\" ? \"deny\" : \"allow\";\n\n/**\n * PermissionMatrix — tool × path × decision grid for fine-grained access\n * control. Used as the \"permissions\" tab in the agent settings.\n *\n * One PermissionRule per row. Click the decision pill to cycle Allow → Ask → Deny.\n *\n * Design decision (2026-05-14): PermissionMatrix stays in `primitives/`\n * — not `composites/` — even though it renders inputs and a select. The native\n * `<input>` / `<select>` elements use Theo design tokens directly (border-input,\n * ring, font-mono) so visual parity with `Input` / `Select` primitives is\n * preserved. Reason for keeping it primitive: a consumer installing\n * `permission-matrix` from the registry gets a single self-contained file with\n * no transitive Theo dependencies — opposite trade-off from `EnvVarEditor`\n * which is intentionally a composite. Both shapes are valid; we ship one of\n * each so consumers can pick the dependency profile that fits their app.\n */\nconst PermissionMatrix = forwardRef<HTMLDivElement, PermissionMatrixProps>(\n (\n {\n className,\n rules,\n title = \"Permissions\",\n toolOptions,\n onAdd,\n onRemove,\n onDecisionChange,\n ...props\n },\n ref,\n ) => {\n const [newTool, setNewTool] = useState(toolOptions?.[0] ?? \"*\");\n const [newPath, setNewPath] = useState(\"\");\n const [newDecision, setNewDecision] = useState<PermissionDecisionKind>(\"ask\");\n\n const submit = () => {\n if (!newPath.trim()) return;\n onAdd?.({ tool: newTool, path: newPath.trim(), decision: newDecision });\n setNewPath(\"\");\n };\n\n return (\n <section\n data-slot=\"permission-matrix\"\n ref={ref}\n className={cn(\"rounded-xl border border-border bg-card\", className)}\n {...props}\n >\n {title ? (\n <header className=\"flex items-baseline justify-between border-border/40 border-b px-4 py-3\">\n <h3 className=\"font-display text-title-md tracking-tight\">{title}</h3>\n <span className=\"font-mono text-label text-muted-foreground\">\n {rules.length} {rules.length === 1 ? \"rule\" : \"rules\"}\n </span>\n </header>\n ) : null}\n\n {onAdd && toolOptions && toolOptions.length > 0 ? (\n <form\n className=\"grid grid-cols-[1fr_2fr_auto_auto] gap-2 border-border/40 border-b p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n submit();\n }}\n >\n <select\n value={newTool}\n onChange={(e) => setNewTool(e.target.value)}\n aria-label=\"Tool\"\n className=\"h-9 rounded-md border border-input bg-card px-2 font-mono text-code-sm\"\n >\n <option value=\"*\">* (any tool)</option>\n {toolOptions.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <input\n type=\"text\"\n value={newPath}\n onChange={(e) => setNewPath(e.target.value)}\n placeholder=\"path glob (e.g. src/**/*.ts)\"\n aria-label=\"Path\"\n className=\"h-9 rounded-md border border-input bg-card px-2 font-mono text-code-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <select\n value={newDecision}\n onChange={(e) => setNewDecision(e.target.value as PermissionDecisionKind)}\n aria-label=\"Decision\"\n className=\"h-9 rounded-md border border-input bg-card px-2 font-mono text-code-sm uppercase\"\n >\n <option value=\"allow\">allow</option>\n <option value=\"ask\">ask</option>\n <option value=\"deny\">deny</option>\n </select>\n <button\n type=\"submit\"\n className=\"inline-flex h-9 items-center gap-1 rounded-md bg-primary px-3 font-sans text-label text-primary-foreground hover:shadow-glow focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <Plus className=\"size-3.5\" /> Add\n </button>\n </form>\n ) : null}\n\n <ul className=\"divide-y divide-border/30\">\n {rules.map((rule) => (\n <li\n key={rule.id}\n className=\"grid grid-cols-[1fr_2fr_auto_auto] items-center gap-3 px-4 py-2.5\"\n >\n <span className=\"truncate font-mono text-code-sm text-foreground\">{rule.tool}</span>\n <span className=\"truncate font-mono text-code-sm text-muted-foreground\">\n {rule.path}\n </span>\n <button\n type=\"button\"\n onClick={() => onDecisionChange?.(rule.id, cycle(rule.decision))}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1\",\n \"font-mono text-label uppercase tracking-wider transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n DECISION_CLASS[rule.decision],\n !onDecisionChange && \"pointer-events-none\",\n )}\n >\n {DECISION_ICON[rule.decision]}\n {rule.decision}\n </button>\n {onRemove ? (\n <button\n type=\"button\"\n onClick={() => onRemove(rule.id)}\n aria-label={`Remove rule ${rule.tool} ${rule.path}`}\n className=\"rounded-md p-1.5 text-muted-foreground hover:bg-muted hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <Trash2 className=\"size-3.5\" />\n </button>\n ) : null}\n </li>\n ))}\n {rules.length === 0 ? (\n <li className=\"px-4 py-8 text-center font-sans text-body-sm text-muted-foreground\">\n No permission rules configured. The agent will fall back to default policy.\n </li>\n ) : null}\n </ul>\n </section>\n );\n },\n);\nPermissionMatrix.displayName = \"PermissionMatrix\";\n\nexport { PermissionMatrix };\n"]}
|
|
@@ -75,7 +75,7 @@ var ChoicePrompt = forwardRef(
|
|
|
75
75
|
"aria-labelledby": questionId,
|
|
76
76
|
onKeyDown: handleKeyDown,
|
|
77
77
|
className: cn(
|
|
78
|
-
"grid w-full gap-4 rounded-xl border bg-card p-5 text-card-foreground shadow-md",
|
|
78
|
+
"grid w-full gap-4 rounded-xl border border-border bg-card p-5 text-card-foreground shadow-md",
|
|
79
79
|
"transition-shadow duration-base ease-out-soft",
|
|
80
80
|
className
|
|
81
81
|
),
|
|
@@ -176,5 +176,5 @@ var ChoicePrompt = forwardRef(
|
|
|
176
176
|
ChoicePrompt.displayName = "ChoicePrompt";
|
|
177
177
|
|
|
178
178
|
export { ChoicePrompt };
|
|
179
|
-
//# sourceMappingURL=chunk-
|
|
180
|
-
//# sourceMappingURL=chunk-
|
|
179
|
+
//# sourceMappingURL=chunk-ACZNFEOZ.js.map
|
|
180
|
+
//# sourceMappingURL=chunk-ACZNFEOZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/choice-prompt/choice-prompt.tsx"],"names":[],"mappings":"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","file":"chunk-5XCTTXC3.js","sourcesContent":["\"use client\";\n\nimport { forwardRef, useId, useState } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport {\n OTHER_OPTION_VALUE,\n type PromptOption,\n digitKeyToIndex,\n isOtherValue,\n} from \"../../../lib/prompt.js\";\nimport { Badge } from \"../../primitives/badge/index.js\";\nimport { Button } from \"../../primitives/button/index.js\";\nimport { Input } from \"../../primitives/input/index.js\";\nimport { Label } from \"../../primitives/label/index.js\";\nimport { RadioGroup } from \"../../primitives/radio-group/index.js\";\n\n/**\n * ChoicePrompt — single-select \"ask the user\" card for agent surfaces.\n *\n * Mirrors the UX of Claude Code's question card: a question with an optional\n * header chip, a list of options each carrying a label + description, optional\n * number-key shortcuts (terminal-style `1`..`9` selection), an injectable\n * free-text \"Other\" option, and a side-by-side preview pane when options carry\n * preview content.\n *\n * Renders one question at a time — sequencing across multiple questions is the\n * consumer's responsibility (there is no built-in flow orchestrator).\n *\n * Controlled or uncontrolled: pass `value` + `onValueChange` to control the\n * selection, or `defaultValue` to let the component own it. Same for the Other\n * text via `otherText` / `onOtherTextChange`.\n */\n\n/** Payload handed to `onConfirm`. */\nexport interface ChoicePromptResult {\n /** The selected option value (or the reserved Other value). */\n value: string;\n /** Present only when the selected value is the synthesized Other option. */\n otherText?: string;\n}\n\nexport interface ChoicePromptProps extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\"> {\n /** The question being asked. */\n question: ReactNode;\n /** Optional secondary line under the question. */\n description?: ReactNode;\n /** Optional short header chip (rendered as a Badge), e.g. \"Deploy\". */\n badge?: ReactNode;\n /** The selectable options. */\n options: PromptOption[];\n /** Controlled selected value. */\n value?: string;\n /** Initial selected value when uncontrolled. */\n defaultValue?: string;\n /** Fired with the option value whenever the selection changes. */\n onValueChange?: (value: string) => void;\n /** Inject a free-text \"Other\" option as the last row. */\n allowOther?: boolean;\n /** Label for the Other row. Defaults to \"Other\". */\n otherLabel?: ReactNode;\n /** Placeholder for the Other text field. */\n otherPlaceholder?: string;\n /** Controlled Other text. */\n otherText?: string;\n /** Fired with the Other text on every keystroke. */\n onOtherTextChange?: (text: string) => void;\n /** Enable `1`..`9` number-key selection. Default true. */\n enableKeyboardShortcuts?: boolean;\n /** Show the `1`..`9` hint chips next to options. Defaults to the shortcut flag. */\n showNumbers?: boolean;\n /** Confirm button label. Defaults to \"Confirm\". Omit `onConfirm` to hide it. */\n confirmLabel?: ReactNode;\n /** Cancel button label. Defaults to \"Cancel\". Omit `onCancel` to hide it. */\n cancelLabel?: ReactNode;\n /** Pressing Confirm. Receives the selection (and Other text when relevant). */\n onConfirm?: (result: ChoicePromptResult) => void;\n /** Pressing Cancel. */\n onCancel?: () => void;\n}\n\nconst ChoicePrompt = forwardRef<HTMLElement, ChoicePromptProps>(\n (\n {\n className,\n question,\n description,\n badge,\n options,\n value,\n defaultValue,\n onValueChange,\n allowOther = false,\n otherLabel = \"Other\",\n otherPlaceholder = \"Type your answer…\",\n otherText,\n onOtherTextChange,\n enableKeyboardShortcuts = true,\n showNumbers,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n onConfirm,\n onCancel,\n ...props\n },\n ref,\n ) => {\n const baseId = useId();\n const questionId = `${baseId}-question`;\n const optionId = (value_: string): string => `${baseId}-opt-${value_}`;\n\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue);\n const selected = value !== undefined ? value : internalValue;\n\n const [internalOther, setInternalOther] = useState(\"\");\n const otherValue = otherText !== undefined ? otherText : internalOther;\n\n const numbersVisible = showNumbers ?? enableKeyboardShortcuts;\n const hasPreview = options.some((option) => option.preview != null);\n const selectedPreview = options.find((option) => option.value === selected)?.preview;\n\n const select = (next: string): void => {\n if (value === undefined) setInternalValue(next);\n onValueChange?.(next);\n };\n\n const setOther = (next: string): void => {\n if (otherText === undefined) setInternalOther(next);\n onOtherTextChange?.(next);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLElement>): void => {\n if (!enableKeyboardShortcuts) return;\n const target = event.target as HTMLElement;\n // Never hijack digits typed into a form field (e.g. the Other input).\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") return;\n const index = digitKeyToIndex(event.key);\n if (index === null || index >= options.length) return;\n const option = options[index];\n if (!option || option.disabled) return;\n event.preventDefault();\n select(option.value);\n };\n\n const confirm = (): void => {\n if (!selected) return;\n onConfirm?.(\n isOtherValue(selected) ? { value: selected, otherText: otherValue } : { value: selected },\n );\n };\n\n return (\n <section\n data-slot=\"choice-prompt\"\n ref={ref}\n aria-labelledby={questionId}\n onKeyDown={handleKeyDown}\n className={cn(\n \"grid w-full gap-4 rounded-xl border bg-card p-5 text-card-foreground shadow-md\",\n \"transition-shadow duration-base ease-out-soft\",\n className,\n )}\n {...props}\n >\n <header className=\"flex items-start justify-between gap-3\">\n <h3 id={questionId} className=\"font-display text-foreground text-title-md tracking-tight\">\n {question}\n </h3>\n {badge != null ? (\n <Badge variant=\"primary\" size=\"sm\" className=\"shrink-0\">\n {badge}\n </Badge>\n ) : null}\n </header>\n {description != null ? (\n <p className=\"text-body-sm text-muted-foreground\">{description}</p>\n ) : null}\n\n <div className={cn(\"grid gap-5\", hasPreview && \"md:grid-cols-2\")}>\n <RadioGroup\n aria-labelledby={questionId}\n value={selected ?? \"\"}\n onValueChange={select}\n className=\"gap-2\"\n >\n {options.map((option, index) => (\n <div key={option.value} className=\"flex items-start gap-3\">\n <RadioGroup.Item\n value={option.value}\n id={optionId(option.value)}\n disabled={option.disabled}\n className=\"mt-0.5\"\n />\n <Label\n htmlFor={optionId(option.value)}\n className=\"flex flex-1 cursor-pointer flex-col items-start gap-0.5\"\n >\n <span className=\"text-body-md text-foreground\">{option.label}</span>\n {option.description != null ? (\n <span className=\"text-body-sm text-muted-foreground\">{option.description}</span>\n ) : null}\n </Label>\n {numbersVisible && index < 9 ? (\n <span\n aria-hidden=\"true\"\n className=\"mt-0.5 shrink-0 rounded border border-border bg-muted px-1.5 font-mono text-label text-muted-foreground\"\n >\n {index + 1}\n </span>\n ) : null}\n </div>\n ))}\n\n {allowOther ? (\n <div className=\"flex flex-col gap-2 border-border/40 border-t pt-2\">\n <div className=\"flex items-start gap-3\">\n <RadioGroup.Item\n value={OTHER_OPTION_VALUE}\n id={optionId(OTHER_OPTION_VALUE)}\n className=\"mt-0.5\"\n />\n <Label\n htmlFor={optionId(OTHER_OPTION_VALUE)}\n className=\"flex-1 cursor-pointer text-body-md\"\n >\n {otherLabel}\n </Label>\n </div>\n {isOtherValue(selected) ? (\n <Input\n size=\"sm\"\n aria-label={typeof otherLabel === \"string\" ? otherLabel : \"Other\"}\n placeholder={otherPlaceholder}\n value={otherValue}\n onChange={(event) => setOther(event.target.value)}\n className=\"ml-7\"\n />\n ) : null}\n </div>\n ) : null}\n </RadioGroup>\n\n {hasPreview ? (\n <div className=\"rounded-lg border border-border/60 bg-muted/40 p-3\">\n <p className=\"mb-2 font-sans text-label-caps text-muted-foreground uppercase tracking-wider\">\n Preview\n </p>\n {selectedPreview != null ? (\n <div className=\"whitespace-pre-wrap break-words font-mono text-code-sm text-foreground\">\n {selectedPreview}\n </div>\n ) : (\n <p className=\"text-body-sm text-muted-foreground\">Select an option to preview.</p>\n )}\n </div>\n ) : null}\n </div>\n\n {onConfirm || onCancel ? (\n <footer className=\"flex items-center justify-end gap-2\">\n {onCancel ? (\n <Button size=\"sm\" variant=\"secondary\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n ) : null}\n {onConfirm ? (\n <Button size=\"sm\" variant=\"primary\" disabled={!selected} onClick={confirm}>\n {confirmLabel}\n </Button>\n ) : null}\n </footer>\n ) : null}\n </section>\n );\n },\n);\nChoicePrompt.displayName = \"ChoicePrompt\";\n\nexport { ChoicePrompt };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/choice-prompt/choice-prompt.tsx"],"names":[],"mappings":"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","file":"chunk-ACZNFEOZ.js","sourcesContent":["\"use client\";\n\nimport { forwardRef, useId, useState } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport {\n OTHER_OPTION_VALUE,\n type PromptOption,\n digitKeyToIndex,\n isOtherValue,\n} from \"../../../lib/prompt.js\";\nimport { Badge } from \"../../primitives/badge/index.js\";\nimport { Button } from \"../../primitives/button/index.js\";\nimport { Input } from \"../../primitives/input/index.js\";\nimport { Label } from \"../../primitives/label/index.js\";\nimport { RadioGroup } from \"../../primitives/radio-group/index.js\";\n\n/**\n * ChoicePrompt — single-select \"ask the user\" card for agent surfaces.\n *\n * Mirrors the UX of Claude Code's question card: a question with an optional\n * header chip, a list of options each carrying a label + description, optional\n * number-key shortcuts (terminal-style `1`..`9` selection), an injectable\n * free-text \"Other\" option, and a side-by-side preview pane when options carry\n * preview content.\n *\n * Renders one question at a time — sequencing across multiple questions is the\n * consumer's responsibility (there is no built-in flow orchestrator).\n *\n * Controlled or uncontrolled: pass `value` + `onValueChange` to control the\n * selection, or `defaultValue` to let the component own it. Same for the Other\n * text via `otherText` / `onOtherTextChange`.\n */\n\n/** Payload handed to `onConfirm`. */\nexport interface ChoicePromptResult {\n /** The selected option value (or the reserved Other value). */\n value: string;\n /** Present only when the selected value is the synthesized Other option. */\n otherText?: string;\n}\n\nexport interface ChoicePromptProps extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\"> {\n /** The question being asked. */\n question: ReactNode;\n /** Optional secondary line under the question. */\n description?: ReactNode;\n /** Optional short header chip (rendered as a Badge), e.g. \"Deploy\". */\n badge?: ReactNode;\n /** The selectable options. */\n options: PromptOption[];\n /** Controlled selected value. */\n value?: string;\n /** Initial selected value when uncontrolled. */\n defaultValue?: string;\n /** Fired with the option value whenever the selection changes. */\n onValueChange?: (value: string) => void;\n /** Inject a free-text \"Other\" option as the last row. */\n allowOther?: boolean;\n /** Label for the Other row. Defaults to \"Other\". */\n otherLabel?: ReactNode;\n /** Placeholder for the Other text field. */\n otherPlaceholder?: string;\n /** Controlled Other text. */\n otherText?: string;\n /** Fired with the Other text on every keystroke. */\n onOtherTextChange?: (text: string) => void;\n /** Enable `1`..`9` number-key selection. Default true. */\n enableKeyboardShortcuts?: boolean;\n /** Show the `1`..`9` hint chips next to options. Defaults to the shortcut flag. */\n showNumbers?: boolean;\n /** Confirm button label. Defaults to \"Confirm\". Omit `onConfirm` to hide it. */\n confirmLabel?: ReactNode;\n /** Cancel button label. Defaults to \"Cancel\". Omit `onCancel` to hide it. */\n cancelLabel?: ReactNode;\n /** Pressing Confirm. Receives the selection (and Other text when relevant). */\n onConfirm?: (result: ChoicePromptResult) => void;\n /** Pressing Cancel. */\n onCancel?: () => void;\n}\n\nconst ChoicePrompt = forwardRef<HTMLElement, ChoicePromptProps>(\n (\n {\n className,\n question,\n description,\n badge,\n options,\n value,\n defaultValue,\n onValueChange,\n allowOther = false,\n otherLabel = \"Other\",\n otherPlaceholder = \"Type your answer…\",\n otherText,\n onOtherTextChange,\n enableKeyboardShortcuts = true,\n showNumbers,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n onConfirm,\n onCancel,\n ...props\n },\n ref,\n ) => {\n const baseId = useId();\n const questionId = `${baseId}-question`;\n const optionId = (value_: string): string => `${baseId}-opt-${value_}`;\n\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue);\n const selected = value !== undefined ? value : internalValue;\n\n const [internalOther, setInternalOther] = useState(\"\");\n const otherValue = otherText !== undefined ? otherText : internalOther;\n\n const numbersVisible = showNumbers ?? enableKeyboardShortcuts;\n const hasPreview = options.some((option) => option.preview != null);\n const selectedPreview = options.find((option) => option.value === selected)?.preview;\n\n const select = (next: string): void => {\n if (value === undefined) setInternalValue(next);\n onValueChange?.(next);\n };\n\n const setOther = (next: string): void => {\n if (otherText === undefined) setInternalOther(next);\n onOtherTextChange?.(next);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLElement>): void => {\n if (!enableKeyboardShortcuts) return;\n const target = event.target as HTMLElement;\n // Never hijack digits typed into a form field (e.g. the Other input).\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") return;\n const index = digitKeyToIndex(event.key);\n if (index === null || index >= options.length) return;\n const option = options[index];\n if (!option || option.disabled) return;\n event.preventDefault();\n select(option.value);\n };\n\n const confirm = (): void => {\n if (!selected) return;\n onConfirm?.(\n isOtherValue(selected) ? { value: selected, otherText: otherValue } : { value: selected },\n );\n };\n\n return (\n <section\n data-slot=\"choice-prompt\"\n ref={ref}\n aria-labelledby={questionId}\n onKeyDown={handleKeyDown}\n className={cn(\n \"grid w-full gap-4 rounded-xl border border-border bg-card p-5 text-card-foreground shadow-md\",\n \"transition-shadow duration-base ease-out-soft\",\n className,\n )}\n {...props}\n >\n <header className=\"flex items-start justify-between gap-3\">\n <h3 id={questionId} className=\"font-display text-foreground text-title-md tracking-tight\">\n {question}\n </h3>\n {badge != null ? (\n <Badge variant=\"primary\" size=\"sm\" className=\"shrink-0\">\n {badge}\n </Badge>\n ) : null}\n </header>\n {description != null ? (\n <p className=\"text-body-sm text-muted-foreground\">{description}</p>\n ) : null}\n\n <div className={cn(\"grid gap-5\", hasPreview && \"md:grid-cols-2\")}>\n <RadioGroup\n aria-labelledby={questionId}\n value={selected ?? \"\"}\n onValueChange={select}\n className=\"gap-2\"\n >\n {options.map((option, index) => (\n <div key={option.value} className=\"flex items-start gap-3\">\n <RadioGroup.Item\n value={option.value}\n id={optionId(option.value)}\n disabled={option.disabled}\n className=\"mt-0.5\"\n />\n <Label\n htmlFor={optionId(option.value)}\n className=\"flex flex-1 cursor-pointer flex-col items-start gap-0.5\"\n >\n <span className=\"text-body-md text-foreground\">{option.label}</span>\n {option.description != null ? (\n <span className=\"text-body-sm text-muted-foreground\">{option.description}</span>\n ) : null}\n </Label>\n {numbersVisible && index < 9 ? (\n <span\n aria-hidden=\"true\"\n className=\"mt-0.5 shrink-0 rounded border border-border bg-muted px-1.5 font-mono text-label text-muted-foreground\"\n >\n {index + 1}\n </span>\n ) : null}\n </div>\n ))}\n\n {allowOther ? (\n <div className=\"flex flex-col gap-2 border-border/40 border-t pt-2\">\n <div className=\"flex items-start gap-3\">\n <RadioGroup.Item\n value={OTHER_OPTION_VALUE}\n id={optionId(OTHER_OPTION_VALUE)}\n className=\"mt-0.5\"\n />\n <Label\n htmlFor={optionId(OTHER_OPTION_VALUE)}\n className=\"flex-1 cursor-pointer text-body-md\"\n >\n {otherLabel}\n </Label>\n </div>\n {isOtherValue(selected) ? (\n <Input\n size=\"sm\"\n aria-label={typeof otherLabel === \"string\" ? otherLabel : \"Other\"}\n placeholder={otherPlaceholder}\n value={otherValue}\n onChange={(event) => setOther(event.target.value)}\n className=\"ml-7\"\n />\n ) : null}\n </div>\n ) : null}\n </RadioGroup>\n\n {hasPreview ? (\n <div className=\"rounded-lg border border-border/60 bg-muted/40 p-3\">\n <p className=\"mb-2 font-sans text-label-caps text-muted-foreground uppercase tracking-wider\">\n Preview\n </p>\n {selectedPreview != null ? (\n <div className=\"whitespace-pre-wrap break-words font-mono text-code-sm text-foreground\">\n {selectedPreview}\n </div>\n ) : (\n <p className=\"text-body-sm text-muted-foreground\">Select an option to preview.</p>\n )}\n </div>\n ) : null}\n </div>\n\n {onConfirm || onCancel ? (\n <footer className=\"flex items-center justify-end gap-2\">\n {onCancel ? (\n <Button size=\"sm\" variant=\"secondary\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n ) : null}\n {onConfirm ? (\n <Button size=\"sm\" variant=\"primary\" disabled={!selected} onClick={confirm}>\n {confirmLabel}\n </Button>\n ) : null}\n </footer>\n ) : null}\n </section>\n );\n },\n);\nChoicePrompt.displayName = \"ChoicePrompt\";\n\nexport { ChoicePrompt };\n"]}
|
|
@@ -24,7 +24,7 @@ var RollbackUI = forwardRef(
|
|
|
24
24
|
{
|
|
25
25
|
"data-slot": "rollback-ui",
|
|
26
26
|
ref,
|
|
27
|
-
className: cn("rounded-xl border bg-card p-5 shadow-sm", className),
|
|
27
|
+
className: cn("rounded-xl border border-border bg-card p-5 shadow-sm", className),
|
|
28
28
|
...props,
|
|
29
29
|
children: [
|
|
30
30
|
/* @__PURE__ */ jsx("header", { className: "mb-4 flex items-baseline justify-between gap-3", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -104,5 +104,5 @@ var RollbackUI = forwardRef(
|
|
|
104
104
|
RollbackUI.displayName = "RollbackUI";
|
|
105
105
|
|
|
106
106
|
export { RollbackUI };
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-AJ2LNQUQ.js.map
|
|
108
|
+
//# sourceMappingURL=chunk-AJ2LNQUQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/rollback-ui/rollback-ui.tsx"],"names":[],"mappings":";;;;;;;AAwCA,IAAM,UAAA,GAAa,UAAA;AAAA,EACjB,CAAC,EAAE,SAAA,EAAW,OAAA,EAAS,YAAY,GAAG,KAAA,IAAS,GAAA,KAAQ;AACrD,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAwB,IAAI,CAAA;AAC9D,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAwB,IAAI,CAAA;AAE9D,IAAA,MAAM,OAAA,GAAU,OAAO,EAAA,KAAe;AACpC,MAAA,YAAA,CAAa,EAAE,CAAA;AACf,MAAA,IAAI;AACF,QAAA,MAAM,aAAa,EAAE,CAAA;AAAA,MACvB,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,IAAI,CAAA;AACjB,QAAA,YAAA,CAAa,IAAI,CAAA;AAAA,MACnB;AAAA,IACF,CAAA;AAEA,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,aAAA;AAAA,QACV,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/rollback-ui/rollback-ui.tsx"],"names":[],"mappings":"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","file":"chunk-AJ2LNQUQ.js","sourcesContent":["\"use client\";\n\nimport { ArrowDownLeft, Clock, GitCommit, RotateCcw } from \"lucide-react\";\nimport { forwardRef, useState } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { Badge } from \"../../primitives/badge/index.js\";\nimport { Button } from \"../../primitives/button/index.js\";\n\nexport interface RollbackTarget {\n id: string;\n version: string;\n commitSha: string;\n commitMessage: string;\n deployedAt: string;\n isCurrent?: boolean;\n /**\n * Optional duration of the deploy (e.g. \"24s\") for context.\n */\n duration?: string;\n}\n\ninterface RollbackUIProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Deployment history, newest first. The current deploy should have `isCurrent: true`.\n */\n history: RollbackTarget[];\n /**\n * Fires when user confirms rollback to a specific target.\n */\n onRollback?: (targetId: string) => void | Promise<void>;\n}\n\n/**\n * RollbackUI — instant rollback selector showing recent versions.\n *\n * The current deploy is marked, every other version offers a \"Roll back\" button.\n * On select, the row enters confirm state (Confirm / Cancel buttons inline) before\n * firing onRollback. This protects against accidental rollbacks while still being one click.\n */\nconst RollbackUI = forwardRef<HTMLDivElement, RollbackUIProps>(\n ({ className, history, onRollback, ...props }, ref) => {\n const [confirmId, setConfirmId] = useState<string | null>(null);\n const [pendingId, setPendingId] = useState<string | null>(null);\n\n const trigger = async (id: string) => {\n setPendingId(id);\n try {\n await onRollback?.(id);\n } finally {\n setPendingId(null);\n setConfirmId(null);\n }\n };\n\n return (\n <div\n data-slot=\"rollback-ui\"\n ref={ref}\n className={cn(\"rounded-xl border border-border bg-card p-5 shadow-sm\", className)}\n {...props}\n >\n <header className=\"mb-4 flex items-baseline justify-between gap-3\">\n <div>\n <h3 className=\"font-display text-title-md tracking-tight\">Rollback</h3>\n <p className=\"text-body-sm text-muted-foreground\">\n Instant rollback to a previous version. Verified in under 5 seconds.\n </p>\n </div>\n </header>\n\n <ol className=\"grid gap-2\">\n {history.map((target, idx) => {\n const isCurrent = target.isCurrent ?? idx === 0;\n const isConfirming = confirmId === target.id;\n const isPending = pendingId === target.id;\n return (\n <li\n key={target.id}\n className={cn(\n \"grid grid-cols-[auto_1fr_auto] items-center gap-3 rounded-lg border p-3\",\n isCurrent ? \"border-primary/40 bg-primary/5\" : \"border-border/40 bg-card\",\n )}\n >\n <span\n className={cn(\n \"grid size-8 place-items-center rounded-md\",\n isCurrent\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground\",\n )}\n aria-hidden=\"true\"\n >\n {isCurrent ? <Clock className=\"size-4\" /> : <GitCommit className=\"size-4\" />}\n </span>\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-mono text-code-sm text-foreground\">{target.version}</span>\n {isCurrent ? <Badge variant=\"success\">Current</Badge> : null}\n {target.duration ? (\n <span className=\"font-mono text-code-sm text-muted-foreground\">\n · {target.duration}\n </span>\n ) : null}\n </div>\n <p className=\"mt-0.5 truncate text-body-sm text-muted-foreground\">\n <span className=\"font-mono\">{target.commitSha.slice(0, 7)}</span> ·{\" \"}\n {target.commitMessage} · {target.deployedAt}\n </p>\n </div>\n <div>\n {isCurrent ? null : isConfirming ? (\n <div className=\"flex items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setConfirmId(null)}\n disabled={isPending}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={() => trigger(target.id)} disabled={isPending}>\n <RotateCcw /> Confirm rollback\n </Button>\n </div>\n ) : (\n <Button size=\"sm\" variant=\"secondary\" onClick={() => setConfirmId(target.id)}>\n <ArrowDownLeft /> Roll back\n </Button>\n )}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n );\n },\n);\nRollbackUI.displayName = \"RollbackUI\";\n\nexport { RollbackUI };\n"]}
|
|
@@ -70,7 +70,7 @@ var ProjectCard = forwardRef(
|
|
|
70
70
|
ref,
|
|
71
71
|
href: sanitizedHref,
|
|
72
72
|
className: cn(
|
|
73
|
-
"group relative flex flex-col gap-3 rounded-xl border bg-card p-5 shadow-sm",
|
|
73
|
+
"group relative flex flex-col gap-3 rounded-xl border border-border bg-card p-5 shadow-sm",
|
|
74
74
|
"transition-[box-shadow,transform,border-color] duration-base ease-out-soft",
|
|
75
75
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
76
76
|
isLink && "hover:-translate-y-px cursor-pointer hover:border-primary/50 hover:shadow-md",
|
|
@@ -85,5 +85,5 @@ var ProjectCard = forwardRef(
|
|
|
85
85
|
ProjectCard.displayName = "ProjectCard";
|
|
86
86
|
|
|
87
87
|
export { ProjectCard };
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
89
|
-
//# sourceMappingURL=chunk-
|
|
88
|
+
//# sourceMappingURL=chunk-AX6P3SDS.js.map
|
|
89
|
+
//# sourceMappingURL=chunk-AX6P3SDS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/project-card/project-card.tsx"],"names":[],"mappings":";;;;;;;AAQA,IAAM,eAAA,GAGF;AAAA,EACF,MAAA,EAAQ,SAAA;AAAA,EACR,QAAA,EAAU,SAAA;AAAA,EACV,SAAA,EAAW,SAAA;AAAA,EACX,IAAA,EAAM,SAAA;AAAA,EACN,MAAA,EAAQ,aAAA;AAAA,EACR,SAAA,EAAW,SAAA;AAAA,EACX,IAAA,EAAM;AACR,CAAA;AACA,IAAM,eAAA,GAGF;AAAA,EACF,MAAA,EAAQ,SAAA;AAAA,EACR,QAAA,EAAU,SAAA;AAAA,EACV,SAAA,EAAW,SAAA;AAAA,EACX,IAAA,EAAM,SAAA;AAAA,EACN,MAAA,EAAQ,aAAA;AAAA,EACR,SAAA,EAAW,OAAA;AAAA,EACX,IAAA,EAAM;AACR,CAAA;AAgCA,IAAM,WAAA,GAAc,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,OAAA,EAAS,IAAA,EAAM,OAAA,EAAS,QAAA,GAAW,IAAA,EAAM,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAIzE,IAAA,MAAM,aAAA,GAAgB,SAAS,IAAI,CAAA;AACnC,IAAA,MAAM,SAAS,aAAA,KAAkB,MAAA;AACjC,IAAA,MAAM,GAAA,GAAM,SAAS,GAAA,GAAM,KAAA;AAC3B,IAAA,MAAM,UAAA,GACJ,QAAQ,MAAA,KAAW,UAAA,IACnB,QAAQ,MAAA,KAAW,WAAA,IACnB,QAAQ,MAAA,KAAW,QAAA;AAErB,IAAA,MAAM,0BACJ,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wCAAA,EACb,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,SAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,oDAAA,EAAsD,QAAA,EAAA,OAAA,CAAQ,IAAA,EAAK,CAAA;AAAA,UAChF,OAAA,CAAQ,4BACP,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,kEAAA,EACV,QAAA,EAAA,OAAA,CAAQ,WACX,CAAA,GACE;AAAA,SAAA,EACN,CAAA;AAAA,6BACC,YAAA,EAAA,EAAM,OAAA,EAAS,eAAA,CAAgB,OAAA,CAAQ,MAAM,CAAA,EAC5C,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,YAAA,CAAM,KAAN,EAAU,IAAA,EAAM,gBAAgB,OAAA,CAAQ,MAAM,CAAA,EAAG,KAAA,EAAO,UAAA,EAAY,CAAA;AAAA,UACpE,OAAA,CAAQ,WAAW,MAAA,GAChB,MAAA,GACA,QAAQ,MAAA,KAAW,UAAA,GACjB,UAAA,GACA,OAAA,CAAQ,MAAA,KAAW,WAAA,GACjB,cACA,OAAA,CAAQ,MAAA,KAAW,QAAA,GACjB,QAAA,GACA,OAAA,CAAQ,MAAA,KAAW,WACjB,QAAA,GACA,OAAA,CAAQ,MAAA,KAAW,MAAA,GACjB,MAAA,GACA;AAAA,SAAA,EAChB;AAAA,OAAA,EACF,CAAA;AAAA,MAEC,QAAA,IAAY,QAAQ,WAAA,mBACnB,GAAA,CAAC,OAAE,SAAA,EAAU,iDAAA,EAAmD,QAAA,EAAA,OAAA,CAAQ,WAAA,EAAY,CAAA,GAClF,IAAA;AAAA,MAEH,QAAA,IAAY,QAAQ,aAAA,mBACnB,GAAA,CAAC,OAAE,SAAA,EAAU,wDAAA,EACV,QAAA,EAAA,OAAA,CAAQ,aAAA,EACX,CAAA,GACE,IAAA;AAAA,sBAEJ,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0FAAA,EACb,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,gCAAA,EACd,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,SAAA,EAAA,EAAU,WAAU,QAAA,EAAS,CAAA;AAAA,UAAE,GAAA;AAAA,UAAE,OAAA,CAAQ;AAAA,SAAA,EAC5C,CAAA;AAAA,wBACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gCAAA,EACd,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,SAAA,EAAA,EAAU,WAAU,QAAA,EAAS,CAAA;AAAA,UAAE,GAAA;AAAA,UAAE,OAAA,CAAQ,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,CAAC;AAAA,SAAA,EAChE,CAAA;AAAA,QACC,OAAA,CAAQ,MAAA,mBACP,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,gCAAA,EACd,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAA,EAAA,EAAS,WAAU,QAAA,EAAS,CAAA;AAAA,UAAE,GAAA;AAAA,UAAE,OAAA,CAAQ;AAAA,SAAA,EAC3C,CAAA,GACE,IAAA;AAAA,wBACJ,GAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,MAAA,EAAC,CAAA;AAAA,wBAC1B,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,OAAA,CAAQ,cAAA,EAAe;AAAA,OAAA,EAChC,CAAA;AAAA,MAEC,0BAAU,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8BAAA,EAAgC,mBAAQ,CAAA,GAAS;AAAA,KAAA,EAC7E,CAAA;AAGF,IAAA,uBACE,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,cAAA;AAAA,QACV,GAAA;AAAA,QACA,IAAA,EAAM,aAAA;AAAA,QACN,SAAA,EAAW,EAAA;AAAA,UACT,
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/project-card/project-card.tsx"],"names":[],"mappings":"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","file":"chunk-AX6P3SDS.js","sourcesContent":["import { Activity, GitBranch, GitCommit } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode, Ref } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { safeHref } from \"../../../lib/safe-href.js\";\nimport { Badge } from \"../../primitives/badge/index.js\";\nimport type { DeploymentStatus } from \"../deployment-row/deployment-row.js\";\n\nconst statusToVariant: Record<\n DeploymentStatus,\n \"default\" | \"primary\" | \"success\" | \"warning\" | \"destructive\"\n> = {\n queued: \"warning\",\n building: \"primary\",\n deploying: \"primary\",\n live: \"success\",\n failed: \"destructive\",\n cancelled: \"default\",\n idle: \"default\",\n};\nconst statusToDotTone: Record<\n DeploymentStatus,\n \"primary\" | \"success\" | \"warning\" | \"destructive\" | \"muted\"\n> = {\n queued: \"warning\",\n building: \"primary\",\n deploying: \"primary\",\n live: \"success\",\n failed: \"destructive\",\n cancelled: \"muted\",\n idle: \"muted\",\n};\n\nexport interface Project {\n id: string;\n name: string;\n description?: string;\n framework?: string;\n branch: string;\n commitSha: string;\n commitMessage?: string;\n status: DeploymentStatus;\n url?: string;\n region?: string;\n lastDeployedAt: string;\n}\n\ninterface ProjectCardProps extends HTMLAttributes<HTMLAnchorElement | HTMLDivElement> {\n project: Project;\n href?: string;\n actions?: ReactNode;\n /**\n * Show the project description and commit message. Default true.\n */\n detailed?: boolean;\n}\n\n/**\n * ProjectCard — surface for a project in a project listing.\n *\n * Light hover lift (no shadow inflation), violet ring on focus,\n * status badge with optional pulse, framework + region in muted footer.\n */\nconst ProjectCard = forwardRef<HTMLElement, ProjectCardProps>(\n ({ className, project, href, actions, detailed = true, ...props }, ref) => {\n // T3.3 (SEC-003): defang javascript:/vbscript:/data:text/html before\n // rendering as <a href>. Consumers passing user-controlled URLs are\n // protected from XSS via dangerous protocols.\n const sanitizedHref = safeHref(href);\n const isLink = sanitizedHref !== undefined;\n const Tag = isLink ? \"a\" : \"div\";\n const isAnimated =\n project.status === \"building\" ||\n project.status === \"deploying\" ||\n project.status === \"queued\";\n\n const content = (\n <>\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <h3 className=\"truncate font-display text-title-md tracking-tight\">{project.name}</h3>\n {project.framework ? (\n <p className=\"mt-0.5 font-mono text-label-caps text-muted-foreground uppercase\">\n {project.framework}\n </p>\n ) : null}\n </div>\n <Badge variant={statusToVariant[project.status]}>\n <Badge.Dot tone={statusToDotTone[project.status]} pulse={isAnimated} />\n {project.status === \"live\"\n ? \"Live\"\n : project.status === \"building\"\n ? \"Building\"\n : project.status === \"deploying\"\n ? \"Deploying\"\n : project.status === \"queued\"\n ? \"Queued\"\n : project.status === \"failed\"\n ? \"Failed\"\n : project.status === \"idle\"\n ? \"Idle\"\n : \"Cancelled\"}\n </Badge>\n </div>\n\n {detailed && project.description ? (\n <p className=\"line-clamp-2 text-body-sm text-muted-foreground\">{project.description}</p>\n ) : null}\n\n {detailed && project.commitMessage ? (\n <p className=\"line-clamp-1 font-mono text-code-sm text-foreground/80\">\n {project.commitMessage}\n </p>\n ) : null}\n\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 font-mono text-code-sm text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1\">\n <GitBranch className=\"size-3\" /> {project.branch}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <GitCommit className=\"size-3\" /> {project.commitSha.slice(0, 7)}\n </span>\n {project.region ? (\n <span className=\"inline-flex items-center gap-1\">\n <Activity className=\"size-3\" /> {project.region}\n </span>\n ) : null}\n <span aria-hidden=\"true\">·</span>\n <span>{project.lastDeployedAt}</span>\n </div>\n\n {actions ? <div className=\"flex items-center gap-2 pt-2\">{actions}</div> : null}\n </>\n );\n\n return (\n <Tag\n data-slot=\"project-card\"\n ref={ref as Ref<HTMLAnchorElement & HTMLDivElement>}\n href={sanitizedHref}\n className={cn(\n \"group relative flex flex-col gap-3 rounded-xl border border-border bg-card p-5 shadow-sm\",\n \"transition-[box-shadow,transform,border-color] duration-base ease-out-soft\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n isLink && \"hover:-translate-y-px cursor-pointer hover:border-primary/50 hover:shadow-md\",\n className,\n )}\n {...(props as HTMLAttributes<HTMLAnchorElement> & HTMLAttributes<HTMLDivElement>)}\n >\n {content}\n </Tag>\n );\n },\n);\nProjectCard.displayName = \"ProjectCard\";\n\nexport { ProjectCard };\n"]}
|
|
@@ -37,7 +37,7 @@ var CostMeter = forwardRef(
|
|
|
37
37
|
{
|
|
38
38
|
"data-slot": "cost-meter",
|
|
39
39
|
ref,
|
|
40
|
-
className: cn("grid gap-2 rounded-xl border bg-card p-4", className),
|
|
40
|
+
className: cn("grid gap-2 rounded-xl border border-border bg-card p-4", className),
|
|
41
41
|
...props,
|
|
42
42
|
children: [
|
|
43
43
|
/* @__PURE__ */ jsxs("header", { className: "flex items-baseline justify-between", children: [
|
|
@@ -102,5 +102,5 @@ var CostMeter = forwardRef(
|
|
|
102
102
|
CostMeter.displayName = "CostMeter";
|
|
103
103
|
|
|
104
104
|
export { CostMeter };
|
|
105
|
-
//# sourceMappingURL=chunk-
|
|
106
|
-
//# sourceMappingURL=chunk-
|
|
105
|
+
//# sourceMappingURL=chunk-B42EOFRD.js.map
|
|
106
|
+
//# sourceMappingURL=chunk-B42EOFRD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/cost-meter/cost-meter.tsx"],"names":[],"mappings":";;;;;AAkBA,IAAM,SAAA,GAAY,CAAC,CAAA,KACjB,CAAA,IAAK,MAAM,CAAA,CAAA,EAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,GAAK,KAAK,EAAA,GAAK,CAAA,CAAA,EAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,KAAK,CAAA,CAAA,EAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA;AAOjF,IAAM,SAAA,GAAY,UAAA;AAAA,EAChB,CAAC,EAAE,SAAA,EAAW,IAAA,EAAM,MAAA,EAAQ,KAAA,GAAQ,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC/E,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,uBACE,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,WAAA,EAAU,YAAA;AAAA,UACV,GAAA;AAAA,UACA,SAAA,EAAW,EAAA;AAAA,YACT,2FAAA;AAAA,YACA,sBAAA;AAAA,YACA;AAAA,WACF;AAAA,UACC,GAAG,KAAA;AAAA,UAEJ,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,qBAAA,EAAsB,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,gCACzD,MAAA,EAAA,EAAK,SAAA,EAAU,8BAAA,EAAgC,QAAA,EAAA,SAAA,CAAU,IAAI,CAAA,EAAE,CAAA;AAAA,YAC/D,MAAA,mBAAS,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EAAwB,QAAA,EAAA;AAAA,cAAA,IAAA;AAAA,cAAG,UAAU,MAAM;AAAA,aAAA,EAAE,CAAA,GAAU;AAAA;AAAA;AAAA,OACnF;AAAA,IAEJ;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,GAAO,MAAM,CAAC,CAAA,GAAI,CAAA;AACjE,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAG,CAAA;AACtC,IAAA,MAAM,UAAA,GAAa,MAAA,KAAW,MAAA,IAAa,IAAA,GAAO,MAAA;AAElD,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,YAAA;AAAA,QACV,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/cost-meter/cost-meter.tsx"],"names":[],"mappings":"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","file":"chunk-B42EOFRD.js","sourcesContent":["import { Coins, TrendingDown, TrendingUp } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\ninterface CostMeterProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Current cost in USD. */\n cost: number;\n /** Optional monthly budget; renders progress bar when present. */\n budget?: number;\n /** Optional title (e.g. \"This session\", \"Monthly\"). */\n title?: ReactNode;\n /** Optional delta vs previous period. */\n delta?: { value: number; period: string };\n /** Compact mode — single-line summary. */\n compact?: boolean;\n}\n\nconst formatUsd = (n: number) =>\n n >= 100 ? `$${n.toFixed(0)}` : n >= 10 ? `$${n.toFixed(1)}` : `$${n.toFixed(2)}`;\n\n/**\n * CostMeter — gauge for token spend. Two visuals:\n * - card: title + big number + optional progress bar + optional delta.\n * - compact: chip \"Coins $4.20\" for nav bars.\n */\nconst CostMeter = forwardRef<HTMLDivElement, CostMeterProps>(\n ({ className, cost, budget, title = \"Spend\", delta, compact, ...props }, ref) => {\n if (compact) {\n return (\n <div\n data-slot=\"cost-meter\"\n ref={ref}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border border-border/60 bg-card px-2.5 py-1\",\n \"font-mono text-label\",\n className,\n )}\n {...props}\n >\n <Coins className=\"size-3 text-primary\" aria-hidden=\"true\" />\n <span className=\"text-foreground tabular-nums\">{formatUsd(cost)}</span>\n {budget ? <span className=\"text-muted-foreground\">/ {formatUsd(budget)}</span> : null}\n </div>\n );\n }\n\n const ratio = budget ? Math.max(0, Math.min(1, cost / budget)) : 0;\n const percent = Math.round(ratio * 100);\n const overBudget = budget !== undefined && cost > budget;\n\n return (\n <div\n data-slot=\"cost-meter\"\n ref={ref}\n className={cn(\"grid gap-2 rounded-xl border border-border bg-card p-4\", className)}\n {...props}\n >\n <header className=\"flex items-baseline justify-between\">\n <span className=\"font-mono text-label-caps text-muted-foreground uppercase tracking-wider\">\n {title}\n </span>\n {delta ? (\n <span\n className={cn(\n \"inline-flex items-center gap-1 font-mono text-body-sm tabular-nums\",\n delta.value >= 0 ? \"text-warning\" : \"text-success\",\n )}\n >\n {delta.value >= 0 ? (\n <TrendingUp className=\"size-3\" aria-hidden=\"true\" />\n ) : (\n <TrendingDown className=\"size-3\" aria-hidden=\"true\" />\n )}\n {delta.value >= 0 ? \"+\" : \"\"}\n {formatUsd(Math.abs(delta.value))}{\" \"}\n <span className=\"text-muted-foreground\">{delta.period}</span>\n </span>\n ) : null}\n </header>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"font-bold font-display text-display-md text-foreground tabular-nums leading-none\">\n {formatUsd(cost)}\n </span>\n {budget !== undefined ? (\n <span className=\"font-mono text-body-sm text-muted-foreground\">\n of {formatUsd(budget)}\n </span>\n ) : null}\n </div>\n {budget !== undefined ? (\n <div className=\"grid gap-1\">\n <div\n className=\"h-1.5 w-full overflow-hidden rounded-full bg-muted\"\n role=\"progressbar\"\n tabIndex={-1}\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className={cn(\n \"h-full rounded-full transition-[width,background-color]\",\n overBudget ? \"bg-destructive\" : ratio > 0.75 ? \"bg-warning\" : \"bg-primary\",\n )}\n style={{ width: `${Math.min(100, percent)}%` }}\n />\n </div>\n <span className=\"font-mono text-label text-muted-foreground tabular-nums\">\n {percent}% of budget {overBudget ? \"· over!\" : \"used\"}\n </span>\n </div>\n ) : null}\n </div>\n );\n },\n);\nCostMeter.displayName = \"CostMeter\";\n\nexport { CostMeter };\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Card } from './chunk-
|
|
1
|
+
import { Card } from './chunk-UJAWV6LM.js';
|
|
2
2
|
import { cn } from './chunk-EWDN56AS.js';
|
|
3
3
|
import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
|
|
4
4
|
import { forwardRef } from 'react';
|
|
@@ -55,5 +55,5 @@ var MetricCard = forwardRef(
|
|
|
55
55
|
MetricCard.displayName = "MetricCard";
|
|
56
56
|
|
|
57
57
|
export { MetricCard };
|
|
58
|
-
//# sourceMappingURL=chunk-
|
|
59
|
-
//# sourceMappingURL=chunk-
|
|
58
|
+
//# sourceMappingURL=chunk-CFVSXYVT.js.map
|
|
59
|
+
//# sourceMappingURL=chunk-CFVSXYVT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/metric-card/metric-card.tsx"],"names":[],"mappings":";;;;;;AAsDA,SAAS,UAAA,CAAW,OAAwB,MAAA,EAAyB;AACnE,EAAA,IAAI,KAAA,KAAU,WAAW,OAAO,uBAAA;AAChC,EAAA,MAAM,UAAA,GAAa,MAAA,GAAS,KAAA,KAAU,MAAA,GAAS,KAAA,KAAU,IAAA;AACzD,EAAA,OAAO,aAAa,cAAA,GAAiB,kBAAA;AACvC;AAEA,SAAS,SAAA,CAAU,EAAE,KAAA,EAAO,SAAA,EAAU,EAAmD;AACvF,EAAA,IAAI,KAAA,KAAU,IAAA,EAAM,uBAAO,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAAG,aAAA,EAAW,IAAA,EAAC,CAAA;AACzF,EAAA,IAAI,KAAA,KAAU,MAAA,EAAQ,uBAAO,GAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAAG,aAAA,EAAW,IAAA,EAAC,CAAA;AAC7F,EAAA,uBAAO,GAAA,CAAC,SAAM,SAAA,EAAW,EAAA,CAAG,YAAY,SAAS,CAAA,EAAG,eAAW,IAAA,EAAC,CAAA;AAClE;AAEO,IAAM,UAAA,GAAa,UAAA;AAAA,EACxB,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,WAAA,GAAc,KAAA,EAAO,SAAA,EAAW,GAAG,IAAA,IAAQ,GAAA,KAAQ;AACrF,IAAA,uBACE,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,aAAA;AAAA,QACV,GAAA;AAAA,QAQA,SAAA,EAAW,EAAA,CAAG,uDAAA,EAAyD,SAAS,CAAA;AAAA,QAChF,aAAA,EAAY,aAAA;AAAA,QACX,GAAG,IAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wCAAA,EACb,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mEAAA,EACb,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,YACC,IAAA,KAAS,0BACR,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,uBAAA,EAAwB,aAAA,EAAW,MAChD,QAAA,EAAA,IAAA,EACH;AAAA,WAAA,EAEJ,CAAA;AAAA,0BAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gFAAA,EACZ,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAAA,CACE,UAAU,MAAA,IAAa,IAAA,KAAS,2BAChC,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iCAAA,EACZ,QAAA,EAAA;AAAA,YAAA,KAAA,KAAU,MAAA,oBACT,IAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,EAAA;AAAA,kBACT,4CAAA;AAAA,kBACA,UAAA,CAAW,KAAA,CAAM,KAAA,EAAO,WAAW;AAAA,iBACrC;AAAA,gBACA,cAAY,KAAA,CAAM,KAAA;AAAA,gBAElB,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,CAAA;AAAA,kBAC9B,KAAA,CAAM;AAAA;AAAA;AAAA,aACT;AAAA,YAED,SAAS,MAAA,oBAAa,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAyB,QAAA,EAAA,IAAA,EAAK;AAAA,WAAA,EACvE;AAAA;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AACA,UAAA,CAAW,WAAA,GAAc,YAAA","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/metric-card/metric-card.tsx"],"names":[],"mappings":";;;;;;AAsDA,SAAS,UAAA,CAAW,OAAwB,MAAA,EAAyB;AACnE,EAAA,IAAI,KAAA,KAAU,WAAW,OAAO,uBAAA;AAChC,EAAA,MAAM,UAAA,GAAa,MAAA,GAAS,KAAA,KAAU,MAAA,GAAS,KAAA,KAAU,IAAA;AACzD,EAAA,OAAO,aAAa,cAAA,GAAiB,kBAAA;AACvC;AAEA,SAAS,SAAA,CAAU,EAAE,KAAA,EAAO,SAAA,EAAU,EAAmD;AACvF,EAAA,IAAI,KAAA,KAAU,IAAA,EAAM,uBAAO,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAAG,aAAA,EAAW,IAAA,EAAC,CAAA;AACzF,EAAA,IAAI,KAAA,KAAU,MAAA,EAAQ,uBAAO,GAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAAG,aAAA,EAAW,IAAA,EAAC,CAAA;AAC7F,EAAA,uBAAO,GAAA,CAAC,SAAM,SAAA,EAAW,EAAA,CAAG,YAAY,SAAS,CAAA,EAAG,eAAW,IAAA,EAAC,CAAA;AAClE;AAEO,IAAM,UAAA,GAAa,UAAA;AAAA,EACxB,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,WAAA,GAAc,KAAA,EAAO,SAAA,EAAW,GAAG,IAAA,IAAQ,GAAA,KAAQ;AACrF,IAAA,uBACE,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,aAAA;AAAA,QACV,GAAA;AAAA,QAQA,SAAA,EAAW,EAAA,CAAG,uDAAA,EAAyD,SAAS,CAAA;AAAA,QAChF,aAAA,EAAY,aAAA;AAAA,QACX,GAAG,IAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wCAAA,EACb,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mEAAA,EACb,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,YACC,IAAA,KAAS,0BACR,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,uBAAA,EAAwB,aAAA,EAAW,MAChD,QAAA,EAAA,IAAA,EACH;AAAA,WAAA,EAEJ,CAAA;AAAA,0BAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gFAAA,EACZ,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAAA,CACE,UAAU,MAAA,IAAa,IAAA,KAAS,2BAChC,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iCAAA,EACZ,QAAA,EAAA;AAAA,YAAA,KAAA,KAAU,MAAA,oBACT,IAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,EAAA;AAAA,kBACT,4CAAA;AAAA,kBACA,UAAA,CAAW,KAAA,CAAM,KAAA,EAAO,WAAW;AAAA,iBACrC;AAAA,gBACA,cAAY,KAAA,CAAM,KAAA;AAAA,gBAElB,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,SAAA,EAAA,EAAU,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,CAAA;AAAA,kBAC9B,KAAA,CAAM;AAAA;AAAA;AAAA,aACT;AAAA,YAED,SAAS,MAAA,oBAAa,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAyB,QAAA,EAAA,IAAA,EAAK;AAAA,WAAA,EACvE;AAAA;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AACA,UAAA,CAAW,WAAA,GAAc,YAAA","file":"chunk-CFVSXYVT.js","sourcesContent":["import { Minus, TrendingDown, TrendingUp } from \"lucide-react\";\nimport { type HTMLAttributes, type ReactNode, forwardRef } from \"react\";\n\nimport { cn } from \"../../../lib/cn.js\";\nimport { Card } from \"../../primitives/card/index.js\";\n\n/**\n * MetricCard — dashboard metric tile (composite).\n *\n * Pattern recurrente \"Card + CardHeader + value + delta + trend icon\" promoted\n * to a first-class composite per ADR-0007 community-best-practices plan.\n *\n * Trend → token mapping (default `invertTrend=false`):\n * up → text-success (positive growth)\n * down → text-destructive (negative growth)\n * neutral → text-muted-foreground\n *\n * EC-17 absorbed: pass `invertTrend` for metrics where \"up is bad\" (cost,\n * churn, latency). The mapping inverts cleanly:\n * up → text-destructive (cost growing = bad)\n * down → text-success (cost dropping = good)\n *\n * @example\n * <MetricCard title=\"Revenue\" value=\"$12,345\" delta={{ value: \"+12%\", trend: \"up\" }} />\n * <MetricCard title=\"Monthly Cost\" value=\"$3,200\" delta={{ value: \"+18%\", trend: \"up\" }} invertTrend />\n */\n\nexport type MetricCardTrend = \"up\" | \"down\" | \"neutral\";\n\nexport interface MetricCardDelta {\n /** Display text (e.g., `\"+12%\"`, `\"-3.4 pp\"`, `\"unchanged\"`). */\n value: string;\n /** Trend direction — drives icon and color (subject to `invertTrend`). */\n trend: MetricCardTrend;\n}\n\nexport interface MetricCardProps extends HTMLAttributes<HTMLDivElement> {\n /** Metric label (e.g., \"Revenue\", \"Active Users\"). */\n title: string;\n /** Headline value (e.g., \"$12,345\", \"1,234\"). */\n value: ReactNode;\n /** Optional delta with trend direction. */\n delta?: MetricCardDelta;\n /** Optional subtle context line below the value (e.g., \"vs last month\"). */\n hint?: ReactNode;\n /** Optional icon rendered top-right (e.g., `<DollarSign />`). */\n icon?: ReactNode;\n /**\n * EC-17: invert default trend semantics. Use for Cost / Churn / Latency\n * metrics where \"up\" is bad. Default `false` (Revenue / Users / Conversions).\n */\n invertTrend?: boolean;\n}\n\nfunction trendColor(trend: MetricCardTrend, invert: boolean): string {\n if (trend === \"neutral\") return \"text-muted-foreground\";\n const isPositive = invert ? trend === \"down\" : trend === \"up\";\n return isPositive ? \"text-success\" : \"text-destructive\";\n}\n\nfunction TrendIcon({ trend, className }: { trend: MetricCardTrend; className?: string }) {\n if (trend === \"up\") return <TrendingUp className={cn(\"size-3.5\", className)} aria-hidden />;\n if (trend === \"down\") return <TrendingDown className={cn(\"size-3.5\", className)} aria-hidden />;\n return <Minus className={cn(\"size-3.5\", className)} aria-hidden />;\n}\n\nexport const MetricCard = forwardRef<HTMLDivElement, MetricCardProps>(\n ({ title, value, delta, hint, icon, invertTrend = false, className, ...rest }, ref) => {\n return (\n <Card\n data-slot=\"metric-card\"\n ref={ref}\n // T5.5: `@container/metric-card` makes the tile responsive to its PARENT\n // width, not the viewport. Consumers can drop multiple cards into any\n // grid and child elements scale via `@sm:`, `@md:`, `@lg:` variants.\n // `w-full` is the right default for a tile: consumers always wrap in a\n // grid/flex parent (grid-cols-N, flex). Without it, the flex-col card\n // collapses to min-content (~150px) when used in isolation — a real\n // regression observed in the docs site preview pane.\n className={cn(\"@container/metric-card flex w-full flex-col gap-2 p-4\", className)}\n data-testid=\"metric-card\"\n {...rest}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <span className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n {title}\n </span>\n {icon !== undefined && (\n <span className=\"text-muted-foreground\" aria-hidden>\n {icon}\n </span>\n )}\n </div>\n {/* Value scales 2xl → 3xl when the card container exceeds 18rem. */}\n <div className=\"font-semibold @sm/metric-card:text-3xl text-2xl text-foreground tracking-tight\">\n {value}\n </div>\n {(delta !== undefined || hint !== undefined) && (\n <div className=\"flex items-center gap-2 text-xs\">\n {delta !== undefined && (\n <span\n className={cn(\n \"inline-flex items-center gap-1 font-medium\",\n trendColor(delta.trend, invertTrend),\n )}\n data-trend={delta.trend}\n >\n <TrendIcon trend={delta.trend} />\n {delta.value}\n </span>\n )}\n {hint !== undefined && <span className=\"text-muted-foreground\">{hint}</span>}\n </div>\n )}\n </Card>\n );\n },\n);\nMetricCard.displayName = \"MetricCard\";\n"]}
|
|
@@ -95,7 +95,7 @@ var BuildLogStream = forwardRef(
|
|
|
95
95
|
/* @__PURE__ */ jsxs(
|
|
96
96
|
"div",
|
|
97
97
|
{
|
|
98
|
-
className: cn("overflow-y-auto rounded-lg border bg-card", "font-mono text-code-sm"),
|
|
98
|
+
className: cn("overflow-y-auto rounded-lg border border-border bg-card", "font-mono text-code-sm"),
|
|
99
99
|
style: { height },
|
|
100
100
|
children: [
|
|
101
101
|
truncated ? /* @__PURE__ */ jsxs("output", { className: "block border-border/30 border-b bg-muted/40 px-4 py-1.5 text-label text-muted-foreground", children: [
|
|
@@ -140,5 +140,5 @@ var BuildLogStream = forwardRef(
|
|
|
140
140
|
BuildLogStream.displayName = "BuildLogStream";
|
|
141
141
|
|
|
142
142
|
export { BuildLogStream };
|
|
143
|
-
//# sourceMappingURL=chunk-
|
|
144
|
-
//# sourceMappingURL=chunk-
|
|
143
|
+
//# sourceMappingURL=chunk-CX54TUTT.js.map
|
|
144
|
+
//# sourceMappingURL=chunk-CX54TUTT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/build-log-stream/build-log-stream.tsx"],"names":[],"mappings":"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","file":"chunk-KDE3NYTI.js","sourcesContent":["\"use client\";\n\nimport { forwardRef, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { isDev } from \"../../../lib/env.js\";\nimport { useInLiveRegion } from \"../../../lib/live-region-context.js\";\n\nexport type LogLevel = \"info\" | \"warn\" | \"error\" | \"success\" | \"debug\";\n\nexport interface LogLine {\n id: string;\n timestamp: string;\n level: LogLevel;\n message: string;\n source?: string;\n}\n\nconst levelClasses: Record<LogLevel, string> = {\n info: \"text-foreground\",\n warn: \"text-warning\",\n error: \"text-destructive\",\n success: \"text-success\",\n debug: \"text-muted-foreground\",\n};\n\nconst levelLabels: Record<LogLevel, string> = {\n info: \"INFO\",\n warn: \"WARN\",\n error: \"ERROR\",\n success: \" OK \",\n debug: \"DBG \",\n};\n\ninterface BuildLogStreamProps extends HTMLAttributes<HTMLDivElement> {\n lines: LogLine[];\n /**\n * If true, shows level filter chips above the stream.\n */\n filterable?: boolean;\n /**\n * Controlled filter — which levels are visible. Empty Set = show all.\n *\n * Pick one mode: either always pass `visibleLevels` + `onVisibleLevelsChange`\n * (controlled), or never (uncontrolled). Mixing the two between renders is\n * not supported and may produce surprising state.\n */\n visibleLevels?: Set<LogLevel>;\n onVisibleLevelsChange?: (levels: Set<LogLevel>) => void;\n /**\n * Height of the scrollable region.\n */\n height?: string | number;\n /**\n * Maximum number of lines rendered. When exceeded, only the tail is shown\n * and a banner indicates truncation. Defaults to 2000 — set higher with\n * caution; React reconciliation cost scales linearly.\n */\n maxLines?: number;\n /**\n * Screen-reader live-region politeness for newly appended lines. Defaults\n * to `\"off\"` because build-log streams can be high-volume; opt into\n * `\"polite\"` only when running the build in the foreground.\n */\n live?: \"off\" | \"polite\";\n}\n\nconst ALL_LEVELS: LogLevel[] = [\"info\", \"warn\", \"error\", \"success\", \"debug\"];\n\n/**\n * BuildLogStream — terminal-like log viewer with timestamps + level coloring.\n *\n * Used in Code workspace and PaaS deployment views. Geist Mono throughout.\n * Lines fade in via animate-fade-in-up on mount; new lines (when prepended/appended)\n * are not animated to avoid feedback noise (consumer's responsibility to render\n * incrementally if needed).\n */\nconst BuildLogStream = forwardRef<HTMLDivElement, BuildLogStreamProps>(\n (\n {\n className,\n lines,\n filterable = true,\n visibleLevels,\n onVisibleLevelsChange,\n height = \"320px\",\n maxLines = 2000,\n live = \"off\",\n ...props\n },\n ref,\n ) => {\n // T4.1 (MF-4): suppress own aria-live when nested in container live region.\n const inLiveRegion = useInLiveRegion();\n const effectiveLive = inLiveRegion ? \"off\" : live;\n const [internalLevels, setInternalLevels] = useState<Set<LogLevel>>(new Set());\n const levels = visibleLevels ?? internalLevels;\n const updateLevels = onVisibleLevelsChange ?? setInternalLevels;\n\n // MEDIUM-002 / T6.5: warn (dev-only) when a consumer flips between\n // controlled and uncontrolled — React's own warning handles `value`/\n // `defaultValue` on form inputs but doesn't see our custom prop pair.\n const wasControlled = useRef<boolean | null>(null);\n useEffect(() => {\n if (!isDev()) return;\n const isControlled = visibleLevels !== undefined;\n if (wasControlled.current === null) {\n wasControlled.current = isControlled;\n return;\n }\n if (wasControlled.current !== isControlled) {\n // biome-ignore lint/suspicious/noConsole: dev-only diagnostic (MEDIUM-002)\n console.warn(\n `[@theokit/ui] BuildLogStream: \\`visibleLevels\\` prop switched between ${\n wasControlled.current ? \"controlled\" : \"uncontrolled\"\n } and ${isControlled ? \"controlled\" : \"uncontrolled\"} between renders. Pick one mode and keep it consistent.`,\n );\n wasControlled.current = isControlled;\n }\n }, [visibleLevels]);\n\n const filtered = useMemo(() => {\n if (levels.size === 0) return lines;\n return lines.filter((l) => levels.has(l.level));\n }, [lines, levels]);\n\n const truncated = filtered.length > maxLines;\n const visible = truncated ? filtered.slice(filtered.length - maxLines) : filtered;\n const hiddenCount = truncated ? filtered.length - maxLines : 0;\n\n const toggle = (level: LogLevel) => {\n const next = new Set(levels);\n if (next.has(level)) next.delete(level);\n else next.add(level);\n updateLevels(next);\n };\n\n return (\n <div\n data-slot=\"build-log-stream\"\n ref={ref}\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {filterable ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {ALL_LEVELS.map((level) => {\n const active = levels.size === 0 || levels.has(level);\n return (\n <button\n key={level}\n type=\"button\"\n onClick={() => toggle(level)}\n aria-pressed={active}\n className={cn(\n \"rounded-md border px-2 py-1 font-mono text-label uppercase tracking-wider\",\n \"transition-colors duration-base ease-out-soft\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n active\n ? cn(\"border-border/60 bg-muted\", levelClasses[level])\n : \"border-border/30 text-muted-foreground/50 hover:text-muted-foreground\",\n )}\n >\n {level}\n </button>\n );\n })}\n </div>\n ) : null}\n <div\n className={cn(\"overflow-y-auto rounded-lg border bg-card\", \"font-mono text-code-sm\")}\n style={{ height }}\n >\n {truncated ? (\n <output className=\"block border-border/30 border-b bg-muted/40 px-4 py-1.5 text-label text-muted-foreground\">\n Showing last {maxLines.toLocaleString()} of {filtered.length.toLocaleString()} lines (\n {hiddenCount.toLocaleString()} earlier lines hidden)\n </output>\n ) : null}\n {visible.length === 0 ? (\n <p className=\"px-4 py-3 text-muted-foreground\">No log lines.</p>\n ) : (\n <ol className=\"divide-y divide-border/30\" aria-live={effectiveLive} aria-atomic=\"false\">\n {visible.map((line) => (\n <li\n key={line.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-3 px-4 py-1.5 leading-relaxed hover:bg-muted/30\"\n >\n <span className=\"select-none text-muted-foreground\">{line.timestamp}</span>\n <span className={cn(\"select-none font-bold\", levelClasses[line.level])}>\n [{levelLabels[line.level]}]\n </span>\n <span className={levelClasses[line.level]}>\n {line.source ? (\n <span className=\"mr-2 text-muted-foreground\">{line.source}:</span>\n ) : null}\n {line.message}\n </span>\n </li>\n ))}\n </ol>\n )}\n </div>\n </div>\n );\n },\n);\nBuildLogStream.displayName = \"BuildLogStream\";\n\nexport { BuildLogStream };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/build-log-stream/build-log-stream.tsx"],"names":[],"mappings":"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","file":"chunk-CX54TUTT.js","sourcesContent":["\"use client\";\n\nimport { forwardRef, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { isDev } from \"../../../lib/env.js\";\nimport { useInLiveRegion } from \"../../../lib/live-region-context.js\";\n\nexport type LogLevel = \"info\" | \"warn\" | \"error\" | \"success\" | \"debug\";\n\nexport interface LogLine {\n id: string;\n timestamp: string;\n level: LogLevel;\n message: string;\n source?: string;\n}\n\nconst levelClasses: Record<LogLevel, string> = {\n info: \"text-foreground\",\n warn: \"text-warning\",\n error: \"text-destructive\",\n success: \"text-success\",\n debug: \"text-muted-foreground\",\n};\n\nconst levelLabels: Record<LogLevel, string> = {\n info: \"INFO\",\n warn: \"WARN\",\n error: \"ERROR\",\n success: \" OK \",\n debug: \"DBG \",\n};\n\ninterface BuildLogStreamProps extends HTMLAttributes<HTMLDivElement> {\n lines: LogLine[];\n /**\n * If true, shows level filter chips above the stream.\n */\n filterable?: boolean;\n /**\n * Controlled filter — which levels are visible. Empty Set = show all.\n *\n * Pick one mode: either always pass `visibleLevels` + `onVisibleLevelsChange`\n * (controlled), or never (uncontrolled). Mixing the two between renders is\n * not supported and may produce surprising state.\n */\n visibleLevels?: Set<LogLevel>;\n onVisibleLevelsChange?: (levels: Set<LogLevel>) => void;\n /**\n * Height of the scrollable region.\n */\n height?: string | number;\n /**\n * Maximum number of lines rendered. When exceeded, only the tail is shown\n * and a banner indicates truncation. Defaults to 2000 — set higher with\n * caution; React reconciliation cost scales linearly.\n */\n maxLines?: number;\n /**\n * Screen-reader live-region politeness for newly appended lines. Defaults\n * to `\"off\"` because build-log streams can be high-volume; opt into\n * `\"polite\"` only when running the build in the foreground.\n */\n live?: \"off\" | \"polite\";\n}\n\nconst ALL_LEVELS: LogLevel[] = [\"info\", \"warn\", \"error\", \"success\", \"debug\"];\n\n/**\n * BuildLogStream — terminal-like log viewer with timestamps + level coloring.\n *\n * Used in Code workspace and PaaS deployment views. Geist Mono throughout.\n * Lines fade in via animate-fade-in-up on mount; new lines (when prepended/appended)\n * are not animated to avoid feedback noise (consumer's responsibility to render\n * incrementally if needed).\n */\nconst BuildLogStream = forwardRef<HTMLDivElement, BuildLogStreamProps>(\n (\n {\n className,\n lines,\n filterable = true,\n visibleLevels,\n onVisibleLevelsChange,\n height = \"320px\",\n maxLines = 2000,\n live = \"off\",\n ...props\n },\n ref,\n ) => {\n // T4.1 (MF-4): suppress own aria-live when nested in container live region.\n const inLiveRegion = useInLiveRegion();\n const effectiveLive = inLiveRegion ? \"off\" : live;\n const [internalLevels, setInternalLevels] = useState<Set<LogLevel>>(new Set());\n const levels = visibleLevels ?? internalLevels;\n const updateLevels = onVisibleLevelsChange ?? setInternalLevels;\n\n // MEDIUM-002 / T6.5: warn (dev-only) when a consumer flips between\n // controlled and uncontrolled — React's own warning handles `value`/\n // `defaultValue` on form inputs but doesn't see our custom prop pair.\n const wasControlled = useRef<boolean | null>(null);\n useEffect(() => {\n if (!isDev()) return;\n const isControlled = visibleLevels !== undefined;\n if (wasControlled.current === null) {\n wasControlled.current = isControlled;\n return;\n }\n if (wasControlled.current !== isControlled) {\n // biome-ignore lint/suspicious/noConsole: dev-only diagnostic (MEDIUM-002)\n console.warn(\n `[@theokit/ui] BuildLogStream: \\`visibleLevels\\` prop switched between ${\n wasControlled.current ? \"controlled\" : \"uncontrolled\"\n } and ${isControlled ? \"controlled\" : \"uncontrolled\"} between renders. Pick one mode and keep it consistent.`,\n );\n wasControlled.current = isControlled;\n }\n }, [visibleLevels]);\n\n const filtered = useMemo(() => {\n if (levels.size === 0) return lines;\n return lines.filter((l) => levels.has(l.level));\n }, [lines, levels]);\n\n const truncated = filtered.length > maxLines;\n const visible = truncated ? filtered.slice(filtered.length - maxLines) : filtered;\n const hiddenCount = truncated ? filtered.length - maxLines : 0;\n\n const toggle = (level: LogLevel) => {\n const next = new Set(levels);\n if (next.has(level)) next.delete(level);\n else next.add(level);\n updateLevels(next);\n };\n\n return (\n <div\n data-slot=\"build-log-stream\"\n ref={ref}\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n >\n {filterable ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {ALL_LEVELS.map((level) => {\n const active = levels.size === 0 || levels.has(level);\n return (\n <button\n key={level}\n type=\"button\"\n onClick={() => toggle(level)}\n aria-pressed={active}\n className={cn(\n \"rounded-md border px-2 py-1 font-mono text-label uppercase tracking-wider\",\n \"transition-colors duration-base ease-out-soft\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n active\n ? cn(\"border-border/60 bg-muted\", levelClasses[level])\n : \"border-border/30 text-muted-foreground/50 hover:text-muted-foreground\",\n )}\n >\n {level}\n </button>\n );\n })}\n </div>\n ) : null}\n <div\n className={cn(\"overflow-y-auto rounded-lg border border-border bg-card\", \"font-mono text-code-sm\")}\n style={{ height }}\n >\n {truncated ? (\n <output className=\"block border-border/30 border-b bg-muted/40 px-4 py-1.5 text-label text-muted-foreground\">\n Showing last {maxLines.toLocaleString()} of {filtered.length.toLocaleString()} lines (\n {hiddenCount.toLocaleString()} earlier lines hidden)\n </output>\n ) : null}\n {visible.length === 0 ? (\n <p className=\"px-4 py-3 text-muted-foreground\">No log lines.</p>\n ) : (\n <ol className=\"divide-y divide-border/30\" aria-live={effectiveLive} aria-atomic=\"false\">\n {visible.map((line) => (\n <li\n key={line.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-3 px-4 py-1.5 leading-relaxed hover:bg-muted/30\"\n >\n <span className=\"select-none text-muted-foreground\">{line.timestamp}</span>\n <span className={cn(\"select-none font-bold\", levelClasses[line.level])}>\n [{levelLabels[line.level]}]\n </span>\n <span className={levelClasses[line.level]}>\n {line.source ? (\n <span className=\"mr-2 text-muted-foreground\">{line.source}:</span>\n ) : null}\n {line.message}\n </span>\n </li>\n ))}\n </ol>\n )}\n </div>\n </div>\n );\n },\n);\nBuildLogStream.displayName = \"BuildLogStream\";\n\nexport { BuildLogStream };\n"]}
|
|
@@ -3,7 +3,7 @@ import { Table } from './chunk-KHBXI6AV.js';
|
|
|
3
3
|
import { Skeleton } from './chunk-CGWIOIEO.js';
|
|
4
4
|
import { Pagination } from './chunk-ZPURFK4C.js';
|
|
5
5
|
import { DropdownMenu } from './chunk-SXKGWHAM.js';
|
|
6
|
-
import { EmptyState } from './chunk-
|
|
6
|
+
import { EmptyState } from './chunk-3YOPTHZH.js';
|
|
7
7
|
import { cn } from './chunk-EWDN56AS.js';
|
|
8
8
|
import { ChevronDown, ChevronRight, MoreHorizontal } from 'lucide-react';
|
|
9
9
|
import { useState, useMemo, Fragment } from 'react';
|
|
@@ -196,5 +196,5 @@ function DataTable(props) {
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
export { DataTable };
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
199
|
+
//# sourceMappingURL=chunk-DJK6H3FD.js.map
|
|
200
|
+
//# sourceMappingURL=chunk-DJK6H3FD.js.map
|