@parto-system-design/ui 1.1.5 → 1.1.8
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/AGENTS.md +233 -0
- package/LICENSE +21 -0
- package/README.md +96 -43
- package/dist/chunk-2ACKKPWA.cjs +112 -0
- package/dist/chunk-2ACKKPWA.cjs.map +1 -0
- package/dist/chunk-2UD3LGVX.cjs +316 -0
- package/dist/chunk-2UD3LGVX.cjs.map +1 -0
- package/dist/chunk-3QYYPPFJ.js +269 -0
- package/dist/chunk-3QYYPPFJ.js.map +1 -0
- package/dist/chunk-4SVQNEVH.js +173 -0
- package/dist/chunk-4SVQNEVH.js.map +1 -0
- package/dist/chunk-4WONHORR.cjs +152 -0
- package/dist/chunk-4WONHORR.cjs.map +1 -0
- package/dist/chunk-5HCXH6GS.js +409 -0
- package/dist/chunk-5HCXH6GS.js.map +1 -0
- package/dist/chunk-5JJSRGJD.js +31 -0
- package/dist/chunk-5JJSRGJD.js.map +1 -0
- package/dist/chunk-5K6E4ZSW.cjs +77 -0
- package/dist/chunk-5K6E4ZSW.cjs.map +1 -0
- package/dist/chunk-5NY26ULO.js +89 -0
- package/dist/chunk-5NY26ULO.js.map +1 -0
- package/dist/chunk-7RVPG3LE.cjs +231 -0
- package/dist/chunk-7RVPG3LE.cjs.map +1 -0
- package/dist/chunk-AYEK3WOM.js +207 -0
- package/dist/chunk-AYEK3WOM.js.map +1 -0
- package/dist/chunk-BRMBLIQG.js +53 -0
- package/dist/chunk-BRMBLIQG.js.map +1 -0
- package/dist/chunk-CAJKSTXX.cjs +54 -0
- package/dist/chunk-CAJKSTXX.cjs.map +1 -0
- package/dist/chunk-CKFWMHQU.js +401 -0
- package/dist/chunk-CKFWMHQU.js.map +1 -0
- package/dist/chunk-CV3N3HVK.js +672 -0
- package/dist/chunk-CV3N3HVK.js.map +1 -0
- package/dist/chunk-D2EBLE2B.cjs +220 -0
- package/dist/chunk-D2EBLE2B.cjs.map +1 -0
- package/dist/chunk-GCZ6YATL.js +940 -0
- package/dist/chunk-GCZ6YATL.js.map +1 -0
- package/dist/chunk-GKRAZGDI.cjs +84 -0
- package/dist/chunk-GKRAZGDI.cjs.map +1 -0
- package/dist/chunk-GPYJ66CG.js +45 -0
- package/dist/chunk-GPYJ66CG.js.map +1 -0
- package/dist/chunk-HF6XU5NI.js +84 -0
- package/dist/chunk-HF6XU5NI.js.map +1 -0
- package/dist/chunk-HJPDZOMJ.cjs +87 -0
- package/dist/chunk-HJPDZOMJ.cjs.map +1 -0
- package/dist/chunk-HS3XI3CC.cjs +69 -0
- package/dist/chunk-HS3XI3CC.cjs.map +1 -0
- package/dist/chunk-HUCC3QH5.cjs +53 -0
- package/dist/chunk-HUCC3QH5.cjs.map +1 -0
- package/dist/chunk-HYZ6BQPS.cjs +425 -0
- package/dist/chunk-HYZ6BQPS.cjs.map +1 -0
- package/dist/chunk-ISCSZMYW.cjs +106 -0
- package/dist/chunk-ISCSZMYW.cjs.map +1 -0
- package/dist/chunk-IXFEFIDO.js +82 -0
- package/dist/chunk-IXFEFIDO.js.map +1 -0
- package/dist/chunk-JCJLN437.js +108 -0
- package/dist/chunk-JCJLN437.js.map +1 -0
- package/dist/chunk-JMKNNH63.cjs +982 -0
- package/dist/chunk-JMKNNH63.cjs.map +1 -0
- package/dist/chunk-JUBHQAA2.js +53 -0
- package/dist/chunk-JUBHQAA2.js.map +1 -0
- package/dist/chunk-K6G63EED.cjs +41 -0
- package/dist/chunk-K6G63EED.cjs.map +1 -0
- package/dist/chunk-KCWRCSI7.js +62 -0
- package/dist/chunk-KCWRCSI7.js.map +1 -0
- package/dist/chunk-KYM7NIJO.cjs +433 -0
- package/dist/chunk-KYM7NIJO.cjs.map +1 -0
- package/dist/chunk-L2L5CKC2.js +291 -0
- package/dist/chunk-L2L5CKC2.js.map +1 -0
- package/dist/chunk-M5CHZ5BA.js +124 -0
- package/dist/chunk-M5CHZ5BA.js.map +1 -0
- package/dist/chunk-MEK4RSGC.js +65 -0
- package/dist/chunk-MEK4RSGC.js.map +1 -0
- package/dist/chunk-MEKWH3GS.js +89 -0
- package/dist/chunk-MEKWH3GS.js.map +1 -0
- package/dist/chunk-MFTX2DDQ.js +27 -0
- package/dist/chunk-MFTX2DDQ.js.map +1 -0
- package/dist/chunk-MMC6M35Q.cjs +272 -0
- package/dist/chunk-MMC6M35Q.cjs.map +1 -0
- package/dist/chunk-NMH43BDC.js +130 -0
- package/dist/chunk-NMH43BDC.js.map +1 -0
- package/dist/chunk-NORDUD2T.cjs +135 -0
- package/dist/chunk-NORDUD2T.cjs.map +1 -0
- package/dist/chunk-NV4JOKWL.cjs +197 -0
- package/dist/chunk-NV4JOKWL.cjs.map +1 -0
- package/dist/chunk-O2JG7WY5.cjs +121 -0
- package/dist/chunk-O2JG7WY5.cjs.map +1 -0
- package/dist/chunk-ONO2FTV4.cjs +68 -0
- package/dist/chunk-ONO2FTV4.cjs.map +1 -0
- package/dist/chunk-OQB6HIUL.cjs +108 -0
- package/dist/chunk-OQB6HIUL.cjs.map +1 -0
- package/dist/chunk-OS6CMYAS.cjs +79 -0
- package/dist/chunk-OS6CMYAS.cjs.map +1 -0
- package/dist/chunk-PYURPUTV.js +402 -0
- package/dist/chunk-PYURPUTV.js.map +1 -0
- package/dist/chunk-RJ3HYZ7S.js +44 -0
- package/dist/chunk-RJ3HYZ7S.js.map +1 -0
- package/dist/chunk-RZNRIOLT.js +128 -0
- package/dist/chunk-RZNRIOLT.js.map +1 -0
- package/dist/chunk-S3T2L6NA.js +38 -0
- package/dist/chunk-S3T2L6NA.js.map +1 -0
- package/dist/chunk-S5IPJQZ3.cjs +161 -0
- package/dist/chunk-S5IPJQZ3.cjs.map +1 -0
- package/dist/chunk-SB5DSYR5.js +211 -0
- package/dist/chunk-SB5DSYR5.js.map +1 -0
- package/dist/chunk-SFXV2DUH.js +106 -0
- package/dist/chunk-SFXV2DUH.js.map +1 -0
- package/dist/chunk-SXEPGD4Z.cjs +152 -0
- package/dist/chunk-SXEPGD4Z.cjs.map +1 -0
- package/dist/chunk-SXWSOU3Y.js +89 -0
- package/dist/chunk-SXWSOU3Y.js.map +1 -0
- package/dist/chunk-SZMVOHT7.cjs +107 -0
- package/dist/chunk-SZMVOHT7.cjs.map +1 -0
- package/dist/chunk-TWJXOV4C.js +145 -0
- package/dist/chunk-TWJXOV4C.js.map +1 -0
- package/dist/chunk-U3ADRIVO.cjs +434 -0
- package/dist/chunk-U3ADRIVO.cjs.map +1 -0
- package/dist/chunk-U5FLLCGC.cjs +151 -0
- package/dist/chunk-U5FLLCGC.cjs.map +1 -0
- package/dist/chunk-UOZN45G4.cjs +130 -0
- package/dist/chunk-UOZN45G4.cjs.map +1 -0
- package/dist/chunk-VHLDOG74.cjs +167 -0
- package/dist/chunk-VHLDOG74.cjs.map +1 -0
- package/dist/chunk-YC5KLN6I.js +139 -0
- package/dist/chunk-YC5KLN6I.js.map +1 -0
- package/dist/chunk-YENXXYUV.cjs +111 -0
- package/dist/chunk-YENXXYUV.cjs.map +1 -0
- package/dist/chunk-YFQWC2PW.js +113 -0
- package/dist/chunk-YFQWC2PW.js.map +1 -0
- package/dist/chunk-Z2TY4A75.cjs +700 -0
- package/dist/chunk-Z2TY4A75.cjs.map +1 -0
- package/dist/chunk-Z56O7UEU.cjs +136 -0
- package/dist/chunk-Z56O7UEU.cjs.map +1 -0
- package/dist/chunk-ZBZDR4ZC.js +106 -0
- package/dist/chunk-ZBZDR4ZC.js.map +1 -0
- package/dist/components/charts/PartoAreaChart.cjs +15 -0
- package/dist/components/charts/PartoAreaChart.cjs.map +1 -0
- package/dist/components/charts/PartoAreaChart.d.cts +53 -0
- package/dist/components/charts/PartoAreaChart.d.ts +53 -0
- package/dist/components/charts/PartoAreaChart.js +6 -0
- package/dist/components/charts/PartoAreaChart.js.map +1 -0
- package/dist/components/charts/PartoBarChart.cjs +15 -0
- package/dist/components/charts/PartoBarChart.cjs.map +1 -0
- package/dist/components/charts/PartoBarChart.d.cts +61 -0
- package/dist/components/charts/PartoBarChart.d.ts +61 -0
- package/dist/components/charts/PartoBarChart.js +6 -0
- package/dist/components/charts/PartoBarChart.js.map +1 -0
- package/dist/components/charts/PartoLineChart.cjs +15 -0
- package/dist/components/charts/PartoLineChart.cjs.map +1 -0
- package/dist/components/charts/PartoLineChart.d.cts +57 -0
- package/dist/components/charts/PartoLineChart.d.ts +57 -0
- package/dist/components/charts/PartoLineChart.js +6 -0
- package/dist/components/charts/PartoLineChart.js.map +1 -0
- package/dist/components/charts/PartoPieChart.cjs +15 -0
- package/dist/components/charts/PartoPieChart.cjs.map +1 -0
- package/dist/components/charts/PartoPieChart.d.cts +52 -0
- package/dist/components/charts/PartoPieChart.d.ts +52 -0
- package/dist/components/charts/PartoPieChart.js +6 -0
- package/dist/components/charts/PartoPieChart.js.map +1 -0
- package/dist/components/ui/alert-rule-card.cjs +15 -0
- package/dist/components/ui/alert-rule-card.cjs.map +1 -0
- package/dist/components/ui/alert-rule-card.d.cts +38 -0
- package/dist/components/ui/alert-rule-card.d.ts +38 -0
- package/dist/components/ui/alert-rule-card.js +6 -0
- package/dist/components/ui/alert-rule-card.js.map +1 -0
- package/dist/components/ui/avatar.cjs +21 -0
- package/dist/components/ui/avatar.cjs.map +1 -0
- package/dist/components/ui/avatar.d.cts +18 -0
- package/dist/components/ui/avatar.d.ts +18 -0
- package/dist/components/ui/avatar.js +4 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.cjs +17 -0
- package/dist/components/ui/badge.cjs.map +1 -0
- package/dist/components/ui/badge.d.cts +16 -0
- package/dist/components/ui/badge.d.ts +16 -0
- package/dist/components/ui/badge.js +4 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/button.cjs +18 -0
- package/dist/components/ui/button.cjs.map +1 -0
- package/dist/components/ui/button.d.cts +37 -0
- package/dist/components/ui/button.d.ts +37 -0
- package/dist/components/ui/button.js +5 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.cjs +15 -0
- package/dist/components/ui/calendar.cjs.map +1 -0
- package/dist/components/ui/calendar.d.cts +17 -0
- package/dist/components/ui/calendar.d.ts +17 -0
- package/dist/components/ui/calendar.js +6 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.cjs +37 -0
- package/dist/components/ui/card.cjs.map +1 -0
- package/dist/components/ui/card.d.cts +18 -0
- package/dist/components/ui/card.d.ts +18 -0
- package/dist/components/ui/card.js +4 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/concept-card.cjs +18 -0
- package/dist/components/ui/concept-card.cjs.map +1 -0
- package/dist/components/ui/concept-card.d.cts +5 -0
- package/dist/components/ui/concept-card.d.ts +5 -0
- package/dist/components/ui/concept-card.js +9 -0
- package/dist/components/ui/concept-card.js.map +1 -0
- package/dist/components/ui/data-table.cjs +18 -0
- package/dist/components/ui/data-table.cjs.map +1 -0
- package/dist/components/ui/data-table.d.cts +181 -0
- package/dist/components/ui/data-table.d.ts +181 -0
- package/dist/components/ui/data-table.js +9 -0
- package/dist/components/ui/data-table.js.map +1 -0
- package/dist/components/ui/dialog.cjs +49 -0
- package/dist/components/ui/dialog.cjs.map +1 -0
- package/dist/components/ui/dialog.d.cts +22 -0
- package/dist/components/ui/dialog.d.ts +22 -0
- package/dist/components/ui/dialog.js +4 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/filter-provider.cjs +20 -0
- package/dist/components/ui/filter-provider.cjs.map +1 -0
- package/dist/components/ui/filter-provider.d.cts +49 -0
- package/dist/components/ui/filter-provider.d.ts +49 -0
- package/dist/components/ui/filter-provider.js +3 -0
- package/dist/components/ui/filter-provider.js.map +1 -0
- package/dist/components/ui/input.cjs +22 -0
- package/dist/components/ui/input.cjs.map +1 -0
- package/dist/components/ui/input.d.cts +16 -0
- package/dist/components/ui/input.d.ts +16 -0
- package/dist/components/ui/input.js +5 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/iran-province-heat.cjs +13 -0
- package/dist/components/ui/iran-province-heat.cjs.map +1 -0
- package/dist/components/ui/iran-province-heat.d.cts +64 -0
- package/dist/components/ui/iran-province-heat.d.ts +64 -0
- package/dist/components/ui/iran-province-heat.js +4 -0
- package/dist/components/ui/iran-province-heat.js.map +1 -0
- package/dist/components/ui/page-card.cjs +16 -0
- package/dist/components/ui/page-card.cjs.map +1 -0
- package/dist/components/ui/page-card.d.cts +6 -0
- package/dist/components/ui/page-card.d.ts +6 -0
- package/dist/components/ui/page-card.js +7 -0
- package/dist/components/ui/page-card.js.map +1 -0
- package/dist/components/ui/popover.cjs +25 -0
- package/dist/components/ui/popover.cjs.map +1 -0
- package/dist/components/ui/popover.d.cts +9 -0
- package/dist/components/ui/popover.d.ts +9 -0
- package/dist/components/ui/popover.js +4 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/saved-query-card.cjs +15 -0
- package/dist/components/ui/saved-query-card.cjs.map +1 -0
- package/dist/components/ui/saved-query-card.d.cts +41 -0
- package/dist/components/ui/saved-query-card.d.ts +41 -0
- package/dist/components/ui/saved-query-card.js +6 -0
- package/dist/components/ui/saved-query-card.js.map +1 -0
- package/dist/components/ui/separator.cjs +13 -0
- package/dist/components/ui/separator.cjs.map +1 -0
- package/dist/components/ui/separator.d.cts +9 -0
- package/dist/components/ui/separator.d.ts +9 -0
- package/dist/components/ui/separator.js +4 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.cjs +45 -0
- package/dist/components/ui/sheet.cjs.map +1 -0
- package/dist/components/ui/sheet.d.cts +44 -0
- package/dist/components/ui/sheet.d.ts +44 -0
- package/dist/components/ui/sheet.js +4 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/sparkline.cjs +13 -0
- package/dist/components/ui/sparkline.cjs.map +1 -0
- package/dist/components/ui/sparkline.d.cts +36 -0
- package/dist/components/ui/sparkline.d.ts +36 -0
- package/dist/components/ui/sparkline.js +4 -0
- package/dist/components/ui/sparkline.js.map +1 -0
- package/dist/components/ui/tooltip.cjs +25 -0
- package/dist/components/ui/tooltip.cjs.map +1 -0
- package/dist/components/ui/tooltip.d.cts +17 -0
- package/dist/components/ui/tooltip.d.ts +17 -0
- package/dist/components/ui/tooltip.js +4 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/concept-card-CcOBb2Nz.d.ts +83 -0
- package/dist/concept-card-RwPbqJ06.d.cts +83 -0
- package/dist/hooks/use-hotkey-registry.cjs +21 -0
- package/dist/hooks/use-hotkey-registry.cjs.map +1 -0
- package/dist/hooks/use-hotkey-registry.d.cts +65 -0
- package/dist/hooks/use-hotkey-registry.d.ts +65 -0
- package/dist/hooks/use-hotkey-registry.js +4 -0
- package/dist/hooks/use-hotkey-registry.js.map +1 -0
- package/dist/hooks/use-hotkeys.cjs +16 -0
- package/dist/hooks/use-hotkeys.cjs.map +1 -0
- package/dist/hooks/use-hotkeys.d.cts +66 -0
- package/dist/hooks/use-hotkeys.d.ts +66 -0
- package/dist/hooks/use-hotkeys.js +3 -0
- package/dist/hooks/use-hotkeys.js.map +1 -0
- package/dist/i18n-ArS3mqj0.d.ts +344 -0
- package/dist/i18n-CAd9wGOr.d.cts +344 -0
- package/dist/index.cjs +12195 -13224
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +490 -34
- package/dist/index.d.cts +1635 -1263
- package/dist/index.d.ts +1635 -1263
- package/dist/index.js +10693 -12364
- package/dist/index.js.map +1 -1
- package/dist/page-card-CmShVqG-.d.cts +100 -0
- package/dist/page-card-HBn-cy4J.d.ts +100 -0
- package/dist/utils-DlXWmDZ-.d.cts +35 -0
- package/dist/utils-DlXWmDZ-.d.ts +35 -0
- package/package.json +160 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/flow-distribution.tsx","../src/components/ui/sentiment-distribution.tsx","../src/components/ui/concept-card.tsx"],"names":["FLOW_KEYS","React","flowLabels","jsx","cn","jsxs","convertToLocalNumbers","calcPercents","React2","React3","StatusBadge","SeverityBadge","Checkbox","Sparkline"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAS,aAAa,IAAA,EAAyC;AAC7D,EAAA,MAAM,KAAA,GAAQA,2BAAA,CAAU,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,IAAK,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,CAAA,EAAI,CAAC,CAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,WAAA,CAAYA,2BAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA;AAC9D,EAAA,IAAI,KAAA,KAAU,GAAG,OAAO,MAAA;AAExB,EAAA,MAAM,MAAA,GAASA,2BAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAA,CAAO,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM;AACpE,IAAA,MAAM,CAAA,GAAA,CAAM,IAAA,CAAK,CAAC,CAAA,IAAK,KAAK,KAAA,GAAS,GAAA;AACrC,IAAA,OAAO,EAAE,CAAA,EAAG,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAG,GAAA,EAAK,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAE;AAAA,EAC3D,CAAC,CAAA;AACD,EAAA,MAAM,SAAA,GAAY,GAAA,GAAM,MAAA,CAAO,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,KAAA,EAAO,CAAC,CAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,GAAG,CAAA;AACvD,EAAA,MAAA,CAAO,KAAA,CAAM,GAAG,SAAS,CAAA,CAAE,QAAQ,CAAC,CAAA,KAAM,EAAE,KAAA,EAAO,CAAA;AACnD,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,EAAE,CAAA,EAAG,OAAM,KAAO,MAAA,CAAO,CAAC,CAAA,GAAI,KAAM,CAAA;AACpD,EAAA,OAAO,MAAA;AACT;AAGA,IAAM,aAAA,GAAoC;AAAA,EACxC,SAAA;AAAA,EACA,iBAAA;AAAA,EACA,mBAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,SAAS,GAAA,EAAsB;AACtC,EAAA,OAAO,UAAU,GAAG,CAAA,CAAA;AACtB;AAEA,IAAM,gBAAA,GAAyBC,gBAAA,CAAA,UAAA;AAAA,EAC7B,CACE;AAAA,IACE,SAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA,GAAU,SAAA;AAAA,IACV,UAAA,GAAa,KAAA;AAAA,IACb,WAAA,GAAc,IAAA;AAAA,IACd,MAAA,GAAS,IAAA;AAAA,IACT,SAAA,GAAY,KAAA;AAAA,IACZ,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,MAAA,GAASC,4BAAA,CAAW,MAAM,CAAA,IAAKA,4BAAA,CAAW,EAAA;AAChD,IAAA,MAAM,QAAA,GAAW,aAAa,IAAI,CAAA;AAClC,IAAA,MAAM,WAAA,GAAc,MAAA,KAAW,IAAA,GAAO,GAAA,GAAM,QAAA;AAE5C,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,uBACEC,cAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAA,EAAU,mBAAA,EAAoB,SAAA,EAAWC,oBAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EAAI,GAAG,KAAA,EACrF,QAAA,EAAA,OAAA,KAAY,4BACXD,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDAAA,EAAiD,CAAA,GAC9D,OAAA,KAAY,SAAA,mBACdA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACZ,QAAA,EAAA,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,qBACdA,cAAA,CAAC,KAAA,EAAA,EAAY,SAAA,EAAU,8CAAA,EAAA,EAAb,CAA4D,CACvE,CAAA,EACH,CAAA,mBAEAA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACZ,QAAA,EAAA,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,qBACjBE,eAAA,CAAC,KAAA,EAAA,EAAY,SAAA,EAAU,yBAAA,EACrB,QAAA,EAAA;AAAA,wBAAAF,cAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yCAAA,EAA0C,CAAA;AAAA,wBACzDA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDAAA,EAAiD,CAAA;AAAA,wBAChEA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCAAA,EAAyC;AAAA,OAAA,EAAA,EAHhD,CAIV,CACD,CAAA,EACH,CAAA,EAEJ,CAAA;AAAA,IAEJ;AAEA,IAAA,IAAI,YAAY,SAAA,EAAW;AACzB,MAAA,MAAM,MAAA,GAAS,cAAc,MAAA,CAAO,CAAC,OAAO,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA;AAC7D,MAAA,MAAM,OAAA,GAAU,OACb,GAAA,CAAI,CAAC,MAAM,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA,EAAIG,wCAAsB,QAAA,CAAS,CAAC,GAAG,MAAM,CAAC,GAAG,WAAW,CAAA,CAAE,CAAA,CACrF,IAAA,CAAK,SAAI,CAAA;AAEZ,MAAA,uBACED,eAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAA,EAAU,mBAAA,EAAoB,SAAA,EAAWD,oBAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EAAI,GAAG,KAAA,EACtF,QAAA,EAAA;AAAA,wBAAAD,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uDAAA,EAAwD,IAAA,EAAK,KAAA,EAAM,cAAY,OAAA,EAC3F,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,qBACXA,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YAEC,SAAA,EAAU,6BAAA;AAAA,YACV,KAAA,EAAO,EAAE,KAAA,EAAO,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA,CAAA,EAAK,eAAA,EAAiB,CAAA,QAAA,EAAW,QAAA,CAAS,CAAC,CAAC,CAAA,EAAA,CAAA;AAAK,WAAA;AAAA,UAF1E;AAAA,SAIR,CAAA,EACH,CAAA;AAAA,wBACAA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gCAAA,EACZ,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,qBACXE,eAAA,CAAC,MAAA,EAAA,EAAa,SAAA,EAAU,gCAAA,EACtB,QAAA,EAAA;AAAA,0BAAAF,cAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,mCAAA;AAAA,cACV,OAAO,EAAE,eAAA,EAAiB,WAAW,QAAA,CAAS,CAAC,CAAC,CAAA,EAAA,CAAA;AAAK;AAAA,WACvD;AAAA,yCACC,MAAA,EAAA,EAAK,SAAA,EAAU,+BAAA,EAAiC,QAAA,EAAA,MAAA,CAAO,CAAC,CAAA,EAAE,CAAA;AAAA,UAC1D,WAAA,oBACCE,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kCAAA,EAAmC,KAAA,EAAO,EAAE,KAAA,EAAO,CAAA,QAAA,EAAW,QAAA,CAAS,CAAC,CAAC,MAAK,EAC3F,QAAA,EAAA;AAAA,YAAAC,uCAAA,CAAsB,QAAA,CAAS,CAAC,CAAA,EAAG,MAAM,CAAA;AAAA,YACzC;AAAA,WAAA,EACH,CAAA;AAAA,UAED,UAAA,oBACCD,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA;AAAA,YAAA,GAAA;AAAA,YACzDC,uCAAA,CAAsB,IAAA,CAAK,CAAC,CAAA,IAAK,GAAG,MAAM,CAAA;AAAA,YAAE;AAAA,WAAA,EAChD;AAAA,SAAA,EAAA,EAfO,CAiBX,CACD,CAAA,EACH;AAAA,OAAA,EACF,CAAA;AAAA,IAEJ;AAEA,IAAA,IAAI,YAAY,SAAA,EAAW;AACzB,MAAA,MAAM,MAAA,GAASN,4BAAU,MAAA,CAAO,CAAC,OAAO,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,OAAO,IAAA,CAAK,CAAC,KAAK,CAAA,KAAM,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,CAAE,CAAA;AACzG,MAAA,uBACEG,cAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,WAAA,EAAU,mBAAA;AAAA,UACV,SAAA,EAAWC,oBAAA,CAAG,6BAAA,EAA+B,SAAS,CAAA;AAAA,UACrD,GAAG,KAAA;AAAA,UAEH,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,qBACXC,eAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cAEC,SAAA,EAAU,yDAAA;AAAA,cACV,KAAA,EAAO;AAAA,gBACL,eAAA,EAAiB,CAAA,QAAA,EAAW,QAAA,CAAS,CAAC,CAAC,CAAA,SAAA,CAAA;AAAA,gBACvC,KAAA,EAAO,CAAA,QAAA,EAAW,QAAA,CAAS,CAAC,CAAC,CAAA,EAAA;AAAA,eAC/B;AAAA,cAEA,QAAA,EAAA;AAAA,gCAAAF,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAuB,QAAA,EAAA,MAAA,CAAO,CAAC,CAAA,EAAE,CAAA;AAAA,gBAChD,WAAA,oBACCE,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gCAAA,EACb,QAAA,EAAA;AAAA,kBAAAC,uCAAA,CAAsB,QAAA,CAAS,CAAC,CAAA,EAAG,MAAM,CAAA;AAAA,kBACzC;AAAA,iBAAA,EACH,CAAA;AAAA,gBAED,UAAA,oBACCD,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA;AAAA,kBAAA,GAAA;AAAA,kBACzDC,uCAAA,CAAsB,IAAA,CAAK,CAAC,CAAA,IAAK,GAAG,MAAM,CAAA;AAAA,kBAAE;AAAA,iBAAA,EAChD;AAAA;AAAA,aAAA;AAAA,YAjBG;AAAA,WAoBR;AAAA;AAAA,OACH;AAAA,IAEJ;AAGA,IAAA,MAAM,MAAA,GAASN,4BAAU,MAAA,CAAO,CAAC,OAAO,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,OAAO,IAAA,CAAK,CAAC,KAAK,CAAA,KAAM,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,CAAE,CAAA;AAEzG,IAAA,sCACG,KAAA,EAAA,EAAI,GAAA,EAAU,aAAU,mBAAA,EAAoB,SAAA,EAAWI,qBAAG,aAAA,EAAe,SAAS,GAAI,GAAG,KAAA,EACvF,iBAAO,GAAA,CAAI,CAAC,sBACXC,eAAA,CAAC,KAAA,EAAA,EAAY,WAAU,yBAAA,EACrB,QAAA,EAAA;AAAA,sBAAAF,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sDAAA,EAAwD,QAAA,EAAA,MAAA,CAAO,CAAC,CAAA,EAAE,CAAA;AAAA,sBAClFA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2DAAA,EACb,QAAA,kBAAAA,cAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,qEAAA;AAAA,UACV,KAAA,EAAO;AAAA,YACL,KAAA,EAAO,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA,CAAA;AAAA,YACrB,eAAA,EAAiB,CAAA,QAAA,EAAW,QAAA,CAAS,CAAC,CAAC,CAAA,EAAA;AAAA,WACzC;AAAA,UACA,IAAA,EAAK,aAAA;AAAA,UACL,eAAA,EAAe,SAAS,CAAC,CAAA;AAAA,UACzB,eAAA,EAAe,CAAA;AAAA,UACf,eAAA,EAAe,GAAA;AAAA,UACf,YAAA,EAAY,GAAG,MAAA,CAAO,CAAC,CAAC,CAAA,EAAA,EAAK,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA;AAAA;AAAA,OAC1C,EACF,CAAA;AAAA,sBACAA,cAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,2DAAA;AAAA,UACV,OAAO,EAAE,KAAA,EAAO,WAAW,QAAA,CAAS,CAAC,CAAC,CAAA,EAAA,CAAA,EAAK;AAAA,UAE1C,uBACGG,uCAAA,CAAA,CAAuB,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,EAAG,gBAAe,EAAG,MAAM,CAAA,GAC7D,CAAA,EAAGA,wCAAsB,QAAA,CAAS,CAAC,GAAG,MAAM,CAAC,GAAG,WAAW,CAAA;AAAA;AAAA;AACjE,KAAA,EAAA,EAvBQ,CAwBV,CACD,CAAA,EACH,CAAA;AAAA,EAEJ;AACF;AAEA,gBAAA,CAAiB,WAAA,GAAc,kBAAA;ACzL/B,IAAM,MAAA,GAAuE;AAAA,EAC3E,EAAA,EAAI,EAAE,QAAA,EAAU,0BAAA,EAAQ,UAAU,0BAAA,EAAQ,OAAA,EAAS,0BAAA,EAAQ,KAAA,EAAO,sCAAA,EAAS;AAAA,EAC3E,EAAA,EAAI,EAAE,QAAA,EAAU,sCAAA,EAAU,UAAU,0BAAA,EAAQ,OAAA,EAAS,gCAAA,EAAS,KAAA,EAAO,gCAAA,EAAQ;AAAA,EAC7E,EAAA,EAAI,EAAE,QAAA,EAAU,UAAA,EAAY,UAAU,UAAA,EAAY,OAAA,EAAS,SAAA,EAAW,KAAA,EAAO,OAAA;AAC/E,CAAA;AAEA,IAAM,gBAAA,GAA2F;AAAA,EAC/F,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,qCAAA;AAAA,IACL,IAAA,EAAM,uCAAA;AAAA,IACN,EAAA,EAAI;AAAA,GACN;AAAA,EACA,QAAA,EAAU;AAAA,IACR,GAAA,EAAK,qCAAA;AAAA,IACL,IAAA,EAAM,uCAAA;AAAA,IACN,EAAA,EAAI;AAAA,GACN;AAAA,EACA,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,oCAAA;AAAA,IACL,IAAA,EAAM,sCAAA;AAAA,IACN,EAAA,EAAI;AAAA,GACN;AAAA,EACA,KAAA,EAAO;AAAA,IACL,GAAA,EAAK,kCAAA;AAAA,IACL,IAAA,EAAM,oCAAA;AAAA,IACN,EAAA,EAAI;AAAA;AAER,CAAA;AAEA,SAASC,cAAa,IAAA,EAA0D;AAC9E,EAAA,MAAM,IAAA,GAAQ,CAAC,UAAA,EAAY,UAAA,EAAY,WAAW,OAAO,CAAA,CAAY,MAAA,CAAO,CAAC,CAAA,KAAA,CAAO,IAAA,CAAK,CAAC,CAAA,IAAK,KAAK,CAAC,CAAA;AACrG,EAAA,MAAM,QAAS,CAAC,UAAA,EAAY,UAAA,EAAY,SAAA,EAAW,OAAO,CAAA,CAAY,MAAA,CAAO,CAAC,GAAA,EAAK,MAAM,GAAA,IAAO,IAAA,CAAK,CAAC,CAAA,IAAK,IAAI,CAAC,CAAA;AAChH,EAAA,IAAI,KAAA,KAAU,CAAA,EAAG,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,CAAA,EAAE;AAGzE,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,CAAC,OAAO,EAAE,CAAA,EAAG,CAAA,EAAA,CAAK,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,IAAK,KAAA,GAAS,KAAI,CAAE,CAAA;AACzE,EAAA,MAAM,MAAA,GAAS,OAAO,GAAA,CAAI,CAAC,EAAE,CAAA,EAAG,CAAA,QAAS,EAAE,CAAA,EAAG,OAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAG,GAAA,EAAK,IAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAE,CAAE,CAAA;AAC7F,EAAA,MAAM,SAAA,GAAY,GAAA,GAAM,MAAA,CAAO,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,KAAA,EAAO,CAAC,CAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,GAAG,CAAA;AACvD,EAAA,MAAA,CAAO,KAAA,CAAM,GAAG,SAAS,CAAA,CAAE,QAAQ,CAAC,CAAA,KAAM,EAAE,KAAA,EAAO,CAAA;AAEnD,EAAA,MAAM,MAAA,GAAiC,EAAE,QAAA,EAAU,CAAA,EAAG,UAAU,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,CAAA,EAAE;AACxF,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,EAAE,CAAA,EAAG,OAAM,KAAO,MAAA,CAAO,CAAC,CAAA,GAAI,KAAM,CAAA;AACpD,EAAA,OAAO,MAAA;AACT;AAEA,IAAM,eAAA,GAA8C,CAAC,UAAA,EAAY,SAAA,EAAW,SAAS,UAAU,CAAA;AAE/F,IAAM,qBAAA,GAA8BC,gBAAA,CAAA,UAAA;AAAA,EAClC,CACE;AAAA,IACE,SAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA,GAAU,MAAA;AAAA,IACV,UAAA,GAAa,KAAA;AAAA,IACb,WAAA,GAAc,IAAA;AAAA,IACd,MAAA,GAAS,IAAA;AAAA,IACT,SAAA,GAAY,KAAA;AAAA,IACZ,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAM,CAAA,IAAK,MAAA,CAAO,EAAA;AACxC,IAAA,MAAM,QAAA,GAAWD,cAAa,IAAI,CAAA;AAClC,IAAA,MAAM,WAAA,GAAc,gBAAgB,MAAA,CAAO,CAAC,SAAS,IAAA,CAAK,GAAG,CAAA,IAAK,CAAA,IAAK,CAAC,CAAA;AAExE,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,uBACEJ,cAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAA,EAAU,wBAAA,EAAyB,SAAA,EAAWC,oBAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EAAI,GAAG,KAAA,EAC1F,QAAA,EAAA,OAAA,KAAY,SAAA,mBACXD,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDAAA,EAAiD,CAAA,GAC9D,OAAA,KAAY,SAAA,mBACdA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,YAAA,EACZ,WAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,qBACdA,cAAAA,CAAC,KAAA,EAAA,EAAY,SAAA,EAAU,yCAAA,EAAA,EAAb,CAAuD,CAClE,CAAA,EACH,CAAA,mBAEAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACZ,QAAA,EAAA,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,qBACdE,eAAAA,CAAC,KAAA,EAAA,EAAY,WAAU,yBAAA,EACrB,QAAA,EAAA;AAAA,wBAAAF,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yCAAA,EAA0C,CAAA;AAAA,wBACzDA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDAAA,EAAiD,CAAA;AAAA,wBAChEA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCAAA,EAAyC;AAAA,OAAA,EAAA,EAHhD,CAIV,CACD,CAAA,EACH,CAAA,EAEJ,CAAA;AAAA,IAEJ;AAGA,IAAA,IAAI,YAAY,SAAA,EAAW;AACzB,MAAA,uBACEE,eAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAA,EAAU,wBAAA,EAAyB,SAAA,EAAWD,oBAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EAAI,GAAG,KAAA,EAE3F,QAAA,EAAA;AAAA,wBAAAD,cAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,uDAAA;AAAA,YACV,IAAA,EAAK,KAAA;AAAA,YACL,cAAY,CAAA,EAAG,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,QAAA,CAAS,QAAQ,CAAA,aAAA,EAAM,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,SAAS,QAAQ,CAAA,aAAA,EAAM,OAAO,OAAO,CAAA,CAAA,EAAI,SAAS,OAAO,CAAA,MAAA,CAAA;AAAA,YAEpI,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,qBAChBA,cAAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBAEC,WAAWC,oBAAA,CAAG,6BAAA,EAA+B,gBAAA,CAAiB,GAAG,EAAE,GAAG,CAAA;AAAA,gBACtE,OAAO,EAAE,KAAA,EAAO,GAAG,QAAA,CAAS,GAAG,CAAC,CAAA,CAAA,CAAA;AAAI,eAAA;AAAA,cAF/B;AAAA,aAIR;AAAA;AAAA,SACH;AAAA,wBAGAD,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gCAAA,EACZ,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,qBAChBE,eAAAA,CAAC,MAAA,EAAA,EAAe,WAAU,gCAAA,EACxB,QAAA,EAAA;AAAA,0BAAAF,cAAAA,CAAC,UAAK,SAAA,EAAWC,oBAAA,CAAG,qCAAqC,gBAAA,CAAiB,GAAG,CAAA,CAAE,GAAG,CAAA,EAAG,CAAA;AAAA,0BACrFD,cAAAA,CAAC,MAAA,EAAA,EAAK,WAAU,+BAAA,EAAiC,QAAA,EAAA,MAAA,CAAO,GAAG,CAAA,EAAE,CAAA;AAAA,UAC5D,WAAA,oBACCE,eAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAWD,oBAAA,CAAG,qBAAA,EAAuB,gBAAA,CAAiB,GAAG,CAAA,CAAE,IAAI,CAAA,EAClE,QAAA,EAAA;AAAA,YAAAE,uCAAA,CAAsB,QAAA,CAAS,GAAG,CAAA,EAAG,MAAM,CAAA;AAAA,YAC3C,MAAA,KAAW,OAAO,GAAA,GAAM;AAAA,WAAA,EAC3B,CAAA;AAAA,UAED,UAAA,oBACCD,eAAAA,CAAC,MAAA,EAAA,EAAK,WAAU,+BAAA,EAAgC,QAAA,EAAA;AAAA,YAAA,GAAA;AAAA,YAC5CC,uCAAA,CAAsB,IAAA,CAAK,GAAG,CAAA,IAAK,GAAG,MAAM,CAAA;AAAA,YAAE;AAAA,WAAA,EAClD;AAAA,SAAA,EAAA,EAZO,GAcX,CACD,CAAA,EACH;AAAA,OAAA,EACF,CAAA;AAAA,IAEJ;AAGA,IAAA,IAAI,YAAY,SAAA,EAAW;AACzB,MAAA,uBACEH,cAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,WAAA,EAAU,wBAAA;AAAA,UACV,SAAA,EAAWC,oBAAA,CAAG,6BAAA,EAA+B,SAAS,CAAA;AAAA,UACrD,GAAG,KAAA;AAAA,UAEH,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,qBAChBC,eAAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cAEC,WAAWD,oBAAA,CAAG,yDAAA,EAA2D,gBAAA,CAAiB,GAAG,EAAE,EAAE,CAAA;AAAA,cAEjG,QAAA,EAAA;AAAA,gCAAAD,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAWC,oBAAA,CAAG,qBAAA,EAAuB,gBAAA,CAAiB,GAAG,CAAA,CAAE,IAAI,CAAA,EAAI,QAAA,EAAA,MAAA,CAAO,GAAG,CAAA,EAAE,CAAA;AAAA,gBACpF,WAAA,oBACCC,eAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAWD,oBAAA,CAAG,gCAAA,EAAkC,gBAAA,CAAiB,GAAG,CAAA,CAAE,IAAI,CAAA,EAC7E,QAAA,EAAA;AAAA,kBAAAE,uCAAA,CAAsB,QAAA,CAAS,GAAG,CAAA,EAAG,MAAM,CAAA;AAAA,kBAC3C,MAAA,KAAW,OAAO,GAAA,GAAM;AAAA,iBAAA,EAC3B,CAAA;AAAA,gBAED,UAAA,oBACCD,eAAAA,CAAC,MAAA,EAAA,EAAK,WAAU,4CAAA,EAA6C,QAAA,EAAA;AAAA,kBAAA,GAAA;AAAA,kBACzDC,yCAAuB,IAAA,CAAK,GAAG,KAAK,CAAA,EAAG,cAAA,IAAkB,MAAM,CAAA;AAAA,kBAAE;AAAA,iBAAA,EACrE;AAAA;AAAA,aAAA;AAAA,YAbG;AAAA,WAgBR;AAAA;AAAA,OACH;AAAA,IAEJ;AAGA,IAAA,uBACEH,eAAC,KAAA,EAAA,EAAI,GAAA,EAAU,aAAU,wBAAA,EAAyB,SAAA,EAAWC,qBAAG,aAAA,EAAe,SAAS,GAAI,GAAG,KAAA,EAC5F,sBAAY,GAAA,CAAI,CAAC,wBAChBC,eAAAA,CAAC,KAAA,EAAA,EAAc,SAAA,EAAU,yBAAA,EAEvB,QAAA,EAAA;AAAA,sBAAAF,eAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sDAAA,EAAwD,QAAA,EAAA,MAAA,CAAO,GAAG,CAAA,EAAE,CAAA;AAAA,sBAGpFA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6DACb,QAAA,kBAAAA,cAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAWC,oBAAA;AAAA,YACT,qEAAA;AAAA,YACA,gBAAA,CAAiB,GAAG,CAAA,CAAE;AAAA,WACxB;AAAA,UACA,OAAO,EAAE,KAAA,EAAO,GAAG,QAAA,CAAS,GAAG,CAAC,CAAA,CAAA,CAAA,EAAI;AAAA,UACpC,IAAA,EAAK,aAAA;AAAA,UACL,eAAA,EAAe,SAAS,GAAG,CAAA;AAAA,UAC3B,eAAA,EAAe,CAAA;AAAA,UACf,eAAA,EAAe,GAAA;AAAA,UACf,YAAA,EAAY,GAAG,MAAA,CAAO,GAAG,CAAC,CAAA,EAAA,EAAK,QAAA,CAAS,GAAG,CAAC,CAAA,CAAA;AAAA;AAAA,OAC9C,EACF,CAAA;AAAA,sBAGAD,cAAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,WAAWC,oBAAA,CAAG,2DAAA,EAA6D,gBAAA,CAAiB,GAAG,EAAE,IAAI,CAAA;AAAA,UAEpG,QAAA,EAAA,UAAA,GACGE,yCAAuB,IAAA,CAAK,GAAG,KAAK,CAAA,EAAG,cAAA,IAAkB,MAAM,CAAA,GAC/D,GAAGA,uCAAA,CAAsB,QAAA,CAAS,GAAG,CAAA,EAAG,MAAM,CAAC,CAAA,EAAG,MAAA,KAAW,IAAA,GAAO,GAAA,GAAM,QAAG,CAAA;AAAA;AAAA;AACnF,KAAA,EAAA,EA3BQ,GA4BV,CACD,CAAA,EACH,CAAA;AAAA,EAEJ;AACF;AAEA,qBAAA,CAAsB,WAAA,GAAc,uBAAA;ACtLpC,IAAM,WAAA,GAAoBG,gBAAA,CAAA,UAAA;AAAA,EACxB,CACE;AAAA,IACE,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA,GAAc,KAAA;AAAA,IACd,MAAA,GAAS,IAAA;AAAA,IACT,OAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,WAAA,GAAc,WAAA,IAAe,CAAC,CAAC,OAAA;AACrC,IAAA,MAAM,WAAA,GAAc,WAAA,GAChB,CAAC,CAAA,KAAwC;AAEvC,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,IAAI,MAAA,IAAU,MAAA,CAAO,OAAA,CAAQ,uCAAuC,CAAA,EAAG;AACvE,MAAA,OAAA,GAAU,CAAC,CAAA;AAAA,IACb,CAAA,GACA,MAAA;AACJ,IAAA,uBACEJ,eAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,cAAA;AAAA,QACV,aAAA,EAAa,MAAA;AAAA,QACb,eAAA,EAAe,QAAA;AAAA,QACf,IAAA,EAAM,cAAc,QAAA,GAAW,SAAA;AAAA,QAC/B,QAAA,EAAU,cAAc,CAAA,GAAI,MAAA;AAAA,QAC5B,OAAA,EAAS,WAAA;AAAA,QACT,SAAA,EACE,WAAA,GACI,CAAC,CAAA,KAAM;AACL,UAAA,IAAA,CAAK,CAAA,CAAE,QAAQ,OAAA,IAAW,CAAA,CAAE,QAAQ,GAAA,KAAQ,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,aAAA,EAAe;AACxE,YAAA,CAAA,CAAE,cAAA,EAAe;AAChB,YAAC,CAAA,CAAE,cAAiC,KAAA,EAAM;AAAA,UAC7C;AAAA,QACF,CAAA,GACA,MAAA;AAAA,QAEN,SAAA,EAAWD,oBAAA;AAAA,UACT,4GAAA;AAAA,UACA,WAAA,IACE,sMAAA;AAAA,UACF;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAGJ,QAAA,EAAA;AAAA,0BAAAC,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EACb,QAAA,EAAA;AAAA,4BAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,8BAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mCAAA,EACb,QAAA,EAAA;AAAA,gCAAAF,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,gDAAA,EAAkD,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,gBACrE,MAAA,oBAAUA,cAAAA,CAACO,6BAAA,EAAA,EAAY,QAAgB,IAAA,EAAK,IAAA,EAAK,QAAA,EAAQ,IAAA,EAAC,MAAA,EAAgB,CAAA;AAAA,gBAC1E,4BAAYP,cAAAA,CAACQ,mCAAc,QAAA,EAAoB,IAAA,EAAK,MAAK,MAAA,EAAgB;AAAA,eAAA,EAC5E,CAAA;AAAA,cACC,4BAAYR,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mDAAmD,QAAA,EAAA,QAAA,EAAS;AAAA,aAAA,EACxF,CAAA;AAAA,YACC,UAAA,oBACCA,cAAAA,CAAC,KAAA,EAAA,EAAI,aAAU,yBAAA,EAA0B,SAAA,EAAU,YACjD,QAAA,kBAAAA,cAAAA;AAAA,cAACS,0BAAA;AAAA,cAAA;AAAA,gBACC,SAAS,UAAA,CAAW,QAAA;AAAA,gBACpB,iBAAiB,CAAC,IAAA,KAAS,UAAA,CAAW,iBAAA,CAAkB,SAAS,IAAI,CAAA;AAAA,gBACrE,YAAA,EACE,OAAO,UAAA,CAAW,KAAA,KAAU,QAAA,GACxB,UAAA,CAAW,KAAA,GACX,MAAA,KAAW,IAAA,GACT,oGAAA,GACA,MAAA,KAAW,IAAA,GACT,iFAAA,GACA;AAAA;AAAA,aAEZ,EACF;AAAA,WAAA,EAEJ,CAAA;AAAA,UAGC,6BAAaT,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,2CAA2C,QAAA,EAAA,SAAA,EAAU,CAAA;AAAA,UAAA,CAG9E,QAAQ,SAAA,qBACRE,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qBAAA,EACZ,QAAA,EAAA;AAAA,YAAA,IAAA,oBACCF,cAAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,mBAAA,EACb,0BAAAA,cAAAA,CAAC,gBAAA,EAAA,EAAiB,IAAA,EAAM,IAAA,EAAM,SAAQ,SAAA,EAAU,UAAA,EAAY,OAAO,WAAA,EAAW,IAAA,EAAC,QAAgB,CAAA,EACjG,CAAA;AAAA,YAED,6BACCA,cAAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,0BACb,QAAA,kBAAAA,cAAAA;AAAA,cAAC,qBAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAM,SAAA;AAAA,gBACN,OAAA,EAAQ,SAAA;AAAA,gBACR,UAAA,EAAY,KAAA;AAAA,gBACZ,WAAA,EAAW,IAAA;AAAA,gBACX;AAAA;AAAA,aACF,EACF;AAAA,WAAA,EAEJ,CAAA;AAAA,UAAA,CAIA,KAAA,IAAS,OAAO,UAAA,KAAe,QAAA,qBAC/BE,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,0EAAA,EACZ,QAAA,EAAA;AAAA,YAAA,KAAA,IAAS,KAAA,CAAM,SAAS,CAAA,mBACvBF,eAAC,KAAA,EAAA,EAAI,WAAA,EAAU,oBAAA,EACb,QAAA,kBAAAA,cAAAA,CAACU,2BAAA,EAAA,EAAU,MAAM,KAAA,EAAO,OAAA,EAAQ,MAAA,EAAO,KAAA,EAAO,GAAA,EAAK,MAAA,EAAQ,IAAI,CAAA,EACjE,CAAA,mBAEAV,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA;AAAA,YAEP,OAAO,UAAA,KAAe,QAAA,oBACrBE,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,UAAA,EACb,QAAA,EAAA;AAAA,8BAAAF,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iCAAA,EACZ,QAAA,EAAA,MAAA,KAAW,OAAO,gCAAA,GAAU,MAAA,KAAW,IAAA,GAAO,kDAAA,GAAa,OAAA,EAC9D,CAAA;AAAA,8BACAA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sDACZ,QAAA,EAAAG,uCAAA,CAAsB,UAAA,EAAY,MAAM,CAAA,EAC3C;AAAA,aAAA,EACF;AAAA,WAAA,EAEJ;AAAA;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-HYZ6BQPS.cjs","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn, convertToLocalNumbers, type SupportedLocale } from '@/lib/utils'\nimport { flowLabels, FLOW_KEYS, type FlowKey } from '@/lib/i18n'\n\nexport type FlowData = Partial<Record<FlowKey, number>>\n\nexport interface FlowDistributionProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Flow counts (auto-normalized). Missing keys treated as 0. */\n data: FlowData\n /** Display mode */\n variant?: 'bars' | 'stacked' | 'compact'\n /** Show numeric counts alongside percent */\n showCounts?: boolean\n /** Show percentages */\n showPercent?: boolean\n /** Locale */\n locale?: SupportedLocale\n /** Loading skeleton */\n isLoading?: boolean\n}\n\nfunction calcPercents(data: FlowData): Record<FlowKey, number> {\n const total = FLOW_KEYS.reduce((s, k) => s + (data[k] ?? 0), 0)\n const result = Object.fromEntries(FLOW_KEYS.map((k) => [k, 0])) as Record<FlowKey, number>\n if (total === 0) return result\n\n const floats = FLOW_KEYS.filter((k) => (data[k] ?? 0) > 0).map((k) => {\n const v = ((data[k] ?? 0) / total) * 100\n return { k, floor: Math.floor(v), rem: v - Math.floor(v) }\n })\n const remaining = 100 - floats.reduce((s, f) => s + f.floor, 0)\n const sorted = [...floats].sort((a, b) => b.rem - a.rem)\n sorted.slice(0, remaining).forEach((f) => f.floor++)\n floats.forEach(({ k, floor }) => (result[k] = floor))\n return result\n}\n\n/** Visual reading order for stacked bar — aligned → opposed → undefined. */\nconst STACKED_ORDER: readonly FlowKey[] = [\n 'pro-gov',\n 'internal-critic',\n 'internal-opponent',\n 'external-opponent',\n 'grey',\n] as const\n\nfunction tokenVar(key: FlowKey): string {\n return `--flow-${key}`\n}\n\nconst FlowDistribution = React.forwardRef<HTMLDivElement, FlowDistributionProps>(\n (\n {\n className,\n data,\n variant = 'stacked',\n showCounts = false,\n showPercent = true,\n locale = 'fa',\n isLoading = false,\n ...props\n },\n ref\n ) => {\n const labels = flowLabels[locale] ?? flowLabels.fa\n const percents = calcPercents(data)\n const percentSign = locale === 'en' ? '%' : '٪'\n\n if (isLoading) {\n return (\n <div ref={ref} data-slot=\"flow-distribution\" className={cn('space-y-2', className)} {...props}>\n {variant === 'stacked' ? (\n <div className=\"h-3 w-full rounded-full bg-muted animate-pulse\" />\n ) : variant === 'compact' ? (\n <div className=\"flex flex-wrap gap-2\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"h-5 w-20 rounded-full bg-muted animate-pulse\" />\n ))}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {[0, 1, 2, 3].map((i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <div className=\"h-3 w-16 rounded bg-muted animate-pulse\" />\n <div className=\"h-2 flex-1 rounded-full bg-muted animate-pulse\" />\n <div className=\"h-3 w-8 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n )}\n </div>\n )\n }\n\n if (variant === 'stacked') {\n const active = STACKED_ORDER.filter((k) => (data[k] ?? 0) > 0)\n const srLabel = active\n .map((k) => `${labels[k]} ${convertToLocalNumbers(percents[k], locale)}${percentSign}`)\n .join('، ')\n\n return (\n <div ref={ref} data-slot=\"flow-distribution\" className={cn('space-y-2', className)} {...props}>\n <div className=\"flex h-3 w-full overflow-hidden rounded-full bg-muted\" role=\"img\" aria-label={srLabel}>\n {active.map((k) => (\n <div\n key={k}\n className=\"transition-all duration-500\"\n style={{ width: `${percents[k]}%`, backgroundColor: `hsl(var(${tokenVar(k)}))` }}\n />\n ))}\n </div>\n <div className=\"flex flex-wrap gap-x-3 gap-y-1\">\n {active.map((k) => (\n <span key={k} className=\"inline-flex items-center gap-1\">\n <span\n className=\"inline-block h-2 w-2 rounded-full\"\n style={{ backgroundColor: `hsl(var(${tokenVar(k)}))` }}\n />\n <span className=\"text-xs text-foreground-light\">{labels[k]}</span>\n {showPercent && (\n <span className=\"text-xs font-medium tabular-nums\" style={{ color: `hsl(var(${tokenVar(k)}))` }}>\n {convertToLocalNumbers(percents[k], locale)}\n {percentSign}\n </span>\n )}\n {showCounts && (\n <span className=\"text-xs text-foreground-muted tabular-nums\">\n ({convertToLocalNumbers(data[k] ?? 0, locale)})\n </span>\n )}\n </span>\n ))}\n </div>\n </div>\n )\n }\n\n if (variant === 'compact') {\n const active = FLOW_KEYS.filter((k) => (data[k] ?? 0) > 0).sort((a, b) => (data[b] ?? 0) - (data[a] ?? 0))\n return (\n <div\n ref={ref}\n data-slot=\"flow-distribution\"\n className={cn('inline-flex flex-wrap gap-2', className)}\n {...props}\n >\n {active.map((k) => (\n <span\n key={k}\n className=\"inline-flex items-center gap-1 rounded-full px-2 py-0.5\"\n style={{\n backgroundColor: `hsl(var(${tokenVar(k)}) / 0.12)`,\n color: `hsl(var(${tokenVar(k)}))`,\n }}\n >\n <span className=\"text-xs font-medium\">{labels[k]}</span>\n {showPercent && (\n <span className=\"text-xs font-bold tabular-nums\">\n {convertToLocalNumbers(percents[k], locale)}\n {percentSign}\n </span>\n )}\n {showCounts && (\n <span className=\"text-xs text-foreground-muted tabular-nums\">\n ({convertToLocalNumbers(data[k] ?? 0, locale)})\n </span>\n )}\n </span>\n ))}\n </div>\n )\n }\n\n // bars — row per flow, sorted by value\n const sorted = FLOW_KEYS.filter((k) => (data[k] ?? 0) > 0).sort((a, b) => (data[b] ?? 0) - (data[a] ?? 0))\n\n return (\n <div ref={ref} data-slot=\"flow-distribution\" className={cn('space-y-1.5', className)} {...props}>\n {sorted.map((k) => (\n <div key={k} className=\"flex items-center gap-2\">\n <span className=\"w-24 shrink-0 text-xs text-foreground-light text-end\">{labels[k]}</span>\n <div className=\"relative flex-1 h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className=\"absolute inset-y-0 start-0 rounded-full transition-all duration-500\"\n style={{\n width: `${percents[k]}%`,\n backgroundColor: `hsl(var(${tokenVar(k)}))`,\n }}\n role=\"progressbar\"\n aria-valuenow={percents[k]}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`${labels[k]}: ${percents[k]}%`}\n />\n </div>\n <span\n className=\"w-12 shrink-0 text-xs font-medium tabular-nums text-start\"\n style={{ color: `hsl(var(${tokenVar(k)}))` }}\n >\n {showCounts\n ? convertToLocalNumbers((data[k] ?? 0).toLocaleString(), locale)\n : `${convertToLocalNumbers(percents[k], locale)}${percentSign}`}\n </span>\n </div>\n ))}\n </div>\n )\n }\n)\n\nFlowDistribution.displayName = 'FlowDistribution'\n\nexport { FlowDistribution }\n","'use client'\n\nimport * as React from 'react'\nimport { cn, convertToLocalNumbers, type SupportedLocale } from '@/lib/utils'\n\nexport interface SentimentData {\n positive: number\n negative: number\n neutral: number\n mixed?: number\n}\n\nexport interface SentimentDistributionProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Sentiment counts (will be auto-normalized to 100%) */\n data: SentimentData\n /** Display mode */\n variant?: 'bars' | 'stacked' | 'compact'\n /** Show numeric count labels */\n showCounts?: boolean\n /** Show percentage labels */\n showPercent?: boolean\n /** Locale for number/label formatting */\n locale?: SupportedLocale\n /** Show loading skeleton */\n isLoading?: boolean\n}\n\nconst LABELS: Record<SupportedLocale, Record<keyof SentimentData, string>> = {\n fa: { positive: 'مثبت', negative: 'منفی', neutral: 'خنثی', mixed: 'ترکیبی' },\n ar: { positive: 'إيجابي', negative: 'سلبي', neutral: 'محايد', mixed: 'مختلط' },\n en: { positive: 'Positive', negative: 'Negative', neutral: 'Neutral', mixed: 'Mixed' },\n}\n\nconst SENTIMENT_STYLES: Record<keyof SentimentData, { bar: string; text: string; bg: string }> = {\n positive: {\n bar: 'bg-[hsl(var(--sentiment-positive))]',\n text: 'text-[hsl(var(--sentiment-positive))]',\n bg: 'bg-[hsl(var(--sentiment-positive)/0.12)]',\n },\n negative: {\n bar: 'bg-[hsl(var(--sentiment-negative))]',\n text: 'text-[hsl(var(--sentiment-negative))]',\n bg: 'bg-[hsl(var(--sentiment-negative)/0.12)]',\n },\n neutral: {\n bar: 'bg-[hsl(var(--sentiment-neutral))]',\n text: 'text-[hsl(var(--sentiment-neutral))]',\n bg: 'bg-[hsl(var(--sentiment-neutral)/0.12)]',\n },\n mixed: {\n bar: 'bg-[hsl(var(--sentiment-mixed))]',\n text: 'text-[hsl(var(--sentiment-mixed))]',\n bg: 'bg-[hsl(var(--sentiment-mixed)/0.12)]',\n },\n}\n\nfunction calcPercents(data: SentimentData): Record<keyof SentimentData, number> {\n const keys = (['positive', 'negative', 'neutral', 'mixed'] as const).filter((k) => (data[k] ?? 0) > 0)\n const total = (['positive', 'negative', 'neutral', 'mixed'] as const).reduce((sum, k) => sum + (data[k] ?? 0), 0)\n if (total === 0) return { positive: 0, negative: 0, neutral: 0, mixed: 0 }\n\n // Largest remainder method — guarantees percentages sum to exactly 100\n const floats = keys.map((k) => ({ k, v: ((data[k] ?? 0) / total) * 100 }))\n const floors = floats.map(({ k, v }) => ({ k, floor: Math.floor(v), rem: v - Math.floor(v) }))\n const remaining = 100 - floors.reduce((s, f) => s + f.floor, 0)\n const sorted = [...floors].sort((a, b) => b.rem - a.rem)\n sorted.slice(0, remaining).forEach((f) => f.floor++)\n\n const result: Record<string, number> = { positive: 0, negative: 0, neutral: 0, mixed: 0 }\n sorted.forEach(({ k, floor }) => (result[k] = floor))\n return result as Record<keyof SentimentData, number>\n}\n\nconst SENTIMENT_ORDER: Array<keyof SentimentData> = ['positive', 'neutral', 'mixed', 'negative']\n\nconst SentimentDistribution = React.forwardRef<HTMLDivElement, SentimentDistributionProps>(\n (\n {\n className,\n data,\n variant = 'bars',\n showCounts = false,\n showPercent = true,\n locale = 'fa',\n isLoading = false,\n ...props\n },\n ref\n ) => {\n const labels = LABELS[locale] ?? LABELS.fa\n const percents = calcPercents(data)\n const activeOrder = SENTIMENT_ORDER.filter((key) => (data[key] ?? 0) > 0)\n\n if (isLoading) {\n return (\n <div ref={ref} data-slot=\"sentiment-distribution\" className={cn('space-y-2', className)} {...props}>\n {variant === 'stacked' ? (\n <div className=\"h-3 w-full rounded-full bg-muted animate-pulse\" />\n ) : variant === 'compact' ? (\n <div className=\"flex gap-2\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"h-4 w-16 rounded bg-muted animate-pulse\" />\n ))}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <div className=\"h-3 w-12 rounded bg-muted animate-pulse\" />\n <div className=\"h-2 flex-1 rounded-full bg-muted animate-pulse\" />\n <div className=\"h-3 w-8 rounded bg-muted animate-pulse\" />\n </div>\n ))}\n </div>\n )}\n </div>\n )\n }\n\n // Stacked bar variant — a single horizontal bar split by sentiment\n if (variant === 'stacked') {\n return (\n <div ref={ref} data-slot=\"sentiment-distribution\" className={cn('space-y-2', className)} {...props}>\n {/* Stacked bar */}\n <div\n className=\"flex h-3 w-full overflow-hidden rounded-full bg-muted\"\n role=\"img\"\n aria-label={`${labels.positive} ${percents.positive}٪، ${labels.negative} ${percents.negative}٪، ${labels.neutral} ${percents.neutral}٪`}\n >\n {activeOrder.map((key) => (\n <div\n key={key}\n className={cn('transition-all duration-500', SENTIMENT_STYLES[key].bar)}\n style={{ width: `${percents[key]}%` }}\n />\n ))}\n </div>\n\n {/* Legend */}\n <div className=\"flex flex-wrap gap-x-3 gap-y-1\">\n {activeOrder.map((key) => (\n <span key={key} className=\"inline-flex items-center gap-1\">\n <span className={cn('inline-block h-2 w-2 rounded-full', SENTIMENT_STYLES[key].bar)} />\n <span className=\"text-xs text-foreground-light\">{labels[key]}</span>\n {showPercent && (\n <span className={cn('text-xs font-medium', SENTIMENT_STYLES[key].text)}>\n {convertToLocalNumbers(percents[key], locale)}\n {locale === 'en' ? '%' : '٪'}\n </span>\n )}\n {showCounts && (\n <span className=\"text-xs text-foreground-muted\">\n ({convertToLocalNumbers(data[key] ?? 0, locale)})\n </span>\n )}\n </span>\n ))}\n </div>\n </div>\n )\n }\n\n // Compact variant — inline chips with percentage\n if (variant === 'compact') {\n return (\n <div\n ref={ref}\n data-slot=\"sentiment-distribution\"\n className={cn('inline-flex flex-wrap gap-2', className)}\n {...props}\n >\n {activeOrder.map((key) => (\n <span\n key={key}\n className={cn('inline-flex items-center gap-1 rounded-full px-2 py-0.5', SENTIMENT_STYLES[key].bg)}\n >\n <span className={cn('text-xs font-medium', SENTIMENT_STYLES[key].text)}>{labels[key]}</span>\n {showPercent && (\n <span className={cn('text-xs font-bold tabular-nums', SENTIMENT_STYLES[key].text)}>\n {convertToLocalNumbers(percents[key], locale)}\n {locale === 'en' ? '%' : '٪'}\n </span>\n )}\n {showCounts && (\n <span className=\"text-xs text-foreground-muted tabular-nums\">\n ({convertToLocalNumbers((data[key] ?? 0).toLocaleString(), locale)})\n </span>\n )}\n </span>\n ))}\n </div>\n )\n }\n\n // Default — \"bars\" variant: individual rows per sentiment\n return (\n <div ref={ref} data-slot=\"sentiment-distribution\" className={cn('space-y-1.5', className)} {...props}>\n {activeOrder.map((key) => (\n <div key={key} className=\"flex items-center gap-2\">\n {/* Label */}\n <span className=\"w-10 shrink-0 text-xs text-foreground-light text-end\">{labels[key]}</span>\n\n {/* Progress bar */}\n <div className=\"relative flex-1 h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={cn(\n 'absolute inset-y-0 start-0 rounded-full transition-all duration-500',\n SENTIMENT_STYLES[key].bar\n )}\n style={{ width: `${percents[key]}%` }}\n role=\"progressbar\"\n aria-valuenow={percents[key]}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`${labels[key]}: ${percents[key]}%`}\n />\n </div>\n\n {/* Value */}\n <span\n className={cn('w-10 shrink-0 text-xs font-medium tabular-nums text-start', SENTIMENT_STYLES[key].text)}\n >\n {showCounts\n ? convertToLocalNumbers((data[key] ?? 0).toLocaleString(), locale)\n : `${convertToLocalNumbers(percents[key], locale)}${locale === 'en' ? '%' : '٪'}`}\n </span>\n </div>\n ))}\n </div>\n )\n }\n)\n\nSentimentDistribution.displayName = 'SentimentDistribution'\n\nexport { SentimentDistribution }\n","'use client'\n\nimport * as React from 'react'\nimport { cn, convertToLocalNumbers, type SupportedLocale } from '@/lib/utils'\nimport { StatusBadge } from './status-badge'\nimport { SeverityBadge } from './severity-badge'\nimport { FlowDistribution, type FlowData } from './flow-distribution'\nimport { SentimentDistribution, type SentimentData } from './sentiment-distribution'\nimport { Sparkline } from './sparkline'\nimport { Checkbox } from './checkbox'\nimport type { StatusKey, SeverityKey } from '@/lib/i18n'\n\n/**\n * ConceptCard — افکارسنجی-flavored headline tile for clustering dashboards.\n * Composes: status badge, severity badge, flow composition bar, sentiment\n * distribution, sparkline trend, AI summary snippet, optional comparison\n * checkbox. Built for government dashboards where each \"concept\" needs\n * to fit in a card grid with rich, comparable signals.\n */\n\nexport interface ConceptCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Concept name (e.g., \"افزایش قیمت بنزین\") */\n title: React.ReactNode\n /** Short subtitle (e.g., \"خوشه ۴ — ۱۲۰ پست\") */\n subtitle?: React.ReactNode\n /** Operational status */\n status?: StatusKey\n /** Criticality of the concept (urgent/high/medium/low) */\n severity?: SeverityKey\n /** Flow composition breakdown (5-class political) */\n flow?: FlowData\n /** Sentiment composition (3-class) */\n sentiment?: SentimentData\n /** Trend sparkline values (e.g., last 14 days mention volume) */\n trend?: number[]\n /** AI-generated short summary (1-2 sentences) */\n aiSummary?: React.ReactNode\n /** Total mentions / size — shown as a stat */\n totalCount?: number\n /** Comparison checkbox state. When provided, renders the checkbox in the header */\n comparison?: {\n selected: boolean\n onSelectionChange: (next: boolean) => void\n label?: React.ReactNode\n }\n /** Make the entire card clickable (cursor + hover/focus ring) */\n interactive?: boolean\n /** Locale @default 'fa' */\n locale?: SupportedLocale\n}\n\nconst ConceptCard = React.forwardRef<HTMLDivElement, ConceptCardProps>(\n (\n {\n className,\n title,\n subtitle,\n status,\n severity,\n flow,\n sentiment,\n trend,\n aiSummary,\n totalCount,\n comparison,\n interactive = false,\n locale = 'fa',\n onClick,\n ...props\n },\n ref\n ) => {\n const isClickable = interactive || !!onClick\n const handleClick = isClickable\n ? (e: React.MouseEvent<HTMLDivElement>) => {\n // Ignore clicks on the comparison checkbox subtree\n const target = e.target as Element | null\n if (target && target.closest('[data-slot=\"concept-card-comparison\"]')) return\n onClick?.(e)\n }\n : undefined\n return (\n <div\n ref={ref}\n data-slot=\"concept-card\"\n data-status={status}\n data-severity={severity}\n role={isClickable ? 'button' : 'article'}\n tabIndex={isClickable ? 0 : undefined}\n onClick={handleClick}\n onKeyDown={\n isClickable\n ? (e) => {\n if ((e.key === 'Enter' || e.key === ' ') && e.target === e.currentTarget) {\n e.preventDefault()\n ;(e.currentTarget as HTMLDivElement).click()\n }\n }\n : undefined\n }\n className={cn(\n 'group/concept-card flex flex-col gap-3 rounded-lg border border-border bg-background p-4 transition-colors',\n isClickable &&\n 'cursor-pointer hover:border-strong hover:bg-surface-100/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n className\n )}\n {...props}\n >\n {/* Header row */}\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h3 className=\"text-sm font-semibold text-foreground truncate\">{title}</h3>\n {status && <StatusBadge status={status} size=\"sm\" animated locale={locale} />}\n {severity && <SeverityBadge severity={severity} size=\"sm\" locale={locale} />}\n </div>\n {subtitle && <p className=\"mt-0.5 text-xs text-foreground-lighter truncate\">{subtitle}</p>}\n </div>\n {comparison && (\n <div data-slot=\"concept-card-comparison\" className=\"shrink-0\">\n <Checkbox\n checked={comparison.selected}\n onCheckedChange={(next) => comparison.onSelectionChange(next === true)}\n aria-label={\n typeof comparison.label === 'string'\n ? comparison.label\n : locale === 'fa'\n ? 'انتخاب برای مقایسه'\n : locale === 'ar'\n ? 'تحديد للمقارنة'\n : 'Select for comparison'\n }\n />\n </div>\n )}\n </div>\n\n {/* AI summary */}\n {aiSummary && <p className=\"text-sm text-foreground leading-relaxed\">{aiSummary}</p>}\n\n {/* Composition bars */}\n {(flow || sentiment) && (\n <div className=\"flex flex-col gap-2\">\n {flow && (\n <div data-slot=\"concept-card-flow\">\n <FlowDistribution data={flow} variant=\"stacked\" showCounts={false} showPercent locale={locale} />\n </div>\n )}\n {sentiment && (\n <div data-slot=\"concept-card-sentiment\">\n <SentimentDistribution\n data={sentiment}\n variant=\"stacked\"\n showCounts={false}\n showPercent\n locale={locale}\n />\n </div>\n )}\n </div>\n )}\n\n {/* Footer row — trend + total */}\n {(trend || typeof totalCount === 'number') && (\n <div className=\"flex items-end justify-between gap-3 pt-1 border-t border-border mt-auto\">\n {trend && trend.length > 0 ? (\n <div data-slot=\"concept-card-trend\">\n <Sparkline data={trend} variant=\"area\" width={120} height={28} />\n </div>\n ) : (\n <span />\n )}\n {typeof totalCount === 'number' && (\n <div className=\"text-end\">\n <div className=\"text-xs text-foreground-lighter\">\n {locale === 'fa' ? 'مجموع' : locale === 'ar' ? 'الإجمالي' : 'Total'}\n </div>\n <div className=\"text-sm font-semibold tabular-nums text-foreground\">\n {convertToLocalNumbers(totalCount, locale)}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n )\n }\n)\nConceptCard.displayName = 'ConceptCard'\n\nexport { ConceptCard }\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkU5FLLCGC_cjs = require('./chunk-U5FLLCGC.cjs');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
function _interopNamespace(e) {
|
|
8
|
+
if (e && e.__esModule) return e;
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
26
|
+
|
|
27
|
+
var HotkeyRegisterContext = React__namespace.createContext(null);
|
|
28
|
+
var HotkeyListContext = React__namespace.createContext([]);
|
|
29
|
+
function HotkeyProvider({ enabled = true, children }) {
|
|
30
|
+
const [entries, setEntries] = React__namespace.useState(() => /* @__PURE__ */ new Map());
|
|
31
|
+
const handlersRef = React__namespace.useRef(/* @__PURE__ */ new Map());
|
|
32
|
+
const register = React__namespace.useRef((entry, handler) => {
|
|
33
|
+
handlersRef.current.set(entry.id, handler);
|
|
34
|
+
setEntries((prev) => {
|
|
35
|
+
const next = new Map(prev);
|
|
36
|
+
next.set(entry.id, entry);
|
|
37
|
+
return next;
|
|
38
|
+
});
|
|
39
|
+
return () => {
|
|
40
|
+
handlersRef.current.delete(entry.id);
|
|
41
|
+
setEntries((prev) => {
|
|
42
|
+
if (!prev.has(entry.id)) return prev;
|
|
43
|
+
const next = new Map(prev);
|
|
44
|
+
next.delete(entry.id);
|
|
45
|
+
return next;
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
}).current;
|
|
49
|
+
const hotkeys = React__namespace.useMemo(() => Array.from(entries.values()), [entries]);
|
|
50
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HotkeyRegisterContext.Provider, { value: register, children: /* @__PURE__ */ jsxRuntime.jsxs(HotkeyListContext.Provider, { value: hotkeys, children: [
|
|
51
|
+
children,
|
|
52
|
+
enabled && /* @__PURE__ */ jsxRuntime.jsx(HotkeyDispatcher, { entries: hotkeys, handlersRef })
|
|
53
|
+
] }) });
|
|
54
|
+
}
|
|
55
|
+
function HotkeyDispatcher({
|
|
56
|
+
entries,
|
|
57
|
+
handlersRef
|
|
58
|
+
}) {
|
|
59
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(HotkeyEntry, { entry, handlersRef }, entry.id)) });
|
|
60
|
+
}
|
|
61
|
+
function HotkeyEntry({
|
|
62
|
+
entry,
|
|
63
|
+
handlersRef
|
|
64
|
+
}) {
|
|
65
|
+
chunkU5FLLCGC_cjs.useHotkeys(
|
|
66
|
+
entry.combo,
|
|
67
|
+
(event) => {
|
|
68
|
+
const handler = handlersRef.current.get(entry.id);
|
|
69
|
+
handler?.(event);
|
|
70
|
+
},
|
|
71
|
+
{ enabled: entry.enabled !== false }
|
|
72
|
+
);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
function useHotkey(id, combo, handler, options = {}) {
|
|
76
|
+
const register = React__namespace.useContext(HotkeyRegisterContext);
|
|
77
|
+
const handlerRef = React__namespace.useRef(handler);
|
|
78
|
+
React__namespace.useEffect(() => {
|
|
79
|
+
handlerRef.current = handler;
|
|
80
|
+
});
|
|
81
|
+
const comboKey = Array.isArray(combo) ? combo.join("|") : combo;
|
|
82
|
+
React__namespace.useEffect(() => {
|
|
83
|
+
if (!register) return;
|
|
84
|
+
if (!comboKey) return;
|
|
85
|
+
return register(
|
|
86
|
+
{
|
|
87
|
+
id,
|
|
88
|
+
combo,
|
|
89
|
+
description: options.description,
|
|
90
|
+
group: options.group,
|
|
91
|
+
enabled: options.enabled
|
|
92
|
+
},
|
|
93
|
+
(event) => handlerRef.current(event)
|
|
94
|
+
);
|
|
95
|
+
}, [register, id, comboKey, options.description, options.group, options.enabled]);
|
|
96
|
+
}
|
|
97
|
+
function useHotkeyRegistry() {
|
|
98
|
+
const hotkeys = React__namespace.useContext(HotkeyListContext);
|
|
99
|
+
return { hotkeys };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
exports.HotkeyProvider = HotkeyProvider;
|
|
103
|
+
exports.useHotkey = useHotkey;
|
|
104
|
+
exports.useHotkeyRegistry = useHotkeyRegistry;
|
|
105
|
+
//# sourceMappingURL=chunk-ISCSZMYW.cjs.map
|
|
106
|
+
//# sourceMappingURL=chunk-ISCSZMYW.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-hotkey-registry.tsx"],"names":["React","jsx","jsxs","Fragment","useHotkeys"],"mappings":"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","file":"chunk-ISCSZMYW.cjs","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useHotkeys, type HotkeyCombo } from './use-hotkeys'\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport interface RegisteredHotkey {\n /** Stable id — used for de-registration + dedupe. */\n id: string\n /** The combo string(s) — `'mod+k'`, `['escape', 'mod+w']`, etc. */\n combo: HotkeyCombo\n /** Short human-readable description (e.g. \"باز کردن پالت دستور\"). */\n description?: string\n /** Optional grouping label for cheatsheet rendering (\"سراسری\", \"ناوبری\"…). */\n group?: string\n /** When false, the entry is listed but the listener doesn't fire. */\n enabled?: boolean\n}\n\ntype RegisterFn = (entry: RegisteredHotkey, handler: (event: KeyboardEvent) => void) => () => void\n\n/**\n * Two contexts so consumers can depend on a *stable* register fn (never\n * changes for the provider's lifetime) without re-running their effect\n * every time the entries list updates.\n */\nconst HotkeyRegisterContext = React.createContext<RegisterFn | null>(null)\nconst HotkeyListContext = React.createContext<RegisteredHotkey[]>([])\n\n/* -------------------------------------------------------------------------- */\n/* Provider */\n/* -------------------------------------------------------------------------- */\n\nexport interface HotkeyProviderProps {\n /** Globally disable all registered hotkeys (e.g. while a modal owns the page). */\n enabled?: boolean\n children: React.ReactNode\n}\n\n/**\n * Centralised hotkey registry. Wrap your app once; descendants register\n * combos via `useHotkey()` and any UI (CommandPalette, help cheatsheet)\n * can read the full list via `useHotkeyRegistry()`.\n *\n * Compared to scattering `useHotkeys` calls across the tree:\n * - Per-entry mounting is centralized (one place that handles\n * `enabled`, key parsing, ignore-when-typing semantics)\n * - Discoverable: cheatsheets / palettes can list every active combo\n * - De-duplicated: registering the same id twice replaces the entry\n *\n * Optional. `useHotkeys` (the bare hook) continues to work outside a provider.\n */\nexport function HotkeyProvider({ enabled = true, children }: HotkeyProviderProps) {\n const [entries, setEntries] = React.useState<Map<string, RegisteredHotkey>>(() => new Map())\n const handlersRef = React.useRef<Map<string, (event: KeyboardEvent) => void>>(new Map())\n\n // Stable across the provider's lifetime so descendants don't re-register\n // every time the entries list changes.\n const register = React.useRef<RegisterFn>((entry, handler) => {\n handlersRef.current.set(entry.id, handler)\n setEntries((prev) => {\n const next = new Map(prev)\n next.set(entry.id, entry)\n return next\n })\n return () => {\n handlersRef.current.delete(entry.id)\n setEntries((prev) => {\n if (!prev.has(entry.id)) return prev\n const next = new Map(prev)\n next.delete(entry.id)\n return next\n })\n }\n }).current\n\n const hotkeys = React.useMemo(() => Array.from(entries.values()), [entries])\n\n return (\n <HotkeyRegisterContext.Provider value={register}>\n <HotkeyListContext.Provider value={hotkeys}>\n {children}\n {enabled && <HotkeyDispatcher entries={hotkeys} handlersRef={handlersRef} />}\n </HotkeyListContext.Provider>\n </HotkeyRegisterContext.Provider>\n )\n}\n\n/**\n * Internal — one useHotkeys per registered entry, mounted under the\n * provider rather than per-component. Per-entry useHotkeys keeps key\n * parsing and ignoreWhenTyping logic in one tested place.\n */\nfunction HotkeyDispatcher({\n entries,\n handlersRef,\n}: {\n entries: RegisteredHotkey[]\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n return (\n <>\n {entries.map((entry) => (\n <HotkeyEntry key={entry.id} entry={entry} handlersRef={handlersRef} />\n ))}\n </>\n )\n}\n\nfunction HotkeyEntry({\n entry,\n handlersRef,\n}: {\n entry: RegisteredHotkey\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n useHotkeys(\n entry.combo,\n (event) => {\n const handler = handlersRef.current.get(entry.id)\n handler?.(event)\n },\n { enabled: entry.enabled !== false }\n )\n return null\n}\n\n/* -------------------------------------------------------------------------- */\n/* Hooks */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Register a hotkey under the active provider. The combo is added to the\n * cheatsheet-readable registry; the handler fires when the combo matches\n * (subject to `useHotkeys` rules around editable targets + modifiers).\n *\n * @example\n * useHotkey('palette', 'mod+k', () => setOpen(true), {\n * description: 'باز کردن پالت دستور',\n * group: 'سراسری',\n * })\n *\n * The first argument is a stable id — use a unique slug per call site so\n * registry updates can dedupe. When called outside a `<HotkeyProvider>`,\n * silently no-ops (so consumers can layer the provider in later without\n * a refactor sweep).\n */\nexport function useHotkey(\n id: string,\n combo: HotkeyCombo,\n handler: (event: KeyboardEvent) => void,\n options: { description?: string; group?: string; enabled?: boolean } = {}\n): void {\n const register = React.useContext(HotkeyRegisterContext)\n\n // Capture the latest handler so callers can pass an inline arrow each\n // render without re-registering the entry.\n const handlerRef = React.useRef(handler)\n React.useEffect(() => {\n handlerRef.current = handler\n })\n\n // Stringify combo for stable dependency tracking.\n const comboKey = Array.isArray(combo) ? combo.join('|') : combo\n\n React.useEffect(() => {\n if (!register) return\n // Skip registration when combo is empty/falsy — lets consumers conditionally\n // disable a hotkey without violating rules of hooks (still call useHotkey\n // unconditionally, but pass `''` to opt out).\n if (!comboKey) return\n return register(\n {\n id,\n combo,\n description: options.description,\n group: options.group,\n enabled: options.enabled,\n },\n (event) => handlerRef.current(event)\n )\n // `combo` (the original value) intentionally elided; comboKey covers it.\n }, [register, id, comboKey, options.description, options.group, options.enabled])\n}\n\n/**\n * Read the active registry. Returns an empty array outside a provider.\n * Useful for CommandPalette items, \"?\" cheatsheet overlays, settings pages.\n */\nexport function useHotkeyRegistry(): { hotkeys: RegisteredHotkey[] } {\n const hotkeys = React.useContext(HotkeyListContext)\n return { hotkeys }\n}\n"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useHotkeys } from './chunk-RZNRIOLT.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var HotkeyRegisterContext = React.createContext(null);
|
|
6
|
+
var HotkeyListContext = React.createContext([]);
|
|
7
|
+
function HotkeyProvider({ enabled = true, children }) {
|
|
8
|
+
const [entries, setEntries] = React.useState(() => /* @__PURE__ */ new Map());
|
|
9
|
+
const handlersRef = React.useRef(/* @__PURE__ */ new Map());
|
|
10
|
+
const register = React.useRef((entry, handler) => {
|
|
11
|
+
handlersRef.current.set(entry.id, handler);
|
|
12
|
+
setEntries((prev) => {
|
|
13
|
+
const next = new Map(prev);
|
|
14
|
+
next.set(entry.id, entry);
|
|
15
|
+
return next;
|
|
16
|
+
});
|
|
17
|
+
return () => {
|
|
18
|
+
handlersRef.current.delete(entry.id);
|
|
19
|
+
setEntries((prev) => {
|
|
20
|
+
if (!prev.has(entry.id)) return prev;
|
|
21
|
+
const next = new Map(prev);
|
|
22
|
+
next.delete(entry.id);
|
|
23
|
+
return next;
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
}).current;
|
|
27
|
+
const hotkeys = React.useMemo(() => Array.from(entries.values()), [entries]);
|
|
28
|
+
return /* @__PURE__ */ jsx(HotkeyRegisterContext.Provider, { value: register, children: /* @__PURE__ */ jsxs(HotkeyListContext.Provider, { value: hotkeys, children: [
|
|
29
|
+
children,
|
|
30
|
+
enabled && /* @__PURE__ */ jsx(HotkeyDispatcher, { entries: hotkeys, handlersRef })
|
|
31
|
+
] }) });
|
|
32
|
+
}
|
|
33
|
+
function HotkeyDispatcher({
|
|
34
|
+
entries,
|
|
35
|
+
handlersRef
|
|
36
|
+
}) {
|
|
37
|
+
return /* @__PURE__ */ jsx(Fragment, { children: entries.map((entry) => /* @__PURE__ */ jsx(HotkeyEntry, { entry, handlersRef }, entry.id)) });
|
|
38
|
+
}
|
|
39
|
+
function HotkeyEntry({
|
|
40
|
+
entry,
|
|
41
|
+
handlersRef
|
|
42
|
+
}) {
|
|
43
|
+
useHotkeys(
|
|
44
|
+
entry.combo,
|
|
45
|
+
(event) => {
|
|
46
|
+
const handler = handlersRef.current.get(entry.id);
|
|
47
|
+
handler?.(event);
|
|
48
|
+
},
|
|
49
|
+
{ enabled: entry.enabled !== false }
|
|
50
|
+
);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function useHotkey(id, combo, handler, options = {}) {
|
|
54
|
+
const register = React.useContext(HotkeyRegisterContext);
|
|
55
|
+
const handlerRef = React.useRef(handler);
|
|
56
|
+
React.useEffect(() => {
|
|
57
|
+
handlerRef.current = handler;
|
|
58
|
+
});
|
|
59
|
+
const comboKey = Array.isArray(combo) ? combo.join("|") : combo;
|
|
60
|
+
React.useEffect(() => {
|
|
61
|
+
if (!register) return;
|
|
62
|
+
if (!comboKey) return;
|
|
63
|
+
return register(
|
|
64
|
+
{
|
|
65
|
+
id,
|
|
66
|
+
combo,
|
|
67
|
+
description: options.description,
|
|
68
|
+
group: options.group,
|
|
69
|
+
enabled: options.enabled
|
|
70
|
+
},
|
|
71
|
+
(event) => handlerRef.current(event)
|
|
72
|
+
);
|
|
73
|
+
}, [register, id, comboKey, options.description, options.group, options.enabled]);
|
|
74
|
+
}
|
|
75
|
+
function useHotkeyRegistry() {
|
|
76
|
+
const hotkeys = React.useContext(HotkeyListContext);
|
|
77
|
+
return { hotkeys };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { HotkeyProvider, useHotkey, useHotkeyRegistry };
|
|
81
|
+
//# sourceMappingURL=chunk-IXFEFIDO.js.map
|
|
82
|
+
//# sourceMappingURL=chunk-IXFEFIDO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-hotkey-registry.tsx"],"names":[],"mappings":"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","file":"chunk-IXFEFIDO.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useHotkeys, type HotkeyCombo } from './use-hotkeys'\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\nexport interface RegisteredHotkey {\n /** Stable id — used for de-registration + dedupe. */\n id: string\n /** The combo string(s) — `'mod+k'`, `['escape', 'mod+w']`, etc. */\n combo: HotkeyCombo\n /** Short human-readable description (e.g. \"باز کردن پالت دستور\"). */\n description?: string\n /** Optional grouping label for cheatsheet rendering (\"سراسری\", \"ناوبری\"…). */\n group?: string\n /** When false, the entry is listed but the listener doesn't fire. */\n enabled?: boolean\n}\n\ntype RegisterFn = (entry: RegisteredHotkey, handler: (event: KeyboardEvent) => void) => () => void\n\n/**\n * Two contexts so consumers can depend on a *stable* register fn (never\n * changes for the provider's lifetime) without re-running their effect\n * every time the entries list updates.\n */\nconst HotkeyRegisterContext = React.createContext<RegisterFn | null>(null)\nconst HotkeyListContext = React.createContext<RegisteredHotkey[]>([])\n\n/* -------------------------------------------------------------------------- */\n/* Provider */\n/* -------------------------------------------------------------------------- */\n\nexport interface HotkeyProviderProps {\n /** Globally disable all registered hotkeys (e.g. while a modal owns the page). */\n enabled?: boolean\n children: React.ReactNode\n}\n\n/**\n * Centralised hotkey registry. Wrap your app once; descendants register\n * combos via `useHotkey()` and any UI (CommandPalette, help cheatsheet)\n * can read the full list via `useHotkeyRegistry()`.\n *\n * Compared to scattering `useHotkeys` calls across the tree:\n * - Per-entry mounting is centralized (one place that handles\n * `enabled`, key parsing, ignore-when-typing semantics)\n * - Discoverable: cheatsheets / palettes can list every active combo\n * - De-duplicated: registering the same id twice replaces the entry\n *\n * Optional. `useHotkeys` (the bare hook) continues to work outside a provider.\n */\nexport function HotkeyProvider({ enabled = true, children }: HotkeyProviderProps) {\n const [entries, setEntries] = React.useState<Map<string, RegisteredHotkey>>(() => new Map())\n const handlersRef = React.useRef<Map<string, (event: KeyboardEvent) => void>>(new Map())\n\n // Stable across the provider's lifetime so descendants don't re-register\n // every time the entries list changes.\n const register = React.useRef<RegisterFn>((entry, handler) => {\n handlersRef.current.set(entry.id, handler)\n setEntries((prev) => {\n const next = new Map(prev)\n next.set(entry.id, entry)\n return next\n })\n return () => {\n handlersRef.current.delete(entry.id)\n setEntries((prev) => {\n if (!prev.has(entry.id)) return prev\n const next = new Map(prev)\n next.delete(entry.id)\n return next\n })\n }\n }).current\n\n const hotkeys = React.useMemo(() => Array.from(entries.values()), [entries])\n\n return (\n <HotkeyRegisterContext.Provider value={register}>\n <HotkeyListContext.Provider value={hotkeys}>\n {children}\n {enabled && <HotkeyDispatcher entries={hotkeys} handlersRef={handlersRef} />}\n </HotkeyListContext.Provider>\n </HotkeyRegisterContext.Provider>\n )\n}\n\n/**\n * Internal — one useHotkeys per registered entry, mounted under the\n * provider rather than per-component. Per-entry useHotkeys keeps key\n * parsing and ignoreWhenTyping logic in one tested place.\n */\nfunction HotkeyDispatcher({\n entries,\n handlersRef,\n}: {\n entries: RegisteredHotkey[]\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n return (\n <>\n {entries.map((entry) => (\n <HotkeyEntry key={entry.id} entry={entry} handlersRef={handlersRef} />\n ))}\n </>\n )\n}\n\nfunction HotkeyEntry({\n entry,\n handlersRef,\n}: {\n entry: RegisteredHotkey\n handlersRef: React.MutableRefObject<Map<string, (event: KeyboardEvent) => void>>\n}) {\n useHotkeys(\n entry.combo,\n (event) => {\n const handler = handlersRef.current.get(entry.id)\n handler?.(event)\n },\n { enabled: entry.enabled !== false }\n )\n return null\n}\n\n/* -------------------------------------------------------------------------- */\n/* Hooks */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Register a hotkey under the active provider. The combo is added to the\n * cheatsheet-readable registry; the handler fires when the combo matches\n * (subject to `useHotkeys` rules around editable targets + modifiers).\n *\n * @example\n * useHotkey('palette', 'mod+k', () => setOpen(true), {\n * description: 'باز کردن پالت دستور',\n * group: 'سراسری',\n * })\n *\n * The first argument is a stable id — use a unique slug per call site so\n * registry updates can dedupe. When called outside a `<HotkeyProvider>`,\n * silently no-ops (so consumers can layer the provider in later without\n * a refactor sweep).\n */\nexport function useHotkey(\n id: string,\n combo: HotkeyCombo,\n handler: (event: KeyboardEvent) => void,\n options: { description?: string; group?: string; enabled?: boolean } = {}\n): void {\n const register = React.useContext(HotkeyRegisterContext)\n\n // Capture the latest handler so callers can pass an inline arrow each\n // render without re-registering the entry.\n const handlerRef = React.useRef(handler)\n React.useEffect(() => {\n handlerRef.current = handler\n })\n\n // Stringify combo for stable dependency tracking.\n const comboKey = Array.isArray(combo) ? combo.join('|') : combo\n\n React.useEffect(() => {\n if (!register) return\n // Skip registration when combo is empty/falsy — lets consumers conditionally\n // disable a hotkey without violating rules of hooks (still call useHotkey\n // unconditionally, but pass `''` to opt out).\n if (!comboKey) return\n return register(\n {\n id,\n combo,\n description: options.description,\n group: options.group,\n enabled: options.enabled,\n },\n (event) => handlerRef.current(event)\n )\n // `combo` (the original value) intentionally elided; comboKey covers it.\n }, [register, id, comboKey, options.description, options.group, options.enabled])\n}\n\n/**\n * Read the active registry. Returns an empty array outside a provider.\n * Useful for CommandPalette items, \"?\" cheatsheet overlays, settings pages.\n */\nexport function useHotkeyRegistry(): { hotkeys: RegisteredHotkey[] } {\n const hotkeys = React.useContext(HotkeyListContext)\n return { hotkeys }\n}\n"]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { useChartTheme, localeAwareCategoryTick, localeAwareNumberTick, ChartLoadingSkeleton, ChartContainer, ChartTooltip, ChartLegend } from './chunk-PYURPUTV.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ResponsiveContainer, AreaChart, CartesianGrid, XAxis, YAxis, Tooltip, Area } from 'recharts';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var PartoAreaChart = React.forwardRef(function PartoAreaChart2({
|
|
7
|
+
data,
|
|
8
|
+
dataKeys,
|
|
9
|
+
xAxisKey = "name",
|
|
10
|
+
curve = "monotone",
|
|
11
|
+
strokeWidth = 2,
|
|
12
|
+
fillOpacity = 0.08,
|
|
13
|
+
showDots = false,
|
|
14
|
+
enableGridY = true,
|
|
15
|
+
enableGridX = false,
|
|
16
|
+
margin = { top: 20, right: 20, bottom: 50, left: 50 },
|
|
17
|
+
axisBottom,
|
|
18
|
+
axisLeft,
|
|
19
|
+
tooltipFormatter,
|
|
20
|
+
locale = "fa",
|
|
21
|
+
className,
|
|
22
|
+
isLoading = false,
|
|
23
|
+
ariaLabel,
|
|
24
|
+
chartProps,
|
|
25
|
+
legend = false
|
|
26
|
+
}, ref) {
|
|
27
|
+
const { chartColors, axisTickStyle, gridStyle, tooltipStyle, crosshairStyle } = useChartTheme();
|
|
28
|
+
const defaultXTick = React.useMemo(() => localeAwareCategoryTick(locale), [locale]);
|
|
29
|
+
const defaultYTick = React.useMemo(() => localeAwareNumberTick(locale), [locale]);
|
|
30
|
+
if (isLoading) {
|
|
31
|
+
return /* @__PURE__ */ jsx(ChartLoadingSkeleton, { className });
|
|
32
|
+
}
|
|
33
|
+
const legendItems = legend ? dataKeys.map((key, i) => ({
|
|
34
|
+
key,
|
|
35
|
+
label: key,
|
|
36
|
+
color: chartColors[i % chartColors.length],
|
|
37
|
+
shape: "line"
|
|
38
|
+
})) : [];
|
|
39
|
+
return /* @__PURE__ */ jsx(ChartContainer, { ref, className, dataSlot: "area-chart", ariaLabel, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", width: "100%", height: "100%" }, children: [
|
|
40
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(AreaChart, { data, margin, ...chartProps, children: [
|
|
41
|
+
/* @__PURE__ */ jsx("defs", { children: dataKeys.map((key, i) => /* @__PURE__ */ jsxs("linearGradient", { id: `area-gradient-${key}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
42
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: chartColors[i % chartColors.length], stopOpacity: fillOpacity }),
|
|
43
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: chartColors[i % chartColors.length], stopOpacity: 0 })
|
|
44
|
+
] }, key)) }),
|
|
45
|
+
(enableGridX || enableGridY) && /* @__PURE__ */ jsx(
|
|
46
|
+
CartesianGrid,
|
|
47
|
+
{
|
|
48
|
+
horizontal: enableGridY,
|
|
49
|
+
vertical: enableGridX,
|
|
50
|
+
stroke: gridStyle.stroke,
|
|
51
|
+
strokeDasharray: gridStyle.strokeDasharray,
|
|
52
|
+
strokeOpacity: gridStyle.strokeOpacity
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
axisBottom !== null && /* @__PURE__ */ jsx(
|
|
56
|
+
XAxis,
|
|
57
|
+
{
|
|
58
|
+
dataKey: xAxisKey,
|
|
59
|
+
tick: axisTickStyle,
|
|
60
|
+
tickLine: false,
|
|
61
|
+
axisLine: false,
|
|
62
|
+
tickMargin: 12,
|
|
63
|
+
tickFormatter: defaultXTick,
|
|
64
|
+
...axisBottom
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
axisLeft !== null && /* @__PURE__ */ jsx(
|
|
68
|
+
YAxis,
|
|
69
|
+
{
|
|
70
|
+
tick: axisTickStyle,
|
|
71
|
+
tickLine: false,
|
|
72
|
+
axisLine: false,
|
|
73
|
+
tickMargin: 12,
|
|
74
|
+
tickFormatter: defaultYTick,
|
|
75
|
+
...axisLeft
|
|
76
|
+
}
|
|
77
|
+
),
|
|
78
|
+
/* @__PURE__ */ jsx(
|
|
79
|
+
Tooltip,
|
|
80
|
+
{
|
|
81
|
+
cursor: crosshairStyle,
|
|
82
|
+
content: /* @__PURE__ */ jsx(ChartTooltip, { tooltipStyle, formatter: tooltipFormatter, locale })
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
dataKeys.map((key, i) => /* @__PURE__ */ jsx(
|
|
86
|
+
Area,
|
|
87
|
+
{
|
|
88
|
+
type: curve,
|
|
89
|
+
dataKey: key,
|
|
90
|
+
stroke: chartColors[i % chartColors.length],
|
|
91
|
+
strokeWidth,
|
|
92
|
+
fill: `url(#area-gradient-${key})`,
|
|
93
|
+
dot: showDots,
|
|
94
|
+
activeDot: { r: 4, strokeWidth: 2 },
|
|
95
|
+
animationDuration: 800,
|
|
96
|
+
animationEasing: "ease-out"
|
|
97
|
+
},
|
|
98
|
+
key
|
|
99
|
+
))
|
|
100
|
+
] }) }) }),
|
|
101
|
+
legend && /* @__PURE__ */ jsx(ChartLegend, { items: legendItems, style: { paddingTop: 12 } })
|
|
102
|
+
] }) });
|
|
103
|
+
});
|
|
104
|
+
PartoAreaChart.displayName = "PartoAreaChart";
|
|
105
|
+
|
|
106
|
+
export { PartoAreaChart };
|
|
107
|
+
//# sourceMappingURL=chunk-JCJLN437.js.map
|
|
108
|
+
//# sourceMappingURL=chunk-JCJLN437.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/charts/PartoAreaChart.tsx"],"names":["PartoAreaChart"],"mappings":"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","file":"chunk-JCJLN437.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'\n\nimport { useChartTheme } from '@/hooks/use-chart-theme'\nimport { type SupportedLocale } from '@/lib/utils'\nimport {\n ChartContainer,\n ChartLegend,\n ChartLoadingSkeleton,\n ChartTooltip,\n localeAwareCategoryTick,\n localeAwareNumberTick,\n type ChartLegendItem,\n} from './chart-utils'\n\nexport interface PartoAreaChartProps {\n /** Row-oriented data: [{ name: \"فروردین\", series1: 50, series2: 30 }] */\n data: Array<Record<string, any>>\n /** Keys for each area series (e.g. ['فروش', 'سود']) */\n dataKeys: string[]\n /** Field name for X axis (default: 'name') */\n xAxisKey?: string\n /** Curve type */\n curve?: 'monotone' | 'linear' | 'natural' | 'step'\n /** Line width */\n strokeWidth?: number\n /** Area fill opacity */\n fillOpacity?: number\n /** Show dots on data points */\n showDots?: boolean\n /** Show horizontal grid lines */\n enableGridY?: boolean\n /** Show vertical grid lines */\n enableGridX?: boolean\n /** Chart margins */\n margin?: { top?: number; right?: number; bottom?: number; left?: number }\n /** Custom X axis config */\n axisBottom?: Record<string, any> | null\n /** Custom Y axis config */\n axisLeft?: Record<string, any> | null\n /** Custom tooltip formatter */\n tooltipFormatter?: (name: string, value: number) => React.ReactNode\n /**\n * Locale for digit formatting in tooltips and axis ticks. fa/ar render\n * Persian/Arabic digits with locale suffixes; en uses Latin K/M/B.\n * Default: 'fa'.\n */\n locale?: SupportedLocale\n className?: string\n isLoading?: boolean\n ariaLabel?: string\n /** Additional Recharts AreaChart props */\n chartProps?: Record<string, any>\n /** Render a colored-marker legend below the chart. @default `false` */\n legend?: boolean\n}\n\nexport const PartoAreaChart = React.forwardRef<HTMLDivElement, PartoAreaChartProps>(function PartoAreaChart(\n {\n data,\n dataKeys,\n xAxisKey = 'name',\n curve = 'monotone',\n strokeWidth = 2,\n fillOpacity = 0.08,\n showDots = false,\n enableGridY = true,\n enableGridX = false,\n margin = { top: 20, right: 20, bottom: 50, left: 50 },\n axisBottom,\n axisLeft,\n tooltipFormatter,\n locale = 'fa',\n className,\n isLoading = false,\n ariaLabel,\n chartProps,\n legend = false,\n },\n ref\n) {\n const { chartColors, axisTickStyle, gridStyle, tooltipStyle, crosshairStyle } = useChartTheme()\n const defaultXTick = React.useMemo(() => localeAwareCategoryTick(locale), [locale])\n const defaultYTick = React.useMemo(() => localeAwareNumberTick(locale), [locale])\n\n if (isLoading) {\n return <ChartLoadingSkeleton className={className} />\n }\n\n const legendItems: ChartLegendItem[] = legend\n ? dataKeys.map((key, i) => ({\n key,\n label: key,\n color: chartColors[i % chartColors.length],\n shape: 'line',\n }))\n : []\n\n return (\n <ChartContainer ref={ref} className={className} dataSlot=\"area-chart\" ariaLabel={ariaLabel}>\n <div style={{ display: 'flex', flexDirection: 'column', width: '100%', height: '100%' }}>\n <div style={{ flex: 1, minHeight: 0 }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={data} margin={margin} {...chartProps}>\n <defs>\n {dataKeys.map((key, i) => (\n <linearGradient key={key} id={`area-gradient-${key}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={chartColors[i % chartColors.length]} stopOpacity={fillOpacity} />\n <stop offset=\"100%\" stopColor={chartColors[i % chartColors.length]} stopOpacity={0} />\n </linearGradient>\n ))}\n </defs>\n\n {(enableGridX || enableGridY) && (\n <CartesianGrid\n horizontal={enableGridY}\n vertical={enableGridX}\n stroke={gridStyle.stroke}\n strokeDasharray={gridStyle.strokeDasharray}\n strokeOpacity={gridStyle.strokeOpacity}\n />\n )}\n\n {axisBottom !== null && (\n <XAxis\n dataKey={xAxisKey}\n tick={axisTickStyle}\n tickLine={false}\n axisLine={false}\n tickMargin={12}\n tickFormatter={defaultXTick}\n {...axisBottom}\n />\n )}\n\n {axisLeft !== null && (\n <YAxis\n tick={axisTickStyle}\n tickLine={false}\n axisLine={false}\n tickMargin={12}\n tickFormatter={defaultYTick}\n {...axisLeft}\n />\n )}\n\n <Tooltip\n cursor={crosshairStyle}\n content={<ChartTooltip tooltipStyle={tooltipStyle} formatter={tooltipFormatter} locale={locale} />}\n />\n\n {dataKeys.map((key, i) => (\n <Area\n key={key}\n type={curve}\n dataKey={key}\n stroke={chartColors[i % chartColors.length]}\n strokeWidth={strokeWidth}\n fill={`url(#area-gradient-${key})`}\n dot={showDots}\n activeDot={{ r: 4, strokeWidth: 2 }}\n animationDuration={800}\n animationEasing=\"ease-out\"\n />\n ))}\n </AreaChart>\n </ResponsiveContainer>\n </div>\n {legend && <ChartLegend items={legendItems} style={{ paddingTop: 12 }} />}\n </div>\n </ChartContainer>\n )\n})\nPartoAreaChart.displayName = 'PartoAreaChart'\n"]}
|