@elabs-ai/components-ui 5.0.0 → 5.2.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 +1 -1
- package/dist/{chunk-6QU7OVFA.js → chunk-2ZMPAD6C.js} +7 -7
- package/dist/{chunk-OBEJUAN6.js → chunk-2ZWUTZHE.js} +5 -5
- package/dist/{chunk-U4LHV5DS.js → chunk-36SY7TID.js} +2 -2
- package/dist/{chunk-IHMFEPIT.js → chunk-3BZBNDRP.js} +3 -3
- package/dist/{chunk-5AWXGBSH.js → chunk-3DJ4KY3U.js} +3 -3
- package/dist/{chunk-LR2CU7HK.js → chunk-3ZR5PMKB.js} +2 -2
- package/dist/{chunk-QDTGDYMM.js → chunk-47YSHR3H.js} +3 -3
- package/dist/{chunk-2HXVFC4B.js → chunk-4B2E4OCZ.js} +2 -2
- package/dist/{chunk-3B7W334A.js → chunk-4C4D6T5M.js} +3 -3
- package/dist/{chunk-YWB7HLL7.js → chunk-4NSCLIES.js} +3 -3
- package/dist/{chunk-UPEMEBWH.js → chunk-55BM2IU2.js} +5 -5
- package/dist/{chunk-XMZ5LXL4.js → chunk-5AJQUJ5C.js} +4 -4
- package/dist/{chunk-5V5J7APL.js → chunk-5C5W52O2.js} +2 -2
- package/dist/{chunk-FINAKMC6.js → chunk-5KNLME6F.js} +14 -8
- package/dist/chunk-5KNLME6F.js.map +1 -0
- package/dist/{chunk-FDPONOOT.js → chunk-5MXQ5CP7.js} +2 -2
- package/dist/{chunk-HVFYAQLK.js → chunk-5QQFXDUY.js} +8 -6
- package/dist/{chunk-HVFYAQLK.js.map → chunk-5QQFXDUY.js.map} +1 -1
- package/dist/{chunk-XZ23AFOP.js → chunk-64BKIIJC.js} +2 -2
- package/dist/{chunk-NBMF7SIS.js → chunk-6HTZBBTC.js} +2 -2
- package/dist/{chunk-5RC32MZH.js → chunk-72H7HUTH.js} +2 -2
- package/dist/{chunk-URVAZW44.js → chunk-7KV7H2TW.js} +2 -2
- package/dist/{chunk-VFF3AN4Y.js → chunk-7Z2RAGOA.js} +2 -2
- package/dist/{chunk-LXW3GNF7.js → chunk-7ZJLR6RP.js} +7 -7
- package/dist/{chunk-R3SYH7RG.js → chunk-A3JF66ZC.js} +16 -11
- package/dist/chunk-A3JF66ZC.js.map +1 -0
- package/dist/{chunk-IGP5E4FC.js → chunk-A3TT32GE.js} +5 -5
- package/dist/{chunk-LVRULYU4.js → chunk-A4ZSNEZD.js} +9 -9
- package/dist/{chunk-BM6NGS3A.js → chunk-AE6LFFME.js} +3 -3
- package/dist/{chunk-KTH3GWAL.js → chunk-AR5PJ5ZR.js} +6 -6
- package/dist/{chunk-RNC4M6SG.js → chunk-B3DANITU.js} +3 -3
- package/dist/{chunk-MGAXCPT7.js → chunk-B7FAQKHH.js} +2 -2
- package/dist/{chunk-35ZTVB35.js → chunk-BGXBANS2.js} +6 -6
- package/dist/{chunk-NJAGSGPF.js → chunk-C4FNDXBM.js} +4 -4
- package/dist/{chunk-VA2OONPE.js → chunk-C5QBV5RE.js} +2 -2
- package/dist/{chunk-LOSXINSS.js → chunk-C6I5I5LA.js} +5 -5
- package/dist/{chunk-7WXDSTNR.js → chunk-CDMJSXCB.js} +2 -2
- package/dist/{chunk-A47AZPCL.js → chunk-CEQ3YKHR.js} +2 -2
- package/dist/{chunk-A43B4IT7.js → chunk-CGY25FAG.js} +5 -5
- package/dist/{chunk-EHGIW7GA.js → chunk-CMP4F537.js} +2 -2
- package/dist/{chunk-6OFWWIEG.js → chunk-D5INX2EF.js} +3 -3
- package/dist/{chunk-HDS64Z5L.js → chunk-DIL73NE3.js} +2 -2
- package/dist/{chunk-3EKVSKGJ.js → chunk-DXC3DTCV.js} +3 -3
- package/dist/{chunk-ZNFHDBUW.js → chunk-EBNPVPR7.js} +2 -2
- package/dist/{chunk-ZXBUOHCR.js → chunk-EHN5ZAHP.js} +3 -3
- package/dist/{chunk-4PITSMJ3.js → chunk-EJ3XWNY3.js} +2 -2
- package/dist/{chunk-4E73UAFA.js → chunk-F6FF4EJN.js} +7 -7
- package/dist/{chunk-FYCCNQXQ.js → chunk-FC2LHNJG.js} +7 -7
- package/dist/{chunk-6OPDRLMU.js → chunk-FCVHZDP7.js} +8 -8
- package/dist/{chunk-B5QQLMEE.js → chunk-FG3PDWE3.js} +2 -2
- package/dist/{chunk-EY2PGOG3.js → chunk-FKDI2T7X.js} +4 -4
- package/dist/{chunk-XONGYCW3.js → chunk-FNRVVVXX.js} +3 -3
- package/dist/{chunk-BLNXHETI.js → chunk-FWAFP76U.js} +4 -4
- package/dist/{chunk-KBNWM27Q.js → chunk-FXWWDMMP.js} +9 -2
- package/dist/chunk-FXWWDMMP.js.map +1 -0
- package/dist/{chunk-KUAVM54Y.js → chunk-FZEG2R3E.js} +2 -2
- package/dist/{chunk-FKUP7QRJ.js → chunk-GTBVTLZJ.js} +2 -2
- package/dist/{chunk-NTTSHOOK.js → chunk-HF6BGFUV.js} +4 -4
- package/dist/{chunk-QNEOO22E.js → chunk-HND6FAMX.js} +2 -2
- package/dist/{chunk-ECCNRCC4.js → chunk-HNLYRHAU.js} +2 -2
- package/dist/{chunk-7G63B2B7.js → chunk-HUIYDDDL.js} +7 -7
- package/dist/{chunk-DCI6IOJX.js → chunk-HUXLE3K3.js} +4 -4
- package/dist/{chunk-HANBQNW3.js → chunk-I2C5RZ4S.js} +25 -1
- package/dist/{chunk-HANBQNW3.js.map → chunk-I2C5RZ4S.js.map} +1 -1
- package/dist/{chunk-J2P4YZLC.js → chunk-I3LBIBVN.js} +6 -6
- package/dist/{chunk-XYACSO57.js → chunk-I3U52BDH.js} +2 -2
- package/dist/{chunk-RRZUMIYG.js → chunk-IIY5JRNW.js} +3 -3
- package/dist/{chunk-4GQFIJAE.js → chunk-IV6OYZTL.js} +3 -3
- package/dist/{chunk-UQHWOPUY.js → chunk-IVEDMK5U.js} +2 -2
- package/dist/{chunk-U26XDHMX.js → chunk-JQIXRCLG.js} +5 -5
- package/dist/{chunk-WW3CD7AU.js → chunk-JU4KW7JN.js} +7 -7
- package/dist/{chunk-YIVL6HWS.js → chunk-JVCIAEFT.js} +2 -2
- package/dist/{chunk-DUF2VZON.js → chunk-K4V2ELUZ.js} +2 -2
- package/dist/{chunk-BPXLHGWI.js → chunk-KK2TIWTF.js} +2 -2
- package/dist/{chunk-NRSSSVWB.js → chunk-KPZFLTZ2.js} +2 -2
- package/dist/{chunk-OYM3NHSD.js → chunk-KXYL3CUS.js} +2 -2
- package/dist/{chunk-KOVHUAHG.js → chunk-L5O2O67Y.js} +6 -6
- package/dist/{chunk-RM5JIUVW.js → chunk-LG33MONJ.js} +2 -2
- package/dist/{chunk-YACASX6X.js → chunk-LLYLDZXC.js} +2 -2
- package/dist/{chunk-RWUKMJYA.js → chunk-LMV225AS.js} +2 -2
- package/dist/{chunk-533R5EKD.js → chunk-LVY7B5PD.js} +5 -5
- package/dist/{chunk-OV4GQOLC.js → chunk-M2KNQZUL.js} +2 -2
- package/dist/{chunk-7PS5MKVH.js → chunk-MIWFBH5S.js} +5 -5
- package/dist/{chunk-XAFRTZQF.js → chunk-MJAIURHO.js} +2 -2
- package/dist/{chunk-YL7VBHPZ.js → chunk-NXCOVGDU.js} +3 -3
- package/dist/{chunk-6TJVJPNU.js → chunk-O6AIFSTX.js} +46 -1
- package/dist/chunk-O6AIFSTX.js.map +1 -0
- package/dist/{chunk-WX3LWMVU.js → chunk-O6V65J5J.js} +2 -2
- package/dist/{chunk-EJQYE4MY.js → chunk-OFFWEDKY.js} +2 -2
- package/dist/{chunk-UXSV6RVS.js → chunk-OKY7ACZK.js} +2 -2
- package/dist/{chunk-ITFDGFOT.js → chunk-ONXBRQJT.js} +3 -3
- package/dist/{chunk-ULIDYFM7.js → chunk-OPBSVEMX.js} +2 -2
- package/dist/{chunk-333EWYWL.js → chunk-PCNQ6NP2.js} +6 -6
- package/dist/{chunk-6HGS5Z2Z.js → chunk-PFGQDW3H.js} +4 -4
- package/dist/{chunk-K6YRTASS.js → chunk-PGKQZBLZ.js} +2 -2
- package/dist/{chunk-57C25JYV.js → chunk-PQZD5W3E.js} +2 -2
- package/dist/{chunk-5Z55AFOW.js → chunk-PT5P4AAU.js} +2 -2
- package/dist/{chunk-EL3OXVOW.js → chunk-PUACHQRH.js} +2 -2
- package/dist/{chunk-HRYH7XQP.js → chunk-QKZX5HDY.js} +2 -2
- package/dist/{chunk-KZWC6JCI.js → chunk-QXXHK34V.js} +6 -6
- package/dist/{chunk-JGS2IHER.js → chunk-R27VUCWR.js} +4 -4
- package/dist/{chunk-QGX37P5L.js → chunk-R6CITZBB.js} +2 -2
- package/dist/{chunk-X6J4KKZZ.js → chunk-RFTC5UVB.js} +4 -4
- package/dist/{chunk-YXHHUJOZ.js → chunk-RHZSAWAU.js} +3 -3
- package/dist/{chunk-LMO3QK7Q.js → chunk-S7YR3FYZ.js} +3 -3
- package/dist/{chunk-GRWGNWIJ.js → chunk-SCCBEFVK.js} +6 -6
- package/dist/{chunk-R7DDZIE3.js → chunk-SD5MGHIJ.js} +4 -4
- package/dist/{chunk-PP7POY7C.js → chunk-SEGTBIR4.js} +2 -2
- package/dist/{chunk-D3C3VVCX.js → chunk-SGBCLZQF.js} +2 -2
- package/dist/{chunk-E3ES2KR6.js → chunk-SJHDX73F.js} +6 -6
- package/dist/{chunk-EKY3A5LO.js → chunk-SLDJYJEG.js} +3 -3
- package/dist/{chunk-KWQ6HV5Z.js → chunk-SQLEVIAD.js} +4 -4
- package/dist/{chunk-T4JNXV75.js → chunk-SR3SC2Q3.js} +6 -6
- package/dist/{chunk-YPLKH5H4.js → chunk-SSQG36MH.js} +6 -6
- package/dist/{chunk-NQY3QNLR.js → chunk-U5BZXNHW.js} +4 -4
- package/dist/{chunk-TEKBTTP2.js → chunk-U756JCDK.js} +2 -2
- package/dist/{chunk-DFYPQ52O.js → chunk-U7CSWQAE.js} +8 -8
- package/dist/{chunk-WCCCW4KD.js → chunk-U7FC5J6J.js} +6 -6
- package/dist/{chunk-W6HCXQBH.js → chunk-UG2T7LMX.js} +4 -4
- package/dist/{chunk-JNWXHPZG.js → chunk-UPGIQXUY.js} +2 -2
- package/dist/{chunk-WZTFU6FJ.js → chunk-UUSOIPM2.js} +2 -2
- package/dist/{chunk-7P24I5OL.js → chunk-UVVVKPSH.js} +2 -2
- package/dist/{chunk-V4DDHF7S.js → chunk-V6U75PIG.js} +3 -3
- package/dist/{chunk-BN4CKDFU.js → chunk-VAWYYETZ.js} +23 -23
- package/dist/chunk-VFS52GGI.js +2 -0
- package/dist/chunk-VFS52GGI.js.map +1 -0
- package/dist/{chunk-DT6RNLCP.js → chunk-W26KFY35.js} +2 -2
- package/dist/{chunk-OPMMD25Z.js → chunk-WDZ47ZTX.js} +5 -5
- package/dist/chunk-WEEVXQIM.js +45 -0
- package/dist/chunk-WEEVXQIM.js.map +1 -0
- package/dist/{chunk-IZJOZJDL.js → chunk-WEM6XJ7Z.js} +2 -2
- package/dist/{chunk-5HBMI2DO.js → chunk-WKNOKJA3.js} +2 -2
- package/dist/{chunk-WTB4DDZP.js → chunk-WL2EZDSD.js} +6 -6
- package/dist/{chunk-QTIKGWU4.js → chunk-XE6GYGWS.js} +4 -4
- package/dist/{chunk-PYPNGKRD.js → chunk-Y3CKZ7SH.js} +5 -5
- package/dist/{chunk-VRIAWF3A.js → chunk-YA2CG4YL.js} +2 -2
- package/dist/{chunk-AXKZBRZK.js → chunk-YA2QGLUL.js} +2 -2
- package/dist/{chunk-35DUHYPC.js → chunk-YFGFNFVW.js} +3 -3
- package/dist/{chunk-6NKILKS6.js → chunk-YFKKMDJL.js} +2 -2
- package/dist/chunk-YHVXYOL6.js +80 -0
- package/dist/chunk-YHVXYOL6.js.map +1 -0
- package/dist/{chunk-CQ5CH3SB.js → chunk-YUFDC6RW.js} +2 -2
- package/dist/{chunk-H5UA5JW4.js → chunk-ZESSUMCO.js} +3 -3
- package/dist/{chunk-N44PNGDS.js → chunk-ZFMM2NLA.js} +2 -2
- package/dist/{chunk-3LWAAK3J.js → chunk-ZGNWDYSC.js} +6 -6
- package/dist/{chunk-TU24Y4HN.js → chunk-ZSYT5H6U.js} +2 -2
- package/dist/components/accordion/accordion.js +2 -2
- package/dist/components/accordion/index.js +2 -2
- package/dist/components/advanced-group/advanced-group.js +6 -6
- package/dist/components/advanced-group/index.js +6 -6
- package/dist/components/alert/alert.js +2 -2
- package/dist/components/alert/index.js +2 -2
- package/dist/components/alert-dialog/alert-dialog.js +3 -3
- package/dist/components/alert-dialog/index.js +3 -3
- package/dist/components/ambient-field/ambient-field.js +2 -2
- package/dist/components/ambient-field/index.js +2 -2
- package/dist/components/app-shell/app-shell.js +4 -4
- package/dist/components/app-shell/index.js +4 -4
- package/dist/components/app-sidebar/app-sidebar.js +12 -12
- package/dist/components/app-sidebar/index.js +12 -12
- package/dist/components/attribution-panel/attribution-panel.js +7 -7
- package/dist/components/attribution-panel/attributions.generated.js +1 -1
- package/dist/components/attribution-panel/index.js +7 -7
- package/dist/components/avatar/avatar.js +2 -2
- package/dist/components/avatar/index.js +2 -2
- package/dist/components/badge/badge.js +2 -2
- package/dist/components/badge/index.js +2 -2
- package/dist/components/bento-grid/bento-grid.js +3 -3
- package/dist/components/bento-grid/index.js +3 -3
- package/dist/components/bounded-number/bounded-number.js +9 -9
- package/dist/components/bounded-number/index.js +9 -9
- package/dist/components/breadcrumb/breadcrumb.js +4 -4
- package/dist/components/breadcrumb/index.js +4 -4
- package/dist/components/button/button.js +2 -2
- package/dist/components/button/index.js +2 -2
- package/dist/components/button-group/button-group.js +3 -3
- package/dist/components/button-group/index.js +3 -3
- package/dist/components/calendar/calendar.js +3 -3
- package/dist/components/calendar/index.js +3 -3
- package/dist/components/card/card.js +2 -2
- package/dist/components/card/index.js +2 -2
- package/dist/components/carousel/carousel.js +5 -5
- package/dist/components/carousel/index.js +5 -5
- package/dist/components/change-review/change-review.js +10 -10
- package/dist/components/change-review/index.js +10 -10
- package/dist/components/checkbox/checkbox.js +2 -2
- package/dist/components/checkbox/index.js +2 -2
- package/dist/components/collapsible/collapsible.js +2 -2
- package/dist/components/collapsible/index.js +2 -2
- package/dist/components/collapsible-panel/index.js +2 -2
- package/dist/components/collapsible-panel/use-collapsible-panel.js +2 -2
- package/dist/components/color-picker/color-picker.js +5 -5
- package/dist/components/color-picker/index.js +5 -5
- package/dist/components/combobox/combobox.js +10 -10
- package/dist/components/combobox/index.js +10 -10
- package/dist/components/command/command.js +7 -7
- package/dist/components/command/index.js +7 -7
- package/dist/components/command-chip/command-chip.js +3 -3
- package/dist/components/command-chip/index.js +3 -3
- package/dist/components/command-trigger/command-trigger.js +3 -3
- package/dist/components/command-trigger/index.js +3 -3
- package/dist/components/confirm-dialog/confirm-dialog.js +7 -7
- package/dist/components/confirm-dialog/index.js +7 -7
- package/dist/components/context-menu/context-menu.js +2 -2
- package/dist/components/context-menu/index.js +2 -2
- package/dist/components/context-rail/context-rail.js +14 -14
- package/dist/components/context-rail/index.js +14 -14
- package/dist/components/copyable-value/copyable-value.js +5 -5
- package/dist/components/copyable-value/index.js +5 -5
- package/dist/components/date-picker/date-picker.js +7 -7
- package/dist/components/date-picker/index.js +7 -7
- package/dist/components/date-range-picker/date-range-picker.js +7 -7
- package/dist/components/date-range-picker/index.js +7 -7
- package/dist/components/descriptions/descriptions.js +2 -2
- package/dist/components/descriptions/index.js +2 -2
- package/dist/components/dialog/dialog.js +6 -6
- package/dist/components/dialog/index.js +6 -6
- package/dist/components/drafting-marks/drafting-marks.js +14 -0
- package/dist/components/drafting-marks/drafting-marks.js.map +1 -0
- package/dist/components/drafting-marks/index.js +15 -0
- package/dist/components/drafting-marks/index.js.map +1 -0
- package/dist/components/drawer/drawer.js +2 -2
- package/dist/components/drawer/index.js +2 -2
- package/dist/components/dropdown-menu/dropdown-menu.js +2 -2
- package/dist/components/dropdown-menu/index.js +2 -2
- package/dist/components/empty-state/empty-state.js +6 -6
- package/dist/components/empty-state/index.js +6 -6
- package/dist/components/error-state/error-state.js +6 -6
- package/dist/components/error-state/index.js +6 -6
- package/dist/components/expand-dialog/expand-dialog.js +7 -7
- package/dist/components/expand-dialog/index.js +7 -7
- package/dist/components/field/field.js +4 -4
- package/dist/components/field/index.js +4 -4
- package/dist/components/field-row/field-row.js +3 -3
- package/dist/components/field-row/index.js +3 -3
- package/dist/components/file-upload/file-upload.js +6 -6
- package/dist/components/file-upload/index.js +6 -6
- package/dist/components/form/form.js +3 -3
- package/dist/components/hover-card/hover-card.js +2 -2
- package/dist/components/hover-card/index.js +2 -2
- package/dist/components/icon-button/icon-button.js +4 -4
- package/dist/components/icon-button/index.js +4 -4
- package/dist/components/input/index.js +2 -2
- package/dist/components/input/input.js +2 -2
- package/dist/components/input-group/index.js +5 -5
- package/dist/components/input-group/input-group.js +5 -5
- package/dist/components/input-otp/index.js +2 -2
- package/dist/components/input-otp/input-otp.js +2 -2
- package/dist/components/install-tabs/index.js +8 -8
- package/dist/components/install-tabs/install-tabs.js +8 -8
- package/dist/components/integration-matrix/index.js +7 -7
- package/dist/components/integration-matrix/integration-matrix.js +7 -7
- package/dist/components/kbd/index.js +2 -2
- package/dist/components/kbd/kbd.js +2 -2
- package/dist/components/key-value-editor/index.js +6 -6
- package/dist/components/key-value-editor/key-value-editor.js +6 -6
- package/dist/components/keyboard-shortcuts/index.js +10 -10
- package/dist/components/keyboard-shortcuts/keyboard-shortcuts.js +10 -10
- package/dist/components/label/index.js +2 -2
- package/dist/components/label/label.js +2 -2
- package/dist/components/link-preview/index.js +3 -3
- package/dist/components/link-preview/link-preview.js +3 -3
- package/dist/components/list-editor/index.js +6 -6
- package/dist/components/list-editor/list-editor.js +6 -6
- package/dist/components/loading-state/index.js +6 -6
- package/dist/components/loading-state/loading-state.js +6 -6
- package/dist/components/locale-provider/index.js +2 -2
- package/dist/components/locale-provider/locale-provider.js +2 -2
- package/dist/components/locale-provider/messages.js +1 -1
- package/dist/components/match-highlight/index.js +2 -2
- package/dist/components/match-highlight/match-highlight.js +2 -2
- package/dist/components/mention-input/index.js +6 -6
- package/dist/components/mention-input/mention-input.js +6 -6
- package/dist/components/menubar/index.js +2 -2
- package/dist/components/menubar/menubar.js +2 -2
- package/dist/components/meter/index.js +2 -2
- package/dist/components/meter/meter.js +2 -2
- package/dist/components/metric-card/index.js +8 -8
- package/dist/components/metric-card/metric-card.js +8 -8
- package/dist/components/model-picker/index.js +11 -11
- package/dist/components/model-picker/model-picker.js +11 -11
- package/dist/components/nav-main/index.js +13 -13
- package/dist/components/nav-main/nav-main.js +13 -13
- package/dist/components/nav-notifications/index.js +7 -7
- package/dist/components/nav-notifications/nav-notifications.js +7 -7
- package/dist/components/nav-user/index.js +14 -14
- package/dist/components/nav-user/nav-user.js +14 -14
- package/dist/components/navigation-menu/index.js +2 -2
- package/dist/components/navigation-menu/navigation-menu.js +2 -2
- package/dist/components/number-input/index.js +8 -8
- package/dist/components/number-input/number-input.js +8 -8
- package/dist/components/page-shell/index.js +2 -2
- package/dist/components/page-shell/page-shell.js +2 -2
- package/dist/components/pagination/index.js +5 -5
- package/dist/components/pagination/pagination.js +5 -5
- package/dist/components/popover/index.js +2 -2
- package/dist/components/popover/popover.js +2 -2
- package/dist/components/progress/index.js +2 -2
- package/dist/components/progress/progress.js +2 -2
- package/dist/components/radio-group/index.js +2 -2
- package/dist/components/radio-group/radio-group.js +2 -2
- package/dist/components/rating/index.js +2 -2
- package/dist/components/rating/rating.js +2 -2
- package/dist/components/resizable/index.js +2 -2
- package/dist/components/resizable/resizable.js +2 -2
- package/dist/components/reveal/index.js +2 -2
- package/dist/components/reveal/reveal.js +2 -2
- package/dist/components/revision-timeline/index.js +4 -4
- package/dist/components/revision-timeline/revision-timeline.js +4 -4
- package/dist/components/schema-form/index.js +29 -29
- package/dist/components/schema-form/schema-form.js +25 -25
- package/dist/components/scroll-area/index.js +2 -2
- package/dist/components/scroll-area/scroll-area.js +2 -2
- package/dist/components/section-header/index.js +2 -2
- package/dist/components/section-header/section-header.js +2 -2
- package/dist/components/segmented-field/index.js +5 -5
- package/dist/components/segmented-field/segmented-field.js +5 -5
- package/dist/components/select/index.js +2 -2
- package/dist/components/select/select.js +2 -2
- package/dist/components/separator/index.js +2 -2
- package/dist/components/separator/separator.js +2 -2
- package/dist/components/sheet/index.js +4 -4
- package/dist/components/sheet/sheet.js +4 -4
- package/dist/components/side-dock/index.js +6 -6
- package/dist/components/side-dock/side-dock.js +6 -6
- package/dist/components/sidebar/index.js +11 -11
- package/dist/components/sidebar/sidebar.js +11 -11
- package/dist/components/skeleton/index.js +2 -2
- package/dist/components/skeleton/skeleton.js +2 -2
- package/dist/components/skip-link/index.js +2 -2
- package/dist/components/skip-link/skip-link.js +2 -2
- package/dist/components/slider/index.js +2 -2
- package/dist/components/slider/slider.js +2 -2
- package/dist/components/slider-number/index.js +10 -10
- package/dist/components/slider-number/slider-number.js +10 -10
- package/dist/components/sonner/index.js +2 -2
- package/dist/components/sonner/sonner.js +2 -2
- package/dist/components/spec-playground/index.js +6 -6
- package/dist/components/spec-playground/spec-playground.js +6 -6
- package/dist/components/spinner/index.js +4 -4
- package/dist/components/spinner/spinner.js +4 -4
- package/dist/components/split-panel/index.js +2 -2
- package/dist/components/split-panel/split-panel.js +2 -2
- package/dist/components/state-panel/index.js +5 -5
- package/dist/components/state-panel/state-panel.js +5 -5
- package/dist/components/status-badge/index.js +3 -3
- package/dist/components/status-badge/status-badge.js +3 -3
- package/dist/components/surface-tour/index.js +8 -8
- package/dist/components/surface-tour/surface-tour.js +8 -8
- package/dist/components/switch/index.js +2 -2
- package/dist/components/switch/switch.js +2 -2
- package/dist/components/table/index.js +4 -4
- package/dist/components/table/table.js +4 -4
- package/dist/components/tabs/index.js +2 -2
- package/dist/components/tabs/tabs.js +2 -2
- package/dist/components/tag-input/index.js +7 -7
- package/dist/components/tag-input/tag-input.js +7 -7
- package/dist/components/team-switcher/index.js +13 -13
- package/dist/components/team-switcher/team-switcher.js +13 -13
- package/dist/components/textarea/index.js +2 -2
- package/dist/components/textarea/textarea.js +2 -2
- package/dist/components/theme-family-switch/index.js +5 -5
- package/dist/components/theme-family-switch/theme-family-switch.js +5 -5
- package/dist/components/theme-switcher/index.js +7 -7
- package/dist/components/theme-switcher/theme-switcher.js +7 -7
- package/dist/components/timeline/index.js +4 -4
- package/dist/components/timeline/timeline.js +4 -4
- package/dist/components/toggle/index.js +2 -2
- package/dist/components/toggle/toggle.js +2 -2
- package/dist/components/toggle-group/index.js +3 -3
- package/dist/components/toggle-group/toggle-group.js +3 -3
- package/dist/components/token-spotlight/index.js +2 -2
- package/dist/components/token-spotlight/token-spotlight.js +2 -2
- package/dist/components/toolbar/index.js +4 -4
- package/dist/components/toolbar/toolbar.js +4 -4
- package/dist/components/tooltip/index.js +2 -2
- package/dist/components/tooltip/tooltip.js +2 -2
- package/dist/components/top-nav/index.js +2 -2
- package/dist/components/top-nav/top-nav.js +2 -2
- package/dist/components/transfer/index.js +10 -10
- package/dist/components/transfer/transfer.js +10 -10
- package/dist/components/tree/index.js +7 -7
- package/dist/components/tree/tree.js +7 -7
- package/dist/components/tree-select/index.js +11 -11
- package/dist/components/tree-select/tree-select.js +11 -11
- package/dist/components/typography/index.js +3 -3
- package/dist/components/typography/prose.js +3 -3
- package/dist/components/typography/typography.js +2 -2
- package/dist/components/view-toolbar/index.js +8 -8
- package/dist/components/view-toolbar/view-toolbar.js +8 -8
- package/dist/components/virtual-select/index.js +8 -8
- package/dist/components/virtual-select/virtual-select.js +8 -8
- package/dist/components/wizard/index.js +3 -3
- package/dist/components/wizard/wizard.js +3 -3
- package/dist/components/workspace-picker/index.js +13 -13
- package/dist/components/workspace-picker/workspace-picker.js +13 -13
- package/dist/form.js +3 -3
- package/dist/illustrations/empty-list-illustration.js +3 -3
- package/dist/illustrations/error-illustration.js +3 -3
- package/dist/illustrations/first-run-illustration.js +3 -3
- package/dist/illustrations/illustration-base.js +2 -2
- package/dist/illustrations/index.js +11 -11
- package/dist/illustrations/no-access-illustration.js +3 -3
- package/dist/illustrations/no-results-illustration.js +3 -3
- package/dist/illustrations/offline-illustration.js +3 -3
- package/dist/illustrations/success-illustration.js +3 -3
- package/dist/index.d.ts +60 -5
- package/dist/index.js +229 -217
- package/dist/lib/cn.js +8 -1
- package/dist/lib/cn.js.map +1 -1
- package/dist/lib/streamdown-translations.js +3 -3
- package/package.json +4 -4
- package/src/components/attribution-panel/attributions.generated.ts +25 -1
- package/src/components/drafting-marks/drafting-marks.stories.tsx +88 -0
- package/src/components/drafting-marks/drafting-marks.test.tsx +55 -0
- package/src/components/drafting-marks/drafting-marks.tsx +120 -0
- package/src/components/drafting-marks/index.ts +7 -0
- package/src/components/locale-provider/messages.ts +47 -0
- package/src/components/section-header/section-header.stories.tsx +23 -0
- package/src/components/section-header/section-header.tsx +26 -6
- package/src/components/sidebar/sidebar.tsx +6 -1
- package/src/components/toolbar/toolbar.tsx +4 -2
- package/src/components/tree/tree.stories.tsx +28 -0
- package/src/components/tree/tree.tsx +17 -2
- package/src/decoration.stories.tsx +153 -123
- package/src/index.ts +4 -0
- package/src/lib/cn.test.ts +29 -0
- package/src/lib/cn.ts +7 -0
- package/dist/chunk-6TJVJPNU.js.map +0 -1
- package/dist/chunk-FINAKMC6.js.map +0 -1
- package/dist/chunk-KBNWM27Q.js.map +0 -1
- package/dist/chunk-OZTM6PYF.js +0 -30
- package/dist/chunk-OZTM6PYF.js.map +0 -1
- package/dist/chunk-R3SYH7RG.js.map +0 -1
- /package/dist/{chunk-6QU7OVFA.js.map → chunk-2ZMPAD6C.js.map} +0 -0
- /package/dist/{chunk-OBEJUAN6.js.map → chunk-2ZWUTZHE.js.map} +0 -0
- /package/dist/{chunk-U4LHV5DS.js.map → chunk-36SY7TID.js.map} +0 -0
- /package/dist/{chunk-IHMFEPIT.js.map → chunk-3BZBNDRP.js.map} +0 -0
- /package/dist/{chunk-5AWXGBSH.js.map → chunk-3DJ4KY3U.js.map} +0 -0
- /package/dist/{chunk-LR2CU7HK.js.map → chunk-3ZR5PMKB.js.map} +0 -0
- /package/dist/{chunk-QDTGDYMM.js.map → chunk-47YSHR3H.js.map} +0 -0
- /package/dist/{chunk-2HXVFC4B.js.map → chunk-4B2E4OCZ.js.map} +0 -0
- /package/dist/{chunk-3B7W334A.js.map → chunk-4C4D6T5M.js.map} +0 -0
- /package/dist/{chunk-YWB7HLL7.js.map → chunk-4NSCLIES.js.map} +0 -0
- /package/dist/{chunk-UPEMEBWH.js.map → chunk-55BM2IU2.js.map} +0 -0
- /package/dist/{chunk-XMZ5LXL4.js.map → chunk-5AJQUJ5C.js.map} +0 -0
- /package/dist/{chunk-5V5J7APL.js.map → chunk-5C5W52O2.js.map} +0 -0
- /package/dist/{chunk-FDPONOOT.js.map → chunk-5MXQ5CP7.js.map} +0 -0
- /package/dist/{chunk-XZ23AFOP.js.map → chunk-64BKIIJC.js.map} +0 -0
- /package/dist/{chunk-NBMF7SIS.js.map → chunk-6HTZBBTC.js.map} +0 -0
- /package/dist/{chunk-5RC32MZH.js.map → chunk-72H7HUTH.js.map} +0 -0
- /package/dist/{chunk-URVAZW44.js.map → chunk-7KV7H2TW.js.map} +0 -0
- /package/dist/{chunk-VFF3AN4Y.js.map → chunk-7Z2RAGOA.js.map} +0 -0
- /package/dist/{chunk-LXW3GNF7.js.map → chunk-7ZJLR6RP.js.map} +0 -0
- /package/dist/{chunk-IGP5E4FC.js.map → chunk-A3TT32GE.js.map} +0 -0
- /package/dist/{chunk-LVRULYU4.js.map → chunk-A4ZSNEZD.js.map} +0 -0
- /package/dist/{chunk-BM6NGS3A.js.map → chunk-AE6LFFME.js.map} +0 -0
- /package/dist/{chunk-KTH3GWAL.js.map → chunk-AR5PJ5ZR.js.map} +0 -0
- /package/dist/{chunk-RNC4M6SG.js.map → chunk-B3DANITU.js.map} +0 -0
- /package/dist/{chunk-MGAXCPT7.js.map → chunk-B7FAQKHH.js.map} +0 -0
- /package/dist/{chunk-35ZTVB35.js.map → chunk-BGXBANS2.js.map} +0 -0
- /package/dist/{chunk-NJAGSGPF.js.map → chunk-C4FNDXBM.js.map} +0 -0
- /package/dist/{chunk-VA2OONPE.js.map → chunk-C5QBV5RE.js.map} +0 -0
- /package/dist/{chunk-LOSXINSS.js.map → chunk-C6I5I5LA.js.map} +0 -0
- /package/dist/{chunk-7WXDSTNR.js.map → chunk-CDMJSXCB.js.map} +0 -0
- /package/dist/{chunk-A47AZPCL.js.map → chunk-CEQ3YKHR.js.map} +0 -0
- /package/dist/{chunk-A43B4IT7.js.map → chunk-CGY25FAG.js.map} +0 -0
- /package/dist/{chunk-EHGIW7GA.js.map → chunk-CMP4F537.js.map} +0 -0
- /package/dist/{chunk-6OFWWIEG.js.map → chunk-D5INX2EF.js.map} +0 -0
- /package/dist/{chunk-HDS64Z5L.js.map → chunk-DIL73NE3.js.map} +0 -0
- /package/dist/{chunk-3EKVSKGJ.js.map → chunk-DXC3DTCV.js.map} +0 -0
- /package/dist/{chunk-ZNFHDBUW.js.map → chunk-EBNPVPR7.js.map} +0 -0
- /package/dist/{chunk-ZXBUOHCR.js.map → chunk-EHN5ZAHP.js.map} +0 -0
- /package/dist/{chunk-4PITSMJ3.js.map → chunk-EJ3XWNY3.js.map} +0 -0
- /package/dist/{chunk-4E73UAFA.js.map → chunk-F6FF4EJN.js.map} +0 -0
- /package/dist/{chunk-FYCCNQXQ.js.map → chunk-FC2LHNJG.js.map} +0 -0
- /package/dist/{chunk-6OPDRLMU.js.map → chunk-FCVHZDP7.js.map} +0 -0
- /package/dist/{chunk-B5QQLMEE.js.map → chunk-FG3PDWE3.js.map} +0 -0
- /package/dist/{chunk-EY2PGOG3.js.map → chunk-FKDI2T7X.js.map} +0 -0
- /package/dist/{chunk-XONGYCW3.js.map → chunk-FNRVVVXX.js.map} +0 -0
- /package/dist/{chunk-BLNXHETI.js.map → chunk-FWAFP76U.js.map} +0 -0
- /package/dist/{chunk-KUAVM54Y.js.map → chunk-FZEG2R3E.js.map} +0 -0
- /package/dist/{chunk-FKUP7QRJ.js.map → chunk-GTBVTLZJ.js.map} +0 -0
- /package/dist/{chunk-NTTSHOOK.js.map → chunk-HF6BGFUV.js.map} +0 -0
- /package/dist/{chunk-QNEOO22E.js.map → chunk-HND6FAMX.js.map} +0 -0
- /package/dist/{chunk-ECCNRCC4.js.map → chunk-HNLYRHAU.js.map} +0 -0
- /package/dist/{chunk-7G63B2B7.js.map → chunk-HUIYDDDL.js.map} +0 -0
- /package/dist/{chunk-DCI6IOJX.js.map → chunk-HUXLE3K3.js.map} +0 -0
- /package/dist/{chunk-J2P4YZLC.js.map → chunk-I3LBIBVN.js.map} +0 -0
- /package/dist/{chunk-XYACSO57.js.map → chunk-I3U52BDH.js.map} +0 -0
- /package/dist/{chunk-RRZUMIYG.js.map → chunk-IIY5JRNW.js.map} +0 -0
- /package/dist/{chunk-4GQFIJAE.js.map → chunk-IV6OYZTL.js.map} +0 -0
- /package/dist/{chunk-UQHWOPUY.js.map → chunk-IVEDMK5U.js.map} +0 -0
- /package/dist/{chunk-U26XDHMX.js.map → chunk-JQIXRCLG.js.map} +0 -0
- /package/dist/{chunk-WW3CD7AU.js.map → chunk-JU4KW7JN.js.map} +0 -0
- /package/dist/{chunk-YIVL6HWS.js.map → chunk-JVCIAEFT.js.map} +0 -0
- /package/dist/{chunk-DUF2VZON.js.map → chunk-K4V2ELUZ.js.map} +0 -0
- /package/dist/{chunk-BPXLHGWI.js.map → chunk-KK2TIWTF.js.map} +0 -0
- /package/dist/{chunk-NRSSSVWB.js.map → chunk-KPZFLTZ2.js.map} +0 -0
- /package/dist/{chunk-OYM3NHSD.js.map → chunk-KXYL3CUS.js.map} +0 -0
- /package/dist/{chunk-KOVHUAHG.js.map → chunk-L5O2O67Y.js.map} +0 -0
- /package/dist/{chunk-RM5JIUVW.js.map → chunk-LG33MONJ.js.map} +0 -0
- /package/dist/{chunk-YACASX6X.js.map → chunk-LLYLDZXC.js.map} +0 -0
- /package/dist/{chunk-RWUKMJYA.js.map → chunk-LMV225AS.js.map} +0 -0
- /package/dist/{chunk-533R5EKD.js.map → chunk-LVY7B5PD.js.map} +0 -0
- /package/dist/{chunk-OV4GQOLC.js.map → chunk-M2KNQZUL.js.map} +0 -0
- /package/dist/{chunk-7PS5MKVH.js.map → chunk-MIWFBH5S.js.map} +0 -0
- /package/dist/{chunk-XAFRTZQF.js.map → chunk-MJAIURHO.js.map} +0 -0
- /package/dist/{chunk-YL7VBHPZ.js.map → chunk-NXCOVGDU.js.map} +0 -0
- /package/dist/{chunk-WX3LWMVU.js.map → chunk-O6V65J5J.js.map} +0 -0
- /package/dist/{chunk-EJQYE4MY.js.map → chunk-OFFWEDKY.js.map} +0 -0
- /package/dist/{chunk-UXSV6RVS.js.map → chunk-OKY7ACZK.js.map} +0 -0
- /package/dist/{chunk-ITFDGFOT.js.map → chunk-ONXBRQJT.js.map} +0 -0
- /package/dist/{chunk-ULIDYFM7.js.map → chunk-OPBSVEMX.js.map} +0 -0
- /package/dist/{chunk-333EWYWL.js.map → chunk-PCNQ6NP2.js.map} +0 -0
- /package/dist/{chunk-6HGS5Z2Z.js.map → chunk-PFGQDW3H.js.map} +0 -0
- /package/dist/{chunk-K6YRTASS.js.map → chunk-PGKQZBLZ.js.map} +0 -0
- /package/dist/{chunk-57C25JYV.js.map → chunk-PQZD5W3E.js.map} +0 -0
- /package/dist/{chunk-5Z55AFOW.js.map → chunk-PT5P4AAU.js.map} +0 -0
- /package/dist/{chunk-EL3OXVOW.js.map → chunk-PUACHQRH.js.map} +0 -0
- /package/dist/{chunk-HRYH7XQP.js.map → chunk-QKZX5HDY.js.map} +0 -0
- /package/dist/{chunk-KZWC6JCI.js.map → chunk-QXXHK34V.js.map} +0 -0
- /package/dist/{chunk-JGS2IHER.js.map → chunk-R27VUCWR.js.map} +0 -0
- /package/dist/{chunk-QGX37P5L.js.map → chunk-R6CITZBB.js.map} +0 -0
- /package/dist/{chunk-X6J4KKZZ.js.map → chunk-RFTC5UVB.js.map} +0 -0
- /package/dist/{chunk-YXHHUJOZ.js.map → chunk-RHZSAWAU.js.map} +0 -0
- /package/dist/{chunk-LMO3QK7Q.js.map → chunk-S7YR3FYZ.js.map} +0 -0
- /package/dist/{chunk-GRWGNWIJ.js.map → chunk-SCCBEFVK.js.map} +0 -0
- /package/dist/{chunk-R7DDZIE3.js.map → chunk-SD5MGHIJ.js.map} +0 -0
- /package/dist/{chunk-PP7POY7C.js.map → chunk-SEGTBIR4.js.map} +0 -0
- /package/dist/{chunk-D3C3VVCX.js.map → chunk-SGBCLZQF.js.map} +0 -0
- /package/dist/{chunk-E3ES2KR6.js.map → chunk-SJHDX73F.js.map} +0 -0
- /package/dist/{chunk-EKY3A5LO.js.map → chunk-SLDJYJEG.js.map} +0 -0
- /package/dist/{chunk-KWQ6HV5Z.js.map → chunk-SQLEVIAD.js.map} +0 -0
- /package/dist/{chunk-T4JNXV75.js.map → chunk-SR3SC2Q3.js.map} +0 -0
- /package/dist/{chunk-YPLKH5H4.js.map → chunk-SSQG36MH.js.map} +0 -0
- /package/dist/{chunk-NQY3QNLR.js.map → chunk-U5BZXNHW.js.map} +0 -0
- /package/dist/{chunk-TEKBTTP2.js.map → chunk-U756JCDK.js.map} +0 -0
- /package/dist/{chunk-DFYPQ52O.js.map → chunk-U7CSWQAE.js.map} +0 -0
- /package/dist/{chunk-WCCCW4KD.js.map → chunk-U7FC5J6J.js.map} +0 -0
- /package/dist/{chunk-W6HCXQBH.js.map → chunk-UG2T7LMX.js.map} +0 -0
- /package/dist/{chunk-JNWXHPZG.js.map → chunk-UPGIQXUY.js.map} +0 -0
- /package/dist/{chunk-WZTFU6FJ.js.map → chunk-UUSOIPM2.js.map} +0 -0
- /package/dist/{chunk-7P24I5OL.js.map → chunk-UVVVKPSH.js.map} +0 -0
- /package/dist/{chunk-V4DDHF7S.js.map → chunk-V6U75PIG.js.map} +0 -0
- /package/dist/{chunk-BN4CKDFU.js.map → chunk-VAWYYETZ.js.map} +0 -0
- /package/dist/{chunk-DT6RNLCP.js.map → chunk-W26KFY35.js.map} +0 -0
- /package/dist/{chunk-OPMMD25Z.js.map → chunk-WDZ47ZTX.js.map} +0 -0
- /package/dist/{chunk-IZJOZJDL.js.map → chunk-WEM6XJ7Z.js.map} +0 -0
- /package/dist/{chunk-5HBMI2DO.js.map → chunk-WKNOKJA3.js.map} +0 -0
- /package/dist/{chunk-WTB4DDZP.js.map → chunk-WL2EZDSD.js.map} +0 -0
- /package/dist/{chunk-QTIKGWU4.js.map → chunk-XE6GYGWS.js.map} +0 -0
- /package/dist/{chunk-PYPNGKRD.js.map → chunk-Y3CKZ7SH.js.map} +0 -0
- /package/dist/{chunk-VRIAWF3A.js.map → chunk-YA2CG4YL.js.map} +0 -0
- /package/dist/{chunk-AXKZBRZK.js.map → chunk-YA2QGLUL.js.map} +0 -0
- /package/dist/{chunk-35DUHYPC.js.map → chunk-YFGFNFVW.js.map} +0 -0
- /package/dist/{chunk-6NKILKS6.js.map → chunk-YFKKMDJL.js.map} +0 -0
- /package/dist/{chunk-CQ5CH3SB.js.map → chunk-YUFDC6RW.js.map} +0 -0
- /package/dist/{chunk-H5UA5JW4.js.map → chunk-ZESSUMCO.js.map} +0 -0
- /package/dist/{chunk-N44PNGDS.js.map → chunk-ZFMM2NLA.js.map} +0 -0
- /package/dist/{chunk-3LWAAK3J.js.map → chunk-ZGNWDYSC.js.map} +0 -0
- /package/dist/{chunk-TU24Y4HN.js.map → chunk-ZSYT5H6U.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/locale-provider/messages.ts"],"sourcesContent":["\"use client\";\n\n/**\n * ICU cardinal-plural category, per `Intl.PluralRules` (\"zero\" | \"one\" | \"two\"\n * | \"few\" | \"many\" | \"other\"). Locales vary in which categories they use —\n * English has only \"one\"/\"other\"; Polish and Russian also use \"few\"/\"many\" —\n * so a `PluralMessage` may omit any category it doesn't need. `\"other\"` is the\n * universal fallback every locale defines.\n */\nexport type PluralCategory = Intl.LDMLPluralRule;\n\n/**\n * A per-count message: one string per plural category, selected at render\n * time via `Intl.PluralRules(locale).select(count)`. Each string still\n * supports the same `{name}`-style interpolation as a plain message.\n * Note: when passed to `t()`, `count` in `vars` must be a number, not a\n * numeric string, to select the correct plural category.\n */\nexport type PluralMessage = Partial<Record<PluralCategory, string>>;\n\n/** A single message value: a plain string, or a plural-form map. */\nexport type MessageValue = string | PluralMessage;\n\n/**\n * Shipped English (en-US) default microcopy bundle.\n *\n * Keys are intentionally terse, semantic, and framework-agnostic so they\n * translate cleanly into any target locale. Keep this list small and real —\n * only add a key here when a component actually needs it.\n */\nexport const DEFAULT_MESSAGES: Record<string, MessageValue> = {\n // ── Generic (shared across packages — reuse these before minting a new key) ──\n close: \"Close\",\n copy: \"Copy\",\n clear: \"Clear\",\n previous: \"Previous\",\n next: \"Next\",\n previousSlide: \"Previous slide\",\n nextSlide: \"Next slide\",\n noResults: \"No results.\",\n noRows: \"No rows.\",\n loading: \"Loading…\",\n more: \"More\",\n selectAll: \"Select all\",\n // Cardinal-plural example (#19) — a shared \"N item(s) selected\" microcopy\n // any multi-select surface can reuse via `t(\"itemsSelected\", { count })`.\n // Demonstrates the plural-form shape: pick the primitive over inventing a\n // near-duplicate flat string per component.\n itemsSelected: { one: \"{count} item selected\", other: \"{count} items selected\" },\n\n // ── @elabs-ai/components-ui ───────────────────────────────────────────────────────────────\n \"ui.metricCard.loading\": \"Loading metric…\",\n // CopyableValue. `hint` is APPENDED to the visible (compact) value, so the\n // accessible name contains what the reader sees — WCAG 2.5.3, Label in Name.\n \"ui.copyableValue.hint\": \"Copy exact value\",\n \"ui.copyableValue.copied\": \"Copied\",\n // ExpandDialog. Names the context pane beside the enlarged content, so a\n // screen-reader user can tell the two scrollable regions apart.\n \"ui.expandDialog.detail\": \"Details\",\n // AttributionPanel. `required` labels a notice a licence obliges us to show —\n // it is the WORD, not a colour, so the distinction survives greyscale (1.4.1).\n \"ui.attributionPanel.label\": \"Third-party attributions\",\n \"ui.attributionPanel.required\": \"Required\",\n \"ui.attributionPanel.empty\": \"No attributions match this filter.\",\n // ModelPicker. `refreshFailed` sits ABOVE a list that still works; `loadFailed`\n // replaces the list. The distinction is load-bearing — see modelPickerBody.\n \"ui.modelPicker.label\": \"Choose a target\",\n \"ui.modelPicker.searchPlaceholder\": \"Search…\",\n \"ui.modelPicker.refreshFailed\": \"Couldn't refresh the list\",\n \"ui.modelPicker.loadFailed\": \"Couldn't load the list\",\n \"ui.modelPicker.nothingYet\": \"Nothing to show yet\",\n \"ui.modelPicker.retry\": \"Retry\",\n // KeyboardShortcuts (#113). `emptyFiltered` keeps the user's own query in the\n // sentence so the empty state says WHY it is empty, not merely that it is.\n \"ui.keyboardShortcuts.searchPlaceholder\": \"Search shortcuts…\",\n \"ui.keyboardShortcuts.emptyTitle\": \"No shortcuts found\",\n \"ui.keyboardShortcuts.emptyFiltered\": \"No shortcuts match “{query}”.\",\n \"ui.keyboardShortcuts.empty\": \"No shortcuts to show.\",\n // WorkspacePicker (#111). It composes ModelPicker, so it carries its OWN\n // label/search strings rather than inheriting the generic \"Choose a target\".\n // `current` is appended into the row's meta so the in-force workspace reaches\n // the option's accessible name as a WORD, not only a check glyph (1.4.1).\n \"ui.workspacePicker.label\": \"Choose a workspace\",\n \"ui.workspacePicker.placeholder\": \"No workspace selected\",\n \"ui.workspacePicker.recent\": \"Recent workspaces\",\n \"ui.workspacePicker.searchPlaceholder\": \"Search workspaces…\",\n \"ui.workspacePicker.current\": \"Current\",\n \"ui.workspacePicker.pathLabel\": \"Workspace path\",\n \"ui.workspacePicker.pathPlaceholder\": \"/path/to/project…\",\n \"ui.workspacePicker.openPath\": \"Open\",\n // ViewToolbar (#331). `removeFilter` deliberately WRAPS the visible chip text\n // so the accessible name contains it (WCAG 2.5.3 Label in Name).\n \"ui.viewToolbar.about\": \"About this view\",\n \"ui.viewToolbar.activeFilters\": \"Active filters\",\n \"ui.viewToolbar.clearAll\": \"Clear all\",\n \"ui.viewToolbar.countOfTotal\": \"{count} of {total}\",\n \"ui.viewToolbar.removeFilter\": \"Remove filter: {label}\",\n // Combobox `allowCustomValue` mode (#359) — `{value}` interpolates the\n // currently typed, non-matching search text.\n \"ui.combobox.useCustomValue\": 'Use \"{value}\"',\n \"ui.combobox.emptyAllowCustom\": \"No matches. Type to add a custom value.\",\n // Form kit (#370–#374).\n \"ui.boundedNumber.emptyLabel\": \"No limit\",\n \"ui.keyValueEditor.addRow\": \"Add row\",\n \"ui.keyValueEditor.keyLabel\": \"Key {n}\",\n \"ui.keyValueEditor.valueLabel\": \"Value {n}\",\n \"ui.keyValueEditor.removeRow\": \"Remove row {n}\",\n \"ui.keyValueEditor.reveal\": \"Reveal value {n}\",\n \"ui.keyValueEditor.hide\": \"Hide value {n}\",\n \"ui.keyValueEditor.empty\": \"No entries yet.\",\n \"ui.listEditor.addItem\": \"Add item\",\n \"ui.listEditor.itemLabel\": \"Item {n}\",\n \"ui.listEditor.removeItem\": \"Remove item {n}\",\n \"ui.listEditor.moveUp\": \"Move item {n} up\",\n \"ui.listEditor.moveDown\": \"Move item {n} down\",\n \"ui.listEditor.empty\": \"No items yet.\",\n \"ui.sliderNumber.reset\": \"Reset\",\n // MentionInput (#368). The listbox lives in a portal with no visible label of\n // its own, so this IS its accessible name. The empty state deliberately\n // reuses the generic `noResults` key rather than minting a near-duplicate.\n \"ui.mentionInput.listLabel\": \"Mention suggestions\",\n // ConfirmDialog's fallback action labels. A real confirmation replaces\n // `confirmLabel` with the CONSEQUENCE (\"Delete skill\"); this generic default\n // exists so the component is never unlabelled.\n \"ui.confirmDialog.confirm\": \"Confirm\",\n \"ui.confirmDialog.cancel\": \"Cancel\",\n \"ui.advancedGroup.title\": \"Advanced\",\n \"ui.advancedGroup.changed\": \"{count} changed\",\n // SchemaForm — the spec-driven config-form renderer (issue #22).\n \"ui.schemaForm.selectPlaceholder\": \"Select…\",\n \"ui.schemaForm.label\": \"Form\",\n \"ui.schemaForm.submit\": \"Submit\",\n \"ui.schemaForm.submitting\": \"Submitting…\",\n \"ui.schemaForm.submitted\": \"Submitted\",\n // SchemaFormTestAction — a form/group-level \"Test connection\" affordance\n // (issue #22 maintainer ruling, 2026-09-01), independent of field validity\n // and never gating submit.\n \"ui.schemaForm.testAction.label\": \"Test connection\",\n \"ui.schemaForm.testAction.pending\": \"Testing…\",\n \"ui.schemaForm.testAction.success\": \"Connected\",\n \"ui.schemaForm.testAction.failure\": \"Test failed\",\n // Pagination's ellipsis (sr-only — the visible glyph is decorative).\n \"ui.breadcrumb.label\": \"breadcrumb\",\n \"ui.pagination.label\": \"pagination\",\n \"ui.pagination.morePages\": \"More pages\",\n // Pagination's prev/next links — the ACCESSIBLE NAME (`aria-label`), distinct\n // from the visible `previous`/`next` text below it: an `aria-label` overrides\n // visible text content as the accessible name, so leaving these hardcoded in\n // English meant a non-English `LocaleProvider` translated the visible label\n // but a screen-reader user still heard English (#12/#53 review, P2).\n \"ui.pagination.previous\": \"Go to previous page\",\n \"ui.pagination.next\": \"Go to next page\",\n // Sidebar's mobile Sheet title (sr-only header — the sheet itself has no\n // visible chrome, so this is only ever read by assistive tech).\n \"ui.sidebar.title\": \"Sidebar\",\n // ContextRail's switcher count phrase (composed into the accessible name,\n // e.g. \"Sources 3 items\") and its default empty-state copy.\n \"ui.contextRail.sectionCount\": { one: \"{count} item\", other: \"{count} items\" },\n \"ui.contextRail.empty\": \"No sections\",\n // SideDock's resize handle — its sr-only label and its live width readout.\n \"ui.sideDock.resize\": \"Resize\",\n \"ui.sideDock.widthValue\": { one: \"{size} pixel\", other: \"{size} pixels\" },\n // Tree's error row — shared by the virtualized and non-virtualized branches.\n \"ui.tree.failedToLoad\": \"Failed to load\",\n // ThemeSwitcher's \"follow the OS\" option, in both dropdown and toggle modes.\n \"ui.themeSwitcher.system\": \"System\",\n // Group labels + scheme names in the family layout (ADR 0036).\n \"ui.themeSwitcher.theme\": \"Theme\",\n \"ui.themeSwitcher.mode\": \"Mode\",\n \"ui.themeSwitcher.light\": \"Light\",\n \"ui.themeSwitcher.dark\": \"Dark\",\n \"ui.navNotifications.label\": \"Notifications\",\n // NavUser — the standard sidebar footer: account menu group label and its\n // two default actions.\n \"ui.navUser.label\": \"Account\",\n \"ui.navUser.settings\": \"Settings\",\n \"ui.navUser.signOut\": \"Sign out\",\n \"ui.teamSwitcher.label\": \"Teams\",\n \"ui.teamSwitcher.addTeam\": \"Add team\",\n // Table's own scroll wrapper (#366). Rendered ONLY when the wrapper actually\n // overflows, so it is never announced for a table that fits — see\n // `packages/ui/src/components/table/table.tsx`. Deliberately a `ui.*`\n // sibling of `data.table.scrollRegion` rather than a shared cross-package\n // key: `Table` is a `@elabs-ai/components-ui` component and each package\n // keeps its own namespace even where the English string coincides (compare\n // `viewer.content` vs this), so a translator can phrase either\n // independently and neither package depends on a string owned by another.\n \"ui.table.scrollRegion\": \"Table contents, scrollable\",\n // NumberInput's step buttons (#4 i18n sweep).\n \"ui.numberInput.decrease\": \"Decrease\",\n \"ui.numberInput.increase\": \"Increase\",\n // Combobox/VirtualSelect/TreeSelect each keep their own placeholder pair\n // (English text coincides, but a translator may phrase a search box\n // differently per surface — same rationale as `ui.table.scrollRegion`).\n \"ui.combobox.placeholder\": \"Select…\",\n \"ui.combobox.searchPlaceholder\": \"Search…\",\n \"ui.virtualSelect.placeholder\": \"Select…\",\n \"ui.virtualSelect.searchPlaceholder\": \"Search…\",\n \"ui.treeSelect.placeholder\": \"Select…\",\n \"ui.treeSelect.moreSelected\": \"and {count} more selected\",\n \"ui.fileUpload.selectedFiles\": \"Selected files\",\n \"ui.fileUpload.dragDropHere\": \"Drag & drop files here\",\n \"ui.fileUpload.browseFiles\": \"Browse files\",\n // Sidebar's mobile Sheet description (sr-only) and the collapse/expand\n // trigger's shared name (SidebarTrigger's sr-only text + SidebarRail's\n // aria-label/title).\n \"ui.sidebar.mobileDescription\": \"Displays the mobile sidebar.\",\n \"ui.sidebar.toggle\": \"Toggle Sidebar\",\n \"ui.revisionTimeline.label\": \"Revisions\",\n \"ui.tree.retry\": \"Retry\",\n \"ui.tree.retryLoadingChildren\": \"Retry loading children\",\n // Spinner's bare default label — kept WITHOUT an ellipsis (unlike the\n // generic `loading` key) to stay byte-identical to its pre-i18n default.\n \"ui.spinner.label\": \"Loading\",\n \"ui.statePanel.errorTitle\": \"Something went wrong\",\n \"ui.statePanel.errorDescription\": \"An unexpected error occurred. Please try again.\",\n \"ui.statePanel.errorEyebrow\": \"Error\",\n \"ui.carousel.label\": \"Carousel\",\n // Transfer (#4 i18n sweep). `panelFallback`/`itemsFallback` back the two\n // spots where the panel title isn't a plain string (a ReactNode) and the\n // sr-only text falls back to a generic word instead.\n \"ui.transfer.selectAllIn\": \"Select all in {title}\",\n \"ui.transfer.panelFallback\": \"panel\",\n \"ui.transfer.searchIn\": \"Search {title}\",\n \"ui.transfer.itemsFallback\": \"items\",\n \"ui.transfer.searchPlaceholder\": \"Search…\",\n \"ui.transfer.empty\": \"No items\",\n \"ui.transfer.defaultSourceTitle\": \"Source\",\n \"ui.transfer.defaultTargetTitle\": \"Target\",\n \"ui.transfer.movedToTarget\": {\n one: \"{count} item moved to the target list.\",\n other: \"{count} items moved to the target list.\",\n },\n \"ui.transfer.movedToSource\": {\n one: \"{count} item moved to the source list.\",\n other: \"{count} items moved to the source list.\",\n },\n \"ui.transfer.moveControls\": \"Move controls\",\n \"ui.transfer.moveSelectedRight\": \"Move selected right\",\n \"ui.transfer.moveAllRight\": \"Move all right\",\n \"ui.transfer.moveSelectedLeft\": \"Move selected left\",\n \"ui.transfer.moveAllLeft\": \"Move all left\",\n // ChangeReview (#4 i18n sweep).\n \"ui.changeReview.heading\": \"Review changes\",\n \"ui.changeReview.approvedCount\": \"{approved} of {total} approved\",\n \"ui.changeReview.rejectAll\": \"Reject all\",\n \"ui.changeReview.rejectAllLabel\": \"Reject all changes\",\n \"ui.changeReview.approveAll\": \"Approve all\",\n \"ui.changeReview.approveAllLabel\": \"Approve all changes\",\n \"ui.changeReview.provenanceLabel\": \"Change provenance\",\n \"ui.changeReview.emptyTitle\": \"No changes to review\",\n \"ui.changeReview.emptyDescription\":\n \"When an agent proposes edits, they'll appear here for your approval.\",\n \"ui.changeReview.statusAdded\": \"added\",\n \"ui.changeReview.statusRemoved\": \"removed\",\n \"ui.changeReview.statusModified\": \"modified\",\n \"ui.changeReview.phaseBefore\": \"Before\",\n \"ui.changeReview.phaseAfter\": \"After\",\n \"ui.changeReview.checkPassed\": \"Passed\",\n \"ui.changeReview.checkFailed\": \"Failed\",\n \"ui.changeReview.showDetail\": \"Show detail\",\n \"ui.changeReview.hideDetail\": \"Hide detail\",\n \"ui.changeReview.rejectHunk\": \"Reject hunk: {title}\",\n \"ui.changeReview.approveHunk\": \"Approve hunk: {title}\",\n \"ui.changeReview.changeType\": \"Change type: {status}\",\n \"ui.changeReview.beforePrefix\": \"Before: \",\n \"ui.changeReview.afterPrefix\": \"After: \",\n \"ui.changeReview.approvedBadge\": \"Approved\",\n \"ui.navNotifications.trigger\": \"Open notifications\",\n \"ui.colorPicker.pickColor\": \"Pick color\",\n \"ui.colorPicker.none\": \"None\",\n \"ui.colorPicker.swatches\": \"Color swatches\",\n \"ui.colorPicker.customHexLabel\": \"Custom hex\",\n \"ui.colorPicker.notThemeAware\": \"(not theme-aware)\",\n \"ui.colorPicker.customHex\": \"Custom hex color\",\n\n // ── @elabs-ai/components-data ─────────────────────────────────────────────────────────────\n // The scroll region's accessible name is rendered ONLY when the table actually\n // overflows its container, so it is never announced for a table that fits.\n \"data.table.scrollRegion\": \"Table contents, scrollable\",\n \"data.table.loading\": \"Loading table data…\",\n // Fallback name for a row's activation control when the row's first cell holds\n // no primitive value to name it after (see `rowActionLabel`).\n \"data.table.rowAction\": \"Activate row\",\n // createSelectionColumn (#11) — the header select-all checkbox and each row's\n // own checkbox. Kept table-scoped (not the generic `selectAll` key) so a\n // translator can phrase \"rows\" distinctly from other bulk-select surfaces.\n \"data.table.selectAllRows\": \"Select all rows\",\n // `selectRowNamed` names each row's checkbox from its own first data column\n // (#11 I4) so screen-reader users hear \"Select Alpha\", not `selectRow`'s\n // identical generic label repeated on every row; `selectRow` stays the\n // fallback when no data column value is derivable.\n \"data.table.selectRowNamed\": \"Select {name}\",\n \"data.table.selectRow\": \"Select row\",\n // Column resizing (#12) — the accessible name for the WAI-ARIA\n // separator-as-slider resize handle at the end of a resizable header cell.\n \"data.table.resizeColumn\": \"Resize column, {name}\",\n // #51 — the handle's accessible VALUE, paired with aria-valuenow (which\n // stays a plain number for AT/TanStack). A bare number reads as a\n // dimensionless ordinal; the unit makes it a size. A `PluralMessage` (PR\n // #81 review, \"Format the announced resize value for the active locale\") —\n // the call site passes both `count` (the raw number, so a locale whose\n // plural rules select something other than \"other\" for a given size is\n // reachable) and `size` (pre-formatted via `formatNumber`, so a locale\n // override renders locale-appropriate digits/grouping instead of a raw\n // Latin-digit JS number).\n \"data.table.resizeColumnValue\": { one: \"{size} pixel\", other: \"{size} pixels\" },\n // `showRanks` (RM-123). The printed number is the row's position in the DATA\n // AS SUPPLIED, not its position on screen: it travels with its row through\n // sorting, filtering and paging, so beside a sorted column it legitimately\n // reads 2, 1, 6, 4. That rule is invisible in a column headed by a bare \"#\",\n // which reads as a broken ranking — so it is said twice: `rankHeader` is the\n // column's accessible NAME (the \"#\" glyph is decorative beside it), and\n // `rankKey` is the one-line key printed above the table for everyone else.\n \"data.table.rankHeader\": \"Position in the data as supplied\",\n \"data.table.rankKey\":\n \"# is each row’s position in the data as supplied, not its position in this view — sorting never renumbers it.\",\n // Row drag-reorder (#13). `reorderHandle`/`reorderColumnHeader` name the\n // grip control and its column; the four `reorder*` announcement keys back\n // the aria-live region dnd-kit's `accessibility.announcements` renders on\n // pickup/move/drop/cancel (WCAG 4.1.3) — `position`/`total` are 1-based so\n // the announcement reads like \"3 of 8\", not a 0-based index.\n \"data.table.reorderColumnHeader\": \"Reorder\",\n \"data.table.reorderHandle\": \"Reorder {name}\",\n \"data.table.reorderPickedUp\": \"Picked up {name}.\",\n \"data.table.reorderMoved\": \"{name} moved to position {position} of {total}.\",\n \"data.table.reorderDropped\": \"{name} dropped at position {position} of {total}.\",\n \"data.table.reorderCancelled\":\n \"Reordering cancelled. {name} returned to position {position} of {total}.\",\n // #98: `@dnd-kit` renders two more AT-visible strings for this same\n // feature that this repo's source never writes — the hidden keyboard\n // usage instructions (wired to the grip via `aria-describedby`) and the\n // activator's `aria-roledescription`. Both ship a hardcoded English\n // default deep inside the library; localizing them means overriding them\n // explicitly with these two keys. The English DEFAULT below is dnd-kit's\n // own default text verbatim (`defaultScreenReaderInstructions.draggable`\n // in `@dnd-kit/core`, and `useSortable`'s `roleDescription: 'sortable'` in\n // `@dnd-kit/sortable`) — not a rewrite — so an English consumer with no\n // `LocaleProvider` override sees byte-identical output to before this\n // fix; only a `messages` override changes it.\n \"data.table.reorderInstructions\":\n \"\\n To pick up a draggable item, press the space bar.\\n While dragging, use the arrow keys to move the item.\\n Press space again to drop the item in its new position, or press escape to cancel.\\n \",\n \"data.table.reorderRoleDescription\": \"sortable\",\n \"data.facetFilter.clearFilters\": \"Clear filters\",\n \"data.columnPicker.toggleColumns\": \"Toggle columns\",\n \"data.columnPicker.label\": \"Columns\",\n \"data.searchInput.label\": \"Search\",\n \"data.searchInput.placeholder\": \"Search…\",\n \"data.searchInput.clear\": \"Clear search\",\n\n // ── @elabs-ai/components-charts ───────────────────────────────────────────────────────────\n // Shared caption for any bare chart surface's layout-shaped skeleton\n // (ChartFrame, ChartCard, AutoChart all show the same \"a chart is loading\"\n // concept — one key, reused, rather than three near-duplicate strings).\n \"charts.chart.loading\": \"Loading chart…\",\n // ChartFallback's default copy per `kind` (#304). Written for the reader of\n // the page, not the developer: the unsupported chart type name goes to a\n // dev-only console warning, never into this string.\n \"charts.chart.empty\": \"No data to display\",\n \"charts.chart.unsupported\": \"This chart can’t be displayed.\",\n \"charts.metricGrid.loading\": \"Loading metrics…\",\n // Chart drill-down (#349). The chart SVG is aria-hidden, so these names are\n // the ONLY thing AT reads for an interactive datapoint — there is no\n // consumer-side workaround if they stay English.\n \"charts.datapointLayer.label\": \"Chart data points\",\n \"charts.datapoint.label\": \"{series}, {category}: {value}\",\n \"charts.datapoint.labelNoSeries\": \"{category}: {value}\",\n // A target with no value (a tree node, a parallel-coordinates line, an empty\n // heatmap cell) drops the separator rather than announcing a dangling \":\".\n \"charts.datapoint.labelNoValue\": \"{series}, {category}\",\n \"charts.datapoint.labelNoSeriesNoValue\": \"{category}\",\n // Stands in for {category} when a target has none, so the name is never a\n // bare value or an empty string. {position} is 1-based.\n \"charts.datapoint.position\": \"Data point {position}\",\n // DumbbellChart: a target spans two values, so both ends are announced.\n \"charts.datapoint.labelRange\": \"{category}: {start} to {end}\",\n // Announced when `copyValueOnActivate` puts a datapoint's exact value on the\n // clipboard — the recovery path for a compact axis label.\n \"charts.datapoint.copied\": \"Exact value copied\",\n // chart selection — RM-073\n // Appended to a datapoint's name when a host's `selectionStates` resolves it,\n // so the selection tri-state never rides on colour/opacity alone (WCAG 1.4.1).\n // `associated` is the resting state and adds nothing.\n \"charts.datapoint.selected\": \"{label}, selected\",\n \"charts.datapoint.excluded\": \"{label}, excluded\",\n // ChartFrame's SVG/PNG export actions (RM-025). Each string is used twice —\n // as the icon button's `aria-label` (its ONLY accessible name) and as the\n // tooltip a sighted user reads — so one key serves both and they cannot\n // drift apart in translation.\n \"charts.chartFrame.exportSvg\": \"Export as SVG\",\n \"charts.chartFrame.exportPng\": \"Export as PNG\",\n \"charts.chartFrame.flipToTable\": \"Flip to table view\",\n \"charts.chartFrame.showChart\": \"Show chart\",\n \"charts.chartFrame.showAsTable\": \"Show as table\",\n \"charts.chartFrame.downloadCsv\": \"Download CSV\",\n \"charts.chartFrame.expandChart\": \"Expand chart\",\n \"charts.chartFrame.expand\": \"Expand\",\n \"charts.chartFrame.summary\": \"Summary\",\n \"charts.chartFrame.noDataToSummarize\": \"No data to summarize.\",\n \"charts.chartFrame.defaultTitle\": \"Chart\",\n \"charts.chartFrame.summaryDetailLabel\": \"Chart summary\",\n // ChartFrame's scrollable body (#432 round 3, WCAG 2.1.1): only set as\n // `aria-label`/`tabIndex` while the body actually overflows its box.\n \"charts.chartFrame.scrollableRegion\": \"Scrollable chart: {title}\",\n \"charts.legend.label\": \"Chart legend\",\n \"charts.gantt.timeline\": \"Timeline\",\n \"charts.gantt.dragToResizeColumn\": \"Drag to resize column\",\n \"charts.gantt.viewControls\": \"Gantt view controls\",\n \"charts.gantt.viewMode\": \"View mode\",\n \"charts.gantt.viewModeLabel\": \"View mode:\",\n \"charts.gantt.taskList\": \"Task list\",\n \"charts.gantt.taskListLabel\": \"Tasks\",\n \"charts.gantt.noTasksToDisplay\": \"No tasks to display\",\n \"charts.gantt.unitDay\": \"Day\",\n \"charts.gantt.unitWeek\": \"Week\",\n \"charts.gantt.unitMonth\": \"Month\",\n \"charts.gantt.unitQuarter\": \"Quarter\",\n \"charts.gantt.unitHour\": \"Hour\",\n \"charts.gantt.unitMinute\": \"Minute\",\n \"charts.gantt.unitSecond\": \"Second\",\n \"charts.gantt.unitMillisecond\": \"Millisecond\",\n // BulletChart (Few's bullet graph, RM-061). The SVG is aria-hidden, so this\n // sentence — built from these fragments — is the ONLY thing AT reads: it\n // states the value, its relationship to the target, and which qualitative\n // band it falls in. {value}/{target} already carry a caller-supplied name\n // via `labels` when one was given (composed before interpolation), so the\n // template itself stays name-agnostic.\n \"charts.bulletChart.noData\": \"No data\",\n \"charts.bulletChart.valueOfTarget\": \"{value} of {target} target\",\n \"charts.bulletChart.gapAbove\": \"{amount} above target\",\n \"charts.bulletChart.gapBelow\": \"{amount} below target\",\n \"charts.bulletChart.onTarget\": \"on target\",\n \"charts.bulletChart.band\": \"in band {band}\",\n \"charts.bulletChart.comparative\": \"compared to {value}\",\n // RM-075 follow-up: `container` dashboard tile's default tablist name when the tile\n // has no `title`.\n \"charts.dashboard.containerTabs\": \"Container tabs\",\n // dashboard edit — RM-078: edit-layer handles, size badge and screen-reader announcements.\n // Columns and rows are announced 1-based; the badge shows the same numbers.\n \"charts.dashboard.edit.instructions\":\n \"To pick up a tile, press Enter. Use the arrow keys to move it one cell, or four cells with Shift. Press Enter to drop it, or Escape to cancel. On a resize handle, the arrow keys resize directly.\",\n \"charts.dashboard.edit.moveTile\": \"Move {title}\",\n \"charts.dashboard.edit.resizeTile\": \"Resize {title} from {edge}\",\n \"charts.dashboard.edit.edgeTop\": \"top\",\n \"charts.dashboard.edit.edgeTopRight\": \"top-right\",\n \"charts.dashboard.edit.edgeRight\": \"right\",\n \"charts.dashboard.edit.edgeBottomRight\": \"bottom-right\",\n \"charts.dashboard.edit.edgeBottom\": \"bottom\",\n \"charts.dashboard.edit.edgeBottomLeft\": \"bottom-left\",\n \"charts.dashboard.edit.edgeLeft\": \"left\",\n \"charts.dashboard.edit.edgeTopLeft\": \"top-left\",\n \"charts.dashboard.edit.sizeBadge\": \"({x},{y}) ⤢ {w} × {h}\",\n \"charts.dashboard.edit.pickedUp\": \"Picked up {title} at column {x}, row {y}\",\n \"charts.dashboard.edit.moved\": \"Moved to column {x}, row {y}\",\n \"charts.dashboard.edit.dropped\": \"Dropped {title} at column {x}, row {y}, size {w} by {h}\",\n \"charts.dashboard.edit.rejected\": \"Cannot place here — not enough room\",\n \"charts.dashboard.edit.resizing\": \"Resizing {title}: {w} by {h}\",\n \"charts.dashboard.edit.resized\": \"Resized {title} to {w} by {h}\",\n // dashboard edit — RM-078 (follow-up 5): a clamped keyboard step (grid edge or a tile's own\n // min/max size) now announces once per key press instead of staying silent once the layout\n // stops changing; cancel (Escape, or tabbing off a resize handle mid-gesture) says which\n // gesture was cancelled and where it was restored to.\n \"charts.dashboard.edit.clampedEdge\": \"At the {edge} edge. ({x},{y}) {w} × {h}\",\n \"charts.dashboard.edit.moveCancelled\": \"Move cancelled. Restored to column {x}, row {y}\",\n \"charts.dashboard.edit.resizeCancelled\":\n \"Resize cancelled. Restored to column {x}, row {y}, size {w} by {h}\",\n // dashboard toolbar — RM-079: mode switch, undo/redo, grid settings, save/discard, shortcuts.\n \"charts.dashboard.toolbar.ariaLabel\": \"Dashboard toolbar\",\n \"charts.dashboard.toolbar.viewMode\": \"View\",\n \"charts.dashboard.toolbar.editMode\": \"Edit\",\n \"charts.dashboard.toolbar.editDisabledNarrow\": \"Editing needs a wider screen\",\n \"charts.dashboard.toolbar.undo\": \"Undo\",\n \"charts.dashboard.toolbar.redo\": \"Redo\",\n \"charts.dashboard.toolbar.add\": \"Add\",\n \"charts.dashboard.toolbar.grid\": \"Grid\",\n \"charts.dashboard.toolbar.gridSettings\": \"Grid settings\",\n \"charts.dashboard.toolbar.save\": \"Save\",\n \"charts.dashboard.toolbar.discard\": \"Discard\",\n \"charts.dashboard.toolbar.unsavedChanges\": \"Unsaved changes\",\n \"charts.dashboard.toolbar.discardTitle\": \"Discard changes?\",\n \"charts.dashboard.toolbar.discardDescription\":\n \"Your edits since the last save will be lost. This cannot be undone.\",\n \"charts.dashboard.toolbar.discardConfirm\": \"Discard changes\",\n \"charts.dashboard.toolbar.shortcuts\": \"Keyboard shortcuts\",\n \"charts.dashboard.toolbar.shortcutsDescription\":\n \"Every shortcut available while this sheet is focused.\",\n \"charts.dashboard.toolbar.shortcutsGroup\": \"Dashboard\",\n \"charts.dashboard.toolbar.shortcutUndo\": \"Undo\",\n \"charts.dashboard.toolbar.shortcutRedo\": \"Redo\",\n \"charts.dashboard.toolbar.shortcutToggleEdit\": \"Toggle edit mode\",\n \"charts.dashboard.toolbar.shortcutDelete\": \"Delete focused tiles\",\n \"charts.dashboard.toolbar.shortcutDuplicate\": \"Duplicate focused tiles\",\n \"charts.dashboard.toolbar.shortcutClearFocus\": \"Clear focus\",\n \"charts.dashboard.toolbar.shortcutSave\": \"Save\",\n // tile operations — RM-081 follow-up 1: labels for the 5 shortcuts RM-081 added\n // (dashboardShortcutDescriptors); the shortcuts sheet fell back to the raw action key\n // without these.\n \"charts.dashboard.toolbar.shortcutCopy\": \"Copy focused tiles\",\n \"charts.dashboard.toolbar.shortcutCut\": \"Cut focused tiles\",\n \"charts.dashboard.toolbar.shortcutPaste\": \"Paste tiles\",\n \"charts.dashboard.toolbar.shortcutSelectAll\": \"Select all tiles\",\n \"charts.dashboard.toolbar.shortcutContextMenu\": \"Open the focused tile’s context menu\",\n // dashboard toolbar export — RM-084: the \"Export sheet…\" menu (SVG, PNG).\n \"charts.dashboard.toolbar.export\": \"Export sheet…\",\n \"charts.dashboard.toolbar.exportSvg\": \"Export as SVG\",\n \"charts.dashboard.toolbar.exportPng\": \"Export as PNG\",\n \"charts.dashboard.grid.mode\": \"Layout mode\",\n \"charts.dashboard.grid.modeFit\": \"Fit to screen\",\n \"charts.dashboard.grid.modeFlow\": \"Flow\",\n \"charts.dashboard.grid.density\": \"Density\",\n \"charts.dashboard.grid.densityWide\": \"Wide\",\n \"charts.dashboard.grid.densityMedium\": \"Medium\",\n \"charts.dashboard.grid.densityNarrow\": \"Narrow\",\n \"charts.dashboard.grid.densityCustom\": \"Custom\",\n \"charts.dashboard.grid.columns\": \"Columns\",\n \"charts.dashboard.grid.rows\": \"Rows\",\n \"charts.dashboard.grid.rowHeight\": \"Row height\",\n \"charts.dashboard.grid.gap\": \"Gap\",\n \"charts.dashboard.grid.extendable\": \"Extend sheet\",\n \"charts.dashboard.grid.extendableDescription\":\n \"Adds 50 % more rows so it never runs out of room.\",\n // dashboard tile ops — RM-081: the tile context menu (right-click, header kebab, Shift+F10)\n // and its \"Replace with…\" submenu, plus the toast on a destructive multi-tile delete.\n \"charts.dashboard.tileOps.menuLabel\": \"Tile actions\",\n \"charts.dashboard.tileOps.duplicate\": \"Duplicate\",\n \"charts.dashboard.tileOps.replaceWith\": \"Replace with…\",\n \"charts.dashboard.tileOps.addToLibrary\": \"Add to library\",\n \"charts.dashboard.tileOps.copy\": \"Copy\",\n \"charts.dashboard.tileOps.cut\": \"Cut\",\n \"charts.dashboard.tileOps.paste\": \"Paste\",\n \"charts.dashboard.tileOps.pasteAndReplace\": \"Paste and replace\",\n \"charts.dashboard.tileOps.bringForward\": \"Bring forward\",\n \"charts.dashboard.tileOps.sendBackward\": \"Send backward\",\n \"charts.dashboard.tileOps.delete\": \"Delete\",\n \"charts.dashboard.tileOps.deletedOne\": \"Tile deleted\",\n \"charts.dashboard.tileOps.deletedMany\": \"{count} tiles deleted\",\n \"charts.dashboard.tileOps.undo\": \"Undo\",\n // tile operations — RM-081 follow-up 1: the header-kebab entry that opens the same context\n // menu, and the floating align/distribute toolbar over a multi-selection.\n \"charts.dashboard.tileOps.openTileMenu\": \"Tile actions…\",\n \"charts.dashboard.tileOps.selectionToolbarLabel\": \"Align selection\",\n \"charts.dashboard.tileOps.alignLeft\": \"Align left edges\",\n \"charts.dashboard.tileOps.alignCenterH\": \"Align horizontal centers\",\n \"charts.dashboard.tileOps.alignRight\": \"Align right edges\",\n \"charts.dashboard.tileOps.alignTop\": \"Align top edges\",\n \"charts.dashboard.tileOps.alignCenterV\": \"Align vertical centers\",\n \"charts.dashboard.tileOps.alignBottom\": \"Align bottom edges\",\n \"charts.dashboard.tileOps.distributeHorizontal\": \"Distribute horizontally\",\n \"charts.dashboard.tileOps.distributeVertical\": \"Distribute vertically\",\n // Dual-axis — RM-121\n \"charts.axis.leftScale\": \"Left scale\",\n \"charts.axis.rightScale\": \"Right scale\",\n\n // ── @elabs-ai/components-maps ─────────────────────────────────────────────────────────────\n \"maps.popup.close\": \"Close popup\",\n \"maps.marker.drag\": \"Draggable marker. Arrow keys move it, Shift for a larger step.\",\n \"maps.canvas.unavailableTitle\": \"Map unavailable\",\n \"maps.canvas.unavailableDescription\": \"This browser can’t render WebGL maps.\",\n \"maps.canvas.loading\": \"Loading map\",\n \"maps.controls.zoomIn\": \"Zoom in\",\n \"maps.controls.zoomOut\": \"Zoom out\",\n \"maps.controls.resetBearing\": \"Reset bearing to north\",\n \"maps.controls.locate\": \"Find my location\",\n \"maps.controls.locating\": \"Locating\",\n \"maps.controls.fullscreen\": \"Toggle fullscreen\",\n \"maps.controls.fit\": \"Fit the whole plan\",\n\n // ── @elabs-ai/components-flow ─────────────────────────────────────────────────────────────\n \"flow.inspectorPanel.close\": \"Close inspector\",\n \"flow.inspectorPanel.title\": \"Inspector\",\n \"flow.inspectorPanel.emptyMessage\": \"Select a node to see its details.\",\n\n // ── @elabs-ai/components-ai ───────────────────────────────────────────────────────────────\n // Namespaced `ai.<area>.<key>` so package microcopy can't collide with the\n // generic keys above, or with a future package's. See ADR 0017.\n //\n // The three attachment errors are the only @elabs-ai/components-ai strings a user reads as a\n // SYSTEM MESSAGE rather than a control label — they are the reason this bundle\n // grew beyond the generic set.\n \"ai.promptInput.errorAccept\": \"No files match the accepted types.\",\n \"ai.promptInput.errorMaxFileSize\": \"All files exceed the maximum size.\",\n \"ai.promptInput.errorMaxFiles\": \"Too many files. Some were not added.\",\n \"ai.promptInput.placeholder\": \"What would you like to know?\",\n \"ai.promptInput.uploadFiles\": \"Upload files\",\n \"ai.promptInput.submit\": \"Submit\",\n \"ai.promptInput.stop\": \"Stop\",\n \"ai.agent.instructions\": \"Instructions\",\n \"ai.agent.tools\": \"Tools\",\n \"ai.agent.outputSchema\": \"Output Schema\",\n \"ai.codeBlock.generating\": \"Generating…\",\n \"ai.composer.placeholder\": \"Ask me anything…\",\n \"ai.tokenUsage.usage\": \"Model context usage\",\n \"ai.tokenUsage.totalCost\": \"Total cost\",\n \"ai.tokenUsage.input\": \"Input\",\n \"ai.tokenUsage.output\": \"Output\",\n \"ai.tokenUsage.reasoning\": \"Reasoning\",\n \"ai.tokenUsage.cache\": \"Cache\",\n \"ai.contextPanel.back\": \"Back to context\",\n \"ai.contextPanel.toggle\": \"Toggle context panel\",\n // The mobile Sheet's sr-only title (#18) — distinct from `contextPanel.toggle`,\n // which labels the button that opens/closes it.\n \"ai.contextPanel.title\": \"Context panel\",\n \"ai.contextPanel.description\": \"Displays the chat context panel.\",\n \"ai.environmentVariables.toggleVisibility\": \"Toggle value visibility\",\n \"ai.gallery.label\": \"Image gallery\",\n \"ai.gallery.expandImage\": \"Expand image\",\n \"ai.gallery.downloadImage\": \"Download image\",\n \"ai.gallery.noImages\": \"No images\",\n \"ai.gallery.noDetails\": \"No details\",\n // Shared by Tool's technical view and SchemaDisplay's request panel.\n \"ai.schemaDisplay.parameters\": \"Parameters\",\n \"ai.schemaDisplay.response\": \"Response\",\n \"ai.schemaDisplay.requestBody\": \"Request Body\",\n // ReasoningTrigger's default not-yet-timed message (before `duration` is known).\n \"ai.reasoning.thoughtDefault\": \"Thought for a few seconds\",\n \"ai.reasoning.thinking\": \"Thinking…\",\n \"ai.reasoning.thoughtForDuration\": \"Thought for {duration} seconds\",\n \"ai.stackTrace.empty\": \"No stack frames\",\n \"ai.webPreview.noConsoleOutput\": \"No console output\",\n // PlanTrigger's icon-only collapse/expand control (sr-only).\n \"ai.plan.togglePlan\": \"Toggle plan\",\n \"ai.message.actions\": \"Message actions\",\n \"ai.message.editMessage\": \"Edit message\",\n \"ai.message.feedback\": \"Message feedback\",\n \"ai.message.previousBranch\": \"Previous branch\",\n \"ai.message.nextBranch\": \"Next branch\",\n \"ai.messageCompare.error\": \"Error\",\n \"ai.messageCompare.tabs\": \"Compare responses\",\n \"ai.persona.idle\": \"Assistant idle\",\n \"ai.persona.listening\": \"Assistant listening\",\n \"ai.persona.thinking\": \"Assistant thinking…\",\n \"ai.persona.speaking\": \"Assistant speaking\",\n \"ai.persona.asleep\": \"Assistant asleep\",\n // Optional-peer lazy engines (issue #33) — one shared pair every lazy\n // boundary's missing-dependency panel resolves through, plus one\n // `feature`-name key per boundary that renders it (mermaid, the terminal).\n \"ai.error.engineMissing\": \"{feature} unavailable\",\n \"ai.error.engineMissingBody\": \"{feature} needs {packages} to be installed.\",\n \"ai.error.retry\": \"Try again\",\n \"ai.mermaid.feature\": \"Mermaid diagrams\",\n \"ai.mermaid.renderError\": \"Diagram couldn't be drawn\",\n \"ai.terminal.feature\": \"Interactive terminal\",\n \"ai.terminal.renderError\": \"Terminal couldn't start\",\n \"ai.audioPlayer.feature\": \"Audio player\",\n \"ai.audioPlayer.renderError\": \"Audio player couldn't load\",\n // AudioVisualizer. Announced through a throttled `role=\"status\"` region —\n // the canvas itself is decorative (see .claude/rules/loading-states.md and\n // issue #21's accessibility guidance).\n \"ai.audioVisualizer.idle\": \"Microphone not connected\",\n \"ai.audioVisualizer.silent\": \"No input detected\",\n \"ai.audioVisualizer.active\": \"Microphone active\",\n \"ai.selectionToolbar.label\": \"Selection actions\",\n \"ai.webPreview.urlPlaceholder\": \"Enter URL...\",\n \"ai.micSelector.searchPlaceholder\": \"Search microphones...\",\n \"ai.messageForm.selectPlaceholder\": \"Select…\",\n \"ai.messageForm.label\": \"Form\",\n \"ai.messageTable.label\": \"Data table\",\n \"ai.voiceSelector.playPreview\": \"Play preview\",\n \"ai.voiceSelector.pausePreview\": \"Pause preview\",\n\n // TurnStatus / SessionStatusBar (#105). `label` itself is caller-supplied\n // (\"Working…\", \"Editing files…\") and rendered verbatim, so it needs no key\n // here — only the component-owned completed-turn sentence and controls do.\n \"ai.turnStatus.completedIn\": \"Turn completed in {elapsed}\",\n \"ai.turnStatus.completed\": \"Turn completed\",\n \"ai.turnStatus.scrollToBottom\": \"Scroll to bottom\",\n \"ai.sessionStatusBar.connections\": \"{connected} of {total} connections\",\n \"ai.sessionStatusBar.connecting\": \"Connecting…\",\n // SessionHeader (#110). The section headings and the quick-action group name\n // are component-owned chrome; the capability/what's-new item text itself is\n // caller-supplied and rendered verbatim.\n \"ai.sessionHeader.capabilities\": \"Capabilities\",\n \"ai.sessionHeader.whatsNew\": \"What’s new\",\n \"ai.sessionHeader.quickActions\": \"Quick actions\",\n // PermissionModeSelect (#104). The in-force marker is a WORD inside the mode\n // label, so the current mode survives greyscale and reaches the accessible name.\n \"ai.permissionModeSelect.current\": \"Current\",\n // AgentEvent (#109). The pass/fail WORD is the non-colour channel — the tone\n // is redundant with it, so a check outcome survives greyscale (WCAG 1.4.1).\n \"ai.agentEvent.checkPassed\": \"Passed\",\n \"ai.agentEvent.checkFailed\": \"Failed\",\n \"ai.agentEvent.checksSummary\": \"{passed}/{ran} checks passed\",\n \"ai.agentEvent.phaseBefore\": \"Before\",\n \"ai.agentEvent.phaseAfter\": \"After\",\n \"ai.agentEvent.phaseLifecycle\": \"Lifecycle\",\n // DiffView (#102). `addedLine` / `removedLine` are the sr-only polarity\n // prefixes — the +/− glyph is aria-hidden, so these WORDS are the channel a\n // greyscale or screen-reader user recovers the polarity from (WCAG 1.4.1).\n // They intentionally end in a space so they read as a prefix to the code line.\n \"ai.diffView.addedLine\": \"Added: \",\n \"ai.diffView.removedLine\": \"Removed: \",\n \"ai.diffView.statsSummary\": \"{additions} additions, {deletions} deletions\",\n \"ai.diffView.showMore\": { one: \"Show {count} more line\", other: \"Show {count} more lines\" },\n \"ai.diffView.pagerLegend\": \"Arrow keys scroll, Page Up/Down page, Home/End jump\",\n \"ai.diffView.regionLabel\": \"Code diff\",\n \"ai.diffView.loading\": \"Loading diff…\",\n // ApprovalCard (#103). The SCOPE sentence is what makes an N-option\n // permission prompt safe to answer: \"Yes\" and \"Yes, and don't ask again\" look\n // alike and mean very different things. Each option links its scope sentence\n // through aria-describedby, so the blast radius of a choice reaches assistive\n // tech as words — never as a colour or a data-* attribute.\n \"ai.approvalCard.scopeOnceDescription\": \"Applies to this action only.\",\n \"ai.approvalCard.scopeSessionDescription\":\n \"Applies to actions like this for the rest of this session.\",\n \"ai.approvalCard.scopeAlwaysDescription\": \"Applies to actions like this from now on.\",\n \"ai.approvalCard.scopeDenyDescription\": \"Rejects this action.\",\n \"ai.approvalCard.reasonLabel\": \"Reason\",\n \"ai.approvalCard.reasonPlaceholder\": \"Add a reason (optional)…\",\n // PromptInputSlash (#106). `listLabel` goes to cmdk's own `label` prop, not\n // `aria-label` — cmdk overwrites a consumer `aria-label` on CommandList and\n // reads its accessible name off `label` instead.\n \"ai.promptInputSlash.listLabel\": \"Commands\",\n \"ai.promptInputSlash.empty\": \"No matching commands.\",\n\n // ── Streamdown chrome (third-party rendering surface) ──────────────────────\n // `streamdown` renders its OWN controls inside every streamed-markdown block\n // (code header, table menus, Mermaid toolbar, external-link interstitial) and\n // exposes them through a `translations` prop. Those strings live in the\n // dependency, not in our source, so `pnpm microcopy:check` structurally cannot\n // see them — without this block a `<LocaleProvider>` stops at the boundary and\n // the chrome stays English (#310).\n //\n // Values are BYTE-IDENTICAL to streamdown@2.5.0's `defaultTranslations`, so\n // wiring them through `t()` is a no-op for anyone who overrides nothing\n // (ADR 0017's defaults-unchanged property). Keep them that way on upgrade.\n //\n // Deliberately NOT aliased onto the generic `close` / `ai.gallery.downloadImage`\n // keys: a locale may want different wording inside markdown chrome than in the\n // surrounding app, and a translator needs the Streamdown surface addressable as\n // one block.\n \"ai.streamdown.copyCode\": \"Copy Code\",\n \"ai.streamdown.downloadFile\": \"Download file\",\n \"ai.streamdown.downloadDiagram\": \"Download diagram\",\n \"ai.streamdown.downloadDiagramAsSvg\": \"Download diagram as SVG\",\n \"ai.streamdown.downloadDiagramAsPng\": \"Download diagram as PNG\",\n \"ai.streamdown.downloadDiagramAsMmd\": \"Download diagram as MMD\",\n \"ai.streamdown.viewFullscreen\": \"View fullscreen\",\n \"ai.streamdown.exitFullscreen\": \"Exit fullscreen\",\n \"ai.streamdown.mermaidFormatSvg\": \"SVG\",\n \"ai.streamdown.mermaidFormatPng\": \"PNG\",\n \"ai.streamdown.mermaidFormatMmd\": \"MMD\",\n \"ai.streamdown.copyTable\": \"Copy table\",\n \"ai.streamdown.copyTableAsMarkdown\": \"Copy table as Markdown\",\n \"ai.streamdown.copyTableAsCsv\": \"Copy table as CSV\",\n \"ai.streamdown.copyTableAsTsv\": \"Copy table as TSV\",\n \"ai.streamdown.downloadTable\": \"Download table\",\n \"ai.streamdown.downloadTableAsCsv\": \"Download table as CSV\",\n \"ai.streamdown.downloadTableAsMarkdown\": \"Download table as Markdown\",\n \"ai.streamdown.tableFormatMarkdown\": \"Markdown\",\n \"ai.streamdown.tableFormatCsv\": \"CSV\",\n \"ai.streamdown.tableFormatTsv\": \"TSV\",\n \"ai.streamdown.imageNotAvailable\": \"Image not available\",\n \"ai.streamdown.downloadImage\": \"Download image\",\n \"ai.streamdown.openExternalLink\": \"Open external link?\",\n // Straight apostrophe on purpose — must stay byte-identical to streamdown's\n // default, so the micro-typography curly-quote preference does not apply here.\n \"ai.streamdown.externalLinkWarning\": \"You're about to visit an external website.\",\n \"ai.streamdown.close\": \"Close\",\n \"ai.streamdown.copyLink\": \"Copy link\",\n \"ai.streamdown.copied\": \"Copied\",\n \"ai.streamdown.openLink\": \"Open link\",\n // Tool (#4 i18n sweep).\n \"ai.tool.showTechnicalDetails\": \"Show technical details\",\n \"ai.tool.error\": \"Error\",\n \"ai.tool.result\": \"Result\",\n // PackageInfo.\n \"ai.packageInfo.dependencies\": \"Dependencies\",\n // AssetPreview.\n \"ai.assetPreview.rowCount\": { one: \"{count} row\", other: \"{count} rows\" },\n \"ai.assetPreview.noPreview\": \"No preview available…\",\n \"ai.assetPreview.preview\": \"Preview\",\n \"ai.assetPreview.raw\": \"Raw\",\n // WebPreview's sandboxed iframe accessible name.\n \"ai.webPreview.previewTitle\": \"Preview\",\n // A2UI surface (D2 — an agent-designed screen rendered from data)\n \"ai.a2ui.loading\": \"Loading surface…\",\n \"ai.a2ui.invalid\": \"This surface can’t be shown — it doesn’t match the catalog.\",\n \"ai.a2ui.moreErrors\": { one: \"…and {count} more problem\", other: \"…and {count} more problems\" },\n // FileTree's expand/collapse chevron control.\n \"ai.fileTree.expandFolder\": \"Expand {name}\",\n \"ai.fileTree.collapseFolder\": \"Collapse {name}\",\n \"ai.fileTree.noAssetsProduced\": \"No assets produced yet.\",\n \"ai.conversation.download\": \"Download conversation\",\n // OpenInChat. `provider` is a brand name (ChatGPT, Claude, …) — kept\n // untranslated data, interpolated into the translated \"Open in …\" phrase.\n \"ai.openInChat.trigger\": \"Open in chat\",\n \"ai.openInChat.openInProvider\": \"Open in {provider}\",\n // TestResults.\n \"ai.testResults.passedCount\": { one: \"{count} passed\", other: \"{count} passed\" },\n \"ai.testResults.failedCount\": { one: \"{count} failed\", other: \"{count} failed\" },\n \"ai.testResults.skippedCount\": { one: \"{count} skipped\", other: \"{count} skipped\" },\n \"ai.testResults.testsPassed\": \"{passed}/{total} tests passed\",\n\n // ── @elabs-ai/components-editor ───────────────────────────────────────────\n // DecisionCard (ai-objects). Status vocabulary + the card's own accessible name\n // and the \"Alternatives considered\" section (shared by its heading and its list's\n // aria-label).\n \"editor.decisionCard.statusAccepted\": \"Accepted\",\n \"editor.decisionCard.statusRejected\": \"Rejected\",\n \"editor.decisionCard.statusProposed\": \"Proposed\",\n \"editor.decisionCard.statusSuperseded\": \"Superseded\",\n \"editor.decisionCard.label\": \"Decision: {label}\",\n \"editor.decisionCard.alternativesConsidered\": \"Alternatives considered\",\n // KnowledgeCard (ai-objects).\n \"editor.knowledgeCard.label\": \"Knowledge fact\",\n \"editor.knowledgeCard.heading\": \"Knowledge\",\n \"editor.knowledgeCard.sources\": \"Sources\",\n \"editor.knowledgeCard.source\": \"Source: {name}\",\n \"editor.knowledgeCard.sourceUnresolved\": \"Source (unresolved): {name}\",\n // CalcBlock. `equals` is the sr-only prefix read before a computed value —\n // intentionally ends in a space so it reads as a prefix (mirrors `ai.diffView.addedLine`).\n \"editor.calcBlock.error\": \"Error: {message}\",\n \"editor.calcBlock.equals\": \"equals \",\n \"editor.calcBlock.total\": \"Total\",\n \"editor.calcBlock.emptyBlock\": \"Empty calc block.\",\n // CopyButton. The \"Copy\" state reuses the shared generic `copy` key.\n \"editor.copyButton.copied\": \"Copied\",\n // EditorToolbar.\n \"editor.editorToolbar.language\": \"Language\",\n // Citations (markdown-academic).\n \"editor.citations.citationLabel\": \"Citation: {name}\",\n \"editor.citations.unresolvedCitation\": \"Unresolved citation\",\n \"editor.citations.unresolvedKey\": \"Unresolved: @{key}\",\n \"editor.citations.references\": \"References\",\n // Math (markdown-academic).\n \"editor.math.renderError\": \"Could not render math\",\n \"editor.math.renderErrorLabel\": \"Math (could not render): {tex}\",\n // CompletionMenu (markdown-editor).\n \"editor.completions.suggestions\": \"Suggestions\",\n \"editor.completions.noSuggestions\": \"No suggestions\",\n // SlashMenu (markdown-editor).\n \"editor.slashMenu.insertBlock\": \"Insert block\",\n \"editor.slashMenu.noMatchingBlocks\": \"No matching blocks\",\n // TableControlsView (markdown-editor/table-view — the WYSIWYG GFM table toolbar).\n \"editor.tableView.tableControls\": \"Table controls\",\n \"editor.tableView.row\": \"Row\",\n \"editor.tableView.col\": \"Col\",\n \"editor.tableView.addRowAbove\": \"Add row above\",\n \"editor.tableView.addRowBelow\": \"Add row below\",\n \"editor.tableView.deleteRow\": \"Delete row\",\n \"editor.tableView.addColumnLeft\": \"Add column left\",\n \"editor.tableView.addColumnRight\": \"Add column right\",\n \"editor.tableView.deleteColumn\": \"Delete column\",\n // Directive node-views (markdown-editor/directive-views — Milkdown WYSIWYG).\n \"editor.directiveViews.cardTitle\": \"Card title\",\n \"editor.directiveViews.calloutTitle\": \"Callout title\",\n \"editor.directiveViews.unknownBlock\": \"Unknown block: {name}\",\n \"editor.directiveViews.unknownInlineBlock\": \"Unknown inline block:\",\n \"editor.directiveViews.metricLabel\": \"Metric label\",\n \"editor.directiveViews.metricLabelPlaceholder\": \"Label\",\n \"editor.directiveViews.metricValue\": \"Metric value\",\n \"editor.directiveViews.metricValuePlaceholder\": \"0\",\n \"editor.directiveViews.editIteration\": \"Edit iteration…\",\n \"editor.directiveViews.changeLayout\": \"Change layout\",\n \"editor.directiveViews.transpose\": \"Transpose\",\n \"editor.directiveViews.convertToStatic\": \"Convert to static\",\n \"editor.directiveViews.needsEmbeddedValues\": \"— needs embedded values\",\n \"editor.directiveViews.pivot\": \"Pivot\",\n \"editor.directiveViews.iterate\": \"Iterate\",\n \"editor.directiveViews.perItem\": \"· per {as}\",\n \"editor.directiveViews.templateSuffix\": \"— template\",\n \"editor.directiveViews.iterationActions\": \"Iteration actions\",\n \"editor.directiveViews.iterationActionsTitle\": \"Iteration actions…\",\n // IterationBuilderDialog (markdown-iteration) — the guided iterate/pivot authoring modal.\n \"editor.iterationBuilder.pivotNoun\": \"pivot\",\n \"editor.iterationBuilder.iterationNoun\": \"iteration\",\n \"editor.iterationBuilder.editTitle\": \"Edit {noun}\",\n \"editor.iterationBuilder.insertTitle\": \"Insert {noun}\",\n \"editor.iterationBuilder.pivotDescription\":\n \"Pick the row and column values, then write the per-cell template. The matrix below fills in live.\",\n \"editor.iterationBuilder.iterationDescription\":\n \"Add the list values, then write the per-row template. The result below fills in live.\",\n \"editor.iterationBuilder.bindName\": \"Bind name\",\n \"editor.iterationBuilder.bindNamePlaceholder\": \"item\",\n \"editor.iterationBuilder.bindNameHintPrefix\": \"Use \",\n \"editor.iterationBuilder.bindNameHintSuffix\": \" in the template.\",\n \"editor.iterationBuilder.rowValues\": \"Row values\",\n \"editor.iterationBuilder.values\": \"Values\",\n \"editor.iterationBuilder.valuePlaceholder\": \"Type a value, press Enter…\",\n \"editor.iterationBuilder.columnValues\": \"Column values\",\n \"editor.iterationBuilder.layout\": \"Layout\",\n \"editor.iterationBuilder.perCellTemplate\": \"Per-cell template\",\n \"editor.iterationBuilder.perRowTemplate\": \"Per-row template\",\n \"editor.iterationBuilder.livePreview\": \"Live preview\",\n \"editor.iterationBuilder.cancel\": \"Cancel\",\n \"editor.iterationBuilder.save\": \"Save\",\n \"editor.iterationBuilder.insert\": \"Insert\",\n // IterationTemplateDialog (markdown-iteration) — the lighter template-only modal.\n \"editor.templateDialog.editPivotTitle\": \"Edit pivot template\",\n \"editor.templateDialog.editIterationTitle\": \"Edit iteration template\",\n \"editor.templateDialog.descriptionPrefix\": \"The per-{unit} template. Use \",\n \"editor.templateDialog.descriptionMiddle\": \" placeholders (e.g. \",\n \"editor.templateDialog.descriptionSuffix\":\n \") — each is filled per {unit} when the block renders.\",\n \"editor.templateDialog.editorLabel\": \"Iteration template editor\",\n \"editor.templateDialog.cancel\": \"Cancel\",\n \"editor.templateDialog.saveTemplate\": \"Save template\",\n // DocumentOutline (markdown-outline).\n \"editor.documentOutline.label\": \"Document outline\",\n \"editor.documentOutline.empty\": \"No headings yet.\",\n // MarkdownToolbar (the source-pane formatting bar). Directive snippet labels\n // are the Insert menu's fallback item text (`DIRECTIVE_SNIPPETS`); the snippet\n // MARKDOWN they insert is example document content, not UI chrome, and stays\n // English (see the `i18n-exempt` comments at each snippet).\n \"editor.markdownToolbar.label\": \"Markdown formatting\",\n \"editor.markdownToolbar.bold\": \"Bold\",\n \"editor.markdownToolbar.italic\": \"Italic\",\n \"editor.markdownToolbar.inlineCode\": \"Inline code\",\n \"editor.markdownToolbar.link\": \"Link\",\n \"editor.markdownToolbar.headingLevel\": \"Heading level\",\n \"editor.markdownToolbar.heading\": \"Heading\",\n \"editor.markdownToolbar.headingLevelItem\": \"Heading {level}\",\n \"editor.markdownToolbar.quote\": \"Quote\",\n \"editor.markdownToolbar.bulletList\": \"Bullet list\",\n \"editor.markdownToolbar.numberedList\": \"Numbered list\",\n \"editor.markdownToolbar.divider\": \"Divider\",\n \"editor.markdownToolbar.insertBlock\": \"Insert block\",\n \"editor.markdownToolbar.insert\": \"Insert\",\n \"editor.markdownToolbar.insertBrandBlock\": \"Insert brand block\",\n \"editor.markdownToolbar.directiveCard\": \"Card\",\n \"editor.markdownToolbar.directiveCallout\": \"Callout\",\n \"editor.markdownToolbar.directiveMetric\": \"Metric\",\n \"editor.markdownToolbar.directiveTimeline\": \"Timeline\",\n // MarkdownWorkspace's focus-writing toggle.\n \"editor.markdownWorkspace.focusWriting\": \"Focus writing\",\n \"editor.markdownWorkspace.focus\": \"Focus\",\n \"editor.markdownWorkspace.focusWritingHint\": \"Typewriter scrolling · inactive paragraphs dim\",\n // MermaidDiagram (the inline renderer).\n \"editor.mermaidDiagram.label\": \"Diagram\",\n \"editor.mermaidDiagram.expand\": \"Expand diagram\",\n \"editor.mermaidDiagram.downloadSvg\": \"Download diagram as SVG\",\n \"editor.mermaidDiagram.copySource\": \"Copy diagram source\",\n \"editor.mermaidDiagram.renderFailed\": \"Diagram failed to render\",\n \"editor.mermaidDiagram.rendering\": \"Rendering diagram…\",\n // MermaidViewer (the expanded zoom/pan/search surface). `nodeCountHint` mirrors\n // the ORIGINAL (pre-i18n) copy exactly, including its always-plural \"nodes\" —\n // it is a static hint (\"N nodes · type to filter\"), not a real plural form, so\n // it stays a plain interpolated string rather than a `PluralMessage`.\n \"editor.mermaidViewer.findPlaceholder\": \"Find in diagram…\",\n \"editor.mermaidViewer.findLabel\": \"Find in diagram\",\n \"editor.mermaidViewer.matchCount\": { one: \"{count} node\", other: \"{count} nodes\" },\n \"editor.mermaidViewer.nodeCountHint\": \"{count} nodes · type to filter\",\n \"editor.mermaidViewer.zoomOut\": \"Zoom out\",\n \"editor.mermaidViewer.zoomIn\": \"Zoom in\",\n \"editor.mermaidViewer.resetZoom\": \"Reset zoom to 100%\",\n \"editor.mermaidViewer.fitDiagram\": \"Fit diagram\",\n\n // ── @elabs-ai/components-viewer (ADR 0024) ─────────────────────────\n // FileViewer chrome. Every control here is icon-only, so these ARE the\n // accessible names — a non-English screen-reader user has no workaround.\n \"viewer.label\": \"File viewer\",\n // The scrolling content region's accessible name. It is a focusable tab stop\n // (WCAG 2.1.1: a pane that scrolls but holds nothing focusable is unreachable\n // from a keyboard), so it needs a name as well as a role.\n \"viewer.content\": \"File content\",\n \"viewer.download\": \"Download {name}\",\n \"viewer.raw\": \"Show source\",\n \"viewer.rendered\": \"Show rendered\",\n // States. `loading` announces the region once (role=\"status\"); the skeleton\n // itself is aria-hidden, so this is the only thing AT hears.\n \"viewer.loading\": \"Loading {name}…\",\n \"viewer.empty\": \"No file selected\",\n \"viewer.emptyBody\": \"Choose a file to preview it here.\",\n // Failures. Each maps to one ViewerErrorCode, so the code is the contract and\n // the wording can change per locale without touching component logic.\n \"viewer.error.unsupportedFormat\": \"Can't preview this file type\",\n \"viewer.error.unsupportedFormatBody\":\n \"{name} can be downloaded, but there's no preview for it here.\",\n \"viewer.error.parserMissing\": \"Preview unavailable\",\n \"viewer.error.parserMissingBody\": \"Previewing {name} needs {packages} to be installed.\",\n \"viewer.error.readFailed\": \"Couldn't open this file\",\n \"viewer.error.readFailedBody\":\n \"{name} couldn't be read. It may have moved, or you may not have access.\",\n \"viewer.error.parseFailed\": \"Couldn't read this file\",\n \"viewer.error.parseFailedBody\": \"{name} isn't a valid {format} file, or it's damaged.\",\n \"viewer.error.imageFailedTitle\": \"Couldn't show this image\",\n \"viewer.error.imageFailed\": \"{name} could not be displayed.\",\n \"viewer.retry\": \"Try again\",\n // Table view (CSV/TSV). The count is a summary for the whole grid.\n \"viewer.table.caption\": \"{rows} rows, {columns} columns\",\n \"viewer.table.truncated\": \"Showing the first {count} rows.\",\n \"viewer.table.emptyCell\": \"Empty\",\n // Text and JSON views.\n \"viewer.text.truncated\": \"Showing the first {shown} of {total} characters.\",\n \"viewer.json.tree\": \"JSON structure\",\n // Page, scale and rotation chrome (ADR 0026). Format-agnostic: one pager\n // serves PDF pages and PowerPoint slides, so the words are about \"pages\" and\n // the slide-specific wording lives on the slide itself.\n \"viewer.pager.controls\": \"Pages\",\n \"viewer.pager.previous\": \"Previous page\",\n \"viewer.pager.next\": \"Next page\",\n // The field's own accessible name. The visible \"of {total}\" beside it is not\n // a label — a screen reader would read the two as one run without this.\n \"viewer.pager.pageNumber\": \"Page number\",\n \"viewer.pager.of\": \"of {total}\",\n // Live region: a repainted canvas and a changed input value both announce\n // nothing, so this sentence is the only confirmation a page turned.\n \"viewer.pager.status\": \"Page {page} of {total}\",\n \"viewer.zoom.controls\": \"Zoom\",\n \"viewer.zoom.in\": \"Zoom in\",\n \"viewer.zoom.out\": \"Zoom out\",\n \"viewer.zoom.level\": \"Zoom level\",\n \"viewer.zoom.fitWidth\": \"Fit width\",\n \"viewer.zoom.fitPage\": \"Fit page\",\n \"viewer.zoom.status\": \"Zoom {level}\",\n \"viewer.rotate\": \"Rotate clockwise\",\n // PDF view.\n \"viewer.pdf.page\": \"Page {page}\",\n \"viewer.pdf.pages\": \"Document pages\",\n \"viewer.pdf.pageFailed\": \"Page {page} couldn't be drawn.\",\n // Media view (video / audio).\n \"viewer.media.label\": \"{name} player\",\n \"viewer.media.unsupportedTitle\": \"Can't play this file\",\n \"viewer.media.unsupported\": \"This browser can't play {name}.\",\n // Office views. A preview shows a document's STRUCTURE, not Word's or\n // PowerPoint's page layout — the copy never promises a faithful reproduction.\n \"viewer.docx.empty\": \"This document has no text\",\n \"viewer.sheet.tabs\": \"Sheets\",\n \"viewer.pptx.slide\": \"Slide {slide}\",\n \"viewer.pptx.untitled\": \"Untitled slide\",\n \"viewer.pptx.notes\": \"Speaker notes\",\n \"viewer.pptx.empty\": \"This slide has no text\",\n // Code and markdown views. `file.empty` is shared: \"the file opened and there\n // is nothing in it\" is one message whatever the format.\n \"viewer.file.empty\": \"This file is empty\",\n // Find-in-document (ADR 0025). The count is a live region read on every step,\n // so it stays short; `findNone` replaces it rather than sitting beside it, so\n // a fruitless search never reads as \"0 of 0\".\n \"viewer.find.open\": \"Find in document\",\n \"viewer.find.label\": \"Find in document\",\n \"viewer.find.placeholder\": \"Find…\",\n \"viewer.find.close\": \"Close find\",\n \"viewer.find.previous\": \"Previous match\",\n \"viewer.find.next\": \"Next match\",\n \"viewer.find.caseSensitive\": \"Match case\",\n \"viewer.find.count\": \"{index} of {total}\",\n \"viewer.find.none\": \"No matches\",\n \"viewer.find.capped\": \"Showing the first {limit} matches of {total}.\",\n // Citations / passages the app points the viewer at. A miss is a STATE, not a\n // silent no-op — the reader is told the passage could not be located, and\n // \"past the part we previewed\" is different news from \"not in this document\".\n \"viewer.highlight.notFound\": \"Couldn't find that passage in this document.\",\n \"viewer.highlight.notFoundTruncated\":\n \"That passage may be beyond the part of this document we could preview.\",\n \"viewer.highlight.unsupported\": \"This build can't point at part of a {format} file.\",\n \"viewer.highlight.previous\": \"Previous passage\",\n \"viewer.highlight.next\": \"Next passage\",\n \"viewer.highlight.count\": \"Passage {index} of {total}\",\n\n // ── @elabs-ai/components-terminal ─────────────────────────────────────────\n // Terminal (the read-only ANSI log): the ONE live-region announcement for\n // its `isStreaming` rung. The blinking cursor block is the only other\n // streaming signal and it is purely visual, so without this a screen-reader\n // user attached to a running build or deploy log gets no indication that\n // anything is still arriving.\n \"terminal.output.streaming\": \"Streaming output…\",\n // TerminalTranscriptRow (#117 T2): the gutter's meaning as words, so the\n // \"who spoke / what it printed / did it fail\" grammar survives greyscale\n // and reaches assistive tech, not only the glyph + colour.\n \"terminal.transcriptRow.user\": \"Prompt\",\n \"terminal.transcriptRow.agent\": \"Agent\",\n \"terminal.transcriptRow.output\": \"Output\",\n \"terminal.transcriptRow.error\": \"Error\",\n \"terminal.transcriptRow.exitCode\": \"Exit {code}\",\n // TerminalTodoList (#117 T5): the three-state checklist's announced word\n // per row — the second, non-colour channel beside the ✔ / ◼ / ◻ glyph and\n // the strikethrough/bold treatment. Wording verified 2026-09-01 against\n // Claude Code v2.1.207's own upstream state words, parentheses included.\n \"terminal.todoList.done\": \"(completed)\",\n \"terminal.todoList.active\": \"(in progress)\",\n \"terminal.todoList.pending\": \"(pending)\",\n // TerminalEventLine (#117 T6): the lifecycle/hook event line. `outcome*` is\n // the sr-only word beside the (always aria-hidden) StatusIcon glyph —\n // never omitted for the default \"ok\" case, so \"succeeded\" is exactly as\n // recoverable as \"failed\". `hooksTotal`/`hooksResult` are the terminal's\n // own literal `[hooks: …]` bracket vocabulary, verified live 2026-09-01\n // against Grok CLI v0.2.93; `hooksFailed` is the sr-only, count-aware\n // \"N hooks failed\" that makes a partial hook failure (e.g. `3/1`) read as\n // bad without relying on colour.\n \"terminal.eventLine.outcomeOk\": \"Succeeded\",\n \"terminal.eventLine.outcomeBlocked\": \"Blocked\",\n \"terminal.eventLine.outcomeFailed\": \"Failed\",\n \"terminal.eventLine.phaseBefore\": \"Before\",\n \"terminal.eventLine.phaseAfter\": \"After\",\n \"terminal.eventLine.phaseLifecycle\": \"Lifecycle\",\n \"terminal.eventLine.hooksTotal\": \"[hooks: {total}]\",\n \"terminal.eventLine.hooksResult\": \"[hooks: {ran}/{passed}]\",\n \"terminal.eventLine.hooksFailed\": {\n one: \"{count} hook failed\",\n other: \"{count} hooks failed\",\n },\n // TerminalWorking (#117 T3): the in-turn footer's default label and its two\n // icon-only controls' accessible names. No generic \"stop\"/\"scroll to\n // bottom\" key exists yet (only the ai-namespaced `ai.promptInput.stop` /\n // `ai.turnStatus.scrollToBottom`), so these are minted under the package's\n // own namespace rather than borrowed cross-package.\n \"terminal.working.label\": \"Waiting for response…\",\n \"terminal.working.stop\": \"Stop\",\n \"terminal.working.scrollToBottom\": \"Scroll to bottom\",\n // TerminalStatusBar (#117 T4): the ambient chrome row's accessible name and\n // the sr-only words beside its aria-hidden numerals/glyphs. Mirrors\n // `ai.sessionStatusBar.connections`' wording under this package's own\n // namespace (cannot import the `ai` key — sibling packages never import\n // each other, `.claude/rules/terminal-components.md` § Reuse means\n // promotion). `disconnected` and `stepsComplete` (\"steps complete\") are\n // verified live 2026-09-01 against Grok CLI v0.2.93.\n \"terminal.statusBar.label\": \"Session status\",\n \"terminal.statusBar.connecting\": \"Connecting…\",\n \"terminal.statusBar.connections\": \"{connected} of {total} connections\",\n \"terminal.statusBar.disconnected\": \"Disconnected\",\n \"terminal.statusBar.context\": \"{used} of {limit} context used\",\n \"terminal.statusBar.stepsComplete\": \"{current} of {total} steps complete\",\n // TerminalBanner (#117 T7): the launch card above an empty transcript.\n // Mirrors `ai.sessionHeader.*`'s wording under this package's own\n // namespace — sibling packages never import each other's locale keys\n // (`.claude/rules/terminal-components.md` § Reuse means promotion).\n \"terminal.banner.capabilities\": \"Capabilities\",\n \"terminal.banner.whatsNew\": \"What’s new\",\n \"terminal.banner.quickActions\": \"Quick actions\",\n // TerminalToolCall (#117 T8): the tool-call row's status word (announced\n // beside the glyph via TerminalRow's gutterLabel — never colour alone),\n // the result row's swapped heading (mirrors ToolOutput's own \"Result\"/\n // \"Error\" heading swap, `@elabs-ai/components-ai`), and the expand\n // trigger's accessible name. Unlike upstream's inert `\"(ctrl+o to\n // expand)\"` hint text, this IS a real focusable control's label — no CLI\n // chord required.\n \"terminal.toolCall.succeeded\": \"Succeeded\",\n \"terminal.toolCall.failed\": \"Failed\",\n \"terminal.toolCall.running\": \"Running\",\n \"terminal.toolCall.result\": \"Result\",\n \"terminal.toolCall.error\": \"Error\",\n \"terminal.toolCall.expandHint\": \"Show details\",\n // TerminalDiffHunk (#117 T9): the header's fixed \"Update ({file})\" phrase,\n // and the collapsed-context-run disclosure's count-aware label. Mirrors\n // `ai.diffView.showMore`'s wording under this package's own namespace —\n // sibling packages never import each other's locale keys\n // (`.claude/rules/terminal-components.md` § Reuse means promotion). The\n // per-line `add`/`del` polarity words are NOT duplicated here: they ride\n // the shared `diffLineAccessibleLabel()` keys (`ai.diffView.addedLine` /\n // `ai.diffView.removedLine`) above, the actual promoted channel.\n \"terminal.diffHunk.header\": \"Update ({file})\",\n \"terminal.diffHunk.showMore\": {\n one: \"Show {count} more line\",\n other: \"Show {count} more lines\",\n },\n // TerminalPermission (#117 T10): the per-call scoped approval prompt's\n // default title/question and its three scoped option labels, verified\n // live 2026-09-01 against Claude Code v2.1.207. The third option is the\n // vendor-free `deny` scope: upstream names its own product in this label,\n // ours reads \"the agent\" instead (#117 acceptance criterion). The reason\n // field reuses `ai.approvalCard.reasonLabel`/`reasonPlaceholder` and the\n // option descriptions reuse `APPROVAL_SCOPE_DESCRIPTION_KEYS` — both\n // already generic, so nothing new is minted for either.\n \"terminal.permission.title\": \"Bash command\",\n \"terminal.permission.question\": \"Do you want to proceed?\",\n \"terminal.permission.optionOnce\": \"Yes\",\n \"terminal.permission.optionSession\": \"Yes, and don’t ask again this session\",\n \"terminal.permission.optionDeny\": \"No, and tell the agent what to do differently\",\n // TerminalComposer (#117 T11): the prompt composer's placeholder, its\n // merged submit/stop affordance's accessible name (mirrors\n // `ai.promptInput.submit`/`stop` under this package's own namespace —\n // sibling packages never import each other's locale keys,\n // `.claude/rules/terminal-components.md` § Reuse means promotion), the\n // effort scale's default accessible name, and the shortcut-hint row's\n // three default words.\n \"terminal.composer.placeholder\": \"Type your next instruction…\",\n \"terminal.composer.submit\": \"Send\",\n \"terminal.composer.stop\": \"Stop\",\n \"terminal.composer.effort\": \"Effort\",\n \"terminal.composer.shortcutSend\": \"send\",\n \"terminal.composer.shortcutNewline\": \"newline\",\n \"terminal.composer.shortcutCancel\": \"cancel\",\n // TerminalSlashMenu (#117 T12): the `/`-command palette's listbox\n // accessible name (mirrors `ai.promptInputSlash.listLabel`'s wording under\n // this package's own namespace — sibling packages never import each\n // other's locale keys, `.claude/rules/terminal-components.md` § Reuse\n // means promotion). The empty state reuses the generic `noResults` key\n // rather than minting a second one.\n \"terminal.slashMenu.listLabel\": \"Commands\",\n // ── @elabs-ai/components-process ──────────────────────────────────────────────────────────\n // ProcessMap (RM-051). Namespaced `process.<area>.<key>` like every other\n // package; a sibling package's keys are never reused across the boundary.\n // The table twin's column headers are here because that table IS the\n // accessible reading of the canvas — an untranslated header would leave a\n // screen-reader user with numbers and no measure name.\n \"process.map.loading\": \"Discovering the process…\",\n \"process.map.empty\": \"No activities to map\",\n \"process.map.emptyBody\":\n \"This log has no events, or the abstraction hid every activity. Widen the abstraction or load a different log.\",\n \"process.map.label\": \"Process map\",\n \"process.map.filter\": \"Filter…\",\n \"process.map.activityCaption\": \"Activities — {metric} per activity\",\n \"process.map.transitionCaption\": \"Transitions — {metric} per directly-follows pair\",\n \"process.map.columnActivity\": \"Activity\",\n \"process.map.columnRole\": \"Role\",\n \"process.map.columnRework\": \"Rework\",\n \"process.map.columnFrom\": \"From\",\n \"process.map.columnTo\": \"To\",\n \"process.map.columnShape\": \"Shape\",\n // State column (#373) — the table twin's own channel for the selection/filter state the\n // canvas already says through real text in its accessible names; the twin used to carry\n // it only as a `data-*` attribute, which reaches no user.\n \"process.map.columnState\": \"State\",\n // The State column's own CELL values (#413 review, PRRT_kwDOT6D7ts6gJX2C). #373 localized\n // the column HEADER but left every cell printing the literal English word — since that cell\n // is also the row's screen-reader channel for its selection/filter state\n // (`selectionStateLabel` below is the un-localized canonical word `process-map.tsx` maps\n // through these keys at the render site), a non-English `LocaleProvider` left both the\n // visible AND the accessible content untranslated. `\"associated\"` (the ordinary case) has\n // no key: it prints nothing, by design.\n \"process.map.stateSelected\": \"Selected\",\n \"process.map.stateExcluded\": \"Excluded\",\n // Filter-intent menu item ACCESSIBLE names (#346). A transition's menu offers the same\n // four intents once per endpoint (eight items total); the visible text\n // (`PROCESS_FILTER_INTENT_LABELS` in map-model.ts) stays unsuffixed and compact, so these\n // compose the activity into the item's real accessible name instead — the channel a\n // screen-reader user actually hears, and the one the visible-only text left ambiguous.\n \"process.map.filterIntentWith\": \"Keep cases containing {activity}\",\n \"process.map.filterIntentWithout\": \"Keep cases without {activity}\",\n \"process.map.filterIntentStartsWith\": \"Keep cases starting with {activity}\",\n \"process.map.filterIntentEndsWith\": \"Keep cases ending with {activity}\",\n // The map's own live-region summary (#375) — one polite `role=\"status\"` announces what\n // the active selection/filter just changed, mirroring `AbstractionControls`' hidden-count\n // summary below: two independently-pluralized fragments, composed at the call site\n // (`process-map.tsx`) rather than merged into one message, for the same reason.\n \"process.map.excludedActivities\": {\n one: \"{count} of {total} activity excluded\",\n other: \"{count} of {total} activities excluded\",\n },\n \"process.map.excludedTransitions\": {\n one: \"{count} of {total} transition excluded\",\n other: \"{count} of {total} transitions excluded\",\n },\n // The live region's AFFECTED-SET fragments (#413 review, PRRT_kwDOT6D7ts6gJX2I). Counts\n // alone are not enough: two selections/filters that exclude DIFFERENT elements but land on\n // the SAME counts produce byte-for-byte identical text, so the polite region — which\n // announces content CHANGES, not model changes — stays silent even though the map\n // re-inked. Naming which elements are excluded makes the string track the actual set, not\n // only its size. Composed at the call site alongside the two counts above, and omitted\n // entirely when nothing of that kind is excluded (so the common case stays as short as\n // before this fix).\n \"process.map.excludedActivityNames\": \"excluding {names}\",\n \"process.map.excludedTransitionNames\": \"excluding {names}\",\n // AbstractionControls (RM-052, issue #227). The two sliders' own labels,\n // the invert switch, the \"Auto\" heuristic button, and the hidden-count\n // status line. `hiddenActivities`/`hiddenPaths` are separate `PluralMessage`s\n // (not one combined key) because `t()` selects its plural category from a\n // SINGLE `count` var — see `resolveMessage` in `locale-provider.tsx` — so\n // the two independently-pluralizable counts are composed as two `t()` calls\n // joined at the call site (`abstraction-controls.tsx`), not one key with two\n // numbers.\n \"process.abstractionControls.label\": \"Abstraction\",\n \"process.abstractionControls.activities\": \"Activities\",\n \"process.abstractionControls.paths\": \"Paths\",\n \"process.abstractionControls.invert\": \"Invert\",\n \"process.abstractionControls.auto\": \"Auto\",\n \"process.abstractionControls.hiddenActivities\": {\n one: \"{count} activity hidden\",\n other: \"{count} activities hidden\",\n },\n \"process.abstractionControls.hiddenPaths\": {\n one: \"{count} path hidden\",\n other: \"{count} paths hidden\",\n },\n // MetricLayerSwitch (RM-052, issue #227). The Frequency/Performance/Rework\n // toggle group, the node/edge metric selects' field labels, and the lock\n // toggle's two accessible-name states. The per-VALUE metric labels\n // (\"Occurrences\", \"Share of transitions\", …) are deliberately NOT\n // duplicated here — they are read straight from `nodeMetricLabel`/\n // `edgeMetricLabel` (`process-map/map-model.ts`), which already resolve\n // each `ProcessMetric` to its correct, audience-specific text; see\n // `metric-layer-switch.tsx`'s module docblock.\n \"process.metricLayerSwitch.label\": \"Metric\",\n \"process.metricLayerSwitch.layer\": \"Metric layer\",\n \"process.metricLayerSwitch.frequency\": \"Frequency\",\n \"process.metricLayerSwitch.performance\": \"Performance\",\n \"process.metricLayerSwitch.rework\": \"Rework\",\n \"process.metricLayerSwitch.node\": \"Activity\",\n \"process.metricLayerSwitch.edge\": \"Transition\",\n \"process.metricLayerSwitch.lockOn\": \"Unlock activity and transition metrics\",\n \"process.metricLayerSwitch.lockOff\": \"Lock activity and transition metrics together\",\n // ProcessKpiStrip (RM-052, issue #227). Six tiles' labels, plus the\n // conformance tile's genuine \"not available\" state (no conformance model\n // has run yet) — a real state, not a fabricated 0%.\n \"process.kpiStrip.cases\": \"Cases\",\n \"process.kpiStrip.events\": \"Events\",\n \"process.kpiStrip.variants\": \"Variants\",\n \"process.kpiStrip.medianThroughput\": \"Median throughput\",\n \"process.kpiStrip.reworkRate\": \"Rework rate\",\n \"process.kpiStrip.conformance\": \"Conformance\",\n \"process.kpiStrip.conformanceUnavailable\": \"Not available\",\n \"process.kpiStrip.conformanceUnavailableHint\": \"Run conformance checking to see this metric.\",\n // Sparkline text alternative (#359). `Sparkline`'s own default alt text is more\n // informative than the tile's own label — passing the label straight through\n // overrode it and left a screen-reader user hearing the tile's name twice with no\n // sense of the trend. `direction` is itself a resolved `t()` value (trendRising/\n // Falling/Steady), composed into this template the same way `hiddenSummary`\n // (abstraction-controls.tsx) composes two already-localized fragments.\n \"process.kpiStrip.trendAlt\":\n \"{subject}, {periods}-period trend, {direction} from {first} to {last}\",\n \"process.kpiStrip.trendRising\": \"rising\",\n \"process.kpiStrip.trendFalling\": \"falling\",\n \"process.kpiStrip.trendSteady\": \"steady\",\n // ProcessFilterBar (RM-056, #205). Filter-chain breadcrumb chip labels — label-in-value\n // text, one key per `FilterIntent[\"kind\"]` — the \"Clear all\" action, the chip's own\n // \"excluded\" count label, and the summary line's two independently-omittable clauses\n // (see `process-filter-bar.tsx`'s module docblock for why they are composed, not merged).\n \"process.filterBar.label\": \"Active filters\",\n \"process.filterBar.with\": \"Contains {activity}\",\n \"process.filterBar.without\": \"Excludes {activity}\",\n \"process.filterBar.startsWith\": \"Starts with {activity}\",\n \"process.filterBar.endsWith\": \"Ends with {activity}\",\n \"process.filterBar.variant\": {\n one: \"{count} variant selected\",\n other: \"{count} variants selected\",\n },\n \"process.filterBar.cases\": {\n one: \"{count} case selected\",\n other: \"{count} cases selected\",\n },\n \"process.filterBar.filter\": \"Filter\",\n \"process.filterBar.excludedLabel\": \"excluded\",\n \"process.filterBar.clearAll\": \"Clear all\",\n \"process.filterBar.showingAll\": {\n one: \"Showing all {total} case\",\n other: \"Showing all {total} cases\",\n },\n \"process.filterBar.showing\": \"Showing {filtered} of {total} cases\",\n \"process.filterBar.hiddenByAbstraction\": {\n one: \"{count} activity hidden by abstraction\",\n other: \"{count} activities hidden by abstraction\",\n },\n // CaseTable (RM-055, issue #204). A column configuration over `data`'s\n // DataTable — see `.claude/rules/data.md`'s \"primitives go down, compositions\n // go up\". `conformance*` labels the three-state badge; `conformance` itself\n // is host-supplied (never fabricated here — same rule as `ProcessKpiStrip`'s\n // own conformance tile).\n \"process.caseTable.columnCaseId\": \"Case\",\n \"process.caseTable.columnStart\": \"Start\",\n \"process.caseTable.columnEnd\": \"End\",\n \"process.caseTable.columnDuration\": \"Duration\",\n \"process.caseTable.columnEventCount\": \"Events\",\n \"process.caseTable.columnVariant\": \"Variant\",\n \"process.caseTable.columnConformance\": \"Conformance\",\n \"process.caseTable.conformanceConforming\": \"Conforming\",\n \"process.caseTable.conformanceNonConforming\": \"Non-conforming\",\n \"process.caseTable.conformanceUnknown\": \"Unknown\",\n \"process.caseTable.exportCsv\": \"Export CSV\",\n \"process.caseTable.empty\": \"No cases to display.\",\n \"process.caseTable.tableLabel\": \"Cases\",\n // CaseTimeline (RM-055, issue #204). A thin `charts/Gantt` wrapper — one row\n // per activity instance, waiting time as gap bands, overlapping instances\n // flagged parallel. `parallelLabel` is the non-colour channel WCAG 1.4.1\n // requires alongside the `info` tone the bar itself carries.\n \"process.caseTimeline.label\": \"Case timeline\",\n \"process.caseTimeline.parallelLabel\": \"Parallel\",\n \"process.caseTimeline.parallelSuffix\": \"parallel with another activity\",\n \"process.caseTimeline.gapLabel\": \"Waiting, {duration}\",\n // ProcessCompare (RM-064, issue #211). `{label}` is the HOST-supplied side name\n // (\"Before\"/\"After\", a log's own file name, …), not a fixed \"A\"/\"B\" — see\n // `process-compare.tsx`'s module docblock for why the diff-state words name the\n // owning side instead of a generic letter.\n \"process.compare.label\": \"Process comparison\",\n \"process.compare.tableView\": \"Table view\",\n \"process.compare.mapLabel\": \"Process map — {label}\",\n \"process.compare.superimposedMapLabel\": \"Process map — {aLabel} vs {bLabel}\",\n \"process.compare.legendTitle\": \"Comparison\",\n \"process.compare.diffSuffixCommon\": \"common\",\n \"process.compare.diffSuffixOnly\": \"{label} only\",\n \"process.compare.cases\": \"{label} — cases\",\n \"process.compare.medianThroughput\": \"{label} — median throughput\",\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/tree/tree.tsx"],"sourcesContent":["// a2ui.exposed: yes\n\"use client\";\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { ChevronRight, AlertCircle, RotateCcw } from \"lucide-react\";\nimport { useVirtualizer, type Virtualizer } from \"@tanstack/react-virtual\";\nimport { cn } from \"../../lib/cn\";\nimport { Checkbox } from \"../checkbox/checkbox\";\nimport { useLocale } from \"../locale-provider\";\nimport { Skeleton } from \"../skeleton/skeleton\";\nimport { Spinner } from \"../spinner/spinner\";\nimport { useTreeKeyboard } from \"./use-tree-keyboard\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface TreeNode<T = unknown> {\n id: string;\n label: ReactNode;\n children?: TreeNode<T>[];\n /**\n * Marks a node as expandable even when `children` is not yet loaded.\n * A node with `hasChildren: true` and no `children` array will show the\n * expand affordance. Calling `loadChildren` will populate its children.\n */\n hasChildren?: boolean;\n disabled?: boolean;\n icon?: ReactNode;\n /**\n * Optional trailing content rendered after the label — e.g. a size or\n * token-count badge (#369). Rendered as a SIBLING of the label and kept out\n * of the row's accessible name: a string `label` names the row via\n * `aria-label`, a `ReactNode` label names it via `aria-labelledby` pointing\n * at the label span only, so the accessory text never joins either.\n *\n * The slot is isolated from the row: click, keydown and focus are stopped at\n * the accessory, so it never selects/expands the row, never lets the tree's\n * roving-tabindex handler swallow its keys, and never has focus yanked back\n * to the row. Interactive content (a button, a link) therefore works and is\n * independently focusable in normal tab order; the row's own keyboard\n * navigation (arrow keys, Enter/Space) is unaffected while the row is focused.\n */\n accessory?: ReactNode;\n data?: T;\n}\n\nexport interface TreeProps<T = unknown> extends Omit<HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n nodes: TreeNode<T>[];\n /** Controlled expanded ids */\n expandedIds?: string[];\n /** Uncontrolled initial expanded ids */\n defaultExpandedIds?: string[];\n onExpandedChange?: (ids: string[]) => void;\n /** \"single\" | \"multiple\" | \"none\" — default \"single\" */\n selectionMode?: \"single\" | \"multiple\" | \"none\";\n /** Controlled selected ids */\n selectedIds?: string[];\n /** Uncontrolled initial selected ids */\n defaultSelectedIds?: string[];\n onSelectionChange?: (ids: string[]) => void;\n /** Show checkboxes for multi-selection affordance — default false */\n checkboxes?: boolean;\n /**\n * The surface on which the tree is rendered.\n * - `\"default\"` (default) — renders selected rows with `bg-selection` (for use\n * on background/card surfaces).\n * - `\"sidebar\"` — renders selected rows with the sidebar's own active-item\n * treatment (`bg-sidebar-accent` + `text-sidebar-accent-foreground` +\n * `font-medium`), so selection reads consistently with `SidebarMenuButton`'s\n * active state on the `--sidebar` surface. (No fill is ≥3:1 on a sidebar;\n * perceivability comes from the foreground/weight shift + `aria-selected`,\n * the same multi-cue approach the Sidebar uses.)\n */\n surface?: \"default\" | \"sidebar\";\n /**\n * Enable windowed rendering for large trees (>50 visible rows).\n * When `true`, only the visible slice of the flattened tree is mounted in\n * the DOM. Requires a bounded scroll container — either via `maxHeight` or\n * by sizing the root element externally with `overflow-auto`.\n * Default: `false` (backward-compatible nested-group DOM).\n */\n virtualize?: boolean;\n /** Estimated row height in px used by the virtualizer. Default 32. */\n estimateRowHeight?: number;\n /** Number of extra rows to render beyond the visible window. Default 8. */\n overscan?: number;\n /**\n * CSS max-height for the scroll viewport when `virtualize` is true.\n * E.g. `\"400px\"` or `\"60vh\"`. When omitted the root div must be sized by\n * the caller (e.g. via `className=\"h-96 overflow-auto\"`).\n */\n maxHeight?: number | string;\n /**\n * Scroll the node with this id into view when the value CHANGES. Reveals a\n * node selected programmatically (via `selectedIds`) that is windowed out of\n * the DOM in `virtualize` mode (or below the fold), so the tree shows \"where\n * I am\", not just structure. Expands the node's (loaded) ancestors and kicks\n * their lazy `loadChildren` as needed, then centers the node. Independent of\n * keyboard focus (keyboard nav's own scroll is unchanged).\n */\n scrollToId?: string;\n /**\n * When `true`, reveal the newly-selected controlled node (the id added to\n * `selectedIds`) into view — the selection-driven equivalent of `scrollToId`.\n * `scrollToId` wins when both are set.\n */\n scrollSelectionIntoView?: boolean;\n /**\n * Async function called when a node with `hasChildren: true` (and no\n * loaded `children`) is expanded for the first time. The returned nodes\n * are merged into the internal tree state and cached so re-expanding the\n * node does not re-fetch.\n */\n loadChildren?: (node: TreeNode<T>) => Promise<TreeNode<T>[]>;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types for lazy-load state\n// ---------------------------------------------------------------------------\n\ntype LoadState = \"idle\" | \"loading\" | \"error\";\n\ninterface LazyState {\n [nodeId: string]: LoadState;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction useControllableSet(\n controlled: string[] | undefined,\n defaultValue: string[] | undefined,\n onChange: ((ids: string[]) => void) | undefined,\n): [Set<string>, (next: Set<string>) => void] {\n const isControlled = controlled !== undefined;\n const [internal, setInternal] = useState<Set<string>>(\n () => new Set(controlled ?? defaultValue ?? []),\n );\n\n // Stable controlled Set: build a new Set only when the controlled array's\n // CONTENT actually changed, not merely its reference (many callers pass a\n // freshly-computed array with the same ids on every render). Without this,\n // `selectedIds`/`expandedIds` changed identity on every render, which made\n // effects keyed on them (the scrollToId/scrollSelectionIntoView reveal\n // effect) fire on every re-render instead of on a real selection change —\n // the scroll-jump-while-scrolling bug.\n const controlledSetRef = useRef<Set<string> | null>(null);\n let value: Set<string>;\n if (isControlled) {\n const prev = controlledSetRef.current;\n const sameContent =\n !!prev && prev.size === controlled!.length && controlled!.every((id) => prev.has(id));\n value = sameContent ? prev! : new Set(controlled);\n controlledSetRef.current = value;\n } else {\n value = internal;\n }\n\n const setValue = useCallback(\n (next: Set<string>) => {\n if (!isControlled) setInternal(next);\n onChange?.(Array.from(next));\n },\n [isControlled, onChange],\n );\n\n return [value, setValue];\n}\n\n/**\n * Reconcile an incoming `nodes` prop against the previous internal tree,\n * preserving any children merged in locally via `loadChildren` that the new\n * prop doesn't (yet) carry. Without this, any parent re-render that hands\n * down a new (even structurally-identical) `nodes` array wipes out every\n * lazily-loaded subtree that isn't also present upstream.\n */\nfunction reconcileNodes<T>(propNodes: TreeNode<T>[], prevNodes: TreeNode<T>[]): TreeNode<T>[] {\n const prevById = new Map(prevNodes.map((n) => [n.id, n] as const));\n return propNodes.map((n) => {\n const prev = prevById.get(n.id);\n if (!prev) return n;\n if (!n.children?.length && prev.children?.length) {\n // The prop still marks this node as lazily-expandable but doesn't (yet)\n // carry the children we already fetched — keep what we loaded.\n return { ...n, children: prev.children, hasChildren: n.hasChildren };\n }\n if (n.children?.length && prev.children?.length) {\n return { ...n, children: reconcileNodes(n.children, prev.children) };\n }\n return n;\n });\n}\n\n/** Merge resolved children into a tree, returning a new tree. */\nfunction mergeChildren<T>(\n nodes: TreeNode<T>[],\n nodeId: string,\n children: TreeNode<T>[],\n): TreeNode<T>[] {\n return nodes.map((n) => {\n if (n.id === nodeId) {\n return { ...n, children, hasChildren: undefined };\n }\n if (n.children?.length) {\n return { ...n, children: mergeChildren(n.children, nodeId, children) };\n }\n return n;\n });\n}\n\n// ---------------------------------------------------------------------------\n// VirtualFlatRow — a single flat row for the virtualized path\n// ---------------------------------------------------------------------------\n\ninterface FlatRow<T> {\n node: TreeNode<T>;\n level: number;\n setSize: number;\n posInSet: number;\n}\n\ninterface VirtualFlatRowProps<T> {\n row: FlatRow<T>;\n isExpanded: boolean;\n isSelected: boolean;\n isActive: boolean;\n lazyState: LoadState;\n expandable: boolean; // has children OR hasChildren flag\n selectionMode: \"single\" | \"multiple\" | \"none\";\n checkboxes: boolean;\n surface: \"default\" | \"sidebar\";\n onToggleExpand: (id: string) => void;\n onSelect: (id: string) => void;\n onRetry: (id: string) => void;\n registerNodeRef: (id: string, el: HTMLElement | null) => void;\n setActiveId: (id: string | null) => void;\n}\n\nfunction VirtualFlatRow<T>({\n row,\n isExpanded,\n isSelected,\n isActive,\n lazyState,\n expandable,\n selectionMode,\n checkboxes,\n surface,\n onToggleExpand,\n onSelect,\n onRetry,\n registerNodeRef,\n setActiveId,\n}: VirtualFlatRowProps<T>) {\n const { t } = useLocale();\n const { node, level, setSize, posInSet } = row;\n const isLoading = lazyState === \"loading\";\n const isError = lazyState === \"error\";\n // A ReactNode label can't name the row via `aria-label`, so without this the\n // name would fall back to the row's CONTENTS — which includes the accessory\n // (#369). Point at the label span instead, so the accessory is excluded for\n // BOTH label shapes.\n const labelId = useId();\n\n const indentStyle = { paddingLeft: `${(level - 1) * 1}rem` };\n\n const handleRowClick = () => {\n if (node.disabled) return;\n setActiveId(node.id);\n onSelect(node.id);\n if (expandable) onToggleExpand(node.id);\n };\n\n return (\n <div\n role=\"treeitem\"\n aria-expanded={expandable ? isExpanded : undefined}\n aria-selected={selectionMode !== \"none\" && !checkboxes ? isSelected : undefined}\n aria-checked={checkboxes ? isSelected : undefined}\n aria-label={typeof node.label === \"string\" ? node.label : undefined}\n aria-labelledby={typeof node.label === \"string\" ? undefined : labelId}\n aria-level={level}\n aria-setsize={setSize}\n aria-posinset={posInSet}\n aria-disabled={node.disabled ? true : undefined}\n aria-busy={isLoading ? true : undefined}\n tabIndex={isActive ? 0 : -1}\n data-tree-id={node.id}\n ref={(el) => registerNodeRef(node.id, el)}\n onClick={node.disabled ? undefined : handleRowClick}\n onFocus={() => setActiveId(node.id)}\n className={cn(\n \"flex min-w-0 cursor-pointer select-none items-center gap-1.5 rounded-md px-2 py-1.5 text-body outline-none\",\n \"transition-colors duration-fast ease-standard motion-reduce:transition-none\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background\",\n isSelected &&\n selectionMode !== \"none\" &&\n (surface === \"sidebar\"\n ? \"bg-sidebar-accent text-sidebar-accent-foreground font-medium\"\n : \"bg-selection text-selection-foreground font-medium\"),\n node.disabled && \"cursor-not-allowed opacity-50 pointer-events-none\",\n )}\n style={indentStyle}\n >\n {/* expand/collapse chevron */}\n {expandable ? (\n <span\n aria-hidden=\"true\"\n onClick={(e) => {\n e.stopPropagation();\n onToggleExpand(node.id);\n }}\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded transition-transform duration-fast ease-standard motion-reduce:transition-none\",\n isExpanded && \"rotate-90\",\n )}\n >\n {isLoading ? (\n <Spinner className=\"size-3.5\" label=\"Loading children\" />\n ) : (\n <ChevronRight className=\"size-3.5 text-muted-foreground\" aria-hidden=\"true\" />\n )}\n </span>\n ) : (\n <span aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n )}\n\n {/* optional checkbox for multi-select */}\n {checkboxes && selectionMode === \"multiple\" && (\n <Checkbox\n checked={isSelected}\n disabled={node.disabled}\n aria-hidden=\"true\"\n tabIndex={-1}\n onClick={(e) => {\n e.stopPropagation();\n onSelect(node.id);\n }}\n className=\"shrink-0\"\n />\n )}\n\n {/* optional node icon */}\n {node.icon && (\n <span aria-hidden=\"true\" className=\"flex size-4 shrink-0 items-center justify-center\">\n {node.icon}\n </span>\n )}\n\n {/* label */}\n {isError ? (\n // #124: running text (\"Failed to load…\"), not a mark — the ink rung\n // clears >=4.5:1 and the wrapped icon inherits it fine (>=3:1 trivially).\n <span id={labelId} className=\"min-w-0 flex items-center gap-1 text-destructive-text\">\n <AlertCircle className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{t(\"ui.tree.failedToLoad\")}</span>\n <button\n type=\"button\"\n aria-label={t(\"ui.tree.retryLoadingChildren\")}\n onClick={(e) => {\n e.stopPropagation();\n onRetry(node.id);\n }}\n className={cn(\n \"ms-1 flex items-center gap-0.5 rounded px-1 py-0.5 text-caption\",\n \"text-muted-foreground hover:text-foreground\",\n \"focus-ring\",\n )}\n >\n <RotateCcw className=\"size-3\" aria-hidden=\"true\" />\n {t(\"ui.tree.retry\")}\n </button>\n </span>\n ) : (\n <span id={labelId} className=\"min-w-0 truncate\">\n {node.label}\n </span>\n )}\n\n {/* optional trailing accessory — a sibling of the label, never inside it\n and never part of the row's accessible name (#369); click/keydown/focus\n are stopped so it never selects, expands or steals the row's handling. */}\n {node.accessory ? (\n <span\n data-slot=\"tree-item-accessory\"\n className=\"ms-auto flex shrink-0 items-center gap-1\"\n onClick={(e) => e.stopPropagation()}\n // The tree's keyboard handler lives on the ROOT and preventDefaults\n // Enter/Space/arrows; without this an interactive accessory could\n // never be activated (its native click is cancelled) and the ROW\n // would be selected instead.\n onKeyDown={(e) => e.stopPropagation()}\n // React's onFocus is focusin (it bubbles), and the row's handler\n // calls setActiveId → el.focus(), which would yank focus straight\n // back out of an interactive accessory.\n onFocus={(e) => e.stopPropagation()}\n >\n {node.accessory}\n </span>\n ) : null}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Lazy-loading skeleton row (child of a loading node in non-virtual path)\n// ---------------------------------------------------------------------------\n\nfunction LoadingRow({ level }: { level: number }) {\n const { t } = useLocale();\n const indentStyle = { paddingLeft: `${(level - 1) * 1}rem` };\n return (\n <div\n role=\"treeitem\"\n aria-label={t(\"loading\")}\n aria-disabled=\"true\"\n tabIndex={-1}\n className=\"flex min-w-0 items-center gap-1.5 px-2 py-1.5\"\n style={indentStyle}\n >\n <span aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n <Skeleton className=\"h-4 w-24\" />\n </div>\n );\n}\n\nfunction ErrorRow({ level, onRetry }: { level: number; onRetry: () => void }) {\n const { t } = useLocale();\n const indentStyle = { paddingLeft: `${(level - 1) * 1}rem` };\n return (\n <div\n role=\"treeitem\"\n aria-label={t(\"ui.tree.failedToLoad\")}\n aria-disabled=\"true\"\n tabIndex={-1}\n className=\"flex min-w-0 items-center gap-1.5 px-2 py-1.5 text-body text-destructive-text\"\n style={indentStyle}\n >\n <span aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n <AlertCircle className=\"size-3.5 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{t(\"ui.tree.failedToLoad\")}</span>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onRetry();\n }}\n className={cn(\n \"ms-1 flex items-center gap-0.5 rounded px-1 py-0.5 text-meta\",\n \"text-muted-foreground hover:text-foreground\",\n \"focus-ring\",\n )}\n >\n <RotateCcw className=\"size-3\" aria-hidden=\"true\" />\n {t(\"ui.tree.retry\")}\n </button>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// TreeItemRow — renders a single treeitem row (recursive, non-virtual path)\n// ---------------------------------------------------------------------------\n\ninterface TreeItemProps<T> {\n node: TreeNode<T>;\n level: number;\n setSize: number;\n posInSet: number;\n expandedIds: Set<string>;\n onExpandedChange: (ids: Set<string>) => void;\n selectionMode: \"single\" | \"multiple\" | \"none\";\n selectedIds: Set<string>;\n onSelectionChange: (ids: Set<string>) => void;\n checkboxes: boolean;\n surface: \"default\" | \"sidebar\";\n activeId: string | null;\n setActiveId: (id: string | null) => void;\n registerNodeRef: (id: string, el: HTMLElement | null) => void;\n lazyState: LazyState;\n onExpandLazy: (node: TreeNode<T>) => void;\n}\n\nfunction TreeItem<T>({\n node,\n level,\n setSize,\n posInSet,\n expandedIds,\n onExpandedChange,\n selectionMode,\n selectedIds,\n onSelectionChange,\n checkboxes,\n surface,\n activeId,\n setActiveId,\n registerNodeRef,\n lazyState,\n onExpandLazy,\n}: TreeItemProps<T>) {\n const hasLoadedChildren = !!node.children?.length;\n // A node is expandable if it has loaded children OR the hasChildren flag is set\n const expandable = hasLoadedChildren || !!node.hasChildren;\n const isExpanded = expandable && expandedIds.has(node.id);\n const isSelected = selectedIds.has(node.id);\n const isActive = activeId === node.id;\n const nodeLoadState: LoadState = lazyState[node.id] ?? \"idle\";\n const isLoading = nodeLoadState === \"loading\";\n const isError = nodeLoadState === \"error\";\n // See VirtualFlatRow: a ReactNode label must name the row via `aria-labelledby`\n // so the trailing accessory never joins the accessible name (#369).\n const labelId = useId();\n\n const toggleExpanded = () => {\n if (!expandable) return;\n const next = new Set(expandedIds);\n if (isExpanded) {\n next.delete(node.id);\n } else {\n next.add(node.id);\n // If no loaded children yet, trigger lazy load\n if (!hasLoadedChildren && node.hasChildren) {\n onExpandLazy(node);\n }\n }\n onExpandedChange(next);\n };\n\n const handleSelect = () => {\n if (node.disabled || selectionMode === \"none\") return;\n setActiveId(node.id);\n if (selectionMode === \"single\") {\n onSelectionChange(new Set([node.id]));\n } else {\n const next = new Set(selectedIds);\n if (next.has(node.id)) {\n next.delete(node.id);\n } else {\n next.add(node.id);\n }\n onSelectionChange(next);\n }\n };\n\n const handleRowClick = () => {\n setActiveId(node.id);\n handleSelect();\n if (expandable) toggleExpanded();\n };\n\n const indentStyle = { paddingLeft: `${(level - 1) * 1}rem` };\n\n return (\n <li role=\"none\">\n {/* treeitem row */}\n <div\n role=\"treeitem\"\n aria-expanded={expandable ? isExpanded : undefined}\n aria-selected={selectionMode !== \"none\" && !checkboxes ? isSelected : undefined}\n aria-checked={checkboxes ? isSelected : undefined}\n aria-label={typeof node.label === \"string\" ? node.label : undefined}\n aria-labelledby={typeof node.label === \"string\" ? undefined : labelId}\n aria-level={level}\n aria-setsize={setSize}\n aria-posinset={posInSet}\n aria-disabled={node.disabled ? true : undefined}\n aria-busy={isLoading ? true : undefined}\n tabIndex={isActive ? 0 : -1}\n data-tree-id={node.id}\n ref={(el) => registerNodeRef(node.id, el)}\n onClick={node.disabled ? undefined : handleRowClick}\n onFocus={() => setActiveId(node.id)}\n className={cn(\n \"flex min-w-0 cursor-pointer select-none items-center gap-1.5 rounded-md px-2 py-1.5 text-body outline-none\",\n \"transition-colors duration-fast ease-standard motion-reduce:transition-none\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background\",\n isSelected &&\n selectionMode !== \"none\" &&\n (surface === \"sidebar\"\n ? \"bg-sidebar-accent text-sidebar-accent-foreground font-medium\"\n : \"bg-selection text-selection-foreground font-medium\"),\n node.disabled && \"cursor-not-allowed opacity-50 pointer-events-none\",\n )}\n style={indentStyle}\n >\n {/* expand/collapse chevron */}\n {expandable ? (\n <span\n aria-hidden=\"true\"\n onClick={(e) => {\n e.stopPropagation();\n toggleExpanded();\n }}\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded transition-transform duration-fast ease-standard motion-reduce:transition-none\",\n isExpanded && !isLoading && \"rotate-90\",\n )}\n >\n {isLoading ? (\n <Spinner className=\"size-3.5\" label=\"Loading children\" />\n ) : (\n <ChevronRight className=\"size-3.5 text-muted-foreground\" aria-hidden=\"true\" />\n )}\n </span>\n ) : (\n <span aria-hidden=\"true\" className=\"size-4 shrink-0\" />\n )}\n\n {/* optional checkbox for multi-select */}\n {checkboxes && selectionMode === \"multiple\" && (\n <Checkbox\n checked={isSelected}\n disabled={node.disabled}\n aria-hidden=\"true\"\n tabIndex={-1}\n onClick={(e) => {\n e.stopPropagation();\n handleSelect();\n }}\n className=\"shrink-0\"\n />\n )}\n\n {/* optional node icon */}\n {node.icon && (\n <span aria-hidden=\"true\" className=\"flex size-4 shrink-0 items-center justify-center\">\n {node.icon}\n </span>\n )}\n\n {/* label */}\n <span id={labelId} className=\"min-w-0 truncate\">\n {node.label}\n </span>\n\n {/* optional trailing accessory — a sibling of the label, never inside\n it and never part of the row's accessible name (#369);\n click/keydown/focus are stopped at the accessory. */}\n {node.accessory ? (\n <span\n data-slot=\"tree-item-accessory\"\n className=\"ms-auto flex shrink-0 items-center gap-1\"\n onClick={(e) => e.stopPropagation()}\n // See VirtualFlatRow: the tree's root keydown handler preventDefaults\n // Enter/Space/arrows, and the row's onFocus (focusin, bubbling) calls\n // setActiveId → el.focus(). Both must stop at the accessory or\n // interactive content in this slot is unusable.\n onKeyDown={(e) => e.stopPropagation()}\n onFocus={(e) => e.stopPropagation()}\n >\n {node.accessory}\n </span>\n ) : null}\n </div>\n\n {/* children group */}\n {isExpanded && (\n <ul role=\"group\" className=\"list-none m-0 p-0\">\n {isLoading ? (\n <li role=\"none\">\n <LoadingRow level={level + 1} />\n </li>\n ) : isError ? (\n <li role=\"none\">\n <ErrorRow level={level + 1} onRetry={() => onExpandLazy(node)} />\n </li>\n ) : (\n node.children?.map((child, i) => (\n <TreeItem\n key={child.id}\n node={child}\n level={level + 1}\n setSize={node.children!.length}\n posInSet={i + 1}\n expandedIds={expandedIds}\n onExpandedChange={onExpandedChange}\n selectionMode={selectionMode}\n selectedIds={selectedIds}\n onSelectionChange={onSelectionChange}\n checkboxes={checkboxes}\n surface={surface}\n activeId={activeId}\n setActiveId={setActiveId}\n registerNodeRef={registerNodeRef}\n lazyState={lazyState}\n onExpandLazy={onExpandLazy}\n />\n ))\n )}\n </ul>\n )}\n </li>\n );\n}\n\n// ---------------------------------------------------------------------------\n// flattenVisibleWithMeta — for the virtual path\n// ---------------------------------------------------------------------------\n\nfunction flattenVisibleWithMeta<T>(\n nodes: TreeNode<T>[],\n expandedIds: Set<string>,\n lazyState: LazyState,\n level = 1,\n parentSetSize?: number,\n): FlatRow<T>[] {\n const result: FlatRow<T>[] = [];\n const setSize = parentSetSize ?? nodes.length;\n nodes.forEach((node, i) => {\n result.push({\n node,\n level,\n setSize,\n posInSet: i + 1,\n });\n const hasLoadedChildren = !!node.children?.length;\n const isExpandable = hasLoadedChildren || !!node.hasChildren;\n if (isExpandable && expandedIds.has(node.id)) {\n const nodeLoad = lazyState[node.id];\n if (nodeLoad === \"loading\" || nodeLoad === \"error\") {\n // placeholder row represented by a synthetic \"loading/error\" node\n // We don't push a row here — the loading/error state is shown via\n // aria-busy on the parent treeitem row (virtual path inline indicators)\n } else if (hasLoadedChildren) {\n const childRows = flattenVisibleWithMeta(\n node.children!,\n expandedIds,\n lazyState,\n level + 1,\n node.children!.length,\n );\n result.push(...childRows);\n }\n }\n });\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Tree — root component\n// ---------------------------------------------------------------------------\n\n/**\n * A fully accessible tree view with roving tabindex keyboard navigation,\n * single/multiple selection, expand/collapse, checkboxes, and type-ahead.\n *\n * Set `virtualize` to window large trees (>50 visible rows). Set `loadChildren`\n * to lazily fetch children on demand when a node has `hasChildren: true`.\n */\n/** Ancestor ids (root → parent) of `id` within the loaded tree, or `null` if absent. */\nfunction findNodePath(nodes: TreeNode[], id: string, trail: string[] = []): string[] | null {\n for (const n of nodes) {\n if (n.id === id) return trail;\n if (n.children?.length) {\n const found = findNodePath(n.children, id, [...trail, n.id]);\n if (found) return found;\n }\n }\n return null;\n}\n\n/** The node with `id` within the loaded tree, or `null`. */\nfunction findNodeById(nodes: TreeNode[], id: string): TreeNode | null {\n for (const n of nodes) {\n if (n.id === id) return n;\n if (n.children?.length) {\n const found = findNodeById(n.children, id);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport const Tree = forwardRef<HTMLDivElement, TreeProps>(function Tree(\n {\n nodes: nodesProp,\n expandedIds: expandedIdsProp,\n defaultExpandedIds,\n onExpandedChange,\n selectionMode = \"single\",\n selectedIds: selectedIdsProp,\n defaultSelectedIds,\n onSelectionChange,\n checkboxes = false,\n virtualize = false,\n estimateRowHeight = 32,\n overscan = 8,\n maxHeight,\n scrollToId,\n scrollSelectionIntoView = false,\n loadChildren,\n surface = \"default\",\n className,\n ...props\n },\n ref,\n) {\n // Internal mutable tree (supports lazy-loaded children merge)\n const [nodes, setNodes] = useState<TreeNode[]>(() => nodesProp as TreeNode[]);\n\n // Keep internal tree in sync with nodesProp if it changes externally,\n // preserving any children merged in locally via lazy `loadChildren`.\n useEffect(() => {\n setNodes((prev) => reconcileNodes(nodesProp as TreeNode[], prev));\n }, [nodesProp]);\n\n const [expandedIds, setExpandedIds] = useControllableSet(\n expandedIdsProp,\n defaultExpandedIds,\n onExpandedChange,\n );\n const [selectedIds, setSelectedIds] = useControllableSet(\n selectedIdsProp,\n defaultSelectedIds,\n onSelectionChange,\n );\n\n // Lazy-load state per node id\n const [lazyState, setLazyState] = useState<LazyState>({});\n\n // Scroll container ref for virtualizer\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Pending focus id — used when the target row isn't yet mounted (virtual path)\n const pendingFocusIdRef = useRef<string | null>(null);\n\n // ---------------------------------------------------------------------------\n // Lazy load handler\n // ---------------------------------------------------------------------------\n\n const handleExpandLazy = useCallback(\n async (node: TreeNode) => {\n if (!loadChildren) return;\n if (lazyState[node.id] === \"loading\") return;\n\n setLazyState((prev) => ({ ...prev, [node.id]: \"loading\" }));\n try {\n const children = await loadChildren(node as TreeNode<unknown>);\n setNodes((prev) => mergeChildren(prev, node.id, children as TreeNode[]));\n setLazyState((prev) => {\n const next = { ...prev };\n delete next[node.id];\n return next;\n });\n } catch {\n setLazyState((prev) => ({ ...prev, [node.id]: \"error\" }));\n }\n },\n [loadChildren, lazyState],\n );\n\n // ---------------------------------------------------------------------------\n // Flattened visible rows (for virtualized path and keyboard hook)\n // ---------------------------------------------------------------------------\n\n const flatRows = useMemo(\n () => flattenVisibleWithMeta(nodes, expandedIds, lazyState),\n [nodes, expandedIds, lazyState],\n );\n const flatNodeIds = useMemo(() => flatRows.map((r) => r.node.id), [flatRows]);\n // O(1) row lookup by id — `handleToggleExpand`/`handleSelectVirtual` run on\n // every click/keypress and previously did an O(n) `Array.find` each time.\n const flatRowIndexById = useMemo(() => {\n const map = new Map<string, number>();\n flatRows.forEach((r, i) => map.set(r.node.id, i));\n return map;\n }, [flatRows]);\n\n // ---------------------------------------------------------------------------\n // Keyboard hook\n // ---------------------------------------------------------------------------\n\n // For the virtual path: when navigating to a node whose DOM is not mounted,\n // we need to scroll to it first and then focus when it mounts.\n // We achieve this by passing a scrollToIndex callback to the keyboard hook.\n\n const virtualizerRef = useRef<Virtualizer<HTMLDivElement, Element> | null>(null);\n\n const scrollToVirtualIndex = useCallback((index: number) => {\n virtualizerRef.current?.scrollToIndex(index, { align: \"auto\" });\n }, []);\n\n const { activeId, setActiveId, registerNodeRef, onKeyDown } = useTreeKeyboard({\n nodes,\n expandedIds,\n onExpandedChange: setExpandedIds,\n selectionMode,\n selectedIds,\n onSelectionChange: setSelectedIds,\n // Virtualization-aware extras\n virtualize,\n flatNodeIds,\n pendingFocusIdRef,\n scrollToVirtualIndex,\n });\n\n // ---------------------------------------------------------------------------\n // Handle expand/collapse for virtual path (needs to call lazy loader)\n // ---------------------------------------------------------------------------\n\n const handleToggleExpand = useCallback(\n (nodeId: string) => {\n const index = flatRowIndexById.get(nodeId);\n if (index === undefined) return;\n const node = flatRows[index]?.node;\n if (!node) return;\n const hasLoadedChildren = !!node.children?.length;\n const next = new Set(expandedIds);\n if (expandedIds.has(nodeId)) {\n next.delete(nodeId);\n } else {\n next.add(nodeId);\n if (!hasLoadedChildren && node.hasChildren && loadChildren) {\n handleExpandLazy(node);\n }\n }\n setExpandedIds(next);\n },\n [expandedIds, flatRows, flatRowIndexById, setExpandedIds, loadChildren, handleExpandLazy],\n );\n\n const handleSelectVirtual = useCallback(\n (nodeId: string) => {\n const index = flatRowIndexById.get(nodeId);\n if (index === undefined) return;\n const node = flatRows[index]?.node;\n if (!node || node.disabled || selectionMode === \"none\") return;\n if (selectionMode === \"single\") {\n setSelectedIds(new Set([nodeId]));\n } else {\n const next = new Set(selectedIds);\n if (next.has(nodeId)) {\n next.delete(nodeId);\n } else {\n next.add(nodeId);\n }\n setSelectedIds(next);\n }\n },\n [flatRows, flatRowIndexById, selectionMode, selectedIds, setSelectedIds],\n );\n\n // ---------------------------------------------------------------------------\n // Layout effect to flush pending focus once a row mounts (virtual path)\n // ---------------------------------------------------------------------------\n\n // This runs after every render; if pendingFocusIdRef has an id, try to focus it.\n // The registerNodeRef callback will have stored the element if it mounted.\n // We use useLayoutEffect so the DOM is painted before we try to focus.\n const nodeRefsForFlush = useRef<Map<string, HTMLElement>>(new Map());\n\n const registerAndFlush = useCallback(\n (id: string, el: HTMLElement | null) => {\n registerNodeRef(id, el);\n if (el) {\n nodeRefsForFlush.current.set(id, el);\n if (pendingFocusIdRef.current === id) {\n pendingFocusIdRef.current = null;\n el.focus();\n }\n } else {\n nodeRefsForFlush.current.delete(id);\n }\n },\n [registerNodeRef],\n );\n\n // ---------------------------------------------------------------------------\n // Virtualizer (only created in virtual mode)\n // ---------------------------------------------------------------------------\n\n const virtualizer = useVirtualizer({\n count: flatRows.length,\n getScrollElement: () => (virtualize ? scrollRef.current : null),\n estimateSize: () => estimateRowHeight,\n overscan,\n enabled: virtualize,\n });\n\n // Keep ref so keyboard handler can call scrollToIndex\n useEffect(() => {\n if (virtualize) {\n virtualizerRef.current = virtualizer;\n }\n });\n\n // ---------------------------------------------------------------------------\n // Reveal-into-view (scrollToId / scrollSelectionIntoView)\n // ---------------------------------------------------------------------------\n\n // Set while a requested node isn't yet a visible row (its ancestors are still\n // expanding / lazy-loading); the retry effect finishes once the rows change.\n const pendingRevealIdRef = useRef<string | null>(null);\n const prevSelectedRef = useRef<Set<string>>(selectedIds);\n const prevScrollToIdRef = useRef<string | undefined>(undefined);\n\n // Scroll `id` into view if it is currently a visible row. Virtual mode drives\n // the virtualizer (the row may be unmounted); non-virtual uses the mounted DOM\n // node (registered via registerAndFlush in both paths).\n const scrollNodeIntoView = useCallback(\n (id: string): boolean => {\n const index = flatRowIndexById.get(id);\n if (index === undefined) return false;\n if (virtualize) {\n virtualizerRef.current?.scrollToIndex(index, { align: \"center\" });\n } else {\n // `?.` on scrollIntoView too — jsdom doesn't implement it (browser-only).\n nodeRefsForFlush.current.get(id)?.scrollIntoView?.({ block: \"center\" });\n }\n return true;\n },\n [flatRowIndexById, virtualize],\n );\n\n // Reveal `id`: scroll it now if visible, else expand its (loaded) ancestors and\n // kick their lazy loaders so it becomes a row — the retry effect finishes the job.\n const revealNode = useCallback(\n (id: string) => {\n if (scrollNodeIntoView(id)) {\n pendingRevealIdRef.current = null;\n return;\n }\n pendingRevealIdRef.current = id;\n const path = findNodePath(nodes, id);\n if (!path || path.length === 0) return; // unknown / not yet loaded — best effort\n const next = new Set(expandedIds);\n path.forEach((ancestorId) => next.add(ancestorId));\n setExpandedIds(next);\n if (loadChildren) {\n for (const ancestorId of path) {\n const anc = findNodeById(nodes, ancestorId);\n if (anc && anc.hasChildren && !anc.children?.length) void handleExpandLazy(anc);\n }\n }\n },\n [scrollNodeIntoView, nodes, expandedIds, setExpandedIds, loadChildren, handleExpandLazy],\n );\n\n // Latest revealNode so the trigger effect fires on target CHANGE only (without\n // re-running when flatNodeIds / expandedIds churn each render).\n const revealNodeRef = useRef(revealNode);\n revealNodeRef.current = revealNode;\n\n // Trigger: reveal when `scrollToId` changes; else (scrollSelectionIntoView) when\n // the selection gains a node. `scrollToId` wins.\n useEffect(() => {\n const scrollIdChanged = scrollToId !== prevScrollToIdRef.current;\n const selectionChanged = selectedIds !== prevSelectedRef.current;\n const prevSel = prevSelectedRef.current;\n prevScrollToIdRef.current = scrollToId;\n prevSelectedRef.current = selectedIds;\n\n if (scrollToId != null && scrollIdChanged) {\n revealNodeRef.current(scrollToId);\n } else if (scrollToId == null && scrollSelectionIntoView && selectionChanged) {\n const added = [...selectedIds].find((sid) => !prevSel.has(sid));\n const target = added ?? (selectedIds.size > 0 ? [...selectedIds][0] : undefined);\n if (target != null) revealNodeRef.current(target);\n }\n }, [scrollToId, scrollSelectionIntoView, selectedIds]);\n\n // Retry a pending reveal after the rows change (ancestors expanded / lazy data\n // arrived) — scroll once the node materialises, then clear.\n useEffect(() => {\n const id = pendingRevealIdRef.current;\n if (id != null && scrollNodeIntoView(id)) {\n pendingRevealIdRef.current = null;\n }\n }, [scrollNodeIntoView]);\n\n // ---------------------------------------------------------------------------\n // Render: NON-virtual path (backward compatible nested-group DOM)\n // ---------------------------------------------------------------------------\n\n if (!virtualize) {\n return (\n <div\n ref={ref}\n role=\"tree\"\n aria-multiselectable={selectionMode === \"multiple\" ? true : undefined}\n onKeyDown={onKeyDown}\n className={cn(\"w-full select-none\", className)}\n {...props}\n >\n <ul role=\"none\" className=\"m-0 list-none p-0\">\n {nodes.map((node, i) => (\n <TreeItem\n key={node.id}\n node={node}\n level={1}\n setSize={nodes.length}\n posInSet={i + 1}\n expandedIds={expandedIds}\n onExpandedChange={setExpandedIds}\n selectionMode={selectionMode}\n selectedIds={selectedIds}\n onSelectionChange={setSelectedIds}\n checkboxes={checkboxes}\n surface={surface}\n activeId={activeId}\n setActiveId={setActiveId}\n // registerAndFlush (not raw registerNodeRef) so nodeRefsForFlush is\n // populated in the non-virtual path too — lets scrollToId reveal a\n // below-the-fold node. pendingFocusIdRef is virtual-only, so the\n // focus-flush branch never fires here: keyboard behavior is unchanged.\n registerNodeRef={registerAndFlush}\n lazyState={lazyState}\n onExpandLazy={handleExpandLazy}\n />\n ))}\n </ul>\n </div>\n );\n }\n\n // ---------------------------------------------------------------------------\n // Render: VIRTUAL path (flat DOM, windowed rows)\n // ---------------------------------------------------------------------------\n\n const virtualItems = virtualizer.getVirtualItems();\n\n const scrollStyle: React.CSSProperties = maxHeight\n ? { maxHeight, overflowY: \"auto\" }\n : { overflowY: \"auto\" };\n\n return (\n <div\n ref={ref}\n role=\"tree\"\n aria-multiselectable={selectionMode === \"multiple\" ? true : undefined}\n onKeyDown={onKeyDown}\n className={cn(\"w-full select-none\", className)}\n {...props}\n >\n {/* Scroll viewport — role=\"presentation\" so the tree still OWNS the\n treeitems (windowing wrappers are skipped in the a11y tree, keeping\n aria-required-children valid). */}\n <div ref={scrollRef} role=\"presentation\" style={scrollStyle} className=\"outline-none\">\n {/* Total-size spacer — gives the scroll container its full height */}\n <div\n role=\"presentation\"\n style={{ height: virtualizer.getTotalSize(), position: \"relative\" }}\n >\n {virtualItems.map((virtualRow) => {\n const row = flatRows[virtualRow.index];\n if (!row) return null;\n const { node } = row;\n const hasLoadedChildren = !!node.children?.length;\n const expandable = hasLoadedChildren || !!node.hasChildren;\n const isExpanded = expandable && expandedIds.has(node.id);\n const isSelected = selectedIds.has(node.id);\n const isActive = activeId === node.id;\n const nodeLoad: LoadState = lazyState[node.id] ?? \"idle\";\n\n return (\n <div\n key={virtualRow.key}\n role=\"presentation\"\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: `${virtualRow.size}px`,\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <VirtualFlatRow\n row={row}\n isExpanded={isExpanded}\n isSelected={isSelected}\n isActive={isActive}\n lazyState={nodeLoad}\n expandable={expandable}\n selectionMode={selectionMode}\n checkboxes={checkboxes}\n surface={surface}\n onToggleExpand={handleToggleExpand}\n onSelect={handleSelectVirtual}\n onRetry={() => handleExpandLazy(node)}\n registerNodeRef={registerAndFlush}\n setActiveId={setActiveId}\n />\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n}) as <T = unknown>(\n props: TreeProps<T> & { ref?: React.Ref<HTMLDivElement> },\n) => React.ReactElement | null;\n"],"mappings":"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","names":["Tree"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cn.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\n/**\n * The semantic type roles (`--text-<role>` tokens → `text-<role>` utilities, #187).\n * tailwind-merge doesn't know custom theme keys, so without registration it\n * classifies `text-title` as a text COLOR — and `cn(\"text-kpi\", \"text-foreground\")`\n * would silently drop the role. Registering the roles in the `font-size` class\n * group makes role-vs-role and role-vs-raw-size conflicts resolve correctly while\n * keeping role + color independent.\n */\nconst TEXT_ROLES = [\n \"display-lg\",\n \"display\",\n \"title\",\n \"subtitle\",\n \"body\",\n \"caption\",\n \"meta\",\n \"eyebrow\",\n \"heading-xs\",\n \"kpi\",\n \"kpi-sm\",\n \"code\",\n];\n\n/**\n * Tailwind v4's CSS-variable shorthand (`leading-(--card-title-leading)`).\n * tailwind-merge 2.x predates it and leaves such a class beside a caller's\n * `leading-tight`, letting stylesheet order pick the winner. A typed hint\n * (`text-(length:--x)`) is read as a variant prefix by 2.x and cannot be\n * registered — give that seam a named `@theme` utility instead\n * (`text-table-header`).\n */\nconst isVarShorthand = (value: string) => /^\\(--[\\w-]+\\)$/.test(value);\n\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n \"font-size\": [{ text: [...TEXT_ROLES, \"table-header\"] }],\n leading: [{ leading: [isVarShorthand] }],\n tracking: [{ tracking: [isVarShorthand] }],\n // `font-display` is the display-face seam (sibling of font-mono, #187).\n \"font-family\": [{ font: [\"display\"] }],\n // Theme-driven control/table/surface knobs (themes.css § CONTROL UTILITIES\n // and the `@theme inline` bridge) — so a caller's `h-8` / `rounded-none` /\n // `font-bold` / `shadow-none` still replaces the token default.\n \"font-weight\": [{ font: [\"control\", \"table-header\", \"tabs-active\"] }],\n rounded: [{ rounded: [\"control\", \"badge\"] }],\n shadow: [{ shadow: [\"input\", \"card\", \"popover\", \"dialog\"] }],\n h: [{ h: [\"control\", \"control-sm\", \"control-lg\", \"header\"] }],\n size: [{ size: [\"control\", \"control-sm\", \"control-lg\"] }],\n \"min-w\": [{ \"min-w\": [\"control\", \"control-sm\", \"control-lg\"] }],\n },\n },\n});\n\n/**\n * Merge class names with conflict resolution. `clsx` handles conditionals;\n * `tailwind-merge` ensures later Tailwind utilities win (e.g. `p-2 p-4` -> `p-4`).\n * Use this in every component that accepts a `className` prop.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;AAAA,SAAS,YAA6B;AACtC,SAAS,2BAA2B;AAUpC,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUA,IAAM,iBAAiB,CAAC,UAAkB,iBAAiB,KAAK,KAAK;AAErE,IAAM,UAAU,oBAAoB;AAAA,EAClC,QAAQ;AAAA,IACN,aAAa;AAAA,MACX,aAAa,CAAC,EAAE,MAAM,CAAC,GAAG,YAAY,cAAc,EAAE,CAAC;AAAA,MACvD,SAAS,CAAC,EAAE,SAAS,CAAC,cAAc,EAAE,CAAC;AAAA,MACvC,UAAU,CAAC,EAAE,UAAU,CAAC,cAAc,EAAE,CAAC;AAAA;AAAA,MAEzC,eAAe,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA,MAIrC,eAAe,CAAC,EAAE,MAAM,CAAC,WAAW,gBAAgB,aAAa,EAAE,CAAC;AAAA,MACpE,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,OAAO,EAAE,CAAC;AAAA,MAC3C,QAAQ,CAAC,EAAE,QAAQ,CAAC,SAAS,QAAQ,WAAW,QAAQ,EAAE,CAAC;AAAA,MAC3D,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,cAAc,cAAc,QAAQ,EAAE,CAAC;AAAA,MAC5D,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,cAAc,YAAY,EAAE,CAAC;AAAA,MACxD,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,cAAc,YAAY,EAAE,CAAC;AAAA,IAChE;AAAA,EACF;AACF,CAAC;AAOM,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
|
package/dist/chunk-OZTM6PYF.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import {
|
|
3
|
-
cn
|
|
4
|
-
} from "./chunk-KBNWM27Q.js";
|
|
5
|
-
|
|
6
|
-
// src/components/section-header/section-header.tsx
|
|
7
|
-
import "react";
|
|
8
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
function SectionHeader({
|
|
10
|
-
title,
|
|
11
|
-
description,
|
|
12
|
-
actions,
|
|
13
|
-
eyebrow,
|
|
14
|
-
as: TitleTag = "h2",
|
|
15
|
-
className
|
|
16
|
-
}) {
|
|
17
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-end justify-between gap-4", className), children: [
|
|
18
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
19
|
-
eyebrow ? /* @__PURE__ */ jsx("div", { className: "text-eyebrow uppercase text-muted-foreground", children: eyebrow }) : null,
|
|
20
|
-
/* @__PURE__ */ jsx(TitleTag, { className: "text-title text-foreground", children: title }),
|
|
21
|
-
description ? /* @__PURE__ */ jsx("p", { className: "text-body text-muted-foreground", children: description }) : null
|
|
22
|
-
] }),
|
|
23
|
-
actions ? /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: actions }) : null
|
|
24
|
-
] });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export {
|
|
28
|
-
SectionHeader
|
|
29
|
-
};
|
|
30
|
-
//# sourceMappingURL=chunk-OZTM6PYF.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/section-header/section-header.tsx"],"sourcesContent":["import { type ReactNode } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport interface SectionHeaderProps {\n title: ReactNode;\n description?: ReactNode;\n /** Right-aligned actions (buttons, menus). */\n actions?: ReactNode;\n /** Optional element rendered above the title (eyebrow / breadcrumbs). */\n eyebrow?: ReactNode;\n /**\n * The heading LEVEL the title contributes to the document outline. The\n * visual (`text-title`) is identical for every value — pick the level the\n * page's structure calls for, not the size you want (WCAG 1.3.1).\n *\n * Use `as=\"h1\"` when this header titles the PAGE (a screen whose route it\n * names); leave it at the default when it titles a section INSIDE a page\n * that already has an `<h1>` elsewhere. @default \"h2\"\n */\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\";\n className?: string;\n}\n\n/** A consistent page/section heading row with optional actions. */\nexport function SectionHeader({\n title,\n description,\n actions,\n eyebrow,\n as: TitleTag = \"h2\",\n className,\n}: SectionHeaderProps) {\n return (\n <div className={cn(\"flex flex-wrap items-end justify-between gap-4\", className)}>\n <div className=\"space-y-1\">\n {eyebrow ? (\n <div className=\"text-eyebrow uppercase text-muted-foreground\">{eyebrow}</div>\n ) : null}\n <TitleTag className=\"text-title text-foreground\">{title}</TitleTag>\n {description ? <p className=\"text-body text-muted-foreground\">{description}</p> : null}\n </div>\n {actions ? <div className=\"flex items-center gap-2\">{actions}</div> : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AAAA,OAA+B;AAkCzB,SAEI,KAFJ;AAVC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,IAAI,WAAW;AAAA,EACf;AACF,GAAuB;AACrB,SACE,qBAAC,SAAI,WAAW,GAAG,kDAAkD,SAAS,GAC5E;AAAA,yBAAC,SAAI,WAAU,aACZ;AAAA,gBACC,oBAAC,SAAI,WAAU,gDAAgD,mBAAQ,IACrE;AAAA,MACJ,oBAAC,YAAS,WAAU,8BAA8B,iBAAM;AAAA,MACvD,cAAc,oBAAC,OAAE,WAAU,mCAAmC,uBAAY,IAAO;AAAA,OACpF;AAAA,IACC,UAAU,oBAAC,SAAI,WAAU,2BAA2B,mBAAQ,IAAS;AAAA,KACxE;AAEJ;","names":[]}
|