@mieweb/ui 0.10.0-dev.31 → 0.10.0-dev.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CsvBlock-CFXSDPBI.js +9 -0
- package/dist/{CsvBlock-VLMG7GUO.js.map → CsvBlock-CFXSDPBI.js.map} +1 -1
- package/dist/CsvBlock-RGO7JXHJ.cjs +18 -0
- package/dist/{CsvBlock-FX5YNGNE.cjs.map → CsvBlock-RGO7JXHJ.cjs.map} +1 -1
- package/dist/HtmlPreviewBlock-VBYXCXVT.cjs +18 -0
- package/dist/{HtmlPreviewBlock-UO37JQ3K.cjs.map → HtmlPreviewBlock-VBYXCXVT.cjs.map} +1 -1
- package/dist/HtmlPreviewBlock-Z2GCK325.js +9 -0
- package/dist/{HtmlPreviewBlock-5JE7L3GR.js.map → HtmlPreviewBlock-Z2GCK325.js.map} +1 -1
- package/dist/MermaidBlock-I2R2BQOX.cjs +18 -0
- package/dist/{MermaidBlock-RZ75RPZA.cjs.map → MermaidBlock-I2R2BQOX.cjs.map} +1 -1
- package/dist/MermaidBlock-XCAK7IA5.js +9 -0
- package/dist/{MermaidBlock-3XHFBAMV.js.map → MermaidBlock-XCAK7IA5.js.map} +1 -1
- package/dist/SurveyBlock-KI5JOWCL.js +9 -0
- package/dist/{SurveyBlock-MUVJ3JUI.js.map → SurveyBlock-KI5JOWCL.js.map} +1 -1
- package/dist/SurveyBlock-UKSGISRT.cjs +18 -0
- package/dist/{SurveyBlock-VH47YXZC.cjs.map → SurveyBlock-UKSGISRT.cjs.map} +1 -1
- package/dist/brands/index.cjs +7 -7
- package/dist/brands/index.js +2 -2
- package/dist/{chunk-6ZPTZTKN.js → chunk-24AFHH4J.js} +3 -3
- package/dist/{chunk-6ZPTZTKN.js.map → chunk-24AFHH4J.js.map} +1 -1
- package/dist/{chunk-BNH4SXJB.js → chunk-2X54ZLT6.js} +6 -6
- package/dist/{chunk-BNH4SXJB.js.map → chunk-2X54ZLT6.js.map} +1 -1
- package/dist/{chunk-TYE5K5WV.cjs → chunk-32ZCJOSR.cjs} +4 -4
- package/dist/{chunk-TYE5K5WV.cjs.map → chunk-32ZCJOSR.cjs.map} +1 -1
- package/dist/chunk-47P5QLX4.cjs +42 -0
- package/dist/chunk-47P5QLX4.cjs.map +1 -0
- package/dist/chunk-4ZB7RSMY.cjs +306 -0
- package/dist/chunk-4ZB7RSMY.cjs.map +1 -0
- package/dist/chunk-56VTM4OX.js +261 -0
- package/dist/chunk-56VTM4OX.js.map +1 -0
- package/dist/{chunk-D22GE27K.js → chunk-5A4SL436.js} +4 -4
- package/dist/{chunk-D22GE27K.js.map → chunk-5A4SL436.js.map} +1 -1
- package/dist/chunk-6BNZLN4B.cjs +548 -0
- package/dist/chunk-6BNZLN4B.cjs.map +1 -0
- package/dist/chunk-6JSFT2J5.js +130 -0
- package/dist/chunk-6JSFT2J5.js.map +1 -0
- package/dist/chunk-6N7NMOSV.js +233 -0
- package/dist/chunk-6N7NMOSV.js.map +1 -0
- package/dist/chunk-6TTCZY3P.cjs +4 -0
- package/dist/chunk-6TTCZY3P.cjs.map +1 -0
- package/dist/{chunk-TTSSUOEV.cjs → chunk-7C5W744U.cjs} +8 -8
- package/dist/{chunk-TTSSUOEV.cjs.map → chunk-7C5W744U.cjs.map} +1 -1
- package/dist/chunk-7HUTR6RX.js +178 -0
- package/dist/chunk-7HUTR6RX.js.map +1 -0
- package/dist/chunk-7IRTD4JT.cjs +61 -0
- package/dist/chunk-7IRTD4JT.cjs.map +1 -0
- package/dist/{chunk-YU55JD35.js → chunk-7QW6TU4X.js} +3 -3
- package/dist/{chunk-YU55JD35.js.map → chunk-7QW6TU4X.js.map} +1 -1
- package/dist/chunk-7WJ6MBF5.cjs +47 -0
- package/dist/chunk-7WJ6MBF5.cjs.map +1 -0
- package/dist/chunk-A4W5CSK7.cjs +216 -0
- package/dist/chunk-A4W5CSK7.cjs.map +1 -0
- package/dist/{chunk-WXFGHDTV.cjs → chunk-AJPFQF3H.cjs} +18 -18
- package/dist/{chunk-WXFGHDTV.cjs.map → chunk-AJPFQF3H.cjs.map} +1 -1
- package/dist/chunk-AMYFRY7K.js +3 -0
- package/dist/chunk-AMYFRY7K.js.map +1 -0
- package/dist/{chunk-X6A27RGO.cjs → chunk-ANMX7YDL.cjs} +2 -2
- package/dist/{chunk-X6A27RGO.cjs.map → chunk-ANMX7YDL.cjs.map} +1 -1
- package/dist/{chunk-DVOQ3JNO.js → chunk-B4CKCNWD.js} +16 -8
- package/dist/chunk-B4CKCNWD.js.map +1 -0
- package/dist/chunk-BJ6ABRSQ.cjs +256 -0
- package/dist/chunk-BJ6ABRSQ.cjs.map +1 -0
- package/dist/chunk-BXRQ6HEP.cjs +4 -0
- package/dist/chunk-BXRQ6HEP.cjs.map +1 -0
- package/dist/{chunk-TJCX4OML.cjs → chunk-C77FAR3F.cjs} +2 -2
- package/dist/{chunk-TJCX4OML.cjs.map → chunk-C77FAR3F.cjs.map} +1 -1
- package/dist/chunk-CBBKWRLG.js +213 -0
- package/dist/chunk-CBBKWRLG.js.map +1 -0
- package/dist/{chunk-ZTMYKAVU.cjs → chunk-CCAVJSWL.cjs} +49 -48
- package/dist/chunk-CCAVJSWL.cjs.map +1 -0
- package/dist/chunk-CPDNX3LS.cjs +47 -0
- package/dist/chunk-CPDNX3LS.cjs.map +1 -0
- package/dist/chunk-CVNPNZMX.js +44 -0
- package/dist/chunk-CVNPNZMX.js.map +1 -0
- package/dist/chunk-DHGCLPFZ.js +91 -0
- package/dist/chunk-DHGCLPFZ.js.map +1 -0
- package/dist/chunk-DO2YN46R.cjs +201 -0
- package/dist/chunk-DO2YN46R.cjs.map +1 -0
- package/dist/chunk-DVDT7TX7.js +151 -0
- package/dist/chunk-DVDT7TX7.js.map +1 -0
- package/dist/{chunk-R5Z7AOVU.cjs → chunk-DZ3JTMKM.cjs} +9 -9
- package/dist/{chunk-R5Z7AOVU.cjs.map → chunk-DZ3JTMKM.cjs.map} +1 -1
- package/dist/chunk-EACNRR3C.cjs +4 -0
- package/dist/chunk-EACNRR3C.cjs.map +1 -0
- package/dist/{chunk-E2PBPQGS.js → chunk-EEOGIGIA.js} +2 -2
- package/dist/{chunk-E2PBPQGS.js.map → chunk-EEOGIGIA.js.map} +1 -1
- package/dist/chunk-EPCUPHEO.js +193 -0
- package/dist/chunk-EPCUPHEO.js.map +1 -0
- package/dist/chunk-EPTP3VKT.js +283 -0
- package/dist/chunk-EPTP3VKT.js.map +1 -0
- package/dist/{chunk-HIZWOAWY.cjs → chunk-ERACGSDY.cjs} +8 -8
- package/dist/{chunk-HIZWOAWY.cjs.map → chunk-ERACGSDY.cjs.map} +1 -1
- package/dist/{chunk-VOQJHSXN.cjs → chunk-F2FOG4EG.cjs} +9 -9
- package/dist/{chunk-VOQJHSXN.cjs.map → chunk-F2FOG4EG.cjs.map} +1 -1
- package/dist/{chunk-GBUVIGD5.js → chunk-F3EWRDIT.js} +99 -3
- package/dist/chunk-F3EWRDIT.js.map +1 -0
- package/dist/{chunk-GVLNXPJX.js → chunk-FGLIP6YR.js} +4 -4
- package/dist/{chunk-GVLNXPJX.js.map → chunk-FGLIP6YR.js.map} +1 -1
- package/dist/chunk-FKGFOBC2.js +314 -0
- package/dist/chunk-FKGFOBC2.js.map +1 -0
- package/dist/chunk-FSGJXCBG.cjs +318 -0
- package/dist/chunk-FSGJXCBG.cjs.map +1 -0
- package/dist/chunk-FTEZNCRI.js +29 -0
- package/dist/chunk-FTEZNCRI.js.map +1 -0
- package/dist/{chunk-COM7RNZU.cjs → chunk-FYQZWLAM.cjs} +2 -2
- package/dist/{chunk-COM7RNZU.cjs.map → chunk-FYQZWLAM.cjs.map} +1 -1
- package/dist/{chunk-YVPC65ZJ.cjs → chunk-GF2BE4FB.cjs} +91 -32
- package/dist/chunk-GF2BE4FB.cjs.map +1 -0
- package/dist/{chunk-JEIW7BSV.cjs → chunk-GKDHMNUA.cjs} +2 -52
- package/dist/chunk-GKDHMNUA.cjs.map +1 -0
- package/dist/{chunk-N7C4OEP7.cjs → chunk-GM32IDVL.cjs} +6 -6
- package/dist/{chunk-N7C4OEP7.cjs.map → chunk-GM32IDVL.cjs.map} +1 -1
- package/dist/chunk-GY5SP4ST.js +3 -0
- package/dist/chunk-GY5SP4ST.js.map +1 -0
- package/dist/chunk-H2Y7HZV5.js +3 -0
- package/dist/chunk-H2Y7HZV5.js.map +1 -0
- package/dist/chunk-H3QPREIJ.js +195 -0
- package/dist/chunk-H3QPREIJ.js.map +1 -0
- package/dist/{chunk-QOVJ6Z6R.js → chunk-HDY7YQFX.js} +3 -3
- package/dist/{chunk-QOVJ6Z6R.js.map → chunk-HDY7YQFX.js.map} +1 -1
- package/dist/chunk-HNFFFFYH.cjs +114 -0
- package/dist/chunk-HNFFFFYH.cjs.map +1 -0
- package/dist/chunk-HNXLLDPN.js +25 -0
- package/dist/chunk-HNXLLDPN.js.map +1 -0
- package/dist/chunk-I2MMUFCN.cjs +154 -0
- package/dist/chunk-I2MMUFCN.cjs.map +1 -0
- package/dist/{chunk-GYXUS65N.cjs → chunk-IGDO62KR.cjs} +5 -5
- package/dist/{chunk-GYXUS65N.cjs.map → chunk-IGDO62KR.cjs.map} +1 -1
- package/dist/{chunk-HC3NAN55.cjs → chunk-IPL2O2OL.cjs} +19 -19
- package/dist/{chunk-HC3NAN55.cjs.map → chunk-IPL2O2OL.cjs.map} +1 -1
- package/dist/chunk-ISUIKUX7.cjs +337 -0
- package/dist/chunk-ISUIKUX7.cjs.map +1 -0
- package/dist/{chunk-N5O47VGS.cjs → chunk-IVGI353O.cjs} +2 -2
- package/dist/{chunk-N5O47VGS.cjs.map → chunk-IVGI353O.cjs.map} +1 -1
- package/dist/chunk-IWRBJHO3.cjs +51 -0
- package/dist/chunk-IWRBJHO3.cjs.map +1 -0
- package/dist/{chunk-BIQ7GSO2.js → chunk-JMAZ2GKT.js} +3 -3
- package/dist/{chunk-BIQ7GSO2.js.map → chunk-JMAZ2GKT.js.map} +1 -1
- package/dist/{chunk-KRU6IGV7.js → chunk-JUJGWUAN.js} +28 -6
- package/dist/chunk-JUJGWUAN.js.map +1 -0
- package/dist/{chunk-BUT6MF5K.cjs → chunk-KQ6GLYFZ.cjs} +4 -4
- package/dist/{chunk-BUT6MF5K.cjs.map → chunk-KQ6GLYFZ.cjs.map} +1 -1
- package/dist/chunk-L6K4PRZK.cjs +4 -0
- package/dist/chunk-L6K4PRZK.cjs.map +1 -0
- package/dist/{chunk-T4L7Q5FA.cjs → chunk-LC3JL2HB.cjs} +6 -2
- package/dist/chunk-LC3JL2HB.cjs.map +1 -0
- package/dist/{chunk-P7UMS4E6.cjs → chunk-LC7PVBXH.cjs} +16 -8
- package/dist/chunk-LC7PVBXH.cjs.map +1 -0
- package/dist/chunk-LRRSD7LR.js +248 -0
- package/dist/chunk-LRRSD7LR.js.map +1 -0
- package/dist/chunk-LSMS6DY7.cjs +331 -0
- package/dist/chunk-LSMS6DY7.cjs.map +1 -0
- package/dist/chunk-M3VPGJMV.js +283 -0
- package/dist/chunk-M3VPGJMV.js.map +1 -0
- package/dist/{chunk-QURJVPRH.cjs → chunk-MJJJDQ5P.cjs} +46 -2
- package/dist/chunk-MJJJDQ5P.cjs.map +1 -0
- package/dist/{chunk-2JICT4A2.js → chunk-N54FYWG6.js} +3 -3
- package/dist/{chunk-2JICT4A2.js.map → chunk-N54FYWG6.js.map} +1 -1
- package/dist/chunk-N5JDL4VE.js +3 -0
- package/dist/chunk-N5JDL4VE.js.map +1 -0
- package/dist/{chunk-KGKBZN3T.cjs → chunk-NAH65KPK.cjs} +8 -8
- package/dist/{chunk-KGKBZN3T.cjs.map → chunk-NAH65KPK.cjs.map} +1 -1
- package/dist/{chunk-NKV76R65.cjs → chunk-O6BJMVGT.cjs} +45 -45
- package/dist/{chunk-NKV76R65.cjs.map → chunk-O6BJMVGT.cjs.map} +1 -1
- package/dist/{chunk-SVSHA7XV.js → chunk-O6XDA3SI.js} +31 -33
- package/dist/chunk-O6XDA3SI.js.map +1 -0
- package/dist/chunk-OIF34LEN.cjs +425 -0
- package/dist/chunk-OIF34LEN.cjs.map +1 -0
- package/dist/chunk-ORCCJ5VY.cjs +218 -0
- package/dist/chunk-ORCCJ5VY.cjs.map +1 -0
- package/dist/{chunk-CRS2CQWM.js → chunk-OSTSZDQC.js} +3 -3
- package/dist/{chunk-CRS2CQWM.js.map → chunk-OSTSZDQC.js.map} +1 -1
- package/dist/chunk-P22YCUVM.cjs +4 -0
- package/dist/chunk-P22YCUVM.cjs.map +1 -0
- package/dist/chunk-P55LNEDH.cjs +306 -0
- package/dist/chunk-P55LNEDH.cjs.map +1 -0
- package/dist/{chunk-R6KPWIGO.js → chunk-P7D7BYFE.js} +4 -4
- package/dist/{chunk-R6KPWIGO.js.map → chunk-P7D7BYFE.js.map} +1 -1
- package/dist/{chunk-GU5OS7JJ.cjs → chunk-PYI2IWNX.cjs} +4 -4
- package/dist/{chunk-GU5OS7JJ.cjs.map → chunk-PYI2IWNX.cjs.map} +1 -1
- package/dist/chunk-Q3YVLO52.cjs +174 -0
- package/dist/chunk-Q3YVLO52.cjs.map +1 -0
- package/dist/{chunk-K34DXMLZ.js → chunk-QJ2L5RU6.js} +7 -7
- package/dist/{chunk-K34DXMLZ.js.map → chunk-QJ2L5RU6.js.map} +1 -1
- package/dist/{chunk-X4LBUPJO.cjs → chunk-QX6AAVDE.cjs} +31 -33
- package/dist/chunk-QX6AAVDE.cjs.map +1 -0
- package/dist/{chunk-LFPJ3OUM.cjs → chunk-RIUQP2QS.cjs} +5 -5
- package/dist/{chunk-LFPJ3OUM.cjs.map → chunk-RIUQP2QS.cjs.map} +1 -1
- package/dist/{chunk-JHG3ELS2.js → chunk-RPFATYUI.js} +2 -2
- package/dist/{chunk-JHG3ELS2.js.map → chunk-RPFATYUI.js.map} +1 -1
- package/dist/{chunk-FZURBQJ2.js → chunk-RSJGTWLM.js} +3 -3
- package/dist/{chunk-FZURBQJ2.js.map → chunk-RSJGTWLM.js.map} +1 -1
- package/dist/{chunk-XBTKZCZF.js → chunk-RZSSQ7AT.js} +3 -3
- package/dist/{chunk-XBTKZCZF.js.map → chunk-RZSSQ7AT.js.map} +1 -1
- package/dist/{chunk-SD7ONW6S.js → chunk-S2JZL4JC.js} +5 -5
- package/dist/{chunk-SD7ONW6S.js.map → chunk-S2JZL4JC.js.map} +1 -1
- package/dist/{chunk-VROIMIHB.cjs → chunk-SHBCUXFS.cjs} +28 -6
- package/dist/chunk-SHBCUXFS.cjs.map +1 -0
- package/dist/{chunk-JELTRRR5.cjs → chunk-SW2E7XKY.cjs} +9 -9
- package/dist/{chunk-JELTRRR5.cjs.map → chunk-SW2E7XKY.cjs.map} +1 -1
- package/dist/chunk-SZSRGUVO.js +402 -0
- package/dist/chunk-SZSRGUVO.js.map +1 -0
- package/dist/{chunk-HZ4MBUC3.js → chunk-TI3TQQ7F.js} +4 -53
- package/dist/chunk-TI3TQQ7F.js.map +1 -0
- package/dist/{chunk-MLAWXPRY.js → chunk-TKWNXAFI.js} +46 -2
- package/dist/chunk-TKWNXAFI.js.map +1 -0
- package/dist/{chunk-H2IAMSHK.js → chunk-TVEJKKIM.js} +3 -3
- package/dist/{chunk-H2IAMSHK.js.map → chunk-TVEJKKIM.js.map} +1 -1
- package/dist/{chunk-LHBWRMNC.cjs → chunk-TVU4KB27.cjs} +130 -12
- package/dist/chunk-TVU4KB27.cjs.map +1 -0
- package/dist/{chunk-ENMXHZNE.js → chunk-TWQSMUE6.js} +6 -2
- package/dist/chunk-TWQSMUE6.js.map +1 -0
- package/dist/{chunk-ZYL4SNOR.js → chunk-UJDWFDKE.js} +3 -3
- package/dist/{chunk-ZYL4SNOR.js.map → chunk-UJDWFDKE.js.map} +1 -1
- package/dist/{chunk-4HC2IBOX.js → chunk-UNFDIBKJ.js} +3 -3
- package/dist/{chunk-4HC2IBOX.js.map → chunk-UNFDIBKJ.js.map} +1 -1
- package/dist/chunk-UTIPENPW.cjs +286 -0
- package/dist/chunk-UTIPENPW.cjs.map +1 -0
- package/dist/{chunk-IYWG72DM.js → chunk-VEE46VTX.js} +4 -4
- package/dist/{chunk-IYWG72DM.js.map → chunk-VEE46VTX.js.map} +1 -1
- package/dist/{chunk-Y4E2WRUR.cjs → chunk-VFFV7EMT.cjs} +6 -6
- package/dist/{chunk-Y4E2WRUR.cjs.map → chunk-VFFV7EMT.cjs.map} +1 -1
- package/dist/chunk-VNEAQCY2.js +308 -0
- package/dist/chunk-VNEAQCY2.js.map +1 -0
- package/dist/chunk-VOYLX32A.cjs +271 -0
- package/dist/chunk-VOYLX32A.cjs.map +1 -0
- package/dist/{chunk-7ZV67VZE.js → chunk-VSRO4PAI.js} +21 -3
- package/dist/chunk-VSRO4PAI.js.map +1 -0
- package/dist/{chunk-L6MDULYB.js → chunk-VU3ZMJBN.js} +2 -2
- package/dist/{chunk-L6MDULYB.js.map → chunk-VU3ZMJBN.js.map} +1 -1
- package/dist/{chunk-CPPUT74P.cjs → chunk-VV2U36T6.cjs} +9 -9
- package/dist/{chunk-CPPUT74P.cjs.map → chunk-VV2U36T6.cjs.map} +1 -1
- package/dist/{chunk-35Y4ILCU.cjs → chunk-VXW7D5LR.cjs} +21 -3
- package/dist/chunk-VXW7D5LR.cjs.map +1 -0
- package/dist/{chunk-7YO7DNUV.js → chunk-WFBUBT54.js} +2 -2
- package/dist/{chunk-7YO7DNUV.js.map → chunk-WFBUBT54.js.map} +1 -1
- package/dist/chunk-WQHBMZSC.js +295 -0
- package/dist/chunk-WQHBMZSC.js.map +1 -0
- package/dist/chunk-X5JOEZVR.js +525 -0
- package/dist/chunk-X5JOEZVR.js.map +1 -0
- package/dist/chunk-XBAAHOCP.js +3 -0
- package/dist/chunk-XBAAHOCP.js.map +1 -0
- package/dist/chunk-XNPDZANN.cjs +238 -0
- package/dist/chunk-XNPDZANN.cjs.map +1 -0
- package/dist/chunk-XXA4NZUC.js +3 -0
- package/dist/chunk-XXA4NZUC.js.map +1 -0
- package/dist/chunk-Y424YL55.js +59 -0
- package/dist/chunk-Y424YL55.js.map +1 -0
- package/dist/chunk-YGS2TRMP.js +38 -0
- package/dist/chunk-YGS2TRMP.js.map +1 -0
- package/dist/{chunk-JBIGSP2T.js → chunk-YMILRSRO.js} +6 -5
- package/dist/chunk-YMILRSRO.js.map +1 -0
- package/dist/chunk-YUMOM3KE.js +167 -0
- package/dist/chunk-YUMOM3KE.js.map +1 -0
- package/dist/{chunk-3KPDQG5O.cjs → chunk-ZG6FXMDX.cjs} +5 -5
- package/dist/{chunk-3KPDQG5O.cjs.map → chunk-ZG6FXMDX.cjs.map} +1 -1
- package/dist/chunk-ZNUMOJOI.cjs +4 -0
- package/dist/chunk-ZNUMOJOI.cjs.map +1 -0
- package/dist/components/Accordion/index.cjs +2 -2
- package/dist/components/Accordion/index.d.cts +6 -0
- package/dist/components/Accordion/index.d.ts +6 -0
- package/dist/components/Accordion/index.js +1 -1
- package/dist/components/ActionPlan/index.cjs +34 -0
- package/dist/components/ActionPlan/index.cjs.map +1 -0
- package/dist/components/ActionPlan/index.d.cts +65 -0
- package/dist/components/ActionPlan/index.d.ts +65 -0
- package/dist/components/ActionPlan/index.js +21 -0
- package/dist/components/ActionPlan/index.js.map +1 -0
- package/dist/components/ActivityFeed/index.cjs +31 -0
- package/dist/components/ActivityFeed/index.cjs.map +1 -0
- package/dist/components/ActivityFeed/index.d.cts +99 -0
- package/dist/components/ActivityFeed/index.d.ts +99 -0
- package/dist/components/ActivityFeed/index.js +18 -0
- package/dist/components/ActivityFeed/index.js.map +1 -0
- package/dist/components/AlertDialog/index.cjs +17 -4
- package/dist/components/AlertDialog/index.d.cts +66 -13
- package/dist/components/AlertDialog/index.d.ts +66 -13
- package/dist/components/AlertDialog/index.js +4 -3
- package/dist/components/AssociationList/index.cjs +29 -0
- package/dist/components/AssociationList/index.cjs.map +1 -0
- package/dist/components/AssociationList/index.d.cts +50 -0
- package/dist/components/AssociationList/index.d.ts +50 -0
- package/dist/components/AssociationList/index.js +16 -0
- package/dist/components/AssociationList/index.js.map +1 -0
- package/dist/components/Avatar/index.cjs +9 -7
- package/dist/components/Avatar/index.d.cts +45 -14
- package/dist/components/Avatar/index.d.ts +45 -14
- package/dist/components/Avatar/index.js +3 -1
- package/dist/components/AvatarGroup/index.cjs +20 -0
- package/dist/components/AvatarGroup/index.cjs.map +1 -0
- package/dist/components/AvatarGroup/index.d.cts +57 -0
- package/dist/components/AvatarGroup/index.d.ts +57 -0
- package/dist/components/AvatarGroup/index.js +7 -0
- package/dist/components/AvatarGroup/index.js.map +1 -0
- package/dist/components/Button/index.cjs +3 -2
- package/dist/components/Button/index.js +2 -1
- package/dist/components/CalendarHeatmap/index.cjs +18 -0
- package/dist/components/CalendarHeatmap/index.cjs.map +1 -0
- package/dist/components/CalendarHeatmap/index.d.cts +47 -0
- package/dist/components/CalendarHeatmap/index.d.ts +47 -0
- package/dist/components/CalendarHeatmap/index.js +5 -0
- package/dist/components/CalendarHeatmap/index.js.map +1 -0
- package/dist/components/CalendarView/index.cjs +5 -4
- package/dist/components/CalendarView/index.js +3 -2
- package/dist/components/ClampedText/index.cjs +3 -2
- package/dist/components/ClampedText/index.js +2 -1
- package/dist/components/CollabStatus/index.cjs +6 -4
- package/dist/components/CollabStatus/index.d.cts +11 -0
- package/dist/components/CollabStatus/index.d.ts +11 -0
- package/dist/components/CollabStatus/index.js +3 -1
- package/dist/components/Collapsible/index.cjs +4 -4
- package/dist/components/Collapsible/index.d.cts +6 -0
- package/dist/components/Collapsible/index.d.ts +6 -0
- package/dist/components/Collapsible/index.js +1 -1
- package/dist/components/CompletenessMeter/index.cjs +22 -0
- package/dist/components/CompletenessMeter/index.cjs.map +1 -0
- package/dist/components/CompletenessMeter/index.d.cts +52 -0
- package/dist/components/CompletenessMeter/index.d.ts +52 -0
- package/dist/components/CompletenessMeter/index.js +5 -0
- package/dist/components/CompletenessMeter/index.js.map +1 -0
- package/dist/components/CustomizableDashboard/index.cjs +10 -9
- package/dist/components/CustomizableDashboard/index.js +3 -2
- package/dist/components/DateInput/index.d.cts +36 -4
- package/dist/components/DateInput/index.d.ts +36 -4
- package/dist/components/Dropdown/index.cjs +9 -8
- package/dist/components/Dropdown/index.js +2 -1
- package/dist/components/FieldHistory/index.cjs +34 -0
- package/dist/components/FieldHistory/index.cjs.map +1 -0
- package/dist/components/FieldHistory/index.d.cts +66 -0
- package/dist/components/FieldHistory/index.d.ts +66 -0
- package/dist/components/FieldHistory/index.js +21 -0
- package/dist/components/FieldHistory/index.js.map +1 -0
- package/dist/components/FloatingWindow/index.cjs +5 -4
- package/dist/components/FloatingWindow/index.js +3 -2
- package/dist/components/InlineEdit/index.cjs +20 -0
- package/dist/components/InlineEdit/index.cjs.map +1 -0
- package/dist/components/InlineEdit/index.d.cts +56 -0
- package/dist/components/InlineEdit/index.d.ts +56 -0
- package/dist/components/InlineEdit/index.js +7 -0
- package/dist/components/InlineEdit/index.js.map +1 -0
- package/dist/components/KeyboardShortcutsOverlay/index.cjs +4 -4
- package/dist/components/KeyboardShortcutsOverlay/index.js +2 -2
- package/dist/components/ListView/index.cjs +5 -4
- package/dist/components/ListView/index.js +3 -2
- package/dist/components/LogoUploader/index.cjs +18 -0
- package/dist/components/LogoUploader/index.cjs.map +1 -0
- package/dist/components/LogoUploader/index.d.cts +49 -0
- package/dist/components/LogoUploader/index.d.ts +49 -0
- package/dist/components/LogoUploader/index.js +5 -0
- package/dist/components/LogoUploader/index.js.map +1 -0
- package/dist/components/Markdown/index.cjs +17 -16
- package/dist/components/Markdown/index.js +8 -7
- package/dist/components/MediaEditor/index.cjs +10 -9
- package/dist/components/MediaEditor/index.js +5 -4
- package/dist/components/MediaFeed/index.cjs +9 -6
- package/dist/components/MediaFeed/index.js +8 -5
- package/dist/components/MediaPlayer/index.cjs +6 -5
- package/dist/components/MediaPlayer/index.js +3 -2
- package/dist/components/MegaMenu/index.cjs +2 -1
- package/dist/components/MegaMenu/index.js +2 -1
- package/dist/components/Modal/index.cjs +9 -9
- package/dist/components/Modal/index.js +1 -1
- package/dist/components/PhiMask/index.cjs +18 -0
- package/dist/components/PhiMask/index.cjs.map +1 -0
- package/dist/components/PhiMask/index.d.cts +45 -0
- package/dist/components/PhiMask/index.d.ts +45 -0
- package/dist/components/PhiMask/index.js +5 -0
- package/dist/components/PhiMask/index.js.map +1 -0
- package/dist/components/PhoneInput/index.d.cts +3 -36
- package/dist/components/PhoneInput/index.d.ts +3 -36
- package/dist/components/PropertyList/index.cjs +25 -0
- package/dist/components/PropertyList/index.cjs.map +1 -0
- package/dist/components/PropertyList/index.d.cts +71 -0
- package/dist/components/PropertyList/index.d.ts +71 -0
- package/dist/components/PropertyList/index.js +12 -0
- package/dist/components/PropertyList/index.js.map +1 -0
- package/dist/components/RadialExplorer/index.cjs +2 -1
- package/dist/components/RadialExplorer/index.js +2 -1
- package/dist/components/Rating/index.cjs +28 -0
- package/dist/components/Rating/index.cjs.map +1 -0
- package/dist/components/Rating/index.d.cts +85 -0
- package/dist/components/Rating/index.d.ts +85 -0
- package/dist/components/Rating/index.js +7 -0
- package/dist/components/Rating/index.js.map +1 -0
- package/dist/components/RecordHeader/index.cjs +29 -0
- package/dist/components/RecordHeader/index.cjs.map +1 -0
- package/dist/components/RecordHeader/index.d.cts +86 -0
- package/dist/components/RecordHeader/index.d.ts +86 -0
- package/dist/components/RecordHeader/index.js +16 -0
- package/dist/components/RecordHeader/index.js.map +1 -0
- package/dist/components/RecordLayout/index.cjs +21 -0
- package/dist/components/RecordLayout/index.cjs.map +1 -0
- package/dist/components/RecordLayout/index.d.cts +40 -0
- package/dist/components/RecordLayout/index.d.ts +40 -0
- package/dist/components/RecordLayout/index.js +8 -0
- package/dist/components/RecordLayout/index.js.map +1 -0
- package/dist/components/RichTextEditor/index.cjs +8 -6
- package/dist/components/RichTextEditor/index.js +5 -3
- package/dist/components/SectionSpyNav/index.cjs +2 -1
- package/dist/components/SectionSpyNav/index.js +2 -1
- package/dist/components/SuperChat/index.cjs +23 -19
- package/dist/components/SuperChat/index.cjs.map +1 -1
- package/dist/components/SuperChat/index.js +11 -7
- package/dist/components/SuperChat/index.js.map +1 -1
- package/dist/components/SuperChat/plugins/index.cjs +5 -4
- package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
- package/dist/components/SuperChat/plugins/index.js +4 -3
- package/dist/components/SuperChat/plugins/index.js.map +1 -1
- package/dist/components/Tabs/index.cjs +9 -7
- package/dist/components/Tabs/index.d.cts +12 -1
- package/dist/components/Tabs/index.d.ts +12 -1
- package/dist/components/Tabs/index.js +3 -1
- package/dist/components/TagEditor/index.cjs +20 -0
- package/dist/components/TagEditor/index.cjs.map +1 -0
- package/dist/components/TagEditor/index.d.cts +46 -0
- package/dist/components/TagEditor/index.d.ts +46 -0
- package/dist/components/TagEditor/index.js +7 -0
- package/dist/components/TagEditor/index.js.map +1 -0
- package/dist/components/UserPicker/index.cjs +24 -0
- package/dist/components/UserPicker/index.cjs.map +1 -0
- package/dist/components/UserPicker/index.d.cts +60 -0
- package/dist/components/UserPicker/index.d.ts +60 -0
- package/dist/components/UserPicker/index.js +11 -0
- package/dist/components/UserPicker/index.js.map +1 -0
- package/dist/components/ViewSet/index.cjs +6 -5
- package/dist/components/ViewSet/index.d.cts +2 -1
- package/dist/components/ViewSet/index.d.ts +2 -1
- package/dist/components/ViewSet/index.js +5 -4
- package/dist/components/ViewSwitcher/index.d.cts +39 -4
- package/dist/components/ViewSwitcher/index.d.ts +39 -4
- package/dist/datavis.cjs +3 -2
- package/dist/datavis.cjs.map +1 -1
- package/dist/datavis.js +2 -1
- package/dist/datavis.js.map +1 -1
- package/dist/esheet.cjs +9 -7
- package/dist/esheet.cjs.map +1 -1
- package/dist/esheet.js +6 -4
- package/dist/esheet.js.map +1 -1
- package/dist/hooks/index.cjs +53 -27
- package/dist/hooks/index.d.cts +91 -6
- package/dist/hooks/index.d.ts +91 -6
- package/dist/hooks/index.js +5 -3
- package/dist/index.cjs +1391 -847
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1253 -168
- package/dist/index.d.ts +1253 -168
- package/dist/index.js +539 -171
- package/dist/index.js.map +1 -1
- package/dist/org-chart.cjs +1302 -0
- package/dist/org-chart.cjs.map +1 -0
- package/dist/org-chart.d.cts +164 -0
- package/dist/org-chart.d.ts +164 -0
- package/dist/org-chart.js +1277 -0
- package/dist/org-chart.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/{index-DoYYWsNc.d.cts → types-CDeBNZiE.d.cts} +1 -36
- package/dist/{index-DoYYWsNc.d.ts → types-CDeBNZiE.d.ts} +1 -36
- package/package.json +22 -2
- package/dist/CsvBlock-FX5YNGNE.cjs +0 -17
- package/dist/CsvBlock-VLMG7GUO.js +0 -8
- package/dist/HtmlPreviewBlock-5JE7L3GR.js +0 -8
- package/dist/HtmlPreviewBlock-UO37JQ3K.cjs +0 -17
- package/dist/MermaidBlock-3XHFBAMV.js +0 -8
- package/dist/MermaidBlock-RZ75RPZA.cjs +0 -17
- package/dist/SurveyBlock-MUVJ3JUI.js +0 -8
- package/dist/SurveyBlock-VH47YXZC.cjs +0 -17
- package/dist/chunk-35Y4ILCU.cjs.map +0 -1
- package/dist/chunk-6N6LIAUJ.cjs +0 -80
- package/dist/chunk-6N6LIAUJ.cjs.map +0 -1
- package/dist/chunk-7ZV67VZE.js.map +0 -1
- package/dist/chunk-7ZVTLTJF.js +0 -109
- package/dist/chunk-7ZVTLTJF.js.map +0 -1
- package/dist/chunk-DVOQ3JNO.js.map +0 -1
- package/dist/chunk-ENMXHZNE.js.map +0 -1
- package/dist/chunk-GBUVIGD5.js.map +0 -1
- package/dist/chunk-HZ4MBUC3.js.map +0 -1
- package/dist/chunk-JBIGSP2T.js.map +0 -1
- package/dist/chunk-JEIW7BSV.cjs.map +0 -1
- package/dist/chunk-KRU6IGV7.js.map +0 -1
- package/dist/chunk-LHBWRMNC.cjs.map +0 -1
- package/dist/chunk-MLAWXPRY.js.map +0 -1
- package/dist/chunk-P7UMS4E6.cjs.map +0 -1
- package/dist/chunk-QURJVPRH.cjs.map +0 -1
- package/dist/chunk-SVSHA7XV.js.map +0 -1
- package/dist/chunk-T4L7Q5FA.cjs.map +0 -1
- package/dist/chunk-UBSH27C2.js +0 -78
- package/dist/chunk-UBSH27C2.js.map +0 -1
- package/dist/chunk-VROIMIHB.cjs.map +0 -1
- package/dist/chunk-X4LBUPJO.cjs.map +0 -1
- package/dist/chunk-YVPC65ZJ.cjs.map +0 -1
- package/dist/chunk-ZTMYKAVU.cjs.map +0 -1
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkGKDHMNUA_cjs = require('./chunk-GKDHMNUA.cjs');
|
|
4
|
+
var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
|
|
5
|
+
var React = require('react');
|
|
6
|
+
var lucideReact = require('lucide-react');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
28
|
+
|
|
29
|
+
var defaultAvatarGroupLabels = {
|
|
30
|
+
list: "People",
|
|
31
|
+
presence: (name, presence) => `${name} is ${presence}`,
|
|
32
|
+
overflow: (names) => `${names.length} more: ${names.join(", ")}`
|
|
33
|
+
};
|
|
34
|
+
var PRESENCE_RING = {
|
|
35
|
+
viewing: "ring-primary-500",
|
|
36
|
+
editing: "ring-warning-500"
|
|
37
|
+
};
|
|
38
|
+
var PRESENCE_BADGE = {
|
|
39
|
+
viewing: "bg-primary-500 text-primary-foreground",
|
|
40
|
+
editing: "bg-warning-500 text-warning-foreground"
|
|
41
|
+
};
|
|
42
|
+
var BADGE_SIZE = {
|
|
43
|
+
xs: "h-3 w-3 [&>svg]:h-2 [&>svg]:w-2",
|
|
44
|
+
sm: "h-3.5 w-3.5 [&>svg]:h-2 [&>svg]:w-2",
|
|
45
|
+
md: "h-4 w-4 [&>svg]:h-2.5 [&>svg]:w-2.5",
|
|
46
|
+
lg: "h-5 w-5 [&>svg]:h-3 [&>svg]:w-3",
|
|
47
|
+
xl: "h-6 w-6 [&>svg]:h-3.5 [&>svg]:w-3.5"
|
|
48
|
+
};
|
|
49
|
+
var ITEM = "-ms-2 first:ms-0 relative";
|
|
50
|
+
var FOCUS = "rounded-full focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
|
|
51
|
+
var AvatarGroup = React__namespace.forwardRef(
|
|
52
|
+
function AvatarGroup2({
|
|
53
|
+
items,
|
|
54
|
+
max,
|
|
55
|
+
size = "md",
|
|
56
|
+
onItemClick,
|
|
57
|
+
labels: labelOverrides,
|
|
58
|
+
children,
|
|
59
|
+
className,
|
|
60
|
+
...props
|
|
61
|
+
}, ref) {
|
|
62
|
+
const labels = { ...defaultAvatarGroupLabels, ...labelOverrides };
|
|
63
|
+
const legacy = items ? [] : React__namespace.Children.toArray(children).filter(
|
|
64
|
+
React__namespace.isValidElement
|
|
65
|
+
);
|
|
66
|
+
const people = items ? [
|
|
67
|
+
...items.filter((i) => i.presence === "editing"),
|
|
68
|
+
...items.filter((i) => i.presence !== "editing")
|
|
69
|
+
] : legacy.map((child, index) => ({
|
|
70
|
+
id: String(child.key ?? index),
|
|
71
|
+
name: child.props.name ?? child.props.alt ?? ""
|
|
72
|
+
}));
|
|
73
|
+
const visibleCount = max ? Math.min(max, people.length) : people.length;
|
|
74
|
+
const hidden = people.slice(visibleCount);
|
|
75
|
+
const overflowLabel = labels.overflow(hidden.map((h) => h.label ?? h.name));
|
|
76
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
77
|
+
"ul",
|
|
78
|
+
{
|
|
79
|
+
ref,
|
|
80
|
+
"aria-label": labels.list,
|
|
81
|
+
"data-slot": "avatar-group",
|
|
82
|
+
className: chunkS5RVSXDV_cjs.cn("flex items-center", className),
|
|
83
|
+
...props,
|
|
84
|
+
children: [
|
|
85
|
+
people.slice(0, visibleCount).map((item, index) => {
|
|
86
|
+
if (!items) {
|
|
87
|
+
const child = legacy[index];
|
|
88
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { className: ITEM, children: React__namespace.cloneElement(child, {
|
|
89
|
+
size,
|
|
90
|
+
className: chunkS5RVSXDV_cjs.cn(
|
|
91
|
+
"ring-background ring-2",
|
|
92
|
+
child.props.className
|
|
93
|
+
)
|
|
94
|
+
}) }, item.id);
|
|
95
|
+
}
|
|
96
|
+
const name = item.label ?? item.name;
|
|
97
|
+
const label = item.presence ? labels.presence(name, item.presence) : name;
|
|
98
|
+
const avatar = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
99
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
100
|
+
chunkGKDHMNUA_cjs.Avatar,
|
|
101
|
+
{
|
|
102
|
+
name: item.name,
|
|
103
|
+
src: item.src,
|
|
104
|
+
alt: "",
|
|
105
|
+
size,
|
|
106
|
+
className: chunkS5RVSXDV_cjs.cn(
|
|
107
|
+
"ring-2",
|
|
108
|
+
item.presence ? PRESENCE_RING[item.presence] : "ring-background"
|
|
109
|
+
),
|
|
110
|
+
style: item.color ? { backgroundColor: item.color } : void 0
|
|
111
|
+
}
|
|
112
|
+
),
|
|
113
|
+
item.presence && /* @__PURE__ */ jsxRuntime.jsx(
|
|
114
|
+
"span",
|
|
115
|
+
{
|
|
116
|
+
"aria-hidden": "true",
|
|
117
|
+
"data-slot": "avatar-group-presence",
|
|
118
|
+
className: chunkS5RVSXDV_cjs.cn(
|
|
119
|
+
"ring-background absolute -end-0.5 -bottom-0.5 flex items-center justify-center rounded-full ring-2",
|
|
120
|
+
PRESENCE_BADGE[item.presence],
|
|
121
|
+
BADGE_SIZE[size]
|
|
122
|
+
),
|
|
123
|
+
children: item.presence === "editing" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, {})
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
] });
|
|
127
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { className: ITEM, children: onItemClick ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
128
|
+
"button",
|
|
129
|
+
{
|
|
130
|
+
type: "button",
|
|
131
|
+
"aria-label": label,
|
|
132
|
+
title: label,
|
|
133
|
+
onClick: () => onItemClick(item.id),
|
|
134
|
+
className: chunkS5RVSXDV_cjs.cn("flex", FOCUS),
|
|
135
|
+
children: avatar
|
|
136
|
+
}
|
|
137
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
138
|
+
"span",
|
|
139
|
+
{
|
|
140
|
+
role: "img",
|
|
141
|
+
"aria-label": label,
|
|
142
|
+
title: label,
|
|
143
|
+
className: "flex",
|
|
144
|
+
children: avatar
|
|
145
|
+
}
|
|
146
|
+
) }, item.id);
|
|
147
|
+
}),
|
|
148
|
+
hidden.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("li", { className: ITEM, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
149
|
+
"span",
|
|
150
|
+
{
|
|
151
|
+
role: "img",
|
|
152
|
+
"aria-label": overflowLabel,
|
|
153
|
+
title: overflowLabel,
|
|
154
|
+
"data-slot": "avatar-group-overflow",
|
|
155
|
+
className: chunkS5RVSXDV_cjs.cn(
|
|
156
|
+
chunkGKDHMNUA_cjs.avatarVariants({ size }),
|
|
157
|
+
"bg-muted text-foreground ring-background ring-2"
|
|
158
|
+
),
|
|
159
|
+
children: [
|
|
160
|
+
"+",
|
|
161
|
+
hidden.length
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
) })
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
exports.AvatarGroup = AvatarGroup;
|
|
172
|
+
exports.defaultAvatarGroupLabels = defaultAvatarGroupLabels;
|
|
173
|
+
//# sourceMappingURL=chunk-Q3YVLO52.cjs.map
|
|
174
|
+
//# sourceMappingURL=chunk-Q3YVLO52.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AvatarGroup/AvatarGroup.tsx"],"names":["React","AvatarGroup","jsxs","cn","Fragment","jsx","Avatar","Pencil","Eye","avatarVariants"],"mappings":"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","file":"chunk-Q3YVLO52.cjs","sourcesContent":["import * as React from 'react';\nimport { Eye, Pencil } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Avatar, avatarVariants, type AvatarProps } from '../Avatar/Avatar';\n\nexport type AvatarPresence = 'viewing' | 'editing';\n\nexport interface AvatarGroupItem {\n /** Stable key, passed back to `onItemClick`. */\n id: string;\n /** Person's name — drives the initials fallback and the accessible name. */\n name: string;\n /** Avatar image URL. */\n src?: string | null;\n /** What the person is doing on the record; adds a ring, badge and label. */\n presence?: AvatarPresence;\n /** Accessible name / tooltip override, e.g. `Bo (2 windows)`. Defaults to `name`. */\n label?: string;\n /** CSS colour for the initials disc, e.g. a collaborator's cursor colour. */\n color?: string;\n}\n\nexport interface AvatarGroupLabels {\n /** Accessible name of the list. */\n list: string;\n /** Accessible name of a person with a presence state. */\n presence: (name: string, presence: AvatarPresence) => string;\n /** Accessible name / tooltip of the \"+N\" chip. */\n overflow: (hiddenNames: string[]) => string;\n}\n\nexport const defaultAvatarGroupLabels: AvatarGroupLabels = {\n list: 'People',\n presence: (name, presence) => `${name} is ${presence}`,\n overflow: (names) => `${names.length} more: ${names.join(', ')}`,\n};\n\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface AvatarGroupProps extends Omit<\n React.HTMLAttributes<HTMLUListElement>,\n 'children'\n> {\n /** People to show, in order (editors are moved to the front). */\n items?: AvatarGroupItem[];\n /** Avatars shown before the rest collapse into a \"+N\" chip. */\n max?: number;\n /** Size applied to every avatar. */\n size?: AvatarSize;\n /** Makes each avatar a button that reports its item `id`. */\n onItemClick?: (id: string) => void;\n /** Overrides for any user-facing string. */\n labels?: Partial<AvatarGroupLabels>;\n /** Legacy API: `<Avatar>` children instead of `items`. */\n children?: React.ReactNode;\n}\n\nconst PRESENCE_RING: Record<AvatarPresence, string> = {\n viewing: 'ring-primary-500',\n editing: 'ring-warning-500',\n};\n\nconst PRESENCE_BADGE: Record<AvatarPresence, string> = {\n viewing: 'bg-primary-500 text-primary-foreground',\n editing: 'bg-warning-500 text-warning-foreground',\n};\n\nconst BADGE_SIZE: Record<AvatarSize, string> = {\n xs: 'h-3 w-3 [&>svg]:h-2 [&>svg]:w-2',\n sm: 'h-3.5 w-3.5 [&>svg]:h-2 [&>svg]:w-2',\n md: 'h-4 w-4 [&>svg]:h-2.5 [&>svg]:w-2.5',\n lg: 'h-5 w-5 [&>svg]:h-3 [&>svg]:w-3',\n xl: 'h-6 w-6 [&>svg]:h-3.5 [&>svg]:w-3.5',\n};\n\nconst ITEM = '-ms-2 first:ms-0 relative';\nconst FOCUS =\n 'rounded-full focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring';\n\n/**\n * Overlapping stack of {@link Avatar}s with an optional viewing / editing\n * presence ring per person and a \"+N\" chip that names everyone it hides.\n *\n * @example\n * ```tsx\n * <AvatarGroup\n * max={3}\n * items={[{ id: '1', name: 'Ann Lee', presence: 'editing' }]}\n * onItemClick={openProfile}\n * />\n * ```\n */\nexport const AvatarGroup = React.forwardRef<HTMLUListElement, AvatarGroupProps>(\n function AvatarGroup(\n {\n items,\n max,\n size = 'md',\n onItemClick,\n labels: labelOverrides,\n children,\n className,\n ...props\n },\n ref\n ) {\n const labels = { ...defaultAvatarGroupLabels, ...labelOverrides };\n\n const legacy = items\n ? []\n : React.Children.toArray(children).filter(\n React.isValidElement<AvatarProps>\n );\n const people: AvatarGroupItem[] = items\n ? [\n ...items.filter((i) => i.presence === 'editing'),\n ...items.filter((i) => i.presence !== 'editing'),\n ]\n : legacy.map((child, index) => ({\n id: String(child.key ?? index),\n name: child.props.name ?? child.props.alt ?? '',\n }));\n\n const visibleCount = max ? Math.min(max, people.length) : people.length;\n const hidden = people.slice(visibleCount);\n const overflowLabel = labels.overflow(hidden.map((h) => h.label ?? h.name));\n\n return (\n <ul\n ref={ref}\n aria-label={labels.list}\n data-slot=\"avatar-group\"\n className={cn('flex items-center', className)}\n {...props}\n >\n {people.slice(0, visibleCount).map((item, index) => {\n if (!items) {\n const child = legacy[index];\n return (\n <li key={item.id} className={ITEM}>\n {React.cloneElement(child, {\n size,\n className: cn(\n 'ring-background ring-2',\n child.props.className\n ),\n })}\n </li>\n );\n }\n const name = item.label ?? item.name;\n const label = item.presence\n ? labels.presence(name, item.presence)\n : name;\n const avatar = (\n <>\n <Avatar\n name={item.name}\n src={item.src}\n alt=\"\"\n size={size}\n className={cn(\n 'ring-2',\n item.presence\n ? PRESENCE_RING[item.presence]\n : 'ring-background'\n )}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n {item.presence && (\n <span\n aria-hidden=\"true\"\n data-slot=\"avatar-group-presence\"\n className={cn(\n 'ring-background absolute -end-0.5 -bottom-0.5 flex items-center justify-center rounded-full ring-2',\n PRESENCE_BADGE[item.presence],\n BADGE_SIZE[size]\n )}\n >\n {item.presence === 'editing' ? <Pencil /> : <Eye />}\n </span>\n )}\n </>\n );\n return (\n <li key={item.id} className={ITEM}>\n {onItemClick ? (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n onClick={() => onItemClick(item.id)}\n className={cn('flex', FOCUS)}\n >\n {avatar}\n </button>\n ) : (\n <span\n role=\"img\"\n aria-label={label}\n title={label}\n className=\"flex\"\n >\n {avatar}\n </span>\n )}\n </li>\n );\n })}\n {hidden.length > 0 && (\n <li className={ITEM}>\n <span\n role=\"img\"\n aria-label={overflowLabel}\n title={overflowLabel}\n data-slot=\"avatar-group-overflow\"\n className={cn(\n avatarVariants({ size }),\n 'bg-muted text-foreground ring-background ring-2'\n )}\n >\n +{hidden.length}\n </span>\n </li>\n )}\n </ul>\n );\n }\n);\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FenceBlock } from './chunk-
|
|
1
|
+
import { FenceBlock } from './chunk-HDY7YQFX.js';
|
|
2
2
|
import { lazy, useRef, useCallback, useMemo, useState, useEffect, Suspense } from 'react';
|
|
3
3
|
import DOMPurify from 'dompurify';
|
|
4
4
|
import hljs from 'highlight.js/lib/core';
|
|
@@ -236,16 +236,16 @@ var CodeBlock = ({ code, language }) => {
|
|
|
236
236
|
) });
|
|
237
237
|
};
|
|
238
238
|
var CsvBlock = lazy(
|
|
239
|
-
() => import('./CsvBlock-
|
|
239
|
+
() => import('./CsvBlock-CFXSDPBI.js').then((m) => ({ default: m.CsvBlock }))
|
|
240
240
|
);
|
|
241
241
|
var HtmlPreviewBlock = lazy(
|
|
242
|
-
() => import('./HtmlPreviewBlock-
|
|
242
|
+
() => import('./HtmlPreviewBlock-Z2GCK325.js').then((m) => ({ default: m.HtmlPreviewBlock }))
|
|
243
243
|
);
|
|
244
244
|
var MermaidBlock = lazy(
|
|
245
|
-
() => import('./MermaidBlock-
|
|
245
|
+
() => import('./MermaidBlock-XCAK7IA5.js').then((m) => ({ default: m.MermaidBlock }))
|
|
246
246
|
);
|
|
247
247
|
var SurveyBlock = lazy(
|
|
248
|
-
() => import('./SurveyBlock-
|
|
248
|
+
() => import('./SurveyBlock-KI5JOWCL.js').then((m) => ({ default: m.SurveyBlock }))
|
|
249
249
|
);
|
|
250
250
|
var BlockFallback = () => /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-4 text-sm text-neutral-500", children: "Loading\u2026" });
|
|
251
251
|
var BLOCK_RE = /<div data-block-type="([^"]+)" data-block-id="([^"]+)" data-code="([^"]*)"([^>]*\bdata-md-fence="1"[^>]*)><\/div>/g;
|
|
@@ -323,5 +323,5 @@ var MarkdownRenderer = ({
|
|
|
323
323
|
};
|
|
324
324
|
|
|
325
325
|
export { CodeBlock, MarkdownRenderer, highlightCode, useMarkdown };
|
|
326
|
-
//# sourceMappingURL=chunk-
|
|
327
|
-
//# sourceMappingURL=chunk-
|
|
326
|
+
//# sourceMappingURL=chunk-QJ2L5RU6.js.map
|
|
327
|
+
//# sourceMappingURL=chunk-QJ2L5RU6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Markdown/useMarkdown.ts","../src/components/Markdown/CodeBlock.tsx","../src/components/Markdown/MarkdownRenderer.tsx"],"names":["useMemo","jsx"],"mappings":"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","file":"chunk-K34DXMLZ.js","sourcesContent":["/** useMarkdown — converts markdown to sanitised HTML with hljs highlighting and special fence blocks. */\nimport DOMPurify from 'dompurify';\nimport hljs from 'highlight.js/lib/core';\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\nimport bash from 'highlight.js/lib/languages/bash';\nimport css from 'highlight.js/lib/languages/css';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport json from 'highlight.js/lib/languages/json';\nimport markdown from 'highlight.js/lib/languages/markdown';\nimport python from 'highlight.js/lib/languages/python';\nimport sql from 'highlight.js/lib/languages/sql';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\nimport { marked, type MarkedOptions, type Tokens } from 'marked';\nimport { useCallback, useMemo, useRef } from 'react';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('python', python);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('xml', xml);\nhljs.registerLanguage('html', xml);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('shell', bash);\nhljs.registerLanguage('sql', sql);\nhljs.registerLanguage('yaml', yaml);\nhljs.registerLanguage('yml', yaml);\nhljs.registerLanguage('markdown', markdown);\nhljs.registerLanguage('md', markdown);\n\nconst lazyLanguages: Record<string, () => Promise<unknown>> = {\n java: () => import('highlight.js/lib/languages/java'),\n cpp: () => import('highlight.js/lib/languages/cpp'),\n 'c++': () => import('highlight.js/lib/languages/cpp'),\n c: () => import('highlight.js/lib/languages/c'),\n csharp: () => import('highlight.js/lib/languages/csharp'),\n php: () => import('highlight.js/lib/languages/php'),\n ruby: () => import('highlight.js/lib/languages/ruby'),\n go: () => import('highlight.js/lib/languages/go'),\n rust: () => import('highlight.js/lib/languages/rust'),\n perl: () => import('highlight.js/lib/languages/perl'),\n r: () => import('highlight.js/lib/languages/r'),\n makefile: () => import('highlight.js/lib/languages/makefile'),\n dockerfile: () => import('highlight.js/lib/languages/dockerfile'),\n};\n\nconst loadedLanguages = new Set<string>([\n 'javascript',\n 'typescript',\n 'python',\n 'json',\n 'xml',\n 'html',\n 'css',\n 'bash',\n 'shell',\n 'sql',\n 'yaml',\n 'yml',\n 'markdown',\n 'md',\n]);\n\nasync function ensureLanguage(lang: string): Promise<boolean> {\n const key = lang.toLowerCase();\n if (loadedLanguages.has(key)) return true;\n const loader = lazyLanguages[key];\n if (!loader) return false;\n try {\n const mod = (await loader()) as { default: unknown };\n hljs.registerLanguage(\n key,\n mod.default as Parameters<typeof hljs.registerLanguage>[1]\n );\n loadedLanguages.add(key);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function highlightCode(code: string, lang?: string): string {\n if (lang && loadedLanguages.has(lang.toLowerCase())) {\n try {\n return hljs.highlight(code, { language: lang.toLowerCase() }).value;\n } catch {\n /* fall through */\n }\n }\n try {\n const result = hljs.highlightAuto(code);\n if (result.relevance > 5) return result.value;\n } catch {\n /* fall through */\n }\n return escapeHtml(code);\n}\n\nfunction sanitise(html: string): string {\n return DOMPurify.sanitize(html, {\n ADD_ATTR: [\n 'target',\n 'rel',\n 'data-block-type',\n 'data-block-id',\n 'data-code',\n 'data-lang',\n 'data-md-fence',\n ],\n }) as string;\n}\n\n// Use globalThis to prevent duplicate DOMPurify hook registration across HMR reloads.\nconst _g = globalThis as unknown as Record<string, boolean>;\n// Guard against SSR: DOMPurify hooks operate on the DOM, so only register in the browser.\nif (typeof document !== 'undefined' && !_g.__markdownAnchorHookInstalled) {\n _g.__markdownAnchorHookInstalled = true;\n DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {\n const isAnchor =\n (typeof HTMLAnchorElement !== 'undefined' &&\n node instanceof HTMLAnchorElement) ||\n node.nodeName === 'A';\n if (isAnchor) {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer');\n }\n });\n}\n\nlet blockCounter = 0;\n\nfunction createRenderer() {\n const renderer = new marked.Renderer();\n\n renderer.code = function (this: unknown, token: Tokens.Code) {\n const { text: code, lang = '' } = token;\n const normalised = lang.toLowerCase().trim();\n const blockId = `block-${++blockCounter}`;\n const encodedCode = encodeURIComponent(code);\n const sentinel = 'data-md-fence=\"1\"';\n\n switch (normalised) {\n case 'mermaid':\n return `<div data-block-type=\"mermaid\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'csv':\n return `<div data-block-type=\"csv\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'survey':\n return `<div data-block-type=\"survey\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'html':\n return `<div data-block-type=\"html-preview\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n default:\n return `<div data-block-type=\"code\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" data-lang=\"${escapeHtml(normalised)}\" ${sentinel}></div>`;\n }\n };\n\n renderer.link = function (this: unknown, token: Tokens.Link) {\n const { href, title, tokens } = token;\n const text =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: { parseInline: (t: Tokens.Link['tokens']) => string };\n }\n ).parser.parseInline(tokens)\n : token.text;\n const titleAttr = title ? ` title=\"${escapeHtml(title)}\"` : '';\n return `<a href=\"${escapeHtml(href)}\" target=\"_blank\" rel=\"noopener noreferrer\"${titleAttr}>${text}</a>`;\n };\n\n renderer.table = function (this: unknown, token: Tokens.Table) {\n const headerCells = token.header\n .map((cell) => {\n const content =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<th>${content}</th>`;\n })\n .join('');\n\n const bodyRows = token.rows\n .map((row) => {\n const cells = row\n .map((cell) => {\n const content =\n this &&\n typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<td>${content}</td>`;\n })\n .join('');\n return `<tr>${cells}</tr>`;\n })\n .join('');\n\n return `<div class=\"overflow-x-auto\"><table class=\"min-w-full divide-y divide-neutral-200 dark:divide-neutral-700\"><thead><tr>${headerCells}</tr></thead><tbody class=\"divide-y divide-neutral-200 dark:divide-neutral-700\">${bodyRows}</tbody></table></div>`;\n };\n\n return renderer;\n}\n\nfunction makeMarkedOptions(): MarkedOptions {\n return { gfm: true, breaks: true, renderer: createRenderer() };\n}\n\nconst CACHE_MAX = 100;\nconst renderCache = new Map<string, string>();\nfunction cacheSet(key: string, value: string) {\n if (renderCache.size >= CACHE_MAX) {\n renderCache.delete(renderCache.keys().next().value as string);\n }\n renderCache.set(key, value);\n}\n\nexport interface UseMarkdownResult {\n /** Render markdown text to sanitised HTML string */\n render: (text: string, cacheKey?: string) => string;\n /** Async-render that lazy-loads needed languages first */\n renderAsync: (text: string, cacheKey?: string) => Promise<string>;\n /** Clear the render cache */\n clearCache: () => void;\n}\n\nexport function useMarkdown(): UseMarkdownResult {\n const cacheRef = useRef(renderCache);\n\n const render = useCallback((text: string, cacheKey?: string): string => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n const raw = marked.parse(text, {\n ...makeMarkedOptions(),\n async: false,\n }) as string;\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n }, []);\n\n const renderAsync = useCallback(\n async (text: string, cacheKey?: string): Promise<string> => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n // Allow `+`, `-`, `.` in language identifiers (c++, objective-c, bash-session, etc.)\n const fenceRegex = /^```([\\w+\\-.]+)\\s*$/gm;\n let match: RegExpExecArray | null;\n const langs: string[] = [];\n while ((match = fenceRegex.exec(text)) !== null) {\n langs.push(match[1]);\n }\n await Promise.all(langs.map((l) => ensureLanguage(l)));\n\n const raw = await marked.parse(text, makeMarkedOptions());\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n },\n []\n );\n\n const clearCache = useCallback(() => {\n cacheRef.current.clear();\n }, []);\n\n return useMemo(\n () => ({ render, renderAsync, clearCache }),\n [render, renderAsync, clearCache]\n );\n}\n","/**\n * CodeBlock — Renders a syntax-highlighted code fence using FenceBlock.\n *\n * Used by `MarkdownRenderer` for plain (non-special) fenced code blocks.\n * Highlighting is performed synchronously via the `highlightCode` helper from\n * `useMarkdown`; if the language was not pre-registered with highlight.js the\n * helper falls back to escaped raw text.\n */\nimport React, { useMemo } from 'react';\n\nimport { FenceBlock } from './FenceBlock';\nimport { highlightCode } from './useMarkdown';\n\ninterface CodeBlockProps {\n code: string;\n language?: string;\n}\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({ code, language }) => {\n const html = useMemo(() => highlightCode(code, language), [code, language]);\n\n return (\n <FenceBlock code={code} language={language}>\n {/* Focusable so keyboard users can horizontally scroll long lines\n (axe: scrollable-region-focusable). */}\n <pre\n className=\"m-0 overflow-x-auto !bg-transparent p-3 text-sm\"\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- scrollable code needs keyboard focus\n tabIndex={0}\n role=\"region\"\n aria-label={language ? `${language} code` : 'Code'}\n >\n <code\n className=\"hljs bg-transparent p-0\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </pre>\n </FenceBlock>\n );\n};\n","/**\n * MarkdownRenderer — renders markdown with React components for special fence blocks.\n */\nimport React, { Suspense, lazy, useEffect, useState } from 'react';\n\nimport './styles.css';\nimport { CodeBlock } from './CodeBlock';\nimport { useMarkdown } from './useMarkdown';\n\n// Block components are lazy-loaded so optional peer deps (papaparse, js-yaml, mermaid)\n// aren't bundled unless actually rendered.\nconst CsvBlock = lazy(() =>\n import('./CsvBlock').then((m) => ({ default: m.CsvBlock }))\n);\nconst HtmlPreviewBlock = lazy(() =>\n import('./HtmlPreviewBlock').then((m) => ({ default: m.HtmlPreviewBlock }))\n);\nconst MermaidBlock = lazy(() =>\n import('./MermaidBlock').then((m) => ({ default: m.MermaidBlock }))\n);\nconst SurveyBlock = lazy(() =>\n import('./SurveyBlock').then((m) => ({ default: m.SurveyBlock }))\n);\n\nconst BlockFallback: React.FC = () => (\n <div className=\"flex items-center justify-center p-4 text-sm text-neutral-500\">\n Loading…\n </div>\n);\n\nexport interface MarkdownRendererProps {\n /** Raw markdown text */\n text: string;\n /** Cache key (e.g., message._id + revisionNumber) */\n cacheKey?: string;\n /** Additional CSS classes */\n className?: string;\n /** Whether the message is still streaming (may have incomplete blocks) */\n streaming?: boolean;\n}\n\n// Matches fence block markers emitted by useMarkdown (sentinel data-md-fence prevents raw-HTML injection)\nconst BLOCK_RE =\n /<div data-block-type=\"([^\"]+)\" data-block-id=\"([^\"]+)\" data-code=\"([^\"]*)\"([^>]*\\bdata-md-fence=\"1\"[^>]*)><\\/div>/g;\n\ninterface HtmlSegment {\n html: string;\n}\ninterface BlockSegment {\n type: string;\n id: string;\n code: string;\n lang?: string;\n}\ntype Segment = HtmlSegment | BlockSegment;\n\nfunction splitHtml(html: string): Segment[] {\n const segments: Segment[] = [];\n let last = 0;\n for (const m of html.matchAll(BLOCK_RE)) {\n if (m.index > last) segments.push({ html: html.slice(last, m.index) });\n const langMatch = m[4]?.match(/data-lang=\"([^\"]*)\"/)?.[1];\n segments.push({\n type: m[1],\n id: m[2],\n code: (() => {\n try {\n return decodeURIComponent(m[3]);\n } catch {\n return m[3];\n }\n })(),\n lang: langMatch ?? undefined,\n });\n last = m.index + m[0].length;\n }\n if (last < html.length) segments.push({ html: html.slice(last) });\n return segments;\n}\n\nfunction renderBlock(seg: BlockSegment): React.ReactNode {\n const wrap = (node: React.ReactNode) => (\n <Suspense key={seg.id} fallback={<BlockFallback />}>\n {node}\n </Suspense>\n );\n switch (seg.type) {\n case 'mermaid':\n return wrap(<MermaidBlock code={seg.code} id={seg.id} />);\n case 'csv':\n return wrap(<CsvBlock code={seg.code} id={seg.id} />);\n case 'survey':\n return wrap(<SurveyBlock code={seg.code} id={seg.id} />);\n case 'html-preview':\n return wrap(<HtmlPreviewBlock code={seg.code} id={seg.id} />);\n case 'code':\n return wrap(\n <CodeBlock code={seg.code} language={seg.lang || undefined} />\n );\n default:\n return null;\n }\n}\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({\n text,\n cacheKey,\n className = '',\n streaming = false,\n}) => {\n const { render, renderAsync } = useMarkdown();\n const [html, setHtml] = useState('');\n\n useEffect(() => {\n let cancelled = false;\n\n // While streaming, append text length to the cache key so each delta\n // produces a fresh render rather than a stale hit on the messageId.\n const effectiveKey = streaming\n ? cacheKey\n ? `${cacheKey}::${text.length}`\n : undefined\n : cacheKey;\n\n async function doRender() {\n const rendered = await renderAsync(text, effectiveKey);\n if (!cancelled) setHtml(rendered);\n }\n\n if (streaming) {\n setHtml(render(text, effectiveKey));\n } else {\n void doRender();\n }\n\n return () => {\n cancelled = true;\n };\n }, [text, cacheKey, streaming, render, renderAsync]);\n\n const segments = splitHtml(html);\n const proseClass = `md-prose ${className}`.trim();\n\n return (\n <div className={proseClass}>\n {segments.map((seg, i) =>\n 'html' in seg ? (\n <div key={i} dangerouslySetInnerHTML={{ __html: seg.html }} />\n ) : (\n renderBlock(seg)\n )\n )}\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/Markdown/useMarkdown.ts","../src/components/Markdown/CodeBlock.tsx","../src/components/Markdown/MarkdownRenderer.tsx"],"names":["useMemo","jsx"],"mappings":";;;;;;;;;;;;;;;;;AAIA,SAAS,WAAW,GAAA,EAAqB;AACvC,EAAA,OAAO,IACJ,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,CACrB,OAAA,CAAQ,MAAM,MAAM,CAAA,CACpB,QAAQ,IAAA,EAAM,MAAM,EACpB,OAAA,CAAQ,IAAA,EAAM,QAAQ,CAAA,CACtB,OAAA,CAAQ,MAAM,QAAQ,CAAA;AAC3B;AAcA,IAAA,CAAK,gBAAA,CAAiB,cAAc,UAAU,CAAA;AAC9C,IAAA,CAAK,gBAAA,CAAiB,cAAc,UAAU,CAAA;AAC9C,IAAA,CAAK,gBAAA,CAAiB,UAAU,MAAM,CAAA;AACtC,IAAA,CAAK,gBAAA,CAAiB,QAAQ,IAAI,CAAA;AAClC,IAAA,CAAK,gBAAA,CAAiB,OAAO,GAAG,CAAA;AAChC,IAAA,CAAK,gBAAA,CAAiB,QAAQ,GAAG,CAAA;AACjC,IAAA,CAAK,gBAAA,CAAiB,OAAO,GAAG,CAAA;AAChC,IAAA,CAAK,gBAAA,CAAiB,QAAQ,IAAI,CAAA;AAClC,IAAA,CAAK,gBAAA,CAAiB,SAAS,IAAI,CAAA;AACnC,IAAA,CAAK,gBAAA,CAAiB,OAAO,GAAG,CAAA;AAChC,IAAA,CAAK,gBAAA,CAAiB,QAAQ,IAAI,CAAA;AAClC,IAAA,CAAK,gBAAA,CAAiB,OAAO,IAAI,CAAA;AACjC,IAAA,CAAK,gBAAA,CAAiB,YAAY,QAAQ,CAAA;AAC1C,IAAA,CAAK,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AAEpC,IAAM,aAAA,GAAwD;AAAA,EAC5D,IAAA,EAAM,MAAM,OAAO,iCAAiC,CAAA;AAAA,EACpD,GAAA,EAAK,MAAM,OAAO,gCAAgC,CAAA;AAAA,EAClD,KAAA,EAAO,MAAM,OAAO,gCAAgC,CAAA;AAAA,EACpD,CAAA,EAAG,MAAM,OAAO,8BAA8B,CAAA;AAAA,EAC9C,MAAA,EAAQ,MAAM,OAAO,mCAAmC,CAAA;AAAA,EACxD,GAAA,EAAK,MAAM,OAAO,gCAAgC,CAAA;AAAA,EAClD,IAAA,EAAM,MAAM,OAAO,iCAAiC,CAAA;AAAA,EACpD,EAAA,EAAI,MAAM,OAAO,+BAA+B,CAAA;AAAA,EAChD,IAAA,EAAM,MAAM,OAAO,iCAAiC,CAAA;AAAA,EACpD,IAAA,EAAM,MAAM,OAAO,iCAAiC,CAAA;AAAA,EACpD,CAAA,EAAG,MAAM,OAAO,8BAA8B,CAAA;AAAA,EAC9C,QAAA,EAAU,MAAM,OAAO,qCAAqC,CAAA;AAAA,EAC5D,UAAA,EAAY,MAAM,OAAO,uCAAuC;AAClE,CAAA;AAEA,IAAM,eAAA,uBAAsB,GAAA,CAAY;AAAA,EACtC,YAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,eAAe,eAAe,IAAA,EAAgC;AAC5D,EAAA,MAAM,GAAA,GAAM,KAAK,WAAA,EAAY;AAC7B,EAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,IAAA;AACrC,EAAA,MAAM,MAAA,GAAS,cAAc,GAAG,CAAA;AAChC,EAAA,IAAI,CAAC,QAAQ,OAAO,KAAA;AACpB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAO,MAAM,MAAA,EAAO;AAC1B,IAAA,IAAA,CAAK,gBAAA;AAAA,MACH,GAAA;AAAA,MACA,GAAA,CAAI;AAAA,KACN;AACA,IAAA,eAAA,CAAgB,IAAI,GAAG,CAAA;AACvB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,aAAA,CAAc,MAAc,IAAA,EAAuB;AACjE,EAAA,IAAI,QAAQ,eAAA,CAAgB,GAAA,CAAI,IAAA,CAAK,WAAA,EAAa,CAAA,EAAG;AACnD,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,UAAU,IAAA,EAAM,EAAE,UAAU,IAAA,CAAK,WAAA,EAAY,EAAG,CAAA,CAAE,KAAA;AAAA,IAChE,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,aAAA,CAAc,IAAI,CAAA;AACtC,IAAA,IAAI,MAAA,CAAO,SAAA,GAAY,CAAA,EAAG,OAAO,MAAA,CAAO,KAAA;AAAA,EAC1C,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,WAAW,IAAI,CAAA;AACxB;AAEA,SAAS,SAAS,IAAA,EAAsB;AACtC,EAAA,OAAO,SAAA,CAAU,SAAS,IAAA,EAAM;AAAA,IAC9B,QAAA,EAAU;AAAA,MACR,QAAA;AAAA,MACA,KAAA;AAAA,MACA,iBAAA;AAAA,MACA,eAAA;AAAA,MACA,WAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AACF,GACD,CAAA;AACH;AAGA,IAAM,EAAA,GAAK,UAAA;AAEX,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,CAAC,GAAG,6BAAA,EAA+B;AACxE,EAAA,EAAA,CAAG,6BAAA,GAAgC,IAAA;AACnC,EAAA,SAAA,CAAU,OAAA,CAAQ,yBAAA,EAA2B,CAAC,IAAA,KAAkB;AAC9D,IAAA,MAAM,WACH,OAAO,iBAAA,KAAsB,eAC5B,IAAA,YAAgB,iBAAA,IAClB,KAAK,QAAA,KAAa,GAAA;AACpB,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAA,CAAK,YAAA,CAAa,UAAU,QAAQ,CAAA;AACpC,MAAA,IAAA,CAAK,YAAA,CAAa,OAAO,qBAAqB,CAAA;AAAA,IAChD;AAAA,EACF,CAAC,CAAA;AACH;AAEA,IAAI,YAAA,GAAe,CAAA;AAEnB,SAAS,cAAA,GAAiB;AACxB,EAAA,MAAM,QAAA,GAAW,IAAI,MAAA,CAAO,QAAA,EAAS;AAErC,EAAA,QAAA,CAAS,IAAA,GAAO,SAAyB,KAAA,EAAoB;AAC3D,IAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,GAAO,IAAG,GAAI,KAAA;AAClC,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,WAAA,EAAY,CAAE,IAAA,EAAK;AAC3C,IAAA,MAAM,OAAA,GAAU,CAAA,MAAA,EAAS,EAAE,YAAY,CAAA,CAAA;AACvC,IAAA,MAAM,WAAA,GAAc,mBAAmB,IAAI,CAAA;AAC3C,IAAA,MAAM,QAAA,GAAW,mBAAA;AAEjB,IAAA,QAAQ,UAAA;AAAY,MAClB,KAAK,SAAA;AACH,QAAA,OAAO,CAAA,8CAAA,EAAiD,OAAO,CAAA,aAAA,EAAgB,WAAW,KAAK,QAAQ,CAAA,OAAA,CAAA;AAAA,MACzG,KAAK,KAAA;AACH,QAAA,OAAO,CAAA,0CAAA,EAA6C,OAAO,CAAA,aAAA,EAAgB,WAAW,KAAK,QAAQ,CAAA,OAAA,CAAA;AAAA,MACrG,KAAK,QAAA;AACH,QAAA,OAAO,CAAA,6CAAA,EAAgD,OAAO,CAAA,aAAA,EAAgB,WAAW,KAAK,QAAQ,CAAA,OAAA,CAAA;AAAA,MACxG,KAAK,MAAA;AACH,QAAA,OAAO,CAAA,mDAAA,EAAsD,OAAO,CAAA,aAAA,EAAgB,WAAW,KAAK,QAAQ,CAAA,OAAA,CAAA;AAAA,MAC9G;AACE,QAAA,OAAO,CAAA,2CAAA,EAA8C,OAAO,CAAA,aAAA,EAAgB,WAAW,gBAAgB,UAAA,CAAW,UAAU,CAAC,CAAA,EAAA,EAAK,QAAQ,CAAA,OAAA,CAAA;AAAA;AAC9I,EACF,CAAA;AAEA,EAAA,QAAA,CAAS,IAAA,GAAO,SAAyB,KAAA,EAAoB;AAC3D,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,MAAA,EAAO,GAAI,KAAA;AAChC,IAAA,MAAM,IAAA,GACJ,IAAA,IAAQ,OAAQ,IAAA,CAAiC,MAAA,KAAW,QAAA,GAEtD,IAAA,CAGA,MAAA,CAAO,WAAA,CAAY,MAAM,CAAA,GAC3B,KAAA,CAAM,IAAA;AACZ,IAAA,MAAM,YAAY,KAAA,GAAQ,CAAA,QAAA,EAAW,UAAA,CAAW,KAAK,CAAC,CAAA,CAAA,CAAA,GAAM,EAAA;AAC5D,IAAA,OAAO,YAAY,UAAA,CAAW,IAAI,CAAC,CAAA,2CAAA,EAA8C,SAAS,IAAI,IAAI,CAAA,IAAA,CAAA;AAAA,EACpG,CAAA;AAEA,EAAA,QAAA,CAAS,KAAA,GAAQ,SAAyB,KAAA,EAAqB;AAC7D,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,MAAA,CACvB,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,MAAA,MAAM,OAAA,GACJ,IAAA,IAAQ,OAAQ,IAAA,CAAiC,MAAA,KAAW,QAAA,GAEtD,IAAA,CAKA,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA,GAChC,IAAA,CAAK,IAAA;AACX,MAAA,OAAO,OAAO,OAAO,CAAA,KAAA,CAAA;AAAA,IACvB,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AAEV,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,IAAA,CACpB,GAAA,CAAI,CAAC,GAAA,KAAQ;AACZ,MAAA,MAAM,KAAA,GAAQ,GAAA,CACX,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,QAAA,MAAM,OAAA,GACJ,IAAA,IACA,OAAQ,IAAA,CAAiC,MAAA,KAAW,QAAA,GAE9C,IAAA,CAKA,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA,GAChC,IAAA,CAAK,IAAA;AACX,QAAA,OAAO,OAAO,OAAO,CAAA,KAAA,CAAA;AAAA,MACvB,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AACV,MAAA,OAAO,OAAO,KAAK,CAAA,KAAA,CAAA;AAAA,IACrB,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AAEV,IAAA,OAAO,CAAA,sHAAA,EAAyH,WAAW,CAAA,gFAAA,EAAmF,QAAQ,CAAA,sBAAA,CAAA;AAAA,EACxO,CAAA;AAEA,EAAA,OAAO,QAAA;AACT;AAEA,SAAS,iBAAA,GAAmC;AAC1C,EAAA,OAAO,EAAE,GAAA,EAAK,IAAA,EAAM,QAAQ,IAAA,EAAM,QAAA,EAAU,gBAAe,EAAE;AAC/D;AAEA,IAAM,SAAA,GAAY,GAAA;AAClB,IAAM,WAAA,uBAAkB,GAAA,EAAoB;AAC5C,SAAS,QAAA,CAAS,KAAa,KAAA,EAAe;AAC5C,EAAA,IAAI,WAAA,CAAY,QAAQ,SAAA,EAAW;AACjC,IAAA,WAAA,CAAY,OAAO,WAAA,CAAY,IAAA,EAAK,CAAE,IAAA,GAAO,KAAe,CAAA;AAAA,EAC9D;AACA,EAAA,WAAA,CAAY,GAAA,CAAI,KAAK,KAAK,CAAA;AAC5B;AAWO,SAAS,WAAA,GAAiC;AAC/C,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AAEnC,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAC,IAAA,EAAc,QAAA,KAA8B;AACtE,IAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,IAAA,MAAM,MAAM,QAAA,IAAY,IAAA;AACxB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AACvC,IAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,IAAA,EAAM;AAAA,MAC7B,GAAG,iBAAA,EAAkB;AAAA,MACrB,KAAA,EAAO;AAAA,KACR,CAAA;AACD,IAAA,MAAM,KAAA,GAAQ,SAAS,GAAG,CAAA;AAC1B,IAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AACnB,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,OAAO,MAAc,QAAA,KAAuC;AAC1D,MAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,MAAA,MAAM,MAAM,QAAA,IAAY,IAAA;AACxB,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AACvC,MAAA,IAAI,QAAQ,OAAO,MAAA;AAGnB,MAAA,MAAM,UAAA,GAAa,uBAAA;AACnB,MAAA,IAAI,KAAA;AACJ,MAAA,MAAM,QAAkB,EAAC;AACzB,MAAA,OAAA,CAAQ,KAAA,GAAQ,UAAA,CAAW,IAAA,CAAK,IAAI,OAAO,IAAA,EAAM;AAC/C,QAAA,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,MACrB;AACA,MAAA,MAAM,OAAA,CAAQ,IAAI,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,cAAA,CAAe,CAAC,CAAC,CAAC,CAAA;AAErD,MAAA,MAAM,MAAM,MAAM,MAAA,CAAO,KAAA,CAAM,IAAA,EAAM,mBAAmB,CAAA;AACxD,MAAA,MAAM,KAAA,GAAQ,SAAS,GAAG,CAAA;AAC1B,MAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AACnB,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,QAAA,CAAS,QAAQ,KAAA,EAAM;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,OAAA;AAAA,IACL,OAAO,EAAE,MAAA,EAAQ,WAAA,EAAa,UAAA,EAAW,CAAA;AAAA,IACzC,CAAC,MAAA,EAAQ,WAAA,EAAa,UAAU;AAAA,GAClC;AACF;ACtRO,IAAM,SAAA,GAAsC,CAAC,EAAE,IAAA,EAAM,UAAS,KAAM;AACzE,EAAA,MAAM,IAAA,GAAOA,OAAAA,CAAQ,MAAM,aAAA,CAAc,IAAA,EAAM,QAAQ,CAAA,EAAG,CAAC,IAAA,EAAM,QAAQ,CAAC,CAAA;AAE1E,EAAA,uBACE,GAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAY,QAAA,EAGtB,QAAA,kBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,iDAAA;AAAA,MAEV,QAAA,EAAU,CAAA;AAAA,MACV,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAY,QAAA,GAAW,CAAA,EAAG,QAAQ,CAAA,KAAA,CAAA,GAAU,MAAA;AAAA,MAE5C,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,yBAAA;AAAA,UACV,uBAAA,EAAyB,EAAE,MAAA,EAAQ,IAAA;AAAK;AAAA;AAC1C;AAAA,GACF,EACF,CAAA;AAEJ;AC5BA,IAAM,QAAA,GAAW,IAAA;AAAA,EAAK,MACpB,OAAO,wBAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,QAAA,EAAS,CAAE;AAC5D,CAAA;AACA,IAAM,gBAAA,GAAmB,IAAA;AAAA,EAAK,MAC5B,OAAO,gCAAoB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,gBAAA,EAAiB,CAAE;AAC5E,CAAA;AACA,IAAM,YAAA,GAAe,IAAA;AAAA,EAAK,MACxB,OAAO,4BAAgB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,YAAA,EAAa,CAAE;AACpE,CAAA;AACA,IAAM,WAAA,GAAc,IAAA;AAAA,EAAK,MACvB,OAAO,2BAAe,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,WAAA,EAAY,CAAE;AAClE,CAAA;AAEA,IAAM,gBAA0B,sBAC9BC,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iEAAgE,QAAA,EAAA,eAAA,EAE/E,CAAA;AAeF,IAAM,QAAA,GACJ,oHAAA;AAaF,SAAS,UAAU,IAAA,EAAyB;AAC1C,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,EAAG;AACvC,IAAA,IAAI,CAAA,CAAE,KAAA,GAAQ,IAAA,EAAM,QAAA,CAAS,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA,CAAE,KAAK,GAAG,CAAA;AACrE,IAAA,MAAM,YAAY,CAAA,CAAE,CAAC,GAAG,KAAA,CAAM,qBAAqB,IAAI,CAAC,CAAA;AACxD,IAAA,QAAA,CAAS,IAAA,CAAK;AAAA,MACZ,IAAA,EAAM,EAAE,CAAC,CAAA;AAAA,MACT,EAAA,EAAI,EAAE,CAAC,CAAA;AAAA,MACP,OAAO,MAAM;AACX,QAAA,IAAI;AACF,UAAA,OAAO,kBAAA,CAAmB,CAAA,CAAE,CAAC,CAAC,CAAA;AAAA,QAChC,CAAA,CAAA,MAAQ;AACN,UAAA,OAAO,EAAE,CAAC,CAAA;AAAA,QACZ;AAAA,MACF,CAAA,GAAG;AAAA,MACH,MAAM,SAAA,IAAa;AAAA,KACpB,CAAA;AACD,IAAA,IAAA,GAAO,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,CAAC,CAAA,CAAE,MAAA;AAAA,EACxB;AACA,EAAA,IAAI,IAAA,GAAO,IAAA,CAAK,MAAA,EAAQ,QAAA,CAAS,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG,CAAA;AAChE,EAAA,OAAO,QAAA;AACT;AAEA,SAAS,YAAY,GAAA,EAAoC;AACvD,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,qBACZA,GAAAA,CAAC,QAAA,EAAA,EAAsB,QAAA,kBAAUA,GAAAA,CAAC,aAAA,EAAA,EAAc,CAAA,EAC7C,QAAA,EAAA,IAAA,EAAA,EADY,IAAI,EAEnB,CAAA;AAEF,EAAA,QAAQ,IAAI,IAAA;AAAM,IAChB,KAAK,SAAA;AACH,MAAA,OAAO,IAAA,iBAAKA,GAAAA,CAAC,YAAA,EAAA,EAAa,IAAA,EAAM,IAAI,IAAA,EAAM,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,CAAE,CAAA;AAAA,IAC1D,KAAK,KAAA;AACH,MAAA,OAAO,IAAA,iBAAKA,GAAAA,CAAC,QAAA,EAAA,EAAS,IAAA,EAAM,IAAI,IAAA,EAAM,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,CAAE,CAAA;AAAA,IACtD,KAAK,QAAA;AACH,MAAA,OAAO,IAAA,iBAAKA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,IAAI,IAAA,EAAM,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,CAAE,CAAA;AAAA,IACzD,KAAK,cAAA;AACH,MAAA,OAAO,IAAA,iBAAKA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,IAAA,EAAM,IAAI,IAAA,EAAM,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,CAAE,CAAA;AAAA,IAC9D,KAAK,MAAA;AACH,MAAA,OAAO,IAAA;AAAA,wBACLA,IAAC,SAAA,EAAA,EAAU,IAAA,EAAM,IAAI,IAAA,EAAM,QAAA,EAAU,GAAA,CAAI,IAAA,IAAQ,MAAA,EAAW;AAAA,OAC9D;AAAA,IACF;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAEO,IAAM,mBAAoD,CAAC;AAAA,EAChE,IAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,SAAA,GAAY;AACd,CAAA,KAAM;AACJ,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,WAAA,EAAY;AAC5C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,EAAE,CAAA;AAEnC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA,GAAY,KAAA;AAIhB,IAAA,MAAM,YAAA,GAAe,YACjB,QAAA,GACE,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,IAAA,CAAK,MAAM,CAAA,CAAA,GAC3B,MAAA,GACF,QAAA;AAEJ,IAAA,eAAe,QAAA,GAAW;AACxB,MAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAY,IAAA,EAAM,YAAY,CAAA;AACrD,MAAA,IAAI,CAAC,SAAA,EAAW,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAClC;AAEA,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,OAAA,CAAQ,MAAA,CAAO,IAAA,EAAM,YAAY,CAAC,CAAA;AAAA,IACpC,CAAA,MAAO;AACL,MAAA,KAAK,QAAA,EAAS;AAAA,IAChB;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,GAAG,CAAC,IAAA,EAAM,UAAU,SAAA,EAAW,MAAA,EAAQ,WAAW,CAAC,CAAA;AAEnD,EAAA,MAAM,QAAA,GAAW,UAAU,IAAI,CAAA;AAC/B,EAAA,MAAM,UAAA,GAAa,CAAA,SAAA,EAAY,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAEhD,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,YACb,QAAA,EAAA,QAAA,CAAS,GAAA;AAAA,IAAI,CAAC,GAAA,EAAK,CAAA,KAClB,MAAA,IAAU,GAAA,mBACRA,GAAAA,CAAC,KAAA,EAAA,EAAY,uBAAA,EAAyB,EAAE,QAAQ,GAAA,CAAI,IAAA,MAA1C,CAAkD,CAAA,GAE5D,YAAY,GAAG;AAAA,GAEnB,EACF,CAAA;AAEJ","file":"chunk-QJ2L5RU6.js","sourcesContent":["/** useMarkdown — converts markdown to sanitised HTML with hljs highlighting and special fence blocks. */\nimport DOMPurify from 'dompurify';\nimport hljs from 'highlight.js/lib/core';\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\nimport bash from 'highlight.js/lib/languages/bash';\nimport css from 'highlight.js/lib/languages/css';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport json from 'highlight.js/lib/languages/json';\nimport markdown from 'highlight.js/lib/languages/markdown';\nimport python from 'highlight.js/lib/languages/python';\nimport sql from 'highlight.js/lib/languages/sql';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\nimport { marked, type MarkedOptions, type Tokens } from 'marked';\nimport { useCallback, useMemo, useRef } from 'react';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('python', python);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('xml', xml);\nhljs.registerLanguage('html', xml);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('shell', bash);\nhljs.registerLanguage('sql', sql);\nhljs.registerLanguage('yaml', yaml);\nhljs.registerLanguage('yml', yaml);\nhljs.registerLanguage('markdown', markdown);\nhljs.registerLanguage('md', markdown);\n\nconst lazyLanguages: Record<string, () => Promise<unknown>> = {\n java: () => import('highlight.js/lib/languages/java'),\n cpp: () => import('highlight.js/lib/languages/cpp'),\n 'c++': () => import('highlight.js/lib/languages/cpp'),\n c: () => import('highlight.js/lib/languages/c'),\n csharp: () => import('highlight.js/lib/languages/csharp'),\n php: () => import('highlight.js/lib/languages/php'),\n ruby: () => import('highlight.js/lib/languages/ruby'),\n go: () => import('highlight.js/lib/languages/go'),\n rust: () => import('highlight.js/lib/languages/rust'),\n perl: () => import('highlight.js/lib/languages/perl'),\n r: () => import('highlight.js/lib/languages/r'),\n makefile: () => import('highlight.js/lib/languages/makefile'),\n dockerfile: () => import('highlight.js/lib/languages/dockerfile'),\n};\n\nconst loadedLanguages = new Set<string>([\n 'javascript',\n 'typescript',\n 'python',\n 'json',\n 'xml',\n 'html',\n 'css',\n 'bash',\n 'shell',\n 'sql',\n 'yaml',\n 'yml',\n 'markdown',\n 'md',\n]);\n\nasync function ensureLanguage(lang: string): Promise<boolean> {\n const key = lang.toLowerCase();\n if (loadedLanguages.has(key)) return true;\n const loader = lazyLanguages[key];\n if (!loader) return false;\n try {\n const mod = (await loader()) as { default: unknown };\n hljs.registerLanguage(\n key,\n mod.default as Parameters<typeof hljs.registerLanguage>[1]\n );\n loadedLanguages.add(key);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function highlightCode(code: string, lang?: string): string {\n if (lang && loadedLanguages.has(lang.toLowerCase())) {\n try {\n return hljs.highlight(code, { language: lang.toLowerCase() }).value;\n } catch {\n /* fall through */\n }\n }\n try {\n const result = hljs.highlightAuto(code);\n if (result.relevance > 5) return result.value;\n } catch {\n /* fall through */\n }\n return escapeHtml(code);\n}\n\nfunction sanitise(html: string): string {\n return DOMPurify.sanitize(html, {\n ADD_ATTR: [\n 'target',\n 'rel',\n 'data-block-type',\n 'data-block-id',\n 'data-code',\n 'data-lang',\n 'data-md-fence',\n ],\n }) as string;\n}\n\n// Use globalThis to prevent duplicate DOMPurify hook registration across HMR reloads.\nconst _g = globalThis as unknown as Record<string, boolean>;\n// Guard against SSR: DOMPurify hooks operate on the DOM, so only register in the browser.\nif (typeof document !== 'undefined' && !_g.__markdownAnchorHookInstalled) {\n _g.__markdownAnchorHookInstalled = true;\n DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {\n const isAnchor =\n (typeof HTMLAnchorElement !== 'undefined' &&\n node instanceof HTMLAnchorElement) ||\n node.nodeName === 'A';\n if (isAnchor) {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer');\n }\n });\n}\n\nlet blockCounter = 0;\n\nfunction createRenderer() {\n const renderer = new marked.Renderer();\n\n renderer.code = function (this: unknown, token: Tokens.Code) {\n const { text: code, lang = '' } = token;\n const normalised = lang.toLowerCase().trim();\n const blockId = `block-${++blockCounter}`;\n const encodedCode = encodeURIComponent(code);\n const sentinel = 'data-md-fence=\"1\"';\n\n switch (normalised) {\n case 'mermaid':\n return `<div data-block-type=\"mermaid\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'csv':\n return `<div data-block-type=\"csv\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'survey':\n return `<div data-block-type=\"survey\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'html':\n return `<div data-block-type=\"html-preview\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n default:\n return `<div data-block-type=\"code\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" data-lang=\"${escapeHtml(normalised)}\" ${sentinel}></div>`;\n }\n };\n\n renderer.link = function (this: unknown, token: Tokens.Link) {\n const { href, title, tokens } = token;\n const text =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: { parseInline: (t: Tokens.Link['tokens']) => string };\n }\n ).parser.parseInline(tokens)\n : token.text;\n const titleAttr = title ? ` title=\"${escapeHtml(title)}\"` : '';\n return `<a href=\"${escapeHtml(href)}\" target=\"_blank\" rel=\"noopener noreferrer\"${titleAttr}>${text}</a>`;\n };\n\n renderer.table = function (this: unknown, token: Tokens.Table) {\n const headerCells = token.header\n .map((cell) => {\n const content =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<th>${content}</th>`;\n })\n .join('');\n\n const bodyRows = token.rows\n .map((row) => {\n const cells = row\n .map((cell) => {\n const content =\n this &&\n typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<td>${content}</td>`;\n })\n .join('');\n return `<tr>${cells}</tr>`;\n })\n .join('');\n\n return `<div class=\"overflow-x-auto\"><table class=\"min-w-full divide-y divide-neutral-200 dark:divide-neutral-700\"><thead><tr>${headerCells}</tr></thead><tbody class=\"divide-y divide-neutral-200 dark:divide-neutral-700\">${bodyRows}</tbody></table></div>`;\n };\n\n return renderer;\n}\n\nfunction makeMarkedOptions(): MarkedOptions {\n return { gfm: true, breaks: true, renderer: createRenderer() };\n}\n\nconst CACHE_MAX = 100;\nconst renderCache = new Map<string, string>();\nfunction cacheSet(key: string, value: string) {\n if (renderCache.size >= CACHE_MAX) {\n renderCache.delete(renderCache.keys().next().value as string);\n }\n renderCache.set(key, value);\n}\n\nexport interface UseMarkdownResult {\n /** Render markdown text to sanitised HTML string */\n render: (text: string, cacheKey?: string) => string;\n /** Async-render that lazy-loads needed languages first */\n renderAsync: (text: string, cacheKey?: string) => Promise<string>;\n /** Clear the render cache */\n clearCache: () => void;\n}\n\nexport function useMarkdown(): UseMarkdownResult {\n const cacheRef = useRef(renderCache);\n\n const render = useCallback((text: string, cacheKey?: string): string => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n const raw = marked.parse(text, {\n ...makeMarkedOptions(),\n async: false,\n }) as string;\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n }, []);\n\n const renderAsync = useCallback(\n async (text: string, cacheKey?: string): Promise<string> => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n // Allow `+`, `-`, `.` in language identifiers (c++, objective-c, bash-session, etc.)\n const fenceRegex = /^```([\\w+\\-.]+)\\s*$/gm;\n let match: RegExpExecArray | null;\n const langs: string[] = [];\n while ((match = fenceRegex.exec(text)) !== null) {\n langs.push(match[1]);\n }\n await Promise.all(langs.map((l) => ensureLanguage(l)));\n\n const raw = await marked.parse(text, makeMarkedOptions());\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n },\n []\n );\n\n const clearCache = useCallback(() => {\n cacheRef.current.clear();\n }, []);\n\n return useMemo(\n () => ({ render, renderAsync, clearCache }),\n [render, renderAsync, clearCache]\n );\n}\n","/**\n * CodeBlock — Renders a syntax-highlighted code fence using FenceBlock.\n *\n * Used by `MarkdownRenderer` for plain (non-special) fenced code blocks.\n * Highlighting is performed synchronously via the `highlightCode` helper from\n * `useMarkdown`; if the language was not pre-registered with highlight.js the\n * helper falls back to escaped raw text.\n */\nimport React, { useMemo } from 'react';\n\nimport { FenceBlock } from './FenceBlock';\nimport { highlightCode } from './useMarkdown';\n\ninterface CodeBlockProps {\n code: string;\n language?: string;\n}\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({ code, language }) => {\n const html = useMemo(() => highlightCode(code, language), [code, language]);\n\n return (\n <FenceBlock code={code} language={language}>\n {/* Focusable so keyboard users can horizontally scroll long lines\n (axe: scrollable-region-focusable). */}\n <pre\n className=\"m-0 overflow-x-auto !bg-transparent p-3 text-sm\"\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- scrollable code needs keyboard focus\n tabIndex={0}\n role=\"region\"\n aria-label={language ? `${language} code` : 'Code'}\n >\n <code\n className=\"hljs bg-transparent p-0\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </pre>\n </FenceBlock>\n );\n};\n","/**\n * MarkdownRenderer — renders markdown with React components for special fence blocks.\n */\nimport React, { Suspense, lazy, useEffect, useState } from 'react';\n\nimport './styles.css';\nimport { CodeBlock } from './CodeBlock';\nimport { useMarkdown } from './useMarkdown';\n\n// Block components are lazy-loaded so optional peer deps (papaparse, js-yaml, mermaid)\n// aren't bundled unless actually rendered.\nconst CsvBlock = lazy(() =>\n import('./CsvBlock').then((m) => ({ default: m.CsvBlock }))\n);\nconst HtmlPreviewBlock = lazy(() =>\n import('./HtmlPreviewBlock').then((m) => ({ default: m.HtmlPreviewBlock }))\n);\nconst MermaidBlock = lazy(() =>\n import('./MermaidBlock').then((m) => ({ default: m.MermaidBlock }))\n);\nconst SurveyBlock = lazy(() =>\n import('./SurveyBlock').then((m) => ({ default: m.SurveyBlock }))\n);\n\nconst BlockFallback: React.FC = () => (\n <div className=\"flex items-center justify-center p-4 text-sm text-neutral-500\">\n Loading…\n </div>\n);\n\nexport interface MarkdownRendererProps {\n /** Raw markdown text */\n text: string;\n /** Cache key (e.g., message._id + revisionNumber) */\n cacheKey?: string;\n /** Additional CSS classes */\n className?: string;\n /** Whether the message is still streaming (may have incomplete blocks) */\n streaming?: boolean;\n}\n\n// Matches fence block markers emitted by useMarkdown (sentinel data-md-fence prevents raw-HTML injection)\nconst BLOCK_RE =\n /<div data-block-type=\"([^\"]+)\" data-block-id=\"([^\"]+)\" data-code=\"([^\"]*)\"([^>]*\\bdata-md-fence=\"1\"[^>]*)><\\/div>/g;\n\ninterface HtmlSegment {\n html: string;\n}\ninterface BlockSegment {\n type: string;\n id: string;\n code: string;\n lang?: string;\n}\ntype Segment = HtmlSegment | BlockSegment;\n\nfunction splitHtml(html: string): Segment[] {\n const segments: Segment[] = [];\n let last = 0;\n for (const m of html.matchAll(BLOCK_RE)) {\n if (m.index > last) segments.push({ html: html.slice(last, m.index) });\n const langMatch = m[4]?.match(/data-lang=\"([^\"]*)\"/)?.[1];\n segments.push({\n type: m[1],\n id: m[2],\n code: (() => {\n try {\n return decodeURIComponent(m[3]);\n } catch {\n return m[3];\n }\n })(),\n lang: langMatch ?? undefined,\n });\n last = m.index + m[0].length;\n }\n if (last < html.length) segments.push({ html: html.slice(last) });\n return segments;\n}\n\nfunction renderBlock(seg: BlockSegment): React.ReactNode {\n const wrap = (node: React.ReactNode) => (\n <Suspense key={seg.id} fallback={<BlockFallback />}>\n {node}\n </Suspense>\n );\n switch (seg.type) {\n case 'mermaid':\n return wrap(<MermaidBlock code={seg.code} id={seg.id} />);\n case 'csv':\n return wrap(<CsvBlock code={seg.code} id={seg.id} />);\n case 'survey':\n return wrap(<SurveyBlock code={seg.code} id={seg.id} />);\n case 'html-preview':\n return wrap(<HtmlPreviewBlock code={seg.code} id={seg.id} />);\n case 'code':\n return wrap(\n <CodeBlock code={seg.code} language={seg.lang || undefined} />\n );\n default:\n return null;\n }\n}\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({\n text,\n cacheKey,\n className = '',\n streaming = false,\n}) => {\n const { render, renderAsync } = useMarkdown();\n const [html, setHtml] = useState('');\n\n useEffect(() => {\n let cancelled = false;\n\n // While streaming, append text length to the cache key so each delta\n // produces a fresh render rather than a stale hit on the messageId.\n const effectiveKey = streaming\n ? cacheKey\n ? `${cacheKey}::${text.length}`\n : undefined\n : cacheKey;\n\n async function doRender() {\n const rendered = await renderAsync(text, effectiveKey);\n if (!cancelled) setHtml(rendered);\n }\n\n if (streaming) {\n setHtml(render(text, effectiveKey));\n } else {\n void doRender();\n }\n\n return () => {\n cancelled = true;\n };\n }, [text, cacheKey, streaming, render, renderAsync]);\n\n const segments = splitHtml(html);\n const proseClass = `md-prose ${className}`.trim();\n\n return (\n <div className={proseClass}>\n {segments.map((seg, i) =>\n 'html' in seg ? (\n <div key={i} dangerouslySetInnerHTML={{ __html: seg.html }} />\n ) : (\n renderBlock(seg)\n )\n )}\n </div>\n );\n};\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkQ3YVLO52_cjs = require('./chunk-Q3YVLO52.cjs');
|
|
3
4
|
var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
|
|
4
5
|
var React2 = require('react');
|
|
5
6
|
var reactDom = require('react-dom');
|
|
@@ -48,12 +49,16 @@ function peerLabels(peers) {
|
|
|
48
49
|
const seen = /* @__PURE__ */ new Map();
|
|
49
50
|
for (const p of peers) {
|
|
50
51
|
const entry = seen.get(p.name);
|
|
51
|
-
if (entry)
|
|
52
|
-
else
|
|
52
|
+
if (!entry) seen.set(p.name, { ...p, count: 1 });
|
|
53
|
+
else {
|
|
54
|
+
entry.count += 1;
|
|
55
|
+
if (entry.mode === "viewing" && p.mode !== "viewing") entry.mode = p.mode;
|
|
56
|
+
entry.avatarUrl ??= p.avatarUrl;
|
|
57
|
+
}
|
|
53
58
|
}
|
|
54
|
-
return [...seen].map((
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
return [...seen.values()].map(({ count, ...p }) => ({
|
|
60
|
+
...p,
|
|
61
|
+
label: count > 1 ? `${p.name} (${count})` : p.name
|
|
57
62
|
}));
|
|
58
63
|
}
|
|
59
64
|
var PANEL_OFFSET = 6;
|
|
@@ -140,7 +145,7 @@ function CollabStatus({
|
|
|
140
145
|
};
|
|
141
146
|
}, [open]);
|
|
142
147
|
const occupants = peerLabels(peers);
|
|
143
|
-
const names = occupants.map((p) => p.label);
|
|
148
|
+
const names = occupants.filter((p) => p.mode !== "viewing").map((p) => p.label);
|
|
144
149
|
const clip = wrapped ? "break-all whitespace-pre-wrap" : "truncate";
|
|
145
150
|
const statusText = connected ? labels.live : labels.connecting;
|
|
146
151
|
const clientLine = `${room?.clientId ?? "\u2014"} \xB7 ${connected ? labels.clientSynced : labels.clientConnecting}`;
|
|
@@ -274,33 +279,26 @@ function CollabStatus({
|
|
|
274
279
|
] }),
|
|
275
280
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "border-border mb-2 border-b pb-2", children: [
|
|
276
281
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { className: "text-foreground mb-1 block", children: labels.peersTitle(peers.length) }),
|
|
277
|
-
peers.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: labels.alone }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
278
|
-
|
|
282
|
+
peers.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: labels.alone }) : /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "collab-status-peers", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
283
|
+
chunkQ3YVLO52_cjs.AvatarGroup,
|
|
279
284
|
{
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
{
|
|
296
|
-
className: chunkS5RVSXDV_cjs.cn("text-foreground", clip),
|
|
297
|
-
title: peer.label,
|
|
298
|
-
children: peer.label
|
|
299
|
-
}
|
|
300
|
-
)
|
|
301
|
-
] }, peer.label))
|
|
285
|
+
size: "sm",
|
|
286
|
+
max: 8,
|
|
287
|
+
className: "flex-wrap ps-0.5",
|
|
288
|
+
labels: {
|
|
289
|
+
list: labels.peersTitle(peers.length),
|
|
290
|
+
...labels.presence && { presence: labels.presence }
|
|
291
|
+
},
|
|
292
|
+
items: occupants.map((peer) => ({
|
|
293
|
+
id: peer.name,
|
|
294
|
+
name: peer.name,
|
|
295
|
+
label: peer.label,
|
|
296
|
+
src: peer.avatarUrl,
|
|
297
|
+
presence: peer.mode,
|
|
298
|
+
color: peer.color
|
|
299
|
+
}))
|
|
302
300
|
}
|
|
303
|
-
)
|
|
301
|
+
) })
|
|
304
302
|
] }),
|
|
305
303
|
log.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: labels.empty }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "max-h-72 space-y-0.5 overflow-y-auto font-mono", children: log.map((e) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
306
304
|
"li",
|
|
@@ -507,5 +505,5 @@ function useYjsCollabStatus({
|
|
|
507
505
|
exports.CollabStatus = CollabStatus;
|
|
508
506
|
exports.defaultCollabStatusLabels = defaultCollabStatusLabels;
|
|
509
507
|
exports.useYjsCollabStatus = useYjsCollabStatus;
|
|
510
|
-
//# sourceMappingURL=chunk-
|
|
511
|
-
//# sourceMappingURL=chunk-
|
|
508
|
+
//# sourceMappingURL=chunk-QX6AAVDE.cjs.map
|
|
509
|
+
//# sourceMappingURL=chunk-QX6AAVDE.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/CollabStatus/CollabStatus.tsx","../src/components/CollabStatus/useYjsCollabStatus.ts"],"names":["React","jsxs","cn","jsx","createPortal","WrapText","X","Fragment","AvatarGroup","React2"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFO,IAAM,yBAAA,GAAgD;AAAA,EAC3D,IAAA,EAAM,MAAA;AAAA,EACN,UAAA,EAAY,kBAAA;AAAA,EACZ,OAAA,EAAS,CAAC,KAAA,KACR,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,MAAA,KAAW,CAAA,GAAI,OAAO,KAAK,CAAA,QAAA,CAAA;AAAA,EAC1D,YAAA,EAAc,6CAAA;AAAA,EACd,UAAA,EAAY,CAAC,KAAA,KAAU,CAAA,aAAA,EAAgB,KAAK,CAAA,CAAA,CAAA;AAAA,EAC5C,KAAA,EAAO,4BAAA;AAAA,EACP,QAAA,EAAU,CAAC,KAAA,KAAU,CAAA,YAAA,EAAe,KAAK,CAAA,CAAA,CAAA;AAAA,EACzC,KAAA,EAAO,kBAAA;AAAA,EACP,IAAA,EAAM,kBAAA;AAAA,EACN,KAAA,EAAO,iBAAA;AAAA,EACP,QAAA,EAAU,MAAA;AAAA,EACV,OAAA,EAAS,QAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,QAAA,EAAU,MAAA;AAAA,EACV,YAAA,EAAc,QAAA;AAAA,EACd,gBAAA,EAAkB;AACpB;AA2CA,SAAS,WAAW,KAAA,EAAiC;AACnD,EAAA,MAAM,IAAA,uBAAW,GAAA,EAA4C;AAC7D,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA;AAC7B,IAAA,IAAI,CAAC,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,CAAA,EAAG,CAAA;AAAA,SAC1C;AACH,MAAA,KAAA,CAAM,KAAA,IAAS,CAAA;AACf,MAAA,IAAI,KAAA,CAAM,SAAS,SAAA,IAAa,CAAA,CAAE,SAAS,SAAA,EAAW,KAAA,CAAM,OAAO,CAAA,CAAE,IAAA;AACrE,MAAA,KAAA,CAAM,cAAc,CAAA,CAAE,SAAA;AAAA,IACxB;AAAA,EACF;AACA,EAAA,OAAO,CAAC,GAAG,IAAA,CAAK,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,EAAE,KAAA,EAAO,GAAG,CAAA,EAAE,MAAO;AAAA,IAClD,GAAG,CAAA;AAAA,IACH,KAAA,EAAO,QAAQ,CAAA,GAAI,CAAA,EAAG,EAAE,IAAI,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA,CAAA,GAAM,CAAA,CAAE;AAAA,GAChD,CAAE,CAAA;AACJ;AAEA,IAAM,YAAA,GAAe,CAAA;AACrB,IAAM,gBAAA,GAAmB,CAAA;AAOzB,SAAS,gBAAA,CACP,IAAA,EACA,SAAA,EACA,QAAA,EACA;AACA,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAUA,iBAAA,CAAA,QAAA;AAAA,IAC1B;AAAA,GACF;AAEA,EAAMA,kCAAgB,MAAM;AAC1B,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAA,CAAO,IAAI,CAAA;AACX,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,MAAM,SAAS,SAAA,CAAU,OAAA;AACzB,MAAA,MAAM,QAAQ,QAAA,CAAS,OAAA;AACvB,MAAA,IAAI,CAAC,MAAA,IAAU,CAAC,KAAA,EAAO;AACvB,MAAA,MAAM,CAAA,GAAI,OAAO,qBAAA,EAAsB;AACvC,MAAA,MAAM,EAAE,WAAA,EAAa,KAAA,EAAO,YAAA,EAAc,QAAO,GAAI,KAAA;AAErD,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,UAAA,GAAa,KAAA,GAAQ,gBAAA;AAC5C,MAAA,MAAM,OAAO,IAAA,CAAK,GAAA;AAAA,QAChB,gBAAA;AAAA,QACA,IAAA,CAAK,IAAI,CAAA,CAAE,KAAA,GAAQ,OAAO,IAAA,CAAK,GAAA,CAAI,gBAAA,EAAkB,OAAO,CAAC;AAAA,OAC/D;AAEA,MAAA,IAAI,GAAA,GAAM,EAAE,MAAA,GAAS,YAAA;AACrB,MAAA,IAAI,GAAA,GAAM,MAAA,GAAS,MAAA,CAAO,WAAA,GAAc,gBAAA,EAAkB;AACxD,QAAA,GAAA,GAAM,KAAK,GAAA,CAAI,gBAAA,EAAkB,CAAA,CAAE,GAAA,GAAM,SAAS,YAAY,CAAA;AAAA,MAChE;AAEA,MAAA,MAAA,CAAO,EAAE,GAAA,EAAK,IAAA,EAAM,CAAA;AAAA,IACtB,CAAA;AAGA,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,qBAAA,CAAsB,MAAM,CAAA;AAC/C,IAAA,MAAA,CAAO,gBAAA,CAAiB,QAAA,EAAU,MAAA,EAAQ,IAAI,CAAA;AAC9C,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,MAAM,CAAA;AACxC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,qBAAqB,GAAG,CAAA;AAC/B,MAAA,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,MAAA,EAAQ,IAAI,CAAA;AACjD,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,MAAM,CAAA;AAAA,IAC7C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,SAAA,EAAW,QAAQ,CAAC,CAAA;AAE9B,EAAA,OAAO,GAAA;AACT;AAEA,IAAM,SAAA,GAA2C;AAAA,EAC/C,GAAA,EAAK,uBAAA;AAAA,EACL,SAAA,EAAW,wCAAA;AAAA,EACX,IAAA,EAAM,wCAAA;AAAA,EACN,KAAA,EAAO;AACT,CAAA;AA6BO,SAAS,YAAA,CAAa;AAAA,EAC3B,SAAA;AAAA,EACA,QAAQ,EAAC;AAAA,EACT,MAAM,EAAC;AAAA,EACP,IAAA,GAAO,IAAA;AAAA,EACP,OAAA,GAAU,IAAA;AAAA,EACV,OAAA,GAAU,KAAA;AAAA,EACV,SAAA,GAAY,IAAA;AAAA,EACZ,MAAA,EAAQ,cAAA;AAAA,EACR;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,yBAAA,EAA2B,GAAG,cAAA,EAAe;AACjE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAUA,2BAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAUA,2BAAS,KAAK,CAAA;AAClD,EAAA,MAAM,UAAA,GAAmBA,yBAA0B,IAAI,CAAA;AACvD,EAAA,MAAM,QAAA,GAAiBA,yBAAuB,IAAI,CAAA;AAClD,EAAA,MAAM,GAAA,GAAM,gBAAA,CAAiB,IAAA,IAAQ,OAAA,EAAS,YAAY,QAAQ,CAAA;AAClE,EAAA,MAAM,UAAgBA,iBAAA,CAAA,KAAA,EAAM;AAG5B,EAAMA,4BAAU,MAAM;AACpB,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACxB,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA,UAAA,CAAW,SAAS,KAAA,EAAM;AAAA,IAC5B,CAAA;AACA,IAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,KAAa;AAClC,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,IAAI,QAAA,CAAS,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AACxC,MAAA,IAAI,UAAA,CAAW,OAAA,EAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1C,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,IAAA,QAAA,CAAS,gBAAA,CAAiB,eAAe,aAAa,CAAA;AACtD,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,SAAS,CAAA;AACjD,MAAA,QAAA,CAAS,mBAAA,CAAoB,eAAe,aAAa,CAAA;AAAA,IAC3D,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,MAAM,SAAA,GAAY,WAAW,KAAK,CAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,SAAA,CACX,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,SAAS,CAAA,CAClC,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AAErB,EAAA,MAAM,IAAA,GAAO,UAAU,+BAAA,GAAkC,UAAA;AACzD,EAAA,MAAM,UAAA,GAAa,SAAA,GAAY,MAAA,CAAO,IAAA,GAAO,MAAA,CAAO,UAAA;AACpD,EAAA,MAAM,UAAA,GAAa,CAAA,EAAG,IAAA,EAAM,QAAA,IAAY,QAAG,SACzC,SAAA,GAAY,MAAA,CAAO,YAAA,GAAe,MAAA,CAAO,gBAC3C,CAAA,CAAA;AAGA,EAAA,MAAM,eAAe,OAAA,GACjB;AAAA,IACE,MAAA,CAAO,YAAA;AAAA,IACP,UAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,MAAA,CAAO,QAAQ,KAAK;AAAA,IAEvC,MAAA,CAAO,OAAO,EACd,IAAA,CAAK,UAAK,IACb,MAAA,CAAO,YAAA;AAEX,EAAA,MAAM,OAAA,mBACJC,eAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,GAAA,EAAK,UAAA;AAAA,MACL,SAAA,EAAWC,oBAAA;AAAA,QACT,yFAAA;AAAA,QACA,qGAAA;AAAA,QACA,OAAA,IAAW,+BAAA;AAAA,QACX;AAAA,OACF;AAAA,MACA,OAAA,EAAS,UAAU,MAAM,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA,GAAI,MAAA;AAAA,MAC9C,UAAU,CAAC,OAAA;AAAA,MACX,KAAA,EAAO,UAAU,YAAA,GAAe,MAAA;AAAA,MAChC,eAAA,EAAe,UAAU,IAAA,GAAO,MAAA;AAAA,MAChC,YAAA,EAAY,UAAU,YAAA,GAAe,MAAA;AAAA,MACrC,WAAA,EAAU,uBAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAC,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,aAAA,EAAY,MAAA;AAAA,YACZ,WAAA,EAAU,mBAAA;AAAA,YACV,SAAA,EAAWD,oBAAA;AAAA,cACT,+BAAA;AAAA,cACA,CAAC,SAAA,IAAa,8BAAA;AAAA,cACd,aAAa,SAAA,IAAa,gBAAA;AAAA,cAC1B,SAAA,IAAa,CAAC,SAAA,IAAa;AAAA;AAC7B;AAAA,SACF;AAAA,QACC,CAAC,OAAA,oBAAWC,cAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,UAAA,EAAW,CAAA;AAAA,QAC9B,CAAC,OAAA,IAAW,SAAA,oBACXF,eAAA,CAAC,MAAA,EAAA,EAAK,WAAU,iDAAA,EAAkD,QAAA,EAAA;AAAA,UAAA,OAAA;AAAA,UAC7D;AAAA,SAAA,EACL,CAAA;AAAA,QAED,CAAC,OAAA,IAAW,KAAA,CAAM,MAAA,GAAS,qBAC1BE,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,QAAA,EAAA,CAAA,KAAA,EAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA,CAAA,EAAG;AAAA;AAAA;AAAA,GAE7D;AAGF,EAAA,IAAI,CAAC,SAAS,OAAO,OAAA;AAErB,EAAA,uBACEF,eAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,mCAAA;AAAA,MACV,WAAA,EAAU,eAAA;AAAA,MAET,QAAA,EAAA;AAAA,QAAA,OAAA;AAAA,QACA,IAAA,IACC,OAAO,QAAA,KAAa,WAAA,IACpBG,qBAAA;AAAA,0BACEH,eAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,QAAA;AAAA,cACL,iBAAA,EAAiB,OAAA;AAAA,cACjB,WAAA,EAAU,qBAAA;AAAA,cACV,SAAA,EAAWC,oBAAA;AAAA,gBACT,0FAAA;AAAA,gBACA;AAAA,eACF;AAAA,cACA,KAAA,EAAO;AAAA,gBACL,GAAA,EAAK,KAAK,GAAA,IAAO,CAAA;AAAA,gBACjB,IAAA,EAAM,KAAK,IAAA,IAAQ,CAAA;AAAA,gBACnB,UAAA,EAAY,MAAM,MAAA,GAAY;AAAA,eAChC;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAAD,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8CAAA,EACb,QAAA,EAAA;AAAA,kCAAAE,cAAA,CAAC,QAAA,EAAA,EAAO,IAAI,OAAA,EAAS,SAAA,EAAU,2BAC5B,QAAA,EAAA,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,EAC7B,CAAA;AAAA,kCACAF,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2BAAA,EACd,QAAA,EAAA;AAAA,oCAAAE,cAAA;AAAA,sBAAC,QAAA;AAAA,sBAAA;AAAA,wBACC,IAAA,EAAK,QAAA;AAAA,wBACL,SAAA,EAAWD,oBAAA;AAAA,0BACT,6GAAA;AAAA,0BACA,UACI,0BAAA,GACA;AAAA,yBACN;AAAA,wBACA,SAAS,MAAM,UAAA,CAAW,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,wBACnC,cAAA,EAAc,OAAA;AAAA,wBACd,cAAY,MAAA,CAAO,IAAA;AAAA,wBACnB,OAAO,MAAA,CAAO,IAAA;AAAA,wBACd,WAAA,EAAU,oBAAA;AAAA,wBAEV,QAAA,kBAAAC,cAAA,CAACE,oBAAA,EAAA,EAAS,SAAA,EAAU,SAAA,EAAU,eAAY,MAAA,EAAO;AAAA;AAAA,qBACnD;AAAA,oCACAF,cAAA;AAAA,sBAAC,QAAA;AAAA,sBAAA;AAAA,wBACC,IAAA,EAAK,QAAA;AAAA,wBACL,SAAA,EAAU,mIAAA;AAAA,wBACV,SAAS,MAAM;AACb,0BAAA,OAAA,CAAQ,KAAK,CAAA;AACb,0BAAA,UAAA,CAAW,SAAS,KAAA,EAAM;AAAA,wBAC5B,CAAA;AAAA,wBACA,cAAY,MAAA,CAAO,KAAA;AAAA,wBAEnB,QAAA,kBAAAA,cAAA,CAACG,aAAA,EAAA,EAAE,SAAA,EAAU,SAAA,EAAU,eAAY,MAAA,EAAO;AAAA;AAAA;AAC5C,mBAAA,EACF;AAAA,iBAAA,EACF,CAAA;AAAA,gBAEC,SAAA,oBACCH,cAAA;AAAA,kBAAC,GAAA;AAAA,kBAAA;AAAA,oBACC,WAAA,EAAU,yBAAA;AAAA,oBACV,SAAA,EAAU,6CAAA;AAAA,oBAET,QAAA,EAAA;AAAA;AAAA,iBACH;AAAA,gBAGD,IAAA,oBACCF,eAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,oGAAA,EACZ,QAAA,EAAA;AAAA,kCAAAE,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,YAAA,EAAc,QAAA,EAAA,MAAA,CAAO,QAAA,EAAS,CAAA;AAAA,kCAE5CA,cAAA,CAAC,QAAG,SAAA,EAAW,IAAA,EAAM,OAAO,IAAA,CAAK,IAAA,EAC9B,eAAK,IAAA,EACR,CAAA;AAAA,kBACC,IAAA,CAAK,uBACJF,eAAA,CAAAM,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,oCAAAJ,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,YAAA,EAAc,QAAA,EAAA,MAAA,CAAO,OAAA,EAAQ,CAAA;AAAA,oCAC3CA,cAAA,CAAC,QAAG,SAAA,EAAW,IAAA,EAAM,OAAO,IAAA,CAAK,GAAA,EAC9B,eAAK,GAAA,EACR;AAAA,mBAAA,EACF,CAAA;AAAA,kCAEFA,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,YAAA,EAAc,iBAAO,UAAA,EAAW,CAAA;AAAA,iDAC7C,IAAA,EAAA,EAAG,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,YACzB,QAAA,EAAA,UAAA,EACH,CAAA;AAAA,kBACC,IAAA,CAAK,0BACJF,eAAA,CAAAM,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,oCAAAJ,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,YAAA,EAAc,QAAA,EAAA,MAAA,CAAO,QAAA,EAAS,CAAA;AAAA,oCAC5CA,cAAA,CAAC,QAAG,SAAA,EAAW,IAAA,EAAM,OAAO,IAAA,CAAK,MAAA,EAC9B,eAAK,MAAA,EACR;AAAA,mBAAA,EACF;AAAA,iBAAA,EAEJ,CAAA;AAAA,gCAGFF,eAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,kCAAA,EACjB,QAAA,EAAA;AAAA,kCAAAE,cAAA,CAAC,YAAO,SAAA,EAAU,4BAAA,EACf,iBAAO,UAAA,CAAW,KAAA,CAAM,MAAM,CAAA,EACjC,CAAA;AAAA,kBACC,KAAA,CAAM,MAAA,KAAW,CAAA,mBAChBA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uBAAA,EAAyB,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA,mBAEnDA,cAAA,CAAC,KAAA,EAAA,EAAI,aAAU,qBAAA,EACb,QAAA,kBAAAA,cAAA;AAAA,oBAACK,6BAAA;AAAA,oBAAA;AAAA,sBACC,IAAA,EAAK,IAAA;AAAA,sBACL,GAAA,EAAK,CAAA;AAAA,sBACL,SAAA,EAAU,kBAAA;AAAA,sBACV,MAAA,EAAQ;AAAA,wBACN,IAAA,EAAM,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,MAAM,CAAA;AAAA,wBACpC,GAAI,MAAA,CAAO,QAAA,IAAY,EAAE,QAAA,EAAU,OAAO,QAAA;AAAS,uBACrD;AAAA,sBACA,KAAA,EAAO,SAAA,CAAU,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,wBAC9B,IAAI,IAAA,CAAK,IAAA;AAAA,wBACT,MAAM,IAAA,CAAK,IAAA;AAAA,wBACX,OAAO,IAAA,CAAK,KAAA;AAAA,wBACZ,KAAK,IAAA,CAAK,SAAA;AAAA,wBACV,UAAU,IAAA,CAAK,IAAA;AAAA,wBACf,OAAO,IAAA,CAAK;AAAA,uBACd,CAAE;AAAA;AAAA,mBACJ,EACF;AAAA,iBAAA,EAEJ,CAAA;AAAA,gBAEC,IAAI,MAAA,KAAW,CAAA,mBACdL,cAAA,CAAC,GAAA,EAAA,EAAE,WAAU,uBAAA,EAAyB,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA,kCAElD,IAAA,EAAA,EAAG,SAAA,EAAU,kDACX,QAAA,EAAA,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,qBACRF,eAAA;AAAA,kBAAC,IAAA;AAAA,kBAAA;AAAA,oBAEC,SAAA,EAAU,sCAAA;AAAA,oBAEV,QAAA,EAAA;AAAA,sCAAAE,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,kCAAA,EACb,QAAA,EAAA,IAAI,KAAK,CAAA,CAAE,EAAE,CAAA,CAAE,kBAAA,EAAmB,EACrC,CAAA;AAAA,sCACAF,eAAA;AAAA,wBAAC,MAAA;AAAA,wBAAA;AAAA,0BACC,SAAA,EAAWC,oBAAA;AAAA,4BACT,mBAAA;AAAA,4BACA,EAAE,MAAA,KAAW,QAAA,GACT,wCAAA,GACA,SAAA,CAAU,EAAE,IAAI;AAAA,2BACtB;AAAA,0BAEC,QAAA,EAAA;AAAA,4BAAA,CAAA,CAAE,IAAA;AAAA,4BACF,CAAA,CAAE,MAAA,GAAS,CAAA,CAAA,EAAI,CAAA,CAAE,MAAM,CAAA,CAAA,GAAK;AAAA;AAAA;AAAA,uBAC/B;AAAA,sCACAC,cAAA;AAAA,wBAAC,MAAA;AAAA,wBAAA;AAAA,0BACC,SAAA,EAAWD,oBAAA,CAAG,iBAAA,EAAmB,IAAI,CAAA;AAAA,0BACrC,OAAO,CAAA,CAAE,MAAA;AAAA,0BAER,QAAA,EAAA,CAAA,CAAE;AAAA;AAAA;AACL;AAAA,mBAAA;AAAA,kBAtBK,CAAA,CAAE;AAAA,iBAwBV,CAAA,EACH;AAAA;AAAA;AAAA,WAEJ;AAAA,UACA,QAAA,CAAS;AAAA;AACX;AAAA;AAAA,GACJ;AAEJ;AC3YO,SAAS,kBAAA,CAAmB;AAAA,EACjC,GAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA,GAAS;AACX,CAAA,EAA+C;AAC7C,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAUO,2BAAS,KAAK,CAAA;AACtD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAUA,iBAAA,CAAA,QAAA,CAAuB,EAAE,CAAA;AACzD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAChCA,2BAAkC,IAAI,CAAA;AAC9C,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAUA,iBAAA,CAAA,QAAA,CAA2B,EAAE,CAAA;AAEzD,EAAA,MAAM,QAAA,GAAiBA,yBAAO,CAAC,CAAA;AAC/B,EAAA,MAAM,YAAA,GAAqBA,yBAAgC,IAAI,CAAA;AAE/D,EAAA,MAAM,WAAA,GAAoBA,yBAAO,EAAE,CAAA;AAEnC,EAAA,MAAM,YAAA,GAAqBA,iBAAA,CAAA,MAAA,iBAAO,IAAI,GAAA,EAAqB,CAAA;AAE3D,EAAA,MAAM,SAAA,GAAkBA,iBAAA,CAAA,MAAA,iBAAO,IAAI,GAAA,EAAqB,CAAA;AAExD,EAAA,MAAM,OAAA,GAAgBA,iBAAA,CAAA,WAAA;AAAA,IACpB,CAAC,KAAA,KAA6C;AAC5C,MAAA,MAAM,IAAA,GAAuB;AAAA,QAC3B,EAAA,EAAI,EAAE,QAAA,CAAS,OAAA;AAAA,QACf,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,QACb,GAAG;AAAA,OACL;AACA,MAAA,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,IAAA,EAAM,GAAG,IAAI,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,MAAM,CAAC,CAAA;AAAA,IACnD,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,QAAA,GAAW,IAAA,EAAM,IAAA,EAAM,IAAA,EAAK;AAClC,EAAA,MAAM,YAAY,IAAA,EAAM,KAAA;AAExB,EAAMA,4BAAU,MAAM;AACpB,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,QAAA,EAAU;AACrB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,QAAA,CAAS,SAAA;AAC3B,IAAA,YAAA,CAAa,OAAA,GAAU,SAAA;AACvB,IAAA,YAAA,CAAa,OAAA,uBAAc,GAAA,EAAI;AAC/B,IAAA,SAAA,CAAU,OAAA,uBAAc,GAAA,EAAI;AAC5B,IAAA,YAAA,CAAa,QAAA,CAAS,UAAU,KAAK,CAAA;AAIrC,IAAA,MAAM,WAAA,GAAc,CAAC,MAAA,EAAoB,MAAA,KAAoB;AAC3D,MAAA,OAAA,CAAQ;AAAA,QACN,IAAA,EAAM,KAAA;AAAA,QACN,MAAA,EAAQ,MAAA,KAAW,QAAA,GAAW,QAAA,GAAW,OAAA;AAAA,QACzC,MAAA,EAAQ,CAAA,gBAAA,EAAgB,MAAA,CAAO,UAAU,CAAA,MAAA;AAAA,OAC1C,CAAA;AAAA,IACH,CAAA;AACA,IAAA,GAAA,CAAI,EAAA,CAAG,UAAU,WAAW,CAAA;AAE5B,IAAA,MAAM,MAAA,GAAS,CAAC,QAAA,KAAsB;AACpC,MAAA,YAAA,CAAa,QAAQ,CAAA;AACrB,MAAA,OAAA,CAAQ;AAAA,QACN,IAAA,EAAM,MAAA;AAAA,QACN,MAAA,EAAQ,WAAW,oBAAA,GAAuB;AAAA,OAC3C,CAAA;AAAA,IACH,CAAA;AACA,IAAA,QAAA,CAAS,EAAA,CAAG,QAAQ,MAAM,CAAA;AAE1B,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAA+B;AAC/C,MAAA,IAAI,KAAA,EAAO,MAAA,KAAW,cAAA,EAAgB,YAAA,CAAa,KAAK,CAAA;AAAA,IAC1D,CAAA;AACA,IAAA,QAAA,CAAS,EAAA,CAAG,UAAU,QAAQ,CAAA;AAE9B,IAAA,MAAM,cAAc,MAAM;AACxB,MAAA,MAAM,SAAuB,EAAC;AAC9B,MAAA,MAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,MAAA,IAAI,QAAA,GAAoC,IAAA;AAExC,MAAA,SAAA,CAAU,SAAA,EAAU,CAAE,OAAA,CAAQ,CAAC,OAAO,QAAA,KAAa;AACjD,QAAA,IAAI,QAAA,KAAa,UAAU,QAAA,EAAU;AACrC,QAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,QAAA,IAAI,MAAM,IAAA,EAAM;AACd,UAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,CAAK,MAAM,KAAA,EAAO,IAAA,CAAK,OAAO,CAAA;AAClD,UAAA,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAU,IAAA,CAAK,IAAI,CAAA;AAAA,QACjC;AACA,QAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,QAAA,IACE,QAAA,IACA,SAAS,EAAA,IAAM,YAAA,CAAa,QAAQ,GAAA,CAAI,QAAQ,KAAK,CAAA,CAAA,EACrD;AACA,UAAA,YAAA,CAAa,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAU,QAAA,CAAS,EAAE,CAAA;AAC9C,UAAA,IAAI,CAAC,QAAA,IAAY,QAAA,CAAS,EAAA,GAAK,SAAS,EAAA,EAAI;AAC1C,YAAA,MAAM,WAAW,CAAC,CAAC,MAAM,IAAA,IAAQ,IAAA,CAAK,SAAS,WAAA,CAAY,OAAA;AAC3D,YAAA,QAAA,GAAW;AAAA,cACT,QAAQ,QAAA,CAAS,MAAA;AAAA,cACjB,EAAA,EAAI,QAAA,GAAW,sBAAA,GAAyB,IAAA,EAAM,IAAA;AAAA,cAC9C,IAAI,QAAA,CAAS;AAAA,aACf;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAED,MAAA,KAAA,MAAW,CAAC,QAAA,EAAU,IAAI,CAAA,IAAK,OAAA,EAAS;AACtC,QAAA,IAAI,CAAC,SAAA,CAAU,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,EAAG;AACpC,UAAA,OAAA,CAAQ;AAAA,YACN,IAAA,EAAM,WAAA;AAAA,YACN,MAAA,EAAQ,QAAA;AAAA,YACR,MAAA,EAAQ,GAAG,IAAI,CAAA,gBAAA;AAAA,WAChB,CAAA;AAAA,QACH;AAAA,MACF;AACA,MAAA,KAAA,MAAW,CAAC,QAAA,EAAU,IAAI,CAAA,IAAK,UAAU,OAAA,EAAS;AAChD,QAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC1B,UAAA,OAAA,CAAQ;AAAA,YACN,IAAA,EAAM,WAAA;AAAA,YACN,MAAA,EAAQ,QAAA;AAAA,YACR,MAAA,EAAQ,GAAG,IAAI,CAAA,cAAA;AAAA,WAChB,CAAA;AAAA,QACH;AAAA,MACF;AACA,MAAA,SAAA,CAAU,OAAA,GAAU,OAAA;AACpB,MAAA,QAAA,CAAS,MAAM,CAAA;AAEf,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,IAAA,GAAO,QAAA;AACb,QAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,QAAA,OAAA,CAAQ;AAAA,UACN,IAAA,EAAM,WAAA;AAAA,UACN,MAAA,EAAQ,QAAA;AAAA,UACR,MAAA,EAAQ,CAAA,EAAG,IAAA,CAAK,EAAA,IAAM,MAAM,WAAW,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,SAC9D,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AACA,IAAA,SAAA,CAAU,EAAA,CAAG,UAAU,WAAW,CAAA;AAElC,IAAA,OAAO,MAAM;AACX,MAAA,GAAA,CAAI,GAAA,CAAI,UAAU,WAAW,CAAA;AAC7B,MAAA,QAAA,CAAS,GAAA,CAAI,QAAQ,MAAM,CAAA;AAC3B,MAAA,QAAA,CAAS,GAAA,CAAI,UAAU,QAAQ,CAAA;AAC/B,MAAA,SAAA,CAAU,GAAA,CAAI,UAAU,WAAW,CAAA;AACnC,MAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,MAAA,YAAA,CAAa,OAAA,uBAAc,GAAA,EAAI;AAC/B,MAAA,SAAA,CAAU,OAAA,uBAAc,GAAA,EAAI;AAC5B,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,MAAA,MAAA,CAAO,EAAE,CAAA;AAAA,IACX,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,GAAA,EAAK,QAAA,EAAU,OAAO,CAAC,CAAA;AAK3B,EAAMA,4BAAU,MAAM;AACpB,IAAA,MAAM,YAAY,YAAA,CAAa,OAAA;AAC/B,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,IAAA,GAAO,QAAA,IAAY,CAAA,KAAA,EAAQ,SAAA,CAAU,QAAQ,CAAA,CAAA;AACnD,IAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,IAAA,SAAA,CAAU,mBAAmB,MAAA,EAAQ,EAAE,IAAA,EAAM,KAAA,EAAO,WAAW,CAAA;AAAA,EACjE,CAAA,EAAG,CAAC,QAAA,EAAU,QAAA,EAAU,SAAS,CAAC,CAAA;AAElC,EAAA,MAAM,eAAA,GAAwBA,iBAAA,CAAA,WAAA;AAAA,IAC5B,CAAC,MAAA,KAAqB;AACpB,MAAA,YAAA,CAAa,OAAA,EAAS,mBAAmB,UAAA,EAAY;AAAA,QACnD,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,QACb;AAAA,OACsB,CAAA;AACxB,MAAA,OAAA,CAAQ;AAAA,QACN,IAAA,EAAM,OAAA;AAAA,QACN,MAAA,EAAQ,OAAA;AAAA,QACR,MAAA,EAAQ,CAAA,OAAA,EAAU,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OACpC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,IAAA,GACJ,OAAO,QAAA,GACH;AAAA,IACE,IAAA,EAAM,QAAA,IAAY,QAAA,CAAS,QAAA,IAAY,MAAA;AAAA,IACvC,GAAA,EAAK,OAAO,QAAA,CAAS,GAAA;AAAA,IACrB,UAAU,GAAA,CAAI,QAAA;AAAA,IACd;AAAA,GACF,GACA,IAAA;AAEN,EAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM,gBAAgB,eAAA,EAAgB;AACxE","file":"chunk-QX6AAVDE.cjs","sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { WrapText, X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { AvatarGroup, type AvatarPresence } from '../AvatarGroup/AvatarGroup';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Another participant currently present in the room. */\nexport interface CollabPeer {\n /** Display name published through presence. */\n name: string;\n /** Optional presence color (cursor/avatar tint). */\n color?: string;\n /**\n * What the peer is doing. Peers without a mode count as editing; `viewing`\n * peers are left out of the \"… are editing\" summary.\n */\n mode?: AvatarPresence;\n /** Avatar image URL. */\n avatarUrl?: string;\n}\n\n/** Static identity of the open collaboration room, shown in the debug panel. */\nexport interface CollabRoomInfo {\n /** Room name on the sync server (e.g. `case/4`). */\n name: string;\n /** Transport URL the client connected to. */\n url?: string;\n /** This window's client id (stable per document), or null before connect. */\n clientId?: number | null;\n /** The acting application user id passed to the sync server. */\n userId?: string;\n}\n\n/** Category of a collaboration event in the debug log. */\nexport type CollabLogKind = 'doc' | 'awareness' | 'sync' | 'patch';\n\n/** A single entry in the collaboration debug log. */\nexport interface CollabLogEntry {\n /** Stable key for rendering. */\n id: number | string;\n /** Wall-clock time of the event (epoch ms). */\n at: number;\n /** Event category. */\n kind: CollabLogKind;\n /** Whether this window or a peer originated it. */\n origin?: 'local' | 'remote';\n /** Human-readable detail line. */\n detail: string;\n}\n\n/** Every user-facing string, so apps can translate the widget. */\nexport interface CollabStatusLabels {\n /** Trigger text once the initial sync completed. */\n live: string;\n /** Trigger text before the initial sync completes. */\n connecting: string;\n /** Summary of who else is editing, e.g. `Ann, Bo are editing`. */\n editing: (names: string[]) => string;\n /** Accessible name / tooltip of the trigger button. */\n triggerLabel: string;\n /** Heading of the room-occupants section. */\n peersTitle: (count: number) => string;\n /** Shown in the occupants section when nobody else is in the room. */\n alone: React.ReactNode;\n /** Accessible name of an occupant with a `mode`, e.g. `Ann is viewing`. */\n presence?: (name: string, mode: AvatarPresence) => string;\n /** Heading of the debug panel. */\n logTitle: (count: number) => string;\n /** Accessible name of the panel close button. */\n close: string;\n /** Accessible name of the toggle that unclips long values. */\n wrap: string;\n /** Shown when the log is empty. */\n empty: React.ReactNode;\n roomTerm: string;\n urlTerm: string;\n clientTerm: string;\n userTerm: string;\n /** Suffix appended to the client id once synced / while connecting. */\n clientSynced: string;\n clientConnecting: string;\n}\n\nexport const defaultCollabStatusLabels: CollabStatusLabels = {\n live: 'Live',\n connecting: 'Connecting…',\n editing: (names) =>\n `${names.join(', ')} ${names.length === 1 ? 'is' : 'are'} editing`,\n triggerLabel: 'Live-sync status — open the update log',\n peersTitle: (count) => `In the room (${count})`,\n alone: 'You are the only one here.',\n logTitle: (count) => `Update log (${count})`,\n close: 'Close update log',\n wrap: 'Wrap long values',\n empty: 'No updates yet.',\n roomTerm: 'Room',\n urlTerm: 'Socket',\n clientTerm: 'Client',\n userTerm: 'User',\n clientSynced: 'synced',\n clientConnecting: 'connecting',\n};\n\nexport interface CollabStatusProps {\n /** True once the room has completed its initial sync with the server. */\n connected: boolean;\n /** Other people in the room right now. */\n peers?: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log?: CollabLogEntry[];\n /** Identity of the open room, shown at the top of the panel. */\n room?: CollabRoomInfo | null;\n /** Set false to render a status-only chip with no debug panel. */\n showLog?: boolean;\n /**\n * Render the trigger as the bare connection dot, moving the status text into\n * its accessible name. For headers with no room for a full chip.\n */\n compact?: boolean;\n /**\n * An app-level condition worth the same glance as the connection state, e.g.\n * `\"Unsaved changes\"`. While set, the dot turns amber and the text joins the\n * trigger's accessible name and heads the panel.\n */\n attention?: React.ReactNode;\n /** Overrides for any user-facing string. */\n labels?: Partial<CollabStatusLabels>;\n /** Additional className for the trigger wrapper. */\n className?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** One occupant: a person, however many windows they have open. */\ninterface Occupant extends CollabPeer {\n label: string;\n}\n\n/**\n * Collapse multiple windows of the same person into `Name (N)`; they count as\n * viewing only if every window is explicitly viewing.\n */\nfunction peerLabels(peers: CollabPeer[]): Occupant[] {\n const seen = new Map<string, CollabPeer & { count: number }>();\n for (const p of peers) {\n const entry = seen.get(p.name);\n if (!entry) seen.set(p.name, { ...p, count: 1 });\n else {\n entry.count += 1;\n if (entry.mode === 'viewing' && p.mode !== 'viewing') entry.mode = p.mode;\n entry.avatarUrl ??= p.avatarUrl;\n }\n }\n return [...seen.values()].map(({ count, ...p }) => ({\n ...p,\n label: count > 1 ? `${p.name} (${count})` : p.name,\n }));\n}\n\nconst PANEL_OFFSET = 6;\nconst VIEWPORT_PADDING = 8;\n\n/**\n * Position the panel under the trigger, right-aligned to it but clamped to the\n * viewport on both axes (it flips above the trigger when it would overflow the\n * bottom). Returns null until the panel has been measured.\n */\nfunction useAnchoredPanel(\n open: boolean,\n anchorRef: React.RefObject<HTMLElement | null>,\n panelRef: React.RefObject<HTMLElement | null>\n) {\n const [pos, setPos] = React.useState<{ top: number; left: number } | null>(\n null\n );\n\n React.useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = anchorRef.current;\n const panel = panelRef.current;\n if (!anchor || !panel) return;\n const a = anchor.getBoundingClientRect();\n const { offsetWidth: width, offsetHeight: height } = panel;\n\n const maxLeft = window.innerWidth - width - VIEWPORT_PADDING;\n const left = Math.max(\n VIEWPORT_PADDING,\n Math.min(a.right - width, Math.max(VIEWPORT_PADDING, maxLeft))\n );\n\n let top = a.bottom + PANEL_OFFSET;\n if (top + height > window.innerHeight - VIEWPORT_PADDING) {\n top = Math.max(VIEWPORT_PADDING, a.top - height - PANEL_OFFSET);\n }\n\n setPos({ top, left });\n };\n\n // Measured after the (hidden) panel has been laid out.\n const raf = window.requestAnimationFrame(update);\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n return () => {\n window.cancelAnimationFrame(raf);\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [open, anchorRef, panelRef]);\n\n return pos;\n}\n\nconst KIND_TONE: Record<CollabLogKind, string> = {\n doc: 'text-muted-foreground',\n awareness: 'text-primary-600 dark:text-primary-400',\n sync: 'text-success-700 dark:text-success-400',\n patch: 'text-muted-foreground',\n};\n\n// =============================================================================\n// Component\n// =============================================================================\n\n/**\n * Live-collaboration status chip: a connection dot, a `Live` / `Connecting…`\n * label, a summary of who else is editing, and a click-to-open panel with the\n * room identity, who is in the room, and a rolling log of collaboration\n * events. Pass `compact` to shrink the trigger down to the dot alone, and\n * `attention` to let an app condition (\"Unsaved changes\") share that dot.\n *\n * Transport-agnostic — it renders whatever presence state you hand it. For a\n * Yjs (`y-websocket`) room, {@link useYjsCollabStatus} produces these props\n * directly:\n *\n * @example\n * ```tsx\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', 'case/4', doc),\n * [doc]\n * );\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n *\n * return <CollabStatus {...status} />;\n * ```\n */\nexport function CollabStatus({\n connected,\n peers = [],\n log = [],\n room = null,\n showLog = true,\n compact = false,\n attention = null,\n labels: labelOverrides,\n className,\n}: CollabStatusProps) {\n const labels = { ...defaultCollabStatusLabels, ...labelOverrides };\n const [open, setOpen] = React.useState(false);\n const [wrapped, setWrapped] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const pos = useAnchoredPanel(open && showLog, triggerRef, panelRef);\n const titleId = React.useId();\n\n // Escape closes and returns focus; a pointer outside dismisses.\n React.useEffect(() => {\n if (!open) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n setOpen(false);\n triggerRef.current?.focus();\n };\n const onPointerDown = (e: Event) => {\n const target = e.target as Node;\n if (panelRef.current?.contains(target)) return;\n if (triggerRef.current?.contains(target)) return;\n setOpen(false);\n };\n document.addEventListener('keydown', onKeyDown);\n document.addEventListener('pointerdown', onPointerDown);\n return () => {\n document.removeEventListener('keydown', onKeyDown);\n document.removeEventListener('pointerdown', onPointerDown);\n };\n }, [open]);\n\n const occupants = peerLabels(peers);\n const names = occupants\n .filter((p) => p.mode !== 'viewing')\n .map((p) => p.label);\n // Long values are clipped to one line; the panel's wrap toggle unclips them.\n const clip = wrapped ? 'break-all whitespace-pre-wrap' : 'truncate';\n const statusText = connected ? labels.live : labels.connecting;\n const clientLine = `${room?.clientId ?? '—'} · ${\n connected ? labels.clientSynced : labels.clientConnecting\n }`;\n // Compact triggers have no visible text, so the status and who is editing\n // have to reach assistive tech (and the tooltip) through the label.\n const triggerLabel = compact\n ? [\n labels.triggerLabel,\n statusText,\n attention,\n names.length > 0 && labels.editing(names),\n ]\n .filter(Boolean)\n .join(' — ')\n : labels.triggerLabel;\n\n const trigger = (\n <button\n type=\"button\"\n ref={triggerRef}\n className={cn(\n 'text-muted-foreground inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 text-xs',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none',\n showLog && 'hover:bg-muted cursor-pointer',\n className\n )}\n onClick={showLog ? () => setOpen((v) => !v) : undefined}\n disabled={!showLog}\n title={showLog ? triggerLabel : undefined}\n aria-expanded={showLog ? open : undefined}\n aria-label={showLog ? triggerLabel : undefined}\n data-slot=\"collab-status-trigger\"\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"collab-status-dot\"\n className={cn(\n 'h-2 w-2 shrink-0 rounded-full',\n !connected && 'bg-warning-500 animate-pulse',\n connected && attention && 'bg-warning-500',\n connected && !attention && 'bg-success-500'\n )}\n />\n {!compact && <span>{statusText}</span>}\n {!compact && attention && (\n <span className=\"text-warning-700 dark:text-warning-400 truncate\">\n · {attention}\n </span>\n )}\n {!compact && names.length > 0 && (\n <span className=\"truncate\">{`· ${labels.editing(names)}`}</span>\n )}\n </button>\n );\n\n if (!showLog) return trigger;\n\n return (\n <span\n className=\"relative inline-flex items-center\"\n data-slot=\"collab-status\"\n >\n {trigger}\n {open &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby={titleId}\n data-slot=\"collab-status-panel\"\n className={cn(\n 'bg-card text-card-foreground border-border fixed z-50 w-[26rem] max-w-[calc(100vw-1rem)]',\n 'rounded-lg border p-3 text-xs shadow-xl'\n )}\n style={{\n top: pos?.top ?? 0,\n left: pos?.left ?? 0,\n visibility: pos ? undefined : 'hidden',\n }}\n >\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <strong id={titleId} className=\"text-foreground text-sm\">\n {labels.logTitle(log.length)}\n </strong>\n <span className=\"flex items-center gap-0.5\">\n <button\n type=\"button\"\n className={cn(\n 'hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none',\n wrapped\n ? 'text-foreground bg-muted'\n : 'text-muted-foreground'\n )}\n onClick={() => setWrapped((v) => !v)}\n aria-pressed={wrapped}\n aria-label={labels.wrap}\n title={labels.wrap}\n data-slot=\"collab-status-wrap\"\n >\n <WrapText className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none\"\n onClick={() => {\n setOpen(false);\n triggerRef.current?.focus();\n }}\n aria-label={labels.close}\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </span>\n </div>\n\n {attention && (\n <p\n data-slot=\"collab-status-attention\"\n className=\"text-warning-700 dark:text-warning-400 mb-2\"\n >\n {attention}\n </p>\n )}\n\n {room && (\n <dl className=\"border-border text-muted-foreground mb-2 grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 border-b pb-2\">\n <dt className=\"opacity-70\">{labels.roomTerm}</dt>\n {/* The values are clipped, so hovering must reveal the rest. */}\n <dd className={clip} title={room.name}>\n {room.name}\n </dd>\n {room.url && (\n <>\n <dt className=\"opacity-70\">{labels.urlTerm}</dt>\n <dd className={clip} title={room.url}>\n {room.url}\n </dd>\n </>\n )}\n <dt className=\"opacity-70\">{labels.clientTerm}</dt>\n <dd className={clip} title={clientLine}>\n {clientLine}\n </dd>\n {room.userId && (\n <>\n <dt className=\"opacity-70\">{labels.userTerm}</dt>\n <dd className={clip} title={room.userId}>\n {room.userId}\n </dd>\n </>\n )}\n </dl>\n )}\n\n <section className=\"border-border mb-2 border-b pb-2\">\n <strong className=\"text-foreground mb-1 block\">\n {labels.peersTitle(peers.length)}\n </strong>\n {peers.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.alone}</p>\n ) : (\n <div data-slot=\"collab-status-peers\">\n <AvatarGroup\n size=\"sm\"\n max={8}\n className=\"flex-wrap ps-0.5\"\n labels={{\n list: labels.peersTitle(peers.length),\n ...(labels.presence && { presence: labels.presence }),\n }}\n items={occupants.map((peer) => ({\n id: peer.name,\n name: peer.name,\n label: peer.label,\n src: peer.avatarUrl,\n presence: peer.mode,\n color: peer.color,\n }))}\n />\n </div>\n )}\n </section>\n\n {log.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.empty}</p>\n ) : (\n <ul className=\"max-h-72 space-y-0.5 overflow-y-auto font-mono\">\n {log.map((e) => (\n <li\n key={e.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-2\"\n >\n <span className=\"text-muted-foreground opacity-70\">\n {new Date(e.at).toLocaleTimeString()}\n </span>\n <span\n className={cn(\n 'whitespace-nowrap',\n e.origin === 'remote'\n ? 'text-primary-600 dark:text-primary-400'\n : KIND_TONE[e.kind]\n )}\n >\n {e.kind}\n {e.origin ? `/${e.origin}` : ''}\n </span>\n <span\n className={cn('text-foreground', clip)}\n title={e.detail}\n >\n {e.detail}\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>,\n document.body\n )}\n </span>\n );\n}\n","import * as React from 'react';\nimport type {\n CollabLogEntry,\n CollabPeer,\n CollabRoomInfo,\n} from './CollabStatus';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// =============================================================================\n// Structural Yjs types\n// =============================================================================\n//\n// Declared structurally (as methods, so parameter bivariance applies) rather\n// than imported from `yjs` / `y-protocols`, so `@mieweb/ui` needs no Yjs\n// dependency at all. A real `Y.Doc`, `Awareness` and `WebsocketProvider`\n// satisfy these as-is.\n\n/** The subset of `Y.Doc` this hook observes. */\nexport interface YjsDocLike {\n clientID: number;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-protocols/awareness`.`Awareness` this hook uses. */\nexport interface YjsAwarenessLike {\n clientID: number;\n getStates(): Map<number, Record<string, any>>;\n setLocalStateField(field: string, value: unknown): void;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-websocket`.`WebsocketProvider` this hook uses. */\nexport interface YjsProviderLike {\n awareness: YjsAwarenessLike;\n /** True once the initial sync completed (y-websocket exposes this). */\n synced?: boolean;\n /** Room name, used as the default label in the debug panel. */\n roomname?: string;\n /** Server URL, used as the default label in the debug panel. */\n url?: string;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** Awareness payload published whenever this window makes a local edit. */\ninterface EditActivity {\n at: number;\n fields: string[];\n}\n\n/** A remote collaborator's edit that just changed the open document. */\nexport interface CollabRemoteEdit {\n /** Human-readable labels of the fields that changed. */\n fields: string[];\n /** Who made the change, when attributable from presence. */\n by?: string;\n /** Timestamp; a new value signals a fresh growl/toast. */\n at: number;\n}\n\nexport interface UseYjsCollabStatusOptions {\n /** The shared document. Pass null to keep the hook inert. */\n doc: YjsDocLike | null | undefined;\n /** The sync provider (e.g. `y-websocket`). Pass null to keep it inert. */\n provider: YjsProviderLike | null | undefined;\n /**\n * Presence identity published for this window. Defaults to\n * `User <clientID>` so windows are distinguishable without a login.\n */\n user?: { name?: string; color?: string };\n /** Room label for the debug panel. Defaults to `provider.roomname`. */\n roomName?: string;\n /** URL label for the debug panel. Defaults to `provider.url`. */\n url?: string;\n /** Application user id shown in the debug panel. */\n userId?: string;\n /** Maximum log entries kept in memory. Default 100. */\n logCap?: number;\n}\n\nexport interface YjsCollabStatus {\n /** True once the initial server sync completed. */\n connected: boolean;\n /** Other windows currently present in the room. */\n peers: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log: CollabLogEntry[];\n /** Room identity for the debug panel. */\n room: CollabRoomInfo | null;\n /** The most recent remote edit, or null. */\n lastRemoteEdit: CollabRemoteEdit | null;\n /**\n * Announce a local edit and the fields it touched, so other windows can\n * attribute it. Also records a `patch` log entry.\n */\n publishActivity: (fields: string[]) => void;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Bind {@link CollabStatus} to a Yjs room: tracks initial-sync state, publishes\n * this window's presence, tracks peers joining/leaving, attributes remote edits,\n * and keeps a capped log of document/awareness/sync events.\n *\n * The return value is spreadable straight into the component.\n *\n * @example\n * ```tsx\n * import * as Y from 'yjs';\n * import { WebsocketProvider } from 'y-websocket';\n * import { CollabStatus, useYjsCollabStatus } from '@mieweb/ui';\n *\n * function Header({ caseId }: { caseId: string }) {\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', `case/${caseId}`, doc),\n * [doc, caseId]\n * );\n * React.useEffect(() => () => provider.destroy(), [provider]);\n *\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n * return <CollabStatus {...status} />;\n * }\n * ```\n */\nexport function useYjsCollabStatus({\n doc,\n provider,\n user,\n roomName,\n url,\n userId,\n logCap = 100,\n}: UseYjsCollabStatusOptions): YjsCollabStatus {\n const [connected, setConnected] = React.useState(false);\n const [peers, setPeers] = React.useState<CollabPeer[]>([]);\n const [lastRemoteEdit, setLastRemoteEdit] =\n React.useState<CollabRemoteEdit | null>(null);\n const [log, setLog] = React.useState<CollabLogEntry[]>([]);\n\n const logIdRef = React.useRef(0);\n const awarenessRef = React.useRef<YjsAwarenessLike | null>(null);\n /** Effective display name published to presence. */\n const selfNameRef = React.useRef('');\n /** Last activity timestamp seen per remote client, to detect new edits. */\n const activitySeen = React.useRef(new Map<number, number>());\n /** Names present, keyed by clientID, to detect join/leave. */\n const peerNames = React.useRef(new Map<number, string>());\n\n const pushLog = React.useCallback(\n (entry: Omit<CollabLogEntry, 'id' | 'at'>) => {\n const full: CollabLogEntry = {\n id: ++logIdRef.current,\n at: Date.now(),\n ...entry,\n };\n setLog((prev) => [full, ...prev].slice(0, logCap));\n },\n [logCap]\n );\n\n const selfName = user?.name?.trim();\n const selfColor = user?.color;\n\n React.useEffect(() => {\n if (!doc || !provider) {\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n return;\n }\n\n const awareness = provider.awareness;\n awarenessRef.current = awareness;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(provider.synced ?? false);\n\n // Remote updates arrive with `origin === provider`; local transactions have\n // a null origin — that is what labels the log entry.\n const onDocUpdate = (update: Uint8Array, origin: unknown) => {\n pushLog({\n kind: 'doc',\n origin: origin === provider ? 'remote' : 'local',\n detail: `doc update · ${update.byteLength} bytes`,\n });\n };\n doc.on('update', onDocUpdate);\n\n const onSync = (isSynced: boolean) => {\n setConnected(isSynced);\n pushLog({\n kind: 'sync',\n detail: isSynced ? 'synced with server' : 'disconnected',\n });\n };\n provider.on('sync', onSync);\n\n const onStatus = (event: { status?: string }) => {\n if (event?.status === 'disconnected') setConnected(false);\n };\n provider.on('status', onStatus);\n\n const onAwareness = () => {\n const others: CollabPeer[] = [];\n const present = new Map<number, string>();\n let freshest: CollabRemoteEdit | null = null;\n\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === awareness.clientID) return; // skip this window\n const peer = state.user as CollabPeer | undefined;\n if (peer?.name) {\n others.push({ name: peer.name, color: peer.color });\n present.set(clientId, peer.name);\n }\n const activity = state.activity as EditActivity | undefined;\n if (\n activity &&\n activity.at > (activitySeen.current.get(clientId) ?? 0)\n ) {\n activitySeen.current.set(clientId, activity.at);\n if (!freshest || activity.at > freshest.at) {\n const sameUser = !!peer?.name && peer.name === selfNameRef.current;\n freshest = {\n fields: activity.fields,\n by: sameUser ? 'You (another window)' : peer?.name,\n at: activity.at,\n };\n }\n }\n });\n\n for (const [clientId, name] of present) {\n if (!peerNames.current.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} joined the room`,\n });\n }\n }\n for (const [clientId, name] of peerNames.current) {\n if (!present.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} left the room`,\n });\n }\n }\n peerNames.current = present;\n setPeers(others);\n\n if (freshest) {\n const edit = freshest as CollabRemoteEdit;\n setLastRemoteEdit(edit);\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${edit.by ?? 'peer'} edited ${edit.fields.join(', ')}`,\n });\n }\n };\n awareness.on('change', onAwareness);\n\n return () => {\n doc.off('update', onDocUpdate);\n provider.off('sync', onSync);\n provider.off('status', onStatus);\n awareness.off('change', onAwareness);\n awarenessRef.current = null;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n setLog([]);\n };\n }, [doc, provider, pushLog]);\n\n // Publish (and re-publish) this window's presence without tearing the room\n // down when the display name changes. Runs after the room effect above, which\n // is what populates `awarenessRef`.\n React.useEffect(() => {\n const awareness = awarenessRef.current;\n if (!awareness) return;\n const name = selfName || `User ${awareness.clientID}`;\n selfNameRef.current = name;\n awareness.setLocalStateField('user', { name, color: selfColor });\n }, [provider, selfName, selfColor]);\n\n const publishActivity = React.useCallback(\n (fields: string[]) => {\n awarenessRef.current?.setLocalStateField('activity', {\n at: Date.now(),\n fields,\n } satisfies EditActivity);\n pushLog({\n kind: 'patch',\n origin: 'local',\n detail: `edited ${fields.join(', ')}`,\n });\n },\n [pushLog]\n );\n\n const room: CollabRoomInfo | null =\n doc && provider\n ? {\n name: roomName ?? provider.roomname ?? 'room',\n url: url ?? provider.url,\n clientId: doc.clientID,\n userId,\n }\n : null;\n\n return { connected, peers, log, room, lastRemoteEdit, publishActivity };\n}\n"]}
|