@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/needs/labels.ts","../src/needs/model.ts"],"sourcesContent":["// The words of the ready-made charts: English by default, an app passes its own (translated) through `labels`.\n// Placeholders are written `{name}`.\n\nexport interface EarningsLabels {\n /** Under the total: `earned over {count} months`. `{count}` is the number of periods. */\n total: string;\n /** The change of the last period: `{change} vs the previous month`. */\n change: string;\n /** The gross series' name. */\n gross: string;\n /** The net series' name. */\n net: string;\n}\n\nexport const EARNINGS_LABELS: EarningsLabels = {\n total: \"earned over {count} periods\",\n change: \"{change} vs the previous period\",\n gross: \"Gross\",\n net: \"Net\",\n};\n\nexport interface ThroughputLabels {\n /** Under the total: `jobs over {count} days`. */\n total: string;\n /** The success rate of the finished jobs: `{rate} succeeded`. */\n success: string;\n}\n\nexport const THROUGHPUT_LABELS: ThroughputLabels = { total: \"jobs over {count} periods\", success: \"{rate} succeeded\" };\n\nexport interface LatencyLabels {\n /** The median series. */\n p50: string;\n /** The 95th percentile series. */\n p95: string;\n /** The slowest p95: `slowest: {name}`. */\n slowest: string;\n /** How many go past the objective: `{count} over the objective`. */\n over: string;\n /** All within the objective. */\n within: string;\n}\n\nexport const LATENCY_LABELS: LatencyLabels = {\n p50: \"Median (p50)\",\n p95: \"p95\",\n slowest: \"p95 of {name}, the slowest\",\n over: \"{count} over the objective\",\n within: \"all within the objective\",\n};\n\nexport interface CreditLabels {\n /** Under the remaining amount: `left of {limit}`. */\n remaining: string;\n /** The used part: `{used} used ({percent})`. */\n used: string;\n /** The projection: `at this pace, runs out on {date}`. */\n runsOut: string;\n /** No use lately: it does not run out. */\n steady: string;\n /** The renewal: `renews on {date}`. */\n renews: string;\n /** The daily use sparkline's title. */\n daily: string;\n}\n\nexport const CREDIT_LABELS: CreditLabels = {\n remaining: \"left of {limit}\",\n used: \"{used} used ({percent})\",\n runsOut: \"At this pace, runs out on {date}\",\n steady: \"No use lately\",\n renews: \"Renews on {date}\",\n daily: \"Use per day\",\n};\n\nexport interface GoalLabels {\n /** Under the amount: `raised of {goal}`. */\n raised: string;\n /** Reached: `goal reached`. */\n reached: string;\n /** The supporters: `{count} supporters`. */\n supporters: string;\n /** The time left: `{time} left`. */\n left: string;\n}\n\nexport const GOAL_LABELS: GoalLabels = { raised: \"raised of {goal}\", reached: \"Goal reached\", supporters: \"{count} supporters\", left: \"{time} left\" };\n\nexport interface TickerLabels {\n /** Under the price: `current bid`. */\n current: string;\n /** The change since the opening: `{change} since the opening ({count} bids)`. */\n change: string;\n /** No bid yet: `opening price`. */\n opening: string;\n /** The reserve line. */\n reserve: string;\n /** The series' name. */\n price: string;\n}\n\nexport const TICKER_LABELS: TickerLabels = {\n current: \"current bid\",\n change: \"{change} since the opening · {count} bids\",\n opening: \"opening price, no bid yet\",\n reserve: \"Reserve price\",\n price: \"Price\",\n};\n","// The arithmetic of the ready-made charts (EarningsChart, JobThroughput, LatencyChart, CreditUsage, GoalProgress,\n// PriceTicker), shared by the web and React Native: totals, the change between the last two periods, a success rate,\n// the day a balance runs out at the current pace. Pure functions: no React, no DOM.\nimport { currencyDigits, getNumberFormat } from \"@krizaka/intl\";\n\nimport type { Accessor, Datum, Locale } from \"../core/types\";\n\n/** Reads a field (or calls a function) of a row; `null` for anything that is not a finite number. */\nexport function numberOf<T extends Datum>(row: T, accessor: Accessor<T, number | null | undefined>, index: number): number | null {\n const value = typeof accessor === \"function\" ? accessor(row, index) : (row as Record<string, unknown>)[accessor];\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\n/** The sum of a column, `null` values left out. */\nexport function total<T extends Datum>(rows: readonly T[], accessor: Accessor<T, number | null | undefined>): number {\n return rows.reduce((sum, row, i) => sum + (numberOf(row, accessor, i) ?? 0), 0);\n}\n\n/**\n * The change of the last period against the one before, as a ratio (`0.12` = +12 %): `null` when it cannot be said\n * (fewer than two periods, a previous period at zero or missing).\n */\nexport function lastChange(values: readonly (number | null)[]): number | null {\n if (values.length < 2) return null;\n const last = values[values.length - 1];\n const previous = values[values.length - 2];\n if (last == null || previous == null || previous === 0) return null;\n return last / previous - 1;\n}\n\n/** `up`, `down` or `flat` (within ±0.5 %): the direction of a change, `null` when there is none. */\nexport function direction(change: number | null): \"up\" | \"down\" | \"flat\" | null {\n if (change == null) return null;\n return Math.abs(change) < 0.005 ? \"flat\" : change > 0 ? \"up\" : \"down\";\n}\n\n/** Succeeded out of finished (succeeded + failed); `null` when nothing finished. */\nexport function successRate(succeeded: number, failed: number): number | null {\n const finished = succeeded + failed;\n return finished > 0 ? succeeded / finished : null;\n}\n\n/**\n * When a balance runs out at the pace of the last `days` days of use (oldest first): the number of whole days left,\n * or `null` when nothing is being used (it never runs out) or there is no history.\n */\nexport function daysLeft(remaining: number, daily: readonly (number | null)[], days = 7): number | null {\n const recent = daily.slice(-days).filter((v): v is number => v != null && v >= 0);\n if (recent.length === 0) return null;\n const pace = recent.reduce((a, b) => a + b, 0) / recent.length;\n if (pace <= 0) return null;\n return Math.max(0, Math.floor(remaining / pace));\n}\n\n/** `from` + `days` days, at the same time of day. */\nexport const addDays = (from: Date, days: number) => new Date(from.getTime() + days * 86_400_000);\n\n/** The level of a quota: `ok` below `warning` (default 0.8), `warning` below `danger` (0.95), then `danger`. */\nexport function quotaLevel(ratio: number, warning = 0.8, danger = 0.95): \"ok\" | \"warning\" | \"danger\" {\n return ratio >= danger ? \"danger\" : ratio >= warning ? \"warning\" : \"ok\";\n}\n\n/** Replaces `{name}` placeholders. */\nexport function fillIn(template: string, values: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => (key in values ? String(values[key]) : match));\n}\n\n/** A signed ratio as a percentage for a change (`+12 %`, `−3 %`), in the locale's way. */\nexport function signedPercent(change: number, locale: Locale): string {\n return getNumberFormat(locale, { style: \"percent\", signDisplay: \"exceptZero\", maximumFractionDigits: Math.abs(change) < 0.1 ? 1 : 0 }).format(change);\n}\n\n/** Milliseconds as a duration: `840 ms`, `1.2 s`, `2.5 min` — the unit follows the size, through Intl. */\nexport function formatDuration(ms: number, locale: Locale): string {\n const unit = (value: number, name: string, digits: number) =>\n getNumberFormat(locale, { style: \"unit\", unit: name, unitDisplay: \"short\", maximumFractionDigits: digits }).format(value);\n const abs = Math.abs(ms);\n if (abs < 1000) return unit(Math.round(ms), \"millisecond\", 0);\n if (abs < 60_000) return unit(ms / 1000, \"second\", abs < 10_000 ? 1 : 0);\n if (abs < 3_600_000) return unit(ms / 60_000, \"minute\", 1);\n return unit(ms / 3_600_000, \"hour\", 1);\n}\n\n/** Money in minor units, without the cents of a round amount (`$500`, `$262.50`): a goal reads as people say it. */\nexport function roundMoney(currency: string): (value: number, locale: Locale) => string {\n const digits = currencyDigits(currency);\n return (value, locale) => {\n const minor = Math.round(value);\n const whole = minor % 10 ** digits === 0;\n return getNumberFormat(locale, { style: \"currency\", currency, minimumFractionDigits: whole ? 0 : digits, maximumFractionDigits: whole ? 0 : digits }).format(minor / 10 ** digits);\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Cartesian
|
|
4
|
+
} from "./chunk-CVWSMUUB.js";
|
|
5
|
+
|
|
6
|
+
// src/bar/bar-chart.tsx
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
function BarChart({ stacked, horizontal, valueLabels = true, ...props }) {
|
|
9
|
+
return /* @__PURE__ */ jsx(Cartesian, { props, options: { kind: "bar", mode: "bar", stacked, horizontal, valueLabels } });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
BarChart
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-WVTIKOII.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bar/bar-chart.tsx"],"sourcesContent":["\"use client\";\nimport { Cartesian, type CartesianProps } from \"../cartesian/cartesian\";\nimport type { Datum } from \"../core/types\";\n\nexport interface BarChartProps<T extends Datum> extends CartesianProps<T> {\n /** Stack the series in one bar per category (a total and its parts); default: grouped side by side. */\n stacked?: boolean;\n /** Bars grow to the right, the categories down the side: long labels, rankings. */\n horizontal?: boolean;\n /** Write each value at the tip of its bar (one series, up to 16 bars). Default true. */\n valueLabels?: boolean;\n}\n\n/** Compare amounts across categories: grouped, stacked or horizontal bars, each value at its tip. */\nexport function BarChart<T extends Datum>({ stacked, horizontal, valueLabels = true, ...props }: BarChartProps<T>) {\n return <Cartesian props={props} options={{ kind: \"bar\", mode: \"bar\", stacked, horizontal, valueLabels }} />;\n}\n"],"mappings":";;;;;;AAeS;AADF,SAAS,SAA0B,EAAE,SAAS,YAAY,cAAc,MAAM,GAAG,MAAM,GAAqB;AACjH,SAAO,oBAAC,aAAU,OAAc,SAAS,EAAE,MAAM,OAAO,MAAM,OAAO,SAAS,YAAY,YAAY,GAAG;AAC3G;","names":[]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
EChartHost,
|
|
4
|
+
baseOption,
|
|
5
|
+
categoryAxis,
|
|
6
|
+
tooltipHtml
|
|
7
|
+
} from "./chunk-PWMMXRMC.js";
|
|
8
|
+
import {
|
|
9
|
+
read
|
|
10
|
+
} from "./chunk-W5FX4TU3.js";
|
|
11
|
+
import {
|
|
12
|
+
asDate,
|
|
13
|
+
categoryFormatter,
|
|
14
|
+
valueFormatter
|
|
15
|
+
} from "./chunk-XLLYNNC6.js";
|
|
16
|
+
import {
|
|
17
|
+
RampLegend,
|
|
18
|
+
useSettings
|
|
19
|
+
} from "./chunk-JTKR7ZWP.js";
|
|
20
|
+
import {
|
|
21
|
+
capitalize,
|
|
22
|
+
fill
|
|
23
|
+
} from "./chunk-3CJHBJXA.js";
|
|
24
|
+
|
|
25
|
+
// src/heatmap/heatmap.tsx
|
|
26
|
+
import { useCallback, useMemo } from "react";
|
|
27
|
+
import { jsx } from "react/jsx-runtime";
|
|
28
|
+
var engine = () => import("./heatmap-JWQOKUGM.js");
|
|
29
|
+
var STEPS = 5;
|
|
30
|
+
var pieces = (theme, min, max) => theme.ramp.map((color, i) => ({ gte: min + (max - min) * i / STEPS, ...i < STEPS - 1 ? { lt: min + (max - min) * (i + 1) / STEPS } : {}, color }));
|
|
31
|
+
function Heatmap(props) {
|
|
32
|
+
const { data, x, y, value, xCategories, yCategories, format, xFormat, yFormat, xLabel, yLabel } = props;
|
|
33
|
+
const { locale, labels } = useSettings(props);
|
|
34
|
+
const fmt = useMemo(
|
|
35
|
+
() => ({ value: valueFormatter(format, locale, labels.noValue), axis: valueFormatter(format, locale, labels.noValue, true), x: categoryFormatter(xFormat ?? "text", locale), y: categoryFormatter(yFormat ?? "text", locale) }),
|
|
36
|
+
[format, xFormat, yFormat, locale, labels.noValue]
|
|
37
|
+
);
|
|
38
|
+
const model = useMemo(() => {
|
|
39
|
+
const xs = xCategories ? [...xCategories] : [...new Set(data.map((d, i) => read(x, d, i)))];
|
|
40
|
+
const ys = yCategories ? [...yCategories] : [...new Set(data.map((d, i) => read(y, d, i)))];
|
|
41
|
+
const cells = data.map((d, i) => ({ xi: xs.findIndex((c) => String(c) === String(read(x, d, i))), yi: ys.findIndex((c) => String(c) === String(read(y, d, i))), v: Number(read(value, d, i)) })).filter((c) => c.xi >= 0 && c.yi >= 0 && Number.isFinite(c.v));
|
|
42
|
+
const values = cells.map((c) => c.v);
|
|
43
|
+
return { xs: xs.map(fmt.x), ys: ys.map(fmt.y), cells, min: Math.min(...values, 0), max: Math.max(...values, 0) };
|
|
44
|
+
}, [data, x, y, value, xCategories, yCategories, fmt]);
|
|
45
|
+
const isEmpty = model.cells.length === 0;
|
|
46
|
+
const peak = model.cells.reduce((best, c) => !best || c.v > best.v ? c : best, null);
|
|
47
|
+
const summary = isEmpty ? labels.empty : `${fill(labels.summaryIntro, { kind: labels.kinds.heatmap, count: `${model.xs.length} \xD7 ${model.ys.length}` })} ${capitalize(fill(labels.summaryPeak, { value: fmt.value(peak.v), at: `${model.ys[peak.yi]}, ${model.xs[peak.xi]}` }))}, ${fill(labels.summaryActive, { count: model.cells.filter((c) => c.v !== 0).length })}.`;
|
|
48
|
+
const items = model.cells.map((c, i) => ({ seriesIndex: 0, dataIndex: i, text: `${model.ys[c.yi]}, ${model.xs[c.xi]}: ${fmt.value(c.v)}` }));
|
|
49
|
+
const build = useCallback(
|
|
50
|
+
(theme, size) => {
|
|
51
|
+
const base = baseOption(theme, true);
|
|
52
|
+
return {
|
|
53
|
+
...base,
|
|
54
|
+
tooltip: {
|
|
55
|
+
...base.tooltip,
|
|
56
|
+
trigger: "item",
|
|
57
|
+
formatter: (p) => {
|
|
58
|
+
const c = model.cells[p.dataIndex];
|
|
59
|
+
return tooltipHtml(`${model.ys[c.yi]} \xB7 ${model.xs[c.xi]}`, [{ label: labels.value, value: fmt.value(c.v) }]);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
grid: { left: 8, right: 8, top: 8, bottom: 8, containLabel: true },
|
|
63
|
+
xAxis: { ...categoryAxis(theme, model.xs), axisLine: { show: false }, axisLabel: { color: theme.text2, interval: size.width < 480 ? "auto" : 0 } },
|
|
64
|
+
yAxis: { ...categoryAxis(theme, model.ys), axisLine: { show: false }, inverse: true },
|
|
65
|
+
visualMap: { show: false, type: "piecewise", pieces: pieces(theme, model.min, model.max), dimension: 2 },
|
|
66
|
+
series: [
|
|
67
|
+
{
|
|
68
|
+
type: "heatmap",
|
|
69
|
+
data: model.cells.map((c) => [c.xi, c.yi, c.v]),
|
|
70
|
+
itemStyle: { borderColor: theme.surface, borderWidth: 2, borderRadius: 3 },
|
|
71
|
+
emphasis: { itemStyle: { borderColor: theme.text, borderWidth: 2 } }
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
[model, fmt, labels.value]
|
|
77
|
+
);
|
|
78
|
+
return /* @__PURE__ */ jsx(
|
|
79
|
+
EChartHost,
|
|
80
|
+
{
|
|
81
|
+
kind: "heatmap",
|
|
82
|
+
frame: props,
|
|
83
|
+
defaultHeight: 260,
|
|
84
|
+
table: { columns: [yLabel && xLabel ? `${yLabel} / ${xLabel}` : yLabel ?? labels.category, ...model.xs], rows: model.ys.map((row, yi) => [row, ...model.xs.map((_, xi) => fmt.value(model.cells.find((c) => c.xi === xi && c.yi === yi)?.v))]) },
|
|
85
|
+
summary,
|
|
86
|
+
isEmpty,
|
|
87
|
+
legend: isEmpty ? null : /* @__PURE__ */ jsx(RampLegend, { min: model.min, max: model.max, steps: STEPS, write: fmt.axis }),
|
|
88
|
+
engine,
|
|
89
|
+
build,
|
|
90
|
+
items
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
var iso = (date) => date.toISOString().slice(0, 10);
|
|
95
|
+
function CalendarHeatmap(props) {
|
|
96
|
+
const { data, date, value, range, format, valueLabel } = props;
|
|
97
|
+
const { locale, labels } = useSettings(props);
|
|
98
|
+
const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), axis: valueFormatter(format, locale, labels.noValue, true), day: categoryFormatter("date", locale) }), [format, locale, labels.noValue]);
|
|
99
|
+
const model = useMemo(() => {
|
|
100
|
+
const days = data.map((d, i) => ({ day: asDate(read(date, d, i)), v: Number(read(value, d, i)) })).filter((d) => d.day !== null && Number.isFinite(d.v)).map((d) => ({ day: iso(d.day), v: d.v })).sort((a, b) => a.day.localeCompare(b.day));
|
|
101
|
+
const last = days[days.length - 1]?.day ?? iso(/* @__PURE__ */ new Date(0));
|
|
102
|
+
const first = /* @__PURE__ */ new Date(`${last}T00:00:00Z`);
|
|
103
|
+
first.setUTCDate(first.getUTCDate() - 364);
|
|
104
|
+
const span = range ?? [iso(first), last];
|
|
105
|
+
const values = days.map((d) => d.v);
|
|
106
|
+
return { days, span, min: Math.min(...values, 0), max: Math.max(...values, 0) };
|
|
107
|
+
}, [data, date, value, range]);
|
|
108
|
+
const isEmpty = model.days.length === 0;
|
|
109
|
+
const peak = model.days.reduce((best, d) => !best || d.v > best.v ? d : best, null);
|
|
110
|
+
const total = model.days.reduce((sum, d) => sum + d.v, 0);
|
|
111
|
+
const summary = isEmpty ? labels.empty : `${fill(labels.summaryIntro, { kind: labels.kinds.calendar, count: `${fmt.day(model.span[0])} \u2013 ${fmt.day(model.span[1])}` })} ${capitalize(fill(labels.summaryTotal, { total: fmt.value(total) }))}, ${fill(labels.summaryPeak, { value: fmt.value(peak.v), at: fmt.day(peak.day) })}, ${fill(labels.summaryActive, { count: model.days.filter((d) => d.v !== 0).length })}.`;
|
|
112
|
+
const items = model.days.map((d, i) => ({ seriesIndex: 0, dataIndex: i, text: `${fmt.day(d.day)}: ${fmt.value(d.v)}` }));
|
|
113
|
+
const build = useCallback(
|
|
114
|
+
(theme, size) => {
|
|
115
|
+
const base = baseOption(theme, true);
|
|
116
|
+
const cell = Math.max(6, Math.min(18, Math.floor((size.width - 48) / 54)));
|
|
117
|
+
const monthNames = Array.from({ length: 12 }, (_, m) => new Intl.DateTimeFormat(locale, { month: "short", timeZone: "UTC" }).format(new Date(Date.UTC(2026, m, 1))));
|
|
118
|
+
const dayNames = Array.from({ length: 7 }, (_, d) => new Intl.DateTimeFormat(locale, { weekday: "narrow", timeZone: "UTC" }).format(new Date(Date.UTC(2026, 2, 1 + d))));
|
|
119
|
+
return {
|
|
120
|
+
...base,
|
|
121
|
+
tooltip: {
|
|
122
|
+
...base.tooltip,
|
|
123
|
+
trigger: "item",
|
|
124
|
+
formatter: (p) => tooltipHtml(fmt.day(p.data[0]), [{ label: valueLabel ?? labels.value, value: fmt.value(p.data[1]) }])
|
|
125
|
+
},
|
|
126
|
+
visualMap: { show: false, type: "piecewise", pieces: pieces(theme, model.min, model.max) },
|
|
127
|
+
calendar: {
|
|
128
|
+
range: [...model.span],
|
|
129
|
+
cellSize: [cell, cell],
|
|
130
|
+
top: 24,
|
|
131
|
+
left: 32,
|
|
132
|
+
right: 8,
|
|
133
|
+
orient: "horizontal",
|
|
134
|
+
splitLine: { show: false },
|
|
135
|
+
itemStyle: { color: theme.surface2, borderColor: theme.surface, borderWidth: 2 },
|
|
136
|
+
yearLabel: { show: false },
|
|
137
|
+
monthLabel: { color: theme.text2, nameMap: monthNames, fontSize: 11 },
|
|
138
|
+
dayLabel: { color: theme.text3, nameMap: dayNames, firstDay: 1, fontSize: 10 }
|
|
139
|
+
},
|
|
140
|
+
series: [{ type: "heatmap", coordinateSystem: "calendar", data: model.days.map((d) => [d.day, d.v]), itemStyle: { borderColor: theme.surface, borderWidth: 2, borderRadius: 2 } }]
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
[model, fmt, valueLabel, locale, labels.value]
|
|
144
|
+
);
|
|
145
|
+
return /* @__PURE__ */ jsx(
|
|
146
|
+
EChartHost,
|
|
147
|
+
{
|
|
148
|
+
kind: "calendar",
|
|
149
|
+
frame: props,
|
|
150
|
+
defaultHeight: 170,
|
|
151
|
+
table: { columns: [labels.category, valueLabel ?? labels.value], rows: model.days.map((d) => [fmt.day(d.day), fmt.value(d.v)]) },
|
|
152
|
+
summary,
|
|
153
|
+
isEmpty,
|
|
154
|
+
legend: isEmpty ? null : /* @__PURE__ */ jsx(RampLegend, { min: model.min, max: model.max, steps: STEPS, write: fmt.axis }),
|
|
155
|
+
engine,
|
|
156
|
+
build,
|
|
157
|
+
items
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export {
|
|
163
|
+
Heatmap,
|
|
164
|
+
CalendarHeatmap
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=chunk-XDDALY4C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/heatmap/heatmap.tsx"],"sourcesContent":["\"use client\";\n// Magnitude across two dimensions — activity by weekday and hour — and its calendar form, one cell a day over a year.\n// One sequential hue (the brand's) in even steps from near the surface; the legend writes each step's range; the\n// keyboard walks the cells that have a value. ECharts, loaded when the chart nears the screen.\nimport { useCallback, useMemo } from \"react\";\n\nimport { read } from \"../core/data\";\nimport { asDate, categoryFormatter, valueFormatter } from \"../core/format\";\nimport { capitalize, fill } from \"../core/labels\";\nimport type { Accessor, CategoryFormat, Datum, ValueFormat } from \"../core/types\";\nimport { EChartHost, type EngineProps, type WalkItem } from \"../echarts/host\";\nimport { baseOption, categoryAxis, type ResolvedTheme, tooltipHtml } from \"../echarts/theme\";\nimport type { ChartFrameProps } from \"../web/frame\";\nimport { useSettings } from \"../web/frame\";\nimport { RampLegend } from \"../web/parts\";\n\nconst engine = () => import(\"../echarts/engines/heatmap\");\nconst STEPS = 5;\n\nconst pieces = (theme: ResolvedTheme, min: number, max: number) =>\n theme.ramp.map((color, i) => ({ gte: min + ((max - min) * i) / STEPS, ...(i < STEPS - 1 ? { lt: min + ((max - min) * (i + 1)) / STEPS } : {}), color }));\n\nexport interface HeatmapProps<T extends Datum> extends ChartFrameProps, EngineProps {\n /** One row per cell. */\n data: readonly T[];\n /** The field of the column (an hour, a day) and of the row (a weekday, a team). */\n x: Accessor<T, unknown>;\n/** The field of the row (a weekday, a team). */\n y: Accessor<T, unknown>;\n /** The field of the cell's value. */\n value: Accessor<T, number>;\n /** The order of the columns and the rows. Default: as they first appear. */\n xCategories?: readonly unknown[];\n/** The order of the rows. Default: as they first appear. */\n yCategories?: readonly unknown[];\n /** How the values, the columns and the rows are written. */\n format?: ValueFormat;\n/** How the columns are written. */\n xFormat?: CategoryFormat;\n/** How the rows are written. */\n yFormat?: CategoryFormat;\n /** The headers of the data table. */\n xLabel?: string;\n/** The header of the rows in the data table. */\n yLabel?: string;\n}\n\nexport function Heatmap<T extends Datum>(props: HeatmapProps<T>) {\n const { data, x, y, value, xCategories, yCategories, format, xFormat, yFormat, xLabel, yLabel } = props;\n const { locale, labels } = useSettings(props);\n const fmt = useMemo(\n () => ({ value: valueFormatter(format, locale, labels.noValue), axis: valueFormatter(format, locale, labels.noValue, true), x: categoryFormatter(xFormat ?? \"text\", locale), y: categoryFormatter(yFormat ?? \"text\", locale) }),\n [format, xFormat, yFormat, locale, labels.noValue],\n );\n const model = useMemo(() => {\n const xs = xCategories ? [...xCategories] : [...new Set(data.map((d, i) => read(x, d, i)))];\n const ys = yCategories ? [...yCategories] : [...new Set(data.map((d, i) => read(y, d, i)))];\n const cells = data\n .map((d, i) => ({ xi: xs.findIndex((c) => String(c) === String(read(x, d, i))), yi: ys.findIndex((c) => String(c) === String(read(y, d, i))), v: Number(read(value, d, i)) }))\n .filter((c) => c.xi >= 0 && c.yi >= 0 && Number.isFinite(c.v));\n const values = cells.map((c) => c.v);\n return { xs: xs.map(fmt.x), ys: ys.map(fmt.y), cells, min: Math.min(...values, 0), max: Math.max(...values, 0) };\n }, [data, x, y, value, xCategories, yCategories, fmt]);\n const isEmpty = model.cells.length === 0;\n const peak = model.cells.reduce<(typeof model.cells)[number] | null>((best, c) => (!best || c.v > best.v ? c : best), null);\n const summary = isEmpty\n ? labels.empty\n : `${fill(labels.summaryIntro, { kind: labels.kinds.heatmap, count: `${model.xs.length} × ${model.ys.length}` })} ${capitalize(fill(labels.summaryPeak, { value: fmt.value(peak!.v), at: `${model.ys[peak!.yi]}, ${model.xs[peak!.xi]}` }))}, ${fill(labels.summaryActive, { count: model.cells.filter((c) => c.v !== 0).length })}.`;\n const items: WalkItem[] = model.cells.map((c, i) => ({ seriesIndex: 0, dataIndex: i, text: `${model.ys[c.yi]}, ${model.xs[c.xi]}: ${fmt.value(c.v)}` }));\n\n const build = useCallback(\n (theme: ResolvedTheme, size: { width: number }) => {\n const base = baseOption(theme, true);\n return {\n ...base,\n tooltip: {\n ...(base.tooltip as object),\n trigger: \"item\",\n formatter: (p: { dataIndex: number }) => {\n const c = model.cells[p.dataIndex]!;\n return tooltipHtml(`${model.ys[c.yi]} · ${model.xs[c.xi]}`, [{ label: labels.value, value: fmt.value(c.v) }]);\n },\n },\n grid: { left: 8, right: 8, top: 8, bottom: 8, containLabel: true },\n xAxis: { ...categoryAxis(theme, model.xs), axisLine: { show: false }, axisLabel: { color: theme.text2, interval: size.width < 480 ? \"auto\" : 0 } },\n yAxis: { ...categoryAxis(theme, model.ys), axisLine: { show: false }, inverse: true },\n visualMap: { show: false, type: \"piecewise\", pieces: pieces(theme, model.min, model.max), dimension: 2 },\n series: [\n {\n type: \"heatmap\",\n data: model.cells.map((c) => [c.xi, c.yi, c.v]),\n itemStyle: { borderColor: theme.surface, borderWidth: 2, borderRadius: 3 },\n emphasis: { itemStyle: { borderColor: theme.text, borderWidth: 2 } },\n },\n ],\n };\n },\n [model, fmt, labels.value],\n );\n\n return (\n <EChartHost\n kind=\"heatmap\"\n frame={props}\n defaultHeight={260}\n table={{ columns: [yLabel && xLabel ? `${yLabel} / ${xLabel}` : (yLabel ?? labels.category), ...model.xs], rows: model.ys.map((row, yi) => [row, ...model.xs.map((_, xi) => fmt.value(model.cells.find((c) => c.xi === xi && c.yi === yi)?.v))]) }}\n summary={summary}\n isEmpty={isEmpty}\n legend={isEmpty ? null : <RampLegend min={model.min} max={model.max} steps={STEPS} write={fmt.axis} />}\n engine={engine}\n build={build}\n items={items}\n />\n );\n}\n\nexport interface CalendarHeatmapProps<T extends Datum> extends ChartFrameProps, EngineProps {\n /** One row per day (days without a row read as nothing). */\n data: readonly T[];\n /** The field of the day: an ISO date (`2026-04-12`), a `Date` or an epoch. */\n date: Accessor<T, unknown>;\n /** The field of the day's value. */\n value: Accessor<T, number>;\n /** The first and last days shown. Default: the year before the last day of the data. */\n range?: readonly [string, string];\n /** How the values are written. */\n format?: ValueFormat;\n /** The header of the values in the data table. */\n valueLabel?: string;\n}\n\nconst iso = (date: Date) => date.toISOString().slice(0, 10);\n\nexport function CalendarHeatmap<T extends Datum>(props: CalendarHeatmapProps<T>) {\n const { data, date, value, range, format, valueLabel } = props;\n const { locale, labels } = useSettings(props);\n const fmt = useMemo(() => ({ value: valueFormatter(format, locale, labels.noValue), axis: valueFormatter(format, locale, labels.noValue, true), day: categoryFormatter(\"date\", locale) }), [format, locale, labels.noValue]);\n const model = useMemo(() => {\n const days = data\n .map((d, i) => ({ day: asDate(read(date, d, i)), v: Number(read(value, d, i)) }))\n .filter((d): d is { day: Date; v: number } => d.day !== null && Number.isFinite(d.v))\n .map((d) => ({ day: iso(d.day), v: d.v }))\n .sort((a, b) => a.day.localeCompare(b.day));\n const last = days[days.length - 1]?.day ?? iso(new Date(0));\n const first = new Date(`${last}T00:00:00Z`);\n first.setUTCDate(first.getUTCDate() - 364);\n const span = range ?? ([iso(first), last] as const);\n const values = days.map((d) => d.v);\n return { days, span, min: Math.min(...values, 0), max: Math.max(...values, 0) };\n }, [data, date, value, range]);\n const isEmpty = model.days.length === 0;\n const peak = model.days.reduce<(typeof model.days)[number] | null>((best, d) => (!best || d.v > best.v ? d : best), null);\n const total = model.days.reduce((sum, d) => sum + d.v, 0);\n const summary = isEmpty\n ? labels.empty\n : `${fill(labels.summaryIntro, { kind: labels.kinds.calendar, count: `${fmt.day(model.span[0])} – ${fmt.day(model.span[1])}` })} ${capitalize(fill(labels.summaryTotal, { total: fmt.value(total) }))}, ${fill(labels.summaryPeak, { value: fmt.value(peak!.v), at: fmt.day(peak!.day) })}, ${fill(labels.summaryActive, { count: model.days.filter((d) => d.v !== 0).length })}.`;\n const items: WalkItem[] = model.days.map((d, i) => ({ seriesIndex: 0, dataIndex: i, text: `${fmt.day(d.day)}: ${fmt.value(d.v)}` }));\n\n const build = useCallback(\n (theme: ResolvedTheme, size: { width: number; height: number }) => {\n const base = baseOption(theme, true);\n const cell = Math.max(6, Math.min(18, Math.floor((size.width - 48) / 54)));\n const monthNames = Array.from({ length: 12 }, (_, m) => new Intl.DateTimeFormat(locale as string, { month: \"short\", timeZone: \"UTC\" }).format(new Date(Date.UTC(2026, m, 1))));\n const dayNames = Array.from({ length: 7 }, (_, d) => new Intl.DateTimeFormat(locale as string, { weekday: \"narrow\", timeZone: \"UTC\" }).format(new Date(Date.UTC(2026, 2, 1 + d))));\n return {\n ...base,\n tooltip: {\n ...(base.tooltip as object),\n trigger: \"item\",\n formatter: (p: { data: [string, number] }) => tooltipHtml(fmt.day(p.data[0]), [{ label: valueLabel ?? labels.value, value: fmt.value(p.data[1]) }]),\n },\n visualMap: { show: false, type: \"piecewise\", pieces: pieces(theme, model.min, model.max) },\n calendar: {\n range: [...model.span],\n cellSize: [cell, cell],\n top: 24,\n left: 32,\n right: 8,\n orient: \"horizontal\",\n splitLine: { show: false },\n itemStyle: { color: theme.surface2, borderColor: theme.surface, borderWidth: 2 },\n yearLabel: { show: false },\n monthLabel: { color: theme.text2, nameMap: monthNames, fontSize: 11 },\n dayLabel: { color: theme.text3, nameMap: dayNames, firstDay: 1, fontSize: 10 },\n },\n series: [{ type: \"heatmap\", coordinateSystem: \"calendar\", data: model.days.map((d) => [d.day, d.v]), itemStyle: { borderColor: theme.surface, borderWidth: 2, borderRadius: 2 } }],\n };\n },\n [model, fmt, valueLabel, locale, labels.value],\n );\n\n return (\n <EChartHost\n kind=\"calendar\"\n frame={props}\n defaultHeight={170}\n table={{ columns: [labels.category, valueLabel ?? labels.value], rows: model.days.map((d) => [fmt.day(d.day), fmt.value(d.v)]) }}\n summary={summary}\n isEmpty={isEmpty}\n legend={isEmpty ? null : <RampLegend min={model.min} max={model.max} steps={STEPS} write={fmt.axis} />}\n engine={engine}\n build={build}\n items={items}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/core/format.ts
|
|
4
|
+
import { currencyDigits, formatCompact, formatDate, formatMoney, formatNumber, formatPercent, getDateTimeFormat, getNumberFormat } from "@krizaka/intl";
|
|
5
|
+
function valueFormatter(format = "number", locale, noValue = "\u2014", axis = false) {
|
|
6
|
+
const write = writerOf(format, locale, axis);
|
|
7
|
+
return (value) => value == null || Number.isNaN(value) ? noValue : write(value);
|
|
8
|
+
}
|
|
9
|
+
function writerOf(format, locale, axis) {
|
|
10
|
+
if (typeof format === "function") return (value) => format(value, locale);
|
|
11
|
+
if (format === "integer") return (value) => formatNumber(Math.round(value), { locale, maximumFractionDigits: 0 });
|
|
12
|
+
if (format === "compact") return (value) => formatCompact(value, { locale });
|
|
13
|
+
if (format === "percent") return (value) => formatPercent(value, { locale, maximumFractionDigits: axis ? 0 : 1 });
|
|
14
|
+
if (format === "number") {
|
|
15
|
+
return (value) => axis && Math.abs(value) >= 1e4 ? formatCompact(value, { locale }) : formatNumber(value, { locale, maximumFractionDigits: 2 });
|
|
16
|
+
}
|
|
17
|
+
if (format.style === "money") {
|
|
18
|
+
const { currency } = format;
|
|
19
|
+
const digits = currencyDigits(currency);
|
|
20
|
+
return (value) => {
|
|
21
|
+
const minor = Math.round(value);
|
|
22
|
+
if ((axis || format.compact) && Math.abs(minor) >= 1e6) {
|
|
23
|
+
const options2 = { style: "currency", currency, currencyDisplay: "narrowSymbol", notation: "compact", minimumFractionDigits: 0, maximumFractionDigits: 1 };
|
|
24
|
+
return getNumberFormat(locale, options2).format(minor / 10 ** digits);
|
|
25
|
+
}
|
|
26
|
+
if (axis && minor % 10 ** digits === 0) {
|
|
27
|
+
return getNumberFormat(locale, { style: "currency", currency, minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(minor / 10 ** digits);
|
|
28
|
+
}
|
|
29
|
+
return formatMoney(minor, { currency, locale });
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (format.style === "unit") {
|
|
33
|
+
const { unit } = format;
|
|
34
|
+
const compact = axis || format.compact;
|
|
35
|
+
const options2 = { style: "unit", unit, unitDisplay: "short", ...compact ? { notation: "compact" } : {}, maximumFractionDigits: compact ? 1 : 2 };
|
|
36
|
+
return (value) => getNumberFormat(locale, options2).format(value);
|
|
37
|
+
}
|
|
38
|
+
const { options } = format;
|
|
39
|
+
return (value) => formatNumber(value, { locale, ...options });
|
|
40
|
+
}
|
|
41
|
+
function asDate(value) {
|
|
42
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
|
|
43
|
+
if (typeof value === "number" && value > 1e10) return new Date(value);
|
|
44
|
+
if (typeof value === "string" && /^\d{4}-\d{2}(-\d{2})?([T ][\d:.]+(Z|[+-]\d{2}:?\d{2})?)?$/.test(value)) {
|
|
45
|
+
const iso = value.length === 7 ? `${value}-01T00:00:00Z` : value.length === 10 ? `${value}T00:00:00Z` : value;
|
|
46
|
+
const date = new Date(iso);
|
|
47
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
var DATE_OPTIONS = {
|
|
52
|
+
year: { year: "numeric", timeZone: "UTC" },
|
|
53
|
+
month: { month: "short", year: "numeric", timeZone: "UTC" },
|
|
54
|
+
day: { month: "short", day: "numeric", timeZone: "UTC" },
|
|
55
|
+
date: { dateStyle: "medium", timeZone: "UTC" },
|
|
56
|
+
time: { timeStyle: "short", timeZone: "UTC" },
|
|
57
|
+
datetime: { dateStyle: "medium", timeStyle: "short", timeZone: "UTC" }
|
|
58
|
+
};
|
|
59
|
+
function categoryFormatter(format, locale) {
|
|
60
|
+
if (typeof format === "function") return (category) => format(category, locale);
|
|
61
|
+
if (format === "text") return (category) => String(category ?? "");
|
|
62
|
+
return (category) => {
|
|
63
|
+
const date = asDate(category);
|
|
64
|
+
if (!date) return String(category ?? "");
|
|
65
|
+
const kind = format ?? guessPrecision(category);
|
|
66
|
+
if (kind === "date") return formatDate(date, { locale, style: "medium", timeZone: "UTC" });
|
|
67
|
+
return getDateTimeFormat(locale, DATE_OPTIONS[kind]).format(date);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function guessPrecision(category) {
|
|
71
|
+
if (typeof category === "string") {
|
|
72
|
+
if (category.length === 7) return "month";
|
|
73
|
+
if (category.length === 10) return "date";
|
|
74
|
+
return "datetime";
|
|
75
|
+
}
|
|
76
|
+
const date = asDate(category);
|
|
77
|
+
return date && date.getUTCHours() === 0 && date.getUTCMinutes() === 0 ? "date" : "datetime";
|
|
78
|
+
}
|
|
79
|
+
function shareFormatter(locale) {
|
|
80
|
+
return (ratio) => formatPercent(ratio, { locale, maximumFractionDigits: Math.abs(ratio) < 0.1 ? 1 : 0 });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export {
|
|
84
|
+
valueFormatter,
|
|
85
|
+
asDate,
|
|
86
|
+
categoryFormatter,
|
|
87
|
+
shareFormatter
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=chunk-XLLYNNC6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/format.ts"],"sourcesContent":["// Values and categories written the same way in the axes, the tooltips, the data table and the summary, through\n// @krizaka/intl (one cached Intl formatter per locale and options).\nimport { currencyDigits, formatCompact, formatDate, formatMoney, formatNumber, formatPercent, getDateTimeFormat, getNumberFormat } from \"@krizaka/intl\";\n\nimport type { CategoryFormat, Locale, ValueFormat } from \"./types\";\n\nexport type ValueFormatter = (value: number | null | undefined) => string;\n\n/**\n * A formatter for `format`. `axis` asks for the short form of the axis ticks (money and units go compact past 10 000).\n * A missing value is written `noValue`.\n */\nexport function valueFormatter(format: ValueFormat = \"number\", locale: Locale, noValue = \"—\", axis = false): ValueFormatter {\n const write = writerOf(format, locale, axis);\n return (value) => (value == null || Number.isNaN(value) ? noValue : write(value));\n}\n\nfunction writerOf(format: ValueFormat, locale: Locale, axis: boolean): (value: number) => string {\n if (typeof format === \"function\") return (value) => format(value, locale);\n if (format === \"integer\") return (value) => formatNumber(Math.round(value), { locale, maximumFractionDigits: 0 });\n if (format === \"compact\") return (value) => formatCompact(value, { locale });\n if (format === \"percent\") return (value) => formatPercent(value, { locale, maximumFractionDigits: axis ? 0 : 1 });\n if (format === \"number\") {\n return (value) => (axis && Math.abs(value) >= 10_000 ? formatCompact(value, { locale }) : formatNumber(value, { locale, maximumFractionDigits: 2 }));\n }\n if (format.style === \"money\") {\n const { currency } = format;\n const digits = currencyDigits(currency);\n return (value) => {\n const minor = Math.round(value);\n // Compact money on the axes (`€12K`): the amount in major units, Intl's compact currency notation.\n if ((axis || format.compact) && Math.abs(minor) >= 1_000_000) {\n const options = { style: \"currency\", currency, currencyDisplay: \"narrowSymbol\", notation: \"compact\", minimumFractionDigits: 0, maximumFractionDigits: 1 } as const;\n return getNumberFormat(locale, options).format(minor / 10 ** digits);\n }\n // An axis tick is a round amount: no cents to write (`€2,500`, not `€2,500.00`).\n if (axis && minor % 10 ** digits === 0) {\n return getNumberFormat(locale, { style: \"currency\", currency, minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(minor / 10 ** digits);\n }\n return formatMoney(minor, { currency, locale });\n };\n }\n if (format.style === \"unit\") {\n const { unit } = format;\n const compact = axis || format.compact;\n const options: Intl.NumberFormatOptions = { style: \"unit\", unit, unitDisplay: \"short\", ...(compact ? { notation: \"compact\" } : {}), maximumFractionDigits: compact ? 1 : 2 };\n return (value) => getNumberFormat(locale, options).format(value);\n }\n const { options } = format;\n return (value) => formatNumber(value, { locale, ...options });\n}\n\n/** An ISO date (`2026-04`, `2026-04-12`, `2026-04-12T14:30Z`), a `Date` or an epoch → a `Date`; anything else → null. */\nexport function asDate(value: unknown): Date | null {\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n if (typeof value === \"number\" && value > 10_000_000_000) return new Date(value);\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}(-\\d{2})?([T ][\\d:.]+(Z|[+-]\\d{2}:?\\d{2})?)?$/.test(value)) {\n // `2026-04` is the first of April, at midnight UTC: a month never slips to March in a negative time zone.\n const iso = value.length === 7 ? `${value}-01T00:00:00Z` : value.length === 10 ? `${value}T00:00:00Z` : value;\n const date = new Date(iso);\n return Number.isNaN(date.getTime()) ? null : date;\n }\n return null;\n}\n\nconst DATE_OPTIONS: Record<Exclude<CategoryFormat, \"text\" | ((category: unknown, locale: Locale) => string)>, Intl.DateTimeFormatOptions> = {\n year: { year: \"numeric\", timeZone: \"UTC\" },\n month: { month: \"short\", year: \"numeric\", timeZone: \"UTC\" },\n day: { month: \"short\", day: \"numeric\", timeZone: \"UTC\" },\n date: { dateStyle: \"medium\", timeZone: \"UTC\" },\n time: { timeStyle: \"short\", timeZone: \"UTC\" },\n datetime: { dateStyle: \"medium\", timeStyle: \"short\", timeZone: \"UTC\" },\n};\n\nexport type CategoryFormatter = (category: unknown) => string;\n\n/**\n * A formatter for the categories. Without a format, a date category is written by its precision (`2026-04` → a month,\n * `2026-04-12` → a day) and anything else as text. Dates are written in UTC, the zone of an ISO date without one:\n * pass a function for a local time.\n */\nexport function categoryFormatter(format: CategoryFormat | undefined, locale: Locale): CategoryFormatter {\n if (typeof format === \"function\") return (category) => format(category, locale);\n if (format === \"text\") return (category) => String(category ?? \"\");\n return (category) => {\n const date = asDate(category);\n if (!date) return String(category ?? \"\");\n const kind = format ?? guessPrecision(category);\n if (kind === \"date\") return formatDate(date, { locale, style: \"medium\", timeZone: \"UTC\" });\n return getDateTimeFormat(locale, DATE_OPTIONS[kind]).format(date);\n };\n}\n\nfunction guessPrecision(category: unknown): \"month\" | \"date\" | \"datetime\" {\n if (typeof category === \"string\") {\n if (category.length === 7) return \"month\";\n if (category.length === 10) return \"date\";\n return \"datetime\";\n }\n const date = asDate(category);\n return date && date.getUTCHours() === 0 && date.getUTCMinutes() === 0 ? \"date\" : \"datetime\";\n}\n\n/** A ratio for the summary and the shares: `0.236` → `24%` (one decimal under 10 %). */\nexport function shareFormatter(locale: Locale): (ratio: number) => string {\n return (ratio) => formatPercent(ratio, { locale, maximumFractionDigits: Math.abs(ratio) < 0.1 ? 1 : 0 });\n}\n"],"mappings":"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","names":["options"]}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface ChartLabels {
|
|
5
|
+
/** The button that shows the data table. */
|
|
6
|
+
showData: string;
|
|
7
|
+
/** The button that hides it. */
|
|
8
|
+
hideData: string;
|
|
9
|
+
/** The caption of the data table: `{title}`. */
|
|
10
|
+
tableCaption: string;
|
|
11
|
+
/** The export buttons. */
|
|
12
|
+
exportPng: string;
|
|
13
|
+
exportSvg: string;
|
|
14
|
+
exportCsv: string;
|
|
15
|
+
/** Announced while the data loads. */
|
|
16
|
+
loading: string;
|
|
17
|
+
/** Shown when there is nothing to draw. */
|
|
18
|
+
empty: string;
|
|
19
|
+
/** Shown when the data could not be loaded. */
|
|
20
|
+
error: string;
|
|
21
|
+
/** The keyboard hint, read once when the plot takes the focus. */
|
|
22
|
+
keyboardHint: string;
|
|
23
|
+
/** The role description of the plot (`chart`). */
|
|
24
|
+
roleDescription: string;
|
|
25
|
+
/** Summary pieces. `{kind}` is the chart's name (`Line chart`), `{count}` a number of points or series. */
|
|
26
|
+
summaryIntro: string;
|
|
27
|
+
summarySeries: string;
|
|
28
|
+
summaryRange: string;
|
|
29
|
+
summaryTrendUp: string;
|
|
30
|
+
summaryTrendDown: string;
|
|
31
|
+
summaryTrendFlat: string;
|
|
32
|
+
summaryTotal: string;
|
|
33
|
+
summaryThreshold: string;
|
|
34
|
+
summaryShare: string;
|
|
35
|
+
/** Scatter: the correlation of x and y (Pearson's r). */
|
|
36
|
+
summaryCorrelation: string;
|
|
37
|
+
/** Funnel: from one stage to the next, and from the first to the last. */
|
|
38
|
+
summaryConversion: string;
|
|
39
|
+
summaryOverall: string;
|
|
40
|
+
/** Heatmap, calendar: the largest cell and the number of cells with a value. */
|
|
41
|
+
summaryPeak: string;
|
|
42
|
+
summaryActive: string;
|
|
43
|
+
/** Candlestick: the period's range. */
|
|
44
|
+
summaryOhlc: string;
|
|
45
|
+
/** The names of the charts, read first in the summary. */
|
|
46
|
+
kinds: Record<ChartKind, string>;
|
|
47
|
+
/** The column of the values, when the chart has no value label. */
|
|
48
|
+
value: string;
|
|
49
|
+
/** The column of the categories in the data table, when the chart has no x label. */
|
|
50
|
+
category: string;
|
|
51
|
+
/** The total row of a stacked chart, a pie, a funnel. */
|
|
52
|
+
total: string;
|
|
53
|
+
/** What a missing value reads as. */
|
|
54
|
+
noValue: string;
|
|
55
|
+
}
|
|
56
|
+
type ChartKind = "line" | "area" | "bar" | "pie" | "donut" | "gauge" | "sparkline" | "radar" | "heatmap" | "calendar" | "sankey" | "funnel" | "candlestick" | "treemap" | "scatter" | "map" | "globe" | "chart";
|
|
57
|
+
declare const DEFAULT_LABELS: ChartLabels;
|
|
58
|
+
/** The words an app or a chart passes: any of them, and any of the chart names. */
|
|
59
|
+
type ChartLabelsInput = Partial<Omit<ChartLabels, "kinds">> & {
|
|
60
|
+
kinds?: Partial<Record<ChartKind, string>>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** A row of data: any object; the chart reads the fields its `x`, `y` and `series` name. */
|
|
64
|
+
type Datum = object;
|
|
65
|
+
/** A field of a row (`"month"`) or a function that reads it. */
|
|
66
|
+
type Accessor<T, V> = (keyof T & string) | ((datum: T, index: number) => V);
|
|
67
|
+
/** A Krizaka brand: its palette leads with the brand's own hue (Krizaka blue, Orazaka orange, Orochia violet). */
|
|
68
|
+
type BrandId = "krizaka" | "orazaka" | "orochia";
|
|
69
|
+
/** A BCP 47 locale (`"en-US"`, `"fr-FR"`), always explicit: server and client write the same figures. */
|
|
70
|
+
type Locale = string | readonly string[];
|
|
71
|
+
/**
|
|
72
|
+
* How a value is written, through `@krizaka/intl`:
|
|
73
|
+
* - `"number"` (default) `12,345.6`, `"integer"` `12,346`, `"compact"` `12.3K`, `"percent"` (a ratio: `0.42` → `42%`);
|
|
74
|
+
* - `{ style: "money", currency }`: the values are **integer minor units** (cents), as the ledger stores them;
|
|
75
|
+
* - `{ style: "unit", unit }`: an `Intl` unit (`"second"`, `"megabyte"`);
|
|
76
|
+
* - a function, for anything else.
|
|
77
|
+
*/
|
|
78
|
+
type ValueFormat = "number" | "integer" | "compact" | "percent" | {
|
|
79
|
+
readonly style: "money";
|
|
80
|
+
readonly currency: string;
|
|
81
|
+
readonly compact?: boolean;
|
|
82
|
+
} | {
|
|
83
|
+
readonly style: "unit";
|
|
84
|
+
readonly unit: string;
|
|
85
|
+
readonly compact?: boolean;
|
|
86
|
+
} | {
|
|
87
|
+
readonly style: "number";
|
|
88
|
+
readonly options: Intl.NumberFormatOptions;
|
|
89
|
+
} | ((value: number, locale: Locale) => string);
|
|
90
|
+
/**
|
|
91
|
+
* How a category of the x axis is written. A category that is a `Date`, an epoch or an ISO date (`"2026-04"`,
|
|
92
|
+
* `"2026-04-12"`) is a date: `"month"` (`Apr 2026`), `"day"` (`Apr 12`), `"date"` (`Apr 12, 2026`), `"time"`
|
|
93
|
+
* (`14:30`), `"datetime"`, `"year"`. `"text"` writes it as is (the default for anything that is not a date).
|
|
94
|
+
*/
|
|
95
|
+
type CategoryFormat = "text" | "year" | "month" | "day" | "date" | "time" | "datetime" | ((category: unknown, locale: Locale) => string);
|
|
96
|
+
/** A series to draw: the field holding its values and the words that name it. */
|
|
97
|
+
interface SeriesSpec<T extends Datum = Datum> {
|
|
98
|
+
/** The field (or a function) holding the series' value in each row. */
|
|
99
|
+
readonly key: Accessor<T, number | null | undefined>;
|
|
100
|
+
/** Its name: in the legend, the tooltip, the data table and the summary. */
|
|
101
|
+
readonly label: string;
|
|
102
|
+
/** A colour role instead of the next palette slot: `"accent"`, a status (`"success"`…) or a `var(--…)`. */
|
|
103
|
+
readonly color?: SeriesColor;
|
|
104
|
+
/** Draw it dashed (a forecast, a previous period). Lines and areas only. */
|
|
105
|
+
readonly dashed?: boolean;
|
|
106
|
+
}
|
|
107
|
+
/** A status or brand role a series, a threshold or a marker may wear instead of a palette slot. */
|
|
108
|
+
type Tone = "neutral" | "accent" | "success" | "warning" | "danger" | "info";
|
|
109
|
+
/** A palette slot (1–8), a tone, or any CSS colour (`var(--kz-…)` preferred). */
|
|
110
|
+
type SeriesColor = Tone | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | (string & {});
|
|
111
|
+
/** A horizontal line at a value: a goal, a payout threshold, a quota. */
|
|
112
|
+
interface Threshold {
|
|
113
|
+
readonly value: number;
|
|
114
|
+
/** What it means, written beside the line and in the summary: “Payout threshold”. */
|
|
115
|
+
readonly label: string;
|
|
116
|
+
/** Default `"neutral"`; a goal reads well in `"success"`, a limit in `"danger"`. */
|
|
117
|
+
readonly tone?: Tone;
|
|
118
|
+
}
|
|
119
|
+
/** A vertical marker at a category: an event worth pointing at (“Campaign launch”). */
|
|
120
|
+
interface Marker {
|
|
121
|
+
/** The category it marks, as in the data (`"2026-04"`). */
|
|
122
|
+
readonly x: unknown;
|
|
123
|
+
readonly label: string;
|
|
124
|
+
readonly tone?: Tone;
|
|
125
|
+
}
|
|
126
|
+
/** What a series says about itself, for the written summary. */
|
|
127
|
+
interface SeriesSummary {
|
|
128
|
+
readonly label: string;
|
|
129
|
+
readonly count: number;
|
|
130
|
+
readonly min: {
|
|
131
|
+
readonly value: number;
|
|
132
|
+
readonly category: string;
|
|
133
|
+
} | null;
|
|
134
|
+
readonly max: {
|
|
135
|
+
readonly value: number;
|
|
136
|
+
readonly category: string;
|
|
137
|
+
} | null;
|
|
138
|
+
readonly first: number | null;
|
|
139
|
+
readonly last: number | null;
|
|
140
|
+
readonly total: number;
|
|
141
|
+
/** `last / first − 1`, or null when it cannot be said (no first value, a first value of 0). */
|
|
142
|
+
readonly change: number | null;
|
|
143
|
+
readonly trend: "up" | "down" | "flat" | "none";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface ChartsSettings {
|
|
147
|
+
/** The locale of every figure and date (`"fr-FR"`). Default `"en-US"`. */
|
|
148
|
+
locale?: Locale;
|
|
149
|
+
/**
|
|
150
|
+
* The brand whose palette the charts use. Without it, a chart follows a `.brand-<id>` ancestor, else Krizaka. Set it
|
|
151
|
+
* when the app loads a brand stylesheet on `:root` (`@krizaka/tokens/brands/orazaka.css`).
|
|
152
|
+
*/
|
|
153
|
+
brand?: BrandId;
|
|
154
|
+
/** The words, translated: the buttons, the states, the written summary. */
|
|
155
|
+
labels?: ChartLabelsInput;
|
|
156
|
+
}
|
|
157
|
+
interface ChartsProviderProps extends ChartsSettings {
|
|
158
|
+
children: ReactNode;
|
|
159
|
+
}
|
|
160
|
+
/** Sets the locale, the brand and the words of every chart below it. */
|
|
161
|
+
declare function ChartsProvider({ locale, brand, labels, children }: ChartsProviderProps): react.JSX.Element;
|
|
162
|
+
|
|
163
|
+
export { type Accessor as A, type BrandId as B, type CategoryFormat as C, DEFAULT_LABELS as D, type Locale as L, type Marker as M, type SeriesColor as S, type Threshold as T, type ValueFormat as V, type ChartKind as a, type ChartLabels as b, type ChartLabelsInput as c, ChartsProvider as d, type ChartsProviderProps as e, type ChartsSettings as f, type Datum as g, type SeriesSpec as h, type SeriesSummary as i, type Tone as j };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { a as CreditLabels } from './labels-DE_743fQ.js';
|
|
2
|
+
export { C as CREDIT_LABELS } from './labels-DE_743fQ.js';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
5
|
+
import { f as ChartsSettings, V as ValueFormat } from './context-BgYUymEO.js';
|
|
6
|
+
|
|
7
|
+
interface CreditUsageProps extends Omit<ChartsSettings, "labels"> {
|
|
8
|
+
/** What the allowance is (“Credits this month”): the heading and the meter's name. */
|
|
9
|
+
title: string;
|
|
10
|
+
/** A line under the title: the plan, the period. */
|
|
11
|
+
description?: ReactNode;
|
|
12
|
+
/** Visually hide the title (it stays the accessible name). */
|
|
13
|
+
hideTitle?: boolean;
|
|
14
|
+
/** How much is used. */
|
|
15
|
+
used: number;
|
|
16
|
+
/** The allowance. */
|
|
17
|
+
limit: number;
|
|
18
|
+
/** How the amounts are written. Default `"integer"`; a `{ style: "unit", unit: "gigabyte" }` for storage. */
|
|
19
|
+
format?: ValueFormat;
|
|
20
|
+
/** The use of each recent day, oldest first: the sparkline and the projection. */
|
|
21
|
+
daily?: readonly (number | null)[];
|
|
22
|
+
/** The days of `daily` (ISO dates), for the sparkline's summary. */
|
|
23
|
+
days?: readonly unknown[];
|
|
24
|
+
/** When the allowance renews (an ISO date or a `Date`). */
|
|
25
|
+
renewsAt?: string | Date;
|
|
26
|
+
/** Today, for the projection (pass it from the server to render the same date on both sides). Default: now. */
|
|
27
|
+
now?: Date;
|
|
28
|
+
/** The share where the meter turns to warning, then danger. Default `[0.8, 0.95]`. */
|
|
29
|
+
levels?: readonly [number, number];
|
|
30
|
+
/** The data is on its way. */
|
|
31
|
+
loading?: boolean;
|
|
32
|
+
/** The words, passed translated; English by default. */
|
|
33
|
+
labels?: Partial<CreditLabels>;
|
|
34
|
+
/** A class on the figure (layout). */
|
|
35
|
+
className?: string;
|
|
36
|
+
/** Inline style on the figure (layout only). */
|
|
37
|
+
style?: CSSProperties;
|
|
38
|
+
}
|
|
39
|
+
/** What is left of an allowance: the remaining amount, a meter in tones, the use per day and the run-out date. */
|
|
40
|
+
declare function CreditUsage({ title, description, hideTitle, used, limit, format, daily, days, renewsAt, now, levels, loading, labels: given, className, style, ...settings }: CreditUsageProps): react.JSX.Element;
|
|
41
|
+
|
|
42
|
+
export { CreditLabels, CreditUsage, type CreditUsageProps };
|
package/dist/credits.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
CreditUsage
|
|
4
|
+
} from "./chunk-L2EKYWVI.js";
|
|
5
|
+
import "./chunk-ARARFMNE.js";
|
|
6
|
+
import "./chunk-WBHFVBSK.js";
|
|
7
|
+
import "./chunk-BISL7DYW.js";
|
|
8
|
+
import "./chunk-ANUCSRUN.js";
|
|
9
|
+
import "./chunk-W5FX4TU3.js";
|
|
10
|
+
import {
|
|
11
|
+
CREDIT_LABELS
|
|
12
|
+
} from "./chunk-WNUFGMS7.js";
|
|
13
|
+
import "./chunk-OB5EFDDH.js";
|
|
14
|
+
import "./chunk-XLLYNNC6.js";
|
|
15
|
+
import "./chunk-JTKR7ZWP.js";
|
|
16
|
+
import "./chunk-3CJHBJXA.js";
|
|
17
|
+
export {
|
|
18
|
+
CREDIT_LABELS,
|
|
19
|
+
CreditUsage
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=credits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { b as EarningsLabels } from './labels-DE_743fQ.js';
|
|
2
|
+
export { E as EARNINGS_LABELS } from './labels-DE_743fQ.js';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { C as CartesianProps } from './cartesian-BRhNQ3ib.js';
|
|
5
|
+
import { g as Datum, A as Accessor, C as CategoryFormat, T as Threshold } from './context-BgYUymEO.js';
|
|
6
|
+
import './frame-I7_xYGy5.js';
|
|
7
|
+
|
|
8
|
+
interface EarningsChartProps<T extends Datum> extends Omit<CartesianProps<T>, "y" | "yLabel" | "series" | "format" | "x" | "xFormat" | "thresholds" | "labels"> {
|
|
9
|
+
/** The field (or function) of the period: an ISO month (`"2026-04"`), a day. Default `"month"`. */
|
|
10
|
+
x?: Accessor<T, unknown>;
|
|
11
|
+
/** The net amount of each period, in **minor units** (cents), as the ledger stores it. */
|
|
12
|
+
net: Accessor<T, number | null | undefined>;
|
|
13
|
+
/** The gross amount (before fees), drawn beside the net when given. */
|
|
14
|
+
gross?: Accessor<T, number | null | undefined>;
|
|
15
|
+
/** The ISO 4217 currency (`"USD"`, `"EUR"`). */
|
|
16
|
+
currency: string;
|
|
17
|
+
/** How the periods are written. Default `"month"` (`Apr 2026`). */
|
|
18
|
+
period?: CategoryFormat;
|
|
19
|
+
/** The minimum to withdraw, drawn as a line: `{ value: 5000, label: "Payout threshold" }`. */
|
|
20
|
+
payoutThreshold?: Threshold;
|
|
21
|
+
/** Hide the total and the change above the bars. */
|
|
22
|
+
hideSummary?: boolean;
|
|
23
|
+
/** The words, passed translated; English by default. */
|
|
24
|
+
labels?: Partial<EarningsLabels>;
|
|
25
|
+
}
|
|
26
|
+
/** Earnings per period in money — the total, the change of the last period, the payout threshold. */
|
|
27
|
+
declare function EarningsChart<T extends Datum>({ x, net, gross, currency, period, payoutThreshold, hideSummary, labels: given, description, data, ...props }: EarningsChartProps<T>): react.JSX.Element;
|
|
28
|
+
|
|
29
|
+
export { EarningsChart, type EarningsChartProps, EarningsLabels };
|