@mieweb/ui 0.8.0 → 0.9.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 +162 -739
- package/agent/mieweb-ui.instructions.md +34 -16
- package/dist/Animated-Cs-naa2g.d.cts +175 -0
- package/dist/Animated-Cs-naa2g.d.ts +175 -0
- package/dist/CsvBlock-D7Z6ZCRP.js +6 -0
- package/dist/{CsvBlock-PUSTBQ5B.js.map → CsvBlock-D7Z6ZCRP.js.map} +1 -1
- package/dist/CsvBlock-QXXZ7ZUM.cjs +15 -0
- package/dist/{CsvBlock-OTFG3PYZ.cjs.map → CsvBlock-QXXZ7ZUM.cjs.map} +1 -1
- package/dist/HtmlPreviewBlock-AADG7MVB.cjs +15 -0
- package/dist/{HtmlPreviewBlock-QHLSIMWJ.cjs.map → HtmlPreviewBlock-AADG7MVB.cjs.map} +1 -1
- package/dist/HtmlPreviewBlock-F5VDM2EN.js +6 -0
- package/dist/{HtmlPreviewBlock-YF2YVKKX.js.map → HtmlPreviewBlock-F5VDM2EN.js.map} +1 -1
- package/dist/MermaidBlock-6PLITRBZ.js +6 -0
- package/dist/{MermaidBlock-H3TWNC4D.js.map → MermaidBlock-6PLITRBZ.js.map} +1 -1
- package/dist/MermaidBlock-TQ2O5CLV.cjs +15 -0
- package/dist/{MermaidBlock-ZLLBO3VY.cjs.map → MermaidBlock-TQ2O5CLV.cjs.map} +1 -1
- package/dist/SurveyBlock-OYL3VNU5.cjs +15 -0
- package/dist/{SurveyBlock-M2ZRTGVJ.cjs.map → SurveyBlock-OYL3VNU5.cjs.map} +1 -1
- package/dist/SurveyBlock-W5PSQ62F.js +6 -0
- package/dist/{SurveyBlock-JLHS3YQD.js.map → SurveyBlock-W5PSQ62F.js.map} +1 -1
- package/dist/ag-grid.cjs +5 -5
- package/dist/ag-grid.js +1 -1
- package/dist/brands/index.cjs +7 -7
- package/dist/brands/index.js +2 -2
- package/dist/{chunk-RZJXCI53.js → chunk-22CYDCXA.js} +3 -3
- package/dist/{chunk-RZJXCI53.js.map → chunk-22CYDCXA.js.map} +1 -1
- package/dist/{chunk-OTQ72WX3.js → chunk-2BPIVWAK.js} +3 -3
- package/dist/{chunk-OTQ72WX3.js.map → chunk-2BPIVWAK.js.map} +1 -1
- package/dist/{chunk-6EWJGRC3.js → chunk-3JWAABYI.js} +6 -6
- package/dist/chunk-3JWAABYI.js.map +1 -0
- package/dist/{chunk-5JZIDILK.cjs → chunk-3LHICE4I.cjs} +6 -6
- package/dist/chunk-3LHICE4I.cjs.map +1 -0
- package/dist/{chunk-JHZW3Y62.js → chunk-3RB35GYK.js} +5 -5
- package/dist/chunk-3RB35GYK.js.map +1 -0
- package/dist/{chunk-BOW7ZGI2.cjs → chunk-4SM3I7WE.cjs} +170 -10
- package/dist/chunk-4SM3I7WE.cjs.map +1 -0
- package/dist/{chunk-26DPQUSB.cjs → chunk-5BVFVXHN.cjs} +224 -157
- package/dist/chunk-5BVFVXHN.cjs.map +1 -0
- package/dist/{chunk-QHTDWIED.js → chunk-5H7SAEQO.js} +5 -5
- package/dist/{chunk-QHTDWIED.js.map → chunk-5H7SAEQO.js.map} +1 -1
- package/dist/{chunk-EMMYFHOT.js → chunk-5WOB4UBD.js} +3 -3
- package/dist/{chunk-EMMYFHOT.js.map → chunk-5WOB4UBD.js.map} +1 -1
- package/dist/{chunk-4CUFXCC5.cjs → chunk-5Z6UPVGC.cjs} +6 -6
- package/dist/{chunk-4CUFXCC5.cjs.map → chunk-5Z6UPVGC.cjs.map} +1 -1
- package/dist/{chunk-YIXTGWT4.cjs → chunk-6QKMMKRY.cjs} +5 -5
- package/dist/{chunk-YIXTGWT4.cjs.map → chunk-6QKMMKRY.cjs.map} +1 -1
- package/dist/{chunk-F57VRLKP.js → chunk-6SAYPXHX.js} +4 -4
- package/dist/{chunk-F57VRLKP.js.map → chunk-6SAYPXHX.js.map} +1 -1
- package/dist/{chunk-SK7H3Z67.cjs → chunk-6XDPJWSC.cjs} +99 -83
- package/dist/chunk-6XDPJWSC.cjs.map +1 -0
- package/dist/{chunk-4AE2L6AO.cjs → chunk-7FTBPLA6.cjs} +8 -8
- package/dist/chunk-7FTBPLA6.cjs.map +1 -0
- package/dist/{chunk-KVE7PQ5P.cjs → chunk-7KN6J7XV.cjs} +20 -20
- package/dist/{chunk-KVE7PQ5P.cjs.map → chunk-7KN6J7XV.cjs.map} +1 -1
- package/dist/{chunk-K4S4FAYX.cjs → chunk-AHINB2TP.cjs} +11 -11
- package/dist/{chunk-K4S4FAYX.cjs.map → chunk-AHINB2TP.cjs.map} +1 -1
- package/dist/{chunk-MYFZYUPR.cjs → chunk-AOHJILLU.cjs} +38 -3
- package/dist/chunk-AOHJILLU.cjs.map +1 -0
- package/dist/chunk-BKSPDTX4.js +3 -0
- package/dist/{chunk-3PXOIAF6.js.map → chunk-BKSPDTX4.js.map} +1 -1
- package/dist/chunk-BN75TLUN.cjs +163 -0
- package/dist/chunk-BN75TLUN.cjs.map +1 -0
- package/dist/{chunk-WWJIW2IH.cjs → chunk-BVMABVC4.cjs} +3 -3
- package/dist/{chunk-WWJIW2IH.cjs.map → chunk-BVMABVC4.cjs.map} +1 -1
- package/dist/{chunk-H7QSGFMZ.cjs → chunk-BZAGP5W6.cjs} +17 -10
- package/dist/chunk-BZAGP5W6.cjs.map +1 -0
- package/dist/{chunk-RS5VA6QU.cjs → chunk-C3DUS2VE.cjs} +3 -3
- package/dist/{chunk-RS5VA6QU.cjs.map → chunk-C3DUS2VE.cjs.map} +1 -1
- package/dist/{chunk-NLBT5O2X.js → chunk-CK3KLRNF.js} +3 -3
- package/dist/{chunk-NLBT5O2X.js.map → chunk-CK3KLRNF.js.map} +1 -1
- package/dist/{chunk-L6D4CKLV.cjs → chunk-CXDMZT45.cjs} +135 -4
- package/dist/chunk-CXDMZT45.cjs.map +1 -0
- package/dist/{chunk-TXRQQMG5.js → chunk-CYMZ2QS5.js} +2 -2
- package/dist/{chunk-TXRQQMG5.js.map → chunk-CYMZ2QS5.js.map} +1 -1
- package/dist/{chunk-DX64KLSN.js → chunk-D25WH7MH.js} +7 -7
- package/dist/{chunk-DX64KLSN.js.map → chunk-D25WH7MH.js.map} +1 -1
- package/dist/{chunk-XBKOZRDO.js → chunk-DFYMIRMW.js} +4 -4
- package/dist/{chunk-XBKOZRDO.js.map → chunk-DFYMIRMW.js.map} +1 -1
- package/dist/{chunk-AESFOMSH.js → chunk-DGRXAIWK.js} +135 -4
- package/dist/chunk-DGRXAIWK.js.map +1 -0
- package/dist/{chunk-UZ5NGGMI.js → chunk-EG7XFZ3W.js} +4 -4
- package/dist/{chunk-UZ5NGGMI.js.map → chunk-EG7XFZ3W.js.map} +1 -1
- package/dist/{chunk-RYQ3S3KO.cjs → chunk-FQBTGS3E.cjs} +23 -20
- package/dist/chunk-FQBTGS3E.cjs.map +1 -0
- package/dist/{chunk-LQHI44OZ.cjs → chunk-FUFBRKOG.cjs} +59 -59
- package/dist/{chunk-LQHI44OZ.cjs.map → chunk-FUFBRKOG.cjs.map} +1 -1
- package/dist/{chunk-DG7KE4YJ.cjs → chunk-FYAKUU2A.cjs} +38 -21
- package/dist/chunk-FYAKUU2A.cjs.map +1 -0
- package/dist/{chunk-7L7OPISJ.cjs → chunk-H4AVMUOC.cjs} +12 -6
- package/dist/chunk-H4AVMUOC.cjs.map +1 -0
- package/dist/{chunk-I2ECTLON.cjs → chunk-HXSA6QC5.cjs} +3 -3
- package/dist/{chunk-I2ECTLON.cjs.map → chunk-HXSA6QC5.cjs.map} +1 -1
- package/dist/{chunk-DCBMTFLE.js → chunk-HZ4MBUC3.js} +3 -3
- package/dist/{chunk-DCBMTFLE.js.map → chunk-HZ4MBUC3.js.map} +1 -1
- package/dist/{chunk-X5ZPYYMS.js → chunk-I3DQXUSC.js} +3 -3
- package/dist/{chunk-X5ZPYYMS.js.map → chunk-I3DQXUSC.js.map} +1 -1
- package/dist/{chunk-FN6VHMLM.cjs → chunk-IB54SKWB.cjs} +8 -8
- package/dist/{chunk-FN6VHMLM.cjs.map → chunk-IB54SKWB.cjs.map} +1 -1
- package/dist/{chunk-JP5SGIXA.cjs → chunk-IFDC4TXM.cjs} +4 -4
- package/dist/{chunk-JP5SGIXA.cjs.map → chunk-IFDC4TXM.cjs.map} +1 -1
- package/dist/{chunk-RDGRKYQ5.cjs → chunk-IINZWUGK.cjs} +58 -6
- package/dist/chunk-IINZWUGK.cjs.map +1 -0
- package/dist/{chunk-U3JU6BI5.cjs → chunk-JEIW7BSV.cjs} +3 -3
- package/dist/{chunk-U3JU6BI5.cjs.map → chunk-JEIW7BSV.cjs.map} +1 -1
- package/dist/{chunk-D2GID3YK.js → chunk-KREUYVMZ.js} +58 -6
- package/dist/chunk-KREUYVMZ.js.map +1 -0
- package/dist/{chunk-Y6YSJPVC.js → chunk-KRU6IGV7.js} +11 -3
- package/dist/chunk-KRU6IGV7.js.map +1 -0
- package/dist/{chunk-LZU7YBXG.js → chunk-KU3XRHWA.js} +169 -10
- package/dist/chunk-KU3XRHWA.js.map +1 -0
- package/dist/{chunk-P2VTQ5AR.cjs → chunk-L52N6BEN.cjs} +39 -23
- package/dist/chunk-L52N6BEN.cjs.map +1 -0
- package/dist/{chunk-XWYKLEKG.js → chunk-L5W7TJQ5.js} +11 -5
- package/dist/chunk-L5W7TJQ5.js.map +1 -0
- package/dist/{chunk-PAM5UUBL.cjs → chunk-L7L5S2HO.cjs} +18 -2
- package/dist/{chunk-PAM5UUBL.cjs.map → chunk-L7L5S2HO.cjs.map} +1 -1
- package/dist/{chunk-SEPYBAML.js → chunk-LAEIVOIY.js} +38 -21
- package/dist/chunk-LAEIVOIY.js.map +1 -0
- package/dist/{chunk-Z5KFXHDP.cjs → chunk-MM7QKUE3.cjs} +5 -5
- package/dist/{chunk-Z5KFXHDP.cjs.map → chunk-MM7QKUE3.cjs.map} +1 -1
- package/dist/{chunk-FJ7YPVKV.js → chunk-MUIDWFYJ.js} +3 -3
- package/dist/{chunk-FJ7YPVKV.js.map → chunk-MUIDWFYJ.js.map} +1 -1
- package/dist/{chunk-FDV7EQWH.js → chunk-MXQ7J4BB.js} +21 -18
- package/dist/chunk-MXQ7J4BB.js.map +1 -0
- package/dist/{chunk-YMHOF6WA.cjs → chunk-MYAU2ZUC.cjs} +3 -3
- package/dist/{chunk-YMHOF6WA.cjs.map → chunk-MYAU2ZUC.cjs.map} +1 -1
- package/dist/{chunk-5J5PEUUA.js → chunk-NHN6A3ZO.js} +6 -6
- package/dist/{chunk-5J5PEUUA.js.map → chunk-NHN6A3ZO.js.map} +1 -1
- package/dist/{chunk-EPQPUFS6.cjs → chunk-NYJIXR4Y.cjs} +6 -6
- package/dist/chunk-NYJIXR4Y.cjs.map +1 -0
- package/dist/{chunk-EKRT7K2K.js → chunk-O6GJ4IYS.js} +222 -157
- package/dist/chunk-O6GJ4IYS.js.map +1 -0
- package/dist/{chunk-WIYQI35R.cjs → chunk-O7XHHTTP.cjs} +8 -8
- package/dist/{chunk-WIYQI35R.cjs.map → chunk-O7XHHTTP.cjs.map} +1 -1
- package/dist/{chunk-IILJGFI5.js → chunk-OAZUDUGX.js} +8 -6
- package/dist/chunk-OAZUDUGX.js.map +1 -0
- package/dist/{chunk-JHGMZX4I.cjs → chunk-OCV33S5Q.cjs} +6 -6
- package/dist/{chunk-JHGMZX4I.cjs.map → chunk-OCV33S5Q.cjs.map} +1 -1
- package/dist/{chunk-IYXCFIMP.js → chunk-ODYQYLO2.js} +33 -17
- package/dist/chunk-ODYQYLO2.js.map +1 -0
- package/dist/{chunk-FPVRQCCL.js → chunk-OHDIJOGG.js} +4 -4
- package/dist/{chunk-FPVRQCCL.js.map → chunk-OHDIJOGG.js.map} +1 -1
- package/dist/{chunk-GQVL2JKQ.cjs → chunk-OHKO5THF.cjs} +3 -3
- package/dist/{chunk-GQVL2JKQ.cjs.map → chunk-OHKO5THF.cjs.map} +1 -1
- package/dist/{chunk-LMBXJZLG.js → chunk-ON4JULCA.js} +3 -3
- package/dist/{chunk-LMBXJZLG.js.map → chunk-ON4JULCA.js.map} +1 -1
- package/dist/{chunk-A5YOIJKL.js → chunk-ONNY7UO4.js} +15 -15
- package/dist/{chunk-A5YOIJKL.js.map → chunk-ONNY7UO4.js.map} +1 -1
- package/dist/{chunk-DWCYEPTT.js → chunk-OSPTA4UR.js} +4 -4
- package/dist/{chunk-DWCYEPTT.js.map → chunk-OSPTA4UR.js.map} +1 -1
- package/dist/{chunk-FDUA6OGN.js → chunk-PFKRHNYV.js} +8 -8
- package/dist/chunk-PFKRHNYV.js.map +1 -0
- package/dist/{chunk-XMECP2MD.js → chunk-PHK4XBO5.js} +4 -4
- package/dist/{chunk-XMECP2MD.js.map → chunk-PHK4XBO5.js.map} +1 -1
- package/dist/{chunk-ZZJ4ZVYR.cjs → chunk-PJ6CC53R.cjs} +3 -3
- package/dist/{chunk-ZZJ4ZVYR.cjs.map → chunk-PJ6CC53R.cjs.map} +1 -1
- package/dist/{chunk-N3Y43KOB.js → chunk-PYHFVYVZ.js} +12 -5
- package/dist/chunk-PYHFVYVZ.js.map +1 -0
- package/dist/{chunk-XMCIXHGH.js → chunk-Q7G56ZIO.js} +39 -23
- package/dist/chunk-Q7G56ZIO.js.map +1 -0
- package/dist/{chunk-4PIW3Y5M.js → chunk-QAKASRE6.js} +34 -26
- package/dist/chunk-QAKASRE6.js.map +1 -0
- package/dist/{chunk-QGZC43L7.js → chunk-QAQOCS2J.js} +5 -5
- package/dist/{chunk-QGZC43L7.js.map → chunk-QAQOCS2J.js.map} +1 -1
- package/dist/{chunk-YVIH26FG.cjs → chunk-QKAYRHWP.cjs} +12 -12
- package/dist/{chunk-YVIH26FG.cjs.map → chunk-QKAYRHWP.cjs.map} +1 -1
- package/dist/{chunk-P3JEMF6E.cjs → chunk-RSCA5AZW.cjs} +4 -4
- package/dist/{chunk-P3JEMF6E.cjs.map → chunk-RSCA5AZW.cjs.map} +1 -1
- package/dist/{chunk-5Y5FSR4N.js → chunk-SCXELRRZ.js} +3 -3
- package/dist/{chunk-5Y5FSR4N.js.map → chunk-SCXELRRZ.js.map} +1 -1
- package/dist/{chunk-JWTCEWQ4.cjs → chunk-SNEQXSC5.cjs} +2 -2
- package/dist/{chunk-JWTCEWQ4.cjs.map → chunk-SNEQXSC5.cjs.map} +1 -1
- package/dist/{chunk-U5TTXN45.cjs → chunk-SRA2L3SQ.cjs} +9 -7
- package/dist/chunk-SRA2L3SQ.cjs.map +1 -0
- package/dist/{chunk-5U6GETAW.js → chunk-TQDZLRIE.js} +3 -3
- package/dist/chunk-TQDZLRIE.js.map +1 -0
- package/dist/{chunk-HK3AMH3Q.cjs → chunk-VROIMIHB.cjs} +11 -3
- package/dist/chunk-VROIMIHB.cjs.map +1 -0
- package/dist/{chunk-3SHLOF4V.cjs → chunk-VTR2KGLY.cjs} +9 -9
- package/dist/{chunk-3SHLOF4V.cjs.map → chunk-VTR2KGLY.cjs.map} +1 -1
- package/dist/{chunk-XO3WLK65.js → chunk-VVDE4CHU.js} +3 -3
- package/dist/{chunk-XO3WLK65.js.map → chunk-VVDE4CHU.js.map} +1 -1
- package/dist/{chunk-XS35KPBZ.cjs → chunk-WIAQQNFU.cjs} +4 -4
- package/dist/{chunk-XS35KPBZ.cjs.map → chunk-WIAQQNFU.cjs.map} +1 -1
- package/dist/{chunk-BOOJDRJO.js → chunk-WSNMQQ4P.js} +38 -3
- package/dist/chunk-WSNMQQ4P.js.map +1 -0
- package/dist/chunk-WYMO3IIK.js +136 -0
- package/dist/chunk-WYMO3IIK.js.map +1 -0
- package/dist/{chunk-SPWVKDGC.cjs → chunk-X5QRRMGB.cjs} +35 -27
- package/dist/chunk-X5QRRMGB.cjs.map +1 -0
- package/dist/{chunk-SH6B4MG5.js → chunk-XBXDUAIM.js} +4 -4
- package/dist/{chunk-SH6B4MG5.js.map → chunk-XBXDUAIM.js.map} +1 -1
- package/dist/{chunk-56QJHQ5C.cjs → chunk-XEEVDZDK.cjs} +5 -5
- package/dist/{chunk-56QJHQ5C.cjs.map → chunk-XEEVDZDK.cjs.map} +1 -1
- package/dist/{chunk-GXODR6V4.js → chunk-XOIIUO6O.js} +3 -3
- package/dist/{chunk-GXODR6V4.js.map → chunk-XOIIUO6O.js.map} +1 -1
- package/dist/{chunk-ELYGV32O.cjs → chunk-XTHMC76F.cjs} +5 -5
- package/dist/{chunk-ELYGV32O.cjs.map → chunk-XTHMC76F.cjs.map} +1 -1
- package/dist/{chunk-FF235PKY.cjs → chunk-XWZEECEX.cjs} +3 -3
- package/dist/chunk-XWZEECEX.cjs.map +1 -0
- package/dist/{chunk-TVLZZI5Q.cjs → chunk-YJP6DUFO.cjs} +9 -9
- package/dist/{chunk-TVLZZI5Q.cjs.map → chunk-YJP6DUFO.cjs.map} +1 -1
- package/dist/{chunk-EHQ77LL5.js → chunk-ZB54MTMQ.js} +3 -3
- package/dist/{chunk-EHQ77LL5.js.map → chunk-ZB54MTMQ.js.map} +1 -1
- package/dist/components/Accordion/index.cjs +2 -2
- package/dist/components/Accordion/index.js +1 -1
- package/dist/components/Alert/index.cjs +5 -5
- package/dist/components/Alert/index.d.cts +1 -1
- package/dist/components/Alert/index.d.ts +1 -1
- package/dist/components/Alert/index.js +1 -1
- package/dist/components/AlertDialog/index.cjs +6 -5
- package/dist/components/AlertDialog/index.js +5 -4
- package/dist/components/AudioPlayer/index.cjs +6 -6
- package/dist/components/AudioPlayer/index.js +1 -1
- package/dist/components/Autocomplete/index.cjs +4 -4
- package/dist/components/Autocomplete/index.js +3 -3
- package/dist/components/Avatar/index.cjs +5 -5
- package/dist/components/Avatar/index.js +1 -1
- package/dist/components/Badge/index.d.cts +1 -1
- package/dist/components/Badge/index.d.ts +1 -1
- package/dist/components/Breadcrumb/index.cjs +3 -3
- package/dist/components/Breadcrumb/index.js +1 -1
- package/dist/components/Button/index.cjs +3 -3
- package/dist/components/Button/index.js +1 -1
- package/dist/components/Card/index.d.cts +2 -2
- package/dist/components/Card/index.d.ts +2 -2
- package/dist/components/CountryCodeDropdown/index.cjs +6 -6
- package/dist/components/CountryCodeDropdown/index.d.cts +11 -1
- package/dist/components/CountryCodeDropdown/index.d.ts +11 -1
- package/dist/components/CountryCodeDropdown/index.js +3 -3
- package/dist/components/CustomizableDashboard/index.cjs +11 -11
- package/dist/components/CustomizableDashboard/index.js +4 -4
- package/dist/components/DateInput/index.cjs +4 -4
- package/dist/components/DateInput/index.js +3 -3
- package/dist/components/Dropdown/index.cjs +13 -9
- package/dist/components/Dropdown/index.d.cts +38 -2
- package/dist/components/Dropdown/index.d.ts +38 -2
- package/dist/components/Dropdown/index.js +3 -3
- package/dist/components/FloatingWindow/index.cjs +4 -4
- package/dist/components/FloatingWindow/index.js +2 -2
- package/dist/components/GlossaryTooltip/index.cjs +4 -4
- package/dist/components/GlossaryTooltip/index.js +3 -3
- package/dist/components/KeyboardShortcutsOverlay/index.cjs +6 -5
- package/dist/components/KeyboardShortcutsOverlay/index.js +4 -3
- package/dist/components/Markdown/index.cjs +19 -19
- package/dist/components/Markdown/index.js +7 -7
- package/dist/components/MediaEditor/index.cjs +15 -14
- package/dist/components/MediaEditor/index.js +10 -9
- package/dist/components/MediaPlayer/index.cjs +6 -6
- package/dist/components/MediaPlayer/index.js +3 -3
- package/dist/components/Modal/index.cjs +11 -10
- package/dist/components/Modal/index.d.cts +1 -1
- package/dist/components/Modal/index.d.ts +1 -1
- package/dist/components/Modal/index.js +3 -2
- package/dist/components/Pagination/index.cjs +4 -4
- package/dist/components/Pagination/index.d.cts +1 -1
- package/dist/components/Pagination/index.d.ts +1 -1
- package/dist/components/Pagination/index.js +1 -1
- package/dist/components/PhoneInput/index.cjs +4 -4
- package/dist/components/PhoneInput/index.js +2 -2
- package/dist/components/Progress/index.d.cts +1 -1
- package/dist/components/Progress/index.d.ts +1 -1
- package/dist/components/QuickAction/index.cjs +6 -6
- package/dist/components/QuickAction/index.js +1 -1
- package/dist/components/RecordButton/index.d.cts +1 -1
- package/dist/components/RecordButton/index.d.ts +1 -1
- package/dist/components/RichTextEditor/index.cjs +9 -9
- package/dist/components/RichTextEditor/index.js +6 -6
- package/dist/components/SectionSpyNav/index.cjs +4 -4
- package/dist/components/SectionSpyNav/index.js +3 -3
- package/dist/components/Select/index.cjs +5 -5
- package/dist/components/Select/index.js +3 -3
- package/dist/components/Sheet/index.cjs +11 -11
- package/dist/components/Sheet/index.js +2 -2
- package/dist/components/Slider/index.cjs +5 -5
- package/dist/components/Slider/index.d.cts +2 -2
- package/dist/components/Slider/index.d.ts +2 -2
- package/dist/components/Slider/index.js +1 -1
- package/dist/components/SourceTip/index.cjs +4 -4
- package/dist/components/SourceTip/index.js +3 -3
- package/dist/components/SuperChat/index.cjs +264 -106
- package/dist/components/SuperChat/index.cjs.map +1 -1
- package/dist/components/SuperChat/index.d.cts +13 -5
- package/dist/components/SuperChat/index.d.ts +13 -5
- package/dist/components/SuperChat/index.js +255 -97
- package/dist/components/SuperChat/index.js.map +1 -1
- package/dist/components/SuperChat/plugins/index.cjs +7 -7
- package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
- package/dist/components/SuperChat/plugins/index.d.cts +2 -2
- package/dist/components/SuperChat/plugins/index.d.ts +2 -2
- package/dist/components/SuperChat/plugins/index.js +6 -6
- package/dist/components/SuperChat/plugins/index.js.map +1 -1
- package/dist/components/Text/index.d.cts +1 -1
- package/dist/components/Text/index.d.ts +1 -1
- package/dist/components/ThemeProvider/index.cjs +9 -9
- package/dist/components/ThemeProvider/index.d.cts +1 -1
- package/dist/components/ThemeProvider/index.d.ts +1 -1
- package/dist/components/ThemeProvider/index.js +3 -3
- package/dist/components/Toggle/index.d.cts +1 -1
- package/dist/components/Toggle/index.d.ts +1 -1
- package/dist/components/Tooltip/index.cjs +3 -3
- package/dist/components/Tooltip/index.js +2 -2
- package/dist/components/TranscriptView/index.cjs +3 -3
- package/dist/components/TranscriptView/index.js +1 -1
- package/dist/datavis.cjs +2 -2
- package/dist/datavis.js +1 -1
- package/dist/esheet.cjs +15 -14
- package/dist/esheet.cjs.map +1 -1
- package/dist/esheet.js +12 -11
- package/dist/esheet.js.map +1 -1
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.d.cts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +2399 -1640
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +278 -43
- package/dist/index.d.ts +278 -43
- package/dist/index.js +1296 -574
- package/dist/index.js.map +1 -1
- package/dist/motion.cjs +87 -0
- package/dist/motion.cjs.map +1 -0
- package/dist/motion.d.cts +52 -0
- package/dist/motion.d.ts +52 -0
- package/dist/motion.js +50 -0
- package/dist/motion.js.map +1 -0
- package/dist/styles/init.css +25 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/{types-BoTeTPdH.d.ts → types-9vK_YdEb.d.ts} +12 -1
- package/dist/{types-DyIB9HYT.d.cts → types-DZDroUW8.d.cts} +12 -1
- package/dist/{useAnchoredPosition-C7PNglzD.d.ts → useAnchoredPosition-CKwLSQW8.d.cts} +10 -3
- package/dist/{useAnchoredPosition-C7PNglzD.d.cts → useAnchoredPosition-CKwLSQW8.d.ts} +10 -3
- package/package.json +21 -2
- package/dist/CsvBlock-OTFG3PYZ.cjs +0 -15
- package/dist/CsvBlock-PUSTBQ5B.js +0 -6
- package/dist/HtmlPreviewBlock-QHLSIMWJ.cjs +0 -15
- package/dist/HtmlPreviewBlock-YF2YVKKX.js +0 -6
- package/dist/MermaidBlock-H3TWNC4D.js +0 -6
- package/dist/MermaidBlock-ZLLBO3VY.cjs +0 -15
- package/dist/SurveyBlock-JLHS3YQD.js +0 -6
- package/dist/SurveyBlock-M2ZRTGVJ.cjs +0 -15
- package/dist/chunk-26DPQUSB.cjs.map +0 -1
- package/dist/chunk-3PXOIAF6.js +0 -3
- package/dist/chunk-4AE2L6AO.cjs.map +0 -1
- package/dist/chunk-4PIW3Y5M.js.map +0 -1
- package/dist/chunk-5JZIDILK.cjs.map +0 -1
- package/dist/chunk-5U6GETAW.js.map +0 -1
- package/dist/chunk-6EWJGRC3.js.map +0 -1
- package/dist/chunk-7L7OPISJ.cjs.map +0 -1
- package/dist/chunk-AESFOMSH.js.map +0 -1
- package/dist/chunk-BOOJDRJO.js.map +0 -1
- package/dist/chunk-BOW7ZGI2.cjs.map +0 -1
- package/dist/chunk-D2GID3YK.js.map +0 -1
- package/dist/chunk-DG7KE4YJ.cjs.map +0 -1
- package/dist/chunk-EKRT7K2K.js.map +0 -1
- package/dist/chunk-EPQPUFS6.cjs.map +0 -1
- package/dist/chunk-FDUA6OGN.js.map +0 -1
- package/dist/chunk-FDV7EQWH.js.map +0 -1
- package/dist/chunk-FF235PKY.cjs.map +0 -1
- package/dist/chunk-H7QSGFMZ.cjs.map +0 -1
- package/dist/chunk-HK3AMH3Q.cjs.map +0 -1
- package/dist/chunk-IILJGFI5.js.map +0 -1
- package/dist/chunk-IYXCFIMP.js.map +0 -1
- package/dist/chunk-JHZW3Y62.js.map +0 -1
- package/dist/chunk-L6D4CKLV.cjs.map +0 -1
- package/dist/chunk-LZU7YBXG.js.map +0 -1
- package/dist/chunk-MYFZYUPR.cjs.map +0 -1
- package/dist/chunk-N3Y43KOB.js.map +0 -1
- package/dist/chunk-P2VTQ5AR.cjs.map +0 -1
- package/dist/chunk-RDGRKYQ5.cjs.map +0 -1
- package/dist/chunk-RYQ3S3KO.cjs.map +0 -1
- package/dist/chunk-SEPYBAML.js.map +0 -1
- package/dist/chunk-SK7H3Z67.cjs.map +0 -1
- package/dist/chunk-SPWVKDGC.cjs.map +0 -1
- package/dist/chunk-U5TTXN45.cjs.map +0 -1
- package/dist/chunk-XMCIXHGH.js.map +0 -1
- package/dist/chunk-XWYKLEKG.js.map +0 -1
- package/dist/chunk-Y6YSJPVC.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/MediaPlayer/MediaPlayer.tsx"],"names":["cva","React","useMediaTransport","jsx","jsxs","Button"],"mappings":"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","file":"chunk-JP5SGIXA.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { Button } from '../Button';\nimport { useMediaTransport } from '../../hooks/useMediaTransport';\n\n// ============================================================================\n// Types & Interfaces\n// ============================================================================\n\nexport type MediaPlayerState =\n | 'idle'\n | 'loading'\n | 'playing'\n | 'paused'\n | 'error';\n\nexport type MediaKind = 'video' | 'audio';\n\n/** Ref handle for controlling {@link MediaPlayer} programmatically. */\nexport interface MediaPlayerRef {\n /** Seek to a specific time in milliseconds. */\n seekToMs: (timeMs: number) => void;\n /** Start playback. */\n play: () => void;\n /** Pause playback. */\n pause: () => void;\n /** Get current playback time in milliseconds. */\n getCurrentTimeMs: () => number;\n /** Get total duration in milliseconds. */\n getDurationMs: () => number;\n /** Whether playback is currently paused. */\n isPaused: () => boolean;\n /** Set playback speed multiplier. */\n setPlaybackRate: (rate: number) => void;\n /**\n * The underlying media element.\n * Escape hatch for host integrations (e.g. thumbnail capture); prefer the\n * typed methods above for playback control.\n */\n mediaElement: HTMLVideoElement | HTMLAudioElement | null;\n}\n\nexport interface MediaPlayerProps extends VariantProps<\n typeof mediaPlayerVariants\n> {\n /** Media source URL. */\n src: string;\n /** Force the media kind; when omitted it is inferred from the src extension. */\n kind?: MediaKind;\n /** Whether to show native controls (default `true`). */\n controls?: boolean;\n /** Callback when playback state changes. */\n onStateChange?: (state: MediaPlayerState) => void;\n /** Callback when playback ends. */\n onEnded?: () => void;\n /** Callback when an error occurs. */\n onError?: (error: Error) => void;\n /** Callback on time updates (milliseconds). */\n onTimeUpdate?: (currentTimeMs: number, durationMs: number) => void;\n /** Additional class name. */\n className?: string;\n /** Accessible label for the media element. */\n 'aria-label'?: string;\n /**\n * Transitional: exposes the raw media element to legacy consumers.\n * Prefer {@link MediaPlayerRef} for playback control.\n */\n mediaElementRef?: React.RefObject<HTMLVideoElement | HTMLAudioElement | null>;\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst mediaPlayerVariants = cva(\n 'flex h-full w-full items-center justify-center',\n {\n variants: {\n variant: {\n plain: '',\n card: 'rounded-xl border border-border bg-card text-card-foreground p-2',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n }\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst VIDEO_EXTENSIONS = /\\.(mp4|mov|avi|webm|mkv|m4v)$/i;\n\n/** Infer media kind from a URL's file extension; defaults to audio. */\nexport function inferMediaKind(src: string): MediaKind {\n // Strip any query string / fragment before matching. Testing the extension\n // against the full URL required a trailing `.*`, which backtracks\n // polynomially on crafted inputs (ReDoS); splitting first is linear.\n const path = src.split(/[?#]/, 1)[0];\n return VIDEO_EXTENSIONS.test(path) ? 'video' : 'audio';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Media playback surface for audio and video with a shared imperative handle.\n *\n * Renders a native `<video>` or `<audio>` element (kind inferred from the src\n * extension unless forced) with themed error/retry handling. Playback state and\n * controls come from the shared {@link useMediaTransport} hook and are exposed\n * through {@link MediaPlayerRef} (all times in milliseconds) — consumers should\n * not reach into the DOM element directly.\n */\nexport const MediaPlayer = React.forwardRef<MediaPlayerRef, MediaPlayerProps>(\n (\n {\n src,\n kind,\n controls = true,\n variant,\n onStateChange,\n onEnded,\n onError,\n onTimeUpdate,\n className,\n 'aria-label': ariaLabel,\n mediaElementRef,\n },\n ref\n ) => {\n const [error, setError] = React.useState<string | null>(null);\n\n // A failed load must not outlive its src: clearing on change lets a host\n // swap in a corrected URL without being trapped on the error surface\n // (which unmounts the media element, so the new src would never load).\n React.useEffect(() => {\n setError(null);\n }, [src]);\n const resolvedKind = kind ?? inferMediaKind(src);\n\n const transport = useMediaTransport({\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError: (err) => {\n setError('Unable to load media. The server may be unavailable.');\n onError?.(err);\n },\n endedState: 'paused',\n errorLabel: `media: ${src}`,\n });\n\n const { setMediaElement, mediaElement } = transport;\n\n const setElement = React.useCallback(\n (el: HTMLVideoElement | HTMLAudioElement | null) => {\n setMediaElement(el);\n if (mediaElementRef) {\n (mediaElementRef as React.MutableRefObject<typeof el>).current = el;\n }\n },\n [setMediaElement, mediaElementRef]\n );\n\n React.useImperativeHandle(\n ref,\n (): MediaPlayerRef => ({\n seekToMs: transport.seekToMs,\n play: transport.play,\n pause: transport.pause,\n getCurrentTimeMs: transport.getCurrentTimeMs,\n getDurationMs: transport.getDurationMs,\n isPaused: transport.isPaused,\n setPlaybackRate: transport.setPlaybackRate,\n get mediaElement() {\n return mediaElement;\n },\n }),\n [transport, mediaElement]\n );\n\n const handleRetry = React.useCallback(() => {\n setError(null);\n mediaElement?.load();\n }, [mediaElement]);\n\n const sharedMediaProps = {\n src,\n controls,\n 'aria-label': ariaLabel,\n };\n\n if (error) {\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n <div\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/10 flex min-h-36 flex-col items-center justify-center gap-3 rounded-lg border p-8 text-center\"\n >\n {/* destructive-700/300 instead of the base token: #dc2626 on the\n destructive/10 tint is 4.14:1 — below WCAG AA (axe: color-contrast). */}\n <p className=\"text-destructive-700 dark:text-destructive-300 m-0 text-sm\">\n {error}\n </p>\n {/* bg-background: the outline button is transparent, and its text on\n the destructive/10 tint sits exactly at the 4.5:1 AA boundary. */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"bg-background\"\n onClick={handleRetry}\n >\n Retry\n </Button>\n </div>\n </div>\n );\n }\n\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n {resolvedKind === 'video' ? (\n // Generic media surface: caption tracks belong to the consumer's media\n // resource and are supplied via children, not this transport component.\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <video\n ref={setElement as React.Ref<HTMLVideoElement>}\n playsInline\n className=\"h-auto max-h-full w-auto max-w-full object-contain\"\n {...sharedMediaProps}\n />\n ) : (\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <audio\n ref={setElement as React.Ref<HTMLAudioElement>}\n className=\"my-4 w-[90%] max-w-lg\"\n {...sharedMediaProps}\n />\n )}\n </div>\n );\n }\n);\n\nMediaPlayer.displayName = 'MediaPlayer';\n\nexport { mediaPlayerVariants };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/MediaPlayer/MediaPlayer.tsx"],"names":["cva","React","useMediaTransport","jsx","jsxs","Button"],"mappings":"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","file":"chunk-IFDC4TXM.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { Button } from '../Button';\nimport { useMediaTransport } from '../../hooks/useMediaTransport';\n\n// ============================================================================\n// Types & Interfaces\n// ============================================================================\n\nexport type MediaPlayerState =\n | 'idle'\n | 'loading'\n | 'playing'\n | 'paused'\n | 'error';\n\nexport type MediaKind = 'video' | 'audio';\n\n/** Ref handle for controlling {@link MediaPlayer} programmatically. */\nexport interface MediaPlayerRef {\n /** Seek to a specific time in milliseconds. */\n seekToMs: (timeMs: number) => void;\n /** Start playback. */\n play: () => void;\n /** Pause playback. */\n pause: () => void;\n /** Get current playback time in milliseconds. */\n getCurrentTimeMs: () => number;\n /** Get total duration in milliseconds. */\n getDurationMs: () => number;\n /** Whether playback is currently paused. */\n isPaused: () => boolean;\n /** Set playback speed multiplier. */\n setPlaybackRate: (rate: number) => void;\n /**\n * The underlying media element.\n * Escape hatch for host integrations (e.g. thumbnail capture); prefer the\n * typed methods above for playback control.\n */\n mediaElement: HTMLVideoElement | HTMLAudioElement | null;\n}\n\nexport interface MediaPlayerProps extends VariantProps<\n typeof mediaPlayerVariants\n> {\n /** Media source URL. */\n src: string;\n /** Force the media kind; when omitted it is inferred from the src extension. */\n kind?: MediaKind;\n /** Whether to show native controls (default `true`). */\n controls?: boolean;\n /** Callback when playback state changes. */\n onStateChange?: (state: MediaPlayerState) => void;\n /** Callback when playback ends. */\n onEnded?: () => void;\n /** Callback when an error occurs. */\n onError?: (error: Error) => void;\n /** Callback on time updates (milliseconds). */\n onTimeUpdate?: (currentTimeMs: number, durationMs: number) => void;\n /** Additional class name. */\n className?: string;\n /** Accessible label for the media element. */\n 'aria-label'?: string;\n /**\n * Transitional: exposes the raw media element to legacy consumers.\n * Prefer {@link MediaPlayerRef} for playback control.\n */\n mediaElementRef?: React.RefObject<HTMLVideoElement | HTMLAudioElement | null>;\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst mediaPlayerVariants = cva(\n 'flex h-full w-full items-center justify-center',\n {\n variants: {\n variant: {\n plain: '',\n card: 'rounded-xl border border-border bg-card text-card-foreground p-2',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n }\n);\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst VIDEO_EXTENSIONS = /\\.(mp4|mov|avi|webm|mkv|m4v)$/i;\n\n/** Infer media kind from a URL's file extension; defaults to audio. */\nexport function inferMediaKind(src: string): MediaKind {\n // Strip any query string / fragment before matching. Testing the extension\n // against the full URL required a trailing `.*`, which backtracks\n // polynomially on crafted inputs (ReDoS); splitting first is linear.\n const path = src.split(/[?#]/, 1)[0];\n return VIDEO_EXTENSIONS.test(path) ? 'video' : 'audio';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Media playback surface for audio and video with a shared imperative handle.\n *\n * Renders a native `<video>` or `<audio>` element (kind inferred from the src\n * extension unless forced) with themed error/retry handling. Playback state and\n * controls come from the shared {@link useMediaTransport} hook and are exposed\n * through {@link MediaPlayerRef} (all times in milliseconds) — consumers should\n * not reach into the DOM element directly.\n */\nexport const MediaPlayer = React.forwardRef<MediaPlayerRef, MediaPlayerProps>(\n (\n {\n src,\n kind,\n controls = true,\n variant,\n onStateChange,\n onEnded,\n onError,\n onTimeUpdate,\n className,\n 'aria-label': ariaLabel,\n mediaElementRef,\n },\n ref\n ) => {\n const [error, setError] = React.useState<string | null>(null);\n\n // A failed load must not outlive its src: clearing on change lets a host\n // swap in a corrected URL without being trapped on the error surface\n // (which unmounts the media element, so the new src would never load).\n React.useEffect(() => {\n setError(null);\n }, [src]);\n const resolvedKind = kind ?? inferMediaKind(src);\n\n const transport = useMediaTransport({\n onTimeUpdate,\n onStateChange,\n onEnded,\n onError: (err) => {\n setError('Unable to load media. The server may be unavailable.');\n onError?.(err);\n },\n endedState: 'paused',\n errorLabel: `media: ${src}`,\n });\n\n const { setMediaElement, mediaElement } = transport;\n\n const setElement = React.useCallback(\n (el: HTMLVideoElement | HTMLAudioElement | null) => {\n setMediaElement(el);\n if (mediaElementRef) {\n (mediaElementRef as React.MutableRefObject<typeof el>).current = el;\n }\n },\n [setMediaElement, mediaElementRef]\n );\n\n React.useImperativeHandle(\n ref,\n (): MediaPlayerRef => ({\n seekToMs: transport.seekToMs,\n play: transport.play,\n pause: transport.pause,\n getCurrentTimeMs: transport.getCurrentTimeMs,\n getDurationMs: transport.getDurationMs,\n isPaused: transport.isPaused,\n setPlaybackRate: transport.setPlaybackRate,\n get mediaElement() {\n return mediaElement;\n },\n }),\n [transport, mediaElement]\n );\n\n const handleRetry = React.useCallback(() => {\n setError(null);\n mediaElement?.load();\n }, [mediaElement]);\n\n const sharedMediaProps = {\n src,\n controls,\n 'aria-label': ariaLabel,\n };\n\n if (error) {\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n <div\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/10 flex min-h-36 flex-col items-center justify-center gap-3 rounded-lg border p-8 text-center\"\n >\n {/* destructive-700/300 instead of the base token: #dc2626 on the\n destructive/10 tint is 4.14:1 — below WCAG AA (axe: color-contrast). */}\n <p className=\"text-destructive-700 dark:text-destructive-300 m-0 text-sm\">\n {error}\n </p>\n {/* bg-background: the outline button is transparent, and its text on\n the destructive/10 tint sits exactly at the 4.5:1 AA boundary. */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"bg-background\"\n onClick={handleRetry}\n >\n Retry\n </Button>\n </div>\n </div>\n );\n }\n\n return (\n <div className={mediaPlayerVariants({ variant, className })}>\n {resolvedKind === 'video' ? (\n // Generic media surface: caption tracks belong to the consumer's media\n // resource and are supplied via children, not this transport component.\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <video\n ref={setElement as React.Ref<HTMLVideoElement>}\n playsInline\n className=\"h-auto max-h-full w-auto max-w-full object-contain\"\n {...sharedMediaProps}\n />\n ) : (\n // eslint-disable-next-line jsx-a11y/media-has-caption\n <audio\n ref={setElement as React.Ref<HTMLAudioElement>}\n className=\"my-4 w-[90%] max-w-lg\"\n {...sharedMediaProps}\n />\n )}\n </div>\n );\n }\n);\n\nMediaPlayer.displayName = 'MediaPlayer';\n\nexport { mediaPlayerVariants };\n"]}
|
|
@@ -25,6 +25,38 @@ function _interopNamespace(e) {
|
|
|
25
25
|
|
|
26
26
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
27
27
|
|
|
28
|
+
// src/components/Button/button-critical.ts
|
|
29
|
+
var STYLE_ID = "mieweb-ui-button-critical";
|
|
30
|
+
var CRITICAL_CSS = [
|
|
31
|
+
"@layer utilities{",
|
|
32
|
+
// Structure: keep icon + label on one line (matches the base utilities
|
|
33
|
+
// inline-flex items-center justify-center gap-2 min-w-0 whitespace-nowrap).
|
|
34
|
+
`:where(button[data-slot='button']){display:inline-flex;flex-wrap:nowrap;align-items:center;justify-content:center;gap:0.5rem;min-width:0;white-space:nowrap;}`,
|
|
35
|
+
// Icons and the loading spinner never shrink (matches shrink-0).
|
|
36
|
+
`:where(button[data-slot='button']) > :where([data-slot='button-icon'],svg){flex-shrink:0;}`,
|
|
37
|
+
// Label truncates instead of wrapping/overflowing (matches truncate).
|
|
38
|
+
`:where(button[data-slot='button']) > :where([data-slot='button-label']){min-width:0;overflow:hidden;text-overflow:ellipsis;}`,
|
|
39
|
+
"}",
|
|
40
|
+
// Icons passed as children land inside the label span; Tailwind preflight
|
|
41
|
+
// makes SVGs display:block, which forces line breaks inside the inline
|
|
42
|
+
// label. Restore inline flow. This rule is deliberately UNLAYERED at
|
|
43
|
+
// specificity (0,2,2): it must beat Tailwind 3's unlayered preflight
|
|
44
|
+
// `svg{display:block}` (0,0,1) — layering it would neuter the fix for
|
|
45
|
+
// exactly the broken-TW3 apps it exists for. It also outranks the
|
|
46
|
+
// (0,1,1) [&_svg]:inline-block utility on the label, but both declare
|
|
47
|
+
// the same values, so they never conflict. Known tradeoff:
|
|
48
|
+
// display utilities on an SVG inside the label slot won't win; consumers
|
|
49
|
+
// should conditionally render icons instead.
|
|
50
|
+
`button[data-slot='button'] [data-slot='button-label'] svg{display:inline-block;vertical-align:middle;}`
|
|
51
|
+
].join("");
|
|
52
|
+
function injectButtonCriticalStyles() {
|
|
53
|
+
if (typeof document === "undefined") return;
|
|
54
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
55
|
+
const style = document.createElement("style");
|
|
56
|
+
style.id = STYLE_ID;
|
|
57
|
+
style.textContent = CRITICAL_CSS;
|
|
58
|
+
document.head.appendChild(style);
|
|
59
|
+
}
|
|
28
60
|
var buttonVariants = classVarianceAuthority.cva(
|
|
29
61
|
// Base styles
|
|
30
62
|
[
|
|
@@ -97,6 +129,7 @@ var buttonVariants = classVarianceAuthority.cva(
|
|
|
97
129
|
}
|
|
98
130
|
}
|
|
99
131
|
);
|
|
132
|
+
var labelClasses = "truncate [&_svg]:inline-block [&_svg]:align-middle";
|
|
100
133
|
var Button = React__namespace.forwardRef(
|
|
101
134
|
({
|
|
102
135
|
className,
|
|
@@ -116,6 +149,9 @@ var Button = React__namespace.forwardRef(
|
|
|
116
149
|
const labelRef = React__namespace.useRef(null);
|
|
117
150
|
const innerRef = React__namespace.useRef(null);
|
|
118
151
|
React__namespace.useImperativeHandle(ref, () => innerRef.current);
|
|
152
|
+
React__namespace.useInsertionEffect(() => {
|
|
153
|
+
injectButtonCriticalStyles();
|
|
154
|
+
}, []);
|
|
119
155
|
React__namespace.useLayoutEffect(() => {
|
|
120
156
|
const label = labelRef.current;
|
|
121
157
|
const button = innerRef.current;
|
|
@@ -149,11 +185,27 @@ var Button = React__namespace.forwardRef(
|
|
|
149
185
|
...props,
|
|
150
186
|
children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
151
187
|
/* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, {}),
|
|
152
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
188
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
189
|
+
"span",
|
|
190
|
+
{
|
|
191
|
+
ref: labelRef,
|
|
192
|
+
"data-slot": "button-label",
|
|
193
|
+
className: labelClasses,
|
|
194
|
+
children: loadingText || children
|
|
195
|
+
}
|
|
196
|
+
)
|
|
153
197
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
154
|
-
React__namespace.isValidElement(leftIcon) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: leftIcon }),
|
|
155
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
156
|
-
|
|
198
|
+
React__namespace.isValidElement(leftIcon) && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "button-icon", className: "shrink-0", children: leftIcon }),
|
|
199
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
200
|
+
"span",
|
|
201
|
+
{
|
|
202
|
+
ref: labelRef,
|
|
203
|
+
"data-slot": "button-label",
|
|
204
|
+
className: labelClasses,
|
|
205
|
+
children
|
|
206
|
+
}
|
|
207
|
+
),
|
|
208
|
+
React__namespace.isValidElement(rightIcon) && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "button-icon", className: "shrink-0", children: rightIcon })
|
|
157
209
|
] })
|
|
158
210
|
}
|
|
159
211
|
);
|
|
@@ -196,5 +248,5 @@ function LoadingSpinner() {
|
|
|
196
248
|
|
|
197
249
|
exports.Button = Button;
|
|
198
250
|
exports.buttonVariants = buttonVariants;
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
251
|
+
//# sourceMappingURL=chunk-IINZWUGK.cjs.map
|
|
252
|
+
//# sourceMappingURL=chunk-IINZWUGK.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Button/button-critical.ts","../src/components/Button/Button.tsx"],"names":["cva","React","jsx","cn","jsxs","Fragment"],"mappings":"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","file":"chunk-IINZWUGK.cjs","sourcesContent":["/**\n * Self-healing structural CSS for Button.\n *\n * Button layout relies on Tailwind utilities (`inline-flex`,\n * `whitespace-nowrap`, ...). Consumer apps with a stale safelist copy or a\n * missing `@source` line never generate those classes, so the button falls\n * back to `inline-block` and the icon stacks above the label.\n *\n * Injecting these rules from the component guarantees every consumer gets\n * correct button structure just by upgrading the library — no app-side\n * changes required.\n *\n * Override safety, by consumer setup:\n * - Tailwind 4: utilities live in `@layer utilities`. The structural rules\n * below join that same layer, so conflicts resolve by specificity — and\n * every selector is wrapped in `:where()` (zero specificity), so real\n * utilities (`hidden`, `gap-0`, ...) always win. (A new layer name can't\n * be used: layers declared later outrank `utilities`.)\n * - Tailwind 3 / no Tailwind: consumer CSS is unlayered, and unlayered\n * always beats layered, so the structural rules stay a pure fallback.\n */\n\nconst STYLE_ID = 'mieweb-ui-button-critical';\n\nconst CRITICAL_CSS = [\n '@layer utilities{',\n // Structure: keep icon + label on one line (matches the base utilities\n // inline-flex items-center justify-center gap-2 min-w-0 whitespace-nowrap).\n `:where(button[data-slot='button']){display:inline-flex;flex-wrap:nowrap;align-items:center;justify-content:center;gap:0.5rem;min-width:0;white-space:nowrap;}`,\n // Icons and the loading spinner never shrink (matches shrink-0).\n `:where(button[data-slot='button']) > :where([data-slot='button-icon'],svg){flex-shrink:0;}`,\n // Label truncates instead of wrapping/overflowing (matches truncate).\n `:where(button[data-slot='button']) > :where([data-slot='button-label']){min-width:0;overflow:hidden;text-overflow:ellipsis;}`,\n '}',\n // Icons passed as children land inside the label span; Tailwind preflight\n // makes SVGs display:block, which forces line breaks inside the inline\n // label. Restore inline flow. This rule is deliberately UNLAYERED at\n // specificity (0,2,2): it must beat Tailwind 3's unlayered preflight\n // `svg{display:block}` (0,0,1) — layering it would neuter the fix for\n // exactly the broken-TW3 apps it exists for. It also outranks the\n // (0,1,1) [&_svg]:inline-block utility on the label, but both declare\n // the same values, so they never conflict. Known tradeoff:\n // display utilities on an SVG inside the label slot won't win; consumers\n // should conditionally render icons instead.\n `button[data-slot='button'] [data-slot='button-label'] svg{display:inline-block;vertical-align:middle;}`,\n].join('');\n\n/** Injects the critical Button styles once per document. SSR-safe. */\nexport function injectButtonCriticalStyles(): void {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = CRITICAL_CSS;\n document.head.appendChild(style);\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { injectButtonCriticalStyles } from './button-critical';\n\nconst buttonVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2',\n 'min-w-0 whitespace-nowrap',\n 'font-semibold transition-all duration-200',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'active:scale-[0.98]',\n ],\n {\n variants: {\n variant: {\n primary: [\n 'bg-primary-800 text-white',\n 'hover:bg-primary-900',\n 'active:bg-primary-950',\n ],\n secondary: [\n 'bg-neutral-200 text-neutral-900',\n 'hover:bg-neutral-300',\n 'active:bg-neutral-400',\n 'dark:bg-neutral-700 dark:text-neutral-100',\n 'dark:hover:bg-neutral-600',\n 'dark:active:bg-neutral-500',\n ],\n ghost: [\n 'bg-transparent text-neutral-600',\n 'hover:bg-neutral-100',\n 'active:bg-neutral-200',\n 'dark:text-neutral-400',\n 'dark:hover:bg-neutral-800',\n 'dark:active:bg-neutral-700',\n ],\n outline: [\n 'border-2 border-primary-800 text-primary-800 bg-transparent',\n 'hover:bg-primary-50 hover:text-primary-900',\n 'active:bg-primary-100',\n 'dark:border-primary-400 dark:text-primary-400',\n 'dark:hover:bg-primary-950',\n 'dark:active:bg-primary-900',\n ],\n danger: [\n 'bg-red-600 text-white',\n 'hover:bg-red-700',\n 'active:bg-red-800',\n ],\n link: [\n 'text-primary-800 underline-offset-4',\n 'hover:underline hover:text-primary-900',\n 'active:text-primary-950',\n 'dark:text-primary-400',\n ],\n },\n size: {\n sm: 'h-8 px-3 text-sm rounded-md',\n md: 'h-10 px-4 text-base rounded-lg',\n lg: 'h-12 px-6 text-lg rounded-xl',\n icon: 'h-10 w-10 rounded-lg',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n fullWidth: false,\n },\n }\n);\n\n/**\n * Label wrapper classes. Icons passed as `children` (rather than\n * leftIcon/rightIcon) land inside this span; preflight makes SVGs\n * display:block which would force line breaks inside the inline span,\n * so restore inline flow for them.\n */\nconst labelClasses = 'truncate [&_svg]:inline-block [&_svg]:align-middle';\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n /** Optional icon element to render before the button text */\n leftIcon?: React.ReactElement | null;\n /** Optional icon element to render after the button text */\n rightIcon?: React.ReactElement | null;\n /** Shows a loading spinner and disables the button */\n isLoading?: boolean;\n /** Accessible label for the loading state */\n loadingText?: string;\n}\n\n/**\n * A versatile button component with multiple variants and sizes.\n *\n * @example\n * ```tsx\n * <Button variant=\"primary\" size=\"md\">Click me</Button>\n * <Button variant=\"danger\" leftIcon={<TrashIcon />}>Delete</Button>\n * <Button variant=\"ghost\" isLoading loadingText=\"Saving...\">Save</Button>\n * ```\n */\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n fullWidth,\n leftIcon,\n rightIcon,\n isLoading,\n loadingText,\n disabled,\n children,\n title,\n ...props\n },\n ref\n ) => {\n const resolvedSize = size ?? 'md';\n const labelRef = React.useRef<HTMLSpanElement>(null);\n const innerRef = React.useRef<HTMLButtonElement>(null);\n React.useImperativeHandle(ref, () => innerRef.current as HTMLButtonElement);\n\n // Guarantees correct icon/label layout even when the consumer's Tailwind\n // build is missing our utility classes. See button-critical.ts.\n React.useInsertionEffect(() => {\n injectButtonCriticalStyles();\n }, []);\n\n // When the label truncates, expose the full text as a native tooltip.\n // A consumer-provided `title` always takes precedence.\n React.useLayoutEffect(() => {\n const label = labelRef.current;\n const button = innerRef.current;\n if (!label || !button || title !== undefined) return;\n\n const update = () => {\n if (label.scrollWidth > label.clientWidth) {\n button.title = label.textContent ?? '';\n } else {\n button.removeAttribute('title');\n }\n };\n\n update();\n if (typeof globalThis.ResizeObserver === 'undefined') return;\n const observer = new globalThis.ResizeObserver(update);\n observer.observe(label);\n return () => observer.disconnect();\n }, [title, children, isLoading, loadingText]);\n\n return (\n <button\n data-slot=\"button\"\n data-size={resolvedSize}\n className={cn(\n buttonVariants({ variant, size: resolvedSize, fullWidth }),\n className\n )}\n ref={innerRef}\n disabled={disabled || isLoading}\n aria-busy={isLoading}\n title={title}\n {...props}\n >\n {isLoading ? (\n <>\n <LoadingSpinner />\n <span\n ref={labelRef}\n data-slot=\"button-label\"\n className={labelClasses}\n >\n {loadingText || children}\n </span>\n </>\n ) : (\n <>\n {React.isValidElement(leftIcon) && (\n <span data-slot=\"button-icon\" className=\"shrink-0\">\n {leftIcon}\n </span>\n )}\n <span\n ref={labelRef}\n data-slot=\"button-label\"\n className={labelClasses}\n >\n {children}\n </span>\n {React.isValidElement(rightIcon) && (\n <span data-slot=\"button-icon\" className=\"shrink-0\">\n {rightIcon}\n </span>\n )}\n </>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n\n/**\n * Simple loading spinner for the button\n */\nfunction LoadingSpinner() {\n return (\n <svg\n className=\"h-4 w-4 shrink-0 animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n );\n}\n\nexport { Button, buttonVariants };\n"]}
|
|
@@ -102,7 +102,7 @@ var AvatarGroup = React__namespace.forwardRef(
|
|
|
102
102
|
{
|
|
103
103
|
ref,
|
|
104
104
|
"data-slot": "avatar-group",
|
|
105
|
-
className: chunkS5RVSXDV_cjs.cn("flex -space-x-2", className),
|
|
105
|
+
className: chunkS5RVSXDV_cjs.cn("flex -space-x-2 rtl:space-x-reverse", className),
|
|
106
106
|
...props,
|
|
107
107
|
children: [
|
|
108
108
|
visibleChildren.map((child, index) => {
|
|
@@ -146,5 +146,5 @@ exports.Avatar = Avatar;
|
|
|
146
146
|
exports.AvatarGroup = AvatarGroup;
|
|
147
147
|
exports.avatarVariants = avatarVariants;
|
|
148
148
|
exports.getInitials = getInitials;
|
|
149
|
-
//# sourceMappingURL=chunk-
|
|
150
|
-
//# sourceMappingURL=chunk-
|
|
149
|
+
//# sourceMappingURL=chunk-JEIW7BSV.cjs.map
|
|
150
|
+
//# sourceMappingURL=chunk-JEIW7BSV.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Avatar/Avatar.tsx"],"names":["cva","React","jsx","cn","jsxs"],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../src/components/Avatar/Avatar.tsx"],"names":["cva","React","jsx","cn","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,IAAM,cAAA,GAAiBA,0BAAA;AAAA,EACrB;AAAA,IACE,kDAAA;AAAA,IACA,8BAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,iBAAA;AAAA,QACJ,EAAA,EAAI,iBAAA;AAAA,QACJ,EAAA,EAAI,mBAAA;AAAA,QACJ,EAAA,EAAI,qBAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,IAAA,EAAM,4BAAA;AAAA,QACN,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,IAAA,EAAM,IAAA;AAAA,MACN,IAAA,EAAM;AAAA;AACR;AAEJ;AAmBA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,OAAO,KACJ,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,CAAC,CAAC,CAAA,CACrB,KAAK,EAAE,CAAA,CACP,aAAY,CACZ,KAAA,CAAM,GAAG,CAAC,CAAA;AACf;AAiBA,IAAM,MAAA,GAAeC,gBAAA,CAAA,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,GAAA,EAAK,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACtE,IAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAUA,0BAAS,KAAK,CAAA;AAGxD,IAAMA,2BAAU,MAAM;AACpB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,IAAA,MAAM,SAAA,GAAY,OAAO,CAAC,UAAA;AAC1B,IAAA,MAAM,QAAA,GAAW,IAAA,GAAO,WAAA,CAAY,IAAI,CAAA,GAAI,IAAA;AAE5C,IAAA,uBACEC,cAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,QAAA;AAAA,QACV,SAAA,EAAWC,qBAAG,cAAA,CAAe,EAAE,MAAM,IAAA,EAAM,GAAG,SAAS,CAAA;AAAA,QACtD,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA,SAAA,mBACCD,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA;AAAA,YACA,GAAA,EAAK,GAAA,KAAQ,MAAA,GAAY,GAAA,GAAM,IAAA,IAAQ,QAAA;AAAA,YACvC,SAAA,EAAU,4BAAA;AAAA,YACV,OAAA,EAAS,MAAM,aAAA,CAAc,IAAI;AAAA;AAAA,YAE3BD,gBAAA,CAAA,cAAA,CAAe,QAAQ,CAAA,GAC/B,QAAA,GACE,WACF,QAAA,mBAEAC,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,aAAA,EAAY,MAAA;AAAA,YACZ,SAAA,EAAU,+BAAA;AAAA,YACV,IAAA,EAAK,cAAA;AAAA,YACL,OAAA,EAAQ,WAAA;AAAA,YAER,QAAA,kBAAAA,cAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,+GAAA,EAAgH;AAAA;AAAA;AAC1H;AAAA,KAEJ;AAAA,EAEJ;AACF;AAEA,MAAA,CAAO,WAAA,GAAc,QAAA;AA4BrB,IAAM,WAAA,GAAoBD,gBAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAA,EAAK,IAAA,GAAO,MAAM,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC5D,IAAA,MAAM,aAAA,GAAsBA,gBAAA,CAAA,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AACrD,IAAA,MAAM,kBAAkB,GAAA,GAAM,aAAA,CAAc,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,aAAA;AAC5D,IAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,GAAA,CAAI,GAAG,aAAA,CAAc,MAAA,GAAS,GAAG,CAAA,GAAI,CAAA;AAEvE,IAAA,uBACEG,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,cAAA;AAAA,QACV,SAAA,EAAWD,oBAAA,CAAG,qCAAA,EAAuC,SAAS,CAAA;AAAA,QAC7D,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,eAAA,CAAgB,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,KAAU;AACrC,YAAA,IAAUF,gBAAA,CAAA,cAAA,CAAe,KAAK,CAAA,EAAG;AAC/B,cAAA,OAAaA,gBAAA,CAAA,YAAA;AAAA,gBACX,KAAA;AAAA,gBACA;AAAA,kBACE,GAAA,EAAK,KAAA;AAAA,kBACL,IAAA;AAAA,kBACA,SAAA,EAAWE,oBAAA;AAAA,oBACT,yCAAA;AAAA,oBACC,MAA0C,KAAA,CAAM;AAAA;AACnD;AACF,eACF;AAAA,YACF;AACA,YAAA,OAAO,KAAA;AAAA,UACT,CAAC,CAAA;AAAA,UACA,iBAAiB,CAAA,oBAChBC,eAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAWD,oBAAA;AAAA,gBACT,cAAA,CAAe,EAAE,IAAA,EAAM,CAAA;AAAA,gBACvB,2EAAA;AAAA,gBACA;AAAA,eACF;AAAA,cACD,QAAA,EAAA;AAAA,gBAAA,GAAA;AAAA,gBACG;AAAA;AAAA;AAAA;AACJ;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AAEA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-JEIW7BSV.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Avatar Component\n// ============================================================================\n\nconst avatarVariants = cva(\n [\n 'relative inline-flex items-center justify-center',\n 'rounded-full overflow-hidden',\n 'bg-primary-800 text-white font-semibold',\n ],\n {\n variants: {\n size: {\n xs: 'h-6 w-6 text-xs',\n sm: 'h-8 w-8 text-sm',\n md: 'h-10 w-10 text-sm',\n lg: 'h-12 w-12 text-base',\n xl: 'h-16 w-16 text-lg',\n },\n ring: {\n true: 'ring-2 ring-primary-400/30',\n false: '',\n },\n },\n defaultVariants: {\n size: 'md',\n ring: false,\n },\n }\n);\n\nexport interface AvatarProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof avatarVariants> {\n /** Image URL for the avatar */\n src?: string | null;\n /** Alt text for the avatar image */\n alt?: string;\n /** Name to generate initials from (used as fallback when no src) */\n name?: string;\n /** Custom fallback content (overrides name initials) */\n fallback?: React.ReactElement | null;\n}\n\n/**\n * Get initials from a name string.\n */\nfunction getInitials(name: string): string {\n return name\n .split(' ')\n .map((part) => part[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n}\n\n/**\n * An avatar component for displaying user profile images with fallback to initials.\n *\n * @example\n * ```tsx\n * // With image\n * <Avatar src=\"/user.jpg\" alt=\"John Doe\" />\n *\n * // With initials fallback\n * <Avatar name=\"John Doe\" />\n *\n * // With custom fallback\n * <Avatar fallback={<UserIcon />} />\n * ```\n */\nconst Avatar = React.forwardRef<HTMLDivElement, AvatarProps>(\n ({ className, src, alt, name, fallback, size, ring, ...props }, ref) => {\n const [imageError, setImageError] = React.useState(false);\n\n // Reset error state when src changes\n React.useEffect(() => {\n setImageError(false);\n }, [src]);\n\n const showImage = src && !imageError;\n const initials = name ? getInitials(name) : null;\n\n return (\n <div\n ref={ref}\n data-slot=\"avatar\"\n className={cn(avatarVariants({ size, ring }), className)}\n {...props}\n >\n {showImage ? (\n <img\n src={src}\n alt={alt !== undefined ? alt : name || 'Avatar'}\n className=\"h-full w-full object-cover\"\n onError={() => setImageError(true)}\n />\n ) : React.isValidElement(fallback) ? (\n fallback\n ) : initials ? (\n initials\n ) : (\n <svg\n aria-hidden=\"true\"\n className=\"h-[60%] w-[60%] text-white/80\"\n fill=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" />\n </svg>\n )}\n </div>\n );\n }\n);\n\nAvatar.displayName = 'Avatar';\n\n// ============================================================================\n// Avatar Group Component\n// ============================================================================\n\nexport interface AvatarGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Maximum number of avatars to show before +N indicator */\n max?: number;\n /** Size of avatars in the group */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Children should be Avatar components */\n children: React.ReactNode;\n}\n\n/**\n * A component for displaying a group of overlapping avatars.\n *\n * @example\n * ```tsx\n * <AvatarGroup max={3}>\n * <Avatar name=\"John Doe\" />\n * <Avatar name=\"Jane Smith\" />\n * <Avatar name=\"Bob Wilson\" />\n * <Avatar name=\"Alice Brown\" />\n * </AvatarGroup>\n * ```\n */\nconst AvatarGroup = React.forwardRef<HTMLDivElement, AvatarGroupProps>(\n ({ className, max, size = 'md', children, ...props }, ref) => {\n const childrenArray = React.Children.toArray(children);\n const visibleChildren = max ? childrenArray.slice(0, max) : childrenArray;\n const remainingCount = max ? Math.max(0, childrenArray.length - max) : 0;\n\n return (\n <div\n ref={ref}\n data-slot=\"avatar-group\"\n className={cn('flex -space-x-2 rtl:space-x-reverse', className)}\n {...props}\n >\n {visibleChildren.map((child, index) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(\n child as React.ReactElement<AvatarProps>,\n {\n key: index,\n size,\n className: cn(\n 'ring-2 ring-white dark:ring-neutral-900',\n (child as React.ReactElement<AvatarProps>).props.className\n ),\n }\n );\n }\n return child;\n })}\n {remainingCount > 0 && (\n <div\n className={cn(\n avatarVariants({ size }),\n 'bg-neutral-200 text-neutral-600 dark:bg-neutral-700 dark:text-neutral-300',\n 'ring-2 ring-white dark:ring-neutral-900'\n )}\n >\n +{remainingCount}\n </div>\n )}\n </div>\n );\n }\n);\n\nAvatarGroup.displayName = 'AvatarGroup';\n\nexport { Avatar, AvatarGroup, avatarVariants, getInitials };\n"]}
|
|
@@ -3,6 +3,38 @@ import * as React from 'react';
|
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
+
// src/components/Button/button-critical.ts
|
|
7
|
+
var STYLE_ID = "mieweb-ui-button-critical";
|
|
8
|
+
var CRITICAL_CSS = [
|
|
9
|
+
"@layer utilities{",
|
|
10
|
+
// Structure: keep icon + label on one line (matches the base utilities
|
|
11
|
+
// inline-flex items-center justify-center gap-2 min-w-0 whitespace-nowrap).
|
|
12
|
+
`:where(button[data-slot='button']){display:inline-flex;flex-wrap:nowrap;align-items:center;justify-content:center;gap:0.5rem;min-width:0;white-space:nowrap;}`,
|
|
13
|
+
// Icons and the loading spinner never shrink (matches shrink-0).
|
|
14
|
+
`:where(button[data-slot='button']) > :where([data-slot='button-icon'],svg){flex-shrink:0;}`,
|
|
15
|
+
// Label truncates instead of wrapping/overflowing (matches truncate).
|
|
16
|
+
`:where(button[data-slot='button']) > :where([data-slot='button-label']){min-width:0;overflow:hidden;text-overflow:ellipsis;}`,
|
|
17
|
+
"}",
|
|
18
|
+
// Icons passed as children land inside the label span; Tailwind preflight
|
|
19
|
+
// makes SVGs display:block, which forces line breaks inside the inline
|
|
20
|
+
// label. Restore inline flow. This rule is deliberately UNLAYERED at
|
|
21
|
+
// specificity (0,2,2): it must beat Tailwind 3's unlayered preflight
|
|
22
|
+
// `svg{display:block}` (0,0,1) — layering it would neuter the fix for
|
|
23
|
+
// exactly the broken-TW3 apps it exists for. It also outranks the
|
|
24
|
+
// (0,1,1) [&_svg]:inline-block utility on the label, but both declare
|
|
25
|
+
// the same values, so they never conflict. Known tradeoff:
|
|
26
|
+
// display utilities on an SVG inside the label slot won't win; consumers
|
|
27
|
+
// should conditionally render icons instead.
|
|
28
|
+
`button[data-slot='button'] [data-slot='button-label'] svg{display:inline-block;vertical-align:middle;}`
|
|
29
|
+
].join("");
|
|
30
|
+
function injectButtonCriticalStyles() {
|
|
31
|
+
if (typeof document === "undefined") return;
|
|
32
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
33
|
+
const style = document.createElement("style");
|
|
34
|
+
style.id = STYLE_ID;
|
|
35
|
+
style.textContent = CRITICAL_CSS;
|
|
36
|
+
document.head.appendChild(style);
|
|
37
|
+
}
|
|
6
38
|
var buttonVariants = cva(
|
|
7
39
|
// Base styles
|
|
8
40
|
[
|
|
@@ -75,6 +107,7 @@ var buttonVariants = cva(
|
|
|
75
107
|
}
|
|
76
108
|
}
|
|
77
109
|
);
|
|
110
|
+
var labelClasses = "truncate [&_svg]:inline-block [&_svg]:align-middle";
|
|
78
111
|
var Button = React.forwardRef(
|
|
79
112
|
({
|
|
80
113
|
className,
|
|
@@ -94,6 +127,9 @@ var Button = React.forwardRef(
|
|
|
94
127
|
const labelRef = React.useRef(null);
|
|
95
128
|
const innerRef = React.useRef(null);
|
|
96
129
|
React.useImperativeHandle(ref, () => innerRef.current);
|
|
130
|
+
React.useInsertionEffect(() => {
|
|
131
|
+
injectButtonCriticalStyles();
|
|
132
|
+
}, []);
|
|
97
133
|
React.useLayoutEffect(() => {
|
|
98
134
|
const label = labelRef.current;
|
|
99
135
|
const button = innerRef.current;
|
|
@@ -127,11 +163,27 @@ var Button = React.forwardRef(
|
|
|
127
163
|
...props,
|
|
128
164
|
children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
129
165
|
/* @__PURE__ */ jsx(LoadingSpinner, {}),
|
|
130
|
-
/* @__PURE__ */ jsx(
|
|
166
|
+
/* @__PURE__ */ jsx(
|
|
167
|
+
"span",
|
|
168
|
+
{
|
|
169
|
+
ref: labelRef,
|
|
170
|
+
"data-slot": "button-label",
|
|
171
|
+
className: labelClasses,
|
|
172
|
+
children: loadingText || children
|
|
173
|
+
}
|
|
174
|
+
)
|
|
131
175
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
132
|
-
React.isValidElement(leftIcon) && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: leftIcon }),
|
|
133
|
-
/* @__PURE__ */ jsx(
|
|
134
|
-
|
|
176
|
+
React.isValidElement(leftIcon) && /* @__PURE__ */ jsx("span", { "data-slot": "button-icon", className: "shrink-0", children: leftIcon }),
|
|
177
|
+
/* @__PURE__ */ jsx(
|
|
178
|
+
"span",
|
|
179
|
+
{
|
|
180
|
+
ref: labelRef,
|
|
181
|
+
"data-slot": "button-label",
|
|
182
|
+
className: labelClasses,
|
|
183
|
+
children
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
React.isValidElement(rightIcon) && /* @__PURE__ */ jsx("span", { "data-slot": "button-icon", className: "shrink-0", children: rightIcon })
|
|
135
187
|
] })
|
|
136
188
|
}
|
|
137
189
|
);
|
|
@@ -173,5 +225,5 @@ function LoadingSpinner() {
|
|
|
173
225
|
}
|
|
174
226
|
|
|
175
227
|
export { Button, buttonVariants };
|
|
176
|
-
//# sourceMappingURL=chunk-
|
|
177
|
-
//# sourceMappingURL=chunk-
|
|
228
|
+
//# sourceMappingURL=chunk-KREUYVMZ.js.map
|
|
229
|
+
//# sourceMappingURL=chunk-KREUYVMZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Button/button-critical.ts","../src/components/Button/Button.tsx"],"names":[],"mappings":"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","file":"chunk-KREUYVMZ.js","sourcesContent":["/**\n * Self-healing structural CSS for Button.\n *\n * Button layout relies on Tailwind utilities (`inline-flex`,\n * `whitespace-nowrap`, ...). Consumer apps with a stale safelist copy or a\n * missing `@source` line never generate those classes, so the button falls\n * back to `inline-block` and the icon stacks above the label.\n *\n * Injecting these rules from the component guarantees every consumer gets\n * correct button structure just by upgrading the library — no app-side\n * changes required.\n *\n * Override safety, by consumer setup:\n * - Tailwind 4: utilities live in `@layer utilities`. The structural rules\n * below join that same layer, so conflicts resolve by specificity — and\n * every selector is wrapped in `:where()` (zero specificity), so real\n * utilities (`hidden`, `gap-0`, ...) always win. (A new layer name can't\n * be used: layers declared later outrank `utilities`.)\n * - Tailwind 3 / no Tailwind: consumer CSS is unlayered, and unlayered\n * always beats layered, so the structural rules stay a pure fallback.\n */\n\nconst STYLE_ID = 'mieweb-ui-button-critical';\n\nconst CRITICAL_CSS = [\n '@layer utilities{',\n // Structure: keep icon + label on one line (matches the base utilities\n // inline-flex items-center justify-center gap-2 min-w-0 whitespace-nowrap).\n `:where(button[data-slot='button']){display:inline-flex;flex-wrap:nowrap;align-items:center;justify-content:center;gap:0.5rem;min-width:0;white-space:nowrap;}`,\n // Icons and the loading spinner never shrink (matches shrink-0).\n `:where(button[data-slot='button']) > :where([data-slot='button-icon'],svg){flex-shrink:0;}`,\n // Label truncates instead of wrapping/overflowing (matches truncate).\n `:where(button[data-slot='button']) > :where([data-slot='button-label']){min-width:0;overflow:hidden;text-overflow:ellipsis;}`,\n '}',\n // Icons passed as children land inside the label span; Tailwind preflight\n // makes SVGs display:block, which forces line breaks inside the inline\n // label. Restore inline flow. This rule is deliberately UNLAYERED at\n // specificity (0,2,2): it must beat Tailwind 3's unlayered preflight\n // `svg{display:block}` (0,0,1) — layering it would neuter the fix for\n // exactly the broken-TW3 apps it exists for. It also outranks the\n // (0,1,1) [&_svg]:inline-block utility on the label, but both declare\n // the same values, so they never conflict. Known tradeoff:\n // display utilities on an SVG inside the label slot won't win; consumers\n // should conditionally render icons instead.\n `button[data-slot='button'] [data-slot='button-label'] svg{display:inline-block;vertical-align:middle;}`,\n].join('');\n\n/** Injects the critical Button styles once per document. SSR-safe. */\nexport function injectButtonCriticalStyles(): void {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = CRITICAL_CSS;\n document.head.appendChild(style);\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { injectButtonCriticalStyles } from './button-critical';\n\nconst buttonVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2',\n 'min-w-0 whitespace-nowrap',\n 'font-semibold transition-all duration-200',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'active:scale-[0.98]',\n ],\n {\n variants: {\n variant: {\n primary: [\n 'bg-primary-800 text-white',\n 'hover:bg-primary-900',\n 'active:bg-primary-950',\n ],\n secondary: [\n 'bg-neutral-200 text-neutral-900',\n 'hover:bg-neutral-300',\n 'active:bg-neutral-400',\n 'dark:bg-neutral-700 dark:text-neutral-100',\n 'dark:hover:bg-neutral-600',\n 'dark:active:bg-neutral-500',\n ],\n ghost: [\n 'bg-transparent text-neutral-600',\n 'hover:bg-neutral-100',\n 'active:bg-neutral-200',\n 'dark:text-neutral-400',\n 'dark:hover:bg-neutral-800',\n 'dark:active:bg-neutral-700',\n ],\n outline: [\n 'border-2 border-primary-800 text-primary-800 bg-transparent',\n 'hover:bg-primary-50 hover:text-primary-900',\n 'active:bg-primary-100',\n 'dark:border-primary-400 dark:text-primary-400',\n 'dark:hover:bg-primary-950',\n 'dark:active:bg-primary-900',\n ],\n danger: [\n 'bg-red-600 text-white',\n 'hover:bg-red-700',\n 'active:bg-red-800',\n ],\n link: [\n 'text-primary-800 underline-offset-4',\n 'hover:underline hover:text-primary-900',\n 'active:text-primary-950',\n 'dark:text-primary-400',\n ],\n },\n size: {\n sm: 'h-8 px-3 text-sm rounded-md',\n md: 'h-10 px-4 text-base rounded-lg',\n lg: 'h-12 px-6 text-lg rounded-xl',\n icon: 'h-10 w-10 rounded-lg',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n fullWidth: false,\n },\n }\n);\n\n/**\n * Label wrapper classes. Icons passed as `children` (rather than\n * leftIcon/rightIcon) land inside this span; preflight makes SVGs\n * display:block which would force line breaks inside the inline span,\n * so restore inline flow for them.\n */\nconst labelClasses = 'truncate [&_svg]:inline-block [&_svg]:align-middle';\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n /** Optional icon element to render before the button text */\n leftIcon?: React.ReactElement | null;\n /** Optional icon element to render after the button text */\n rightIcon?: React.ReactElement | null;\n /** Shows a loading spinner and disables the button */\n isLoading?: boolean;\n /** Accessible label for the loading state */\n loadingText?: string;\n}\n\n/**\n * A versatile button component with multiple variants and sizes.\n *\n * @example\n * ```tsx\n * <Button variant=\"primary\" size=\"md\">Click me</Button>\n * <Button variant=\"danger\" leftIcon={<TrashIcon />}>Delete</Button>\n * <Button variant=\"ghost\" isLoading loadingText=\"Saving...\">Save</Button>\n * ```\n */\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant,\n size,\n fullWidth,\n leftIcon,\n rightIcon,\n isLoading,\n loadingText,\n disabled,\n children,\n title,\n ...props\n },\n ref\n ) => {\n const resolvedSize = size ?? 'md';\n const labelRef = React.useRef<HTMLSpanElement>(null);\n const innerRef = React.useRef<HTMLButtonElement>(null);\n React.useImperativeHandle(ref, () => innerRef.current as HTMLButtonElement);\n\n // Guarantees correct icon/label layout even when the consumer's Tailwind\n // build is missing our utility classes. See button-critical.ts.\n React.useInsertionEffect(() => {\n injectButtonCriticalStyles();\n }, []);\n\n // When the label truncates, expose the full text as a native tooltip.\n // A consumer-provided `title` always takes precedence.\n React.useLayoutEffect(() => {\n const label = labelRef.current;\n const button = innerRef.current;\n if (!label || !button || title !== undefined) return;\n\n const update = () => {\n if (label.scrollWidth > label.clientWidth) {\n button.title = label.textContent ?? '';\n } else {\n button.removeAttribute('title');\n }\n };\n\n update();\n if (typeof globalThis.ResizeObserver === 'undefined') return;\n const observer = new globalThis.ResizeObserver(update);\n observer.observe(label);\n return () => observer.disconnect();\n }, [title, children, isLoading, loadingText]);\n\n return (\n <button\n data-slot=\"button\"\n data-size={resolvedSize}\n className={cn(\n buttonVariants({ variant, size: resolvedSize, fullWidth }),\n className\n )}\n ref={innerRef}\n disabled={disabled || isLoading}\n aria-busy={isLoading}\n title={title}\n {...props}\n >\n {isLoading ? (\n <>\n <LoadingSpinner />\n <span\n ref={labelRef}\n data-slot=\"button-label\"\n className={labelClasses}\n >\n {loadingText || children}\n </span>\n </>\n ) : (\n <>\n {React.isValidElement(leftIcon) && (\n <span data-slot=\"button-icon\" className=\"shrink-0\">\n {leftIcon}\n </span>\n )}\n <span\n ref={labelRef}\n data-slot=\"button-label\"\n className={labelClasses}\n >\n {children}\n </span>\n {React.isValidElement(rightIcon) && (\n <span data-slot=\"button-icon\" className=\"shrink-0\">\n {rightIcon}\n </span>\n )}\n </>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n\n/**\n * Simple loading spinner for the button\n */\nfunction LoadingSpinner() {\n return (\n <svg\n className=\"h-4 w-4 shrink-0 animate-spin\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n );\n}\n\nexport { Button, buttonVariants };\n"]}
|
|
@@ -78,6 +78,7 @@ var Accordion = React.forwardRef(
|
|
|
78
78
|
{
|
|
79
79
|
type: "button",
|
|
80
80
|
id: triggerId,
|
|
81
|
+
"data-slot": "accordion-trigger",
|
|
81
82
|
"aria-expanded": isOpen,
|
|
82
83
|
"aria-controls": panelId,
|
|
83
84
|
disabled: item.disabled,
|
|
@@ -114,7 +115,14 @@ var Accordion = React.forwardRef(
|
|
|
114
115
|
"grid transition-[grid-template-rows] duration-200 ease-out",
|
|
115
116
|
isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
|
|
116
117
|
),
|
|
117
|
-
children: /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
118
|
+
children: /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
"data-slot": "accordion-content",
|
|
122
|
+
className: "text-muted-foreground px-5 pb-4 text-sm leading-relaxed",
|
|
123
|
+
children: item.content
|
|
124
|
+
}
|
|
125
|
+
) })
|
|
118
126
|
}
|
|
119
127
|
)
|
|
120
128
|
] }, item.id);
|
|
@@ -125,5 +133,5 @@ var Accordion = React.forwardRef(
|
|
|
125
133
|
);
|
|
126
134
|
|
|
127
135
|
export { Accordion };
|
|
128
|
-
//# sourceMappingURL=chunk-
|
|
129
|
-
//# sourceMappingURL=chunk-
|
|
136
|
+
//# sourceMappingURL=chunk-KRU6IGV7.js.map
|
|
137
|
+
//# sourceMappingURL=chunk-KRU6IGV7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Accordion/Accordion.tsx"],"names":["Accordion"],"mappings":"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","file":"chunk-KRU6IGV7.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst accordionVariants = cva('', {\n variants: {\n variant: {\n // Each item is its own card with spacing between\n separated: 'flex flex-col gap-3',\n // One bordered list with dividers\n joined: 'border-border divide-border divide-y rounded-lg border',\n },\n },\n defaultVariants: {\n variant: 'separated',\n },\n});\n\nconst itemVariants = cva('overflow-hidden', {\n variants: {\n variant: {\n separated: 'border-border bg-card rounded-lg border',\n joined: 'bg-card first:rounded-t-lg last:rounded-b-lg',\n },\n },\n defaultVariants: {\n variant: 'separated',\n },\n});\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AccordionItem {\n /** Stable id used for open state and aria wiring. */\n id: string;\n /** Header label (e.g. an FAQ question). */\n title: React.ReactNode;\n /** Panel content (e.g. the answer). */\n content: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface AccordionProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>,\n VariantProps<typeof accordionVariants> {\n items: AccordionItem[];\n /** `single` keeps at most one panel open; `multiple` allows any number. */\n type?: 'single' | 'multiple';\n /** Ids open initially (uncontrolled). */\n defaultOpenIds?: string[];\n /** Controlled open ids. Changes reported via `onOpenChange`. */\n openIds?: string[];\n onOpenChange?: (openIds: string[]) => void;\n /** In `single` mode, allow closing the open panel (default true). */\n collapsible?: boolean;\n /** Heading level wrapping each trigger for document outline (default h3). */\n headingLevel?: 'h2' | 'h3' | 'h4';\n}\n\n// =============================================================================\n// Accordion\n// =============================================================================\n\n/**\n * A vertically stacked set of expandable panels — FAQ lists, settings\n * groups, progressive disclosure. Panels animate open to their natural\n * height (CSS grid rows, no max-height clipping), and headers are real\n * buttons inside headings with full `aria-expanded`/`aria-controls` wiring.\n *\n * @example\n * ```tsx\n * <Accordion\n * type=\"single\"\n * items={[\n * { id: 'pricing', title: 'How is pricing calculated?', content: <p>…</p> },\n * { id: 'billing', title: 'When am I billed?', content: <p>…</p> },\n * ]}\n * />\n * ```\n */\nexport const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(\n function Accordion(\n {\n items,\n type = 'single',\n defaultOpenIds,\n openIds: controlledOpen,\n onOpenChange,\n collapsible = true,\n headingLevel: Heading = 'h3',\n variant,\n className,\n ...props\n },\n ref\n ) {\n const baseId = React.useId();\n const [internalOpen, setInternalOpen] = React.useState<string[]>(\n () => defaultOpenIds ?? []\n );\n const rawOpen = controlledOpen ?? internalOpen;\n // Single mode keeps at most one panel open, even if defaultOpenIds or a\n // controlled openIds array hands us several.\n const open = React.useMemo(\n () => (type === 'single' ? rawOpen.slice(0, 1) : rawOpen),\n [type, rawOpen]\n );\n const openSet = React.useMemo(() => new Set(open), [open]);\n\n const toggle = (id: string) => {\n let next: string[];\n if (openSet.has(id)) {\n if (type === 'single' && !collapsible) return;\n next = open.filter((o) => o !== id);\n } else {\n next = type === 'single' ? [id] : [...open, id];\n }\n if (controlledOpen === undefined) setInternalOpen(next);\n onOpenChange?.(next);\n };\n\n return (\n <div\n ref={ref}\n className={cn(accordionVariants({ variant }), className)}\n {...props}\n >\n {items.map((item) => {\n const isOpen = openSet.has(item.id);\n const triggerId = `${baseId}-${item.id}-trigger`;\n const panelId = `${baseId}-${item.id}-panel`;\n return (\n <div key={item.id} className={cn(itemVariants({ variant }))}>\n <Heading className=\"m-0\">\n <button\n type=\"button\"\n id={triggerId}\n data-slot=\"accordion-trigger\"\n aria-expanded={isOpen}\n aria-controls={panelId}\n disabled={item.disabled}\n onClick={() => toggle(item.id)}\n className={cn(\n 'hover:bg-muted/60 flex w-full items-center justify-between gap-4 px-5 py-4 text-start transition-colors',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset',\n 'disabled:pointer-events-none disabled:opacity-50'\n )}\n >\n <span className=\"text-foreground min-w-0 text-sm font-semibold\">\n {item.title}\n </span>\n <ChevronDown\n aria-hidden=\"true\"\n className={cn(\n 'text-muted-foreground h-5 w-5 shrink-0 transition-transform duration-200',\n isOpen && 'rotate-180'\n )}\n />\n </button>\n </Heading>\n {/* grid-rows 0fr→1fr animates to natural height without a max-height clip;\n collapsed panels are hidden from AT and unfocusable via aria-hidden + inert */}\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n aria-hidden={!isOpen}\n inert={!isOpen || undefined}\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-out',\n isOpen ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'\n )}\n >\n <div className=\"overflow-hidden\">\n <div\n data-slot=\"accordion-content\"\n className=\"text-muted-foreground px-5 pb-4 text-sm leading-relaxed\"\n >\n {item.content}\n </div>\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n }\n);\n"]}
|