@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,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
BarChart
|
|
4
|
+
} from "./chunk-WVTIKOII.js";
|
|
5
|
+
import {
|
|
6
|
+
Kpi
|
|
7
|
+
} from "./chunk-WBHFVBSK.js";
|
|
8
|
+
import {
|
|
9
|
+
THROUGHPUT_LABELS,
|
|
10
|
+
fillIn,
|
|
11
|
+
successRate,
|
|
12
|
+
total
|
|
13
|
+
} from "./chunk-WNUFGMS7.js";
|
|
14
|
+
import {
|
|
15
|
+
valueFormatter
|
|
16
|
+
} from "./chunk-XLLYNNC6.js";
|
|
17
|
+
import {
|
|
18
|
+
useSettings
|
|
19
|
+
} from "./chunk-JTKR7ZWP.js";
|
|
20
|
+
|
|
21
|
+
// src/needs/statuses.ts
|
|
22
|
+
var DEFAULT_STATUSES = [
|
|
23
|
+
{ key: "completed", label: "Completed", tone: "success", outcome: "succeeded" },
|
|
24
|
+
{ key: "failed", label: "Failed", tone: "danger", outcome: "failed" },
|
|
25
|
+
{ key: "running", label: "Running", tone: "info" },
|
|
26
|
+
{ key: "queued", label: "Queued", tone: "neutral" }
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
// src/throughput/job-throughput.tsx
|
|
30
|
+
import { useMemo } from "react";
|
|
31
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
32
|
+
function JobThroughput({
|
|
33
|
+
x = "day",
|
|
34
|
+
period = "day",
|
|
35
|
+
statuses = DEFAULT_STATUSES,
|
|
36
|
+
hideSummary,
|
|
37
|
+
labels: given,
|
|
38
|
+
description,
|
|
39
|
+
data,
|
|
40
|
+
...props
|
|
41
|
+
}) {
|
|
42
|
+
const words = { ...THROUGHPUT_LABELS, ...given };
|
|
43
|
+
const { locale } = useSettings(props);
|
|
44
|
+
const series = useMemo(
|
|
45
|
+
() => statuses.map((s) => ({ key: s.key, label: s.label, color: s.tone })),
|
|
46
|
+
[statuses]
|
|
47
|
+
);
|
|
48
|
+
const sum = (outcome) => statuses.filter((s) => outcome === void 0 || s.outcome === outcome).reduce((n, s) => n + total(data, s.key), 0);
|
|
49
|
+
const rate = successRate(sum("succeeded"), sum("failed"));
|
|
50
|
+
const summary = hideSummary ? null : /* @__PURE__ */ jsx(
|
|
51
|
+
Kpi,
|
|
52
|
+
{
|
|
53
|
+
value: valueFormatter("integer", locale)(sum()),
|
|
54
|
+
label: fillIn(words.total, { count: data.length }),
|
|
55
|
+
delta: rate == null ? null : fillIn(words.success, { rate: valueFormatter("percent", locale)(rate) })
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
return /* @__PURE__ */ jsx(
|
|
59
|
+
BarChart,
|
|
60
|
+
{
|
|
61
|
+
...props,
|
|
62
|
+
data,
|
|
63
|
+
x,
|
|
64
|
+
xFormat: period,
|
|
65
|
+
series,
|
|
66
|
+
format: "integer",
|
|
67
|
+
stacked: true,
|
|
68
|
+
description: description || summary ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
69
|
+
description,
|
|
70
|
+
description && summary ? /* @__PURE__ */ jsx("br", {}) : null,
|
|
71
|
+
summary
|
|
72
|
+
] }) : void 0
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
DEFAULT_STATUSES,
|
|
79
|
+
JobThroughput
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=chunk-SLEJDQ3A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/needs/statuses.ts","../src/throughput/job-throughput.tsx"],"sourcesContent":["import type { Tone } from \"../core/types\";\n\n/** A status of a job: the field holding its count per period, its name, its tone, and its part in the success rate. */\nexport interface JobStatus {\n /** The field of the row holding the count (`\"completed\"`). */\n readonly key: string;\n /** Its name, passed translated (`\"Completed\"`). */\n readonly label: string;\n /** Its tone: the status colours (`success`, `danger`, `info`, `neutral`). */\n readonly tone: Tone;\n /** `succeeded` or `failed`: counted in the success rate. Absent: still running or waiting. */\n readonly outcome?: \"succeeded\" | \"failed\";\n}\n\n/** The four statuses of an Orazaka job, in English: pass your own (translated) `statuses`. */\nexport const DEFAULT_STATUSES: readonly JobStatus[] = [\n { key: \"completed\", label: \"Completed\", tone: \"success\", outcome: \"succeeded\" },\n { key: \"failed\", label: \"Failed\", tone: \"danger\", outcome: \"failed\" },\n { key: \"running\", label: \"Running\", tone: \"info\" },\n { key: \"queued\", label: \"Queued\", tone: \"neutral\" },\n];\n","\"use client\";\n// Jobs per period, stacked by status (Orazaka insights, the console's supervision, the mobile Jobs screen): the total\n// and the success rate of the finished jobs written above, `live` for a stream. A stacked BarChart preset.\nimport { useMemo } from \"react\";\n\nimport { BarChart } from \"../bar/bar-chart\";\nimport type { CartesianProps } from \"../cartesian/cartesian\";\nimport { valueFormatter } from \"../core/format\";\nimport type { Accessor, CategoryFormat, Datum, SeriesSpec } from \"../core/types\";\nimport { Kpi } from \"../needs/kpi\";\nimport { THROUGHPUT_LABELS, type ThroughputLabels } from \"../needs/labels\";\nimport { fillIn, successRate, total } from \"../needs/model\";\nimport { DEFAULT_STATUSES, type JobStatus } from \"../needs/statuses\";\nimport { useSettings } from \"../web/frame\";\n\nexport interface JobThroughputProps<T extends Datum>\n extends Omit<CartesianProps<T>, \"y\" | \"yLabel\" | \"series\" | \"format\" | \"x\" | \"xFormat\" | \"labels\"> {\n /** The field (or function) of the period. Default `\"day\"`. */\n x?: Accessor<T, unknown>;\n /** How the periods are written. Default `\"day\"` (`Oct 11`); `\"time\"` for hours. */\n period?: CategoryFormat;\n /** The statuses, in stacking order, with their field, name and tone. Default: completed, failed, running, queued. */\n statuses?: readonly JobStatus[];\n /** Hide the total and the success rate above the bars. */\n hideSummary?: boolean;\n /** The words, passed translated; English by default. */\n labels?: Partial<ThroughputLabels>;\n}\n\n/** Jobs per period, stacked by status, with the total and the success rate. */\nexport function JobThroughput<T extends Datum>({\n x = \"day\" as Accessor<T, unknown>,\n period = \"day\",\n statuses = DEFAULT_STATUSES,\n hideSummary,\n labels: given,\n description,\n data,\n ...props\n}: JobThroughputProps<T>) {\n const words = { ...THROUGHPUT_LABELS, ...given };\n const { locale } = useSettings(props as CartesianProps<T>);\n const series = useMemo<SeriesSpec<T>[]>(\n () => statuses.map((s) => ({ key: s.key as Accessor<T, number | null | undefined>, label: s.label, color: s.tone })),\n [statuses],\n );\n const sum = (outcome?: \"succeeded\" | \"failed\") =>\n statuses.filter((s) => outcome === undefined || s.outcome === outcome).reduce((n, s) => n + total(data, s.key as Accessor<T, number>), 0);\n const rate = successRate(sum(\"succeeded\"), sum(\"failed\"));\n const summary = hideSummary ? null : (\n <Kpi\n value={valueFormatter(\"integer\", locale)(sum())}\n label={fillIn(words.total, { count: data.length })}\n delta={rate == null ? null : fillIn(words.success, { rate: valueFormatter(\"percent\", locale)(rate) })}\n />\n );\n return (\n <BarChart\n {...props}\n data={data}\n x={x}\n xFormat={period}\n series={series}\n format=\"integer\"\n stacked\n description={\n description || summary ? (\n <>\n {description}\n {description && summary ? <br /> : null}\n {summary}\n </>\n ) : undefined\n }\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAeO,IAAM,mBAAyC;AAAA,EACpD,EAAE,KAAK,aAAa,OAAO,aAAa,MAAM,WAAW,SAAS,YAAY;AAAA,EAC9E,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,SAAS;AAAA,EACpE,EAAE,KAAK,WAAW,OAAO,WAAW,MAAM,OAAO;AAAA,EACjD,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU;AACpD;;;ACjBA,SAAS,eAAe;AA+CpB,SAiBM,UAjBN,KAiBM,YAjBN;AApBG,SAAS,cAA+B;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,WAAW;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA0B;AACxB,QAAM,QAAQ,EAAE,GAAG,mBAAmB,GAAG,MAAM;AAC/C,QAAM,EAAE,OAAO,IAAI,YAAY,KAA0B;AACzD,QAAM,SAAS;AAAA,IACb,MAAM,SAAS,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAA+C,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AAAA,IACnH,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,MAAM,CAAC,YACX,SAAS,OAAO,CAAC,MAAM,YAAY,UAAa,EAAE,YAAY,OAAO,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,MAAM,MAAM,EAAE,GAA0B,GAAG,CAAC;AAC1I,QAAM,OAAO,YAAY,IAAI,WAAW,GAAG,IAAI,QAAQ,CAAC;AACxD,QAAM,UAAU,cAAc,OAC5B;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,eAAe,WAAW,MAAM,EAAE,IAAI,CAAC;AAAA,MAC9C,OAAO,OAAO,MAAM,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;AAAA,MACjD,OAAO,QAAQ,OAAO,OAAO,OAAO,MAAM,SAAS,EAAE,MAAM,eAAe,WAAW,MAAM,EAAE,IAAI,EAAE,CAAC;AAAA;AAAA,EACtG;AAEF,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA,QAAO;AAAA,MACP,SAAO;AAAA,MACP,aACE,eAAe,UACb,iCACG;AAAA;AAAA,QACA,eAAe,UAAU,oBAAC,QAAG,IAAK;AAAA,QAClC;AAAA,SACH,IACE;AAAA;AAAA,EAER;AAEJ;","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/web/realtime.ts
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
|
+
function useSlidingWindow(size, initial = []) {
|
|
6
|
+
const [data, setData] = useState(() => initial.slice(-size));
|
|
7
|
+
const push = useCallback((...points) => setData((current) => [...current, ...points].slice(-size)), [size]);
|
|
8
|
+
const reset = useCallback((points = []) => setData(points.slice(-size)), [size]);
|
|
9
|
+
return { data, push, reset };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
useSlidingWindow
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-TPJDOB7R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web/realtime.ts"],"sourcesContent":["\"use client\";\n// Live data — a job queue's throughput, an auction's bids — as a sliding window: append points as they arrive, keep\n// the last `size`. Pass the window to a chart with `live`: no entrance replayed on each update, no announcement of\n// every point (the reader asks for it with the keyboard).\nimport { useCallback, useState } from \"react\";\n\nexport interface SlidingWindow<T> {\n /** The points in the window, oldest first. */\n readonly data: readonly T[];\n /** Appends one point or several; the oldest fall out past `size`. */\n readonly push: (...points: T[]) => void;\n /** Replaces the whole window (a reconnection, a new period). */\n readonly reset: (points?: readonly T[]) => void;\n}\n\nexport function useSlidingWindow<T>(size: number, initial: readonly T[] = []): SlidingWindow<T> {\n const [data, setData] = useState<readonly T[]>(() => initial.slice(-size));\n const push = useCallback((...points: T[]) => setData((current) => [...current, ...points].slice(-size)), [size]);\n const reset = useCallback((points: readonly T[] = []) => setData(points.slice(-size)), [size]);\n return { data, push, reset };\n}\n"],"mappings":";;;AAIA,SAAS,aAAa,gBAAgB;AAW/B,SAAS,iBAAoB,MAAc,UAAwB,CAAC,GAAqB;AAC9F,QAAM,CAAC,MAAM,OAAO,IAAI,SAAuB,MAAM,QAAQ,MAAM,CAAC,IAAI,CAAC;AACzE,QAAM,OAAO,YAAY,IAAI,WAAgB,QAAQ,CAAC,YAAY,CAAC,GAAG,SAAS,GAAG,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AAC/G,QAAM,QAAQ,YAAY,CAAC,SAAuB,CAAC,MAAM,QAAQ,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7F,SAAO,EAAE,MAAM,MAAM,MAAM;AAC7B;","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
EChartHost,
|
|
4
|
+
baseOption,
|
|
5
|
+
tooltipHtml
|
|
6
|
+
} from "./chunk-PWMMXRMC.js";
|
|
7
|
+
import {
|
|
8
|
+
normalizeSeries,
|
|
9
|
+
summarize,
|
|
10
|
+
tabulate
|
|
11
|
+
} from "./chunk-W5FX4TU3.js";
|
|
12
|
+
import {
|
|
13
|
+
categoryFormatter,
|
|
14
|
+
valueFormatter
|
|
15
|
+
} from "./chunk-XLLYNNC6.js";
|
|
16
|
+
import {
|
|
17
|
+
Legend,
|
|
18
|
+
useSettings
|
|
19
|
+
} from "./chunk-JTKR7ZWP.js";
|
|
20
|
+
import {
|
|
21
|
+
fill
|
|
22
|
+
} from "./chunk-3CJHBJXA.js";
|
|
23
|
+
|
|
24
|
+
// src/radar/radar-chart.tsx
|
|
25
|
+
import { useCallback, useMemo } from "react";
|
|
26
|
+
import { jsx } from "react/jsx-runtime";
|
|
27
|
+
var engine = () => import("./radar-75GRJ2IK.js");
|
|
28
|
+
function RadarChart(props) {
|
|
29
|
+
const { data, x, series, format, max, xLabel } = props;
|
|
30
|
+
const { locale, labels } = useSettings(props);
|
|
31
|
+
const specs = useMemo(() => normalizeSeries(series, void 0, void 0), [series]);
|
|
32
|
+
const table = useMemo(() => tabulate(data, x, specs), [data, x, specs]);
|
|
33
|
+
const value = useMemo(() => valueFormatter(format, locale, labels.noValue), [format, locale, labels.noValue]);
|
|
34
|
+
const axisNames = useMemo(() => table.categories.map((c) => categoryFormatter("text", locale)(c)), [table, locale]);
|
|
35
|
+
const isEmpty = !data.length || !specs.length;
|
|
36
|
+
const top = max ?? Math.max(1, ...table.series.flatMap((s) => s.values.map((v) => v ?? 0))) * 1.1;
|
|
37
|
+
const summary = isEmpty ? labels.empty : [
|
|
38
|
+
fill(labels.summaryIntro, { kind: labels.kinds.radar, count: `${specs.length} \xD7 ${data.length}` }),
|
|
39
|
+
...table.series.map((s) => {
|
|
40
|
+
const sum = summarize(s, axisNames, String);
|
|
41
|
+
return `${s.label}: ${fill(labels.summaryRange, { min: value(sum.min?.value), minAt: sum.min?.category ?? "", max: value(sum.max?.value), maxAt: sum.max?.category ?? "" })}.`;
|
|
42
|
+
})
|
|
43
|
+
].join(" ");
|
|
44
|
+
const items = table.series.map((s, k) => ({ seriesIndex: 0, dataIndex: k, text: `${s.label}: ${axisNames.map((a, i) => `${a} ${value(s.values[i])}`).join(", ")}` }));
|
|
45
|
+
const build = useCallback(
|
|
46
|
+
(theme) => ({
|
|
47
|
+
...baseOption(theme, true),
|
|
48
|
+
tooltip: {
|
|
49
|
+
...baseOption(theme, true).tooltip,
|
|
50
|
+
trigger: "item",
|
|
51
|
+
formatter: (p) => {
|
|
52
|
+
const s = table.series[p.dataIndex];
|
|
53
|
+
return tooltipHtml(s.label, axisNames.map((a, i) => ({ label: a, value: value(s.values[i]) })));
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
radar: {
|
|
57
|
+
indicator: axisNames.map((name) => ({ name, max: top })),
|
|
58
|
+
radius: "68%",
|
|
59
|
+
splitNumber: 4,
|
|
60
|
+
axisName: { color: theme.text2, fontSize: 11 },
|
|
61
|
+
splitLine: { lineStyle: { color: theme.grid } },
|
|
62
|
+
splitArea: { show: false },
|
|
63
|
+
axisLine: { lineStyle: { color: theme.grid } }
|
|
64
|
+
},
|
|
65
|
+
series: [
|
|
66
|
+
{
|
|
67
|
+
type: "radar",
|
|
68
|
+
symbol: "circle",
|
|
69
|
+
symbolSize: 6,
|
|
70
|
+
data: table.series.map((s, k) => ({
|
|
71
|
+
name: s.label,
|
|
72
|
+
value: s.values.map((v) => v ?? 0),
|
|
73
|
+
lineStyle: { width: 2, color: theme.palette[k % 8] },
|
|
74
|
+
itemStyle: { color: theme.palette[k % 8], borderColor: theme.surface, borderWidth: 2 },
|
|
75
|
+
areaStyle: { color: theme.palette[k % 8], opacity: 0.12 }
|
|
76
|
+
})),
|
|
77
|
+
emphasis: { lineStyle: { width: 3 }, areaStyle: { opacity: 0.25 } }
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}),
|
|
81
|
+
[table, axisNames, value, top]
|
|
82
|
+
);
|
|
83
|
+
return /* @__PURE__ */ jsx(
|
|
84
|
+
EChartHost,
|
|
85
|
+
{
|
|
86
|
+
kind: "radar",
|
|
87
|
+
frame: props,
|
|
88
|
+
defaultHeight: 320,
|
|
89
|
+
table: { columns: [xLabel ?? labels.category, ...table.series.map((s) => s.label)], rows: axisNames.map((a, i) => [a, ...table.series.map((s) => value(s.values[i]))]) },
|
|
90
|
+
summary,
|
|
91
|
+
isEmpty,
|
|
92
|
+
legend: /* @__PURE__ */ jsx(Legend, { items: table.series.map((s) => ({ label: s.label, color: `var(--kzc-${s.slot})` })) }),
|
|
93
|
+
engine,
|
|
94
|
+
build,
|
|
95
|
+
items
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
RadarChart
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=chunk-VKZZY2QD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/radar/radar-chart.tsx"],"sourcesContent":["\"use client\";\n// Several measures of a few entities at once — models compared on latency, cost, quality — on ECharts (loaded when\n// the chart comes near the screen). The rows are the axes, the series the entities, as in a line chart.\nimport { useCallback, useMemo } from \"react\";\n\nimport { normalizeSeries, summarize, tabulate } from \"../core/data\";\nimport { categoryFormatter, valueFormatter } from \"../core/format\";\nimport { fill } from \"../core/labels\";\nimport type { Accessor, Datum, SeriesSpec, 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\";\nimport { Legend } from \"../web/parts\";\n\nconst engine = () => import(\"../echarts/engines/radar\");\n\nexport interface RadarChartProps<T extends Datum> extends ChartFrameProps, EngineProps {\n /** One row per axis (“Latency”, “Quality”…). */\n data: readonly T[];\n /** The field (or function) naming the axis. */\n x: Accessor<T, string>;\n /** The entities compared, one value per axis each. */\n series: readonly SeriesSpec<T>[];\n /** How the values are written. */\n format?: ValueFormat;\n /** The end of every axis. Default: the largest value, rounded up. */\n max?: number;\n /** The header of the axes in the data table. */\n xLabel?: string;\n}\n\nexport function RadarChart<T extends Datum>(props: RadarChartProps<T>) {\n const { data, x, series, format, max, xLabel } = props;\n const { locale, labels } = useSettings(props);\n const specs = useMemo(() => normalizeSeries(series, undefined, undefined), [series]);\n const table = useMemo(() => tabulate(data, x, specs), [data, x, specs]);\n const value = useMemo(() => valueFormatter(format, locale, labels.noValue), [format, locale, labels.noValue]);\n const axisNames = useMemo(() => table.categories.map((c) => categoryFormatter(\"text\", locale)(c)), [table, locale]);\n const isEmpty = !data.length || !specs.length;\n const top = max ?? Math.max(1, ...table.series.flatMap((s) => s.values.map((v) => v ?? 0))) * 1.1;\n\n const summary = isEmpty\n ? labels.empty\n : [\n fill(labels.summaryIntro, { kind: labels.kinds.radar, count: `${specs.length} × ${data.length}` }),\n ...table.series.map((s) => {\n const sum = summarize(s, axisNames, String);\n return `${s.label}: ${fill(labels.summaryRange, { min: value(sum.min?.value), minAt: sum.min?.category ?? \"\", max: value(sum.max?.value), maxAt: sum.max?.category ?? \"\" })}.`;\n }),\n ].join(\" \");\n\n const items: WalkItem[] = table.series.map((s, k) => ({ seriesIndex: 0, dataIndex: k, text: `${s.label}: ${axisNames.map((a, i) => `${a} ${value(s.values[i])}`).join(\", \")}` }));\n\n const build = useCallback(\n (theme: ResolvedTheme) => ({\n ...baseOption(theme, true),\n tooltip: {\n ...(baseOption(theme, true).tooltip as object),\n trigger: \"item\",\n formatter: (p: { dataIndex: number }) => {\n const s = table.series[p.dataIndex]!;\n return tooltipHtml(s.label, axisNames.map((a, i) => ({ label: a, value: value(s.values[i]) })));\n },\n },\n radar: {\n indicator: axisNames.map((name) => ({ name, max: top })),\n radius: \"68%\",\n splitNumber: 4,\n axisName: { color: theme.text2, fontSize: 11 },\n splitLine: { lineStyle: { color: theme.grid } },\n splitArea: { show: false },\n axisLine: { lineStyle: { color: theme.grid } },\n },\n series: [\n {\n type: \"radar\",\n symbol: \"circle\",\n symbolSize: 6,\n data: table.series.map((s, k) => ({\n name: s.label,\n value: s.values.map((v) => v ?? 0),\n lineStyle: { width: 2, color: theme.palette[k % 8] },\n itemStyle: { color: theme.palette[k % 8], borderColor: theme.surface, borderWidth: 2 },\n areaStyle: { color: theme.palette[k % 8], opacity: 0.12 },\n })),\n emphasis: { lineStyle: { width: 3 }, areaStyle: { opacity: 0.25 } },\n },\n ],\n }),\n [table, axisNames, value, top],\n );\n\n return (\n <EChartHost\n kind=\"radar\"\n frame={props}\n defaultHeight={320}\n table={{ columns: [xLabel ?? labels.category, ...table.series.map((s) => s.label)], rows: axisNames.map((a, i) => [a, ...table.series.map((s) => value(s.values[i]))]) }}\n summary={summary}\n isEmpty={isEmpty}\n legend={<Legend items={table.series.map((s) => ({ label: s.label, color: `var(--kzc-${s.slot})` }))} />}\n engine={engine}\n build={build}\n items={items}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/core/data.ts
|
|
4
|
+
function read(accessor, datum, index) {
|
|
5
|
+
return typeof accessor === "function" ? accessor(datum, index) : datum[accessor];
|
|
6
|
+
}
|
|
7
|
+
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
8
|
+
function normalizeSeries(series, y, label) {
|
|
9
|
+
if (series?.length) return series;
|
|
10
|
+
if (y !== void 0) return [{ key: y, label: label ?? (typeof y === "string" ? y : "") }];
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
function tabulate(data, x, series) {
|
|
14
|
+
return {
|
|
15
|
+
categories: data.map((datum, i) => x === void 0 ? i + 1 : read(x, datum, i)),
|
|
16
|
+
series: series.map((spec, s) => ({
|
|
17
|
+
id: typeof spec.key === "string" ? spec.key : `series-${s}`,
|
|
18
|
+
label: spec.label,
|
|
19
|
+
values: data.map((datum, i) => toNumber(read(spec.key, datum, i))),
|
|
20
|
+
color: spec.color,
|
|
21
|
+
dashed: spec.dashed,
|
|
22
|
+
slot: s % 8 + 1
|
|
23
|
+
}))
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function extent(series, stacked = false) {
|
|
27
|
+
let min = Number.POSITIVE_INFINITY;
|
|
28
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
29
|
+
const count = series[0]?.values.length ?? 0;
|
|
30
|
+
if (stacked) {
|
|
31
|
+
for (let i = 0; i < count; i += 1) {
|
|
32
|
+
let pos = 0;
|
|
33
|
+
let neg = 0;
|
|
34
|
+
for (const s of series) {
|
|
35
|
+
const v = s.values[i] ?? 0;
|
|
36
|
+
if (v >= 0) pos += v;
|
|
37
|
+
else neg += v;
|
|
38
|
+
}
|
|
39
|
+
min = Math.min(min, neg);
|
|
40
|
+
max = Math.max(max, pos);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
for (const s of series) {
|
|
44
|
+
for (const v of s.values) {
|
|
45
|
+
if (v == null) continue;
|
|
46
|
+
min = Math.min(min, v);
|
|
47
|
+
max = Math.max(max, v);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (min === Number.POSITIVE_INFINITY) return [0, 0];
|
|
52
|
+
return [min, max];
|
|
53
|
+
}
|
|
54
|
+
function stack(series) {
|
|
55
|
+
const count = series[0]?.values.length ?? 0;
|
|
56
|
+
const out = series.map(() => []);
|
|
57
|
+
for (let i = 0; i < count; i += 1) {
|
|
58
|
+
let pos = 0;
|
|
59
|
+
let neg = 0;
|
|
60
|
+
series.forEach((s, k) => {
|
|
61
|
+
const v = s.values[i] ?? 0;
|
|
62
|
+
if (v >= 0) {
|
|
63
|
+
out[k].push({ base: pos, top: pos + v });
|
|
64
|
+
pos += v;
|
|
65
|
+
} else {
|
|
66
|
+
out[k].push({ base: neg, top: neg + v });
|
|
67
|
+
neg += v;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
function summarize(series, categories, writeCategory) {
|
|
74
|
+
let min = null;
|
|
75
|
+
let max = null;
|
|
76
|
+
let first = null;
|
|
77
|
+
let last = null;
|
|
78
|
+
let total = 0;
|
|
79
|
+
let count = 0;
|
|
80
|
+
series.values.forEach((v, i) => {
|
|
81
|
+
if (v == null) return;
|
|
82
|
+
count += 1;
|
|
83
|
+
total += v;
|
|
84
|
+
if (first === null) first = v;
|
|
85
|
+
last = v;
|
|
86
|
+
if (!min || v < min.value) min = { value: v, category: writeCategory(categories[i]) };
|
|
87
|
+
if (!max || v > max.value) max = { value: v, category: writeCategory(categories[i]) };
|
|
88
|
+
});
|
|
89
|
+
const change = first !== null && last !== null && first !== 0 && count > 1 ? last / first - 1 : null;
|
|
90
|
+
const trend = count < 2 || change === null ? count < 2 ? "none" : last > first ? "up" : last < first ? "down" : "flat" : Math.abs(change) < 0.01 ? "flat" : change > 0 ? "up" : "down";
|
|
91
|
+
return { label: series.label, count, min, max, first, last, total, change, trend };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
read,
|
|
96
|
+
normalizeSeries,
|
|
97
|
+
tabulate,
|
|
98
|
+
extent,
|
|
99
|
+
stack,
|
|
100
|
+
summarize
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=chunk-W5FX4TU3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/data.ts"],"sourcesContent":["// From the app's rows to what a chart draws: the categories (x) and, per series, one value per category. Missing\n// values stay `null` (a gap), never a zero.\nimport type { Accessor, Datum, SeriesColor, SeriesSpec, SeriesSummary } from \"./types\";\n\n/** Reads a field or calls the accessor. */\nexport function read<T, V>(accessor: Accessor<T, V>, datum: T, index: number): V {\n return typeof accessor === \"function\" ? accessor(datum, index) : (datum[accessor as keyof T] as V);\n}\n\nexport interface Series {\n readonly id: string;\n readonly label: string;\n readonly values: readonly (number | null)[];\n readonly color?: SeriesColor;\n readonly dashed?: boolean;\n /** Its palette slot (1–8), in the order the series were given: a series keeps its colour whatever is filtered. */\n readonly slot: number;\n}\n\nexport interface Table {\n readonly categories: readonly unknown[];\n readonly series: readonly Series[];\n}\n\nconst toNumber = (value: unknown): number | null => (typeof value === \"number\" && Number.isFinite(value) ? value : null);\n\n/** `series`, or a single series from `y` and `label`. */\nexport function normalizeSeries<T extends Datum>(series: readonly SeriesSpec<T>[] | undefined, y: Accessor<T, number | null | undefined> | undefined, label: string | undefined): readonly SeriesSpec<T>[] {\n if (series?.length) return series;\n if (y !== undefined) return [{ key: y, label: label ?? (typeof y === \"string\" ? y : \"\") }];\n return [];\n}\n\n/** The categories and the series' values, row by row. */\nexport function tabulate<T extends Datum>(data: readonly T[], x: Accessor<T, unknown> | undefined, series: readonly SeriesSpec<T>[]): Table {\n return {\n categories: data.map((datum, i) => (x === undefined ? i + 1 : read(x, datum, i))),\n series: series.map((spec, s) => ({\n id: typeof spec.key === \"string\" ? spec.key : `series-${s}`,\n label: spec.label,\n values: data.map((datum, i) => toNumber(read(spec.key, datum, i))),\n color: spec.color,\n dashed: spec.dashed,\n slot: (s % 8) + 1,\n })),\n };\n}\n\n/** The smallest and largest value of the series, `stacked` summing them per category (positives and negatives apart). */\nexport function extent(series: readonly Series[], stacked = false): [number, number] {\n let min = Number.POSITIVE_INFINITY;\n let max = Number.NEGATIVE_INFINITY;\n const count = series[0]?.values.length ?? 0;\n if (stacked) {\n for (let i = 0; i < count; i += 1) {\n let pos = 0;\n let neg = 0;\n for (const s of series) {\n const v = s.values[i] ?? 0;\n if (v >= 0) pos += v;\n else neg += v;\n }\n min = Math.min(min, neg);\n max = Math.max(max, pos);\n }\n } else {\n for (const s of series) {\n for (const v of s.values) {\n if (v == null) continue;\n min = Math.min(min, v);\n max = Math.max(max, v);\n }\n }\n }\n if (min === Number.POSITIVE_INFINITY) return [0, 0];\n return [min, max];\n}\n\n/** Per category and series, the base and top of a stacked mark (positives up, negatives down). */\nexport function stack(series: readonly Series[]): { base: number; top: number }[][] {\n const count = series[0]?.values.length ?? 0;\n const out = series.map(() => [] as { base: number; top: number }[]);\n for (let i = 0; i < count; i += 1) {\n let pos = 0;\n let neg = 0;\n series.forEach((s, k) => {\n const v = s.values[i] ?? 0;\n if (v >= 0) {\n out[k]!.push({ base: pos, top: pos + v });\n pos += v;\n } else {\n out[k]!.push({ base: neg, top: neg + v });\n neg += v;\n }\n });\n }\n return out;\n}\n\n/** What a series says: its extremes, its first and last values, its total and its trend (±1 % is flat). */\nexport function summarize(series: Series, categories: readonly unknown[], writeCategory: (c: unknown) => string): SeriesSummary {\n let min: SeriesSummary[\"min\"] = null;\n let max: SeriesSummary[\"max\"] = null;\n let first: number | null = null;\n let last: number | null = null;\n let total = 0;\n let count = 0;\n series.values.forEach((v, i) => {\n if (v == null) return;\n count += 1;\n total += v;\n if (first === null) first = v;\n last = v;\n if (!min || v < min.value) min = { value: v, category: writeCategory(categories[i]) };\n if (!max || v > max.value) max = { value: v, category: writeCategory(categories[i]) };\n });\n const change = first !== null && last !== null && first !== 0 && count > 1 ? (last as number) / first - 1 : null;\n const trend = count < 2 || change === null ? (count < 2 ? \"none\" : last! > first! ? \"up\" : last! < first! ? \"down\" : \"flat\") : Math.abs(change) < 0.01 ? \"flat\" : change > 0 ? \"up\" : \"down\";\n return { label: series.label, count, min, max, first, last, total, change, trend };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
EChartHost,
|
|
4
|
+
baseOption,
|
|
5
|
+
tooltipHtml
|
|
6
|
+
} from "./chunk-PWMMXRMC.js";
|
|
7
|
+
import {
|
|
8
|
+
describeParts
|
|
9
|
+
} from "./chunk-ANUCSRUN.js";
|
|
10
|
+
import {
|
|
11
|
+
shareFormatter,
|
|
12
|
+
valueFormatter
|
|
13
|
+
} from "./chunk-XLLYNNC6.js";
|
|
14
|
+
import {
|
|
15
|
+
useSettings
|
|
16
|
+
} from "./chunk-JTKR7ZWP.js";
|
|
17
|
+
import {
|
|
18
|
+
contrast
|
|
19
|
+
} from "./chunk-3CJHBJXA.js";
|
|
20
|
+
|
|
21
|
+
// src/treemap/treemap.tsx
|
|
22
|
+
import { useCallback, useMemo } from "react";
|
|
23
|
+
import { jsx } from "react/jsx-runtime";
|
|
24
|
+
var engine = () => import("./treemap-OMGGGB5U.js");
|
|
25
|
+
var total = (node) => node.value ?? (node.children ?? []).reduce((sum, child) => sum + total(child), 0);
|
|
26
|
+
function leaves(nodes, path = []) {
|
|
27
|
+
return nodes.flatMap((n) => n.children?.length ? leaves(n.children, [...path, n.name]) : [{ path: [...path, n.name], value: total(n) }]);
|
|
28
|
+
}
|
|
29
|
+
function Treemap(props) {
|
|
30
|
+
const { data, format, pathLabel, valueLabel, title } = props;
|
|
31
|
+
const { locale, labels } = useSettings(props);
|
|
32
|
+
const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), share: shareFormatter(locale) }), [format, locale, labels.noValue]);
|
|
33
|
+
const parts = useMemo(() => data.map((n) => ({ label: n.name, value: total(n) })), [data]);
|
|
34
|
+
const all = parts.reduce((sum, p) => sum + p.value, 0);
|
|
35
|
+
const flat = useMemo(() => leaves(data), [data]);
|
|
36
|
+
const isEmpty = all <= 0;
|
|
37
|
+
const summary = isEmpty ? labels.empty : describeParts("treemap", parts, { labels, value: fmt.value, share: fmt.share });
|
|
38
|
+
const items = useMemo(() => {
|
|
39
|
+
const count = (n) => 1 + (n.children ?? []).reduce((sum, c) => sum + count(c), 0);
|
|
40
|
+
const starts = data.map((_, i) => 1 + data.slice(0, i).reduce((sum, n) => sum + count(n), 0));
|
|
41
|
+
return data.map((n, i) => ({ seriesIndex: 0, dataIndex: starts[i], text: `${n.name}: ${fmt.value(parts[i].value)} (${fmt.share(all ? parts[i].value / all : 0)})` }));
|
|
42
|
+
}, [data, parts, all, fmt]);
|
|
43
|
+
const build = useCallback(
|
|
44
|
+
(theme) => {
|
|
45
|
+
const base = baseOption(theme, true);
|
|
46
|
+
const ink = (fillColor) => contrast(fillColor, theme.text) >= contrast(fillColor, theme.surface) ? theme.text : theme.surface;
|
|
47
|
+
const toNode = (n, color) => ({
|
|
48
|
+
name: n.name,
|
|
49
|
+
value: total(n),
|
|
50
|
+
itemStyle: { color },
|
|
51
|
+
label: { color: ink(color) },
|
|
52
|
+
upperLabel: { color: ink(color) },
|
|
53
|
+
children: n.children?.map((c) => toNode(c, color))
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
...base,
|
|
57
|
+
tooltip: {
|
|
58
|
+
...base.tooltip,
|
|
59
|
+
trigger: "item",
|
|
60
|
+
formatter: (p) => {
|
|
61
|
+
const path = p.treePathInfo.slice(1).map((s) => s.name);
|
|
62
|
+
return tooltipHtml(path.join(" \u203A "), [{ label: valueLabel ?? labels.value, value: fmt.value(p.value) }, { label: "%", value: fmt.share(all ? p.value / all : 0) }]);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
series: [
|
|
66
|
+
{
|
|
67
|
+
type: "treemap",
|
|
68
|
+
name: title,
|
|
69
|
+
left: 0,
|
|
70
|
+
right: 0,
|
|
71
|
+
top: 0,
|
|
72
|
+
bottom: 28,
|
|
73
|
+
roam: false,
|
|
74
|
+
nodeClick: "zoomToNode",
|
|
75
|
+
data: data.map((n, i) => toNode(n, theme.palette[i % 8])),
|
|
76
|
+
label: { show: true, fontFamily: theme.font, fontSize: 12, formatter: (p) => `${p.name}
|
|
77
|
+
${fmt.value(p.value)}` },
|
|
78
|
+
upperLabel: { show: true, height: 22, fontFamily: theme.font, fontSize: 11, fontWeight: 600 },
|
|
79
|
+
itemStyle: { borderColor: theme.surface, borderWidth: 2, gapWidth: 2, borderRadius: 4 },
|
|
80
|
+
levels: [{ itemStyle: { borderWidth: 0, gapWidth: 3 }, upperLabel: { show: false } }, { itemStyle: { borderColor: theme.surface, borderWidth: 2, gapWidth: 2 } }, { colorSaturation: [0.35, 0.6], itemStyle: { borderColor: theme.surface, borderWidth: 1, gapWidth: 1 } }],
|
|
81
|
+
breadcrumb: { show: true, bottom: 0, left: 0, height: 22, itemStyle: { color: theme.surface2, borderColor: theme.border, textStyle: { color: theme.text } }, emphasis: { itemStyle: { color: theme.surface3 } } }
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
[data, fmt, all, valueLabel, title, labels.value]
|
|
87
|
+
);
|
|
88
|
+
return /* @__PURE__ */ jsx(
|
|
89
|
+
EChartHost,
|
|
90
|
+
{
|
|
91
|
+
kind: "treemap",
|
|
92
|
+
frame: props,
|
|
93
|
+
defaultHeight: 320,
|
|
94
|
+
table: { columns: [pathLabel ?? labels.category, valueLabel ?? labels.value, "%"], rows: flat.map((l) => [l.path.join(" \u203A "), fmt.value(l.value), fmt.share(all ? l.value / all : 0)]) },
|
|
95
|
+
summary,
|
|
96
|
+
isEmpty,
|
|
97
|
+
engine,
|
|
98
|
+
build,
|
|
99
|
+
items
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export {
|
|
105
|
+
Treemap
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=chunk-W5ILLSPK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/treemap/treemap.tsx"],"sourcesContent":["\"use client\";\n// Part of a whole, nested — storage by project then by kind, credits by team then by model. Each top-level part keeps\n// a palette slot and its children wear it; labels inside the rectangles take the text colour that reads best on the\n// fill (WCAG contrast computed, never assumed); a click zooms into a part, the path is written above it. ECharts,\n// loaded when the chart nears the screen.\nimport { useCallback, useMemo } from \"react\";\n\nimport { describeParts } from \"../core/describe\";\nimport { shareFormatter, valueFormatter } from \"../core/format\";\nimport { contrast } from \"../core/palette\";\nimport type { 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/treemap\");\n\n/** A part: a name and either a value or children (whose values add up). */\nexport interface TreemapNode {\n readonly name: string;\n readonly value?: number;\n readonly children?: readonly TreemapNode[];\n}\n\nexport interface TreemapProps extends ChartFrameProps, EngineProps {\n /** The top-level parts. */\n data: readonly TreemapNode[];\n /** How the values are written. */\n format?: ValueFormat;\n /** The headers of the data table. */\n pathLabel?: string;\n/** The header of the values. */\n valueLabel?: string;\n}\n\nconst total = (node: TreemapNode): number => node.value ?? (node.children ?? []).reduce((sum, child) => sum + total(child), 0);\n\nfunction leaves(nodes: readonly TreemapNode[], path: string[] = []): { path: string[]; value: number }[] {\n return nodes.flatMap((n) => (n.children?.length ? leaves(n.children, [...path, n.name]) : [{ path: [...path, n.name], value: total(n) }]));\n}\n\nexport function Treemap(props: TreemapProps) {\n const { data, format, pathLabel, valueLabel, title } = 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 parts = useMemo(() => data.map((n) => ({ label: n.name, value: total(n) })), [data]);\n const all = parts.reduce((sum, p) => sum + p.value, 0);\n const flat = useMemo(() => leaves(data), [data]);\n const isEmpty = all <= 0;\n const summary = isEmpty ? labels.empty : describeParts(\"treemap\", parts, { labels, value: fmt.value, share: fmt.share });\n // The keyboard walks the top-level parts (ECharts numbers the tree depth-first: the root is 0).\n const items: WalkItem[] = useMemo(() => {\n const count = (n: TreemapNode): number => 1 + (n.children ?? []).reduce((sum, c) => sum + count(c), 0);\n // Each part's index: 1 (after the root) plus the sizes of the parts before it.\n const starts = data.map((_, i) => 1 + data.slice(0, i).reduce((sum, n) => sum + count(n), 0));\n return data.map((n, i) => ({ seriesIndex: 0, dataIndex: starts[i]!, text: `${n.name}: ${fmt.value(parts[i]!.value)} (${fmt.share(all ? parts[i]!.value / all : 0)})` }));\n }, [data, parts, all, fmt]);\n\n const build = useCallback(\n (theme: ResolvedTheme) => {\n const base = baseOption(theme, true);\n const ink = (fillColor: string) => (contrast(fillColor, theme.text) >= contrast(fillColor, theme.surface) ? theme.text : theme.surface);\n const toNode = (n: TreemapNode, color: string): Record<string, unknown> => ({\n name: n.name,\n value: total(n),\n itemStyle: { color },\n label: { color: ink(color) },\n upperLabel: { color: ink(color) },\n children: n.children?.map((c) => toNode(c, color)),\n });\n return {\n ...base,\n tooltip: {\n ...(base.tooltip as object),\n trigger: \"item\",\n formatter: (p: { treePathInfo: { name: string }[]; value: number }) => {\n const path = p.treePathInfo.slice(1).map((s) => s.name);\n return tooltipHtml(path.join(\" › \"), [{ label: valueLabel ?? labels.value, value: fmt.value(p.value) }, { label: \"%\", value: fmt.share(all ? p.value / all : 0) }]);\n },\n },\n series: [\n {\n type: \"treemap\",\n name: title,\n left: 0,\n right: 0,\n top: 0,\n bottom: 28,\n roam: false,\n nodeClick: \"zoomToNode\",\n data: data.map((n, i) => toNode(n, theme.palette[i % 8]!)),\n label: { show: true, fontFamily: theme.font, fontSize: 12, formatter: (p: { name: string; value: number }) => `${p.name}\\n${fmt.value(p.value)}` },\n upperLabel: { show: true, height: 22, fontFamily: theme.font, fontSize: 11, fontWeight: 600 },\n itemStyle: { borderColor: theme.surface, borderWidth: 2, gapWidth: 2, borderRadius: 4 },\n levels: [{ itemStyle: { borderWidth: 0, gapWidth: 3 }, upperLabel: { show: false } }, { itemStyle: { borderColor: theme.surface, borderWidth: 2, gapWidth: 2 } }, { colorSaturation: [0.35, 0.6], itemStyle: { borderColor: theme.surface, borderWidth: 1, gapWidth: 1 } }],\n breadcrumb: { show: true, bottom: 0, left: 0, height: 22, itemStyle: { color: theme.surface2, borderColor: theme.border, textStyle: { color: theme.text } }, emphasis: { itemStyle: { color: theme.surface3 } } },\n },\n ],\n };\n },\n [data, fmt, all, valueLabel, title, labels.value],\n );\n\n return (\n <EChartHost\n kind=\"treemap\"\n frame={props}\n defaultHeight={320}\n table={{ columns: [pathLabel ?? labels.category, valueLabel ?? labels.value, \"%\"], rows: flat.map((l) => [l.path.join(\" › \"), fmt.value(l.value), fmt.share(all ? l.value / all : 0)]) }}\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":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/needs/kpi.tsx
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var ARROW = { up: "M7 17 17 7M8 7h9v9", down: "M7 7l10 10M17 8v9H8", flat: "M5 12h14M13 6l6 6-6 6" };
|
|
6
|
+
function Kpi({ value, label, delta, direction, tone = "neutral" }) {
|
|
7
|
+
return /* @__PURE__ */ jsxs("span", { className: "kzc-kpi", children: [
|
|
8
|
+
/* @__PURE__ */ jsx("span", { className: "kzc-kpi-value", children: value }),
|
|
9
|
+
label ? /* @__PURE__ */ jsx("span", { className: "kzc-kpi-label", children: label }) : null,
|
|
10
|
+
delta ? /* @__PURE__ */ jsxs("span", { className: "kzc-kpi-delta", "data-tone": tone, children: [
|
|
11
|
+
direction ? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: ARROW[direction] }) }) : null,
|
|
12
|
+
delta
|
|
13
|
+
] }) : null
|
|
14
|
+
] });
|
|
15
|
+
}
|
|
16
|
+
function toneOf(direction, good) {
|
|
17
|
+
if (!direction || direction === "flat") return "neutral";
|
|
18
|
+
return direction === good ? "success" : "danger";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
Kpi,
|
|
23
|
+
toneOf
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=chunk-WBHFVBSK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/needs/kpi.tsx"],"sourcesContent":["// The key figure of a ready-made chart, written under its title: the value, what it is, and the change in words with\n// a decorative arrow in the direction's tone (the words carry the meaning: colour is never alone). Spans only — it\n// sits in the chart's description paragraph.\nimport type { ReactNode } from \"react\";\n\nimport type { Tone } from \"../core/types\";\n\nconst ARROW = { up: \"M7 17 17 7M8 7h9v9\", down: \"M7 7l10 10M17 8v9H8\", flat: \"M5 12h14M13 6l6 6-6 6\" } as const;\n\nexport interface KpiProps {\n readonly value: ReactNode;\n readonly label?: ReactNode;\n /** The change, in words (`+12 % vs September`). */\n readonly delta?: ReactNode;\n readonly direction?: \"up\" | \"down\" | \"flat\" | null;\n /** The arrow's tone: a rise of earnings is good (`success`), a rise of latency is not (`danger`). */\n readonly tone?: Tone;\n}\n\nexport function Kpi({ value, label, delta, direction, tone = \"neutral\" }: KpiProps) {\n return (\n <span className=\"kzc-kpi\">\n <span className=\"kzc-kpi-value\">{value}</span>\n {label ? <span className=\"kzc-kpi-label\">{label}</span> : null}\n {delta ? (\n <span className=\"kzc-kpi-delta\" data-tone={tone}>\n {direction ? (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d={ARROW[direction]} />\n </svg>\n ) : null}\n {delta}\n </span>\n ) : null}\n </span>\n );\n}\n\n/** The tone of a change: `good` says which direction is good news (earnings up, latency down). */\nexport function toneOf(direction: \"up\" | \"down\" | \"flat\" | null, good: \"up\" | \"down\"): Tone {\n if (!direction || direction === \"flat\") return \"neutral\";\n return direction === good ? \"success\" : \"danger\";\n}\n"],"mappings":";;;AAsBM,cAGE,YAHF;AAfN,IAAM,QAAQ,EAAE,IAAI,sBAAsB,MAAM,uBAAuB,MAAM,wBAAwB;AAY9F,SAAS,IAAI,EAAE,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU,GAAa;AAClF,SACE,qBAAC,UAAK,WAAU,WACd;AAAA,wBAAC,UAAK,WAAU,iBAAiB,iBAAM;AAAA,IACtC,QAAQ,oBAAC,UAAK,WAAU,iBAAiB,iBAAM,IAAU;AAAA,IACzD,QACC,qBAAC,UAAK,WAAU,iBAAgB,aAAW,MACxC;AAAA,kBACC,oBAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAG,MAAM,SAAS,GAAG,GAC7B,IACE;AAAA,MACH;AAAA,OACH,IACE;AAAA,KACN;AAEJ;AAGO,SAAS,OAAO,WAA0C,MAA2B;AAC1F,MAAI,CAAC,aAAa,cAAc,OAAQ,QAAO;AAC/C,SAAO,cAAc,OAAO,YAAY;AAC1C;","names":[]}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/needs/labels.ts
|
|
4
|
+
var EARNINGS_LABELS = {
|
|
5
|
+
total: "earned over {count} periods",
|
|
6
|
+
change: "{change} vs the previous period",
|
|
7
|
+
gross: "Gross",
|
|
8
|
+
net: "Net"
|
|
9
|
+
};
|
|
10
|
+
var THROUGHPUT_LABELS = { total: "jobs over {count} periods", success: "{rate} succeeded" };
|
|
11
|
+
var LATENCY_LABELS = {
|
|
12
|
+
p50: "Median (p50)",
|
|
13
|
+
p95: "p95",
|
|
14
|
+
slowest: "p95 of {name}, the slowest",
|
|
15
|
+
over: "{count} over the objective",
|
|
16
|
+
within: "all within the objective"
|
|
17
|
+
};
|
|
18
|
+
var CREDIT_LABELS = {
|
|
19
|
+
remaining: "left of {limit}",
|
|
20
|
+
used: "{used} used ({percent})",
|
|
21
|
+
runsOut: "At this pace, runs out on {date}",
|
|
22
|
+
steady: "No use lately",
|
|
23
|
+
renews: "Renews on {date}",
|
|
24
|
+
daily: "Use per day"
|
|
25
|
+
};
|
|
26
|
+
var GOAL_LABELS = { raised: "raised of {goal}", reached: "Goal reached", supporters: "{count} supporters", left: "{time} left" };
|
|
27
|
+
var TICKER_LABELS = {
|
|
28
|
+
current: "current bid",
|
|
29
|
+
change: "{change} since the opening \xB7 {count} bids",
|
|
30
|
+
opening: "opening price, no bid yet",
|
|
31
|
+
reserve: "Reserve price",
|
|
32
|
+
price: "Price"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/needs/model.ts
|
|
36
|
+
import { currencyDigits, getNumberFormat } from "@krizaka/intl";
|
|
37
|
+
function numberOf(row, accessor, index) {
|
|
38
|
+
const value = typeof accessor === "function" ? accessor(row, index) : row[accessor];
|
|
39
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
40
|
+
}
|
|
41
|
+
function total(rows, accessor) {
|
|
42
|
+
return rows.reduce((sum, row, i) => sum + (numberOf(row, accessor, i) ?? 0), 0);
|
|
43
|
+
}
|
|
44
|
+
function lastChange(values) {
|
|
45
|
+
if (values.length < 2) return null;
|
|
46
|
+
const last = values[values.length - 1];
|
|
47
|
+
const previous = values[values.length - 2];
|
|
48
|
+
if (last == null || previous == null || previous === 0) return null;
|
|
49
|
+
return last / previous - 1;
|
|
50
|
+
}
|
|
51
|
+
function direction(change) {
|
|
52
|
+
if (change == null) return null;
|
|
53
|
+
return Math.abs(change) < 5e-3 ? "flat" : change > 0 ? "up" : "down";
|
|
54
|
+
}
|
|
55
|
+
function successRate(succeeded, failed) {
|
|
56
|
+
const finished = succeeded + failed;
|
|
57
|
+
return finished > 0 ? succeeded / finished : null;
|
|
58
|
+
}
|
|
59
|
+
function daysLeft(remaining, daily, days = 7) {
|
|
60
|
+
const recent = daily.slice(-days).filter((v) => v != null && v >= 0);
|
|
61
|
+
if (recent.length === 0) return null;
|
|
62
|
+
const pace = recent.reduce((a, b) => a + b, 0) / recent.length;
|
|
63
|
+
if (pace <= 0) return null;
|
|
64
|
+
return Math.max(0, Math.floor(remaining / pace));
|
|
65
|
+
}
|
|
66
|
+
var addDays = (from, days) => new Date(from.getTime() + days * 864e5);
|
|
67
|
+
function quotaLevel(ratio, warning = 0.8, danger = 0.95) {
|
|
68
|
+
return ratio >= danger ? "danger" : ratio >= warning ? "warning" : "ok";
|
|
69
|
+
}
|
|
70
|
+
function fillIn(template, values) {
|
|
71
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => key in values ? String(values[key]) : match);
|
|
72
|
+
}
|
|
73
|
+
function signedPercent(change, locale) {
|
|
74
|
+
return getNumberFormat(locale, { style: "percent", signDisplay: "exceptZero", maximumFractionDigits: Math.abs(change) < 0.1 ? 1 : 0 }).format(change);
|
|
75
|
+
}
|
|
76
|
+
function formatDuration(ms, locale) {
|
|
77
|
+
const unit = (value, name, digits) => getNumberFormat(locale, { style: "unit", unit: name, unitDisplay: "short", maximumFractionDigits: digits }).format(value);
|
|
78
|
+
const abs = Math.abs(ms);
|
|
79
|
+
if (abs < 1e3) return unit(Math.round(ms), "millisecond", 0);
|
|
80
|
+
if (abs < 6e4) return unit(ms / 1e3, "second", abs < 1e4 ? 1 : 0);
|
|
81
|
+
if (abs < 36e5) return unit(ms / 6e4, "minute", 1);
|
|
82
|
+
return unit(ms / 36e5, "hour", 1);
|
|
83
|
+
}
|
|
84
|
+
function roundMoney(currency) {
|
|
85
|
+
const digits = currencyDigits(currency);
|
|
86
|
+
return (value, locale) => {
|
|
87
|
+
const minor = Math.round(value);
|
|
88
|
+
const whole = minor % 10 ** digits === 0;
|
|
89
|
+
return getNumberFormat(locale, { style: "currency", currency, minimumFractionDigits: whole ? 0 : digits, maximumFractionDigits: whole ? 0 : digits }).format(minor / 10 ** digits);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
EARNINGS_LABELS,
|
|
95
|
+
THROUGHPUT_LABELS,
|
|
96
|
+
LATENCY_LABELS,
|
|
97
|
+
CREDIT_LABELS,
|
|
98
|
+
GOAL_LABELS,
|
|
99
|
+
TICKER_LABELS,
|
|
100
|
+
numberOf,
|
|
101
|
+
total,
|
|
102
|
+
lastChange,
|
|
103
|
+
direction,
|
|
104
|
+
successRate,
|
|
105
|
+
daysLeft,
|
|
106
|
+
addDays,
|
|
107
|
+
quotaLevel,
|
|
108
|
+
fillIn,
|
|
109
|
+
signedPercent,
|
|
110
|
+
formatDuration,
|
|
111
|
+
roundMoney
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=chunk-WNUFGMS7.js.map
|