@krizaka/charts 0.1.0 → 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.
Files changed (193) hide show
  1. package/README.md +17 -5
  2. package/dist/bar.js +5 -4
  3. package/dist/candlestick.js +3 -3
  4. package/dist/chart.js +3 -3
  5. package/dist/{chunk-EK3Z647J.js → chunk-4LBXEAGC.js} +3 -3
  6. package/dist/{chunk-AHQXJSAQ.js → chunk-AA5EWWYV.js} +2 -2
  7. package/dist/{chunk-VKO2OYYM.js → chunk-ARARFMNE.js} +2 -2
  8. package/dist/{chunk-WBH2QU77.js → chunk-BV4DBGN7.js} +2 -2
  9. package/dist/{chunk-BZ5CQFPH.js → chunk-C4MFZLJM.js} +2 -2
  10. package/dist/{chunk-XAJ3KCC4.js → chunk-CSSZLFLO.js} +3 -3
  11. package/dist/{chunk-UNK4MJVG.js → chunk-CVWSMUUB.js} +8 -8
  12. package/dist/chunk-E5DKBSWX.js +2 -0
  13. package/dist/chunk-E5DKBSWX.js.map +1 -0
  14. package/dist/chunk-EEP7PS2L.js +54 -0
  15. package/dist/chunk-EEP7PS2L.js.map +1 -0
  16. package/dist/{chunk-DZB6HEVO.js → chunk-EQLC2QVN.js} +2 -2
  17. package/dist/chunk-FINOPIDN.js +2 -0
  18. package/dist/chunk-FINOPIDN.js.map +1 -0
  19. package/dist/chunk-G2KF2WL4.js +2 -0
  20. package/dist/chunk-G2KF2WL4.js.map +1 -0
  21. package/dist/{chunk-PTSB3H5Q.js → chunk-I3D7KUGN.js} +2 -2
  22. package/dist/chunk-IKQV3NSL.js +76 -0
  23. package/dist/chunk-IKQV3NSL.js.map +1 -0
  24. package/dist/{chunk-DWJPPEMC.js → chunk-JTKR7ZWP.js} +73 -60
  25. package/dist/chunk-JTKR7ZWP.js.map +1 -0
  26. package/dist/chunk-KNDHO67X.js +78 -0
  27. package/dist/chunk-KNDHO67X.js.map +1 -0
  28. package/dist/chunk-L2EKYWVI.js +94 -0
  29. package/dist/chunk-L2EKYWVI.js.map +1 -0
  30. package/dist/{chunk-XC6BQ3RN.js → chunk-MXLITIGU.js} +3 -3
  31. package/dist/{chunk-OER6ETT4.js → chunk-NCIQMRV3.js} +3 -3
  32. package/dist/chunk-OIRHLJBC.js +83 -0
  33. package/dist/chunk-OIRHLJBC.js.map +1 -0
  34. package/dist/{chunk-WIRCIOLH.js → chunk-PBQV3B6O.js} +5 -5
  35. package/dist/chunk-POQIHFAZ.js +2 -0
  36. package/dist/chunk-POQIHFAZ.js.map +1 -0
  37. package/dist/{chunk-I5QUZVU2.js → chunk-PWMMXRMC.js} +2 -2
  38. package/dist/chunk-SLEJDQ3A.js +81 -0
  39. package/dist/chunk-SLEJDQ3A.js.map +1 -0
  40. package/dist/{chunk-7TIFCK5E.js → chunk-VKZZY2QD.js} +3 -3
  41. package/dist/{chunk-VKTZD7UT.js → chunk-W5ILLSPK.js} +3 -3
  42. package/dist/chunk-WBHFVBSK.js +25 -0
  43. package/dist/chunk-WBHFVBSK.js.map +1 -0
  44. package/dist/chunk-WNUFGMS7.js +113 -0
  45. package/dist/chunk-WNUFGMS7.js.map +1 -0
  46. package/dist/{chunk-XR4ZJDOV.js → chunk-WVTIKOII.js} +2 -2
  47. package/dist/{chunk-7CSAGFBW.js → chunk-XDDALY4C.js} +3 -3
  48. package/dist/credits.d.ts +42 -0
  49. package/dist/credits.js +21 -0
  50. package/dist/credits.js.map +1 -0
  51. package/dist/earnings.d.ts +29 -0
  52. package/dist/earnings.js +22 -0
  53. package/dist/earnings.js.map +1 -0
  54. package/dist/funnel.js +3 -3
  55. package/dist/gauge.js +3 -2
  56. package/dist/geo.js +2 -2
  57. package/dist/globe.js +2 -2
  58. package/dist/goal.d.ts +26 -0
  59. package/dist/goal.js +17 -0
  60. package/dist/goal.js.map +1 -0
  61. package/dist/heatmap.js +3 -3
  62. package/dist/index.d.ts +7 -0
  63. package/dist/index.js +80 -33
  64. package/dist/labels-DE_743fQ.d.ts +72 -0
  65. package/dist/latency.d.ts +33 -0
  66. package/dist/latency.js +24 -0
  67. package/dist/latency.js.map +1 -0
  68. package/dist/line.js +5 -4
  69. package/dist/native.d.ts +195 -1
  70. package/dist/native.js +383 -14
  71. package/dist/native.js.map +1 -1
  72. package/dist/pie.js +3 -3
  73. package/dist/radar.js +3 -3
  74. package/dist/sankey.js +3 -3
  75. package/dist/scatter.js +3 -3
  76. package/dist/sparkline.js +4 -3
  77. package/dist/throughput.d.ts +37 -0
  78. package/dist/throughput.js +24 -0
  79. package/dist/throughput.js.map +1 -0
  80. package/dist/ticker.d.ts +38 -0
  81. package/dist/ticker.js +22 -0
  82. package/dist/ticker.js.map +1 -0
  83. package/dist/treemap.js +3 -3
  84. package/package.json +100 -4
  85. package/registry/area-chart.json +1 -0
  86. package/registry/bar-chart.json +1 -0
  87. package/registry/calendar-heatmap.json +1 -0
  88. package/registry/candlestick.json +1 -0
  89. package/registry/chart.json +1 -0
  90. package/registry/charts-provider.json +1 -0
  91. package/registry/credit-usage.json +473 -0
  92. package/registry/earnings-chart.json +703 -0
  93. package/registry/examples/credit-usage/monthly-credits.d.ts +4 -0
  94. package/registry/examples/credit-usage/monthly-credits.js +24 -0
  95. package/registry/examples/credit-usage/monthly-credits.tsx +19 -0
  96. package/registry/examples/credit-usage/native/monthly-credits.d.ts +4 -0
  97. package/registry/examples/credit-usage/native/monthly-credits.dark.png +0 -0
  98. package/registry/examples/credit-usage/native/monthly-credits.js +23 -0
  99. package/registry/examples/credit-usage/native/monthly-credits.light.png +0 -0
  100. package/registry/examples/credit-usage/native/monthly-credits.tsx +18 -0
  101. package/registry/examples/credit-usage/storage-plan.d.ts +4 -0
  102. package/registry/examples/credit-usage/storage-plan.js +21 -0
  103. package/registry/examples/credit-usage/storage-plan.tsx +15 -0
  104. package/registry/examples/earnings-chart/creator-month.d.ts +4 -0
  105. package/registry/examples/earnings-chart/creator-month.js +29 -0
  106. package/registry/examples/earnings-chart/creator-month.tsx +24 -0
  107. package/registry/examples/earnings-chart/gross-and-net.d.ts +4 -0
  108. package/registry/examples/earnings-chart/gross-and-net.js +29 -0
  109. package/registry/examples/earnings-chart/gross-and-net.tsx +24 -0
  110. package/registry/examples/earnings-chart/native/creator-month.d.ts +4 -0
  111. package/registry/examples/earnings-chart/native/creator-month.dark.png +0 -0
  112. package/registry/examples/earnings-chart/native/creator-month.js +29 -0
  113. package/registry/examples/earnings-chart/native/creator-month.light.png +0 -0
  114. package/registry/examples/earnings-chart/native/creator-month.tsx +24 -0
  115. package/registry/examples/goal-progress/challenge-pot.d.ts +4 -0
  116. package/registry/examples/goal-progress/challenge-pot.js +22 -0
  117. package/registry/examples/goal-progress/challenge-pot.tsx +16 -0
  118. package/registry/examples/goal-progress/goal-reached.d.ts +4 -0
  119. package/registry/examples/goal-progress/goal-reached.js +11 -0
  120. package/registry/examples/goal-progress/goal-reached.tsx +6 -0
  121. package/registry/examples/goal-progress/native/challenge-pot.d.ts +4 -0
  122. package/registry/examples/goal-progress/native/challenge-pot.dark.png +0 -0
  123. package/registry/examples/goal-progress/native/challenge-pot.js +11 -0
  124. package/registry/examples/goal-progress/native/challenge-pot.light.png +0 -0
  125. package/registry/examples/goal-progress/native/challenge-pot.tsx +6 -0
  126. package/registry/examples/job-throughput/live-hours.d.ts +4 -0
  127. package/registry/examples/job-throughput/live-hours.js +33 -0
  128. package/registry/examples/job-throughput/live-hours.tsx +28 -0
  129. package/registry/examples/job-throughput/native/week-of-jobs.d.ts +4 -0
  130. package/registry/examples/job-throughput/native/week-of-jobs.dark.png +0 -0
  131. package/registry/examples/job-throughput/native/week-of-jobs.js +20 -0
  132. package/registry/examples/job-throughput/native/week-of-jobs.light.png +0 -0
  133. package/registry/examples/job-throughput/native/week-of-jobs.tsx +16 -0
  134. package/registry/examples/job-throughput/week-of-jobs.d.ts +4 -0
  135. package/registry/examples/job-throughput/week-of-jobs.js +20 -0
  136. package/registry/examples/job-throughput/week-of-jobs.tsx +16 -0
  137. package/registry/examples/latency-chart/by-capability.d.ts +4 -0
  138. package/registry/examples/latency-chart/by-capability.js +26 -0
  139. package/registry/examples/latency-chart/by-capability.tsx +21 -0
  140. package/registry/examples/latency-chart/native/by-capability.d.ts +4 -0
  141. package/registry/examples/latency-chart/native/by-capability.dark.png +0 -0
  142. package/registry/examples/latency-chart/native/by-capability.js +17 -0
  143. package/registry/examples/latency-chart/native/by-capability.light.png +0 -0
  144. package/registry/examples/latency-chart/native/by-capability.tsx +13 -0
  145. package/registry/examples/latency-chart/time-to-result.d.ts +4 -0
  146. package/registry/examples/latency-chart/time-to-result.js +27 -0
  147. package/registry/examples/latency-chart/time-to-result.tsx +22 -0
  148. package/registry/examples/price-ticker/auction-room.d.ts +4 -0
  149. package/registry/examples/price-ticker/auction-room.js +21 -0
  150. package/registry/examples/price-ticker/auction-room.tsx +17 -0
  151. package/registry/examples/price-ticker/native/auction-room.d.ts +4 -0
  152. package/registry/examples/price-ticker/native/auction-room.dark.png +0 -0
  153. package/registry/examples/price-ticker/native/auction-room.js +19 -0
  154. package/registry/examples/price-ticker/native/auction-room.light.png +0 -0
  155. package/registry/examples/price-ticker/native/auction-room.tsx +15 -0
  156. package/registry/examples/price-ticker/no-bid-yet.d.ts +4 -0
  157. package/registry/examples/price-ticker/no-bid-yet.js +11 -0
  158. package/registry/examples/price-ticker/no-bid-yet.tsx +6 -0
  159. package/registry/funnel.json +1 -0
  160. package/registry/gauge.json +1 -0
  161. package/registry/geo-map.json +1 -0
  162. package/registry/globe.json +1 -0
  163. package/registry/goal-progress.json +520 -0
  164. package/registry/heatmap.json +1 -0
  165. package/registry/index.json +163 -1
  166. package/registry/job-throughput.json +654 -0
  167. package/registry/latency-chart.json +671 -0
  168. package/registry/line-chart.json +1 -0
  169. package/registry/pie-chart.json +1 -0
  170. package/registry/price-ticker.json +684 -0
  171. package/registry/radar-chart.json +1 -0
  172. package/registry/sankey.json +1 -0
  173. package/registry/scatter-chart.json +1 -0
  174. package/registry/sparkline.json +1 -0
  175. package/registry/treemap.json +1 -0
  176. package/dist/chunk-DWJPPEMC.js.map +0 -1
  177. /package/dist/{chunk-EK3Z647J.js.map → chunk-4LBXEAGC.js.map} +0 -0
  178. /package/dist/{chunk-AHQXJSAQ.js.map → chunk-AA5EWWYV.js.map} +0 -0
  179. /package/dist/{chunk-VKO2OYYM.js.map → chunk-ARARFMNE.js.map} +0 -0
  180. /package/dist/{chunk-WBH2QU77.js.map → chunk-BV4DBGN7.js.map} +0 -0
  181. /package/dist/{chunk-BZ5CQFPH.js.map → chunk-C4MFZLJM.js.map} +0 -0
  182. /package/dist/{chunk-XAJ3KCC4.js.map → chunk-CSSZLFLO.js.map} +0 -0
  183. /package/dist/{chunk-UNK4MJVG.js.map → chunk-CVWSMUUB.js.map} +0 -0
  184. /package/dist/{chunk-DZB6HEVO.js.map → chunk-EQLC2QVN.js.map} +0 -0
  185. /package/dist/{chunk-PTSB3H5Q.js.map → chunk-I3D7KUGN.js.map} +0 -0
  186. /package/dist/{chunk-XC6BQ3RN.js.map → chunk-MXLITIGU.js.map} +0 -0
  187. /package/dist/{chunk-OER6ETT4.js.map → chunk-NCIQMRV3.js.map} +0 -0
  188. /package/dist/{chunk-WIRCIOLH.js.map → chunk-PBQV3B6O.js.map} +0 -0
  189. /package/dist/{chunk-I5QUZVU2.js.map → chunk-PWMMXRMC.js.map} +0 -0
  190. /package/dist/{chunk-7TIFCK5E.js.map → chunk-VKZZY2QD.js.map} +0 -0
  191. /package/dist/{chunk-VKTZD7UT.js.map → chunk-W5ILLSPK.js.map} +0 -0
  192. /package/dist/{chunk-XR4ZJDOV.js.map → chunk-WVTIKOII.js.map} +0 -0
  193. /package/dist/{chunk-7CSAGFBW.js.map → chunk-XDDALY4C.js.map} +0 -0
package/README.md CHANGED
@@ -27,6 +27,18 @@ import { LineChart } from "@krizaka/charts/line";
27
27
  />;
28
28
  ```
29
29
 
30
+ **Start from the need.** The ready-made charts answer the screens of the Krizaka apps with their formats, words and
31
+ defaults chosen; the core charts are what they are built on; the advanced ones have no product use today.
32
+
33
+ | Need (screen) | Ready-made chart | Entry | Native |
34
+ | :-- | :-- | :-- | :-- |
35
+ | Earnings per month (Orochia /earnings, the console's treasury) | `EarningsChart` | `@krizaka/charts/earnings` | yes |
36
+ | Jobs per day by status, success rate (Orazaka insights, supervision, mobile Jobs) | `JobThroughput` | `@krizaka/charts/throughput` | yes |
37
+ | Latency / time to result per capability, against an objective | `LatencyChart` | `@krizaka/charts/latency` | yes |
38
+ | Credits or storage left, run-out date (Orazaka billing, Orochia storage) | `CreditUsage` | `@krizaka/charts/credits` | yes |
39
+ | A challenge's pot towards its goal (Orochia web and app) | `GoalProgress` | `@krizaka/charts/goal` | yes |
40
+ | A live auction's price (Orochia auction room, web and app) | `PriceTicker` | `@krizaka/charts/ticker` | yes |
41
+
30
42
  | Entry | Charts | Engine |
31
43
  | :-- | :-- | :-- |
32
44
  | `@krizaka/charts/line` | `LineChart`, `AreaChart` | SVG, 13 kB |
@@ -34,12 +46,12 @@ import { LineChart } from "@krizaka/charts/line";
34
46
  | `@krizaka/charts/pie` | `PieChart`, `DonutChart` | SVG, 9 kB |
35
47
  | `@krizaka/charts/gauge` | `Gauge` | SVG, 8 kB |
36
48
  | `@krizaka/charts/sparkline` | `Sparkline` | SVG, 10 kB |
37
- | `@krizaka/charts/geo` | `GeoMap` | SVG (d3-geo) + the world on demand |
38
- | `@krizaka/charts/globe` | `Globe3D` | SVG (orthographic, no WebGL) |
39
- | `@krizaka/charts/radar` · `heatmap` · `sankey` · `funnel` · `candlestick` · `treemap` · `scatter` | `RadarChart`, `Heatmap`, `CalendarHeatmap`, `Sankey`, `Funnel`, `Candlestick`, `Treemap`, `ScatterChart` | ECharts, loaded when the chart nears the screen (~11 kB before) |
40
- | `@krizaka/charts/chart` | `Chart` — any ECharts option, themed and framed | ECharts (`modules` to tree-shake) |
49
+ | `@krizaka/charts/geo` | `GeoMap` — advanced | SVG (d3-geo) + the world on demand |
50
+ | `@krizaka/charts/globe` | `Globe3D` — advanced | SVG (orthographic, no WebGL) |
51
+ | advanced: `@krizaka/charts/radar` · `heatmap` · `sankey` · `funnel` · `candlestick` · `treemap` · `scatter` | `RadarChart`, `Heatmap`, `CalendarHeatmap`, `Sankey`, `Funnel`, `Candlestick`, `Treemap`, `ScatterChart` | ECharts, loaded when the chart nears the screen (~11 kB before) |
52
+ | `@krizaka/charts/chart` | `Chart` — advanced: any ECharts option, themed and framed | ECharts (`modules` to tree-shake) |
41
53
  | `@krizaka/charts/provider` | `ChartsProvider` (locale, brand, words), `useSlidingWindow` | — |
42
- | `@krizaka/charts/native` | `LineChart`, `AreaChart`, `BarChart`, `PieChart`, `DonutChart`, `Gauge`, `Sparkline` | react-native-svg |
54
+ | `@krizaka/charts/native` | the six ready-made charts, `LineChart`, `AreaChart`, `BarChart`, `PieChart`, `DonutChart`, `Gauge`, `Sparkline` | react-native-svg |
43
55
 
44
56
  Needs React 19 and the Krizaka tokens in the page (`@krizaka/tokens/tokens.css`, or `@krizaka/tailwind`); the
45
57
  charts' own CSS is embedded. Themes follow `color-scheme` (`html.light`, `.theme-light`); brands follow a
package/dist/bar.js CHANGED
@@ -1,14 +1,15 @@
1
1
  "use client";
2
+ import "./chunk-FINOPIDN.js";
2
3
  import {
3
4
  BarChart
4
- } from "./chunk-XR4ZJDOV.js";
5
- import "./chunk-UNK4MJVG.js";
5
+ } from "./chunk-WVTIKOII.js";
6
+ import "./chunk-CVWSMUUB.js";
6
7
  import "./chunk-BISL7DYW.js";
7
8
  import "./chunk-ANUCSRUN.js";
8
- import "./chunk-OB5EFDDH.js";
9
9
  import "./chunk-W5FX4TU3.js";
10
+ import "./chunk-OB5EFDDH.js";
10
11
  import "./chunk-XLLYNNC6.js";
11
- import "./chunk-DWJPPEMC.js";
12
+ import "./chunk-JTKR7ZWP.js";
12
13
  import "./chunk-3CJHBJXA.js";
13
14
  export {
14
15
  BarChart
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  import {
3
3
  Candlestick
4
- } from "./chunk-OER6ETT4.js";
5
- import "./chunk-I5QUZVU2.js";
4
+ } from "./chunk-NCIQMRV3.js";
5
+ import "./chunk-PWMMXRMC.js";
6
6
  import "./chunk-W5FX4TU3.js";
7
7
  import "./chunk-XLLYNNC6.js";
8
- import "./chunk-DWJPPEMC.js";
8
+ import "./chunk-JTKR7ZWP.js";
9
9
  import "./chunk-3CJHBJXA.js";
10
10
  export {
11
11
  Candlestick
package/dist/chart.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import {
3
3
  Chart
4
- } from "./chunk-AHQXJSAQ.js";
5
- import "./chunk-I5QUZVU2.js";
6
- import "./chunk-DWJPPEMC.js";
4
+ } from "./chunk-AA5EWWYV.js";
5
+ import "./chunk-PWMMXRMC.js";
6
+ import "./chunk-JTKR7ZWP.js";
7
7
  import "./chunk-3CJHBJXA.js";
8
8
  export {
9
9
  Chart
@@ -4,7 +4,7 @@ import {
4
4
  baseOption,
5
5
  tooltipHtml,
6
6
  valueAxis
7
- } from "./chunk-I5QUZVU2.js";
7
+ } from "./chunk-PWMMXRMC.js";
8
8
  import {
9
9
  read
10
10
  } from "./chunk-W5FX4TU3.js";
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  Legend,
16
16
  useSettings
17
- } from "./chunk-DWJPPEMC.js";
17
+ } from "./chunk-JTKR7ZWP.js";
18
18
  import {
19
19
  fill
20
20
  } from "./chunk-3CJHBJXA.js";
@@ -130,4 +130,4 @@ export {
130
130
  correlation,
131
131
  ScatterChart
132
132
  };
133
- //# sourceMappingURL=chunk-EK3Z647J.js.map
133
+ //# sourceMappingURL=chunk-4LBXEAGC.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  EChartHost,
4
4
  baseOption
5
- } from "./chunk-I5QUZVU2.js";
5
+ } from "./chunk-PWMMXRMC.js";
6
6
 
7
7
  // src/chart/chart.tsx
8
8
  import { useCallback } from "react";
@@ -35,4 +35,4 @@ function Chart({ option, modules = fullEngine, summaryText, table, items, onItem
35
35
  export {
36
36
  Chart
37
37
  };
38
- //# sourceMappingURL=chunk-AHQXJSAQ.js.map
38
+ //# sourceMappingURL=chunk-AA5EWWYV.js.map
@@ -20,7 +20,7 @@ import {
20
20
  ChartFrame,
21
21
  colorOf,
22
22
  useSettings
23
- } from "./chunk-DWJPPEMC.js";
23
+ } from "./chunk-JTKR7ZWP.js";
24
24
 
25
25
  // src/sparkline/sparkline.tsx
26
26
  import { useMemo } from "react";
@@ -85,4 +85,4 @@ function Sparkline(props) {
85
85
  export {
86
86
  Sparkline
87
87
  };
88
- //# sourceMappingURL=chunk-VKO2OYYM.js.map
88
+ //# sourceMappingURL=chunk-ARARFMNE.js.map
@@ -17,7 +17,7 @@ import {
17
17
  stepColor,
18
18
  useMounted,
19
19
  useSettings
20
- } from "./chunk-DWJPPEMC.js";
20
+ } from "./chunk-JTKR7ZWP.js";
21
21
  import {
22
22
  capitalize,
23
23
  fill
@@ -175,4 +175,4 @@ function GeoMap(props) {
175
175
  export {
176
176
  GeoMap
177
177
  };
178
- //# sourceMappingURL=chunk-WBH2QU77.js.map
178
+ //# sourceMappingURL=chunk-BV4DBGN7.js.map
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Cartesian
4
- } from "./chunk-UNK4MJVG.js";
4
+ } from "./chunk-CVWSMUUB.js";
5
5
 
6
6
  // src/line/line-chart.tsx
7
7
  import { jsx } from "react/jsx-runtime";
@@ -16,4 +16,4 @@ export {
16
16
  LineChart,
17
17
  AreaChart
18
18
  };
19
- //# sourceMappingURL=chunk-BZ5CQFPH.js.map
19
+ //# sourceMappingURL=chunk-C4MFZLJM.js.map
@@ -3,7 +3,7 @@ import {
3
3
  EChartHost,
4
4
  baseOption,
5
5
  tooltipHtml
6
- } from "./chunk-I5QUZVU2.js";
6
+ } from "./chunk-PWMMXRMC.js";
7
7
  import {
8
8
  read
9
9
  } from "./chunk-W5FX4TU3.js";
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-XLLYNNC6.js";
14
14
  import {
15
15
  useSettings
16
- } from "./chunk-DWJPPEMC.js";
16
+ } from "./chunk-JTKR7ZWP.js";
17
17
  import {
18
18
  capitalize,
19
19
  fill
@@ -113,4 +113,4 @@ function Funnel(props) {
113
113
  export {
114
114
  Funnel
115
115
  };
116
- //# sourceMappingURL=chunk-XAJ3KCC4.js.map
116
+ //# sourceMappingURL=chunk-CSSZLFLO.js.map
@@ -9,18 +9,18 @@ import {
9
9
  import {
10
10
  describeSeries
11
11
  } from "./chunk-ANUCSRUN.js";
12
- import {
13
- areaPath,
14
- barPath,
15
- linePath,
16
- segments
17
- } from "./chunk-OB5EFDDH.js";
18
12
  import {
19
13
  extent,
20
14
  normalizeSeries,
21
15
  stack,
22
16
  tabulate
23
17
  } from "./chunk-W5FX4TU3.js";
18
+ import {
19
+ areaPath,
20
+ barPath,
21
+ linePath,
22
+ segments
23
+ } from "./chunk-OB5EFDDH.js";
24
24
  import {
25
25
  categoryFormatter,
26
26
  shareFormatter,
@@ -33,7 +33,7 @@ import {
33
33
  colorOf,
34
34
  cx,
35
35
  useSettings
36
- } from "./chunk-DWJPPEMC.js";
36
+ } from "./chunk-JTKR7ZWP.js";
37
37
  import {
38
38
  fill
39
39
  } from "./chunk-3CJHBJXA.js";
@@ -375,4 +375,4 @@ function sameCategory(a, b) {
375
375
  export {
376
376
  Cartesian
377
377
  };
378
- //# sourceMappingURL=chunk-UNK4MJVG.js.map
378
+ //# sourceMappingURL=chunk-CVWSMUUB.js.map
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ //# sourceMappingURL=chunk-E5DKBSWX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import {
3
+ Gauge
4
+ } from "./chunk-EQLC2QVN.js";
5
+ import {
6
+ GOAL_LABELS,
7
+ fillIn,
8
+ roundMoney
9
+ } from "./chunk-WNUFGMS7.js";
10
+ import {
11
+ valueFormatter
12
+ } from "./chunk-XLLYNNC6.js";
13
+ import {
14
+ useSettings
15
+ } from "./chunk-JTKR7ZWP.js";
16
+
17
+ // src/goal/goal-progress.tsx
18
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
19
+ function GoalProgress({ raised, goal, currency, supporters, timeLeft, labels: given, description, ...props }) {
20
+ const words = { ...GOAL_LABELS, ...given };
21
+ const { locale } = useSettings(props);
22
+ const format = roundMoney(currency);
23
+ const reached = goal > 0 && raised >= goal;
24
+ const facts = [
25
+ supporters != null ? fillIn(words.supporters, { count: valueFormatter("integer", locale)(supporters) }) : null,
26
+ reached ? words.reached : null
27
+ ].filter(Boolean);
28
+ const line = facts.length > 0 || timeLeft ? /* @__PURE__ */ jsxs(Fragment, { children: [
29
+ facts.join(" \xB7 "),
30
+ facts.length > 0 && timeLeft ? " \xB7 " : null,
31
+ timeLeft ? /* @__PURE__ */ jsx(Fragment, { children: typeof timeLeft === "string" ? fillIn(words.left, { time: timeLeft }) : timeLeft }) : null
32
+ ] }) : null;
33
+ return /* @__PURE__ */ jsx(
34
+ Gauge,
35
+ {
36
+ ...props,
37
+ value: raised,
38
+ max: goal,
39
+ format,
40
+ caption: fillIn(words.raised, { goal: valueFormatter(format, locale)(goal) }),
41
+ tone: reached ? "success" : "accent",
42
+ description: description || line ? /* @__PURE__ */ jsxs(Fragment, { children: [
43
+ description,
44
+ description && line ? " \xB7 " : null,
45
+ line
46
+ ] }) : void 0
47
+ }
48
+ );
49
+ }
50
+
51
+ export {
52
+ GoalProgress
53
+ };
54
+ //# sourceMappingURL=chunk-EEP7PS2L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/goal/goal-progress.tsx"],"sourcesContent":["\"use client\";\n// A pot towards its goal (an Orochia challenge, a crowdfunded request): the amount raised in money minor units on a\n// gauge whose arc fills towards the goal, “raised of $500” under it, the supporters and the time left beside the\n// title, the success tone once the goal is reached (and the amount past it still written). A Gauge preset.\nimport type { ReactNode } from \"react\";\n\nimport { valueFormatter } from \"../core/format\";\nimport { Gauge, type GaugeProps } from \"../gauge/gauge\";\nimport { GOAL_LABELS, type GoalLabels } from \"../needs/labels\";\nimport { fillIn, roundMoney } from \"../needs/model\";\nimport { useSettings } from \"../web/frame\";\n\nexport interface GoalProgressProps extends Omit<GaugeProps, \"value\" | \"min\" | \"max\" | \"format\" | \"caption\" | \"target\" | \"zones\" | \"tone\" | \"labels\"> {\n /** The amount raised, in **minor units** (cents). */\n raised: number;\n /** The goal, in minor units. */\n goal: number;\n /** The ISO 4217 currency. */\n currency: string;\n /** How many people chipped in. */\n supporters?: number;\n /** The time left, written by the app (a `Countdown`, “2 days”). */\n timeLeft?: ReactNode;\n /** The words, passed translated; English by default. */\n labels?: Partial<GoalLabels>;\n}\n\n/** A pot towards its goal, in money: the arc fills, the words say how much of what, and who chipped in. */\nexport function GoalProgress({ raised, goal, currency, supporters, timeLeft, labels: given, description, ...props }: GoalProgressProps) {\n const words = { ...GOAL_LABELS, ...given };\n const { locale } = useSettings(props);\n const format = roundMoney(currency);\n const reached = goal > 0 && raised >= goal;\n const facts = [\n supporters != null ? fillIn(words.supporters, { count: valueFormatter(\"integer\", locale)(supporters) }) : null,\n reached ? words.reached : null,\n ].filter(Boolean);\n const line =\n facts.length > 0 || timeLeft ? (\n <>\n {facts.join(\" · \")}\n {facts.length > 0 && timeLeft ? \" · \" : null}\n {timeLeft ? <>{typeof timeLeft === \"string\" ? fillIn(words.left, { time: timeLeft }) : timeLeft}</> : null}\n </>\n ) : null;\n return (\n <Gauge\n {...props}\n value={raised}\n max={goal}\n format={format}\n caption={fillIn(words.raised, { goal: valueFormatter(format, locale)(goal) })}\n tone={reached ? \"success\" : \"accent\"}\n description={\n description || line ? (\n <>\n {description}\n {description && line ? \" · \" : null}\n {line}\n </>\n ) : undefined\n }\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuCM,SAGc,eAHd;AAXC,SAAS,aAAa,EAAE,QAAQ,MAAM,UAAU,YAAY,UAAU,QAAQ,OAAO,aAAa,GAAG,MAAM,GAAsB;AACtI,QAAM,QAAQ,EAAE,GAAG,aAAa,GAAG,MAAM;AACzC,QAAM,EAAE,OAAO,IAAI,YAAY,KAAK;AACpC,QAAM,SAAS,WAAW,QAAQ;AAClC,QAAM,UAAU,OAAO,KAAK,UAAU;AACtC,QAAM,QAAQ;AAAA,IACZ,cAAc,OAAO,OAAO,MAAM,YAAY,EAAE,OAAO,eAAe,WAAW,MAAM,EAAE,UAAU,EAAE,CAAC,IAAI;AAAA,IAC1G,UAAU,MAAM,UAAU;AAAA,EAC5B,EAAE,OAAO,OAAO;AAChB,QAAM,OACJ,MAAM,SAAS,KAAK,WAClB,iCACG;AAAA,UAAM,KAAK,QAAK;AAAA,IAChB,MAAM,SAAS,KAAK,WAAW,WAAQ;AAAA,IACvC,WAAW,gCAAG,iBAAO,aAAa,WAAW,OAAO,MAAM,MAAM,EAAE,MAAM,SAAS,CAAC,IAAI,UAAS,IAAM;AAAA,KACxG,IACE;AACN,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,OAAO;AAAA,MACP,KAAK;AAAA,MACL;AAAA,MACA,SAAS,OAAO,MAAM,QAAQ,EAAE,MAAM,eAAe,QAAQ,MAAM,EAAE,IAAI,EAAE,CAAC;AAAA,MAC5E,MAAM,UAAU,YAAY;AAAA,MAC5B,aACE,eAAe,OACb,iCACG;AAAA;AAAA,QACA,eAAe,OAAO,WAAQ;AAAA,QAC9B;AAAA,SACH,IACE;AAAA;AAAA,EAER;AAEJ;","names":[]}
@@ -10,7 +10,7 @@ import {
10
10
  ChartFrame,
11
11
  colorOf,
12
12
  useSettings
13
- } from "./chunk-DWJPPEMC.js";
13
+ } from "./chunk-JTKR7ZWP.js";
14
14
  import {
15
15
  fill
16
16
  } from "./chunk-3CJHBJXA.js";
@@ -70,4 +70,4 @@ function Gauge(props) {
70
70
  export {
71
71
  Gauge
72
72
  };
73
- //# sourceMappingURL=chunk-DZB6HEVO.js.map
73
+ //# sourceMappingURL=chunk-EQLC2QVN.js.map
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ //# sourceMappingURL=chunk-FINOPIDN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ //# sourceMappingURL=chunk-G2KF2WL4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -13,7 +13,7 @@ import {
13
13
  useMounted,
14
14
  useReducedMotion,
15
15
  useSettings
16
- } from "./chunk-DWJPPEMC.js";
16
+ } from "./chunk-JTKR7ZWP.js";
17
17
  import {
18
18
  fill
19
19
  } from "./chunk-3CJHBJXA.js";
@@ -202,4 +202,4 @@ function Globe3D(props) {
202
202
  export {
203
203
  Globe3D
204
204
  };
205
- //# sourceMappingURL=chunk-PTSB3H5Q.js.map
205
+ //# sourceMappingURL=chunk-I3D7KUGN.js.map
@@ -0,0 +1,76 @@
1
+ "use client";
2
+ import {
3
+ BarChart
4
+ } from "./chunk-WVTIKOII.js";
5
+ import {
6
+ Kpi
7
+ } from "./chunk-WBHFVBSK.js";
8
+ import {
9
+ LATENCY_LABELS,
10
+ fillIn,
11
+ formatDuration,
12
+ numberOf
13
+ } from "./chunk-WNUFGMS7.js";
14
+ import {
15
+ useSettings
16
+ } from "./chunk-JTKR7ZWP.js";
17
+
18
+ // src/latency/latency-chart.tsx
19
+ import { useMemo } from "react";
20
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
21
+ function LatencyChart({
22
+ x = "name",
23
+ p50 = "p50",
24
+ p95 = "p95",
25
+ objective,
26
+ vertical,
27
+ hideSummary,
28
+ labels: given,
29
+ description,
30
+ data,
31
+ ...props
32
+ }) {
33
+ const words = { ...LATENCY_LABELS, ...given };
34
+ const { locale } = useSettings(props);
35
+ const series = useMemo(
36
+ () => [{ key: p50, label: words.p50, color: "neutral" }, ...p95 ? [{ key: p95, label: words.p95, color: 1 }] : []],
37
+ [p50, p95, words.p50, words.p95]
38
+ );
39
+ const tail = p95 ?? p50;
40
+ const measured = data.map((row, i) => ({ row, i, value: numberOf(row, tail, i) })).filter((m) => m.value != null);
41
+ const slowest = measured.reduce((a, m) => !a || (m.value ?? 0) > (a.value ?? 0) ? m : a, null);
42
+ const over = objective ? measured.filter((m) => (m.value ?? 0) > objective.value).length : 0;
43
+ const nameOf = (row, i) => String(typeof x === "function" ? x(row, i) : row[x]);
44
+ const summary = hideSummary || !slowest ? null : /* @__PURE__ */ jsx(
45
+ Kpi,
46
+ {
47
+ value: formatDuration(slowest.value ?? 0, locale),
48
+ label: fillIn(words.slowest, { name: nameOf(slowest.row, slowest.i) }),
49
+ delta: objective ? over > 0 ? fillIn(words.over, { count: over }) : words.within : null,
50
+ direction: objective ? over > 0 ? "up" : "flat" : null,
51
+ tone: over > 0 ? "danger" : "success"
52
+ }
53
+ );
54
+ return /* @__PURE__ */ jsx(
55
+ BarChart,
56
+ {
57
+ ...props,
58
+ data,
59
+ x,
60
+ series,
61
+ format: (value, l) => formatDuration(value, l),
62
+ horizontal: !vertical,
63
+ thresholds: objective ? [{ ...objective, tone: "danger" }] : void 0,
64
+ description: description || summary ? /* @__PURE__ */ jsxs(Fragment, { children: [
65
+ description,
66
+ description && summary ? /* @__PURE__ */ jsx("br", {}) : null,
67
+ summary
68
+ ] }) : void 0
69
+ }
70
+ );
71
+ }
72
+
73
+ export {
74
+ LatencyChart
75
+ };
76
+ //# sourceMappingURL=chunk-IKQV3NSL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/latency/latency-chart.tsx"],"sourcesContent":["\"use client\";\n// Latency per capability, model or kind of job (the console's supervision, Orazaka's \"time to result\"): the median\n// and the 95th percentile side by side in horizontal bars, durations written in the unit that fits (ms, s, min), the\n// service objective as a line, the slowest p95 and how many go past the objective written above.\nimport { useMemo } from \"react\";\n\nimport { BarChart } from \"../bar/bar-chart\";\nimport type { CartesianProps } from \"../cartesian/cartesian\";\nimport type { Accessor, Datum, SeriesSpec } from \"../core/types\";\nimport { Kpi } from \"../needs/kpi\";\nimport { LATENCY_LABELS, type LatencyLabels } from \"../needs/labels\";\nimport { fillIn, formatDuration, numberOf } from \"../needs/model\";\nimport { useSettings } from \"../web/frame\";\n\nexport interface LatencyChartProps<T extends Datum>\n extends Omit<CartesianProps<T>, \"y\" | \"yLabel\" | \"series\" | \"format\" | \"x\" | \"xFormat\" | \"thresholds\" | \"labels\"> {\n /** The field (or function) naming what is measured (a capability, a model). Default `\"name\"`. */\n x?: Accessor<T, unknown>;\n /** The median, in milliseconds. Default `\"p50\"`. */\n p50?: Accessor<T, number | null | undefined>;\n /** The 95th percentile, in milliseconds. Default `\"p95\"`; `null` to draw the median alone. */\n p95?: Accessor<T, number | null | undefined> | null;\n /** The service objective, in milliseconds: a line, and the count of what goes past it (by p95). */\n objective?: { readonly value: number; readonly label: string };\n /** Vertical bars instead of horizontal ones (few, short names). */\n vertical?: boolean;\n /** Hide the slowest p95 and the count over the objective. */\n hideSummary?: boolean;\n /** The words, passed translated; English by default. */\n labels?: Partial<LatencyLabels>;\n}\n\n/** Median and p95 latency per item, durations in the unit that fits, against a service objective. */\nexport function LatencyChart<T extends Datum>({\n x = \"name\" as Accessor<T, unknown>,\n p50 = \"p50\" as Accessor<T, number | null | undefined>,\n p95 = \"p95\" as Accessor<T, number | null | undefined>,\n objective,\n vertical,\n hideSummary,\n labels: given,\n description,\n data,\n ...props\n}: LatencyChartProps<T>) {\n const words = { ...LATENCY_LABELS, ...given };\n const { locale } = useSettings(props as CartesianProps<T>);\n const series = useMemo<SeriesSpec<T>[]>(\n () => [{ key: p50, label: words.p50, color: \"neutral\" }, ...(p95 ? [{ key: p95, label: words.p95, color: 1 as const }] : [])],\n [p50, p95, words.p50, words.p95],\n );\n const tail = p95 ?? p50;\n const measured = data.map((row, i) => ({ row, i, value: numberOf(row, tail, i) })).filter((m) => m.value != null);\n const slowest = measured.reduce<(typeof measured)[number] | null>((a, m) => (!a || (m.value ?? 0) > (a.value ?? 0) ? m : a), null);\n const over = objective ? measured.filter((m) => (m.value ?? 0) > objective.value).length : 0;\n const nameOf = (row: T, i: number) => String(typeof x === \"function\" ? x(row, i) : (row as Record<string, unknown>)[x]);\n const summary =\n hideSummary || !slowest ? null : (\n <Kpi\n value={formatDuration(slowest.value ?? 0, locale)}\n label={fillIn(words.slowest, { name: nameOf(slowest.row, slowest.i) })}\n delta={objective ? (over > 0 ? fillIn(words.over, { count: over }) : words.within) : null}\n direction={objective ? (over > 0 ? \"up\" : \"flat\") : null}\n tone={over > 0 ? \"danger\" : \"success\"}\n />\n );\n return (\n <BarChart\n {...props}\n data={data}\n x={x}\n series={series}\n format={(value, l) => formatDuration(value, l)}\n horizontal={!vertical}\n thresholds={objective ? [{ ...objective, tone: \"danger\" }] : undefined}\n description={\n description || summary ? (\n <>\n {description}\n {description && summary ? <br /> : null}\n {summary}\n </>\n ) : undefined\n }\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAIA,SAAS,eAAe;AAsDlB,SAmBI,UAnBJ,KAmBI,YAnBJ;AAzBC,SAAS,aAA8B;AAAA,EAC5C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAyB;AACvB,QAAM,QAAQ,EAAE,GAAG,gBAAgB,GAAG,MAAM;AAC5C,QAAM,EAAE,OAAO,IAAI,YAAY,KAA0B;AACzD,QAAM,SAAS;AAAA,IACb,MAAM,CAAC,EAAE,KAAK,KAAK,OAAO,MAAM,KAAK,OAAO,UAAU,GAAG,GAAI,MAAM,CAAC,EAAE,KAAK,KAAK,OAAO,MAAM,KAAK,OAAO,EAAW,CAAC,IAAI,CAAC,CAAE;AAAA,IAC5H,CAAC,KAAK,KAAK,MAAM,KAAK,MAAM,GAAG;AAAA,EACjC;AACA,QAAM,OAAO,OAAO;AACpB,QAAM,WAAW,KAAK,IAAI,CAAC,KAAK,OAAO,EAAE,KAAK,GAAG,OAAO,SAAS,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAChH,QAAM,UAAU,SAAS,OAAyC,CAAC,GAAG,MAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,KAAK,IAAI,GAAI,IAAI;AACjI,QAAM,OAAO,YAAY,SAAS,OAAO,CAAC,OAAO,EAAE,SAAS,KAAK,UAAU,KAAK,EAAE,SAAS;AAC3F,QAAM,SAAS,CAAC,KAAQ,MAAc,OAAO,OAAO,MAAM,aAAa,EAAE,KAAK,CAAC,IAAK,IAAgC,CAAC,CAAC;AACtH,QAAM,UACJ,eAAe,CAAC,UAAU,OACxB;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,eAAe,QAAQ,SAAS,GAAG,MAAM;AAAA,MAChD,OAAO,OAAO,MAAM,SAAS,EAAE,MAAM,OAAO,QAAQ,KAAK,QAAQ,CAAC,EAAE,CAAC;AAAA,MACrE,OAAO,YAAa,OAAO,IAAI,OAAO,MAAM,MAAM,EAAE,OAAO,KAAK,CAAC,IAAI,MAAM,SAAU;AAAA,MACrF,WAAW,YAAa,OAAO,IAAI,OAAO,SAAU;AAAA,MACpD,MAAM,OAAO,IAAI,WAAW;AAAA;AAAA,EAC9B;AAEJ,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,CAAC,OAAO,MAAM,eAAe,OAAO,CAAC;AAAA,MAC7C,YAAY,CAAC;AAAA,MACb,YAAY,YAAY,CAAC,EAAE,GAAG,WAAW,MAAM,SAAS,CAAC,IAAI;AAAA,MAC7D,aACE,eAAe,UACb,iCACG;AAAA;AAAA,QACA,eAAe,UAAU,oBAAC,QAAG,IAAK;AAAA,QAClC;AAAA,SACH,IACE;AAAA;AAAA,EAER;AAEJ;","names":[]}
@@ -140,65 +140,6 @@ function RampLegend({ min, max, steps, write }) {
140
140
  ] });
141
141
  }
142
142
 
143
- // src/web/frame.tsx
144
- import { useCallback, useId, useMemo, useRef, useState as useState2 } from "react";
145
-
146
- // src/web/export.ts
147
- function toCsv(rows) {
148
- const cell = (value) => /[",\n;]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value;
149
- return rows.map((row) => row.map(cell).join(",")).join("\n");
150
- }
151
- function fileName(title, extension) {
152
- const base = (title ?? "chart").normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "chart";
153
- return `${base}.${extension}`;
154
- }
155
- function download(name, content) {
156
- const url = typeof content === "string" ? content : URL.createObjectURL(content);
157
- const link = document.createElement("a");
158
- link.href = url;
159
- link.download = name;
160
- link.click();
161
- if (typeof content !== "string") setTimeout(() => URL.revokeObjectURL(url), 1e3);
162
- }
163
- var PROPS = ["fill", "stroke", "stroke-width", "stroke-dasharray", "opacity", "fill-opacity", "font-size", "font-weight", "font-family"];
164
- function serializeSvg(svg, background) {
165
- const clone = svg.cloneNode(true);
166
- const source = [svg, ...svg.querySelectorAll("*")];
167
- const target = [clone, ...clone.querySelectorAll("*")];
168
- source.forEach((el, i) => {
169
- const style = getComputedStyle(el);
170
- const out = target[i];
171
- for (const prop of PROPS) {
172
- const value = style.getPropertyValue(prop);
173
- if (value) out.style.setProperty(prop, value);
174
- }
175
- out.style.removeProperty("stroke-dasharray");
176
- if (el.getAttribute("stroke-dasharray")) out.style.setProperty("stroke-dasharray", el.getAttribute("stroke-dasharray"));
177
- });
178
- clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
179
- if (background) clone.style.setProperty("background", background);
180
- return new XMLSerializer().serializeToString(clone);
181
- }
182
- function svgToPng(markup, width, height, background, scale = 2) {
183
- return new Promise((resolve, reject) => {
184
- const image = new Image();
185
- image.onload = () => {
186
- const canvas = document.createElement("canvas");
187
- canvas.width = width * scale;
188
- canvas.height = height * scale;
189
- const context = canvas.getContext("2d");
190
- if (!context) return reject(new Error("No 2D canvas"));
191
- context.fillStyle = background;
192
- context.fillRect(0, 0, canvas.width, canvas.height);
193
- context.drawImage(image, 0, 0, canvas.width, canvas.height);
194
- resolve(canvas.toDataURL("image/png"));
195
- return void 0;
196
- };
197
- image.onerror = () => reject(new Error("The SVG could not be rasterised"));
198
- image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(markup)}`;
199
- });
200
- }
201
-
202
143
  // src/web/styles.tsx
203
144
  import { jsx as jsx2 } from "react/jsx-runtime";
204
145
  var slots = (brand) => ORDERS[brand].map((hue, i) => `--kzc-${i + 1}:light-dark(${HUES[hue].light},${HUES[hue].dark});`).join("");
@@ -259,6 +200,16 @@ ${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)
259
200
  .kzc-live{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}
260
201
  .kzc-host{position:absolute;inset:0}
261
202
  .kzc-host>div{border-radius:inherit}
203
+ .kzc-kpi{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px;margin-top:4px}
204
+ .kzc-kpi-value{font-family:var(--kz-font-display,inherit);font-size:24px;line-height:30px;font-weight:800;letter-spacing:-.01em;color:var(--kzc-text)}
205
+ .kzc-kpi-label{font-size:13px;color:var(--kzc-text-2)}
206
+ .kzc-kpi-delta{display:inline-flex;align-items:center;gap:4px;font-size:13px;font-weight:600;color:var(--kzc-text)}
207
+ .kzc-kpi-delta svg{width:12px;height:12px;flex:none;color:var(--kzc-tone)}
208
+ .kzc-meter{position:relative;height:10px;border-radius:999px;background:var(--kz-surface-3);overflow:hidden;--kzc-tone:var(--kz-accent)}
209
+ .kzc-meter>i{position:absolute;inset:0 auto 0 0;border-radius:inherit;background:var(--kzc-tone);transition:width .6s var(--kz-ease,ease-out)}
210
+ .kzc-meter[data-tone=warning]{--kzc-tone:var(--kz-warning)}.kzc-meter[data-tone=danger]{--kzc-tone:var(--kz-danger)}
211
+ .kzc-row{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:4px 12px;margin:0;font-size:12px;line-height:18px;color:var(--kzc-text-2)}
212
+ .kzc-row b{font-weight:600;color:var(--kzc-text)}
262
213
  @media (prefers-reduced-motion:no-preference){
263
214
  .kzc-skeleton i{animation:kzc-pulse 1.6s ease-in-out infinite}
264
215
  .kzc[data-inview] .kzc-enter-line{stroke-dasharray:1;stroke-dashoffset:1;animation:kzc-draw .9s var(--kz-ease,ease-out) forwards}
@@ -270,6 +221,8 @@ ${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)
270
221
  .kzc[data-inview] .kzc-enter-pop{opacity:0;transform:scale(.92);transform-box:view-box;transform-origin:center;animation:kzc-pop .6s var(--kz-ease,ease-out) forwards}
271
222
  .kzc:not([data-inview]) .kzc-enter-line,.kzc:not([data-inview]) .kzc-enter-fade,.kzc:not([data-inview]) .kzc-enter-grow,.kzc:not([data-inview]) .kzc-enter-growx,.kzc:not([data-inview]) .kzc-enter-pop{visibility:hidden}
272
223
  .kzc[data-live] *{animation:none!important}
224
+ .kzc[data-live] .kzc-enter-line{stroke-dasharray:none;stroke-dashoffset:0}
225
+ .kzc[data-live] :is(.kzc-enter-fade,.kzc-enter-grow,.kzc-enter-growx,.kzc-enter-pop){opacity:1;transform:none;visibility:visible}
273
226
  }
274
227
  @keyframes kzc-draw{to{stroke-dashoffset:0}}
275
228
  @keyframes kzc-fade{to{opacity:1}}
@@ -283,6 +236,65 @@ function ChartStyles() {
283
236
  return /* @__PURE__ */ jsx2("style", { href: "krizaka-charts", precedence: "default", children: CSS });
284
237
  }
285
238
 
239
+ // src/web/frame.tsx
240
+ import { useCallback, useId, useMemo, useRef, useState as useState2 } from "react";
241
+
242
+ // src/web/export.ts
243
+ function toCsv(rows) {
244
+ const cell = (value) => /[",\n;]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value;
245
+ return rows.map((row) => row.map(cell).join(",")).join("\n");
246
+ }
247
+ function fileName(title, extension) {
248
+ const base = (title ?? "chart").normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "chart";
249
+ return `${base}.${extension}`;
250
+ }
251
+ function download(name, content) {
252
+ const url = typeof content === "string" ? content : URL.createObjectURL(content);
253
+ const link = document.createElement("a");
254
+ link.href = url;
255
+ link.download = name;
256
+ link.click();
257
+ if (typeof content !== "string") setTimeout(() => URL.revokeObjectURL(url), 1e3);
258
+ }
259
+ var PROPS = ["fill", "stroke", "stroke-width", "stroke-dasharray", "opacity", "fill-opacity", "font-size", "font-weight", "font-family"];
260
+ function serializeSvg(svg, background) {
261
+ const clone = svg.cloneNode(true);
262
+ const source = [svg, ...svg.querySelectorAll("*")];
263
+ const target = [clone, ...clone.querySelectorAll("*")];
264
+ source.forEach((el, i) => {
265
+ const style = getComputedStyle(el);
266
+ const out = target[i];
267
+ for (const prop of PROPS) {
268
+ const value = style.getPropertyValue(prop);
269
+ if (value) out.style.setProperty(prop, value);
270
+ }
271
+ out.style.removeProperty("stroke-dasharray");
272
+ if (el.getAttribute("stroke-dasharray")) out.style.setProperty("stroke-dasharray", el.getAttribute("stroke-dasharray"));
273
+ });
274
+ clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
275
+ if (background) clone.style.setProperty("background", background);
276
+ return new XMLSerializer().serializeToString(clone);
277
+ }
278
+ function svgToPng(markup, width, height, background, scale = 2) {
279
+ return new Promise((resolve, reject) => {
280
+ const image = new Image();
281
+ image.onload = () => {
282
+ const canvas = document.createElement("canvas");
283
+ canvas.width = width * scale;
284
+ canvas.height = height * scale;
285
+ const context = canvas.getContext("2d");
286
+ if (!context) return reject(new Error("No 2D canvas"));
287
+ context.fillStyle = background;
288
+ context.fillRect(0, 0, canvas.width, canvas.height);
289
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
290
+ resolve(canvas.toDataURL("image/png"));
291
+ return void 0;
292
+ };
293
+ image.onerror = () => reject(new Error("The SVG could not be rasterised"));
294
+ image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(markup)}`;
295
+ });
296
+ }
297
+
286
298
  // src/web/frame.tsx
287
299
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
288
300
  function useSettings(frame) {
@@ -448,8 +460,9 @@ export {
448
460
  Tooltip,
449
461
  stepColor,
450
462
  RampLegend,
463
+ ChartStyles,
451
464
  useSettings,
452
465
  ChartFrame,
453
466
  resolveColor
454
467
  };
455
- //# sourceMappingURL=chunk-DWJPPEMC.js.map
468
+ //# sourceMappingURL=chunk-JTKR7ZWP.js.map