@12-apps/ui 6.45.5 → 6.45.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/_internal/components/form/RadioGroup/RadioGroup.js +4 -2
  2. package/dist/_internal/components/form/RadioGroup/RadioGroup.variants.js +3 -1
  3. package/dist/_internal/components/form/index.js +2 -2
  4. package/dist/_internal/components/index.js +2 -2
  5. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.js +4 -4
  6. package/dist/_internal/components/layout/SettingsLayout/SettingsPanel.js +3 -3
  7. package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.js +2 -2
  8. package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.scroll.js +1 -1
  9. package/dist/{chunk-QLAFJZDS.js → chunk-AJUSBPWG.js} +5 -2
  10. package/dist/chunk-AJUSBPWG.js.map +1 -0
  11. package/dist/{chunk-FNLD2KCQ.js → chunk-EWVJJ32N.js} +2 -2
  12. package/dist/{chunk-YWQ7QCWR.js → chunk-F3Q4CMRB.js} +2 -2
  13. package/dist/{chunk-XHA2NXLD.js → chunk-HSKLX2NO.js} +2 -2
  14. package/dist/{chunk-B7HYM3QB.js → chunk-RIAZPGHT.js} +2 -2
  15. package/dist/{chunk-6H4TPEMO.js → chunk-SDWOWB6F.js} +6 -1
  16. package/dist/chunk-SDWOWB6F.js.map +1 -0
  17. package/dist/form/RadioGroup.js +4 -2
  18. package/dist/layout/SettingsLayout.js +4 -4
  19. package/dist/types/components/form/RadioGroup/RadioGroup.variants.d.ts.map +1 -1
  20. package/dist/types/components/layout/SettingsLayout/SettingsSectionChips.scroll.d.ts +6 -7
  21. package/dist/types/components/layout/SettingsLayout/SettingsSectionChips.scroll.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/src/components/form/RadioGroup/RadioGroup.variants.tsx +11 -0
  24. package/src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts +19 -19
  25. package/dist/chunk-6H4TPEMO.js.map +0 -1
  26. package/dist/chunk-QLAFJZDS.js.map +0 -1
  27. /package/dist/{chunk-FNLD2KCQ.js.map → chunk-EWVJJ32N.js.map} +0 -0
  28. /package/dist/{chunk-YWQ7QCWR.js.map → chunk-F3Q4CMRB.js.map} +0 -0
  29. /package/dist/{chunk-XHA2NXLD.js.map → chunk-HSKLX2NO.js.map} +0 -0
  30. /package/dist/{chunk-B7HYM3QB.js.map → chunk-RIAZPGHT.js.map} +0 -0
@@ -1,14 +1,16 @@
1
1
  import {
2
2
  RadioGroup
3
- } from "../../../../chunk-XHA2NXLD.js";
4
- import "../../../../chunk-6H4TPEMO.js";
3
+ } from "../../../../chunk-HSKLX2NO.js";
4
+ import "../../../../chunk-SDWOWB6F.js";
5
5
  import "../../../../chunk-GG62LKA3.js";
6
6
  import "../../../../chunk-Z6WSW6B4.js";
7
7
  import "../../../../chunk-HPK33ACY.js";
8
+ import "../../../../chunk-7ZPUN7TV.js";
8
9
  import "../../../../chunk-M47ZOUGF.js";
9
10
  import "../../../../chunk-7FDU3FIN.js";
10
11
  import "../../../../chunk-EPEJMTCQ.js";
11
12
  import "../../../../chunk-GDN2LUTZ.js";
13
+ import "../../../../chunk-FZXKH2ZT.js";
12
14
  import "../../../../chunk-O6MJWHU5.js";
13
15
  import "../../../../chunk-26X4CZVR.js";
14
16
  import "../../../../chunk-FQ6UW7IY.js";
@@ -7,13 +7,15 @@ import {
7
7
  OptionLabel,
8
8
  SegmentRadios,
9
9
  testId
10
- } from "../../../../chunk-6H4TPEMO.js";
10
+ } from "../../../../chunk-SDWOWB6F.js";
11
11
  import "../../../../chunk-GG62LKA3.js";
12
12
  import "../../../../chunk-Z6WSW6B4.js";
13
+ import "../../../../chunk-7ZPUN7TV.js";
13
14
  import "../../../../chunk-M47ZOUGF.js";
14
15
  import "../../../../chunk-7FDU3FIN.js";
15
16
  import "../../../../chunk-EPEJMTCQ.js";
16
17
  import "../../../../chunk-GDN2LUTZ.js";
18
+ import "../../../../chunk-FZXKH2ZT.js";
17
19
  import "../../../../chunk-O6MJWHU5.js";
18
20
  import "../../../../chunk-26X4CZVR.js";
19
21
  import "../../../../chunk-FQ6UW7IY.js";
@@ -8,8 +8,8 @@ import "../../../chunk-QWVETTIY.js";
8
8
  import "../../../chunk-IQ6WX2GS.js";
9
9
  import {
10
10
  RadioGroup
11
- } from "../../../chunk-XHA2NXLD.js";
12
- import "../../../chunk-6H4TPEMO.js";
11
+ } from "../../../chunk-HSKLX2NO.js";
12
+ import "../../../chunk-SDWOWB6F.js";
13
13
  import "../../../chunk-GG62LKA3.js";
14
14
  import "../../../chunk-Z6WSW6B4.js";
15
15
  import "../../../chunk-WMY276HD.js";
@@ -231,8 +231,8 @@ import "../../chunk-YBVKLJAL.js";
231
231
  import "../../chunk-IQ6WX2GS.js";
232
232
  import {
233
233
  RadioGroup
234
- } from "../../chunk-XHA2NXLD.js";
235
- import "../../chunk-6H4TPEMO.js";
234
+ } from "../../chunk-HSKLX2NO.js";
235
+ import "../../chunk-SDWOWB6F.js";
236
236
  import "../../chunk-GG62LKA3.js";
237
237
  import "../../chunk-Z6WSW6B4.js";
238
238
  import "../../chunk-WMY276HD.js";
@@ -1,14 +1,14 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsLayout
4
- } from "../../../../chunk-FNLD2KCQ.js";
5
- import "../../../../chunk-B7HYM3QB.js";
4
+ } from "../../../../chunk-EWVJJ32N.js";
5
+ import "../../../../chunk-RIAZPGHT.js";
6
6
  import "../../../../chunk-TNYKM4UU.js";
7
7
  import "../../../../chunk-V5EWCJBT.js";
8
8
  import "../../../../chunk-BXC6GRLE.js";
9
9
  import "../../../../chunk-6KEXHOIF.js";
10
- import "../../../../chunk-YWQ7QCWR.js";
11
- import "../../../../chunk-QLAFJZDS.js";
10
+ import "../../../../chunk-F3Q4CMRB.js";
11
+ import "../../../../chunk-AJUSBPWG.js";
12
12
  import "../../../../chunk-DBFRCTI5.js";
13
13
  import "../../../../chunk-NYFNF7I5.js";
14
14
  import "../../../../chunk-HPK33ACY.js";
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsPanel
4
- } from "../../../../chunk-B7HYM3QB.js";
4
+ } from "../../../../chunk-RIAZPGHT.js";
5
5
  import "../../../../chunk-6KEXHOIF.js";
6
- import "../../../../chunk-YWQ7QCWR.js";
7
- import "../../../../chunk-QLAFJZDS.js";
6
+ import "../../../../chunk-F3Q4CMRB.js";
7
+ import "../../../../chunk-AJUSBPWG.js";
8
8
  import "../../../../chunk-DBFRCTI5.js";
9
9
  import "../../../../chunk-NYFNF7I5.js";
10
10
  import "../../../../chunk-YKCAJ2TN.js";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsSectionChips
4
- } from "../../../../chunk-YWQ7QCWR.js";
5
- import "../../../../chunk-QLAFJZDS.js";
4
+ } from "../../../../chunk-F3Q4CMRB.js";
5
+ import "../../../../chunk-AJUSBPWG.js";
6
6
  import "../../../../chunk-DBFRCTI5.js";
7
7
  import "../../../../chunk-NYFNF7I5.js";
8
8
  import "../../../../chunk-YKCAJ2TN.js";
@@ -3,7 +3,7 @@ import {
3
3
  physicalScrollLeft,
4
4
  toRawScrollLeft,
5
5
  watchVisitorScroll
6
- } from "../../../../chunk-QLAFJZDS.js";
6
+ } from "../../../../chunk-AJUSBPWG.js";
7
7
  import "../../../../chunk-PZ5AY32C.js";
8
8
  export {
9
9
  isRtlStrip,
@@ -8,6 +8,7 @@ function horizontalDelta(event) {
8
8
  if (!(event instanceof WheelEvent)) return 0;
9
9
  return event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0;
10
10
  }
11
+ var STRIP_SCROLLING_KEYS = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowRight"]);
11
12
  var cachedRtlScrollType;
12
13
  function detectRtlScrollType(doc) {
13
14
  if (cachedRtlScrollType) return cachedRtlScrollType;
@@ -100,7 +101,9 @@ function createGestureListeners(state) {
100
101
  nudge();
101
102
  onPointerUp();
102
103
  };
103
- const onKeydown = nudge;
104
+ const onKeydown = (event) => {
105
+ if (event instanceof KeyboardEvent && STRIP_SCROLLING_KEYS.has(event.key)) nudge();
106
+ };
104
107
  const onWheel = (event) => {
105
108
  if (horizontalDelta(event) !== 0) nudge();
106
109
  };
@@ -199,4 +202,4 @@ export {
199
202
  toRawScrollLeft,
200
203
  watchVisitorScroll
201
204
  };
202
- //# sourceMappingURL=chunk-QLAFJZDS.js.map
205
+ //# sourceMappingURL=chunk-AJUSBPWG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts"],"sourcesContent":["/**\n * Telling the strip's own scrolls from the visitor's (FUT-2606). Split from\n * `SettingsSectionChips.tsx` so the chips stay a component file and the rule\n * for \"who moved the strip\" can be read in one place.\n */\n\n/**\n * How near to where the strip aimed itself it has to come to rest for the scroll\n * to count as the strip's own. A smooth scroll lands on a device pixel, and the\n * target it was given is fractional.\n */\nconst LANDED_SLACK = 1;\n\n/**\n * Where `scrollend` is missing: how long the strip goes without a `scroll`\n * before it counts as settled — generous, since a busy thread can go several\n * frames between smooth-scroll ticks and judging one mid-flight would read\n * the strip's own animation as the visitor's. Too short can latch it for good.\n */\nconst QUIET_BEFORE_SETTLED_MS = 250;\n\n/**\n * How much `scrollLeft` has to move, tick to tick, before a `scroll` event is\n * even a CANDIDATE for arming (FUT-2775). Below this, a browser's own rounding\n * or a repeated event carrying no real motion cannot arm anything by itself.\n * This alone does not stop the false latch the ticket describes: the strip's\n * own `scrollTo` produces real per-tick deltas well past this line, same as a\n * drag would. It only rules out a scroll event that moved nothing.\n */\nconst SCROLL_DELTA_EPSILON = 2;\n\n/**\n * How far a pointer/touch must travel from where it went down to count as\n * MOVED, not merely resting (FUT-2775) — below this, a held tremor isn't a drag.\n */\nconst POINTER_MOVE_EPSILON = 2;\n\n/**\n * How long a key, sideways wheel or pan stays armed through a scroll the strip\n * made itself (FUT-2848) — a busy thread can finish a re-centre before the\n * key's scroll ticks once; past this it lapses, so a later clamp isn't the visitor.\n */\nconst NUDGE_FRESH_MS = 1000;\n\ninterface VisitorScrollWatch {\n /** True once the visitor has moved the strip themselves. */\n hasScrolled: () => boolean;\n /**\n * True while a scroll the visitor MAY be making has not come to rest yet. The\n * strip must not scroll itself under it: that would yank a drag in progress.\n */\n isUndecided: () => boolean;\n /**\n * Where the strip last aimed itself, PHYSICAL pixels (see {@link physicalScrollLeft}) —\n * direction-blind, like every other geometry read in this file. `NaN` before it has.\n */\n aimedAt: () => number;\n /**\n * The strip is about to scroll itself to `left` (physical pixels). Records the\n * aim and NOTHING\n * else: it used to disarm too, and a re-centre landing between a visitor's key\n * press (or wheel, or pan) and the first tick of the scroll it causes wiped\n * the arming — their scroll went unclaimed, read as the strip's own. Left\n * armed, the worst a stale arming does is put the strip's OWN next scroll\n * under judgement, which rests on its aim, is not latched, and disarms.\n */\n beforeOwnScroll: (left: number) => void;\n /** Called once an undecided scroll has come to rest and been judged. */\n onSettled: (listener: () => void) => void;\n detach: () => void;\n}\n\ntype Listeners = Array<[string, (event: Event) => void]>;\n\n/** A wheel's sideways travel: `deltaX`, or `deltaY` with Shift held, as browsers read it. */\nfunction horizontalDelta(event: Event): number {\n if (!(event instanceof WheelEvent)) return 0;\n return event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0;\n}\n\nconst STRIP_SCROLLING_KEYS = new Set(['ArrowLeft', 'ArrowRight']); // verified live in Chromium (FUT-2862)\n\ninterface WatchState {\n pointer: boolean;\n touch: boolean;\n nudged: boolean;\n /** When `nudged` was set (`Date.now()` ms), and whether it outlived an own verdict. */\n nudgedAt: number;\n nudgeKept: boolean;\n undecided: boolean;\n scrolled: boolean;\n aimed: number;\n quiet: ReturnType<typeof setTimeout> | undefined;\n settled: () => void;\n /** `scrollLeft` as of the last `scroll` tick, updated every tick regardless of arming. */\n lastScrollLeft: number;\n /** Where a `pointerdown` on the strip landed, in viewport `clientX`. `NaN` while up. */\n pointerDownAt: number;\n /** True once that pointer has travelled past {@link POINTER_MOVE_EPSILON} from `pointerDownAt`. */\n pointerMoved: boolean;\n /** Same pair, for `touchstart`/`touchmove` — a distinct event stream on some engines. */\n touchDownAt: number;\n touchMoved: boolean;\n}\n\ntype RtlScrollType = 'default' | 'negative' | 'reverse';\n\nlet cachedRtlScrollType: RtlScrollType | undefined;\n\n/**\n * Which of the three incompatible conventions this engine reports an RTL\n * scroller's `scrollLeft` in, probed once and cached (FUT-2775).\n *\n * Per the CSSOM View spec, an RTL scroller's `scrollLeft` is `0` at its\n * (right-hand) start and goes NEGATIVE toward the end — `'negative'` below,\n * what every current evergreen engine implements. Older WebKit mirrored that\n * (`'reverse'`: `0` at the start, growing toward `+max`), and older\n * Chromium/Safari ignored `dir` altogether and kept the plain left-to-right\n * numbering (`'default'`). A hidden probe, not a version sniff, tells them\n * apart — the same technique `@mui/utils`'s `detectScrollType` uses for\n * `Tabs`; reimplemented here rather than taking a new dependency for one\n * probe.\n */\nfunction detectRtlScrollType(doc: Document): RtlScrollType {\n if (cachedRtlScrollType) return cachedRtlScrollType;\n // The exact pixel values below are the probe's mechanism, not a design size:\n // what matters is only that the INNER box is wider than the OUTER one, so the\n // outer one has something to scroll — same technique `@mui/utils` uses,\n // detached and off-screen either way.\n const probe = doc.createElement('div');\n const inner = doc.createElement('div');\n inner.style.width = '10px';\n probe.appendChild(inner);\n probe.dir = 'rtl';\n probe.style.width = '4px';\n probe.style.position = 'absolute';\n probe.style.top = '-1000px';\n probe.style.overflow = 'scroll';\n doc.body.appendChild(probe);\n let type: RtlScrollType = 'reverse';\n if (probe.scrollLeft > 0) {\n type = 'default';\n } else {\n probe.scrollLeft = 1;\n if (probe.scrollLeft === 0) type = 'negative';\n }\n doc.body.removeChild(probe);\n cachedRtlScrollType = type;\n return type;\n}\n\n/** True when the strip's own computed direction is right-to-left. */\nexport function isRtlStrip(strip: HTMLElement): boolean {\n const view = strip.ownerDocument.defaultView;\n const getComputedStyle = view?.getComputedStyle ?? globalThis.getComputedStyle;\n return getComputedStyle(strip).direction === 'rtl';\n}\n\n/**\n * `strip.scrollLeft`, renumbered so `0` is always the strip's physical LEFT\n * edge and larger is always further physically right — whatever `direction`\n * and whatever convention this engine uses to report it raw (FUT-2775).\n *\n * Every geometry read in this file (`getBoundingClientRect`) is already in\n * that same physical, direction-blind coordinate space, so this is what makes\n * `scrollLeft` combinable with it at all.\n */\nexport function physicalScrollLeft(strip: HTMLElement): number {\n const raw = strip.scrollLeft;\n if (!isRtlStrip(strip)) return raw;\n const max = strip.scrollWidth - strip.clientWidth;\n const type = detectRtlScrollType(strip.ownerDocument);\n if (type === 'negative') return raw + max;\n if (type === 'reverse') return max - raw;\n return raw;\n}\n\n/** The inverse of {@link physicalScrollLeft}: a physical offset back to this engine's raw `scrollLeft`. */\nexport function toRawScrollLeft(strip: HTMLElement, physical: number): number {\n if (!isRtlStrip(strip)) return physical;\n const max = strip.scrollWidth - strip.clientWidth;\n const type = detectRtlScrollType(strip.ownerDocument);\n if (type === 'negative') return physical - max;\n if (type === 'reverse') return max - physical;\n return physical;\n}\n\n/** Whether the gesture that armed `nudged` happened within {@link NUDGE_FRESH_MS}. */\nfunction nudgeIsFresh(state: WatchState): boolean {\n return Date.now() - state.nudgedAt <= NUDGE_FRESH_MS;\n}\n\n/** Whether the strip came to rest where it last aimed itself — clamped as the browser would. */\nfunction restsOnAim(strip: HTMLElement, aimed: number): boolean {\n const reachable = Math.min(aimed, strip.scrollWidth - strip.clientWidth);\n // Written so that `NaN` — the strip never aimed — reads as \"not on aim\".\n return Math.abs(physicalScrollLeft(strip) - reachable) <= LANDED_SLACK;\n}\n\n/** The pointer/touch/keydown/wheel listeners that arm `state`, split out of `watchVisitorScroll` (line budget). */\nfunction createGestureListeners(state: WatchState): { onStrip: Listeners; onView: Listeners } {\n // `MouseEvent`, not `PointerEvent`: a real `PointerEvent` IS one (it extends\n // `MouseEvent`), so this reads `clientX` off it just the same in a browser —\n // but jsdom (this file's own test environment) has never implemented\n // `PointerEvent` at all, and the bare identifier throws a `ReferenceError`\n // the moment anything evaluates `instanceof PointerEvent`, pointer event or\n // not. Same reasoning as feature-checking `scrollTo` elsewhere in this file:\n // nothing in here is worth a crash over which constructor a probe prefers.\n const onPointerDown = (event: Event): void => {\n state.pointer = true;\n state.pointerMoved = false;\n state.pointerDownAt = event instanceof MouseEvent ? event.clientX : Number.NaN;\n };\n const onPointerMove = (event: Event): void => {\n if (!(event instanceof MouseEvent) || Number.isNaN(state.pointerDownAt)) return;\n if (Math.abs(event.clientX - state.pointerDownAt) > POINTER_MOVE_EPSILON) state.pointerMoved = true;\n };\n const onPointerUp = (): void => {\n state.pointer = false;\n state.pointerDownAt = Number.NaN;\n };\n const onTouchStart = (event: Event): void => {\n state.touch = true;\n state.touchMoved = false;\n state.touchDownAt = event instanceof TouchEvent ? (event.touches[0]?.clientX ?? Number.NaN) : Number.NaN;\n };\n const onTouchMove = (event: Event): void => {\n if (!(event instanceof TouchEvent) || Number.isNaN(state.touchDownAt)) return;\n const clientX = event.touches[0]?.clientX;\n if (clientX !== undefined && Math.abs(clientX - state.touchDownAt) > POINTER_MOVE_EPSILON) {\n state.touchMoved = true;\n }\n };\n const onTouchEnd = (): void => {\n state.touch = false;\n state.touchDownAt = Number.NaN;\n };\n const nudge = (): void => {\n state.nudged = true;\n state.nudgedAt = Date.now();\n state.nudgeKept = false;\n };\n const onPointerCancel = (): void => {\n nudge();\n onPointerUp();\n };\n const onKeydown = (event: Event): void => {\n if (event instanceof KeyboardEvent && STRIP_SCROLLING_KEYS.has(event.key)) nudge();\n };\n const onWheel = (event: Event): void => {\n if (horizontalDelta(event) !== 0) nudge();\n };\n return {\n onStrip: [\n ['pointerdown', onPointerDown],\n ['pointermove', onPointerMove],\n ['touchstart', onTouchStart],\n ['touchmove', onTouchMove],\n ['pointercancel', onPointerCancel],\n ['keydown', onKeydown],\n ['wheel', onWheel],\n ],\n // A gesture can END off the strip, so its end is heard on the window.\n onView: [\n ['pointerup', onPointerUp],\n ['pointercancel', onPointerUp],\n ['touchend', onTouchEnd],\n ['touchcancel', onTouchEnd],\n ],\n };\n}\n\n/**\n * Judge the scroll under judgement once the strip rests. Only a scroll UNDER\n * JUDGEMENT disarms: Chromium can fire `scrollend` for the strip's own scroll\n * cut off by another BEFORE that one's first `scroll`, and disarming there\n * would hand the visitor's scroll to nobody.\n */\nfunction settleJudgement(strip: HTMLElement, state: WatchState): void {\n if (!state.undecided) return;\n state.undecided = false;\n const own = restsOnAim(strip, state.aimed);\n if (!own) state.scrolled = true;\n // The strip's own scroll does not use up a gesture armed moments ago: the\n // scroll that gesture causes may still be on its way (FUT-2848).\n state.nudgeKept = own && nudgeIsFresh(state);\n if (!state.nudgeKept) state.nudged = false;\n state.settled();\n}\n\n/** A gesture kept through the strip's own scroll lapses once stale (FUT-2848). */\nfunction dropStaleNudge(state: WatchState): void {\n if (!state.nudgeKept || nudgeIsFresh(state)) return;\n state.nudged = false;\n state.nudgeKept = false;\n}\n\n/**\n * Tell a scroll the VISITOR made from every other one.\n *\n * The `scroll` event cannot say: the strip's own `scrollTo` fires it, and so does\n * the browser clamping a strip whose content shrank. So a scroll is only a\n * CANDIDATE when it arrives during something only a visitor does:\n *\n * - a finger held on the strip (`touchstart` until `touchend`) — a drag;\n * - a pointer held on it (`pointerdown` until `pointerup`);\n * - a strip-scrolling key press (`STRIP_SCROLLING_KEYS`, FUT-2862), a SIDEWAYS\n * wheel, or the browser taking a pointer over to pan it (`pointercancel`),\n * each armed until the next scroll under judgement has been judged.\n *\n * and the verdict waits until the strip comes to REST (`scrollend`, or a quiet\n * spell where the browser has no `scrollend`): it is the visitor's only if the\n * strip rests somewhere other than where it last aimed itself.\n *\n * Judged at rest rather than per `scroll` because the strip's own smooth scroll\n * fires `scroll` for a third of a second, and a visitor who presses Tab or puts\n * a finger on a chip to scroll the PAGE in that window is not scrolling the\n * strip. Every tick of that animation used to count as theirs, the strip stopped\n * re-centring for good, and the open chip could be left clipped (FUT-2606\n * again, by another door). A visitor who really drags or wheels the strip\n * mid-animation cancels it, so the strip rests where THEY left it — and that\n * still counts. The one loss: a visitor who happens to leave it within a pixel\n * of the strip's own aim is not told apart from it, and the strip there is\n * already where it would have put itself.\n *\n * A tap is a pointer held with no scroll under it, so it never counts. A\n * vertical wheel scrolls the PAGE — the strip is `overflowY: hidden` — and is\n * not armed at all.\n */\nexport function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {\n const view = strip.ownerDocument.defaultView;\n const hasScrollEnd = 'onscrollend' in strip;\n const state: WatchState = {\n pointer: false,\n touch: false,\n nudged: false,\n nudgedAt: Number.NaN,\n nudgeKept: false,\n undecided: false,\n scrolled: false,\n aimed: Number.NaN,\n quiet: undefined,\n settled: () => undefined,\n lastScrollLeft: physicalScrollLeft(strip),\n pointerDownAt: Number.NaN,\n pointerMoved: false,\n touchDownAt: Number.NaN,\n touchMoved: false,\n };\n const settle = (): void => settleJudgement(strip, state);\n const onScroll = (): void => {\n const now = physicalScrollLeft(strip);\n const movedFarEnough = Math.abs(now - state.lastScrollLeft) > SCROLL_DELTA_EPSILON;\n state.lastScrollLeft = now;\n // Pointer/touch need BOTH signals (FUT-2775): the pointer/finger must have\n // itself MOVED since going down, AND this tick's delta must be real. Either\n // alone still latches on the other's shape — a pointer merely resting on\n // the strip while its OWN `scrollTo` produces real per-tick deltas would\n // arm under a delta-only check (`pointerMoved`/`touchMoved` rules that out);\n // a pointer that drifts a sub-epsilon amount while resting would arm under\n // a moved-only check with no delta floor (`movedFarEnough` rules that out).\n dropStaleNudge(state);\n const pointerDrag = state.pointer && state.pointerMoved && movedFarEnough;\n const touchDrag = state.touch && state.touchMoved && movedFarEnough;\n // `nudged` (a keypress, a sideways wheel, the browser taking the pointer\n // over to pan) is already a discrete, one-shot gesture with no \"resting\n // pointer coincides with an unrelated animation\" shape to rule out — unlike\n // pointer/touch, requiring a delta on the SAME tick that arms it would only\n // race the strip's own scroll ending before a qualifying tick arrives (seen:\n // it broke the existing \"keeps a wheel/drag scroll\" stories against a real\n // browser's `scrollend` timing). So it arms as it always has.\n if (pointerDrag || touchDrag || state.nudged) state.undecided = true;\n if (!state.undecided || hasScrollEnd) return;\n // Every tick while undecided, armed or not: a quiet spell that began while\n // the strip was still moving would judge it mid-flight, away from its aim.\n clearTimeout(state.quiet);\n state.quiet = setTimeout(settle, QUIET_BEFORE_SETTLED_MS);\n };\n const gestures = createGestureListeners(state);\n const onStrip: Listeners = [...gestures.onStrip, ['scroll', onScroll], ['scrollend', settle]];\n const onView = gestures.onView;\n for (const [type, listener] of onStrip) strip.addEventListener(type, listener, { passive: true });\n for (const [type, listener] of onView) view?.addEventListener(type, listener, { passive: true });\n return {\n hasScrolled: () => state.scrolled,\n isUndecided: () => state.undecided,\n aimedAt: () => state.aimed,\n beforeOwnScroll: (left) => {\n state.aimed = left;\n },\n onSettled: (listener) => {\n state.settled = listener;\n },\n detach: () => {\n clearTimeout(state.quiet);\n for (const [type, listener] of onStrip) strip.removeEventListener(type, listener);\n for (const [type, listener] of onView) view?.removeEventListener(type, listener);\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SettingsPanel
3
- } from "./chunk-B7HYM3QB.js";
3
+ } from "./chunk-RIAZPGHT.js";
4
4
  import {
5
5
  SettingsRail
6
6
  } from "./chunk-TNYKM4UU.js";
@@ -135,4 +135,4 @@ SettingsLayout.displayName = "SettingsLayout";
135
135
  export {
136
136
  SettingsLayout
137
137
  };
138
- //# sourceMappingURL=chunk-FNLD2KCQ.js.map
138
+ //# sourceMappingURL=chunk-EWVJJ32N.js.map
@@ -2,7 +2,7 @@ import {
2
2
  physicalScrollLeft,
3
3
  toRawScrollLeft,
4
4
  watchVisitorScroll
5
- } from "./chunk-QLAFJZDS.js";
5
+ } from "./chunk-AJUSBPWG.js";
6
6
  import {
7
7
  SettingsStatusMarker
8
8
  } from "./chunk-DBFRCTI5.js";
@@ -186,4 +186,4 @@ SettingsSectionChips.displayName = "SettingsSectionChips";
186
186
  export {
187
187
  SettingsSectionChips
188
188
  };
189
- //# sourceMappingURL=chunk-YWQ7QCWR.js.map
189
+ //# sourceMappingURL=chunk-F3Q4CMRB.js.map
@@ -5,7 +5,7 @@ import {
5
5
  GroupLabel,
6
6
  SegmentRadios,
7
7
  testId
8
- } from "./chunk-6H4TPEMO.js";
8
+ } from "./chunk-SDWOWB6F.js";
9
9
  import {
10
10
  withDefaults
11
11
  } from "./chunk-HPK33ACY.js";
@@ -96,4 +96,4 @@ RadioGroup.displayName = "RadioGroup";
96
96
  export {
97
97
  RadioGroup
98
98
  };
99
- //# sourceMappingURL=chunk-XHA2NXLD.js.map
99
+ //# sourceMappingURL=chunk-HSKLX2NO.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-6KEXHOIF.js";
4
4
  import {
5
5
  SettingsSectionChips
6
- } from "./chunk-YWQ7QCWR.js";
6
+ } from "./chunk-F3Q4CMRB.js";
7
7
  import {
8
8
  TOUCH_TARGET,
9
9
  atLeastRail,
@@ -167,4 +167,4 @@ function SettingsPanel({
167
167
  export {
168
168
  SettingsPanel
169
169
  };
170
- //# sourceMappingURL=chunk-B7HYM3QB.js.map
170
+ //# sourceMappingURL=chunk-RIAZPGHT.js.map
@@ -5,6 +5,9 @@ import {
5
5
  segmentButtonSx,
6
6
  segmentContainerSx
7
7
  } from "./chunk-GG62LKA3.js";
8
+ import {
9
+ muiSize
10
+ } from "./chunk-7ZPUN7TV.js";
8
11
 
9
12
  // src/components/form/RadioGroup/RadioGroup.variants.tsx
10
13
  import Box from "@mui/material/Box/index.js";
@@ -54,6 +57,7 @@ var DefaultRadios = ({
54
57
  options,
55
58
  value,
56
59
  color,
60
+ size,
57
61
  direction,
58
62
  showDescriptions,
59
63
  dataTestId,
@@ -79,6 +83,7 @@ var DefaultRadios = ({
79
83
  Radio,
80
84
  {
81
85
  color: muiRadioColor(color),
86
+ size: muiSize(size),
82
87
  "data-testid": testId(dataTestId, `radio-${index}`)
83
88
  }
84
89
  ),
@@ -244,4 +249,4 @@ export {
244
249
  SegmentRadios,
245
250
  GroupLabel
246
251
  };
247
- //# sourceMappingURL=chunk-6H4TPEMO.js.map
252
+ //# sourceMappingURL=chunk-SDWOWB6F.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/RadioGroup/RadioGroup.variants.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport ButtonBase from '@mui/material/ButtonBase/index.js';\nimport Card from '@mui/material/Card/index.js';\nimport CardContent from '@mui/material/CardContent/index.js';\nimport FormControlLabel from '@mui/material/FormControlLabel/index.js';\nimport FormLabel from '@mui/material/FormLabel/index.js';\nimport Radio from '@mui/material/Radio/index.js';\nimport MuiRadioGroup from '@mui/material/RadioGroup/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { styled } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport {\n buttonRadioSx,\n formLabelSx,\n radioCardSx,\n segmentButtonSx,\n segmentContainerSx,\n} from './RadioGroup.styles';\nimport type { SurfaceFlags } from './RadioGroup.styles';\nimport type { RadioOption, RadioGroupProps } from './RadioGroup.types';\nimport { muiSize } from '../../../tokens/vocabulary';\nimport type { RadioProps } from '@mui/material/Radio/index.js';\n\nconst StyledFormLabel = styled(FormLabel, {\n shouldForwardProp: (prop) => !['glass', 'error'].includes(prop as string),\n})<{ glass?: boolean; error?: boolean }>(({ theme, glass, error }) => ({\n ...formLabelSx(theme, glass, error),\n}));\n\nconst StyledRadioCard = styled(Card, {\n shouldForwardProp: (prop) =>\n !['selected', 'customColor', 'glass', 'gradient', 'glow', 'customSize', 'animated'].includes(\n prop as string,\n ),\n})<SurfaceFlags>(({ theme, ...flags }) => ({ ...radioCardSx(theme, flags) }));\n\nconst StyledButtonRadio = styled(ButtonBase, {\n shouldForwardProp: (prop) =>\n !['selected', 'customColor', 'glass', 'gradient', 'customSize', 'animated'].includes(\n prop as string,\n ),\n})<SurfaceFlags>(({ theme, ...flags }) => ({ ...buttonRadioSx(theme, flags) }));\n\nconst StyledSegmentContainer = styled(Box, {\n shouldForwardProp: (prop) => !['glass', 'customColor'].includes(prop as string),\n})<{ glass?: boolean; customColor?: string }>(({ theme, glass, customColor }) => ({\n ...segmentContainerSx(theme, glass, customColor),\n}));\n\nconst StyledSegmentButton = styled(ButtonBase, {\n shouldForwardProp: (prop) =>\n !['selected', 'customColor', 'customSize', 'animated'].includes(prop as string),\n})<SurfaceFlags>(({ theme, ...flags }) => ({ ...segmentButtonSx(theme, flags) }));\n\n\nexport interface VariantProps {\n options: RadioOption[];\n value?: unknown;\n color: NonNullable<RadioGroupProps['color']>;\n size: NonNullable<RadioGroupProps['size']>;\n direction: NonNullable<RadioGroupProps['direction']>;\n showDescriptions: boolean;\n glass: boolean;\n gradient: boolean;\n glow: boolean;\n dataTestId?: string;\n onSelect: (option: RadioOption) => void;\n /** Only the default variant hands its ref and extra props to MUI's group. */\n groupRef?: React.Ref<HTMLDivElement>;\n onChange?: RadioGroupProps['onChange'];\n rest?: Record<string, unknown>;\n}\n\n/** `${dataTestId}-${suffix}`, or nothing when the caller supplied no id. */\nexport const testId = (base: string | undefined, suffix: string) =>\n base ? `${base}-${suffix}` : undefined;\n\n/**\n * MUI's Radio has no `danger`; this component's palette calls the error colour\n * that, so the name is translated at the boundary.\n */\nconst muiRadioColor = (color: string) =>\n color === 'danger'\n ? 'error'\n : (color as 'primary' | 'secondary' | 'success' | 'warning' | 'error');\n\n/** An option's icon beside its label, the run every variant but `cards` uses. */\nconst OptionLabel: React.FC<{ option: RadioOption; testIdValue?: string }> = ({\n option,\n testIdValue,\n}) => (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }} data-testid={testIdValue}>\n {option.icon}\n {option.label}\n </Box>\n);\n\nexport const DefaultRadios: React.FC<VariantProps> = ({\n options,\n value,\n color,\n size,\n direction,\n showDescriptions,\n dataTestId,\n groupRef,\n onChange,\n rest,\n}) => (\n <MuiRadioGroup\n ref={groupRef}\n value={value}\n onChange={onChange}\n {...rest}\n sx={{ flexDirection: direction, gap: 1 }}\n data-testid={testId(dataTestId, 'group')}\n >\n {options.map((option, index) => (\n <FormControlLabel\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n data-testid={testId(dataTestId, `option-${index}`)}\n control={\n <Radio\n color={muiRadioColor(color)}\n // MUI's own `Radio` types `size` as `'small' | 'medium'` only, but its\n // glyph (`RadioButtonIcon`, an `SvgIcon`) reads whatever `size` it is\n // given as its own `fontSize` and draws it at that step regardless —\n // `'large'` already renders at 35px (`SvgIcon.js`'s own\n // `fontSize: pxToRem(35)` for that step), MUI's public type just never\n // advertised it. Confined to this one call site rather than a module\n // augmentation, which would widen every consumer's `Radio` type.\n size={muiSize(size) as RadioProps['size']}\n data-testid={testId(dataTestId, `radio-${index}`)}\n />\n }\n label={\n <Box\n sx={{ display: 'flex', alignItems: 'center', gap: 1 }}\n data-testid={testId(dataTestId, `label-${index}`)}\n >\n {option.icon}\n <Box>\n <Typography>{option.label}</Typography>\n {option.description && showDescriptions && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {option.description}\n </Typography>\n )}\n </Box>\n </Box>\n }\n />\n ))}\n </MuiRadioGroup>\n);\n\nexport interface CardBodyProps {\n option: RadioOption;\n index: number;\n isSelected: boolean;\n color: string;\n showDescriptions: boolean;\n dataTestId?: string;\n}\n\n/** A card's contents: the icon, the label, and the optional description under it. */\nexport const CardBody: React.FC<CardBodyProps> = ({\n option,\n index,\n isSelected,\n color,\n showDescriptions,\n dataTestId,\n}) => (\n <CardContent sx={{ p: 2, '&:last-child': { pb: 2 } }}>\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>\n {option.icon && (\n <Box sx={{ mt: 0.5, color: isSelected ? `${color}.main` : 'text.secondary' }}>\n {option.icon}\n </Box>\n )}\n <Box sx={{ flex: 1 }}>\n <Typography\n variant=\"subtitle1\"\n fontWeight={600}\n color={isSelected ? `${color}.main` : 'text.primary'}\n data-testid={testId(dataTestId, `label-${index}`)}\n >\n {option.label}\n </Typography>\n {option.description && showDescriptions && (\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 0.5 }}>\n {option.description}\n </Typography>\n )}\n </Box>\n </Box>\n </CardContent>\n);\n\nexport { OptionLabel };\n\nexport const CardRadios: React.FC<VariantProps> = ({\n options, value, color, size, direction, showDescriptions, glass, gradient, glow, dataTestId, onSelect,\n}) => (\n <Box\n sx={{ display: 'flex', flexDirection: direction, gap: 2 }}\n data-testid={testId(dataTestId, 'container')}\n >\n {options.map((option, index) => (\n <StyledRadioCard\n key={option.value}\n selected={value === option.value}\n customColor={color}\n glass={glass}\n gradient={gradient}\n glow={glow}\n customSize={size}\n animated\n data-testid={testId(dataTestId, `card-${index}`)}\n onClick={() => onSelect(option)}\n >\n <CardBody\n option={option}\n index={index}\n isSelected={value === option.value}\n color={color}\n showDescriptions={showDescriptions}\n dataTestId={dataTestId}\n />\n </StyledRadioCard>\n ))}\n </Box>\n);\n\nexport const ButtonRadios: React.FC<VariantProps> = ({\n options, value, color, size, direction, glass, gradient, dataTestId, onSelect,\n}) => (\n <Box\n sx={{ display: 'flex', flexDirection: direction, gap: 1, flexWrap: 'wrap' }}\n data-testid={testId(dataTestId, 'container')}\n >\n {options.map((option, index) => (\n <StyledButtonRadio\n key={option.value}\n selected={value === option.value}\n customColor={color}\n glass={glass}\n gradient={gradient}\n customSize={size}\n animated\n disabled={option.disabled}\n data-testid={testId(dataTestId, `button-${index}`)}\n onClick={() => onSelect(option)}\n >\n <OptionLabel option={option} testIdValue={testId(dataTestId, `label-${index}`)} />\n </StyledButtonRadio>\n ))}\n </Box>\n);\n\nexport const SegmentRadios: React.FC<VariantProps> = ({\n options, value, color, size, glass, dataTestId, onSelect,\n}) => (\n <StyledSegmentContainer\n glass={glass}\n customColor={color}\n data-testid={testId(dataTestId, 'container')}\n >\n {options.map((option, index) => (\n <StyledSegmentButton\n key={option.value}\n selected={value === option.value}\n customColor={color}\n customSize={size}\n animated\n disabled={option.disabled}\n data-testid={testId(dataTestId, `segment-${index}`)}\n onClick={() => onSelect(option)}\n >\n <OptionLabel option={option} testIdValue={testId(dataTestId, `label-${index}`)} />\n </StyledSegmentButton>\n ))}\n </StyledSegmentContainer>\n);\n\n/** The group's own label, which can carry the glass treatment independently. */\nexport const GroupLabel: React.FC<{\n glass?: boolean;\n error?: boolean;\n dataTestId?: string;\n children: React.ReactNode;\n}> = ({ glass, error, dataTestId, children }) => (\n <StyledFormLabel glass={glass} error={error} data-testid={testId(dataTestId, 'label')}>\n {children}\n </StyledFormLabel>\n);\n"],"mappings":"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","names":[]}
@@ -1,15 +1,17 @@
1
1
  import "../chunk-IQ6WX2GS.js";
2
2
  import {
3
3
  RadioGroup
4
- } from "../chunk-XHA2NXLD.js";
5
- import "../chunk-6H4TPEMO.js";
4
+ } from "../chunk-HSKLX2NO.js";
5
+ import "../chunk-SDWOWB6F.js";
6
6
  import "../chunk-GG62LKA3.js";
7
7
  import "../chunk-Z6WSW6B4.js";
8
8
  import "../chunk-HPK33ACY.js";
9
+ import "../chunk-7ZPUN7TV.js";
9
10
  import "../chunk-M47ZOUGF.js";
10
11
  import "../chunk-7FDU3FIN.js";
11
12
  import "../chunk-EPEJMTCQ.js";
12
13
  import "../chunk-GDN2LUTZ.js";
14
+ import "../chunk-FZXKH2ZT.js";
13
15
  import "../chunk-O6MJWHU5.js";
14
16
  import "../chunk-26X4CZVR.js";
15
17
  import "../chunk-FQ6UW7IY.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  SettingsLayout
3
- } from "../chunk-FNLD2KCQ.js";
4
- import "../chunk-B7HYM3QB.js";
3
+ } from "../chunk-EWVJJ32N.js";
4
+ import "../chunk-RIAZPGHT.js";
5
5
  import "../chunk-TNYKM4UU.js";
6
6
  import "../chunk-V5EWCJBT.js";
7
7
  import "../chunk-BXC6GRLE.js";
8
8
  import "../chunk-6KEXHOIF.js";
9
9
  import {
10
10
  SettingsSectionChips
11
- } from "../chunk-YWQ7QCWR.js";
12
- import "../chunk-QLAFJZDS.js";
11
+ } from "../chunk-F3Q4CMRB.js";
12
+ import "../chunk-AJUSBPWG.js";
13
13
  import {
14
14
  SettingsStatusMarker
15
15
  } from "../chunk-DBFRCTI5.js";
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.variants.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/RadioGroup/RadioGroup.variants.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAkCvE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,IAAI,EAAE,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IACrD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,4EAA4E;AAC5E,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,GAAG,SAAS,EAAE,QAAQ,MAAM,uBACvB,CAAC;AAWzC,iFAAiF;AACjF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAQxE,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAkDhD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qFAAqF;AACrF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAgC5C,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA+B7C,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAwB/C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAuBhD,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAIA,CAAC"}
1
+ {"version":3,"file":"RadioGroup.variants.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/RadioGroup/RadioGroup.variants.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAoCvE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,IAAI,EAAE,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3C,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IACrD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,4EAA4E;AAC5E,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,GAAG,SAAS,EAAE,QAAQ,MAAM,uBACvB,CAAC;AAWzC,iFAAiF;AACjF,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAQxE,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA2DhD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qFAAqF;AACrF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAgC5C,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA+B7C,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAwB/C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAuBhD,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAIA,CAAC"}
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Telling the strip's own scrolls from the visitor's (FUT-2606).
3
- *
4
- * Split from `SettingsSectionChips.tsx` so the chips stay a component file and
5
- * the rule for "who moved the strip" can be read in one place.
2
+ * Telling the strip's own scrolls from the visitor's (FUT-2606). Split from
3
+ * `SettingsSectionChips.tsx` so the chips stay a component file and the rule
4
+ * for "who moved the strip" can be read in one place.
6
5
  */
7
6
  interface VisitorScrollWatch {
8
7
  /** True once the visitor has moved the strip themselves. */
@@ -54,9 +53,9 @@ export declare function toRawScrollLeft(strip: HTMLElement, physical: number): n
54
53
  *
55
54
  * - a finger held on the strip (`touchstart` until `touchend`) — a drag;
56
55
  * - a pointer held on it (`pointerdown` until `pointerup`);
57
- * - a key press, a SIDEWAYS wheel, or the browser taking a pointer over to pan
58
- * it (`pointercancel`), each armed until the next scroll under judgement has
59
- * been judged — whoever's it turns out to be.
56
+ * - a strip-scrolling key press (`STRIP_SCROLLING_KEYS`, FUT-2862), a SIDEWAYS
57
+ * wheel, or the browser taking a pointer over to pan it (`pointercancel`),
58
+ * each armed until the next scroll under judgement has been judged.
60
59
  *
61
60
  * and the verdict waits until the strip comes to REST (`scrollend`, or a quiet
62
61
  * spell where the browser has no `scrollend`): it is the visitor's only if the
@@ -1 +1 @@
1
- {"version":3,"file":"SettingsSectionChips.scroll.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2CH,UAAU,kBAAkB;IAC1B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B;;;OAGG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B;;;OAGG;IACH,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,wEAAwE;IACxE,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AA+ED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAItD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAQ7D;AAED,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO5E;AA8GD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,CAsEzE"}
1
+ {"version":3,"file":"SettingsSectionChips.scroll.d.ts","sourceRoot":"","sources":["../../../../../src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAwCH,UAAU,kBAAkB;IAC1B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B;;;OAGG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B;;;OAGG;IACH,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,wEAAwE;IACxE,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAiFD,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAItD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAQ7D;AAED,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO5E;AAgHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,CAsEzE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.45.5",
3
+ "version": "6.45.7",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -19,6 +19,8 @@ import {
19
19
  } from './RadioGroup.styles';
20
20
  import type { SurfaceFlags } from './RadioGroup.styles';
21
21
  import type { RadioOption, RadioGroupProps } from './RadioGroup.types';
22
+ import { muiSize } from '../../../tokens/vocabulary';
23
+ import type { RadioProps } from '@mui/material/Radio/index.js';
22
24
 
23
25
  const StyledFormLabel = styled(FormLabel, {
24
26
  shouldForwardProp: (prop) => !['glass', 'error'].includes(prop as string),
@@ -98,6 +100,7 @@ export const DefaultRadios: React.FC<VariantProps> = ({
98
100
  options,
99
101
  value,
100
102
  color,
103
+ size,
101
104
  direction,
102
105
  showDescriptions,
103
106
  dataTestId,
@@ -122,6 +125,14 @@ export const DefaultRadios: React.FC<VariantProps> = ({
122
125
  control={
123
126
  <Radio
124
127
  color={muiRadioColor(color)}
128
+ // MUI's own `Radio` types `size` as `'small' | 'medium'` only, but its
129
+ // glyph (`RadioButtonIcon`, an `SvgIcon`) reads whatever `size` it is
130
+ // given as its own `fontSize` and draws it at that step regardless —
131
+ // `'large'` already renders at 35px (`SvgIcon.js`'s own
132
+ // `fontSize: pxToRem(35)` for that step), MUI's public type just never
133
+ // advertised it. Confined to this one call site rather than a module
134
+ // augmentation, which would widen every consumer's `Radio` type.
135
+ size={muiSize(size) as RadioProps['size']}
125
136
  data-testid={testId(dataTestId, `radio-${index}`)}
126
137
  />
127
138
  }
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Telling the strip's own scrolls from the visitor's (FUT-2606).
3
- *
4
- * Split from `SettingsSectionChips.tsx` so the chips stay a component file and
5
- * the rule for "who moved the strip" can be read in one place.
2
+ * Telling the strip's own scrolls from the visitor's (FUT-2606). Split from
3
+ * `SettingsSectionChips.tsx` so the chips stay a component file and the rule
4
+ * for "who moved the strip" can be read in one place.
6
5
  */
7
6
 
8
7
  /**
@@ -13,11 +12,10 @@
13
12
  const LANDED_SLACK = 1;
14
13
 
15
14
  /**
16
- * Where `scrollend` is missing: how long the strip has to go without a `scroll`
17
- * before it counts as settled. Generous on purpose — a busy main thread can go
18
- * several frames between ticks of a smooth scroll, and judging one mid-flight
19
- * would read the strip's own animation as the visitor's. Too long only delays a
20
- * re-centre; too short can latch the strip for good.
15
+ * Where `scrollend` is missing: how long the strip goes without a `scroll`
16
+ * before it counts as settled — generous, since a busy thread can go several
17
+ * frames between smooth-scroll ticks and judging one mid-flight would read
18
+ * the strip's own animation as the visitor's. Too short can latch it for good.
21
19
  */
22
20
  const QUIET_BEFORE_SETTLED_MS = 250;
23
21
 
@@ -25,7 +23,6 @@ const QUIET_BEFORE_SETTLED_MS = 250;
25
23
  * How much `scrollLeft` has to move, tick to tick, before a `scroll` event is
26
24
  * even a CANDIDATE for arming (FUT-2775). Below this, a browser's own rounding
27
25
  * or a repeated event carrying no real motion cannot arm anything by itself.
28
- *
29
26
  * This alone does not stop the false latch the ticket describes: the strip's
30
27
  * own `scrollTo` produces real per-tick deltas well past this line, same as a
31
28
  * drag would. It only rules out a scroll event that moved nothing.
@@ -33,16 +30,15 @@ const QUIET_BEFORE_SETTLED_MS = 250;
33
30
  const SCROLL_DELTA_EPSILON = 2;
34
31
 
35
32
  /**
36
- * How far a pointer or touch has to travel from where it went down before it
37
- * counts as having MOVED, rather than merely resting (FUT-2775). Below this,
38
- * an held-still finger's sub-pixel tremor does not count as a drag.
33
+ * How far a pointer/touch must travel from where it went down to count as
34
+ * MOVED, not merely resting (FUT-2775) — below this, a held tremor isn't a drag.
39
35
  */
40
36
  const POINTER_MOVE_EPSILON = 2;
41
37
 
42
38
  /**
43
39
  * How long a key, sideways wheel or pan stays armed through a scroll the strip
44
- * made itself (FUT-2848): a busy thread can finish a re-centre before the key's
45
- * scroll ticks once. Past this it lapses, so a later clamp is not the visitor.
40
+ * made itself (FUT-2848) — a busy thread can finish a re-centre before the
41
+ * key's scroll ticks once; past this it lapses, so a later clamp isn't the visitor.
46
42
  */
47
43
  const NUDGE_FRESH_MS = 1000;
48
44
 
@@ -82,6 +78,8 @@ function horizontalDelta(event: Event): number {
82
78
  return event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0;
83
79
  }
84
80
 
81
+ const STRIP_SCROLLING_KEYS = new Set(['ArrowLeft', 'ArrowRight']); // verified live in Chromium (FUT-2862)
82
+
85
83
  interface WatchState {
86
84
  pointer: boolean;
87
85
  touch: boolean;
@@ -246,7 +244,9 @@ function createGestureListeners(state: WatchState): { onStrip: Listeners; onView
246
244
  nudge();
247
245
  onPointerUp();
248
246
  };
249
- const onKeydown = nudge;
247
+ const onKeydown = (event: Event): void => {
248
+ if (event instanceof KeyboardEvent && STRIP_SCROLLING_KEYS.has(event.key)) nudge();
249
+ };
250
250
  const onWheel = (event: Event): void => {
251
251
  if (horizontalDelta(event) !== 0) nudge();
252
252
  };
@@ -304,9 +304,9 @@ function dropStaleNudge(state: WatchState): void {
304
304
  *
305
305
  * - a finger held on the strip (`touchstart` until `touchend`) — a drag;
306
306
  * - a pointer held on it (`pointerdown` until `pointerup`);
307
- * - a key press, a SIDEWAYS wheel, or the browser taking a pointer over to pan
308
- * it (`pointercancel`), each armed until the next scroll under judgement has
309
- * been judged — whoever's it turns out to be.
307
+ * - a strip-scrolling key press (`STRIP_SCROLLING_KEYS`, FUT-2862), a SIDEWAYS
308
+ * wheel, or the browser taking a pointer over to pan it (`pointercancel`),
309
+ * each armed until the next scroll under judgement has been judged.
310
310
  *
311
311
  * and the verdict waits until the strip comes to REST (`scrollend`, or a quiet
312
312
  * spell where the browser has no `scrollend`): it is the visitor's only if the
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/RadioGroup/RadioGroup.variants.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport ButtonBase from '@mui/material/ButtonBase/index.js';\nimport Card from '@mui/material/Card/index.js';\nimport CardContent from '@mui/material/CardContent/index.js';\nimport FormControlLabel from '@mui/material/FormControlLabel/index.js';\nimport FormLabel from '@mui/material/FormLabel/index.js';\nimport Radio from '@mui/material/Radio/index.js';\nimport MuiRadioGroup from '@mui/material/RadioGroup/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { styled } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport {\n buttonRadioSx,\n formLabelSx,\n radioCardSx,\n segmentButtonSx,\n segmentContainerSx,\n} from './RadioGroup.styles';\nimport type { SurfaceFlags } from './RadioGroup.styles';\nimport type { RadioOption, RadioGroupProps } from './RadioGroup.types';\n\nconst StyledFormLabel = styled(FormLabel, {\n shouldForwardProp: (prop) => !['glass', 'error'].includes(prop as string),\n})<{ glass?: boolean; error?: boolean }>(({ theme, glass, error }) => ({\n ...formLabelSx(theme, glass, error),\n}));\n\nconst StyledRadioCard = styled(Card, {\n shouldForwardProp: (prop) =>\n !['selected', 'customColor', 'glass', 'gradient', 'glow', 'customSize', 'animated'].includes(\n prop as string,\n ),\n})<SurfaceFlags>(({ theme, ...flags }) => ({ ...radioCardSx(theme, flags) }));\n\nconst StyledButtonRadio = styled(ButtonBase, {\n shouldForwardProp: (prop) =>\n !['selected', 'customColor', 'glass', 'gradient', 'customSize', 'animated'].includes(\n prop as string,\n ),\n})<SurfaceFlags>(({ theme, ...flags }) => ({ ...buttonRadioSx(theme, flags) }));\n\nconst StyledSegmentContainer = styled(Box, {\n shouldForwardProp: (prop) => !['glass', 'customColor'].includes(prop as string),\n})<{ glass?: boolean; customColor?: string }>(({ theme, glass, customColor }) => ({\n ...segmentContainerSx(theme, glass, customColor),\n}));\n\nconst StyledSegmentButton = styled(ButtonBase, {\n shouldForwardProp: (prop) =>\n !['selected', 'customColor', 'customSize', 'animated'].includes(prop as string),\n})<SurfaceFlags>(({ theme, ...flags }) => ({ ...segmentButtonSx(theme, flags) }));\n\n\nexport interface VariantProps {\n options: RadioOption[];\n value?: unknown;\n color: NonNullable<RadioGroupProps['color']>;\n size: NonNullable<RadioGroupProps['size']>;\n direction: NonNullable<RadioGroupProps['direction']>;\n showDescriptions: boolean;\n glass: boolean;\n gradient: boolean;\n glow: boolean;\n dataTestId?: string;\n onSelect: (option: RadioOption) => void;\n /** Only the default variant hands its ref and extra props to MUI's group. */\n groupRef?: React.Ref<HTMLDivElement>;\n onChange?: RadioGroupProps['onChange'];\n rest?: Record<string, unknown>;\n}\n\n/** `${dataTestId}-${suffix}`, or nothing when the caller supplied no id. */\nexport const testId = (base: string | undefined, suffix: string) =>\n base ? `${base}-${suffix}` : undefined;\n\n/**\n * MUI's Radio has no `danger`; this component's palette calls the error colour\n * that, so the name is translated at the boundary.\n */\nconst muiRadioColor = (color: string) =>\n color === 'danger'\n ? 'error'\n : (color as 'primary' | 'secondary' | 'success' | 'warning' | 'error');\n\n/** An option's icon beside its label, the run every variant but `cards` uses. */\nconst OptionLabel: React.FC<{ option: RadioOption; testIdValue?: string }> = ({\n option,\n testIdValue,\n}) => (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }} data-testid={testIdValue}>\n {option.icon}\n {option.label}\n </Box>\n);\n\nexport const DefaultRadios: React.FC<VariantProps> = ({\n options,\n value,\n color,\n direction,\n showDescriptions,\n dataTestId,\n groupRef,\n onChange,\n rest,\n}) => (\n <MuiRadioGroup\n ref={groupRef}\n value={value}\n onChange={onChange}\n {...rest}\n sx={{ flexDirection: direction, gap: 1 }}\n data-testid={testId(dataTestId, 'group')}\n >\n {options.map((option, index) => (\n <FormControlLabel\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n data-testid={testId(dataTestId, `option-${index}`)}\n control={\n <Radio\n color={muiRadioColor(color)}\n data-testid={testId(dataTestId, `radio-${index}`)}\n />\n }\n label={\n <Box\n sx={{ display: 'flex', alignItems: 'center', gap: 1 }}\n data-testid={testId(dataTestId, `label-${index}`)}\n >\n {option.icon}\n <Box>\n <Typography>{option.label}</Typography>\n {option.description && showDescriptions && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {option.description}\n </Typography>\n )}\n </Box>\n </Box>\n }\n />\n ))}\n </MuiRadioGroup>\n);\n\nexport interface CardBodyProps {\n option: RadioOption;\n index: number;\n isSelected: boolean;\n color: string;\n showDescriptions: boolean;\n dataTestId?: string;\n}\n\n/** A card's contents: the icon, the label, and the optional description under it. */\nexport const CardBody: React.FC<CardBodyProps> = ({\n option,\n index,\n isSelected,\n color,\n showDescriptions,\n dataTestId,\n}) => (\n <CardContent sx={{ p: 2, '&:last-child': { pb: 2 } }}>\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>\n {option.icon && (\n <Box sx={{ mt: 0.5, color: isSelected ? `${color}.main` : 'text.secondary' }}>\n {option.icon}\n </Box>\n )}\n <Box sx={{ flex: 1 }}>\n <Typography\n variant=\"subtitle1\"\n fontWeight={600}\n color={isSelected ? `${color}.main` : 'text.primary'}\n data-testid={testId(dataTestId, `label-${index}`)}\n >\n {option.label}\n </Typography>\n {option.description && showDescriptions && (\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 0.5 }}>\n {option.description}\n </Typography>\n )}\n </Box>\n </Box>\n </CardContent>\n);\n\nexport { OptionLabel };\n\nexport const CardRadios: React.FC<VariantProps> = ({\n options, value, color, size, direction, showDescriptions, glass, gradient, glow, dataTestId, onSelect,\n}) => (\n <Box\n sx={{ display: 'flex', flexDirection: direction, gap: 2 }}\n data-testid={testId(dataTestId, 'container')}\n >\n {options.map((option, index) => (\n <StyledRadioCard\n key={option.value}\n selected={value === option.value}\n customColor={color}\n glass={glass}\n gradient={gradient}\n glow={glow}\n customSize={size}\n animated\n data-testid={testId(dataTestId, `card-${index}`)}\n onClick={() => onSelect(option)}\n >\n <CardBody\n option={option}\n index={index}\n isSelected={value === option.value}\n color={color}\n showDescriptions={showDescriptions}\n dataTestId={dataTestId}\n />\n </StyledRadioCard>\n ))}\n </Box>\n);\n\nexport const ButtonRadios: React.FC<VariantProps> = ({\n options, value, color, size, direction, glass, gradient, dataTestId, onSelect,\n}) => (\n <Box\n sx={{ display: 'flex', flexDirection: direction, gap: 1, flexWrap: 'wrap' }}\n data-testid={testId(dataTestId, 'container')}\n >\n {options.map((option, index) => (\n <StyledButtonRadio\n key={option.value}\n selected={value === option.value}\n customColor={color}\n glass={glass}\n gradient={gradient}\n customSize={size}\n animated\n disabled={option.disabled}\n data-testid={testId(dataTestId, `button-${index}`)}\n onClick={() => onSelect(option)}\n >\n <OptionLabel option={option} testIdValue={testId(dataTestId, `label-${index}`)} />\n </StyledButtonRadio>\n ))}\n </Box>\n);\n\nexport const SegmentRadios: React.FC<VariantProps> = ({\n options, value, color, size, glass, dataTestId, onSelect,\n}) => (\n <StyledSegmentContainer\n glass={glass}\n customColor={color}\n data-testid={testId(dataTestId, 'container')}\n >\n {options.map((option, index) => (\n <StyledSegmentButton\n key={option.value}\n selected={value === option.value}\n customColor={color}\n customSize={size}\n animated\n disabled={option.disabled}\n data-testid={testId(dataTestId, `segment-${index}`)}\n onClick={() => onSelect(option)}\n >\n <OptionLabel option={option} testIdValue={testId(dataTestId, `label-${index}`)} />\n </StyledSegmentButton>\n ))}\n </StyledSegmentContainer>\n);\n\n/** The group's own label, which can carry the glass treatment independently. */\nexport const GroupLabel: React.FC<{\n glass?: boolean;\n error?: boolean;\n dataTestId?: string;\n children: React.ReactNode;\n}> = ({ glass, error, dataTestId, children }) => (\n <StyledFormLabel glass={glass} error={error} data-testid={testId(dataTestId, 'label')}>\n {children}\n </StyledFormLabel>\n);\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts"],"sourcesContent":["/**\n * Telling the strip's own scrolls from the visitor's (FUT-2606).\n *\n * Split from `SettingsSectionChips.tsx` so the chips stay a component file and\n * the rule for \"who moved the strip\" can be read in one place.\n */\n\n/**\n * How near to where the strip aimed itself it has to come to rest for the scroll\n * to count as the strip's own. A smooth scroll lands on a device pixel, and the\n * target it was given is fractional.\n */\nconst LANDED_SLACK = 1;\n\n/**\n * Where `scrollend` is missing: how long the strip has to go without a `scroll`\n * before it counts as settled. Generous on purpose — a busy main thread can go\n * several frames between ticks of a smooth scroll, and judging one mid-flight\n * would read the strip's own animation as the visitor's. Too long only delays a\n * re-centre; too short can latch the strip for good.\n */\nconst QUIET_BEFORE_SETTLED_MS = 250;\n\n/**\n * How much `scrollLeft` has to move, tick to tick, before a `scroll` event is\n * even a CANDIDATE for arming (FUT-2775). Below this, a browser's own rounding\n * or a repeated event carrying no real motion cannot arm anything by itself.\n *\n * This alone does not stop the false latch the ticket describes: the strip's\n * own `scrollTo` produces real per-tick deltas well past this line, same as a\n * drag would. It only rules out a scroll event that moved nothing.\n */\nconst SCROLL_DELTA_EPSILON = 2;\n\n/**\n * How far a pointer or touch has to travel from where it went down before it\n * counts as having MOVED, rather than merely resting (FUT-2775). Below this,\n * an held-still finger's sub-pixel tremor does not count as a drag.\n */\nconst POINTER_MOVE_EPSILON = 2;\n\n/**\n * How long a key, sideways wheel or pan stays armed through a scroll the strip\n * made itself (FUT-2848): a busy thread can finish a re-centre before the key's\n * scroll ticks once. Past this it lapses, so a later clamp is not the visitor.\n */\nconst NUDGE_FRESH_MS = 1000;\n\ninterface VisitorScrollWatch {\n /** True once the visitor has moved the strip themselves. */\n hasScrolled: () => boolean;\n /**\n * True while a scroll the visitor MAY be making has not come to rest yet. The\n * strip must not scroll itself under it: that would yank a drag in progress.\n */\n isUndecided: () => boolean;\n /**\n * Where the strip last aimed itself, PHYSICAL pixels (see {@link physicalScrollLeft}) —\n * direction-blind, like every other geometry read in this file. `NaN` before it has.\n */\n aimedAt: () => number;\n /**\n * The strip is about to scroll itself to `left` (physical pixels). Records the\n * aim and NOTHING\n * else: it used to disarm too, and a re-centre landing between a visitor's key\n * press (or wheel, or pan) and the first tick of the scroll it causes wiped\n * the arming — their scroll went unclaimed, read as the strip's own. Left\n * armed, the worst a stale arming does is put the strip's OWN next scroll\n * under judgement, which rests on its aim, is not latched, and disarms.\n */\n beforeOwnScroll: (left: number) => void;\n /** Called once an undecided scroll has come to rest and been judged. */\n onSettled: (listener: () => void) => void;\n detach: () => void;\n}\n\ntype Listeners = Array<[string, (event: Event) => void]>;\n\n/** A wheel's sideways travel: `deltaX`, or `deltaY` with Shift held, as browsers read it. */\nfunction horizontalDelta(event: Event): number {\n if (!(event instanceof WheelEvent)) return 0;\n return event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0;\n}\n\ninterface WatchState {\n pointer: boolean;\n touch: boolean;\n nudged: boolean;\n /** When `nudged` was set (`Date.now()` ms), and whether it outlived an own verdict. */\n nudgedAt: number;\n nudgeKept: boolean;\n undecided: boolean;\n scrolled: boolean;\n aimed: number;\n quiet: ReturnType<typeof setTimeout> | undefined;\n settled: () => void;\n /** `scrollLeft` as of the last `scroll` tick, updated every tick regardless of arming. */\n lastScrollLeft: number;\n /** Where a `pointerdown` on the strip landed, in viewport `clientX`. `NaN` while up. */\n pointerDownAt: number;\n /** True once that pointer has travelled past {@link POINTER_MOVE_EPSILON} from `pointerDownAt`. */\n pointerMoved: boolean;\n /** Same pair, for `touchstart`/`touchmove` — a distinct event stream on some engines. */\n touchDownAt: number;\n touchMoved: boolean;\n}\n\ntype RtlScrollType = 'default' | 'negative' | 'reverse';\n\nlet cachedRtlScrollType: RtlScrollType | undefined;\n\n/**\n * Which of the three incompatible conventions this engine reports an RTL\n * scroller's `scrollLeft` in, probed once and cached (FUT-2775).\n *\n * Per the CSSOM View spec, an RTL scroller's `scrollLeft` is `0` at its\n * (right-hand) start and goes NEGATIVE toward the end — `'negative'` below,\n * what every current evergreen engine implements. Older WebKit mirrored that\n * (`'reverse'`: `0` at the start, growing toward `+max`), and older\n * Chromium/Safari ignored `dir` altogether and kept the plain left-to-right\n * numbering (`'default'`). A hidden probe, not a version sniff, tells them\n * apart — the same technique `@mui/utils`'s `detectScrollType` uses for\n * `Tabs`; reimplemented here rather than taking a new dependency for one\n * probe.\n */\nfunction detectRtlScrollType(doc: Document): RtlScrollType {\n if (cachedRtlScrollType) return cachedRtlScrollType;\n // The exact pixel values below are the probe's mechanism, not a design size:\n // what matters is only that the INNER box is wider than the OUTER one, so the\n // outer one has something to scroll — same technique `@mui/utils` uses,\n // detached and off-screen either way.\n const probe = doc.createElement('div');\n const inner = doc.createElement('div');\n inner.style.width = '10px';\n probe.appendChild(inner);\n probe.dir = 'rtl';\n probe.style.width = '4px';\n probe.style.position = 'absolute';\n probe.style.top = '-1000px';\n probe.style.overflow = 'scroll';\n doc.body.appendChild(probe);\n let type: RtlScrollType = 'reverse';\n if (probe.scrollLeft > 0) {\n type = 'default';\n } else {\n probe.scrollLeft = 1;\n if (probe.scrollLeft === 0) type = 'negative';\n }\n doc.body.removeChild(probe);\n cachedRtlScrollType = type;\n return type;\n}\n\n/** True when the strip's own computed direction is right-to-left. */\nexport function isRtlStrip(strip: HTMLElement): boolean {\n const view = strip.ownerDocument.defaultView;\n const getComputedStyle = view?.getComputedStyle ?? globalThis.getComputedStyle;\n return getComputedStyle(strip).direction === 'rtl';\n}\n\n/**\n * `strip.scrollLeft`, renumbered so `0` is always the strip's physical LEFT\n * edge and larger is always further physically right — whatever `direction`\n * and whatever convention this engine uses to report it raw (FUT-2775).\n *\n * Every geometry read in this file (`getBoundingClientRect`) is already in\n * that same physical, direction-blind coordinate space, so this is what makes\n * `scrollLeft` combinable with it at all.\n */\nexport function physicalScrollLeft(strip: HTMLElement): number {\n const raw = strip.scrollLeft;\n if (!isRtlStrip(strip)) return raw;\n const max = strip.scrollWidth - strip.clientWidth;\n const type = detectRtlScrollType(strip.ownerDocument);\n if (type === 'negative') return raw + max;\n if (type === 'reverse') return max - raw;\n return raw;\n}\n\n/** The inverse of {@link physicalScrollLeft}: a physical offset back to this engine's raw `scrollLeft`. */\nexport function toRawScrollLeft(strip: HTMLElement, physical: number): number {\n if (!isRtlStrip(strip)) return physical;\n const max = strip.scrollWidth - strip.clientWidth;\n const type = detectRtlScrollType(strip.ownerDocument);\n if (type === 'negative') return physical - max;\n if (type === 'reverse') return max - physical;\n return physical;\n}\n\n/** Whether the gesture that armed `nudged` happened within {@link NUDGE_FRESH_MS}. */\nfunction nudgeIsFresh(state: WatchState): boolean {\n return Date.now() - state.nudgedAt <= NUDGE_FRESH_MS;\n}\n\n/** Whether the strip came to rest where it last aimed itself — clamped as the browser would. */\nfunction restsOnAim(strip: HTMLElement, aimed: number): boolean {\n const reachable = Math.min(aimed, strip.scrollWidth - strip.clientWidth);\n // Written so that `NaN` — the strip never aimed — reads as \"not on aim\".\n return Math.abs(physicalScrollLeft(strip) - reachable) <= LANDED_SLACK;\n}\n\n/** The pointer/touch/keydown/wheel listeners that arm `state`, split out of `watchVisitorScroll` (line budget). */\nfunction createGestureListeners(state: WatchState): { onStrip: Listeners; onView: Listeners } {\n // `MouseEvent`, not `PointerEvent`: a real `PointerEvent` IS one (it extends\n // `MouseEvent`), so this reads `clientX` off it just the same in a browser —\n // but jsdom (this file's own test environment) has never implemented\n // `PointerEvent` at all, and the bare identifier throws a `ReferenceError`\n // the moment anything evaluates `instanceof PointerEvent`, pointer event or\n // not. Same reasoning as feature-checking `scrollTo` elsewhere in this file:\n // nothing in here is worth a crash over which constructor a probe prefers.\n const onPointerDown = (event: Event): void => {\n state.pointer = true;\n state.pointerMoved = false;\n state.pointerDownAt = event instanceof MouseEvent ? event.clientX : Number.NaN;\n };\n const onPointerMove = (event: Event): void => {\n if (!(event instanceof MouseEvent) || Number.isNaN(state.pointerDownAt)) return;\n if (Math.abs(event.clientX - state.pointerDownAt) > POINTER_MOVE_EPSILON) state.pointerMoved = true;\n };\n const onPointerUp = (): void => {\n state.pointer = false;\n state.pointerDownAt = Number.NaN;\n };\n const onTouchStart = (event: Event): void => {\n state.touch = true;\n state.touchMoved = false;\n state.touchDownAt = event instanceof TouchEvent ? (event.touches[0]?.clientX ?? Number.NaN) : Number.NaN;\n };\n const onTouchMove = (event: Event): void => {\n if (!(event instanceof TouchEvent) || Number.isNaN(state.touchDownAt)) return;\n const clientX = event.touches[0]?.clientX;\n if (clientX !== undefined && Math.abs(clientX - state.touchDownAt) > POINTER_MOVE_EPSILON) {\n state.touchMoved = true;\n }\n };\n const onTouchEnd = (): void => {\n state.touch = false;\n state.touchDownAt = Number.NaN;\n };\n const nudge = (): void => {\n state.nudged = true;\n state.nudgedAt = Date.now();\n state.nudgeKept = false;\n };\n const onPointerCancel = (): void => {\n nudge();\n onPointerUp();\n };\n const onKeydown = nudge;\n const onWheel = (event: Event): void => {\n if (horizontalDelta(event) !== 0) nudge();\n };\n return {\n onStrip: [\n ['pointerdown', onPointerDown],\n ['pointermove', onPointerMove],\n ['touchstart', onTouchStart],\n ['touchmove', onTouchMove],\n ['pointercancel', onPointerCancel],\n ['keydown', onKeydown],\n ['wheel', onWheel],\n ],\n // A gesture can END off the strip, so its end is heard on the window.\n onView: [\n ['pointerup', onPointerUp],\n ['pointercancel', onPointerUp],\n ['touchend', onTouchEnd],\n ['touchcancel', onTouchEnd],\n ],\n };\n}\n\n/**\n * Judge the scroll under judgement once the strip rests. Only a scroll UNDER\n * JUDGEMENT disarms: Chromium can fire `scrollend` for the strip's own scroll\n * cut off by another BEFORE that one's first `scroll`, and disarming there\n * would hand the visitor's scroll to nobody.\n */\nfunction settleJudgement(strip: HTMLElement, state: WatchState): void {\n if (!state.undecided) return;\n state.undecided = false;\n const own = restsOnAim(strip, state.aimed);\n if (!own) state.scrolled = true;\n // The strip's own scroll does not use up a gesture armed moments ago: the\n // scroll that gesture causes may still be on its way (FUT-2848).\n state.nudgeKept = own && nudgeIsFresh(state);\n if (!state.nudgeKept) state.nudged = false;\n state.settled();\n}\n\n/** A gesture kept through the strip's own scroll lapses once stale (FUT-2848). */\nfunction dropStaleNudge(state: WatchState): void {\n if (!state.nudgeKept || nudgeIsFresh(state)) return;\n state.nudged = false;\n state.nudgeKept = false;\n}\n\n/**\n * Tell a scroll the VISITOR made from every other one.\n *\n * The `scroll` event cannot say: the strip's own `scrollTo` fires it, and so does\n * the browser clamping a strip whose content shrank. So a scroll is only a\n * CANDIDATE when it arrives during something only a visitor does:\n *\n * - a finger held on the strip (`touchstart` until `touchend`) — a drag;\n * - a pointer held on it (`pointerdown` until `pointerup`);\n * - a key press, a SIDEWAYS wheel, or the browser taking a pointer over to pan\n * it (`pointercancel`), each armed until the next scroll under judgement has\n * been judged — whoever's it turns out to be.\n *\n * and the verdict waits until the strip comes to REST (`scrollend`, or a quiet\n * spell where the browser has no `scrollend`): it is the visitor's only if the\n * strip rests somewhere other than where it last aimed itself.\n *\n * Judged at rest rather than per `scroll` because the strip's own smooth scroll\n * fires `scroll` for a third of a second, and a visitor who presses Tab or puts\n * a finger on a chip to scroll the PAGE in that window is not scrolling the\n * strip. Every tick of that animation used to count as theirs, the strip stopped\n * re-centring for good, and the open chip could be left clipped (FUT-2606\n * again, by another door). A visitor who really drags or wheels the strip\n * mid-animation cancels it, so the strip rests where THEY left it — and that\n * still counts. The one loss: a visitor who happens to leave it within a pixel\n * of the strip's own aim is not told apart from it, and the strip there is\n * already where it would have put itself.\n *\n * A tap is a pointer held with no scroll under it, so it never counts. A\n * vertical wheel scrolls the PAGE — the strip is `overflowY: hidden` — and is\n * not armed at all.\n */\nexport function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {\n const view = strip.ownerDocument.defaultView;\n const hasScrollEnd = 'onscrollend' in strip;\n const state: WatchState = {\n pointer: false,\n touch: false,\n nudged: false,\n nudgedAt: Number.NaN,\n nudgeKept: false,\n undecided: false,\n scrolled: false,\n aimed: Number.NaN,\n quiet: undefined,\n settled: () => undefined,\n lastScrollLeft: physicalScrollLeft(strip),\n pointerDownAt: Number.NaN,\n pointerMoved: false,\n touchDownAt: Number.NaN,\n touchMoved: false,\n };\n const settle = (): void => settleJudgement(strip, state);\n const onScroll = (): void => {\n const now = physicalScrollLeft(strip);\n const movedFarEnough = Math.abs(now - state.lastScrollLeft) > SCROLL_DELTA_EPSILON;\n state.lastScrollLeft = now;\n // Pointer/touch need BOTH signals (FUT-2775): the pointer/finger must have\n // itself MOVED since going down, AND this tick's delta must be real. Either\n // alone still latches on the other's shape — a pointer merely resting on\n // the strip while its OWN `scrollTo` produces real per-tick deltas would\n // arm under a delta-only check (`pointerMoved`/`touchMoved` rules that out);\n // a pointer that drifts a sub-epsilon amount while resting would arm under\n // a moved-only check with no delta floor (`movedFarEnough` rules that out).\n dropStaleNudge(state);\n const pointerDrag = state.pointer && state.pointerMoved && movedFarEnough;\n const touchDrag = state.touch && state.touchMoved && movedFarEnough;\n // `nudged` (a keypress, a sideways wheel, the browser taking the pointer\n // over to pan) is already a discrete, one-shot gesture with no \"resting\n // pointer coincides with an unrelated animation\" shape to rule out — unlike\n // pointer/touch, requiring a delta on the SAME tick that arms it would only\n // race the strip's own scroll ending before a qualifying tick arrives (seen:\n // it broke the existing \"keeps a wheel/drag scroll\" stories against a real\n // browser's `scrollend` timing). So it arms as it always has.\n if (pointerDrag || touchDrag || state.nudged) state.undecided = true;\n if (!state.undecided || hasScrollEnd) return;\n // Every tick while undecided, armed or not: a quiet spell that began while\n // the strip was still moving would judge it mid-flight, away from its aim.\n clearTimeout(state.quiet);\n state.quiet = setTimeout(settle, QUIET_BEFORE_SETTLED_MS);\n };\n const gestures = createGestureListeners(state);\n const onStrip: Listeners = [...gestures.onStrip, ['scroll', onScroll], ['scrollend', settle]];\n const onView = gestures.onView;\n for (const [type, listener] of onStrip) strip.addEventListener(type, listener, { passive: true });\n for (const [type, listener] of onView) view?.addEventListener(type, listener, { passive: true });\n return {\n hasScrolled: () => state.scrolled,\n isUndecided: () => state.undecided,\n aimedAt: () => state.aimed,\n beforeOwnScroll: (left) => {\n state.aimed = left;\n },\n onSettled: (listener) => {\n state.settled = listener;\n },\n detach: () => {\n clearTimeout(state.quiet);\n for (const [type, listener] of onStrip) strip.removeEventListener(type, listener);\n for (const [type, listener] of onView) view?.removeEventListener(type, listener);\n },\n };\n}\n"],"mappings":"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","names":[]}