@krizaka/charts 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +59 -2
- package/dist/bar.d.ts +17 -0
- package/dist/bar.js +17 -0
- package/dist/bar.js.map +1 -0
- package/dist/candlestick-IG626XL4.js +13 -0
- package/dist/candlestick-IG626XL4.js.map +1 -0
- package/dist/candlestick.d.ts +42 -0
- package/dist/candlestick.js +13 -0
- package/dist/candlestick.js.map +1 -0
- package/dist/canvas-4MSYDVFO.js +14 -0
- package/dist/canvas-4MSYDVFO.js.map +1 -0
- package/dist/cartesian-BRhNQ3ib.d.ts +34 -0
- package/dist/chart.d.ts +58 -0
- package/dist/chart.js +11 -0
- package/dist/chart.js.map +1 -0
- package/dist/chunk-3CJHBJXA.js +186 -0
- package/dist/chunk-3CJHBJXA.js.map +1 -0
- package/dist/chunk-4LBXEAGC.js +133 -0
- package/dist/chunk-4LBXEAGC.js.map +1 -0
- package/dist/chunk-6FINSUOS.js +49 -0
- package/dist/chunk-6FINSUOS.js.map +1 -0
- package/dist/chunk-AA5EWWYV.js +38 -0
- package/dist/chunk-AA5EWWYV.js.map +1 -0
- package/dist/chunk-ANUCSRUN.js +43 -0
- package/dist/chunk-ANUCSRUN.js.map +1 -0
- package/dist/chunk-ARARFMNE.js +88 -0
- package/dist/chunk-ARARFMNE.js.map +1 -0
- package/dist/chunk-BISL7DYW.js +66 -0
- package/dist/chunk-BISL7DYW.js.map +1 -0
- package/dist/chunk-BV4DBGN7.js +178 -0
- package/dist/chunk-BV4DBGN7.js.map +1 -0
- package/dist/chunk-C4MFZLJM.js +19 -0
- package/dist/chunk-C4MFZLJM.js.map +1 -0
- package/dist/chunk-CSSZLFLO.js +116 -0
- package/dist/chunk-CSSZLFLO.js.map +1 -0
- package/dist/chunk-CVWSMUUB.js +378 -0
- package/dist/chunk-CVWSMUUB.js.map +1 -0
- package/dist/chunk-E5DKBSWX.js +2 -0
- package/dist/chunk-E5DKBSWX.js.map +1 -0
- package/dist/chunk-EEP7PS2L.js +54 -0
- package/dist/chunk-EEP7PS2L.js.map +1 -0
- package/dist/chunk-EQLC2QVN.js +73 -0
- package/dist/chunk-EQLC2QVN.js.map +1 -0
- package/dist/chunk-FINOPIDN.js +2 -0
- package/dist/chunk-FINOPIDN.js.map +1 -0
- package/dist/chunk-G2KF2WL4.js +2 -0
- package/dist/chunk-G2KF2WL4.js.map +1 -0
- package/dist/chunk-I3D7KUGN.js +205 -0
- package/dist/chunk-I3D7KUGN.js.map +1 -0
- package/dist/chunk-IKQV3NSL.js +76 -0
- package/dist/chunk-IKQV3NSL.js.map +1 -0
- package/dist/chunk-JTKR7ZWP.js +468 -0
- package/dist/chunk-JTKR7ZWP.js.map +1 -0
- package/dist/chunk-KNDHO67X.js +78 -0
- package/dist/chunk-KNDHO67X.js.map +1 -0
- package/dist/chunk-L2EKYWVI.js +94 -0
- package/dist/chunk-L2EKYWVI.js.map +1 -0
- package/dist/chunk-MXLITIGU.js +92 -0
- package/dist/chunk-MXLITIGU.js.map +1 -0
- package/dist/chunk-NCIQMRV3.js +155 -0
- package/dist/chunk-NCIQMRV3.js.map +1 -0
- package/dist/chunk-OB5EFDDH.js +118 -0
- package/dist/chunk-OB5EFDDH.js.map +1 -0
- package/dist/chunk-OIRHLJBC.js +83 -0
- package/dist/chunk-OIRHLJBC.js.map +1 -0
- package/dist/chunk-PBQV3B6O.js +145 -0
- package/dist/chunk-PBQV3B6O.js.map +1 -0
- package/dist/chunk-POQIHFAZ.js +2 -0
- package/dist/chunk-POQIHFAZ.js.map +1 -0
- package/dist/chunk-PWMMXRMC.js +234 -0
- package/dist/chunk-PWMMXRMC.js.map +1 -0
- package/dist/chunk-SLEJDQ3A.js +81 -0
- package/dist/chunk-SLEJDQ3A.js.map +1 -0
- package/dist/chunk-TPJDOB7R.js +15 -0
- package/dist/chunk-TPJDOB7R.js.map +1 -0
- package/dist/chunk-VKZZY2QD.js +103 -0
- package/dist/chunk-VKZZY2QD.js.map +1 -0
- package/dist/chunk-W5FX4TU3.js +102 -0
- package/dist/chunk-W5FX4TU3.js.map +1 -0
- package/dist/chunk-W5ILLSPK.js +107 -0
- package/dist/chunk-W5ILLSPK.js.map +1 -0
- package/dist/chunk-WBHFVBSK.js +25 -0
- package/dist/chunk-WBHFVBSK.js.map +1 -0
- package/dist/chunk-WNUFGMS7.js +113 -0
- package/dist/chunk-WNUFGMS7.js.map +1 -0
- package/dist/chunk-WVTIKOII.js +15 -0
- package/dist/chunk-WVTIKOII.js.map +1 -0
- package/dist/chunk-XDDALY4C.js +166 -0
- package/dist/chunk-XDDALY4C.js.map +1 -0
- package/dist/chunk-XLLYNNC6.js +89 -0
- package/dist/chunk-XLLYNNC6.js.map +1 -0
- package/dist/context-BgYUymEO.d.ts +163 -0
- package/dist/credits.d.ts +42 -0
- package/dist/credits.js +21 -0
- package/dist/credits.js.map +1 -0
- package/dist/earnings.d.ts +29 -0
- package/dist/earnings.js +22 -0
- package/dist/earnings.js.map +1 -0
- package/dist/frame-I7_xYGy5.d.ts +45 -0
- package/dist/full-S2MBPEEP.js +11 -0
- package/dist/full-S2MBPEEP.js.map +1 -0
- package/dist/funnel-QU5ZPC52.js +13 -0
- package/dist/funnel-QU5ZPC52.js.map +1 -0
- package/dist/funnel.d.ts +26 -0
- package/dist/funnel.js +13 -0
- package/dist/funnel.js.map +1 -0
- package/dist/gauge.d.ts +38 -0
- package/dist/gauge.js +13 -0
- package/dist/gauge.js.map +1 -0
- package/dist/geo.d.ts +37 -0
- package/dist/geo.js +13 -0
- package/dist/geo.js.map +1 -0
- package/dist/globe.d.ts +36 -0
- package/dist/globe.js +12 -0
- package/dist/globe.js.map +1 -0
- package/dist/goal.d.ts +26 -0
- package/dist/goal.js +17 -0
- package/dist/goal.js.map +1 -0
- package/dist/heatmap-JWQOKUGM.js +13 -0
- package/dist/heatmap-JWQOKUGM.js.map +1 -0
- package/dist/heatmap.d.ts +47 -0
- package/dist/heatmap.js +15 -0
- package/dist/heatmap.js.map +1 -0
- package/dist/host-_F8RgiIz.d.ts +15 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/dist/labels-DE_743fQ.d.ts +72 -0
- package/dist/latency.d.ts +33 -0
- package/dist/latency.js +24 -0
- package/dist/latency.js.map +1 -0
- package/dist/line.d.ts +25 -0
- package/dist/line.js +19 -0
- package/dist/line.js.map +1 -0
- package/dist/native.d.ts +494 -0
- package/dist/native.js +1244 -0
- package/dist/native.js.map +1 -0
- package/dist/pie.d.ts +37 -0
- package/dist/pie.js +16 -0
- package/dist/pie.js.map +1 -0
- package/dist/provider.d.ts +73 -0
- package/dist/provider.js +24 -0
- package/dist/provider.js.map +1 -0
- package/dist/radar-75GRJ2IK.js +13 -0
- package/dist/radar-75GRJ2IK.js.map +1 -0
- package/dist/radar.d.ts +22 -0
- package/dist/radar.js +13 -0
- package/dist/radar.js.map +1 -0
- package/dist/sankey-XQTX2EG6.js +13 -0
- package/dist/sankey-XQTX2EG6.js.map +1 -0
- package/dist/sankey.d.ts +28 -0
- package/dist/sankey.js +13 -0
- package/dist/sankey.js.map +1 -0
- package/dist/scatter-XSNG4OKD.js +13 -0
- package/dist/scatter-XSNG4OKD.js.map +1 -0
- package/dist/scatter.d.ts +41 -0
- package/dist/scatter.js +15 -0
- package/dist/scatter.js.map +1 -0
- package/dist/sparkline.d.ts +26 -0
- package/dist/sparkline.js +16 -0
- package/dist/sparkline.js.map +1 -0
- package/dist/svg-BJUHYX3B.js +14 -0
- package/dist/svg-BJUHYX3B.js.map +1 -0
- package/dist/throughput.d.ts +37 -0
- package/dist/throughput.js +24 -0
- package/dist/throughput.js.map +1 -0
- package/dist/ticker.d.ts +38 -0
- package/dist/ticker.js +22 -0
- package/dist/ticker.js.map +1 -0
- package/dist/treemap-OMGGGB5U.js +13 -0
- package/dist/treemap-OMGGGB5U.js.map +1 -0
- package/dist/treemap.d.ts +24 -0
- package/dist/treemap.js +14 -0
- package/dist/treemap.js.map +1 -0
- package/dist/world-110m-DVFWXS42.js +18 -0
- package/dist/world-110m-DVFWXS42.js.map +1 -0
- package/package.json +614 -3
- package/registry/area-chart.json +785 -0
- package/registry/bar-chart.json +784 -0
- package/registry/calendar-heatmap.json +460 -0
- package/registry/candlestick.json +553 -0
- package/registry/chart.json +441 -0
- package/registry/charts-provider.json +191 -0
- package/registry/credit-usage.json +473 -0
- package/registry/earnings-chart.json +703 -0
- package/registry/examples/area-chart/credits-usage.d.ts +4 -0
- package/registry/examples/area-chart/credits-usage.js +38 -0
- package/registry/examples/area-chart/credits-usage.tsx +32 -0
- package/registry/examples/area-chart/native/credits-usage.d.ts +4 -0
- package/registry/examples/area-chart/native/credits-usage.dark.png +0 -0
- package/registry/examples/area-chart/native/credits-usage.js +33 -0
- package/registry/examples/area-chart/native/credits-usage.light.png +0 -0
- package/registry/examples/area-chart/native/credits-usage.tsx +27 -0
- package/registry/examples/area-chart/storage.d.ts +4 -0
- package/registry/examples/area-chart/storage.js +27 -0
- package/registry/examples/area-chart/storage.tsx +21 -0
- package/registry/examples/bar-chart/jobs-by-status.d.ts +4 -0
- package/registry/examples/bar-chart/jobs-by-status.js +37 -0
- package/registry/examples/bar-chart/jobs-by-status.tsx +31 -0
- package/registry/examples/bar-chart/native/jobs-by-status.d.ts +4 -0
- package/registry/examples/bar-chart/native/jobs-by-status.dark.png +0 -0
- package/registry/examples/bar-chart/native/jobs-by-status.js +32 -0
- package/registry/examples/bar-chart/native/jobs-by-status.light.png +0 -0
- package/registry/examples/bar-chart/native/jobs-by-status.tsx +26 -0
- package/registry/examples/bar-chart/plans-by-quarter.d.ts +4 -0
- package/registry/examples/bar-chart/plans-by-quarter.js +31 -0
- package/registry/examples/bar-chart/plans-by-quarter.tsx +26 -0
- package/registry/examples/bar-chart/top-supporters.d.ts +4 -0
- package/registry/examples/bar-chart/top-supporters.js +32 -0
- package/registry/examples/bar-chart/top-supporters.tsx +27 -0
- package/registry/examples/calendar-heatmap/publishing.d.ts +4 -0
- package/registry/examples/calendar-heatmap/publishing.js +28 -0
- package/registry/examples/calendar-heatmap/publishing.tsx +23 -0
- package/registry/examples/candlestick/auction-bids.d.ts +4 -0
- package/registry/examples/candlestick/auction-bids.js +37 -0
- package/registry/examples/candlestick/auction-bids.tsx +32 -0
- package/registry/examples/chart/polar-uploads.d.ts +4 -0
- package/registry/examples/chart/polar-uploads.js +34 -0
- package/registry/examples/chart/polar-uploads.tsx +30 -0
- package/registry/examples/charts-provider/french-orazaka.d.ts +4 -0
- package/registry/examples/charts-provider/french-orazaka.js +26 -0
- package/registry/examples/charts-provider/french-orazaka.tsx +22 -0
- package/registry/examples/charts-provider/native/french-orazaka.d.ts +4 -0
- package/registry/examples/charts-provider/native/french-orazaka.dark.png +0 -0
- package/registry/examples/charts-provider/native/french-orazaka.js +17 -0
- package/registry/examples/charts-provider/native/french-orazaka.light.png +0 -0
- package/registry/examples/charts-provider/native/french-orazaka.tsx +17 -0
- package/registry/examples/credit-usage/monthly-credits.d.ts +4 -0
- package/registry/examples/credit-usage/monthly-credits.js +24 -0
- package/registry/examples/credit-usage/monthly-credits.tsx +19 -0
- package/registry/examples/credit-usage/native/monthly-credits.d.ts +4 -0
- package/registry/examples/credit-usage/native/monthly-credits.dark.png +0 -0
- package/registry/examples/credit-usage/native/monthly-credits.js +23 -0
- package/registry/examples/credit-usage/native/monthly-credits.light.png +0 -0
- package/registry/examples/credit-usage/native/monthly-credits.tsx +18 -0
- package/registry/examples/credit-usage/storage-plan.d.ts +4 -0
- package/registry/examples/credit-usage/storage-plan.js +21 -0
- package/registry/examples/credit-usage/storage-plan.tsx +15 -0
- package/registry/examples/earnings-chart/creator-month.d.ts +4 -0
- package/registry/examples/earnings-chart/creator-month.js +29 -0
- package/registry/examples/earnings-chart/creator-month.tsx +24 -0
- package/registry/examples/earnings-chart/gross-and-net.d.ts +4 -0
- package/registry/examples/earnings-chart/gross-and-net.js +29 -0
- package/registry/examples/earnings-chart/gross-and-net.tsx +24 -0
- package/registry/examples/earnings-chart/native/creator-month.d.ts +4 -0
- package/registry/examples/earnings-chart/native/creator-month.dark.png +0 -0
- package/registry/examples/earnings-chart/native/creator-month.js +29 -0
- package/registry/examples/earnings-chart/native/creator-month.light.png +0 -0
- package/registry/examples/earnings-chart/native/creator-month.tsx +24 -0
- package/registry/examples/funnel/signup.d.ts +4 -0
- package/registry/examples/funnel/signup.js +30 -0
- package/registry/examples/funnel/signup.tsx +24 -0
- package/registry/examples/gauge/challenge-goal.d.ts +4 -0
- package/registry/examples/gauge/challenge-goal.js +24 -0
- package/registry/examples/gauge/challenge-goal.tsx +18 -0
- package/registry/examples/gauge/credits-quota.d.ts +4 -0
- package/registry/examples/gauge/credits-quota.js +26 -0
- package/registry/examples/gauge/credits-quota.tsx +19 -0
- package/registry/examples/gauge/native/credits-quota.d.ts +4 -0
- package/registry/examples/gauge/native/credits-quota.dark.png +0 -0
- package/registry/examples/gauge/native/credits-quota.js +25 -0
- package/registry/examples/gauge/native/credits-quota.light.png +0 -0
- package/registry/examples/gauge/native/credits-quota.tsx +18 -0
- package/registry/examples/geo-map/viewers.d.ts +4 -0
- package/registry/examples/geo-map/viewers.js +43 -0
- package/registry/examples/geo-map/viewers.tsx +29 -0
- package/registry/examples/globe/deployment-regions.d.ts +4 -0
- package/registry/examples/globe/deployment-regions.js +36 -0
- package/registry/examples/globe/deployment-regions.tsx +30 -0
- package/registry/examples/goal-progress/challenge-pot.d.ts +4 -0
- package/registry/examples/goal-progress/challenge-pot.js +22 -0
- package/registry/examples/goal-progress/challenge-pot.tsx +16 -0
- package/registry/examples/goal-progress/goal-reached.d.ts +4 -0
- package/registry/examples/goal-progress/goal-reached.js +11 -0
- package/registry/examples/goal-progress/goal-reached.tsx +6 -0
- package/registry/examples/goal-progress/native/challenge-pot.d.ts +4 -0
- package/registry/examples/goal-progress/native/challenge-pot.dark.png +0 -0
- package/registry/examples/goal-progress/native/challenge-pot.js +11 -0
- package/registry/examples/goal-progress/native/challenge-pot.light.png +0 -0
- package/registry/examples/goal-progress/native/challenge-pot.tsx +6 -0
- package/registry/examples/heatmap/upload-activity.d.ts +4 -0
- package/registry/examples/heatmap/upload-activity.js +30 -0
- package/registry/examples/heatmap/upload-activity.tsx +25 -0
- package/registry/examples/job-throughput/live-hours.d.ts +4 -0
- package/registry/examples/job-throughput/live-hours.js +33 -0
- package/registry/examples/job-throughput/live-hours.tsx +28 -0
- package/registry/examples/job-throughput/native/week-of-jobs.d.ts +4 -0
- package/registry/examples/job-throughput/native/week-of-jobs.dark.png +0 -0
- package/registry/examples/job-throughput/native/week-of-jobs.js +20 -0
- package/registry/examples/job-throughput/native/week-of-jobs.light.png +0 -0
- package/registry/examples/job-throughput/native/week-of-jobs.tsx +16 -0
- package/registry/examples/job-throughput/week-of-jobs.d.ts +4 -0
- package/registry/examples/job-throughput/week-of-jobs.js +20 -0
- package/registry/examples/job-throughput/week-of-jobs.tsx +16 -0
- package/registry/examples/latency-chart/by-capability.d.ts +4 -0
- package/registry/examples/latency-chart/by-capability.js +26 -0
- package/registry/examples/latency-chart/by-capability.tsx +21 -0
- package/registry/examples/latency-chart/native/by-capability.d.ts +4 -0
- package/registry/examples/latency-chart/native/by-capability.dark.png +0 -0
- package/registry/examples/latency-chart/native/by-capability.js +17 -0
- package/registry/examples/latency-chart/native/by-capability.light.png +0 -0
- package/registry/examples/latency-chart/native/by-capability.tsx +13 -0
- package/registry/examples/latency-chart/time-to-result.d.ts +4 -0
- package/registry/examples/latency-chart/time-to-result.js +27 -0
- package/registry/examples/latency-chart/time-to-result.tsx +22 -0
- package/registry/examples/line-chart/creator-earnings.d.ts +4 -0
- package/registry/examples/line-chart/creator-earnings.js +35 -0
- package/registry/examples/line-chart/creator-earnings.tsx +30 -0
- package/registry/examples/line-chart/forecast.d.ts +4 -0
- package/registry/examples/line-chart/forecast.js +36 -0
- package/registry/examples/line-chart/forecast.tsx +30 -0
- package/registry/examples/line-chart/live-jobs.d.ts +4 -0
- package/registry/examples/line-chart/live-jobs.js +21 -0
- package/registry/examples/line-chart/live-jobs.tsx +23 -0
- package/registry/examples/line-chart/native/creator-earnings.d.ts +4 -0
- package/registry/examples/line-chart/native/creator-earnings.dark.png +0 -0
- package/registry/examples/line-chart/native/creator-earnings.js +32 -0
- package/registry/examples/line-chart/native/creator-earnings.light.png +0 -0
- package/registry/examples/line-chart/native/creator-earnings.tsx +26 -0
- package/registry/examples/line-chart/states.d.ts +4 -0
- package/registry/examples/line-chart/states.js +16 -0
- package/registry/examples/line-chart/states.tsx +13 -0
- package/registry/examples/pie-chart/credit-spend.d.ts +4 -0
- package/registry/examples/pie-chart/credit-spend.js +30 -0
- package/registry/examples/pie-chart/credit-spend.tsx +24 -0
- package/registry/examples/pie-chart/native/credit-spend.d.ts +4 -0
- package/registry/examples/pie-chart/native/credit-spend.dark.png +0 -0
- package/registry/examples/pie-chart/native/credit-spend.js +17 -0
- package/registry/examples/pie-chart/native/credit-spend.light.png +0 -0
- package/registry/examples/pie-chart/native/credit-spend.tsx +12 -0
- package/registry/examples/pie-chart/storage-by-kind.d.ts +4 -0
- package/registry/examples/pie-chart/storage-by-kind.js +31 -0
- package/registry/examples/pie-chart/storage-by-kind.tsx +26 -0
- package/registry/examples/price-ticker/auction-room.d.ts +4 -0
- package/registry/examples/price-ticker/auction-room.js +21 -0
- package/registry/examples/price-ticker/auction-room.tsx +17 -0
- package/registry/examples/price-ticker/native/auction-room.d.ts +4 -0
- package/registry/examples/price-ticker/native/auction-room.dark.png +0 -0
- package/registry/examples/price-ticker/native/auction-room.js +19 -0
- package/registry/examples/price-ticker/native/auction-room.light.png +0 -0
- package/registry/examples/price-ticker/native/auction-room.tsx +15 -0
- package/registry/examples/price-ticker/no-bid-yet.d.ts +4 -0
- package/registry/examples/price-ticker/no-bid-yet.js +11 -0
- package/registry/examples/price-ticker/no-bid-yet.tsx +6 -0
- package/registry/examples/radar-chart/model-comparison.d.ts +4 -0
- package/registry/examples/radar-chart/model-comparison.js +33 -0
- package/registry/examples/radar-chart/model-comparison.tsx +28 -0
- package/registry/examples/sankey/credit-flow.d.ts +4 -0
- package/registry/examples/sankey/credit-flow.js +37 -0
- package/registry/examples/sankey/credit-flow.tsx +32 -0
- package/registry/examples/scatter-chart/watch-time.d.ts +4 -0
- package/registry/examples/scatter-chart/watch-time.js +36 -0
- package/registry/examples/scatter-chart/watch-time.tsx +31 -0
- package/registry/examples/sparkline/bars.d.ts +4 -0
- package/registry/examples/sparkline/bars.js +12 -0
- package/registry/examples/sparkline/bars.tsx +7 -0
- package/registry/examples/sparkline/native/stat-trend.d.ts +4 -0
- package/registry/examples/sparkline/native/stat-trend.dark.png +0 -0
- package/registry/examples/sparkline/native/stat-trend.js +12 -0
- package/registry/examples/sparkline/native/stat-trend.light.png +0 -0
- package/registry/examples/sparkline/native/stat-trend.tsx +7 -0
- package/registry/examples/sparkline/stat-trend.d.ts +4 -0
- package/registry/examples/sparkline/stat-trend.js +18 -0
- package/registry/examples/sparkline/stat-trend.tsx +15 -0
- package/registry/examples/sparkline/table-rows.d.ts +4 -0
- package/registry/examples/sparkline/table-rows.js +23 -0
- package/registry/examples/sparkline/table-rows.tsx +26 -0
- package/registry/examples/treemap/storage.d.ts +4 -0
- package/registry/examples/treemap/storage.js +17 -0
- package/registry/examples/treemap/storage.tsx +13 -0
- package/registry/funnel.json +487 -0
- package/registry/gauge.json +600 -0
- package/registry/geo-map.json +484 -0
- package/registry/globe.json +469 -0
- package/registry/goal-progress.json +520 -0
- package/registry/heatmap.json +531 -0
- package/registry/index.json +582 -0
- package/registry/job-throughput.json +654 -0
- package/registry/latency-chart.json +671 -0
- package/registry/line-chart.json +793 -0
- package/registry/pie-chart.json +1288 -0
- package/registry/price-ticker.json +684 -0
- package/registry/radar-chart.json +459 -0
- package/registry/sankey.json +503 -0
- package/registry/scatter-chart.json +559 -0
- package/registry/sparkline.json +563 -0
- package/registry/treemap.json +432 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sparkline/sparkline.tsx"],"sourcesContent":["\"use client\";\n// A word-sized chart: the shape of a series inside a sentence, a table cell or a stat. With a `width` it is drawn on\n// the server too (no placeholder); otherwise it fills its container. No axes: its title and summary carry the figures.\nimport { useMemo } from \"react\";\n\nimport { describeSeries } from \"../core/describe\";\nimport { categoryFormatter, shareFormatter, valueFormatter } from \"../core/format\";\nimport { niceDomain } from \"../core/scale\";\nimport { areaPath, barPath, linePath, type Point, segments } from \"../core/shape\";\nimport type { SeriesColor, Threshold, ValueFormat } from \"../core/types\";\nimport { ChartFrame, type ChartFrameProps, useSettings } from \"../web/frame\";\nimport { colorOf } from \"../web/parts\";\n\nexport interface SparklineProps extends Omit<ChartFrameProps, \"hideTitle\" | \"dataTable\" | \"exportable\" | \"description\"> {\n /** The values, oldest first (`null` for a gap). */\n data: readonly (number | null)[];\n /** The labels of the values (dates, ISO or `Date`), for the summary and the table. Default: their positions. */\n categories?: readonly unknown[];\n /** `line` (default), `area` (line over a wash) or `bar` (discrete counts: jobs per hour). */\n variant?: \"line\" | \"area\" | \"bar\";\n /** A palette slot, a tone or a CSS colour. Default: the trend's tone when `trendTone`, else slot 1. */\n color?: SeriesColor;\n /** Colour by the trend: success up, danger down (or the reverse with `\"inverse\"`: costs, latency). */\n trendTone?: boolean | \"inverse\";\n /** A dashed reference line (yesterday's average, a quota). */\n threshold?: Threshold;\n /** How the values are written in the summary and table. */\n format?: ValueFormat;\n /** A fixed width in pixels: drawn on the server too. Default: the container's width. */\n width?: number;\n}\n\n/** The shape of a trend in a few pixels: a stat's last 30 days, a job's throughput. */\nexport function Sparkline(props: SparklineProps) {\n const { data, categories, variant = \"line\", color, trendTone, threshold, format, width: fixed, height = 32 } = props;\n const { locale, labels } = useSettings(props);\n const table = useMemo(() => ({ categories: categories ?? data.map((_, i) => i + 1), series: [{ id: \"v\", label: props.title, values: data, slot: 1 }] }), [data, categories, props.title]);\n const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), category: categoryFormatter(undefined, locale), share: shareFormatter(locale) }), [format, locale, labels.noValue]);\n const values = data.filter((v): v is number => v != null);\n const isEmpty = values.length === 0;\n const summary = isEmpty ? labels.empty : describeSeries(table, { kind: \"sparkline\", labels, value: fmt.value, category: fmt.category, share: fmt.share, thresholds: threshold ? [threshold] : [] });\n const first = values[0] ?? 0;\n const last = values[values.length - 1] ?? 0;\n const up = last >= first;\n const tone = trendTone ? ((trendTone === \"inverse\" ? !up : up) ? \"success\" : \"danger\") : undefined;\n const stroke = colorOf(color ?? tone, 1);\n\n return (\n <ChartFrame\n kind=\"sparkline\"\n frame={{ ...props, hideTitle: true, dataTable: false, height, style: { ...(fixed ? { width: fixed, display: \"inline-flex\" } : {}), ...props.style } }}\n defaultHeight={32}\n table={{ columns: [labels.category, props.title], rows: table.categories.map((c, i) => [fmt.category(c), fmt.value(data[i])]) }}\n summary={summary}\n isEmpty={isEmpty}\n navigable={false}\n ssrWidth={fixed}\n compact\n >\n {(width, h) => {\n let lo = Math.min(...values, threshold?.value ?? Number.POSITIVE_INFINITY);\n let hi = Math.max(...values, threshold?.value ?? Number.NEGATIVE_INFINITY);\n if (variant === \"bar\") {\n lo = Math.min(0, lo);\n hi = Math.max(0, hi);\n }\n const [d0, d1] = lo === hi ? niceDomain(lo, hi).domain : [lo, hi];\n const pad = variant === \"bar\" ? 0 : 3;\n const yOf = (v: number) => pad + (1 - (v - d0) / (d1 - d0 || 1)) * (h - pad * 2);\n const n = data.length;\n const xOf = (i: number) => (variant === \"bar\" ? (i + 0.5) * (width / n) : n > 1 ? pad + (i / (n - 1)) * (width - pad * 2) : width / 2);\n const pts = data.map((v, i) => (v == null ? null : ([xOf(i), yOf(v)] as Point)));\n const lastPoint = [...pts].reverse().find(Boolean);\n return (\n <svg className=\"kzc-svg\" width={width} height={h} viewBox={`0 0 ${width} ${h}`} aria-hidden>\n {threshold && <line x1={0} x2={width} y1={yOf(threshold.value)} y2={yOf(threshold.value)} data-tone={threshold.tone ?? \"neutral\"} className=\"kzc-threshold\" style={{ strokeWidth: 1 }} />}\n {variant === \"bar\"\n ? data.map((v, i) => {\n if (v == null || v === 0) return null;\n const bw = Math.max(1, Math.min(8, (width / n) * 0.7));\n const top = Math.min(yOf(v), yOf(0));\n return <path key={i} d={barPath(xOf(i) - bw / 2, top, bw, Math.abs(yOf(v) - yOf(0)), 1.5, false, v < 0)} style={{ fill: stroke }} />;\n })\n : segments(pts).map((seg) => (\n <g key={seg[0]![0]}>\n {variant === \"area\" && <path d={areaPath(seg, h, \"monotone\")} className=\"kzc-area\" style={{ fill: stroke }} />}\n <path d={linePath(seg, \"monotone\")} className=\"kzc-line\" style={{ stroke, strokeWidth: 1.75 }} />\n </g>\n ))}\n {variant !== \"bar\" && lastPoint && <circle cx={lastPoint[0]} cy={lastPoint[1]} r={2.75} style={{ fill: stroke }} />}\n </svg>\n );\n }}\n </ChartFrame>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/core/scale.ts
|
|
4
|
+
function niceStep(span, count) {
|
|
5
|
+
if (!(span > 0) || !(count > 0)) return 1;
|
|
6
|
+
const raw = span / count;
|
|
7
|
+
const power = 10 ** Math.floor(Math.log10(raw));
|
|
8
|
+
const fraction = raw / power;
|
|
9
|
+
const nice = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;
|
|
10
|
+
return nice * power;
|
|
11
|
+
}
|
|
12
|
+
function niceDomain(min, max, count = 5) {
|
|
13
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return { domain: [0, 1], ticks: [0, 1] };
|
|
14
|
+
if (min === max) {
|
|
15
|
+
if (min === 0) return { domain: [0, 1], ticks: [0, 0.5, 1] };
|
|
16
|
+
const pad = Math.abs(min) * 0.5;
|
|
17
|
+
[min, max] = min > 0 ? [0, max + pad] : [min - pad, 0];
|
|
18
|
+
}
|
|
19
|
+
const step = niceStep(max - min, count);
|
|
20
|
+
const lo = Math.floor(min / step) * step;
|
|
21
|
+
const hi = Math.ceil(max / step) * step;
|
|
22
|
+
const ticks = [];
|
|
23
|
+
const digits = Math.max(0, -Math.floor(Math.log10(step)) + 2);
|
|
24
|
+
for (let v = lo; v <= hi + step / 2; v += step) ticks.push(Number(v.toFixed(digits)));
|
|
25
|
+
return { domain: [lo, hi], ticks };
|
|
26
|
+
}
|
|
27
|
+
function linearScale(domain, range, ticks = domain) {
|
|
28
|
+
const [d0, d1] = domain;
|
|
29
|
+
const [r0, r1] = range;
|
|
30
|
+
const k = d1 === d0 ? 0 : (r1 - r0) / (d1 - d0);
|
|
31
|
+
const scale = ((value) => r0 + (value - d0) * k);
|
|
32
|
+
return Object.assign(scale, { domain, range, ticks });
|
|
33
|
+
}
|
|
34
|
+
function bandScale(count, range, padding = 0.3) {
|
|
35
|
+
const [r0, r1] = range;
|
|
36
|
+
const step = count > 0 ? (r1 - r0) / count : 0;
|
|
37
|
+
const bandwidth = step * (1 - padding);
|
|
38
|
+
const scale = ((index) => r0 + index * step + (step - bandwidth) / 2);
|
|
39
|
+
return Object.assign(scale, { bandwidth, step, count });
|
|
40
|
+
}
|
|
41
|
+
function pointScale(count, range) {
|
|
42
|
+
const [r0, r1] = range;
|
|
43
|
+
if (count <= 1) return () => (r0 + r1) / 2;
|
|
44
|
+
const step = (r1 - r0) / (count - 1);
|
|
45
|
+
return (index) => r0 + index * step;
|
|
46
|
+
}
|
|
47
|
+
function thinLabels(count, max) {
|
|
48
|
+
if (count <= max) return Array.from({ length: count }, (_, i) => i);
|
|
49
|
+
const every = Math.ceil(count / Math.max(1, max));
|
|
50
|
+
const out = [];
|
|
51
|
+
for (let i = 0; i < count; i += every) out.push(i);
|
|
52
|
+
if (out[out.length - 1] !== count - 1) {
|
|
53
|
+
if (count - 1 - out[out.length - 1] < every) out.pop();
|
|
54
|
+
out.push(count - 1);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
niceDomain,
|
|
61
|
+
linearScale,
|
|
62
|
+
bandScale,
|
|
63
|
+
pointScale,
|
|
64
|
+
thinLabels
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=chunk-BISL7DYW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/scale.ts"],"sourcesContent":["// Scales and ticks: the few functions a cartesian chart needs, without d3-scale (the charts draw a handful of shapes;\n// a full scale library would weigh more than the charts themselves).\n\nexport interface LinearScale {\n (value: number): number;\n readonly domain: readonly [number, number];\n readonly range: readonly [number, number];\n readonly ticks: readonly number[];\n}\n\n/** A step of 1, 2, 2.5 or 5 × 10ⁿ near `span / count`: ticks a reader counts without effort (0, 250, 500…). */\nexport function niceStep(span: number, count: number): number {\n if (!(span > 0) || !(count > 0)) return 1;\n const raw = span / count;\n const power = 10 ** Math.floor(Math.log10(raw));\n const fraction = raw / power;\n const nice = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;\n return nice * power;\n}\n\n/**\n * A domain stretched to round ticks: `[0, 4870]` with about 5 ticks → `[0, 5000]`, ticks `0 1000 … 5000`. A single\n * value is padded towards zero, so a lone point never sits on the edge.\n */\nexport function niceDomain(min: number, max: number, count = 5): { domain: [number, number]; ticks: number[] } {\n if (!Number.isFinite(min) || !Number.isFinite(max)) return { domain: [0, 1], ticks: [0, 1] };\n if (min === max) {\n if (min === 0) return { domain: [0, 1], ticks: [0, 0.5, 1] };\n const pad = Math.abs(min) * 0.5;\n [min, max] = min > 0 ? [0, max + pad] : [min - pad, 0];\n }\n const step = niceStep(max - min, count);\n const lo = Math.floor(min / step) * step;\n const hi = Math.ceil(max / step) * step;\n const ticks: number[] = [];\n // Rounded to the step's precision: 0.1 + 0.2 must read 0.3.\n const digits = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n for (let v = lo; v <= hi + step / 2; v += step) ticks.push(Number(v.toFixed(digits)));\n return { domain: [lo, hi], ticks };\n}\n\n/** A linear scale from a domain to pixels, with its round ticks. */\nexport function linearScale(domain: readonly [number, number], range: readonly [number, number], ticks: readonly number[] = domain): LinearScale {\n const [d0, d1] = domain;\n const [r0, r1] = range;\n const k = d1 === d0 ? 0 : (r1 - r0) / (d1 - d0);\n const scale = ((value: number) => r0 + (value - d0) * k) as LinearScale;\n return Object.assign(scale, { domain, range, ticks });\n}\n\nexport interface BandScale {\n (index: number): number;\n /** The width of one band (the bars of a category share it). */\n readonly bandwidth: number;\n /** The distance between the starts of two bands. */\n readonly step: number;\n readonly count: number;\n}\n\n/** `count` bands over the range, with an inner padding between them (a ratio of the step). */\nexport function bandScale(count: number, range: readonly [number, number], padding = 0.3): BandScale {\n const [r0, r1] = range;\n const step = count > 0 ? (r1 - r0) / count : 0;\n const bandwidth = step * (1 - padding);\n const scale = ((index: number) => r0 + index * step + (step - bandwidth) / 2) as BandScale;\n return Object.assign(scale, { bandwidth, step, count });\n}\n\n/** A point scale: `count` points from one end of the range to the other (lines, areas). */\nexport function pointScale(count: number, range: readonly [number, number]): (index: number) => number {\n const [r0, r1] = range;\n if (count <= 1) return () => (r0 + r1) / 2;\n const step = (r1 - r0) / (count - 1);\n return (index) => r0 + index * step;\n}\n\n/** At most `max` of `count` labels, evenly spaced, the last one always kept: which indexes to write on an axis. */\nexport function thinLabels(count: number, max: number): number[] {\n if (count <= max) return Array.from({ length: count }, (_, i) => i);\n const every = Math.ceil(count / Math.max(1, max));\n const out: number[] = [];\n for (let i = 0; i < count; i += every) out.push(i);\n if (out[out.length - 1] !== count - 1) {\n // The last label is always written; the one before it gives way when they would touch.\n if (count - 1 - out[out.length - 1]! < every) out.pop();\n out.push(count - 1);\n }\n return out;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
regionName,
|
|
4
|
+
useWorld
|
|
5
|
+
} from "./chunk-6FINSUOS.js";
|
|
6
|
+
import {
|
|
7
|
+
read
|
|
8
|
+
} from "./chunk-W5FX4TU3.js";
|
|
9
|
+
import {
|
|
10
|
+
shareFormatter,
|
|
11
|
+
valueFormatter
|
|
12
|
+
} from "./chunk-XLLYNNC6.js";
|
|
13
|
+
import {
|
|
14
|
+
ChartFrame,
|
|
15
|
+
RampLegend,
|
|
16
|
+
Tooltip,
|
|
17
|
+
stepColor,
|
|
18
|
+
useMounted,
|
|
19
|
+
useSettings
|
|
20
|
+
} from "./chunk-JTKR7ZWP.js";
|
|
21
|
+
import {
|
|
22
|
+
capitalize,
|
|
23
|
+
fill
|
|
24
|
+
} from "./chunk-3CJHBJXA.js";
|
|
25
|
+
|
|
26
|
+
// src/geo/geo-map.tsx
|
|
27
|
+
import { geoEqualEarth, geoPath } from "d3-geo";
|
|
28
|
+
import { useMemo, useState } from "react";
|
|
29
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
30
|
+
function GeoMap(props) {
|
|
31
|
+
const { data, region, value, format, points = [], steps = 5, regionLabel, valueLabel, onSelect } = props;
|
|
32
|
+
const { locale, labels } = useSettings(props);
|
|
33
|
+
const mounted = useMounted();
|
|
34
|
+
const { world, failed } = useWorld(mounted);
|
|
35
|
+
const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), axis: valueFormatter(format, locale, labels.noValue, true), share: shareFormatter(locale) }), [format, locale, labels.noValue]);
|
|
36
|
+
const rows = useMemo(
|
|
37
|
+
() => data.map((datum, index) => ({ datum, index, code: String(read(region, datum, index)).toUpperCase(), value: Number(read(value, datum, index)) })).filter((r) => Number.isFinite(r.value)).sort((a, b) => b.value - a.value),
|
|
38
|
+
[data, region, value]
|
|
39
|
+
);
|
|
40
|
+
const byCode = useMemo(() => new Map(rows.map((r) => [r.code, r])), [rows]);
|
|
41
|
+
const max = rows[0]?.value ?? 0;
|
|
42
|
+
const min = rows[rows.length - 1]?.value ?? 0;
|
|
43
|
+
const stepOf = (v) => max === min ? steps - 1 : Math.min(steps - 1, Math.floor((v - min) / (max - min) * steps));
|
|
44
|
+
const name = (code) => regionName(code, code, locale);
|
|
45
|
+
const total = rows.reduce((sum, r) => sum + r.value, 0);
|
|
46
|
+
const isEmpty = rows.length === 0 && points.length === 0;
|
|
47
|
+
const summary = isEmpty ? labels.empty : [
|
|
48
|
+
fill(labels.summaryIntro, { kind: labels.kinds.map, count: rows.length || points.length }),
|
|
49
|
+
rows.slice(0, 5).map((r) => fill(labels.summaryShare, { label: name(r.code), value: fmt.value(r.value), share: fmt.share(total ? r.value / total : 0) })).join(", ") + (rows.length ? "." : ""),
|
|
50
|
+
rows.length ? `${capitalize(fill(labels.summaryTotal, { total: fmt.value(total) }))}.` : ""
|
|
51
|
+
].filter(Boolean).join(" ");
|
|
52
|
+
const table = {
|
|
53
|
+
columns: [regionLabel ?? labels.category, valueLabel ?? labels.value, "%"],
|
|
54
|
+
rows: [
|
|
55
|
+
...rows.map((r) => [name(r.code), fmt.value(r.value), fmt.share(total ? r.value / total : 0)]),
|
|
56
|
+
...points.map((p) => [p.label, p.value == null ? labels.noValue : fmt.value(p.value), ""])
|
|
57
|
+
]
|
|
58
|
+
};
|
|
59
|
+
const walk = [...rows.map((r) => ({ kind: "region", code: r.code })), ...points.map((_, i) => ({ kind: "point", i }))];
|
|
60
|
+
const [active, setActive] = useState(null);
|
|
61
|
+
const [hover, setHover] = useState(null);
|
|
62
|
+
const onKeyDown = (event) => {
|
|
63
|
+
const n = walk.length;
|
|
64
|
+
if (!n) return;
|
|
65
|
+
const moves = {
|
|
66
|
+
ArrowRight: () => ((active ?? -1) + 1) % n,
|
|
67
|
+
ArrowDown: () => ((active ?? -1) + 1) % n,
|
|
68
|
+
ArrowLeft: () => ((active ?? 0) - 1 + n) % n,
|
|
69
|
+
ArrowUp: () => ((active ?? 0) - 1 + n) % n,
|
|
70
|
+
Home: () => 0,
|
|
71
|
+
End: () => n - 1,
|
|
72
|
+
Escape: () => null
|
|
73
|
+
};
|
|
74
|
+
const current2 = active !== null ? walk[active] : null;
|
|
75
|
+
if (event.key === "Enter" && current2?.kind === "region" && onSelect) {
|
|
76
|
+
const row = byCode.get(current2.code);
|
|
77
|
+
onSelect(row.datum, row.index);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const move = moves[event.key];
|
|
81
|
+
if (!move) return;
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
setHover(null);
|
|
84
|
+
setActive(move());
|
|
85
|
+
};
|
|
86
|
+
const current = active !== null ? walk[active] : null;
|
|
87
|
+
const announce = !current ? "" : current.kind === "region" ? `${name(current.code)}: ${fmt.value(byCode.get(current.code).value)}` : `${points[current.i].label}${points[current.i].value != null ? `: ${fmt.value(points[current.i].value)}` : ""}`;
|
|
88
|
+
const legend = rows.length > 0 ? /* @__PURE__ */ jsx(RampLegend, { min, max, steps, write: fmt.axis }) : null;
|
|
89
|
+
return /* @__PURE__ */ jsx(
|
|
90
|
+
ChartFrame,
|
|
91
|
+
{
|
|
92
|
+
kind: "map",
|
|
93
|
+
frame: { ...props, error: props.error ?? (failed || void 0), loading: props.loading || mounted && !world && !failed },
|
|
94
|
+
pending: !world && !failed,
|
|
95
|
+
defaultHeight: 360,
|
|
96
|
+
table,
|
|
97
|
+
summary,
|
|
98
|
+
isEmpty,
|
|
99
|
+
legend,
|
|
100
|
+
announcement: announce,
|
|
101
|
+
active: active !== null,
|
|
102
|
+
handlers: {
|
|
103
|
+
onKeyDown,
|
|
104
|
+
onBlur: () => setActive(null),
|
|
105
|
+
onPointerLeave: () => setHover(null)
|
|
106
|
+
},
|
|
107
|
+
children: (width, height) => {
|
|
108
|
+
if (!world) return null;
|
|
109
|
+
const projection = geoEqualEarth().fitExtent(
|
|
110
|
+
[
|
|
111
|
+
[4, 4],
|
|
112
|
+
[width - 4, height - 4]
|
|
113
|
+
],
|
|
114
|
+
{ type: "Sphere" }
|
|
115
|
+
);
|
|
116
|
+
const path = geoPath(projection);
|
|
117
|
+
const maxPoint = Math.max(0, ...points.map((p) => p.value ?? 0));
|
|
118
|
+
const radiusOf = (p) => p.value && maxPoint ? 3 + Math.sqrt(p.value / maxPoint) * 15 : 4;
|
|
119
|
+
const focusCode = hover?.code ?? (current?.kind === "region" ? current.code : null);
|
|
120
|
+
let tip = null;
|
|
121
|
+
if (hover) {
|
|
122
|
+
const row = byCode.get(hover.code);
|
|
123
|
+
tip = { x: hover.x, y: hover.y, title: name(hover.code), value: row ? fmt.value(row.value) : labels.noValue };
|
|
124
|
+
} else if (current?.kind === "region") {
|
|
125
|
+
const feature = world.features.find((f) => f.id === current.code);
|
|
126
|
+
const [cx, cy] = feature ? path.centroid(feature) : [width / 2, height / 2];
|
|
127
|
+
tip = { x: cx, y: cy, title: name(current.code), value: fmt.value(byCode.get(current.code).value) };
|
|
128
|
+
} else if (current?.kind === "point") {
|
|
129
|
+
const p = points[current.i];
|
|
130
|
+
const [px, py] = projection([p.lon, p.lat]) ?? [0, 0];
|
|
131
|
+
tip = { x: px, y: py, title: p.label, value: p.value == null ? "" : fmt.value(p.value) };
|
|
132
|
+
}
|
|
133
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
134
|
+
/* @__PURE__ */ jsxs("svg", { className: "kzc-svg kzc-enter-fade", width, height, viewBox: `0 0 ${width} ${height}`, "aria-hidden": true, children: [
|
|
135
|
+
/* @__PURE__ */ jsx("path", { d: path({ type: "Sphere" }) ?? "", style: { fill: "var(--kz-surface-2)", opacity: 0.5 } }),
|
|
136
|
+
world.features.map((f, i) => {
|
|
137
|
+
const row = f.id ? byCode.get(f.id) : void 0;
|
|
138
|
+
return /* @__PURE__ */ jsx(
|
|
139
|
+
"path",
|
|
140
|
+
{
|
|
141
|
+
d: path(f) ?? "",
|
|
142
|
+
className: "kzc-mark",
|
|
143
|
+
"data-dim": focusCode && focusCode !== f.id ? "" : void 0,
|
|
144
|
+
style: {
|
|
145
|
+
fill: row ? stepColor(stepOf(row.value), steps) : "var(--kz-surface-3)",
|
|
146
|
+
stroke: focusCode === f.id ? "var(--kzc-text)" : "var(--kzc-surface)",
|
|
147
|
+
strokeWidth: focusCode === f.id ? 1.5 : 0.5,
|
|
148
|
+
cursor: row && onSelect ? "pointer" : void 0
|
|
149
|
+
},
|
|
150
|
+
onPointerMove: (event) => {
|
|
151
|
+
if (!f.id) return;
|
|
152
|
+
const box = (event.currentTarget.ownerSVGElement ?? event.currentTarget).getBoundingClientRect();
|
|
153
|
+
setActive(null);
|
|
154
|
+
setHover({ code: f.id, x: event.clientX - box.left, y: event.clientY - box.top });
|
|
155
|
+
},
|
|
156
|
+
onClick: row && onSelect ? () => onSelect(row.datum, row.index) : void 0
|
|
157
|
+
},
|
|
158
|
+
`${f.id ?? "x"}-${i}`
|
|
159
|
+
);
|
|
160
|
+
}),
|
|
161
|
+
points.map((p, i) => {
|
|
162
|
+
const at = projection([p.lon, p.lat]);
|
|
163
|
+
if (!at) return null;
|
|
164
|
+
const on = current?.kind === "point" && current.i === i;
|
|
165
|
+
return /* @__PURE__ */ jsx("circle", { cx: at[0], cy: at[1], r: radiusOf(p), className: "kzc-dot", style: { fill: "var(--kzc-2)", fillOpacity: on ? 1 : 0.8, strokeWidth: on ? 2.5 : 1.5 } }, `${p.label}-${i}`);
|
|
166
|
+
})
|
|
167
|
+
] }),
|
|
168
|
+
tip && /* @__PURE__ */ jsx(Tooltip, { x: tip.x, y: tip.y, width, title: tip.title, rows: tip.value ? [{ label: valueLabel ?? labels.value, value: tip.value }] : [] })
|
|
169
|
+
] });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export {
|
|
176
|
+
GeoMap
|
|
177
|
+
};
|
|
178
|
+
//# sourceMappingURL=chunk-BV4DBGN7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/geo/geo-map.tsx"],"sourcesContent":["\"use client\";\n// Where: a choropleth of the world (one sequential hue — the brand's — in even steps from near the surface), and\n// optional bubbles on places (cities, data centres). Plain SVG through d3-geo's Equal Earth projection (areas stay\n// true: no Greenland the size of Africa); country names in the reader's language (Intl.DisplayNames). The keyboard\n// walks the regions that have data, largest first.\nimport { geoEqualEarth, geoPath } from \"d3-geo\";\nimport { type KeyboardEvent, useMemo, useState } from \"react\";\n\nimport { read } from \"../core/data\";\nimport { shareFormatter, valueFormatter } from \"../core/format\";\nimport { capitalize, fill } from \"../core/labels\";\nimport type { Accessor, Datum, ValueFormat } from \"../core/types\";\nimport { ChartFrame, type ChartFrameProps, useSettings } from \"../web/frame\";\nimport { useMounted } from \"../web/hooks\";\nimport { RampLegend, stepColor, Tooltip } from \"../web/parts\";\nimport { regionName, useWorld } from \"./world\";\n\n/** A place on the map or the globe. */\nexport interface GeoPoint {\n /** Longitude, then latitude, in degrees. */\n readonly lon: number;\n readonly lat: number;\n /** Its name (“Montréal”, “eu-west-3 · Paris”). */\n readonly label: string;\n /** An amount: the bubble's area on a map; written in the tooltip and the table. */\n readonly value?: number;\n}\n\nexport interface GeoMapProps<T extends Datum> extends ChartFrameProps {\n /** One row per region with a value. */\n data: readonly T[];\n /** The field (or function) of the region's ISO 3166-1 alpha-2 code (`\"FR\"`, `\"US\"`). */\n region: Accessor<T, string>;\n /** The field (or function) of its value. */\n value: Accessor<T, number>;\n /** How the values are written. */\n format?: ValueFormat;\n /** Bubbles on places, their area by `value`. */\n points?: readonly GeoPoint[];\n /** The number of colour steps of the scale. Default 5. */\n steps?: number;\n /** The header of the regions and of the values in the table (“Country”, “Viewers”). */\n regionLabel?: string;\n/** The header of the values (“Viewers”). */\n valueLabel?: string;\n /** Called with the row when a region is clicked (or Enter is pressed on it). */\n onSelect?: (datum: T, index: number) => void;\n}\n\nexport function GeoMap<T extends Datum>(props: GeoMapProps<T>) {\n const { data, region, value, format, points = [], steps = 5, regionLabel, valueLabel, onSelect } = props;\n const { locale, labels } = useSettings(props);\n const mounted = useMounted();\n const { world, failed } = useWorld(mounted);\n const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), axis: valueFormatter(format, locale, labels.noValue, true), share: shareFormatter(locale) }), [format, locale, labels.noValue]);\n\n const rows = useMemo(\n () =>\n data\n .map((datum, index) => ({ datum, index, code: String(read(region, datum, index)).toUpperCase(), value: Number(read(value, datum, index)) }))\n .filter((r) => Number.isFinite(r.value))\n .sort((a, b) => b.value - a.value),\n [data, region, value],\n );\n const byCode = useMemo(() => new Map(rows.map((r) => [r.code, r])), [rows]);\n const max = rows[0]?.value ?? 0;\n const min = rows[rows.length - 1]?.value ?? 0;\n const stepOf = (v: number) => (max === min ? steps - 1 : Math.min(steps - 1, Math.floor(((v - min) / (max - min)) * steps)));\n const name = (code: string) => regionName(code, code, locale);\n const total = rows.reduce((sum, r) => sum + r.value, 0);\n const isEmpty = rows.length === 0 && points.length === 0;\n\n const summary = isEmpty\n ? labels.empty\n : [\n fill(labels.summaryIntro, { kind: labels.kinds.map, count: rows.length || points.length }),\n rows\n .slice(0, 5)\n .map((r) => fill(labels.summaryShare, { label: name(r.code), value: fmt.value(r.value), share: fmt.share(total ? r.value / total : 0) }))\n .join(\", \") + (rows.length ? \".\" : \"\"),\n rows.length ? `${capitalize(fill(labels.summaryTotal, { total: fmt.value(total) }))}.` : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n const table = {\n columns: [regionLabel ?? labels.category, valueLabel ?? labels.value, \"%\"],\n rows: [\n ...rows.map((r) => [name(r.code), fmt.value(r.value), fmt.share(total ? r.value / total : 0)]),\n ...points.map((p) => [p.label, p.value == null ? labels.noValue : fmt.value(p.value), \"\"]),\n ],\n };\n\n const walk = [...rows.map((r) => ({ kind: \"region\" as const, code: r.code })), ...points.map((_, i) => ({ kind: \"point\" as const, i }))];\n const [active, setActive] = useState<number | null>(null);\n const [hover, setHover] = useState<{ code: string; x: number; y: number } | null>(null);\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const n = walk.length;\n if (!n) return;\n const moves: Record<string, () => number | null> = {\n ArrowRight: () => ((active ?? -1) + 1) % n,\n ArrowDown: () => ((active ?? -1) + 1) % n,\n ArrowLeft: () => ((active ?? 0) - 1 + n) % n,\n ArrowUp: () => ((active ?? 0) - 1 + n) % n,\n Home: () => 0,\n End: () => n - 1,\n Escape: () => null,\n };\n const current = active !== null ? walk[active] : null;\n if (event.key === \"Enter\" && current?.kind === \"region\" && onSelect) {\n const row = byCode.get(current.code)!;\n onSelect(row.datum, row.index);\n return;\n }\n const move = moves[event.key];\n if (!move) return;\n event.preventDefault();\n setHover(null);\n setActive(move());\n };\n const current = active !== null ? walk[active] : null;\n const announce = !current ? \"\" : current.kind === \"region\" ? `${name(current.code)}: ${fmt.value(byCode.get(current.code)!.value)}` : `${points[current.i]!.label}${points[current.i]!.value != null ? `: ${fmt.value(points[current.i]!.value)}` : \"\"}`;\n\n const legend = rows.length > 0 ? <RampLegend min={min} max={max} steps={steps} write={fmt.axis} /> : null;\n\n return (\n <ChartFrame\n kind=\"map\"\n frame={{ ...props, error: props.error ?? (failed || undefined), loading: props.loading || (mounted && !world && !failed) }}\n pending={!world && !failed}\n defaultHeight={360}\n table={table}\n summary={summary}\n isEmpty={isEmpty}\n legend={legend}\n announcement={announce}\n active={active !== null}\n handlers={{\n onKeyDown,\n onBlur: () => setActive(null),\n onPointerLeave: () => setHover(null),\n }}\n >\n {(width, height) => {\n if (!world) return null;\n const projection = geoEqualEarth().fitExtent(\n [\n [4, 4],\n [width - 4, height - 4],\n ],\n { type: \"Sphere\" },\n );\n const path = geoPath(projection);\n const maxPoint = Math.max(0, ...points.map((p) => p.value ?? 0));\n const radiusOf = (p: GeoPoint) => (p.value && maxPoint ? 3 + Math.sqrt(p.value / maxPoint) * 15 : 4);\n const focusCode = hover?.code ?? (current?.kind === \"region\" ? current.code : null);\n let tip: { x: number; y: number; title: string; value: string } | null = null;\n if (hover) {\n const row = byCode.get(hover.code);\n tip = { x: hover.x, y: hover.y, title: name(hover.code), value: row ? fmt.value(row.value) : labels.noValue };\n } else if (current?.kind === \"region\") {\n const feature = world.features.find((f) => f.id === current.code);\n const [cx, cy] = feature ? path.centroid(feature) : [width / 2, height / 2];\n tip = { x: cx, y: cy, title: name(current.code), value: fmt.value(byCode.get(current.code)!.value) };\n } else if (current?.kind === \"point\") {\n const p = points[current.i]!;\n const [px, py] = projection([p.lon, p.lat]) ?? [0, 0];\n tip = { x: px, y: py, title: p.label, value: p.value == null ? \"\" : fmt.value(p.value) };\n }\n return (\n <>\n <svg className=\"kzc-svg kzc-enter-fade\" width={width} height={height} viewBox={`0 0 ${width} ${height}`} aria-hidden>\n <path d={path({ type: \"Sphere\" }) ?? \"\"} style={{ fill: \"var(--kz-surface-2)\", opacity: 0.5 }} />\n {world.features.map((f, i) => {\n const row = f.id ? byCode.get(f.id) : undefined;\n return (\n <path\n key={`${f.id ?? \"x\"}-${i}`}\n d={path(f) ?? \"\"}\n className=\"kzc-mark\"\n data-dim={focusCode && focusCode !== f.id ? \"\" : undefined}\n style={{\n fill: row ? stepColor(stepOf(row.value), steps) : \"var(--kz-surface-3)\",\n stroke: focusCode === f.id ? \"var(--kzc-text)\" : \"var(--kzc-surface)\",\n strokeWidth: focusCode === f.id ? 1.5 : 0.5,\n cursor: row && onSelect ? \"pointer\" : undefined,\n }}\n onPointerMove={(event) => {\n if (!f.id) return;\n const box = (event.currentTarget.ownerSVGElement ?? event.currentTarget).getBoundingClientRect();\n setActive(null);\n setHover({ code: f.id, x: event.clientX - box.left, y: event.clientY - box.top });\n }}\n onClick={row && onSelect ? () => onSelect(row.datum, row.index) : undefined}\n />\n );\n })}\n {points.map((p, i) => {\n const at = projection([p.lon, p.lat]);\n if (!at) return null;\n const on = current?.kind === \"point\" && current.i === i;\n return <circle key={`${p.label}-${i}`} cx={at[0]} cy={at[1]} r={radiusOf(p)} className=\"kzc-dot\" style={{ fill: \"var(--kzc-2)\", fillOpacity: on ? 1 : 0.8, strokeWidth: on ? 2.5 : 1.5 }} />;\n })}\n </svg>\n {tip && <Tooltip x={tip.x} y={tip.y} width={width} title={tip.title} rows={tip.value ? [{ label: valueLabel ?? labels.value, value: tip.value }] : []} />}\n </>\n );\n }}\n </ChartFrame>\n );\n}\n"],"mappings":"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","names":["current"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Cartesian
|
|
4
|
+
} from "./chunk-CVWSMUUB.js";
|
|
5
|
+
|
|
6
|
+
// src/line/line-chart.tsx
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
function LineChart({ curve, dots, endLabels = true, ...props }) {
|
|
9
|
+
return /* @__PURE__ */ jsx(Cartesian, { props, options: { kind: "line", mode: "line", curve, dots, endLabels } });
|
|
10
|
+
}
|
|
11
|
+
function AreaChart({ curve, dots, endLabels = true, stacked, ...props }) {
|
|
12
|
+
return /* @__PURE__ */ jsx(Cartesian, { props, options: { kind: "area", mode: "area", curve, dots, endLabels: endLabels && !stacked, stacked } });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
LineChart,
|
|
17
|
+
AreaChart
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=chunk-C4MFZLJM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/line/line-chart.tsx"],"sourcesContent":["\"use client\";\nimport { Cartesian, type CartesianProps } from \"../cartesian/cartesian\";\nimport type { Curve } from \"../core/shape\";\nimport type { Datum } from \"../core/types\";\n\nexport interface LineChartProps<T extends Datum> extends CartesianProps<T> {\n /** The shape between points: `monotone` (default, never overshoots), `linear`, `step` (a value that holds). */\n curve?: Curve;\n /** A dot on every point (short series). Default false: the end of each line carries one. */\n dots?: boolean;\n /** Write the last value at the end of each line (up to three series). Default true. */\n endLabels?: boolean;\n}\n\n/** Change over time: one line per series, the last value written at its end, a crosshair tooltip, the keyboard. */\nexport function LineChart<T extends Datum>({ curve, dots, endLabels = true, ...props }: LineChartProps<T>) {\n return <Cartesian props={props} options={{ kind: \"line\", mode: \"line\", curve, dots, endLabels }} />;\n}\n\nexport interface AreaChartProps<T extends Datum> extends LineChartProps<T> {\n /** Stack the series: a total and its parts over time. */\n stacked?: boolean;\n}\n\n/** A volume over time: a line over a soft wash (stacked: the parts of a total). */\nexport function AreaChart<T extends Datum>({ curve, dots, endLabels = true, stacked, ...props }: AreaChartProps<T>) {\n return <Cartesian props={props} options={{ kind: \"area\", mode: \"area\", curve, dots, endLabels: endLabels && !stacked, stacked }} />;\n}\n"],"mappings":";;;;;;AAgBS;AADF,SAAS,UAA2B,EAAE,OAAO,MAAM,YAAY,MAAM,GAAG,MAAM,GAAsB;AACzG,SAAO,oBAAC,aAAU,OAAc,SAAS,EAAE,MAAM,QAAQ,MAAM,QAAQ,OAAO,MAAM,UAAU,GAAG;AACnG;AAQO,SAAS,UAA2B,EAAE,OAAO,MAAM,YAAY,MAAM,SAAS,GAAG,MAAM,GAAsB;AAClH,SAAO,oBAAC,aAAU,OAAc,SAAS,EAAE,MAAM,QAAQ,MAAM,QAAQ,OAAO,MAAM,WAAW,aAAa,CAAC,SAAS,QAAQ,GAAG;AACnI;","names":[]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
EChartHost,
|
|
4
|
+
baseOption,
|
|
5
|
+
tooltipHtml
|
|
6
|
+
} from "./chunk-PWMMXRMC.js";
|
|
7
|
+
import {
|
|
8
|
+
read
|
|
9
|
+
} from "./chunk-W5FX4TU3.js";
|
|
10
|
+
import {
|
|
11
|
+
shareFormatter,
|
|
12
|
+
valueFormatter
|
|
13
|
+
} from "./chunk-XLLYNNC6.js";
|
|
14
|
+
import {
|
|
15
|
+
useSettings
|
|
16
|
+
} from "./chunk-JTKR7ZWP.js";
|
|
17
|
+
import {
|
|
18
|
+
capitalize,
|
|
19
|
+
fill
|
|
20
|
+
} from "./chunk-3CJHBJXA.js";
|
|
21
|
+
|
|
22
|
+
// src/funnel/funnel.tsx
|
|
23
|
+
import { useCallback, useMemo } from "react";
|
|
24
|
+
import { jsx } from "react/jsx-runtime";
|
|
25
|
+
var engine = () => import("./funnel-QU5ZPC52.js");
|
|
26
|
+
function Funnel(props) {
|
|
27
|
+
const { data, label, value, format = "integer", stageLabel, valueLabel, fromFirstLabel = "% first", fromPreviousLabel = "% previous" } = props;
|
|
28
|
+
const { locale, labels } = useSettings(props);
|
|
29
|
+
const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), share: shareFormatter(locale) }), [format, locale, labels.noValue]);
|
|
30
|
+
const stages = useMemo(() => data.map((d, i) => ({ label: String(read(label, d, i)), value: Math.max(0, Number(read(value, d, i)) || 0) })), [data, label, value]);
|
|
31
|
+
const isEmpty = stages.length === 0 || stages.every((s) => s.value === 0);
|
|
32
|
+
const first = stages[0]?.value ?? 0;
|
|
33
|
+
const rate = useCallback((i) => i === 0 || !stages[i - 1].value ? 1 : stages[i].value / stages[i - 1].value, [stages]);
|
|
34
|
+
const overall = first && stages.length ? stages[stages.length - 1].value / first : 0;
|
|
35
|
+
const summary = isEmpty ? labels.empty : [
|
|
36
|
+
fill(labels.summaryIntro, { kind: labels.kinds.funnel, count: stages.length }),
|
|
37
|
+
`${stages.slice(1).map((s, k) => fill(labels.summaryConversion, { from: stages[k].label, to: s.label, rate: fmt.share(rate(k + 1)) })).join(", ")}.`,
|
|
38
|
+
`${capitalize(fill(labels.summaryOverall, { rate: fmt.share(overall) }))}.`
|
|
39
|
+
].join(" ");
|
|
40
|
+
const items = stages.map((s, i) => ({ seriesIndex: 0, dataIndex: i, text: `${s.label}: ${fmt.value(s.value)}${i ? ` (${fmt.share(rate(i))})` : ""}` }));
|
|
41
|
+
const build = useCallback(
|
|
42
|
+
(theme, size) => {
|
|
43
|
+
const base = baseOption(theme, true);
|
|
44
|
+
const steps = [...theme.ramp].reverse();
|
|
45
|
+
const labelRoom = Math.min(220, Math.max(120, size.width * 0.38));
|
|
46
|
+
return {
|
|
47
|
+
...base,
|
|
48
|
+
tooltip: {
|
|
49
|
+
...base.tooltip,
|
|
50
|
+
trigger: "item",
|
|
51
|
+
formatter: (p) => {
|
|
52
|
+
const i = p.dataIndex;
|
|
53
|
+
const s = stages[i];
|
|
54
|
+
return tooltipHtml(
|
|
55
|
+
s.label,
|
|
56
|
+
[
|
|
57
|
+
{ label: valueLabel ?? labels.value, value: fmt.value(s.value) },
|
|
58
|
+
...i ? [{ label: fromPreviousLabel, value: fmt.share(rate(i)) }] : [],
|
|
59
|
+
{ label: fromFirstLabel, value: fmt.share(first ? s.value / first : 0) }
|
|
60
|
+
]
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
series: [
|
|
65
|
+
{
|
|
66
|
+
type: "funnel",
|
|
67
|
+
sort: "none",
|
|
68
|
+
left: 8,
|
|
69
|
+
right: labelRoom,
|
|
70
|
+
top: 8,
|
|
71
|
+
bottom: 8,
|
|
72
|
+
minSize: "8%",
|
|
73
|
+
gap: 2,
|
|
74
|
+
data: stages.map((s, i) => ({ name: s.label, value: s.value, itemStyle: { color: steps[Math.round(i / Math.max(1, stages.length - 1) * (steps.length - 2))], borderWidth: 0 } })),
|
|
75
|
+
label: {
|
|
76
|
+
position: "right",
|
|
77
|
+
color: theme.text,
|
|
78
|
+
fontFamily: theme.font,
|
|
79
|
+
fontSize: 12,
|
|
80
|
+
formatter: (p) => {
|
|
81
|
+
const i = p.dataIndex;
|
|
82
|
+
return `{name|${stages[i].label}} {value|${fmt.value(stages[i].value)}}${i ? ` {rate|${fmt.share(rate(i))}}` : ""}`;
|
|
83
|
+
},
|
|
84
|
+
rich: { name: { color: theme.text2, fontSize: 12 }, value: { color: theme.text, fontWeight: 600, fontSize: 12 }, rate: { color: theme.text3, fontSize: 11 } }
|
|
85
|
+
},
|
|
86
|
+
labelLine: { lineStyle: { color: theme.axis } },
|
|
87
|
+
emphasis: { itemStyle: { borderColor: theme.text, borderWidth: 2 } }
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
[stages, fmt, first, valueLabel, fromFirstLabel, fromPreviousLabel, labels.value, rate]
|
|
93
|
+
);
|
|
94
|
+
return /* @__PURE__ */ jsx(
|
|
95
|
+
EChartHost,
|
|
96
|
+
{
|
|
97
|
+
kind: "funnel",
|
|
98
|
+
frame: props,
|
|
99
|
+
defaultHeight: 280,
|
|
100
|
+
table: {
|
|
101
|
+
columns: [stageLabel ?? labels.category, valueLabel ?? labels.value, fromFirstLabel, fromPreviousLabel],
|
|
102
|
+
rows: stages.map((s, i) => [s.label, fmt.value(s.value), fmt.share(first ? s.value / first : 0), i ? fmt.share(rate(i)) : labels.noValue])
|
|
103
|
+
},
|
|
104
|
+
summary,
|
|
105
|
+
isEmpty,
|
|
106
|
+
engine,
|
|
107
|
+
build,
|
|
108
|
+
items
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export {
|
|
114
|
+
Funnel
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=chunk-CSSZLFLO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/funnel/funnel.tsx"],"sourcesContent":["\"use client\";\n// Stages that lose people on the way — sign-up, verification, first video, first sale — with what the industry's\n// funnels leave out: the conversion from each stage to the next and from the first, written beside each stage, in the\n// summary and in the table. Ordinal steps of the brand hue (full → light), labels outside the shapes in the text\n// colours. ECharts, loaded when the chart nears the screen.\nimport { useCallback, useMemo } from \"react\";\n\nimport { read } from \"../core/data\";\nimport { shareFormatter, valueFormatter } from \"../core/format\";\nimport { capitalize, fill } from \"../core/labels\";\nimport type { Accessor, Datum, ValueFormat } from \"../core/types\";\nimport { EChartHost, type EngineProps, type WalkItem } from \"../echarts/host\";\nimport { baseOption, type ResolvedTheme, tooltipHtml } from \"../echarts/theme\";\nimport type { ChartFrameProps } from \"../web/frame\";\nimport { useSettings } from \"../web/frame\";\n\nconst engine = () => import(\"../echarts/engines/funnel\");\n\nexport interface FunnelProps<T extends Datum> extends ChartFrameProps, EngineProps {\n /** One row per stage, first stage first. */\n data: readonly T[];\n /** The field (or function) naming the stage. */\n label: Accessor<T, string>;\n /** The field of how many reached it. */\n value: Accessor<T, number>;\n /** How the counts are written. Default `\"integer\"`. */\n format?: ValueFormat;\n /** The headers of the data table: the stage, the count, the share of the first, of the previous. */\n stageLabel?: string;\n/** The header of the counts. */\n valueLabel?: string;\n/** The header of the share of the first stage. Default “% first”. */\n fromFirstLabel?: string;\n/** The header of the share of the previous stage. Default “% previous”. */\n fromPreviousLabel?: string;\n}\n\nexport function Funnel<T extends Datum>(props: FunnelProps<T>) {\n const { data, label, value, format = \"integer\", stageLabel, valueLabel, fromFirstLabel = \"% first\", fromPreviousLabel = \"% previous\" } = props;\n const { locale, labels } = useSettings(props);\n const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), share: shareFormatter(locale) }), [format, locale, labels.noValue]);\n const stages = useMemo(() => data.map((d, i) => ({ label: String(read(label, d, i)), value: Math.max(0, Number(read(value, d, i)) || 0) })), [data, label, value]);\n const isEmpty = stages.length === 0 || stages.every((s) => s.value === 0);\n const first = stages[0]?.value ?? 0;\n const rate = useCallback((i: number) => (i === 0 || !stages[i - 1]!.value ? 1 : stages[i]!.value / stages[i - 1]!.value), [stages]);\n const overall = first && stages.length ? stages[stages.length - 1]!.value / first : 0;\n const summary = isEmpty\n ? labels.empty\n : [\n fill(labels.summaryIntro, { kind: labels.kinds.funnel, count: stages.length }),\n `${stages\n .slice(1)\n .map((s, k) => fill(labels.summaryConversion, { from: stages[k]!.label, to: s.label, rate: fmt.share(rate(k + 1)) }))\n .join(\", \")}.`,\n `${capitalize(fill(labels.summaryOverall, { rate: fmt.share(overall) }))}.`,\n ].join(\" \");\n const items: WalkItem[] = stages.map((s, i) => ({ seriesIndex: 0, dataIndex: i, text: `${s.label}: ${fmt.value(s.value)}${i ? ` (${fmt.share(rate(i))})` : \"\"}` }));\n\n const build = useCallback(\n (theme: ResolvedTheme, size: { width: number }) => {\n const base = baseOption(theme, true);\n const steps = [...theme.ramp].reverse();\n const labelRoom = Math.min(220, Math.max(120, size.width * 0.38));\n return {\n ...base,\n tooltip: {\n ...(base.tooltip as object),\n trigger: \"item\",\n formatter: (p: { dataIndex: number }) => {\n const i = p.dataIndex;\n const s = stages[i]!;\n return tooltipHtml(\n s.label,\n [\n { label: valueLabel ?? labels.value, value: fmt.value(s.value) },\n ...(i ? [{ label: fromPreviousLabel, value: fmt.share(rate(i)) }] : []),\n { label: fromFirstLabel, value: fmt.share(first ? s.value / first : 0) },\n ],\n );\n },\n },\n series: [\n {\n type: \"funnel\",\n sort: \"none\",\n left: 8,\n right: labelRoom,\n top: 8,\n bottom: 8,\n minSize: \"8%\",\n gap: 2,\n data: stages.map((s, i) => ({ name: s.label, value: s.value, itemStyle: { color: steps[Math.round((i / Math.max(1, stages.length - 1)) * (steps.length - 2))], borderWidth: 0 } })),\n label: {\n position: \"right\",\n color: theme.text,\n fontFamily: theme.font,\n fontSize: 12,\n formatter: (p: { dataIndex: number }) => {\n const i = p.dataIndex;\n return `{name|${stages[i]!.label}} {value|${fmt.value(stages[i]!.value)}}${i ? ` {rate|${fmt.share(rate(i))}}` : \"\"}`;\n },\n rich: { name: { color: theme.text2, fontSize: 12 }, value: { color: theme.text, fontWeight: 600, fontSize: 12 }, rate: { color: theme.text3, fontSize: 11 } },\n },\n labelLine: { lineStyle: { color: theme.axis } },\n emphasis: { itemStyle: { borderColor: theme.text, borderWidth: 2 } },\n },\n ],\n };\n },\n [stages, fmt, first, valueLabel, fromFirstLabel, fromPreviousLabel, labels.value, rate],\n );\n\n return (\n <EChartHost\n kind=\"funnel\"\n frame={props}\n defaultHeight={280}\n table={{\n columns: [stageLabel ?? labels.category, valueLabel ?? labels.value, fromFirstLabel, fromPreviousLabel],\n rows: stages.map((s, i) => [s.label, fmt.value(s.value), fmt.share(first ? s.value / first : 0), i ? fmt.share(rate(i)) : labels.noValue]),\n }}\n summary={summary}\n isEmpty={isEmpty}\n engine={engine}\n build={build}\n items={items}\n />\n );\n}\n"],"mappings":"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","names":[]}
|