@usetheo/ui 0.13.1 → 0.14.0
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/README.md +4 -466
- package/dist/components/composites/command-palette/command-palette.d.ts +1 -1
- package/dist/components/primitives/badge/badge.d.ts +1 -1
- package/dist/components/primitives/button/button.d.ts +1 -1
- package/dist/components/primitives/danger-zone/danger-zone.d.ts +1 -1
- package/dist/components/primitives/dialog/dialog.d.ts +3 -3
- package/dist/components/primitives/dropdown-menu/dropdown-menu.d.ts +1 -1
- package/dist/components/primitives/sheet/sheet.d.ts +3 -3
- package/dist/components/primitives/toast/toast.d.ts +1 -1
- package/dist/index.d.ts +0 -89
- package/dist/index.js +4657 -1545
- package/dist/lib/cn.d.ts +1 -1
- package/dist/{preset-v3-legacy.js → tailwind-preset.js} +1 -16
- package/package.json +28 -788
- package/CHANGELOG.md +0 -1797
- package/DESIGN.md +0 -456
- package/NOTICE +0 -38
- package/dist/chunk-23YEYNDS.js +0 -89
- package/dist/chunk-23YEYNDS.js.map +0 -1
- package/dist/chunk-25KBUQEQ.js +0 -95
- package/dist/chunk-25KBUQEQ.js.map +0 -1
- package/dist/chunk-2A3E5Y72.js +0 -165
- package/dist/chunk-2A3E5Y72.js.map +0 -1
- package/dist/chunk-2EUKYGH5.js +0 -98
- package/dist/chunk-2EUKYGH5.js.map +0 -1
- package/dist/chunk-2NZYMQKT.js +0 -56
- package/dist/chunk-2NZYMQKT.js.map +0 -1
- package/dist/chunk-2OVFVPSZ.js +0 -26
- package/dist/chunk-2OVFVPSZ.js.map +0 -1
- package/dist/chunk-2UP7SECE.js +0 -78
- package/dist/chunk-2UP7SECE.js.map +0 -1
- package/dist/chunk-33ETHPT7.js +0 -112
- package/dist/chunk-33ETHPT7.js.map +0 -1
- package/dist/chunk-33IIDFSM.js +0 -43
- package/dist/chunk-33IIDFSM.js.map +0 -1
- package/dist/chunk-345HYADQ.js +0 -88
- package/dist/chunk-345HYADQ.js.map +0 -1
- package/dist/chunk-3ZXZGZOX.js +0 -57
- package/dist/chunk-3ZXZGZOX.js.map +0 -1
- package/dist/chunk-45FWKR23.js +0 -62
- package/dist/chunk-45FWKR23.js.map +0 -1
- package/dist/chunk-4DTLUBRW.js +0 -122
- package/dist/chunk-4DTLUBRW.js.map +0 -1
- package/dist/chunk-4EH6F54D.js +0 -69
- package/dist/chunk-4EH6F54D.js.map +0 -1
- package/dist/chunk-4EKF4EIE.js +0 -140
- package/dist/chunk-4EKF4EIE.js.map +0 -1
- package/dist/chunk-4SMYNLTA.js +0 -83
- package/dist/chunk-4SMYNLTA.js.map +0 -1
- package/dist/chunk-4UBFLXS3.js +0 -35
- package/dist/chunk-4UBFLXS3.js.map +0 -1
- package/dist/chunk-52J7SDYH.js +0 -48
- package/dist/chunk-52J7SDYH.js.map +0 -1
- package/dist/chunk-5XCTTXC3.js +0 -180
- package/dist/chunk-5XCTTXC3.js.map +0 -1
- package/dist/chunk-624AATQZ.js +0 -77
- package/dist/chunk-624AATQZ.js.map +0 -1
- package/dist/chunk-6IODJQWC.js +0 -47
- package/dist/chunk-6IODJQWC.js.map +0 -1
- package/dist/chunk-75IDWFYX.js +0 -134
- package/dist/chunk-75IDWFYX.js.map +0 -1
- package/dist/chunk-7BGCWJQR.js +0 -113
- package/dist/chunk-7BGCWJQR.js.map +0 -1
- package/dist/chunk-7BQXMG2A.js +0 -93
- package/dist/chunk-7BQXMG2A.js.map +0 -1
- package/dist/chunk-7RFWVNQA.js +0 -47
- package/dist/chunk-7RFWVNQA.js.map +0 -1
- package/dist/chunk-7T4NK6W6.js +0 -192
- package/dist/chunk-7T4NK6W6.js.map +0 -1
- package/dist/chunk-A3OU6ICP.js +0 -91
- package/dist/chunk-A3OU6ICP.js.map +0 -1
- package/dist/chunk-ABBXLAJW.js +0 -74
- package/dist/chunk-ABBXLAJW.js.map +0 -1
- package/dist/chunk-AENNHS3S.js +0 -83
- package/dist/chunk-AENNHS3S.js.map +0 -1
- package/dist/chunk-AXNJFBYX.js +0 -136
- package/dist/chunk-AXNJFBYX.js.map +0 -1
- package/dist/chunk-AXUAQM45.js +0 -154
- package/dist/chunk-AXUAQM45.js.map +0 -1
- package/dist/chunk-B2FL7KBJ.js +0 -65
- package/dist/chunk-B2FL7KBJ.js.map +0 -1
- package/dist/chunk-BE232OKN.js +0 -42
- package/dist/chunk-BE232OKN.js.map +0 -1
- package/dist/chunk-BP4RQSX7.js +0 -200
- package/dist/chunk-BP4RQSX7.js.map +0 -1
- package/dist/chunk-BPJ3RN3U.js +0 -112
- package/dist/chunk-BPJ3RN3U.js.map +0 -1
- package/dist/chunk-BSF4Y4UT.js +0 -77
- package/dist/chunk-BSF4Y4UT.js.map +0 -1
- package/dist/chunk-BWIDDAR7.js +0 -86
- package/dist/chunk-BWIDDAR7.js.map +0 -1
- package/dist/chunk-BYUWQ6OP.js +0 -45
- package/dist/chunk-BYUWQ6OP.js.map +0 -1
- package/dist/chunk-C5ULP2P5.js +0 -140
- package/dist/chunk-C5ULP2P5.js.map +0 -1
- package/dist/chunk-CCG7PXLX.js +0 -24
- package/dist/chunk-CCG7PXLX.js.map +0 -1
- package/dist/chunk-CED2LKHI.js +0 -117
- package/dist/chunk-CED2LKHI.js.map +0 -1
- package/dist/chunk-CGWIOIEO.js +0 -27
- package/dist/chunk-CGWIOIEO.js.map +0 -1
- package/dist/chunk-CSEGVTKO.js +0 -110
- package/dist/chunk-CSEGVTKO.js.map +0 -1
- package/dist/chunk-CVFSNA4K.js +0 -716
- package/dist/chunk-CVFSNA4K.js.map +0 -1
- package/dist/chunk-E26M7ATD.js +0 -61
- package/dist/chunk-E26M7ATD.js.map +0 -1
- package/dist/chunk-E63IRXZZ.js +0 -78
- package/dist/chunk-E63IRXZZ.js.map +0 -1
- package/dist/chunk-ESJUISWY.js +0 -45
- package/dist/chunk-ESJUISWY.js.map +0 -1
- package/dist/chunk-ET7A3TQZ.js +0 -158
- package/dist/chunk-ET7A3TQZ.js.map +0 -1
- package/dist/chunk-ETTL6XGU.js +0 -139
- package/dist/chunk-ETTL6XGU.js.map +0 -1
- package/dist/chunk-EWDN56AS.js +0 -24
- package/dist/chunk-EWDN56AS.js.map +0 -1
- package/dist/chunk-FJZKA2LV.js +0 -165
- package/dist/chunk-FJZKA2LV.js.map +0 -1
- package/dist/chunk-G2WCT6PJ.js +0 -69
- package/dist/chunk-G2WCT6PJ.js.map +0 -1
- package/dist/chunk-GC52HWIL.js +0 -41
- package/dist/chunk-GC52HWIL.js.map +0 -1
- package/dist/chunk-GCKFA7X7.js +0 -83
- package/dist/chunk-GCKFA7X7.js.map +0 -1
- package/dist/chunk-GDMCDW66.js +0 -19
- package/dist/chunk-GDMCDW66.js.map +0 -1
- package/dist/chunk-GIXHBTHH.js +0 -59
- package/dist/chunk-GIXHBTHH.js.map +0 -1
- package/dist/chunk-GLEOUWPN.js +0 -108
- package/dist/chunk-GLEOUWPN.js.map +0 -1
- package/dist/chunk-GLRUM43F.js +0 -121
- package/dist/chunk-GLRUM43F.js.map +0 -1
- package/dist/chunk-H3L7WZDZ.js +0 -74
- package/dist/chunk-H3L7WZDZ.js.map +0 -1
- package/dist/chunk-H55WXDME.js +0 -45
- package/dist/chunk-H55WXDME.js.map +0 -1
- package/dist/chunk-H5QPJNVD.js +0 -98
- package/dist/chunk-H5QPJNVD.js.map +0 -1
- package/dist/chunk-HB45JHMM.js +0 -43
- package/dist/chunk-HB45JHMM.js.map +0 -1
- package/dist/chunk-HETHTYEZ.js +0 -80
- package/dist/chunk-HETHTYEZ.js.map +0 -1
- package/dist/chunk-HHSKNB32.js +0 -55
- package/dist/chunk-HHSKNB32.js.map +0 -1
- package/dist/chunk-HILOUYES.js +0 -151
- package/dist/chunk-HILOUYES.js.map +0 -1
- package/dist/chunk-HTJVHFNW.js +0 -178
- package/dist/chunk-HTJVHFNW.js.map +0 -1
- package/dist/chunk-HZ7Z22VW.js +0 -130
- package/dist/chunk-HZ7Z22VW.js.map +0 -1
- package/dist/chunk-JFKBFQA5.js +0 -129
- package/dist/chunk-JFKBFQA5.js.map +0 -1
- package/dist/chunk-JIZKW3WC.js +0 -74
- package/dist/chunk-JIZKW3WC.js.map +0 -1
- package/dist/chunk-JQTCCKZA.js +0 -154
- package/dist/chunk-JQTCCKZA.js.map +0 -1
- package/dist/chunk-JR4H3FJ2.js +0 -74
- package/dist/chunk-JR4H3FJ2.js.map +0 -1
- package/dist/chunk-JRW53TVG.js +0 -53
- package/dist/chunk-JRW53TVG.js.map +0 -1
- package/dist/chunk-JXOCE27Z.js +0 -82
- package/dist/chunk-JXOCE27Z.js.map +0 -1
- package/dist/chunk-JYW5YNF7.js +0 -188
- package/dist/chunk-JYW5YNF7.js.map +0 -1
- package/dist/chunk-K72DJOXR.js +0 -81
- package/dist/chunk-K72DJOXR.js.map +0 -1
- package/dist/chunk-KDE3NYTI.js +0 -144
- package/dist/chunk-KDE3NYTI.js.map +0 -1
- package/dist/chunk-KFUFTZLS.js +0 -111
- package/dist/chunk-KFUFTZLS.js.map +0 -1
- package/dist/chunk-KHBXI6AV.js +0 -149
- package/dist/chunk-KHBXI6AV.js.map +0 -1
- package/dist/chunk-M74ZYBOK.js +0 -93
- package/dist/chunk-M74ZYBOK.js.map +0 -1
- package/dist/chunk-ML7WLNIK.js +0 -11
- package/dist/chunk-ML7WLNIK.js.map +0 -1
- package/dist/chunk-MXB2GVEQ.js +0 -57
- package/dist/chunk-MXB2GVEQ.js.map +0 -1
- package/dist/chunk-NEMXW2LB.js +0 -102
- package/dist/chunk-NEMXW2LB.js.map +0 -1
- package/dist/chunk-OJPPSJMF.js +0 -65
- package/dist/chunk-OJPPSJMF.js.map +0 -1
- package/dist/chunk-OMR6ZGME.js +0 -63
- package/dist/chunk-OMR6ZGME.js.map +0 -1
- package/dist/chunk-ORVYP73T.js +0 -223
- package/dist/chunk-ORVYP73T.js.map +0 -1
- package/dist/chunk-OZFUUO2Q.js +0 -50
- package/dist/chunk-OZFUUO2Q.js.map +0 -1
- package/dist/chunk-P44UAK45.js +0 -115
- package/dist/chunk-P44UAK45.js.map +0 -1
- package/dist/chunk-PJUP4BJD.js +0 -116
- package/dist/chunk-PJUP4BJD.js.map +0 -1
- package/dist/chunk-PJWYIOY4.js +0 -3
- package/dist/chunk-PJWYIOY4.js.map +0 -1
- package/dist/chunk-PVCW4O37.js +0 -147
- package/dist/chunk-PVCW4O37.js.map +0 -1
- package/dist/chunk-PXT47DRZ.js +0 -59
- package/dist/chunk-PXT47DRZ.js.map +0 -1
- package/dist/chunk-PZGUZHI7.js +0 -142
- package/dist/chunk-PZGUZHI7.js.map +0 -1
- package/dist/chunk-Q2BAL2PF.js +0 -965
- package/dist/chunk-Q2BAL2PF.js.map +0 -1
- package/dist/chunk-QBUTRD2M.js +0 -58
- package/dist/chunk-QBUTRD2M.js.map +0 -1
- package/dist/chunk-QCQTTOMD.js +0 -236
- package/dist/chunk-QCQTTOMD.js.map +0 -1
- package/dist/chunk-QNYOIVQ4.js +0 -36
- package/dist/chunk-QNYOIVQ4.js.map +0 -1
- package/dist/chunk-QPURZJJM.js +0 -88
- package/dist/chunk-QPURZJJM.js.map +0 -1
- package/dist/chunk-QRXIYPWP.js +0 -121
- package/dist/chunk-QRXIYPWP.js.map +0 -1
- package/dist/chunk-QV4BQRNH.js +0 -29
- package/dist/chunk-QV4BQRNH.js.map +0 -1
- package/dist/chunk-REFY5MLN.js +0 -212
- package/dist/chunk-REFY5MLN.js.map +0 -1
- package/dist/chunk-RJ6RAMKH.js +0 -89
- package/dist/chunk-RJ6RAMKH.js.map +0 -1
- package/dist/chunk-RJBCTMVW.js +0 -59
- package/dist/chunk-RJBCTMVW.js.map +0 -1
- package/dist/chunk-RLWULF5B.js +0 -113
- package/dist/chunk-RLWULF5B.js.map +0 -1
- package/dist/chunk-RPZMFGYI.js +0 -31
- package/dist/chunk-RPZMFGYI.js.map +0 -1
- package/dist/chunk-RQT5DWGG.js +0 -34
- package/dist/chunk-RQT5DWGG.js.map +0 -1
- package/dist/chunk-SBKVVVYY.js +0 -89
- package/dist/chunk-SBKVVVYY.js.map +0 -1
- package/dist/chunk-SOJW47EZ.js +0 -70
- package/dist/chunk-SOJW47EZ.js.map +0 -1
- package/dist/chunk-SQ66DCXY.js +0 -35
- package/dist/chunk-SQ66DCXY.js.map +0 -1
- package/dist/chunk-SXKGWHAM.js +0 -179
- package/dist/chunk-SXKGWHAM.js.map +0 -1
- package/dist/chunk-T2OKGV6M.js +0 -13
- package/dist/chunk-T2OKGV6M.js.map +0 -1
- package/dist/chunk-TJLULCZW.js +0 -108
- package/dist/chunk-TJLULCZW.js.map +0 -1
- package/dist/chunk-TY6NTWN5.js +0 -29
- package/dist/chunk-TY6NTWN5.js.map +0 -1
- package/dist/chunk-U3AEEFVB.js +0 -152
- package/dist/chunk-U3AEEFVB.js.map +0 -1
- package/dist/chunk-UGKI466V.js +0 -12
- package/dist/chunk-UGKI466V.js.map +0 -1
- package/dist/chunk-V3HFDVZ3.js +0 -102
- package/dist/chunk-V3HFDVZ3.js.map +0 -1
- package/dist/chunk-V6H2RUVP.js +0 -77
- package/dist/chunk-V6H2RUVP.js.map +0 -1
- package/dist/chunk-VB53UMAL.js +0 -106
- package/dist/chunk-VB53UMAL.js.map +0 -1
- package/dist/chunk-VBEMLZGX.js +0 -86
- package/dist/chunk-VBEMLZGX.js.map +0 -1
- package/dist/chunk-VBQFE5RV.js +0 -92
- package/dist/chunk-VBQFE5RV.js.map +0 -1
- package/dist/chunk-VHK2OUCW.js +0 -38
- package/dist/chunk-VHK2OUCW.js.map +0 -1
- package/dist/chunk-VHTAVROO.js +0 -53
- package/dist/chunk-VHTAVROO.js.map +0 -1
- package/dist/chunk-VM4RMQQN.js +0 -11
- package/dist/chunk-VM4RMQQN.js.map +0 -1
- package/dist/chunk-VZX4HLBM.js +0 -84
- package/dist/chunk-VZX4HLBM.js.map +0 -1
- package/dist/chunk-W47V2F3Q.js +0 -115
- package/dist/chunk-W47V2F3Q.js.map +0 -1
- package/dist/chunk-W7I3ZX66.js +0 -76
- package/dist/chunk-W7I3ZX66.js.map +0 -1
- package/dist/chunk-WD42UBGR.js +0 -64
- package/dist/chunk-WD42UBGR.js.map +0 -1
- package/dist/chunk-XC7SYZYR.js +0 -86
- package/dist/chunk-XC7SYZYR.js.map +0 -1
- package/dist/chunk-XJA4B3F5.js +0 -68
- package/dist/chunk-XJA4B3F5.js.map +0 -1
- package/dist/chunk-XSENM65D.js +0 -128
- package/dist/chunk-XSENM65D.js.map +0 -1
- package/dist/chunk-YD2QEVHO.js +0 -68
- package/dist/chunk-YD2QEVHO.js.map +0 -1
- package/dist/chunk-YDKRUSB5.js +0 -35
- package/dist/chunk-YDKRUSB5.js.map +0 -1
- package/dist/chunk-YES6SPDT.js +0 -55
- package/dist/chunk-YES6SPDT.js.map +0 -1
- package/dist/chunk-YNDHYMPI.js +0 -46
- package/dist/chunk-YNDHYMPI.js.map +0 -1
- package/dist/chunk-YO3WEMOH.js +0 -130
- package/dist/chunk-YO3WEMOH.js.map +0 -1
- package/dist/chunk-YUFFAWNB.js +0 -90
- package/dist/chunk-YUFFAWNB.js.map +0 -1
- package/dist/chunk-YVXMWUWD.js +0 -118
- package/dist/chunk-YVXMWUWD.js.map +0 -1
- package/dist/chunk-Z6HZMGO2.js +0 -106
- package/dist/chunk-Z6HZMGO2.js.map +0 -1
- package/dist/chunk-ZAMPCRFJ.js +0 -121
- package/dist/chunk-ZAMPCRFJ.js.map +0 -1
- package/dist/chunk-ZEFOXF2I.js +0 -87
- package/dist/chunk-ZEFOXF2I.js.map +0 -1
- package/dist/chunk-ZJXOHLQE.js +0 -66
- package/dist/chunk-ZJXOHLQE.js.map +0 -1
- package/dist/chunk-ZPURFK4C.js +0 -203
- package/dist/chunk-ZPURFK4C.js.map +0 -1
- package/dist/chunk-ZXPDS6DH.js +0 -3
- package/dist/chunk-ZXPDS6DH.js.map +0 -1
- package/dist/chunk-ZZZIOTLC.js +0 -89
- package/dist/chunk-ZZZIOTLC.js.map +0 -1
- package/dist/components/composites/agent-composer/agent-composer.d.ts +0 -41
- package/dist/components/composites/agent-composer/index.d.ts +0 -1
- package/dist/components/composites/agent-editor/agent-editor.d.ts +0 -31
- package/dist/components/composites/agent-editor/index.d.ts +0 -1
- package/dist/components/composites/agent-stream/agent-stream.d.ts +0 -72
- package/dist/components/composites/agent-stream/index.d.ts +0 -2
- package/dist/components/composites/agent-stream/to-agent-stream-items.d.ts +0 -32
- package/dist/components/composites/agent-timeline/agent-timeline.d.ts +0 -22
- package/dist/components/composites/agent-timeline/index.d.ts +0 -1
- package/dist/components/composites/agent-tool-renderer/agent-tool-renderer.d.ts +0 -60
- package/dist/components/composites/agent-tool-renderer/index.d.ts +0 -1
- package/dist/components/composites/agent-tool-renderer/tool-call-part.d.ts +0 -5
- package/dist/components/composites/approval-card/approval-card.d.ts +0 -35
- package/dist/components/composites/approval-card/index.d.ts +0 -1
- package/dist/components/composites/chat-composer/chat-composer.d.ts +0 -68
- package/dist/components/composites/chat-composer/index.d.ts +0 -1
- package/dist/components/composites/chat-message/chat-message-actions.d.ts +0 -22
- package/dist/components/composites/chat-message/chat-message-branch.d.ts +0 -17
- package/dist/components/composites/chat-message/chat-message-response.d.ts +0 -15
- package/dist/components/composites/chat-message/chat-message-toolbar.d.ts +0 -7
- package/dist/components/composites/chat-message/chat-message.d.ts +0 -94
- package/dist/components/composites/chat-message/index.d.ts +0 -23
- package/dist/components/composites/chat-message/parts/data-part.d.ts +0 -9
- package/dist/components/composites/chat-message/parts/file-part.d.ts +0 -5
- package/dist/components/composites/chat-message/parts/reasoning-part.d.ts +0 -7
- package/dist/components/composites/chat-message/parts/source-part.d.ts +0 -9
- package/dist/components/composites/chat-message/parts/text-part.d.ts +0 -11
- package/dist/components/composites/choice-prompt/choice-prompt.d.ts +0 -65
- package/dist/components/composites/choice-prompt/index.d.ts +0 -2
- package/dist/components/composites/confirm-prompt/confirm-prompt.d.ts +0 -31
- package/dist/components/composites/confirm-prompt/index.d.ts +0 -1
- package/dist/components/composites/cron-jobs-list/cron-jobs-list.d.ts +0 -15
- package/dist/components/composites/cron-jobs-list/index.d.ts +0 -1
- package/dist/components/composites/mcp-server-list/index.d.ts +0 -1
- package/dist/components/composites/mcp-server-list/mcp-server-list.d.ts +0 -15
- package/dist/components/composites/multi-select-prompt/index.d.ts +0 -1
- package/dist/components/composites/multi-select-prompt/multi-select-prompt.d.ts +0 -61
- package/dist/components/composites/permission-modal/index.d.ts +0 -1
- package/dist/components/composites/permission-modal/permission-modal.d.ts +0 -48
- package/dist/components/composites/preview-panel/index.d.ts +0 -1
- package/dist/components/composites/preview-panel/preview-panel.d.ts +0 -24
- package/dist/components/composites/rule-editor/index.d.ts +0 -1
- package/dist/components/composites/rule-editor/rule-editor.d.ts +0 -18
- package/dist/components/composites/skill-editor/index.d.ts +0 -1
- package/dist/components/composites/skill-editor/skill-editor.d.ts +0 -19
- package/dist/components/composites/skills-list/index.d.ts +0 -1
- package/dist/components/composites/skills-list/skills-list.d.ts +0 -15
- package/dist/components/composites/slide-deck/context.d.ts +0 -23
- package/dist/components/composites/slide-deck/controls.d.ts +0 -8
- package/dist/components/composites/slide-deck/fragments.d.ts +0 -20
- package/dist/components/composites/slide-deck/index.d.ts +0 -21
- package/dist/components/composites/slide-deck/notes.d.ts +0 -14
- package/dist/components/composites/slide-deck/presenter-view.d.ts +0 -15
- package/dist/components/composites/slide-deck/print-styles.d.ts +0 -21
- package/dist/components/composites/slide-deck/progress-bar.d.ts +0 -8
- package/dist/components/composites/slide-deck/schema.d.ts +0 -31
- package/dist/components/composites/slide-deck/slide-deck.d.ts +0 -78
- package/dist/components/composites/slide-deck/slide-number.d.ts +0 -11
- package/dist/components/composites/slide-deck/split-deck.d.ts +0 -2
- package/dist/components/composites/slide-deck/thumbnails.d.ts +0 -19
- package/dist/components/composites/slide-deck/use-deck-hash-routing.d.ts +0 -23
- package/dist/components/composites/slide-deck/use-deck-keyboard.d.ts +0 -25
- package/dist/components/composites/slide-deck/use-deck-state.d.ts +0 -57
- package/dist/components/composites/slide-deck/use-deck-swipe.d.ts +0 -20
- package/dist/components/composites/slide-deck/use-fullscreen.d.ts +0 -18
- package/dist/components/composites/stability-bundle-viewer/index.d.ts +0 -1
- package/dist/components/composites/stability-bundle-viewer/stability-bundle-viewer.d.ts +0 -28
- package/dist/components/composites/text-prompt/index.d.ts +0 -1
- package/dist/components/composites/text-prompt/text-prompt.d.ts +0 -48
- package/dist/components/composites/usage-meter/index.d.ts +0 -1
- package/dist/components/composites/usage-meter/usage-meter.d.ts +0 -56
- package/dist/components/primitives/agent-error-card/agent-error-card.d.ts +0 -47
- package/dist/components/primitives/agent-error-card/index.d.ts +0 -1
- package/dist/components/primitives/agent-event/agent-event.d.ts +0 -25
- package/dist/components/primitives/agent-event/index.d.ts +0 -1
- package/dist/components/primitives/agent-handoff/agent-handoff.d.ts +0 -24
- package/dist/components/primitives/agent-handoff/index.d.ts +0 -1
- package/dist/components/primitives/agent-profile/agent-profile.d.ts +0 -28
- package/dist/components/primitives/agent-profile/index.d.ts +0 -1
- package/dist/components/primitives/agent-starting-state/agent-starting-state.d.ts +0 -15
- package/dist/components/primitives/agent-starting-state/index.d.ts +0 -1
- package/dist/components/primitives/agent-streaming/agent-streaming.d.ts +0 -16
- package/dist/components/primitives/agent-streaming/index.d.ts +0 -1
- package/dist/components/primitives/artifact-preview/artifact-preview.d.ts +0 -25
- package/dist/components/primitives/artifact-preview/index.d.ts +0 -1
- package/dist/components/primitives/attachment-chip/attachment-chip.d.ts +0 -14
- package/dist/components/primitives/attachment-chip/index.d.ts +0 -1
- package/dist/components/primitives/audit-log-entry/audit-log-entry.d.ts +0 -29
- package/dist/components/primitives/audit-log-entry/index.d.ts +0 -1
- package/dist/components/primitives/auto-compact-notice/auto-compact-notice.d.ts +0 -24
- package/dist/components/primitives/auto-compact-notice/index.d.ts +0 -1
- package/dist/components/primitives/branch-indicator/branch-indicator.d.ts +0 -13
- package/dist/components/primitives/branch-indicator/index.d.ts +0 -1
- package/dist/components/primitives/browser-controls/browser-controls.d.ts +0 -19
- package/dist/components/primitives/browser-controls/index.d.ts +0 -1
- package/dist/components/primitives/build-log-stream/build-log-stream.d.ts +0 -51
- package/dist/components/primitives/build-log-stream/index.d.ts +0 -1
- package/dist/components/primitives/capability-indicator/capability-indicator.d.ts +0 -57
- package/dist/components/primitives/capability-indicator/index.d.ts +0 -1
- package/dist/components/primitives/channel-card/channel-card.d.ts +0 -28
- package/dist/components/primitives/channel-card/index.d.ts +0 -1
- package/dist/components/primitives/chat-thread/chat-thread.d.ts +0 -12
- package/dist/components/primitives/chat-thread/index.d.ts +0 -1
- package/dist/components/primitives/context-card/context-card.d.ts +0 -18
- package/dist/components/primitives/context-card/index.d.ts +0 -1
- package/dist/components/primitives/context-window-bar/context-window-bar.d.ts +0 -27
- package/dist/components/primitives/context-window-bar/index.d.ts +0 -1
- package/dist/components/primitives/cost-meter/cost-meter.d.ts +0 -23
- package/dist/components/primitives/cost-meter/index.d.ts +0 -1
- package/dist/components/primitives/created-files-card/created-files-card.d.ts +0 -30
- package/dist/components/primitives/created-files-card/index.d.ts +0 -1
- package/dist/components/primitives/cron-job-card/cron-job-card.d.ts +0 -30
- package/dist/components/primitives/cron-job-card/index.d.ts +0 -1
- package/dist/components/primitives/diff-viewer/diff-viewer.d.ts +0 -45
- package/dist/components/primitives/diff-viewer/index.d.ts +0 -1
- package/dist/components/primitives/export-chat-dialog/export-chat-dialog.d.ts +0 -18
- package/dist/components/primitives/export-chat-dialog/index.d.ts +0 -1
- package/dist/components/primitives/folder-context-card/folder-context-card.d.ts +0 -40
- package/dist/components/primitives/folder-context-card/index.d.ts +0 -1
- package/dist/components/primitives/folder-selector/folder-selector.d.ts +0 -18
- package/dist/components/primitives/folder-selector/index.d.ts +0 -1
- package/dist/components/primitives/gateway-status-indicator/gateway-status-indicator.d.ts +0 -19
- package/dist/components/primitives/gateway-status-indicator/index.d.ts +0 -1
- package/dist/components/primitives/hook-config/hook-config.d.ts +0 -27
- package/dist/components/primitives/hook-config/index.d.ts +0 -1
- package/dist/components/primitives/hook-event-log/hook-event-log.d.ts +0 -27
- package/dist/components/primitives/hook-event-log/index.d.ts +0 -1
- package/dist/components/primitives/intent-selector/index.d.ts +0 -1
- package/dist/components/primitives/intent-selector/intent-selector.d.ts +0 -22
- package/dist/components/primitives/lane-board/index.d.ts +0 -1
- package/dist/components/primitives/lane-board/lane-board.d.ts +0 -26
- package/dist/components/primitives/mcp-server-card/index.d.ts +0 -1
- package/dist/components/primitives/mcp-server-card/mcp-server-card.d.ts +0 -32
- package/dist/components/primitives/memory-editor/index.d.ts +0 -1
- package/dist/components/primitives/memory-editor/memory-editor.d.ts +0 -29
- package/dist/components/primitives/mention-menu/index.d.ts +0 -1
- package/dist/components/primitives/mention-menu/mention-menu.d.ts +0 -44
- package/dist/components/primitives/model-card/index.d.ts +0 -1
- package/dist/components/primitives/model-card/model-card.d.ts +0 -72
- package/dist/components/primitives/model-selector/index.d.ts +0 -1
- package/dist/components/primitives/model-selector/model-selector.d.ts +0 -21
- package/dist/components/primitives/permission-matrix/index.d.ts +0 -1
- package/dist/components/primitives/permission-matrix/permission-matrix.d.ts +0 -43
- package/dist/components/primitives/progress-checklist/index.d.ts +0 -1
- package/dist/components/primitives/progress-checklist/progress-checklist.d.ts +0 -18
- package/dist/components/primitives/project-switcher/index.d.ts +0 -1
- package/dist/components/primitives/project-switcher/project-switcher.d.ts +0 -32
- package/dist/components/primitives/quick-action-chips/index.d.ts +0 -1
- package/dist/components/primitives/quick-action-chips/quick-action-chips.d.ts +0 -22
- package/dist/components/primitives/recent-folders-list/index.d.ts +0 -1
- package/dist/components/primitives/recent-folders-list/recent-folders-list.d.ts +0 -21
- package/dist/components/primitives/rule-card/index.d.ts +0 -1
- package/dist/components/primitives/rule-card/rule-card.d.ts +0 -15
- package/dist/components/primitives/run-stats/index.d.ts +0 -1
- package/dist/components/primitives/run-stats/run-stats.d.ts +0 -16
- package/dist/components/primitives/run-status-pill/index.d.ts +0 -1
- package/dist/components/primitives/run-status-pill/run-status-pill.d.ts +0 -13
- package/dist/components/primitives/running-tasks-panel/index.d.ts +0 -1
- package/dist/components/primitives/running-tasks-panel/running-tasks-panel.d.ts +0 -20
- package/dist/components/primitives/session-list-item/index.d.ts +0 -1
- package/dist/components/primitives/session-list-item/session-list-item.d.ts +0 -35
- package/dist/components/primitives/session-timeline/index.d.ts +0 -1
- package/dist/components/primitives/session-timeline/session-timeline.d.ts +0 -32
- package/dist/components/primitives/skill-card/index.d.ts +0 -1
- package/dist/components/primitives/skill-card/skill-card.d.ts +0 -28
- package/dist/components/primitives/slide/alerts.d.ts +0 -31
- package/dist/components/primitives/slide/frontmatter.d.ts +0 -23
- package/dist/components/primitives/slide/index.d.ts +0 -16
- package/dist/components/primitives/slide/json-schema.d.ts +0 -9
- package/dist/components/primitives/slide/marpit-bg.d.ts +0 -36
- package/dist/components/primitives/slide/parse.d.ts +0 -59
- package/dist/components/primitives/slide/plugin.d.ts +0 -79
- package/dist/components/primitives/slide/plugins/emoji/index.d.ts +0 -8
- package/dist/components/primitives/slide/plugins/emoji/map.d.ts +0 -15
- package/dist/components/primitives/slide/plugins/math/index.d.ts +0 -6
- package/dist/components/primitives/slide/plugins/mermaid/index.d.ts +0 -48
- package/dist/components/primitives/slide/plugins/shiki/index.d.ts +0 -11
- package/dist/components/primitives/slide/sanitize.d.ts +0 -33
- package/dist/components/primitives/slide/schema.d.ts +0 -109
- package/dist/components/primitives/slide/slide.d.ts +0 -53
- package/dist/components/primitives/slide/themes/index.d.ts +0 -9
- package/dist/components/primitives/slide/use-slide-fit.d.ts +0 -21
- package/dist/components/primitives/slide/validate.d.ts +0 -33
- package/dist/components/primitives/steps-rail/index.d.ts +0 -1
- package/dist/components/primitives/steps-rail/steps-rail.d.ts +0 -24
- package/dist/components/primitives/sub-agent-dispatch/index.d.ts +0 -1
- package/dist/components/primitives/sub-agent-dispatch/sub-agent-dispatch.d.ts +0 -30
- package/dist/components/primitives/system-prompt-editor/index.d.ts +0 -1
- package/dist/components/primitives/system-prompt-editor/system-prompt-editor.d.ts +0 -25
- package/dist/components/primitives/task-plan/index.d.ts +0 -1
- package/dist/components/primitives/task-plan/task-plan.d.ts +0 -36
- package/dist/components/primitives/terminal-panel/index.d.ts +0 -1
- package/dist/components/primitives/terminal-panel/terminal-panel.d.ts +0 -32
- package/dist/components/primitives/thinking-level-selector/index.d.ts +0 -1
- package/dist/components/primitives/thinking-level-selector/thinking-level-selector.d.ts +0 -24
- package/dist/components/primitives/token-usage-chart/index.d.ts +0 -2
- package/dist/components/primitives/token-usage-chart/token-usage-chart.d.ts +0 -44
- package/dist/components/primitives/token-usage-chart/usage-metrics.d.ts +0 -23
- package/dist/components/primitives/tool-call/index.d.ts +0 -1
- package/dist/components/primitives/tool-call/tool-call.d.ts +0 -30
- package/dist/components/primitives/tool-call-card/index.d.ts +0 -1
- package/dist/components/primitives/tool-call-card/tool-call-card.d.ts +0 -30
- package/dist/components/primitives/tool-result/index.d.ts +0 -1
- package/dist/components/primitives/tool-result/tool-result.d.ts +0 -19
- package/dist/components/primitives/tools-list/index.d.ts +0 -1
- package/dist/components/primitives/tools-list/tools-list.d.ts +0 -32
- package/dist/components/primitives/whiteboard/index.d.ts +0 -2
- package/dist/components/primitives/whiteboard/render/freedraw.d.ts +0 -2
- package/dist/components/primitives/whiteboard/render/line.d.ts +0 -4
- package/dist/components/primitives/whiteboard/render/rough-paths.d.ts +0 -16
- package/dist/components/primitives/whiteboard/render/scene.d.ts +0 -3
- package/dist/components/primitives/whiteboard/render/shape.d.ts +0 -5
- package/dist/components/primitives/whiteboard/render/style.d.ts +0 -24
- package/dist/components/primitives/whiteboard/render/text.d.ts +0 -2
- package/dist/components/primitives/whiteboard/schema.d.ts +0 -596
- package/dist/components/primitives/whiteboard/seed.d.ts +0 -22
- package/dist/components/primitives/whiteboard/validate.d.ts +0 -26
- package/dist/components/primitives/whiteboard/viewport/use-pointer-pan.d.ts +0 -11
- package/dist/components/primitives/whiteboard/viewport/use-viewport.d.ts +0 -33
- package/dist/components/primitives/whiteboard/whiteboard.d.ts +0 -21
- package/dist/components.css +0 -2
- package/dist/composites/account-menu/index.js +0 -6
- package/dist/composites/account-menu/index.js.map +0 -1
- package/dist/composites/agent-composer/index.js +0 -8
- package/dist/composites/agent-composer/index.js.map +0 -1
- package/dist/composites/agent-editor/index.js +0 -11
- package/dist/composites/agent-editor/index.js.map +0 -1
- package/dist/composites/agent-stream/index.js +0 -24
- package/dist/composites/agent-stream/index.js.map +0 -1
- package/dist/composites/agent-timeline/index.js +0 -5
- package/dist/composites/agent-timeline/index.js.map +0 -1
- package/dist/composites/agent-tool-renderer/index.js +0 -17
- package/dist/composites/agent-tool-renderer/index.js.map +0 -1
- package/dist/composites/approval-card/index.js +0 -5
- package/dist/composites/approval-card/index.js.map +0 -1
- package/dist/composites/chat-composer/index.js +0 -6
- package/dist/composites/chat-composer/index.js.map +0 -1
- package/dist/composites/chat-message/index.js +0 -20
- package/dist/composites/chat-message/index.js.map +0 -1
- package/dist/composites/choice-prompt/index.js +0 -11
- package/dist/composites/choice-prompt/index.js.map +0 -1
- package/dist/composites/code-block/index.js +0 -5
- package/dist/composites/code-block/index.js.map +0 -1
- package/dist/composites/command-palette/index.js +0 -6
- package/dist/composites/command-palette/index.js.map +0 -1
- package/dist/composites/confirm-dialog/index.js +0 -8
- package/dist/composites/confirm-dialog/index.js.map +0 -1
- package/dist/composites/confirm-prompt/index.js +0 -7
- package/dist/composites/confirm-prompt/index.js.map +0 -1
- package/dist/composites/cron-jobs-list/index.js +0 -5
- package/dist/composites/cron-jobs-list/index.js.map +0 -1
- package/dist/composites/data-table/index.js +0 -11
- package/dist/composites/data-table/index.js.map +0 -1
- package/dist/composites/deployment-row/index.js +0 -5
- package/dist/composites/deployment-row/index.js.map +0 -1
- package/dist/composites/domain-config/index.js +0 -8
- package/dist/composites/domain-config/index.js.map +0 -1
- package/dist/composites/env-var-editor/index.js +0 -9
- package/dist/composites/env-var-editor/index.js.map +0 -1
- package/dist/composites/mcp-server-list/index.js +0 -6
- package/dist/composites/mcp-server-list/index.js.map +0 -1
- package/dist/composites/metric-card/index.js +0 -5
- package/dist/composites/metric-card/index.js.map +0 -1
- package/dist/composites/multi-select-prompt/index.js +0 -11
- package/dist/composites/multi-select-prompt/index.js.map +0 -1
- package/dist/composites/page-shell/index.js +0 -8
- package/dist/composites/page-shell/index.js.map +0 -1
- package/dist/composites/permission-modal/index.js +0 -7
- package/dist/composites/permission-modal/index.js.map +0 -1
- package/dist/composites/preview-env-card/index.js +0 -6
- package/dist/composites/preview-env-card/index.js.map +0 -1
- package/dist/composites/preview-panel/index.js +0 -5
- package/dist/composites/preview-panel/index.js.map +0 -1
- package/dist/composites/project-card/index.js +0 -6
- package/dist/composites/project-card/index.js.map +0 -1
- package/dist/composites/rollback-ui/index.js +0 -7
- package/dist/composites/rollback-ui/index.js.map +0 -1
- package/dist/composites/rule-editor/index.js +0 -12
- package/dist/composites/rule-editor/index.js.map +0 -1
- package/dist/composites/skill-editor/index.js +0 -12
- package/dist/composites/skill-editor/index.js.map +0 -1
- package/dist/composites/skills-list/index.js +0 -6
- package/dist/composites/skills-list/index.js.map +0 -1
- package/dist/composites/stability-bundle-viewer/index.js +0 -5
- package/dist/composites/stability-bundle-viewer/index.js.map +0 -1
- package/dist/composites/status-indicator/index.js +0 -4
- package/dist/composites/status-indicator/index.js.map +0 -1
- package/dist/composites/task-header/index.js +0 -5
- package/dist/composites/task-header/index.js.map +0 -1
- package/dist/composites/text-prompt/index.js +0 -10
- package/dist/composites/text-prompt/index.js.map +0 -1
- package/dist/composites/usage-meter/index.js +0 -5
- package/dist/composites/usage-meter/index.js.map +0 -1
- package/dist/fonts/LICENSE-GEIST.txt +0 -92
- package/dist/fonts/geist-400.woff2 +0 -0
- package/dist/fonts/geist-500.woff2 +0 -0
- package/dist/fonts/geist-600.woff2 +0 -0
- package/dist/fonts/geist-mono-400.woff2 +0 -0
- package/dist/fonts/geist-mono-500.woff2 +0 -0
- package/dist/fonts/geist-mono-600.woff2 +0 -0
- package/dist/fonts-cdn.css +0 -28
- package/dist/fonts.css +0 -75
- package/dist/index.js.map +0 -1
- package/dist/lib/markdown/code-block.d.ts +0 -14
- package/dist/lib/markdown/inline-code.d.ts +0 -10
- package/dist/lib/markdown/math.d.ts +0 -12
- package/dist/lib/markdown/mermaid.d.ts +0 -6
- package/dist/lib/markdown/parser.d.ts +0 -47
- package/dist/lib/markdown/streaming-preprocess.d.ts +0 -39
- package/dist/lib/prompt.d.ts +0 -40
- package/dist/lib/sdk-tools-adapters/index.d.ts +0 -1
- package/dist/lib/sdk-tools-adapters/index.js +0 -3
- package/dist/lib/sdk-tools-adapters/index.js.map +0 -1
- package/dist/lib/sdk-tools-adapters/sdk-tools-adapters.d.ts +0 -60
- package/dist/preset-v3-legacy.d.ts +0 -32
- package/dist/preset-v3-legacy.js.map +0 -1
- package/dist/preset.css +0 -27
- package/dist/primitives/action-bar/index.js +0 -4
- package/dist/primitives/action-bar/index.js.map +0 -1
- package/dist/primitives/agent-error-card/index.js +0 -5
- package/dist/primitives/agent-error-card/index.js.map +0 -1
- package/dist/primitives/agent-event/index.js +0 -5
- package/dist/primitives/agent-event/index.js.map +0 -1
- package/dist/primitives/agent-handoff/index.js +0 -4
- package/dist/primitives/agent-handoff/index.js.map +0 -1
- package/dist/primitives/agent-profile/index.js +0 -4
- package/dist/primitives/agent-profile/index.js.map +0 -1
- package/dist/primitives/agent-starting-state/index.js +0 -5
- package/dist/primitives/agent-starting-state/index.js.map +0 -1
- package/dist/primitives/agent-streaming/index.js +0 -5
- package/dist/primitives/agent-streaming/index.js.map +0 -1
- package/dist/primitives/alert/index.js +0 -4
- package/dist/primitives/alert/index.js.map +0 -1
- package/dist/primitives/artifact-preview/index.js +0 -4
- package/dist/primitives/artifact-preview/index.js.map +0 -1
- package/dist/primitives/attachment-chip/index.js +0 -4
- package/dist/primitives/attachment-chip/index.js.map +0 -1
- package/dist/primitives/audit-log-entry/index.js +0 -4
- package/dist/primitives/audit-log-entry/index.js.map +0 -1
- package/dist/primitives/auto-compact-notice/index.js +0 -5
- package/dist/primitives/auto-compact-notice/index.js.map +0 -1
- package/dist/primitives/avatar/index.js +0 -4
- package/dist/primitives/avatar/index.js.map +0 -1
- package/dist/primitives/badge/index.js +0 -4
- package/dist/primitives/badge/index.js.map +0 -1
- package/dist/primitives/branch-indicator/index.js +0 -4
- package/dist/primitives/branch-indicator/index.js.map +0 -1
- package/dist/primitives/browser-controls/index.js +0 -4
- package/dist/primitives/browser-controls/index.js.map +0 -1
- package/dist/primitives/build-log-stream/index.js +0 -7
- package/dist/primitives/build-log-stream/index.js.map +0 -1
- package/dist/primitives/button/index.js +0 -4
- package/dist/primitives/button/index.js.map +0 -1
- package/dist/primitives/capability-indicator/index.js +0 -4
- package/dist/primitives/capability-indicator/index.js.map +0 -1
- package/dist/primitives/card/index.js +0 -5
- package/dist/primitives/card/index.js.map +0 -1
- package/dist/primitives/channel-card/index.js +0 -4
- package/dist/primitives/channel-card/index.js.map +0 -1
- package/dist/primitives/chat-thread/index.js +0 -5
- package/dist/primitives/chat-thread/index.js.map +0 -1
- package/dist/primitives/checkbox/index.js +0 -4
- package/dist/primitives/checkbox/index.js.map +0 -1
- package/dist/primitives/context-card/index.js +0 -4
- package/dist/primitives/context-card/index.js.map +0 -1
- package/dist/primitives/context-window-bar/index.js +0 -4
- package/dist/primitives/context-window-bar/index.js.map +0 -1
- package/dist/primitives/copy-button/index.js +0 -5
- package/dist/primitives/copy-button/index.js.map +0 -1
- package/dist/primitives/cost-meter/index.js +0 -4
- package/dist/primitives/cost-meter/index.js.map +0 -1
- package/dist/primitives/created-files-card/index.js +0 -4
- package/dist/primitives/created-files-card/index.js.map +0 -1
- package/dist/primitives/cron-job-card/index.js +0 -4
- package/dist/primitives/cron-job-card/index.js.map +0 -1
- package/dist/primitives/danger-zone/index.js +0 -4
- package/dist/primitives/danger-zone/index.js.map +0 -1
- package/dist/primitives/dialog/index.js +0 -4
- package/dist/primitives/dialog/index.js.map +0 -1
- package/dist/primitives/diff-viewer/index.js +0 -4
- package/dist/primitives/diff-viewer/index.js.map +0 -1
- package/dist/primitives/dropdown-menu/index.js +0 -4
- package/dist/primitives/dropdown-menu/index.js.map +0 -1
- package/dist/primitives/empty-state/index.js +0 -4
- package/dist/primitives/empty-state/index.js.map +0 -1
- package/dist/primitives/export-chat-dialog/index.js +0 -5
- package/dist/primitives/export-chat-dialog/index.js.map +0 -1
- package/dist/primitives/folder-context-card/index.js +0 -4
- package/dist/primitives/folder-context-card/index.js.map +0 -1
- package/dist/primitives/folder-selector/index.js +0 -4
- package/dist/primitives/folder-selector/index.js.map +0 -1
- package/dist/primitives/form-field/index.js +0 -5
- package/dist/primitives/form-field/index.js.map +0 -1
- package/dist/primitives/gateway-status-indicator/index.js +0 -4
- package/dist/primitives/gateway-status-indicator/index.js.map +0 -1
- package/dist/primitives/hook-config/index.js +0 -5
- package/dist/primitives/hook-config/index.js.map +0 -1
- package/dist/primitives/hook-event-log/index.js +0 -4
- package/dist/primitives/hook-event-log/index.js.map +0 -1
- package/dist/primitives/input/index.js +0 -4
- package/dist/primitives/input/index.js.map +0 -1
- package/dist/primitives/intent-selector/index.js +0 -4
- package/dist/primitives/intent-selector/index.js.map +0 -1
- package/dist/primitives/label/index.js +0 -4
- package/dist/primitives/label/index.js.map +0 -1
- package/dist/primitives/lane-board/index.js +0 -4
- package/dist/primitives/lane-board/index.js.map +0 -1
- package/dist/primitives/login-split/index.js +0 -4
- package/dist/primitives/login-split/index.js.map +0 -1
- package/dist/primitives/mcp-server-card/index.js +0 -4
- package/dist/primitives/mcp-server-card/index.js.map +0 -1
- package/dist/primitives/memory-editor/index.js +0 -4
- package/dist/primitives/memory-editor/index.js.map +0 -1
- package/dist/primitives/mention-menu/index.js +0 -5
- package/dist/primitives/mention-menu/index.js.map +0 -1
- package/dist/primitives/metrics-panel/index.js +0 -4
- package/dist/primitives/metrics-panel/index.js.map +0 -1
- package/dist/primitives/model-card/index.js +0 -4
- package/dist/primitives/model-card/index.js.map +0 -1
- package/dist/primitives/model-selector/index.js +0 -4
- package/dist/primitives/model-selector/index.js.map +0 -1
- package/dist/primitives/pagination/index.js +0 -4
- package/dist/primitives/pagination/index.js.map +0 -1
- package/dist/primitives/permission-matrix/index.js +0 -5
- package/dist/primitives/permission-matrix/index.js.map +0 -1
- package/dist/primitives/pin-input/index.js +0 -5
- package/dist/primitives/pin-input/index.js.map +0 -1
- package/dist/primitives/plan-badge/index.js +0 -4
- package/dist/primitives/plan-badge/index.js.map +0 -1
- package/dist/primitives/progress/index.js +0 -4
- package/dist/primitives/progress/index.js.map +0 -1
- package/dist/primitives/progress-checklist/index.js +0 -4
- package/dist/primitives/progress-checklist/index.js.map +0 -1
- package/dist/primitives/project-switcher/index.js +0 -4
- package/dist/primitives/project-switcher/index.js.map +0 -1
- package/dist/primitives/quick-action-chips/index.js +0 -4
- package/dist/primitives/quick-action-chips/index.js.map +0 -1
- package/dist/primitives/radio-group/index.js +0 -4
- package/dist/primitives/radio-group/index.js.map +0 -1
- package/dist/primitives/recent-folders-list/index.js +0 -4
- package/dist/primitives/recent-folders-list/index.js.map +0 -1
- package/dist/primitives/rule-card/index.js +0 -4
- package/dist/primitives/rule-card/index.js.map +0 -1
- package/dist/primitives/run-stats/index.js +0 -4
- package/dist/primitives/run-stats/index.js.map +0 -1
- package/dist/primitives/run-status-pill/index.js +0 -4
- package/dist/primitives/run-status-pill/index.js.map +0 -1
- package/dist/primitives/running-tasks-panel/index.js +0 -4
- package/dist/primitives/running-tasks-panel/index.js.map +0 -1
- package/dist/primitives/scroll-area/index.js +0 -5
- package/dist/primitives/scroll-area/index.js.map +0 -1
- package/dist/primitives/select/index.js +0 -4
- package/dist/primitives/select/index.js.map +0 -1
- package/dist/primitives/session-list-item/index.js +0 -4
- package/dist/primitives/session-list-item/index.js.map +0 -1
- package/dist/primitives/session-timeline/index.js +0 -4
- package/dist/primitives/session-timeline/index.js.map +0 -1
- package/dist/primitives/sheet/index.js +0 -4
- package/dist/primitives/sheet/index.js.map +0 -1
- package/dist/primitives/sidebar/index.js +0 -4
- package/dist/primitives/sidebar/index.js.map +0 -1
- package/dist/primitives/skeleton/index.js +0 -5
- package/dist/primitives/skeleton/index.js.map +0 -1
- package/dist/primitives/skill-card/index.js +0 -4
- package/dist/primitives/skill-card/index.js.map +0 -1
- package/dist/primitives/social-auth-row/index.js +0 -4
- package/dist/primitives/social-auth-row/index.js.map +0 -1
- package/dist/primitives/stat-tile/index.js +0 -4
- package/dist/primitives/stat-tile/index.js.map +0 -1
- package/dist/primitives/status-dot/index.js +0 -6
- package/dist/primitives/status-dot/index.js.map +0 -1
- package/dist/primitives/steps-rail/index.js +0 -4
- package/dist/primitives/steps-rail/index.js.map +0 -1
- package/dist/primitives/sub-agent-dispatch/index.js +0 -4
- package/dist/primitives/sub-agent-dispatch/index.js.map +0 -1
- package/dist/primitives/switch/index.js +0 -4
- package/dist/primitives/switch/index.js.map +0 -1
- package/dist/primitives/system-prompt-editor/index.js +0 -5
- package/dist/primitives/system-prompt-editor/index.js.map +0 -1
- package/dist/primitives/table/index.js +0 -5
- package/dist/primitives/table/index.js.map +0 -1
- package/dist/primitives/tabs/index.js +0 -4
- package/dist/primitives/tabs/index.js.map +0 -1
- package/dist/primitives/task-plan/index.js +0 -4
- package/dist/primitives/task-plan/index.js.map +0 -1
- package/dist/primitives/terminal-panel/index.js +0 -5
- package/dist/primitives/terminal-panel/index.js.map +0 -1
- package/dist/primitives/textarea/index.js +0 -4
- package/dist/primitives/textarea/index.js.map +0 -1
- package/dist/primitives/thinking-level-selector/index.js +0 -5
- package/dist/primitives/thinking-level-selector/index.js.map +0 -1
- package/dist/primitives/timestamp/index.js +0 -6
- package/dist/primitives/timestamp/index.js.map +0 -1
- package/dist/primitives/toast/index.js +0 -5
- package/dist/primitives/toast/index.js.map +0 -1
- package/dist/primitives/token-usage-chart/index.js +0 -4
- package/dist/primitives/token-usage-chart/index.js.map +0 -1
- package/dist/primitives/tool-call/index.js +0 -5
- package/dist/primitives/tool-call/index.js.map +0 -1
- package/dist/primitives/tool-call-card/index.js +0 -5
- package/dist/primitives/tool-call-card/index.js.map +0 -1
- package/dist/primitives/tool-result/index.js +0 -4
- package/dist/primitives/tool-result/index.js.map +0 -1
- package/dist/primitives/tools-list/index.js +0 -4
- package/dist/primitives/tools-list/index.js.map +0 -1
- package/dist/primitives/tooltip/index.js +0 -4
- package/dist/primitives/tooltip/index.js.map +0 -1
- package/dist/primitives/topnav/index.js +0 -4
- package/dist/primitives/topnav/index.js.map +0 -1
- package/dist/primitives/update-banner/index.js +0 -4
- package/dist/primitives/update-banner/index.js.map +0 -1
- package/dist/screens/theo-code-shell.d.ts +0 -9
- package/dist/screens/theo-code-shell.data.d.ts +0 -147
- package/dist/slide/index.js +0 -4
- package/dist/slide/index.js.map +0 -1
- package/dist/slide/plugins/emoji/index.js +0 -157
- package/dist/slide/plugins/emoji/index.js.map +0 -1
- package/dist/slide/plugins/math/index.js +0 -145
- package/dist/slide/plugins/math/index.js.map +0 -1
- package/dist/slide/plugins/mermaid/index.js +0 -218
- package/dist/slide/plugins/mermaid/index.js.map +0 -1
- package/dist/slide/plugins/shiki/index.js +0 -87
- package/dist/slide/plugins/shiki/index.js.map +0 -1
- package/dist/slide/themes/default.css +0 -256
- package/dist/slide/themes/layouts.css +0 -143
- package/dist/slide/themes/violet-forge.css +0 -256
- package/dist/slide-deck/index.css +0 -52
- package/dist/slide-deck/index.css.map +0 -1
- package/dist/slide-deck/index.js +0 -1122
- package/dist/slide-deck/index.js.map +0 -1
- package/dist/styles-v3-legacy.css +0 -88
- package/dist/styles.css +0 -137
- package/dist/themes/anthropic-style.d.ts +0 -11
- package/dist/themes/aurora-terminal.d.ts +0 -9
- package/dist/themes/classic-paper.d.ts +0 -17
- package/dist/themes/color-value-pattern.d.ts +0 -22
- package/dist/themes/color.d.ts +0 -62
- package/dist/themes/define.d.ts +0 -65
- package/dist/themes/density.d.ts +0 -17
- package/dist/themes/dracula.d.ts +0 -14
- package/dist/themes/github-dark.d.ts +0 -11
- package/dist/themes/index.d.ts +0 -26
- package/dist/themes/linear-glass.d.ts +0 -11
- package/dist/themes/one-dark.d.ts +0 -11
- package/dist/themes/openai-style.d.ts +0 -10
- package/dist/themes/schema.d.ts +0 -112
- package/dist/themes/theme-provider.d.ts +0 -82
- package/dist/themes/theme-script.d.ts +0 -48
- package/dist/themes/theme-switcher.d.ts +0 -17
- package/dist/themes/types.d.ts +0 -88
- package/dist/themes/vercel-mono.d.ts +0 -11
- package/dist/themes/violet-forge.d.ts +0 -12
- package/dist/theo-ui-provider.d.ts +0 -50
- package/dist/tokens-v4.css +0 -223
- package/dist/tokens.css +0 -315
- package/dist/types/agent.d.ts +0 -19
- package/dist/types/chat.d.ts +0 -173
- package/dist/types/mode.d.ts +0 -16
- package/dist/types/permission.d.ts +0 -8
- package/dist/types/rule.d.ts +0 -28
- package/dist/vite-plugin.d.ts +0 -25
- package/dist/vite-plugin.js +0 -76
- package/dist/vite-plugin.js.map +0 -1
- package/dist/whiteboard/index.js +0 -741
- package/dist/whiteboard/index.js.map +0 -1
- package/llms.txt +0 -273
- package/registry/index.json +0 -910
- package/registry/r/account-menu.json +0 -24
- package/registry/r/action-bar.json +0 -22
- package/registry/r/agent-composer.json +0 -22
- package/registry/r/agent-editor.json +0 -27
- package/registry/r/agent-error-card.json +0 -22
- package/registry/r/agent-event.json +0 -24
- package/registry/r/agent-handoff.json +0 -22
- package/registry/r/agent-profile.json +0 -23
- package/registry/r/agent-starting-state.json +0 -22
- package/registry/r/agent-stream.json +0 -27
- package/registry/r/agent-streaming.json +0 -22
- package/registry/r/agent-timeline.json +0 -22
- package/registry/r/agent-tool-renderer.json +0 -40
- package/registry/r/agent-types.json +0 -15
- package/registry/r/alert.json +0 -22
- package/registry/r/approval-card.json +0 -25
- package/registry/r/artifact-preview.json +0 -22
- package/registry/r/attachment-chip.json +0 -24
- package/registry/r/audit-log-entry.json +0 -23
- package/registry/r/auto-compact-notice.json +0 -22
- package/registry/r/avatar.json +0 -23
- package/registry/r/badge.json +0 -22
- package/registry/r/browser-controls.json +0 -22
- package/registry/r/build-log-stream.json +0 -20
- package/registry/r/button.json +0 -23
- package/registry/r/capability-indicator.json +0 -23
- package/registry/r/card.json +0 -22
- package/registry/r/chat-composer.json +0 -23
- package/registry/r/chat-message.json +0 -124
- package/registry/r/chat-thread.json +0 -20
- package/registry/r/chat-types.json +0 -15
- package/registry/r/checkbox.json +0 -24
- package/registry/r/choice-prompt.json +0 -25
- package/registry/r/cn.json +0 -19
- package/registry/r/code-block.json +0 -21
- package/registry/r/command-palette.json +0 -25
- package/registry/r/confirm-dialog.json +0 -25
- package/registry/r/confirm-prompt.json +0 -21
- package/registry/r/context-card.json +0 -23
- package/registry/r/context-window-bar.json +0 -20
- package/registry/r/copy-button.json +0 -22
- package/registry/r/cost-meter.json +0 -22
- package/registry/r/created-files-card.json +0 -23
- package/registry/r/cron-job-card.json +0 -22
- package/registry/r/cron-jobs-list.json +0 -23
- package/registry/r/danger-zone.json +0 -20
- package/registry/r/data-table.json +0 -27
- package/registry/r/deployment-row.json +0 -23
- package/registry/r/dialog.json +0 -23
- package/registry/r/diff-viewer.json +0 -20
- package/registry/r/domain-config.json +0 -25
- package/registry/r/dropdown-menu.json +0 -23
- package/registry/r/empty-state.json +0 -20
- package/registry/r/env-var-editor.json +0 -26
- package/registry/r/env.json +0 -15
- package/registry/r/folder-context-card.json +0 -23
- package/registry/r/folder-selector.json +0 -22
- package/registry/r/form-field.json +0 -23
- package/registry/r/hook-config.json +0 -22
- package/registry/r/hook-event-log.json +0 -22
- package/registry/r/input.json +0 -22
- package/registry/r/intent-selector.json +0 -24
- package/registry/r/label.json +0 -22
- package/registry/r/lane-board.json +0 -20
- package/registry/r/live-region-context.json +0 -16
- package/registry/r/login-split.json +0 -20
- package/registry/r/mcp-server-card.json +0 -22
- package/registry/r/mcp-server-list.json +0 -23
- package/registry/r/memory-editor.json +0 -23
- package/registry/r/mention-menu.json +0 -23
- package/registry/r/metric-card.json +0 -23
- package/registry/r/metrics-panel.json +0 -22
- package/registry/r/mode-types.json +0 -15
- package/registry/r/model-card.json +0 -23
- package/registry/r/model-selector.json +0 -23
- package/registry/r/multi-select-prompt.json +0 -25
- package/registry/r/page-shell.json +0 -25
- package/registry/r/pagination.json +0 -22
- package/registry/r/permission-matrix.json +0 -22
- package/registry/r/permission-modal.json +0 -24
- package/registry/r/permission-types.json +0 -15
- package/registry/r/pin-input.json +0 -20
- package/registry/r/plan-badge.json +0 -20
- package/registry/r/preview-env-card.json +0 -25
- package/registry/r/preview-panel.json +0 -21
- package/registry/r/progress-checklist.json +0 -23
- package/registry/r/progress.json +0 -20
- package/registry/r/project-card.json +0 -25
- package/registry/r/project-switcher.json +0 -22
- package/registry/r/prompt.json +0 -15
- package/registry/r/quick-action-chips.json +0 -21
- package/registry/r/radio-group.json +0 -23
- package/registry/r/recent-folders-list.json +0 -22
- package/registry/r/rollback-ui.json +0 -24
- package/registry/r/rule-card.json +0 -23
- package/registry/r/rule-editor.json +0 -28
- package/registry/r/rule-types.json +0 -18
- package/registry/r/run-stats.json +0 -22
- package/registry/r/running-tasks-panel.json +0 -22
- package/registry/r/safe-href.json +0 -16
- package/registry/r/scroll-area.json +0 -22
- package/registry/r/select.json +0 -24
- package/registry/r/session-list-item.json +0 -20
- package/registry/r/session-timeline.json +0 -22
- package/registry/r/sheet.json +0 -24
- package/registry/r/sidebar.json +0 -19
- package/registry/r/skeleton.json +0 -19
- package/registry/r/skill-card.json +0 -24
- package/registry/r/skill-editor.json +0 -28
- package/registry/r/skills-list.json +0 -23
- package/registry/r/slide-deck.json +0 -130
- package/registry/r/slide-plugin-emoji.json +0 -28
- package/registry/r/slide-plugin-math.json +0 -24
- package/registry/r/slide-plugin-mermaid.json +0 -23
- package/registry/r/slide-plugin-shiki.json +0 -23
- package/registry/r/slide.json +0 -123
- package/registry/r/social-auth-row.json +0 -21
- package/registry/r/stat-tile.json +0 -22
- package/registry/r/status-dot.json +0 -21
- package/registry/r/status-indicator.json +0 -20
- package/registry/r/steps-rail.json +0 -20
- package/registry/r/sub-agent-dispatch.json +0 -22
- package/registry/r/switch.json +0 -23
- package/registry/r/system-prompt-editor.json +0 -22
- package/registry/r/table.json +0 -22
- package/registry/r/tabs.json +0 -22
- package/registry/r/tailwind-preset.json +0 -19
- package/registry/r/task-header.json +0 -24
- package/registry/r/task-plan.json +0 -22
- package/registry/r/task-types.json +0 -15
- package/registry/r/terminal-panel.json +0 -22
- package/registry/r/text-prompt.json +0 -24
- package/registry/r/textarea.json +0 -22
- package/registry/r/theme-provider.json +0 -60
- package/registry/r/theme-script.json +0 -18
- package/registry/r/theo-ui-provider.json +0 -20
- package/registry/r/timestamp.json +0 -21
- package/registry/r/toast.json +0 -30
- package/registry/r/token-usage-chart.json +0 -20
- package/registry/r/tokens.json +0 -21
- package/registry/r/tool-call-card.json +0 -23
- package/registry/r/tool-call.json +0 -22
- package/registry/r/tool-result.json +0 -20
- package/registry/r/tools-list.json +0 -23
- package/registry/r/tooltip.json +0 -22
- package/registry/r/topnav.json +0 -22
- package/registry/r/types.json +0 -15
- package/registry/r/usage-meter.json +0 -21
- package/registry/r/whiteboard.json +0 -101
package/registry/r/tabs.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "tabs",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "Tabs",
|
|
6
|
-
"description": "Built on Radix Tabs with active-underline styling and focus-visible ring.",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"@radix-ui/react-tabs"
|
|
9
|
-
],
|
|
10
|
-
"registryDependencies": [
|
|
11
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
12
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
|
|
13
|
-
],
|
|
14
|
-
"files": [
|
|
15
|
-
{
|
|
16
|
-
"path": "components/primitives/tabs/tabs.tsx",
|
|
17
|
-
"type": "registry:ui",
|
|
18
|
-
"target": "components/ui/tabs.tsx",
|
|
19
|
-
"content": "import * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ElementRef } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Tabs — built on Radix Tabs.\n *\n * Visual: underlined active tab in primary (violet), inactive in muted-foreground.\n * Used in project views (Overview / Deployments / Logs / Settings).\n */\n\nconst List = forwardRef<\n ElementRef<typeof TabsPrimitive.List>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n ref={ref}\n className={cn(\n \"inline-flex h-10 items-center border-border/40 border-b text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\nList.displayName = \"Tabs.List\";\n\nconst Trigger = forwardRef<\n ElementRef<typeof TabsPrimitive.Trigger>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n ref={ref}\n className={cn(\n \"relative inline-flex h-10 items-center justify-center whitespace-nowrap px-4\",\n \"font-medium font-sans text-body-sm text-muted-foreground\",\n \"transition-colors duration-base ease-out-soft\",\n \"hover:text-foreground\",\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:pointer-events-none disabled:opacity-50\",\n \"data-[state=active]:text-foreground\",\n // Active underline using a pseudo-element via shadow\n \"data-[state=active]:shadow-[inset_0_-2px_0_0_hsl(var(--primary))]\",\n className,\n )}\n {...props}\n />\n));\nTrigger.displayName = \"Tabs.Trigger\";\n\nconst Content = forwardRef<\n ElementRef<typeof TabsPrimitive.Content>,\n ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n ref={ref}\n className={cn(\n \"mt-4 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n className,\n )}\n {...props}\n />\n));\nContent.displayName = \"Tabs.Content\";\n\nconst Tabs = /*#__PURE__*/ Object.assign(TabsPrimitive.Root, {\n List,\n Trigger,\n Content,\n});\n\nexport { Tabs };\n"
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "tailwind-preset",
|
|
4
|
-
"type": "registry:lib",
|
|
5
|
-
"title": "Theo UI Tailwind preset",
|
|
6
|
-
"description": "Type scale, fontFamily, colors and motion tokens consumed by every Theo UI component. Add to tailwind.config.ts#presets before installing any other component.",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"tailwindcss",
|
|
9
|
-
"tailwindcss-animate"
|
|
10
|
-
],
|
|
11
|
-
"files": [
|
|
12
|
-
{
|
|
13
|
-
"path": "styles/tailwind-preset.ts",
|
|
14
|
-
"type": "registry:lib",
|
|
15
|
-
"target": "styles/tailwind-preset.ts",
|
|
16
|
-
"content": "/**\n * Theo UI Tailwind preset — Violet Forge identity.\n *\n * Single source of truth for the design system's utility-level tokens:\n * - colors mapped to CSS variables (HSL split via `hsl(var(--x) / <alpha>)`)\n * - Geist-inspired typescale (display / title / body / label / code tiers)\n * - radii, shadows, motion timing & duration, keyframes\n * - tailwindcss-animate plugin\n *\n * Consumed by:\n * - `tailwind.config.ts` (this repo) via `presets: [theoUIPreset]`\n * - registry/r/tailwind-preset.json (shipped to consumers via shadcn CLI)\n *\n * Consumers integrate as:\n *\n * import type { Config } from \"tailwindcss\";\n * import { theoUIPreset } from \"./styles/tailwind-preset\";\n *\n * export default {\n * darkMode: \"class\",\n * content: [\"./src/**\\/*.{ts,tsx}\"],\n * presets: [theoUIPreset],\n * } satisfies Config;\n *\n * Note: `darkMode` and `content` are NOT in the preset — they are consumer\n * decisions. The preset only contains `theme.extend.*` and `plugins`.\n */\n\nimport type { Config } from \"tailwindcss\";\nimport animate from \"tailwindcss-animate\";\n\n// Post-T2.4 (ADR-0005): tokens are OKLCH. The previous `hsl(var(--x) / <alpha>)`\n// pattern resolves to `hsl(oklch(...))` which is invalid CSS — utilities\n// silently fall back to transparent. OKLCH relative-color syntax preserves\n// Tailwind's `<alpha-value>` slot for opacity modifiers (e.g. `bg-primary/50`).\nconst hsl = (token: string) => `oklch(from var(${token}) l c h / <alpha-value>)`;\n\nexport const theoUIPreset: Partial<Config> = {\n theme: {\n container: {\n center: true,\n padding: \"1rem\",\n screens: {\n \"2xl\": \"1280px\",\n },\n },\n extend: {\n colors: {\n background: hsl(\"--background\"),\n foreground: hsl(\"--foreground\"),\n card: {\n DEFAULT: hsl(\"--card\"),\n foreground: hsl(\"--card-foreground\"),\n },\n popover: {\n DEFAULT: hsl(\"--popover\"),\n foreground: hsl(\"--popover-foreground\"),\n },\n primary: {\n DEFAULT: hsl(\"--primary\"),\n deep: hsl(\"--primary-deep\"),\n glow: hsl(\"--primary-glow\"),\n foreground: hsl(\"--primary-foreground\"),\n },\n secondary: {\n DEFAULT: hsl(\"--secondary\"),\n foreground: hsl(\"--secondary-foreground\"),\n },\n accent: {\n DEFAULT: hsl(\"--accent\"),\n deep: hsl(\"--accent-deep\"),\n foreground: hsl(\"--accent-foreground\"),\n },\n muted: {\n DEFAULT: hsl(\"--muted\"),\n foreground: hsl(\"--muted-foreground\"),\n },\n success: {\n DEFAULT: hsl(\"--success\"),\n foreground: hsl(\"--success-foreground\"),\n },\n warning: {\n DEFAULT: hsl(\"--warning\"),\n foreground: hsl(\"--warning-foreground\"),\n },\n destructive: {\n DEFAULT: hsl(\"--destructive\"),\n foreground: hsl(\"--destructive-foreground\"),\n },\n info: {\n DEFAULT: hsl(\"--info\"),\n foreground: hsl(\"--info-foreground\"),\n },\n // Status palette (online/offline/degraded/info) consumed by\n // StatusIndicator via `bg-status-*`. The `--status-*` tokens already\n // live in tokens.css; this block was missing from the v3 preset (only\n // the v4 `@theme` declared `--color-status-*`), so `bg-status-online`\n // resolved to nothing in the v3/Ladle build — transparent dots.\n status: {\n online: {\n DEFAULT: hsl(\"--status-online\"),\n foreground: hsl(\"--status-online-foreground\"),\n },\n offline: {\n DEFAULT: hsl(\"--status-offline\"),\n foreground: hsl(\"--status-offline-foreground\"),\n },\n degraded: {\n DEFAULT: hsl(\"--status-degraded\"),\n foreground: hsl(\"--status-degraded-foreground\"),\n },\n info: { DEFAULT: hsl(\"--status-info\"), foreground: hsl(\"--status-info-foreground\") },\n },\n border: hsl(\"--border\"),\n input: hsl(\"--input\"),\n ring: hsl(\"--ring\"),\n },\n fontFamily: {\n display: \"var(--font-display)\",\n sans: \"var(--font-body)\",\n mono: \"var(--font-mono)\",\n },\n /* Geist-inspired Violet Forge typescale.\n *\n * Three strict weights: 400 (body), 500 (UI), 600 (display/headings).\n * Letter-spacing scales with size — aggressive negative on display.\n * Mirrors the Vercel/Geist vocabulary while keeping Theo's identity.\n */\n fontSize: {\n // Display tier — aggressive compression, content-led headlines\n \"display-2xl\": [\"64px\", { lineHeight: \"1\", letterSpacing: \"-0.0464em\", fontWeight: \"600\" }],\n \"display-xl\": [\"48px\", { lineHeight: \"1.05\", letterSpacing: \"-0.05em\", fontWeight: \"600\" }],\n \"display-lg\": [\"40px\", { lineHeight: \"1.1\", letterSpacing: \"-0.05em\", fontWeight: \"600\" }],\n \"display-md\": [\"32px\", { lineHeight: \"1.2\", letterSpacing: \"-0.04em\", fontWeight: \"600\" }],\n headline: [\"28px\", { lineHeight: \"1.25\", letterSpacing: \"-0.035em\", fontWeight: \"600\" }],\n // Title tier — section / card heads\n \"title-lg\": [\"24px\", { lineHeight: \"1.33\", letterSpacing: \"-0.04em\", fontWeight: \"600\" }],\n \"title-md\": [\"20px\", { lineHeight: \"1.4\", letterSpacing: \"-0.03em\", fontWeight: \"600\" }],\n // Body tier — FAANG-density realignment 2026-05-22: body-md is the\n // industry-standard 14px (shadcn / Vercel Geist / Linear / Stripe /\n // Mantine). The previous 15px was idiosyncratic. body-sm (14px label\n // weight) remains separate via its line-height / weight signature.\n \"body-lg\": [\"18px\", { lineHeight: \"1.56\", letterSpacing: \"-0.01em\", fontWeight: \"400\" }],\n \"body-md\": [\"14px\", { lineHeight: \"1.43\", letterSpacing: \"0\", fontWeight: \"400\" }],\n \"body-sm\": [\"13px\", { lineHeight: \"1.46\", fontWeight: \"400\" }],\n // Label tier — used on buttons, nav, secondary actions\n label: [\"14px\", { lineHeight: \"1.43\", fontWeight: \"500\" }],\n \"label-caps\": [\"12px\", { lineHeight: \"1.33\", letterSpacing: \"0.04em\", fontWeight: \"500\" }],\n // Mono — code surfaces, technical labels\n \"code-md\": [\"14px\", { lineHeight: \"1.5\", fontWeight: \"400\" }],\n \"code-sm\": [\"13px\", { lineHeight: \"1.54\", fontWeight: \"500\" }],\n },\n borderRadius: {\n none: \"var(--radius-none)\",\n sm: \"var(--radius-sm)\",\n md: \"var(--radius-md)\",\n lg: \"var(--radius-lg)\",\n xl: \"var(--radius-xl)\",\n \"2xl\": \"var(--radius-2xl)\",\n full: \"var(--radius-full)\",\n },\n boxShadow: {\n sm: \"var(--shadow-sm)\",\n md: \"var(--shadow-md)\",\n lg: \"var(--shadow-lg)\",\n glow: \"var(--shadow-glow)\",\n \"glow-strong\": \"var(--shadow-glow-strong)\",\n },\n transitionTimingFunction: {\n \"out-soft\": \"var(--ease-out-soft)\",\n snap: \"var(--ease-snap)\",\n },\n transitionDuration: {\n fast: \"var(--duration-fast)\",\n base: \"var(--duration-base)\",\n slow: \"var(--duration-slow)\",\n },\n keyframes: {\n \"fade-in-up\": {\n \"0%\": { opacity: \"0\", transform: \"translateY(8px)\" },\n \"100%\": { opacity: \"1\", transform: \"translateY(0)\" },\n },\n \"pulse-glow\": {\n \"0%, 100%\": { boxShadow: \"0 0 0 0 hsl(var(--primary) / 0.5)\" },\n \"50%\": { boxShadow: \"0 0 0 8px hsl(var(--primary) / 0)\" },\n },\n },\n animation: {\n \"fade-in-up\": \"fade-in-up var(--duration-base) var(--ease-out-soft) both\",\n \"pulse-glow\": \"pulse-glow 1.5s var(--ease-in-out) infinite\",\n },\n },\n },\n plugins: [animate],\n};\n"
|
|
17
|
-
}
|
|
18
|
-
]
|
|
19
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "task-header",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "TaskHeader",
|
|
6
|
-
"description": "Title bar for a task pane — composite combining heading, status badge, and chevron menu.",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"lucide-react"
|
|
9
|
-
],
|
|
10
|
-
"registryDependencies": [
|
|
11
|
-
"https://usetheodev.github.io/theo-ui/r/badge.json",
|
|
12
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
13
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json",
|
|
14
|
-
"https://usetheodev.github.io/theo-ui/r/task-types.json"
|
|
15
|
-
],
|
|
16
|
-
"files": [
|
|
17
|
-
{
|
|
18
|
-
"path": "components/composites/task-header/task-header.tsx",
|
|
19
|
-
"type": "registry:ui",
|
|
20
|
-
"target": "components/ui/task-header.tsx",
|
|
21
|
-
"content": "import { ChevronDown } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport type { TaskStatus } from \"@/types/task\";\nimport { Badge } from \"@/components/ui/badge\";\n\nconst statusVariant: Record<\n TaskStatus,\n \"default\" | \"primary\" | \"warning\" | \"success\" | \"destructive\"\n> = {\n idle: \"default\",\n permission_required: \"warning\",\n starting: \"primary\",\n running: \"primary\",\n verifying: \"primary\",\n completed: \"success\",\n failed: \"destructive\",\n};\nconst statusDot: Record<TaskStatus, \"primary\" | \"success\" | \"warning\" | \"destructive\" | \"muted\"> = {\n idle: \"muted\",\n permission_required: \"warning\",\n starting: \"primary\",\n running: \"primary\",\n verifying: \"primary\",\n completed: \"success\",\n failed: \"destructive\",\n};\nconst statusLabel: Record<TaskStatus, string> = {\n idle: \"Idle\",\n permission_required: \"Permission required\",\n starting: \"Starting up\",\n running: \"Running\",\n verifying: \"Verifying\",\n completed: \"Completed\",\n failed: \"Failed\",\n};\n\ninterface TaskHeaderProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n title: ReactNode;\n status?: TaskStatus;\n /**\n * If provided, a chevron is shown next to the title and clicking it fires this callback.\n * Used as the \"expand task metadata\" affordance in the Infra shell.\n */\n onToggle?: () => void;\n /** Right-side actions (e.g. cancel task, close panel). */\n actions?: ReactNode;\n}\n\n/**\n * TaskHeader — title bar for a task pane.\n *\n * Visual: display-md title with chevron + optional status badge with pulse + actions slot.\n */\nconst TaskHeader = forwardRef<HTMLElement, TaskHeaderProps>(\n ({ className, title, status, onToggle, actions, ...props }, ref) => (\n <header\n data-slot=\"task-header\"\n ref={ref}\n className={cn(\n \"flex items-center justify-between gap-3 rounded-xl border border-border/40 bg-card px-4 py-3\",\n className,\n )}\n {...props}\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n <h2 className=\"truncate font-display text-title-lg tracking-tight\">{title}</h2>\n {onToggle ? (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-label=\"Toggle task details\"\n className=\"rounded-md p-1 text-muted-foreground hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronDown className=\"size-4\" />\n </button>\n ) : null}\n </div>\n <div className=\"flex items-center gap-2\">\n {status ? (\n <Badge variant={statusVariant[status]}>\n <Badge.Dot\n tone={statusDot[status]}\n pulse={status === \"running\" || status === \"starting\" || status === \"verifying\"}\n />\n {statusLabel[status]}\n </Badge>\n ) : null}\n {actions}\n </div>\n </header>\n ),\n);\nTaskHeader.displayName = \"TaskHeader\";\n\nexport { TaskHeader };\n"
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "task-plan",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "TaskPlan",
|
|
6
|
-
"description": "Hierarchical task plan, à la Claude \"plan mode\".",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"lucide-react"
|
|
9
|
-
],
|
|
10
|
-
"registryDependencies": [
|
|
11
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
12
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
|
|
13
|
-
],
|
|
14
|
-
"files": [
|
|
15
|
-
{
|
|
16
|
-
"path": "components/primitives/task-plan/task-plan.tsx",
|
|
17
|
-
"type": "registry:ui",
|
|
18
|
-
"target": "components/ui/task-plan.tsx",
|
|
19
|
-
"content": "import { CheckCircle2, Circle, CircleDashed, CircleX, Loader2 } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nexport type PlanNodeStatus = \"pending\" | \"running\" | \"done\" | \"skipped\" | \"failed\";\n\nexport interface PlanNode {\n id: string;\n label: string;\n status: PlanNodeStatus;\n /** Optional details / sub-explanation. */\n detail?: string;\n /** Sub-nodes (rendered indented). */\n children?: PlanNode[];\n}\n\nconst STATUS_ICON = {\n pending: CircleDashed,\n running: Loader2,\n done: CheckCircle2,\n skipped: Circle,\n failed: CircleX,\n} as const;\n\nconst STATUS_COLOR: Record<PlanNodeStatus, string> = {\n pending: \"text-muted-foreground\",\n running: \"text-primary\",\n done: \"text-success\",\n skipped: \"text-muted-foreground/60\",\n failed: \"text-destructive\",\n};\n\nconst LABEL_STYLE: Record<PlanNodeStatus, string> = {\n pending: \"text-foreground\",\n running: \"text-foreground\",\n done: \"text-foreground line-through decoration-muted-foreground/40\",\n skipped: \"text-muted-foreground line-through\",\n failed: \"text-destructive\",\n};\n\ninterface TaskNodeProps extends HTMLAttributes<HTMLLIElement> {\n node: PlanNode;\n depth?: number;\n}\n\n/**\n * TaskNode — single row in a task plan. Renders its own children recursively\n * with increasing indentation.\n */\nconst TaskNode = forwardRef<HTMLLIElement, TaskNodeProps>(\n ({ className, node, depth = 0, ...props }, ref) => {\n const Icon = STATUS_ICON[node.status];\n return (\n <li\n data-slot=\"task-node\"\n ref={ref}\n className={cn(\"grid gap-1\", className)}\n style={{ marginLeft: `${depth * 1.25}rem` }}\n {...props}\n >\n <div className=\"grid grid-cols-[auto_1fr] items-baseline gap-2\">\n <Icon\n aria-hidden=\"true\"\n className={cn(\n \"mt-0.5 size-3.5 shrink-0\",\n STATUS_COLOR[node.status],\n node.status === \"running\" && \"animate-spin\",\n )}\n />\n <div className=\"min-w-0\">\n <p className={cn(\"text-body-sm\", LABEL_STYLE[node.status])}>{node.label}</p>\n {node.detail ? (\n <p className=\"text-body-sm text-muted-foreground\">{node.detail}</p>\n ) : null}\n </div>\n </div>\n {node.children && node.children.length > 0 ? (\n <ul className=\"grid gap-1 border-border/30 border-l pl-2\">\n {node.children.map((child) => (\n <TaskNode key={child.id} node={child} depth={depth + 1} />\n ))}\n </ul>\n ) : null}\n </li>\n );\n },\n);\nTaskNode.displayName = \"TaskNode\";\n\ninterface TaskPlanProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n nodes: PlanNode[];\n /** Header title. */\n title?: ReactNode;\n /** Summary line shown next to the title (e.g. \"3 of 7 done\"). */\n summary?: ReactNode;\n}\n\n/**\n * TaskPlan — hierarchical task plan, à la Claude \"plan mode\".\n *\n * The agent emits a structured plan; the user sees each step progress from\n * pending → running → done (or failed/skipped). Children render with one\n * extra indent level and a left border to suggest hierarchy.\n */\nconst TaskPlan = forwardRef<HTMLElement, TaskPlanProps>(\n ({ className, nodes, title = \"Plan\", summary, ...props }, ref) => {\n const auto = nodes.length;\n const done = nodes.filter((n) => n.status === \"done\").length;\n const computedSummary = summary ?? (auto > 0 ? `${done} of ${auto} done` : \"no steps\");\n return (\n <section\n data-slot=\"task-plan\"\n ref={ref}\n className={cn(\"rounded-xl border bg-card p-4\", className)}\n {...props}\n >\n <header className=\"mb-3 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 {computedSummary}\n </span>\n </header>\n <ul className=\"grid gap-1.5\">\n {nodes.map((node) => (\n <TaskNode key={node.id} node={node} />\n ))}\n </ul>\n </section>\n );\n },\n);\nTaskPlan.displayName = \"TaskPlan\";\n\nexport { TaskNode, TaskPlan };\n"
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "task-types",
|
|
4
|
-
"type": "registry:lib",
|
|
5
|
-
"title": "Theo UI task types",
|
|
6
|
-
"description": "Shared TypeScript types for task plans, steps, and progress state.",
|
|
7
|
-
"files": [
|
|
8
|
-
{
|
|
9
|
-
"path": "types/task.ts",
|
|
10
|
-
"type": "registry:lib",
|
|
11
|
-
"target": "types/task.ts",
|
|
12
|
-
"content": "export type TaskStatus =\n | \"idle\"\n | \"permission_required\"\n | \"starting\"\n | \"running\"\n | \"verifying\"\n | \"completed\"\n | \"failed\";\n\nexport type TaskStepStatus = \"pending\" | \"running\" | \"done\" | \"skipped\";\n\nexport interface TaskStep {\n id: string;\n label: string;\n status: TaskStepStatus;\n /** 0..1 progress for in-flight steps. */\n progress?: number;\n}\n"
|
|
13
|
-
}
|
|
14
|
-
]
|
|
15
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "terminal-panel",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "TerminalPanel",
|
|
6
|
-
"description": "Minimal terminal output viewer.",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"lucide-react"
|
|
9
|
-
],
|
|
10
|
-
"registryDependencies": [
|
|
11
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
12
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
|
|
13
|
-
],
|
|
14
|
-
"files": [
|
|
15
|
-
{
|
|
16
|
-
"path": "components/primitives/terminal-panel/terminal-panel.tsx",
|
|
17
|
-
"type": "registry:ui",
|
|
18
|
-
"target": "components/ui/terminal-panel.tsx",
|
|
19
|
-
"content": "import { Terminal as TerminalIcon } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { useInLiveRegion } from \"@/lib/live-region-context\";\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 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"
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "text-prompt",
|
|
4
|
-
"type": "registry:block",
|
|
5
|
-
"title": "TextPrompt",
|
|
6
|
-
"description": "Free-text ask-the-user card with single-line or multi-line input and an optional required gate.",
|
|
7
|
-
"registryDependencies": [
|
|
8
|
-
"https://usetheodev.github.io/theo-ui/r/badge.json",
|
|
9
|
-
"https://usetheodev.github.io/theo-ui/r/button.json",
|
|
10
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
11
|
-
"https://usetheodev.github.io/theo-ui/r/input.json",
|
|
12
|
-
"https://usetheodev.github.io/theo-ui/r/label.json",
|
|
13
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json",
|
|
14
|
-
"https://usetheodev.github.io/theo-ui/r/textarea.json"
|
|
15
|
-
],
|
|
16
|
-
"files": [
|
|
17
|
-
{
|
|
18
|
-
"path": "components/composites/text-prompt/text-prompt.tsx",
|
|
19
|
-
"type": "registry:block",
|
|
20
|
-
"target": "components/blocks/text-prompt.tsx",
|
|
21
|
-
"content": "\"use client\";\n\nimport { forwardRef, useId, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\n\n/**\n * TextPrompt — free-text \"ask the user\" card for agent surfaces.\n *\n * The open-ended sibling of `ChoicePrompt`: a question with an optional header\n * chip and a single-line (`Input`) or multi-line (`Textarea`) field. Equivalent\n * to the \"Other\" affordance promoted to a question of its own.\n *\n * Renders one question at a time — sequencing is the consumer's responsibility.\n * Controlled (`value` + `onValueChange`) or uncontrolled (`defaultValue`).\n */\n\n/** Payload handed to `onConfirm`. */\nexport interface TextPromptResult {\n /** The typed text. */\n text: string;\n}\n\nexport interface TextPromptProps 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). */\n badge?: ReactNode;\n /** Controlled text value. */\n value?: string;\n /** Initial text when uncontrolled. */\n defaultValue?: string;\n /** Fired with the text on every keystroke. */\n onValueChange?: (text: string) => void;\n /** Field placeholder. */\n placeholder?: string;\n /** Render a multi-line Textarea instead of a single-line Input. */\n multiline?: boolean;\n /** Rows for the Textarea when `multiline`. Default 3. */\n rows?: number;\n /** Require non-empty text before Confirm enables. */\n required?: 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 typed text. */\n onConfirm?: (result: TextPromptResult) => void;\n /** Pressing Cancel. */\n onCancel?: () => void;\n}\n\nconst TextPrompt = forwardRef<HTMLElement, TextPromptProps>(\n (\n {\n className,\n question,\n description,\n badge,\n value,\n defaultValue,\n onValueChange,\n placeholder,\n multiline = false,\n rows = 3,\n required = false,\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 fieldId = `${baseId}-field`;\n\n const [internalValue, setInternalValue] = useState(defaultValue ?? \"\");\n const text = value !== undefined ? value : internalValue;\n\n const setText = (next: string): void => {\n if (value === undefined) setInternalValue(next);\n onValueChange?.(next);\n };\n\n const confirmDisabled = required && text.trim().length === 0;\n\n const confirm = (): void => {\n if (confirmDisabled) return;\n onConfirm?.({ text });\n };\n\n return (\n <section\n data-slot=\"text-prompt\"\n ref={ref}\n aria-labelledby={questionId}\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 <Label\n htmlFor={fieldId}\n id={questionId}\n required={required}\n className=\"font-display text-foreground text-title-md tracking-tight\"\n >\n {question}\n </Label>\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 {multiline ? (\n <Textarea\n id={fieldId}\n rows={rows}\n placeholder={placeholder}\n value={text}\n onChange={(event) => setText(event.target.value)}\n />\n ) : (\n <Input\n id={fieldId}\n placeholder={placeholder}\n value={text}\n onChange={(event) => setText(event.target.value)}\n />\n )}\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={confirmDisabled} onClick={confirm}>\n {confirmLabel}\n </Button>\n ) : null}\n </footer>\n ) : null}\n </section>\n );\n },\n);\nTextPrompt.displayName = \"TextPrompt\";\n\nexport { TextPrompt };\n"
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
package/registry/r/textarea.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "textarea",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "Textarea",
|
|
6
|
-
"description": "Multi-line input mirror of Input.",
|
|
7
|
-
"registryDependencies": [
|
|
8
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
9
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
|
|
10
|
-
],
|
|
11
|
-
"files": [
|
|
12
|
-
{
|
|
13
|
-
"path": "components/primitives/textarea/textarea.tsx",
|
|
14
|
-
"type": "registry:ui",
|
|
15
|
-
"target": "components/ui/textarea.tsx",
|
|
16
|
-
"content": "import { type VariantProps, cva } from \"class-variance-authority\";\nimport { forwardRef } from \"react\";\nimport type { TextareaHTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Textarea — multi-line input mirror of Input.\n *\n * Matches Input visuals (violet focus ring, --input border, --card bg).\n * The `size` prop accepts `\"sm\" | \"md\" | \"lg\"`. Default `md` preserves the\n * 80px (5rem) min-height + body-md text from before this prop existed.\n *\n * Note: `TextareaHTMLAttributes<HTMLTextAreaElement>` does NOT declare a\n * native `size` attribute (textareas use `rows` / `cols`), so no Omit is\n * needed — contrast with `<Input>` which had EC-1 collision.\n */\nconst textareaVariants = cva(\n [\n \"flex w-full resize-y rounded-md border border-input bg-card\",\n \"text-foreground placeholder:text-muted-foreground\",\n \"transition-[box-shadow,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 \"focus-visible:border-primary\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n ],\n {\n variants: {\n size: {\n sm: \"min-h-[64px] px-2.5 py-1.5 text-body-sm\",\n // md: text scale + padding tighten to body-sm per FAANG density.\n // min-h stays 96px because multiline has its own height rationale.\n md: \"min-h-[6rem] px-[var(--theo-control-px,0.875rem)] py-1.5 text-body-sm\",\n lg: \"min-h-[128px] px-4 py-2.5 text-body-md\",\n },\n },\n defaultVariants: { size: \"md\" },\n },\n);\n\nexport interface TextareaProps\n extends TextareaHTMLAttributes<HTMLTextAreaElement>,\n VariantProps<typeof textareaVariants> {}\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, rows = 3, size, ...props }, ref) => (\n <textarea\n data-slot=\"textarea\"\n data-size={size}\n ref={ref}\n rows={rows}\n className={cn(textareaVariants({ size }), className)}\n {...props}\n />\n ),\n);\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea, textareaVariants };\n"
|
|
17
|
-
}
|
|
18
|
-
],
|
|
19
|
-
"dependencies": [
|
|
20
|
-
"class-variance-authority"
|
|
21
|
-
]
|
|
22
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "theme-provider",
|
|
4
|
-
"type": "registry:lib",
|
|
5
|
-
"title": "ThemeProvider",
|
|
6
|
-
"description": "Theme + dark mode provider with built-in Violet Forge, Classic Paper, and Aurora Terminal themes.",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"@radix-ui/react-dropdown-menu",
|
|
9
|
-
"lucide-react"
|
|
10
|
-
],
|
|
11
|
-
"registryDependencies": [
|
|
12
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
13
|
-
"https://usetheodev.github.io/theo-ui/r/env.json",
|
|
14
|
-
"https://usetheodev.github.io/theo-ui/r/tokens.json"
|
|
15
|
-
],
|
|
16
|
-
"files": [
|
|
17
|
-
{
|
|
18
|
-
"path": "themes/types.ts",
|
|
19
|
-
"type": "registry:lib",
|
|
20
|
-
"target": "themes/types.ts",
|
|
21
|
-
"content": "/**\n * Theo UI — Theme types.\n *\n * A Theme is a frozen bundle of CSS-var values that the runtime can swap by\n * setting `data-theme=\"<name>\"` on `<html>`. The structure mirrors what lives\n * in tokens.css so themes can be merged without ambiguity.\n */\n\nexport type ThemeMode = \"light\" | \"dark\";\n\nexport interface ColorScale {\n background: string;\n foreground: string;\n card: string;\n \"card-foreground\": string;\n popover: string;\n \"popover-foreground\": string;\n primary: string;\n /**\n * Tonal scale variants of `primary`. Optional since T3.2 (ADR-0006).\n * When omitted, derived in CSS from `--primary` via `oklch(from ...)`.\n * Override per-theme by providing an explicit string.\n */\n \"primary-deep\"?: string;\n \"primary-glow\"?: string;\n \"primary-foreground\": string;\n secondary: string;\n \"secondary-foreground\": string;\n accent: string;\n /**\n * Tonal scale variant of `accent`. Optional since T3.2 — derived in CSS\n * when omitted. Override per-theme by providing an explicit string.\n */\n \"accent-deep\"?: string;\n \"accent-foreground\": string;\n muted: string;\n \"muted-foreground\": string;\n border: string;\n input: string;\n ring: string;\n success: string;\n \"success-foreground\": string;\n warning: string;\n \"warning-foreground\": string;\n destructive: string;\n \"destructive-foreground\": string;\n info: string;\n \"info-foreground\": string;\n /**\n * Status semantic group (D4 ADR — community-best-practices plan).\n *\n * Operational state colors (gateway connected/disconnected/slow/info-flag)\n * separated from action-result semantics (success/destructive/warning/info).\n * Defaults in built-in themes mirror their semantic counterparts; consumers\n * may override for visually-distinct status surfaces. `defineTheme(partial)`\n * auto-populates from semantic group when omitted.\n */\n \"status-online\": string;\n \"status-online-foreground\": string;\n \"status-offline\": string;\n \"status-offline-foreground\": string;\n \"status-degraded\": string;\n \"status-degraded-foreground\": string;\n \"status-info\": string;\n \"status-info-foreground\": string;\n}\n\nexport interface ThemeFonts {\n /** Display headlines (h1-h3, hero text). */\n display: string;\n /** Body / UI text. */\n body: string;\n /** Code, mono, paths, timestamps. */\n mono: string;\n}\n\nexport interface Theme {\n /** Stable id, used in `data-theme`. */\n name: string;\n /** Human-readable label for theme switchers. */\n label: string;\n /** Optional short description shown in switchers. */\n description?: string;\n fonts: ThemeFonts;\n light: ColorScale;\n dark: ColorScale;\n /**\n * Optional URL(s) to fetch before applying. The provider injects a `<link>`\n * tag once per URL to load remote fonts. Already-injected URLs are deduped.\n */\n fontUrls?: string[];\n}\n"
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"path": "themes/violet-forge.ts",
|
|
25
|
-
"type": "registry:lib",
|
|
26
|
-
"target": "themes/violet-forge.ts",
|
|
27
|
-
"content": "import type { Theme } from \"@/themes/types\";\n\n/**\n * Violet Forge — the default Theo theme.\n *\n * Identity: Theo violet electric primary (#A855F7, unified 2026-06-09),\n * burnt sienna accent (#C96442), Vercel-style neutral surfaces\n * (pure white light / charcoal dark), Geist Sans + Geist Mono throughout.\n *\n * Source of truth for `data-theme` overrides. Values mirror\n * src/styles/tokens.css for the default `:root`.\n */\nexport const violetForge: Theme = {\n name: \"violet-forge\",\n label: \"Violet Forge\",\n description: \"Theo default — violet primary, burnt sienna accent, Geist Sans + Geist Mono.\",\n fonts: {\n display: '\"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n body: '\"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n mono: '\"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n },\n fontUrls: [\n \"https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=Geist+Mono:wght@100..900&display=swap\",\n ],\n light: {\n background: \"oklch(1 0 0)\",\n foreground: \"oklch(0.146 0 0)\",\n card: \"oklch(1 0 0)\",\n \"card-foreground\": \"oklch(0.146 0 0)\",\n popover: \"oklch(1 0 0)\",\n \"popover-foreground\": \"oklch(0.146 0 0)\",\n primary: \"oklch(0.628 0.225 296)\",\n \"primary-foreground\": \"oklch(1 0 0)\",\n secondary: \"oklch(0.97 0 0)\",\n \"secondary-foreground\": \"oklch(0.146 0 0)\",\n accent: \"oklch(0.621 0.132 39)\",\n \"accent-foreground\": \"oklch(1 0 0)\",\n muted: \"oklch(0.97 0 0)\",\n \"muted-foreground\": \"oklch(0.555 0 0)\",\n border: \"oklch(0.931 0 0)\",\n input: \"oklch(0.931 0 0)\",\n ring: \"oklch(0.628 0.225 296)\",\n success: \"oklch(0.611 0.161 149.7)\",\n \"success-foreground\": \"oklch(1 0 0)\",\n warning: \"oklch(0.67 0.154 60.6)\",\n \"warning-foreground\": \"oklch(1 0 0)\",\n destructive: \"oklch(0.579 0.214 27.2)\",\n \"destructive-foreground\": \"oklch(1 0 0)\",\n info: \"oklch(0.626 0.186 259.6)\",\n \"info-foreground\": \"oklch(1 0 0)\",\n \"status-online\": \"oklch(0.611 0.161 149.7)\",\n \"status-online-foreground\": \"oklch(1 0 0)\",\n \"status-offline\": \"oklch(0.579 0.214 27.2)\",\n \"status-offline-foreground\": \"oklch(1 0 0)\",\n \"status-degraded\": \"oklch(0.67 0.154 60.6)\",\n \"status-degraded-foreground\": \"oklch(1 0 0)\",\n \"status-info\": \"oklch(0.626 0.186 259.6)\",\n \"status-info-foreground\": \"oklch(1 0 0)\",\n },\n dark: {\n background: \"oklch(0.146 0 0)\",\n foreground: \"oklch(0.97 0 0)\",\n card: \"oklch(0.182 0 0)\",\n \"card-foreground\": \"oklch(0.97 0 0)\",\n popover: \"oklch(0.204 0 0)\",\n \"popover-foreground\": \"oklch(0.97 0 0)\",\n primary: \"oklch(0.628 0.225 296)\",\n \"primary-foreground\": \"oklch(1 0 0)\",\n secondary: \"oklch(0.227 0 0)\",\n \"secondary-foreground\": \"oklch(0.97 0 0)\",\n accent: \"oklch(0.621 0.132 39)\",\n \"accent-foreground\": \"oklch(1 0 0)\",\n muted: \"oklch(0.227 0 0)\",\n \"muted-foreground\": \"oklch(0.683 0 0)\",\n border: \"oklch(0.28 0 0)\",\n input: \"oklch(0.227 0 0)\",\n ring: \"oklch(0.628 0.225 296)\",\n success: \"oklch(0.814 0.192 155.7)\",\n \"success-foreground\": \"oklch(0.146 0 0)\",\n warning: \"oklch(0.77 0.165 70.6)\",\n \"warning-foreground\": \"oklch(0.146 0 0)\",\n destructive: \"oklch(0.677 0.213 15.6)\",\n \"destructive-foreground\": \"oklch(0.146 0 0)\",\n info: \"oklch(0.732 0.142 254.4)\",\n \"info-foreground\": \"oklch(0.146 0 0)\",\n \"status-online\": \"oklch(0.814 0.192 155.7)\",\n \"status-online-foreground\": \"oklch(0.146 0 0)\",\n \"status-offline\": \"oklch(0.677 0.213 15.6)\",\n \"status-offline-foreground\": \"oklch(0.146 0 0)\",\n \"status-degraded\": \"oklch(0.77 0.165 70.6)\",\n \"status-degraded-foreground\": \"oklch(0.146 0 0)\",\n \"status-info\": \"oklch(0.732 0.142 254.4)\",\n \"status-info-foreground\": \"oklch(0.146 0 0)\",\n },\n};\n"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"path": "themes/classic-paper.ts",
|
|
31
|
-
"type": "registry:lib",
|
|
32
|
-
"target": "themes/classic-paper.ts",
|
|
33
|
-
"content": "import type { Theme } from \"@/themes/types\";\n\n/**\n * Classic Paper — visibly warm cream surface; Inter + JetBrains Mono.\n *\n * Identity: cream paper background with sepia warmth (calibrated against the\n * Vintage Paper / Anthropic Claude UI references), deep navy foreground,\n * indigo primary. Optimized for long agent/chat sessions where pure-white\n * surfaces cause vision fatigue (per IxDF 2026 + ACM 2025 light-mode studies).\n *\n * Token calibration (light mode):\n * - background L=0.95 chroma=0.025 hue=80 — visibly cream paper\n * - card L=0.97 chroma=0.012 hue=80 — sub-paper layer (cards stand out)\n * - foreground unchanged (deep navy, AAA contrast >12:1 vs background)\n *\n * Dark mirror unchanged.\n */\nexport const classicPaper: Theme = {\n name: \"classic-paper\",\n label: \"Classic Paper\",\n description: \"Inter + paper background. Maximum legibility, conservative.\",\n fonts: {\n display: '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n body: '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n mono: '\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n },\n fontUrls: [\n \"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap\",\n ],\n light: {\n background: \"oklch(0.95 0.025 80)\",\n foreground: \"oklch(0.206 0.039 265.5)\",\n card: \"oklch(0.97 0.012 80)\",\n \"card-foreground\": \"oklch(0.206 0.039 265.5)\",\n popover: \"oklch(0.98 0.008 80)\",\n \"popover-foreground\": \"oklch(0.206 0.039 265.5)\",\n primary: \"oklch(0.545 0.215 262.7)\",\n \"primary-foreground\": \"oklch(1 0 0)\",\n secondary: \"oklch(0.93 0.02 80)\",\n \"secondary-foreground\": \"oklch(0.206 0.039 265.5)\",\n accent: \"oklch(0.647 0.139 69)\",\n \"accent-foreground\": \"oklch(1 0 0)\",\n muted: \"oklch(0.93 0.02 80)\",\n \"muted-foreground\": \"oklch(0.45 0.03 80)\",\n border: \"oklch(0.88 0.025 80)\",\n input: \"oklch(0.92 0.02 80)\",\n ring: \"oklch(0.545 0.215 262.7)\",\n success: \"oklch(0.611 0.161 149.7)\",\n \"success-foreground\": \"oklch(1 0 0)\",\n warning: \"oklch(0.67 0.154 60.6)\",\n \"warning-foreground\": \"oklch(1 0 0)\",\n destructive: \"oklch(0.579 0.214 27.2)\",\n \"destructive-foreground\": \"oklch(1 0 0)\",\n info: \"oklch(0.626 0.186 259.6)\",\n \"info-foreground\": \"oklch(1 0 0)\",\n \"status-online\": \"oklch(0.611 0.161 149.7)\",\n \"status-online-foreground\": \"oklch(1 0 0)\",\n \"status-offline\": \"oklch(0.579 0.214 27.2)\",\n \"status-offline-foreground\": \"oklch(1 0 0)\",\n \"status-degraded\": \"oklch(0.67 0.154 60.6)\",\n \"status-degraded-foreground\": \"oklch(1 0 0)\",\n \"status-info\": \"oklch(0.626 0.186 259.6)\",\n \"status-info-foreground\": \"oklch(1 0 0)\",\n },\n // Dark mirror — mainly the same hues with inverted lightness so the theme\n // still feels coherent if a consumer toggles `.dark`.\n dark: {\n background: \"oklch(0.177 0.029 265.8)\",\n foreground: \"oklch(0.984 0.003 247.9)\",\n card: \"oklch(0.206 0.039 265.5)\",\n \"card-foreground\": \"oklch(0.984 0.003 247.9)\",\n popover: \"oklch(0.206 0.039 265.5)\",\n \"popover-foreground\": \"oklch(0.984 0.003 247.9)\",\n primary: \"oklch(0.626 0.186 259.6)\",\n \"primary-foreground\": \"oklch(0.206 0.039 265.5)\",\n secondary: \"oklch(0.291 0.022 259.9)\",\n \"secondary-foreground\": \"oklch(0.984 0.003 247.9)\",\n accent: \"oklch(0.803 0.15 74.7)\",\n \"accent-foreground\": \"oklch(0.206 0.039 265.5)\",\n muted: \"oklch(0.291 0.022 259.9)\",\n \"muted-foreground\": \"oklch(0.71 0.035 256.8)\",\n border: \"oklch(0.329 0.026 259.9)\",\n input: \"oklch(0.291 0.022 259.9)\",\n ring: \"oklch(0.626 0.186 259.6)\",\n success: \"oklch(0.814 0.192 155.7)\",\n \"success-foreground\": \"oklch(0.206 0.039 265.5)\",\n warning: \"oklch(0.77 0.165 70.6)\",\n \"warning-foreground\": \"oklch(0.206 0.039 265.5)\",\n destructive: \"oklch(0.677 0.213 15.6)\",\n \"destructive-foreground\": \"oklch(0.206 0.039 265.5)\",\n info: \"oklch(0.732 0.142 254.4)\",\n \"info-foreground\": \"oklch(0.206 0.039 265.5)\",\n \"status-online\": \"oklch(0.814 0.192 155.7)\",\n \"status-online-foreground\": \"oklch(0.206 0.039 265.5)\",\n \"status-offline\": \"oklch(0.677 0.213 15.6)\",\n \"status-offline-foreground\": \"oklch(0.206 0.039 265.5)\",\n \"status-degraded\": \"oklch(0.77 0.165 70.6)\",\n \"status-degraded-foreground\": \"oklch(0.206 0.039 265.5)\",\n \"status-info\": \"oklch(0.732 0.142 254.4)\",\n \"status-info-foreground\": \"oklch(0.206 0.039 265.5)\",\n },\n};\n"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"path": "themes/aurora-terminal.ts",
|
|
37
|
-
"type": "registry:lib",
|
|
38
|
-
"target": "themes/aurora-terminal.ts",
|
|
39
|
-
"content": "import type { Theme } from \"@/themes/types\";\n\n/**\n * Aurora Terminal — dark-first, cyan-aurora primary, Geist Mono everywhere.\n *\n * Identity: deep oceanic background, cyan-aurora primary, aurora-pink accent.\n * Headers use Geist with heavier tracking; body uses Geist Mono for full\n * \"developer console\" feel. Suits CLI/devtools showcase.\n */\nexport const auroraTerminal: Theme = {\n name: \"aurora-terminal\",\n label: \"Aurora Terminal\",\n description: \"Dark sci-fi developer console — cyan-aurora + Geist Mono body.\",\n fonts: {\n display: '\"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n body: '\"Geist\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n mono: '\"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, monospace',\n },\n fontUrls: [\n \"https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=Geist+Mono:wght@100..900&display=swap\",\n ],\n light: {\n background: \"oklch(0.966 0.006 264.5)\",\n foreground: \"oklch(0.206 0.039 265.5)\",\n card: \"oklch(1 0 0)\",\n \"card-foreground\": \"oklch(0.206 0.039 265.5)\",\n popover: \"oklch(1 0 0)\",\n \"popover-foreground\": \"oklch(0.206 0.039 265.5)\",\n primary: \"oklch(0.714 0.12 191)\",\n \"primary-foreground\": \"oklch(0.206 0.039 265.5)\",\n secondary: \"oklch(0.968 0.007 247.9)\",\n \"secondary-foreground\": \"oklch(0.206 0.039 265.5)\",\n accent: \"oklch(0.646 0.206 4.9)\",\n \"accent-foreground\": \"oklch(1 0 0)\",\n muted: \"oklch(0.926 0.013 255)\",\n \"muted-foreground\": \"oklch(0.556 0.04 256.8)\",\n border: \"oklch(0.926 0.013 255)\",\n input: \"oklch(0.926 0.013 255)\",\n ring: \"oklch(0.714 0.12 191)\",\n success: \"oklch(0.711 0.171 155.2)\",\n \"success-foreground\": \"oklch(1 0 0)\",\n warning: \"oklch(0.67 0.154 60.6)\",\n \"warning-foreground\": \"oklch(1 0 0)\",\n destructive: \"oklch(0.579 0.214 27.2)\",\n \"destructive-foreground\": \"oklch(1 0 0)\",\n info: \"oklch(0.626 0.186 259.6)\",\n \"info-foreground\": \"oklch(1 0 0)\",\n \"status-online\": \"oklch(0.711 0.171 155.2)\",\n \"status-online-foreground\": \"oklch(1 0 0)\",\n \"status-offline\": \"oklch(0.579 0.214 27.2)\",\n \"status-offline-foreground\": \"oklch(1 0 0)\",\n \"status-degraded\": \"oklch(0.67 0.154 60.6)\",\n \"status-degraded-foreground\": \"oklch(1 0 0)\",\n \"status-info\": \"oklch(0.626 0.186 259.6)\",\n \"status-info-foreground\": \"oklch(1 0 0)\",\n },\n dark: {\n background: \"oklch(0.169 0.021 268.7)\",\n foreground: \"oklch(0.966 0.006 264.5)\",\n card: \"oklch(0.199 0.027 268.5)\",\n \"card-foreground\": \"oklch(0.966 0.006 264.5)\",\n popover: \"oklch(0.199 0.027 268.5)\",\n \"popover-foreground\": \"oklch(0.966 0.006 264.5)\",\n primary: \"oklch(0.834 0.122 191.9)\",\n \"primary-foreground\": \"oklch(0.169 0.021 268.7)\",\n secondary: \"oklch(0.242 0.03 266.3)\",\n \"secondary-foreground\": \"oklch(0.966 0.006 264.5)\",\n accent: \"oklch(0.68 0.2 3.6)\",\n \"accent-foreground\": \"oklch(0.169 0.021 268.7)\",\n muted: \"oklch(0.242 0.03 266.3)\",\n \"muted-foreground\": \"oklch(0.71 0.035 256.8)\",\n border: \"oklch(0.281 0.035 266.3)\",\n input: \"oklch(0.242 0.03 266.3)\",\n ring: \"oklch(0.834 0.122 191.9)\",\n success: \"oklch(0.814 0.192 155.7)\",\n \"success-foreground\": \"oklch(0.169 0.021 268.7)\",\n warning: \"oklch(0.77 0.165 70.6)\",\n \"warning-foreground\": \"oklch(0.169 0.021 268.7)\",\n destructive: \"oklch(0.677 0.213 15.6)\",\n \"destructive-foreground\": \"oklch(0.169 0.021 268.7)\",\n info: \"oklch(0.732 0.142 254.4)\",\n \"info-foreground\": \"oklch(0.169 0.021 268.7)\",\n \"status-online\": \"oklch(0.814 0.192 155.7)\",\n \"status-online-foreground\": \"oklch(0.169 0.021 268.7)\",\n \"status-offline\": \"oklch(0.677 0.213 15.6)\",\n \"status-offline-foreground\": \"oklch(0.169 0.021 268.7)\",\n \"status-degraded\": \"oklch(0.77 0.165 70.6)\",\n \"status-degraded-foreground\": \"oklch(0.169 0.021 268.7)\",\n \"status-info\": \"oklch(0.732 0.142 254.4)\",\n \"status-info-foreground\": \"oklch(0.169 0.021 268.7)\",\n },\n};\n"
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"path": "themes/theme-provider.tsx",
|
|
43
|
-
"type": "registry:lib",
|
|
44
|
-
"target": "themes/theme-provider.tsx",
|
|
45
|
-
"content": "import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { JSX, ReactNode } from \"react\";\nimport { isDev } from \"@/lib/env\";\nimport { safeHref } from \"@/lib/safe-href\";\nimport { COLOR_VALUE_PATTERN } from \"./color-value-pattern\";\nimport { type Density, DensityContext, injectDensityCss } from \"./density\";\nimport { formatThemeIssues, validateTheme } from \"./schema\";\nimport type { ColorScale, Theme, ThemeMode } from \"@/themes/types\";\n\ninterface ThemeContextValue {\n /** Active theme (full descriptor). */\n theme: Theme;\n /** Active mode: light or dark. */\n mode: ThemeMode;\n /** All available themes. */\n themes: Theme[];\n /** Swap the active theme by name. */\n setTheme: (name: string) => void;\n /** Set light/dark explicitly. */\n setMode: (mode: ThemeMode) => void;\n /** Toggle light <> dark. */\n toggleMode: () => void;\n /** Register an additional theme at runtime. */\n registerTheme: (theme: Theme) => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined);\n\nconst STYLE_ELEMENT_ID = \"theo-ui-theme-vars\";\n\n// T3.2 (SEC-001): allowlist validators for theme values. injectThemeCss\n// interpolates theme name + color values + font families into a <style>\n// textContent. Without validation, a theme object from an untrusted source\n// (e.g., a feature-flag service, a CMS) could inject arbitrary CSS via\n// closing the declaration with `}` or smuggling `url(...)` for exfiltration.\n// We reject rather than escape: themes are code, not user input. Invalid\n// values cause a dev-time throw (caller sees the problem); production\n// silently substitutes a safe fallback so a misconfigured theme can't\n// crash the app.\n\n// COLOR_VALUE_PATTERN was inlined here pre-T2.5. Now extracted to\n// `color-value-pattern.ts` so the regex is reusable by the Valibot schema (T2.7)\n// and so the OKLCH relative-color syntax (`oklch(from var(--x) calc(l - 0.16) c h)`,\n// required by T3.1 tonal derivations) is supported without expanding the inline\n// regex monolith. See EC-5 in the edge-case review.\n\n// Font family: word chars, spaces, commas, hyphens, dots, quotes. Excludes\n// parens (blocks `url(...)`) and semicolons (blocks declaration breakouts).\nconst FONT_FAMILY_PATTERN = /^[\\w\\s,\"'\\-.]+$/;\n\n// Theme name: kebab-case identifier. Excludes anything that could break out\n// of an attribute selector or inject additional rules.\nconst THEME_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;\n\nconst IS_DEV = isDev();\n\nfunction rejectOrFallback(scope: string, value: string, fallback: string): string {\n if (IS_DEV) {\n throw new Error(\n `[@theokit/ui] invalid ${scope} value: ${JSON.stringify(value)}. Theme values must match the allowlist (see src/themes/theme-provider.tsx). Refusing to inject potentially unsafe CSS.`,\n );\n }\n return fallback;\n}\n\nfunction validatedColor(token: string, value: string): string {\n if (COLOR_VALUE_PATTERN.test(value)) return value;\n return rejectOrFallback(`color \"${token}\"`, value, \"transparent\");\n}\n\nfunction validatedFontFamily(slot: string, value: string): string {\n if (FONT_FAMILY_PATTERN.test(value)) return value;\n return rejectOrFallback(`fontFamily \"${slot}\"`, value, \"inherit\");\n}\n\nfunction validatedThemeName(value: string): string {\n if (THEME_NAME_PATTERN.test(value)) return value;\n return rejectOrFallback(\"theme.name\", value, \"invalid-theme\");\n}\n\nfunction colorScaleToCss(name: string, mode: ThemeMode, colors: ColorScale): string {\n const safeName = validatedThemeName(name);\n const selector =\n mode === \"light\"\n ? `[data-theme=\"${safeName}\"]`\n : `[data-theme=\"${safeName}\"].dark, [data-theme=\"${safeName}\"][data-mode=\"dark\"]`;\n const decls = Object.entries(colors)\n .map(([token, value]) => ` --${token}: ${validatedColor(token, value)};`)\n .join(\"\\n\");\n return `${selector} {\\n${decls}\\n}`;\n}\n\nfunction fontsToCss(name: string, fonts: Theme[\"fonts\"]): string {\n const safeName = validatedThemeName(name);\n const display = validatedFontFamily(\"display\", fonts.display);\n const body = validatedFontFamily(\"body\", fonts.body);\n const mono = validatedFontFamily(\"mono\", fonts.mono);\n return `[data-theme=\"${safeName}\"] {\\n --font-display: ${display};\\n --font-body: ${body};\\n --font-mono: ${mono};\\n}`;\n}\n\nfunction injectThemeCss(themes: Theme[]): void {\n if (typeof document === \"undefined\") return;\n let style = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (!style) {\n style = document.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n document.head.appendChild(style);\n }\n const blocks: string[] = [];\n for (const theme of themes) {\n blocks.push(fontsToCss(theme.name, theme.fonts));\n blocks.push(colorScaleToCss(theme.name, \"light\", theme.light));\n blocks.push(colorScaleToCss(theme.name, \"dark\", theme.dark));\n }\n style.textContent = blocks.join(\"\\n\\n\");\n}\n\n/**\n * loadThemeFonts — idempotently inject `<link rel=\"stylesheet\">` for each\n * font URL declared by the theme.\n *\n * T4.2: the previous implementation kept a module-level `Set` to track\n * already-injected URLs. That singleton broke test isolation (state\n * leaked across renders) and silently skipped injection in micro-frontend\n * setups with multiple `<ThemeProvider>` mounts. Replaced with a DOM\n * check: we query `document.head` for an existing link with the same\n * `href` before appending a new one. The DOM is the single source of\n * truth; no shared state across instances.\n */\nfunction loadThemeFonts(theme: Theme): void {\n if (typeof document === \"undefined\") return;\n if (!theme.fontUrls) return;\n for (const url of theme.fontUrls) {\n // Re-audit NEW-001 (SSRF, LOW): defang dangerous protocols on\n // consumer-provided font URLs. Built-in themes use\n // fonts.googleapis.com/gstatic.com — safe. registerTheme accepts\n // arbitrary objects at runtime; a malicious theme could try to inject\n // javascript:/data:text/html via fontUrls. safeHref returns undefined\n // for dangerous protocols, which we skip silently.\n const safe = safeHref(url);\n if (!safe) continue;\n if (document.head.querySelector(`link[rel=\"stylesheet\"][href=\"${CSS.escape(safe)}\"]`)) {\n continue;\n }\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = safe;\n document.head.appendChild(link);\n }\n}\n\ninterface ThemeProviderProps {\n children: ReactNode;\n /**\n * Theme to start with. Must match the `name` of an entry in `themes`.\n * Defaults to `\"violet-forge\"` for backward compat — if you don't pass\n * `violet-forge` in `themes`, set this prop explicitly.\n */\n defaultTheme?: string;\n /** Mode to start with. Defaults to `\"dark\"` (library is dark-first). */\n defaultMode?: ThemeMode;\n /**\n * Available themes. **Required**: ThemeProvider does not auto-include any\n * built-in theme since v0.1.0-next.0 — pass `builtinThemes` for all three\n * Violet Forge defaults, or your own array for a slimmer bundle.\n *\n * Migration: consumers previously calling `<ThemeProvider>` without this\n * prop now must pass `themes={builtinThemes}` (or use `<TheoUIProvider>`\n * which defaults to `builtinThemes` for you).\n */\n themes: Theme[];\n /**\n * Persist selection in localStorage under this key. Pass `null` to disable.\n * Default: \"theo-ui:theme\".\n */\n storageKey?: string | null;\n /**\n * Initial density. Drives `data-density` on `<html>` and the `--theo-control-h`\n * / `--theo-control-px` CSS vars consumed by form-control `md` variants.\n * Defaults to `\"comfortable\"` (36px controls — FAANG-tier modern density).\n * Plan: faang-density-tightening (D3).\n */\n defaultDensity?: Density;\n /**\n * Respect the consumer's OS `prefers-color-scheme` preference on initial\n * mount (D6 / T5.1). When `true` (default) and no theme-mode is stored in\n * `localStorage[storageKey]`, the provider reads\n * `matchMedia('(prefers-color-scheme: dark)')` and subscribes to changes.\n * User-driven `setMode()` overrides the system signal — subsequent OS\n * changes are ignored after the user fixes a preference.\n *\n * Pass `false` to force `defaultMode` regardless of the system preference.\n * EC-12: matchMedia listener is cleaned up on unmount.\n */\n respectSystemMode?: boolean;\n}\n\n/**\n * Storage failure diagnostic — dev-only one-line warn so engineers see\n * something when localStorage throws (Safari private mode, blocked\n * third-party cookies, sandboxed iframes). In production we stay silent;\n * runtime behavior is fail-safe (state still lives in memory).\n *\n * Per HIGH-006: silent catches diverge from the \"fail loud\" principle\n * declared in the global CLAUDE.md. We accept silence in prod because the\n * fallback is correct, but we surface a single warn per call site in dev.\n */\nfunction warnStorageFailure(scope: string, err: unknown): void {\n if (!isDev()) return;\n // biome-ignore lint/suspicious/noConsole: dev-only diagnostic for storage failures (HIGH-006)\n console.warn(`[@theokit/ui] theme storage failure (${scope}):`, err);\n}\n\n// T2.7: production-mode diagnostic for invalid themes that fall through\n// dev-time throw. Single console.warn so engineer sees something instead of\n// total silence; theme is kept in the array but per-value regex fallback\n// substitutes `transparent` for unsafe values downstream.\nfunction warnInvalidTheme(message: string): void {\n // biome-ignore lint/suspicious/noConsole: dev/prod diagnostic for invalid theme (T2.7/D5)\n console.warn(message);\n}\n\n/**\n * ThemeProvider — central registry + runtime switcher for Theo themes.\n *\n * Behavior:\n * 1. On mount, injects a `<style id=\"theo-ui-theme-vars\">` element with\n * one CSS block per theme (`[data-theme=\"<name>\"] { --token: ... }`).\n * 2. Sets `data-theme` and `data-mode` on `<html>` so any element nested\n * below inherits the right tokens (the Tailwind config consumes them).\n * 3. Lazy-loads theme font URLs by injecting `<link rel=\"stylesheet\">`.\n * 4. Optionally persists choice in localStorage.\n */\nfunction ThemeProvider({\n children,\n defaultTheme = \"violet-forge\",\n defaultMode = \"dark\",\n themes: themesProp,\n storageKey = \"theo-ui:theme\",\n defaultDensity = \"comfortable\",\n respectSystemMode = true,\n}: ThemeProviderProps): JSX.Element {\n // Themes prop is required since v0.1.0-next.0 — see migration note in\n // the JSDoc on ThemeProviderProps. Pass `builtinThemes` for the legacy\n // default behavior (violet-forge + classic-paper + aurora-terminal), or\n // an array of your own. Empty array is rejected: ThemeProvider has no\n // valid state without at least one registered theme.\n if (!themesProp || themesProp.length === 0) {\n throw new Error(\n \"<ThemeProvider> requires the `themes` prop with at least one Theme. \" +\n \"Pass `themes={builtinThemes}` for the Violet Forge defaults (importable \" +\n \"via the package barrel), or use <TheoUIProvider> which sets this for you.\",\n );\n }\n\n // T3.2 (SEC-001): eager validation. Calling validatedColor/FontFamily/\n // ThemeName here ensures CSS-injection attempts throw at construction\n // time rather than inside the deferred useEffect that injects the\n // <style>. Production-mode fallbacks keep the app rendering even if a\n // theme has bad values.\n //\n // Re-audit NEW-3: wrapped in useMemo so the validation cost (O(themes *\n // tokens), ~60 ops per built-in theme) only runs when themesProp's\n // reference changes — not on every parent re-render. Consumers passing\n // inline array literals (`themes={[violetForge, classicPaper]}`) would\n // otherwise pay this on every parent update.\n const mergedThemes = useMemo<Theme[]>(() => {\n // T2.7 (D5): valibot shape validation runs FIRST — catches missing keys,\n // wrong types, malformed font URLs. Existing per-value regex validation\n // below stays as the second defense layer against CSS injection.\n for (const t of themesProp) {\n const result = validateTheme(t);\n if (!result.success) {\n const message = formatThemeIssues(\n (t as { name?: string }).name ?? \"(unnamed)\",\n result.issues ?? [],\n );\n if (IS_DEV) throw new Error(message);\n warnInvalidTheme(message);\n // In production we keep the theme array intact; the per-value regex\n // fallbacks below will substitute `transparent` for any value that\n // still fails the second layer, so the app continues rendering.\n }\n }\n for (const t of themesProp) {\n validatedThemeName(t.name);\n validatedFontFamily(\"display\", t.fonts.display);\n validatedFontFamily(\"body\", t.fonts.body);\n validatedFontFamily(\"mono\", t.fonts.mono);\n for (const [token, value] of Object.entries(t.light)) {\n validatedColor(token, value);\n }\n for (const [token, value] of Object.entries(t.dark)) {\n validatedColor(token, value);\n }\n }\n // Dedup by theme name; last writer wins (allows registerTheme override).\n const map = new Map<string, Theme>();\n for (const t of themesProp) map.set(t.name, t);\n return Array.from(map.values());\n }, [themesProp]);\n\n const [themes, setThemes] = useState<Theme[]>(mergedThemes);\n\n // Re-sync state when the `themes` prop changes between renders. Avoids the\n // common pitfall where the user passes a different array later and the\n // initial-state-only seed silently ignores the change.\n useEffect(() => {\n setThemes(mergedThemes);\n }, [mergedThemes]);\n\n // SSR-safe initialization (0.6.3-next.0 hydration-mismatch fix).\n //\n // Previously: `useState(() => localStorage.getItem(…))`. The initializer\n // ran on BOTH server (no `window`, returned default) AND client at\n // hydration time (with `window`, returned the stored value). The two\n // results disagreed → React threw a hydration error on every page load\n // for any user who had previously changed themes, and re-rendered the\n // entire tree from scratch — defeating SSR.\n //\n // Fix: initialize with the SSR default ALWAYS. Promote to the stored\n // value in a post-mount `useEffect` below. The 1-frame visual flicker\n // is mitigated by the optional `<ThemeScript>` component, which sets\n // `data-theme` / `data-mode` / `data-density` on `<html>` before React\n // hydrates — see `theme-script.tsx`.\n //\n // The `hydratedRef` flag below guards the persist effect so that\n // first-mount writes (with the SSR default values) don't clobber the\n // user's stored preference in the brief window between mount and the\n // post-mount hydration effect.\n const [themeName, setThemeName] = useState<string>(defaultTheme);\n const [mode, setModeState] = useState<ThemeMode>(defaultMode);\n const [density, setDensityState] = useState<Density>(defaultDensity);\n\n // T5.1 / D6: track whether the user has explicitly fixed the mode via\n // setMode / toggleMode. Once true, OS prefers-color-scheme changes do\n // NOT override the user's choice.\n const userOverrodeModeRef = useRef(false);\n\n // First-run guard for the persist effect below. On initial mount the\n // state is the SSR-safe default; we MUST NOT clobber the user's stored\n // preference with that default before the post-mount hydration effect\n // can promote it. After the first persist-effect call returns early,\n // every subsequent change (post-hydration setState OR user-driven)\n // persists normally.\n const skipFirstPersistRef = useRef(true);\n\n // Post-mount hydration: read localStorage and promote stored values to\n // state. Runs ONCE on mount. If `storageKey` is null or no value is\n // stored, this is a no-op — state stays at the SSR defaults.\n useEffect(() => {\n if (typeof window === \"undefined\" || !storageKey) return;\n try {\n const storedName = window.localStorage.getItem(`${storageKey}:name`);\n const storedMode = window.localStorage.getItem(`${storageKey}:mode`);\n const storedDensity = window.localStorage.getItem(`${storageKey}:density`);\n if (storedName) setThemeName(storedName);\n if (storedMode === \"dark\" || storedMode === \"light\") {\n setModeState(storedMode);\n // Stored value implies user fixed a preference at some point.\n userOverrodeModeRef.current = true;\n }\n if (\n storedDensity === \"compact\" ||\n storedDensity === \"comfortable\" ||\n storedDensity === \"spacious\"\n ) {\n setDensityState(storedDensity);\n }\n } catch (err) {\n warnStorageFailure(\"read theme + mode + density\", err);\n }\n }, [storageKey]);\n\n // T5.1 / D6 / EC-12: subscribe to OS prefers-color-scheme when\n // respectSystemMode is true. On mount, if user has NOT overridden the\n // mode (no stored preference), align with the OS signal. Re-aligns on\n // OS changes UNLESS user explicitly fixed a preference. Cleanup on\n // unmount via removeEventListener (EC-12) to avoid listener leaks in\n // micro-frontend scenarios.\n useEffect(() => {\n if (!respectSystemMode) return;\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n const mql = window.matchMedia(\"(prefers-color-scheme: dark)\");\n // Align on first run if user hasn't overridden.\n if (!userOverrodeModeRef.current) {\n setModeState(mql.matches ? \"dark\" : \"light\");\n }\n const onChange = (event: MediaQueryListEvent): void => {\n if (!userOverrodeModeRef.current) {\n setModeState(event.matches ? \"dark\" : \"light\");\n }\n };\n mql.addEventListener(\"change\", onChange);\n return () => {\n mql.removeEventListener(\"change\", onChange);\n };\n }, [respectSystemMode]);\n\n // Inject CSS vars whenever the themes list changes.\n useEffect(() => {\n injectThemeCss(themes);\n }, [themes]);\n\n // Apply data-theme + data-mode + data-density to <html>, load fonts,\n // inject density CSS vars.\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const active = themes.find((t) => t.name === themeName) ?? themes[0];\n if (!active) return;\n document.documentElement.setAttribute(\"data-theme\", active.name);\n document.documentElement.setAttribute(\"data-mode\", mode);\n document.documentElement.setAttribute(\"data-density\", density);\n document.documentElement.classList.toggle(\"dark\", mode === \"dark\");\n loadThemeFonts(active);\n injectDensityCss();\n }, [themeName, mode, density, themes]);\n\n // Persist on change.\n //\n // The first run is SKIPPED via `skipFirstPersistRef`: state at mount\n // is the SSR-safe default. If we wrote it to storage immediately,\n // we'd clobber the user's stored preference between mount and the\n // post-mount hydration effect that promotes the stored value. After\n // the first call, every subsequent run persists — whether the change\n // came from the hydration effect (no-op write back of the stored\n // value) or a user-driven `setTheme` / `toggleMode` / `setDensity`.\n useEffect(() => {\n if (skipFirstPersistRef.current) {\n skipFirstPersistRef.current = false;\n return;\n }\n if (typeof window === \"undefined\" || !storageKey) return;\n try {\n window.localStorage.setItem(`${storageKey}:name`, themeName);\n window.localStorage.setItem(`${storageKey}:mode`, mode);\n window.localStorage.setItem(`${storageKey}:density`, density);\n } catch (err) {\n // Storage may fail in private mode; behavior remains correct (state\n // lives in memory). Per HIGH-006 we surface a one-time dev warning so\n // the engineer sees something instead of complete silence.\n warnStorageFailure(\"persist theme + mode + density\", err);\n }\n }, [themeName, mode, density, storageKey]);\n\n const setTheme = useCallback((name: string) => setThemeName(name), []);\n const setMode = useCallback((next: ThemeMode) => {\n // T5.1 / D6: fix the user preference; subsequent system changes no longer override.\n userOverrodeModeRef.current = true;\n setModeState(next);\n }, []);\n const toggleMode = useCallback(() => {\n userOverrodeModeRef.current = true;\n setModeState((cur) => (cur === \"light\" ? \"dark\" : \"light\"));\n }, []);\n const setDensity = useCallback((next: Density) => setDensityState(next), []);\n const registerTheme = useCallback((theme: Theme) => {\n setThemes((cur) => {\n const idx = cur.findIndex((t) => t.name === theme.name);\n if (idx >= 0) {\n const next = cur.slice();\n next[idx] = theme;\n return next;\n }\n return [...cur, theme];\n });\n }, []);\n\n // themes[0] is guaranteed non-undefined by the constructor-time check\n // above (themesProp is non-empty); the non-null assert encodes that\n // invariant for TypeScript, which can't trace it through useState.\n // biome-ignore lint/style/noNonNullAssertion: T2.5 runtime invariant — themesProp non-empty validated at top of function\n const active = themes.find((t) => t.name === themeName) ?? themes[0]!;\n\n const value = useMemo<ThemeContextValue>(\n () => ({\n theme: active,\n mode,\n themes,\n setTheme,\n setMode,\n toggleMode,\n registerTheme,\n }),\n [active, mode, themes, setTheme, setMode, toggleMode, registerTheme],\n );\n\n const densityValue = useMemo(() => ({ density, setDensity }), [density, setDensity]);\n\n return (\n <ThemeContext.Provider value={value}>\n <DensityContext.Provider value={densityValue}>{children}</DensityContext.Provider>\n </ThemeContext.Provider>\n );\n}\n\n/**\n * useTheme — access theme state from any component inside <ThemeProvider>.\n * Throws if used outside the provider — fail-fast.\n */\nfunction useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) {\n throw new Error(\"useTheme must be used inside <ThemeProvider>.\");\n }\n return ctx;\n}\n\nexport { ThemeProvider, useTheme };\n"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"path": "themes/theme-switcher.tsx",
|
|
49
|
-
"type": "registry:lib",
|
|
50
|
-
"target": "themes/theme-switcher.tsx",
|
|
51
|
-
"content": "import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\";\nimport { Check, Moon, Palette, Sun } from \"lucide-react\";\nimport type { JSX } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { useTheme } from \"@/themes/theme-provider\";\n\ninterface ThemeSwitcherProps {\n className?: string;\n /** If true, renders mode toggle inline next to the theme menu. */\n showModeToggle?: boolean;\n}\n\n/**\n * ThemeSwitcher — drop-in theme + mode picker.\n *\n * Two affordances:\n * - Palette dropdown lists all registered themes with the active marked.\n * - Optional sun/moon button toggles light/dark.\n *\n * Stateless wrt itself — pulls state from `useTheme()`.\n */\nfunction ThemeSwitcher({ className, showModeToggle = true }: ThemeSwitcherProps): JSX.Element {\n const { theme, themes, setTheme, mode, toggleMode } = useTheme();\n\n return (\n <div className={cn(\"inline-flex items-center gap-1\", className)}>\n {/* LOW-006: announce theme + mode changes to assistive tech. The\n * Provider applies tokens via `data-theme`/`data-mode` (visual cue),\n * but screen-reader users get no feedback without this aria-live\n * region. Polite so it doesn't interrupt the user's flow. */}\n <span aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n Theme: {theme.label}, mode: {mode}\n </span>\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n aria-label={`Theme: ${theme.label}`}\n className={cn(\n \"inline-flex h-9 items-center gap-2 rounded-lg border border-border/60 bg-card px-3\",\n \"font-medium font-sans text-body-sm text-foreground\",\n \"transition-colors hover:bg-muted\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n )}\n >\n <Palette className=\"size-4 text-primary\" aria-hidden=\"true\" />\n <span>{theme.label}</span>\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n align=\"end\"\n sideOffset={6}\n className={cn(\n \"z-50 min-w-[16rem] overflow-hidden rounded-lg border bg-popover p-1 text-popover-foreground shadow-md\",\n \"data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:animate-out\",\n )}\n >\n {themes.map((t) => (\n <DropdownMenu.Item\n key={t.name}\n onSelect={() => setTheme(t.name)}\n className={cn(\n \"flex cursor-pointer items-start justify-between gap-3 rounded-md px-2 py-2\",\n \"focus:bg-muted focus:outline-none data-[highlighted]:bg-muted\",\n )}\n >\n <span className=\"flex min-w-0 flex-col\">\n <span className=\"font-medium text-body-sm\">{t.label}</span>\n {t.description ? (\n <span className=\"text-body-sm text-muted-foreground\">{t.description}</span>\n ) : null}\n </span>\n {t.name === theme.name ? (\n <Check className=\"mt-1 size-4 shrink-0 text-primary\" aria-hidden=\"true\" />\n ) : null}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n\n {showModeToggle ? (\n <button\n type=\"button\"\n onClick={toggleMode}\n aria-label={`Switch to ${mode === \"light\" ? \"dark\" : \"light\"} mode`}\n className={cn(\n \"inline-flex size-9 items-center justify-center rounded-lg border border-border/60 bg-card\",\n \"text-foreground transition-colors hover:bg-muted\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n )}\n >\n {mode === \"light\" ? <Moon className=\"size-4\" /> : <Sun className=\"size-4\" />}\n </button>\n ) : null}\n </div>\n );\n}\n\nexport { ThemeSwitcher };\n"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"path": "themes/index.ts",
|
|
55
|
-
"type": "registry:lib",
|
|
56
|
-
"target": "themes/index.ts",
|
|
57
|
-
"content": "export type { ColorScale, Theme, ThemeFonts, ThemeMode } from \"@/themes/types\";\nexport { ThemeProvider, useTheme } from \"@/themes/theme-provider\";\nexport { ThemeScript } from \"@/themes/theme-script\";\nexport { ThemeSwitcher } from \"@/themes/theme-switcher\";\nexport { violetForge } from \"@/themes/violet-forge\";\nexport { classicPaper } from \"@/themes/classic-paper\";\nexport { auroraTerminal } from \"@/themes/aurora-terminal\";\nexport { defineTheme, type DefineThemeInput } from \"./define\";\nexport { hex, hexToHsl, rgb, rgbToHslLegacy } from \"./color\";\nexport { useDensity, type Density, type DensityContextValue } from \"./density\";\n// Seven new themes — RFC 0007, plan: seven-themes (2026-05-22).\n// Trademark-safe slugs (D1.1) — `*-style` / `*-mono` / `*-glass` suffixes,\n// description includes \"Inspired by, not affiliated with [X]\".\nexport { vercelMono } from \"./vercel-mono\";\nexport { githubDark } from \"./github-dark\";\nexport { dracula } from \"./dracula\";\nexport { oneDark } from \"./one-dark\";\nexport { anthropicStyle } from \"./anthropic-style\";\nexport { openaiStyle } from \"./openai-style\";\nexport { linearGlass } from \"./linear-glass\";\n\nimport { anthropicStyle } from \"./anthropic-style\";\nimport { auroraTerminal } from \"@/themes/aurora-terminal\";\nimport { classicPaper } from \"@/themes/classic-paper\";\nimport { dracula } from \"./dracula\";\nimport { githubDark } from \"./github-dark\";\nimport { linearGlass } from \"./linear-glass\";\nimport { oneDark } from \"./one-dark\";\nimport { openaiStyle } from \"./openai-style\";\nimport { vercelMono } from \"./vercel-mono\";\nimport { violetForge } from \"@/themes/violet-forge\";\n\n/**\n * All themes bundled with Theo UI. Pass to `<ThemeProvider themes={builtinThemes}>`\n * if you want all 10 available out of the box.\n *\n * EC-4 note: passing the full 10-entry list triggers ~60 KB CSS injection in\n * `<style id=\"theo-ui-theme-vars\">`. For apps focused on 1-2 themes, prefer\n * `themes={[violetForge, dracula]}` to keep the payload at ~12 KB.\n */\nexport const builtinThemes = [\n violetForge,\n classicPaper,\n auroraTerminal,\n vercelMono,\n githubDark,\n dracula,\n oneDark,\n anthropicStyle,\n openaiStyle,\n linearGlass,\n];\n"
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "theme-script",
|
|
4
|
-
"type": "registry:lib",
|
|
5
|
-
"title": "ThemeScript",
|
|
6
|
-
"description": "Inline script for SSR-safe theme initialization in Next.js / Astro / Remix. Place in <head> to read persisted theme + mode from localStorage BEFORE React hydrates, eliminating FOUC and hydration mismatch.",
|
|
7
|
-
"registryDependencies": [
|
|
8
|
-
"https://usetheodev.github.io/theo-ui/r/theme-provider.json"
|
|
9
|
-
],
|
|
10
|
-
"files": [
|
|
11
|
-
{
|
|
12
|
-
"path": "themes/theme-script.tsx",
|
|
13
|
-
"type": "registry:lib",
|
|
14
|
-
"target": "themes/theme-script.tsx",
|
|
15
|
-
"content": "/**\n * ThemeScript — inline `<script>` for SSR-safe theme initialization.\n *\n * Renders a synchronous script that runs BEFORE React hydration. It reads the\n * persisted theme + mode from localStorage (or falls back to the defaults) and\n * sets `data-theme` / `data-mode` on `<html>`, plus the `.dark` class when\n * mode is dark. This eliminates FOUC and avoids hydration mismatch warnings\n * when the user's persisted choice differs from the SSR defaults.\n *\n * Place this in `<head>` ABOVE `<body>`. The component does not need to live\n * inside `<ThemeProvider>`.\n *\n * Security: every interpolated value is passed through `safe()`, which both\n * `JSON.stringify`s the value AND escapes `<` to `<`. The `<` escape is\n * REQUIRED because `JSON.stringify` alone does NOT escape `/`, so a payload\n * like `\"</script><script>alert(1)</script>\"` would otherwise break out of\n * the inline `<script>` tag even though it stays inside a JS string literal.\n * (The browser tokenizes `</script>` at the HTML layer before JS parses.)\n *\n * Example (Next.js App Router): see docs/design-system.md → SSR section.\n * Pass `defaultTheme` and `defaultMode` to align with the consumer's\n * preferred initial state. Always wrap the root in `<html\n * suppressHydrationWarning>` to silence the expected one-render diff.\n */\nimport type { JSX } from \"react\";\nimport type { ThemeMode } from \"@/themes/types\";\n\ninterface ThemeScriptProps {\n /** Theme name to apply when no persisted value exists. Default `\"violet-forge\"`. */\n defaultTheme?: string;\n /** Mode to apply when no persisted value exists. Default `\"dark\"`. */\n defaultMode?: ThemeMode;\n /**\n * Density to apply when no persisted value exists. Default `\"comfortable\"`.\n * Mirrors `ThemeProvider`'s `defaultDensity` so the inline-script and\n * the React provider agree on the SSR-default density (and the\n * `data-density` attribute set by this script matches what\n * `ThemeProvider` promotes via its post-mount hydration effect).\n */\n defaultDensity?: \"compact\" | \"comfortable\" | \"spacious\";\n /**\n * localStorage namespace. Must match the `storageKey` passed to\n * `<ThemeProvider>`. Default `\"theo-ui:theme\"`. Pass `null` to disable\n * persistence reads (the script will always apply defaults).\n */\n storageKey?: string | null;\n}\n\n/**\n * Encode a value for safe embedding inside an inline `<script>` block.\n *\n * `JSON.stringify` does NOT escape `/` by default, so `\"</script>\"` survives\n * as the literal three-character sequence inside the resulting string. When\n * that string is then rendered inside `<script>...</script>`, the browser's\n * HTML tokenizer sees `</script>` and ends the script tag — regardless of\n * whether the JS parser would have kept it inside a string. Escaping `<` to\n * its Unicode escape `<` preserves JS semantics (the JS parser still\n * resolves the escape to `<`) while making the HTML tokenizer happy.\n *\n * Reference: OWASP \"JSON-in-script\" guidance; React's own server-renderer\n * applies the same escape for inline JSON.\n */\nfunction safe(value: unknown): string {\n return JSON.stringify(value).replace(/</g, \"\\\\u003c\");\n}\n\nfunction buildScript(\n defaultTheme: string,\n defaultMode: ThemeMode,\n defaultDensity: \"compact\" | \"comfortable\" | \"spacious\",\n storageKey: string | null,\n): string {\n const k = safe(storageKey);\n const t = safe(defaultTheme);\n const m = safe(defaultMode);\n const dn = safe(defaultDensity);\n return `(function(){try{var k=${k};var d=document.documentElement;var t=null;var m=null;var dn=null;if(k){t=localStorage.getItem(k+\":name\");m=localStorage.getItem(k+\":mode\");dn=localStorage.getItem(k+\":density\");}d.setAttribute(\"data-theme\",t||${t});d.setAttribute(\"data-mode\",m||${m});d.setAttribute(\"data-density\",dn||${dn});if((m||${m})===\"dark\"){d.classList.add(\"dark\");}}catch(e){}})();`;\n}\n\nfunction ThemeScript({\n defaultTheme = \"violet-forge\",\n defaultMode = \"dark\",\n defaultDensity = \"comfortable\",\n storageKey = \"theo-ui:theme\",\n}: ThemeScriptProps): JSX.Element {\n const code = buildScript(defaultTheme, defaultMode, defaultDensity, storageKey);\n // biome-ignore lint/security/noDangerouslySetInnerHtml: payload is JSON.stringify-encoded literals (no user input); intentional for SSR theme bootstrap before React hydrates\n return <script suppressHydrationWarning dangerouslySetInnerHTML={{ __html: code }} />;\n}\n\nexport { ThemeScript };\n"
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "theo-ui-provider",
|
|
4
|
-
"type": "registry:lib",
|
|
5
|
-
"title": "TheoUIProvider",
|
|
6
|
-
"description": "Primary entry-point provider — composes ThemeProvider + Toaster with sensible defaults. Use as the single root wrapper in consumer apps.",
|
|
7
|
-
"dependencies": [],
|
|
8
|
-
"registryDependencies": [
|
|
9
|
-
"https://usetheodev.github.io/theo-ui/r/theme-provider.json",
|
|
10
|
-
"https://usetheodev.github.io/theo-ui/r/toast.json"
|
|
11
|
-
],
|
|
12
|
-
"files": [
|
|
13
|
-
{
|
|
14
|
-
"path": "theo-ui-provider.tsx",
|
|
15
|
-
"type": "registry:lib",
|
|
16
|
-
"target": "theo-ui-provider.tsx",
|
|
17
|
-
"content": "\"use client\";\n\nimport type { ComponentProps, JSX, ReactNode } from \"react\";\nimport { Toaster } from \"@/components/ui/toaster\";\nimport { builtinThemes } from \"@/themes/index\";\nimport { ThemeProvider } from \"@/themes/theme-provider\";\n\n/**\n * TheoUIProvider — primary entry point composing `<ThemeProvider>` and\n * `<Toaster>` in the correct order with sensible defaults.\n *\n * Recommended for consumer apps to avoid hand-wiring the provider stack.\n * Equivalent to:\n *\n * <ThemeProvider themes={builtinThemes} {...theme}>\n * <Toaster {...toaster}>{children}</Toaster>\n * </ThemeProvider>\n *\n * Notes:\n * - Since v0.1.0-next.0, `<ThemeProvider>` requires the `themes` prop\n * (T2.5 decoupling). `<TheoUIProvider>` defaults it to `builtinThemes`\n * to preserve \"works out of the box\" DX. Pass `theme.themes` to override.\n * - The `\"use client\"` directive is required for Next.js App Router (RSC)\n * because `<ThemeProvider>` uses React state and effects internally.\n * - `<Tooltip>` provider stays per-instance (Radix recommendation) — this\n * wrapper does NOT introduce a global tooltip context.\n * - `<ThemeProvider>` and `<Toaster>` remain independently exported for\n * consumers who want bespoke control.\n *\n * SSR:\n * - Place `<ThemeScript>` in `<head>` to avoid FOUC + hydration mismatch.\n * - Wrap `<html lang=\"en\" suppressHydrationWarning>`.\n *\n * @example\n * import { TheoUIProvider } from \"@theokit/ui\";\n *\n * export default function App({ children }) {\n * return <TheoUIProvider>{children}</TheoUIProvider>;\n * }\n */\nexport interface TheoUIProviderProps {\n children: ReactNode;\n /** Pass-through props for the inner `<ThemeProvider>`. Optional. */\n theme?: Omit<ComponentProps<typeof ThemeProvider>, \"children\" | \"themes\"> & {\n /** Override the default theme set (defaults to `builtinThemes`). */\n themes?: ComponentProps<typeof ThemeProvider>[\"themes\"];\n };\n /** Pass-through props for the inner `<Toaster>`. */\n toaster?: Omit<ComponentProps<typeof Toaster>, \"children\">;\n}\n\nexport function TheoUIProvider({ children, theme, toaster }: TheoUIProviderProps): JSX.Element {\n const { themes, ...restTheme } = theme ?? {};\n return (\n <ThemeProvider themes={themes ?? builtinThemes} {...restTheme}>\n <Toaster {...toaster}>{children}</Toaster>\n </ThemeProvider>\n );\n}\n\nTheoUIProvider.displayName = \"TheoUIProvider\";\n"
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "timestamp",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "Timestamp",
|
|
6
|
-
"description": "Accessible <time> primitive with relative/absolute/both formats, auto-refresh interval (default 60s, 0 disables), native title tooltip with absolute time, and aria-label that always carries the full date. Built on Intl.RelativeTimeFormat (zero deps). value accepts ISO string, Date, or Unix ms (NOT seconds). Invalid date renders empty element; invalid locale falls back to default with dev warning.",
|
|
7
|
-
"dependencies": [],
|
|
8
|
-
"registryDependencies": [
|
|
9
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
10
|
-
"https://usetheodev.github.io/theo-ui/r/env.json",
|
|
11
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
|
|
12
|
-
],
|
|
13
|
-
"files": [
|
|
14
|
-
{
|
|
15
|
-
"path": "components/primitives/timestamp/timestamp.tsx",
|
|
16
|
-
"type": "registry:ui",
|
|
17
|
-
"target": "components/ui/timestamp.tsx",
|
|
18
|
-
"content": "\"use client\";\n\nimport { forwardRef, useEffect, useState } from \"react\";\nimport type { TimeHTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { isDev } from \"@/lib/env\";\n\n/**\n * Timestamp — accessible relative/absolute time primitive.\n *\n * Renders a semantic `<time datetime>` element. Format modes:\n * - `relative` (default) — \"just now\", \"5 minutes ago\", \"2 hours ago\",\n * \"Dec 5\" (>7d), \"Dec 5, 2024\" (different year)\n * - `absolute` — full localized date+time\n * - `both` — \"Dec 5, 2026 (2 hours ago)\"\n *\n * Uses zero-dep `Intl.RelativeTimeFormat`. The tooltip on hover is the\n * HTML `title` attribute (not the `<Tooltip>` component) — keeps this\n * file a true primitive without sibling-primitive imports.\n *\n * Auto-refreshes via `setInterval` (default 60_000ms); pass\n * `refreshInterval={0}` to disable. `aria-label` always carries the\n * absolute time so screen readers read \"May 23, 2026 14:32 — posted\n * 2 hours ago\".\n *\n * @param value Source date — ISO string, Date object, or **Unix ms**\n * (NOT seconds). Passing seconds renders ~1970.\n */\nexport interface TimestampProps extends Omit<TimeHTMLAttributes<HTMLTimeElement>, \"children\"> {\n value: string | Date | number;\n format?: \"relative\" | \"absolute\" | \"both\";\n /** Auto-refresh interval when format=relative. Default 60000. 0 disables. */\n refreshInterval?: number;\n /** Locale for absolute formatting + Intl.RelativeTimeFormat. Default browser locale. */\n locale?: string;\n /** When true, omit the `title` tooltip. */\n noTooltip?: boolean;\n}\n\nfunction toDate(value: string | Date | number): Date | null {\n const d = value instanceof Date ? value : new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\nconst SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;\nconst UNITS: Array<{ unit: Intl.RelativeTimeFormatUnit; ms: number }> = [\n { unit: \"year\", ms: 365 * 24 * 60 * 60 * 1000 },\n { unit: \"month\", ms: 30 * 24 * 60 * 60 * 1000 },\n { unit: \"day\", ms: 24 * 60 * 60 * 1000 },\n { unit: \"hour\", ms: 60 * 60 * 1000 },\n { unit: \"minute\", ms: 60 * 1000 },\n];\n\nfunction safeRelativeFormatter(locale: string | undefined): Intl.RelativeTimeFormat | null {\n try {\n return new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" });\n } catch {\n // EC-8: invalid locale tag — fall back to default locale.\n if (isDev()) {\n // biome-ignore lint/suspicious/noConsole: dev-only diagnostic.\n console.warn(`<Timestamp locale=\"${locale}\">: invalid locale tag, falling back to default.`);\n }\n try {\n return new Intl.RelativeTimeFormat(undefined, { numeric: \"auto\" });\n } catch {\n return null;\n }\n }\n}\n\nfunction safeAbsoluteFormat(date: Date, locale: string | undefined, withYear: boolean): string {\n try {\n return date.toLocaleDateString(locale, {\n month: \"short\",\n day: \"numeric\",\n ...(withYear ? { year: \"numeric\" } : {}),\n });\n } catch {\n return date.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n ...(withYear ? { year: \"numeric\" } : {}),\n });\n }\n}\n\nfunction formatRelative(date: Date, now: Date, locale: string | undefined): string {\n const diffMs = date.getTime() - now.getTime();\n const absMs = Math.abs(diffMs);\n\n if (absMs < 60_000) return \"just now\";\n\n if (diffMs < 0 && absMs > SEVEN_DAYS_MS) {\n const sameYear = date.getFullYear() === now.getFullYear();\n return safeAbsoluteFormat(date, locale, !sameYear);\n }\n\n const rtf = safeRelativeFormatter(locale);\n if (rtf === null) {\n return safeAbsoluteFormat(date, locale, date.getFullYear() !== now.getFullYear());\n }\n\n for (const { unit, ms } of UNITS) {\n if (absMs >= ms) {\n return rtf.format(Math.round(diffMs / ms), unit);\n }\n }\n return \"just now\";\n}\n\nfunction formatAbsolute(date: Date, locale: string | undefined): string {\n try {\n return date.toLocaleString(locale, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n } catch {\n return date.toLocaleString(undefined, {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n }\n}\n\nconst Timestamp = forwardRef<HTMLTimeElement, TimestampProps>(\n (\n {\n className,\n value,\n format = \"relative\",\n refreshInterval = 60_000,\n locale,\n noTooltip,\n ...props\n },\n ref,\n ) => {\n const date = toDate(value);\n const [now, setNow] = useState<Date>(() => new Date());\n\n useEffect(() => {\n if (format !== \"relative\" || refreshInterval === 0 || date === null) return;\n const id = setInterval(() => setNow(new Date()), refreshInterval);\n return () => clearInterval(id);\n }, [format, refreshInterval, date]);\n\n if (date === null) {\n return (\n <time\n data-slot=\"timestamp\"\n ref={ref}\n className={cn(className)}\n suppressHydrationWarning\n {...props}\n />\n );\n }\n\n const iso = date.toISOString();\n const absolute = formatAbsolute(date, locale);\n const relative = formatRelative(date, now, locale);\n const visibleText =\n format === \"absolute\" ? absolute : format === \"both\" ? `${absolute} (${relative})` : relative;\n\n return (\n <time\n data-slot=\"timestamp\"\n ref={ref}\n dateTime={iso}\n title={noTooltip ? undefined : absolute}\n aria-label={absolute}\n suppressHydrationWarning\n className={cn(className)}\n {...props}\n >\n {visibleText}\n </time>\n );\n },\n);\nTimestamp.displayName = \"Timestamp\";\n\nexport { Timestamp };\n"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
package/registry/r/toast.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
-
"name": "toast",
|
|
4
|
-
"type": "registry:ui",
|
|
5
|
-
"title": "Toast",
|
|
6
|
-
"description": "Transient notification built on Radix Toast.",
|
|
7
|
-
"dependencies": [
|
|
8
|
-
"@radix-ui/react-toast",
|
|
9
|
-
"class-variance-authority",
|
|
10
|
-
"lucide-react"
|
|
11
|
-
],
|
|
12
|
-
"registryDependencies": [
|
|
13
|
-
"https://usetheodev.github.io/theo-ui/r/cn.json",
|
|
14
|
-
"https://usetheodev.github.io/theo-ui/r/tailwind-preset.json"
|
|
15
|
-
],
|
|
16
|
-
"files": [
|
|
17
|
-
{
|
|
18
|
-
"path": "components/primitives/toast/toast.tsx",
|
|
19
|
-
"type": "registry:ui",
|
|
20
|
-
"target": "components/ui/toast.tsx",
|
|
21
|
-
"content": "import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { AlertCircle, CheckCircle2, Info, TriangleAlert, X } from \"lucide-react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ElementRef, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Toast — transient notification built on Radix Toast.\n *\n * Composition: app mounts <Toaster /> once. Components call `toast(...)` via\n * the `useToast()` hook (see toaster.tsx). The look is theme-aware: status\n * icon coloured by --primary/--success/--warning/--destructive; the body\n * card uses --popover surface.\n *\n * Variants:\n * - default (neutral)\n * - info (primary tint)\n * - success (deploy ok, action completed)\n * - warning (queued, permission requested)\n * - destructive (failed, fatal)\n */\n\nconst toastVariants = cva(\n [\n \"group pointer-events-auto relative flex w-full items-start gap-3 overflow-hidden rounded-lg border pr-10 shadow-md\",\n \"data-[state=open]:slide-in-from-top-full data-[state=open]:fade-in-0 data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=closed]:animate-out\",\n \"data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)]\",\n \"data-[swipe=end]:animate-out data-[swipe=cancel]:transition-[transform_var(--duration-base)] data-[swipe=move]:transition-none\",\n ],\n {\n variants: {\n variant: {\n default: \"border-border/40 bg-popover text-popover-foreground\",\n info: \"border-primary/40 bg-popover text-popover-foreground\",\n success: \"border-success/40 bg-popover text-popover-foreground\",\n warning: \"border-warning/40 bg-popover text-popover-foreground\",\n destructive: \"border-destructive/50 bg-popover text-popover-foreground\",\n },\n size: {\n sm: \"p-3 text-body-sm\",\n md: \"p-4 text-body-md\",\n lg: \"p-5 text-body-lg\",\n },\n },\n defaultVariants: { variant: \"default\", size: \"md\" },\n },\n);\n\nconst iconForVariant: Record<NonNullable<ToastVariant>, ReactNode> = {\n default: <Info className=\"size-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />,\n info: <Info className=\"size-4 shrink-0 text-primary\" aria-hidden=\"true\" />,\n success: <CheckCircle2 className=\"size-4 shrink-0 text-success\" aria-hidden=\"true\" />,\n warning: <TriangleAlert className=\"size-4 shrink-0 text-warning\" aria-hidden=\"true\" />,\n destructive: <AlertCircle className=\"size-4 shrink-0 text-destructive\" aria-hidden=\"true\" />,\n};\n\ntype ToastVariant = NonNullable<VariantProps<typeof toastVariants>[\"variant\"]>;\n\ninterface ToastProps\n extends ComponentPropsWithoutRef<typeof ToastPrimitive.Root>,\n VariantProps<typeof toastVariants> {}\n\nconst ToastRoot = forwardRef<ElementRef<typeof ToastPrimitive.Root>, ToastProps>(\n ({ className, variant = \"default\", size, children, ...props }, ref) => (\n <ToastPrimitive.Root\n data-slot=\"toast\"\n data-variant={variant}\n data-size={size}\n ref={ref}\n className={cn(toastVariants({ variant, size }), className)}\n {...props}\n >\n <span aria-hidden=\"true\">{iconForVariant[variant as ToastVariant]}</span>\n <div className=\"min-w-0 flex-1\">{children}</div>\n </ToastPrimitive.Root>\n ),\n);\nToastRoot.displayName = \"Toast\";\n\nconst ToastTitle = forwardRef<\n ElementRef<typeof ToastPrimitive.Title>,\n ComponentPropsWithoutRef<typeof ToastPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Title\n data-slot=\"toast-title\"\n ref={ref}\n className={cn(\"font-medium text-body-sm text-foreground\", className)}\n {...props}\n />\n));\nToastTitle.displayName = \"Toast.Title\";\n\nconst ToastDescription = forwardRef<\n ElementRef<typeof ToastPrimitive.Description>,\n ComponentPropsWithoutRef<typeof ToastPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Description\n data-slot=\"toast-description\"\n ref={ref}\n className={cn(\"mt-0.5 text-body-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nToastDescription.displayName = \"Toast.Description\";\n\nconst ToastClose = forwardRef<\n ElementRef<typeof ToastPrimitive.Close>,\n ComponentPropsWithoutRef<typeof ToastPrimitive.Close>\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Close\n data-slot=\"toast-close\"\n ref={ref}\n className={cn(\n \"absolute top-2 right-2 rounded-md p-1 text-muted-foreground opacity-70 transition-opacity hover:opacity-100\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n className,\n )}\n toast-close=\"\"\n {...props}\n >\n <X className=\"size-3.5\" />\n <span className=\"sr-only\">Close</span>\n </ToastPrimitive.Close>\n));\nToastClose.displayName = \"Toast.Close\";\n\nconst ToastAction = forwardRef<\n ElementRef<typeof ToastPrimitive.Action>,\n ComponentPropsWithoutRef<typeof ToastPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Action\n data-slot=\"toast-action\"\n ref={ref}\n className={cn(\n \"mt-2 inline-flex h-7 items-center rounded-md border border-border/60 bg-card px-2 font-sans text-foreground text-label\",\n \"transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n className,\n )}\n {...props}\n />\n));\nToastAction.displayName = \"Toast.Action\";\n\nconst Toast = /*#__PURE__*/ Object.assign(ToastRoot, {\n Title: ToastTitle,\n Description: ToastDescription,\n Close: ToastClose,\n Action: ToastAction,\n Provider: ToastPrimitive.Provider,\n Viewport: ToastPrimitive.Viewport,\n});\n\nexport { Toast, toastVariants, type ToastVariant };\n"
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
"path": "components/primitives/toast/toaster.tsx",
|
|
25
|
-
"type": "registry:ui",
|
|
26
|
-
"target": "components/ui/toaster.tsx",
|
|
27
|
-
"content": "\"use client\";\n\nimport { createContext, useCallback, useContext, useMemo, useState } from \"react\";\nimport type { JSX, ReactNode } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { Toast, type ToastVariant } from \"@/components/ui/toast\";\n\ninterface ToastDescriptor {\n id: string;\n title?: ReactNode;\n description?: ReactNode;\n variant?: ToastVariant;\n /** Auto-dismiss in ms. Default 5000. Pass `null` for sticky. */\n duration?: number | null;\n action?: { label: ReactNode; onClick: () => void };\n}\n\ninterface ToastContextValue {\n toast: (descriptor: Omit<ToastDescriptor, \"id\">) => string;\n dismiss: (id: string) => void;\n}\n\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\n\ninterface ToasterProps {\n children: ReactNode;\n /** Toast viewport position. Default bottom-right. */\n position?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n className?: string;\n}\n\nconst POSITION_CLASS: Record<NonNullable<ToasterProps[\"position\"]>, string> = {\n \"top-right\": \"top-4 right-4\",\n \"top-left\": \"top-4 left-4\",\n \"bottom-right\": \"bottom-4 right-4\",\n \"bottom-left\": \"bottom-4 left-4\",\n};\n\n/**\n * Toaster — mount once at the app root. Wraps children in a Radix Toast\n * Provider + Viewport and exposes the `useToast()` hook for descendants.\n */\nfunction Toaster({ children, position = \"bottom-right\", className }: ToasterProps): JSX.Element {\n const [toasts, setToasts] = useState<ToastDescriptor[]>([]);\n\n const dismiss = useCallback((id: string) => {\n setToasts((cur) => cur.filter((t) => t.id !== id));\n }, []);\n\n const toast = useCallback((descriptor: Omit<ToastDescriptor, \"id\">) => {\n const id = `t-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n setToasts((cur) => [...cur, { id, ...descriptor }]);\n return id;\n }, []);\n\n const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);\n\n return (\n <ToastContext.Provider data-slot=\"toaster\" value={value}>\n <Toast.Provider swipeDirection=\"right\" duration={5000}>\n {children}\n {toasts.map((t) => (\n <Toast\n key={t.id}\n variant={t.variant ?? \"default\"}\n duration={t.duration === null ? Number.POSITIVE_INFINITY : (t.duration ?? 5000)}\n onOpenChange={(open) => {\n if (!open) dismiss(t.id);\n }}\n >\n {t.title ? <Toast.Title>{t.title}</Toast.Title> : null}\n {t.description ? <Toast.Description>{t.description}</Toast.Description> : null}\n {t.action ? (\n <Toast.Action altText={String(t.action.label)} onClick={t.action.onClick}>\n {t.action.label}\n </Toast.Action>\n ) : null}\n <Toast.Close />\n </Toast>\n ))}\n <Toast.Viewport\n className={cn(\n \"fixed z-50 flex max-h-screen w-full max-w-sm flex-col gap-2 outline-none\",\n POSITION_CLASS[position],\n className,\n )}\n />\n </Toast.Provider>\n </ToastContext.Provider>\n );\n}\n\n/**\n * useToast — fire toasts from anywhere inside <Toaster>.\n *\n * Example:\n * const { toast } = useToast();\n * toast({ title: \"Deployed\", variant: \"success\" });\n */\nfunction useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used inside <Toaster>.\");\n return ctx;\n}\n\nexport { Toaster, useToast };\n"
|
|
28
|
-
}
|
|
29
|
-
]
|
|
30
|
-
}
|