@crewlethq/ui 0.4.3 → 0.5.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 (237) hide show
  1. package/README.md +888 -24
  2. package/dist/Accordion/index.js +2 -2
  3. package/dist/AddPill/index.js +1 -1
  4. package/dist/{AddPill-DFWXYLIQ.css → AddPill-IJQYCY6C.css} +9 -0
  5. package/dist/AppShell/AppShell.d.ts +26 -5
  6. package/dist/AppShell/index.js +3 -3
  7. package/dist/{AppShell-NVE6LHNI.css → AppShell-XARELGIH.css} +178 -25
  8. package/dist/Avatar/Avatar.d.ts +85 -40
  9. package/dist/Avatar/AvatarStack.d.ts +76 -0
  10. package/dist/Avatar/index.d.ts +5 -2
  11. package/dist/Avatar/index.js +1 -1
  12. package/dist/Avatar-XID7Z74C.css +200 -0
  13. package/dist/AvatarStack-GEJBNV7E.css +72 -0
  14. package/dist/BrandLockup/index.js +1 -1
  15. package/dist/{BrandLockup-6ISDEHPJ.css → BrandLockup-JKGXFCZF.css} +25 -19
  16. package/dist/Button/Button.d.ts +7 -2
  17. package/dist/Button/index.js +1 -1
  18. package/dist/{Button-D4J6B4MA.css → Button-X4B2TJAQ.css} +50 -19
  19. package/dist/Callout/index.js +1 -1
  20. package/dist/Canvas/index.js +4 -4
  21. package/dist/Card/Card.d.ts +9 -5
  22. package/dist/Card/index.js +1 -1
  23. package/dist/{Card-RLR254LD.css → Card-GLP7SUV6.css} +25 -18
  24. package/dist/Charts/BarList.d.ts +18 -1
  25. package/dist/Charts/ChartTooltip.d.ts +68 -0
  26. package/dist/Charts/StackedBar.d.ts +25 -7
  27. package/dist/Charts/StackedColumns.d.ts +112 -0
  28. package/dist/Charts/TimeSeries.d.ts +33 -2
  29. package/dist/Charts/dataColor.d.ts +22 -14
  30. package/dist/Charts/index.d.ts +6 -0
  31. package/dist/Charts/index.js +1 -1
  32. package/dist/Charts/useChartHover.d.ts +56 -0
  33. package/dist/Charts-B3YEF7R4.css +742 -0
  34. package/dist/Checkbox/index.js +1 -1
  35. package/dist/{Checkbox-VGW26YLQ.css → Checkbox-BOXQ747I.css} +2 -2
  36. package/dist/CodeBlock/index.js +4 -4
  37. package/dist/Combobox/index.js +5 -5
  38. package/dist/CommandPalette/CommandPalette.d.ts +97 -6
  39. package/dist/CommandPalette/index.d.ts +1 -1
  40. package/dist/CommandPalette/index.js +9 -7
  41. package/dist/CommandPalette-C5AMKGN2.css +259 -0
  42. package/dist/Copyable/index.js +3 -3
  43. package/dist/DataTable/index.js +7 -7
  44. package/dist/{DataTable-ITNACQ2X.css → DataTable-OLHPF7D4.css} +44 -43
  45. package/dist/DataView/index.js +14 -14
  46. package/dist/{DataView-256YF32J.css → DataView-N6JX464S.css} +5 -4
  47. package/dist/DateTimePicker/index.js +5 -5
  48. package/dist/DiffList/index.js +1 -1
  49. package/dist/Disclosure/index.js +2 -2
  50. package/dist/EntityChip/EntityChip.d.ts +9 -12
  51. package/dist/EntityChip/index.d.ts +1 -1
  52. package/dist/EntityChip/index.js +2 -2
  53. package/dist/ErrorBoundary/index.js +2 -2
  54. package/dist/{ErrorBoundary-ME36CQTA.css → ErrorBoundary-U2PA3LY2.css} +4 -4
  55. package/dist/IconButton/index.js +1 -1
  56. package/dist/{IconButton-VQGNMJDI.css → IconButton-TVEUWK6L.css} +2 -2
  57. package/dist/ImageUpload/ImageUpload.d.ts +10 -7
  58. package/dist/ImageUpload/index.js +2 -2
  59. package/dist/{ImageUpload-HKFIZR6D.css → ImageUpload-YCHJMUGX.css} +24 -10
  60. package/dist/Input/index.js +2 -2
  61. package/dist/Kbd/Kbd.d.ts +14 -4
  62. package/dist/Kbd/index.js +1 -1
  63. package/dist/Kbd-JPLDVJIP.css +71 -0
  64. package/dist/Layer/index.js +1 -1
  65. package/dist/Link/index.js +1 -1
  66. package/dist/List/index.js +1 -1
  67. package/dist/{List-XTHESXLR.css → List-MYJIV6MP.css} +12 -2
  68. package/dist/ListInput/index.js +5 -5
  69. package/dist/Listbox/index.js +2 -2
  70. package/dist/Listbox/useListbox.d.ts +16 -0
  71. package/dist/Listbox/useOptionKeys.d.ts +12 -1
  72. package/dist/{Listbox-X2DOTSQA.css → Listbox-6WJNJQVQ.css} +60 -7
  73. package/dist/Menu/index.js +4 -4
  74. package/dist/{Menu-6DE7I66I.css → Menu-BT5PMFJI.css} +15 -0
  75. package/dist/Meter/Meter.d.ts +103 -16
  76. package/dist/Meter/index.d.ts +2 -2
  77. package/dist/Meter/index.js +1 -1
  78. package/dist/{Meter-SKOOXQBC.css → Meter-5VCSFMZW.css} +46 -7
  79. package/dist/Modal/index.js +4 -4
  80. package/dist/{Modal-XYQJ4BL6.css → Modal-JAYBS2KS.css} +13 -4
  81. package/dist/OrgLabel/OrgLabel.d.ts +60 -24
  82. package/dist/OrgLabel/index.d.ts +1 -1
  83. package/dist/OrgLabel/index.js +2 -1
  84. package/dist/{OrgLabel-D7U6QJZD.css → OrgLabel-CR233G34.css} +9 -18
  85. package/dist/OrgNode/index.js +3 -2
  86. package/dist/OrgTable/OrgTable.d.ts +2 -2
  87. package/dist/OrgTable/index.js +8 -7
  88. package/dist/Popover/index.js +2 -2
  89. package/dist/PricingCard/index.js +3 -3
  90. package/dist/{PricingCard-JFI7RYXP.css → PricingCard-7EFXRSD2.css} +4 -5
  91. package/dist/SearchTrigger/SearchTrigger.d.ts +23 -4
  92. package/dist/SearchTrigger/index.d.ts +1 -1
  93. package/dist/SearchTrigger/index.js +1 -1
  94. package/dist/SearchTrigger-Z5D4AAY7.css +112 -0
  95. package/dist/SegmentedControl/index.js +2 -2
  96. package/dist/SegmentedMeter/SegmentedMeter.d.ts +107 -0
  97. package/dist/SegmentedMeter/index.d.ts +3 -0
  98. package/dist/SegmentedMeter/index.js +2 -0
  99. package/dist/SegmentedMeter-KQNML2TW.css +109 -0
  100. package/dist/Select/index.js +3 -3
  101. package/dist/{Select-2X77FSWR.css → Select-E24U5LBC.css} +34 -0
  102. package/dist/Shortcut/index.js +2 -2
  103. package/dist/SidebarNav/SidebarNav.d.ts +85 -25
  104. package/dist/SidebarNav/index.d.ts +1 -1
  105. package/dist/SidebarNav/index.js +1 -1
  106. package/dist/SidebarNav-X5NLZNWA.css +424 -0
  107. package/dist/StatCard/StatCard.d.ts +59 -12
  108. package/dist/StatCard/index.d.ts +1 -1
  109. package/dist/StatCard/index.js +1 -1
  110. package/dist/StatCard-KPAFD4E2.css +204 -0
  111. package/dist/StatGroup/index.js +1 -1
  112. package/dist/{StatGroup-TGB6AEKM.css → StatGroup-HVG6O62W.css} +8 -9
  113. package/dist/StatusDot/StatusDot.d.ts +24 -6
  114. package/dist/StatusDot/index.js +1 -1
  115. package/dist/StatusDot-7OMCQCZF.css +186 -0
  116. package/dist/Stepper/Stepper.d.ts +78 -0
  117. package/dist/Stepper/index.d.ts +3 -0
  118. package/dist/Stepper/index.js +4 -0
  119. package/dist/Stepper-HW4JM3YH.css +176 -0
  120. package/dist/Table/index.js +1 -1
  121. package/dist/{Table-MDOLVUAW.css → Table-TGCS4C3F.css} +14 -4
  122. package/dist/Tabs/index.js +1 -1
  123. package/dist/{Tabs-VLICJFVB.css → Tabs-XCNPHA7B.css} +79 -27
  124. package/dist/Tag/Tag.d.ts +29 -22
  125. package/dist/Tag/index.js +2 -2
  126. package/dist/{Tag-VNZEYLB6.css → Tag-GBE7LQJP.css} +82 -83
  127. package/dist/TagsInput/index.js +6 -6
  128. package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +53 -21
  129. package/dist/ThemeSwitcher/index.d.ts +3 -3
  130. package/dist/ThemeSwitcher/index.js +4 -3
  131. package/dist/ThemeSwitcher/preferences.d.ts +19 -5
  132. package/dist/ThemeToggle/ThemeToggle.d.ts +40 -0
  133. package/dist/ThemeToggle/index.d.ts +2 -0
  134. package/dist/ThemeToggle/index.js +5 -0
  135. package/dist/TimeWindowPicker/index.js +8 -8
  136. package/dist/Toaster/index.js +2 -2
  137. package/dist/Toolbar/index.js +2 -2
  138. package/dist/{Toolbar-IP6LXN45.css → Toolbar-HUOSMNTH.css} +3 -1
  139. package/dist/Tooltip/index.js +2 -2
  140. package/dist/Tree/index.d.ts +2 -2
  141. package/dist/Tree/index.js +1 -1
  142. package/dist/Tree/layout.d.ts +103 -28
  143. package/dist/TreeCanvas/TreeCanvas.d.ts +60 -14
  144. package/dist/TreeCanvas/index.d.ts +1 -1
  145. package/dist/TreeCanvas/index.js +6 -6
  146. package/dist/TreeCanvas/motion.d.ts +3 -2
  147. package/dist/{TreeCanvas-WBNQPHC7.css → TreeCanvas-HVOV4SQN.css} +154 -30
  148. package/dist/TreeGrid/index.js +4 -4
  149. package/dist/{chunk-F6OE5FH3.js → chunk-2FPENTCF.js} +1 -1
  150. package/dist/chunk-4AK52VHB.js +88 -0
  151. package/dist/{chunk-7EM5T4ME.js → chunk-4IQD3HUQ.js} +2 -2
  152. package/dist/{chunk-YODNNSZL.js → chunk-4PZ6FJKW.js} +43 -13
  153. package/dist/{chunk-F27EPQ7D.js → chunk-4UQ7SMPK.js} +1 -1
  154. package/dist/chunk-5QWIJSQM.js +73 -0
  155. package/dist/{chunk-GTOUGQQK.js → chunk-6MU7HNB4.js} +13 -10
  156. package/dist/{chunk-S2XHHEW4.js → chunk-74KMX7YH.js} +4 -4
  157. package/dist/{chunk-WNI2WSJF.js → chunk-7KBNFFM3.js} +1 -1
  158. package/dist/{chunk-DD5BBGBE.js → chunk-AUS5FNQE.js} +9 -5
  159. package/dist/{chunk-CMEE37QJ.js → chunk-BMYPGGPV.js} +4 -4
  160. package/dist/{chunk-H4FBTAYS.js → chunk-BNCCEER3.js} +8 -8
  161. package/dist/chunk-C5WJUZVR.js +56 -0
  162. package/dist/{chunk-5WS6L6FA.js → chunk-CAIHUYXV.js} +9 -9
  163. package/dist/{chunk-XV6WRMBC.js → chunk-CQY5NTRS.js} +4 -1
  164. package/dist/{chunk-UOGSZKLT.js → chunk-D6EVJUGU.js} +2 -2
  165. package/dist/{chunk-6ZFVFA56.js → chunk-DHPUMOTX.js} +2 -2
  166. package/dist/{chunk-HZ5XZNPS.js → chunk-DS2C73RJ.js} +3 -3
  167. package/dist/{chunk-O6232G37.js → chunk-DSUY5F4E.js} +17 -5
  168. package/dist/{chunk-Q4ZPPART.js → chunk-EFYPAJT3.js} +3 -3
  169. package/dist/{chunk-WQX73TWF.js → chunk-ERVO6OUF.js} +18 -17
  170. package/dist/{chunk-BZYDZBAN.js → chunk-ETYEBKR4.js} +3 -3
  171. package/dist/{chunk-34VGEDVV.js → chunk-FD5UEN6X.js} +30 -30
  172. package/dist/{chunk-5SDBMKUO.js → chunk-FIFNP6PL.js} +3 -3
  173. package/dist/{chunk-7HPRF5XN.js → chunk-FUF52K7E.js} +98 -16
  174. package/dist/{chunk-5KPQ6D7N.js → chunk-FZVJDJFN.js} +2 -2
  175. package/dist/chunk-IA232OTU.js +156 -0
  176. package/dist/{chunk-2EOKFKHX.js → chunk-IG27QX7Q.js} +7 -7
  177. package/dist/chunk-IKB6HFGK.js +55 -0
  178. package/dist/{chunk-FBZAKNSX.js → chunk-IPVQKAHO.js} +10 -7
  179. package/dist/{chunk-3EYF6HKB.js → chunk-IVFJD7WY.js} +28 -9
  180. package/dist/{chunk-WOYYD2YR.js → chunk-JGRNTBF2.js} +11 -11
  181. package/dist/chunk-K3OWD7BJ.js +121 -0
  182. package/dist/{chunk-BJSKPEZI.js → chunk-KD4H66L6.js} +7 -20
  183. package/dist/{chunk-SFZOKW2G.js → chunk-KJ34ZBBI.js} +8 -3
  184. package/dist/{chunk-HQNHV7D6.js → chunk-LFHCXZO5.js} +6 -6
  185. package/dist/{chunk-LWKJQTOM.js → chunk-MICH6QSJ.js} +1 -1
  186. package/dist/chunk-N3DPO6HG.js +226 -0
  187. package/dist/{chunk-S4GZWSKR.js → chunk-OM5E3TTK.js} +1 -1
  188. package/dist/{chunk-3QRYCPXQ.js → chunk-OPKIKM35.js} +6 -6
  189. package/dist/{chunk-5EKIWVOR.js → chunk-PGRPNDWM.js} +2 -2
  190. package/dist/{chunk-LFJ6UJTI.js → chunk-PQNILU27.js} +9 -9
  191. package/dist/{chunk-QNCVHRZL.js → chunk-QVAFL2LE.js} +1 -1
  192. package/dist/{chunk-QEUY3A5P.js → chunk-QY7UU5ZB.js} +3 -2
  193. package/dist/{chunk-ITHXJHBB.js → chunk-R25RGPUB.js} +1 -0
  194. package/dist/{chunk-KLJCCMF3.js → chunk-R6735B37.js} +2 -2
  195. package/dist/{chunk-3ZP55QZE.js → chunk-R6FBDTP3.js} +4 -4
  196. package/dist/{chunk-7FZ53WDJ.js → chunk-RIAZM6L3.js} +1 -1
  197. package/dist/chunk-RJM4QCGG.js +550 -0
  198. package/dist/{chunk-NTRZGNEX.js → chunk-S3BCVWTU.js} +215 -46
  199. package/dist/chunk-S7KW47IQ.js +121 -0
  200. package/dist/{chunk-OFHBK7RI.js → chunk-SJQ546ID.js} +34 -14
  201. package/dist/{chunk-D35VTV2Z.js → chunk-SV7QAONL.js} +1 -1
  202. package/dist/{chunk-IAJLHVUA.js → chunk-TIWAHZZ6.js} +1 -1
  203. package/dist/{chunk-2PRH365R.js → chunk-UA7O3KKJ.js} +1 -1
  204. package/dist/{chunk-NPZY6YYL.js → chunk-UG5ZMAXW.js} +6 -6
  205. package/dist/{chunk-FEFTGVMF.js → chunk-V2N3BMOT.js} +7 -2
  206. package/dist/{chunk-NDCATSW7.js → chunk-V34H2YCY.js} +1 -1
  207. package/dist/chunk-WIATRXEJ.js +22 -0
  208. package/dist/{chunk-5C5YMZQU.js → chunk-WOFOMTGB.js} +16 -10
  209. package/dist/{chunk-QYOFACSP.js → chunk-WSOFKOLP.js} +3 -3
  210. package/dist/{chunk-MNAXYY3R.js → chunk-WUVZDFHS.js} +31 -11
  211. package/dist/{chunk-UG46QBLT.js → chunk-YIMOT5OO.js} +10 -10
  212. package/dist/{chunk-2ZQMA2WB.js → chunk-ZPSOF6VL.js} +2 -2
  213. package/dist/generated/index.d.ts +3 -0
  214. package/dist/generated/index.js +66 -62
  215. package/dist/index.js +66 -62
  216. package/dist/styles.css +2719 -799
  217. package/dist/utils/index.d.ts +1 -1
  218. package/dist/utils/tone.d.ts +7 -12
  219. package/package.json +4 -4
  220. package/scripts/check-css-literals.mjs +159 -23
  221. package/scripts/check-css-variables.mjs +5 -3
  222. package/scripts/css-source.mjs +97 -5
  223. package/dist/Avatar-P2KRQM2B.css +0 -156
  224. package/dist/Charts-D7G2BSXH.css +0 -277
  225. package/dist/CommandPalette-CSJDUCQA.css +0 -115
  226. package/dist/Kbd-W66MXQI5.css +0 -61
  227. package/dist/SearchTrigger-QXOYAUUY.css +0 -79
  228. package/dist/SidebarNav-QGSFKZYA.css +0 -319
  229. package/dist/StatCard-KYPKZUWX.css +0 -111
  230. package/dist/StatusDot-HA2L2FSX.css +0 -84
  231. package/dist/chunk-22O7LAW2.js +0 -41
  232. package/dist/chunk-2HQR4U4D.js +0 -143
  233. package/dist/chunk-ESCO4XYW.js +0 -144
  234. package/dist/chunk-F4PJZ4ED.js +0 -245
  235. package/dist/chunk-PNFASD6F.js +0 -98
  236. package/dist/chunk-PZSWF74H.js +0 -15
  237. /package/dist/{chunk-ZCR6YGQ4.js → chunk-PKIN4IMB.js} +0 -0
@@ -0,0 +1,550 @@
1
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './Charts-B3YEF7R4.css';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+ import { useState, useRef, useCallback, useId } from 'react';
6
+
7
+ // src/Charts/dataColor.ts
8
+ var DATA_COLORS = [
9
+ "var(--color-data-1)",
10
+ "var(--color-data-2)",
11
+ "var(--color-data-3)",
12
+ "var(--color-data-4)"
13
+ ];
14
+ var DATA_COLOR_OTHER = "var(--color-data-other)";
15
+ function dataColor(index) {
16
+ return DATA_COLORS[index] ?? DATA_COLOR_OTHER;
17
+ }
18
+ function Legend({ items, className }) {
19
+ return (
20
+ /*
21
+ * `role="list"` although a `ul` already has one, which is why the lint
22
+ * rule that calls it redundant is silenced here rather than obeyed: the
23
+ * stylesheet takes the markers off, and WebKit answers a marker-less list
24
+ * as a group of paragraphs, so a reader is no longer told how many series
25
+ * there are before they are read. The role puts that back.
26
+ */
27
+ // eslint-disable-next-line jsx-a11y/no-redundant-roles
28
+ /* @__PURE__ */ jsx("ul", { role: "list", className: cx("crewlet-legend", className), children: items.map((item, index) => /* @__PURE__ */ jsxs("li", { className: "crewlet-legend__item", children: [
29
+ /* @__PURE__ */ jsx(
30
+ "span",
31
+ {
32
+ className: "crewlet-legend__swatch",
33
+ "aria-hidden": true,
34
+ style: { "--crewlet-legend-swatch-color": item.color ?? dataColor(index) }
35
+ }
36
+ ),
37
+ /* @__PURE__ */ jsx("span", { className: "crewlet-legend__label", children: item.label }),
38
+ item.value != null && /* @__PURE__ */ jsx("span", { className: "crewlet-legend__value", children: item.value })
39
+ ] }, item.id)) })
40
+ );
41
+ }
42
+ function BarList({
43
+ data,
44
+ layout = "stacked",
45
+ max,
46
+ limit,
47
+ moreLabel = (remaining) => `and ${remaining} more`,
48
+ emptyLabel = "Nothing recorded in this window",
49
+ className
50
+ }) {
51
+ const capped = limit != null;
52
+ const shown = capped ? data.slice(0, limit) : data;
53
+ const top = max ?? Math.max(1, ...data.map((datum) => datum.value));
54
+ const remaining = capped ? Math.max(0, data.length - limit) : 0;
55
+ if (!shown.length) return /* @__PURE__ */ jsx("p", { className: "crewlet-bar-list__empty", children: emptyLabel });
56
+ return (
57
+ // A list, and said to be one: the markers are off, and WebKit drops the
58
+ // list role with them. See Legend for the same note, including why the
59
+ // redundant-role rule is silenced rather than obeyed.
60
+ // eslint-disable-next-line jsx-a11y/no-redundant-roles
61
+ /* @__PURE__ */ jsxs("ul", { role: "list", className: cx("crewlet-bar-list", `crewlet-bar-list--${layout}`, className), children: [
62
+ shown.map((datum, index) => {
63
+ const width = top > 0 && datum.value > 0 ? Math.max(1, datum.value / top * 100) : 0;
64
+ const bar = width > 0 ? /* @__PURE__ */ jsx(
65
+ "span",
66
+ {
67
+ className: "crewlet-bar-list__bar",
68
+ "aria-hidden": true,
69
+ style: {
70
+ width: `${width}%`,
71
+ "--crewlet-bar-list-bar-color": datum.color ?? dataColor(index)
72
+ }
73
+ }
74
+ ) : null;
75
+ const value = /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__value", children: datum.display ?? datum.value.toLocaleString() });
76
+ const body = layout === "beside" ? /* @__PURE__ */ jsxs(Fragment, { children: [
77
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-bar-list__names", children: [
78
+ /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__label", children: datum.label }),
79
+ datum.sub && /* @__PURE__ */ jsxs(Fragment, { children: [
80
+ " ",
81
+ /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__sub", children: datum.sub })
82
+ ] })
83
+ ] }),
84
+ " ",
85
+ /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__plot", children: /* @__PURE__ */ jsxs("span", { className: "crewlet-bar-list__scale", children: [
86
+ bar,
87
+ value
88
+ ] }) })
89
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
90
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-bar-list__head", children: [
91
+ /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__label", children: datum.label }),
92
+ " ",
93
+ value
94
+ ] }),
95
+ /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__track", "aria-hidden": true, children: bar }),
96
+ datum.sub && /* @__PURE__ */ jsxs(Fragment, { children: [
97
+ " ",
98
+ /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__sub", children: datum.sub })
99
+ ] })
100
+ ] });
101
+ return /* @__PURE__ */ jsx("li", { className: "crewlet-bar-list__item", children: datum.href ? /* @__PURE__ */ jsx("a", { className: "crewlet-bar-list__row crewlet-bar-list__row--pressable", href: datum.href, children: body }) : datum.onSelect ? /* @__PURE__ */ jsx(
102
+ "button",
103
+ {
104
+ type: "button",
105
+ className: "crewlet-bar-list__row crewlet-bar-list__row--pressable",
106
+ onClick: datum.onSelect,
107
+ children: body
108
+ }
109
+ ) : /* @__PURE__ */ jsx("span", { className: "crewlet-bar-list__row", children: body }) }, datum.id);
110
+ }),
111
+ remaining > 0 && /* @__PURE__ */ jsx("li", { className: "crewlet-bar-list__more", children: moreLabel(remaining) })
112
+ ] })
113
+ );
114
+ }
115
+ function ChartTooltip({ open, anchor, title, rows = [], total, className }) {
116
+ const start = anchor?.start ?? 0;
117
+ const end = anchor?.end ?? start;
118
+ const after = (start + end) / 2 <= 0.5;
119
+ const at = after ? end : start;
120
+ return /* @__PURE__ */ jsx("div", { className: "crewlet-chart-tooltip-live", "aria-live": "polite", "aria-atomic": "true", children: open ? /* @__PURE__ */ jsxs(
121
+ "div",
122
+ {
123
+ className: cx("crewlet-chart-tooltip", after ? "crewlet-chart-tooltip--after" : "crewlet-chart-tooltip--before", className),
124
+ style: { left: `${(Math.min(Math.max(at, 0), 1) * 100).toFixed(3)}%` },
125
+ children: [
126
+ title != null && /* @__PURE__ */ jsx("p", { className: "crewlet-chart-tooltip__title", children: title }),
127
+ rows.length > 0 && // A list, said to be one: the markers are off, and WebKit drops the
128
+ // role with them (see Legend).
129
+ // eslint-disable-next-line jsx-a11y/no-redundant-roles
130
+ /* @__PURE__ */ jsx("ul", { role: "list", className: "crewlet-chart-tooltip__rows", children: rows.map((row) => /* @__PURE__ */ jsxs("li", { className: "crewlet-chart-tooltip__row", children: [
131
+ /* @__PURE__ */ jsx(
132
+ "span",
133
+ {
134
+ className: "crewlet-chart-tooltip__swatch",
135
+ "aria-hidden": true,
136
+ style: row.color == null ? void 0 : { "--crewlet-chart-tooltip-swatch-color": row.color }
137
+ }
138
+ ),
139
+ /* @__PURE__ */ jsx("span", { className: "crewlet-chart-tooltip__name", children: row.name }),
140
+ /* @__PURE__ */ jsx("span", { className: "crewlet-chart-tooltip__value", children: row.value })
141
+ ] }, row.id)) }),
142
+ total != null && /* @__PURE__ */ jsxs("p", { className: "crewlet-chart-tooltip__total", children: [
143
+ /* @__PURE__ */ jsx("span", { className: "crewlet-chart-tooltip__name", children: total.label ?? "Total" }),
144
+ /* @__PURE__ */ jsx("span", { className: "crewlet-chart-tooltip__value", children: total.value })
145
+ ] })
146
+ ]
147
+ }
148
+ ) : null });
149
+ }
150
+ function useChartHover(count) {
151
+ const [reading, setReading] = useState({
152
+ index: null,
153
+ source: null
154
+ });
155
+ const remembered = useRef(null);
156
+ const clamp = (index) => Math.min(Math.max(index, 0), count - 1);
157
+ const active = reading.index == null || count === 0 ? null : clamp(reading.index);
158
+ const open = useCallback((index, source) => {
159
+ if (index != null) remembered.current = index;
160
+ setReading(index == null ? { index: null, source: null } : { index, source });
161
+ }, []);
162
+ const point = useCallback((index) => open(index, "pointer"), [open]);
163
+ const onKeyDown = (event) => {
164
+ if (event.key === "Escape") {
165
+ if (active == null) return;
166
+ event.preventDefault();
167
+ event.stopPropagation();
168
+ open(null, "keyboard");
169
+ return;
170
+ }
171
+ if (count === 0) return;
172
+ const from = active ?? (remembered.current == null ? null : clamp(remembered.current));
173
+ let next;
174
+ switch (event.key) {
175
+ case "ArrowLeft":
176
+ next = from == null ? count - 1 : active == null ? from : from - 1;
177
+ break;
178
+ case "ArrowRight":
179
+ next = from == null ? 0 : active == null ? from : from + 1;
180
+ break;
181
+ case "Home":
182
+ next = 0;
183
+ break;
184
+ case "End":
185
+ next = count - 1;
186
+ break;
187
+ default:
188
+ return;
189
+ }
190
+ event.preventDefault();
191
+ open(clamp(next), "keyboard");
192
+ };
193
+ const onBlur = () => {
194
+ if (reading.index != null) open(null, "keyboard");
195
+ };
196
+ const onPointerLeave = () => {
197
+ if (reading.source === "pointer") open(null, "pointer");
198
+ };
199
+ return {
200
+ active,
201
+ source: active == null ? null : reading.source,
202
+ point,
203
+ plotProps: { tabIndex: 0, onKeyDown, onBlur, onPointerLeave }
204
+ };
205
+ }
206
+ function StackedBar({ segments, summary, format = (value) => value.toLocaleString(), className }) {
207
+ const named = useId();
208
+ const total = segments.reduce((sum, segment) => sum + Math.max(0, segment.value), 0);
209
+ const drawn = segments.map((segment, index) => ({ ...segment, color: segment.color ?? dataColor(index) })).filter((segment) => segment.value > 0);
210
+ const parts = drawn.map((segment) => ({
211
+ label: segment.label,
212
+ value: segment.value,
213
+ percent: total > 0 ? Math.round(segment.value / total * 100) : 0
214
+ }));
215
+ const sentence = summary ? summary(parts) : parts.map((part) => `${part.label}: ${format(part.value)} (${part.percent}%)`).join(", ");
216
+ const hover = useChartHover(drawn.length);
217
+ const active = hover.active == null ? null : drawn[hover.active];
218
+ const edges = drawn.reduce((at, segment) => [...at, at[at.length - 1] + segment.value / total], [0]);
219
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-stacked-bar", className), children: [
220
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-chart-frame", role: "group", "aria-labelledby": named, ...hover.plotProps, children: [
221
+ /* @__PURE__ */ jsx("div", { className: "crewlet-stacked-bar__track", "aria-hidden": true, children: drawn.map((segment, index) => /* @__PURE__ */ jsx(
222
+ "span",
223
+ {
224
+ className: "crewlet-stacked-bar__segment",
225
+ onPointerEnter: () => hover.point(index),
226
+ style: {
227
+ flexGrow: segment.value,
228
+ "--crewlet-stacked-bar-segment-color": segment.color
229
+ }
230
+ },
231
+ segment.id
232
+ )) }),
233
+ /* @__PURE__ */ jsx(
234
+ ChartTooltip,
235
+ {
236
+ open: active != null,
237
+ anchor: hover.active == null ? void 0 : { start: edges[hover.active], end: edges[hover.active + 1] },
238
+ rows: active == null || hover.active == null ? [] : [
239
+ {
240
+ id: active.id,
241
+ name: active.label,
242
+ value: `${format(active.value)} (${parts[hover.active].percent}%)`,
243
+ color: active.color
244
+ }
245
+ ],
246
+ total: active == null ? void 0 : { value: format(total) }
247
+ }
248
+ )
249
+ ] }),
250
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: named, children: sentence })
251
+ ] });
252
+ }
253
+ function ActivityStrip({ buckets, label, summary, className }) {
254
+ const peak = Math.max(1, ...buckets.map((bucket) => bucket.v));
255
+ const total = buckets.reduce((sum, bucket) => sum + bucket.v, 0);
256
+ const sentence = summary ? summary({ peak, total, buckets: buckets.length }) : `${label}. ${total.toLocaleString()} in ${buckets.length} buckets, peak ${peak.toLocaleString()}.`;
257
+ return /* @__PURE__ */ jsx("div", { className: cx("crewlet-activity-strip", className), role: "img", "aria-label": sentence, children: buckets.map((bucket) => /* @__PURE__ */ jsx(
258
+ "span",
259
+ {
260
+ className: cx("crewlet-activity-strip__cell", bucket.v > 0 && "is-active"),
261
+ style: {
262
+ /*
263
+ * A floor of a fifth, so a bucket with one event in it reads as a
264
+ * mark rather than as a line nobody can resolve, and an empty one
265
+ * keeps the baseline hairline that says the bucket existed.
266
+ */
267
+ "--crewlet-activity-strip-fill": bucket.v > 0 ? `${Math.max(20, bucket.v / peak * 100)}%` : "10%"
268
+ }
269
+ },
270
+ bucket.t
271
+ )) });
272
+ }
273
+ function TimeSeries({
274
+ series,
275
+ from,
276
+ to,
277
+ label,
278
+ height = "7.5rem",
279
+ format = (value) => value.toLocaleString(),
280
+ formatTime = (at) => new Date(at).toLocaleString(),
281
+ summary,
282
+ className
283
+ }) {
284
+ const id = useId();
285
+ const width = 1e3;
286
+ const plot = 120;
287
+ const footer = 18;
288
+ const head = 6;
289
+ const span = Math.max(1, to - from);
290
+ const peaks = series.map((one) => Math.max(0, ...one.points.map((point) => point.v)));
291
+ const peak = Math.max(1, ...peaks);
292
+ const x = (at) => (at - from) / span * width;
293
+ const y = (value) => head + (1 - value / peak) * (plot - head - footer);
294
+ const instants = [...new Set(series.flatMap((one) => one.points.map((point) => point.t)))].sort((a, b) => a - b);
295
+ const hover = useChartHover(instants.length);
296
+ const reading = hover.active == null ? null : instants[hover.active];
297
+ const onPointerMove = (event) => {
298
+ const box = event.currentTarget.getBoundingClientRect();
299
+ if (box.width <= 0 || instants.length === 0) return;
300
+ const at = from + (event.clientX - box.left) / box.width * span;
301
+ let nearest = 0;
302
+ for (let index = 1; index < instants.length; index += 1) {
303
+ if (Math.abs(instants[index] - at) < Math.abs(instants[nearest] - at)) nearest = index;
304
+ }
305
+ hover.point(nearest);
306
+ };
307
+ const sentence = summary ? summary({ from, to, peak, series: series.map((one, index) => ({ name: one.name, peak: peaks[index] ?? 0 })) }) : `${label}. ${formatTime(from)} to ${formatTime(to)}, peak ${format(peak)}.`;
308
+ return /* @__PURE__ */ jsxs("figure", { className: cx("crewlet-time-series", className), children: [
309
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-chart-frame", role: "group", "aria-label": label, ...hover.plotProps, children: [
310
+ /* @__PURE__ */ jsxs(
311
+ "svg",
312
+ {
313
+ className: "crewlet-chart",
314
+ viewBox: `0 0 ${width} ${plot}`,
315
+ preserveAspectRatio: "none",
316
+ style: { height },
317
+ role: "img",
318
+ "aria-label": sentence,
319
+ onPointerMove,
320
+ children: [
321
+ [0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */ jsx(
322
+ "line",
323
+ {
324
+ className: "crewlet-chart__grid-line",
325
+ x1: 0,
326
+ x2: width,
327
+ y1: y(peak * fraction),
328
+ y2: y(peak * fraction)
329
+ },
330
+ fraction
331
+ )),
332
+ /* @__PURE__ */ jsx("line", { className: "crewlet-chart__axis-line", x1: 0, x2: width, y1: plot - footer, y2: plot - footer }),
333
+ series.map((one, index) => {
334
+ const color = one.color ?? dataColor(index);
335
+ const points = [...one.points].sort((a, b) => a.t - b.t);
336
+ if (points.length === 0) return null;
337
+ const line = points.map((point) => `${x(point.t).toFixed(2)},${y(point.v).toFixed(2)}`).join(" ");
338
+ const first = points[0];
339
+ const last = points[points.length - 1];
340
+ const area = `${x(first.t).toFixed(2)},${plot - footer} ${line} ${x(last.t).toFixed(2)},${plot - footer}`;
341
+ return /* @__PURE__ */ jsxs("g", { children: [
342
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: `${id}-${index}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
343
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color, stopOpacity: "0.22" }),
344
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: color, stopOpacity: "0" })
345
+ ] }) }),
346
+ /* @__PURE__ */ jsx("polygon", { points: area, fill: `url(#${id}-${index})` }),
347
+ /* @__PURE__ */ jsx(
348
+ "polyline",
349
+ {
350
+ className: "crewlet-chart__series",
351
+ points: line,
352
+ stroke: color,
353
+ vectorEffect: "non-scaling-stroke"
354
+ }
355
+ )
356
+ ] }, one.id);
357
+ }),
358
+ reading != null && /* @__PURE__ */ jsx(
359
+ "line",
360
+ {
361
+ className: "crewlet-chart__crosshair",
362
+ x1: x(reading),
363
+ x2: x(reading),
364
+ y1: 0,
365
+ y2: plot - footer,
366
+ vectorEffect: "non-scaling-stroke"
367
+ }
368
+ )
369
+ ]
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx(
373
+ ChartTooltip,
374
+ {
375
+ open: reading != null,
376
+ anchor: reading == null ? void 0 : { start: (reading - from) / span },
377
+ title: reading == null ? void 0 : formatTime(reading),
378
+ rows: reading == null ? [] : series.flatMap((one, index) => {
379
+ const point = one.points.find((candidate) => candidate.t === reading);
380
+ return point ? [{ id: one.id, name: one.name, value: format(point.v), color: one.color ?? dataColor(index) }] : [];
381
+ })
382
+ }
383
+ )
384
+ ] }),
385
+ /* @__PURE__ */ jsxs("figcaption", { className: "crewlet-time-series__scale", children: [
386
+ /* @__PURE__ */ jsx("span", { children: formatTime(from) }),
387
+ /* @__PURE__ */ jsxs("span", { children: [
388
+ "peak ",
389
+ format(peak)
390
+ ] }),
391
+ /* @__PURE__ */ jsx("span", { children: formatTime(to) })
392
+ ] })
393
+ ] });
394
+ }
395
+ function Sparkline({
396
+ values,
397
+ color = DATA_COLOR_OTHER,
398
+ current = false,
399
+ height = "1.75rem",
400
+ className
401
+ }) {
402
+ const width = 200;
403
+ const box = 28;
404
+ const classes = cx("crewlet-spark", current && "crewlet-spark--current", className);
405
+ if (values.length < 2) return /* @__PURE__ */ jsx("div", { className: classes, style: { height }, "aria-hidden": true });
406
+ const peak = Math.max(1, ...values);
407
+ const step = width / (values.length - 1);
408
+ const y = (value) => box - value / peak * (box - 2) - 1;
409
+ const points = values.map((value, index) => `${(index * step).toFixed(2)},${y(value).toFixed(2)}`).join(" ");
410
+ const last = values[values.length - 1];
411
+ return /* @__PURE__ */ jsxs("div", { className: classes, style: { height }, "aria-hidden": true, children: [
412
+ /* @__PURE__ */ jsx("svg", { className: "crewlet-spark__plot", viewBox: `0 0 ${width} ${box}`, preserveAspectRatio: "none", children: /* @__PURE__ */ jsx("polyline", { className: "crewlet-chart__series", points, stroke: color, vectorEffect: "non-scaling-stroke" }) }),
413
+ current ? /* @__PURE__ */ jsx("span", { className: "crewlet-spark__current", style: { top: `${(y(last) / box * 100).toFixed(2)}%` } }) : null
414
+ ] });
415
+ }
416
+ function niceScale(peak, steps = 4) {
417
+ if (!(peak > 0)) return { top: steps, step: 1 };
418
+ const raw = peak / steps;
419
+ const magnitude = 10 ** Math.floor(Math.log10(raw));
420
+ const step = ([1, 2, 2.5, 5, 10].find((candidate) => candidate * magnitude >= raw) ?? 10) * magnitude;
421
+ const top = Number((Math.max(1, Math.ceil(peak / step - 1e-9)) * step).toPrecision(12));
422
+ return { top, step: Number(step.toPrecision(12)) };
423
+ }
424
+ var COMPACT = new Intl.NumberFormat(void 0, { notation: "compact", maximumFractionDigits: 1 });
425
+ function StackedColumns({
426
+ series,
427
+ buckets,
428
+ hidden = [],
429
+ label,
430
+ legend = "below",
431
+ head,
432
+ height = "11.5rem",
433
+ format = (value) => COMPACT.format(value),
434
+ formatTime = (at) => new Date(at).toLocaleDateString(),
435
+ summary,
436
+ className
437
+ }) {
438
+ const colored = series.map((one, index) => ({ ...one, color: one.color ?? dataColor(index) }));
439
+ const shown = colored.filter((one) => !hidden.includes(one.id));
440
+ const valueOf = (bucket, id) => Math.max(0, bucket.values[id] ?? 0);
441
+ const totals = buckets.map((bucket) => shown.reduce((sum, one) => sum + valueOf(bucket, one.id), 0));
442
+ const peak = Math.max(0, ...totals);
443
+ const { top, step } = niceScale(peak);
444
+ const intervals = Math.round(top / step);
445
+ const ticks = Array.from(
446
+ { length: intervals + 1 },
447
+ (_, index) => Number(((intervals - index) * step).toPrecision(12))
448
+ );
449
+ const hover = useChartHover(buckets.length);
450
+ const active = hover.active == null ? null : buckets[hover.active];
451
+ const first = buckets[0]?.t ?? null;
452
+ const last = buckets[buckets.length - 1]?.t ?? null;
453
+ const centre = Math.floor((buckets.length - 1) / 2);
454
+ const middle = buckets.length > 2 ? buckets[centre].t : null;
455
+ const facts = {
456
+ from: first,
457
+ to: last,
458
+ peak,
459
+ series: shown.map((one) => ({
460
+ name: one.name,
461
+ total: buckets.reduce((sum, bucket) => sum + valueOf(bucket, one.id), 0)
462
+ }))
463
+ };
464
+ const sentence = summary ? summary(facts) : first == null || last == null ? `${label}. Nothing recorded.` : `${label}. ${formatTime(first)} to ${formatTime(last)}, tallest ${format(peak)}. ${facts.series.map((one) => `${one.name} ${format(one.total)}`).join(", ")}.`;
465
+ const key = legend === "none" ? null : /* @__PURE__ */ jsx(
466
+ Legend,
467
+ {
468
+ className: cx("crewlet-stacked-columns__legend", `crewlet-stacked-columns__legend--${legend}`),
469
+ items: shown.map((one) => ({ id: one.id, label: one.name, color: one.color }))
470
+ }
471
+ );
472
+ const hasHead = head !== void 0 && head !== null && head !== false;
473
+ return /* @__PURE__ */ jsxs("figure", { className: cx("crewlet-stacked-columns", className), children: [
474
+ hasHead || legend === "head" ? /* @__PURE__ */ jsxs("div", { className: "crewlet-stacked-columns__head", children: [
475
+ hasHead ? /* @__PURE__ */ jsx("div", { className: "crewlet-stacked-columns__heading", children: head }) : null,
476
+ legend === "head" ? key : null
477
+ ] }) : null,
478
+ /* @__PURE__ */ jsx("div", { className: "crewlet-stacked-columns__axis", "aria-hidden": true, style: { height }, children: ticks.map((tick) => /* @__PURE__ */ jsx("span", { className: "crewlet-stacked-columns__tick", children: format(tick) }, tick)) }),
479
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-chart-frame", role: "group", "aria-label": label, ...hover.plotProps, children: [
480
+ /* @__PURE__ */ jsxs(
481
+ "div",
482
+ {
483
+ className: "crewlet-stacked-columns__plot",
484
+ role: "img",
485
+ "aria-label": sentence,
486
+ style: { height },
487
+ children: [
488
+ /* @__PURE__ */ jsx("div", { className: "crewlet-stacked-columns__grid", "aria-hidden": true, children: ticks.map((tick) => /* @__PURE__ */ jsx("span", { className: "crewlet-stacked-columns__grid-line" }, tick)) }),
489
+ buckets.map((bucket, index) => {
490
+ const total = totals[index] ?? 0;
491
+ const parts = shown.filter((one) => valueOf(bucket, one.id) > 0);
492
+ return /* @__PURE__ */ jsx(
493
+ "div",
494
+ {
495
+ className: cx("crewlet-stacked-columns__slot", hover.active === index && "is-active"),
496
+ onPointerEnter: () => hover.point(index),
497
+ children: /* @__PURE__ */ jsx(
498
+ "div",
499
+ {
500
+ className: "crewlet-stacked-columns__column",
501
+ style: { height: `${(total / top * 100).toFixed(3)}%` },
502
+ children: parts.map((one) => /* @__PURE__ */ jsx(
503
+ "span",
504
+ {
505
+ className: "crewlet-stacked-columns__segment",
506
+ "data-series": one.id,
507
+ style: {
508
+ flexGrow: valueOf(bucket, one.id),
509
+ "--crewlet-stacked-columns-segment-color": one.color
510
+ }
511
+ },
512
+ one.id
513
+ ))
514
+ }
515
+ )
516
+ },
517
+ bucket.t
518
+ );
519
+ })
520
+ ]
521
+ }
522
+ ),
523
+ /* @__PURE__ */ jsx(
524
+ ChartTooltip,
525
+ {
526
+ open: active != null,
527
+ anchor: hover.active == null ? void 0 : { start: hover.active / buckets.length, end: (hover.active + 1) / buckets.length },
528
+ title: active == null ? void 0 : formatTime(active.t),
529
+ rows: active == null ? [] : shown.map((one) => ({ id: one.id, name: one.name, value: format(valueOf(active, one.id)), color: one.color })),
530
+ total: active == null || hover.active == null ? void 0 : { value: format(totals[hover.active] ?? 0) }
531
+ }
532
+ )
533
+ ] }),
534
+ /* @__PURE__ */ jsxs("figcaption", { className: "crewlet-stacked-columns__scale", children: [
535
+ /* @__PURE__ */ jsx("span", { children: first == null ? "" : formatTime(first) }),
536
+ middle != null && /* @__PURE__ */ jsx(
537
+ "span",
538
+ {
539
+ className: "crewlet-stacked-columns__middle",
540
+ style: { left: `${((centre + 0.5) / buckets.length * 100).toFixed(3)}%` },
541
+ children: formatTime(middle)
542
+ }
543
+ ),
544
+ /* @__PURE__ */ jsx("span", { children: last == null || last === first ? "" : formatTime(last) })
545
+ ] }),
546
+ legend === "below" ? key : null
547
+ ] });
548
+ }
549
+
550
+ export { ActivityStrip, BarList, ChartTooltip, DATA_COLORS, DATA_COLOR_OTHER, Legend, Sparkline, StackedBar, StackedColumns, TimeSeries, dataColor, niceScale, useChartHover };