@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,156 @@
1
+ import { cx } from './chunk-ODEQTPFM.js';
2
+ import './Avatar-XID7Z74C.css';
3
+ import './AvatarStack-GEJBNV7E.css';
4
+ import { useState, useEffect } from 'react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ var AVATAR_SIZES = { xs: 20, sm: 26, md: 32, lg: 40 };
8
+ var AVATAR_CORNER_RATIO = 0.29;
9
+ var getInitials = (name) => {
10
+ if (!name) return "?";
11
+ const words = name.trim().split(/[\s\-_.]+/).filter(Boolean);
12
+ if (words.length === 0) return "?";
13
+ const first = (word2) => (Array.from(word2)[0] ?? "").toUpperCase();
14
+ if (words.length >= 2) return words.slice(0, 2).map(first).join("") || "?";
15
+ const word = words[0];
16
+ const humps = word.split(/(?<=\p{Ll})(?=\p{Lu})/u);
17
+ if (humps.length >= 2) return humps.slice(0, 2).map(first).join("");
18
+ return Array.from(word).slice(0, 2).map((character) => character.toUpperCase()).join("") || "?";
19
+ };
20
+ var TINT_COUNT = 10;
21
+ var avatarTint = (seed) => {
22
+ let hash = 0;
23
+ for (let i = 0; i < seed.length; i += 1) {
24
+ hash = hash * 31 + seed.charCodeAt(i) >>> 0;
25
+ }
26
+ return hash % TINT_COUNT;
27
+ };
28
+ function avatarPixels(size) {
29
+ return typeof size === "number" ? size : AVATAR_SIZES[size];
30
+ }
31
+ function avatarCorner(pixels) {
32
+ return pixels * AVATAR_CORNER_RATIO;
33
+ }
34
+ var Avatar = ({
35
+ src,
36
+ name,
37
+ size = "md",
38
+ kind = "agent",
39
+ tone = "neutral",
40
+ ring,
41
+ decorative = false,
42
+ colorSeed,
43
+ className,
44
+ style,
45
+ ...rest
46
+ }) => {
47
+ const [imageFailed, setImageFailed] = useState(false);
48
+ useEffect(() => {
49
+ setImageFailed(false);
50
+ }, [src]);
51
+ const step = typeof size === "number" ? null : size;
52
+ const pixels = avatarPixels(size);
53
+ const measured = step === null ? {
54
+ "--crewlet-avatar-size": `${pixels}px`,
55
+ fontSize: Math.max(9, Math.round(pixels * 0.36))
56
+ } : {};
57
+ const seeded = tone === "seeded" ? avatarTint(colorSeed ?? name ?? "") : null;
58
+ const classes = cx(
59
+ "crewlet-avatar",
60
+ `crewlet-avatar--${kind}`,
61
+ step === null ? null : `crewlet-avatar--${step}`,
62
+ ring === void 0 ? null : `crewlet-avatar--ring-${ring}`,
63
+ className
64
+ );
65
+ if (src && !imageFailed) {
66
+ return /* @__PURE__ */ jsx(
67
+ "img",
68
+ {
69
+ ...rest,
70
+ className: cx(classes, "crewlet-avatar--image"),
71
+ style: { ...measured, ...style },
72
+ src,
73
+ alt: decorative ? "" : name ?? "",
74
+ "aria-hidden": decorative ? true : void 0,
75
+ onError: () => setImageFailed(true)
76
+ }
77
+ );
78
+ }
79
+ return /* @__PURE__ */ jsx(
80
+ "span",
81
+ {
82
+ ...rest,
83
+ className: cx(
84
+ classes,
85
+ "crewlet-avatar--fallback",
86
+ `crewlet-avatar--${tone}`,
87
+ seeded === null ? null : `crewlet-avatar--tint-${seeded}`
88
+ ),
89
+ style: { ...measured, ...style },
90
+ role: decorative ? void 0 : "img",
91
+ "aria-hidden": decorative ? true : void 0,
92
+ "aria-label": decorative ? void 0 : name ? `${name} avatar` : "Avatar",
93
+ children: getInitials(name)
94
+ }
95
+ );
96
+ };
97
+ function counted(count, one, many) {
98
+ return `${count} ${count === 1 ? one : many}`;
99
+ }
100
+ function avatarStackLabel(members) {
101
+ const humans = members.filter((member) => member.kind === "human").length;
102
+ const agents = members.length - humans;
103
+ const agentWords = counted(agents, "agent", "agents");
104
+ const humanWords = counted(humans, "person", "people");
105
+ const who = humans === 0 ? agentWords : agents === 0 ? humanWords : `${agentWords} and ${humanWords}`;
106
+ return `${who}: ${members.map((member) => member.name).join(", ")}`;
107
+ }
108
+ function AvatarStack({
109
+ members,
110
+ max = 4,
111
+ size = "sm",
112
+ label,
113
+ decorative = false,
114
+ className,
115
+ style,
116
+ ...rest
117
+ }) {
118
+ if (!Number.isInteger(max) || max < 1) {
119
+ throw new RangeError(`AvatarStack max must be a whole number of at least 1; it was ${max}`);
120
+ }
121
+ if (members.length === 0) return null;
122
+ const shown = members.slice(0, max);
123
+ const overflow = members.length - shown.length;
124
+ return /* @__PURE__ */ jsxs(
125
+ "span",
126
+ {
127
+ ...rest,
128
+ className: cx("crewlet-avatar-stack", className),
129
+ style: { "--crewlet-avatar-stack-size": `${AVATAR_SIZES[size]}px`, ...style },
130
+ role: decorative ? void 0 : "img",
131
+ "aria-label": decorative ? void 0 : label ?? avatarStackLabel(members),
132
+ "aria-hidden": decorative ? true : void 0,
133
+ children: [
134
+ shown.map((member) => /* @__PURE__ */ jsx(
135
+ Avatar,
136
+ {
137
+ className: "crewlet-avatar-stack__member",
138
+ name: member.name,
139
+ kind: member.kind,
140
+ src: member.src,
141
+ ring: member.ring,
142
+ size,
143
+ decorative: true
144
+ },
145
+ member.id ?? member.name
146
+ )),
147
+ overflow > 0 ? /* @__PURE__ */ jsxs("span", { className: "crewlet-avatar-stack__member crewlet-avatar-stack__more", "aria-hidden": "true", children: [
148
+ "+",
149
+ overflow
150
+ ] }) : null
151
+ ]
152
+ }
153
+ );
154
+ }
155
+
156
+ export { AVATAR_CORNER_RATIO, AVATAR_SIZES, Avatar, AvatarStack, avatarCorner, avatarPixels, avatarStackLabel, avatarTint, getInitials };
@@ -1,13 +1,13 @@
1
1
  import { HeadingLevelProvider } from './chunk-PQADV6P6.js';
2
2
  import { useLayerContainer } from './chunk-7RPGY3JE.js';
3
- import { focusables, useModalLayer, useBodyScrollLock } from './chunk-ITHXJHBB.js';
4
- import { IconButton } from './chunk-F27EPQ7D.js';
5
- import { Button } from './chunk-BZYDZBAN.js';
3
+ import { focusables, useModalLayer, useBodyScrollLock } from './chunk-R25RGPUB.js';
4
+ import { IconButton } from './chunk-4UQ7SMPK.js';
5
+ import { Button } from './chunk-ETYEBKR4.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
- import './Modal-XYQJ4BL6.css';
7
+ import './Modal-JAYBS2KS.css';
8
8
  import { useId, useRef, useCallback } from 'react';
9
9
  import { createPortal } from 'react-dom';
10
- import { CloseGlyph } from '@crewlethq/icons/glyphs';
10
+ import { XGlyph } from '@crewlethq/icons/glyphs';
11
11
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
12
12
 
13
13
  function Modal({ open, ...rest }) {
@@ -120,7 +120,7 @@ function ModalFrame({
120
120
  {
121
121
  className: "crewlet-modal__close",
122
122
  label: closeLabel,
123
- icon: /* @__PURE__ */ jsx(CloseGlyph, { size: "md" }),
123
+ icon: /* @__PURE__ */ jsx(XGlyph, { size: "md" }),
124
124
  onClick: onClose,
125
125
  disabledReason: dismissable ? void 0 : closeDisabledReason
126
126
  }
@@ -197,7 +197,7 @@ function ConfirmModal({
197
197
  cancelLabel = "Cancel",
198
198
  destructive = false,
199
199
  confirmVariant,
200
- cancelVariant = "tertiary",
200
+ cancelVariant = "ghost",
201
201
  confirmDisabled = false,
202
202
  confirmDisabledReason = "Complete the confirmation above to continue.",
203
203
  submitting = false,
@@ -0,0 +1,55 @@
1
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './StatCard-KPAFD4E2.css';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ var StatCard = ({
7
+ label,
8
+ value,
9
+ unit,
10
+ sub,
11
+ subTone = "neutral",
12
+ delta,
13
+ trend,
14
+ icon,
15
+ tone = "neutral",
16
+ loading = false,
17
+ loadingLabel = "Loading",
18
+ flush = false,
19
+ className,
20
+ ...rest
21
+ }) => {
22
+ const change = loading ? void 0 : delta;
23
+ const said = sub !== void 0 && sub !== null && sub !== false && sub !== "";
24
+ return /* @__PURE__ */ jsxs(
25
+ "div",
26
+ {
27
+ ...rest,
28
+ className: cx("crewlet-statcard", `crewlet-statcard--${tone}`, flush && "crewlet-statcard--flush", className),
29
+ "aria-busy": loading || void 0,
30
+ children: [
31
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-statcard__label", children: [
32
+ icon ? /* @__PURE__ */ jsx("span", { className: "crewlet-statcard__icon", "aria-hidden": true, children: icon }) : null,
33
+ label
34
+ ] }),
35
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-statcard__reading", children: [
36
+ /* @__PURE__ */ jsx("div", { className: "crewlet-statcard__value", children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
37
+ /* @__PURE__ */ jsx("span", { className: "crewlet-statcard__placeholder", "aria-hidden": true }),
38
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: loadingLabel })
39
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
40
+ value,
41
+ unit ? /* @__PURE__ */ jsx("span", { className: "crewlet-statcard__unit", children: unit }) : null
42
+ ] }) }),
43
+ trend && !loading ? /* @__PURE__ */ jsx("div", { className: "crewlet-statcard__trend", children: trend }) : null
44
+ ] }),
45
+ /* @__PURE__ */ jsxs("div", { className: cx("crewlet-statcard__sub", subTone !== "neutral" && `crewlet-statcard__sub--${subTone}`), children: [
46
+ change ? /* @__PURE__ */ jsx("span", { className: cx("crewlet-statcard__delta", `crewlet-statcard__delta--${change.polarity}`), children: change.value }) : null,
47
+ change && said ? " " : null,
48
+ sub
49
+ ] })
50
+ ]
51
+ }
52
+ );
53
+ };
54
+
55
+ export { StatCard };
@@ -1,12 +1,12 @@
1
1
  import { useLayerContainer, viewportBounds, LAYER_GAP, outsideBounds, placePopup, LAYER_REPOSITION_EVENT } from './chunk-7RPGY3JE.js';
2
- import { usePopupLayer } from './chunk-ITHXJHBB.js';
3
- import { IconButton } from './chunk-F27EPQ7D.js';
4
- import { Button } from './chunk-BZYDZBAN.js';
2
+ import { usePopupLayer } from './chunk-R25RGPUB.js';
3
+ import { IconButton } from './chunk-4UQ7SMPK.js';
4
+ import { Button } from './chunk-ETYEBKR4.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
- import './Menu-6DE7I66I.css';
6
+ import './Menu-BT5PMFJI.css';
7
7
  import { useId, useState, useRef, useCallback, useLayoutEffect, useEffect } from 'react';
8
8
  import { createPortal } from 'react-dom';
9
- import { MoreVertGlyph, CheckGlyph } from '@crewlethq/icons/glyphs';
9
+ import { EllipsisVerticalGlyph, CheckGlyph } from '@crewlethq/icons/glyphs';
10
10
  import { jsx, jsxs } from 'react/jsx-runtime';
11
11
 
12
12
  var ITEM_SELECTOR = "[role='menuitem'],[role='menuitemradio']";
@@ -29,7 +29,7 @@ function Menu({
29
29
  items,
30
30
  icon,
31
31
  trigger,
32
- triggerVariant = "tertiary",
32
+ triggerVariant = "ghost",
33
33
  triggerTabIndex,
34
34
  open: controlled,
35
35
  onOpenChange,
@@ -113,10 +113,13 @@ function Menu({
113
113
  container?.addEventListener(LAYER_REPOSITION_EVENT, onLayout);
114
114
  window.addEventListener("resize", onLayout);
115
115
  window.addEventListener("scroll", onLayout, true);
116
+ const resize = typeof ResizeObserver === "function" ? new ResizeObserver(onLayout) : null;
117
+ if (menu.current) resize?.observe(menu.current);
116
118
  return () => {
117
119
  container?.removeEventListener(LAYER_REPOSITION_EVENT, onLayout);
118
120
  window.removeEventListener("resize", onLayout);
119
121
  window.removeEventListener("scroll", onLayout, true);
122
+ resize?.disconnect();
120
123
  };
121
124
  }, [open, container, position]);
122
125
  useEffect(() => {
@@ -255,7 +258,7 @@ function Menu({
255
258
  onKeyDown: onTriggerKeyDown
256
259
  };
257
260
  return /* @__PURE__ */ jsxs("span", { className: "crewlet-menu-anchor", children: [
258
- trigger === void 0 ? /* @__PURE__ */ jsx(IconButton, { ...shared, label, icon: icon ?? /* @__PURE__ */ jsx(MoreVertGlyph, {}), size: "sm" }) : /* @__PURE__ */ jsx(Button, { ...shared, variant: triggerVariant, size: "small", leadingIcon: icon, children: trigger }),
261
+ trigger === void 0 ? /* @__PURE__ */ jsx(IconButton, { ...shared, label, icon: icon ?? /* @__PURE__ */ jsx(EllipsisVerticalGlyph, {}), size: "sm" }) : /* @__PURE__ */ jsx(Button, { ...shared, variant: triggerVariant, size: "small", leadingIcon: icon, children: trigger }),
259
262
  list && container ? createPortal(list, container) : null
260
263
  ] });
261
264
  }
@@ -1,14 +1,14 @@
1
1
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './SidebarNav-QGSFKZYA.css';
3
+ import './SidebarNav-X5NLZNWA.css';
4
4
  import { useId, useState } from 'react';
5
- import { KeyboardArrowDownGlyph } from '@crewlethq/icons/glyphs';
5
+ import { ChevronDownGlyph } from '@crewlethq/icons/glyphs';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  function SidebarNav({ label, className, children }) {
9
9
  return /* @__PURE__ */ jsx("nav", { className: cx("crewlet-sidebar-nav", className), "aria-label": label, children });
10
10
  }
11
- function NavGroup({ label, className, children }) {
11
+ function NavGroup({ label, action, className, children }) {
12
12
  const id = useId();
13
13
  const named = label !== void 0 && label !== null && label !== false && label !== "";
14
14
  return /* @__PURE__ */ jsxs(
@@ -18,17 +18,30 @@ function NavGroup({ label, className, children }) {
18
18
  role: named ? "group" : void 0,
19
19
  "aria-labelledby": named ? id : void 0,
20
20
  children: [
21
- named ? /* @__PURE__ */ jsx("div", { className: "crewlet-nav-group__label", id, children: label }) : null,
21
+ named || action ? /* @__PURE__ */ jsxs("div", { className: "crewlet-nav-group__head", children: [
22
+ named ? /* @__PURE__ */ jsx("span", { className: "crewlet-nav-group__label", id, children: label }) : null,
23
+ action ? /* @__PURE__ */ jsx("button", { type: "button", className: "crewlet-nav-group__action", "aria-label": action.label, onClick: action.onClick, children: /* @__PURE__ */ jsx("span", { className: "crewlet-nav-group__action-icon", "aria-hidden": true, children: action.icon }) }) : null
24
+ ] }) : null,
22
25
  children
23
26
  ]
24
27
  }
25
28
  );
26
29
  }
30
+ function Figure({ figure, className, mark }) {
31
+ return /* @__PURE__ */ jsx("span", { className, "aria-hidden": true, children: /* @__PURE__ */ jsxs("span", { className: "crewlet-nav-item__figure", children: [
32
+ mark ? /* @__PURE__ */ jsx("span", { className: "crewlet-nav-item__mark", children: mark }) : null,
33
+ figure.value
34
+ ] }) });
35
+ }
36
+ function spoken(figures) {
37
+ return figures.filter((figure) => figure !== void 0).map((figure) => `, ${String(figure.value)} ${figure.label}`).join("");
38
+ }
27
39
  function NavItem({
28
40
  label,
29
41
  icon,
42
+ lead,
43
+ count,
30
44
  badge,
31
- badgeTone = "neutral",
32
45
  href,
33
46
  current = false,
34
47
  disabledReason,
@@ -53,8 +66,14 @@ function NavItem({
53
66
  }
54
67
  const inside = /* @__PURE__ */ jsxs(Fragment, { children: [
55
68
  icon ? /* @__PURE__ */ jsx("span", { className: "crewlet-nav-item__icon", "aria-hidden": true, children: icon }) : null,
56
- /* @__PURE__ */ jsx("span", { className: "crewlet-nav-item__label", children: label }),
57
- badge ? /* @__PURE__ */ jsx("span", { className: cx("crewlet-nav-item__badge", badgeTone === "attention" && "crewlet-nav-item__badge--attention"), children: badge }) : null
69
+ lead ? /* @__PURE__ */ jsx("span", { className: "crewlet-nav-item__lead", children: lead }) : null,
70
+ lead ? " " : null,
71
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-nav-item__label", children: [
72
+ label,
73
+ count || badge ? /* @__PURE__ */ jsx(VisuallyHidden, { children: spoken([count, badge]) }) : null
74
+ ] }),
75
+ count ? /* @__PURE__ */ jsx(Figure, { figure: count, mark: count.mark, className: "crewlet-nav-item__count" }) : null,
76
+ badge ? /* @__PURE__ */ jsx(Figure, { figure: badge, className: "crewlet-nav-item__badge" }) : null
58
77
  ] });
59
78
  const rowClass = "crewlet-nav-item__row";
60
79
  let row;
@@ -96,7 +115,7 @@ function NavItem({
96
115
  },
97
116
  children: [
98
117
  inside,
99
- nested ? /* @__PURE__ */ jsx("span", { className: cx("crewlet-nav-item__chevron", open && "crewlet-nav-item__chevron--open"), "aria-hidden": true, children: /* @__PURE__ */ jsx(KeyboardArrowDownGlyph, { size: "sm" }) }) : null
118
+ nested ? /* @__PURE__ */ jsx("span", { className: cx("crewlet-nav-item__chevron", open && "crewlet-nav-item__chevron--open"), "aria-hidden": true, children: /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "sm" }) }) : null
100
119
  ]
101
120
  }
102
121
  );
@@ -120,7 +139,7 @@ function NavItem({
120
139
  "aria-controls": `${id}-children`,
121
140
  "aria-label": expandLabel ?? (typeof label === "string" ? `${label} sections` : "Sections"),
122
141
  onClick: toggle,
123
- children: /* @__PURE__ */ jsx("span", { className: cx("crewlet-nav-item__chevron", open && "crewlet-nav-item__chevron--open"), "aria-hidden": true, children: /* @__PURE__ */ jsx(KeyboardArrowDownGlyph, { size: "sm" }) })
142
+ children: /* @__PURE__ */ jsx("span", { className: cx("crewlet-nav-item__chevron", open && "crewlet-nav-item__chevron--open"), "aria-hidden": true, children: /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "sm" }) })
124
143
  }
125
144
  ) : null
126
145
  ] }),
@@ -1,14 +1,14 @@
1
- import { Select } from './chunk-OFHBK7RI.js';
2
- import { Popover } from './chunk-DD5BBGBE.js';
1
+ import { Select } from './chunk-SJQ546ID.js';
2
+ import { Popover } from './chunk-AUS5FNQE.js';
3
3
  import { today, shiftMonth, CalendarGrid, compareDays } from './chunk-GXQ3B46I.js';
4
- import { Input } from './chunk-O6232G37.js';
5
- import { isComposing } from './chunk-ITHXJHBB.js';
6
- import { IconButton } from './chunk-F27EPQ7D.js';
7
- import { Button } from './chunk-BZYDZBAN.js';
4
+ import { Input } from './chunk-DSUY5F4E.js';
5
+ import { isComposing } from './chunk-R25RGPUB.js';
6
+ import { IconButton } from './chunk-4UQ7SMPK.js';
7
+ import { Button } from './chunk-ETYEBKR4.js';
8
8
  import { cx } from './chunk-ODEQTPFM.js';
9
9
  import './TimeWindowPicker-7I7KWCMU.css';
10
10
  import { useMemo, useState, useRef, useId, useEffect } from 'react';
11
- import { ScheduleGlyph, KeyboardArrowDownGlyph, CheckGlyph, ChevronLeftGlyph, ChevronRightGlyph } from '@crewlethq/icons/glyphs';
11
+ import { ClockGlyph, ChevronDownGlyph, CheckGlyph, ChevronLeftGlyph, ChevronRightGlyph } from '@crewlethq/icons/glyphs';
12
12
  import { jsx, jsxs } from 'react/jsx-runtime';
13
13
 
14
14
  // src/TimeWindowPicker/mask.ts
@@ -354,9 +354,9 @@ function TimeWindowPicker({
354
354
  "aria-expanded": open,
355
355
  "aria-label": labels.triggerName(ariaLabel, shown),
356
356
  children: [
357
- /* @__PURE__ */ jsx(ScheduleGlyph, { className: "crewlet-time-window__icon", size: "sm" }),
357
+ /* @__PURE__ */ jsx(ClockGlyph, { className: "crewlet-time-window__icon", size: "sm" }),
358
358
  /* @__PURE__ */ jsx("span", { className: cx("crewlet-time-window__label", !isSet && "is-placeholder"), children: shown }),
359
- /* @__PURE__ */ jsx(KeyboardArrowDownGlyph, { className: "crewlet-time-window__chevron", size: "sm" })
359
+ /* @__PURE__ */ jsx(ChevronDownGlyph, { className: "crewlet-time-window__chevron", size: "sm" })
360
360
  ]
361
361
  }
362
362
  ),
@@ -438,12 +438,12 @@ function Panel({
438
438
  Button,
439
439
  {
440
440
  size: "small",
441
- variant: "tertiary",
441
+ variant: "ghost",
442
442
  onClick: () => setDraft(normalise(defaultValue)),
443
443
  children: labels.resetLabel
444
444
  }
445
445
  ) : null,
446
- /* @__PURE__ */ jsx(Button, { size: "small", variant: "tertiary", onClick: close, children: labels.cancelLabel }),
446
+ /* @__PURE__ */ jsx(Button, { size: "small", variant: "ghost", onClick: close, children: labels.cancelLabel }),
447
447
  /* @__PURE__ */ jsx(
448
448
  Button,
449
449
  {
@@ -0,0 +1,121 @@
1
+ import { useSyncExternalStore, useCallback, useEffect } from 'react';
2
+
3
+ // src/ThemeSwitcher/preferences.ts
4
+ var THEMES = ["system", "light", "dark"];
5
+ var DENSITIES = ["normal", "compact", "comfortable"];
6
+ function read(key, allowed, fallback) {
7
+ try {
8
+ const held2 = globalThis.localStorage?.getItem(key);
9
+ return allowed.includes(held2) ? held2 : fallback;
10
+ } catch {
11
+ return fallback;
12
+ }
13
+ }
14
+ function write(key, value) {
15
+ try {
16
+ const storage = globalThis.localStorage;
17
+ if (!storage) return false;
18
+ storage.setItem(key, value);
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+ var listeners = /* @__PURE__ */ new Map();
25
+ var unsaved = /* @__PURE__ */ new Map();
26
+ function held(key, allowed, fallback) {
27
+ const kept = unsaved.get(key);
28
+ if (kept !== void 0) return kept;
29
+ return read(key, allowed, fallback);
30
+ }
31
+ function keep(key, value) {
32
+ if (write(key, value)) unsaved.delete(key);
33
+ else unsaved.set(key, value);
34
+ for (const notify of listeners.get(key) ?? []) notify();
35
+ }
36
+ function subscribeTo(key, notify) {
37
+ let set = listeners.get(key);
38
+ if (!set) listeners.set(key, set = /* @__PURE__ */ new Set());
39
+ set.add(notify);
40
+ const fromElsewhere = (event) => {
41
+ if (event.key === key || event.key === null) notify();
42
+ };
43
+ const target = typeof window === "undefined" ? null : window;
44
+ target?.addEventListener("storage", fromElsewhere);
45
+ return () => {
46
+ set.delete(notify);
47
+ if (set.size === 0) listeners.delete(key);
48
+ target?.removeEventListener("storage", fromElsewhere);
49
+ };
50
+ }
51
+ function useStoredChoice(key, allowed, fallback, apply) {
52
+ const subscribe = useCallback((notify) => subscribeTo(key, notify), [key]);
53
+ const value = useSyncExternalStore(
54
+ subscribe,
55
+ () => held(key, allowed, fallback),
56
+ () => fallback
57
+ );
58
+ useEffect(() => {
59
+ apply(value);
60
+ }, [apply, value]);
61
+ const choose = useCallback(
62
+ (next) => {
63
+ apply(next);
64
+ keep(key, next);
65
+ },
66
+ [apply, key]
67
+ );
68
+ return [value, choose];
69
+ }
70
+ function root() {
71
+ return typeof document === "undefined" ? null : document.documentElement;
72
+ }
73
+ function applyTheme(theme) {
74
+ const el = root();
75
+ if (!el) return;
76
+ if (theme === "system") el.removeAttribute("data-theme");
77
+ else el.setAttribute("data-theme", theme);
78
+ }
79
+ function applyDensity(density) {
80
+ const el = root();
81
+ if (!el) return;
82
+ if (density === "normal") el.removeAttribute("data-density");
83
+ else el.setAttribute("data-density", density);
84
+ }
85
+ function useThemePreference({
86
+ storageKey
87
+ }) {
88
+ return useStoredChoice(storageKey, THEMES, "system", applyTheme);
89
+ }
90
+ function useDensityPreference({
91
+ storageKey
92
+ }) {
93
+ return useStoredChoice(storageKey, DENSITIES, "normal", applyDensity);
94
+ }
95
+ var LIGHT_SYSTEM = "(prefers-color-scheme: light)";
96
+ function systemLight() {
97
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(LIGHT_SYSTEM).matches : false;
98
+ }
99
+ function subscribeToSystem(notify) {
100
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {
101
+ };
102
+ const list = window.matchMedia(LIGHT_SYSTEM);
103
+ list.addEventListener("change", notify);
104
+ return () => list.removeEventListener("change", notify);
105
+ }
106
+ function useSystemTheme() {
107
+ const light = useSyncExternalStore(subscribeToSystem, systemLight, () => false);
108
+ return light ? "light" : "dark";
109
+ }
110
+ function resolveTheme(preference, system) {
111
+ return preference === "system" ? system : preference;
112
+ }
113
+ function applyStoredPreferences({ themeKey, densityKey }) {
114
+ const theme = themeKey ? held(themeKey, THEMES, "system") : "system";
115
+ const density = densityKey ? held(densityKey, DENSITIES, "normal") : "normal";
116
+ applyTheme(theme);
117
+ applyDensity(density);
118
+ return { theme, density };
119
+ }
120
+
121
+ export { applyDensity, applyStoredPreferences, applyTheme, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference };
@@ -1,8 +1,8 @@
1
- import { Tag } from './chunk-S2XHHEW4.js';
2
- import { useListbox } from './chunk-GTOUGQQK.js';
1
+ import { Tag } from './chunk-74KMX7YH.js';
2
+ import { useListbox } from './chunk-6MU7HNB4.js';
3
3
  import { announce } from './chunk-RSAQOKH3.js';
4
- import { isComposing } from './chunk-ITHXJHBB.js';
5
- import { IconButton } from './chunk-F27EPQ7D.js';
4
+ import { isComposing } from './chunk-R25RGPUB.js';
5
+ import { IconButton } from './chunk-4UQ7SMPK.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './TagsInput-W4P36PRJ.css';
8
8
  import { forwardRef, useState, useRef, useId, useImperativeHandle, useEffect, useMemo, useLayoutEffect } from 'react';
@@ -44,7 +44,6 @@ var TagsInput = forwardRef(function TagsInput2({
44
44
  const [open, setOpen] = useState(false);
45
45
  const field = useRef(null);
46
46
  const chips = useRef(null);
47
- const list = useRef(null);
48
47
  const generatedId = useId();
49
48
  const fieldId = id ?? generatedId;
50
49
  useImperativeHandle(ref, () => ({ focus: () => field.current?.focus() }));
@@ -87,9 +86,9 @@ var TagsInput = forwardRef(function TagsInput2({
87
86
  const want = wanted.current;
88
87
  if (!want) return;
89
88
  wanted.current = null;
90
- const list2 = chips.current;
89
+ const list = chips.current;
91
90
  const control = (index2, prefer) => {
92
- const chip = list2?.querySelector(`[data-chip="${index2}"]`);
91
+ const chip = list?.querySelector(`[data-chip="${index2}"]`);
93
92
  if (!chip) return null;
94
93
  const order = prefer === "remove" ? ["button:not([data-move])"] : prefer === "earlier" ? ['[data-move="earlier"]', '[data-move="later"]', "button:not([data-move])"] : ['[data-move="later"]', '[data-move="earlier"]', "button:not([data-move])"];
95
94
  for (const selector of order) {
@@ -155,15 +154,6 @@ var TagsInput = forwardRef(function TagsInput2({
155
154
  },
156
155
  onClose: () => setOpen(false)
157
156
  });
158
- useEffect(() => {
159
- const box = list.current;
160
- const row = box?.querySelector('[data-active="true"]');
161
- if (!box || !row) return;
162
- const bounds = box.getBoundingClientRect();
163
- const spot = row.getBoundingClientRect();
164
- if (spot.top < bounds.top) box.scrollTop -= bounds.top - spot.top;
165
- else if (spot.bottom > bounds.bottom) box.scrollTop += spot.bottom - bounds.bottom;
166
- }, [listbox.active, flat.length, lists]);
167
157
  function onKeyDown(event) {
168
158
  if (isComposing(event)) return;
169
159
  if (picking && !showing && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
@@ -330,10 +320,7 @@ var TagsInput = forwardRef(function TagsInput2({
330
320
  lists ? /* @__PURE__ */ jsx(
331
321
  "div",
332
322
  {
333
- ref: (el) => {
334
- list.current = el;
335
- listbox.listRef(el);
336
- },
323
+ ref: listbox.listRef,
337
324
  id: listbox.listId,
338
325
  className: "crewlet-tags-input__list crewlet-listbox",
339
326
  role: "listbox",
@@ -1,6 +1,7 @@
1
1
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './Kbd-W66MXQI5.css';
3
+ import './Kbd-JPLDVJIP.css';
4
+ import { Fragment } from 'react';
4
5
  import { jsx, jsxs } from 'react/jsx-runtime';
5
6
 
6
7
  function isApplePlatform() {
@@ -38,13 +39,17 @@ function keyGlyph(key, apple) {
38
39
  return { glyph: shown, spoken: shown };
39
40
  }
40
41
  var Kbd = ({ subtle = false, keys, apple, className, children, ...rest }) => {
42
+ const cap = cx("crewlet-kbd", subtle && "crewlet-kbd--subtle");
41
43
  if (keys === void 0) {
42
- return /* @__PURE__ */ jsx("kbd", { ...rest, className: cx("crewlet-kbd", subtle && "crewlet-kbd--subtle", className), children });
44
+ return /* @__PURE__ */ jsx("kbd", { ...rest, className: cx(cap, className), children });
43
45
  }
44
46
  const onApple = apple ?? isApplePlatform();
45
47
  const mapped = keys.map((key) => keyGlyph(key, onApple));
46
48
  return /* @__PURE__ */ jsxs("span", { ...rest, className: cx("crewlet-kbd-combo", className), children: [
47
- /* @__PURE__ */ jsx("span", { className: "crewlet-kbd-keys", "aria-hidden": true, children: mapped.map((key, index) => /* @__PURE__ */ jsx("kbd", { className: cx("crewlet-kbd", subtle && "crewlet-kbd--subtle"), children: key.glyph }, index)) }),
49
+ /* @__PURE__ */ jsx("kbd", { className: cap, "aria-hidden": true, children: mapped.map((key, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
50
+ index > 0 && !onApple ? "+" : null,
51
+ /* @__PURE__ */ jsx("kbd", { className: "crewlet-kbd__key", children: key.glyph })
52
+ ] }, index)) }),
48
53
  /* @__PURE__ */ jsx(VisuallyHidden, { children: mapped.map((key) => key.spoken).join(" plus ") })
49
54
  ] });
50
55
  };