@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/composites/domain-config/domain-config.tsx"],"names":[],"mappings":"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","file":"chunk-JFKBFQA5.js","sourcesContent":["\"use client\";\n\nimport { Check, Globe, Plus, ShieldCheck, ShieldX, Trash2 } 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\";\nimport { Input } from \"../../primitives/input/index.js\";\n\nexport type DomainStatus = \"verified\" | \"pending\" | \"invalid\";\n\nexport interface Domain {\n id: string;\n hostname: string;\n status: DomainStatus;\n primary?: boolean;\n /**\n * TLS state. If true, certificate is provisioned & valid.\n */\n tls?: boolean;\n /**\n * DNS record the user must add to verify ownership.\n */\n verificationRecord?: {\n type: \"TXT\" | \"CNAME\" | \"A\";\n name: string;\n value: string;\n };\n}\n\nconst statusVariant: Record<DomainStatus, \"success\" | \"warning\" | \"destructive\"> = {\n verified: \"success\",\n pending: \"warning\",\n invalid: \"destructive\",\n};\nconst statusDot: Record<DomainStatus, \"success\" | \"warning\" | \"destructive\"> = {\n verified: \"success\",\n pending: \"warning\",\n invalid: \"destructive\",\n};\nconst statusLabel: Record<DomainStatus, string> = {\n verified: \"Verified\",\n pending: \"Pending DNS\",\n invalid: \"Invalid\",\n};\n\ninterface DomainConfigProps extends HTMLAttributes<HTMLDivElement> {\n domains: Domain[];\n onAdd?: (hostname: string) => void;\n onRemove?: (id: string) => void;\n onSetPrimary?: (id: string) => void;\n}\n\n/**\n * DomainConfig — manage custom domains for a project.\n *\n * Shows: hostname, status, TLS, primary flag, and verification DNS record when pending.\n * Common in every cloud dashboard (Vercel, Railway, Render).\n */\nconst DomainConfig = forwardRef<HTMLDivElement, DomainConfigProps>(\n ({ className, domains, onAdd, onRemove, onSetPrimary, ...props }, ref) => {\n const [hostname, setHostname] = useState(\"\");\n\n return (\n <div\n data-slot=\"domain-config\"\n ref={ref}\n className={cn(\"rounded-xl 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\">Domains</h3>\n <p className=\"text-body-sm text-muted-foreground\">{domains.length} configured</p>\n </div>\n </header>\n\n {onAdd ? (\n <form\n className=\"mb-4 grid grid-cols-[1fr_auto] gap-2\"\n onSubmit={(e) => {\n e.preventDefault();\n const v = hostname.trim();\n if (!v) return;\n onAdd(v);\n setHostname(\"\");\n }}\n >\n <Input\n placeholder=\"api.acme.com\"\n value={hostname}\n onChange={(e) => setHostname(e.target.value)}\n aria-label=\"Hostname\"\n className=\"font-mono\"\n />\n <Button type=\"submit\">\n <Plus /> Add domain\n </Button>\n </form>\n ) : null}\n\n <ul className=\"grid gap-3\">\n {domains.map((d) => (\n <li key={d.id} className=\"grid gap-3 rounded-lg border border-border/40 p-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Globe className=\"size-4 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"font-mono text-code-md text-foreground\">{d.hostname}</span>\n <Badge variant={statusVariant[d.status]}>\n <Badge.Dot tone={statusDot[d.status]} pulse={d.status === \"pending\"} />\n {statusLabel[d.status]}\n </Badge>\n {d.tls === true ? (\n <Badge variant=\"primary\">\n <ShieldCheck className=\"size-3\" /> TLS\n </Badge>\n ) : d.tls === false ? (\n <Badge variant=\"destructive\">\n <ShieldX className=\"size-3\" /> No TLS\n </Badge>\n ) : null}\n {d.primary ? (\n <Badge variant=\"accent\">\n <Check className=\"size-3\" /> Primary\n </Badge>\n ) : null}\n <div className=\"ml-auto flex items-center gap-1\">\n {!d.primary && onSetPrimary ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onSetPrimary(d.id)}>\n Set primary\n </Button>\n ) : null}\n {onRemove ? (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => onRemove(d.id)}\n aria-label={`Remove ${d.hostname}`}\n >\n <Trash2 />\n </Button>\n ) : null}\n </div>\n </div>\n {d.status === \"pending\" && d.verificationRecord ? (\n <div className=\"rounded-md border border-border/60 border-dashed bg-muted/30 p-3 font-mono text-code-sm\">\n <p className=\"mb-2 font-sans text-label-caps text-muted-foreground uppercase\">\n Add this DNS record to verify\n </p>\n <div className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n <span className=\"text-muted-foreground\">type</span>\n <span>{d.verificationRecord.type}</span>\n <span className=\"text-muted-foreground\">name</span>\n <span>{d.verificationRecord.name}</span>\n <span className=\"text-muted-foreground\">value</span>\n <span className=\"break-all\">{d.verificationRecord.value}</span>\n </div>\n </div>\n ) : null}\n </li>\n ))}\n {domains.length === 0 ? (\n <li className=\"rounded-lg border border-border/40 border-dashed p-8 text-center text-body-sm text-muted-foreground\">\n No domains yet. Add one to route traffic to this project.\n </li>\n ) : null}\n </ul>\n </div>\n );\n },\n);\nDomainConfig.displayName = \"DomainConfig\";\n\nexport { DomainConfig };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/domain-config/domain-config.tsx"],"names":[],"mappings":"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","file":"chunk-HNRFBJ25.js","sourcesContent":["\"use client\";\n\nimport { Check, Globe, Plus, ShieldCheck, ShieldX, Trash2 } 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\";\nimport { Input } from \"../../primitives/input/index.js\";\n\nexport type DomainStatus = \"verified\" | \"pending\" | \"invalid\";\n\nexport interface Domain {\n id: string;\n hostname: string;\n status: DomainStatus;\n primary?: boolean;\n /**\n * TLS state. If true, certificate is provisioned & valid.\n */\n tls?: boolean;\n /**\n * DNS record the user must add to verify ownership.\n */\n verificationRecord?: {\n type: \"TXT\" | \"CNAME\" | \"A\";\n name: string;\n value: string;\n };\n}\n\nconst statusVariant: Record<DomainStatus, \"success\" | \"warning\" | \"destructive\"> = {\n verified: \"success\",\n pending: \"warning\",\n invalid: \"destructive\",\n};\nconst statusDot: Record<DomainStatus, \"success\" | \"warning\" | \"destructive\"> = {\n verified: \"success\",\n pending: \"warning\",\n invalid: \"destructive\",\n};\nconst statusLabel: Record<DomainStatus, string> = {\n verified: \"Verified\",\n pending: \"Pending DNS\",\n invalid: \"Invalid\",\n};\n\ninterface DomainConfigProps extends HTMLAttributes<HTMLDivElement> {\n domains: Domain[];\n onAdd?: (hostname: string) => void;\n onRemove?: (id: string) => void;\n onSetPrimary?: (id: string) => void;\n}\n\n/**\n * DomainConfig — manage custom domains for a project.\n *\n * Shows: hostname, status, TLS, primary flag, and verification DNS record when pending.\n * Common in every cloud dashboard (Vercel, Railway, Render).\n */\nconst DomainConfig = forwardRef<HTMLDivElement, DomainConfigProps>(\n ({ className, domains, onAdd, onRemove, onSetPrimary, ...props }, ref) => {\n const [hostname, setHostname] = useState(\"\");\n\n return (\n <div\n data-slot=\"domain-config\"\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\">Domains</h3>\n <p className=\"text-body-sm text-muted-foreground\">{domains.length} configured</p>\n </div>\n </header>\n\n {onAdd ? (\n <form\n className=\"mb-4 grid grid-cols-[1fr_auto] gap-2\"\n onSubmit={(e) => {\n e.preventDefault();\n const v = hostname.trim();\n if (!v) return;\n onAdd(v);\n setHostname(\"\");\n }}\n >\n <Input\n placeholder=\"api.acme.com\"\n value={hostname}\n onChange={(e) => setHostname(e.target.value)}\n aria-label=\"Hostname\"\n className=\"font-mono\"\n />\n <Button type=\"submit\">\n <Plus /> Add domain\n </Button>\n </form>\n ) : null}\n\n <ul className=\"grid gap-3\">\n {domains.map((d) => (\n <li key={d.id} className=\"grid gap-3 rounded-lg border border-border/40 p-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Globe className=\"size-4 text-muted-foreground\" aria-hidden=\"true\" />\n <span className=\"font-mono text-code-md text-foreground\">{d.hostname}</span>\n <Badge variant={statusVariant[d.status]}>\n <Badge.Dot tone={statusDot[d.status]} pulse={d.status === \"pending\"} />\n {statusLabel[d.status]}\n </Badge>\n {d.tls === true ? (\n <Badge variant=\"primary\">\n <ShieldCheck className=\"size-3\" /> TLS\n </Badge>\n ) : d.tls === false ? (\n <Badge variant=\"destructive\">\n <ShieldX className=\"size-3\" /> No TLS\n </Badge>\n ) : null}\n {d.primary ? (\n <Badge variant=\"accent\">\n <Check className=\"size-3\" /> Primary\n </Badge>\n ) : null}\n <div className=\"ml-auto flex items-center gap-1\">\n {!d.primary && onSetPrimary ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onSetPrimary(d.id)}>\n Set primary\n </Button>\n ) : null}\n {onRemove ? (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={() => onRemove(d.id)}\n aria-label={`Remove ${d.hostname}`}\n >\n <Trash2 />\n </Button>\n ) : null}\n </div>\n </div>\n {d.status === \"pending\" && d.verificationRecord ? (\n <div className=\"rounded-md border border-border/60 border-dashed bg-muted/30 p-3 font-mono text-code-sm\">\n <p className=\"mb-2 font-sans text-label-caps text-muted-foreground uppercase\">\n Add this DNS record to verify\n </p>\n <div className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n <span className=\"text-muted-foreground\">type</span>\n <span>{d.verificationRecord.type}</span>\n <span className=\"text-muted-foreground\">name</span>\n <span>{d.verificationRecord.name}</span>\n <span className=\"text-muted-foreground\">value</span>\n <span className=\"break-all\">{d.verificationRecord.value}</span>\n </div>\n </div>\n ) : null}\n </li>\n ))}\n {domains.length === 0 ? (\n <li className=\"rounded-lg border border-border/40 border-dashed p-8 text-center text-body-sm text-muted-foreground\">\n No domains yet. Add one to route traffic to this project.\n </li>\n ) : null}\n </ul>\n </div>\n );\n },\n);\nDomainConfig.displayName = \"DomainConfig\";\n\nexport { DomainConfig };\n"]}
|
|
@@ -76,7 +76,7 @@ var TokenUsageChart = forwardRef(
|
|
|
76
76
|
{
|
|
77
77
|
"data-slot": "token-usage-chart",
|
|
78
78
|
ref,
|
|
79
|
-
className: cn("rounded-xl border bg-card p-4", className),
|
|
79
|
+
className: cn("rounded-xl border border-border bg-card p-4", className),
|
|
80
80
|
"aria-label": "Token usage over time",
|
|
81
81
|
...props,
|
|
82
82
|
children: [
|
|
@@ -232,5 +232,5 @@ var TokenUsageChart = forwardRef(
|
|
|
232
232
|
TokenUsageChart.displayName = "TokenUsageChart";
|
|
233
233
|
|
|
234
234
|
export { TokenUsageChart, splitUsagePoints, toUsageMetrics };
|
|
235
|
-
//# sourceMappingURL=chunk-
|
|
236
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-II5Q5RIO.js.map
|
|
236
|
+
//# sourceMappingURL=chunk-II5Q5RIO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/token-usage-chart/usage-metrics.ts","../src/components/primitives/token-usage-chart/token-usage-chart.tsx"],"names":["inputH","outputH"],"mappings":"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","file":"chunk-QCQTTOMD.js","sourcesContent":["/**\n * Pure aggregate + transpose helpers for `TokenUsagePoint[]` (M5-7).\n * No React — usable to drive metric displays, fixed-scale comparisons, or\n * other chart surfaces.\n */\nimport type { TokenUsagePoint } from \"./token-usage-chart.js\";\n\nexport interface UsageMetrics {\n totalInput: number;\n totalOutput: number;\n total: number;\n /** The largest per-period total (`input + output`); 0 for an empty series. */\n peak: number;\n pointCount: number;\n}\n\n/** Aggregate totals + the peak per-period total. Pure. */\nexport function toUsageMetrics(points: TokenUsagePoint[]): UsageMetrics {\n let totalInput = 0;\n let totalOutput = 0;\n let peak = 0;\n for (const p of points) {\n totalInput += p.input;\n totalOutput += p.output;\n const periodTotal = p.input + p.output;\n if (periodTotal > peak) peak = periodTotal;\n }\n return {\n totalInput,\n totalOutput,\n total: totalInput + totalOutput,\n peak,\n pointCount: points.length,\n };\n}\n\nexport interface UsageSeries {\n labels: string[];\n input: number[];\n output: number[];\n}\n\n/** Transpose stacked points into parallel `labels`/`input`/`output` arrays. Pure. */\nexport function splitUsagePoints(points: TokenUsagePoint[]): UsageSeries {\n return {\n labels: points.map((p) => p.label),\n input: points.map((p) => p.input),\n output: points.map((p) => p.output),\n };\n}\n","import { forwardRef, useMemo } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { toUsageMetrics } from \"./usage-metrics.js\";\n\nexport interface TokenUsagePoint {\n /** ISO date or friendly label for the x-axis tooltip. */\n label: string;\n /** Input tokens for this period (e.g. day). */\n input: number;\n /** Output tokens for this period. */\n output: number;\n}\n\ninterface TokenUsageChartProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n points: TokenUsagePoint[];\n /** Title above the chart. */\n title?: ReactNode;\n /** Chart height in px. Default 160. */\n height?: number;\n /** Show legend below the chart. Default true. */\n showLegend?: boolean;\n /**\n * Maximum number of bars to render. When `points.length` exceeds this, the\n * series is binned (summed in equal-width windows) so the chart stays\n * legible and SVG node count stays bounded. Default 60.\n */\n maxBars?: number;\n /**\n * Fix the y-axis maximum (the token value mapped to 100% height) so multiple\n * charts share a scale. When omitted, the scale auto-fits the data. Bars whose\n * value exceeds `maxScale` are clamped to 100% (the tooltip + a11y table still\n * show the true number).\n */\n maxScale?: number;\n /**\n * Render input and output as two adjacent (grouped) bars per period instead of\n * one stacked bar. Default false (stacked).\n */\n splitSeries?: boolean;\n}\n\nfunction binPoints(points: TokenUsagePoint[], maxBars: number): TokenUsagePoint[] {\n if (points.length <= maxBars) return points;\n const binSize = Math.ceil(points.length / maxBars);\n const out: TokenUsagePoint[] = [];\n for (let i = 0; i < points.length; i += binSize) {\n const slice = points.slice(i, i + binSize);\n if (slice.length === 0) continue;\n const first = slice[0]?.label ?? \"\";\n const last = slice[slice.length - 1]?.label ?? first;\n out.push({\n label: slice.length === 1 ? first : `${first}…${last}`,\n input: slice.reduce((a, p) => a + p.input, 0),\n output: slice.reduce((a, p) => a + p.output, 0),\n });\n }\n return out;\n}\n\nconst formatTokens = (n: number) => {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;\n return `${n}`;\n};\n\n/**\n * TokenUsageChart — stacked-bar chart of input vs output tokens over time.\n *\n * Pure SVG, no chart lib. Width is fluid; bars adjust to viewBox. Hover any\n * bar to see the breakdown in the tooltip slot below.\n */\nconst TokenUsageChart = forwardRef<HTMLDivElement, TokenUsageChartProps>(\n (\n {\n className,\n points,\n title = \"Token usage\",\n height = 160,\n showLegend = true,\n maxBars = 60,\n maxScale,\n splitSeries = false,\n ...props\n },\n ref,\n ) => {\n const series = useMemo(() => binPoints(points, maxBars), [points, maxBars]);\n const autoMax = Math.max(1, ...series.map((p) => p.input + p.output));\n const max = maxScale && maxScale > 0 ? maxScale : autoMax;\n const pct = (value: number): number => Math.min(100, (value / max) * 100);\n const barCount = series.length;\n const barWidth = 100 / Math.max(1, barCount);\n const gap = Math.min(2, barWidth * 0.2);\n const innerWidth = barWidth - gap;\n\n const total = toUsageMetrics(series).total;\n\n return (\n <section\n data-slot=\"token-usage-chart\"\n ref={ref}\n className={cn(\"rounded-xl border bg-card p-4\", className)}\n aria-label=\"Token usage over time\"\n {...props}\n >\n <header className=\"flex items-baseline justify-between gap-3\">\n {title ? (\n <h3 className=\"font-display text-title-md tracking-tight\">{title}</h3>\n ) : (\n <span />\n )}\n <span className=\"font-mono text-label text-muted-foreground tabular-nums\">\n total · {formatTokens(total)}\n </span>\n </header>\n <div className=\"mt-3 grid grid-cols-[auto_1fr] gap-2\">\n {/* Y-axis ticks */}\n <div\n className=\"grid font-mono text-label text-muted-foreground\"\n style={{ height, gridTemplateRows: \"1fr 1fr 1fr\" }}\n aria-hidden=\"true\"\n >\n <span className=\"tabular-nums\">{formatTokens(max)}</span>\n <span className=\"tabular-nums\">{formatTokens(max / 2)}</span>\n <span className=\"self-end tabular-nums\">0</span>\n </div>\n {/* Chart */}\n <svg\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n className=\"w-full\"\n style={{ height }}\n role=\"img\"\n aria-label={`Token usage across ${barCount} periods`}\n >\n {/* gridlines */}\n {[25, 50, 75].map((y) => (\n <line\n key={y}\n x1={0}\n y1={y}\n x2={100}\n y2={y}\n stroke=\"hsl(var(--border) / 0.4)\"\n strokeWidth={0.2}\n />\n ))}\n {series.map((p, idx) => {\n const x = idx * barWidth + gap / 2;\n const titleText = `${p.label} — input ${formatTokens(p.input)} · output ${formatTokens(p.output)}`;\n if (splitSeries) {\n // Grouped: input + output as two adjacent half-width bars, each\n // scaled independently (and clamped) to the scale.\n const half = innerWidth / 2;\n const inputH = pct(p.input);\n const outputH = pct(p.output);\n return (\n <g key={p.label}>\n <title>{titleText}</title>\n <rect\n x={x}\n y={100 - inputH}\n width={half}\n height={inputH}\n fill=\"hsl(var(--accent))\"\n opacity={0.85}\n />\n <rect\n x={x + half}\n y={100 - outputH}\n width={half}\n height={outputH}\n fill=\"hsl(var(--primary))\"\n opacity={0.85}\n />\n </g>\n );\n }\n // Stacked: output on top of input. The total is clamped to the\n // scale, then split PROPORTIONALLY so the two segments tile to the\n // clamped total without overlap (a bar over `maxScale` keeps its\n // input/output ratio instead of both segments hitting 100%).\n const periodTotal = p.input + p.output;\n const totalH = pct(periodTotal);\n const outputH = periodTotal > 0 ? (totalH * p.output) / periodTotal : 0;\n const inputH = totalH - outputH;\n return (\n <g key={p.label}>\n <title>{titleText}</title>\n {/* output (top, primary tone) */}\n <rect\n x={x}\n y={100 - totalH}\n width={innerWidth}\n height={outputH}\n fill=\"hsl(var(--primary))\"\n opacity={0.85}\n />\n {/* input (bottom, accent tone) */}\n <rect\n x={x}\n y={100 - inputH}\n width={innerWidth}\n height={inputH}\n fill=\"hsl(var(--accent))\"\n opacity={0.85}\n />\n </g>\n );\n })}\n </svg>\n </div>\n {/* x-axis labels — aligned with the chart column of the parent grid */}\n <div\n className=\"mt-1 grid grid-cols-[auto_1fr] gap-2 font-mono text-label text-muted-foreground\"\n aria-hidden=\"true\"\n >\n <span aria-hidden=\"true\" />\n <div className=\"grid\" style={{ gridTemplateColumns: `repeat(${barCount}, 1fr)` }}>\n {series.map((p) => (\n <span key={p.label} className=\"truncate text-center\">\n {p.label}\n </span>\n ))}\n </div>\n </div>\n {/* Screen-reader fallback: the SVG is decorative-ish for AT users.\n * `<title>` per bar is unreliably exposed across NVDA/VoiceOver/JAWS,\n * so we ship an `sr-only` table with the same data. Sighted users\n * never see this; AT users can navigate the values cell-by-cell.\n * Reference: WCAG 1.1.1 (Non-text content). */}\n <table className=\"sr-only\">\n <caption>Token usage by period — input vs output</caption>\n <thead>\n <tr>\n <th scope=\"col\">Period</th>\n <th scope=\"col\">Input tokens</th>\n <th scope=\"col\">Output tokens</th>\n </tr>\n </thead>\n <tbody>\n {series.map((p) => (\n <tr key={`a11y-${p.label}`}>\n <td>{p.label}</td>\n <td>{p.input}</td>\n <td>{p.output}</td>\n </tr>\n ))}\n </tbody>\n </table>\n {showLegend ? (\n <footer className=\"mt-3 flex items-center gap-4 font-mono text-label text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1.5\">\n <span className=\"size-2 rounded-sm bg-accent\" aria-hidden=\"true\" />\n Input\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <span className=\"size-2 rounded-sm bg-primary\" aria-hidden=\"true\" />\n Output\n </span>\n </footer>\n ) : null}\n </section>\n );\n },\n);\nTokenUsageChart.displayName = \"TokenUsageChart\";\n\nexport { TokenUsageChart };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/token-usage-chart/usage-metrics.ts","../src/components/primitives/token-usage-chart/token-usage-chart.tsx"],"names":["inputH","outputH"],"mappings":"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","file":"chunk-II5Q5RIO.js","sourcesContent":["/**\n * Pure aggregate + transpose helpers for `TokenUsagePoint[]` (M5-7).\n * No React — usable to drive metric displays, fixed-scale comparisons, or\n * other chart surfaces.\n */\nimport type { TokenUsagePoint } from \"./token-usage-chart.js\";\n\nexport interface UsageMetrics {\n totalInput: number;\n totalOutput: number;\n total: number;\n /** The largest per-period total (`input + output`); 0 for an empty series. */\n peak: number;\n pointCount: number;\n}\n\n/** Aggregate totals + the peak per-period total. Pure. */\nexport function toUsageMetrics(points: TokenUsagePoint[]): UsageMetrics {\n let totalInput = 0;\n let totalOutput = 0;\n let peak = 0;\n for (const p of points) {\n totalInput += p.input;\n totalOutput += p.output;\n const periodTotal = p.input + p.output;\n if (periodTotal > peak) peak = periodTotal;\n }\n return {\n totalInput,\n totalOutput,\n total: totalInput + totalOutput,\n peak,\n pointCount: points.length,\n };\n}\n\nexport interface UsageSeries {\n labels: string[];\n input: number[];\n output: number[];\n}\n\n/** Transpose stacked points into parallel `labels`/`input`/`output` arrays. Pure. */\nexport function splitUsagePoints(points: TokenUsagePoint[]): UsageSeries {\n return {\n labels: points.map((p) => p.label),\n input: points.map((p) => p.input),\n output: points.map((p) => p.output),\n };\n}\n","import { forwardRef, useMemo } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { toUsageMetrics } from \"./usage-metrics.js\";\n\nexport interface TokenUsagePoint {\n /** ISO date or friendly label for the x-axis tooltip. */\n label: string;\n /** Input tokens for this period (e.g. day). */\n input: number;\n /** Output tokens for this period. */\n output: number;\n}\n\ninterface TokenUsageChartProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n points: TokenUsagePoint[];\n /** Title above the chart. */\n title?: ReactNode;\n /** Chart height in px. Default 160. */\n height?: number;\n /** Show legend below the chart. Default true. */\n showLegend?: boolean;\n /**\n * Maximum number of bars to render. When `points.length` exceeds this, the\n * series is binned (summed in equal-width windows) so the chart stays\n * legible and SVG node count stays bounded. Default 60.\n */\n maxBars?: number;\n /**\n * Fix the y-axis maximum (the token value mapped to 100% height) so multiple\n * charts share a scale. When omitted, the scale auto-fits the data. Bars whose\n * value exceeds `maxScale` are clamped to 100% (the tooltip + a11y table still\n * show the true number).\n */\n maxScale?: number;\n /**\n * Render input and output as two adjacent (grouped) bars per period instead of\n * one stacked bar. Default false (stacked).\n */\n splitSeries?: boolean;\n}\n\nfunction binPoints(points: TokenUsagePoint[], maxBars: number): TokenUsagePoint[] {\n if (points.length <= maxBars) return points;\n const binSize = Math.ceil(points.length / maxBars);\n const out: TokenUsagePoint[] = [];\n for (let i = 0; i < points.length; i += binSize) {\n const slice = points.slice(i, i + binSize);\n if (slice.length === 0) continue;\n const first = slice[0]?.label ?? \"\";\n const last = slice[slice.length - 1]?.label ?? first;\n out.push({\n label: slice.length === 1 ? first : `${first}…${last}`,\n input: slice.reduce((a, p) => a + p.input, 0),\n output: slice.reduce((a, p) => a + p.output, 0),\n });\n }\n return out;\n}\n\nconst formatTokens = (n: number) => {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;\n return `${n}`;\n};\n\n/**\n * TokenUsageChart — stacked-bar chart of input vs output tokens over time.\n *\n * Pure SVG, no chart lib. Width is fluid; bars adjust to viewBox. Hover any\n * bar to see the breakdown in the tooltip slot below.\n */\nconst TokenUsageChart = forwardRef<HTMLDivElement, TokenUsageChartProps>(\n (\n {\n className,\n points,\n title = \"Token usage\",\n height = 160,\n showLegend = true,\n maxBars = 60,\n maxScale,\n splitSeries = false,\n ...props\n },\n ref,\n ) => {\n const series = useMemo(() => binPoints(points, maxBars), [points, maxBars]);\n const autoMax = Math.max(1, ...series.map((p) => p.input + p.output));\n const max = maxScale && maxScale > 0 ? maxScale : autoMax;\n const pct = (value: number): number => Math.min(100, (value / max) * 100);\n const barCount = series.length;\n const barWidth = 100 / Math.max(1, barCount);\n const gap = Math.min(2, barWidth * 0.2);\n const innerWidth = barWidth - gap;\n\n const total = toUsageMetrics(series).total;\n\n return (\n <section\n data-slot=\"token-usage-chart\"\n ref={ref}\n className={cn(\"rounded-xl border border-border bg-card p-4\", className)}\n aria-label=\"Token usage over time\"\n {...props}\n >\n <header className=\"flex items-baseline justify-between gap-3\">\n {title ? (\n <h3 className=\"font-display text-title-md tracking-tight\">{title}</h3>\n ) : (\n <span />\n )}\n <span className=\"font-mono text-label text-muted-foreground tabular-nums\">\n total · {formatTokens(total)}\n </span>\n </header>\n <div className=\"mt-3 grid grid-cols-[auto_1fr] gap-2\">\n {/* Y-axis ticks */}\n <div\n className=\"grid font-mono text-label text-muted-foreground\"\n style={{ height, gridTemplateRows: \"1fr 1fr 1fr\" }}\n aria-hidden=\"true\"\n >\n <span className=\"tabular-nums\">{formatTokens(max)}</span>\n <span className=\"tabular-nums\">{formatTokens(max / 2)}</span>\n <span className=\"self-end tabular-nums\">0</span>\n </div>\n {/* Chart */}\n <svg\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\"\n className=\"w-full\"\n style={{ height }}\n role=\"img\"\n aria-label={`Token usage across ${barCount} periods`}\n >\n {/* gridlines */}\n {[25, 50, 75].map((y) => (\n <line\n key={y}\n x1={0}\n y1={y}\n x2={100}\n y2={y}\n stroke=\"hsl(var(--border) / 0.4)\"\n strokeWidth={0.2}\n />\n ))}\n {series.map((p, idx) => {\n const x = idx * barWidth + gap / 2;\n const titleText = `${p.label} — input ${formatTokens(p.input)} · output ${formatTokens(p.output)}`;\n if (splitSeries) {\n // Grouped: input + output as two adjacent half-width bars, each\n // scaled independently (and clamped) to the scale.\n const half = innerWidth / 2;\n const inputH = pct(p.input);\n const outputH = pct(p.output);\n return (\n <g key={p.label}>\n <title>{titleText}</title>\n <rect\n x={x}\n y={100 - inputH}\n width={half}\n height={inputH}\n fill=\"hsl(var(--accent))\"\n opacity={0.85}\n />\n <rect\n x={x + half}\n y={100 - outputH}\n width={half}\n height={outputH}\n fill=\"hsl(var(--primary))\"\n opacity={0.85}\n />\n </g>\n );\n }\n // Stacked: output on top of input. The total is clamped to the\n // scale, then split PROPORTIONALLY so the two segments tile to the\n // clamped total without overlap (a bar over `maxScale` keeps its\n // input/output ratio instead of both segments hitting 100%).\n const periodTotal = p.input + p.output;\n const totalH = pct(periodTotal);\n const outputH = periodTotal > 0 ? (totalH * p.output) / periodTotal : 0;\n const inputH = totalH - outputH;\n return (\n <g key={p.label}>\n <title>{titleText}</title>\n {/* output (top, primary tone) */}\n <rect\n x={x}\n y={100 - totalH}\n width={innerWidth}\n height={outputH}\n fill=\"hsl(var(--primary))\"\n opacity={0.85}\n />\n {/* input (bottom, accent tone) */}\n <rect\n x={x}\n y={100 - inputH}\n width={innerWidth}\n height={inputH}\n fill=\"hsl(var(--accent))\"\n opacity={0.85}\n />\n </g>\n );\n })}\n </svg>\n </div>\n {/* x-axis labels — aligned with the chart column of the parent grid */}\n <div\n className=\"mt-1 grid grid-cols-[auto_1fr] gap-2 font-mono text-label text-muted-foreground\"\n aria-hidden=\"true\"\n >\n <span aria-hidden=\"true\" />\n <div className=\"grid\" style={{ gridTemplateColumns: `repeat(${barCount}, 1fr)` }}>\n {series.map((p) => (\n <span key={p.label} className=\"truncate text-center\">\n {p.label}\n </span>\n ))}\n </div>\n </div>\n {/* Screen-reader fallback: the SVG is decorative-ish for AT users.\n * `<title>` per bar is unreliably exposed across NVDA/VoiceOver/JAWS,\n * so we ship an `sr-only` table with the same data. Sighted users\n * never see this; AT users can navigate the values cell-by-cell.\n * Reference: WCAG 1.1.1 (Non-text content). */}\n <table className=\"sr-only\">\n <caption>Token usage by period — input vs output</caption>\n <thead>\n <tr>\n <th scope=\"col\">Period</th>\n <th scope=\"col\">Input tokens</th>\n <th scope=\"col\">Output tokens</th>\n </tr>\n </thead>\n <tbody>\n {series.map((p) => (\n <tr key={`a11y-${p.label}`}>\n <td>{p.label}</td>\n <td>{p.input}</td>\n <td>{p.output}</td>\n </tr>\n ))}\n </tbody>\n </table>\n {showLegend ? (\n <footer className=\"mt-3 flex items-center gap-4 font-mono text-label text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1.5\">\n <span className=\"size-2 rounded-sm bg-accent\" aria-hidden=\"true\" />\n Input\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <span className=\"size-2 rounded-sm bg-primary\" aria-hidden=\"true\" />\n Output\n </span>\n </footer>\n ) : null}\n </section>\n );\n },\n);\nTokenUsageChart.displayName = \"TokenUsageChart\";\n\nexport { TokenUsageChart };\n"]}
|
|
@@ -39,7 +39,7 @@ var PreviewEnvCard = forwardRef(
|
|
|
39
39
|
"data-slot": "preview-env-card",
|
|
40
40
|
ref,
|
|
41
41
|
className: cn(
|
|
42
|
-
"rounded-xl border bg-card p-5 shadow-sm",
|
|
42
|
+
"rounded-xl border border-border bg-card p-5 shadow-sm",
|
|
43
43
|
"transition-[border-color,box-shadow] duration-base ease-out-soft",
|
|
44
44
|
"hover:border-primary/40",
|
|
45
45
|
className
|
|
@@ -117,5 +117,5 @@ var PreviewEnvCard = forwardRef(
|
|
|
117
117
|
PreviewEnvCard.displayName = "PreviewEnvCard";
|
|
118
118
|
|
|
119
119
|
export { PreviewEnvCard };
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
120
|
+
//# sourceMappingURL=chunk-ITEIRMSH.js.map
|
|
121
|
+
//# sourceMappingURL=chunk-ITEIRMSH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/preview-env-card/preview-env-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,WAAA,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;AACA,IAAM,YAAA,GAAiD;AAAA,EACrD,MAAA,EAAQ,QAAA;AAAA,EACR,QAAA,EAAU,UAAA;AAAA,EACV,SAAA,EAAW,WAAA;AAAA,EACX,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA,EACX,IAAA,EAAM;AACR,CAAA;AAkCA,IAAM,cAAA,GAAiB,UAAA;AAAA,EACrB,CAAC,EAAE,SAAA,EAAW,GAAA,EAAK,SAAS,GAAG,KAAA,IAAS,GAAA,qBACtC,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,kBAAA;AAAA,MACV,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/preview-env-card/preview-env-card.tsx"],"names":[],"mappings":"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","file":"chunk-ITEIRMSH.js","sourcesContent":["import { ExternalLink, GitPullRequest, Server } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } 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 statusToDot: 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};\nconst statusLabels: Record<DeploymentStatus, string> = {\n queued: \"Queued\",\n building: \"Building\",\n deploying: \"Deploying\",\n live: \"Live\",\n failed: \"Failed\",\n cancelled: \"Cancelled\",\n idle: \"Idle\",\n};\n\nexport interface PreviewService {\n /** Service name e.g. \"api\", \"web\", \"worker\". */\n name: string;\n /** Live URL or null if not exposed (worker). */\n url?: string;\n status: DeploymentStatus;\n}\n\nexport interface PreviewEnv {\n id: string;\n prNumber: number;\n prTitle: string;\n branch: string;\n author?: { name: string; avatarUrl?: string };\n services: PreviewService[];\n createdAt: string;\n}\n\ninterface PreviewEnvCardProps extends HTMLAttributes<HTMLDivElement> {\n env: PreviewEnv;\n actions?: ReactNode;\n}\n\n/**\n * PreviewEnvCard — preview environment card surfacing all services from one PR.\n *\n * Theo's killer feature: full-stack preview environments. The card shows:\n * - PR number + title at the top\n * - branch + author in the metadata row\n * - one badge per service with its own status + URL\n * - bottom action row (Open, Promote, Delete)\n */\nconst PreviewEnvCard = forwardRef<HTMLDivElement, PreviewEnvCardProps>(\n ({ className, env, actions, ...props }, ref) => (\n <article\n data-slot=\"preview-env-card\"\n ref={ref}\n className={cn(\n \"rounded-xl border border-border bg-card p-5 shadow-sm\",\n \"transition-[border-color,box-shadow] duration-base ease-out-soft\",\n \"hover:border-primary/40\",\n className,\n )}\n {...(props as HTMLAttributes<HTMLDivElement>)}\n >\n <header className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <p className=\"flex items-center gap-2 font-mono text-label-caps text-muted-foreground uppercase\">\n <GitPullRequest className=\"size-3\" /> PR #{env.prNumber}\n </p>\n <h3 className=\"mt-1 truncate font-display text-title-md tracking-tight\">{env.prTitle}</h3>\n <p className=\"mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-body-sm text-muted-foreground\">\n <span className=\"font-mono text-code-sm\">{env.branch}</span>\n {env.author ? (\n <>\n <span aria-hidden=\"true\">·</span>\n <span>by {env.author.name}</span>\n </>\n ) : null}\n <span aria-hidden=\"true\">·</span>\n <span>opened {env.createdAt}</span>\n </p>\n </div>\n <Badge variant=\"primary\">\n <Server className=\"size-3\" /> {env.services.length} service\n {env.services.length === 1 ? \"\" : \"s\"}\n </Badge>\n </header>\n\n <ul className=\"mt-4 divide-y divide-border/30 rounded-lg border border-border/30\">\n {env.services.map((s) => {\n // T3.3 (SEC-003): defang dangerous URL protocols before rendering\n // as <a href>. Consumers passing user-controlled URLs from API\n // responses are protected from javascript:/vbscript:/data:text/html\n // XSS payloads.\n const sanitized = safeHref(s.url);\n return (\n <li key={s.name} className=\"flex items-center justify-between gap-3 px-3 py-2\">\n <span className=\"font-mono text-code-sm text-foreground\">{s.name}</span>\n <div className=\"flex items-center gap-2\">\n {sanitized ? (\n <a\n href={sanitized}\n className=\"inline-flex items-center gap-1 font-mono text-code-sm text-primary hover:underline\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {sanitized.replace(/^https?:\\/\\//, \"\")}\n <ExternalLink className=\"size-3\" />\n </a>\n ) : (\n <span className=\"font-mono text-code-sm text-muted-foreground\">internal</span>\n )}\n <Badge variant={statusToVariant[s.status]}>\n <Badge.Dot\n tone={statusToDot[s.status]}\n pulse={\n s.status === \"building\" || s.status === \"deploying\" || s.status === \"queued\"\n }\n />\n {statusLabels[s.status]}\n </Badge>\n </div>\n </li>\n );\n })}\n </ul>\n\n {actions ? <div className=\"mt-4 flex items-center gap-2\">{actions}</div> : null}\n </article>\n ),\n);\nPreviewEnvCard.displayName = \"PreviewEnvCard\";\n\nexport { PreviewEnvCard };\n"]}
|
|
@@ -132,7 +132,7 @@ var PinInput = forwardRef(
|
|
|
132
132
|
onPaste: (e) => handlePaste(i, e),
|
|
133
133
|
"aria-label": `Digit ${i + 1} of ${length}`,
|
|
134
134
|
className: cn(
|
|
135
|
-
"rounded-md border bg-card text-center font-medium font-mono",
|
|
135
|
+
"rounded-md border border-border bg-card text-center font-medium font-mono",
|
|
136
136
|
"transition-colors",
|
|
137
137
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
138
138
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
@@ -150,5 +150,5 @@ var PinInput = forwardRef(
|
|
|
150
150
|
PinInput.displayName = "PinInput";
|
|
151
151
|
|
|
152
152
|
export { PinInput };
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
154
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-JP3SHERK.js.map
|
|
154
|
+
//# sourceMappingURL=chunk-JP3SHERK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/pin-input/pin-input.tsx"],"names":["next"],"mappings":"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","file":"chunk-JQTCCKZA.js","sourcesContent":["\"use client\";\n\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport type { ClipboardEvent, HTMLAttributes, KeyboardEvent } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\n/**\n * PinInput — multi-slot OTP / code input primitive.\n *\n * Renders N separate boxes (default 6) that auto-advance focus on\n * input. Paste handling fills all slots from clipboard (whitespace\n * stripped). Arrow keys navigate; backspace clears current slot\n * then moves focus back when empty.\n *\n * Industry-standard pattern for email verification codes (Apple,\n * Stripe, Clerk, Auth0, GitHub two-factor).\n *\n * @example\n * <PinInput\n * length={6}\n * value={code}\n * onChange={setCode}\n * onComplete={(v) => verify(v)}\n * inputMode=\"numeric\"\n * aria-label=\"Verification code\"\n * />\n *\n * Note: value is treated as controlled. If you pass a complete value\n * on mount, onComplete will NOT fire — onComplete fires only on\n * transitions from incomplete → complete.\n */\nexport interface PinInputProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\" | \"inputMode\"> {\n length?: number;\n value?: string;\n onChange?: (value: string) => void;\n onComplete?: (value: string) => void;\n inputMode?: \"numeric\" | \"alphanumeric\";\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n error?: boolean;\n \"aria-label\": string;\n autoFocus?: boolean;\n mask?: boolean;\n}\n\nconst SIZE_CLASS: Record<NonNullable<PinInputProps[\"size\"]>, string> = {\n sm: \"size-8 text-body-sm\",\n md: \"size-10 text-body-md\",\n lg: \"size-12 text-title-sm\",\n};\n\nfunction sanitize(raw: string, inputMode: \"numeric\" | \"alphanumeric\"): string {\n const noWhitespace = raw.replace(/\\s/g, \"\");\n if (inputMode === \"numeric\") {\n return noWhitespace.replace(/\\D/g, \"\");\n }\n return noWhitespace.toUpperCase().replace(/[^A-Z0-9]/g, \"\");\n}\n\nconst PinInput = forwardRef<HTMLDivElement, PinInputProps>(\n (\n {\n className,\n length = 6,\n value = \"\",\n onChange,\n onComplete,\n inputMode = \"numeric\",\n size = \"md\",\n disabled = false,\n error = false,\n autoFocus = false,\n mask = false,\n \"aria-label\": ariaLabel,\n ...props\n },\n ref,\n ) => {\n const inputRefs = useRef<Array<HTMLInputElement | null>>([]);\n const wasCompleteRef = useRef<boolean>(value.length === length);\n\n // Auto-focus first slot on mount (SSR-safe)\n useEffect(() => {\n if (!autoFocus) return;\n if (typeof window === \"undefined\") return;\n inputRefs.current[0]?.focus();\n }, [autoFocus]);\n\n // Fire onComplete on transitions from incomplete → complete\n useEffect(() => {\n const isComplete = value.length === length && value.length > 0;\n if (isComplete && !wasCompleteRef.current) {\n onComplete?.(value);\n }\n wasCompleteRef.current = isComplete;\n }, [value, length, onComplete]);\n\n function commit(next: string) {\n const sanitized = sanitize(next, inputMode).slice(0, length);\n onChange?.(sanitized);\n }\n\n function handleChange(slot: number, raw: string) {\n const sanitized = sanitize(raw, inputMode);\n if (sanitized.length === 0) {\n // Clear current slot\n const next = `${value.slice(0, slot)}${value.slice(slot + 1)}`;\n commit(next);\n return;\n }\n // Take the last character typed (handles browser autocomplete that fills multiple)\n const ch = sanitized[sanitized.length - 1] ?? \"\";\n const next = `${value.slice(0, slot)}${ch}${value.slice(slot + 1)}`;\n commit(next);\n // Advance focus\n if (slot < length - 1) {\n inputRefs.current[slot + 1]?.focus();\n }\n }\n\n function handleKeyDown(slot: number, e: KeyboardEvent<HTMLInputElement>) {\n if (disabled) return;\n const slotChar = value[slot] ?? \"\";\n\n if (e.key === \"Backspace\") {\n if (slotChar === \"\") {\n // Move focus back if current is empty\n if (slot > 0) {\n inputRefs.current[slot - 1]?.focus();\n }\n } else {\n // Clear current slot, stay focused\n const next = `${value.slice(0, slot)}${value.slice(slot + 1)}`;\n commit(next);\n }\n e.preventDefault();\n } else if (e.key === \"ArrowLeft\") {\n if (slot > 0) inputRefs.current[slot - 1]?.focus();\n e.preventDefault();\n } else if (e.key === \"ArrowRight\") {\n if (slot < length - 1) inputRefs.current[slot + 1]?.focus();\n e.preventDefault();\n }\n }\n\n function handlePaste(slot: number, e: ClipboardEvent<HTMLInputElement>) {\n if (disabled) return;\n e.preventDefault();\n const pasted = e.clipboardData.getData(\"text/plain\");\n const sanitized = sanitize(pasted, inputMode);\n if (sanitized.length === 0) return;\n // Build slot-indexed array, then overwrite from `slot` onwards.\n // Previous string-concat approach didn't pad when value was shorter\n // than `slot`, which made paste-from-middle-when-empty fill from 0.\n const slotArr: string[] = Array.from({ length }, (_, i) => value[i] ?? \"\");\n const remaining = length - slot;\n const filled = sanitized.slice(0, remaining);\n for (let i = 0; i < filled.length; i++) {\n slotArr[slot + i] = filled[i] ?? \"\";\n }\n const next = slotArr.join(\"\");\n commit(next);\n // Focus the slot after the last filled, or the last slot if completed\n const focusAt = Math.min(slot + filled.length, length - 1);\n requestAnimationFrame(() => inputRefs.current[focusAt]?.focus());\n }\n\n const slots = Array.from({ length }, (_, i) => i);\n\n return (\n <div\n data-slot=\"pin-input\"\n ref={ref}\n // biome-ignore lint/a11y/useSemanticElements: <fieldset> would force a different visual layout (rectangular border by default) and is form-bound; we use a div with role=\"group\" + aria-label for grouping semantics.\n role=\"group\"\n aria-label={ariaLabel}\n className={cn(\"inline-flex items-center gap-2\", className)}\n {...props}\n >\n {slots.map((i) => {\n const ch = value[i] ?? \"\";\n const display = mask && ch !== \"\" ? \"•\" : ch;\n return (\n <input\n key={i}\n ref={(el) => {\n inputRefs.current[i] = el;\n }}\n type=\"text\"\n inputMode={inputMode === \"numeric\" ? \"numeric\" : \"text\"}\n pattern={inputMode === \"numeric\" ? \"[0-9]*\" : undefined}\n maxLength={1}\n autoComplete={i === 0 ? \"one-time-code\" : \"off\"}\n disabled={disabled}\n value={display}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={(e) => handlePaste(i, e)}\n aria-label={`Digit ${i + 1} of ${length}`}\n className={cn(\n \"rounded-md border bg-card text-center font-medium font-mono\",\n \"transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n SIZE_CLASS[size],\n error ? \"border-destructive\" : \"border-border/60 hover:border-border\",\n )}\n />\n );\n })}\n </div>\n );\n },\n);\nPinInput.displayName = \"PinInput\";\n\nexport { PinInput };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/pin-input/pin-input.tsx"],"names":["next"],"mappings":"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","file":"chunk-JP3SHERK.js","sourcesContent":["\"use client\";\n\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport type { ClipboardEvent, HTMLAttributes, KeyboardEvent } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\n/**\n * PinInput — multi-slot OTP / code input primitive.\n *\n * Renders N separate boxes (default 6) that auto-advance focus on\n * input. Paste handling fills all slots from clipboard (whitespace\n * stripped). Arrow keys navigate; backspace clears current slot\n * then moves focus back when empty.\n *\n * Industry-standard pattern for email verification codes (Apple,\n * Stripe, Clerk, Auth0, GitHub two-factor).\n *\n * @example\n * <PinInput\n * length={6}\n * value={code}\n * onChange={setCode}\n * onComplete={(v) => verify(v)}\n * inputMode=\"numeric\"\n * aria-label=\"Verification code\"\n * />\n *\n * Note: value is treated as controlled. If you pass a complete value\n * on mount, onComplete will NOT fire — onComplete fires only on\n * transitions from incomplete → complete.\n */\nexport interface PinInputProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onChange\" | \"inputMode\"> {\n length?: number;\n value?: string;\n onChange?: (value: string) => void;\n onComplete?: (value: string) => void;\n inputMode?: \"numeric\" | \"alphanumeric\";\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n error?: boolean;\n \"aria-label\": string;\n autoFocus?: boolean;\n mask?: boolean;\n}\n\nconst SIZE_CLASS: Record<NonNullable<PinInputProps[\"size\"]>, string> = {\n sm: \"size-8 text-body-sm\",\n md: \"size-10 text-body-md\",\n lg: \"size-12 text-title-sm\",\n};\n\nfunction sanitize(raw: string, inputMode: \"numeric\" | \"alphanumeric\"): string {\n const noWhitespace = raw.replace(/\\s/g, \"\");\n if (inputMode === \"numeric\") {\n return noWhitespace.replace(/\\D/g, \"\");\n }\n return noWhitespace.toUpperCase().replace(/[^A-Z0-9]/g, \"\");\n}\n\nconst PinInput = forwardRef<HTMLDivElement, PinInputProps>(\n (\n {\n className,\n length = 6,\n value = \"\",\n onChange,\n onComplete,\n inputMode = \"numeric\",\n size = \"md\",\n disabled = false,\n error = false,\n autoFocus = false,\n mask = false,\n \"aria-label\": ariaLabel,\n ...props\n },\n ref,\n ) => {\n const inputRefs = useRef<Array<HTMLInputElement | null>>([]);\n const wasCompleteRef = useRef<boolean>(value.length === length);\n\n // Auto-focus first slot on mount (SSR-safe)\n useEffect(() => {\n if (!autoFocus) return;\n if (typeof window === \"undefined\") return;\n inputRefs.current[0]?.focus();\n }, [autoFocus]);\n\n // Fire onComplete on transitions from incomplete → complete\n useEffect(() => {\n const isComplete = value.length === length && value.length > 0;\n if (isComplete && !wasCompleteRef.current) {\n onComplete?.(value);\n }\n wasCompleteRef.current = isComplete;\n }, [value, length, onComplete]);\n\n function commit(next: string) {\n const sanitized = sanitize(next, inputMode).slice(0, length);\n onChange?.(sanitized);\n }\n\n function handleChange(slot: number, raw: string) {\n const sanitized = sanitize(raw, inputMode);\n if (sanitized.length === 0) {\n // Clear current slot\n const next = `${value.slice(0, slot)}${value.slice(slot + 1)}`;\n commit(next);\n return;\n }\n // Take the last character typed (handles browser autocomplete that fills multiple)\n const ch = sanitized[sanitized.length - 1] ?? \"\";\n const next = `${value.slice(0, slot)}${ch}${value.slice(slot + 1)}`;\n commit(next);\n // Advance focus\n if (slot < length - 1) {\n inputRefs.current[slot + 1]?.focus();\n }\n }\n\n function handleKeyDown(slot: number, e: KeyboardEvent<HTMLInputElement>) {\n if (disabled) return;\n const slotChar = value[slot] ?? \"\";\n\n if (e.key === \"Backspace\") {\n if (slotChar === \"\") {\n // Move focus back if current is empty\n if (slot > 0) {\n inputRefs.current[slot - 1]?.focus();\n }\n } else {\n // Clear current slot, stay focused\n const next = `${value.slice(0, slot)}${value.slice(slot + 1)}`;\n commit(next);\n }\n e.preventDefault();\n } else if (e.key === \"ArrowLeft\") {\n if (slot > 0) inputRefs.current[slot - 1]?.focus();\n e.preventDefault();\n } else if (e.key === \"ArrowRight\") {\n if (slot < length - 1) inputRefs.current[slot + 1]?.focus();\n e.preventDefault();\n }\n }\n\n function handlePaste(slot: number, e: ClipboardEvent<HTMLInputElement>) {\n if (disabled) return;\n e.preventDefault();\n const pasted = e.clipboardData.getData(\"text/plain\");\n const sanitized = sanitize(pasted, inputMode);\n if (sanitized.length === 0) return;\n // Build slot-indexed array, then overwrite from `slot` onwards.\n // Previous string-concat approach didn't pad when value was shorter\n // than `slot`, which made paste-from-middle-when-empty fill from 0.\n const slotArr: string[] = Array.from({ length }, (_, i) => value[i] ?? \"\");\n const remaining = length - slot;\n const filled = sanitized.slice(0, remaining);\n for (let i = 0; i < filled.length; i++) {\n slotArr[slot + i] = filled[i] ?? \"\";\n }\n const next = slotArr.join(\"\");\n commit(next);\n // Focus the slot after the last filled, or the last slot if completed\n const focusAt = Math.min(slot + filled.length, length - 1);\n requestAnimationFrame(() => inputRefs.current[focusAt]?.focus());\n }\n\n const slots = Array.from({ length }, (_, i) => i);\n\n return (\n <div\n data-slot=\"pin-input\"\n ref={ref}\n // biome-ignore lint/a11y/useSemanticElements: <fieldset> would force a different visual layout (rectangular border by default) and is form-bound; we use a div with role=\"group\" + aria-label for grouping semantics.\n role=\"group\"\n aria-label={ariaLabel}\n className={cn(\"inline-flex items-center gap-2\", className)}\n {...props}\n >\n {slots.map((i) => {\n const ch = value[i] ?? \"\";\n const display = mask && ch !== \"\" ? \"•\" : ch;\n return (\n <input\n key={i}\n ref={(el) => {\n inputRefs.current[i] = el;\n }}\n type=\"text\"\n inputMode={inputMode === \"numeric\" ? \"numeric\" : \"text\"}\n pattern={inputMode === \"numeric\" ? \"[0-9]*\" : undefined}\n maxLength={1}\n autoComplete={i === 0 ? \"one-time-code\" : \"off\"}\n disabled={disabled}\n value={display}\n onChange={(e) => handleChange(i, e.target.value)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={(e) => handlePaste(i, e)}\n aria-label={`Digit ${i + 1} of ${length}`}\n className={cn(\n \"rounded-md border border-border bg-card text-center font-medium font-mono\",\n \"transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n SIZE_CLASS[size],\n error ? \"border-destructive\" : \"border-border/60 hover:border-border\",\n )}\n />\n );\n })}\n </div>\n );\n },\n);\nPinInput.displayName = \"PinInput\";\n\nexport { PinInput };\n"]}
|
|
@@ -9,7 +9,7 @@ var MetricsPanel = forwardRef(
|
|
|
9
9
|
{
|
|
10
10
|
"data-slot": "metrics-panel",
|
|
11
11
|
ref,
|
|
12
|
-
className: cn("rounded-xl border bg-card p-5 shadow-sm", className),
|
|
12
|
+
className: cn("rounded-xl border border-border bg-card p-5 shadow-sm", className),
|
|
13
13
|
...props,
|
|
14
14
|
children: [
|
|
15
15
|
title || description ? /* @__PURE__ */ jsxs("header", { className: "mb-4 grid gap-0.5", children: [
|
|
@@ -82,5 +82,5 @@ function Sparkline({ values }) {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export { MetricsPanel };
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
85
|
+
//# sourceMappingURL=chunk-JS5T2CRO.js.map
|
|
86
|
+
//# sourceMappingURL=chunk-JS5T2CRO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/metrics-panel/metrics-panel.tsx"],"names":[],"mappings":";;;;;AAkEA,IAAM,YAAA,GAAe,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,WAAA,EAAa,SAAS,OAAA,EAAS,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC9D,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,eAAA;AAAA,MACV,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/metrics-panel/metrics-panel.tsx"],"names":[],"mappings":";;;;;AAkEA,IAAM,YAAA,GAAe,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,WAAA,EAAa,SAAS,OAAA,EAAS,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC9D,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,eAAA;AAAA,MACV,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,uDAAA,EAAyD,SAAS,CAAA;AAAA,MAC/E,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA;AAAA,QAAA,KAAA,IAAS,WAAA,mBACR,IAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,mBAAA,EACf,QAAA,EAAA;AAAA,UAAA,KAAA,mBAAQ,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,2CAAA,EAA6C,iBAAM,CAAA,GAAQ,IAAA;AAAA,UACjF,8BAAc,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,oCAAA,EAAsC,uBAAY,CAAA,GAAO;AAAA,SAAA,EACvF,CAAA,GACE,IAAA;AAAA,wBACJ,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,YAAA;AAAA,YACV,KAAA,EAAO;AAAA,cACL,mBAAA,EAAqB,OAAA,GACjB,CAAA,OAAA,EAAU,OAAO,CAAA,iBAAA,CAAA,GACjB;AAAA,aACN;AAAA,YAEC,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,qBACZ,GAAA,CAAC,QAAmB,MAAA,EAAQ,CAAA,EAAA,EAAjB,CAAA,CAAE,KAAkB,CAChC;AAAA;AAAA;AACH;AAAA;AAAA;AAGN;AACA,YAAA,CAAa,WAAA,GAAc,cAAA;AAE3B,SAAS,IAAA,CAAK,EAAE,MAAA,EAAO,EAAuB;AAC5C,EAAA,MAAM,WAAA,GAAc,OAAO,OAAA,KAAY,MAAA;AACvC,EAAA,MAAM,GAAA,GAAM,cAAc,QAAA,GAAW,KAAA;AAKrC,EAAA,MAAM,YAAY,WAAA,GACb,MAAA,CAAO,eAAe,CAAA,KAAA,EAAQ,MAAA,CAAO,KAAK,CAAA,QAAA,CAAA,GAC3C,MAAA;AACJ,EAAA,uBACE,IAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,cAAc,QAAA,GAAW,MAAA;AAAA,MAC/B,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,YAAA,EAAY,SAAA;AAAA,MACZ,SAAA,EAAW,EAAA;AAAA,QACT,kFAAA;AAAA,QACA,+CAAA;AAAA,QACA,WAAA,IACE;AAAA,OACJ;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2DAAA,EACb,QAAA,EAAA,MAAA,CAAO,KAAA,EACV,CAAA;AAAA,wBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kEAAA,EACb,QAAA,EAAA,MAAA,CAAO,KAAA,EACV,CAAA;AAAA,UACC,MAAA,CAAO,uBACN,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,8CAAA,EAAgD,QAAA,EAAA,MAAA,CAAO,MAAK,CAAA,GAC1E;AAAA,SAAA,EACN,CAAA;AAAA,wBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACZ,QAAA,EAAA;AAAA,UAAA,MAAA,CAAO,KAAA,mBAAQ,GAAA,CAAC,KAAA,EAAA,EAAM,MAAA,EAAgB,CAAA,GAAK,IAAA;AAAA,UAC3C,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,SAAA,CAAU,MAAA,GAAS,CAAA,mBAC7C,GAAA,CAAC,SAAA,EAAA,EAAU,MAAA,EAAQ,MAAA,CAAO,SAAA,EAAW,CAAA,GACnC;AAAA,SAAA,EACN;AAAA;AAAA;AAAA,GACF;AAEJ;AAEA,SAAS,KAAA,CAAM,EAAE,MAAA,EAAO,EAAuB;AAC7C,EAAA,MAAM,OACJ,MAAA,CAAO,SAAA,KAAc,SACjB,uBAAA,GACA,MAAA,CAAO,YACL,cAAA,GACA,kBAAA;AACR,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,SAAA,KAAc,KAAA,GAAQ,YAAA,GAAe,UAAA;AACzD,EAAA,4BACG,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,uDAAA,EAAyD,IAAI,CAAA,EAC/E,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,QAAA,EAAS,CAAA;AAAA,IAAE,GAAA;AAAA,IAAE,MAAA,CAAO;AAAA,GAAA,EACtC,CAAA;AAEJ;AAEA,SAAS,SAAA,CAAU,EAAE,MAAA,EAAO,EAAyB;AACnD,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA;AAC7D,EAAA,uBACE,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sCAAA,EAAuC,aAAA,EAAY,QAChE,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,EAAG,GAAA,qBACf,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MAGC,SAAA,EAAU,kCAAA;AAAA,MACV,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,GAAI,GAAG,CAAC,CAAA,CAAA,CAAA;AAAI,KAAA;AAAA,IAFvC;AAAA,GAIR,CAAA,EACH,CAAA;AAEJ","file":"chunk-JS5T2CRO.js","sourcesContent":["import { TrendingDown, TrendingUp } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\nexport interface Metric {\n /**\n * Short label, e.g. \"Requests/s\", \"p95 latency\", \"Error rate\".\n */\n label: string;\n /**\n * Pre-formatted value string, e.g. \"1.2k\", \"182ms\", \"0.03%\".\n * Consumer formats; the component does not parse.\n */\n value: string;\n /**\n * Optional unit suffix appended after value with .9 opacity.\n */\n unit?: string;\n /**\n * Optional change vs comparison period, e.g. \"+12%\", \"-4ms\", \"+0.01pp\".\n */\n delta?: string;\n /**\n * If true, delta is \"good\" (success color); if false, \"bad\" (destructive).\n * If omitted, delta is rendered in muted (neutral).\n *\n * Caller decides semantics — \"more requests\" is good but \"more errors\" is bad.\n */\n deltaGood?: boolean;\n /**\n * Optional sparkline data, 0..1 normalized. Consumer is responsible for normalization.\n */\n sparkline?: number[];\n /**\n * Optional onClick to drill into the metric.\n */\n onClick?: () => void;\n /**\n * Optional override for the clickable tile's accessible name. When the\n * tile is interactive (`onClick` set), defaults to `View <label> details`.\n * Has no effect when `onClick` is absent (tile is rendered as a non-link\n * `<div>` with no button semantics). T4.3.\n */\n actionLabel?: string;\n}\n\ninterface MetricsPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n title?: ReactNode;\n description?: ReactNode;\n metrics: Metric[];\n /**\n * Grid columns. Defaults to auto-fit ~180px min.\n */\n columns?: number;\n}\n\n/**\n * MetricsPanel — grid of metric tiles for observability dashboards.\n *\n * Visual: each tile is a soft surface with a big value (font-display),\n * label uppercase muted, optional delta with arrow icon + tone color,\n * optional CSS-only sparkline drawn as flexed bars.\n *\n * No external chart lib — keeps the registry copy-pasteable.\n */\nconst MetricsPanel = forwardRef<HTMLDivElement, MetricsPanelProps>(\n ({ className, title, description, metrics, columns, ...props }, ref) => (\n <div\n data-slot=\"metrics-panel\"\n ref={ref}\n className={cn(\"rounded-xl border border-border bg-card p-5 shadow-sm\", className)}\n {...props}\n >\n {title || description ? (\n <header className=\"mb-4 grid gap-0.5\">\n {title ? <h3 className=\"font-display text-title-md tracking-tight\">{title}</h3> : null}\n {description ? <p className=\"text-body-sm text-muted-foreground\">{description}</p> : null}\n </header>\n ) : null}\n <div\n className=\"grid gap-4\"\n style={{\n gridTemplateColumns: columns\n ? `repeat(${columns}, minmax(0, 1fr))`\n : \"repeat(auto-fit, minmax(180px, 1fr))\",\n }}\n >\n {metrics.map((m) => (\n <Tile key={m.label} metric={m} />\n ))}\n </div>\n </div>\n ),\n);\nMetricsPanel.displayName = \"MetricsPanel\";\n\nfunction Tile({ metric }: { metric: Metric }) {\n const interactive = metric.onClick !== undefined;\n const Tag = interactive ? \"button\" : \"div\";\n // T4.3 (Code Issue 3): clickable tiles need an explicit accessible name\n // so AT users hear \"View Requests/s details, button\" instead of just\n // the spoken value cluster. Falls back to metric.actionLabel when the\n // caller wants custom text (e.g., \"Drill into requests\").\n const ariaLabel = interactive\n ? (metric.actionLabel ?? `View ${metric.label} details`)\n : undefined;\n return (\n <Tag\n type={interactive ? \"button\" : undefined}\n onClick={metric.onClick}\n aria-label={ariaLabel}\n className={cn(\n \"flex flex-col gap-2 rounded-lg border border-border/30 bg-muted/30 p-4 text-left\",\n \"transition-colors duration-base ease-out-soft\",\n interactive &&\n \"hover:border-primary/40 hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card\",\n )}\n >\n <span className=\"font-sans text-label-caps text-muted-foreground uppercase\">\n {metric.label}\n </span>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"font-bold font-display text-display-md tabular-nums leading-none\">\n {metric.value}\n </span>\n {metric.unit ? (\n <span className=\"font-mono text-body-sm text-muted-foreground\">{metric.unit}</span>\n ) : null}\n </div>\n <div className=\"flex items-center gap-2\">\n {metric.delta ? <Delta metric={metric} /> : null}\n {metric.sparkline && metric.sparkline.length > 0 ? (\n <Sparkline values={metric.sparkline} />\n ) : null}\n </div>\n </Tag>\n );\n}\n\nfunction Delta({ metric }: { metric: Metric }) {\n const tone =\n metric.deltaGood === undefined\n ? \"text-muted-foreground\"\n : metric.deltaGood\n ? \"text-success\"\n : \"text-destructive\";\n const Icon = metric.deltaGood === false ? TrendingDown : TrendingUp;\n return (\n <span className={cn(\"inline-flex items-center gap-1 font-mono text-body-sm\", tone)}>\n <Icon className=\"size-3\" /> {metric.delta}\n </span>\n );\n}\n\nfunction Sparkline({ values }: { values: number[] }) {\n const clamped = values.map((v) => Math.max(0, Math.min(1, v)));\n return (\n <span className=\"ml-auto flex h-6 items-end gap-[2px]\" aria-hidden=\"true\">\n {clamped.map((v, idx) => (\n <span\n // biome-ignore lint/suspicious/noArrayIndexKey: positional, values are not stable identifiers\n key={idx}\n className=\"w-[3px] rounded-sm bg-primary/60\"\n style={{ height: `${Math.max(8, v * 100)}%` }}\n />\n ))}\n </span>\n );\n}\n\nexport { MetricsPanel };\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { Dialog } from './chunk-
|
|
2
|
+
import { Dialog } from './chunk-T4Z7HBZR.js';
|
|
3
3
|
import { Button } from './chunk-25KBUQEQ.js';
|
|
4
4
|
import { ShieldAlert, FolderOpen, AlertTriangle } from 'lucide-react';
|
|
5
5
|
import { useRef } from 'react';
|
|
@@ -88,5 +88,5 @@ function PermissionModal({
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
export { PermissionModal };
|
|
91
|
-
//# sourceMappingURL=chunk-
|
|
92
|
-
//# sourceMappingURL=chunk-
|
|
91
|
+
//# sourceMappingURL=chunk-KXZH7BTX.js.map
|
|
92
|
+
//# sourceMappingURL=chunk-KXZH7BTX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/permission-modal/permission-modal.tsx"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/permission-modal/permission-modal.tsx"],"names":[],"mappings":"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","file":"chunk-KXZH7BTX.js","sourcesContent":["\"use client\";\n\nimport { AlertTriangle, FolderOpen, ShieldAlert } from \"lucide-react\";\nimport { useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type {\n PermissionDecision,\n PermissionOperation,\n PermissionRequest,\n} from \"../../../types/permission.js\";\nimport { Button } from \"../../primitives/button/index.js\";\nimport { Dialog } from \"../../primitives/dialog/index.js\";\n\n/**\n * Friendly operation labels used by the default copy. Override with the\n * `operationLabels` prop to localize or rephrase per project.\n */\nexport const defaultOperationLabels: Record<PermissionOperation, string> = {\n read: \"read\",\n write: \"edit\",\n delete: \"permanently delete\",\n};\n\ninterface PermissionModalLabels {\n /** \"Cancel\" button. */\n cancel: ReactNode;\n /** \"Always allow\" tertiary button. */\n always: ReactNode;\n /** \"Allow once\" primary button. */\n allow: ReactNode;\n /** Inline label rendered before the operation list inside the body card. */\n requestedOps: ReactNode;\n}\n\nconst defaultLabels: PermissionModalLabels = {\n cancel: \"Cancel\",\n always: \"Always allow\",\n allow: \"Allow once\",\n requestedOps: \"Requested operations:\",\n};\n\ninterface PermissionModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n request: PermissionRequest;\n /**\n * Fires when the user picks a decision. The modal does NOT auto-close;\n * caller decides whether the decision should dismiss the modal.\n */\n onDecide: (decision: PermissionDecision) => void;\n /** Override the modal title. Defaults to \"Allow Theo to {ops} files in {path}?\". */\n title?: ReactNode;\n /** Override the modal description (body lead text). */\n description?: ReactNode;\n /** Override the verb used for each operation in the default copy. */\n operationLabels?: Partial<Record<PermissionOperation, string>>;\n /** Override button text + inline labels. Useful for i18n. */\n labels?: Partial<PermissionModalLabels>;\n}\n\n/**\n * PermissionModal — local-files access prompt built on Dialog.\n *\n * Three actions: Cancel (denied), Always allow, Allow once. Per WIREMOCKS §5,\n * the path is shown in the title (not hidden in body) and destructive\n * operations are listed inline.\n *\n * All visible text can be overridden via `title`, `description`,\n * `operationLabels`, and `labels`. Defaults are English; pass overrides for\n * other locales.\n */\nfunction PermissionModal({\n open,\n onOpenChange,\n request,\n onDecide,\n title,\n description,\n operationLabels,\n labels,\n}: PermissionModalProps) {\n const opLabels = { ...defaultOperationLabels, ...operationLabels };\n const opsList = request.operations.map((op) => opLabels[op]).join(\", \");\n const text = { ...defaultLabels, ...labels };\n\n // T4.4 (Code Issue 4): Esc / overlay-click previously fired onOpenChange(false)\n // but never onDecide — users saw \"Cancel\" semantics, app saw silent dismissal.\n // Track whether an explicit button decision happened; if the dialog closes\n // without one, treat it as denied. decidedRef must reset on every fresh open\n // so a rapid close-then-open doesn't carry state forward.\n const decidedRef = useRef(false);\n function handleDecide(decision: PermissionDecision) {\n decidedRef.current = true;\n onDecide(decision);\n }\n function handleOpenChange(next: boolean) {\n const wasDecided = decidedRef.current;\n // Reset BEFORE invoking onDecide so a re-open within the same tick starts\n // clean. Edge case from SF-6: rapid toggle could leave decidedRef=true.\n decidedRef.current = false;\n if (!next && !wasDecided) {\n onDecide(\"denied\");\n }\n onOpenChange(next);\n }\n\n const defaultTitle = (\n <span className=\"flex items-center gap-2\">\n <ShieldAlert className=\"size-5 text-warning\" aria-hidden=\"true\" />\n Allow Theo to {opsList} files in{\" \"}\n <code className=\"rounded-md bg-muted px-1.5 py-0.5 font-mono text-code-md text-primary\">\n {request.path}\n </code>\n ?\n </span>\n );\n\n const defaultDescription = (\n <>\n This includes all files and subfolders. Theo will be able to {opsList} and may share the\n contents with connected third-party tools. Be careful when exposing confidential information.\n </>\n );\n\n return (\n <Dialog data-slot=\"permission-modal\" open={open} onOpenChange={handleOpenChange}>\n <Dialog.Content className=\"max-w-xl\">\n <Dialog.Header>\n <Dialog.Title>{title ?? defaultTitle}</Dialog.Title>\n <Dialog.Description>{description ?? defaultDescription}</Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n <div className=\"flex items-start gap-3 rounded-md border border-border/40 bg-muted/40 p-3\">\n <FolderOpen\n className=\"mt-0.5 size-4 shrink-0 text-muted-foreground\"\n aria-hidden=\"true\"\n />\n <div className=\"grid gap-1\">\n <p className=\"font-mono text-code-sm text-foreground\">{request.path}</p>\n <p className=\"flex items-center gap-1.5 font-sans text-label text-warning\">\n <AlertTriangle className=\"size-3\" aria-hidden=\"true\" />\n {text.requestedOps} {opsList}\n </p>\n </div>\n </div>\n </Dialog.Body>\n <Dialog.Footer>\n <Button variant=\"secondary\" onClick={() => handleDecide(\"denied\")}>\n {text.cancel}\n </Button>\n <Button variant=\"ghost\" onClick={() => handleDecide(\"always_allowed\")}>\n {text.always}\n </Button>\n <Button onClick={() => handleDecide(\"allowed_once\")}>{text.allow}</Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog>\n );\n}\n\nexport { PermissionModal };\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CronJobCard } from './chunk-
|
|
1
|
+
import { CronJobCard } from './chunk-SPGNNN4R.js';
|
|
2
2
|
import { cn } from './chunk-EWDN56AS.js';
|
|
3
3
|
import { Plus } from 'lucide-react';
|
|
4
4
|
import { forwardRef } from 'react';
|
|
@@ -53,5 +53,5 @@ var CronJobsList = forwardRef(
|
|
|
53
53
|
CronJobsList.displayName = "CronJobsList";
|
|
54
54
|
|
|
55
55
|
export { CronJobsList };
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
56
|
+
//# sourceMappingURL=chunk-LB4PMLCX.js.map
|
|
57
|
+
//# sourceMappingURL=chunk-LB4PMLCX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/composites/cron-jobs-list/cron-jobs-list.tsx"],"names":[],"mappings":";;;;;;AAkBA,IAAM,YAAA,GAAe,UAAA;AAAA,EACnB,CACE,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,GAAQ,gBAAA,EAAkB,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAA,EAAU,GAAG,KAAA,IACrF,GAAA,qBAEA,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,gBAAA;AAAA,MACV,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,YAAA,EAAc,SAAS,CAAA;AAAA,MACrC,YAAA,EAAW,sBAAA;AAAA,MACV,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,QAAA,EAAA,EAAO,WAAU,qCAAA,EACf,QAAA,EAAA;AAAA,UAAA,KAAA,uBAAS,IAAA,EAAA,EAAG,SAAA,EAAU,6CAA6C,QAAA,EAAA,KAAA,EAAM,CAAA,uBAAS,MAAA,EAAA,EAAK,CAAA;AAAA,0BACxF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,4CAAA,EACb,QAAA,EAAA;AAAA,cAAA,IAAA,CAAK,MAAA;AAAA,cAAO,GAAA;AAAA,cAAE,IAAA,CAAK,MAAA,KAAW,CAAA,GAAI,KAAA,GAAQ;AAAA,aAAA,EAC7C,CAAA;AAAA,YACC,KAAA,mBACC,IAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,OAAA,EAAS,KAAA;AAAA,gBACT,SAAA,EAAU,yMAAA;AAAA,gBAEV,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,UAAA,EAAW,CAAA;AAAA,kBAAE;AAAA;AAAA;AAAA,aAC/B,GACE;AAAA,WAAA,EACN;AAAA,SAAA,EACF,CAAA;AAAA,QACC,KAAK,MAAA,KAAW,CAAA,mBACf,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,iIAAA,EAAkI,QAAA,EAAA,wBAAA,EAE/I,CAAA,mBAEA,GAAA,CAAC,SAAI,SAAA,EAAU,uCAAA,EACZ,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,GAAA;AAAA,UAAC,WAAA;AAAA,UAAA;AAAA,YAEC,GAAA;AAAA,YACC,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,YAC/B,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,YAC/B,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,WAAA;AAAA,UAJ3B,GAAA,CAAI;AAAA,SAMZ,CAAA,EACH;AAAA;AAAA;AAAA;AAIR;AACA,YAAA,CAAa,WAAA,GAAc,cAAA","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/composites/cron-jobs-list/cron-jobs-list.tsx"],"names":[],"mappings":";;;;;;AAkBA,IAAM,YAAA,GAAe,UAAA;AAAA,EACnB,CACE,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,GAAQ,gBAAA,EAAkB,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAA,EAAU,GAAG,KAAA,IACrF,GAAA,qBAEA,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,gBAAA;AAAA,MACV,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,YAAA,EAAc,SAAS,CAAA;AAAA,MACrC,YAAA,EAAW,sBAAA;AAAA,MACV,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,QAAA,EAAA,EAAO,WAAU,qCAAA,EACf,QAAA,EAAA;AAAA,UAAA,KAAA,uBAAS,IAAA,EAAA,EAAG,SAAA,EAAU,6CAA6C,QAAA,EAAA,KAAA,EAAM,CAAA,uBAAS,MAAA,EAAA,EAAK,CAAA;AAAA,0BACxF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,4CAAA,EACb,QAAA,EAAA;AAAA,cAAA,IAAA,CAAK,MAAA;AAAA,cAAO,GAAA;AAAA,cAAE,IAAA,CAAK,MAAA,KAAW,CAAA,GAAI,KAAA,GAAQ;AAAA,aAAA,EAC7C,CAAA;AAAA,YACC,KAAA,mBACC,IAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,OAAA,EAAS,KAAA;AAAA,gBACT,SAAA,EAAU,yMAAA;AAAA,gBAEV,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,UAAA,EAAW,CAAA;AAAA,kBAAE;AAAA;AAAA;AAAA,aAC/B,GACE;AAAA,WAAA,EACN;AAAA,SAAA,EACF,CAAA;AAAA,QACC,KAAK,MAAA,KAAW,CAAA,mBACf,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,iIAAA,EAAkI,QAAA,EAAA,wBAAA,EAE/I,CAAA,mBAEA,GAAA,CAAC,SAAI,SAAA,EAAU,uCAAA,EACZ,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,GAAA;AAAA,UAAC,WAAA;AAAA,UAAA;AAAA,YAEC,GAAA;AAAA,YACC,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,YAC/B,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa,EAAC;AAAA,YAC/B,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,WAAA;AAAA,UAJ3B,GAAA,CAAI;AAAA,SAMZ,CAAA,EACH;AAAA;AAAA;AAAA;AAIR;AACA,YAAA,CAAa,WAAA,GAAc,cAAA","file":"chunk-LB4PMLCX.js","sourcesContent":["import { Plus } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\nimport { type CronJob, CronJobCard } from \"../../primitives/cron-job-card/index.js\";\n\ninterface CronJobsListProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"onToggle\"> {\n jobs: CronJob[];\n title?: ReactNode;\n onAdd?: () => void;\n onRunNow?: (id: string) => void;\n onToggle?: (id: string, enabled: boolean) => void;\n onRemove?: (id: string) => void;\n}\n\n/**\n * CronJobsList — grid of CronJobCards with a sticky \"new job\" action.\n */\nconst CronJobsList = forwardRef<HTMLDivElement, CronJobsListProps>(\n (\n { className, jobs, title = \"Scheduled jobs\", onAdd, onRunNow, onToggle, onRemove, ...props },\n ref,\n ) => (\n <section\n data-slot=\"cron-jobs-list\"\n ref={ref}\n className={cn(\"grid gap-3\", className)}\n aria-label=\"Scheduled agent jobs\"\n {...props}\n >\n <header className=\"flex items-baseline justify-between\">\n {title ? <h3 className=\"font-display text-title-md tracking-tight\">{title}</h3> : <span />}\n <div className=\"flex items-center gap-3\">\n <span className=\"font-mono text-label text-muted-foreground\">\n {jobs.length} {jobs.length === 1 ? \"job\" : \"jobs\"}\n </span>\n {onAdd ? (\n <button\n type=\"button\"\n onClick={onAdd}\n className=\"inline-flex items-center gap-1 rounded-md bg-primary px-2.5 py-1 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\" /> New job\n </button>\n ) : null}\n </div>\n </header>\n {jobs.length === 0 ? (\n <p className=\"rounded-xl border border-border/60 border-dashed bg-muted/30 px-4 py-8 text-center font-sans text-body-sm text-muted-foreground\">\n No scheduled jobs yet.\n </p>\n ) : (\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n {jobs.map((job) => (\n <CronJobCard\n key={job.id}\n job={job}\n {...(onRunNow ? { onRunNow } : {})}\n {...(onToggle ? { onToggle } : {})}\n {...(onRemove ? { onRemove } : {})}\n />\n ))}\n </div>\n )}\n </section>\n ),\n);\nCronJobsList.displayName = \"CronJobsList\";\n\nexport { CronJobsList };\n"]}
|
|
@@ -21,7 +21,7 @@ var SessionTimeline = forwardRef(
|
|
|
21
21
|
{
|
|
22
22
|
"data-slot": "session-timeline",
|
|
23
23
|
ref,
|
|
24
|
-
className: cn("rounded-xl border bg-card", className),
|
|
24
|
+
className: cn("rounded-xl border border-border bg-card", className),
|
|
25
25
|
"aria-label": "Session history",
|
|
26
26
|
...props,
|
|
27
27
|
children: [
|
|
@@ -113,5 +113,5 @@ var SessionTimeline = forwardRef(
|
|
|
113
113
|
SessionTimeline.displayName = "SessionTimeline";
|
|
114
114
|
|
|
115
115
|
export { SessionTimeline };
|
|
116
|
-
//# sourceMappingURL=chunk-
|
|
117
|
-
//# sourceMappingURL=chunk-
|
|
116
|
+
//# sourceMappingURL=chunk-LMGE2QEO.js.map
|
|
117
|
+
//# sourceMappingURL=chunk-LMGE2QEO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives/session-timeline/session-timeline.tsx"],"names":[],"mappings":";;;;;AAiCA,IAAM,YAAA,GAA8C;AAAA,EAClD,MAAA,EAAQ,8CAAA;AAAA,EACR,SAAA,EAAW,8CAAA;AAAA,EACX,MAAA,EAAQ,0DAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,YAAA,GAA8C;AAAA,EAClD,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA,EACX,MAAA,EAAQ,QAAA;AAAA,EACR,OAAA,EAAS;AACX,CAAA;AAMA,IAAM,eAAA,GAAkB,UAAA;AAAA,EACtB,CAAC,EAAE,SAAA,EAAW,QAAA,EAAU,KAAA,GAAQ,mBAAmB,MAAA,EAAQ,GAAG,KAAA,EAAM,EAAG,GAAA,qBACrE,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,kBAAA;AAAA,MACV,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives/session-timeline/session-timeline.tsx"],"names":[],"mappings":"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","file":"chunk-LMGE2QEO.js","sourcesContent":["import { ChevronRight, Clock, Coins, MessageSquare, Sparkles } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../../../lib/cn.js\";\n\nexport type SessionStatus = \"active\" | \"completed\" | \"failed\" | \"aborted\";\n\nexport interface SessionSummary {\n id: string;\n /** Friendly title (often the first user message). */\n title: string;\n /** ISO timestamp / friendly date label. */\n startedAt: string;\n duration?: string;\n status: SessionStatus;\n /** Agent/model that ran the session. */\n model?: string;\n /** Total tokens consumed (formatted, e.g. \"35.7k\"). */\n tokens?: string;\n /** Total cost (USD). */\n cost?: number;\n /** Number of messages in the session. */\n messageCount?: number;\n}\n\ninterface SessionTimelineProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n sessions: SessionSummary[];\n /** Title above the list. */\n title?: ReactNode;\n /** Fires when a row is clicked. */\n onOpen?: (id: string) => void;\n}\n\nconst STATUS_CLASS: Record<SessionStatus, string> = {\n active: \"border-primary/40 bg-primary/15 text-primary\",\n completed: \"border-success/40 bg-success/15 text-success\",\n failed: \"border-destructive/40 bg-destructive/15 text-destructive\",\n aborted: \"border-border/40 bg-muted text-muted-foreground\",\n};\n\nconst STATUS_LABEL: Record<SessionStatus, string> = {\n active: \"Active\",\n completed: \"Completed\",\n failed: \"Failed\",\n aborted: \"Aborted\",\n};\n\n/**\n * SessionTimeline — historical view of past agent sessions with per-row\n * tokens / cost / duration / status. Click a row to open the full session.\n */\nconst SessionTimeline = forwardRef<HTMLDivElement, SessionTimelineProps>(\n ({ className, sessions, title = \"Recent sessions\", onOpen, ...props }, ref) => (\n <section\n data-slot=\"session-timeline\"\n ref={ref}\n className={cn(\"rounded-xl border border-border bg-card\", className)}\n aria-label=\"Session history\"\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 {sessions.length} {sessions.length === 1 ? \"session\" : \"sessions\"}\n </span>\n </header>\n ) : null}\n <ul className=\"divide-y divide-border/30\">\n {sessions.map((s) => {\n const RowTag = onOpen ? \"button\" : \"div\";\n return (\n <li key={s.id}>\n <RowTag\n type={onOpen ? \"button\" : undefined}\n onClick={onOpen ? () => onOpen(s.id) : undefined}\n className={cn(\n \"grid w-full grid-cols-[1fr_auto] items-center gap-3 px-4 py-3 text-left\",\n onOpen &&\n \"hover:bg-muted/40 focus-visible:bg-muted/40 focus-visible:outline-none\",\n )}\n >\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"truncate font-medium text-body-sm text-foreground\">{s.title}</p>\n <span\n className={cn(\n \"inline-flex shrink-0 items-center rounded-full border px-2 py-0.5\",\n \"font-mono text-label uppercase tracking-wider\",\n STATUS_CLASS[s.status],\n )}\n >\n {STATUS_LABEL[s.status]}\n </span>\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-3 font-mono text-label text-muted-foreground\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"size-3\" aria-hidden=\"true\" /> {s.startedAt}\n {s.duration ? <> · {s.duration}</> : null}\n </span>\n {s.model ? (\n <span className=\"inline-flex items-center gap-1\">\n <Sparkles className=\"size-3\" aria-hidden=\"true\" /> {s.model}\n </span>\n ) : null}\n {s.tokens ? (\n <span className=\"inline-flex items-center gap-1\">\n <Coins className=\"size-3\" aria-hidden=\"true\" /> {s.tokens} tok\n </span>\n ) : null}\n {s.cost !== undefined ? (\n <span className=\"tabular-nums\">${s.cost.toFixed(2)}</span>\n ) : null}\n {s.messageCount !== undefined ? (\n <span className=\"inline-flex items-center gap-1\">\n <MessageSquare className=\"size-3\" aria-hidden=\"true\" /> {s.messageCount}\n </span>\n ) : null}\n </div>\n </div>\n {onOpen ? (\n <ChevronRight\n className=\"size-4 shrink-0 text-muted-foreground\"\n aria-hidden=\"true\"\n />\n ) : null}\n </RowTag>\n </li>\n );\n })}\n {sessions.length === 0 ? (\n <li className=\"px-4 py-8 text-center font-sans text-body-sm text-muted-foreground\">\n No sessions yet.\n </li>\n ) : null}\n </ul>\n </section>\n ),\n);\nSessionTimeline.displayName = \"SessionTimeline\";\n\nexport { SessionTimeline };\n"]}
|