@stackone/malachite 2.23.0 → 2.23.1

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.
@@ -1,22 +1,22 @@
1
- import { jsxs as X, jsx as u } from "react/jsx-runtime";
2
- import $, { useRef as Z, useState as bt, useCallback as L, useLayoutEffect as F } from "react";
3
- import Ft from "./CustomIcons/ArrowLeftIcon.js";
4
- import Ht from "./CustomIcons/ForwardArrowIcon.js";
5
- import Xt from "./CustomIcons/PlusIcon.js";
6
- import { CONTENT_INSET as mt } from "./PageLayout/constants.js";
7
- import { CARD_FLARE_PX as m, STRIP_RULE_PX as Wt, CARD_FLARE_TIP_PX as tt, CARD_WIDTH_PX as Mt, FLARE_CLASS as Yt } from "./SelectableCard.js";
8
- import { CardStripSlotContext as Rt, PINNED_SLOT as Vt, SCROLLED_SLOT as zt } from "./cardStripSlot.js";
9
- import { FOCUS_RING as Kt } from "./focusRing.js";
10
- import { useAdoptedStyleSheet as jt } from "./useAdoptedStyleSheet.js";
11
- const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End"]), I = '[role="radio"]', Zt = "data-card-strip-scroller", Jt = "data-card-strip-trough", W = "malachite-card-strip", R = "malachite-card-strip-scroller", Dt = "malachite-card-strip-fade", x = "malachite-card-strip-add-tile", Ot = "[data-selectable-card-actions]", Qt = 'a[href], area[href], button, input, select, textarea, iframe, [contenteditable="true"], [tabindex]', w = "data-card-strip-prev-tabindex", J = 1, te = 0.8, ee = (t) => {
1
+ import { jsxs as M, jsx as u } from "react/jsx-runtime";
2
+ import $, { useRef as H, useState as mt, useCallback as L, useLayoutEffect as X } from "react";
3
+ import Xt from "./CustomIcons/ArrowLeftIcon.js";
4
+ import Wt from "./CustomIcons/ForwardArrowIcon.js";
5
+ import Mt from "./CustomIcons/PlusIcon.js";
6
+ import { CONTENT_INSET as Rt } from "./PageLayout/constants.js";
7
+ import { CARD_FLARE_PX as m, STRIP_RULE_PX as Yt, CARD_FLARE_TIP_PX as et, CARD_WIDTH_PX as Vt, FLARE_CLASS as zt } from "./SelectableCard.js";
8
+ import { CardStripSlotContext as gt, PINNED_SLOT as Kt, SCROLLED_SLOT as jt } from "./cardStripSlot.js";
9
+ import { FOCUS_RING as qt } from "./focusRing.js";
10
+ import { useAdoptedStyleSheet as Zt } from "./useAdoptedStyleSheet.js";
11
+ const Jt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End"]), I = '[role="radio"]', Qt = "data-card-strip-scroller", te = "data-card-strip-trough", Y = "malachite-card-strip", R = "malachite-card-strip-scroller", wt = "malachite-card-strip-fade", x = "malachite-card-strip-add-tile", Ct = "[data-selectable-card-actions]", ee = 'a[href], area[href], button, input, select, textarea, iframe, [contenteditable="true"], [tabindex]', C = "data-card-strip-prev-tabindex", Q = 1, re = 0.8, ne = (t) => {
12
12
  const [r, c] = Array.from(t.children), s = r && c ? c.getBoundingClientRect().left - r.getBoundingClientRect().left : (r == null ? void 0 : r.getBoundingClientRect().width) ?? 0, i = t.clientWidth - m * 2;
13
- return s <= 0 ? i * te : Math.max(1, Math.floor(i / s)) * s;
14
- }, re = 80, ne = 20, gt = 11, T = 12, P = 52, oe = (P + ne) / 2, Ct = "var(--malachite-shadow-default)", ae = "var(--malachite-card-strip-arrow-background, var(--malachite-card-background, #ffffff))", ce = "var(--malachite-card-strip-arrow-border, #e8e8e8)", et = "var(--malachite-card-strip-background, #f1f1f1)", _t = "var(--malachite-radius-xxl, 14px)", se = `${_t} ${_t} 0 0`, At = "var(--malachite-radius-xxxl, 16px)", ie = `${At} ${At} 0 0`, M = 4, xt = re + (m - M), le = Mt, de = "var(--malachite-card-strip-divider, #dddddd)", St = "var(--malachite-card-strip-fade, transparent)", ue = "var(--malachite-selectable-card-hover-background, #e8e8e8)", fe = "var(--malachite-card-strip-arrow-border, #e8e8e8)", Et = "var(--malachite-selectable-card-hover-rule, #bbbbbb)", Lt = "0px 1px 0px 0px rgba(0, 0, 0, 0.4)", pe = "var(--malachite-card-background, #ffffff)", he = "var(--malachite-text-primary, #0a0a0a)", be = "var(--malachite-card-strip-add-primary-background, var(--malachite-text-primary, #0a0a0a))", me = "var(--malachite-card-strip-add-primary-foreground, var(--malachite-card-background, #ffffff))", Re = "0px 1px 0px 0px rgba(10, 10, 10, 0.7)", nt = Wt, $t = 16, H = 9999, ge = 4, _e = `
15
- .${W} {
16
- clip-path: inset(-${H}px -${H}px 0);
13
+ return s <= 0 ? i * re : Math.max(1, Math.floor(i / s)) * s;
14
+ }, oe = 80, ae = 20, _t = 11, T = 12, P = 52, ce = (P + ae) / 2, It = "var(--malachite-shadow-default)", se = "var(--malachite-card-strip-arrow-background, var(--malachite-card-background, #ffffff))", ie = "var(--malachite-card-strip-arrow-border, #e8e8e8)", rt = "var(--malachite-card-strip-background, #f1f1f1)", At = "var(--malachite-radius-xxl, 14px)", le = `${At} ${At} 0 0`, xt = "var(--malachite-radius-xxxl, 16px)", de = `${xt} ${xt} 0 0`, V = 4, St = oe + (m - V), ue = Vt, fe = "var(--malachite-card-strip-divider, #dddddd)", Et = "var(--malachite-card-strip-fade, transparent)", pe = "var(--malachite-selectable-card-hover-background, #e8e8e8)", he = "var(--malachite-card-strip-arrow-border, #e8e8e8)", Lt = "var(--malachite-selectable-card-hover-rule, #bbbbbb)", $t = "0px 1px 0px 0px rgba(0, 0, 0, 0.4)", be = "var(--malachite-card-background, #ffffff)", me = "var(--malachite-text-primary, #0a0a0a)", Re = "var(--malachite-card-strip-add-primary-background, var(--malachite-text-primary, #0a0a0a))", ge = "var(--malachite-card-strip-add-primary-foreground, var(--malachite-card-background, #ffffff))", _e = "0px 1px 0px 0px rgba(10, 10, 10, 0.7)", ot = Yt, Tt = 16, W = 9999, Ae = 4, xe = `
15
+ .${Y} {
16
+ clip-path: inset(-${W}px -${W}px 0);
17
17
  }
18
- .${W}:has(:focus-visible) {
19
- clip-path: inset(-${H}px -${H}px -${ge}px);
18
+ .${Y}:has(:focus-visible) {
19
+ clip-path: inset(-${W}px -${W}px -${Ae}px);
20
20
  }
21
21
  .${R} {
22
22
  display: flex;
@@ -26,8 +26,8 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
26
26
  scroll-behavior: smooth;
27
27
  scrollbar-width: none;
28
28
  -ms-overflow-style: none;
29
- padding-block: ${$t}px;
30
- margin-block: -${$t}px;
29
+ padding-block: ${Tt}px;
30
+ margin-block: -${Tt}px;
31
31
  /* overflow-x clips both axes, so the end cards would lose a flare; the negative margin trades
32
32
  the padding back out and scroll-padding keeps the rest position at zero. */
33
33
  padding-inline: ${m}px;
@@ -35,7 +35,7 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
35
35
  scroll-padding-inline: ${m}px;
36
36
  }
37
37
  /* A card focused at a faded edge has to stay readable, so the fade lifts entirely. */
38
- .${W}:has(:focus-visible) .${Dt} {
38
+ .${Y}:has(:focus-visible) .${wt} {
39
39
  display: none;
40
40
  }
41
41
  .${R}::-webkit-scrollbar {
@@ -43,40 +43,40 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
43
43
  }
44
44
  /* No bottom edge: the strip's rule is the baseline for the add tile as much as for a card. */
45
45
  .${x} > * {
46
- background: ${et};
47
- border-radius: ${se};
46
+ background: ${rt};
47
+ border-radius: ${le};
48
48
  }
49
49
  .${x}:hover:not(:has(button:disabled)) > * {
50
- background: ${ue};
50
+ background: ${pe};
51
51
  }
52
52
  .${x} button:active:not(:disabled) {
53
53
  opacity: 0.8;
54
54
  }
55
55
  .${x}:has(button:active) > * {
56
- background: ${et};
56
+ background: ${rt};
57
57
  }
58
58
  .${x}[data-emphasis='secondary'] button {
59
- border-color: ${fe};
60
- box-shadow: ${Ct};
59
+ border-color: ${he};
60
+ box-shadow: ${It};
61
61
  }
62
62
  .${x}[data-emphasis='secondary']:hover:not(:has(button:disabled)) button {
63
- border-color: ${Et};
64
- box-shadow: ${Lt};
63
+ border-color: ${Lt};
64
+ box-shadow: ${$t};
65
65
  }
66
66
  .${x}[data-emphasis='secondary'] button:active:not(:disabled) {
67
- border-color: ${Et};
68
- box-shadow: ${Lt};
67
+ border-color: ${Lt};
68
+ box-shadow: ${$t};
69
69
  }
70
70
  .${x}[data-emphasis='primary'] button {
71
71
  border-color: transparent;
72
- box-shadow: ${Re};
72
+ box-shadow: ${_e};
73
73
  }
74
74
  .${R} > * {
75
75
  flex: 0 0 auto;
76
76
  min-width: 0;
77
77
  }
78
78
  .${R} > * + * {
79
- border-left: 1px solid ${de};
79
+ border-left: 1px solid ${fe};
80
80
  }
81
81
  .${R}[data-snap='true'] {
82
82
  scroll-snap-type: x proximity;
@@ -94,14 +94,14 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
94
94
  .${R}[data-snap='true'] > * {
95
95
  scroll-snap-align: none;
96
96
  }
97
- }`, Ae = "malachite-card-strip-style", xe = () => typeof window > "u" || typeof window.matchMedia != "function" ? !0 : window.matchMedia("(prefers-reduced-motion: reduce)").matches, A = (t) => t.dataset.value ?? t.getAttribute("value"), Q = (t) => t.hasAttribute("disabled") || t.getAttribute("aria-disabled") === "true", Se = (t) => {
97
+ }`, Se = "malachite-card-strip-style", vt = () => typeof window > "u" || typeof window.matchMedia != "function" ? !0 : window.matchMedia("(prefers-reduced-motion: reduce)").matches, A = (t) => t.dataset.value ?? t.getAttribute("value"), tt = (t) => t.hasAttribute("disabled") || t.getAttribute("aria-disabled") === "true", Ee = (t) => {
98
98
  const r = t.parentElement;
99
- return !r || r.querySelectorAll(I).length !== 1 ? null : r.querySelector(Ot);
100
- }, Ee = (t, r) => {
99
+ return !r || r.querySelectorAll(I).length !== 1 ? null : r.querySelector(Ct);
100
+ }, Le = (t, r) => {
101
101
  const c = t.closest(I);
102
102
  if (c)
103
103
  return c;
104
- if (t.closest(Ot))
104
+ if (t.closest(Ct))
105
105
  return null;
106
106
  let s = t;
107
107
  for (; s && r.contains(s); ) {
@@ -111,63 +111,63 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
111
111
  s = s.parentElement;
112
112
  }
113
113
  return null;
114
- }, Le = (t) => {
115
- const r = Se(t);
116
- return r ? Array.from(r.querySelectorAll(Qt)) : [];
117
114
  }, $e = (t) => {
118
- t.hasAttribute(w) || t.setAttribute(w, t.getAttribute("tabindex") ?? ""), t.setAttribute("tabindex", "-1");
115
+ const r = Ee(t);
116
+ return r ? Array.from(r.querySelectorAll(ee)) : [];
119
117
  }, Te = (t) => {
120
- if (!t.hasAttribute(w))
118
+ t.hasAttribute(C) || t.setAttribute(C, t.getAttribute("tabindex") ?? ""), t.setAttribute("tabindex", "-1");
119
+ }, ve = (t) => {
120
+ if (!t.hasAttribute(C))
121
121
  return;
122
- const r = t.getAttribute(w);
123
- t.removeAttribute(w), r ? t.setAttribute("tabindex", r) : t.removeAttribute("tabindex");
124
- }, ve = {
122
+ const r = t.getAttribute(C);
123
+ t.removeAttribute(C), r ? t.setAttribute("tabindex", r) : t.removeAttribute("tabindex");
124
+ }, ye = {
125
125
  profile: "var(--malachite-selectable-card-selected-border, #047b43)",
126
126
  library: "var(--malachite-selectable-card-library-selected-border, #bbbbbb)",
127
127
  editing: "var(--malachite-selectable-card-pending-foreground, #96580a)"
128
- }, ye = {
128
+ }, De = {
129
129
  backgroundRepeat: "no-repeat",
130
130
  backgroundPosition: "left bottom",
131
- backgroundSize: `100% ${nt}px`
132
- }, Tt = 0.5, vt = m - tt, De = (t) => {
133
- const r = t.querySelector(`:scope > .${Yt}`);
131
+ backgroundSize: `100% ${ot}px`
132
+ }, yt = 0.5, Dt = m - et, Oe = (t) => {
133
+ const r = t.querySelector(`:scope > .${zt}`);
134
134
  if (!r)
135
135
  return null;
136
136
  const { left: c, right: s } = r.getBoundingClientRect();
137
- return { left: c + vt, right: s - vt };
138
- }, Oe = (t, r, c, s) => {
137
+ return { left: c + Dt, right: s - Dt };
138
+ }, we = (t, r, c, s) => {
139
139
  if (!t)
140
140
  return;
141
- const i = ve[s], S = t.getBoundingClientRect(), v = S.left, k = c && (r != null && r.contains(c)) ? r.getBoundingClientRect() : S, E = c == null ? void 0 : c.getBoundingClientRect(), g = c ? De(c) : null, V = (g == null ? void 0 : g.left) ?? (E ? E.left - tt : 0), z = (g == null ? void 0 : g.right) ?? (E ? E.right + tt : 0), y = E ? Math.max(V, k.left) + Tt - v : 0, b = E ? Math.min(z, k.right) - Tt - v : 0;
141
+ const i = ye[s], S = t.getBoundingClientRect(), v = S.left, k = c && (r != null && r.contains(c)) ? r.getBoundingClientRect() : S, E = c == null ? void 0 : c.getBoundingClientRect(), g = c ? Oe(c) : null, K = (g == null ? void 0 : g.left) ?? (E ? E.left - et : 0), j = (g == null ? void 0 : g.right) ?? (E ? E.right + et : 0), y = E ? Math.max(K, k.left) + yt - v : 0, b = E ? Math.min(j, k.right) - yt - v : 0;
142
142
  t.style.backgroundImage = b > y ? `linear-gradient(to right, ${i} 0 ${y}px, transparent ${y}px ${b}px, ${i} ${b}px 100%)` : `linear-gradient(to right, ${i} 0 100%)`;
143
143
  }, Ce = {
144
- marginInline: `calc(${mt} * -1)`,
145
- paddingInline: mt
146
- }, Y = {
147
- background: et,
148
- borderRadius: ie,
149
- paddingTop: `${M}px`,
150
- paddingInline: `${M}px`,
151
- marginBottom: `${nt}px`
152
- }, we = {
153
- ...Y,
144
+ marginInline: `calc(${Rt} * -1)`,
145
+ paddingInline: Rt
146
+ }, z = {
147
+ background: rt,
148
+ borderRadius: de,
149
+ paddingTop: `${V}px`,
150
+ paddingInline: `${V}px`,
151
+ marginBottom: `${ot}px`
152
+ }, Ie = {
153
+ ...z,
154
154
  marginInline: `${T}px`
155
- }, Ie = Object.fromEntries(
155
+ }, Pe = Object.fromEntries(
156
156
  [T, P].flatMap(
157
157
  (t) => [T, P].map((r) => [
158
158
  `${t}:${r}`,
159
- { ...Y, marginInline: `${t}px ${r}px` }
159
+ { ...z, marginInline: `${t}px ${r}px` }
160
160
  ])
161
161
  )
162
- ), Pe = Y, ke = Y, Ne = {
162
+ ), ke = z, Ne = z, Ue = {
163
163
  marginInlineStart: `${T}px`
164
- }, Ue = {
164
+ }, Be = {
165
165
  primary: {
166
- backgroundColor: be,
167
- color: me
166
+ backgroundColor: Re,
167
+ color: ge
168
168
  },
169
- secondary: { backgroundColor: pe, color: he }
170
- }, wt = ({
169
+ secondary: { backgroundColor: be, color: me }
170
+ }, Pt = ({
171
171
  label: t,
172
172
  icon: r,
173
173
  onClick: c,
@@ -180,26 +180,26 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
180
180
  className: x,
181
181
  "data-emphasis": i,
182
182
  style: {
183
- ...Pe,
184
- width: `${le}px`,
185
- height: `calc(100% - ${nt}px)`
183
+ ...ke,
184
+ width: `${ue}px`,
185
+ height: `calc(100% - ${ot}px)`
186
186
  },
187
- children: /* @__PURE__ */ u("div", { className: "flex h-full items-center justify-center px-4", children: /* @__PURE__ */ X(
187
+ children: /* @__PURE__ */ u("div", { className: "flex h-full items-center justify-center px-4", children: /* @__PURE__ */ M(
188
188
  "button",
189
189
  {
190
190
  type: "button",
191
191
  onClick: c,
192
192
  disabled: s,
193
- style: Ue[i],
194
- className: `${Kt} inline-flex items-center justify-center gap-1.5 h-[var(--malachite-control-height-medium,32px)] w-[108px] px-2.5 rounded-xl border border-solid text-[length:var(--malachite-font-size-small,13px)] font-medium whitespace-nowrap ${s ? "opacity-50 cursor-not-allowed" : "cursor-pointer"} ${S}`,
193
+ style: Be[i],
194
+ className: `${qt} inline-flex items-center justify-center gap-1.5 h-[var(--malachite-control-height-medium,32px)] w-[108px] px-2.5 rounded-xl border border-solid text-[length:var(--malachite-font-size-small,13px)] font-medium whitespace-nowrap ${s ? "opacity-50 cursor-not-allowed" : "cursor-pointer"} ${S}`,
195
195
  children: [
196
- /* @__PURE__ */ u("span", { className: "inline-flex h-[13px] w-[13px] shrink-0 items-center justify-center", children: r ?? /* @__PURE__ */ u(Xt, { size: 13 }) }),
196
+ /* @__PURE__ */ u("span", { className: "inline-flex h-[13px] w-[13px] shrink-0 items-center justify-center", children: r ?? /* @__PURE__ */ u(Mt, { size: 13 }) }),
197
197
  t
198
198
  ]
199
199
  }
200
200
  ) })
201
201
  }
202
- ), rt = (t) => $.isValidElement(t) && t.type === wt, Be = (t) => $.isValidElement(t) && t.type === $.Fragment && $.Children.toArray(t.props.children).some(rt), yt = ({ side: t, onClick: r }) => /* @__PURE__ */ u(
202
+ ), nt = (t) => $.isValidElement(t) && t.type === Pt, Ge = (t) => $.isValidElement(t) && t.type === $.Fragment && $.Children.toArray(t.props.children).some(nt), Ot = ({ side: t, onClick: r }) => /* @__PURE__ */ u(
203
203
  "button",
204
204
  {
205
205
  type: "button",
@@ -209,14 +209,14 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
209
209
  onClick: r,
210
210
  className: "absolute top-1/2 -translate-y-1/2 z-10 inline-flex items-center justify-center w-5 h-5 rounded-lg cursor-pointer text-[var(--malachite-text-secondary)]",
211
211
  style: {
212
- [t]: `-${oe}px`,
213
- background: ae,
214
- border: `1px solid ${ce}`,
215
- boxShadow: Ct
212
+ [t]: `-${ce}px`,
213
+ background: se,
214
+ border: `1px solid ${ie}`,
215
+ boxShadow: It
216
216
  },
217
- children: t === "left" ? /* @__PURE__ */ u(Ft, { size: gt }) : /* @__PURE__ */ u(Ht, { size: gt })
217
+ children: t === "left" ? /* @__PURE__ */ u(Xt, { size: _t }) : /* @__PURE__ */ u(Wt, { size: _t })
218
218
  }
219
- ), Ge = ({
219
+ ), Fe = ({
220
220
  value: t,
221
221
  tone: r,
222
222
  onChange: c,
@@ -227,95 +227,95 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
227
227
  snap: k = !0,
228
228
  bleed: E = !1,
229
229
  scrollSelectedIntoView: g = !0,
230
- "aria-label": V,
231
- "aria-labelledby": z,
230
+ "aria-label": K,
231
+ "aria-labelledby": j,
232
232
  className: y = "",
233
233
  style: b
234
234
  }) => {
235
- const D = Z(null), O = Z(null), [N, It] = bt({ canScrollLeft: !1, canScrollRight: !1 });
236
- jt(D, _e, Ae);
237
- const K = $.Children.toArray(s), j = K.filter((e) => !rt(e)), Pt = j.some(Be), U = j.length > 0, ot = K.filter(rt).map(
235
+ const D = H(null), O = H(null), at = H(!1), [N, kt] = mt({ canScrollLeft: !1, canScrollRight: !1 });
236
+ Zt(D, xe, Se);
237
+ const q = $.Children.toArray(s), Z = q.filter((e) => !nt(e)), Nt = Z.some(Ge), U = Z.length > 0, ct = q.filter(nt).map(
238
238
  (e) => e.props.emphasis === void 0 ? $.cloneElement(e, { emphasis: U ? "secondary" : "primary" }) : e
239
- ), at = K.length, _ = L(() => {
239
+ ), st = q.length, _ = L(() => {
240
240
  const e = D.current;
241
241
  return e ? Array.from(e.querySelectorAll(I)) : [];
242
- }, []), q = L(
242
+ }, []), J = L(
243
243
  () => _().filter((e) => A(e) !== null),
244
244
  [_]
245
- ), ct = Z(/* @__PURE__ */ new Set()), C = L((e, n) => {
246
- ct.current.has(e) || (ct.current.add(e), console.warn(n));
247
- }, []), [kt, Nt] = bt("profile");
248
- F(() => {
245
+ ), it = H(/* @__PURE__ */ new Set()), w = L((e, n) => {
246
+ it.current.has(e) || (it.current.add(e), console.warn(n));
247
+ }, []), [Ut, Bt] = mt("profile");
248
+ X(() => {
249
249
  var n, a;
250
250
  const e = (a = (n = _().find((d) => A(d) === t)) == null ? void 0 : n.parentElement) == null ? void 0 : a.getAttribute("data-variant");
251
- (e === "profile" || e === "library" || e === "editing") && Nt(e);
252
- }, [_, t]), F(() => {
253
- const e = _(), n = q(), d = n.find((o) => A(o) === t) ?? n.find((o) => !Q(o)) ?? null;
251
+ (e === "profile" || e === "library" || e === "editing") && Bt(e);
252
+ }, [_, t]), X(() => {
253
+ const e = _(), n = J(), d = n.find((o) => A(o) === t) ?? n.find((o) => !tt(o)) ?? null;
254
254
  if (e.forEach((o) => {
255
255
  const h = o === d, G = h ? 0 : -1;
256
256
  o.tabIndex !== G && (o.tabIndex = G);
257
- for (const ht of Le(o))
258
- h ? Te(ht) : $e(ht);
257
+ for (const F of $e(o))
258
+ h ? ve(F) : Te(F);
259
259
  }), process.env.NODE_ENV === "production")
260
260
  return;
261
- n.length !== e.length && C(
261
+ n.length !== e.length && w(
262
262
  "missing-value",
263
263
  'CardStrip: a child with role="radio" has no `data-value`. It cannot be selected or reached by arrow keys, so it is excluded from the radio set. Give every card a `data-value`.'
264
264
  );
265
265
  const l = /* @__PURE__ */ new Set();
266
266
  for (const o of n) {
267
267
  const h = A(o);
268
- h !== null && (l.has(h) && C(
268
+ h !== null && (l.has(h) && w(
269
269
  `duplicate:${h}`,
270
270
  `CardStrip: two cards share the data-value "${h}". Both will read as checked and only the first is selectable — data-value must be unique.`
271
271
  ), l.add(h));
272
272
  }
273
273
  const p = t !== "";
274
- e.length > 0 && p && !l.has(t) && C(
274
+ e.length > 0 && p && !l.has(t) && w(
275
275
  `unmatched:${t}`,
276
276
  `CardStrip: value "${t}" matches no card's data-value, so the group reports no selection.`
277
277
  );
278
278
  const f = e.filter(
279
279
  (o) => o.getAttribute("aria-checked") === "true"
280
280
  ).length;
281
- e.length > 0 && p && f !== 1 && C(
281
+ e.length > 0 && p && f !== 1 && w(
282
282
  `checked:${f}`,
283
283
  `CardStrip: ${f} cards are aria-checked, but a radiogroup has exactly one. Drive each card's checked state from the strip's \`value\`.`
284
- ), Pt && C(
284
+ ), Nt && w(
285
285
  "wrapped-add-tile",
286
286
  "CardStrip: a CardStrip.AddTile inside a fragment is treated as a card and scrolls with them. The add tile must be a direct child of CardStrip."
287
287
  );
288
- }), F(() => {
288
+ }), X(() => {
289
289
  if (!g)
290
290
  return;
291
- const e = O.current, n = _().find((G) => A(G) === t);
291
+ const e = O.current, n = _().find((F) => A(F) === t);
292
292
  if (!e || !n || typeof e.scrollTo != "function")
293
293
  return;
294
- const d = (n.closest('[role="radio"]') ?? n).getBoundingClientRect(), l = e.getBoundingClientRect(), p = e.scrollLeft + (d.left - l.left), f = p + d.width, o = e.scrollLeft + m, h = e.scrollLeft + e.clientWidth - m;
295
- p >= o && f <= h || e.scrollTo({
294
+ const d = (n.closest('[role="radio"]') ?? n).getBoundingClientRect(), l = e.getBoundingClientRect(), p = e.scrollLeft + (d.left - l.left), f = p + d.width, o = e.scrollLeft + m, h = e.scrollLeft + e.clientWidth - m, G = at.current;
295
+ at.current = !0, !(p >= o && f <= h) && e.scrollTo({
296
296
  left: f > h ? f - e.clientWidth + m : p - m,
297
- behavior: "instant"
297
+ behavior: G && !vt() ? "smooth" : "instant"
298
298
  });
299
- }, [_, g, t, at]);
300
- const st = r ?? kt, it = (b == null ? void 0 : b.background) !== void 0 || (b == null ? void 0 : b.backgroundImage) !== void 0, B = L(() => {
299
+ }, [_, g, t, st]);
300
+ const lt = r ?? Ut, dt = (b == null ? void 0 : b.background) !== void 0 || (b == null ? void 0 : b.backgroundImage) !== void 0, B = L(() => {
301
301
  var f;
302
302
  const e = O.current;
303
- if (it || Oe(
303
+ if (dt || we(
304
304
  D.current,
305
305
  e,
306
306
  (f = _().find((o) => A(o) === t)) == null ? void 0 : f.parentElement,
307
- st
307
+ lt
308
308
  ), !e)
309
309
  return;
310
- const { scrollWidth: n, clientWidth: a, scrollLeft: d } = e, l = n > a + J, p = {
311
- canScrollLeft: l && d > J,
312
- canScrollRight: l && d + a < n - J
310
+ const { scrollWidth: n, clientWidth: a, scrollLeft: d } = e, l = n > a + Q, p = {
311
+ canScrollLeft: l && d > Q,
312
+ canScrollRight: l && d + a < n - Q
313
313
  };
314
- It(
314
+ kt(
315
315
  (o) => o.canScrollLeft === p.canScrollLeft && o.canScrollRight === p.canScrollRight ? o : p
316
316
  );
317
- }, [it, _, st, t]);
318
- F(() => {
317
+ }, [dt, _, lt, t]);
318
+ X(() => {
319
319
  B();
320
320
  const e = O.current;
321
321
  if (!e)
@@ -326,21 +326,21 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
326
326
  return a == null || a.observe(e), () => {
327
327
  e.removeEventListener("scroll", n), a == null || a.disconnect();
328
328
  };
329
- }, [B, at]);
330
- const lt = L((e) => {
329
+ }, [B, st]);
330
+ const ut = L((e) => {
331
331
  const n = O.current;
332
332
  !n || typeof n.scrollBy != "function" || n.scrollBy({
333
- left: e * ee(n),
334
- behavior: xe() ? "auto" : "smooth"
333
+ left: e * ne(n),
334
+ behavior: vt() ? "auto" : "smooth"
335
335
  });
336
- }, []), Ut = L(
336
+ }, []), Gt = L(
337
337
  (e) => {
338
- if (!qt.has(e.key))
338
+ if (!Jt.has(e.key))
339
339
  return;
340
340
  const n = e.target;
341
341
  if (!(n instanceof Element) || !n.closest(I))
342
342
  return;
343
- const a = q().filter((o) => !Q(o));
343
+ const a = J().filter((o) => !tt(o));
344
344
  if (a.length === 0)
345
345
  return;
346
346
  e.preventDefault();
@@ -357,8 +357,8 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
357
357
  const p = a[l], f = A(p);
358
358
  f !== null && f !== t && c(f), p.focus();
359
359
  },
360
- [q, c, t]
361
- ), Bt = L(
360
+ [J, c, t]
361
+ ), Ft = L(
362
362
  (e) => {
363
363
  const n = e.target;
364
364
  if (!(n instanceof Element))
@@ -366,65 +366,65 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
366
366
  const a = D.current;
367
367
  if (!a)
368
368
  return;
369
- const d = Ee(n, a);
370
- if (!d || Q(d))
369
+ const d = Le(n, a);
370
+ if (!d || tt(d))
371
371
  return;
372
372
  const l = A(d);
373
373
  l !== null && l !== t && c(l);
374
374
  },
375
375
  [c, t]
376
- ), dt = S && N.canScrollLeft, ut = S && N.canScrollRight, ft = v && N.canScrollLeft, pt = v && N.canScrollRight, Gt = S ? Ie[`${dt ? P : T}:${ut ? P : T}`] : we;
377
- return /* @__PURE__ */ X(
376
+ ), ft = S && N.canScrollLeft, pt = S && N.canScrollRight, ht = v && N.canScrollLeft, bt = v && N.canScrollRight, Ht = S ? Pe[`${ft ? P : T}:${pt ? P : T}`] : Ie;
377
+ return /* @__PURE__ */ M(
378
378
  "div",
379
379
  {
380
380
  ref: D,
381
- onKeyDown: Ut,
382
- onClick: Bt,
383
- className: `${W} flex items-stretch ${y}`,
381
+ onKeyDown: Gt,
382
+ onClick: Ft,
383
+ className: `${Y} flex items-stretch ${y}`,
384
384
  style: {
385
- ...ye,
385
+ ...De,
386
386
  ...E ? Ce : null,
387
387
  ...b
388
388
  },
389
389
  children: [
390
- /* @__PURE__ */ X(
390
+ /* @__PURE__ */ M(
391
391
  "div",
392
392
  {
393
393
  role: "radiogroup",
394
- "aria-label": V,
395
- "aria-labelledby": z,
394
+ "aria-label": K,
395
+ "aria-labelledby": j,
396
396
  className: U ? "flex items-stretch min-w-0" : "flex items-stretch",
397
397
  children: [
398
- i ? /* @__PURE__ */ u(Rt.Provider, { value: Vt, children: /* @__PURE__ */ u("div", { className: "shrink-0", style: ke, children: i }) }) : null,
399
- U ? /* @__PURE__ */ X(
398
+ i ? /* @__PURE__ */ u(gt.Provider, { value: Kt, children: /* @__PURE__ */ u("div", { className: "shrink-0", style: Ne, children: i }) }) : null,
399
+ U ? /* @__PURE__ */ M(
400
400
  "div",
401
401
  {
402
- [Jt]: "",
402
+ [te]: "",
403
403
  className: "relative min-w-0 shrink basis-auto",
404
- style: Gt,
404
+ style: Ht,
405
405
  children: [
406
406
  /* @__PURE__ */ u(
407
407
  "div",
408
408
  {
409
409
  ref: O,
410
410
  tabIndex: -1,
411
- [Zt]: "",
411
+ [Qt]: "",
412
412
  "data-snap": k ? "true" : "false",
413
413
  className: R,
414
- children: /* @__PURE__ */ u(Rt.Provider, { value: zt, children: j })
414
+ children: /* @__PURE__ */ u(gt.Provider, { value: jt, children: Z })
415
415
  }
416
416
  ),
417
- dt ? /* @__PURE__ */ u(yt, { side: "left", onClick: () => lt(-1) }) : null,
418
- ut ? /* @__PURE__ */ u(yt, { side: "right", onClick: () => lt(1) }) : null,
419
- ft || pt ? /* @__PURE__ */ u(
417
+ ft ? /* @__PURE__ */ u(Ot, { side: "left", onClick: () => ut(-1) }) : null,
418
+ pt ? /* @__PURE__ */ u(Ot, { side: "right", onClick: () => ut(1) }) : null,
419
+ ht || bt ? /* @__PURE__ */ u(
420
420
  "div",
421
421
  {
422
422
  "aria-hidden": !0,
423
423
  "data-card-strip-fade": "",
424
- className: `${Dt} absolute pointer-events-none`,
424
+ className: `${wt} absolute pointer-events-none`,
425
425
  style: {
426
- inset: `-${M}px -${m}px 0`,
427
- background: `linear-gradient(to right, ${ft ? St : "transparent"} 0, transparent ${xt}px, transparent calc(100% - ${xt}px), ${pt ? St : "transparent"} 100%)`
426
+ inset: `-${V}px -${m}px 0`,
427
+ background: `linear-gradient(to right, ${ht ? Et : "transparent"} 0, transparent ${St}px, transparent calc(100% - ${St}px), ${bt ? Et : "transparent"} 100%)`
428
428
  }
429
429
  }
430
430
  ) : null
@@ -434,21 +434,21 @@ const qt = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "Arrow
434
434
  ]
435
435
  }
436
436
  ),
437
- ot.length > 0 ? /* @__PURE__ */ u(
437
+ ct.length > 0 ? /* @__PURE__ */ u(
438
438
  "div",
439
439
  {
440
440
  className: "shrink-0",
441
- style: !U && i ? Ne : void 0,
442
- children: ot
441
+ style: !U && i ? Ue : void 0,
442
+ children: ct
443
443
  }
444
444
  ) : null
445
445
  ]
446
446
  }
447
447
  );
448
448
  };
449
- Ge.AddTile = wt;
449
+ Fe.AddTile = Pt;
450
450
  export {
451
- Ge as CardStrip,
452
- Ge as default
451
+ Fe as CardStrip,
452
+ Fe as default
453
453
  };
454
454
  //# sourceMappingURL=CardStrip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CardStrip.js","sources":["../../src/components/CardStrip.tsx"],"sourcesContent":["import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport ForwardArrowIcon from './CustomIcons/ForwardArrowIcon';\nimport PlusIcon from './CustomIcons/PlusIcon';\nimport { CONTENT_INSET } from './PageLayout/constants';\nimport {\n CARD_FLARE_PX,\n CARD_FLARE_TIP_PX,\n CARD_WIDTH_PX,\n FLARE_CLASS,\n STRIP_RULE_PX,\n} from './SelectableCard';\nimport { CardStripSlotContext, PINNED_SLOT, SCROLLED_SLOT } from './cardStripSlot';\nimport { FOCUS_RING } from './focusRing';\nimport { useAdoptedStyleSheet } from './useAdoptedStyleSheet';\n\nexport type CardStripAddTileEmphasis = 'primary' | 'secondary';\n\nexport interface CardStripAddTileProps {\n /** Visible label, e.g. \"Add Profile\". Also names the button for assistive tech. */\n label: string;\n /** Defaults to a plus. */\n icon?: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n /** Leave unset: CardStrip picks `primary` while the strip is empty and `secondary` once cards exist. */\n emphasis?: CardStripAddTileEmphasis;\n className?: string;\n}\n\n/** Palette for the strip's rule. Pass the tone of whatever card is selected. */\nexport type CardStripTone = 'profile' | 'library' | 'editing';\n\nexport interface CardStripProps {\n /** The selected card's value, matched against each radio child's `data-value`. */\n value: string;\n /** Overrides the palette the strip reads off the selected card. See `CardStripTone`. */\n tone?: CardStripTone;\n onChange: (value: string) => void;\n /** Cards. Any element with `role=\"radio\"` and a `data-value` joins the group; an\n * add tile must be a direct child or it scrolls with the cards. */\n children: React.ReactNode;\n /** Pinned, non-scrolling slot before the cards (the Library card in the profile picker). */\n leading?: React.ReactNode;\n /** Circular scroll affordances, shown only on an edge that can actually scroll. */\n arrows?: boolean;\n /** Fade the cards out at any edge they scroll past. */\n fadeEdges?: boolean;\n /** Snap cards to the leading edge as the strip scrolls. */\n snap?: boolean;\n /** Run the bottom rule the full width of the page card while the cards stay on the gutter.\n * Only has an effect inside a layout that publishes its inset (`PageLayout`). */\n bleed?: boolean;\n /** Whether a selection change scrolls the selected card into view. Set `false` when the\n * value comes from a URL, or a deep-linked strip below the fold jumps the page on load. */\n scrollSelectedIntoView?: boolean;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/** Arrow keys move AND select, per the WAI-ARIA radiogroup pattern. */\nconst NAV_KEYS = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End']);\n\nconst RADIO_SELECTOR = '[role=\"radio\"]';\nconst SCROLLER_ATTR = 'data-card-strip-scroller';\nconst TROUGH_ATTR = 'data-card-strip-trough';\nconst ROOT_CLASS = 'malachite-card-strip';\nconst SCROLLER_CLASS = 'malachite-card-strip-scroller';\nconst FADE_CLASS = 'malachite-card-strip-fade';\nconst ADD_TILE_CLASS = 'malachite-card-strip-add-tile';\n\nconst ACTIONS_SELECTOR = '[data-selectable-card-actions]';\nconst FOCUSABLE_SELECTOR =\n 'a[href], area[href], button, input, select, textarea, iframe, [contenteditable=\"true\"], [tabindex]';\nconst PREV_TABINDEX_ATTR = 'data-card-strip-prev-tabindex';\n\nconst EDGE_EPSILON_PX = 1;\nconst SCROLL_STEP_RATIO = 0.8;\n\nconst scrollStepFor = (scroller: HTMLElement): number => {\n const [first, second] = Array.from(scroller.children);\n const pitch =\n first && second\n ? second.getBoundingClientRect().left - first.getBoundingClientRect().left\n : (first?.getBoundingClientRect().width ?? 0);\n // `clientWidth` counts the flare padding, which is not width a card can be read in.\n const visible = scroller.clientWidth - CARD_FLARE_PX * 2;\n\n if (pitch <= 0) {\n return visible * SCROLL_STEP_RATIO;\n }\n\n return Math.max(1, Math.floor(visible / pitch)) * pitch;\n};\nconst FADE_WIDTH_PX = 80;\n\nconst ARROW_SIZE_PX = 20;\nconst ARROW_GLYPH_PX = 11;\nconst GUTTER_REST_PX = 12;\nconst GUTTER_OPEN_PX = 52;\nconst ARROW_OFFSET_PX = (GUTTER_OPEN_PX + ARROW_SIZE_PX) / 2;\n\nconst LIP_SHADOW = 'var(--malachite-shadow-default)';\nconst ARROW_BACKGROUND =\n 'var(--malachite-card-strip-arrow-background, var(--malachite-card-background, #ffffff))';\nconst ARROW_BORDER = 'var(--malachite-card-strip-arrow-border, #e8e8e8)';\nconst TROUGH_BACKGROUND = 'var(--malachite-card-strip-background, #f1f1f1)';\nconst CARD_CORNER = 'var(--malachite-radius-xxl, 14px)';\nconst CARD_RADIUS = `${CARD_CORNER} ${CARD_CORNER} 0 0`;\nconst TROUGH_CORNER = 'var(--malachite-radius-xxxl, 16px)';\nconst TROUGH_RADIUS = `${TROUGH_CORNER} ${TROUGH_CORNER} 0 0`;\nconst TROUGH_SHOULDER_PX = 4;\nconst FADE_RAMP_PX = FADE_WIDTH_PX + (CARD_FLARE_PX - TROUGH_SHOULDER_PX);\nconst SLOT_WIDTH_PX = CARD_WIDTH_PX;\nconst DIVIDER_COLOR = 'var(--malachite-card-strip-divider, #dddddd)';\nconst FADE_COLOR = 'var(--malachite-card-strip-fade, transparent)';\nconst ADD_HOVER_BACKGROUND = 'var(--malachite-selectable-card-hover-background, #e8e8e8)';\nconst ADD_PILL_BORDER = 'var(--malachite-card-strip-arrow-border, #e8e8e8)';\nconst ADD_PILL_BORDER_ACTIVE = 'var(--malachite-selectable-card-hover-rule, #bbbbbb)';\nconst ADD_PILL_SHADOW_DEEP = '0px 1px 0px 0px rgba(0, 0, 0, 0.4)';\nconst ADD_PILL_BACKGROUND = 'var(--malachite-card-background, #ffffff)';\nconst ADD_PILL_FOREGROUND = 'var(--malachite-text-primary, #0a0a0a)';\nconst ADD_PILL_PRIMARY_BACKGROUND =\n 'var(--malachite-card-strip-add-primary-background, var(--malachite-text-primary, #0a0a0a))';\nconst ADD_PILL_PRIMARY_FOREGROUND =\n 'var(--malachite-card-strip-add-primary-foreground, var(--malachite-card-background, #ffffff))';\nconst ADD_PILL_PRIMARY_SHADOW = '0px 1px 0px 0px rgba(10, 10, 10, 0.7)';\n\nconst BOTTOM_RULE_WEIGHT_PX = STRIP_RULE_PX;\n\nconst OVERFLOW_INSET_PX = 16;\n\nconst CLIP_SLACK_PX = 9999;\nconst FOCUS_RING_REACH_PX = 4;\n\n/** A sheet, not inline styles: these rules have to reach children this component does not render. */\nconst SCROLLER_CSS = `\n.${ROOT_CLASS} {\n clip-path: inset(-${CLIP_SLACK_PX}px -${CLIP_SLACK_PX}px 0);\n}\n.${ROOT_CLASS}:has(:focus-visible) {\n clip-path: inset(-${CLIP_SLACK_PX}px -${CLIP_SLACK_PX}px -${FOCUS_RING_REACH_PX}px);\n}\n.${SCROLLER_CLASS} {\n display: flex;\n flex-wrap: nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n scroll-behavior: smooth;\n scrollbar-width: none;\n -ms-overflow-style: none;\n padding-block: ${OVERFLOW_INSET_PX}px;\n margin-block: -${OVERFLOW_INSET_PX}px;\n /* overflow-x clips both axes, so the end cards would lose a flare; the negative margin trades\n the padding back out and scroll-padding keeps the rest position at zero. */\n padding-inline: ${CARD_FLARE_PX}px;\n margin-inline: -${CARD_FLARE_PX}px;\n scroll-padding-inline: ${CARD_FLARE_PX}px;\n}\n/* A card focused at a faded edge has to stay readable, so the fade lifts entirely. */\n.${ROOT_CLASS}:has(:focus-visible) .${FADE_CLASS} {\n display: none;\n}\n.${SCROLLER_CLASS}::-webkit-scrollbar {\n display: none;\n}\n/* No bottom edge: the strip's rule is the baseline for the add tile as much as for a card. */\n.${ADD_TILE_CLASS} > * {\n background: ${TROUGH_BACKGROUND};\n border-radius: ${CARD_RADIUS};\n}\n.${ADD_TILE_CLASS}:hover:not(:has(button:disabled)) > * {\n background: ${ADD_HOVER_BACKGROUND};\n}\n.${ADD_TILE_CLASS} button:active:not(:disabled) {\n opacity: 0.8;\n}\n.${ADD_TILE_CLASS}:has(button:active) > * {\n background: ${TROUGH_BACKGROUND};\n}\n.${ADD_TILE_CLASS}[data-emphasis='secondary'] button {\n border-color: ${ADD_PILL_BORDER};\n box-shadow: ${LIP_SHADOW};\n}\n.${ADD_TILE_CLASS}[data-emphasis='secondary']:hover:not(:has(button:disabled)) button {\n border-color: ${ADD_PILL_BORDER_ACTIVE};\n box-shadow: ${ADD_PILL_SHADOW_DEEP};\n}\n.${ADD_TILE_CLASS}[data-emphasis='secondary'] button:active:not(:disabled) {\n border-color: ${ADD_PILL_BORDER_ACTIVE};\n box-shadow: ${ADD_PILL_SHADOW_DEEP};\n}\n.${ADD_TILE_CLASS}[data-emphasis='primary'] button {\n border-color: transparent;\n box-shadow: ${ADD_PILL_PRIMARY_SHADOW};\n}\n.${SCROLLER_CLASS} > * {\n flex: 0 0 auto;\n min-width: 0;\n}\n.${SCROLLER_CLASS} > * + * {\n border-left: 1px solid ${DIVIDER_COLOR};\n}\n.${SCROLLER_CLASS}[data-snap='true'] {\n scroll-snap-type: x proximity;\n}\n.${SCROLLER_CLASS}[data-snap='true'] > * {\n scroll-snap-align: start;\n}\n@media (prefers-reduced-motion: reduce) {\n .${SCROLLER_CLASS} {\n scroll-behavior: auto;\n }\n .${SCROLLER_CLASS}[data-snap='true'] {\n scroll-snap-type: none;\n }\n .${SCROLLER_CLASS}[data-snap='true'] > * {\n scroll-snap-align: none;\n }\n}`;\n\nconst STYLE_ID = 'malachite-card-strip-style';\n\n/** `window.matchMedia` is absent under SSR and in older test environments. */\nconst prefersReducedMotion = (): boolean => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return true;\n }\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n};\n\nconst radioValue = (radio: HTMLElement): string | null =>\n radio.dataset.value ?? radio.getAttribute('value');\n\nconst isRadioDisabled = (radio: HTMLElement): boolean =>\n radio.hasAttribute('disabled') || radio.getAttribute('aria-disabled') === 'true';\n\nconst actionsFor = (radio: HTMLElement): HTMLElement | null => {\n const card = radio.parentElement;\n if (!card || card.querySelectorAll(RADIO_SELECTOR).length !== 1) {\n return null;\n }\n return card.querySelector<HTMLElement>(ACTIONS_SELECTOR);\n};\n\n/** A card is wider than its radio, so `closest` misses clicks on the count row. */\nconst radioForClick = (target: Element, root: Element): HTMLElement | null => {\n const direct = target.closest<HTMLElement>(RADIO_SELECTOR);\n if (direct) {\n return direct;\n }\n if (target.closest(ACTIONS_SELECTOR)) {\n return null;\n }\n let node: Element | null = target;\n while (node && root.contains(node)) {\n const radios: NodeListOf<HTMLElement> = node.querySelectorAll(RADIO_SELECTOR);\n if (radios.length === 1 && radios[0].parentElement === node) {\n return radios[0];\n }\n node = node.parentElement;\n }\n return null;\n};\n\nconst actionControls = (radio: HTMLElement): HTMLElement[] => {\n const actions = actionsFor(radio);\n return actions ? Array.from(actions.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)) : [];\n};\n\nconst suppressTabStop = (element: HTMLElement): void => {\n if (!element.hasAttribute(PREV_TABINDEX_ATTR)) {\n element.setAttribute(PREV_TABINDEX_ATTR, element.getAttribute('tabindex') ?? '');\n }\n element.setAttribute('tabindex', '-1');\n};\n\nconst restoreTabStop = (element: HTMLElement): void => {\n if (!element.hasAttribute(PREV_TABINDEX_ATTR)) {\n return;\n }\n const previous = element.getAttribute(PREV_TABINDEX_ATTR);\n element.removeAttribute(PREV_TABINDEX_ATTR);\n if (previous) {\n element.setAttribute('tabindex', previous);\n } else {\n element.removeAttribute('tabindex');\n }\n};\n\nconst TONE_RULE: Record<CardStripTone, string> = {\n profile: 'var(--malachite-selectable-card-selected-border, #047b43)',\n library: 'var(--malachite-selectable-card-library-selected-border, #bbbbbb)',\n editing: 'var(--malachite-selectable-card-pending-foreground, #96580a)',\n};\nconst RULE_ROW_STYLE: React.CSSProperties = {\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'left bottom',\n backgroundSize: `100% ${BOTTOM_RULE_WEIGHT_PX}px`,\n};\n\n/** The rule runs under the flare's tip rather than butting against it, so antialiasing\n * cannot open the junction into a gap. */\nconst RULE_GAP_OVERLAP_PX = 0.5;\n\nconst FLARE_TIP_INSET_PX = CARD_FLARE_PX - CARD_FLARE_TIP_PX;\n\nconst flareTips = (card: HTMLElement): { left: number; right: number } | null => {\n const flare = card.querySelector(`:scope > .${FLARE_CLASS}`);\n if (!flare) {\n return null;\n }\n const { left, right } = flare.getBoundingClientRect();\n return { left: left + FLARE_TIP_INSET_PX, right: right - FLARE_TIP_INSET_PX };\n};\n\n/** The rule is cut where the selected card stands, never covered: the strip's clip lands on the\n * rule's own edge, so a cover takes the same partial alpha and the rule bleeds through it. */\nconst paintRule = (\n root: HTMLElement | null,\n scroller: HTMLElement | null,\n card: HTMLElement | null | undefined,\n tone: CardStripTone,\n): void => {\n if (!root) {\n return;\n }\n const colour = TONE_RULE[tone];\n const rootRect = root.getBoundingClientRect();\n const rootLeft = rootRect.left;\n const clip = card && scroller?.contains(card) ? scroller.getBoundingClientRect() : rootRect;\n const cardRect = card?.getBoundingClientRect();\n const tips = card ? flareTips(card) : null;\n const tipLeft = tips?.left ?? (cardRect ? cardRect.left - CARD_FLARE_TIP_PX : 0);\n const tipRight = tips?.right ?? (cardRect ? cardRect.right + CARD_FLARE_TIP_PX : 0);\n const from = cardRect ? Math.max(tipLeft, clip.left) + RULE_GAP_OVERLAP_PX - rootLeft : 0;\n const to = cardRect ? Math.min(tipRight, clip.right) - RULE_GAP_OVERLAP_PX - rootLeft : 0;\n\n root.style.backgroundImage =\n to > from\n ? `linear-gradient(to right, ${colour} 0 ${from}px, transparent ${from}px ${to}px, ${colour} ${to}px 100%)`\n : `linear-gradient(to right, ${colour} 0 100%)`;\n};\n\nconst BLEED_STYLE: React.CSSProperties = {\n marginInline: `calc(${CONTENT_INSET} * -1)`,\n paddingInline: CONTENT_INSET,\n};\n\n/** The rule's row is a margin, never padding: a background paints under its own padding, which\n * would hide the very line the troughs stand on. */\nconst TROUGH_SURFACE: React.CSSProperties = {\n background: TROUGH_BACKGROUND,\n borderRadius: TROUGH_RADIUS,\n paddingTop: `${TROUGH_SHOULDER_PX}px`,\n paddingInline: `${TROUGH_SHOULDER_PX}px`,\n marginBottom: `${BOTTOM_RULE_WEIGHT_PX}px`,\n};\nconst TROUGH_STYLE: React.CSSProperties = {\n ...TROUGH_SURFACE,\n marginInline: `${GUTTER_REST_PX}px`,\n};\nconst TROUGH_GUTTER_STYLES: Record<string, React.CSSProperties> = Object.fromEntries(\n [GUTTER_REST_PX, GUTTER_OPEN_PX].flatMap((start) =>\n [GUTTER_REST_PX, GUTTER_OPEN_PX].map((end) => [\n `${start}:${end}`,\n { ...TROUGH_SURFACE, marginInline: `${start}px ${end}px` },\n ]),\n ),\n);\nconst ADD_TILE_SHAPE_STYLE: React.CSSProperties = TROUGH_SURFACE;\n\nconst PINNED_SLOT_STYLE: React.CSSProperties = TROUGH_SURFACE;\n\nconst EMPTY_ADD_SLOT_STYLE: React.CSSProperties = {\n marginInlineStart: `${GUTTER_REST_PX}px`,\n};\n\nconst ADD_PILL_FILL: Record<CardStripAddTileEmphasis, React.CSSProperties> = {\n primary: {\n backgroundColor: ADD_PILL_PRIMARY_BACKGROUND,\n color: ADD_PILL_PRIMARY_FOREGROUND,\n },\n secondary: { backgroundColor: ADD_PILL_BACKGROUND, color: ADD_PILL_FOREGROUND },\n};\n\nconst AddTile: React.FC<CardStripAddTileProps> = ({\n label,\n icon,\n onClick,\n disabled = false,\n emphasis = 'secondary',\n className = '',\n}) => (\n <div\n className={ADD_TILE_CLASS}\n data-emphasis={emphasis}\n style={{\n ...ADD_TILE_SHAPE_STYLE,\n width: `${SLOT_WIDTH_PX}px`,\n height: `calc(100% - ${BOTTOM_RULE_WEIGHT_PX}px)`,\n }}\n >\n <div className=\"flex h-full items-center justify-center px-4\">\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n style={ADD_PILL_FILL[emphasis]}\n className={`${FOCUS_RING} inline-flex items-center justify-center gap-1.5 h-[var(--malachite-control-height-medium,32px)] w-[108px] px-2.5 rounded-xl border border-solid text-[length:var(--malachite-font-size-small,13px)] font-medium whitespace-nowrap ${\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'\n } ${className}`}\n >\n <span className=\"inline-flex h-[13px] w-[13px] shrink-0 items-center justify-center\">\n {icon ?? <PlusIcon size={13} />}\n </span>\n {label}\n </button>\n </div>\n </div>\n);\n\nconst isAddTile = (node: React.ReactNode): node is React.ReactElement<CardStripAddTileProps> =>\n React.isValidElement(node) && node.type === AddTile;\n\nconst hidesAddTile = (child: React.ReactNode): boolean =>\n React.isValidElement<{ children?: React.ReactNode }>(child) &&\n child.type === React.Fragment &&\n React.Children.toArray(child.props.children).some(isAddTile);\n\ninterface ArrowButtonProps {\n side: 'left' | 'right';\n onClick: () => void;\n}\n\nconst ArrowButton: React.FC<ArrowButtonProps> = ({ side, onClick }) => (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n aria-label={side === 'left' ? 'Scroll left' : 'Scroll right'}\n onClick={onClick}\n className=\"absolute top-1/2 -translate-y-1/2 z-10 inline-flex items-center justify-center w-5 h-5 rounded-lg cursor-pointer text-[var(--malachite-text-secondary)]\"\n style={{\n [side]: `-${ARROW_OFFSET_PX}px`,\n background: ARROW_BACKGROUND,\n border: `1px solid ${ARROW_BORDER}`,\n boxShadow: LIP_SHADOW,\n }}\n >\n {side === 'left' ? (\n <ArrowLeftIcon size={ARROW_GLYPH_PX} />\n ) : (\n <ForwardArrowIcon size={ARROW_GLYPH_PX} />\n )}\n </button>\n);\n\n/** A horizontally scrolling radiogroup of cards — the \"pick one of these\" strip. */\nconst CardStrip: React.FC<CardStripProps> & { AddTile: React.FC<CardStripAddTileProps> } = ({\n value,\n tone,\n onChange,\n children,\n leading,\n arrows = true,\n fadeEdges = true,\n snap = true,\n bleed = false,\n scrollSelectedIntoView = true,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className = '',\n style,\n}) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const scrollerRef = useRef<HTMLDivElement>(null);\n const [edges, setEdges] = useState({ canScrollLeft: false, canScrollRight: false });\n\n useAdoptedStyleSheet(rootRef, SCROLLER_CSS, STYLE_ID);\n\n const childList = React.Children.toArray(children);\n const cards = childList.filter((child) => !isAddTile(child));\n const wrappedAddTile = cards.some(hidesAddTile);\n const hasCards = cards.length > 0;\n\n const addTiles = childList\n .filter(isAddTile)\n .map((tile) =>\n tile.props.emphasis === undefined\n ? React.cloneElement(tile, { emphasis: hasCards ? 'secondary' : 'primary' })\n : tile,\n );\n\n const childCount = childList.length;\n\n const getRadios = useCallback((): HTMLElement[] => {\n const root = rootRef.current;\n if (!root) {\n return [];\n }\n return Array.from(root.querySelectorAll<HTMLElement>(RADIO_SELECTOR));\n }, []);\n\n const getNavigableRadios = useCallback(\n (): HTMLElement[] => getRadios().filter((radio) => radioValue(radio) !== null),\n [getRadios],\n );\n\n const warned = useRef(new Set<string>());\n const warnOnce = useCallback((key: string, message: string): void => {\n if (warned.current.has(key)) {\n return;\n }\n warned.current.add(key);\n console.warn(message);\n }, []);\n\n const [derivedTone, setDerivedTone] = useState<CardStripTone>('profile');\n\n useLayoutEffect(() => {\n const selectedCard = getRadios()\n .find((radio) => radioValue(radio) === value)\n ?.parentElement?.getAttribute('data-variant');\n if (\n selectedCard === 'profile' ||\n selectedCard === 'library' ||\n selectedCard === 'editing'\n ) {\n setDerivedTone(selectedCard);\n }\n }, [getRadios, value]);\n\n useLayoutEffect(() => {\n const radios = getRadios();\n const navigable = getNavigableRadios();\n const selected = navigable.find((radio) => radioValue(radio) === value);\n const tabStop = selected ?? navigable.find((radio) => !isRadioDisabled(radio)) ?? null;\n\n radios.forEach((radio) => {\n const holdsTabStop = radio === tabStop;\n const nextTabIndex = holdsTabStop ? 0 : -1;\n if (radio.tabIndex !== nextTabIndex) {\n radio.tabIndex = nextTabIndex;\n }\n for (const control of actionControls(radio)) {\n if (holdsTabStop) {\n restoreTabStop(control);\n } else {\n suppressTabStop(control);\n }\n }\n });\n\n if (process.env.NODE_ENV === 'production') {\n return;\n }\n\n if (navigable.length !== radios.length) {\n warnOnce(\n 'missing-value',\n 'CardStrip: a child with role=\"radio\" has no `data-value`. It cannot be selected or reached by arrow keys, so it is excluded from the radio set. Give every card a `data-value`.',\n );\n }\n\n const values = new Set<string>();\n for (const radio of navigable) {\n const current = radioValue(radio);\n if (current === null) {\n continue;\n }\n if (values.has(current)) {\n warnOnce(\n `duplicate:${current}`,\n `CardStrip: two cards share the data-value \"${current}\". Both will read as checked and only the first is selectable — data-value must be unique.`,\n );\n }\n values.add(current);\n }\n\n const selectionSettled = value !== '';\n\n if (radios.length > 0 && selectionSettled && !values.has(value)) {\n warnOnce(\n `unmatched:${value}`,\n `CardStrip: value \"${value}\" matches no card's data-value, so the group reports no selection.`,\n );\n }\n\n const checked = radios.filter(\n (radio) => radio.getAttribute('aria-checked') === 'true',\n ).length;\n if (radios.length > 0 && selectionSettled && checked !== 1) {\n warnOnce(\n `checked:${checked}`,\n `CardStrip: ${checked} cards are aria-checked, but a radiogroup has exactly one. Drive each card's checked state from the strip's \\`value\\`.`,\n );\n }\n\n if (wrappedAddTile) {\n warnOnce(\n 'wrapped-add-tile',\n 'CardStrip: a CardStrip.AddTile inside a fragment is treated as a card and scrolls with them. The add tile must be a direct child of CardStrip.',\n );\n }\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: cards arriving is the signal\n useLayoutEffect(() => {\n if (!scrollSelectedIntoView) {\n return;\n }\n const scroller = scrollerRef.current;\n const selected = getRadios().find((radio) => radioValue(radio) === value);\n // jsdom implements neither, and a strip that cannot scroll has nothing to bring into view.\n if (!scroller || !selected || typeof scroller.scrollTo !== 'function') {\n return;\n }\n\n // Positioned rather than asked for: the track is scroll-snapped, and `scrollIntoView`\n // on a card several widths away lands back on the nearest snap point instead — so a\n // card appended past the end never came into view at all.\n // Measured against the scroller rather than an offset parent: the cards are flex\n // children whose `offsetParent` is not the scroller, so `offsetLeft` is not its frame.\n const card = (selected.closest('[role=\"radio\"]') ?? selected) as HTMLElement;\n const cardRect = card.getBoundingClientRect();\n const viewRect = scroller.getBoundingClientRect();\n const left = scroller.scrollLeft + (cardRect.left - viewRect.left);\n const right = left + cardRect.width;\n const visibleFrom = scroller.scrollLeft + CARD_FLARE_PX;\n const visibleTo = scroller.scrollLeft + scroller.clientWidth - CARD_FLARE_PX;\n\n if (left >= visibleFrom && right <= visibleTo) {\n return;\n }\n\n scroller.scrollTo({\n left:\n right > visibleTo\n ? right - scroller.clientWidth + CARD_FLARE_PX\n : left - CARD_FLARE_PX,\n behavior: 'instant',\n });\n }, [getRadios, scrollSelectedIntoView, value, childCount]);\n\n const ruleTone = tone ?? derivedTone;\n const callerPaintsBackground =\n style?.background !== undefined || style?.backgroundImage !== undefined;\n\n const measure = useCallback(() => {\n const scroller = scrollerRef.current;\n if (!callerPaintsBackground) {\n paintRule(\n rootRef.current,\n scroller,\n getRadios().find((radio) => radioValue(radio) === value)?.parentElement,\n ruleTone,\n );\n }\n if (!scroller) {\n return;\n }\n const { scrollWidth, clientWidth, scrollLeft } = scroller;\n const overflows = scrollWidth > clientWidth + EDGE_EPSILON_PX;\n const next = {\n canScrollLeft: overflows && scrollLeft > EDGE_EPSILON_PX,\n canScrollRight: overflows && scrollLeft + clientWidth < scrollWidth - EDGE_EPSILON_PX,\n };\n setEdges((previous) =>\n previous.canScrollLeft === next.canScrollLeft &&\n previous.canScrollRight === next.canScrollRight\n ? previous\n : next,\n );\n }, [callerPaintsBackground, getRadios, ruleTone, value]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: adding or removing a card changes the scroll width, so re-measure on the count\n useLayoutEffect(() => {\n measure();\n\n const scroller = scrollerRef.current;\n if (!scroller) {\n return;\n }\n\n const onScroll = (): void => measure();\n scroller.addEventListener('scroll', onScroll, { passive: true });\n\n const observer =\n typeof ResizeObserver !== 'undefined' ? new ResizeObserver(() => measure()) : null;\n observer?.observe(scroller);\n\n return () => {\n scroller.removeEventListener('scroll', onScroll);\n observer?.disconnect();\n };\n }, [measure, childCount]);\n\n const scrollByStep = useCallback((direction: -1 | 1) => {\n const scroller = scrollerRef.current;\n if (!scroller || typeof scroller.scrollBy !== 'function') {\n return;\n }\n scroller.scrollBy({\n left: direction * scrollStepFor(scroller),\n behavior: prefersReducedMotion() ? 'auto' : 'smooth',\n });\n }, []);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (!NAV_KEYS.has(event.key)) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Element) || !target.closest(RADIO_SELECTOR)) {\n return;\n }\n\n const enabled = getNavigableRadios().filter((radio) => !isRadioDisabled(radio));\n if (enabled.length === 0) {\n return;\n }\n\n event.preventDefault();\n\n const currentPosition = enabled.findIndex((radio) => radioValue(radio) === value);\n let nextPosition: number;\n if (event.key === 'Home') {\n nextPosition = 0;\n } else if (event.key === 'End') {\n nextPosition = enabled.length - 1;\n } else {\n const delta = event.key === 'ArrowLeft' || event.key === 'ArrowUp' ? -1 : 1;\n const from = currentPosition === -1 ? 0 : currentPosition;\n nextPosition = (from + delta + enabled.length) % enabled.length;\n }\n\n const next = enabled[nextPosition];\n const nextValue = radioValue(next);\n if (nextValue !== null && nextValue !== value) {\n onChange(nextValue);\n }\n next.focus();\n },\n [getNavigableRadios, onChange, value],\n );\n\n const handleClick = useCallback(\n (event: React.MouseEvent) => {\n const target = event.target;\n if (!(target instanceof Element)) {\n return;\n }\n const root = rootRef.current;\n if (!root) {\n return;\n }\n const radio = radioForClick(target, root);\n if (!radio || isRadioDisabled(radio)) {\n return;\n }\n const clicked = radioValue(radio);\n if (clicked !== null && clicked !== value) {\n onChange(clicked);\n }\n },\n [onChange, value],\n );\n\n const showLeftArrow = arrows && edges.canScrollLeft;\n const showRightArrow = arrows && edges.canScrollRight;\n\n const fadeLeft = fadeEdges && edges.canScrollLeft;\n const fadeRight = fadeEdges && edges.canScrollRight;\n const troughStyle = arrows\n ? TROUGH_GUTTER_STYLES[\n `${showLeftArrow ? GUTTER_OPEN_PX : GUTTER_REST_PX}:${\n showRightArrow ? GUTTER_OPEN_PX : GUTTER_REST_PX\n }`\n ]\n : TROUGH_STYLE;\n\n return (\n <div\n ref={rootRef}\n onKeyDown={handleKeyDown}\n onClick={handleClick}\n className={`${ROOT_CLASS} flex items-stretch ${className}`}\n style={{\n ...RULE_ROW_STYLE,\n ...(bleed ? BLEED_STYLE : null),\n ...style,\n }}\n >\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={hasCards ? 'flex items-stretch min-w-0' : 'flex items-stretch'}\n >\n {leading ? (\n <CardStripSlotContext.Provider value={PINNED_SLOT}>\n <div className=\"shrink-0\" style={PINNED_SLOT_STYLE}>\n {leading}\n </div>\n </CardStripSlotContext.Provider>\n ) : null}\n {hasCards ? (\n <div\n {...{ [TROUGH_ATTR]: '' }}\n className=\"relative min-w-0 shrink basis-auto\"\n style={troughStyle}\n >\n <div\n ref={scrollerRef}\n tabIndex={-1}\n {...{ [SCROLLER_ATTR]: '' }}\n data-snap={snap ? 'true' : 'false'}\n className={SCROLLER_CLASS}\n >\n <CardStripSlotContext.Provider value={SCROLLED_SLOT}>\n {cards}\n </CardStripSlotContext.Provider>\n </div>\n {showLeftArrow ? (\n <ArrowButton side=\"left\" onClick={() => scrollByStep(-1)} />\n ) : null}\n {showRightArrow ? (\n <ArrowButton side=\"right\" onClick={() => scrollByStep(1)} />\n ) : null}\n {fadeLeft || fadeRight ? (\n <div\n aria-hidden\n data-card-strip-fade=\"\"\n className={`${FADE_CLASS} absolute pointer-events-none`}\n style={{\n inset: `-${TROUGH_SHOULDER_PX}px -${CARD_FLARE_PX}px 0`,\n background: `linear-gradient(to right, ${fadeLeft ? FADE_COLOR : 'transparent'} 0, transparent ${FADE_RAMP_PX}px, transparent calc(100% - ${FADE_RAMP_PX}px), ${fadeRight ? FADE_COLOR : 'transparent'} 100%)`,\n }}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n {addTiles.length > 0 ? (\n <div\n className=\"shrink-0\"\n style={!hasCards && leading ? EMPTY_ADD_SLOT_STYLE : undefined}\n >\n {addTiles}\n </div>\n ) : null}\n </div>\n );\n};\n\nCardStrip.AddTile = AddTile;\n\nexport default CardStrip;\nexport { CardStrip };\n"],"names":["NAV_KEYS","RADIO_SELECTOR","SCROLLER_ATTR","TROUGH_ATTR","ROOT_CLASS","SCROLLER_CLASS","FADE_CLASS","ADD_TILE_CLASS","ACTIONS_SELECTOR","FOCUSABLE_SELECTOR","PREV_TABINDEX_ATTR","EDGE_EPSILON_PX","SCROLL_STEP_RATIO","scrollStepFor","scroller","first","second","pitch","visible","CARD_FLARE_PX","FADE_WIDTH_PX","ARROW_SIZE_PX","ARROW_GLYPH_PX","GUTTER_REST_PX","GUTTER_OPEN_PX","ARROW_OFFSET_PX","LIP_SHADOW","ARROW_BACKGROUND","ARROW_BORDER","TROUGH_BACKGROUND","CARD_CORNER","CARD_RADIUS","TROUGH_CORNER","TROUGH_RADIUS","TROUGH_SHOULDER_PX","FADE_RAMP_PX","SLOT_WIDTH_PX","CARD_WIDTH_PX","DIVIDER_COLOR","FADE_COLOR","ADD_HOVER_BACKGROUND","ADD_PILL_BORDER","ADD_PILL_BORDER_ACTIVE","ADD_PILL_SHADOW_DEEP","ADD_PILL_BACKGROUND","ADD_PILL_FOREGROUND","ADD_PILL_PRIMARY_BACKGROUND","ADD_PILL_PRIMARY_FOREGROUND","ADD_PILL_PRIMARY_SHADOW","BOTTOM_RULE_WEIGHT_PX","STRIP_RULE_PX","OVERFLOW_INSET_PX","CLIP_SLACK_PX","FOCUS_RING_REACH_PX","SCROLLER_CSS","STYLE_ID","prefersReducedMotion","radioValue","radio","isRadioDisabled","actionsFor","card","radioForClick","target","root","direct","node","radios","actionControls","actions","suppressTabStop","element","restoreTabStop","previous","TONE_RULE","RULE_ROW_STYLE","RULE_GAP_OVERLAP_PX","FLARE_TIP_INSET_PX","CARD_FLARE_TIP_PX","flareTips","flare","FLARE_CLASS","left","right","paintRule","tone","colour","rootRect","rootLeft","clip","cardRect","tips","tipLeft","tipRight","from","to","BLEED_STYLE","CONTENT_INSET","TROUGH_SURFACE","TROUGH_STYLE","TROUGH_GUTTER_STYLES","start","end","ADD_TILE_SHAPE_STYLE","PINNED_SLOT_STYLE","EMPTY_ADD_SLOT_STYLE","ADD_PILL_FILL","AddTile","label","icon","onClick","disabled","emphasis","className","jsx","jsxs","FOCUS_RING","PlusIcon","isAddTile","React","hidesAddTile","child","ArrowButton","side","ArrowLeftIcon","ForwardArrowIcon","CardStrip","value","onChange","children","leading","arrows","fadeEdges","snap","bleed","scrollSelectedIntoView","ariaLabel","ariaLabelledBy","style","rootRef","useRef","scrollerRef","edges","setEdges","useState","useAdoptedStyleSheet","childList","cards","wrappedAddTile","hasCards","addTiles","tile","childCount","getRadios","useCallback","getNavigableRadios","warned","warnOnce","key","message","derivedTone","setDerivedTone","useLayoutEffect","selectedCard","_b","_a","navigable","tabStop","holdsTabStop","nextTabIndex","control","values","current","selectionSettled","checked","selected","viewRect","visibleFrom","visibleTo","ruleTone","callerPaintsBackground","measure","scrollWidth","clientWidth","scrollLeft","overflows","next","onScroll","observer","scrollByStep","direction","handleKeyDown","event","enabled","currentPosition","nextPosition","delta","nextValue","handleClick","clicked","showLeftArrow","showRightArrow","fadeLeft","fadeRight","troughStyle","CardStripSlotContext","PINNED_SLOT","SCROLLED_SLOT"],"mappings":"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"}
1
+ {"version":3,"file":"CardStrip.js","sources":["../../src/components/CardStrip.tsx"],"sourcesContent":["import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport ForwardArrowIcon from './CustomIcons/ForwardArrowIcon';\nimport PlusIcon from './CustomIcons/PlusIcon';\nimport { CONTENT_INSET } from './PageLayout/constants';\nimport {\n CARD_FLARE_PX,\n CARD_FLARE_TIP_PX,\n CARD_WIDTH_PX,\n FLARE_CLASS,\n STRIP_RULE_PX,\n} from './SelectableCard';\nimport { CardStripSlotContext, PINNED_SLOT, SCROLLED_SLOT } from './cardStripSlot';\nimport { FOCUS_RING } from './focusRing';\nimport { useAdoptedStyleSheet } from './useAdoptedStyleSheet';\n\nexport type CardStripAddTileEmphasis = 'primary' | 'secondary';\n\nexport interface CardStripAddTileProps {\n /** Visible label, e.g. \"Add Profile\". Also names the button for assistive tech. */\n label: string;\n /** Defaults to a plus. */\n icon?: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n /** Leave unset: CardStrip picks `primary` while the strip is empty and `secondary` once cards exist. */\n emphasis?: CardStripAddTileEmphasis;\n className?: string;\n}\n\n/** Palette for the strip's rule. Pass the tone of whatever card is selected. */\nexport type CardStripTone = 'profile' | 'library' | 'editing';\n\nexport interface CardStripProps {\n /** The selected card's value, matched against each radio child's `data-value`. */\n value: string;\n /** Overrides the palette the strip reads off the selected card. See `CardStripTone`. */\n tone?: CardStripTone;\n onChange: (value: string) => void;\n /** Cards. Any element with `role=\"radio\"` and a `data-value` joins the group; an\n * add tile must be a direct child or it scrolls with the cards. */\n children: React.ReactNode;\n /** Pinned, non-scrolling slot before the cards (the Library card in the profile picker). */\n leading?: React.ReactNode;\n /** Circular scroll affordances, shown only on an edge that can actually scroll. */\n arrows?: boolean;\n /** Fade the cards out at any edge they scroll past. */\n fadeEdges?: boolean;\n /** Snap cards to the leading edge as the strip scrolls. */\n snap?: boolean;\n /** Run the bottom rule the full width of the page card while the cards stay on the gutter.\n * Only has an effect inside a layout that publishes its inset (`PageLayout`). */\n bleed?: boolean;\n /** Whether a selection change scrolls the selected card into view. The strip's opening\n * selection is placed instantly; later ones slide, unless motion is reduced. Set `false`\n * when the value comes from a URL, or a deep-linked strip below the fold jumps the page\n * on load. */\n scrollSelectedIntoView?: boolean;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/** Arrow keys move AND select, per the WAI-ARIA radiogroup pattern. */\nconst NAV_KEYS = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End']);\n\nconst RADIO_SELECTOR = '[role=\"radio\"]';\nconst SCROLLER_ATTR = 'data-card-strip-scroller';\nconst TROUGH_ATTR = 'data-card-strip-trough';\nconst ROOT_CLASS = 'malachite-card-strip';\nconst SCROLLER_CLASS = 'malachite-card-strip-scroller';\nconst FADE_CLASS = 'malachite-card-strip-fade';\nconst ADD_TILE_CLASS = 'malachite-card-strip-add-tile';\n\nconst ACTIONS_SELECTOR = '[data-selectable-card-actions]';\nconst FOCUSABLE_SELECTOR =\n 'a[href], area[href], button, input, select, textarea, iframe, [contenteditable=\"true\"], [tabindex]';\nconst PREV_TABINDEX_ATTR = 'data-card-strip-prev-tabindex';\n\nconst EDGE_EPSILON_PX = 1;\nconst SCROLL_STEP_RATIO = 0.8;\n\nconst scrollStepFor = (scroller: HTMLElement): number => {\n const [first, second] = Array.from(scroller.children);\n const pitch =\n first && second\n ? second.getBoundingClientRect().left - first.getBoundingClientRect().left\n : (first?.getBoundingClientRect().width ?? 0);\n // `clientWidth` counts the flare padding, which is not width a card can be read in.\n const visible = scroller.clientWidth - CARD_FLARE_PX * 2;\n\n if (pitch <= 0) {\n return visible * SCROLL_STEP_RATIO;\n }\n\n return Math.max(1, Math.floor(visible / pitch)) * pitch;\n};\nconst FADE_WIDTH_PX = 80;\n\nconst ARROW_SIZE_PX = 20;\nconst ARROW_GLYPH_PX = 11;\nconst GUTTER_REST_PX = 12;\nconst GUTTER_OPEN_PX = 52;\nconst ARROW_OFFSET_PX = (GUTTER_OPEN_PX + ARROW_SIZE_PX) / 2;\n\nconst LIP_SHADOW = 'var(--malachite-shadow-default)';\nconst ARROW_BACKGROUND =\n 'var(--malachite-card-strip-arrow-background, var(--malachite-card-background, #ffffff))';\nconst ARROW_BORDER = 'var(--malachite-card-strip-arrow-border, #e8e8e8)';\nconst TROUGH_BACKGROUND = 'var(--malachite-card-strip-background, #f1f1f1)';\nconst CARD_CORNER = 'var(--malachite-radius-xxl, 14px)';\nconst CARD_RADIUS = `${CARD_CORNER} ${CARD_CORNER} 0 0`;\nconst TROUGH_CORNER = 'var(--malachite-radius-xxxl, 16px)';\nconst TROUGH_RADIUS = `${TROUGH_CORNER} ${TROUGH_CORNER} 0 0`;\nconst TROUGH_SHOULDER_PX = 4;\nconst FADE_RAMP_PX = FADE_WIDTH_PX + (CARD_FLARE_PX - TROUGH_SHOULDER_PX);\nconst SLOT_WIDTH_PX = CARD_WIDTH_PX;\nconst DIVIDER_COLOR = 'var(--malachite-card-strip-divider, #dddddd)';\nconst FADE_COLOR = 'var(--malachite-card-strip-fade, transparent)';\nconst ADD_HOVER_BACKGROUND = 'var(--malachite-selectable-card-hover-background, #e8e8e8)';\nconst ADD_PILL_BORDER = 'var(--malachite-card-strip-arrow-border, #e8e8e8)';\nconst ADD_PILL_BORDER_ACTIVE = 'var(--malachite-selectable-card-hover-rule, #bbbbbb)';\nconst ADD_PILL_SHADOW_DEEP = '0px 1px 0px 0px rgba(0, 0, 0, 0.4)';\nconst ADD_PILL_BACKGROUND = 'var(--malachite-card-background, #ffffff)';\nconst ADD_PILL_FOREGROUND = 'var(--malachite-text-primary, #0a0a0a)';\nconst ADD_PILL_PRIMARY_BACKGROUND =\n 'var(--malachite-card-strip-add-primary-background, var(--malachite-text-primary, #0a0a0a))';\nconst ADD_PILL_PRIMARY_FOREGROUND =\n 'var(--malachite-card-strip-add-primary-foreground, var(--malachite-card-background, #ffffff))';\nconst ADD_PILL_PRIMARY_SHADOW = '0px 1px 0px 0px rgba(10, 10, 10, 0.7)';\n\nconst BOTTOM_RULE_WEIGHT_PX = STRIP_RULE_PX;\n\nconst OVERFLOW_INSET_PX = 16;\n\nconst CLIP_SLACK_PX = 9999;\nconst FOCUS_RING_REACH_PX = 4;\n\n/** A sheet, not inline styles: these rules have to reach children this component does not render. */\nconst SCROLLER_CSS = `\n.${ROOT_CLASS} {\n clip-path: inset(-${CLIP_SLACK_PX}px -${CLIP_SLACK_PX}px 0);\n}\n.${ROOT_CLASS}:has(:focus-visible) {\n clip-path: inset(-${CLIP_SLACK_PX}px -${CLIP_SLACK_PX}px -${FOCUS_RING_REACH_PX}px);\n}\n.${SCROLLER_CLASS} {\n display: flex;\n flex-wrap: nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n scroll-behavior: smooth;\n scrollbar-width: none;\n -ms-overflow-style: none;\n padding-block: ${OVERFLOW_INSET_PX}px;\n margin-block: -${OVERFLOW_INSET_PX}px;\n /* overflow-x clips both axes, so the end cards would lose a flare; the negative margin trades\n the padding back out and scroll-padding keeps the rest position at zero. */\n padding-inline: ${CARD_FLARE_PX}px;\n margin-inline: -${CARD_FLARE_PX}px;\n scroll-padding-inline: ${CARD_FLARE_PX}px;\n}\n/* A card focused at a faded edge has to stay readable, so the fade lifts entirely. */\n.${ROOT_CLASS}:has(:focus-visible) .${FADE_CLASS} {\n display: none;\n}\n.${SCROLLER_CLASS}::-webkit-scrollbar {\n display: none;\n}\n/* No bottom edge: the strip's rule is the baseline for the add tile as much as for a card. */\n.${ADD_TILE_CLASS} > * {\n background: ${TROUGH_BACKGROUND};\n border-radius: ${CARD_RADIUS};\n}\n.${ADD_TILE_CLASS}:hover:not(:has(button:disabled)) > * {\n background: ${ADD_HOVER_BACKGROUND};\n}\n.${ADD_TILE_CLASS} button:active:not(:disabled) {\n opacity: 0.8;\n}\n.${ADD_TILE_CLASS}:has(button:active) > * {\n background: ${TROUGH_BACKGROUND};\n}\n.${ADD_TILE_CLASS}[data-emphasis='secondary'] button {\n border-color: ${ADD_PILL_BORDER};\n box-shadow: ${LIP_SHADOW};\n}\n.${ADD_TILE_CLASS}[data-emphasis='secondary']:hover:not(:has(button:disabled)) button {\n border-color: ${ADD_PILL_BORDER_ACTIVE};\n box-shadow: ${ADD_PILL_SHADOW_DEEP};\n}\n.${ADD_TILE_CLASS}[data-emphasis='secondary'] button:active:not(:disabled) {\n border-color: ${ADD_PILL_BORDER_ACTIVE};\n box-shadow: ${ADD_PILL_SHADOW_DEEP};\n}\n.${ADD_TILE_CLASS}[data-emphasis='primary'] button {\n border-color: transparent;\n box-shadow: ${ADD_PILL_PRIMARY_SHADOW};\n}\n.${SCROLLER_CLASS} > * {\n flex: 0 0 auto;\n min-width: 0;\n}\n.${SCROLLER_CLASS} > * + * {\n border-left: 1px solid ${DIVIDER_COLOR};\n}\n.${SCROLLER_CLASS}[data-snap='true'] {\n scroll-snap-type: x proximity;\n}\n.${SCROLLER_CLASS}[data-snap='true'] > * {\n scroll-snap-align: start;\n}\n@media (prefers-reduced-motion: reduce) {\n .${SCROLLER_CLASS} {\n scroll-behavior: auto;\n }\n .${SCROLLER_CLASS}[data-snap='true'] {\n scroll-snap-type: none;\n }\n .${SCROLLER_CLASS}[data-snap='true'] > * {\n scroll-snap-align: none;\n }\n}`;\n\nconst STYLE_ID = 'malachite-card-strip-style';\n\n/** `window.matchMedia` is absent under SSR and in older test environments. */\nconst prefersReducedMotion = (): boolean => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return true;\n }\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n};\n\nconst radioValue = (radio: HTMLElement): string | null =>\n radio.dataset.value ?? radio.getAttribute('value');\n\nconst isRadioDisabled = (radio: HTMLElement): boolean =>\n radio.hasAttribute('disabled') || radio.getAttribute('aria-disabled') === 'true';\n\nconst actionsFor = (radio: HTMLElement): HTMLElement | null => {\n const card = radio.parentElement;\n if (!card || card.querySelectorAll(RADIO_SELECTOR).length !== 1) {\n return null;\n }\n return card.querySelector<HTMLElement>(ACTIONS_SELECTOR);\n};\n\n/** A card is wider than its radio, so `closest` misses clicks on the count row. */\nconst radioForClick = (target: Element, root: Element): HTMLElement | null => {\n const direct = target.closest<HTMLElement>(RADIO_SELECTOR);\n if (direct) {\n return direct;\n }\n if (target.closest(ACTIONS_SELECTOR)) {\n return null;\n }\n let node: Element | null = target;\n while (node && root.contains(node)) {\n const radios: NodeListOf<HTMLElement> = node.querySelectorAll(RADIO_SELECTOR);\n if (radios.length === 1 && radios[0].parentElement === node) {\n return radios[0];\n }\n node = node.parentElement;\n }\n return null;\n};\n\nconst actionControls = (radio: HTMLElement): HTMLElement[] => {\n const actions = actionsFor(radio);\n return actions ? Array.from(actions.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)) : [];\n};\n\nconst suppressTabStop = (element: HTMLElement): void => {\n if (!element.hasAttribute(PREV_TABINDEX_ATTR)) {\n element.setAttribute(PREV_TABINDEX_ATTR, element.getAttribute('tabindex') ?? '');\n }\n element.setAttribute('tabindex', '-1');\n};\n\nconst restoreTabStop = (element: HTMLElement): void => {\n if (!element.hasAttribute(PREV_TABINDEX_ATTR)) {\n return;\n }\n const previous = element.getAttribute(PREV_TABINDEX_ATTR);\n element.removeAttribute(PREV_TABINDEX_ATTR);\n if (previous) {\n element.setAttribute('tabindex', previous);\n } else {\n element.removeAttribute('tabindex');\n }\n};\n\nconst TONE_RULE: Record<CardStripTone, string> = {\n profile: 'var(--malachite-selectable-card-selected-border, #047b43)',\n library: 'var(--malachite-selectable-card-library-selected-border, #bbbbbb)',\n editing: 'var(--malachite-selectable-card-pending-foreground, #96580a)',\n};\nconst RULE_ROW_STYLE: React.CSSProperties = {\n backgroundRepeat: 'no-repeat',\n backgroundPosition: 'left bottom',\n backgroundSize: `100% ${BOTTOM_RULE_WEIGHT_PX}px`,\n};\n\n/** The rule runs under the flare's tip rather than butting against it, so antialiasing\n * cannot open the junction into a gap. */\nconst RULE_GAP_OVERLAP_PX = 0.5;\n\nconst FLARE_TIP_INSET_PX = CARD_FLARE_PX - CARD_FLARE_TIP_PX;\n\nconst flareTips = (card: HTMLElement): { left: number; right: number } | null => {\n const flare = card.querySelector(`:scope > .${FLARE_CLASS}`);\n if (!flare) {\n return null;\n }\n const { left, right } = flare.getBoundingClientRect();\n return { left: left + FLARE_TIP_INSET_PX, right: right - FLARE_TIP_INSET_PX };\n};\n\n/** The rule is cut where the selected card stands, never covered: the strip's clip lands on the\n * rule's own edge, so a cover takes the same partial alpha and the rule bleeds through it. */\nconst paintRule = (\n root: HTMLElement | null,\n scroller: HTMLElement | null,\n card: HTMLElement | null | undefined,\n tone: CardStripTone,\n): void => {\n if (!root) {\n return;\n }\n const colour = TONE_RULE[tone];\n const rootRect = root.getBoundingClientRect();\n const rootLeft = rootRect.left;\n const clip = card && scroller?.contains(card) ? scroller.getBoundingClientRect() : rootRect;\n const cardRect = card?.getBoundingClientRect();\n const tips = card ? flareTips(card) : null;\n const tipLeft = tips?.left ?? (cardRect ? cardRect.left - CARD_FLARE_TIP_PX : 0);\n const tipRight = tips?.right ?? (cardRect ? cardRect.right + CARD_FLARE_TIP_PX : 0);\n const from = cardRect ? Math.max(tipLeft, clip.left) + RULE_GAP_OVERLAP_PX - rootLeft : 0;\n const to = cardRect ? Math.min(tipRight, clip.right) - RULE_GAP_OVERLAP_PX - rootLeft : 0;\n\n root.style.backgroundImage =\n to > from\n ? `linear-gradient(to right, ${colour} 0 ${from}px, transparent ${from}px ${to}px, ${colour} ${to}px 100%)`\n : `linear-gradient(to right, ${colour} 0 100%)`;\n};\n\nconst BLEED_STYLE: React.CSSProperties = {\n marginInline: `calc(${CONTENT_INSET} * -1)`,\n paddingInline: CONTENT_INSET,\n};\n\n/** The rule's row is a margin, never padding: a background paints under its own padding, which\n * would hide the very line the troughs stand on. */\nconst TROUGH_SURFACE: React.CSSProperties = {\n background: TROUGH_BACKGROUND,\n borderRadius: TROUGH_RADIUS,\n paddingTop: `${TROUGH_SHOULDER_PX}px`,\n paddingInline: `${TROUGH_SHOULDER_PX}px`,\n marginBottom: `${BOTTOM_RULE_WEIGHT_PX}px`,\n};\nconst TROUGH_STYLE: React.CSSProperties = {\n ...TROUGH_SURFACE,\n marginInline: `${GUTTER_REST_PX}px`,\n};\nconst TROUGH_GUTTER_STYLES: Record<string, React.CSSProperties> = Object.fromEntries(\n [GUTTER_REST_PX, GUTTER_OPEN_PX].flatMap((start) =>\n [GUTTER_REST_PX, GUTTER_OPEN_PX].map((end) => [\n `${start}:${end}`,\n { ...TROUGH_SURFACE, marginInline: `${start}px ${end}px` },\n ]),\n ),\n);\nconst ADD_TILE_SHAPE_STYLE: React.CSSProperties = TROUGH_SURFACE;\n\nconst PINNED_SLOT_STYLE: React.CSSProperties = TROUGH_SURFACE;\n\nconst EMPTY_ADD_SLOT_STYLE: React.CSSProperties = {\n marginInlineStart: `${GUTTER_REST_PX}px`,\n};\n\nconst ADD_PILL_FILL: Record<CardStripAddTileEmphasis, React.CSSProperties> = {\n primary: {\n backgroundColor: ADD_PILL_PRIMARY_BACKGROUND,\n color: ADD_PILL_PRIMARY_FOREGROUND,\n },\n secondary: { backgroundColor: ADD_PILL_BACKGROUND, color: ADD_PILL_FOREGROUND },\n};\n\nconst AddTile: React.FC<CardStripAddTileProps> = ({\n label,\n icon,\n onClick,\n disabled = false,\n emphasis = 'secondary',\n className = '',\n}) => (\n <div\n className={ADD_TILE_CLASS}\n data-emphasis={emphasis}\n style={{\n ...ADD_TILE_SHAPE_STYLE,\n width: `${SLOT_WIDTH_PX}px`,\n height: `calc(100% - ${BOTTOM_RULE_WEIGHT_PX}px)`,\n }}\n >\n <div className=\"flex h-full items-center justify-center px-4\">\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n style={ADD_PILL_FILL[emphasis]}\n className={`${FOCUS_RING} inline-flex items-center justify-center gap-1.5 h-[var(--malachite-control-height-medium,32px)] w-[108px] px-2.5 rounded-xl border border-solid text-[length:var(--malachite-font-size-small,13px)] font-medium whitespace-nowrap ${\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'\n } ${className}`}\n >\n <span className=\"inline-flex h-[13px] w-[13px] shrink-0 items-center justify-center\">\n {icon ?? <PlusIcon size={13} />}\n </span>\n {label}\n </button>\n </div>\n </div>\n);\n\nconst isAddTile = (node: React.ReactNode): node is React.ReactElement<CardStripAddTileProps> =>\n React.isValidElement(node) && node.type === AddTile;\n\nconst hidesAddTile = (child: React.ReactNode): boolean =>\n React.isValidElement<{ children?: React.ReactNode }>(child) &&\n child.type === React.Fragment &&\n React.Children.toArray(child.props.children).some(isAddTile);\n\ninterface ArrowButtonProps {\n side: 'left' | 'right';\n onClick: () => void;\n}\n\nconst ArrowButton: React.FC<ArrowButtonProps> = ({ side, onClick }) => (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n aria-label={side === 'left' ? 'Scroll left' : 'Scroll right'}\n onClick={onClick}\n className=\"absolute top-1/2 -translate-y-1/2 z-10 inline-flex items-center justify-center w-5 h-5 rounded-lg cursor-pointer text-[var(--malachite-text-secondary)]\"\n style={{\n [side]: `-${ARROW_OFFSET_PX}px`,\n background: ARROW_BACKGROUND,\n border: `1px solid ${ARROW_BORDER}`,\n boxShadow: LIP_SHADOW,\n }}\n >\n {side === 'left' ? (\n <ArrowLeftIcon size={ARROW_GLYPH_PX} />\n ) : (\n <ForwardArrowIcon size={ARROW_GLYPH_PX} />\n )}\n </button>\n);\n\n/** A horizontally scrolling radiogroup of cards — the \"pick one of these\" strip. */\nconst CardStrip: React.FC<CardStripProps> & { AddTile: React.FC<CardStripAddTileProps> } = ({\n value,\n tone,\n onChange,\n children,\n leading,\n arrows = true,\n fadeEdges = true,\n snap = true,\n bleed = false,\n scrollSelectedIntoView = true,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className = '',\n style,\n}) => {\n const rootRef = useRef<HTMLDivElement>(null);\n const scrollerRef = useRef<HTMLDivElement>(null);\n const hasPositioned = useRef(false);\n const [edges, setEdges] = useState({ canScrollLeft: false, canScrollRight: false });\n\n useAdoptedStyleSheet(rootRef, SCROLLER_CSS, STYLE_ID);\n\n const childList = React.Children.toArray(children);\n const cards = childList.filter((child) => !isAddTile(child));\n const wrappedAddTile = cards.some(hidesAddTile);\n const hasCards = cards.length > 0;\n\n const addTiles = childList\n .filter(isAddTile)\n .map((tile) =>\n tile.props.emphasis === undefined\n ? React.cloneElement(tile, { emphasis: hasCards ? 'secondary' : 'primary' })\n : tile,\n );\n\n const childCount = childList.length;\n\n const getRadios = useCallback((): HTMLElement[] => {\n const root = rootRef.current;\n if (!root) {\n return [];\n }\n return Array.from(root.querySelectorAll<HTMLElement>(RADIO_SELECTOR));\n }, []);\n\n const getNavigableRadios = useCallback(\n (): HTMLElement[] => getRadios().filter((radio) => radioValue(radio) !== null),\n [getRadios],\n );\n\n const warned = useRef(new Set<string>());\n const warnOnce = useCallback((key: string, message: string): void => {\n if (warned.current.has(key)) {\n return;\n }\n warned.current.add(key);\n console.warn(message);\n }, []);\n\n const [derivedTone, setDerivedTone] = useState<CardStripTone>('profile');\n\n useLayoutEffect(() => {\n const selectedCard = getRadios()\n .find((radio) => radioValue(radio) === value)\n ?.parentElement?.getAttribute('data-variant');\n if (\n selectedCard === 'profile' ||\n selectedCard === 'library' ||\n selectedCard === 'editing'\n ) {\n setDerivedTone(selectedCard);\n }\n }, [getRadios, value]);\n\n useLayoutEffect(() => {\n const radios = getRadios();\n const navigable = getNavigableRadios();\n const selected = navigable.find((radio) => radioValue(radio) === value);\n const tabStop = selected ?? navigable.find((radio) => !isRadioDisabled(radio)) ?? null;\n\n radios.forEach((radio) => {\n const holdsTabStop = radio === tabStop;\n const nextTabIndex = holdsTabStop ? 0 : -1;\n if (radio.tabIndex !== nextTabIndex) {\n radio.tabIndex = nextTabIndex;\n }\n for (const control of actionControls(radio)) {\n if (holdsTabStop) {\n restoreTabStop(control);\n } else {\n suppressTabStop(control);\n }\n }\n });\n\n if (process.env.NODE_ENV === 'production') {\n return;\n }\n\n if (navigable.length !== radios.length) {\n warnOnce(\n 'missing-value',\n 'CardStrip: a child with role=\"radio\" has no `data-value`. It cannot be selected or reached by arrow keys, so it is excluded from the radio set. Give every card a `data-value`.',\n );\n }\n\n const values = new Set<string>();\n for (const radio of navigable) {\n const current = radioValue(radio);\n if (current === null) {\n continue;\n }\n if (values.has(current)) {\n warnOnce(\n `duplicate:${current}`,\n `CardStrip: two cards share the data-value \"${current}\". Both will read as checked and only the first is selectable — data-value must be unique.`,\n );\n }\n values.add(current);\n }\n\n const selectionSettled = value !== '';\n\n if (radios.length > 0 && selectionSettled && !values.has(value)) {\n warnOnce(\n `unmatched:${value}`,\n `CardStrip: value \"${value}\" matches no card's data-value, so the group reports no selection.`,\n );\n }\n\n const checked = radios.filter(\n (radio) => radio.getAttribute('aria-checked') === 'true',\n ).length;\n if (radios.length > 0 && selectionSettled && checked !== 1) {\n warnOnce(\n `checked:${checked}`,\n `CardStrip: ${checked} cards are aria-checked, but a radiogroup has exactly one. Drive each card's checked state from the strip's \\`value\\`.`,\n );\n }\n\n if (wrappedAddTile) {\n warnOnce(\n 'wrapped-add-tile',\n 'CardStrip: a CardStrip.AddTile inside a fragment is treated as a card and scrolls with them. The add tile must be a direct child of CardStrip.',\n );\n }\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: cards arriving is the signal\n useLayoutEffect(() => {\n if (!scrollSelectedIntoView) {\n return;\n }\n const scroller = scrollerRef.current;\n const selected = getRadios().find((radio) => radioValue(radio) === value);\n // jsdom implements neither, and a strip that cannot scroll has nothing to bring into view.\n if (!scroller || !selected || typeof scroller.scrollTo !== 'function') {\n return;\n }\n\n // Positioned rather than asked for: the track is scroll-snapped, and `scrollIntoView`\n // on a card several widths away lands back on the nearest snap point instead — so a\n // card appended past the end never came into view at all.\n // Measured against the scroller rather than an offset parent: the cards are flex\n // children whose `offsetParent` is not the scroller, so `offsetLeft` is not its frame.\n const card = (selected.closest('[role=\"radio\"]') ?? selected) as HTMLElement;\n const cardRect = card.getBoundingClientRect();\n const viewRect = scroller.getBoundingClientRect();\n const left = scroller.scrollLeft + (cardRect.left - viewRect.left);\n const right = left + cardRect.width;\n const visibleFrom = scroller.scrollLeft + CARD_FLARE_PX;\n const visibleTo = scroller.scrollLeft + scroller.clientWidth - CARD_FLARE_PX;\n\n // The first placement is where the strip opens — a deep link, not a move — so it is\n // instant. Every later one is the selection travelling, and travel is legible only if\n // you can see it happen.\n const wasPositioned = hasPositioned.current;\n hasPositioned.current = true;\n\n if (left >= visibleFrom && right <= visibleTo) {\n return;\n }\n\n scroller.scrollTo({\n left:\n right > visibleTo\n ? right - scroller.clientWidth + CARD_FLARE_PX\n : left - CARD_FLARE_PX,\n behavior: wasPositioned && !prefersReducedMotion() ? 'smooth' : 'instant',\n });\n }, [getRadios, scrollSelectedIntoView, value, childCount]);\n\n const ruleTone = tone ?? derivedTone;\n const callerPaintsBackground =\n style?.background !== undefined || style?.backgroundImage !== undefined;\n\n const measure = useCallback(() => {\n const scroller = scrollerRef.current;\n if (!callerPaintsBackground) {\n paintRule(\n rootRef.current,\n scroller,\n getRadios().find((radio) => radioValue(radio) === value)?.parentElement,\n ruleTone,\n );\n }\n if (!scroller) {\n return;\n }\n const { scrollWidth, clientWidth, scrollLeft } = scroller;\n const overflows = scrollWidth > clientWidth + EDGE_EPSILON_PX;\n const next = {\n canScrollLeft: overflows && scrollLeft > EDGE_EPSILON_PX,\n canScrollRight: overflows && scrollLeft + clientWidth < scrollWidth - EDGE_EPSILON_PX,\n };\n setEdges((previous) =>\n previous.canScrollLeft === next.canScrollLeft &&\n previous.canScrollRight === next.canScrollRight\n ? previous\n : next,\n );\n }, [callerPaintsBackground, getRadios, ruleTone, value]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: adding or removing a card changes the scroll width, so re-measure on the count\n useLayoutEffect(() => {\n measure();\n\n const scroller = scrollerRef.current;\n if (!scroller) {\n return;\n }\n\n const onScroll = (): void => measure();\n scroller.addEventListener('scroll', onScroll, { passive: true });\n\n const observer =\n typeof ResizeObserver !== 'undefined' ? new ResizeObserver(() => measure()) : null;\n observer?.observe(scroller);\n\n return () => {\n scroller.removeEventListener('scroll', onScroll);\n observer?.disconnect();\n };\n }, [measure, childCount]);\n\n const scrollByStep = useCallback((direction: -1 | 1) => {\n const scroller = scrollerRef.current;\n if (!scroller || typeof scroller.scrollBy !== 'function') {\n return;\n }\n scroller.scrollBy({\n left: direction * scrollStepFor(scroller),\n behavior: prefersReducedMotion() ? 'auto' : 'smooth',\n });\n }, []);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (!NAV_KEYS.has(event.key)) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Element) || !target.closest(RADIO_SELECTOR)) {\n return;\n }\n\n const enabled = getNavigableRadios().filter((radio) => !isRadioDisabled(radio));\n if (enabled.length === 0) {\n return;\n }\n\n event.preventDefault();\n\n const currentPosition = enabled.findIndex((radio) => radioValue(radio) === value);\n let nextPosition: number;\n if (event.key === 'Home') {\n nextPosition = 0;\n } else if (event.key === 'End') {\n nextPosition = enabled.length - 1;\n } else {\n const delta = event.key === 'ArrowLeft' || event.key === 'ArrowUp' ? -1 : 1;\n const from = currentPosition === -1 ? 0 : currentPosition;\n nextPosition = (from + delta + enabled.length) % enabled.length;\n }\n\n const next = enabled[nextPosition];\n const nextValue = radioValue(next);\n if (nextValue !== null && nextValue !== value) {\n onChange(nextValue);\n }\n next.focus();\n },\n [getNavigableRadios, onChange, value],\n );\n\n const handleClick = useCallback(\n (event: React.MouseEvent) => {\n const target = event.target;\n if (!(target instanceof Element)) {\n return;\n }\n const root = rootRef.current;\n if (!root) {\n return;\n }\n const radio = radioForClick(target, root);\n if (!radio || isRadioDisabled(radio)) {\n return;\n }\n const clicked = radioValue(radio);\n if (clicked !== null && clicked !== value) {\n onChange(clicked);\n }\n },\n [onChange, value],\n );\n\n const showLeftArrow = arrows && edges.canScrollLeft;\n const showRightArrow = arrows && edges.canScrollRight;\n\n const fadeLeft = fadeEdges && edges.canScrollLeft;\n const fadeRight = fadeEdges && edges.canScrollRight;\n const troughStyle = arrows\n ? TROUGH_GUTTER_STYLES[\n `${showLeftArrow ? GUTTER_OPEN_PX : GUTTER_REST_PX}:${\n showRightArrow ? GUTTER_OPEN_PX : GUTTER_REST_PX\n }`\n ]\n : TROUGH_STYLE;\n\n return (\n <div\n ref={rootRef}\n onKeyDown={handleKeyDown}\n onClick={handleClick}\n className={`${ROOT_CLASS} flex items-stretch ${className}`}\n style={{\n ...RULE_ROW_STYLE,\n ...(bleed ? BLEED_STYLE : null),\n ...style,\n }}\n >\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={hasCards ? 'flex items-stretch min-w-0' : 'flex items-stretch'}\n >\n {leading ? (\n <CardStripSlotContext.Provider value={PINNED_SLOT}>\n <div className=\"shrink-0\" style={PINNED_SLOT_STYLE}>\n {leading}\n </div>\n </CardStripSlotContext.Provider>\n ) : null}\n {hasCards ? (\n <div\n {...{ [TROUGH_ATTR]: '' }}\n className=\"relative min-w-0 shrink basis-auto\"\n style={troughStyle}\n >\n <div\n ref={scrollerRef}\n tabIndex={-1}\n {...{ [SCROLLER_ATTR]: '' }}\n data-snap={snap ? 'true' : 'false'}\n className={SCROLLER_CLASS}\n >\n <CardStripSlotContext.Provider value={SCROLLED_SLOT}>\n {cards}\n </CardStripSlotContext.Provider>\n </div>\n {showLeftArrow ? (\n <ArrowButton side=\"left\" onClick={() => scrollByStep(-1)} />\n ) : null}\n {showRightArrow ? (\n <ArrowButton side=\"right\" onClick={() => scrollByStep(1)} />\n ) : null}\n {fadeLeft || fadeRight ? (\n <div\n aria-hidden\n data-card-strip-fade=\"\"\n className={`${FADE_CLASS} absolute pointer-events-none`}\n style={{\n inset: `-${TROUGH_SHOULDER_PX}px -${CARD_FLARE_PX}px 0`,\n background: `linear-gradient(to right, ${fadeLeft ? FADE_COLOR : 'transparent'} 0, transparent ${FADE_RAMP_PX}px, transparent calc(100% - ${FADE_RAMP_PX}px), ${fadeRight ? FADE_COLOR : 'transparent'} 100%)`,\n }}\n />\n ) : null}\n </div>\n ) : null}\n </div>\n {addTiles.length > 0 ? (\n <div\n className=\"shrink-0\"\n style={!hasCards && leading ? EMPTY_ADD_SLOT_STYLE : undefined}\n >\n {addTiles}\n </div>\n ) : null}\n </div>\n );\n};\n\nCardStrip.AddTile = AddTile;\n\nexport default CardStrip;\nexport { CardStrip };\n"],"names":["NAV_KEYS","RADIO_SELECTOR","SCROLLER_ATTR","TROUGH_ATTR","ROOT_CLASS","SCROLLER_CLASS","FADE_CLASS","ADD_TILE_CLASS","ACTIONS_SELECTOR","FOCUSABLE_SELECTOR","PREV_TABINDEX_ATTR","EDGE_EPSILON_PX","SCROLL_STEP_RATIO","scrollStepFor","scroller","first","second","pitch","visible","CARD_FLARE_PX","FADE_WIDTH_PX","ARROW_SIZE_PX","ARROW_GLYPH_PX","GUTTER_REST_PX","GUTTER_OPEN_PX","ARROW_OFFSET_PX","LIP_SHADOW","ARROW_BACKGROUND","ARROW_BORDER","TROUGH_BACKGROUND","CARD_CORNER","CARD_RADIUS","TROUGH_CORNER","TROUGH_RADIUS","TROUGH_SHOULDER_PX","FADE_RAMP_PX","SLOT_WIDTH_PX","CARD_WIDTH_PX","DIVIDER_COLOR","FADE_COLOR","ADD_HOVER_BACKGROUND","ADD_PILL_BORDER","ADD_PILL_BORDER_ACTIVE","ADD_PILL_SHADOW_DEEP","ADD_PILL_BACKGROUND","ADD_PILL_FOREGROUND","ADD_PILL_PRIMARY_BACKGROUND","ADD_PILL_PRIMARY_FOREGROUND","ADD_PILL_PRIMARY_SHADOW","BOTTOM_RULE_WEIGHT_PX","STRIP_RULE_PX","OVERFLOW_INSET_PX","CLIP_SLACK_PX","FOCUS_RING_REACH_PX","SCROLLER_CSS","STYLE_ID","prefersReducedMotion","radioValue","radio","isRadioDisabled","actionsFor","card","radioForClick","target","root","direct","node","radios","actionControls","actions","suppressTabStop","element","restoreTabStop","previous","TONE_RULE","RULE_ROW_STYLE","RULE_GAP_OVERLAP_PX","FLARE_TIP_INSET_PX","CARD_FLARE_TIP_PX","flareTips","flare","FLARE_CLASS","left","right","paintRule","tone","colour","rootRect","rootLeft","clip","cardRect","tips","tipLeft","tipRight","from","to","BLEED_STYLE","CONTENT_INSET","TROUGH_SURFACE","TROUGH_STYLE","TROUGH_GUTTER_STYLES","start","end","ADD_TILE_SHAPE_STYLE","PINNED_SLOT_STYLE","EMPTY_ADD_SLOT_STYLE","ADD_PILL_FILL","AddTile","label","icon","onClick","disabled","emphasis","className","jsx","jsxs","FOCUS_RING","PlusIcon","isAddTile","React","hidesAddTile","child","ArrowButton","side","ArrowLeftIcon","ForwardArrowIcon","CardStrip","value","onChange","children","leading","arrows","fadeEdges","snap","bleed","scrollSelectedIntoView","ariaLabel","ariaLabelledBy","style","rootRef","useRef","scrollerRef","hasPositioned","edges","setEdges","useState","useAdoptedStyleSheet","childList","cards","wrappedAddTile","hasCards","addTiles","tile","childCount","getRadios","useCallback","getNavigableRadios","warned","warnOnce","key","message","derivedTone","setDerivedTone","useLayoutEffect","selectedCard","_b","_a","navigable","tabStop","holdsTabStop","nextTabIndex","control","values","current","selectionSettled","checked","selected","viewRect","visibleFrom","visibleTo","wasPositioned","ruleTone","callerPaintsBackground","measure","scrollWidth","clientWidth","scrollLeft","overflows","next","onScroll","observer","scrollByStep","direction","handleKeyDown","event","enabled","currentPosition","nextPosition","delta","nextValue","handleClick","clicked","showLeftArrow","showRightArrow","fadeLeft","fadeRight","troughStyle","CardStripSlotContext","PINNED_SLOT","SCROLLED_SLOT"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -420,8 +420,10 @@ export declare interface CardStripProps {
420
420
  /** Run the bottom rule the full width of the page card while the cards stay on the gutter.
421
421
  * Only has an effect inside a layout that publishes its inset (`PageLayout`). */
422
422
  bleed?: boolean;
423
- /** Whether a selection change scrolls the selected card into view. Set `false` when the
424
- * value comes from a URL, or a deep-linked strip below the fold jumps the page on load. */
423
+ /** Whether a selection change scrolls the selected card into view. The strip's opening
424
+ * selection is placed instantly; later ones slide, unless motion is reduced. Set `false`
425
+ * when the value comes from a URL, or a deep-linked strip below the fold jumps the page
426
+ * on load. */
425
427
  scrollSelectedIntoView?: boolean;
426
428
  'aria-label'?: string;
427
429
  'aria-labelledby'?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackone/malachite",
3
- "version": "2.23.0",
3
+ "version": "2.23.1",
4
4
  "description": "StackOne's themeable React component library — Shadow DOM isolated, scoped Tailwind, theme-token driven.",
5
5
  "license": "MIT",
6
6
  "author": "StackOne",