@mieweb/ui 0.10.0-dev.16 → 0.10.0-dev.17
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-FX5YNGNE.cjs +17 -0
- package/dist/{CsvBlock-FVOKKWIY.cjs.map → CsvBlock-FX5YNGNE.cjs.map} +1 -1
- package/dist/CsvBlock-VLMG7GUO.js +8 -0
- package/dist/{CsvBlock-MXZO4W3N.js.map → CsvBlock-VLMG7GUO.js.map} +1 -1
- package/dist/HtmlPreviewBlock-5JE7L3GR.js +8 -0
- package/dist/{HtmlPreviewBlock-2UGW33SQ.js.map → HtmlPreviewBlock-5JE7L3GR.js.map} +1 -1
- package/dist/HtmlPreviewBlock-UO37JQ3K.cjs +17 -0
- package/dist/{HtmlPreviewBlock-CZKTQUCL.cjs.map → HtmlPreviewBlock-UO37JQ3K.cjs.map} +1 -1
- package/dist/MermaidBlock-3XHFBAMV.js +8 -0
- package/dist/{MermaidBlock-QXAEMOAA.js.map → MermaidBlock-3XHFBAMV.js.map} +1 -1
- package/dist/MermaidBlock-RZ75RPZA.cjs +17 -0
- package/dist/{MermaidBlock-NLDOJZUJ.cjs.map → MermaidBlock-RZ75RPZA.cjs.map} +1 -1
- package/dist/SurveyBlock-MUVJ3JUI.js +8 -0
- package/dist/{SurveyBlock-M5BEFZGT.js.map → SurveyBlock-MUVJ3JUI.js.map} +1 -1
- package/dist/SurveyBlock-VH47YXZC.cjs +17 -0
- package/dist/{SurveyBlock-GSHYZMTW.cjs.map → SurveyBlock-VH47YXZC.cjs.map} +1 -1
- package/dist/{chunk-77PNQILS.js → chunk-2BARVD4C.js} +3 -3
- package/dist/{chunk-77PNQILS.js.map → chunk-2BARVD4C.js.map} +1 -1
- package/dist/{chunk-IUQMOBFB.cjs → chunk-3KPDQG5O.cjs} +5 -5
- package/dist/{chunk-IUQMOBFB.cjs.map → chunk-3KPDQG5O.cjs.map} +1 -1
- package/dist/{chunk-OWLWABAS.js → chunk-4HC2IBOX.js} +3 -3
- package/dist/{chunk-OWLWABAS.js.map → chunk-4HC2IBOX.js.map} +1 -1
- package/dist/{chunk-R5AFQWR5.js → chunk-673GMFA6.js} +3 -3
- package/dist/{chunk-R5AFQWR5.js.map → chunk-673GMFA6.js.map} +1 -1
- package/dist/{chunk-UV4IJNSN.js → chunk-7YO7DNUV.js} +3 -3
- package/dist/{chunk-UV4IJNSN.js.map → chunk-7YO7DNUV.js.map} +1 -1
- package/dist/{chunk-XU2E7MTG.js → chunk-DSB4DKWG.js} +7 -7
- package/dist/{chunk-XU2E7MTG.js.map → chunk-DSB4DKWG.js.map} +1 -1
- package/dist/{chunk-XFLEW7AT.cjs → chunk-DXEPYK3I.cjs} +8 -4
- package/dist/chunk-DXEPYK3I.cjs.map +1 -0
- package/dist/{chunk-IBCCFWD4.js → chunk-EK3BCET6.js} +7 -2
- package/dist/chunk-EK3BCET6.js.map +1 -0
- package/dist/{chunk-WN6A4QOF.js → chunk-FBLVPM2K.js} +3 -3
- package/dist/{chunk-WN6A4QOF.js.map → chunk-FBLVPM2K.js.map} +1 -1
- package/dist/{chunk-CATY3P2U.js → chunk-FIKO4WR6.js} +3 -3
- package/dist/{chunk-CATY3P2U.js.map → chunk-FIKO4WR6.js.map} +1 -1
- package/dist/{chunk-FDP6VS5G.js → chunk-FZURBQJ2.js} +3 -3
- package/dist/{chunk-FDP6VS5G.js.map → chunk-FZURBQJ2.js.map} +1 -1
- package/dist/{chunk-O5A4GTTG.cjs → chunk-GU5OS7JJ.cjs} +4 -4
- package/dist/{chunk-O5A4GTTG.cjs.map → chunk-GU5OS7JJ.cjs.map} +1 -1
- package/dist/{chunk-YEQLSYJO.cjs → chunk-GVBHDRC7.cjs} +5 -5
- package/dist/{chunk-YEQLSYJO.cjs.map → chunk-GVBHDRC7.cjs.map} +1 -1
- package/dist/{chunk-W5TPBCBM.js → chunk-GVLNXPJX.js} +4 -4
- package/dist/{chunk-W5TPBCBM.js.map → chunk-GVLNXPJX.js.map} +1 -1
- package/dist/{chunk-AXRRBEER.js → chunk-GVM6DTR5.js} +8 -4
- package/dist/chunk-GVM6DTR5.js.map +1 -0
- package/dist/{chunk-UKUKBUME.cjs → chunk-GYXUS65N.cjs} +5 -5
- package/dist/{chunk-UKUKBUME.cjs.map → chunk-GYXUS65N.cjs.map} +1 -1
- package/dist/{chunk-R47H3Y7J.js → chunk-H2IAMSHK.js} +3 -3
- package/dist/{chunk-R47H3Y7J.js.map → chunk-H2IAMSHK.js.map} +1 -1
- package/dist/{chunk-KM5OQQL5.cjs → chunk-HIZWOAWY.cjs} +8 -8
- package/dist/{chunk-KM5OQQL5.cjs.map → chunk-HIZWOAWY.cjs.map} +1 -1
- package/dist/{chunk-6GZKQR7P.cjs → chunk-I4LXSHKO.cjs} +4 -4
- package/dist/{chunk-6GZKQR7P.cjs.map → chunk-I4LXSHKO.cjs.map} +1 -1
- package/dist/{chunk-4LPGJ3ZO.js → chunk-IYWG72DM.js} +4 -4
- package/dist/{chunk-4LPGJ3ZO.js.map → chunk-IYWG72DM.js.map} +1 -1
- package/dist/{chunk-OZ2LP2VQ.cjs → chunk-JELTRRR5.cjs} +9 -9
- package/dist/{chunk-OZ2LP2VQ.cjs.map → chunk-JELTRRR5.cjs.map} +1 -1
- package/dist/{chunk-DXCATYEO.js → chunk-K2K2HP35.js} +3 -3
- package/dist/{chunk-DXCATYEO.js.map → chunk-K2K2HP35.js.map} +1 -1
- package/dist/{chunk-M5NYHH3Z.cjs → chunk-KDW6BD4O.cjs} +4 -4
- package/dist/{chunk-M5NYHH3Z.cjs.map → chunk-KDW6BD4O.cjs.map} +1 -1
- package/dist/{chunk-VNCIIXGO.js → chunk-KHSFJTEX.js} +3 -3
- package/dist/{chunk-VNCIIXGO.js.map → chunk-KHSFJTEX.js.map} +1 -1
- package/dist/{chunk-DF7K6DOJ.cjs → chunk-LFPJ3OUM.cjs} +5 -5
- package/dist/{chunk-DF7K6DOJ.cjs.map → chunk-LFPJ3OUM.cjs.map} +1 -1
- package/dist/{chunk-JX4UZEBZ.cjs → chunk-MQPG3KVK.cjs} +8 -8
- package/dist/{chunk-JX4UZEBZ.cjs.map → chunk-MQPG3KVK.cjs.map} +1 -1
- package/dist/{chunk-VLBUT2QM.cjs → chunk-N2CJJHHB.cjs} +4 -4
- package/dist/{chunk-VLBUT2QM.cjs.map → chunk-N2CJJHHB.cjs.map} +1 -1
- package/dist/{chunk-MB5KIIT4.cjs → chunk-N7C4OEP7.cjs} +6 -6
- package/dist/{chunk-MB5KIIT4.cjs.map → chunk-N7C4OEP7.cjs.map} +1 -1
- package/dist/{chunk-LGIQVSAE.cjs → chunk-NUQSQRG3.cjs} +16 -16
- package/dist/{chunk-LGIQVSAE.cjs.map → chunk-NUQSQRG3.cjs.map} +1 -1
- package/dist/{chunk-ETCHEURD.js → chunk-OYBJQBLO.js} +4 -4
- package/dist/{chunk-ETCHEURD.js.map → chunk-OYBJQBLO.js.map} +1 -1
- package/dist/{chunk-VPRKE2YU.cjs → chunk-P5CMZZRZ.cjs} +5 -5
- package/dist/{chunk-VPRKE2YU.cjs.map → chunk-P5CMZZRZ.cjs.map} +1 -1
- package/dist/{chunk-NEFBVO5W.cjs → chunk-QNDP6PE5.cjs} +7 -2
- package/dist/chunk-QNDP6PE5.cjs.map +1 -0
- package/dist/{chunk-WBBOH5QF.js → chunk-QOVJ6Z6R.js} +3 -3
- package/dist/{chunk-WBBOH5QF.js.map → chunk-QOVJ6Z6R.js.map} +1 -1
- package/dist/{chunk-4IETGCMD.js → chunk-R6KPWIGO.js} +4 -4
- package/dist/{chunk-4IETGCMD.js.map → chunk-R6KPWIGO.js.map} +1 -1
- package/dist/{chunk-GRV4MOEO.cjs → chunk-SVXWO37F.cjs} +26 -26
- package/dist/{chunk-GRV4MOEO.cjs.map → chunk-SVXWO37F.cjs.map} +1 -1
- package/dist/{chunk-T7U5HHGK.js → chunk-THLIL6PY.js} +3 -3
- package/dist/{chunk-T7U5HHGK.js.map → chunk-THLIL6PY.js.map} +1 -1
- package/dist/{chunk-PLDJU623.cjs → chunk-TTSSUOEV.cjs} +8 -8
- package/dist/{chunk-PLDJU623.cjs.map → chunk-TTSSUOEV.cjs.map} +1 -1
- package/dist/{chunk-E2B5BLAF.cjs → chunk-TYE5K5WV.cjs} +4 -4
- package/dist/{chunk-E2B5BLAF.cjs.map → chunk-TYE5K5WV.cjs.map} +1 -1
- package/dist/{chunk-YIWJTNR5.cjs → chunk-WCDJFMZO.cjs} +7 -7
- package/dist/{chunk-YIWJTNR5.cjs.map → chunk-WCDJFMZO.cjs.map} +1 -1
- package/dist/{chunk-EQXFDPXV.cjs → chunk-X5KAO35W.cjs} +14 -14
- package/dist/{chunk-EQXFDPXV.cjs.map → chunk-X5KAO35W.cjs.map} +1 -1
- package/dist/{chunk-2BGS7RFM.cjs → chunk-X6A27RGO.cjs} +4 -4
- package/dist/{chunk-2BGS7RFM.cjs.map → chunk-X6A27RGO.cjs.map} +1 -1
- package/dist/{chunk-7U5QYH54.js → chunk-XBTKZCZF.js} +3 -3
- package/dist/{chunk-7U5QYH54.js.map → chunk-XBTKZCZF.js.map} +1 -1
- package/dist/{chunk-TVSGJT6G.cjs → chunk-Y4E2WRUR.cjs} +6 -6
- package/dist/{chunk-TVSGJT6G.cjs.map → chunk-Y4E2WRUR.cjs.map} +1 -1
- package/dist/{chunk-UXI33QGR.js → chunk-YIV4Y4SK.js} +3 -3
- package/dist/{chunk-UXI33QGR.js.map → chunk-YIV4Y4SK.js.map} +1 -1
- package/dist/{chunk-VVZALGPI.js → chunk-YU55JD35.js} +3 -3
- package/dist/{chunk-VVZALGPI.js.map → chunk-YU55JD35.js.map} +1 -1
- package/dist/{chunk-WC25GQZD.js → chunk-ZYL4SNOR.js} +3 -3
- package/dist/{chunk-WC25GQZD.js.map → chunk-ZYL4SNOR.js.map} +1 -1
- package/dist/components/AlertDialog/index.cjs +4 -4
- package/dist/components/AlertDialog/index.js +3 -3
- package/dist/components/Button/index.cjs +4 -4
- package/dist/components/Button/index.js +2 -2
- package/dist/components/CalendarView/index.cjs +5 -5
- package/dist/components/CalendarView/index.js +3 -3
- package/dist/components/CustomizableDashboard/index.cjs +10 -10
- package/dist/components/CustomizableDashboard/index.js +3 -3
- package/dist/components/FloatingWindow/index.cjs +5 -5
- package/dist/components/FloatingWindow/index.js +3 -3
- package/dist/components/ListView/index.cjs +5 -5
- package/dist/components/ListView/index.js +3 -3
- package/dist/components/Markdown/index.cjs +17 -17
- package/dist/components/Markdown/index.js +8 -8
- package/dist/components/MediaEditor/index.cjs +9 -9
- package/dist/components/MediaEditor/index.js +4 -4
- package/dist/components/MediaPlayer/index.cjs +6 -6
- package/dist/components/MediaPlayer/index.js +3 -3
- package/dist/components/MegaMenu/index.cjs +6 -6
- package/dist/components/MegaMenu/index.js +3 -3
- package/dist/components/RadialExplorer/index.cjs +4 -4
- package/dist/components/RadialExplorer/index.js +3 -3
- package/dist/components/RichTextEditor/index.cjs +6 -6
- package/dist/components/RichTextEditor/index.js +3 -3
- package/dist/components/SectionSpyNav/index.cjs +4 -4
- package/dist/components/SectionSpyNav/index.js +3 -3
- package/dist/components/ViewSet/index.cjs +6 -6
- package/dist/components/ViewSet/index.js +5 -5
- package/dist/datavis.cjs +3 -3
- package/dist/datavis.js +2 -2
- package/dist/esheet.cjs +6 -6
- package/dist/esheet.js +3 -3
- package/dist/index.cjs +333 -333
- package/dist/index.js +28 -28
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/templates.cjs +24 -24
- package/dist/templates.js +2 -2
- package/package.json +1 -1
- package/dist/CsvBlock-FVOKKWIY.cjs +0 -17
- package/dist/CsvBlock-MXZO4W3N.js +0 -8
- package/dist/HtmlPreviewBlock-2UGW33SQ.js +0 -8
- package/dist/HtmlPreviewBlock-CZKTQUCL.cjs +0 -17
- package/dist/MermaidBlock-NLDOJZUJ.cjs +0 -17
- package/dist/MermaidBlock-QXAEMOAA.js +0 -8
- package/dist/SurveyBlock-GSHYZMTW.cjs +0 -17
- package/dist/SurveyBlock-M5BEFZGT.js +0 -8
- package/dist/chunk-AXRRBEER.js.map +0 -1
- package/dist/chunk-IBCCFWD4.js.map +0 -1
- package/dist/chunk-NEFBVO5W.cjs.map +0 -1
- package/dist/chunk-XFLEW7AT.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk7ZDPD5ZX_cjs = require('./chunk-7ZDPD5ZX.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkX6A27RGO_cjs = require('./chunk-X6A27RGO.cjs');
|
|
5
5
|
var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
|
|
@@ -58,9 +58,9 @@ function AlertDialog({
|
|
|
58
58
|
children
|
|
59
59
|
] }),
|
|
60
60
|
/* @__PURE__ */ jsxRuntime.jsxs(chunk7ZDPD5ZX_cjs.ModalFooter, { children: [
|
|
61
|
-
!hideCancel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
61
|
+
!hideCancel && /* @__PURE__ */ jsxRuntime.jsx(chunkX6A27RGO_cjs.Button, { variant: "secondary", onClick: handleCancel, children: cancelLabel }),
|
|
62
62
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63
|
-
|
|
63
|
+
chunkX6A27RGO_cjs.Button,
|
|
64
64
|
{
|
|
65
65
|
variant: variant === "destructive" ? "danger" : "primary",
|
|
66
66
|
onClick: handleAction,
|
|
@@ -76,5 +76,5 @@ function AlertDialog({
|
|
|
76
76
|
AlertDialog.displayName = "AlertDialog";
|
|
77
77
|
|
|
78
78
|
exports.AlertDialog = AlertDialog;
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
80
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-GVBHDRC7.cjs.map
|
|
80
|
+
//# sourceMappingURL=chunk-GVBHDRC7.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/AlertDialog/AlertDialog.tsx"],"names":["jsxs","Modal","ModalBody","jsx","cn","ModalFooter","Button"],"mappings":";;;;;;;AAqDA,SAAS,WAAA,CAAY;AAAA,EACnB,IAAA;AAAA,EACA,YAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc,QAAA;AAAA,EACd,WAAA,GAAc,UAAA;AAAA,EACd,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA,GAAU,SAAA;AAAA,EACV,cAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,QAAA,IAAW;AACX,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,QAAA,IAAW;AAAA,EACb,CAAA;AAEA,EAAA,uBACEA,eAAA;AAAA,IAACC,uBAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA;AAAA,MACA,IAAA,EAAK,IAAA;AAAA,MACL,mBAAA,EAAqB,KAAA;AAAA,MACrB,aAAA,EAAe,KAAA;AAAA,MACf,SAAA;AAAA,MACA,YAAA,EAAY,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,MAAA;AAAA,MAEhD,QAAA,EAAA;AAAA,wBAAAD,eAAA,CAACE,2BAAA,EAAA,EAAU,WAAU,WAAA,EACnB,QAAA,EAAA;AAAA,0BAAAC,cAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,oBAAA;AAAA,cACV,SAAA,EAAU,sCAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,UACC,WAAA,oBACCA,cAAA;AAAA,YAAC,GAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,0BAAA;AAAA,cACV,SAAA,EAAWC,qBAAG,oCAAoC,CAAA;AAAA,cAEjD,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,UAED;AAAA,SAAA,EACH,CAAA;AAAA,wCACCC,6BAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,CAAC,8BACAF,cAAA,CAACG,wBAAA,EAAA,EAAO,SAAQ,WAAA,EAAY,OAAA,EAAS,cAClC,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,0BAEFH,cAAA;AAAA,YAACG,wBAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAS,OAAA,KAAY,aAAA,GAAgB,QAAA,GAAW,SAAA;AAAA,cAChD,OAAA,EAAS,YAAA;AAAA,cACT,QAAA,EAAU,cAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA;AACH,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;AAEA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/AlertDialog/AlertDialog.tsx"],"names":["jsxs","Modal","ModalBody","jsx","cn","ModalFooter","Button"],"mappings":";;;;;;;AAqDA,SAAS,WAAA,CAAY;AAAA,EACnB,IAAA;AAAA,EACA,YAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc,QAAA;AAAA,EACd,WAAA,GAAc,UAAA;AAAA,EACd,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA,GAAU,SAAA;AAAA,EACV,cAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,QAAA,IAAW;AACX,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,QAAA,IAAW;AAAA,EACb,CAAA;AAEA,EAAA,uBACEA,eAAA;AAAA,IAACC,uBAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA;AAAA,MACA,IAAA,EAAK,IAAA;AAAA,MACL,mBAAA,EAAqB,KAAA;AAAA,MACrB,aAAA,EAAe,KAAA;AAAA,MACf,SAAA;AAAA,MACA,YAAA,EAAY,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,MAAA;AAAA,MAEhD,QAAA,EAAA;AAAA,wBAAAD,eAAA,CAACE,2BAAA,EAAA,EAAU,WAAU,WAAA,EACnB,QAAA,EAAA;AAAA,0BAAAC,cAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,oBAAA;AAAA,cACV,SAAA,EAAU,sCAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,UACC,WAAA,oBACCA,cAAA;AAAA,YAAC,GAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,0BAAA;AAAA,cACV,SAAA,EAAWC,qBAAG,oCAAoC,CAAA;AAAA,cAEjD,QAAA,EAAA;AAAA;AAAA,WACH;AAAA,UAED;AAAA,SAAA,EACH,CAAA;AAAA,wCACCC,6BAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,CAAC,8BACAF,cAAA,CAACG,wBAAA,EAAA,EAAO,SAAQ,WAAA,EAAY,OAAA,EAAS,cAClC,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,0BAEFH,cAAA;AAAA,YAACG,wBAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAS,OAAA,KAAY,aAAA,GAAgB,QAAA,GAAW,SAAA;AAAA,cAChD,OAAA,EAAS,YAAA;AAAA,cACT,QAAA,EAAU,cAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA;AACH,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;AAEA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-GVBHDRC7.cjs","sourcesContent":["import * as React from 'react';\nimport { cn } from '../../utils/cn';\nimport { Modal, ModalBody, ModalFooter, type ModalProps } from '../Modal';\nimport { Button } from '../Button';\n\nexport interface AlertDialogProps extends Pick<\n ModalProps,\n 'open' | 'onOpenChange'\n> {\n /** Dialog title */\n title: React.ReactNode;\n /** Optional descriptive body text */\n description?: React.ReactNode;\n /** Custom body content (rendered below the description) */\n children?: React.ReactNode;\n /** Label for the cancel button (default \"Cancel\") */\n cancelLabel?: React.ReactNode;\n /** Label for the confirm/action button (default \"Continue\") */\n actionLabel?: React.ReactNode;\n /** Called when the action button is clicked */\n onAction?: () => void;\n /** Called when the cancel button is clicked */\n onCancel?: () => void;\n /** Visual emphasis for the action button */\n variant?: 'default' | 'destructive';\n /** Disables the action button */\n actionDisabled?: boolean;\n /** Hides the cancel button */\n hideCancel?: boolean;\n /** Additional class name for the dialog content */\n className?: string;\n}\n\n/**\n * A modal dialog that interrupts the user with important content and expects\n * a response. Built on top of {@link Modal}.\n *\n * Unlike a regular Modal, it does not close on overlay click or Escape by\n * default — the user must explicitly choose an action.\n *\n * @example\n * ```tsx\n * <AlertDialog\n * open={open}\n * onOpenChange={setOpen}\n * title=\"Delete case?\"\n * description=\"This action cannot be undone.\"\n * variant=\"destructive\"\n * actionLabel=\"Delete\"\n * onAction={handleDelete}\n * />\n * ```\n */\nfunction AlertDialog({\n open,\n onOpenChange,\n title,\n description,\n children,\n cancelLabel = 'Cancel',\n actionLabel = 'Continue',\n onAction,\n onCancel,\n variant = 'default',\n actionDisabled,\n hideCancel,\n className,\n}: AlertDialogProps) {\n const handleCancel = () => {\n onCancel?.();\n onOpenChange(false);\n };\n\n const handleAction = () => {\n onAction?.();\n };\n\n return (\n <Modal\n open={open}\n onOpenChange={onOpenChange}\n size=\"sm\"\n closeOnOverlayClick={false}\n closeOnEscape={false}\n className={className}\n aria-label={typeof title === 'string' ? title : undefined}\n >\n <ModalBody className=\"px-6 py-5\">\n <h2\n data-slot=\"alert-dialog-title\"\n className=\"text-lg font-semibold tracking-tight\"\n >\n {title}\n </h2>\n {description && (\n <p\n data-slot=\"alert-dialog-description\"\n className={cn('text-muted-foreground mt-2 text-sm')}\n >\n {description}\n </p>\n )}\n {children}\n </ModalBody>\n <ModalFooter>\n {!hideCancel && (\n <Button variant=\"secondary\" onClick={handleCancel}>\n {cancelLabel}\n </Button>\n )}\n <Button\n variant={variant === 'destructive' ? 'danger' : 'primary'}\n onClick={handleAction}\n disabled={actionDisabled}\n >\n {actionLabel}\n </Button>\n </ModalFooter>\n </Modal>\n );\n}\n\nAlertDialog.displayName = 'AlertDialog';\n\nexport { AlertDialog };\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FenceBlock } from './chunk-
|
|
2
|
-
import { Button } from './chunk-
|
|
1
|
+
import { FenceBlock } from './chunk-QOVJ6Z6R.js';
|
|
2
|
+
import { Button } from './chunk-7YO7DNUV.js';
|
|
3
3
|
import { Code, Eye, Maximize2 } from 'lucide-react';
|
|
4
4
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
5
5
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
@@ -131,5 +131,5 @@ var HtmlPreviewBlock = ({
|
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
export { HtmlPreviewBlock };
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
135
|
-
//# sourceMappingURL=chunk-
|
|
134
|
+
//# sourceMappingURL=chunk-GVLNXPJX.js.map
|
|
135
|
+
//# sourceMappingURL=chunk-GVLNXPJX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Markdown/HtmlPreviewBlock.tsx"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/Markdown/HtmlPreviewBlock.tsx"],"names":[],"mappings":";;;;;;AAYA,SAAS,eAAe,IAAA,EAAuB;AAC7C,EAAA,OAAO,kBAAA,CAAmB,KAAK,IAAI,CAAA;AACrC;AAEA,SAAS,aAAa,IAAA,EAAsB;AAC1C,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA,MAAA,EAGD,IAAI,CAAA;AAAA,OAAA,CAAA;AAEZ;AAEO,IAAM,mBAAoD,CAAC;AAAA,EAChE,IAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AACpD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,KAAK,CAAA;AAC9C,EAAA,MAAM,SAAA,GAAY,OAA0B,IAAI,CAAA;AAChD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,GAAG,CAAA;AAEpD,EAAA,MAAM,SAAS,cAAA,CAAe,IAAI,CAAA,GAAI,IAAA,GAAO,aAAa,IAAI,CAAA;AAE9D,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,cAAc,KAAA,EAAgC;AAErD,MAAA,IAAI,MAAM,MAAA,KAAW,MAAA,IAAU,KAAA,CAAM,MAAA,KAAW,OAAO,QAAA,CAAS,MAAA;AAC9D,QAAA;AACF,MAAA,IAAI,KAAA,CAAM,MAAA,KAAW,SAAA,CAAU,OAAA,EAAS,aAAA,EAAe;AACvD,MAAA,IAAI,MAAM,IAAA,EAAM,IAAA,KAAS,yBAAyB,KAAA,CAAM,IAAA,EAAM,OAAO,EAAA,EAAI;AACvE,QAAA,eAAA,CAAgB,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,KAAK,MAAA,EAAQ,GAAG,CAAA,EAAG,GAAI,CAAC,CAAA;AAAA,MAClE;AAAA,IACF;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,aAAa,CAAA;AAChD,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,aAAa,CAAA;AAAA,EAClE,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AAEP,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,QAAA,EAAU;AACf,IAAA,SAAS,UAAU,CAAA,EAAkB;AACnC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU,WAAA,CAAY,KAAK,CAAA;AAAA,IAC3C;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA;AAAA,EAChE,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,MAAM,cAAA,CAAe,CAAC,MAAM,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA;AAErE,EAAA,MAAM,gCACJ,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,OAAA;AAAA,QACR,IAAA,EAAK,IAAA;AAAA,QACL,OAAA,EAAS,aAAA;AAAA,QACT,SAAA,EAAU,wBAAA;AAAA,QAET,QAAA,EAAA;AAAA,UAAA,WAAA,mBACC,GAAA,CAAC,QAAK,SAAA,EAAU,SAAA,EAAU,oBAE1B,GAAA,CAAC,GAAA,EAAA,EAAI,WAAU,SAAA,EAAU,CAAA;AAAA,UAE1B,cAAc,MAAA,GAAS;AAAA;AAAA;AAAA,KAC1B;AAAA,IACC,WAAA,oBACC,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,OAAA;AAAA,QACR,IAAA,EAAK,IAAA;AAAA,QACL,OAAA,EAAS,MAAM,WAAA,CAAY,IAAI,CAAA;AAAA,QAC/B,SAAA,EAAU,aAAA;AAAA,QACV,YAAA,EAAW,gBAAA;AAAA,QAEX,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA;AACjC,GAAA,EAEJ,CAAA;AAGF,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,MAAY,QAAA,EAAS,MAAA,EAAO,eACtC,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,UAAA,EACZ,QAAA,EAAA,WAAA,mBACC,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,SAAA;AAAA,QACL,MAAA,EAAQ,MAAA;AAAA,QAKR,OAAA,EAAQ,2BAAA;AAAA,QACR,cAAA,EAAe,aAAA;AAAA,QACf,SAAA,EAAU,iBAAA;AAAA,QACV,KAAA,EAAO,EAAE,MAAA,EAAQ,YAAA,EAAa;AAAA,QAC9B,KAAA,EAAM;AAAA;AAAA,KACR,mBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EACb,8BAAC,MAAA,EAAA,EAAM,QAAA,EAAA,IAAA,EAAK,CAAA,EACd,CAAA,EAEJ,CAAA,EACF,CAAA;AAAA,IAEC,QAAA,oBACC,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,iEAAA;AAAA,QACV,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,MAAA;AAAA,QACX,YAAA,EAAW,cAAA;AAAA,QAEX,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,YAAA,EAAW,eAAA;AAAA,cACX,SAAA,EAAU,2EAAA;AAAA,cACV,OAAA,EAAS,MAAM,WAAA,CAAY,KAAK;AAAA;AAAA,WAClC;AAAA,0BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8FAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iGAAA,EACb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,cAAA,EAAY,CAAA;AAAA,8BAClD,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAQ,OAAA;AAAA,kBACR,IAAA,EAAK,IAAA;AAAA,kBACL,OAAA,EAAS,MAAM,WAAA,CAAY,KAAK,CAAA;AAAA,kBACjC,QAAA,EAAA;AAAA;AAAA;AAED,aAAA,EACF,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,MAAA,EAAQ,MAAA;AAAA,gBACR,OAAA,EAAQ,2BAAA;AAAA,gBACR,cAAA,EAAe,aAAA;AAAA,gBACf,SAAA,EAAU,wBAAA;AAAA,gBACV,KAAA,EAAM;AAAA;AAAA;AACR,WAAA,EACF;AAAA;AAAA;AAAA;AACF,GAAA,EAEJ,CAAA;AAEJ","file":"chunk-GVLNXPJX.js","sourcesContent":["/** Sandboxed iframe preview for HTML code blocks. */\nimport { Code, Eye, Maximize2 } from 'lucide-react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Button } from '../Button';\nimport { FenceBlock } from './FenceBlock';\n\ninterface HtmlPreviewBlockProps {\n code: string;\n id: string;\n}\n\nfunction isFullDocument(html: string): boolean {\n return /<!DOCTYPE|<html/i.test(html);\n}\n\nfunction wrapFragment(html: string): string {\n return `<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><style>body{margin:0;padding:8px;font-family:system-ui,sans-serif;font-size:14px}</style></head>\n<body>${html}</body>\n</html>`;\n}\n\nexport const HtmlPreviewBlock: React.FC<HtmlPreviewBlockProps> = ({\n code,\n id,\n}) => {\n const [showPreview, setShowPreview] = useState(false);\n const [expanded, setExpanded] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const [iframeHeight, setIframeHeight] = useState(200);\n\n const srcdoc = isFullDocument(code) ? code : wrapFragment(code);\n\n useEffect(() => {\n function handleMessage(event: globalThis.MessageEvent) {\n // Sandboxed srcDoc iframes report origin \"null\"; validate source to prevent spoofing.\n if (event.origin !== 'null' && event.origin !== window.location.origin)\n return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n if (event.data?.type === 'HTML_PREVIEW_RESIZE' && event.data?.id === id) {\n setIframeHeight(Math.min(Math.max(event.data.height, 200), 4000));\n }\n }\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [id]);\n\n useEffect(() => {\n if (!expanded) return;\n function handleKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setExpanded(false);\n }\n document.addEventListener('keydown', handleKey);\n return () => document.removeEventListener('keydown', handleKey);\n }, [expanded]);\n\n const togglePreview = useCallback(() => setShowPreview((v) => !v), []);\n\n const headerActions = (\n <>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={togglePreview}\n className=\"h-7 gap-1 px-2 text-xs\"\n >\n {showPreview ? (\n <Code className=\"h-3 w-3\" />\n ) : (\n <Eye className=\"h-3 w-3\" />\n )}\n {showPreview ? 'Code' : 'Preview'}\n </Button>\n {showPreview && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded(true)}\n className=\"h-7 w-7 p-0\"\n aria-label=\"Expand preview\"\n >\n <Maximize2 className=\"h-3 w-3\" />\n </Button>\n )}\n </>\n );\n\n return (\n <>\n <FenceBlock code={code} language=\"html\" headerActions={headerActions}>\n <div className=\"relative\">\n {showPreview ? (\n <iframe\n ref={iframeRef}\n srcDoc={srcdoc}\n // `allow-scripts` lets previewed HTML run its own JS (charts, demos,\n // and the optional resize-postMessage handshake). It is intentionally\n // NOT paired with `allow-same-origin`, so the content runs in an\n // opaque (null) origin with no access to this page, cookies, or storage.\n sandbox=\"allow-scripts allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"w-full border-0\"\n style={{ height: iframeHeight }}\n title=\"HTML Preview\"\n />\n ) : (\n <pre className=\"overflow-x-auto p-3 text-sm\">\n <code>{code}</code>\n </pre>\n )}\n </div>\n </FenceBlock>\n\n {expanded && (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"HTML Preview\"\n >\n <button\n type=\"button\"\n aria-label=\"Close preview\"\n className=\"absolute inset-0 h-full w-full cursor-default border-0 bg-transparent p-0\"\n onClick={() => setExpanded(false)}\n />\n <div className=\"relative h-[90vh] w-[90vw] overflow-hidden rounded-lg bg-white shadow-xl dark:bg-neutral-900\">\n <div className=\"flex items-center justify-between border-b border-neutral-200 px-4 py-2 dark:border-neutral-700\">\n <span className=\"text-sm font-medium\">HTML Preview</span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpanded(false)}\n >\n Close\n </Button>\n </div>\n <iframe\n srcDoc={srcdoc}\n sandbox=\"allow-scripts allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full border-0\"\n title=\"HTML Preview (expanded)\"\n />\n </div>\n </div>\n )}\n </>\n );\n};\n"]}
|
|
@@ -40,8 +40,12 @@ var buttonVariants = cva(
|
|
|
40
40
|
"hover:bg-primary-50 hover:text-primary-900",
|
|
41
41
|
"active:bg-primary-100",
|
|
42
42
|
"dark:border-primary-400 dark:text-primary-400",
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// Lighten the label as the hover/active fill darkens: primary-400
|
|
44
|
+
// on primary-950 is only ~3.3:1 in the BlueHive palette (WCAG AA
|
|
45
|
+
// needs 4.5:1); primary-200/950 and primary-100/900 clear it in
|
|
46
|
+
// every brand palette. See issue #511.
|
|
47
|
+
"dark:hover:bg-primary-950 dark:hover:text-primary-200",
|
|
48
|
+
"dark:active:bg-primary-900 dark:active:text-primary-100"
|
|
45
49
|
],
|
|
46
50
|
danger: [
|
|
47
51
|
"bg-red-600 text-white",
|
|
@@ -82,5 +86,5 @@ var buttonVariants = cva(
|
|
|
82
86
|
);
|
|
83
87
|
|
|
84
88
|
export { buttonVariants };
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
89
|
+
//# sourceMappingURL=chunk-GVM6DTR5.js.map
|
|
90
|
+
//# sourceMappingURL=chunk-GVM6DTR5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Button/button-variants.ts"],"names":[],"mappings":";;;AAIO,IAAM,cAAA,GAAiB,GAAA;AAAA;AAAA,EAE5B;AAAA,IACE,+CAAA;AAAA,IACA,2BAAA;AAAA,IACA,2CAAA;AAAA,IACA,qGAAA;AAAA,IACA,kDAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS;AAAA,UACP,2BAAA;AAAA,UACA,sBAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,SAAA,EAAW;AAAA,UACT,iCAAA;AAAA,UACA,sBAAA;AAAA,UACA,uBAAA;AAAA,UACA,2CAAA;AAAA,UACA,2BAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,KAAA,EAAO;AAAA,UACL,iCAAA;AAAA,UACA,sBAAA;AAAA,UACA,uBAAA;AAAA,UACA,uBAAA;AAAA,UACA,2BAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,OAAA,EAAS;AAAA,UACP,6DAAA;AAAA,UACA,4CAAA;AAAA,UACA,uBAAA;AAAA,UACA,+CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAKA,uDAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,MAAA,EAAQ;AAAA,UACN,uBAAA;AAAA,UACA,kBAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,IAAA,EAAM;AAAA,UACJ,qCAAA;AAAA,UACA,wCAAA;AAAA,UACA,yBAAA;AAAA,UACA;AAAA;AACF,OACF;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,6BAAA;AAAA,QACJ,EAAA,EAAI,gCAAA;AAAA,QACJ,EAAA,EAAI,8BAAA;AAAA,QACJ,IAAA,EAAM;AAAA,OACR;AAAA,MACA,SAAA,EAAW;AAAA,QACT,IAAA,EAAM,QAAA;AAAA,QACN,KAAA,EAAO;AAAA,OACT;AAAA;AAAA,MAEA,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,EAAA;AAAA,QACN,KAAA,EAAO,qCAAA;AAAA,QACP,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM,IAAA;AAAA,MACN,SAAA,EAAW,KAAA;AAAA,MACX,MAAA,EAAQ;AAAA;AACV;AAEJ","file":"chunk-GVM6DTR5.js","sourcesContent":["import { cva } from 'class-variance-authority';\n\n// Kept apart from Button.tsx so hook-free consumers (the Templates tier) can\n// style anchors without importing the Button component module.\nexport const buttonVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2',\n 'min-w-0 whitespace-nowrap',\n 'font-semibold transition-all duration-200',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'active:scale-[0.98]',\n ],\n {\n variants: {\n variant: {\n primary: [\n 'bg-primary-800 text-white',\n 'hover:bg-primary-900',\n 'active:bg-primary-950',\n ],\n secondary: [\n 'bg-neutral-200 text-neutral-900',\n 'hover:bg-neutral-300',\n 'active:bg-neutral-400',\n 'dark:bg-neutral-700 dark:text-neutral-100',\n 'dark:hover:bg-neutral-600',\n 'dark:active:bg-neutral-500',\n ],\n ghost: [\n 'bg-transparent text-neutral-600',\n 'hover:bg-neutral-100',\n 'active:bg-neutral-200',\n 'dark:text-neutral-400',\n 'dark:hover:bg-neutral-800',\n 'dark:active:bg-neutral-700',\n ],\n outline: [\n 'border-2 border-primary-800 text-primary-800 bg-transparent',\n 'hover:bg-primary-50 hover:text-primary-900',\n 'active:bg-primary-100',\n 'dark:border-primary-400 dark:text-primary-400',\n // Lighten the label as the hover/active fill darkens: primary-400\n // on primary-950 is only ~3.3:1 in the BlueHive palette (WCAG AA\n // needs 4.5:1); primary-200/950 and primary-100/900 clear it in\n // every brand palette. See issue #511.\n 'dark:hover:bg-primary-950 dark:hover:text-primary-200',\n 'dark:active:bg-primary-900 dark:active:text-primary-100',\n ],\n danger: [\n 'bg-red-600 text-white',\n 'hover:bg-red-700',\n 'active:bg-red-800',\n ],\n link: [\n 'text-primary-800 underline-offset-4',\n 'hover:underline hover:text-primary-900',\n 'active:text-primary-950',\n 'dark:text-primary-400',\n ],\n },\n size: {\n sm: 'h-8 px-3 text-sm rounded-md',\n md: 'h-10 px-4 text-base rounded-lg',\n lg: 'h-12 px-6 text-lg rounded-xl',\n icon: 'h-10 w-10 rounded-lg',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n /** Opt-in hover motion (see src/styles/effects.css). */\n effect: {\n none: '',\n sheen: 'mie-fx-sheen hover:-translate-y-0.5',\n orbit: 'mie-fx-orbit hover:-translate-y-0.5',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n fullWidth: false,\n effect: 'none',\n },\n }\n);\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkLFPJ3OUM_cjs = require('./chunk-LFPJ3OUM.cjs');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
@@ -85,11 +85,11 @@ var SurveyBlock = ({ code, id }) => {
|
|
|
85
85
|
};
|
|
86
86
|
}, [code]);
|
|
87
87
|
if (!parsed) {
|
|
88
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
88
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkLFPJ3OUM_cjs.FenceBlock, { code, language: "survey", supportsRawView: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-6 text-sm text-neutral-500", children: "Loading survey\u2026" }) });
|
|
89
89
|
}
|
|
90
90
|
const { fields, error } = parsed;
|
|
91
91
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
92
|
-
|
|
92
|
+
chunkLFPJ3OUM_cjs.FenceBlock,
|
|
93
93
|
{
|
|
94
94
|
code,
|
|
95
95
|
language: "survey",
|
|
@@ -194,5 +194,5 @@ var SurveyBlock = ({ code, id }) => {
|
|
|
194
194
|
};
|
|
195
195
|
|
|
196
196
|
exports.SurveyBlock = SurveyBlock;
|
|
197
|
-
//# sourceMappingURL=chunk-
|
|
198
|
-
//# sourceMappingURL=chunk-
|
|
197
|
+
//# sourceMappingURL=chunk-GYXUS65N.cjs.map
|
|
198
|
+
//# sourceMappingURL=chunk-GYXUS65N.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Markdown/SurveyBlock.tsx"],"names":["useState","useEffect","jsx","FenceBlock","jsxs"],"mappings":"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","file":"chunk-UKUKBUME.cjs","sourcesContent":["/** Survey/questionnaire preview from JSON or YAML. Requires `js-yaml` for YAML input. */\nimport React, { useEffect, useState } from 'react';\n\nimport { FenceBlock } from './FenceBlock';\n\ninterface SurveyBlockProps {\n code: string;\n id: string;\n}\n\ninterface SurveyField {\n type: string;\n name: string;\n title?: string;\n label?: string;\n choices?: Array<string | { value: string; text: string }>;\n isRequired?: boolean;\n}\n\ninterface ParsedSurvey {\n fields: SurveyField[];\n error: string | null;\n}\n\ntype YamlLoadFn = (input: string) => unknown;\nlet yamlPromise: Promise<YamlLoadFn> | null = null;\nfunction loadYaml(): Promise<YamlLoadFn> {\n if (!yamlPromise) {\n yamlPromise = import(/* @vite-ignore */ 'js-yaml')\n .then((mod) => {\n const api =\n (mod as { default?: { load?: YamlLoadFn }; load?: YamlLoadFn })\n .default ?? mod;\n const load = (api as { load?: YamlLoadFn }).load;\n if (typeof load !== 'function')\n throw new Error('js-yaml load not found');\n return load;\n })\n .catch((err) => {\n yamlPromise = null;\n throw err;\n });\n }\n return yamlPromise;\n}\n\nfunction tryParseJson(\n code: string\n): { ok: true; data: unknown } | { ok: false } {\n try {\n return { ok: true, data: JSON.parse(code) };\n } catch {\n return { ok: false };\n }\n}\n\nfunction elementsToParsed(data: unknown): ParsedSurvey {\n if (!data || typeof data !== 'object') {\n return { fields: [], error: 'Invalid survey data format' };\n }\n const obj = data as Record<string, unknown>;\n\n let elements: unknown[] = [];\n if (Array.isArray(obj.pages)) {\n for (const page of obj.pages as Array<Record<string, unknown>>) {\n if (Array.isArray(page.elements)) {\n elements = elements.concat(page.elements);\n }\n }\n } else if (Array.isArray(obj.elements)) {\n elements = obj.elements;\n } else if (Array.isArray(obj.questions)) {\n elements = obj.questions;\n } else if (Array.isArray(obj.fields)) {\n elements = obj.fields;\n } else {\n return { fields: [], error: 'No survey questions found in data' };\n }\n\n return { fields: elements as SurveyField[], error: null };\n}\n\nexport const SurveyBlock: React.FC<SurveyBlockProps> = ({ code, id }) => {\n const [parsed, setParsed] = useState<ParsedSurvey | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n const jsonResult = tryParseJson(code);\n if (jsonResult.ok) {\n setParsed(elementsToParsed(jsonResult.data));\n return;\n }\n\n loadYaml()\n .then((load) => {\n try {\n const data = load(code);\n if (!cancelled) setParsed(elementsToParsed(data));\n } catch (err) {\n if (!cancelled)\n setParsed({\n fields: [],\n error: `Failed to parse survey data: ${(err as Error).message}`,\n });\n }\n })\n .catch(() => {\n if (!cancelled)\n setParsed({\n fields: [],\n error:\n 'Survey preview requires the `js-yaml` package for YAML input. Install it with `npm install js-yaml`.',\n });\n });\n return () => {\n cancelled = true;\n };\n }, [code]);\n\n if (!parsed) {\n return (\n <FenceBlock code={code} language=\"survey\" supportsRawView>\n <div className=\"flex items-center justify-center p-6 text-sm text-neutral-500\">\n Loading survey…\n </div>\n </FenceBlock>\n );\n }\n\n const { fields, error } = parsed;\n\n return (\n <FenceBlock\n code={code}\n language=\"survey\"\n supportsRawView\n error={error ?? undefined}\n >\n <div className=\"space-y-4 p-4\">\n <h4 className=\"text-sm font-medium text-neutral-700 dark:text-neutral-300\">\n Survey Preview\n </h4>\n {fields.map((field, i) => {\n const fieldId = `${id}-field-${field.name ?? i}`;\n return (\n <div key={field.name ?? i} className=\"space-y-1.5\">\n <label\n htmlFor={fieldId}\n className=\"block text-sm font-medium text-neutral-700 dark:text-neutral-300\"\n >\n {field.title ?? field.label ?? field.name}\n {field.isRequired && (\n <span className=\"ms-1 text-red-500\">*</span>\n )}\n </label>\n\n {(field.type === 'radiogroup' || field.type === 'radio') &&\n field.choices && (\n <div className=\"space-y-1\">\n {field.choices.map((choice, ci) => {\n const value =\n typeof choice === 'string' ? choice : choice.value;\n const text =\n typeof choice === 'string' ? choice : choice.text;\n return (\n <label\n key={ci}\n className=\"flex items-center gap-2 text-sm text-neutral-600 dark:text-neutral-400\"\n >\n <input\n type=\"radio\"\n name={`${id}-${field.name}`}\n value={value}\n disabled\n className=\"accent-primary-500\"\n />\n {text}\n </label>\n );\n })}\n </div>\n )}\n\n {(field.type === 'checkbox' || field.type === 'boolean') && (\n <input\n id={fieldId}\n type=\"checkbox\"\n disabled\n className=\"accent-primary-500\"\n />\n )}\n\n {(field.type === 'text' || field.type === 'comment') && (\n <input\n id={fieldId}\n type=\"text\"\n disabled\n placeholder={field.title ?? field.name}\n className=\"w-full rounded-md border border-neutral-300 bg-neutral-100 px-3 py-1.5 text-sm dark:border-neutral-600 dark:bg-neutral-800\"\n />\n )}\n\n {field.type === 'rating' && (\n <div\n role=\"img\"\n className=\"flex gap-1\"\n aria-label=\"Rating: 0 out of 5\"\n >\n {[1, 2, 3, 4, 5].map((n) => (\n <span\n key={n}\n aria-hidden=\"true\"\n className=\"text-lg text-neutral-500 dark:text-neutral-500\"\n >\n ★\n </span>\n ))}\n </div>\n )}\n\n {field.type === 'dropdown' && field.choices && (\n <select\n id={fieldId}\n name={fieldId}\n disabled\n className=\"w-full rounded-md border border-neutral-300 bg-neutral-100 px-3 py-1.5 text-sm dark:border-neutral-600 dark:bg-neutral-800\"\n >\n {field.choices.map((choice, ci) => {\n const value =\n typeof choice === 'string' ? choice : choice.value;\n const text =\n typeof choice === 'string' ? choice : choice.text;\n return (\n <option key={ci} value={value}>\n {text}\n </option>\n );\n })}\n </select>\n )}\n </div>\n );\n })}\n <p className=\"text-xs text-neutral-600 dark:text-neutral-400\">\n This is a preview. Interactive survey support coming soon.\n </p>\n </div>\n </FenceBlock>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/Markdown/SurveyBlock.tsx"],"names":["useState","useEffect","jsx","FenceBlock","jsxs"],"mappings":"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","file":"chunk-GYXUS65N.cjs","sourcesContent":["/** Survey/questionnaire preview from JSON or YAML. Requires `js-yaml` for YAML input. */\nimport React, { useEffect, useState } from 'react';\n\nimport { FenceBlock } from './FenceBlock';\n\ninterface SurveyBlockProps {\n code: string;\n id: string;\n}\n\ninterface SurveyField {\n type: string;\n name: string;\n title?: string;\n label?: string;\n choices?: Array<string | { value: string; text: string }>;\n isRequired?: boolean;\n}\n\ninterface ParsedSurvey {\n fields: SurveyField[];\n error: string | null;\n}\n\ntype YamlLoadFn = (input: string) => unknown;\nlet yamlPromise: Promise<YamlLoadFn> | null = null;\nfunction loadYaml(): Promise<YamlLoadFn> {\n if (!yamlPromise) {\n yamlPromise = import(/* @vite-ignore */ 'js-yaml')\n .then((mod) => {\n const api =\n (mod as { default?: { load?: YamlLoadFn }; load?: YamlLoadFn })\n .default ?? mod;\n const load = (api as { load?: YamlLoadFn }).load;\n if (typeof load !== 'function')\n throw new Error('js-yaml load not found');\n return load;\n })\n .catch((err) => {\n yamlPromise = null;\n throw err;\n });\n }\n return yamlPromise;\n}\n\nfunction tryParseJson(\n code: string\n): { ok: true; data: unknown } | { ok: false } {\n try {\n return { ok: true, data: JSON.parse(code) };\n } catch {\n return { ok: false };\n }\n}\n\nfunction elementsToParsed(data: unknown): ParsedSurvey {\n if (!data || typeof data !== 'object') {\n return { fields: [], error: 'Invalid survey data format' };\n }\n const obj = data as Record<string, unknown>;\n\n let elements: unknown[] = [];\n if (Array.isArray(obj.pages)) {\n for (const page of obj.pages as Array<Record<string, unknown>>) {\n if (Array.isArray(page.elements)) {\n elements = elements.concat(page.elements);\n }\n }\n } else if (Array.isArray(obj.elements)) {\n elements = obj.elements;\n } else if (Array.isArray(obj.questions)) {\n elements = obj.questions;\n } else if (Array.isArray(obj.fields)) {\n elements = obj.fields;\n } else {\n return { fields: [], error: 'No survey questions found in data' };\n }\n\n return { fields: elements as SurveyField[], error: null };\n}\n\nexport const SurveyBlock: React.FC<SurveyBlockProps> = ({ code, id }) => {\n const [parsed, setParsed] = useState<ParsedSurvey | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n const jsonResult = tryParseJson(code);\n if (jsonResult.ok) {\n setParsed(elementsToParsed(jsonResult.data));\n return;\n }\n\n loadYaml()\n .then((load) => {\n try {\n const data = load(code);\n if (!cancelled) setParsed(elementsToParsed(data));\n } catch (err) {\n if (!cancelled)\n setParsed({\n fields: [],\n error: `Failed to parse survey data: ${(err as Error).message}`,\n });\n }\n })\n .catch(() => {\n if (!cancelled)\n setParsed({\n fields: [],\n error:\n 'Survey preview requires the `js-yaml` package for YAML input. Install it with `npm install js-yaml`.',\n });\n });\n return () => {\n cancelled = true;\n };\n }, [code]);\n\n if (!parsed) {\n return (\n <FenceBlock code={code} language=\"survey\" supportsRawView>\n <div className=\"flex items-center justify-center p-6 text-sm text-neutral-500\">\n Loading survey…\n </div>\n </FenceBlock>\n );\n }\n\n const { fields, error } = parsed;\n\n return (\n <FenceBlock\n code={code}\n language=\"survey\"\n supportsRawView\n error={error ?? undefined}\n >\n <div className=\"space-y-4 p-4\">\n <h4 className=\"text-sm font-medium text-neutral-700 dark:text-neutral-300\">\n Survey Preview\n </h4>\n {fields.map((field, i) => {\n const fieldId = `${id}-field-${field.name ?? i}`;\n return (\n <div key={field.name ?? i} className=\"space-y-1.5\">\n <label\n htmlFor={fieldId}\n className=\"block text-sm font-medium text-neutral-700 dark:text-neutral-300\"\n >\n {field.title ?? field.label ?? field.name}\n {field.isRequired && (\n <span className=\"ms-1 text-red-500\">*</span>\n )}\n </label>\n\n {(field.type === 'radiogroup' || field.type === 'radio') &&\n field.choices && (\n <div className=\"space-y-1\">\n {field.choices.map((choice, ci) => {\n const value =\n typeof choice === 'string' ? choice : choice.value;\n const text =\n typeof choice === 'string' ? choice : choice.text;\n return (\n <label\n key={ci}\n className=\"flex items-center gap-2 text-sm text-neutral-600 dark:text-neutral-400\"\n >\n <input\n type=\"radio\"\n name={`${id}-${field.name}`}\n value={value}\n disabled\n className=\"accent-primary-500\"\n />\n {text}\n </label>\n );\n })}\n </div>\n )}\n\n {(field.type === 'checkbox' || field.type === 'boolean') && (\n <input\n id={fieldId}\n type=\"checkbox\"\n disabled\n className=\"accent-primary-500\"\n />\n )}\n\n {(field.type === 'text' || field.type === 'comment') && (\n <input\n id={fieldId}\n type=\"text\"\n disabled\n placeholder={field.title ?? field.name}\n className=\"w-full rounded-md border border-neutral-300 bg-neutral-100 px-3 py-1.5 text-sm dark:border-neutral-600 dark:bg-neutral-800\"\n />\n )}\n\n {field.type === 'rating' && (\n <div\n role=\"img\"\n className=\"flex gap-1\"\n aria-label=\"Rating: 0 out of 5\"\n >\n {[1, 2, 3, 4, 5].map((n) => (\n <span\n key={n}\n aria-hidden=\"true\"\n className=\"text-lg text-neutral-500 dark:text-neutral-500\"\n >\n ★\n </span>\n ))}\n </div>\n )}\n\n {field.type === 'dropdown' && field.choices && (\n <select\n id={fieldId}\n name={fieldId}\n disabled\n className=\"w-full rounded-md border border-neutral-300 bg-neutral-100 px-3 py-1.5 text-sm dark:border-neutral-600 dark:bg-neutral-800\"\n >\n {field.choices.map((choice, ci) => {\n const value =\n typeof choice === 'string' ? choice : choice.value;\n const text =\n typeof choice === 'string' ? choice : choice.text;\n return (\n <option key={ci} value={value}>\n {text}\n </option>\n );\n })}\n </select>\n )}\n </div>\n );\n })}\n <p className=\"text-xs text-neutral-600 dark:text-neutral-400\">\n This is a preview. Interactive survey support coming soon.\n </p>\n </div>\n </FenceBlock>\n );\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Switch } from './chunk-AQ564XO7.js';
|
|
2
2
|
import { Sheet, SheetHeader, SheetTitle, SheetDescription, SheetBody, SheetFooter } from './chunk-LMBXJZLG.js';
|
|
3
|
-
import { Button } from './chunk-
|
|
3
|
+
import { Button } from './chunk-7YO7DNUV.js';
|
|
4
4
|
import { cn } from './chunk-TQONQSJO.js';
|
|
5
5
|
import * as React2 from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
@@ -704,5 +704,5 @@ var CustomizableDashboard = React2.forwardRef(function CustomizableDashboard2({
|
|
|
704
704
|
});
|
|
705
705
|
|
|
706
706
|
export { CustomizableDashboard, DashboardCustomizePanel, consolidateColumns, mergeColumnOrder, moveAcrossColumns, reorderOnDrop, requiredColumns };
|
|
707
|
-
//# sourceMappingURL=chunk-
|
|
708
|
-
//# sourceMappingURL=chunk-
|
|
707
|
+
//# sourceMappingURL=chunk-H2IAMSHK.js.map
|
|
708
|
+
//# sourceMappingURL=chunk-H2IAMSHK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CustomizableDashboard/DashboardCustomizePanel.tsx","../src/components/CustomizableDashboard/CustomizableDashboard.tsx"],"names":["React","jsx","jsxs","CustomizableDashboard"],"mappings":";;;;;;;;;;;;AA8EO,SAAS,uBAAA,CAAwB;AAAA,EACtC,IAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA,GAAQ,qBAAA;AAAA,EACR,WAAA,GAAc;AAChB,CAAA,EAAiC;AAC/B,EAAA,MAAM,MAAA,GAAeA,eAAQ,MAAM,IAAI,IAAI,SAAS,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAElE,EAAA,MAAM,MAAA,GAAeA,eAAQ,MAAM;AACjC,IAAA,MAAM,GAAA,uBAAU,GAAA,EAAgC;AAChD,IAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,MAAA,MAAM,GAAA,GAAM,EAAE,QAAA,IAAY,EAAA;AAC1B,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACxB,MAAA,IAAI,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAAA,WAChB,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,CAAC,CAAC,CAAC,CAAA;AAAA,IACvB;AACA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,MAAA,GAAS,MAAA,CAAO,IAAA;AAE7C,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAA;AAAA,MACA,IAAA,EAAK,KAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MAEZ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,cAAY,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BACnB,GAAA,CAAC,oBAAkB,QAAA,EAAA,WAAA,EAAY;AAAA,SAAA,EACjC,CAAA,EACF,CAAA;AAAA,wBACA,IAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,qBAAA,EACnB,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,GAAA,EAAA,EAAE,WAAU,2CAAA,EACV,QAAA,EAAA;AAAA,YAAA,YAAA;AAAA,YAAa,MAAA;AAAA,YAAK,OAAA,CAAQ,MAAA;AAAA,YAAO;AAAA,WAAA,EACpC,CAAA;AAAA,UACC,MAAA,CAAO,GAAA,CAAI,CAAC,CAAC,QAAA,EAAU,KAAK,CAAA,qBAC3B,IAAA,CAAC,KAAA,EAAA,EAAgC,SAAA,EAAU,qBAAA,EACxC,QAAA,EAAA;AAAA,YAAA,QAAA,oBACC,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,0EAAA,EACX,QAAA,EAAA,QAAA,EACH,CAAA;AAAA,gCAED,IAAA,EAAA,EAAG,SAAA,EAAU,qCACX,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,MAAA,KAAW;AACrB,cAAA,MAAM,SAAA,GAAY,CAAC,MAAA,CAAO,GAAA,CAAI,OAAO,EAAE,CAAA;AACvC,cAAA,uBACE,IAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBAEC,SAAA,EAAW,EAAA;AAAA,oBACT,+EAAA;AAAA,oBACA,YAAY,SAAA,GAAY;AAAA,mBAC1B;AAAA,kBAEC,QAAA,EAAA;AAAA,oBAAA,MAAA,CAAO,IAAA,oBACN,GAAA;AAAA,sBAAC,MAAA;AAAA,sBAAA;AAAA,wBACC,SAAA,EAAW,EAAA;AAAA,0BACT,UAAA;AAAA,0BACA,YACI,wCAAA,GACA;AAAA,yBACN;AAAA,wBAEC,QAAA,EAAA,MAAA,CAAO;AAAA;AAAA,qBACV;AAAA,oCAEF,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,8BAAA,EACd,QAAA,EAAA;AAAA,sCAAA,GAAA;AAAA,wBAAC,MAAA;AAAA,wBAAA;AAAA,0BACC,SAAA,EAAW,EAAA;AAAA,4BACT,8BAAA;AAAA,4BACA,YACI,iBAAA,GACA;AAAA,2BACN;AAAA,0BAEC,QAAA,EAAA,MAAA,CAAO;AAAA;AAAA,uBACV;AAAA,sBACC,OAAO,WAAA,oBACN,GAAA,CAAC,UAAK,SAAA,EAAU,wCAAA,EACb,iBAAO,WAAA,EACV;AAAA,qBAAA,EAEJ,CAAA;AAAA,oCACA,GAAA;AAAA,sBAAC,MAAA;AAAA,sBAAA;AAAA,wBACC,OAAA,EAAS,SAAA;AAAA,wBACT,iBAAiB,CAAC,OAAA,KAChB,cAAA,CAAe,MAAA,CAAO,IAAI,OAAO,CAAA;AAAA,wBAEnC,YAAA,EAAY,CAAA,KAAA,EAAQ,MAAA,CAAO,KAAK,CAAA;AAAA;AAAA;AAClC;AAAA,iBAAA;AAAA,gBAzCK,MAAA,CAAO;AAAA,eA0Cd;AAAA,YAEJ,CAAC,CAAA,EACH;AAAA,WAAA,EAAA,EAxDQ,QAAA,IAAY,SAyDtB,CACD;AAAA,SAAA,EACH,CAAA;AAAA,QACC,OAAA,wBACE,WAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,SAAA;AAAA,YACR,IAAA,EAAK,IAAA;AAAA,YACL,OAAA,EAAS,OAAA;AAAA,YACT,0BAAU,GAAA,CAAC,SAAA,EAAA,EAAU,aAAA,EAAY,MAAA,EAAO,WAAU,SAAA,EAAU,CAAA;AAAA,YAC7D,QAAA,EAAA;AAAA;AAAA,SAED,EACF;AAAA;AAAA;AAAA,GAEJ;AAEJ;ACrEA,IAAM,OAAA,GAAU,CAAC,UAAA,EAAY,UAAA,EAAY,UAAU,CAAA;AAEnD,IAAM,uBAAA,GAA0B,uCAAA;AAKhC,IAAM,qBAAA,GAAwB;AAAA,EAC5B,MAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,gBAAgB,IAAA,EAAsB;AAC7C,EAAA,OAAO,GAAG,IAAI,CAAA,cAAA,CAAA;AAChB;AAEA,SAAS,iBAAiB,IAAA,EAAsB;AAC9C,EAAA,OAAO,GAAG,IAAI,CAAA,iBAAA,CAAA;AAChB;AAEA,SAAS,iBAAiB,IAAA,EAAsB;AAC9C,EAAA,OAAO,GAAG,IAAI,CAAA,iBAAA,CAAA;AAChB;AAEA,SAAS,WAAW,IAAA,EAA2C;AAC7D,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,gBAAA,CAAiB,IAAI,CAAC,CAAA;AACvD,IAAA,MAAM,MAAA,GAAS,GAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,GAAgB,IAAA;AACpD,IAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GACvB,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,OAAO,CAAA,KAAM,QAAQ,CAAA,GAC1C,IAAA;AAAA,EACN,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,UAAA,CAAW,MAA0B,GAAA,EAAe;AAC3D,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,QAAQ,gBAAA,CAAiB,IAAI,GAAG,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA;AAAA,EAClE,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,SAAS,WAAW,IAAA,EAAkD;AACpE,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,gBAAA,CAAiB,IAAI,CAAC,CAAA;AACvD,IAAA,MAAM,GAAA,GAAM,GAAA,GAAM,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA;AAChC,IAAA,OAAO,QAAQ,CAAA,IAAK,GAAA,KAAQ,CAAA,IAAK,GAAA,KAAQ,IAAI,GAAA,GAAM,IAAA;AAAA,EACrD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,UAAA,CAAW,MAA0B,IAAA,EAAuB;AACnE,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,QAAQ,gBAAA,CAAiB,IAAI,CAAA,EAAG,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,EAC3D,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,SAAS,aAAa,KAAA,EAA0B;AAC9C,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GACtB,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,CAAA,KAAM,QAAQ,CAAA,GACtD,EAAC;AACP;AAEA,SAAS,UAAU,IAAA,EAAiD;AAClE,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,eAAA,CAAgB,IAAI,CAAC,CAAA;AACtD,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,OAAO;AAAA,MACL,YAAA,CAAa,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MACtB,YAAA,CAAa,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MACtB,YAAA,CAAa,MAAA,CAAO,CAAC,CAAC;AAAA,KACxB;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,SAAA,CAAU,MAA0B,KAAA,EAAuB;AAClE,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI;AACF,IAAA,MAAM,SAAmC,EAAC;AAC1C,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AACxB,MAAA,MAAA,CAAO,CAAC,CAAA,GAAI,GAAA;AAAA,IACd,CAAC,CAAA;AACD,IAAA,YAAA,CAAa,QAAQ,eAAA,CAAgB,IAAI,GAAG,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA,EACpE,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAOO,SAAS,gBAAA,CACd,SACA,KAAA,EACgB;AAChB,EAAA,MAAM,SAAS,IAAI,GAAA;AAAA,IACjB,CAAC,GAAG,OAAA,CAAQ,CAAC,CAAA,EAAG,GAAG,QAAQ,CAAC,CAAA,EAAG,GAAG,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,EAAE,EAAE;AAAA,GAC/D;AACA,EAAA,MAAM,SAAyB,CAAC,IAAI,EAAC,EAAG,EAAE,CAAA;AAC1C,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAE/B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,KAAA,MAAW,EAAA,IAAM,KAAA,GAAQ,CAAC,CAAA,IAAK,EAAC,EAAG;AACjC,MAAA,IAAI,MAAA,CAAO,IAAI,EAAE,CAAA,IAAK,CAAC,MAAA,CAAO,GAAA,CAAI,EAAE,CAAA,EAAG;AACrC,QAAA,MAAA,CAAO,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AACjB,QAAA,MAAA,CAAO,IAAI,EAAE,CAAA;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,CAAC,CAAA,EAAG;AAC7B,MAAA,IAAI,CAAC,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AACxB,QAAA,MAAA,CAAO,CAAC,CAAA,CAAE,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA;AACtB,QAAA,MAAA,CAAO,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,aAAa,OAAA,EAAqD;AACzE,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAyB;AACzC,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,IAAA,KAAA,MAAW,QAAQ,GAAA,EAAK,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,IAAI,IAAI,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,UAAA,CAAW,UAAsB,MAAA,EAAwB;AAChE,EAAA,OAAO,SAAS,SAAA,CAAU,CAAC,QAAQ,GAAA,CAAI,QAAA,CAAS,MAAM,CAAC,CAAA;AACzD;AAOO,SAAS,iBAAA,CACd,KAAA,EACA,QAAA,EACA,MAAA,EACgB;AAChB,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,MAAkC,CAAA;AACjE,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,KAAA,EAAO,QAAQ,CAAA;AAC5C,EAAA,IAAI,SAAA,KAAc,IAAI,OAAO,KAAA;AAE7B,EAAA,MAAM,YAAY,MAAA,KAAW,EAAA,GAAK,MAAA,GAAS,UAAA,CAAW,OAAO,MAAM,CAAA;AACnE,EAAA,IAAI,SAAA,KAAc,EAAA,IAAM,SAAA,KAAc,SAAA,EAAW,OAAO,KAAA;AAExD,EAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAA;AACxC,EAAA,IAAA,CAAK,SAAS,IAAI,IAAA,CAAK,SAAS,EAAE,MAAA,CAAO,CAAC,EAAA,KAAO,EAAA,KAAO,QAAQ,CAAA;AAChE,EAAA,MAAM,OAAA,GAAU,WAAW,EAAA,GAAK,EAAA,GAAK,KAAK,SAAS,CAAA,CAAE,QAAQ,MAAM,CAAA;AACnE,EAAA,IAAI,YAAY,EAAA,EAAI;AAClB,IAAA,IAAA,CAAK,SAAS,CAAA,CAAE,IAAA,CAAK,QAAQ,CAAA;AAAA,EAC/B,CAAA,MAAO;AACL,IAAA,IAAA,CAAK,SAAS,CAAA,CAAE,MAAA,CAAO,OAAA,EAAS,GAAG,QAAQ,CAAA;AAAA,EAC7C;AACA,EAAA,OAAO,IAAA;AACT;AAUO,SAAS,aAAA,CACd,KAAA,EACA,QAAA,EACA,MAAA,EACA,cAAA,EACgB;AAChB,EAAA,MAAM,cAAA,GACJ,OAAA,CAAQ,OAAA,CAAQ,MAAkC,CAAA,KAAM,EAAA;AAC1D,EAAA,IAAI,cAAA,IAAkB,MAAA,KAAW,QAAA,EAAU,OAAO,KAAA;AAElD,EAAA,MAAM,GAAA,GAAM,UAAA,CAAW,KAAA,EAAO,QAAQ,CAAA;AACtC,EAAA,IAAI,QAAQ,EAAA,IAAM,UAAA,CAAW,OAAO,MAAM,CAAA,KAAM,KAAK,OAAO,KAAA;AAE5D,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAG,CAAA,CAAE,QAAQ,QAAQ,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAG,CAAA,CAAE,QAAQ,MAAM,CAAA;AACxC,EAAA,IAAI,MAAA,KAAW,EAAA,IAAM,MAAA,KAAW,EAAA,EAAI,OAAO,KAAA;AAG3C,EAAA,IAAI,cAAA,IAAkB,MAAA,KAAW,MAAA,GAAS,CAAA,EAAG,OAAO,KAAA;AAEpD,EAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;AACpC,EAAA,IAAA,CAAK,GAAG,CAAA,GAAI,SAAA,CAAU,KAAK,GAAG,CAAA,EAAG,QAAQ,MAAM,CAAA;AAC/C,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,kBAAA,CACd,OACA,IAAA,EACgB;AAChB,EAAA,IAAI,QAAQ,CAAA,IAAK,eAAA,CAAgB,KAAK,CAAA,IAAK,MAAM,OAAO,KAAA;AACxD,EAAA,IAAI,IAAA,KAAS,GAAG,OAAO,CAAC,CAAC,GAAG,KAAA,CAAM,CAAC,CAAA,EAAG,GAAG,MAAM,CAAC,CAAA,EAAG,GAAG,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,EAAC,EAAG,EAAE,CAAA;AACvE,EAAA,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAA,CAAM,CAAC,GAAG,GAAG,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA;AACvD;AAMO,SAAS,gBAAgB,KAAA,EAAwC;AACtE,EAAA,OAAO,IAAA,CAAK,GAAA;AAAA,IACV,CAAA;AAAA,IACA,GAAG,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,KAAO,GAAA,CAAI,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,CAAE;AAAA,GACvD;AACF;AAMA,IAAM,kBAAA,GAAyC,CAAC,IAAA,KAAS;AACvD,EAAA,MAAM,EAAA,GAAK,cAAc,IAAI,CAAA;AAC7B,EAAA,IAAI,EAAA,CAAG,MAAA,GAAS,CAAA,EAAG,OAAO,EAAA;AAC1B,EAAA,MAAM,EAAA,GAAK,cAAc,IAAI,CAAA;AAC7B,EAAA,IAAI,EAAA,CAAG,MAAA,GAAS,CAAA,EAAG,OAAO,EAAA;AAC1B,EAAA,OAAO,iBAAiB,IAAI,CAAA;AAC9B,CAAA;AAMA,SAAS,eAAA,CAAgB;AAAA,EACvB,EAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,MAAM;AAAA,IACJ,UAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF,GAAI,WAAA,CAAY,EAAE,EAAA,EAAI,CAAA;AAEtB,EAAA,MAAM,UAAA,GAAmB,cAAuB,IAAI,CAAA;AACpD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAU,gBAA6B,IAAI,CAAA;AACvE,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAU,gBAAS,KAAK,CAAA;AAEpD,EAAA,MAAM,KAAA,GAA6B;AAAA,IACjC,SAAA,EAAW,GAAA,CAAI,SAAA,CAAU,QAAA,CAAS,SAAS,CAAA;AAAA,IAC3C,UAAA;AAAA,IACA,OAAA,EAAS,aAAa,GAAA,GAAM;AAAA,GAC9B;AAIA,EAAM,iBAAU,MAAM;AACpB,IAAA,MAAM,YAAY,UAAA,CAAW,OAAA;AAC7B,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,IAAA,MAAM,aAAa,MAAM;AACvB,MAAA,MAAM,MAAA,GAAS,SAAA,CAAU,aAAA,CAAc,cAAc,CAAA;AACrD,MAAA,IAAI,kBAAkB,WAAA,EAAa;AACjC,QAAA,MAAA,CAAO,SAAA,CAAU,GAAA,CAAI,GAAG,qBAAqB,CAAA;AAC7C,QAAA,WAAA,CAAY,MAAM,CAAA;AAClB,QAAA,QAAA,CAAS,UAAA,EAAW;AAAA,MACtB,CAAA,MAAO;AACL,QAAA,WAAA,CAAY,IAAI,CAAA;AAAA,MAClB;AACA,MAAA,WAAA,CAAY,IAAI,CAAA;AAAA,IAClB,CAAA;AAEA,IAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,CAAiB,MAAM;AAC1C,MAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,MAAA,KAAA,GAAQ,sBAAsB,UAAU,CAAA;AAAA,IAC1C,CAAC,CAAA;AAED,IAAA,UAAA,EAAW;AACX,IAAA,QAAA,CAAS,QAAQ,SAAA,EAAW,EAAE,WAAW,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAE9D,IAAA,OAAO,MAAM;AACX,MAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,MAAA,QAAA,CAAS,UAAA,EAAW;AAAA,IACtB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,MAAM,yBACJC,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,SAAA,EAAW,EAAA;AAAA,QACT,oHAAA;AAAA,QACA,mFAAA;AAAA,QACA,yFAAA;AAAA,QACA,kCAAA;AAAA,QACA,CAAC,QAAA,IAAY;AAAA,OACf;AAAA,MACA,YAAA,EAAW,iBAAA;AAAA,MACV,GAAG,UAAA;AAAA,MACH,GAAG,SAAA;AAAA,MAEJ,0BAAAA,GAAAA,CAAC,YAAA,EAAA,EAAa,aAAA,EAAY,MAAA,EAAO,WAAU,SAAA,EAAU;AAAA;AAAA,GACvD;AAGF,EAAA,uBACEC,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,QAAA,UAAA,CAAW,IAAI,CAAA;AACf,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MACvB,CAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA,EAAU,gCAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EAAkB,QAAA,EAAS,CAAA;AAAA,QACzC,WAAW,YAAA,CAAa,MAAA,EAAQ,QAAQ,CAAA,GAAI,WAAW,MAAA,GAAS;AAAA;AAAA;AAAA,GACnE;AAEJ;AAMA,SAAS,eAAA,CAAgB;AAAA,EACvB,EAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAOG;AACD,EAAA,MAAM,EAAE,UAAA,EAAY,MAAA,KAAW,YAAA,CAAa,EAAE,IAAI,CAAA;AAClD,EAAA,MAAM,MAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAEjC,EAAA,uBACEA,GAAAA,CAAC,eAAA,EAAA,EAAgB,OAAO,GAAA,EAAK,QAAA,EAAU,6BACrC,QAAA,kBAAAC,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,UAAA;AAAA,MACL,SAAA,EAAW,EAAA;AAAA,QACT,sCAAA;AAAA,QACA,OAAA,IAAW;AAAA,OACb;AAAA,MACA,IAAA,EAAK,OAAA;AAAA,MACL,YAAA,EAAY,CAAA,iBAAA,EAAoB,WAAA,GAAc,CAAC,CAAA,CAAA;AAAA,MAE9C,QAAA,EAAA;AAAA,QAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,qBACVD,GAAAA;AAAA,UAAC,eAAA;AAAA,UAAA;AAAA,YAEC,IAAI,IAAA,CAAK,EAAA;AAAA,YACT,cAAA;AAAA,YAEC,QAAA,EAAA,IAAA,CAAK;AAAA,WAAA;AAAA,UAJD,IAAA,CAAK;AAAA,SAMb,CAAA;AAAA,QACA,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,UAAA,oBACrBA,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,aAAA,EAAY,MAAA;AAAA,YACZ,SAAA,EAAW,EAAA;AAAA,cACT,uJAAA;AAAA,cACA,MAAA,IAAU;AAAA,aACZ;AAAA,YACD,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA,GAEJ,EACF,CAAA;AAEJ;AAqCO,IAAM,qBAAA,GAA8B,MAAA,CAAA,UAAA,CAGzC,SAASE,sBAAAA,CACT;AAAA,EACE,OAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,KAAA,EAAO,eAAA;AAAA,EACP,aAAA;AAAA,EACA,aAAA,GAAgB,CAAA;AAAA,EAChB,MAAA,EAAQ,gBAAA;AAAA,EACR,cAAA;AAAA,EACA,kBAAA,GAAqB,uBAAA;AAAA,EACrB,OAAA;AAAA,EACA,gBAAA;AAAA,EACA,SAAA,EAAW,gBAAA;AAAA,EACX,cAAA;AAAA,EACA,cAAA,GAAiB,WAAA;AAAA,EACjB;AACF,CAAA,EACA,GAAA,EACA;AACA,EAAA,MAAM,OAAA,GAAgB,eAAQ,MAAM,YAAA,CAAa,OAAO,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAIpE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAChC,gBAA0B,aAAa,CAAA;AAC/C,EAAA,MAAM,aAAa,gBAAA,IAAoB,cAAA;AAEvC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAU,MAAA,CAAA,QAAA;AAAA,IAAyB,MAC7D,kBAAA;AAAA,MACE,gBAAA,CAAiB,OAAA,EAAS,eAAA,IAAmB,YAAA,IAAgB,IAAI,CAAA;AAAA,MACjE,gBAAA,IAAoB;AAAA;AACtB,GACF;AACA,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAU,gBAAwB,IAAI,CAAA;AAElE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAU,MAAA,CAAA,QAAA;AAAA,IAChD,MAAM,oBAAoB;AAAC,GAC7B;AACA,EAAA,MAAM,aAAa,gBAAA,IAAoB,cAAA;AACvC,EAAA,MAAM,SAAA,GAAkB,eAAQ,MAAM,IAAI,IAAI,UAAU,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AACvE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAU,gBAAS,KAAK,CAAA;AAEtD,EAAA,MAAM,YAAA,GAAqB,cAAO,QAAQ,CAAA;AAC1C,EAAA,MAAM,aAAA,GAAsB,cAAO,UAAU,CAAA;AAC7C,EAAA,aAAA,CAAc,OAAA,GAAU,UAAA;AACxB,EAAA,MAAM,WAAA,GAAoB,cAAO,QAAQ,CAAA;AACzC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AACtB,EAAA,MAAM,UAAA,GAAmB,cAAO,OAAO,CAAA;AACvC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAA,MAAM,WAAA,GAAoB,cAAO,KAAK,CAAA;AAItC,EAAM,iBAAU,MAAM;AACpB,IAAA,IAAI,CAAC,UAAA,EAAY;AACjB,IAAA,IAAI,qBAAqB,MAAA,EAAW;AAClC,MAAA,MAAM,WAAA,GAAc,WAAW,UAAU,CAAA;AACzC,MAAA,IAAI,WAAA,KAAgB,IAAA,EAAM,iBAAA,CAAkB,WAAW,CAAA;AAAA,IACzD;AACA,IAAA,IAAI,oBAAoB,MAAA,EAAW;AACjC,MAAA,MAAM,UAAA,GAAa,UAAU,UAAU,CAAA;AACvC,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,WAAA,CAAY,gBAAA,CAAiB,UAAA,CAAW,OAAA,EAAS,UAAU,CAAC,CAAA;AAAA,MAC9D;AAAA,IACF;AACA,IAAA,IAAI,qBAAqB,MAAA,EAAW;AAClC,MAAA,MAAM,WAAA,GAAc,WAAW,UAAU,CAAA;AACzC,MAAA,IAAI,WAAA,oBAA+B,WAAW,CAAA;AAAA,IAChD;AAAA,EAEF,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAMf,EAAM,iBAAU,MAAM;AACpB,IAAA,IAAI,YAAY,OAAA,EAAS;AACzB,IAAA,WAAA,CAAY,CAAC,IAAA,KAAS;AACpB,MAAA,MAAM,IAAA,GAAO,kBAAA;AAAA,QACX,gBAAA,CAAiB,OAAA,EAAS,eAAA,IAAmB,IAAI,CAAA;AAAA,QACjD;AAAA,OACF;AACA,MAAA,OAAO,IAAA,CAAK,UAAU,IAAI,CAAA,KAAM,KAAK,SAAA,CAAU,IAAI,IAAI,IAAA,GAAO,IAAA;AAAA,IAChE,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,OAAA,EAAS,eAAA,EAAiB,UAAU,CAAC,CAAA;AAEzC,EAAA,MAAM,SAAA,GAAkB,MAAA,CAAA,WAAA;AAAA,IACtB,CAAC,IAAA,KAA0B;AACzB,MAAA,IAAI,gBAAA,KAAqB,MAAA,EAAW,iBAAA,CAAkB,IAAI,CAAA;AAC1D,MAAA,UAAA,CAAW,YAAY,IAAI,CAAA;AAC3B,MAAA,cAAA,GAAiB,IAAI,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,CAAC,gBAAA,EAAkB,UAAA,EAAY,cAAc;AAAA,GAC/C;AAEA,EAAA,MAAM,WAAA,GAAoB,MAAA,CAAA,WAAA;AAAA,IACxB,CAAC,IAAA,KAAyB;AACxB,MAAA,SAAA,CAAU,YAAY,IAAI,CAAA;AAC1B,MAAA,aAAA,GAAgB,IAAI,CAAA;AAIpB,MAAA,MAAM,QAAA,GAAW,gBAAgB,IAAI,CAAA;AACrC,MAAA,IAAI,QAAA,GAAW,cAAc,OAAA,EAAS;AACpC,QAAA,SAAA,CAAU,QAAQ,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAA,EAAY,aAAA,EAAe,SAAS;AAAA,GACvC;AAEA,EAAA,MAAM,kBAAA,GAA2B,MAAA,CAAA,WAAA;AAAA,IAC/B,CAAC,IAAA,KAA0B;AACzB,MAAA,SAAA,CAAU,IAAI,CAAA;AAGd,MAAA,MAAM,IAAA,GAAO,kBAAA,CAAmB,WAAA,CAAY,OAAA,EAAS,IAAI,CAAA;AACzD,MAAA,IAAI,IAAA,KAAS,YAAY,OAAA,EAAS;AAChC,QAAA,WAAA,CAAY,IAAI,CAAA;AAChB,QAAA,SAAA,CAAU,YAAY,IAAI,CAAA;AAC1B,QAAA,aAAA,GAAgB,IAAI,CAAA;AAAA,MACtB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAA,EAAW,UAAA,EAAY,aAAa;AAAA,GACvC;AAEA,EAAA,MAAM,OAAA,GAAU,UAAA;AAAA,IACd,SAAA,CAAU,eAAe,EAAE,oBAAA,EAAsB,EAAE,QAAA,EAAU,CAAA,IAAK,CAAA;AAAA,IAClE,SAAA,CAAU,cAAA,EAAgB,EAAE,gBAAA,EAAkB,6BAA6B;AAAA,GAC7E;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,GAAA,KACf,GAAA,CACG,OAAO,CAAC,EAAA,KAAO,CAAC,SAAA,CAAU,GAAA,CAAI,EAAE,CAAC,CAAA,CACjC,GAAA,CAAI,CAAC,EAAA,KAAO,OAAA,CAAQ,IAAI,EAAE,CAAC,CAAA,CAC3B,MAAA,CAAO,OAAO,CAAA;AAEnB,EAAA,MAAM,eAAA,GAAwB,MAAA,CAAA,WAAA;AAAA,IAC5B,CAAC,KAAA,KAA0B;AACzB,MAAA,YAAA,CAAa,OAAA,GAAU,QAAA;AACvB,MAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,MAAA,WAAA,CAAY,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,EAAE,CAAC,CAAA;AAAA,IACrC,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,MAAM,cAAA,GAAuB,MAAA,CAAA,WAAA,CAAY,CAAC,KAAA,KAAyB;AACjE,IAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,KAAA;AACzB,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,IAAA,GAAO,iBAAA;AAAA,MACX,WAAA,CAAY,OAAA;AAAA,MACZ,MAAA,CAAO,OAAO,EAAE,CAAA;AAAA,MAChB,MAAA,CAAO,KAAK,EAAE;AAAA,KAChB;AACA,IAAA,IAAI,IAAA,KAAS,WAAA,CAAY,OAAA,EAAS,WAAA,CAAY,IAAI,CAAA;AAAA,EACpD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAsB,MAAA,CAAA,WAAA;AAAA,IAC1B,CAAC,KAAA,KAAwB;AACvB,MAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,KAAA;AACzB,MAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,MAAA,WAAA,CAAY,IAAI,CAAA;AAEhB,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,WAAA,CAAY,aAAa,OAAO,CAAA;AAChC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,YAAA,GAAe,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAIrC,MAAA,MAAM,cAAA,GACJ,WAAW,YAAA,CAAa,OAAA,EAAS,YAAY,CAAA,KAC7C,UAAA,CAAW,WAAA,CAAY,OAAA,EAAS,YAAY,CAAA;AAC9C,MAAA,MAAM,IAAA,GAAO,aAAA;AAAA,QACX,WAAA,CAAY,OAAA;AAAA,QACZ,YAAA;AAAA,QACA,MAAA,CAAO,KAAK,EAAE,CAAA;AAAA,QACd;AAAA,OACF;AACA,MAAA,IAAI,IAAA,KAAS,WAAA,CAAY,OAAA,EAAS,WAAA,CAAY,IAAI,CAAA;AAGlD,MAAA,IAAI,IAAA,CAAK,UAAU,IAAI,CAAA,KAAM,KAAK,SAAA,CAAU,YAAA,CAAa,OAAO,CAAA,EAAG;AACjE,QAAA,WAAA,CAAY,IAAI,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,MAAM,gBAAA,GAAyB,mBAAY,MAAM;AAC/C,IAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,IAAA,WAAA,CAAY,IAAI,CAAA;AAChB,IAAA,WAAA,CAAY,aAAa,OAAO,CAAA;AAAA,EAClC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,SAAA,GAAkB,MAAA,CAAA,WAAA;AAAA,IACtB,CAAC,GAAA,KAAkB;AACjB,MAAA,IAAI,gBAAA,KAAqB,MAAA,EAAW,iBAAA,CAAkB,GAAG,CAAA;AACzD,MAAA,UAAA,CAAW,YAAY,GAAG,CAAA;AAC1B,MAAA,cAAA,GAAiB,GAAG,CAAA;AAAA,IACtB,CAAA;AAAA,IACA,CAAC,gBAAA,EAAkB,UAAA,EAAY,cAAc;AAAA,GAC/C;AAEA,EAAA,MAAM,kBAAA,GAA2B,MAAA,CAAA,WAAA;AAAA,IAC/B,CAAC,IAAY,OAAA,KAAqB;AAChC,MAAA,SAAA;AAAA,QACE,OAAA,GAAU,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,KAAM,EAAE,CAAA,GAAI,CAAC,GAAG,UAAA,EAAY,EAAE;AAAA,OACnE;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAY,SAAS;AAAA,GACxB;AAEA,EAAA,MAAM,WAAA,GAAoB,mBAAY,MAAM;AAC1C,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,UAAA,CAAW,eAAA,CAAgB,UAAU,CAAC,CAAA;AACnD,QAAA,YAAA,CAAa,UAAA,CAAW,gBAAA,CAAiB,UAAU,CAAC,CAAA;AACpD,QAAA,YAAA,CAAa,UAAA,CAAW,gBAAA,CAAiB,UAAU,CAAC,CAAA;AAAA,MACtD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,OAAA,EAAS,YAAA,IAAgB,IAAI,CAAA;AAC3D,IAAA,WAAA,CAAY,IAAI,CAAA;AAChB,IAAA,aAAA,GAAgB,IAAI,CAAA;AACpB,IAAA,IAAI,gBAAA,KAAqB,MAAA,EAAW,iBAAA,CAAkB,aAAa,CAAA;AACnE,IAAA,cAAA,GAAiB,aAAa,CAAA;AAC9B,IAAA,MAAM,MAAA,GAAS,oBAAoB,EAAC;AACpC,IAAA,IAAI,gBAAA,KAAqB,MAAA,EAAW,iBAAA,CAAkB,MAAM,CAAA;AAC5D,IAAA,cAAA,GAAiB,MAAM,CAAA;AAAA,EACzB,CAAA,EAAG;AAAA,IACD,UAAA;AAAA,IACA,OAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAA;AAAA,IACA,gBAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,IAAA,GAAyB;AAAA,IAC7B,OAAA,CAAQ,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,IACnB,OAAA,CAAQ,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,IACnB,OAAA,CAAQ,QAAA,CAAS,CAAC,CAAC;AAAA,GACrB;AAEA,EAAA,MAAM,cACJ,UAAA,KAAe,CAAA,GAAI,CAAC,IAAA,CAAK,CAAC,CAAC,CAAA,GAAI,UAAA,KAAe,CAAA,GAAI,CAAC,IAAA,CAAK,CAAC,GAAG,IAAA,CAAK,CAAC,CAAC,CAAA,GAAI,IAAA;AAEzE,EAAA,MAAM,OAAA,mBACJD,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,0CAAA,EACZ,QAAA,EAAA;AAAA,IAAA,KAAA,oBACCD,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,iDACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,IAED,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,oBAC3BA,GAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,SAAA;AAAA,QACR,IAAA,EAAK,IAAA;AAAA,QACL,OAAA,EAAS,MAAM,YAAA,CAAa,IAAI,CAAA;AAAA,QAChC,eAAA,EAAc,QAAA;AAAA,QACd,0BACEA,GAAAA,CAAC,qBAAkB,aAAA,EAAY,MAAA,EAAO,WAAU,SAAA,EAAU,CAAA;AAAA,QAG3D,QAAA,EAAA;AAAA;AAAA,KACH;AAAA,oBAEFA,GAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,2EAAA;AAAA,QACV,IAAA,EAAK,YAAA;AAAA,QACL,YAAA,EAAW,eAAA;AAAA,QAET,WAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAY,GAAA,CAAI,CAAC,IAAA,KAAS;AAClC,UAAA,MAAM,OAAO,IAAA,KAAS,CAAA,GAAI,QAAA,GAAW,IAAA,KAAS,IAAI,QAAA,GAAW,MAAA;AAC7D,UAAA,uBACEA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEC,IAAA,EAAK,QAAA;AAAA,cACL,SAAA,EAAW,EAAA;AAAA,gBACT,oEAAA;AAAA,gBACA,UAAA,KAAe,OACX,yCAAA,GACA;AAAA,eACN;AAAA,cACA,OAAA,EAAS,MAAM,kBAAA,CAAmB,IAAI,CAAA;AAAA,cACtC,IAAA,EAAK,OAAA;AAAA,cACL,gBAAc,UAAA,KAAe,IAAA;AAAA,cAC7B,YAAA,EAAY,GAAG,IAAI,CAAA,cAAA,CAAA;AAAA,cACnB,OAAO,CAAA,EAAG,IAAI,UAAU,IAAA,GAAO,CAAA,GAAI,MAAM,EAAE,CAAA,CAAA;AAAA,cAE3C,0BAAAA,GAAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,WAAU,SAAA,EAAU;AAAA,aAAA;AAAA,YAdxC;AAAA,WAeP;AAAA,QAEJ,CAAC;AAAA;AAAA;AACH,GAAA,EACF,CAAA;AAGF,EAAA,uBACEC,IAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,kBAAA;AAAA,MACA,WAAA,EAAa,eAAA;AAAA,MACb,UAAA,EAAY,cAAA;AAAA,MACZ,SAAA,EAAW,aAAA;AAAA,MACX,YAAA,EAAc,gBAAA;AAAA,MAEb,QAAA,EAAA;AAAA,QAAA,WAAA,GAAc,YAAA,CAAa,OAAA,EAAS,WAAW,CAAA,GAAI,OAAA;AAAA,wBACpDD,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA;AAAA,YACA,SAAA,EAAW,EAAA;AAAA,cACT,wBAAA;AAAA,cACA,eAAe,CAAA,IAAK,2CAAA;AAAA,cACpB,eAAe,CAAA,IAAK,4BAAA;AAAA,cACpB,eAAe,CAAA,IAAK,aAAA;AAAA,cACpB;AAAA,aACF;AAAA,YACA,IAAA,EAAK,QAAA;AAAA,YACL,cAAY,SAAA,IAAa,WAAA;AAAA,YAExB,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,EAAK,sBACrBA,GAAAA;AAAA,cAAC,eAAA;AAAA,cAAA;AAAA,gBAEC,EAAA,EAAI,QAAQ,CAAC,CAAA;AAAA,gBACb,KAAA,EAAO,GAAA;AAAA,gBACP,WAAA,EAAa,CAAA;AAAA,gBACb,cAAA,EAAgB,kBAAA;AAAA,gBAChB,SAAS,UAAA,KAAe,CAAA;AAAA,gBACxB,YAAY,QAAA,KAAa;AAAA,eAAA;AAAA,cANpB,QAAQ,CAAC;AAAA,aAQjB;AAAA;AAAA,SACH;AAAA,QACC,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,oBAC3BA,GAAAA;AAAA,UAAC,uBAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAM,SAAA;AAAA,YACN,YAAA,EAAc,YAAA;AAAA,YACd,OAAA;AAAA,YACA,SAAA,EAAW,UAAA;AAAA,YACX,cAAA,EAAgB,kBAAA;AAAA,YAChB,OAAA,EAAS;AAAA;AAAA;AACX;AAAA;AAAA,GAEJ;AAEJ,CAAC","file":"chunk-R47H3Y7J.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { RotateCcw } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Sheet,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetBody,\n SheetFooter,\n} from '../Sheet';\nimport { Switch } from '../Switch';\nimport { Button } from '../Button';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Catalog metadata for a widget a user can show or hide on a dashboard. */\nexport interface WidgetDefinition {\n /** Matches the portlet's `PortletItem.id`. */\n id: string;\n title: string;\n description?: string;\n /** Small leading icon, e.g. `<Activity className=\"h-4 w-4\" />`. */\n icon?: React.ReactNode;\n /** Widgets sharing a category are grouped under a heading. */\n category?: string;\n}\n\nexport interface DashboardCustomizePanelProps {\n /** Whether the panel is open. */\n open: boolean;\n /** Callback when the panel should open or close. */\n onOpenChange: (open: boolean) => void;\n /** The full widget catalog for this dashboard. */\n widgets: WidgetDefinition[];\n /** Ids of widgets currently hidden. */\n hiddenIds: string[];\n /** Called when a widget is shown (`visible: true`) or hidden. */\n onToggleWidget: (id: string, visible: boolean) => void;\n /** When provided, renders a \"Reset layout\" action in the footer. */\n onReset?: () => void;\n /** Panel heading (default \"Customize dashboard\"). */\n title?: string;\n /** Supporting copy under the heading. */\n description?: string;\n}\n\n// =============================================================================\n// DashboardCustomizePanel\n// =============================================================================\n\n/**\n * A slide-in panel listing a dashboard's widget catalog with show/hide\n * toggles, grouped by category, plus an optional layout reset.\n *\n * Used automatically by `CustomizableDashboard` when its `widgets` prop is\n * set, and exported standalone for hosts that render their own trigger or\n * persist visibility elsewhere.\n *\n * @example\n * ```tsx\n * <DashboardCustomizePanel\n * open={open}\n * onOpenChange={setOpen}\n * widgets={WIDGETS}\n * hiddenIds={hidden}\n * onToggleWidget={(id, visible) =>\n * setHidden((prev) =>\n * visible ? prev.filter((h) => h !== id) : [...prev, id]\n * )\n * }\n * />\n * ```\n */\nexport function DashboardCustomizePanel({\n open,\n onOpenChange,\n widgets,\n hiddenIds,\n onToggleWidget,\n onReset,\n title = 'Customize dashboard',\n description = 'Choose which widgets appear on this dashboard. Drag a widget by its handle to rearrange it.',\n}: DashboardCustomizePanelProps) {\n const hidden = React.useMemo(() => new Set(hiddenIds), [hiddenIds]);\n\n const groups = React.useMemo(() => {\n const map = new Map<string, WidgetDefinition[]>();\n for (const w of widgets) {\n const key = w.category ?? '';\n const list = map.get(key);\n if (list) list.push(w);\n else map.set(key, [w]);\n }\n return Array.from(map.entries());\n }, [widgets]);\n\n const visibleCount = widgets.length - hidden.size;\n\n return (\n <Sheet\n open={open}\n onOpenChange={onOpenChange}\n side=\"end\"\n aria-label={title}\n >\n <SheetHeader>\n <div className=\"flex flex-col gap-1.5\">\n <SheetTitle>{title}</SheetTitle>\n <SheetDescription>{description}</SheetDescription>\n </div>\n </SheetHeader>\n <SheetBody className=\"flex flex-col gap-5\">\n <p className=\"text-muted-foreground text-xs font-medium\">\n {visibleCount} of {widgets.length} widgets shown\n </p>\n {groups.map(([category, items]) => (\n <div key={category || 'general'} className=\"flex flex-col gap-1\">\n {category && (\n <h3 className=\"text-muted-foreground pb-1 text-xs font-semibold tracking-wide uppercase\">\n {category}\n </h3>\n )}\n <ul className=\"flex list-none flex-col gap-1 p-0\">\n {items.map((widget) => {\n const isVisible = !hidden.has(widget.id);\n return (\n <li\n key={widget.id}\n className={cn(\n 'border-border flex items-center gap-3 rounded-lg border p-3 transition-colors',\n isVisible ? 'bg-card' : 'bg-muted/50'\n )}\n >\n {widget.icon && (\n <span\n className={cn(\n 'shrink-0',\n isVisible\n ? 'text-primary-600 dark:text-primary-400'\n : 'text-muted-foreground'\n )}\n >\n {widget.icon}\n </span>\n )}\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span\n className={cn(\n 'truncate text-sm font-medium',\n isVisible\n ? 'text-foreground'\n : 'text-muted-foreground'\n )}\n >\n {widget.title}\n </span>\n {widget.description && (\n <span className=\"text-muted-foreground truncate text-xs\">\n {widget.description}\n </span>\n )}\n </span>\n <Switch\n checked={isVisible}\n onCheckedChange={(checked) =>\n onToggleWidget(widget.id, checked)\n }\n aria-label={`Show ${widget.title}`}\n />\n </li>\n );\n })}\n </ul>\n </div>\n ))}\n </SheetBody>\n {onReset && (\n <SheetFooter>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onReset}\n leftIcon={<RotateCcw aria-hidden=\"true\" className=\"h-4 w-4\" />}\n >\n Reset layout\n </Button>\n </SheetFooter>\n )}\n </Sheet>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n DndContext,\n closestCenter,\n pointerWithin,\n rectIntersection,\n PointerSensor,\n KeyboardSensor,\n useSensor,\n useSensors,\n useDroppable,\n type DragStartEvent,\n type DragOverEvent,\n type DragEndEvent,\n type CollisionDetection,\n} from '@dnd-kit/core';\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n useSortable,\n arrayMove,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport {\n GripVertical,\n Columns2,\n Columns3,\n Square,\n SlidersHorizontal,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Button } from '../Button';\nimport {\n DashboardCustomizePanel,\n type WidgetDefinition,\n} from './DashboardCustomizePanel';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** A dashboard item: a stable id plus the rendered content. */\nexport interface PortletItem {\n id: string;\n node: React.ReactNode;\n}\n\n/** Number of visible columns. */\nexport type DashboardLayout = 1 | 2 | 3;\n\n/** Portlet items grouped into three logical columns. */\nexport type DashboardColumns = [PortletItem[], PortletItem[], PortletItem[]];\n\n/** Portlet ids grouped into three logical columns. */\nexport type DashboardOrder = [string[], string[], string[]];\n\nexport interface CustomizableDashboardProps {\n /**\n * Portlets grouped into three columns. This is the default arrangement;\n * user reordering (persisted or controlled) takes precedence. Items later\n * removed from props disappear from saved layouts automatically, and new\n * items appear in their props column.\n */\n columns: DashboardColumns;\n /** Toolbar heading rendered before the layout toggle. */\n title?: string;\n /**\n * Base localStorage key used to persist column order and layout mode\n * (`{storageKey}-portlet-order` / `{storageKey}-dashboard-layout`).\n * Omit to disable built-in persistence (e.g. when using `order` /\n * `onOrderChange` with a server-side store). Distinct dashboards must\n * pass distinct keys.\n */\n storageKey?: string;\n /** Accessible label for the dashboard grid region. */\n ariaLabel?: string;\n /**\n * Optional DOM element to portal the toolbar (title + layout toggle)\n * into, e.g. a page header actions row. When omitted, the toolbar\n * renders inline above the grid.\n */\n toolbarSlot?: HTMLElement | null;\n /** Initial column order for uncontrolled usage with external persistence. */\n defaultOrder?: DashboardOrder;\n /** Controlled column order. Changes are reported via `onOrderChange`. */\n order?: DashboardOrder;\n /** Called with the full new order after a drop or layout normalization. */\n onOrderChange?: (order: DashboardOrder) => void;\n /** Initial layout mode for uncontrolled usage (default 3). */\n defaultLayout?: DashboardLayout;\n /** Controlled layout mode. Changes are reported via `onLayoutChange`. */\n layout?: DashboardLayout;\n /** Called when the user changes the column layout (or it auto-shrinks). */\n onLayoutChange?: (layout: DashboardLayout) => void;\n /**\n * CSS selector for the header element inside each portlet that receives\n * the drag handle. Defaults to the `DashboardWidget` header slot. When no\n * header matches, the handle floats over the portlet's top end corner.\n */\n dragHandleSelector?: string;\n /**\n * Widget catalog metadata. When provided, the toolbar gains a Customize\n * button opening a panel where users show/hide widgets and reset the\n * layout. Ids must match the portlet ids in `columns`.\n */\n widgets?: WidgetDefinition[];\n /** Initially hidden widget ids for uncontrolled usage. */\n defaultHiddenIds?: string[];\n /** Controlled hidden widget ids. Changes reported via `onHiddenChange`. */\n hiddenIds?: string[];\n /** Called with the full hidden-id list when visibility changes. */\n onHiddenChange?: (hiddenIds: string[]) => void;\n /** Label for the toolbar customize button (default \"Customize\"). */\n customizeLabel?: string;\n /** Additional class name for the grid element. */\n className?: string;\n}\n\n// =============================================================================\n// Internals\n// =============================================================================\n\nconst COL_IDS = ['column-0', 'column-1', 'column-2'] as const;\n\nconst DEFAULT_HANDLE_SELECTOR = '[data-slot=\"dashboard-widget-header\"]';\n\n// Applied to a discovered header so the appended handle lays out correctly:\n// an auto start margin on the 2nd child pushes trailing controls (and the\n// handle after them) to the end, even inside `justify-between` headers.\nconst HEADER_LAYOUT_CLASSES = [\n 'flex',\n 'flex-row',\n 'flex-nowrap',\n 'items-center',\n '[&>:nth-child(2)]:ms-auto',\n];\n\nfunction orderStorageKey(base: string): string {\n return `${base}-portlet-order`;\n}\n\nfunction layoutStorageKey(base: string): string {\n return `${base}-dashboard-layout`;\n}\n\nfunction hiddenStorageKey(base: string): string {\n return `${base}-dashboard-hidden`;\n}\n\nfunction loadHidden(base: string | undefined): string[] | null {\n if (!base) return null;\n try {\n const raw = localStorage.getItem(hiddenStorageKey(base));\n const parsed = raw ? (JSON.parse(raw) as unknown) : null;\n return Array.isArray(parsed)\n ? parsed.filter((v) => typeof v === 'string')\n : null;\n } catch {\n return null;\n }\n}\n\nfunction saveHidden(base: string | undefined, ids: string[]) {\n if (!base) return;\n try {\n localStorage.setItem(hiddenStorageKey(base), JSON.stringify(ids));\n } catch {\n /* storage unavailable */\n }\n}\n\nfunction loadLayout(base: string | undefined): DashboardLayout | null {\n if (!base) return null;\n try {\n const raw = localStorage.getItem(layoutStorageKey(base));\n const val = raw ? Number(raw) : null;\n return val === 1 || val === 2 || val === 3 ? val : null;\n } catch {\n return null;\n }\n}\n\nfunction saveLayout(base: string | undefined, mode: DashboardLayout) {\n if (!base) return;\n try {\n localStorage.setItem(layoutStorageKey(base), String(mode));\n } catch {\n /* storage unavailable */\n }\n}\n\nfunction sanitizeSlot(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((v): v is string => typeof v === 'string')\n : [];\n}\n\nfunction loadOrder(base: string | undefined): DashboardOrder | null {\n if (!base) return null;\n try {\n const raw = localStorage.getItem(orderStorageKey(base));\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Record<number, unknown>;\n return [\n sanitizeSlot(parsed[0]),\n sanitizeSlot(parsed[1]),\n sanitizeSlot(parsed[2]),\n ];\n } catch {\n return null;\n }\n}\n\nfunction saveOrder(base: string | undefined, order: DashboardOrder) {\n if (!base) return;\n try {\n const record: Record<number, string[]> = {};\n order.forEach((ids, i) => {\n record[i] = ids;\n });\n localStorage.setItem(orderStorageKey(base), JSON.stringify(record));\n } catch {\n /* storage unavailable */\n }\n}\n\n/**\n * Merge a saved/provided order with the current props columns: saved\n * positions win, unknown saved ids are dropped, and new items are appended\n * to their original props column.\n */\nexport function mergeColumnOrder(\n columns: DashboardColumns,\n saved: DashboardOrder | null\n): DashboardOrder {\n const allIds = new Set(\n [...columns[0], ...columns[1], ...columns[2]].map((p) => p.id)\n );\n const result: DashboardOrder = [[], [], []];\n const placed = new Set<string>();\n\n for (let i = 0; i < 3; i++) {\n for (const id of saved?.[i] ?? []) {\n if (allIds.has(id) && !placed.has(id)) {\n result[i].push(id);\n placed.add(id);\n }\n }\n }\n for (let i = 0; i < 3; i++) {\n for (const item of columns[i]) {\n if (!placed.has(item.id)) {\n result[i].push(item.id);\n placed.add(item.id);\n }\n }\n }\n return result;\n}\n\nfunction buildItemMap(columns: DashboardColumns): Map<string, PortletItem> {\n const map = new Map<string, PortletItem>();\n for (const col of columns) {\n for (const item of col) map.set(item.id, item);\n }\n return map;\n}\n\nfunction findColumn(colOrder: string[][], itemId: string): number {\n return colOrder.findIndex((ids) => ids.includes(itemId));\n}\n\n/**\n * Move `activeId` into the column named by `overId` (a column id or an item\n * id), inserted before the hovered item. Returns the same reference when no\n * cross-column move is needed.\n */\nexport function moveAcrossColumns(\n order: DashboardOrder,\n activeId: string,\n overId: string\n): DashboardOrder {\n const colIdx = COL_IDS.indexOf(overId as (typeof COL_IDS)[number]);\n const sourceCol = findColumn(order, activeId);\n if (sourceCol === -1) return order;\n\n const targetCol = colIdx !== -1 ? colIdx : findColumn(order, overId);\n if (targetCol === -1 || sourceCol === targetCol) return order;\n\n const next = order.map((col) => [...col]) as DashboardOrder;\n next[sourceCol] = next[sourceCol].filter((id) => id !== activeId);\n const overIdx = colIdx !== -1 ? -1 : next[targetCol].indexOf(overId);\n if (overIdx === -1) {\n next[targetCol].push(activeId);\n } else {\n next[targetCol].splice(overIdx, 0, activeId);\n }\n return next;\n}\n\n/**\n * Final order for a drop. Same-column drags reorder around the hovered\n * item. After a cross-column move, the one position `moveAcrossColumns`\n * already chose — active sitting immediately before the hovered item — is\n * kept (reordering would flip it to the other side of that item), but\n * hovering any other item in the destination column still reorders, so a\n * drag can keep moving after it crosses.\n */\nexport function reorderOnDrop(\n order: DashboardOrder,\n activeId: string,\n overId: string,\n crossedColumns: boolean\n): DashboardOrder {\n const isColumnTarget =\n COL_IDS.indexOf(overId as (typeof COL_IDS)[number]) !== -1;\n if (isColumnTarget || overId === activeId) return order;\n\n const col = findColumn(order, activeId);\n if (col === -1 || findColumn(order, overId) !== col) return order;\n\n const oldIdx = order[col].indexOf(activeId);\n const newIdx = order[col].indexOf(overId);\n if (oldIdx === -1 || newIdx === -1) return order;\n // Immediately-before adjacency after a cross is dragOver's insertion,\n // not a new reorder request.\n if (crossedColumns && newIdx === oldIdx + 1) return order;\n\n const next = order.map((c) => [...c]) as DashboardOrder;\n next[col] = arrayMove(next[col], oldIdx, newIdx);\n return next;\n}\n\n/**\n * Consolidate columns beyond the visible count into the last visible one.\n * Returns the same reference when nothing needs to move so callers can use\n * reference equality to skip persistence/notification.\n */\nexport function consolidateColumns(\n order: DashboardOrder,\n mode: DashboardLayout\n): DashboardOrder {\n if (mode >= 3 || requiredColumns(order) <= mode) return order;\n if (mode === 1) return [[...order[0], ...order[1], ...order[2]], [], []];\n return [[...order[0]], [...order[1], ...order[2]], []];\n}\n\n/**\n * Columns needed to show every item: the highest occupied index + 1, so a\n * gap like `[a], [], [c]` still requires three columns.\n */\nexport function requiredColumns(order: DashboardOrder): DashboardLayout {\n return Math.max(\n 1,\n ...order.map((ids, i) => (ids.length > 0 ? i + 1 : 0))\n ) as DashboardLayout;\n}\n\n/**\n * pointerWithin first (drops into empty columns), then closestCenter for\n * items, then rectIntersection for columns.\n */\nconst collisionDetection: CollisionDetection = (args) => {\n const pw = pointerWithin(args);\n if (pw.length > 0) return pw;\n const cc = closestCenter(args);\n if (cc.length > 0) return cc;\n return rectIntersection(args);\n};\n\n// =============================================================================\n// SortablePortlet\n// =============================================================================\n\nfunction SortablePortlet({\n id,\n handleSelector,\n children,\n}: {\n id: string;\n handleSelector: string;\n children: React.ReactNode;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id });\n\n const wrapperRef = React.useRef<HTMLDivElement>(null);\n const [headerEl, setHeaderEl] = React.useState<HTMLElement | null>(null);\n const [searched, setSearched] = React.useState(false);\n\n const style: React.CSSProperties = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.4 : 1,\n };\n\n // Portlet content can render asynchronously, so watch for the header with\n // a MutationObserver (rAF-coalesced) and disconnect once found.\n React.useEffect(() => {\n const container = wrapperRef.current;\n if (!container) return;\n\n let rafId = 0;\n\n const findHeader = () => {\n const header = container.querySelector(handleSelector);\n if (header instanceof HTMLElement) {\n header.classList.add(...HEADER_LAYOUT_CLASSES);\n setHeaderEl(header);\n observer.disconnect();\n } else {\n setHeaderEl(null);\n }\n setSearched(true);\n };\n\n const observer = new MutationObserver(() => {\n cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(findHeader);\n });\n\n findHeader();\n observer.observe(container, { childList: true, subtree: true });\n\n return () => {\n cancelAnimationFrame(rafId);\n observer.disconnect();\n };\n }, [handleSelector]);\n\n const handle = (\n <button\n type=\"button\"\n className={cn(\n 'inline-flex h-7 w-6 shrink-0 cursor-grab touch-none items-center justify-center rounded border-none bg-transparent',\n 'text-muted-foreground hover:bg-muted hover:text-foreground active:cursor-grabbing',\n 'opacity-40 transition-opacity group-hover/portlet:opacity-100 focus-visible:opacity-100',\n '[@media(hover:none)]:opacity-100',\n !headerEl && 'bg-card/80 absolute end-2 top-2 z-10 shadow-sm'\n )}\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical aria-hidden=\"true\" className=\"h-4 w-4\" />\n </button>\n );\n\n return (\n <div\n ref={(node) => {\n setNodeRef(node);\n wrapperRef.current = node;\n }}\n style={style}\n className=\"group/portlet relative min-w-0\"\n >\n <div className=\"w-full min-w-0\">{children}</div>\n {headerEl ? createPortal(handle, headerEl) : searched ? handle : null}\n </div>\n );\n}\n\n// =============================================================================\n// DroppableColumn\n// =============================================================================\n\nfunction DroppableColumn({\n id,\n items,\n columnIndex,\n handleSelector,\n flatten,\n dragActive,\n}: {\n id: string;\n items: PortletItem[];\n columnIndex: number;\n handleSelector: string;\n flatten: boolean;\n dragActive: boolean;\n}) {\n const { setNodeRef, isOver } = useDroppable({ id });\n const ids = items.map((p) => p.id);\n\n return (\n <SortableContext items={ids} strategy={verticalListSortingStrategy}>\n <div\n ref={setNodeRef}\n className={cn(\n 'flex min-h-16 min-w-0 flex-col gap-3',\n flatten && 'max-lg:contents'\n )}\n role=\"group\"\n aria-label={`Dashboard column ${columnIndex + 1}`}\n >\n {items.map((item) => (\n <SortablePortlet\n key={item.id}\n id={item.id}\n handleSelector={handleSelector}\n >\n {item.node}\n </SortablePortlet>\n ))}\n {items.length === 0 && dragActive && (\n <div\n aria-hidden=\"true\"\n className={cn(\n 'border-border text-muted-foreground flex min-h-32 items-center justify-center rounded-lg border-2 border-dashed text-sm font-medium transition-colors',\n isOver && 'border-primary-500 bg-primary-500/10 text-primary-600'\n )}\n >\n Drop here\n </div>\n )}\n </div>\n </SortableContext>\n );\n}\n\n// =============================================================================\n// CustomizableDashboard\n// =============================================================================\n\n/**\n * A user-customizable portlet dashboard: a responsive 1–3 column grid whose\n * items can be dragged between and within columns, with a column-layout\n * toggle and optional persistence.\n *\n * Each portlet's drag handle is appended to the header element matched by\n * `dragHandleSelector` inside its content — `DashboardWidget` headers are\n * matched by default. Portlets without a matching header get a floating\n * handle in their top end corner.\n *\n * Order and layout are persisted to localStorage when `storageKey` is set,\n * or can be controlled via `order`/`onOrderChange` and\n * `layout`/`onLayoutChange` for server-side persistence.\n *\n * Passing a `widgets` catalog adds a toolbar Customize button opening a\n * `DashboardCustomizePanel` where users show/hide widgets and reset the\n * layout; visibility follows the same persistence rules via\n * `hiddenIds`/`onHiddenChange`.\n *\n * @example\n * ```tsx\n * <CustomizableDashboard\n * storageKey=\"home\"\n * columns={[\n * [{ id: 'stats', node: <StatsWidget /> }],\n * [{ id: 'tasks', node: <TasksWidget /> }],\n * [{ id: 'orders', node: <OrdersWidget /> }],\n * ]}\n * />\n * ```\n */\nexport const CustomizableDashboard = React.forwardRef<\n HTMLDivElement,\n CustomizableDashboardProps\n>(function CustomizableDashboard(\n {\n columns,\n title,\n storageKey,\n ariaLabel,\n toolbarSlot,\n defaultOrder,\n order: controlledOrder,\n onOrderChange,\n defaultLayout = 3,\n layout: controlledLayout,\n onLayoutChange,\n dragHandleSelector = DEFAULT_HANDLE_SELECTOR,\n widgets,\n defaultHiddenIds,\n hiddenIds: controlledHidden,\n onHiddenChange,\n customizeLabel = 'Customize',\n className,\n },\n ref\n) {\n const itemMap = React.useMemo(() => buildItemMap(columns), [columns]);\n\n // Initial state ignores persistence so the first client render matches SSR;\n // saved values are restored in a mount effect below.\n const [internalLayout, setInternalLayout] =\n React.useState<DashboardLayout>(defaultLayout);\n const layoutMode = controlledLayout ?? internalLayout;\n\n const [colOrder, setColOrder] = React.useState<DashboardOrder>(() =>\n consolidateColumns(\n mergeColumnOrder(columns, controlledOrder ?? defaultOrder ?? null),\n controlledLayout ?? defaultLayout\n )\n );\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const [internalHidden, setInternalHidden] = React.useState<string[]>(\n () => defaultHiddenIds ?? []\n );\n const hiddenList = controlledHidden ?? internalHidden;\n const hiddenSet = React.useMemo(() => new Set(hiddenList), [hiddenList]);\n const [panelOpen, setPanelOpen] = React.useState(false);\n\n const prevColOrder = React.useRef(colOrder);\n const layoutModeRef = React.useRef(layoutMode);\n layoutModeRef.current = layoutMode;\n const colOrderRef = React.useRef(colOrder);\n colOrderRef.current = colOrder;\n const columnsRef = React.useRef(columns);\n columnsRef.current = columns;\n const draggingRef = React.useRef(false);\n\n // Restore persisted layout/order/visibility after mount (uncontrolled\n // concerns only) so the first client render matches SSR.\n React.useEffect(() => {\n if (!storageKey) return;\n if (controlledLayout === undefined) {\n const savedLayout = loadLayout(storageKey);\n if (savedLayout !== null) setInternalLayout(savedLayout);\n }\n if (controlledOrder === undefined) {\n const savedOrder = loadOrder(storageKey);\n if (savedOrder) {\n setColOrder(mergeColumnOrder(columnsRef.current, savedOrder));\n }\n }\n if (controlledHidden === undefined) {\n const savedHidden = loadHidden(storageKey);\n if (savedHidden) setInternalHidden(savedHidden);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- mount-only restore\n }, [storageKey]);\n\n // Sync controlled order and newly added/removed items while not dragging,\n // consolidating into the effective layout so portlets in columns beyond the\n // visible count (e.g. mounting with `defaultLayout` 1/2, or a restored or\n // controlled layout) are never sliced off the render.\n React.useEffect(() => {\n if (draggingRef.current) return;\n setColOrder((prev) => {\n const next = consolidateColumns(\n mergeColumnOrder(columns, controlledOrder ?? prev),\n layoutMode\n );\n return JSON.stringify(next) === JSON.stringify(prev) ? prev : next;\n });\n }, [columns, controlledOrder, layoutMode]);\n\n const setLayout = React.useCallback(\n (mode: DashboardLayout) => {\n if (controlledLayout === undefined) setInternalLayout(mode);\n saveLayout(storageKey, mode);\n onLayoutChange?.(mode);\n },\n [controlledLayout, storageKey, onLayoutChange]\n );\n\n const commitOrder = React.useCallback(\n (next: DashboardOrder) => {\n saveOrder(storageKey, next);\n onOrderChange?.(next);\n\n // Auto-shrink only when trailing columns are empty (gaps keep their\n // column so no item is hidden by a reduced layout)\n const occupied = requiredColumns(next);\n if (occupied < layoutModeRef.current) {\n setLayout(occupied);\n }\n },\n [storageKey, onOrderChange, setLayout]\n );\n\n const handleLayoutChange = React.useCallback(\n (mode: DashboardLayout) => {\n setLayout(mode);\n // Consolidate so droppable ids match visible columns; persist/notify\n // outside the state updater so replayed renders can't double-fire.\n const next = consolidateColumns(colOrderRef.current, mode);\n if (next !== colOrderRef.current) {\n setColOrder(next);\n saveOrder(storageKey, next);\n onOrderChange?.(next);\n }\n },\n [setLayout, storageKey, onOrderChange]\n );\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n );\n\n const resolve = (ids: string[]): PortletItem[] =>\n ids\n .filter((id) => !hiddenSet.has(id))\n .map((id) => itemMap.get(id))\n .filter(Boolean) as PortletItem[];\n\n const handleDragStart = React.useCallback(\n (event: DragStartEvent) => {\n prevColOrder.current = colOrder;\n draggingRef.current = true;\n setActiveId(String(event.active.id));\n },\n [colOrder]\n );\n\n const handleDragOver = React.useCallback((event: DragOverEvent) => {\n const { active, over } = event;\n if (!over) return;\n const next = moveAcrossColumns(\n colOrderRef.current,\n String(active.id),\n String(over.id)\n );\n if (next !== colOrderRef.current) setColOrder(next);\n }, []);\n\n const handleDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n draggingRef.current = false;\n setActiveId(null);\n\n if (!over) {\n setColOrder(prevColOrder.current);\n return;\n }\n\n const activeItemId = String(active.id);\n // A drag that ends in a different column than it started already sits\n // where moveAcrossColumns placed it; reordering again would flip it\n // to the other side of the hovered item.\n const crossedColumns =\n findColumn(prevColOrder.current, activeItemId) !==\n findColumn(colOrderRef.current, activeItemId);\n const next = reorderOnDrop(\n colOrderRef.current,\n activeItemId,\n String(over.id),\n crossedColumns\n );\n if (next !== colOrderRef.current) setColOrder(next);\n // A drag that ends where it started is a no-op: skip the commit so it\n // can't write storage, notify hosts, or auto-shrink the layout.\n if (JSON.stringify(next) !== JSON.stringify(prevColOrder.current)) {\n commitOrder(next);\n }\n },\n [commitOrder]\n );\n\n const handleDragCancel = React.useCallback(() => {\n draggingRef.current = false;\n setActiveId(null);\n setColOrder(prevColOrder.current);\n }, []);\n\n const setHidden = React.useCallback(\n (ids: string[]) => {\n if (controlledHidden === undefined) setInternalHidden(ids);\n saveHidden(storageKey, ids);\n onHiddenChange?.(ids);\n },\n [controlledHidden, storageKey, onHiddenChange]\n );\n\n const handleToggleWidget = React.useCallback(\n (id: string, visible: boolean) => {\n setHidden(\n visible ? hiddenList.filter((h) => h !== id) : [...hiddenList, id]\n );\n },\n [hiddenList, setHidden]\n );\n\n const handleReset = React.useCallback(() => {\n if (storageKey) {\n try {\n localStorage.removeItem(orderStorageKey(storageKey));\n localStorage.removeItem(layoutStorageKey(storageKey));\n localStorage.removeItem(hiddenStorageKey(storageKey));\n } catch {\n /* storage unavailable */\n }\n }\n const next = mergeColumnOrder(columns, defaultOrder ?? null);\n setColOrder(next);\n onOrderChange?.(next);\n if (controlledLayout === undefined) setInternalLayout(defaultLayout);\n onLayoutChange?.(defaultLayout);\n const hidden = defaultHiddenIds ?? [];\n if (controlledHidden === undefined) setInternalHidden(hidden);\n onHiddenChange?.(hidden);\n }, [\n storageKey,\n columns,\n defaultOrder,\n onOrderChange,\n controlledLayout,\n defaultLayout,\n onLayoutChange,\n defaultHiddenIds,\n controlledHidden,\n onHiddenChange,\n ]);\n\n const cols: DashboardColumns = [\n resolve(colOrder[0]),\n resolve(colOrder[1]),\n resolve(colOrder[2]),\n ];\n\n const visibleCols =\n layoutMode === 1 ? [cols[0]] : layoutMode === 2 ? [cols[0], cols[1]] : cols;\n\n const toolbar = (\n <div className=\"flex items-center justify-end gap-3 pb-2\">\n {title && (\n <h2 className=\"text-foreground me-auto text-lg font-semibold\">\n {title}\n </h2>\n )}\n {widgets && widgets.length > 0 && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setPanelOpen(true)}\n aria-haspopup=\"dialog\"\n leftIcon={\n <SlidersHorizontal aria-hidden=\"true\" className=\"h-4 w-4\" />\n }\n >\n {customizeLabel}\n </Button>\n )}\n <div\n className=\"border-border bg-muted flex gap-0.5 rounded-md border p-0.5 max-md:hidden\"\n role=\"radiogroup\"\n aria-label=\"Column layout\"\n >\n {([3, 2, 1] as const).map((mode) => {\n const Icon = mode === 3 ? Columns3 : mode === 2 ? Columns2 : Square;\n return (\n <button\n key={mode}\n type=\"button\"\n className={cn(\n 'flex h-7 w-7 items-center justify-center rounded transition-colors',\n layoutMode === mode\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:bg-background hover:text-foreground'\n )}\n onClick={() => handleLayoutChange(mode)}\n role=\"radio\"\n aria-checked={layoutMode === mode}\n aria-label={`${mode} column layout`}\n title={`${mode} column${mode > 1 ? 's' : ''}`}\n >\n <Icon aria-hidden=\"true\" className=\"h-4 w-4\" />\n </button>\n );\n })}\n </div>\n </div>\n );\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={collisionDetection}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n >\n {toolbarSlot ? createPortal(toolbar, toolbarSlot) : toolbar}\n <div\n ref={ref}\n className={cn(\n 'grid items-start gap-3',\n layoutMode === 3 && 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',\n layoutMode === 2 && 'grid-cols-1 md:grid-cols-2',\n layoutMode === 1 && 'grid-cols-1',\n className\n )}\n role=\"region\"\n aria-label={ariaLabel ?? 'Dashboard'}\n >\n {visibleCols.map((col, i) => (\n <DroppableColumn\n key={COL_IDS[i]}\n id={COL_IDS[i]}\n items={col}\n columnIndex={i}\n handleSelector={dragHandleSelector}\n flatten={layoutMode === 3}\n dragActive={activeId !== null}\n />\n ))}\n </div>\n {widgets && widgets.length > 0 && (\n <DashboardCustomizePanel\n open={panelOpen}\n onOpenChange={setPanelOpen}\n widgets={widgets}\n hiddenIds={hiddenList}\n onToggleWidget={handleToggleWidget}\n onReset={handleReset}\n />\n )}\n </DndContext>\n );\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/CustomizableDashboard/DashboardCustomizePanel.tsx","../src/components/CustomizableDashboard/CustomizableDashboard.tsx"],"names":["React","jsx","jsxs","CustomizableDashboard"],"mappings":"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","file":"chunk-H2IAMSHK.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { RotateCcw } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n Sheet,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetBody,\n SheetFooter,\n} from '../Sheet';\nimport { Switch } from '../Switch';\nimport { Button } from '../Button';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Catalog metadata for a widget a user can show or hide on a dashboard. */\nexport interface WidgetDefinition {\n /** Matches the portlet's `PortletItem.id`. */\n id: string;\n title: string;\n description?: string;\n /** Small leading icon, e.g. `<Activity className=\"h-4 w-4\" />`. */\n icon?: React.ReactNode;\n /** Widgets sharing a category are grouped under a heading. */\n category?: string;\n}\n\nexport interface DashboardCustomizePanelProps {\n /** Whether the panel is open. */\n open: boolean;\n /** Callback when the panel should open or close. */\n onOpenChange: (open: boolean) => void;\n /** The full widget catalog for this dashboard. */\n widgets: WidgetDefinition[];\n /** Ids of widgets currently hidden. */\n hiddenIds: string[];\n /** Called when a widget is shown (`visible: true`) or hidden. */\n onToggleWidget: (id: string, visible: boolean) => void;\n /** When provided, renders a \"Reset layout\" action in the footer. */\n onReset?: () => void;\n /** Panel heading (default \"Customize dashboard\"). */\n title?: string;\n /** Supporting copy under the heading. */\n description?: string;\n}\n\n// =============================================================================\n// DashboardCustomizePanel\n// =============================================================================\n\n/**\n * A slide-in panel listing a dashboard's widget catalog with show/hide\n * toggles, grouped by category, plus an optional layout reset.\n *\n * Used automatically by `CustomizableDashboard` when its `widgets` prop is\n * set, and exported standalone for hosts that render their own trigger or\n * persist visibility elsewhere.\n *\n * @example\n * ```tsx\n * <DashboardCustomizePanel\n * open={open}\n * onOpenChange={setOpen}\n * widgets={WIDGETS}\n * hiddenIds={hidden}\n * onToggleWidget={(id, visible) =>\n * setHidden((prev) =>\n * visible ? prev.filter((h) => h !== id) : [...prev, id]\n * )\n * }\n * />\n * ```\n */\nexport function DashboardCustomizePanel({\n open,\n onOpenChange,\n widgets,\n hiddenIds,\n onToggleWidget,\n onReset,\n title = 'Customize dashboard',\n description = 'Choose which widgets appear on this dashboard. Drag a widget by its handle to rearrange it.',\n}: DashboardCustomizePanelProps) {\n const hidden = React.useMemo(() => new Set(hiddenIds), [hiddenIds]);\n\n const groups = React.useMemo(() => {\n const map = new Map<string, WidgetDefinition[]>();\n for (const w of widgets) {\n const key = w.category ?? '';\n const list = map.get(key);\n if (list) list.push(w);\n else map.set(key, [w]);\n }\n return Array.from(map.entries());\n }, [widgets]);\n\n const visibleCount = widgets.length - hidden.size;\n\n return (\n <Sheet\n open={open}\n onOpenChange={onOpenChange}\n side=\"end\"\n aria-label={title}\n >\n <SheetHeader>\n <div className=\"flex flex-col gap-1.5\">\n <SheetTitle>{title}</SheetTitle>\n <SheetDescription>{description}</SheetDescription>\n </div>\n </SheetHeader>\n <SheetBody className=\"flex flex-col gap-5\">\n <p className=\"text-muted-foreground text-xs font-medium\">\n {visibleCount} of {widgets.length} widgets shown\n </p>\n {groups.map(([category, items]) => (\n <div key={category || 'general'} className=\"flex flex-col gap-1\">\n {category && (\n <h3 className=\"text-muted-foreground pb-1 text-xs font-semibold tracking-wide uppercase\">\n {category}\n </h3>\n )}\n <ul className=\"flex list-none flex-col gap-1 p-0\">\n {items.map((widget) => {\n const isVisible = !hidden.has(widget.id);\n return (\n <li\n key={widget.id}\n className={cn(\n 'border-border flex items-center gap-3 rounded-lg border p-3 transition-colors',\n isVisible ? 'bg-card' : 'bg-muted/50'\n )}\n >\n {widget.icon && (\n <span\n className={cn(\n 'shrink-0',\n isVisible\n ? 'text-primary-600 dark:text-primary-400'\n : 'text-muted-foreground'\n )}\n >\n {widget.icon}\n </span>\n )}\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span\n className={cn(\n 'truncate text-sm font-medium',\n isVisible\n ? 'text-foreground'\n : 'text-muted-foreground'\n )}\n >\n {widget.title}\n </span>\n {widget.description && (\n <span className=\"text-muted-foreground truncate text-xs\">\n {widget.description}\n </span>\n )}\n </span>\n <Switch\n checked={isVisible}\n onCheckedChange={(checked) =>\n onToggleWidget(widget.id, checked)\n }\n aria-label={`Show ${widget.title}`}\n />\n </li>\n );\n })}\n </ul>\n </div>\n ))}\n </SheetBody>\n {onReset && (\n <SheetFooter>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onReset}\n leftIcon={<RotateCcw aria-hidden=\"true\" className=\"h-4 w-4\" />}\n >\n Reset layout\n </Button>\n </SheetFooter>\n )}\n </Sheet>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n DndContext,\n closestCenter,\n pointerWithin,\n rectIntersection,\n PointerSensor,\n KeyboardSensor,\n useSensor,\n useSensors,\n useDroppable,\n type DragStartEvent,\n type DragOverEvent,\n type DragEndEvent,\n type CollisionDetection,\n} from '@dnd-kit/core';\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n useSortable,\n arrayMove,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport {\n GripVertical,\n Columns2,\n Columns3,\n Square,\n SlidersHorizontal,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Button } from '../Button';\nimport {\n DashboardCustomizePanel,\n type WidgetDefinition,\n} from './DashboardCustomizePanel';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** A dashboard item: a stable id plus the rendered content. */\nexport interface PortletItem {\n id: string;\n node: React.ReactNode;\n}\n\n/** Number of visible columns. */\nexport type DashboardLayout = 1 | 2 | 3;\n\n/** Portlet items grouped into three logical columns. */\nexport type DashboardColumns = [PortletItem[], PortletItem[], PortletItem[]];\n\n/** Portlet ids grouped into three logical columns. */\nexport type DashboardOrder = [string[], string[], string[]];\n\nexport interface CustomizableDashboardProps {\n /**\n * Portlets grouped into three columns. This is the default arrangement;\n * user reordering (persisted or controlled) takes precedence. Items later\n * removed from props disappear from saved layouts automatically, and new\n * items appear in their props column.\n */\n columns: DashboardColumns;\n /** Toolbar heading rendered before the layout toggle. */\n title?: string;\n /**\n * Base localStorage key used to persist column order and layout mode\n * (`{storageKey}-portlet-order` / `{storageKey}-dashboard-layout`).\n * Omit to disable built-in persistence (e.g. when using `order` /\n * `onOrderChange` with a server-side store). Distinct dashboards must\n * pass distinct keys.\n */\n storageKey?: string;\n /** Accessible label for the dashboard grid region. */\n ariaLabel?: string;\n /**\n * Optional DOM element to portal the toolbar (title + layout toggle)\n * into, e.g. a page header actions row. When omitted, the toolbar\n * renders inline above the grid.\n */\n toolbarSlot?: HTMLElement | null;\n /** Initial column order for uncontrolled usage with external persistence. */\n defaultOrder?: DashboardOrder;\n /** Controlled column order. Changes are reported via `onOrderChange`. */\n order?: DashboardOrder;\n /** Called with the full new order after a drop or layout normalization. */\n onOrderChange?: (order: DashboardOrder) => void;\n /** Initial layout mode for uncontrolled usage (default 3). */\n defaultLayout?: DashboardLayout;\n /** Controlled layout mode. Changes are reported via `onLayoutChange`. */\n layout?: DashboardLayout;\n /** Called when the user changes the column layout (or it auto-shrinks). */\n onLayoutChange?: (layout: DashboardLayout) => void;\n /**\n * CSS selector for the header element inside each portlet that receives\n * the drag handle. Defaults to the `DashboardWidget` header slot. When no\n * header matches, the handle floats over the portlet's top end corner.\n */\n dragHandleSelector?: string;\n /**\n * Widget catalog metadata. When provided, the toolbar gains a Customize\n * button opening a panel where users show/hide widgets and reset the\n * layout. Ids must match the portlet ids in `columns`.\n */\n widgets?: WidgetDefinition[];\n /** Initially hidden widget ids for uncontrolled usage. */\n defaultHiddenIds?: string[];\n /** Controlled hidden widget ids. Changes reported via `onHiddenChange`. */\n hiddenIds?: string[];\n /** Called with the full hidden-id list when visibility changes. */\n onHiddenChange?: (hiddenIds: string[]) => void;\n /** Label for the toolbar customize button (default \"Customize\"). */\n customizeLabel?: string;\n /** Additional class name for the grid element. */\n className?: string;\n}\n\n// =============================================================================\n// Internals\n// =============================================================================\n\nconst COL_IDS = ['column-0', 'column-1', 'column-2'] as const;\n\nconst DEFAULT_HANDLE_SELECTOR = '[data-slot=\"dashboard-widget-header\"]';\n\n// Applied to a discovered header so the appended handle lays out correctly:\n// an auto start margin on the 2nd child pushes trailing controls (and the\n// handle after them) to the end, even inside `justify-between` headers.\nconst HEADER_LAYOUT_CLASSES = [\n 'flex',\n 'flex-row',\n 'flex-nowrap',\n 'items-center',\n '[&>:nth-child(2)]:ms-auto',\n];\n\nfunction orderStorageKey(base: string): string {\n return `${base}-portlet-order`;\n}\n\nfunction layoutStorageKey(base: string): string {\n return `${base}-dashboard-layout`;\n}\n\nfunction hiddenStorageKey(base: string): string {\n return `${base}-dashboard-hidden`;\n}\n\nfunction loadHidden(base: string | undefined): string[] | null {\n if (!base) return null;\n try {\n const raw = localStorage.getItem(hiddenStorageKey(base));\n const parsed = raw ? (JSON.parse(raw) as unknown) : null;\n return Array.isArray(parsed)\n ? parsed.filter((v) => typeof v === 'string')\n : null;\n } catch {\n return null;\n }\n}\n\nfunction saveHidden(base: string | undefined, ids: string[]) {\n if (!base) return;\n try {\n localStorage.setItem(hiddenStorageKey(base), JSON.stringify(ids));\n } catch {\n /* storage unavailable */\n }\n}\n\nfunction loadLayout(base: string | undefined): DashboardLayout | null {\n if (!base) return null;\n try {\n const raw = localStorage.getItem(layoutStorageKey(base));\n const val = raw ? Number(raw) : null;\n return val === 1 || val === 2 || val === 3 ? val : null;\n } catch {\n return null;\n }\n}\n\nfunction saveLayout(base: string | undefined, mode: DashboardLayout) {\n if (!base) return;\n try {\n localStorage.setItem(layoutStorageKey(base), String(mode));\n } catch {\n /* storage unavailable */\n }\n}\n\nfunction sanitizeSlot(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((v): v is string => typeof v === 'string')\n : [];\n}\n\nfunction loadOrder(base: string | undefined): DashboardOrder | null {\n if (!base) return null;\n try {\n const raw = localStorage.getItem(orderStorageKey(base));\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Record<number, unknown>;\n return [\n sanitizeSlot(parsed[0]),\n sanitizeSlot(parsed[1]),\n sanitizeSlot(parsed[2]),\n ];\n } catch {\n return null;\n }\n}\n\nfunction saveOrder(base: string | undefined, order: DashboardOrder) {\n if (!base) return;\n try {\n const record: Record<number, string[]> = {};\n order.forEach((ids, i) => {\n record[i] = ids;\n });\n localStorage.setItem(orderStorageKey(base), JSON.stringify(record));\n } catch {\n /* storage unavailable */\n }\n}\n\n/**\n * Merge a saved/provided order with the current props columns: saved\n * positions win, unknown saved ids are dropped, and new items are appended\n * to their original props column.\n */\nexport function mergeColumnOrder(\n columns: DashboardColumns,\n saved: DashboardOrder | null\n): DashboardOrder {\n const allIds = new Set(\n [...columns[0], ...columns[1], ...columns[2]].map((p) => p.id)\n );\n const result: DashboardOrder = [[], [], []];\n const placed = new Set<string>();\n\n for (let i = 0; i < 3; i++) {\n for (const id of saved?.[i] ?? []) {\n if (allIds.has(id) && !placed.has(id)) {\n result[i].push(id);\n placed.add(id);\n }\n }\n }\n for (let i = 0; i < 3; i++) {\n for (const item of columns[i]) {\n if (!placed.has(item.id)) {\n result[i].push(item.id);\n placed.add(item.id);\n }\n }\n }\n return result;\n}\n\nfunction buildItemMap(columns: DashboardColumns): Map<string, PortletItem> {\n const map = new Map<string, PortletItem>();\n for (const col of columns) {\n for (const item of col) map.set(item.id, item);\n }\n return map;\n}\n\nfunction findColumn(colOrder: string[][], itemId: string): number {\n return colOrder.findIndex((ids) => ids.includes(itemId));\n}\n\n/**\n * Move `activeId` into the column named by `overId` (a column id or an item\n * id), inserted before the hovered item. Returns the same reference when no\n * cross-column move is needed.\n */\nexport function moveAcrossColumns(\n order: DashboardOrder,\n activeId: string,\n overId: string\n): DashboardOrder {\n const colIdx = COL_IDS.indexOf(overId as (typeof COL_IDS)[number]);\n const sourceCol = findColumn(order, activeId);\n if (sourceCol === -1) return order;\n\n const targetCol = colIdx !== -1 ? colIdx : findColumn(order, overId);\n if (targetCol === -1 || sourceCol === targetCol) return order;\n\n const next = order.map((col) => [...col]) as DashboardOrder;\n next[sourceCol] = next[sourceCol].filter((id) => id !== activeId);\n const overIdx = colIdx !== -1 ? -1 : next[targetCol].indexOf(overId);\n if (overIdx === -1) {\n next[targetCol].push(activeId);\n } else {\n next[targetCol].splice(overIdx, 0, activeId);\n }\n return next;\n}\n\n/**\n * Final order for a drop. Same-column drags reorder around the hovered\n * item. After a cross-column move, the one position `moveAcrossColumns`\n * already chose — active sitting immediately before the hovered item — is\n * kept (reordering would flip it to the other side of that item), but\n * hovering any other item in the destination column still reorders, so a\n * drag can keep moving after it crosses.\n */\nexport function reorderOnDrop(\n order: DashboardOrder,\n activeId: string,\n overId: string,\n crossedColumns: boolean\n): DashboardOrder {\n const isColumnTarget =\n COL_IDS.indexOf(overId as (typeof COL_IDS)[number]) !== -1;\n if (isColumnTarget || overId === activeId) return order;\n\n const col = findColumn(order, activeId);\n if (col === -1 || findColumn(order, overId) !== col) return order;\n\n const oldIdx = order[col].indexOf(activeId);\n const newIdx = order[col].indexOf(overId);\n if (oldIdx === -1 || newIdx === -1) return order;\n // Immediately-before adjacency after a cross is dragOver's insertion,\n // not a new reorder request.\n if (crossedColumns && newIdx === oldIdx + 1) return order;\n\n const next = order.map((c) => [...c]) as DashboardOrder;\n next[col] = arrayMove(next[col], oldIdx, newIdx);\n return next;\n}\n\n/**\n * Consolidate columns beyond the visible count into the last visible one.\n * Returns the same reference when nothing needs to move so callers can use\n * reference equality to skip persistence/notification.\n */\nexport function consolidateColumns(\n order: DashboardOrder,\n mode: DashboardLayout\n): DashboardOrder {\n if (mode >= 3 || requiredColumns(order) <= mode) return order;\n if (mode === 1) return [[...order[0], ...order[1], ...order[2]], [], []];\n return [[...order[0]], [...order[1], ...order[2]], []];\n}\n\n/**\n * Columns needed to show every item: the highest occupied index + 1, so a\n * gap like `[a], [], [c]` still requires three columns.\n */\nexport function requiredColumns(order: DashboardOrder): DashboardLayout {\n return Math.max(\n 1,\n ...order.map((ids, i) => (ids.length > 0 ? i + 1 : 0))\n ) as DashboardLayout;\n}\n\n/**\n * pointerWithin first (drops into empty columns), then closestCenter for\n * items, then rectIntersection for columns.\n */\nconst collisionDetection: CollisionDetection = (args) => {\n const pw = pointerWithin(args);\n if (pw.length > 0) return pw;\n const cc = closestCenter(args);\n if (cc.length > 0) return cc;\n return rectIntersection(args);\n};\n\n// =============================================================================\n// SortablePortlet\n// =============================================================================\n\nfunction SortablePortlet({\n id,\n handleSelector,\n children,\n}: {\n id: string;\n handleSelector: string;\n children: React.ReactNode;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id });\n\n const wrapperRef = React.useRef<HTMLDivElement>(null);\n const [headerEl, setHeaderEl] = React.useState<HTMLElement | null>(null);\n const [searched, setSearched] = React.useState(false);\n\n const style: React.CSSProperties = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.4 : 1,\n };\n\n // Portlet content can render asynchronously, so watch for the header with\n // a MutationObserver (rAF-coalesced) and disconnect once found.\n React.useEffect(() => {\n const container = wrapperRef.current;\n if (!container) return;\n\n let rafId = 0;\n\n const findHeader = () => {\n const header = container.querySelector(handleSelector);\n if (header instanceof HTMLElement) {\n header.classList.add(...HEADER_LAYOUT_CLASSES);\n setHeaderEl(header);\n observer.disconnect();\n } else {\n setHeaderEl(null);\n }\n setSearched(true);\n };\n\n const observer = new MutationObserver(() => {\n cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(findHeader);\n });\n\n findHeader();\n observer.observe(container, { childList: true, subtree: true });\n\n return () => {\n cancelAnimationFrame(rafId);\n observer.disconnect();\n };\n }, [handleSelector]);\n\n const handle = (\n <button\n type=\"button\"\n className={cn(\n 'inline-flex h-7 w-6 shrink-0 cursor-grab touch-none items-center justify-center rounded border-none bg-transparent',\n 'text-muted-foreground hover:bg-muted hover:text-foreground active:cursor-grabbing',\n 'opacity-40 transition-opacity group-hover/portlet:opacity-100 focus-visible:opacity-100',\n '[@media(hover:none)]:opacity-100',\n !headerEl && 'bg-card/80 absolute end-2 top-2 z-10 shadow-sm'\n )}\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical aria-hidden=\"true\" className=\"h-4 w-4\" />\n </button>\n );\n\n return (\n <div\n ref={(node) => {\n setNodeRef(node);\n wrapperRef.current = node;\n }}\n style={style}\n className=\"group/portlet relative min-w-0\"\n >\n <div className=\"w-full min-w-0\">{children}</div>\n {headerEl ? createPortal(handle, headerEl) : searched ? handle : null}\n </div>\n );\n}\n\n// =============================================================================\n// DroppableColumn\n// =============================================================================\n\nfunction DroppableColumn({\n id,\n items,\n columnIndex,\n handleSelector,\n flatten,\n dragActive,\n}: {\n id: string;\n items: PortletItem[];\n columnIndex: number;\n handleSelector: string;\n flatten: boolean;\n dragActive: boolean;\n}) {\n const { setNodeRef, isOver } = useDroppable({ id });\n const ids = items.map((p) => p.id);\n\n return (\n <SortableContext items={ids} strategy={verticalListSortingStrategy}>\n <div\n ref={setNodeRef}\n className={cn(\n 'flex min-h-16 min-w-0 flex-col gap-3',\n flatten && 'max-lg:contents'\n )}\n role=\"group\"\n aria-label={`Dashboard column ${columnIndex + 1}`}\n >\n {items.map((item) => (\n <SortablePortlet\n key={item.id}\n id={item.id}\n handleSelector={handleSelector}\n >\n {item.node}\n </SortablePortlet>\n ))}\n {items.length === 0 && dragActive && (\n <div\n aria-hidden=\"true\"\n className={cn(\n 'border-border text-muted-foreground flex min-h-32 items-center justify-center rounded-lg border-2 border-dashed text-sm font-medium transition-colors',\n isOver && 'border-primary-500 bg-primary-500/10 text-primary-600'\n )}\n >\n Drop here\n </div>\n )}\n </div>\n </SortableContext>\n );\n}\n\n// =============================================================================\n// CustomizableDashboard\n// =============================================================================\n\n/**\n * A user-customizable portlet dashboard: a responsive 1–3 column grid whose\n * items can be dragged between and within columns, with a column-layout\n * toggle and optional persistence.\n *\n * Each portlet's drag handle is appended to the header element matched by\n * `dragHandleSelector` inside its content — `DashboardWidget` headers are\n * matched by default. Portlets without a matching header get a floating\n * handle in their top end corner.\n *\n * Order and layout are persisted to localStorage when `storageKey` is set,\n * or can be controlled via `order`/`onOrderChange` and\n * `layout`/`onLayoutChange` for server-side persistence.\n *\n * Passing a `widgets` catalog adds a toolbar Customize button opening a\n * `DashboardCustomizePanel` where users show/hide widgets and reset the\n * layout; visibility follows the same persistence rules via\n * `hiddenIds`/`onHiddenChange`.\n *\n * @example\n * ```tsx\n * <CustomizableDashboard\n * storageKey=\"home\"\n * columns={[\n * [{ id: 'stats', node: <StatsWidget /> }],\n * [{ id: 'tasks', node: <TasksWidget /> }],\n * [{ id: 'orders', node: <OrdersWidget /> }],\n * ]}\n * />\n * ```\n */\nexport const CustomizableDashboard = React.forwardRef<\n HTMLDivElement,\n CustomizableDashboardProps\n>(function CustomizableDashboard(\n {\n columns,\n title,\n storageKey,\n ariaLabel,\n toolbarSlot,\n defaultOrder,\n order: controlledOrder,\n onOrderChange,\n defaultLayout = 3,\n layout: controlledLayout,\n onLayoutChange,\n dragHandleSelector = DEFAULT_HANDLE_SELECTOR,\n widgets,\n defaultHiddenIds,\n hiddenIds: controlledHidden,\n onHiddenChange,\n customizeLabel = 'Customize',\n className,\n },\n ref\n) {\n const itemMap = React.useMemo(() => buildItemMap(columns), [columns]);\n\n // Initial state ignores persistence so the first client render matches SSR;\n // saved values are restored in a mount effect below.\n const [internalLayout, setInternalLayout] =\n React.useState<DashboardLayout>(defaultLayout);\n const layoutMode = controlledLayout ?? internalLayout;\n\n const [colOrder, setColOrder] = React.useState<DashboardOrder>(() =>\n consolidateColumns(\n mergeColumnOrder(columns, controlledOrder ?? defaultOrder ?? null),\n controlledLayout ?? defaultLayout\n )\n );\n const [activeId, setActiveId] = React.useState<string | null>(null);\n\n const [internalHidden, setInternalHidden] = React.useState<string[]>(\n () => defaultHiddenIds ?? []\n );\n const hiddenList = controlledHidden ?? internalHidden;\n const hiddenSet = React.useMemo(() => new Set(hiddenList), [hiddenList]);\n const [panelOpen, setPanelOpen] = React.useState(false);\n\n const prevColOrder = React.useRef(colOrder);\n const layoutModeRef = React.useRef(layoutMode);\n layoutModeRef.current = layoutMode;\n const colOrderRef = React.useRef(colOrder);\n colOrderRef.current = colOrder;\n const columnsRef = React.useRef(columns);\n columnsRef.current = columns;\n const draggingRef = React.useRef(false);\n\n // Restore persisted layout/order/visibility after mount (uncontrolled\n // concerns only) so the first client render matches SSR.\n React.useEffect(() => {\n if (!storageKey) return;\n if (controlledLayout === undefined) {\n const savedLayout = loadLayout(storageKey);\n if (savedLayout !== null) setInternalLayout(savedLayout);\n }\n if (controlledOrder === undefined) {\n const savedOrder = loadOrder(storageKey);\n if (savedOrder) {\n setColOrder(mergeColumnOrder(columnsRef.current, savedOrder));\n }\n }\n if (controlledHidden === undefined) {\n const savedHidden = loadHidden(storageKey);\n if (savedHidden) setInternalHidden(savedHidden);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- mount-only restore\n }, [storageKey]);\n\n // Sync controlled order and newly added/removed items while not dragging,\n // consolidating into the effective layout so portlets in columns beyond the\n // visible count (e.g. mounting with `defaultLayout` 1/2, or a restored or\n // controlled layout) are never sliced off the render.\n React.useEffect(() => {\n if (draggingRef.current) return;\n setColOrder((prev) => {\n const next = consolidateColumns(\n mergeColumnOrder(columns, controlledOrder ?? prev),\n layoutMode\n );\n return JSON.stringify(next) === JSON.stringify(prev) ? prev : next;\n });\n }, [columns, controlledOrder, layoutMode]);\n\n const setLayout = React.useCallback(\n (mode: DashboardLayout) => {\n if (controlledLayout === undefined) setInternalLayout(mode);\n saveLayout(storageKey, mode);\n onLayoutChange?.(mode);\n },\n [controlledLayout, storageKey, onLayoutChange]\n );\n\n const commitOrder = React.useCallback(\n (next: DashboardOrder) => {\n saveOrder(storageKey, next);\n onOrderChange?.(next);\n\n // Auto-shrink only when trailing columns are empty (gaps keep their\n // column so no item is hidden by a reduced layout)\n const occupied = requiredColumns(next);\n if (occupied < layoutModeRef.current) {\n setLayout(occupied);\n }\n },\n [storageKey, onOrderChange, setLayout]\n );\n\n const handleLayoutChange = React.useCallback(\n (mode: DashboardLayout) => {\n setLayout(mode);\n // Consolidate so droppable ids match visible columns; persist/notify\n // outside the state updater so replayed renders can't double-fire.\n const next = consolidateColumns(colOrderRef.current, mode);\n if (next !== colOrderRef.current) {\n setColOrder(next);\n saveOrder(storageKey, next);\n onOrderChange?.(next);\n }\n },\n [setLayout, storageKey, onOrderChange]\n );\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),\n useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })\n );\n\n const resolve = (ids: string[]): PortletItem[] =>\n ids\n .filter((id) => !hiddenSet.has(id))\n .map((id) => itemMap.get(id))\n .filter(Boolean) as PortletItem[];\n\n const handleDragStart = React.useCallback(\n (event: DragStartEvent) => {\n prevColOrder.current = colOrder;\n draggingRef.current = true;\n setActiveId(String(event.active.id));\n },\n [colOrder]\n );\n\n const handleDragOver = React.useCallback((event: DragOverEvent) => {\n const { active, over } = event;\n if (!over) return;\n const next = moveAcrossColumns(\n colOrderRef.current,\n String(active.id),\n String(over.id)\n );\n if (next !== colOrderRef.current) setColOrder(next);\n }, []);\n\n const handleDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n draggingRef.current = false;\n setActiveId(null);\n\n if (!over) {\n setColOrder(prevColOrder.current);\n return;\n }\n\n const activeItemId = String(active.id);\n // A drag that ends in a different column than it started already sits\n // where moveAcrossColumns placed it; reordering again would flip it\n // to the other side of the hovered item.\n const crossedColumns =\n findColumn(prevColOrder.current, activeItemId) !==\n findColumn(colOrderRef.current, activeItemId);\n const next = reorderOnDrop(\n colOrderRef.current,\n activeItemId,\n String(over.id),\n crossedColumns\n );\n if (next !== colOrderRef.current) setColOrder(next);\n // A drag that ends where it started is a no-op: skip the commit so it\n // can't write storage, notify hosts, or auto-shrink the layout.\n if (JSON.stringify(next) !== JSON.stringify(prevColOrder.current)) {\n commitOrder(next);\n }\n },\n [commitOrder]\n );\n\n const handleDragCancel = React.useCallback(() => {\n draggingRef.current = false;\n setActiveId(null);\n setColOrder(prevColOrder.current);\n }, []);\n\n const setHidden = React.useCallback(\n (ids: string[]) => {\n if (controlledHidden === undefined) setInternalHidden(ids);\n saveHidden(storageKey, ids);\n onHiddenChange?.(ids);\n },\n [controlledHidden, storageKey, onHiddenChange]\n );\n\n const handleToggleWidget = React.useCallback(\n (id: string, visible: boolean) => {\n setHidden(\n visible ? hiddenList.filter((h) => h !== id) : [...hiddenList, id]\n );\n },\n [hiddenList, setHidden]\n );\n\n const handleReset = React.useCallback(() => {\n if (storageKey) {\n try {\n localStorage.removeItem(orderStorageKey(storageKey));\n localStorage.removeItem(layoutStorageKey(storageKey));\n localStorage.removeItem(hiddenStorageKey(storageKey));\n } catch {\n /* storage unavailable */\n }\n }\n const next = mergeColumnOrder(columns, defaultOrder ?? null);\n setColOrder(next);\n onOrderChange?.(next);\n if (controlledLayout === undefined) setInternalLayout(defaultLayout);\n onLayoutChange?.(defaultLayout);\n const hidden = defaultHiddenIds ?? [];\n if (controlledHidden === undefined) setInternalHidden(hidden);\n onHiddenChange?.(hidden);\n }, [\n storageKey,\n columns,\n defaultOrder,\n onOrderChange,\n controlledLayout,\n defaultLayout,\n onLayoutChange,\n defaultHiddenIds,\n controlledHidden,\n onHiddenChange,\n ]);\n\n const cols: DashboardColumns = [\n resolve(colOrder[0]),\n resolve(colOrder[1]),\n resolve(colOrder[2]),\n ];\n\n const visibleCols =\n layoutMode === 1 ? [cols[0]] : layoutMode === 2 ? [cols[0], cols[1]] : cols;\n\n const toolbar = (\n <div className=\"flex items-center justify-end gap-3 pb-2\">\n {title && (\n <h2 className=\"text-foreground me-auto text-lg font-semibold\">\n {title}\n </h2>\n )}\n {widgets && widgets.length > 0 && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setPanelOpen(true)}\n aria-haspopup=\"dialog\"\n leftIcon={\n <SlidersHorizontal aria-hidden=\"true\" className=\"h-4 w-4\" />\n }\n >\n {customizeLabel}\n </Button>\n )}\n <div\n className=\"border-border bg-muted flex gap-0.5 rounded-md border p-0.5 max-md:hidden\"\n role=\"radiogroup\"\n aria-label=\"Column layout\"\n >\n {([3, 2, 1] as const).map((mode) => {\n const Icon = mode === 3 ? Columns3 : mode === 2 ? Columns2 : Square;\n return (\n <button\n key={mode}\n type=\"button\"\n className={cn(\n 'flex h-7 w-7 items-center justify-center rounded transition-colors',\n layoutMode === mode\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:bg-background hover:text-foreground'\n )}\n onClick={() => handleLayoutChange(mode)}\n role=\"radio\"\n aria-checked={layoutMode === mode}\n aria-label={`${mode} column layout`}\n title={`${mode} column${mode > 1 ? 's' : ''}`}\n >\n <Icon aria-hidden=\"true\" className=\"h-4 w-4\" />\n </button>\n );\n })}\n </div>\n </div>\n );\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={collisionDetection}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n >\n {toolbarSlot ? createPortal(toolbar, toolbarSlot) : toolbar}\n <div\n ref={ref}\n className={cn(\n 'grid items-start gap-3',\n layoutMode === 3 && 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',\n layoutMode === 2 && 'grid-cols-1 md:grid-cols-2',\n layoutMode === 1 && 'grid-cols-1',\n className\n )}\n role=\"region\"\n aria-label={ariaLabel ?? 'Dashboard'}\n >\n {visibleCols.map((col, i) => (\n <DroppableColumn\n key={COL_IDS[i]}\n id={COL_IDS[i]}\n items={col}\n columnIndex={i}\n handleSelector={dragHandleSelector}\n flatten={layoutMode === 3}\n dragActive={activeId !== null}\n />\n ))}\n </div>\n {widgets && widgets.length > 0 && (\n <DashboardCustomizePanel\n open={panelOpen}\n onOpenChange={setPanelOpen}\n widgets={widgets}\n hiddenIds={hiddenList}\n onToggleWidget={handleToggleWidget}\n onReset={handleReset}\n />\n )}\n </DndContext>\n );\n});\n"]}
|