@exponential_app/eui-react 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  ChoiceTilesFrame2,
3
3
  choiceColumns2,
4
- choiceValues2
5
- } from "./chunks/index-5yzzfez5.js";
4
+ choiceValues2,
5
+ ZOOM_MATH2,
6
+ useZoomableImage2
7
+ } from "./chunks/index-eny7hh6w.js";
6
8
 
7
9
  // packages/exponential-ui-react/src/surface.tsx
8
- import { useCallback as useCallback11, useEffect as useEffect20, useId as useId7, useImperativeHandle as useImperativeHandle2, useLayoutEffect as useLayoutEffect6, useMemo as useMemo18, useRef as useRef25, useState as useState21, useSyncExternalStore as useSyncExternalStore3 } from "react";
10
+ import { useCallback as useCallback11, useEffect as useEffect22, useId as useId7, useImperativeHandle as useImperativeHandle2, useLayoutEffect as useLayoutEffect7, useMemo as useMemo19, useRef as useRef26, useState as useState22, useSyncExternalStore as useSyncExternalStore3 } from "react";
9
11
  import {
10
12
  activeBreakpoint,
11
13
  applyContrast,
@@ -117,7 +119,7 @@ function extensionComponent(extensions, component) {
117
119
  }
118
120
 
119
121
  // packages/exponential-ui-react/src/node-view.tsx
120
- import { Component, Fragment as Fragment7, memo as memo2, useCallback as useCallback10, useContext as useContext6, useEffect as useEffect19, useMemo as useMemo17, useRef as useRef24 } from "react";
122
+ import { Component, Fragment as Fragment8, memo as memo2, useCallback as useCallback10, useContext as useContext6, useEffect as useEffect21, useMemo as useMemo18, useRef as useRef25 } from "react";
121
123
  import { UNKNOWN_COMPONENT, instanceSegment, isResponsiveValue, nativeRecipeProps as nativeRecipeProps4, responsiveAt, templateItemKeys, templateSiteKey, withOwnWrites } from "@exponential_app/eui";
122
124
  import { dynamicStyleEntries, nodeClass, queryToken, styleDirection } from "@exponential_app/eui/web";
123
125
 
@@ -252,7 +254,8 @@ import {
252
254
  File,
253
255
  Hand,
254
256
  Info,
255
- Loader,
257
+ LoaderCircle,
258
+ Maximize2,
256
259
  Menu,
257
260
  Mic,
258
261
  MicOff,
@@ -261,6 +264,7 @@ import {
261
264
  PhoneIncoming,
262
265
  PhoneOff,
263
266
  Play,
267
+ Pause,
264
268
  Plus,
265
269
  QrCode,
266
270
  ScanLine,
@@ -288,8 +292,9 @@ var CHROME = {
288
292
  send: Send,
289
293
  stop: Square,
290
294
  play: Play,
295
+ pause: Pause,
291
296
  attach: Paperclip,
292
- spinner: Loader,
297
+ spinner: LoaderCircle,
293
298
  placeholder: CircleDashed
294
299
  };
295
300
  var FALLBACK_ICONS = {
@@ -321,6 +326,7 @@ var FALLBACK_ICONS = {
321
326
  "ui-scan": ScanLine,
322
327
  "ui-qr-code": QrCode,
323
328
  "ui-hold": Hand,
329
+ "ui-fullscreen": Maximize2,
324
330
  "voice-level": AudioLines,
325
331
  "call-mute": Mic,
326
332
  "call-unmute": MicOff,
@@ -631,7 +637,8 @@ function ButtonNative({ node, props, rootProps, emit, children }) {
631
637
  const label = str(props.label);
632
638
  const icon = str(props.icon);
633
639
  const loading = bool(props.loading) || pending || submit && form.busy;
634
- const disabled = bool(props.disabled) || loading;
640
+ const disabled = bool(props.disabled);
641
+ const inert = disabled || loading;
635
642
  const iconOnly = props.size === `icon`;
636
643
  const Spinner = CHROME.spinner;
637
644
  const hasChild = node.children.length > 0;
@@ -646,7 +653,7 @@ function ButtonNative({ node, props, rootProps, emit, children }) {
646
653
  });
647
654
  const rootStyle = rootProps.style;
648
655
  const hold = bool(props.hold);
649
- const { held, handlers } = useHold(hold, disabled, emit);
656
+ const { held, handlers } = useHold(hold, inert, emit);
650
657
  const holdingLabel = str(props.holdingLabel);
651
658
  const paintedLabel = held && holdingLabel ? holdingLabel : shownLabel;
652
659
  const states = [...ctx.states ?? [], disabled ? `disabled` : ``, pending ? `pending` : ``, held ? `pressed` : ``].filter(Boolean).join(` `);
@@ -665,7 +672,7 @@ function ButtonNative({ node, props, rootProps, emit, children }) {
665
672
  ...hold ? handlers : {},
666
673
  onClick: (e) => {
667
674
  e.stopPropagation();
668
- if (hold)
675
+ if (hold || inert)
669
676
  return;
670
677
  track(emit(`press`));
671
678
  if (submit)
@@ -966,12 +973,12 @@ function ChartNative({ node, props, rootProps }) {
966
973
  strokeLinejoin: "round",
967
974
  strokeLinecap: "round"
968
975
  }),
969
- !sparkline ? s.values.map((v, i) => Number.isFinite(v) ? /* @__PURE__ */ jsx5("circle", {
970
- cx: px(i),
971
- cy: y(v),
972
- r: active === i ? 4 : 2.5,
976
+ !sparkline && active !== null && Number.isFinite(s.values[active]) ? /* @__PURE__ */ jsx5("circle", {
977
+ cx: px(active),
978
+ cy: y(s.values[active]),
979
+ r: 4,
973
980
  fill: color
974
- }, i) : null) : null
981
+ }) : null
975
982
  ]
976
983
  }, si);
977
984
  });
@@ -1136,15 +1143,17 @@ function ChartNative({ node, props, rootProps }) {
1136
1143
  fill: "currentColor",
1137
1144
  fontSize: AXIS_FONT,
1138
1145
  children: [
1139
- /* @__PURE__ */ jsx5("line", {
1140
- x1: mx(pad.l),
1141
- x2: mx(width - pad.r),
1142
- y1: zero,
1143
- y2: zero,
1144
- stroke: "currentColor",
1145
- strokeWidth: 1,
1146
- opacity: 0.6,
1147
- shapeRendering: "crispEdges"
1146
+ /* @__PURE__ */ jsx5("g", {
1147
+ ...part(`grid`),
1148
+ children: /* @__PURE__ */ jsx5("line", {
1149
+ x1: mx(pad.l),
1150
+ x2: mx(width - pad.r),
1151
+ y1: zero,
1152
+ y2: zero,
1153
+ stroke: "currentColor",
1154
+ strokeWidth: 1,
1155
+ shapeRendering: "crispEdges"
1156
+ })
1148
1157
  }),
1149
1158
  ticks.ticks.map((t, i) => /* @__PURE__ */ jsx5("text", {
1150
1159
  x: mx(pad.l - 6),
@@ -2274,8 +2283,7 @@ function TimePickerNative({ node, props, rootProps, emit, scope, domId }) {
2274
2283
  out.push(m);
2275
2284
  return out;
2276
2285
  }, [lo, hi, step]);
2277
- const clock = useMemo8(() => new Intl.DateTimeFormat(ctx.locale, { hour: `numeric`, minute: `2-digit` }), [ctx.locale]);
2278
- const show = (m) => clock.format(new Date(2000, 0, 1, Math.floor(m / 60), m % 60));
2286
+ const show = formatHHmm;
2279
2287
  const current = parseTime(value);
2280
2288
  const pick = (i) => {
2281
2289
  const next = formatHHmm(times[i]);
@@ -2384,10 +2392,46 @@ function TimePickerNative({ node, props, rootProps, emit, scope, domId }) {
2384
2392
  });
2385
2393
  }
2386
2394
 
2395
+ // packages/exponential-ui-react/src/natives/motion.tsx
2396
+ import { useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useRef as useRef11 } from "react";
2397
+ import { MotionView, motionA11y, motionBoxStyle, motionDeclaredSize } from "@exponential_app/eui/web";
2398
+ import { jsx as jsx10 } from "react/jsx-runtime";
2399
+ var CANVAS_STYLE = { display: `block`, width: `100%`, height: `100%` };
2400
+ function MotionNative({ node, props, rootProps, emit }) {
2401
+ const ctx = useSurfaceContext();
2402
+ const root = useRef11(null);
2403
+ const canvas = useRef11(null);
2404
+ const view = useRef11(null);
2405
+ useLayoutEffect3(() => {
2406
+ view.current = new MotionView(root.current, canvas.current);
2407
+ return () => {
2408
+ view.current?.destroy();
2409
+ view.current = null;
2410
+ };
2411
+ }, []);
2412
+ const host = ctx.host;
2413
+ const surfaceId = ctx.surfaceId;
2414
+ const pressable = Boolean(node.on?.press);
2415
+ useEffect8(() => {
2416
+ view.current?.update(props, { theme: ctx.theme, mode: ctx.mode, reducedMotion: ctx.reducedMotion, host, onError: (message) => host.onPaintError?.({ surfaceId, componentId: node.id, message }), emit: (event, payload) => void emit(event, payload), pressable }, node.style);
2417
+ });
2418
+ return /* @__PURE__ */ jsx10("div", {
2419
+ ref: root,
2420
+ ...rootProps,
2421
+ ...motionA11y(props.label, pressable),
2422
+ style: mergeStyle(rootProps, motionBoxStyle(motionDeclaredSize(props), node.style)),
2423
+ children: /* @__PURE__ */ jsx10("canvas", {
2424
+ ref: canvas,
2425
+ "aria-hidden": "true",
2426
+ style: CANVAS_STYLE
2427
+ })
2428
+ });
2429
+ }
2430
+
2387
2431
  // packages/exponential-ui-react/src/natives/resizable.tsx
2388
- import { useMemo as useMemo9, useRef as useRef11, useState as useState11 } from "react";
2432
+ import { useMemo as useMemo9, useRef as useRef12, useState as useState11 } from "react";
2389
2433
  import { dragDelta, keyboardResize, normalizeSizes, resizePanels, RESIZE_HANDLE_HIT } from "@exponential_app/eui";
2390
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2434
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2391
2435
  var RESIZE_KEYS = new Set([`ArrowLeft`, `ArrowRight`, `ArrowUp`, `ArrowDown`, `Home`, `End`, `Enter`]);
2392
2436
  function ResizableNative({ node, props, rootProps, emit, scope, domId }) {
2393
2437
  const ctx = useSurfaceContext();
@@ -2398,11 +2442,11 @@ function ResizableNative({ node, props, rootProps, emit, scope, domId }) {
2398
2442
  const external = useMemo9(() => normalizeSizes(arr(props.sizes), count, limits), [props.sizes, count, limits]);
2399
2443
  const [sizes, setBound] = useBoundState(node, scope, `sizes`, external);
2400
2444
  const [live, setLive] = useState11(null);
2401
- const liveRef = useRef11(null);
2445
+ const liveRef = useRef12(null);
2402
2446
  const shown = live ?? (sizes.length === count ? sizes : external);
2403
2447
  const hairline = num(ctx.theme.tokens.control?.hairline, 1);
2404
- const rootRef = useRef11(null);
2405
- const drag = useRef11(null);
2448
+ const rootRef = useRef12(null);
2449
+ const drag = useRef12(null);
2406
2450
  const commit = (next) => {
2407
2451
  setBound(next);
2408
2452
  emit(`change`, { sizes: next }, { sizes: next });
@@ -2453,12 +2497,12 @@ function ResizableNative({ node, props, rootProps, emit, scope, domId }) {
2453
2497
  const parts = [];
2454
2498
  for (let i = 0;i < count; i++) {
2455
2499
  const size = shown[i] ?? 0;
2456
- parts.push(/* @__PURE__ */ jsx10("div", {
2500
+ parts.push(/* @__PURE__ */ jsx11("div", {
2457
2501
  ...part.at(`panel`, i),
2458
2502
  id: `${domId}.panel.${i}`,
2459
2503
  "data-size": size,
2460
2504
  style: { flex: `${size} 1 0px` },
2461
- children: /* @__PURE__ */ jsx10(NodeView, {
2505
+ children: /* @__PURE__ */ jsx11(NodeView, {
2462
2506
  node: node.children[i]
2463
2507
  })
2464
2508
  }, node.children[i].id));
@@ -2481,12 +2525,12 @@ function ResizableNative({ node, props, rootProps, emit, scope, domId }) {
2481
2525
  onPointerCancel: onPointerEnd,
2482
2526
  onKeyDown: onKey(i),
2483
2527
  children: [
2484
- /* @__PURE__ */ jsx10("span", {
2528
+ /* @__PURE__ */ jsx11("span", {
2485
2529
  className: "xui-resize-hit",
2486
2530
  "aria-hidden": "true",
2487
2531
  style: { [orientation === `horizontal` ? `width` : `height`]: RESIZE_HANDLE_HIT }
2488
2532
  }),
2489
- bool(props.handle) ? /* @__PURE__ */ jsx10("span", {
2533
+ bool(props.handle) ? /* @__PURE__ */ jsx11("span", {
2490
2534
  ...part.at(`grip`, i),
2491
2535
  "aria-hidden": "true"
2492
2536
  }) : null
@@ -2494,7 +2538,7 @@ function ResizableNative({ node, props, rootProps, emit, scope, domId }) {
2494
2538
  }, `h${i}`));
2495
2539
  }
2496
2540
  }
2497
- return /* @__PURE__ */ jsx10("div", {
2541
+ return /* @__PURE__ */ jsx11("div", {
2498
2542
  ref: rootRef,
2499
2543
  ...rootProps,
2500
2544
  role: "group",
@@ -2505,10 +2549,10 @@ function ResizableNative({ node, props, rootProps, emit, scope, domId }) {
2505
2549
  }
2506
2550
 
2507
2551
  // packages/exponential-ui-react/src/natives/feedback.tsx
2508
- import { useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useRef as useRef12 } from "react";
2552
+ import { useEffect as useEffect9, useLayoutEffect as useLayoutEffect4, useRef as useRef13 } from "react";
2509
2553
  import { resolveRecipe, nativeRecipeProps as nativeRecipeProps2, voiceWave, voiceWaveBars, voiceWaveChildBox, voiceWavePath, voiceWaveVariant, TREE_GUIDE_BRIDGE, TREE_GUIDE_COLUMN, TREE_GUIDE_RADIUS, VOICE_WAVE_ACTIVITIES } from "@exponential_app/eui";
2510
2554
  import { voiceWaveAnimates, voiceWaveClock, voiceWaveFitChild, voiceWaveName } from "@exponential_app/eui/web";
2511
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2555
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2512
2556
  function sizeOf(ctx, component, part, props, fallback) {
2513
2557
  const style = resolveRecipe(ctx.theme, { component, part, props: nativeRecipeProps2(component, props, ctx.extensionDefs) }, ctx.mode);
2514
2558
  return typeof style.width === `number` ? style.width : fallback;
@@ -2538,7 +2582,7 @@ function RingNative({ node, props, rootProps }) {
2538
2582
  width: size,
2539
2583
  height: size,
2540
2584
  children: [
2541
- /* @__PURE__ */ jsx11("circle", {
2585
+ /* @__PURE__ */ jsx12("circle", {
2542
2586
  ...part(`track`),
2543
2587
  cx: size / 2,
2544
2588
  cy: size / 2,
@@ -2548,7 +2592,7 @@ function RingNative({ node, props, rootProps }) {
2548
2592
  strokeWidth: stroke,
2549
2593
  style: { color: String(trackStyle.color ?? `currentColor`) }
2550
2594
  }),
2551
- /* @__PURE__ */ jsx11("circle", {
2595
+ /* @__PURE__ */ jsx12("circle", {
2552
2596
  ...part(`fill`),
2553
2597
  cx: size / 2,
2554
2598
  cy: size / 2,
@@ -2563,7 +2607,7 @@ function RingNative({ node, props, rootProps }) {
2563
2607
  })
2564
2608
  ]
2565
2609
  }),
2566
- label ? /* @__PURE__ */ jsx11("span", {
2610
+ label ? /* @__PURE__ */ jsx12("span", {
2567
2611
  ...part(`label`),
2568
2612
  children: label
2569
2613
  }) : null
@@ -2575,12 +2619,12 @@ function SpinnerNative({ props, rootProps }) {
2575
2619
  const size = sizeOf(ctx, `Spinner`, `root`, props, 20);
2576
2620
  const Icon = CHROME.spinner;
2577
2621
  const label = str(props.label) || ctx.t(`loading`);
2578
- return /* @__PURE__ */ jsx11("span", {
2622
+ return /* @__PURE__ */ jsx12("span", {
2579
2623
  ...rootProps,
2580
2624
  role: "status",
2581
2625
  "aria-label": label,
2582
2626
  style: mergeStyle(rootProps, { width: size, height: size }),
2583
- children: /* @__PURE__ */ jsx11(Icon, {
2627
+ children: /* @__PURE__ */ jsx12(Icon, {
2584
2628
  "aria-hidden": "true"
2585
2629
  })
2586
2630
  });
@@ -2596,7 +2640,7 @@ function SkeletonNative({ node, props, rootProps }) {
2596
2640
  if (rows >= 1) {
2597
2641
  const dot = props.dot === undefined ? true : bool(props.dot);
2598
2642
  const height = props.rowHeight === undefined ? `var(--xui-control-row)` : `${num(props.rowHeight)}px`;
2599
- return /* @__PURE__ */ jsx11("div", {
2643
+ return /* @__PURE__ */ jsx12("div", {
2600
2644
  ...rootProps,
2601
2645
  "data-rows": "",
2602
2646
  "aria-hidden": "true",
@@ -2606,14 +2650,14 @@ function SkeletonNative({ node, props, rootProps }) {
2606
2650
  ...part.at(`row`, r),
2607
2651
  style: { height },
2608
2652
  children: [
2609
- dot ? /* @__PURE__ */ jsx11("span", {
2653
+ dot ? /* @__PURE__ */ jsx12("span", {
2610
2654
  ...part.at(`dot`, r)
2611
2655
  }) : null,
2612
- /* @__PURE__ */ jsx11("span", {
2656
+ /* @__PURE__ */ jsx12("span", {
2613
2657
  ...part.at(`bar`, `${r}.0`),
2614
2658
  style: { width: lead }
2615
2659
  }),
2616
- /* @__PURE__ */ jsx11("span", {
2660
+ /* @__PURE__ */ jsx12("span", {
2617
2661
  ...part.at(`bar`, `${r}.1`),
2618
2662
  "data-title": "",
2619
2663
  style: { width: title }
@@ -2625,7 +2669,7 @@ function SkeletonNative({ node, props, rootProps }) {
2625
2669
  }
2626
2670
  const width = str(props.width, `100%`);
2627
2671
  const height = str(props.height, `16px`);
2628
- return /* @__PURE__ */ jsx11("div", {
2672
+ return /* @__PURE__ */ jsx12("div", {
2629
2673
  ...rootProps,
2630
2674
  "aria-hidden": "true",
2631
2675
  style: mergeStyle(rootProps, { width, height, borderRadius: bool(props.rounded) ? 9999 : undefined })
@@ -2641,7 +2685,7 @@ function TreeGuidesNative({ node, props, rootProps }) {
2641
2685
  const stroke = sizeOf(ctx, `TreeGuides`, `line`, props, 1);
2642
2686
  const line = part(`line`);
2643
2687
  const x = TREE_GUIDE_COLUMN / 2;
2644
- const vertical = (key) => /* @__PURE__ */ jsx11("i", {
2688
+ const vertical = (key) => /* @__PURE__ */ jsx12("i", {
2645
2689
  ...line,
2646
2690
  "data-vertical": "",
2647
2691
  style: { left: x, width: stroke, top: -TREE_GUIDE_BRIDGE, bottom: 0 }
@@ -2656,7 +2700,7 @@ function TreeGuidesNative({ node, props, rootProps }) {
2656
2700
  children: [
2657
2701
  pass.has(i) && !elbow ? vertical(`p`) : null,
2658
2702
  elbow && tee ? vertical(`t`) : null,
2659
- elbow ? /* @__PURE__ */ jsx11("i", {
2703
+ elbow ? /* @__PURE__ */ jsx12("i", {
2660
2704
  ...line,
2661
2705
  "data-elbow": "",
2662
2706
  style: {
@@ -2672,7 +2716,7 @@ function TreeGuidesNative({ node, props, rootProps }) {
2672
2716
  ]
2673
2717
  }, i));
2674
2718
  }
2675
- return /* @__PURE__ */ jsx11("span", {
2719
+ return /* @__PURE__ */ jsx12("span", {
2676
2720
  ...rootProps,
2677
2721
  "aria-hidden": "true",
2678
2722
  "data-tee": tee ? `true` : undefined,
@@ -2680,9 +2724,9 @@ function TreeGuidesNative({ node, props, rootProps }) {
2680
2724
  });
2681
2725
  }
2682
2726
  function VoiceWaveNative(p) {
2683
- return voiceWaveVariant(p.props.variant) === `bars` ? /* @__PURE__ */ jsx11(VoiceWaveBarsNative, {
2727
+ return voiceWaveVariant(p.props.variant) === `bars` ? /* @__PURE__ */ jsx12(VoiceWaveBarsNative, {
2684
2728
  ...p
2685
- }) : /* @__PURE__ */ jsx11(VoiceWaveRingNative, {
2729
+ }) : /* @__PURE__ */ jsx12(VoiceWaveRingNative, {
2686
2730
  ...p
2687
2731
  });
2688
2732
  }
@@ -2691,12 +2735,12 @@ function VoiceWaveBarsNative({ node, props, rootProps, children }) {
2691
2735
  const part = useParts(node, props);
2692
2736
  const activity = VOICE_WAVE_ACTIVITIES.includes(str(props.activity)) ? str(props.activity) : `idle`;
2693
2737
  const input = { size: str(props.size, `md`), activity, level: num(props.level, 0), bands: arr(props.bands).map((b) => num(b, 0)), reducedMotion: ctx.reducedMotion };
2694
- const latest = useRef12(input);
2738
+ const latest = useRef13(input);
2695
2739
  latest.current = input;
2696
- const elapsed = useRef12(0);
2697
- const rects = useRef12([]);
2740
+ const elapsed = useRef13(0);
2741
+ const rects = useRef13([]);
2698
2742
  const animates = voiceWaveAnimates(activity) && !ctx.reducedMotion;
2699
- useEffect8(() => {
2743
+ useEffect9(() => {
2700
2744
  if (!animates) {
2701
2745
  elapsed.current = 0;
2702
2746
  return;
@@ -2723,13 +2767,13 @@ function VoiceWaveBarsNative({ node, props, rootProps, children }) {
2723
2767
  "data-variant": "bars",
2724
2768
  style: mergeStyle(rootProps, { width: meter.width, height: meter.height }),
2725
2769
  children: [
2726
- /* @__PURE__ */ jsx11("svg", {
2770
+ /* @__PURE__ */ jsx12("svg", {
2727
2771
  viewBox: `0 0 ${meter.width} ${meter.height}`,
2728
2772
  width: meter.width,
2729
2773
  height: meter.height,
2730
2774
  "aria-hidden": "true",
2731
2775
  style: { color: colour },
2732
- children: meter.bars.map((bar, i) => /* @__PURE__ */ jsx11("rect", {
2776
+ children: meter.bars.map((bar, i) => /* @__PURE__ */ jsx12("rect", {
2733
2777
  ref: (el) => {
2734
2778
  rects.current[i] = el;
2735
2779
  },
@@ -2742,7 +2786,7 @@ function VoiceWaveBarsNative({ node, props, rootProps, children }) {
2742
2786
  fill: "currentColor"
2743
2787
  }, i))
2744
2788
  }),
2745
- node.children.length > 0 ? /* @__PURE__ */ jsx11("span", {
2789
+ node.children.length > 0 ? /* @__PURE__ */ jsx12("span", {
2746
2790
  ...part(`child`),
2747
2791
  "data-hidden": "true",
2748
2792
  "aria-hidden": "true",
@@ -2757,12 +2801,12 @@ function VoiceWaveRingNative({ node, props, rootProps, children }) {
2757
2801
  const size = sizeOf(ctx, `VoiceWave`, `root`, props, 56);
2758
2802
  const activity = VOICE_WAVE_ACTIVITIES.includes(str(props.activity)) ? str(props.activity) : `idle`;
2759
2803
  const input = { size, activity, level: num(props.level, 0), bands: arr(props.bands).map((b) => num(b, 0)), reducedMotion: ctx.reducedMotion };
2760
- const latest = useRef12(input);
2804
+ const latest = useRef13(input);
2761
2805
  latest.current = input;
2762
- const elapsed = useRef12(0);
2763
- const paths = useRef12([]);
2806
+ const elapsed = useRef13(0);
2807
+ const paths = useRef13([]);
2764
2808
  const animates = voiceWaveAnimates(activity) && !ctx.reducedMotion;
2765
- useEffect8(() => {
2809
+ useEffect9(() => {
2766
2810
  if (!animates) {
2767
2811
  elapsed.current = 0;
2768
2812
  return;
@@ -2772,9 +2816,9 @@ function VoiceWaveRingNative({ node, props, rootProps, children }) {
2772
2816
  voiceWave({ ...latest.current, elapsed: t }).rings.forEach((ring, k) => paths.current[k]?.setAttribute(`d`, voiceWavePath(ring)));
2773
2817
  });
2774
2818
  }, [animates]);
2775
- const childEl = useRef12(null);
2819
+ const childEl = useRef13(null);
2776
2820
  const hasChild = node.children.length > 0;
2777
- useLayoutEffect3(() => hasChild && childEl.current ? voiceWaveFitChild(childEl.current, (c) => voiceWaveChildBox(size, c).scale) : undefined, [hasChild, size]);
2821
+ useLayoutEffect4(() => hasChild && childEl.current ? voiceWaveFitChild(childEl.current, (c) => voiceWaveChildBox(size, c).scale) : undefined, [hasChild, size]);
2778
2822
  const wave = voiceWave({ ...input, elapsed: elapsed.current });
2779
2823
  const recipeProps = nativeRecipeProps2(`VoiceWave`, props);
2780
2824
  const colour = (name) => String(resolveRecipe(ctx.theme, { component: `VoiceWave`, part: name, props: recipeProps }, ctx.mode).color ?? `currentColor`);
@@ -2786,12 +2830,12 @@ function VoiceWaveRingNative({ node, props, rootProps, children }) {
2786
2830
  "aria-hidden": name ? undefined : `true`,
2787
2831
  style: mergeStyle(rootProps, { width: size, height: size }),
2788
2832
  children: [
2789
- /* @__PURE__ */ jsx11("svg", {
2833
+ /* @__PURE__ */ jsx12("svg", {
2790
2834
  viewBox: `0 0 ${size} ${size}`,
2791
2835
  width: size,
2792
2836
  height: size,
2793
2837
  "aria-hidden": "true",
2794
- children: wave.rings.map((ring, k) => /* @__PURE__ */ jsx11("path", {
2838
+ children: wave.rings.map((ring, k) => /* @__PURE__ */ jsx12("path", {
2795
2839
  ref: (el) => {
2796
2840
  paths.current[k] = el;
2797
2841
  },
@@ -2806,7 +2850,7 @@ function VoiceWaveRingNative({ node, props, rootProps, children }) {
2806
2850
  style: { color: colour(ring.part) }
2807
2851
  }, ring.part))
2808
2852
  }),
2809
- hasChild ? /* @__PURE__ */ jsx11("span", {
2853
+ hasChild ? /* @__PURE__ */ jsx12("span", {
2810
2854
  ref: childEl,
2811
2855
  ...part(`child`),
2812
2856
  "data-hidden": wave.childSize > 0 ? undefined : `true`,
@@ -2819,25 +2863,25 @@ function VoiceWaveRingNative({ node, props, rootProps, children }) {
2819
2863
  }
2820
2864
 
2821
2865
  // packages/exponential-ui-react/src/natives/inputs.tsx
2822
- import { useEffect as useEffect10, useId as useId4, useMemo as useMemo10, useRef as useRef14, useState as useState12 } from "react";
2866
+ import { useEffect as useEffect11, useId as useId4, useMemo as useMemo10, useRef as useRef15, useState as useState12 } from "react";
2823
2867
  import { Checkbox as CheckboxPrimitive, RadioGroup as RadioPrimitive, Slider as SliderPrimitive, Switch as SwitchPrimitive } from "radix-ui";
2824
2868
  import { boundPath as boundPath2, hostPath } from "@exponential_app/eui/web";
2825
2869
 
2826
2870
  // packages/exponential-ui-react/src/inputs.ts
2827
- import { useCallback as useCallback5, useEffect as useEffect9, useReducer, useRef as useRef13 } from "react";
2871
+ import { useCallback as useCallback5, useEffect as useEffect10, useReducer, useRef as useRef14 } from "react";
2828
2872
  import { DEBOUNCE_MS, HostOwnedController } from "@exponential_app/eui/web";
2829
2873
  function useHostOwnedValue({ external, send, writeLocal, debounceMs = DEBOUNCE_MS }) {
2830
2874
  const [, rerender] = useReducer((n) => n + 1, 0);
2831
- const ref = useRef13(null);
2875
+ const ref = useRef14(null);
2832
2876
  if (!ref.current)
2833
2877
  ref.current = new HostOwnedController({ initial: external, send, writeLocal, debounceMs, onChange: rerender });
2834
2878
  const c = ref.current;
2835
2879
  c.configure({ send, writeLocal, debounceMs });
2836
- useEffect9(() => {
2880
+ useEffect10(() => {
2837
2881
  c.attach();
2838
2882
  return () => c.dispose();
2839
2883
  }, [c]);
2840
- useEffect9(() => {
2884
+ useEffect10(() => {
2841
2885
  c.push(external);
2842
2886
  }, [c, external]);
2843
2887
  const onFocus = useCallback5(() => c.focus(), [c]);
@@ -2849,7 +2893,7 @@ function useHostOwnedValue({ external, send, writeLocal, debounceMs = DEBOUNCE_M
2849
2893
 
2850
2894
  // packages/exponential-ui-react/src/natives/inputs.tsx
2851
2895
  import { parseLocaleNumber } from "@exponential_app/eui/web";
2852
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2896
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
2853
2897
  function useInputSender(node, scope, prop, domId = node.id) {
2854
2898
  const ctx = useSurfaceContext();
2855
2899
  const path = boundPath2(node.props, prop, scope);
@@ -2862,13 +2906,13 @@ function useInputSender(node, scope, prop, domId = node.id) {
2862
2906
  return { send, writeLocal, path, name };
2863
2907
  }
2864
2908
  function InputNative(p) {
2865
- return /* @__PURE__ */ jsx12(TextFieldNative, {
2909
+ return /* @__PURE__ */ jsx13(TextFieldNative, {
2866
2910
  ...p,
2867
2911
  multiline: false
2868
2912
  });
2869
2913
  }
2870
2914
  function TextareaNative(p) {
2871
- return /* @__PURE__ */ jsx12(TextFieldNative, {
2915
+ return /* @__PURE__ */ jsx13(TextFieldNative, {
2872
2916
  ...p,
2873
2917
  multiline: true
2874
2918
  });
@@ -2891,7 +2935,7 @@ function TextFieldNative({ node, props, rootProps, emit, scope, domId, multiline
2891
2935
  const { send, writeLocal } = useInputSender(node, scope, `value`, domId);
2892
2936
  const external = str(props.value);
2893
2937
  const field = useHostOwnedValue({ external, send, writeLocal });
2894
- const focusRef = useRef14(null);
2938
+ const focusRef = useRef15(null);
2895
2939
  const f = useField({ node, domId, props, value: field.value, focusRef });
2896
2940
  const disabled = bool(props.disabled) || Boolean(f.form?.disabled);
2897
2941
  const label = str(props.label);
@@ -2900,7 +2944,7 @@ function TextFieldNative({ node, props, rootProps, emit, scope, domId, multiline
2900
2944
  const rows = Math.max(1, num(props.rows, 3));
2901
2945
  const maxRows = props.maxRows === undefined ? null : Math.max(rows, num(props.maxRows, rows));
2902
2946
  const auto = multiline && bool(props.autosize);
2903
- useEffect10(() => {
2947
+ useEffect11(() => {
2904
2948
  if (auto && focusRef.current)
2905
2949
  autosize(focusRef.current, rows, maxRows);
2906
2950
  }, [auto, field.value, rows, maxRows]);
@@ -2933,19 +2977,19 @@ function TextFieldNative({ node, props, rootProps, emit, scope, domId, multiline
2933
2977
  "data-pending": field.pending ? `true` : undefined,
2934
2978
  "data-revision": field.revision,
2935
2979
  children: [
2936
- /* @__PURE__ */ jsx12(TextPart, {
2980
+ /* @__PURE__ */ jsx13(TextPart, {
2937
2981
  part: part(`label`),
2938
2982
  text: label,
2939
2983
  as: "label",
2940
2984
  htmlFor: id
2941
2985
  }),
2942
- multiline ? /* @__PURE__ */ jsx12("textarea", {
2986
+ multiline ? /* @__PURE__ */ jsx13("textarea", {
2943
2987
  ref: focusRef,
2944
2988
  ...part(`field`, ...fieldStates),
2945
2989
  ...shared,
2946
2990
  rows,
2947
2991
  "data-autosize": auto ? `true` : undefined
2948
- }) : /* @__PURE__ */ jsx12("input", {
2992
+ }) : /* @__PURE__ */ jsx13("input", {
2949
2993
  ref: focusRef,
2950
2994
  ...part(`field`, ...fieldStates),
2951
2995
  ...shared,
@@ -2959,12 +3003,12 @@ function TextFieldNative({ node, props, rootProps, emit, scope, domId, multiline
2959
3003
  }
2960
3004
  }
2961
3005
  }),
2962
- /* @__PURE__ */ jsx12(TextPart, {
3006
+ /* @__PURE__ */ jsx13(TextPart, {
2963
3007
  part: part(`description`),
2964
3008
  text: description,
2965
3009
  id: `${id}-d`
2966
3010
  }),
2967
- /* @__PURE__ */ jsx12(FieldErrors, {
3011
+ /* @__PURE__ */ jsx13(FieldErrors, {
2968
3012
  part,
2969
3013
  field: f
2970
3014
  })
@@ -2987,7 +3031,7 @@ function NumberFieldNative({ node, props, rootProps, emit, scope, domId }) {
2987
3031
  const external = props.value === undefined || props.value === null || props.value === `` ? null : num(props.value);
2988
3032
  const [value, setValue] = useBoundState(node, scope, `value`, external);
2989
3033
  const [text, setText] = useState12(null);
2990
- const focusRef = useRef14(null);
3034
+ const focusRef = useRef15(null);
2991
3035
  const f = useField({ node, domId, props, value, focusRef });
2992
3036
  const disabled = bool(props.disabled) || Boolean(f.form?.disabled);
2993
3037
  const decimalSep = useMemo10(() => new Intl.NumberFormat(ctx.locale).formatToParts(1.1).find((p) => p.type === `decimal`)?.value ?? `.`, [ctx.locale]);
@@ -3015,7 +3059,7 @@ function NumberFieldNative({ node, props, rootProps, emit, scope, domId }) {
3015
3059
  return /* @__PURE__ */ jsxs9("div", {
3016
3060
  ...rootProps,
3017
3061
  children: [
3018
- /* @__PURE__ */ jsx12(TextPart, {
3062
+ /* @__PURE__ */ jsx13(TextPart, {
3019
3063
  part: part(`label`),
3020
3064
  text: props.label,
3021
3065
  as: "label",
@@ -3025,18 +3069,18 @@ function NumberFieldNative({ node, props, rootProps, emit, scope, domId }) {
3025
3069
  ...part(`field`, disabled && `disabled`, f.invalid && `invalid`),
3026
3070
  "data-xui-numberfield": "",
3027
3071
  children: [
3028
- /* @__PURE__ */ jsx12("button", {
3072
+ /* @__PURE__ */ jsx13("button", {
3029
3073
  type: "button",
3030
3074
  ...part(`decrement`, disabled && `disabled`),
3031
3075
  "aria-label": ctx.t(`decrement`),
3032
3076
  tabIndex: -1,
3033
3077
  disabled: disabled || min !== null && value !== null && value <= min,
3034
3078
  onClick: () => stepBy(-step),
3035
- children: /* @__PURE__ */ jsx12(BuiltinIcon, {
3079
+ children: /* @__PURE__ */ jsx13(BuiltinIcon, {
3036
3080
  slot: "NumberField.decrement"
3037
3081
  })
3038
3082
  }),
3039
- /* @__PURE__ */ jsx12("input", {
3083
+ /* @__PURE__ */ jsx13("input", {
3040
3084
  ref: focusRef,
3041
3085
  id,
3042
3086
  ...part(`input`),
@@ -3103,24 +3147,24 @@ function NumberFieldNative({ node, props, rootProps, emit, scope, domId }) {
3103
3147
  }
3104
3148
  }
3105
3149
  }),
3106
- unit ? /* @__PURE__ */ jsx12("span", {
3150
+ unit ? /* @__PURE__ */ jsx13("span", {
3107
3151
  ...part(`unit`),
3108
3152
  children: unit
3109
3153
  }) : null,
3110
- /* @__PURE__ */ jsx12("button", {
3154
+ /* @__PURE__ */ jsx13("button", {
3111
3155
  type: "button",
3112
3156
  ...part(`increment`, disabled && `disabled`),
3113
3157
  "aria-label": ctx.t(`increment`),
3114
3158
  tabIndex: -1,
3115
3159
  disabled: disabled || max !== null && value !== null && value >= max,
3116
3160
  onClick: () => stepBy(step),
3117
- children: /* @__PURE__ */ jsx12(BuiltinIcon, {
3161
+ children: /* @__PURE__ */ jsx13(BuiltinIcon, {
3118
3162
  slot: "NumberField.increment"
3119
3163
  })
3120
3164
  })
3121
3165
  ]
3122
3166
  }),
3123
- /* @__PURE__ */ jsx12(FieldErrors, {
3167
+ /* @__PURE__ */ jsx13(FieldErrors, {
3124
3168
  part,
3125
3169
  field: f
3126
3170
  })
@@ -3131,13 +3175,13 @@ function CheckboxNative({ node, props, rootProps, emit, scope, domId }) {
3131
3175
  const part = useParts(node, props);
3132
3176
  const id = useId4();
3133
3177
  const [checked, setChecked] = useBoundState(node, scope, `checked`, bool(props.checked));
3134
- const focusRef = useRef14(null);
3178
+ const focusRef = useRef15(null);
3135
3179
  const f = useField({ node, domId, props, value: checked, focusRef });
3136
3180
  const disabled = bool(props.disabled) || Boolean(f.form?.disabled);
3137
3181
  return /* @__PURE__ */ jsxs9("div", {
3138
3182
  ...rootProps,
3139
3183
  children: [
3140
- /* @__PURE__ */ jsx12(CheckboxPrimitive.Root, {
3184
+ /* @__PURE__ */ jsx13(CheckboxPrimitive.Root, {
3141
3185
  ref: focusRef,
3142
3186
  id,
3143
3187
  ...part(`box`, checked && `checked`, disabled && `disabled`, f.invalid && `invalid`),
@@ -3153,9 +3197,9 @@ function CheckboxNative({ node, props, rootProps, emit, scope, domId }) {
3153
3197
  f.touch();
3154
3198
  emit(`change`, { checked: value }, { checked: value });
3155
3199
  },
3156
- children: /* @__PURE__ */ jsx12(CheckboxPrimitive.Indicator, {
3200
+ children: /* @__PURE__ */ jsx13(CheckboxPrimitive.Indicator, {
3157
3201
  ...part(`check`),
3158
- children: /* @__PURE__ */ jsx12(BuiltinIcon, {
3202
+ children: /* @__PURE__ */ jsx13(BuiltinIcon, {
3159
3203
  slot: "Checkbox.check"
3160
3204
  })
3161
3205
  })
@@ -3163,17 +3207,17 @@ function CheckboxNative({ node, props, rootProps, emit, scope, domId }) {
3163
3207
  /* @__PURE__ */ jsxs9("div", {
3164
3208
  className: "xui-field-text",
3165
3209
  children: [
3166
- /* @__PURE__ */ jsx12(TextPart, {
3210
+ /* @__PURE__ */ jsx13(TextPart, {
3167
3211
  part: part(`label`),
3168
3212
  text: props.label,
3169
3213
  as: "label",
3170
3214
  htmlFor: id
3171
3215
  }),
3172
- /* @__PURE__ */ jsx12(TextPart, {
3216
+ /* @__PURE__ */ jsx13(TextPart, {
3173
3217
  part: part(`description`),
3174
3218
  text: props.description
3175
3219
  }),
3176
- /* @__PURE__ */ jsx12(FieldErrors, {
3220
+ /* @__PURE__ */ jsx13(FieldErrors, {
3177
3221
  part,
3178
3222
  field: f
3179
3223
  })
@@ -3187,7 +3231,7 @@ function SwitchNative({ node, props, rootProps, emit, scope, domId }) {
3187
3231
  const id = useId4();
3188
3232
  const ctx = useSurfaceContext();
3189
3233
  const [checked, setChecked] = useBoundState(node, scope, `checked`, bool(props.checked));
3190
- const focusRef = useRef14(null);
3234
+ const focusRef = useRef15(null);
3191
3235
  const f = useField({ node, domId, props, value: checked, focusRef });
3192
3236
  const disabled = bool(props.disabled) || Boolean(f.form?.disabled);
3193
3237
  const travel = useMemo10(() => {
@@ -3209,24 +3253,24 @@ function SwitchNative({ node, props, rootProps, emit, scope, domId }) {
3209
3253
  /* @__PURE__ */ jsxs9("div", {
3210
3254
  ...part(`body`),
3211
3255
  children: [
3212
- /* @__PURE__ */ jsx12(TextPart, {
3256
+ /* @__PURE__ */ jsx13(TextPart, {
3213
3257
  part: part(`label`),
3214
3258
  text: props.label,
3215
3259
  as: "label",
3216
3260
  htmlFor: id
3217
3261
  }),
3218
- /* @__PURE__ */ jsx12(TextPart, {
3262
+ /* @__PURE__ */ jsx13(TextPart, {
3219
3263
  part: part(`description`),
3220
3264
  text: description,
3221
3265
  id: `${id}-d`
3222
3266
  }),
3223
- /* @__PURE__ */ jsx12(FieldErrors, {
3267
+ /* @__PURE__ */ jsx13(FieldErrors, {
3224
3268
  part,
3225
3269
  field: f
3226
3270
  })
3227
3271
  ]
3228
3272
  }),
3229
- /* @__PURE__ */ jsx12(SwitchPrimitive.Root, {
3273
+ /* @__PURE__ */ jsx13(SwitchPrimitive.Root, {
3230
3274
  ref: focusRef,
3231
3275
  id,
3232
3276
  ...part(`track`, checked && `checked`, disabled && `disabled`),
@@ -3240,7 +3284,7 @@ function SwitchNative({ node, props, rootProps, emit, scope, domId }) {
3240
3284
  f.change(next);
3241
3285
  emit(`change`, { checked: next }, { checked: next });
3242
3286
  },
3243
- children: /* @__PURE__ */ jsx12(SwitchPrimitive.Thumb, {
3287
+ children: /* @__PURE__ */ jsx13(SwitchPrimitive.Thumb, {
3244
3288
  ...part(`thumb`, checked && `checked`)
3245
3289
  })
3246
3290
  })
@@ -3253,7 +3297,7 @@ function RadioNative({ node, props, rootProps, emit, scope, domId }) {
3253
3297
  const id = useId4();
3254
3298
  const options = objects(props.options);
3255
3299
  const [value, setValue] = useBoundState(node, scope, `value`, str(props.value));
3256
- const focusRef = useRef14(null);
3300
+ const focusRef = useRef15(null);
3257
3301
  const itemRef = useMemo10(() => ({
3258
3302
  get current() {
3259
3303
  return focusRef.current?.querySelector(`[data-state="checked"]`) ?? focusRef.current?.querySelector(`button`);
@@ -3266,12 +3310,12 @@ function RadioNative({ node, props, rootProps, emit, scope, domId }) {
3266
3310
  "aria-labelledby": props.label ? `${id}-l` : undefined,
3267
3311
  "aria-describedby": f.describedBy,
3268
3312
  children: [
3269
- /* @__PURE__ */ jsx12(TextPart, {
3313
+ /* @__PURE__ */ jsx13(TextPart, {
3270
3314
  part: part(`label`),
3271
3315
  text: props.label,
3272
3316
  id: `${id}-l`
3273
3317
  }),
3274
- /* @__PURE__ */ jsx12(RadioPrimitive.Root, {
3318
+ /* @__PURE__ */ jsx13(RadioPrimitive.Root, {
3275
3319
  ref: focusRef,
3276
3320
  ...part(`items`),
3277
3321
  className: `${part(`items`).className} xui-radio-items`,
@@ -3294,24 +3338,24 @@ function RadioNative({ node, props, rootProps, emit, scope, domId }) {
3294
3338
  htmlFor: oid,
3295
3339
  "data-xui-id": `${part.domId}.item.${i}`,
3296
3340
  children: [
3297
- /* @__PURE__ */ jsx12(RadioPrimitive.Item, {
3341
+ /* @__PURE__ */ jsx13(RadioPrimitive.Item, {
3298
3342
  id: oid,
3299
3343
  value: o.value,
3300
3344
  disabled: bool(o.disabled),
3301
3345
  ...part(`item`, checked && `checked`, bool(o.disabled) && `disabled`, f.invalid && `invalid`),
3302
3346
  "data-xui-id": `${part.domId}.dot.${i}`,
3303
- children: /* @__PURE__ */ jsx12(RadioPrimitive.Indicator, {
3347
+ children: /* @__PURE__ */ jsx13(RadioPrimitive.Indicator, {
3304
3348
  ...part(`dot`, checked && `checked`)
3305
3349
  })
3306
3350
  }),
3307
- o.icon ? /* @__PURE__ */ jsx12(IconGlyph, {
3351
+ o.icon ? /* @__PURE__ */ jsx13(IconGlyph, {
3308
3352
  icons: ctx.host.icons,
3309
3353
  name: o.icon,
3310
3354
  className: "xui-icon",
3311
3355
  width: 16,
3312
3356
  height: 16
3313
3357
  }) : null,
3314
- /* @__PURE__ */ jsx12("span", {
3358
+ /* @__PURE__ */ jsx13("span", {
3315
3359
  ...part.at(`label`, i),
3316
3360
  children: str(o.label)
3317
3361
  })
@@ -3319,7 +3363,7 @@ function RadioNative({ node, props, rootProps, emit, scope, domId }) {
3319
3363
  }, o.value);
3320
3364
  })
3321
3365
  }),
3322
- /* @__PURE__ */ jsx12(FieldErrors, {
3366
+ /* @__PURE__ */ jsx13(FieldErrors, {
3323
3367
  part,
3324
3368
  field: f
3325
3369
  })
@@ -3341,13 +3385,13 @@ function SliderNative({ node, props, rootProps, emit, scope }) {
3341
3385
  ...part(`header`),
3342
3386
  className: `${part(`header`).className} xui-slider-head`,
3343
3387
  children: [
3344
- /* @__PURE__ */ jsx12(TextPart, {
3388
+ /* @__PURE__ */ jsx13(TextPart, {
3345
3389
  part: part(`label`),
3346
3390
  text: props.label,
3347
3391
  as: "label",
3348
3392
  htmlFor: id
3349
3393
  }),
3350
- /* @__PURE__ */ jsx12("span", {
3394
+ /* @__PURE__ */ jsx13("span", {
3351
3395
  ...part(`value`),
3352
3396
  children: ctx.formatter.number(value)
3353
3397
  })
@@ -3364,13 +3408,13 @@ function SliderNative({ node, props, rootProps, emit, scope }) {
3364
3408
  onValueChange: ([next]) => setValue(next),
3365
3409
  onValueCommit: ([next]) => void emit(`change`, { value: next }, { value: next }),
3366
3410
  children: [
3367
- /* @__PURE__ */ jsx12(SliderPrimitive.Track, {
3411
+ /* @__PURE__ */ jsx13(SliderPrimitive.Track, {
3368
3412
  ...part(`track`),
3369
- children: /* @__PURE__ */ jsx12(SliderPrimitive.Range, {
3413
+ children: /* @__PURE__ */ jsx13(SliderPrimitive.Range, {
3370
3414
  ...part(`range`)
3371
3415
  })
3372
3416
  }),
3373
- /* @__PURE__ */ jsx12(SliderPrimitive.Thumb, {
3417
+ /* @__PURE__ */ jsx13(SliderPrimitive.Thumb, {
3374
3418
  id,
3375
3419
  ...part(`thumb`),
3376
3420
  "aria-label": str(props.label) || undefined
@@ -3387,7 +3431,7 @@ function ComposerNative({ node, props, rootProps, emit, scope, domId }) {
3387
3431
  const external = str(props.value);
3388
3432
  const field = useHostOwnedValue({ external, send, writeLocal });
3389
3433
  const busy = bool(props.busy);
3390
- const ref = useRef14(null);
3434
+ const ref = useRef15(null);
3391
3435
  const grow = () => {
3392
3436
  const el = ref.current;
3393
3437
  if (!el)
@@ -3395,7 +3439,7 @@ function ComposerNative({ node, props, rootProps, emit, scope, domId }) {
3395
3439
  el.style.height = `auto`;
3396
3440
  el.style.height = `${Math.min(200, el.scrollHeight)}px`;
3397
3441
  };
3398
- useEffect10(grow, [field.value]);
3442
+ useEffect11(grow, [field.value]);
3399
3443
  const submit = () => {
3400
3444
  if (busy) {
3401
3445
  emit(`stop`);
@@ -3414,7 +3458,7 @@ function ComposerNative({ node, props, rootProps, emit, scope, domId }) {
3414
3458
  ...rootProps,
3415
3459
  "data-busy": busy ? `true` : undefined,
3416
3460
  children: [
3417
- /* @__PURE__ */ jsx12("textarea", {
3461
+ /* @__PURE__ */ jsx13("textarea", {
3418
3462
  ref,
3419
3463
  ...part(`field`, field.focused && `focus`),
3420
3464
  rows: 1,
@@ -3437,24 +3481,24 @@ function ComposerNative({ node, props, rootProps, emit, scope, domId }) {
3437
3481
  /* @__PURE__ */ jsxs9("div", {
3438
3482
  className: "xui-composer-bar",
3439
3483
  children: [
3440
- bool(props.attachments) ? /* @__PURE__ */ jsx12("button", {
3484
+ bool(props.attachments) ? /* @__PURE__ */ jsx13("button", {
3441
3485
  type: "button",
3442
3486
  ...part(`attachment`),
3443
3487
  "aria-label": ctx.t(`browse`),
3444
3488
  onClick: () => void emit(`attach`),
3445
- children: /* @__PURE__ */ jsx12(BuiltinIcon, {
3489
+ children: /* @__PURE__ */ jsx13(BuiltinIcon, {
3446
3490
  slot: "Composer.attachment"
3447
3491
  })
3448
3492
  }) : null,
3449
- /* @__PURE__ */ jsx12("button", {
3493
+ /* @__PURE__ */ jsx13("button", {
3450
3494
  type: "button",
3451
3495
  ...part(`send`, busy && `pressed`),
3452
3496
  "aria-label": busy ? ctx.t(`stop`) : submitLabel,
3453
3497
  disabled: !busy && field.value.trim() === ``,
3454
3498
  onClick: submit,
3455
- children: busy ? /* @__PURE__ */ jsx12(BuiltinIcon, {
3499
+ children: busy ? /* @__PURE__ */ jsx13(BuiltinIcon, {
3456
3500
  slot: "Composer.stop"
3457
- }) : /* @__PURE__ */ jsx12(BuiltinIcon, {
3501
+ }) : /* @__PURE__ */ jsx13(BuiltinIcon, {
3458
3502
  slot: "Composer.send"
3459
3503
  })
3460
3504
  })
@@ -3465,30 +3509,30 @@ function ComposerNative({ node, props, rootProps, emit, scope, domId }) {
3465
3509
  }
3466
3510
 
3467
3511
  // packages/exponential-ui-react/src/natives/layout.tsx
3468
- import { memo, useCallback as useCallback7, useContext as useContext4, useEffect as useEffect12, useMemo as useMemo12, useRef as useRef16 } from "react";
3512
+ import { memo, useCallback as useCallback7, useContext as useContext4, useEffect as useEffect13, useMemo as useMemo12, useRef as useRef17 } from "react";
3469
3513
  import { listSections, sectionRows, WINDOW_THRESHOLD as CATALOG_WINDOW_THRESHOLD } from "@exponential_app/eui";
3470
3514
  import { getPointer, LITERAL_ROWS_ROOT } from "@exponential_app/eui/web";
3471
3515
 
3472
3516
  // packages/exponential-ui-react/src/list.tsx
3473
- import { forwardRef, useCallback as useCallback6, useEffect as useEffect11, useImperativeHandle, useLayoutEffect as useLayoutEffect4, useMemo as useMemo11, useRef as useRef15, useState as useState13 } from "react";
3517
+ import { forwardRef, useCallback as useCallback6, useEffect as useEffect12, useImperativeHandle, useLayoutEffect as useLayoutEffect5, useMemo as useMemo11, useRef as useRef16, useState as useState13 } from "react";
3474
3518
  import { itemExtents, itemOffsets, scrollOffsetForIndex, stickyHeader, virtualWindow, WINDOW_OVERSCAN } from "@exponential_app/eui";
3475
3519
  import { listViewport as viewportOf, scrollParent } from "@exponential_app/eui/web";
3476
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
3477
- var useIsoLayoutEffect2 = typeof window === `undefined` ? useEffect11 : useLayoutEffect4;
3520
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
3521
+ var useIsoLayoutEffect2 = typeof window === `undefined` ? useEffect12 : useLayoutEffect5;
3478
3522
  var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem, estimatedItemHeight = 40, overscan = WINDOW_OVERSCAN, className, axis = `vertical`, direction = `ltr`, gap = 0, divider, stickyRows, itemProps }, handle) {
3479
- const ref = useRef15(null);
3480
- const extentsByKey = useRef15(new Map);
3481
- const crossByKey = useRef15(new Map);
3482
- const observed = useRef15(new Map);
3483
- const keyOfEl = useRef15(new WeakMap);
3484
- const observer = useRef15(null);
3523
+ const ref = useRef16(null);
3524
+ const extentsByKey = useRef16(new Map);
3525
+ const crossByKey = useRef16(new Map);
3526
+ const observed = useRef16(new Map);
3527
+ const keyOfEl = useRef16(new WeakMap);
3528
+ const observer = useRef16(null);
3485
3529
  const [version, bump] = useState13(0);
3486
3530
  const [view, setView] = useState13(null);
3487
3531
  const horizontal = axis === `horizontal`;
3488
3532
  const rtl = horizontal && direction === `rtl`;
3489
3533
  const estimate = useCallback6((i) => typeof estimatedItemHeight === `function` ? estimatedItemHeight(i) : estimatedItemHeight, [estimatedItemHeight]);
3490
- const measured = useRef15(0);
3491
- const extentsCache = useRef15(null);
3534
+ const measured = useRef16(0);
3535
+ const extentsCache = useRef16(null);
3492
3536
  const extents = () => {
3493
3537
  const c = extentsCache.current;
3494
3538
  if (c && c.count === count && c.itemKey === itemKey && c.estimate === estimatedItemHeight && c.measured === measured.current)
@@ -3504,7 +3548,7 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3504
3548
  extentsCache.current = { count, itemKey, estimate: estimatedItemHeight, measured: measured.current, ext };
3505
3549
  return ext;
3506
3550
  };
3507
- useEffect11(() => {
3551
+ useEffect12(() => {
3508
3552
  if (typeof ResizeObserver === `undefined`)
3509
3553
  return;
3510
3554
  const ro = new ResizeObserver((entries) => {
@@ -3593,7 +3637,7 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3593
3637
  const win = virtualWindow(ext, gap, scroll, viewport, overscan);
3594
3638
  const headers = useMemo11(() => [...stickyRows ?? []].filter((r) => r >= 0 && r < count).sort((a, b) => a - b), [stickyRows, count]);
3595
3639
  const pinned = headers.length && scroll >= 0 ? stickyHeader(off, ext, headers, scroll) : null;
3596
- const pending = useRef15(null);
3640
+ const pending = useRef16(null);
3597
3641
  const jump = (index, align) => {
3598
3642
  const el = ref.current;
3599
3643
  if (!el || index < 0 || index >= count)
@@ -3616,7 +3660,7 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3616
3660
  window.scrollBy(by);
3617
3661
  return true;
3618
3662
  };
3619
- useEffect11(() => {
3663
+ useEffect12(() => {
3620
3664
  const p = pending.current;
3621
3665
  if (!p)
3622
3666
  return;
@@ -3625,7 +3669,7 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3625
3669
  else
3626
3670
  jump(p.index, p.align);
3627
3671
  });
3628
- useEffect11(() => {
3672
+ useEffect12(() => {
3629
3673
  const target = scroller ?? window;
3630
3674
  const cancel = () => {
3631
3675
  pending.current = null;
@@ -3666,7 +3710,7 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3666
3710
  ...itemProps?.(i) ?? {},
3667
3711
  style: { ...place(at), ...isPinned ? { zIndex: 1 } : {} },
3668
3712
  children: [
3669
- line ? /* @__PURE__ */ jsx13("div", {
3713
+ line ? /* @__PURE__ */ jsx14("div", {
3670
3714
  className: "xui-list-gap",
3671
3715
  "aria-hidden": "true",
3672
3716
  "data-axis": axis,
@@ -3678,7 +3722,7 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3678
3722
  }, key);
3679
3723
  });
3680
3724
  const spacer = horizontal ? { width: total, height: cross || undefined } : { height: total };
3681
- return /* @__PURE__ */ jsx13("div", {
3725
+ return /* @__PURE__ */ jsx14("div", {
3682
3726
  ref,
3683
3727
  className: className ? `xui-list-window ${className}` : `xui-list-window`,
3684
3728
  "data-axis": axis,
@@ -3690,11 +3734,11 @@ var WindowedList = forwardRef(function WindowedList({ count, itemKey, renderItem
3690
3734
  });
3691
3735
 
3692
3736
  // packages/exponential-ui-react/src/natives/layout.tsx
3693
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
3737
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
3694
3738
  function BoxNative({ node, props, rootProps, emit, children }) {
3695
3739
  const pressable = bool(props.pressable) || Boolean(node.on?.press);
3696
3740
  if (!pressable)
3697
- return /* @__PURE__ */ jsx14("div", {
3741
+ return /* @__PURE__ */ jsx15("div", {
3698
3742
  ...rootProps,
3699
3743
  children
3700
3744
  });
@@ -3706,7 +3750,7 @@ function BoxNative({ node, props, rootProps, emit, children }) {
3706
3750
  emit(`press`);
3707
3751
  }
3708
3752
  };
3709
- return /* @__PURE__ */ jsx14("div", {
3753
+ return /* @__PURE__ */ jsx15("div", {
3710
3754
  ...rootProps,
3711
3755
  "data-pressable": "true",
3712
3756
  role: "button",
@@ -3763,10 +3807,10 @@ function ListNative({ node, props, rootProps, scope, domId }) {
3763
3807
  const prev = rows[r - 1];
3764
3808
  return `item` in row && `item` in prev ? row.item : null;
3765
3809
  };
3766
- const windowRef = useRef16(null);
3767
- const rootRef = useRef16(null);
3810
+ const windowRef = useRef17(null);
3811
+ const rootRef = useRef17(null);
3768
3812
  const rowOfIndex = useCallback7((index) => rows.findIndex((r) => (`item` in r) && r.item === (tpl ? childCount + index : index)), [rows, tpl, childCount]);
3769
- useEffect12(() => ctx.registerScroller(domId, (index, align) => {
3813
+ useEffect13(() => ctx.registerScroller(domId, (index, align) => {
3770
3814
  const r = rowOfIndex(index);
3771
3815
  if (r < 0)
3772
3816
  return;
@@ -3778,7 +3822,7 @@ function ListNative({ node, props, rootProps, scope, domId }) {
3778
3822
  el?.scrollIntoView(horizontal ? { inline: block, block: `nearest` } : { block, inline: `nearest` });
3779
3823
  }
3780
3824
  }), [ctx, domId, rowOfIndex, windowed, horizontal]);
3781
- const renderRow = (r) => /* @__PURE__ */ jsx14(ListRowView, {
3825
+ const renderRow = (r) => /* @__PURE__ */ jsx15(ListRowView, {
3782
3826
  row: rows[r],
3783
3827
  node,
3784
3828
  tpl,
@@ -3794,19 +3838,19 @@ function ListNative({ node, props, rootProps, scope, domId }) {
3794
3838
  };
3795
3839
  const divider = (r) => {
3796
3840
  const before = dividerBefore(r);
3797
- return before === null ? null : /* @__PURE__ */ jsx14("div", {
3841
+ return before === null ? null : /* @__PURE__ */ jsx15("div", {
3798
3842
  ...part.at(`divider`, before),
3799
3843
  role: "separator"
3800
3844
  });
3801
3845
  };
3802
3846
  if (windowed) {
3803
3847
  const headerRows = sticky ? rows.flatMap((row, r) => (`header` in row) ? [r] : []) : undefined;
3804
- return /* @__PURE__ */ jsx14("div", {
3848
+ return /* @__PURE__ */ jsx15("div", {
3805
3849
  ref: rootRef,
3806
3850
  ...rootProps,
3807
3851
  style,
3808
3852
  role: listRole,
3809
- children: /* @__PURE__ */ jsx14(WindowedList, {
3853
+ children: /* @__PURE__ */ jsx15(WindowedList, {
3810
3854
  ref: windowRef,
3811
3855
  count: rows.length,
3812
3856
  itemKey: keyOf,
@@ -3831,7 +3875,7 @@ function ListNative({ node, props, rootProps, scope, domId }) {
3831
3875
  "data-xui-row": r,
3832
3876
  ...itemAttrs(r),
3833
3877
  children: [
3834
- line ? /* @__PURE__ */ jsx14("div", {
3878
+ line ? /* @__PURE__ */ jsx15("div", {
3835
3879
  className: "xui-list-gap",
3836
3880
  "aria-hidden": "true",
3837
3881
  "data-axis": axis,
@@ -3842,7 +3886,7 @@ function ListNative({ node, props, rootProps, scope, domId }) {
3842
3886
  ]
3843
3887
  }, keyOf(r)));
3844
3888
  }
3845
- return /* @__PURE__ */ jsx14("div", {
3889
+ return /* @__PURE__ */ jsx15("div", {
3846
3890
  ref: rootRef,
3847
3891
  ...rootProps,
3848
3892
  style,
@@ -3855,11 +3899,11 @@ var ListRowView = memo(function ListRowView({ row, node, tpl, sections, childCou
3855
3899
  const section = sections?.[row.header];
3856
3900
  if (!section)
3857
3901
  return null;
3858
- return /* @__PURE__ */ jsx14("div", {
3902
+ return /* @__PURE__ */ jsx15("div", {
3859
3903
  ...part.at(`section`, row.header),
3860
3904
  role: "heading",
3861
3905
  "aria-level": 3,
3862
- children: node.slots?.section ? /* @__PURE__ */ jsx14(LiteralScope, {
3906
+ children: node.slots?.section ? /* @__PURE__ */ jsx15(LiteralScope, {
3863
3907
  value: { value: section.value, count: section.count, index: row.header },
3864
3908
  pointer: `${LITERAL_ROWS_ROOT}/${node.id.replace(/[~/]/g, `_`)}/sections/${row.header}`,
3865
3909
  suffix: `.${row.header}`,
@@ -3868,13 +3912,13 @@ var ListRowView = memo(function ListRowView({ row, node, tpl, sections, childCou
3868
3912
  });
3869
3913
  }
3870
3914
  if (row.item < childCount)
3871
- return /* @__PURE__ */ jsx14(NodeView, {
3915
+ return /* @__PURE__ */ jsx15(NodeView, {
3872
3916
  node: node.children[row.item]
3873
3917
  });
3874
3918
  const item = tpl?.items[row.item - childCount];
3875
3919
  if (!tpl || !item)
3876
3920
  return null;
3877
- return /* @__PURE__ */ jsx14(TemplateItemView, {
3921
+ return /* @__PURE__ */ jsx15(TemplateItemView, {
3878
3922
  tpl: tpl.tpl,
3879
3923
  item
3880
3924
  });
@@ -3890,13 +3934,13 @@ function LiteralScope({ value, pointer, suffix, node }) {
3890
3934
  };
3891
3935
  return deriveContext(ctx, { setData }, data);
3892
3936
  }, [ctx, pointer, value]);
3893
- return /* @__PURE__ */ jsx14(SurfaceContext.Provider, {
3937
+ return /* @__PURE__ */ jsx15(SurfaceContext.Provider, {
3894
3938
  value: view,
3895
- children: /* @__PURE__ */ jsx14(ScopeContext.Provider, {
3939
+ children: /* @__PURE__ */ jsx15(ScopeContext.Provider, {
3896
3940
  value: pointer,
3897
- children: /* @__PURE__ */ jsx14(InstanceContext.Provider, {
3941
+ children: /* @__PURE__ */ jsx15(InstanceContext.Provider, {
3898
3942
  value: `${outer}${suffix}`,
3899
- children: /* @__PURE__ */ jsx14(NodeView, {
3943
+ children: /* @__PURE__ */ jsx15(NodeView, {
3900
3944
  node
3901
3945
  })
3902
3946
  })
@@ -3911,7 +3955,7 @@ function UnknownNative({ node, props, rootProps }) {
3911
3955
  role: "note",
3912
3956
  "data-xui-unknown": str(props.component, node.component),
3913
3957
  children: [
3914
- /* @__PURE__ */ jsx14(BuiltinIcon, {
3958
+ /* @__PURE__ */ jsx15(BuiltinIcon, {
3915
3959
  slot: "Unknown.root",
3916
3960
  size: 16
3917
3961
  }),
@@ -3928,12 +3972,13 @@ function UnknownNative({ node, props, rootProps }) {
3928
3972
  }
3929
3973
 
3930
3974
  // packages/exponential-ui-react/src/natives/media.tsx
3931
- import { useEffect as useEffect13, useRef as useRef17, useState as useState14 } from "react";
3975
+ import { useEffect as useEffect14, useRef as useRef18, useState as useState14 } from "react";
3932
3976
  import { Avatar as AvatarPrimitive } from "radix-ui";
3933
3977
  import { MEDIA_ASPECT_RATIO, MEDIA_INTRINSIC_WIDTH } from "@exponential_app/eui";
3934
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
3978
+ import { mediaClock } from "@exponential_app/eui/web";
3979
+ import { jsx as jsx16, jsxs as jsxs12, Fragment as Fragment2 } from "react/jsx-runtime";
3935
3980
  function MediaSizer() {
3936
- return /* @__PURE__ */ jsx15("svg", {
3981
+ return /* @__PURE__ */ jsx16("svg", {
3937
3982
  className: "xui-media-sizer",
3938
3983
  "aria-hidden": "true",
3939
3984
  width: MEDIA_INTRINSIC_WIDTH,
@@ -3948,7 +3993,7 @@ function ImageNative({ node, props, rootProps }) {
3948
3993
  const alt = str(props.alt);
3949
3994
  const fit = str(props.fit, `cover`);
3950
3995
  const [state, setState] = useState14(`loading`);
3951
- useEffect13(() => setState(`loading`), [src]);
3996
+ useEffect14(() => setState(`loading`), [src]);
3952
3997
  const style = {};
3953
3998
  if (props.width !== undefined)
3954
3999
  style.width = num(props.width);
@@ -3973,7 +4018,7 @@ function ImageNative({ node, props, rootProps }) {
3973
4018
  "aria-label": failed ? alt : undefined,
3974
4019
  "data-state": src ? shown : `empty`,
3975
4020
  children: [
3976
- src && url && shown !== `error` ? /* @__PURE__ */ jsx15("img", {
4021
+ src && url && shown !== `error` ? /* @__PURE__ */ jsx16("img", {
3977
4022
  src: url,
3978
4023
  alt,
3979
4024
  loading: props.loading === `eager` ? `eager` : `lazy`,
@@ -3982,14 +4027,14 @@ function ImageNative({ node, props, rootProps }) {
3982
4027
  onLoad: () => setState(`loaded`),
3983
4028
  onError: () => setState(`error`)
3984
4029
  }) : null,
3985
- /* @__PURE__ */ jsx15(MediaSizer, {}),
3986
- failed ? /* @__PURE__ */ jsx15("div", {
4030
+ /* @__PURE__ */ jsx16(MediaSizer, {}),
4031
+ failed ? /* @__PURE__ */ jsx16("div", {
3987
4032
  ...part(`fallback`),
3988
4033
  "aria-hidden": "true",
3989
- children: fallback ? /* @__PURE__ */ jsx15(IconGlyph, {
4034
+ children: fallback ? /* @__PURE__ */ jsx16(IconGlyph, {
3990
4035
  icons: ctx.host.icons,
3991
4036
  name: fallback
3992
- }) : /* @__PURE__ */ jsx15(BuiltinIcon, {
4037
+ }) : /* @__PURE__ */ jsx16(BuiltinIcon, {
3993
4038
  slot: "Image.fallback"
3994
4039
  })
3995
4040
  }) : null
@@ -4001,24 +4046,54 @@ function VideoNative({ node, props, rootProps }) {
4001
4046
  const part = useParts(node, props);
4002
4047
  const src = str(props.src);
4003
4048
  const poster = str(props.poster);
4049
+ const autoplay = bool(props.autoplay);
4050
+ const [started, setStarted] = useState14(false);
4004
4051
  const url = useMediaSrc(ctx.host, src, `stream`);
4005
4052
  const posterUrl = useMediaSrc(ctx.host, poster);
4006
4053
  const ratio = num(props.aspectRatio, MEDIA_ASPECT_RATIO) || MEDIA_ASPECT_RATIO;
4054
+ const durationMs = props.durationMs !== undefined ? num(props.durationMs) : undefined;
4055
+ const Play = CHROME.play;
4007
4056
  return /* @__PURE__ */ jsxs12("div", {
4008
4057
  ...rootProps,
4009
4058
  style: mergeStyle(rootProps, { aspectRatio: String(ratio) }),
4010
4059
  children: [
4011
- /* @__PURE__ */ jsx15(MediaSizer, {}),
4012
- /* @__PURE__ */ jsx15("video", {
4060
+ /* @__PURE__ */ jsx16(MediaSizer, {}),
4061
+ started || autoplay ? /* @__PURE__ */ jsx16("video", {
4013
4062
  ...part(`controls`),
4014
4063
  src: url,
4015
4064
  poster: posterUrl,
4016
4065
  controls: true,
4017
- autoPlay: bool(props.autoplay),
4018
- muted: bool(props.autoplay),
4066
+ autoPlay: true,
4067
+ muted: autoplay && !started,
4019
4068
  playsInline: true,
4020
4069
  preload: "metadata",
4021
- "data-duration-ms": props.durationMs !== undefined ? num(props.durationMs) : undefined
4070
+ "data-duration-ms": durationMs
4071
+ }) : /* @__PURE__ */ jsxs12(Fragment2, {
4072
+ children: [
4073
+ posterUrl ? /* @__PURE__ */ jsx16("img", {
4074
+ className: "xui-video-poster",
4075
+ src: posterUrl,
4076
+ alt: "",
4077
+ "aria-hidden": "true",
4078
+ decoding: "async",
4079
+ draggable: false
4080
+ }) : null,
4081
+ /* @__PURE__ */ jsx16("button", {
4082
+ type: "button",
4083
+ className: "xui-media-play",
4084
+ "data-size": "lg",
4085
+ "aria-label": ctx.t(`play`),
4086
+ disabled: !url,
4087
+ onClick: () => setStarted(true),
4088
+ children: /* @__PURE__ */ jsx16(Play, {
4089
+ "aria-hidden": "true"
4090
+ })
4091
+ }),
4092
+ durationMs !== undefined ? /* @__PURE__ */ jsx16("span", {
4093
+ className: "xui-video-duration",
4094
+ children: mediaClock(durationMs)
4095
+ }) : null
4096
+ ]
4022
4097
  })
4023
4098
  ]
4024
4099
  });
@@ -4029,21 +4104,67 @@ function AudioPlayerNative({ node, props, rootProps }) {
4029
4104
  const src = str(props.src);
4030
4105
  const title = str(props.title);
4031
4106
  const url = useMediaSrc(ctx.host, src, `stream`);
4107
+ const audio = useRef18(null);
4108
+ const [playing, setPlaying] = useState14(false);
4109
+ const [position, setPosition] = useState14(0);
4110
+ const [loadedMs, setLoadedMs] = useState14(null);
4111
+ const durationMs = props.durationMs !== undefined ? num(props.durationMs) : loadedMs ?? 0;
4112
+ const Glyph = playing ? CHROME.pause : CHROME.play;
4113
+ const toggle = () => {
4114
+ const el = audio.current;
4115
+ if (!el)
4116
+ return;
4117
+ if (el.paused)
4118
+ el.play()?.catch(() => setPlaying(false));
4119
+ else
4120
+ el.pause();
4121
+ };
4032
4122
  return /* @__PURE__ */ jsxs12("div", {
4033
4123
  ...rootProps,
4034
4124
  style: mergeStyle(rootProps, { flexDirection: `column`, gap: `var(--xui-spacing-xs)` }),
4035
4125
  children: [
4036
- title ? /* @__PURE__ */ jsx15("span", {
4126
+ title ? /* @__PURE__ */ jsx16("span", {
4037
4127
  ...part(`track`),
4038
4128
  children: title
4039
4129
  }) : null,
4040
- /* @__PURE__ */ jsx15("audio", {
4130
+ /* @__PURE__ */ jsxs12("div", {
4041
4131
  ...part(`controls`),
4132
+ "data-duration-ms": props.durationMs !== undefined ? num(props.durationMs) : undefined,
4133
+ children: [
4134
+ /* @__PURE__ */ jsx16("button", {
4135
+ type: "button",
4136
+ className: "xui-media-play",
4137
+ "data-size": "sm",
4138
+ "aria-label": ctx.t(playing ? `pause` : `play`),
4139
+ disabled: !url,
4140
+ onClick: toggle,
4141
+ children: /* @__PURE__ */ jsx16(Glyph, {
4142
+ "aria-hidden": "true"
4143
+ })
4144
+ }),
4145
+ /* @__PURE__ */ jsx16("span", {
4146
+ className: "xui-audio-progress",
4147
+ "aria-hidden": "true",
4148
+ children: /* @__PURE__ */ jsx16("span", {
4149
+ style: { width: `${durationMs > 0 ? Math.min(100, position / durationMs * 100) : 0}%` }
4150
+ })
4151
+ }),
4152
+ /* @__PURE__ */ jsx16("span", {
4153
+ className: "xui-audio-clock",
4154
+ children: `${mediaClock(position)} / ${mediaClock(durationMs)}`
4155
+ })
4156
+ ]
4157
+ }),
4158
+ /* @__PURE__ */ jsx16("audio", {
4159
+ ref: audio,
4042
4160
  src: url,
4043
- controls: true,
4044
4161
  preload: "metadata",
4045
4162
  "aria-label": title || undefined,
4046
- "data-duration-ms": props.durationMs !== undefined ? num(props.durationMs) : undefined
4163
+ onPlay: () => setPlaying(true),
4164
+ onPause: () => setPlaying(false),
4165
+ onEnded: () => setPlaying(false),
4166
+ onTimeUpdate: (e) => setPosition(e.currentTarget.currentTime * 1000),
4167
+ onLoadedMetadata: (e) => setLoadedMs(Number.isFinite(e.currentTarget.duration) ? e.currentTarget.duration * 1000 : null)
4047
4168
  })
4048
4169
  ]
4049
4170
  });
@@ -4071,12 +4192,12 @@ function AvatarNative({ node, props, rootProps }) {
4071
4192
  "aria-label": name || undefined,
4072
4193
  role: "img",
4073
4194
  children: [
4074
- src ? /* @__PURE__ */ jsx15(AvatarPrimitive.Image, {
4195
+ src ? /* @__PURE__ */ jsx16(AvatarPrimitive.Image, {
4075
4196
  ...part(`image`),
4076
4197
  src: url,
4077
4198
  alt: name
4078
4199
  }) : null,
4079
- /* @__PURE__ */ jsx15(AvatarPrimitive.Fallback, {
4200
+ /* @__PURE__ */ jsx16(AvatarPrimitive.Fallback, {
4080
4201
  ...part(`fallback`),
4081
4202
  delayMs: src ? 300 : undefined,
4082
4203
  style: tint,
@@ -4088,28 +4209,39 @@ function AvatarNative({ node, props, rootProps }) {
4088
4209
  function CarouselThumbnail({ attrs, src, current, label, onPress }) {
4089
4210
  const ctx = useSurfaceContext();
4090
4211
  const url = useMediaSrc(ctx.host, src);
4091
- return /* @__PURE__ */ jsx15("button", {
4212
+ const [broken, setBroken] = useState14(null);
4213
+ return /* @__PURE__ */ jsxs12("button", {
4092
4214
  type: "button",
4093
4215
  ...attrs,
4094
4216
  "aria-label": label,
4095
4217
  "aria-current": current ? `true` : undefined,
4096
4218
  "data-current": current ? `true` : undefined,
4097
4219
  onClick: onPress,
4098
- children: src && url ? /* @__PURE__ */ jsx15("img", {
4099
- className: "xui-carousel-thumb",
4100
- src: url,
4101
- alt: "",
4102
- "aria-hidden": "true",
4103
- loading: "lazy",
4104
- decoding: "async",
4105
- draggable: false
4106
- }) : null
4220
+ children: [
4221
+ /* @__PURE__ */ jsx16("span", {
4222
+ className: "xui-carousel-thumb-fallback",
4223
+ "aria-hidden": "true",
4224
+ children: /* @__PURE__ */ jsx16(BuiltinIcon, {
4225
+ slot: "Image.fallback"
4226
+ })
4227
+ }),
4228
+ src && url && broken !== url ? /* @__PURE__ */ jsx16("img", {
4229
+ className: "xui-carousel-thumb",
4230
+ src: url,
4231
+ alt: "",
4232
+ "aria-hidden": "true",
4233
+ loading: "lazy",
4234
+ decoding: "async",
4235
+ draggable: false,
4236
+ onError: () => setBroken(url)
4237
+ }) : null
4238
+ ]
4107
4239
  });
4108
4240
  }
4109
4241
  function CarouselNative({ node, props, rootProps, emit, scope }) {
4110
4242
  const ctx = useSurfaceContext();
4111
4243
  const part = useParts(node, props);
4112
- const track = useRef17(null);
4244
+ const track = useRef18(null);
4113
4245
  const pages = node.children;
4114
4246
  const [page, setPage] = useBoundState(node, scope, `page`, num(props.page, 0));
4115
4247
  const scrollTo = (i) => {
@@ -4118,7 +4250,7 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4118
4250
  el.scrollTo({ left: el.children[i].offsetLeft, behavior: ctx.reducedMotion ? `auto` : `smooth` });
4119
4251
  };
4120
4252
  const external = num(props.page, 0);
4121
- useEffect13(() => scrollTo(external), [external]);
4253
+ useEffect14(() => scrollTo(external), [external]);
4122
4254
  const onScroll = () => {
4123
4255
  const el = track.current;
4124
4256
  if (!el || el.clientWidth === 0)
@@ -4141,8 +4273,8 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4141
4273
  const many = pages.length > 1;
4142
4274
  const counter = many && bool(props.counter);
4143
4275
  const thumbnails = many && Array.isArray(props.thumbnails) ? props.thumbnails : null;
4144
- const strip = useRef17(null);
4145
- useEffect13(() => {
4276
+ const strip = useRef18(null);
4277
+ useEffect14(() => {
4146
4278
  const el = strip.current;
4147
4279
  const thumb = el?.children[page];
4148
4280
  if (!el || !thumb)
@@ -4153,7 +4285,7 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4153
4285
  if (delta !== 0)
4154
4286
  el.scrollLeft += delta;
4155
4287
  }, [page, thumbnails !== null]);
4156
- const trackView = /* @__PURE__ */ jsx15("div", {
4288
+ const trackView = /* @__PURE__ */ jsx16("div", {
4157
4289
  ref: track,
4158
4290
  className: "xui-carousel-track",
4159
4291
  onScroll,
@@ -4163,7 +4295,7 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4163
4295
  const attrs = part(`page`, active && `selected`);
4164
4296
  if (!active)
4165
4297
  delete attrs[`data-xui-id`];
4166
- return /* @__PURE__ */ jsx15("div", {
4298
+ return /* @__PURE__ */ jsx16("div", {
4167
4299
  ...attrs,
4168
4300
  role: "group",
4169
4301
  "aria-roledescription": ctx.t(`slide`),
@@ -4171,7 +4303,7 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4171
4303
  "aria-hidden": active ? undefined : true,
4172
4304
  "data-xui-inactive": active ? undefined : ``,
4173
4305
  ...active ? {} : INERT,
4174
- children: /* @__PURE__ */ jsx15(NodeView, {
4306
+ children: /* @__PURE__ */ jsx16(NodeView, {
4175
4307
  node: child
4176
4308
  })
4177
4309
  }, child.id);
@@ -4193,17 +4325,17 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4193
4325
  className: "xui-carousel-stage",
4194
4326
  children: [
4195
4327
  trackView,
4196
- /* @__PURE__ */ jsx15("span", {
4328
+ /* @__PURE__ */ jsx16("span", {
4197
4329
  ...part(`counter`),
4198
4330
  "aria-hidden": "true",
4199
4331
  children: ctx.t(`pageCounter`, { page: page + 1, total: pages.length })
4200
4332
  })
4201
4333
  ]
4202
4334
  }) : trackView,
4203
- thumbnails ? /* @__PURE__ */ jsx15("div", {
4335
+ thumbnails ? /* @__PURE__ */ jsx16("div", {
4204
4336
  ref: strip,
4205
4337
  ...part(`thumbnails`),
4206
- children: pages.map((child, i) => /* @__PURE__ */ jsx15(CarouselThumbnail, {
4338
+ children: pages.map((child, i) => /* @__PURE__ */ jsx16(CarouselThumbnail, {
4207
4339
  attrs: part.at(`thumbnail`, i, i === page && `selected`),
4208
4340
  src: typeof thumbnails[i] === `string` ? thumbnails[i] : ``,
4209
4341
  current: i === page,
@@ -4214,22 +4346,22 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4214
4346
  many ? /* @__PURE__ */ jsxs12("div", {
4215
4347
  ...withClass(part(`controls`), `xui-carousel-controls`),
4216
4348
  children: [
4217
- /* @__PURE__ */ jsx15("button", {
4349
+ /* @__PURE__ */ jsx16("button", {
4218
4350
  type: "button",
4219
4351
  ...withClass(part(`previous`), `xui-carousel-nav`),
4220
4352
  "aria-label": ctx.t(`previous`),
4221
4353
  disabled: !bool(props.loop) && page === 0,
4222
4354
  onClick: () => go(page - 1),
4223
- children: /* @__PURE__ */ jsx15(BuiltinIcon, {
4355
+ children: /* @__PURE__ */ jsx16(BuiltinIcon, {
4224
4356
  slot: "Carousel.previous"
4225
4357
  })
4226
4358
  }),
4227
- props.indicators !== false ? /* @__PURE__ */ jsx15("div", {
4359
+ props.indicators !== false ? /* @__PURE__ */ jsx16("div", {
4228
4360
  ...part(`indicator`),
4229
4361
  className: "xui-carousel-dots",
4230
4362
  "data-xui-part": "Carousel/indicators",
4231
4363
  role: "tablist",
4232
- children: pages.map((child, i) => /* @__PURE__ */ jsx15("button", {
4364
+ children: pages.map((child, i) => /* @__PURE__ */ jsx16("button", {
4233
4365
  type: "button",
4234
4366
  ...part(`indicator`, i === page && `selected`),
4235
4367
  "data-xui-id": undefined,
@@ -4239,13 +4371,13 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4239
4371
  onClick: () => go(i)
4240
4372
  }, child.id))
4241
4373
  }) : null,
4242
- /* @__PURE__ */ jsx15("button", {
4374
+ /* @__PURE__ */ jsx16("button", {
4243
4375
  type: "button",
4244
4376
  ...withClass(part(`next`), `xui-carousel-nav`),
4245
4377
  "aria-label": ctx.t(`next`),
4246
4378
  disabled: !bool(props.loop) && page === pages.length - 1,
4247
4379
  onClick: () => go(page + 1),
4248
- children: /* @__PURE__ */ jsx15(BuiltinIcon, {
4380
+ children: /* @__PURE__ */ jsx16(BuiltinIcon, {
4249
4381
  slot: "Carousel.next"
4250
4382
  })
4251
4383
  })
@@ -4256,10 +4388,10 @@ function CarouselNative({ node, props, rootProps, emit, scope }) {
4256
4388
  }
4257
4389
 
4258
4390
  // packages/exponential-ui-react/src/natives/nav.tsx
4259
- import { Fragment as Fragment2, useRef as useRef18, useState as useState15 } from "react";
4391
+ import { Fragment as Fragment3, useRef as useRef19, useState as useState15 } from "react";
4260
4392
  import { Accordion as AccordionPrimitive, Tabs as TabsPrimitive, ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
4261
4393
  import { segmentedBadge } from "@exponential_app/eui/web";
4262
- import { jsx as jsx16, jsxs as jsxs13, Fragment as Fragment3 } from "react/jsx-runtime";
4394
+ import { jsx as jsx17, jsxs as jsxs13, Fragment as Fragment4 } from "react/jsx-runtime";
4263
4395
  function TabsNative({ node, props, rootProps, emit, scope }) {
4264
4396
  const ctx = useSurfaceContext();
4265
4397
  const part = useParts(node, props);
@@ -4300,23 +4432,23 @@ function TabsNative({ node, props, rootProps, emit, scope }) {
4300
4432
  /* @__PURE__ */ jsxs13("span", {
4301
4433
  className: "xui-Tabs-tab-body",
4302
4434
  children: [
4303
- tab.icon ? /* @__PURE__ */ jsx16(IconGlyph, {
4435
+ tab.icon ? /* @__PURE__ */ jsx17(IconGlyph, {
4304
4436
  icons: ctx.host.icons,
4305
4437
  name: tab.icon,
4306
4438
  className: "xui-icon",
4307
4439
  width: 16,
4308
4440
  height: 16
4309
4441
  }) : null,
4310
- /* @__PURE__ */ jsx16("span", {
4442
+ /* @__PURE__ */ jsx17("span", {
4311
4443
  children: str(tab.label)
4312
4444
  }),
4313
- tab.count !== undefined ? /* @__PURE__ */ jsx16("span", {
4445
+ tab.count !== undefined ? /* @__PURE__ */ jsx17("span", {
4314
4446
  "data-count": "",
4315
4447
  children: ctx.formatter.number(num(tab.count))
4316
4448
  }) : null
4317
4449
  ]
4318
4450
  }),
4319
- /* @__PURE__ */ jsx16("span", {
4451
+ /* @__PURE__ */ jsx17("span", {
4320
4452
  ...part(`indicator`, selected && `selected`),
4321
4453
  "aria-hidden": "true"
4322
4454
  })
@@ -4324,29 +4456,29 @@ function TabsNative({ node, props, rootProps, emit, scope }) {
4324
4456
  }, tab.value);
4325
4457
  if (!closable)
4326
4458
  return trigger;
4327
- return /* @__PURE__ */ jsxs13(Fragment2, {
4459
+ return /* @__PURE__ */ jsxs13(Fragment3, {
4328
4460
  children: [
4329
4461
  trigger,
4330
- /* @__PURE__ */ jsx16("button", {
4462
+ /* @__PURE__ */ jsx17("button", {
4331
4463
  type: "button",
4332
4464
  ...part.at(`close`, i, lent?.index === i && lent.state),
4333
4465
  "aria-label": ctx.t(`closeTab`, { name: str(tab.label) }),
4334
4466
  onPointerEnter: lending ? () => lend(i, `hover`) : undefined,
4335
4467
  onPointerLeave: lending ? () => lend(i, null) : undefined,
4336
4468
  onClick: () => void emit(`close`, { value: tab.value }),
4337
- children: /* @__PURE__ */ jsx16(BuiltinIcon, {
4469
+ children: /* @__PURE__ */ jsx17(BuiltinIcon, {
4338
4470
  slot: "Tabs.close"
4339
4471
  })
4340
4472
  })
4341
4473
  ]
4342
4474
  }, tab.value);
4343
4475
  }),
4344
- bool(props.addable) ? /* @__PURE__ */ jsx16("button", {
4476
+ bool(props.addable) ? /* @__PURE__ */ jsx17("button", {
4345
4477
  type: "button",
4346
4478
  ...part(`new`),
4347
4479
  "aria-label": ctx.t(`newTab`),
4348
4480
  onClick: () => void emit(`new`),
4349
- children: /* @__PURE__ */ jsx16(BuiltinIcon, {
4481
+ children: /* @__PURE__ */ jsx17(BuiltinIcon, {
4350
4482
  slot: "Tabs.new"
4351
4483
  })
4352
4484
  }) : null
@@ -4356,10 +4488,10 @@ function TabsNative({ node, props, rootProps, emit, scope }) {
4356
4488
  const attrs = part(`content`);
4357
4489
  if (tab.value !== value)
4358
4490
  delete attrs[`data-xui-id`];
4359
- return /* @__PURE__ */ jsx16(TabsPrimitive.Content, {
4491
+ return /* @__PURE__ */ jsx17(TabsPrimitive.Content, {
4360
4492
  value: tab.value,
4361
4493
  ...attrs,
4362
- children: node.children[i] ? /* @__PURE__ */ jsx16(NodeView, {
4494
+ children: node.children[i] ? /* @__PURE__ */ jsx17(NodeView, {
4363
4495
  node: node.children[i]
4364
4496
  }) : null
4365
4497
  }, tab.value);
@@ -4383,26 +4515,26 @@ function SegmentedNative({ node, props, rootProps, emit, scope }) {
4383
4515
  const isSelected = (item) => multiple ? asArray(value).includes(item.value) : value === item.value;
4384
4516
  const content = (item, selected) => {
4385
4517
  const badge = bar ? segmentedBadge(item.count) : null;
4386
- return /* @__PURE__ */ jsxs13(Fragment3, {
4518
+ return /* @__PURE__ */ jsxs13(Fragment4, {
4387
4519
  children: [
4388
4520
  item.icon ? /* @__PURE__ */ jsxs13("span", {
4389
4521
  ...part(`icon`, selected && `selected`),
4390
4522
  "aria-hidden": "true",
4391
4523
  children: [
4392
- /* @__PURE__ */ jsx16(IconGlyph, {
4524
+ /* @__PURE__ */ jsx17(IconGlyph, {
4393
4525
  icons: ctx.host.icons,
4394
4526
  name: item.icon,
4395
4527
  className: "xui-icon",
4396
4528
  width: bar ? 20 : 16,
4397
4529
  height: bar ? 20 : 16
4398
4530
  }),
4399
- badge ? /* @__PURE__ */ jsx16("span", {
4531
+ badge ? /* @__PURE__ */ jsx17("span", {
4400
4532
  ...part(`badge`, selected && `selected`),
4401
4533
  children: badge
4402
4534
  }) : null
4403
4535
  ]
4404
4536
  }) : null,
4405
- item.label ? /* @__PURE__ */ jsx16("span", {
4537
+ item.label ? /* @__PURE__ */ jsx17("span", {
4406
4538
  ...part(`label`, selected && `selected`),
4407
4539
  children: str(item.label)
4408
4540
  }) : null
@@ -4410,7 +4542,7 @@ function SegmentedNative({ node, props, rootProps, emit, scope }) {
4410
4542
  });
4411
4543
  };
4412
4544
  if (bar)
4413
- return /* @__PURE__ */ jsx16(SegmentedBar, {
4545
+ return /* @__PURE__ */ jsx17(SegmentedBar, {
4414
4546
  node,
4415
4547
  rootProps,
4416
4548
  vertical,
@@ -4425,7 +4557,7 @@ function SegmentedNative({ node, props, rootProps, emit, scope }) {
4425
4557
  });
4426
4558
  const body = items.map((item) => {
4427
4559
  const selected = isSelected(item);
4428
- return /* @__PURE__ */ jsx16(ToggleGroupPrimitive.Item, {
4560
+ return /* @__PURE__ */ jsx17(ToggleGroupPrimitive.Item, {
4429
4561
  value: item.value,
4430
4562
  disabled: bool(item.disabled),
4431
4563
  "aria-label": item.label ? undefined : item.value,
@@ -4434,7 +4566,7 @@ function SegmentedNative({ node, props, rootProps, emit, scope }) {
4434
4566
  }, item.value);
4435
4567
  });
4436
4568
  if (multiple) {
4437
- return /* @__PURE__ */ jsx16(ToggleGroupPrimitive.Root, {
4569
+ return /* @__PURE__ */ jsx17(ToggleGroupPrimitive.Root, {
4438
4570
  ...rootProps,
4439
4571
  type: "multiple",
4440
4572
  value: Array.isArray(value) ? value : asArray(value),
@@ -4448,7 +4580,7 @@ function SegmentedNative({ node, props, rootProps, emit, scope }) {
4448
4580
  children: body
4449
4581
  });
4450
4582
  }
4451
- return /* @__PURE__ */ jsx16(ToggleGroupPrimitive.Root, {
4583
+ return /* @__PURE__ */ jsx17(ToggleGroupPrimitive.Root, {
4452
4584
  ...rootProps,
4453
4585
  type: "single",
4454
4586
  value,
@@ -4466,7 +4598,7 @@ function SegmentedNative({ node, props, rootProps, emit, scope }) {
4466
4598
  }
4467
4599
  function SegmentedBar({ rootProps, vertical, items, value, part, content, onPick }) {
4468
4600
  const ctx = useSurfaceContext();
4469
- const refs = useRef18([]);
4601
+ const refs = useRef19([]);
4470
4602
  const enabled = items.map((item, i) => bool(item.disabled) ? -1 : i).filter((i) => i >= 0);
4471
4603
  const selectedIndex = items.findIndex((item) => item.value === value && !bool(item.disabled));
4472
4604
  const [focusIndex, setFocusIndex] = useState15(null);
@@ -4493,13 +4625,13 @@ function SegmentedBar({ rootProps, vertical, items, value, part, content, onPick
4493
4625
  refs.current[next]?.focus();
4494
4626
  return true;
4495
4627
  };
4496
- return /* @__PURE__ */ jsx16("nav", {
4628
+ return /* @__PURE__ */ jsx17("nav", {
4497
4629
  ...rootProps,
4498
4630
  dir: ctx.direction,
4499
4631
  children: items.map((item, i) => {
4500
4632
  const selected = item.value === value;
4501
4633
  const disabled = bool(item.disabled);
4502
- return /* @__PURE__ */ jsx16("button", {
4634
+ return /* @__PURE__ */ jsx17("button", {
4503
4635
  ref: (el) => void (refs.current[i] = el),
4504
4636
  type: "button",
4505
4637
  ...part(`item`, selected && `selected`, disabled && `disabled`),
@@ -4533,9 +4665,9 @@ function AccordionNative({ node, props, rootProps, emit, scope }) {
4533
4665
  value: item.value,
4534
4666
  ...part.at(`item`, i, open && `open`),
4535
4667
  children: [
4536
- /* @__PURE__ */ jsx16(AccordionPrimitive.Header, {
4668
+ /* @__PURE__ */ jsx17(AccordionPrimitive.Header, {
4537
4669
  asChild: true,
4538
- children: /* @__PURE__ */ jsx16("div", {
4670
+ children: /* @__PURE__ */ jsx17("div", {
4539
4671
  style: { display: `flex` },
4540
4672
  children: /* @__PURE__ */ jsxs13(AccordionPrimitive.Trigger, {
4541
4673
  ...part.at(`trigger`, i, open && `open`),
@@ -4544,13 +4676,13 @@ function AccordionNative({ node, props, rootProps, emit, scope }) {
4544
4676
  className: "xui-accordion-title",
4545
4677
  children: [
4546
4678
  str(item.title),
4547
- item.count !== undefined ? /* @__PURE__ */ jsx16("span", {
4679
+ item.count !== undefined ? /* @__PURE__ */ jsx17("span", {
4548
4680
  ...part.at(`count`, i),
4549
4681
  children: ctx.formatter.number(num(item.count))
4550
4682
  }) : null
4551
4683
  ]
4552
4684
  }),
4553
- /* @__PURE__ */ jsx16(BuiltinIcon, {
4685
+ /* @__PURE__ */ jsx17(BuiltinIcon, {
4554
4686
  slot: "Accordion.trigger",
4555
4687
  size: 16
4556
4688
  })
@@ -4558,9 +4690,9 @@ function AccordionNative({ node, props, rootProps, emit, scope }) {
4558
4690
  })
4559
4691
  })
4560
4692
  }),
4561
- /* @__PURE__ */ jsx16(AccordionPrimitive.Content, {
4693
+ /* @__PURE__ */ jsx17(AccordionPrimitive.Content, {
4562
4694
  ...part.at(`content`, i, open && `open`),
4563
- children: node.children[i] ? /* @__PURE__ */ jsx16(NodeView, {
4695
+ children: node.children[i] ? /* @__PURE__ */ jsx17(NodeView, {
4564
4696
  node: node.children[i]
4565
4697
  }) : null
4566
4698
  })
@@ -4568,7 +4700,7 @@ function AccordionNative({ node, props, rootProps, emit, scope }) {
4568
4700
  }, item.value);
4569
4701
  });
4570
4702
  if (multiple) {
4571
- return /* @__PURE__ */ jsx16(AccordionPrimitive.Root, {
4703
+ return /* @__PURE__ */ jsx17(AccordionPrimitive.Root, {
4572
4704
  ...rootProps,
4573
4705
  type: "multiple",
4574
4706
  value: asArray(value),
@@ -4580,7 +4712,7 @@ function AccordionNative({ node, props, rootProps, emit, scope }) {
4580
4712
  children: body
4581
4713
  });
4582
4714
  }
4583
- return /* @__PURE__ */ jsx16(AccordionPrimitive.Root, {
4715
+ return /* @__PURE__ */ jsx17(AccordionPrimitive.Root, {
4584
4716
  ...rootProps,
4585
4717
  type: "single",
4586
4718
  collapsible: true,
@@ -4596,17 +4728,17 @@ function AccordionNative({ node, props, rootProps, emit, scope }) {
4596
4728
  var asArray = (v) => Array.isArray(v) ? v : v ? v.split(`,`) : [];
4597
4729
 
4598
4730
  // packages/exponential-ui-react/src/natives/overlays.tsx
4599
- import { forwardRef as forwardRef2, useCallback as useCallback8, useEffect as useEffect15, useRef as useRef20, useState as useState17 } from "react";
4731
+ import { forwardRef as forwardRef2, useCallback as useCallback8, useEffect as useEffect16, useRef as useRef21, useState as useState17 } from "react";
4600
4732
  import { createPortal } from "react-dom";
4601
4733
  import { ContextMenu as ContextPrimitive, Dialog as DialogPrimitive, DropdownMenu as MenuPrimitive, Popover as PopoverPrimitive2, Tooltip as TooltipPrimitive } from "radix-ui";
4602
4734
  import { OVERLAY_OFFSET as OVERLAY_OFFSET2, OVERLAY_PADDING as OVERLAY_PADDING2 } from "@exponential_app/eui";
4603
- import { isBinding as isBinding2 } from "@exponential_app/eui/web";
4735
+ import { isBinding as isBinding2, overlayOpenFocus } from "@exponential_app/eui/web";
4604
4736
  import { absolutePath as absolutePath2 } from "@exponential_app/eui/web";
4605
4737
 
4606
4738
  // packages/exponential-ui-react/src/natives/search.tsx
4607
- import { useEffect as useEffect14, useId as useId5, useLayoutEffect as useLayoutEffect5, useRef as useRef19, useState as useState16 } from "react";
4739
+ import { useEffect as useEffect15, useId as useId5, useLayoutEffect as useLayoutEffect6, useRef as useRef20, useState as useState16 } from "react";
4608
4740
  import { elementScale } from "@exponential_app/eui/web";
4609
- import { jsx as jsx17, jsxs as jsxs14, Fragment as Fragment4 } from "react/jsx-runtime";
4741
+ import { jsx as jsx18, jsxs as jsxs14, Fragment as Fragment5 } from "react/jsx-runtime";
4610
4742
  function searchMatches(item, query) {
4611
4743
  const needle = query.trim().toLowerCase();
4612
4744
  return needle === `` || str(item.label).toLowerCase().includes(needle) || str(item.identifier).toLowerCase().includes(needle);
@@ -4615,7 +4747,7 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4615
4747
  const ctx = useSurfaceContext();
4616
4748
  const listId = useId5();
4617
4749
  const [active, setActive] = useState16(0);
4618
- const listRef = useRef19(null);
4750
+ const listRef = useRef20(null);
4619
4751
  const [moreBelow, setMoreBelow] = useState16(false);
4620
4752
  const at = Math.min(active, Math.max(0, rows.length - 1));
4621
4753
  const single = (name) => {
@@ -4624,14 +4756,14 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4624
4756
  attrs[`data-xui-id`] = `${attrs[`data-xui-id`]}${suffix}`;
4625
4757
  return attrs;
4626
4758
  };
4627
- useEffect14(() => setActive(0), [query]);
4759
+ useEffect15(() => setActive(0), [query]);
4628
4760
  const measure = () => {
4629
4761
  const list = listRef.current;
4630
4762
  if (list)
4631
4763
  setMoreBelow(list.scrollTop + list.clientHeight < list.scrollHeight - 1);
4632
4764
  };
4633
- useLayoutEffect5(measure, [rows.length, maxRows]);
4634
- useLayoutEffect5(() => {
4765
+ useLayoutEffect6(measure, [rows.length, maxRows]);
4766
+ useLayoutEffect6(() => {
4635
4767
  const list = listRef.current;
4636
4768
  const row = list?.querySelector(`[data-active="true"]`);
4637
4769
  if (!list || !row)
@@ -4665,7 +4797,7 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4665
4797
  }
4666
4798
  };
4667
4799
  const activeId = rows[at] ? `${listId}-${rows[at].index}` : undefined;
4668
- return /* @__PURE__ */ jsxs14(Fragment4, {
4800
+ return /* @__PURE__ */ jsxs14(Fragment5, {
4669
4801
  children: [
4670
4802
  /* @__PURE__ */ jsxs14("div", {
4671
4803
  ...single(`head`),
@@ -4673,10 +4805,10 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4673
4805
  /* @__PURE__ */ jsxs14("div", {
4674
4806
  ...single(`search`),
4675
4807
  children: [
4676
- /* @__PURE__ */ jsx17(BuiltinIcon, {
4808
+ /* @__PURE__ */ jsx18(BuiltinIcon, {
4677
4809
  slot: "SearchList.search"
4678
4810
  }),
4679
- /* @__PURE__ */ jsx17("input", {
4811
+ /* @__PURE__ */ jsx18("input", {
4680
4812
  type: "text",
4681
4813
  role: "combobox",
4682
4814
  "aria-expanded": "true",
@@ -4691,7 +4823,7 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4691
4823
  })
4692
4824
  ]
4693
4825
  }),
4694
- showCount && query.trim() !== `` ? /* @__PURE__ */ jsx17("span", {
4826
+ showCount && query.trim() !== `` ? /* @__PURE__ */ jsx18("span", {
4695
4827
  ...single(`count`),
4696
4828
  role: "status",
4697
4829
  "aria-live": "polite",
@@ -4713,7 +4845,7 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4713
4845
  rows.map(({ index, item }, pos) => {
4714
4846
  const isActive = pos === at;
4715
4847
  const disabled = bool(item.disabled);
4716
- return /* @__PURE__ */ jsx17("div", {
4848
+ return /* @__PURE__ */ jsx18("div", {
4717
4849
  id: `${listId}-${index}`,
4718
4850
  role: "option",
4719
4851
  "aria-selected": isActive,
@@ -4723,28 +4855,28 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4723
4855
  onPointerMove: () => pos !== at && setActive(pos),
4724
4856
  onPointerDown: (e) => e.preventDefault(),
4725
4857
  onClick: () => pick(pos),
4726
- children: renderRow ? renderRow(item, index) : /* @__PURE__ */ jsxs14(Fragment4, {
4858
+ children: renderRow ? renderRow(item, index) : /* @__PURE__ */ jsxs14(Fragment5, {
4727
4859
  children: [
4728
- item.icon ? /* @__PURE__ */ jsx17("span", {
4860
+ item.icon ? /* @__PURE__ */ jsx18("span", {
4729
4861
  ...part.at(`icon`, index),
4730
4862
  "aria-hidden": "true",
4731
- children: /* @__PURE__ */ jsx17(IconGlyph, {
4863
+ children: /* @__PURE__ */ jsx18(IconGlyph, {
4732
4864
  icons: ctx.host.icons,
4733
4865
  name: item.icon
4734
4866
  })
4735
4867
  }) : null,
4736
- str(item.identifier) ? /* @__PURE__ */ jsx17("span", {
4868
+ str(item.identifier) ? /* @__PURE__ */ jsx18("span", {
4737
4869
  ...part.at(`identifier`, index),
4738
4870
  children: str(item.identifier)
4739
4871
  }) : null,
4740
- /* @__PURE__ */ jsx17("span", {
4872
+ /* @__PURE__ */ jsx18("span", {
4741
4873
  ...part.at(`label`, index),
4742
4874
  children: str(item.label)
4743
4875
  }),
4744
- picked !== undefined && picked !== `` && item.value === picked ? /* @__PURE__ */ jsx17("span", {
4876
+ picked !== undefined && picked !== `` && item.value === picked ? /* @__PURE__ */ jsx18("span", {
4745
4877
  ...part.at(`check`, index),
4746
4878
  "aria-hidden": "true",
4747
- children: /* @__PURE__ */ jsx17(BuiltinIcon, {
4879
+ children: /* @__PURE__ */ jsx18(BuiltinIcon, {
4748
4880
  slot: "SearchList.check"
4749
4881
  })
4750
4882
  }) : null
@@ -4752,13 +4884,13 @@ function SearchBody({ part, owner, suffix, rows, query, onQuery, placeholder, em
4752
4884
  })
4753
4885
  }, `${index}`);
4754
4886
  }),
4755
- rows.length === 0 ? /* @__PURE__ */ jsx17("div", {
4887
+ rows.length === 0 ? /* @__PURE__ */ jsx18("div", {
4756
4888
  ...single(`empty`),
4757
4889
  children: emptyText
4758
4890
  }) : null
4759
4891
  ]
4760
4892
  }),
4761
- moreBelow && rows.length > maxRows ? /* @__PURE__ */ jsx17("div", {
4893
+ moreBelow && rows.length > maxRows ? /* @__PURE__ */ jsx18("div", {
4762
4894
  ...single(`fade`),
4763
4895
  "aria-hidden": "true"
4764
4896
  }) : null
@@ -4774,8 +4906,8 @@ function SearchListNative({ node, props, rootProps, emit, scope }) {
4774
4906
  const [query, setQuery] = useBoundState(node, scope, `query`, str(props.query));
4775
4907
  const [picked, setPicked] = useBoundState(node, scope, `value`, str(props.value));
4776
4908
  const hostSearches = Boolean(node.on?.search);
4777
- const typed = useRef19(false);
4778
- useEffect14(() => {
4909
+ const typed = useRef20(false);
4910
+ useEffect15(() => {
4779
4911
  if (!typed.current)
4780
4912
  return;
4781
4913
  const t = setTimeout(() => void emit(`search`, { query }), DEBOUNCE_MS);
@@ -4783,9 +4915,9 @@ function SearchListNative({ node, props, rootProps, emit, scope }) {
4783
4915
  }, [query]);
4784
4916
  const rows = items.map((item, index) => ({ index, item })).filter(({ item }) => hostSearches || searchMatches(item, query));
4785
4917
  const maxRows = Math.max(1, Math.floor(num(props.maxRows, 8)));
4786
- return /* @__PURE__ */ jsx17("div", {
4918
+ return /* @__PURE__ */ jsx18("div", {
4787
4919
  ...rootProps,
4788
- children: /* @__PURE__ */ jsx17(SearchBody, {
4920
+ children: /* @__PURE__ */ jsx18(SearchBody, {
4789
4921
  part,
4790
4922
  owner: "SearchList",
4791
4923
  suffix: "",
@@ -4809,7 +4941,7 @@ function SearchListNative({ node, props, rootProps, emit, scope }) {
4809
4941
  }
4810
4942
 
4811
4943
  // packages/exponential-ui-react/src/natives/overlays.tsx
4812
- import { jsx as jsx18, jsxs as jsxs15, Fragment as Fragment5 } from "react/jsx-runtime";
4944
+ import { jsx as jsx19, jsxs as jsxs15, Fragment as Fragment6 } from "react/jsx-runtime";
4813
4945
  function useOpenState(node, scope, external, emit) {
4814
4946
  const [open, setOpen] = useBoundState(node, scope, `open`, external);
4815
4947
  const change = useCallback8((next) => {
@@ -4819,7 +4951,7 @@ function useOpenState(node, scope, external, emit) {
4819
4951
  return [open, change];
4820
4952
  }
4821
4953
  var Trigger = forwardRef2(function Trigger({ children, ...rest }, ref) {
4822
- return /* @__PURE__ */ jsx18("span", {
4954
+ return /* @__PURE__ */ jsx19("span", {
4823
4955
  ref,
4824
4956
  className: "xui-trigger",
4825
4957
  ...rest,
@@ -4832,20 +4964,20 @@ function overlayRootProps(rootProps, trigger, triggerNode) {
4832
4964
  return { ...rootProps, "data-xui-overlay-root": triggerNode?.component === `Link` ? `stretch` : `` };
4833
4965
  }
4834
4966
  function DialogNative(p) {
4835
- return /* @__PURE__ */ jsx18(ModalNative, {
4967
+ return /* @__PURE__ */ jsx19(ModalNative, {
4836
4968
  ...p,
4837
4969
  kind: "Dialog"
4838
4970
  });
4839
4971
  }
4840
4972
  function DrawerNative(p) {
4841
- return /* @__PURE__ */ jsx18(ModalNative, {
4973
+ return /* @__PURE__ */ jsx19(ModalNative, {
4842
4974
  ...p,
4843
4975
  kind: "Drawer"
4844
4976
  });
4845
4977
  }
4846
4978
  function useDragToDismiss(side, enabled, onDismiss, reducedMotion) {
4847
- const panel = useRef20(null);
4848
- const drag = useRef20(null);
4979
+ const panel = useRef21(null);
4980
+ const drag = useRef21(null);
4849
4981
  const sign = side === `bottom` || side === `right` ? 1 : -1;
4850
4982
  const axis = side === `left` || side === `right` ? `x` : `y`;
4851
4983
  const distance = (e) => {
@@ -4905,11 +5037,11 @@ function ModalNative({ node, props, rootProps, emit, children, slots, scope, kin
4905
5037
  open,
4906
5038
  onOpenChange: (next) => next || dismissible ? setOpen(next) : undefined,
4907
5039
  children: [
4908
- /* @__PURE__ */ jsx18("div", {
5040
+ /* @__PURE__ */ jsx19("div", {
4909
5041
  ...overlayRootProps(rootProps, slots.trigger, node.slots?.trigger),
4910
- children: slots.trigger ? /* @__PURE__ */ jsx18(DialogPrimitive.Trigger, {
5042
+ children: slots.trigger ? /* @__PURE__ */ jsx19(DialogPrimitive.Trigger, {
4911
5043
  asChild: true,
4912
- children: /* @__PURE__ */ jsx18(Trigger, {
5044
+ children: /* @__PURE__ */ jsx19(Trigger, {
4913
5045
  children: slots.trigger
4914
5046
  })
4915
5047
  }) : null
@@ -4917,7 +5049,7 @@ function ModalNative({ node, props, rootProps, emit, children, slots, scope, kin
4917
5049
  /* @__PURE__ */ jsxs15(DialogPrimitive.Portal, {
4918
5050
  container: ctx.portal ?? undefined,
4919
5051
  children: [
4920
- /* @__PURE__ */ jsx18(DialogPrimitive.Overlay, {
5052
+ /* @__PURE__ */ jsx19(DialogPrimitive.Overlay, {
4921
5053
  ...part(`overlay`, open && `open`),
4922
5054
  "data-xui-overlay-backdrop": kind
4923
5055
  }),
@@ -4931,18 +5063,10 @@ function ModalNative({ node, props, rootProps, emit, children, slots, scope, kin
4931
5063
  onEscapeKeyDown: dismissible ? undefined : (e) => e.preventDefault(),
4932
5064
  onPointerDownOutside: dismissible ? undefined : (e) => e.preventDefault(),
4933
5065
  onInteractOutside: dismissible ? undefined : (e) => e.preventDefault(),
4934
- onOpenAutoFocus: (e) => {
4935
- const content = e.currentTarget;
4936
- const marked = content?.querySelector(`[data-xui-autofocus]`) ?? content?.querySelector(`[data-xui-part="AlertDialog/cancel"]`);
4937
- const target = marked && (marked.matches(`button,input,textarea,select,a[href],[tabindex]`) ? marked : marked.querySelector(`button,input,textarea,select,a[href],[tabindex]`));
4938
- if (target) {
4939
- e.preventDefault();
4940
- target.focus();
4941
- }
4942
- },
5066
+ onOpenAutoFocus: overlayOpenFocus,
4943
5067
  ...description ? {} : { "aria-describedby": undefined },
4944
5068
  children: [
4945
- kind === `Drawer` && (side === `bottom` || side === `top`) ? /* @__PURE__ */ jsx18("div", {
5069
+ kind === `Drawer` && (side === `bottom` || side === `top`) ? /* @__PURE__ */ jsx19("div", {
4946
5070
  ...part(`handle`),
4947
5071
  "aria-hidden": "true",
4948
5072
  ...drag.handlers
@@ -4951,39 +5075,39 @@ function ModalNative({ node, props, rootProps, emit, children, slots, scope, kin
4951
5075
  className: "xui-overlay-head",
4952
5076
  ...kind === `Drawer` ? drag.handlers : {},
4953
5077
  children: [
4954
- title ? /* @__PURE__ */ jsx18(DialogPrimitive.Title, {
5078
+ title ? /* @__PURE__ */ jsx19(DialogPrimitive.Title, {
4955
5079
  ...part(`title`),
4956
5080
  children: title
4957
- }) : /* @__PURE__ */ jsx18(DialogPrimitive.Title, {
5081
+ }) : /* @__PURE__ */ jsx19(DialogPrimitive.Title, {
4958
5082
  className: "xui-sr-only",
4959
5083
  children: ctx.t(`dialog`)
4960
5084
  }),
4961
- description ? /* @__PURE__ */ jsx18(DialogPrimitive.Description, {
5085
+ description ? /* @__PURE__ */ jsx19(DialogPrimitive.Description, {
4962
5086
  ...part(`description`),
4963
5087
  children: description
4964
5088
  }) : null
4965
5089
  ]
4966
- }) : /* @__PURE__ */ jsx18(DialogPrimitive.Title, {
5090
+ }) : /* @__PURE__ */ jsx19(DialogPrimitive.Title, {
4967
5091
  className: "xui-sr-only",
4968
5092
  children: ctx.t(`dialog`)
4969
5093
  }),
4970
5094
  /* @__PURE__ */ jsxs15(CloseOnSubmitContext.Provider, {
4971
5095
  value: dismissible ? close : null,
4972
5096
  children: [
4973
- /* @__PURE__ */ jsx18("div", {
5097
+ /* @__PURE__ */ jsx19("div", {
4974
5098
  className: "xui-overlay-body",
4975
5099
  children
4976
5100
  }),
4977
- slots.footer ? /* @__PURE__ */ jsx18("div", {
5101
+ slots.footer ? /* @__PURE__ */ jsx19("div", {
4978
5102
  ...part(`footer`),
4979
5103
  children: slots.footer
4980
5104
  }) : null
4981
5105
  ]
4982
5106
  }),
4983
- kind === `Dialog` && dismissible ? /* @__PURE__ */ jsx18(DialogPrimitive.Close, {
5107
+ kind === `Dialog` && dismissible ? /* @__PURE__ */ jsx19(DialogPrimitive.Close, {
4984
5108
  ...part(`close`),
4985
5109
  "aria-label": ctx.t(`close`),
4986
- children: /* @__PURE__ */ jsx18(BuiltinIcon, {
5110
+ children: /* @__PURE__ */ jsx19(BuiltinIcon, {
4987
5111
  slot: "Dialog.close"
4988
5112
  })
4989
5113
  }) : null
@@ -5002,10 +5126,10 @@ function PopoverNative({ node, props, rootProps, emit, children, slots, scope })
5002
5126
  const [open, setOpen] = useOpenState(node, scope, bool(props.open), emit);
5003
5127
  const side = str(props.side, `bottom`);
5004
5128
  const hoverMode = props.openOn === `hover` && ctx.hover;
5005
- const timer = useRef20(null);
5006
- const openRef = useRef20(open);
5129
+ const timer = useRef21(null);
5130
+ const openRef = useRef21(open);
5007
5131
  openRef.current = open;
5008
- const contentRef = useRef20(null);
5132
+ const contentRef = useRef21(null);
5009
5133
  const schedule = (next) => {
5010
5134
  if (timer.current)
5011
5135
  clearTimeout(timer.current);
@@ -5014,7 +5138,7 @@ function PopoverNative({ node, props, rootProps, emit, children, slots, scope })
5014
5138
  setOpen(next);
5015
5139
  }, next ? HOVER_OPEN_MS : HOVER_CLOSE_MS);
5016
5140
  };
5017
- useEffect15(() => () => void (timer.current && clearTimeout(timer.current)), []);
5141
+ useEffect16(() => () => void (timer.current && clearTimeout(timer.current)), []);
5018
5142
  const hoverProps = hoverMode ? {
5019
5143
  onPointerEnter: (e) => e.pointerType !== `touch` && schedule(true),
5020
5144
  onPointerLeave: (e) => e.pointerType !== `touch` && schedule(false),
@@ -5029,24 +5153,24 @@ function PopoverNative({ node, props, rootProps, emit, children, slots, scope })
5029
5153
  open,
5030
5154
  onOpenChange: setOpen,
5031
5155
  children: [
5032
- /* @__PURE__ */ jsx18("div", {
5156
+ /* @__PURE__ */ jsx19("div", {
5033
5157
  ...overlayRootProps(rootProps, slots.trigger, node.slots?.trigger),
5034
- children: slots.trigger ? /* @__PURE__ */ jsx18(PopoverPrimitive2.Trigger, {
5158
+ children: slots.trigger ? /* @__PURE__ */ jsx19(PopoverPrimitive2.Trigger, {
5035
5159
  asChild: true,
5036
- children: /* @__PURE__ */ jsx18(Trigger, {
5160
+ children: /* @__PURE__ */ jsx19(Trigger, {
5037
5161
  ...hoverProps,
5038
5162
  children: slots.trigger
5039
5163
  })
5040
- }) : /* @__PURE__ */ jsx18(PopoverPrimitive2.Anchor, {
5164
+ }) : /* @__PURE__ */ jsx19(PopoverPrimitive2.Anchor, {
5041
5165
  asChild: true,
5042
- children: /* @__PURE__ */ jsx18("span", {
5166
+ children: /* @__PURE__ */ jsx19("span", {
5043
5167
  style: { display: `inline-flex` }
5044
5168
  })
5045
5169
  })
5046
5170
  }),
5047
- /* @__PURE__ */ jsx18(PopoverPrimitive2.Portal, {
5171
+ /* @__PURE__ */ jsx19(PopoverPrimitive2.Portal, {
5048
5172
  container: ctx.portal ?? undefined,
5049
- children: /* @__PURE__ */ jsx18(PopoverPrimitive2.Content, {
5173
+ children: /* @__PURE__ */ jsx19(PopoverPrimitive2.Content, {
5050
5174
  ref: contentRef,
5051
5175
  ...part(`content`, open && `open`),
5052
5176
  side,
@@ -5059,7 +5183,7 @@ function PopoverNative({ node, props, rootProps, emit, children, slots, scope })
5059
5183
  onOpenAutoFocus: hoverMode ? (e) => e.preventDefault() : undefined,
5060
5184
  onPointerEnter: hoverMode ? () => schedule(true) : undefined,
5061
5185
  onPointerLeave: hoverMode ? () => schedule(false) : undefined,
5062
- children: /* @__PURE__ */ jsx18(CloseOnSubmitContext.Provider, {
5186
+ children: /* @__PURE__ */ jsx19(CloseOnSubmitContext.Provider, {
5063
5187
  value: null,
5064
5188
  children
5065
5189
  })
@@ -5073,25 +5197,25 @@ function TooltipNative({ node, props, rootProps, children }) {
5073
5197
  const part = useParts(node, props);
5074
5198
  const side = str(props.side, `top`);
5075
5199
  const content = str(props.content) || str(props.text);
5076
- return /* @__PURE__ */ jsx18(TooltipPrimitive.Provider, {
5200
+ return /* @__PURE__ */ jsx19(TooltipPrimitive.Provider, {
5077
5201
  delayDuration: 300,
5078
5202
  children: /* @__PURE__ */ jsxs15(TooltipPrimitive.Root, {
5079
5203
  children: [
5080
- /* @__PURE__ */ jsx18("div", {
5204
+ /* @__PURE__ */ jsx19("div", {
5081
5205
  ...rootProps,
5082
5206
  "data-xui-overlay-root": "",
5083
- children: /* @__PURE__ */ jsx18(TooltipPrimitive.Trigger, {
5207
+ children: /* @__PURE__ */ jsx19(TooltipPrimitive.Trigger, {
5084
5208
  asChild: true,
5085
- children: /* @__PURE__ */ jsx18("div", {
5209
+ children: /* @__PURE__ */ jsx19("div", {
5086
5210
  ...part(`anchor`),
5087
5211
  tabIndex: 0,
5088
5212
  children
5089
5213
  })
5090
5214
  })
5091
5215
  }),
5092
- /* @__PURE__ */ jsx18(TooltipPrimitive.Portal, {
5216
+ /* @__PURE__ */ jsx19(TooltipPrimitive.Portal, {
5093
5217
  container: ctx.portal ?? undefined,
5094
- children: /* @__PURE__ */ jsx18(TooltipPrimitive.Content, {
5218
+ children: /* @__PURE__ */ jsx19(TooltipPrimitive.Content, {
5095
5219
  ...part(`content`),
5096
5220
  side,
5097
5221
  sideOffset: OVERLAY_OFFSET2,
@@ -5107,13 +5231,13 @@ function TooltipNative({ node, props, rootProps, children }) {
5107
5231
  function MenuSearch({ item, i, part, emit, close }) {
5108
5232
  const ctx = useSurfaceContext();
5109
5233
  const [query, setQuery] = useState17(``);
5110
- const box = useRef20(null);
5111
- useEffect15(() => {
5234
+ const box = useRef21(null);
5235
+ useEffect16(() => {
5112
5236
  const frame = requestAnimationFrame(() => box.current?.querySelector(`input`)?.focus({ preventScroll: true }));
5113
5237
  return () => cancelAnimationFrame(frame);
5114
5238
  }, []);
5115
5239
  const rows = objects(item.items).map((entry, index) => ({ index, entry })).filter(({ entry }) => entry.kind !== `separator` && entry.kind !== `label` && !entry.separator && searchMatches({ label: str(entry.label) }, query)).map(({ index, entry }) => ({ index, item: { label: str(entry.label), value: str(entry.value ?? entry.label), icon: entry.icon, disabled: bool(entry.disabled) } }));
5116
- return /* @__PURE__ */ jsx18("div", {
5240
+ return /* @__PURE__ */ jsx19("div", {
5117
5241
  ref: box,
5118
5242
  className: "xui-menu-search",
5119
5243
  onPointerEnter: (e) => {
@@ -5121,7 +5245,7 @@ function MenuSearch({ item, i, part, emit, close }) {
5121
5245
  if (input && !e.currentTarget.contains(document.activeElement))
5122
5246
  input.focus({ preventScroll: true });
5123
5247
  },
5124
- children: /* @__PURE__ */ jsx18(SearchBody, {
5248
+ children: /* @__PURE__ */ jsx19(SearchBody, {
5125
5249
  part,
5126
5250
  owner: "Menu",
5127
5251
  suffix: `.${i}`,
@@ -5139,13 +5263,13 @@ function MenuSearch({ item, i, part, emit, close }) {
5139
5263
  close();
5140
5264
  },
5141
5265
  rowPart: (_, __, active) => part(`item`, active && `selected`),
5142
- renderRow: (row) => /* @__PURE__ */ jsxs15(Fragment5, {
5266
+ renderRow: (row) => /* @__PURE__ */ jsxs15(Fragment6, {
5143
5267
  children: [
5144
- row.icon ? /* @__PURE__ */ jsx18(IconGlyph, {
5268
+ row.icon ? /* @__PURE__ */ jsx19(IconGlyph, {
5145
5269
  icons: ctx.host.icons,
5146
5270
  name: row.icon
5147
5271
  }) : null,
5148
- /* @__PURE__ */ jsx18("span", {
5272
+ /* @__PURE__ */ jsx19("span", {
5149
5273
  className: "xui-menu-label",
5150
5274
  children: row.label
5151
5275
  })
@@ -5158,24 +5282,24 @@ function MenuItems({ ns, items, rawItems, part, overlay, emit, scope, path, clos
5158
5282
  const ctx = useSurfaceContext();
5159
5283
  const raws = objects(rawItems);
5160
5284
  const N = ns;
5161
- return /* @__PURE__ */ jsx18(Fragment5, {
5285
+ return /* @__PURE__ */ jsx19(Fragment6, {
5162
5286
  children: items.map((item, i) => {
5163
5287
  const kind = item.separator ? `separator` : item.kind ?? `item`;
5164
5288
  const key = `${path}${i}`;
5165
- const icon = item.icon ? /* @__PURE__ */ jsx18(IconGlyph, {
5289
+ const icon = item.icon ? /* @__PURE__ */ jsx19(IconGlyph, {
5166
5290
  icons: ctx.host.icons,
5167
5291
  name: item.icon
5168
5292
  }) : null;
5169
- const shortcut = item.shortcut ? /* @__PURE__ */ jsx18("span", {
5293
+ const shortcut = item.shortcut ? /* @__PURE__ */ jsx19("span", {
5170
5294
  ...part(`shortcut`),
5171
5295
  children: item.shortcut
5172
5296
  }) : null;
5173
5297
  if (kind === `separator`)
5174
- return /* @__PURE__ */ jsx18(N.Separator, {
5298
+ return /* @__PURE__ */ jsx19(N.Separator, {
5175
5299
  ...part(`separator`)
5176
5300
  }, key);
5177
5301
  if (kind === `label`)
5178
- return /* @__PURE__ */ jsx18(N.Label, {
5302
+ return /* @__PURE__ */ jsx19(N.Label, {
5179
5303
  ...part(`label`),
5180
5304
  children: str(item.label)
5181
5305
  }, key);
@@ -5187,33 +5311,33 @@ function MenuItems({ ns, items, rawItems, part, overlay, emit, scope, path, clos
5187
5311
  disabled: bool(item.disabled),
5188
5312
  children: [
5189
5313
  icon,
5190
- /* @__PURE__ */ jsx18("span", {
5314
+ /* @__PURE__ */ jsx19("span", {
5191
5315
  className: "xui-menu-label",
5192
5316
  children: str(item.label)
5193
5317
  }),
5194
- /* @__PURE__ */ jsx18("span", {
5318
+ /* @__PURE__ */ jsx19("span", {
5195
5319
  ...part(`submenuIndicator`),
5196
- children: /* @__PURE__ */ jsx18(BuiltinIcon, {
5320
+ children: /* @__PURE__ */ jsx19(BuiltinIcon, {
5197
5321
  slot: "Menu.submenuIndicator"
5198
5322
  })
5199
5323
  })
5200
5324
  ]
5201
5325
  }),
5202
- /* @__PURE__ */ jsx18(N.Portal, {
5326
+ /* @__PURE__ */ jsx19(N.Portal, {
5203
5327
  container: ctx.portal ?? undefined,
5204
- children: /* @__PURE__ */ jsx18(N.SubContent, {
5328
+ children: /* @__PURE__ */ jsx19(N.SubContent, {
5205
5329
  ...part(`content`),
5206
5330
  sideOffset: 2,
5207
5331
  collisionPadding: OVERLAY_PADDING2,
5208
5332
  "data-xui-overlay": `${overlay}.sub`,
5209
5333
  "data-searchable": item.searchable ? `true` : undefined,
5210
- children: item.searchable ? /* @__PURE__ */ jsx18(MenuSearch, {
5334
+ children: item.searchable ? /* @__PURE__ */ jsx19(MenuSearch, {
5211
5335
  item,
5212
5336
  i: key,
5213
5337
  part,
5214
5338
  emit,
5215
5339
  close
5216
- }) : /* @__PURE__ */ jsx18(MenuItems, {
5340
+ }) : /* @__PURE__ */ jsx19(MenuItems, {
5217
5341
  ns,
5218
5342
  items: objects(item.items),
5219
5343
  rawItems: raws[i]?.items,
@@ -5243,15 +5367,15 @@ function MenuItems({ ns, items, rawItems, part, overlay, emit, scope, path, clos
5243
5367
  },
5244
5368
  onSelect: (e) => e.preventDefault(),
5245
5369
  children: [
5246
- /* @__PURE__ */ jsx18("span", {
5370
+ /* @__PURE__ */ jsx19("span", {
5247
5371
  ...part(`check`),
5248
- children: /* @__PURE__ */ jsx18(N.ItemIndicator, {
5249
- children: /* @__PURE__ */ jsx18(BuiltinIcon, {
5372
+ children: /* @__PURE__ */ jsx19(N.ItemIndicator, {
5373
+ children: /* @__PURE__ */ jsx19(BuiltinIcon, {
5250
5374
  slot: "Menu.check"
5251
5375
  })
5252
5376
  })
5253
5377
  }),
5254
- /* @__PURE__ */ jsx18("span", {
5378
+ /* @__PURE__ */ jsx19("span", {
5255
5379
  className: "xui-menu-label",
5256
5380
  children: str(item.label)
5257
5381
  }),
@@ -5266,7 +5390,7 @@ function MenuItems({ ns, items, rawItems, part, overlay, emit, scope, path, clos
5266
5390
  onSelect: () => void emit(`select`, { value: item.value ?? item.label }),
5267
5391
  children: [
5268
5392
  icon,
5269
- /* @__PURE__ */ jsx18("span", {
5393
+ /* @__PURE__ */ jsx19("span", {
5270
5394
  className: "xui-menu-label",
5271
5395
  children: str(item.label)
5272
5396
  }),
@@ -5277,9 +5401,9 @@ function MenuItems({ ns, items, rawItems, part, overlay, emit, scope, path, clos
5277
5401
  });
5278
5402
  }
5279
5403
  function MenuNative(p) {
5280
- return p.props.openOn === `contextmenu` ? /* @__PURE__ */ jsx18(ContextMenuOpening, {
5404
+ return p.props.openOn === `contextmenu` ? /* @__PURE__ */ jsx19(ContextMenuOpening, {
5281
5405
  ...p
5282
- }) : /* @__PURE__ */ jsx18(PressMenuOpening, {
5406
+ }) : /* @__PURE__ */ jsx19(PressMenuOpening, {
5283
5407
  ...p
5284
5408
  });
5285
5409
  }
@@ -5296,41 +5420,41 @@ function PressMenuOpening({ node, props, rootProps, emit, children, scope }) {
5296
5420
  onOpenChange: setOpen,
5297
5421
  dir: ctx.direction,
5298
5422
  children: [
5299
- /* @__PURE__ */ jsx18("div", {
5423
+ /* @__PURE__ */ jsx19("div", {
5300
5424
  ...overlayRootProps(rootProps, true, child),
5301
- children: /* @__PURE__ */ jsx18(MenuPrimitive.Trigger, {
5425
+ children: /* @__PURE__ */ jsx19(MenuPrimitive.Trigger, {
5302
5426
  asChild: true,
5303
- children: child ? /* @__PURE__ */ jsx18(Trigger, {
5427
+ children: child ? /* @__PURE__ */ jsx19(Trigger, {
5304
5428
  children
5305
5429
  }) : /* @__PURE__ */ jsxs15("button", {
5306
5430
  type: "button",
5307
5431
  ...part(`trigger`, open && `open`),
5308
5432
  "aria-label": label || ctx.t(`menu`),
5309
5433
  children: [
5310
- icon ? /* @__PURE__ */ jsx18(IconGlyph, {
5434
+ icon ? /* @__PURE__ */ jsx19(IconGlyph, {
5311
5435
  icons: ctx.host.icons,
5312
5436
  name: icon,
5313
5437
  className: "xui-icon",
5314
5438
  width: 16,
5315
5439
  height: 16
5316
5440
  }) : null,
5317
- label || !icon ? /* @__PURE__ */ jsx18("span", {
5441
+ label || !icon ? /* @__PURE__ */ jsx19("span", {
5318
5442
  children: label || ctx.t(`menu`)
5319
5443
  }) : null
5320
5444
  ]
5321
5445
  })
5322
5446
  })
5323
5447
  }),
5324
- /* @__PURE__ */ jsx18(MenuPrimitive.Portal, {
5448
+ /* @__PURE__ */ jsx19(MenuPrimitive.Portal, {
5325
5449
  container: ctx.portal ?? undefined,
5326
- children: /* @__PURE__ */ jsx18(MenuPrimitive.Content, {
5450
+ children: /* @__PURE__ */ jsx19(MenuPrimitive.Content, {
5327
5451
  ...part(`content`, open && `open`),
5328
5452
  align: "start",
5329
5453
  sideOffset: OVERLAY_OFFSET2,
5330
5454
  collisionPadding: OVERLAY_PADDING2,
5331
5455
  "data-xui-overlay": "Menu",
5332
5456
  "data-open-on": "press",
5333
- children: /* @__PURE__ */ jsx18(MenuItems, {
5457
+ children: /* @__PURE__ */ jsx19(MenuItems, {
5334
5458
  ns: MenuPrimitive,
5335
5459
  items,
5336
5460
  rawItems: node.props.items,
@@ -5358,9 +5482,9 @@ function ContextMenuOpening({ node, props, rootProps, emit, children, scope }) {
5358
5482
  onOpenChange: setOpen,
5359
5483
  dir: ctx.direction,
5360
5484
  children: [
5361
- /* @__PURE__ */ jsx18(ContextPrimitive.Trigger, {
5485
+ /* @__PURE__ */ jsx19(ContextPrimitive.Trigger, {
5362
5486
  asChild: true,
5363
- children: /* @__PURE__ */ jsx18("div", {
5487
+ children: /* @__PURE__ */ jsx19("div", {
5364
5488
  ...rootProps,
5365
5489
  "data-state": open ? `open` : `closed`,
5366
5490
  onKeyDown: (e) => {
@@ -5373,14 +5497,14 @@ function ContextMenuOpening({ node, props, rootProps, emit, children, scope }) {
5373
5497
  children
5374
5498
  })
5375
5499
  }),
5376
- /* @__PURE__ */ jsx18(ContextPrimitive.Portal, {
5500
+ /* @__PURE__ */ jsx19(ContextPrimitive.Portal, {
5377
5501
  container: ctx.portal ?? undefined,
5378
- children: /* @__PURE__ */ jsx18(ContextPrimitive.Content, {
5502
+ children: /* @__PURE__ */ jsx19(ContextPrimitive.Content, {
5379
5503
  ...part(`content`, open && `open`),
5380
5504
  collisionPadding: OVERLAY_PADDING2,
5381
5505
  "data-xui-overlay": "Menu",
5382
5506
  "data-open-on": "contextmenu",
5383
- children: /* @__PURE__ */ jsx18(MenuItems, {
5507
+ children: /* @__PURE__ */ jsx19(MenuItems, {
5384
5508
  ns: ContextPrimitive,
5385
5509
  items,
5386
5510
  rawItems: node.props.items,
@@ -5404,15 +5528,15 @@ function ToastNative({ node, props, rootProps, emit, scope }) {
5404
5528
  const [paused, setPaused] = useState17(false);
5405
5529
  const duration = props.duration === undefined ? 5000 : Math.max(0, num(props.duration, 5000));
5406
5530
  const type = str(props.type, `info`);
5407
- const remaining = useRef20(duration);
5408
- const startedAt = useRef20(0);
5531
+ const remaining = useRef21(duration);
5532
+ const startedAt = useRef21(0);
5409
5533
  const close = useCallback8(() => {
5410
5534
  setOpenState(false);
5411
5535
  emit(`dismiss`, undefined, { open: false });
5412
5536
  emit(`change`, { open: false }, { open: false });
5413
5537
  }, [setOpenState, emit]);
5414
5538
  const [shown, setShown] = useState17(open);
5415
- useEffect15(() => {
5539
+ useEffect16(() => {
5416
5540
  if (open) {
5417
5541
  setShown(true);
5418
5542
  setLeaving(false);
@@ -5429,7 +5553,7 @@ function ToastNative({ node, props, rootProps, emit, scope }) {
5429
5553
  }, ms);
5430
5554
  return () => clearTimeout(t);
5431
5555
  }, [open]);
5432
- useEffect15(() => {
5556
+ useEffect16(() => {
5433
5557
  if (!open || duration === 0 || paused)
5434
5558
  return;
5435
5559
  startedAt.current = Date.now();
@@ -5463,37 +5587,37 @@ function ToastNative({ node, props, rootProps, emit, scope }) {
5463
5587
  }
5464
5588
  },
5465
5589
  children: [
5466
- /* @__PURE__ */ jsx18("span", {
5590
+ /* @__PURE__ */ jsx19("span", {
5467
5591
  ...part(`icon`),
5468
- children: /* @__PURE__ */ jsx18(BuiltinIcon, {
5592
+ children: /* @__PURE__ */ jsx19(BuiltinIcon, {
5469
5593
  slot: `Toast.icon.${type}`
5470
5594
  })
5471
5595
  }),
5472
5596
  /* @__PURE__ */ jsxs15("div", {
5473
5597
  className: "xui-toast-text",
5474
5598
  children: [
5475
- /* @__PURE__ */ jsx18("span", {
5599
+ /* @__PURE__ */ jsx19("span", {
5476
5600
  ...part(`title`),
5477
5601
  children: title
5478
5602
  }),
5479
- description ? /* @__PURE__ */ jsx18("span", {
5603
+ description ? /* @__PURE__ */ jsx19("span", {
5480
5604
  ...part(`description`),
5481
5605
  children: description
5482
5606
  }) : null
5483
5607
  ]
5484
5608
  }),
5485
- actionLabel ? /* @__PURE__ */ jsx18("button", {
5609
+ actionLabel ? /* @__PURE__ */ jsx19("button", {
5486
5610
  type: "button",
5487
5611
  ...part(`action`),
5488
5612
  onClick: () => void emit(`action`),
5489
5613
  children: actionLabel
5490
5614
  }) : null,
5491
- props.dismissible !== false ? /* @__PURE__ */ jsx18("button", {
5615
+ props.dismissible !== false ? /* @__PURE__ */ jsx19("button", {
5492
5616
  type: "button",
5493
5617
  ...part(`close`),
5494
5618
  "aria-label": ctx.t(`dismiss`),
5495
5619
  onClick: close,
5496
- children: /* @__PURE__ */ jsx18(BuiltinIcon, {
5620
+ children: /* @__PURE__ */ jsx19(BuiltinIcon, {
5497
5621
  slot: "Toast.close"
5498
5622
  })
5499
5623
  }) : null
@@ -5502,10 +5626,10 @@ function ToastNative({ node, props, rootProps, emit, scope }) {
5502
5626
  }
5503
5627
 
5504
5628
  // packages/exponential-ui-react/src/natives/qr.tsx
5505
- import { useEffect as useEffect16, useMemo as useMemo13, useRef as useRef21, useState as useState18 } from "react";
5629
+ import { useEffect as useEffect17, useMemo as useMemo13, useRef as useRef22, useState as useState18 } from "react";
5506
5630
  import { nativeRecipeProps as nativeRecipeProps3, resolveRecipe as resolveRecipe2 } from "@exponential_app/eui";
5507
5631
  import { QR_CORNERS, QR_SCANNER, qrCornerPath, qrFeedColour, qrPaint, qrScanFormats, qrScanReporter } from "@exponential_app/eui/web";
5508
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
5632
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5509
5633
  function recipeOf(ctx, component, part, props) {
5510
5634
  return resolveRecipe2(ctx.theme, { component, part, props: nativeRecipeProps3(component, props, ctx.extensionDefs) }, ctx.mode);
5511
5635
  }
@@ -5532,24 +5656,24 @@ function QrCodeNative({ node, props, rootProps }) {
5532
5656
  "aria-hidden": label ? undefined : `true`,
5533
5657
  "data-empty": paint.matrix ? undefined : `true`,
5534
5658
  children: [
5535
- /* @__PURE__ */ jsx19("span", {
5659
+ /* @__PURE__ */ jsx20("span", {
5536
5660
  ...part(`plate`),
5537
5661
  style: { width: size, height: size, backgroundColor: paint.plate },
5538
- children: paint.matrix ? /* @__PURE__ */ jsx19("svg", {
5662
+ children: paint.matrix ? /* @__PURE__ */ jsx20("svg", {
5539
5663
  viewBox: `0 0 ${paint.modules} ${paint.modules}`,
5540
5664
  width: size,
5541
5665
  height: size,
5542
5666
  shapeRendering: "crispEdges",
5543
5667
  "aria-hidden": "true",
5544
5668
  focusable: "false",
5545
- children: /* @__PURE__ */ jsx19("path", {
5669
+ children: /* @__PURE__ */ jsx20("path", {
5546
5670
  ...part(`module`),
5547
5671
  d: paint.path,
5548
5672
  fill: paint.module
5549
5673
  })
5550
5674
  }) : null
5551
5675
  }),
5552
- label ? /* @__PURE__ */ jsx19("span", {
5676
+ label ? /* @__PURE__ */ jsx20("span", {
5553
5677
  ...part(`label`),
5554
5678
  "aria-hidden": "true",
5555
5679
  children: label
@@ -5564,13 +5688,13 @@ function QrScannerNative({ node, props, rootProps, emit }) {
5564
5688
  const host = ctx.host.qrScanner;
5565
5689
  const formats = qrScanFormats(props.formats);
5566
5690
  const formatsKey = formats.join(`,`);
5567
- const feedRef = useRef21(null);
5691
+ const feedRef = useRef22(null);
5568
5692
  const [live, setLive] = useState18(false);
5569
- const emitRef = useRef21(emit);
5693
+ const emitRef = useRef22(emit);
5570
5694
  emitRef.current = emit;
5571
- const announce = useRef21(ctx.announce);
5695
+ const announce = useRef22(ctx.announce);
5572
5696
  announce.current = ctx.announce;
5573
- useEffect16(() => {
5697
+ useEffect17(() => {
5574
5698
  const feed = feedRef.current;
5575
5699
  if (!host || disabled || !feed) {
5576
5700
  setLive(false);
@@ -5608,19 +5732,19 @@ function QrScannerNative({ node, props, rootProps, emit }) {
5608
5732
  role: "img",
5609
5733
  "aria-label": camera ? label : `${label}, ${ctx.t(`cameraUnavailable`)}`,
5610
5734
  children: [
5611
- /* @__PURE__ */ jsx19("span", {
5735
+ /* @__PURE__ */ jsx20("span", {
5612
5736
  ref: feedRef,
5613
5737
  ...part(`feed`),
5614
5738
  style: { backgroundColor: qrFeedColour(feedColour) },
5615
5739
  "aria-hidden": "true"
5616
5740
  }),
5617
- QR_CORNERS.map((corner) => /* @__PURE__ */ jsx19("svg", {
5741
+ QR_CORNERS.map((corner) => /* @__PURE__ */ jsx20("svg", {
5618
5742
  ...part(`corner`),
5619
5743
  "data-corner": corner,
5620
5744
  viewBox: `0 0 ${QR_SCANNER.cornerLength} ${QR_SCANNER.cornerLength}`,
5621
5745
  "aria-hidden": "true",
5622
5746
  focusable: "false",
5623
- children: /* @__PURE__ */ jsx19("path", {
5747
+ children: /* @__PURE__ */ jsx20("path", {
5624
5748
  d: qrCornerPath(corner, radius),
5625
5749
  fill: "none",
5626
5750
  stroke: "currentColor",
@@ -5629,30 +5753,30 @@ function QrScannerNative({ node, props, rootProps, emit }) {
5629
5753
  strokeLinejoin: "round"
5630
5754
  })
5631
5755
  }, corner)),
5632
- camera ? /* @__PURE__ */ jsx19("span", {
5756
+ camera ? /* @__PURE__ */ jsx20("span", {
5633
5757
  ...part(`scanLine`),
5634
5758
  "aria-hidden": "true"
5635
5759
  }) : /* @__PURE__ */ jsxs16("span", {
5636
5760
  ...part(`placeholder`),
5637
5761
  "aria-hidden": "true",
5638
5762
  children: [
5639
- /* @__PURE__ */ jsx19("span", {
5763
+ /* @__PURE__ */ jsx20("span", {
5640
5764
  ...part(`placeholderIcon`),
5641
- children: /* @__PURE__ */ jsx19(IconGlyph, {
5765
+ children: /* @__PURE__ */ jsx20(IconGlyph, {
5642
5766
  icons: ctx.host.icons,
5643
5767
  name: QR_SCANNER.placeholderIcon,
5644
5768
  width: QR_SCANNER.placeholderIconSize,
5645
5769
  height: QR_SCANNER.placeholderIconSize
5646
5770
  })
5647
5771
  }),
5648
- /* @__PURE__ */ jsx19("span", {
5772
+ /* @__PURE__ */ jsx20("span", {
5649
5773
  children: ctx.t(`cameraUnavailable`)
5650
5774
  })
5651
5775
  ]
5652
5776
  })
5653
5777
  ]
5654
5778
  }),
5655
- hint ? /* @__PURE__ */ jsx19("span", {
5779
+ hint ? /* @__PURE__ */ jsx20("span", {
5656
5780
  ...part(`hint`),
5657
5781
  children: hint
5658
5782
  }) : null
@@ -5661,18 +5785,18 @@ function QrScannerNative({ node, props, rootProps, emit }) {
5661
5785
  }
5662
5786
 
5663
5787
  // packages/exponential-ui-react/src/natives/select.tsx
5664
- import { useEffect as useEffect17, useId as useId6, useMemo as useMemo14, useRef as useRef22, useState as useState19 } from "react";
5788
+ import { useEffect as useEffect18, useId as useId6, useMemo as useMemo14, useRef as useRef23, useState as useState19 } from "react";
5665
5789
  import { Popover as PopoverPrimitive3, Select as SelectPrimitive } from "radix-ui";
5666
5790
  import { OVERLAY_OFFSET as OVERLAY_OFFSET3, OVERLAY_PADDING as OVERLAY_PADDING3 } from "@exponential_app/eui";
5667
5791
  import { boundPath as boundPath3 } from "@exponential_app/eui/web";
5668
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
5792
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5669
5793
  var EMPTY = `\x00xui-empty`;
5670
5794
  var toRadix = (value) => value === `` ? EMPTY : value;
5671
5795
  var fromRadix = (value) => value === EMPTY ? `` : value;
5672
5796
  function useNativeEmptyOption(root, empty) {
5673
- const emptyNow = useRef22(empty);
5797
+ const emptyNow = useRef23(empty);
5674
5798
  emptyNow.current = empty;
5675
- useEffect17(() => {
5799
+ useEffect18(() => {
5676
5800
  if (!root || typeof MutationObserver === `undefined`)
5677
5801
  return;
5678
5802
  const seen = new WeakSet;
@@ -5706,7 +5830,7 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5706
5830
  const raw = props.value;
5707
5831
  const rawIsArray = Array.isArray(raw);
5708
5832
  const [value, setValue] = useBoundState(node, scope, `value`, multiple ? asList(raw) : str(raw));
5709
- const triggerRef = useRef22(null);
5833
+ const triggerRef = useRef23(null);
5710
5834
  const f = useField({ node, domId, props, value, focusRef: triggerRef });
5711
5835
  const disabled = bool(props.disabled) || Boolean(f.form?.disabled);
5712
5836
  const [open, setOpen] = useState19(false);
@@ -5714,7 +5838,7 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5714
5838
  const source = str(props.source);
5715
5839
  const optionsBound = boundPath3(node.props, `options`, scope) !== undefined;
5716
5840
  const [sourced, setSourced] = useState19(null);
5717
- const request = useRef22(0);
5841
+ const request = useRef23(0);
5718
5842
  const askSource = (q) => {
5719
5843
  if (!source || !ctx.host.optionSource)
5720
5844
  return;
@@ -5731,7 +5855,7 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5731
5855
  else
5732
5856
  take(r);
5733
5857
  };
5734
- useEffect17(() => () => {
5858
+ useEffect18(() => () => {
5735
5859
  request.current++;
5736
5860
  }, []);
5737
5861
  const inline = objects(props.options);
@@ -5746,7 +5870,7 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5746
5870
  f.touch();
5747
5871
  emit(`change`, { value: out }, { value: out });
5748
5872
  };
5749
- useEffect17(() => {
5873
+ useEffect18(() => {
5750
5874
  if (!searchable || !open)
5751
5875
  return;
5752
5876
  const t = setTimeout(() => {
@@ -5755,12 +5879,12 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5755
5879
  }, DEBOUNCE_MS);
5756
5880
  return () => clearTimeout(t);
5757
5881
  }, [query, open, searchable, source]);
5758
- useEffect17(() => {
5882
+ useEffect18(() => {
5759
5883
  if (!source || !ctx.host.optionSource || searchable)
5760
5884
  return;
5761
5885
  askSource(``);
5762
5886
  }, [source, ctx.host, searchable]);
5763
- const label = /* @__PURE__ */ jsx20(TextPart, {
5887
+ const label = /* @__PURE__ */ jsx21(TextPart, {
5764
5888
  part: part(`label`),
5765
5889
  text: props.label,
5766
5890
  as: "label",
@@ -5796,26 +5920,26 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5796
5920
  "aria-invalid": f.invalid || undefined,
5797
5921
  "aria-describedby": f.describedBy,
5798
5922
  children: [
5799
- /* @__PURE__ */ jsx20("span", {
5800
- children: chosen ? /* @__PURE__ */ jsx20(SelectPrimitive.Value, {
5923
+ /* @__PURE__ */ jsx21("span", {
5924
+ children: chosen ? /* @__PURE__ */ jsx21(SelectPrimitive.Value, {
5801
5925
  placeholder: chosenLabel,
5802
5926
  children: chosenLabel
5803
- }) : /* @__PURE__ */ jsx20("span", {
5927
+ }) : /* @__PURE__ */ jsx21("span", {
5804
5928
  ...part(`placeholder`),
5805
5929
  children: placeholder
5806
5930
  })
5807
5931
  }),
5808
- /* @__PURE__ */ jsx20(SelectPrimitive.Icon, {
5932
+ /* @__PURE__ */ jsx21(SelectPrimitive.Icon, {
5809
5933
  asChild: true,
5810
- children: /* @__PURE__ */ jsx20(BuiltinIcon, {
5934
+ children: /* @__PURE__ */ jsx21(BuiltinIcon, {
5811
5935
  slot: "Select.trigger"
5812
5936
  })
5813
5937
  })
5814
5938
  ]
5815
5939
  }),
5816
- /* @__PURE__ */ jsx20(SelectPrimitive.Portal, {
5940
+ /* @__PURE__ */ jsx21(SelectPrimitive.Portal, {
5817
5941
  container: ctx.portal ?? undefined,
5818
- children: /* @__PURE__ */ jsx20(SelectPrimitive.Content, {
5942
+ children: /* @__PURE__ */ jsx21(SelectPrimitive.Content, {
5819
5943
  ...part(`content`, open && `open`),
5820
5944
  position: "popper",
5821
5945
  sideOffset: OVERLAY_OFFSET3,
@@ -5824,7 +5948,7 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5824
5948
  style: { minWidth: `var(--radix-select-trigger-width)` },
5825
5949
  children: /* @__PURE__ */ jsxs17(SelectPrimitive.Viewport, {
5826
5950
  children: [
5827
- options.length === 0 ? /* @__PURE__ */ jsx20("div", {
5951
+ options.length === 0 ? /* @__PURE__ */ jsx21("div", {
5828
5952
  ...part(`empty`),
5829
5953
  children: str(props.emptyText) || ctx.t(`noResults`)
5830
5954
  }) : null,
@@ -5833,17 +5957,17 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5833
5957
  disabled: bool(o.disabled),
5834
5958
  ...part(`item`, o.value === value && `selected`, bool(o.disabled) && `disabled`),
5835
5959
  children: [
5836
- o.icon ? /* @__PURE__ */ jsx20(IconGlyph, {
5960
+ o.icon ? /* @__PURE__ */ jsx21(IconGlyph, {
5837
5961
  icons: ctx.host.icons,
5838
5962
  name: o.icon
5839
5963
  }) : null,
5840
- /* @__PURE__ */ jsx20(SelectPrimitive.ItemText, {
5964
+ /* @__PURE__ */ jsx21(SelectPrimitive.ItemText, {
5841
5965
  children: str(o.label)
5842
5966
  }),
5843
- /* @__PURE__ */ jsx20(SelectPrimitive.ItemIndicator, {
5967
+ /* @__PURE__ */ jsx21(SelectPrimitive.ItemIndicator, {
5844
5968
  ...part(`check`),
5845
5969
  className: `${part(`check`).className} xui-Select-check`,
5846
- children: /* @__PURE__ */ jsx20(BuiltinIcon, {
5970
+ children: /* @__PURE__ */ jsx21(BuiltinIcon, {
5847
5971
  slot: "Select.check",
5848
5972
  size: 16
5849
5973
  })
@@ -5856,14 +5980,14 @@ function SelectNative({ node, props, rootProps, emit, scope, domId }) {
5856
5980
  })
5857
5981
  ]
5858
5982
  }),
5859
- /* @__PURE__ */ jsx20(FieldErrors, {
5983
+ /* @__PURE__ */ jsx21(FieldErrors, {
5860
5984
  part,
5861
5985
  field: f
5862
5986
  })
5863
5987
  ]
5864
5988
  });
5865
5989
  }
5866
- return /* @__PURE__ */ jsx20(Combobox, {
5990
+ return /* @__PURE__ */ jsx21(Combobox, {
5867
5991
  ...{ node, props, rootProps, part, id, listId, multiple, searchable, placeholder, options, value, commit, open, setOpen, query, setQuery, disabled, triggerRef, label, source },
5868
5992
  localFilter: !optionsBound && !source,
5869
5993
  field: f
@@ -5874,7 +5998,7 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
5874
5998
  const selected = multiple ? value : value ? [value] : [];
5875
5999
  const chosen = options.filter((o) => selected.includes(o.value));
5876
6000
  const shown = useMemo14(() => query && localFilter ? options.filter((o) => str(o.label).toLowerCase().includes(query.toLowerCase())) : options, [options, query, localFilter]);
5877
- const listRef = useRef22(null);
6001
+ const listRef = useRef23(null);
5878
6002
  const pick = (i) => {
5879
6003
  const o = shown[i];
5880
6004
  if (!o || bool(o.disabled))
@@ -5887,21 +6011,21 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
5887
6011
  }
5888
6012
  };
5889
6013
  const nav = useListNavigation({ count: shown.length, isDisabled: (i) => bool(shown[i]?.disabled), labelOf: (i) => str(shown[i]?.label), onPick: pick, typeahead: !searchable });
5890
- useEffect17(() => {
6014
+ useEffect18(() => {
5891
6015
  if (open) {
5892
6016
  const i = shown.findIndex((o) => selected.includes(o.value));
5893
6017
  nav.setActive(i >= 0 ? i : shown.findIndex((o) => !bool(o.disabled)));
5894
6018
  } else
5895
6019
  setQuery(``);
5896
6020
  }, [open]);
5897
- useEffect17(() => {
6021
+ useEffect18(() => {
5898
6022
  if (!searchable || !open)
5899
6023
  return;
5900
6024
  nav.setActive(shown.findIndex((o) => !bool(o.disabled)));
5901
6025
  }, [query]);
5902
6026
  const optionId = (i) => `${listId}-${i}`;
5903
6027
  const activeId = nav.active >= 0 && nav.active < shown.length ? optionId(nav.active) : undefined;
5904
- useEffect17(() => {
6028
+ useEffect18(() => {
5905
6029
  if (activeId)
5906
6030
  listRef.current?.querySelector(`[id="${activeId}"]`)?.scrollIntoView?.({ block: `nearest` });
5907
6031
  }, [activeId]);
@@ -5932,18 +6056,18 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
5932
6056
  }
5933
6057
  },
5934
6058
  children: [
5935
- /* @__PURE__ */ jsx20("span", {
5936
- children: chosen.length ? chosen.map((o) => str(o.label)).join(`, `) : /* @__PURE__ */ jsx20("span", {
6059
+ /* @__PURE__ */ jsx21("span", {
6060
+ children: chosen.length ? chosen.map((o) => str(o.label)).join(`, `) : /* @__PURE__ */ jsx21("span", {
5937
6061
  ...part(`placeholder`),
5938
6062
  children: placeholder
5939
6063
  })
5940
6064
  }),
5941
- /* @__PURE__ */ jsx20(BuiltinIcon, {
6065
+ /* @__PURE__ */ jsx21(BuiltinIcon, {
5942
6066
  slot: "Select.trigger"
5943
6067
  })
5944
6068
  ]
5945
6069
  }),
5946
- /* @__PURE__ */ jsx20(PopoverPrimitive3.Portal, {
6070
+ /* @__PURE__ */ jsx21(PopoverPrimitive3.Portal, {
5947
6071
  container: ctx.portal ?? undefined,
5948
6072
  children: /* @__PURE__ */ jsxs17(PopoverPrimitive3.Content, {
5949
6073
  ...part(`content`, open && `open`),
@@ -5963,11 +6087,11 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
5963
6087
  searchable ? /* @__PURE__ */ jsxs17("div", {
5964
6088
  className: "xui-Select-searchbox",
5965
6089
  children: [
5966
- /* @__PURE__ */ jsx20(BuiltinIcon, {
6090
+ /* @__PURE__ */ jsx21(BuiltinIcon, {
5967
6091
  slot: "Select.search",
5968
6092
  size: 16
5969
6093
  }),
5970
- /* @__PURE__ */ jsx20("input", {
6094
+ /* @__PURE__ */ jsx21("input", {
5971
6095
  ...part(`search`),
5972
6096
  className: `${part(`search`).className} xui-Select-search`,
5973
6097
  role: "combobox",
@@ -5994,7 +6118,7 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
5994
6118
  className: "xui-Select-listbox",
5995
6119
  onKeyDown: searchable ? undefined : nav.onKeyDown,
5996
6120
  children: [
5997
- shown.length === 0 ? /* @__PURE__ */ jsx20("div", {
6121
+ shown.length === 0 ? /* @__PURE__ */ jsx21("div", {
5998
6122
  ...part(`empty`),
5999
6123
  children: str(props.emptyText) || ctx.t(`noResults`)
6000
6124
  }) : null,
@@ -6012,17 +6136,17 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
6012
6136
  onMouseDown: (e) => e.preventDefault(),
6013
6137
  onClick: () => pick(i),
6014
6138
  children: [
6015
- o.icon ? /* @__PURE__ */ jsx20(IconGlyph, {
6139
+ o.icon ? /* @__PURE__ */ jsx21(IconGlyph, {
6016
6140
  icons: ctx.host.icons,
6017
6141
  name: o.icon
6018
6142
  }) : null,
6019
- /* @__PURE__ */ jsx20("span", {
6143
+ /* @__PURE__ */ jsx21("span", {
6020
6144
  children: str(o.label)
6021
6145
  }),
6022
- isSel ? /* @__PURE__ */ jsx20("span", {
6146
+ isSel ? /* @__PURE__ */ jsx21("span", {
6023
6147
  ...part(`check`),
6024
6148
  className: `${part(`check`).className} xui-Select-check`,
6025
- children: /* @__PURE__ */ jsx20(BuiltinIcon, {
6149
+ children: /* @__PURE__ */ jsx21(BuiltinIcon, {
6026
6150
  slot: "Select.check",
6027
6151
  size: 16
6028
6152
  })
@@ -6037,7 +6161,7 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
6037
6161
  })
6038
6162
  ]
6039
6163
  }),
6040
- /* @__PURE__ */ jsx20(FieldErrors, {
6164
+ /* @__PURE__ */ jsx21(FieldErrors, {
6041
6165
  part,
6042
6166
  field
6043
6167
  })
@@ -6046,14 +6170,14 @@ function Combobox({ props, rootProps, part, id, listId, multiple, searchable, pl
6046
6170
  }
6047
6171
 
6048
6172
  // packages/exponential-ui-react/src/natives/table.tsx
6049
- import { useCallback as useCallback9, useContext as useContext5, useEffect as useEffect18, useMemo as useMemo15, useRef as useRef23, useState as useState20 } from "react";
6173
+ import { useCallback as useCallback9, useContext as useContext5, useEffect as useEffect19, useMemo as useMemo15, useRef as useRef24, useState as useState20 } from "react";
6050
6174
  import { Checkbox as CheckboxPrimitive2 } from "radix-ui";
6051
6175
  import { tableRowKeys, WINDOW_THRESHOLD as WINDOW_THRESHOLD2 } from "@exponential_app/eui";
6052
6176
  import { boundPath as boundPath4, getPointer as getPointer2, setPointer as setPointer2, LITERAL_ROWS_ROOT as LITERAL_ROWS_ROOT2 } from "@exponential_app/eui/web";
6053
6177
  import { partClass as partClass3 } from "@exponential_app/eui/web";
6054
6178
  import { displayString as displayString2 } from "@exponential_app/eui";
6055
- import { sortRows } from "@exponential_app/eui/web";
6056
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
6179
+ import { sortRows, tableMinWidth, tableTemplate } from "@exponential_app/eui/web";
6180
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
6057
6181
  var CURRENCY_CODE = /^[A-Za-z]{3}$/;
6058
6182
  var cellNumber = (v) => typeof v === `number` ? v : typeof v === `string` && v.trim() !== `` ? Number(v) : NaN;
6059
6183
  function TableNative({ node, props, rootProps, emit, scope, domId }) {
@@ -6072,7 +6196,8 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6072
6196
  const rowKeys = useMemo15(() => tableRowKeys(rows, rowKey), [rows, rowKey]);
6073
6197
  const keyOf = (_row, i) => rowKeys[i] ?? String(i);
6074
6198
  const order = useMemo15(() => sortBound ? rows.map((_, i) => i) : sortRows(rows, sort, columns.find((c) => c.key === sort?.key), ctx.locale), [rows, sort, sortBound, columns, ctx.locale]);
6075
- const template = [selectable === `multiple` ? `var(--xui-control-checkbox, 16px)` : null, ...columns.map((c) => c.width ? `${c.width}px` : `minmax(0, 1fr)`)].filter(Boolean).join(` `);
6199
+ const template = tableTemplate(columns, selectable === `multiple`);
6200
+ const minWidth = tableMinWidth(columns, selectable === `multiple`);
6076
6201
  const cycle = (c) => {
6077
6202
  const next = sort?.key === c.key && sort.direction === `asc` ? { key: c.key, direction: `desc` } : { key: c.key, direction: `asc` };
6078
6203
  setSort(next);
@@ -6090,9 +6215,9 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6090
6215
  const [focusKey, setFocusKey] = useState20(null);
6091
6216
  const orderKeys = order.map((i) => keyOf(rows[i], i));
6092
6217
  const stopKey = focusKey !== null && orderKeys.includes(focusKey) ? focusKey : orderKeys.find((k) => selected.includes(k)) ?? orderKeys[0] ?? null;
6093
- const bodyRef = useRef23(null);
6094
- const windowRef = useRef23(null);
6095
- const pendingFocus = useRef23(null);
6218
+ const bodyRef = useRef24(null);
6219
+ const windowRef = useRef24(null);
6220
+ const pendingFocus = useRef24(null);
6096
6221
  const focusRow = useCallback9((key) => {
6097
6222
  const k = `[role="row"][data-key="${typeof CSS !== `undefined` && CSS.escape ? CSS.escape(key) : key.replace(/"/g, `\\"`)}"]`;
6098
6223
  return bodyRef.current?.querySelector(`:scope > ${k}, :scope > .xui-list-window > .xui-list-item > ${k}`) ?? null;
@@ -6111,7 +6236,7 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6111
6236
  windowRef.current?.scrollToIndex(clamped);
6112
6237
  }
6113
6238
  };
6114
- useEffect18(() => ctx.registerScroller(domId, (index, align) => {
6239
+ useEffect19(() => ctx.registerScroller(domId, (index, align) => {
6115
6240
  const pos = order.indexOf(index);
6116
6241
  if (pos < 0)
6117
6242
  return;
@@ -6143,19 +6268,19 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6143
6268
  case `relativeTime`:
6144
6269
  return missing ? `` : ctx.formatter.relativeTime(v, ctx.now());
6145
6270
  case `boolean`:
6146
- return v ? /* @__PURE__ */ jsx21(BuiltinIcon, {
6271
+ return v ? /* @__PURE__ */ jsx22(BuiltinIcon, {
6147
6272
  slot: "Checkbox.check",
6148
6273
  size: 16
6149
- }) : /* @__PURE__ */ jsx21("span", {
6274
+ }) : /* @__PURE__ */ jsx22("span", {
6150
6275
  className: "xui-sr-only",
6151
6276
  children: "—"
6152
6277
  });
6153
6278
  case `badge`:
6154
- return v === undefined || v === null || v === `` ? null : /* @__PURE__ */ jsx21("span", {
6279
+ return v === undefined || v === null || v === `` ? null : /* @__PURE__ */ jsx22("span", {
6155
6280
  className: `${ctx.compiled.scope} ${partClass3(`Badge`, `root`)} xui-table-badge`,
6156
6281
  "data-xui-part": "Badge/root",
6157
6282
  "data-m-variant": "secondary",
6158
- children: /* @__PURE__ */ jsx21("span", {
6283
+ children: /* @__PURE__ */ jsx22("span", {
6159
6284
  className: `${ctx.compiled.scope} ${partClass3(`Badge`, `label`)}`,
6160
6285
  "data-xui-part": "Badge/label",
6161
6286
  "data-m-variant": "secondary",
@@ -6167,7 +6292,7 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6167
6292
  if (!slot)
6168
6293
  return null;
6169
6294
  const key = keyOf(row, index);
6170
- return /* @__PURE__ */ jsx21(RowScope, {
6295
+ return /* @__PURE__ */ jsx22(RowScope, {
6171
6296
  rowsPath,
6172
6297
  row: rowsPath ? row : literalEdits[key] ?? row,
6173
6298
  rowKey: key,
@@ -6225,55 +6350,60 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6225
6350
  }
6226
6351
  },
6227
6352
  children: [
6228
- selectable === `multiple` ? /* @__PURE__ */ jsx21("div", {
6353
+ selectable === `multiple` ? /* @__PURE__ */ jsx22("div", {
6229
6354
  role: "gridcell",
6230
6355
  className: "xui-table-check",
6231
- children: /* @__PURE__ */ jsx21(CheckboxPrimitive2.Root, {
6356
+ children: /* @__PURE__ */ jsx22(CheckboxPrimitive2.Root, {
6232
6357
  ...part.at(`checkbox`, key, isSel && `checked`),
6233
6358
  className: `${part(`checkbox`).className} xui-Checkbox-box`,
6234
6359
  checked: isSel,
6235
6360
  "aria-label": ctx.t(`selectRow`),
6236
6361
  onClick: (e) => e.stopPropagation(),
6237
6362
  onCheckedChange: (next) => select(next === true ? [...selected, key] : selected.filter((k) => k !== key)),
6238
- children: /* @__PURE__ */ jsx21(CheckboxPrimitive2.Indicator, {
6363
+ children: /* @__PURE__ */ jsx22(CheckboxPrimitive2.Indicator, {
6239
6364
  className: "xui-Checkbox-check",
6240
- children: /* @__PURE__ */ jsx21(BuiltinIcon, {
6365
+ children: /* @__PURE__ */ jsx22(BuiltinIcon, {
6241
6366
  slot: "Checkbox.check"
6242
6367
  })
6243
6368
  })
6244
6369
  })
6245
6370
  }) : null,
6246
- columns.map((c, ci) => /* @__PURE__ */ jsx21("div", {
6371
+ columns.map((c, ci) => /* @__PURE__ */ jsx22("div", {
6247
6372
  role: interactive ? `gridcell` : `cell`,
6248
6373
  ...part.atWith(`cell`, `${key}.${ci}`, { align: c.align ?? `start` }),
6249
6374
  "data-type": c.type ?? `text`,
6250
- children: cell(c, row, index)
6375
+ "data-truncate": c.truncate ? `true` : undefined,
6376
+ children: c.truncate ? /* @__PURE__ */ jsx22("span", {
6377
+ className: "xui-table-text",
6378
+ children: cell(c, row, index)
6379
+ }) : cell(c, row, index)
6251
6380
  }, c.key))
6252
6381
  ]
6253
6382
  }, key);
6254
6383
  };
6255
- const header = /* @__PURE__ */ jsx21("div", {
6384
+ const header = /* @__PURE__ */ jsx22("div", {
6256
6385
  role: "rowgroup",
6257
6386
  ...part(`header`),
6258
6387
  "data-sticky": bool(props.stickyHeader) ? `true` : undefined,
6388
+ style: { minWidth },
6259
6389
  children: /* @__PURE__ */ jsxs18("div", {
6260
6390
  role: "row",
6261
6391
  "aria-rowindex": 1,
6262
6392
  className: "xui-table-row",
6263
6393
  style: { gridTemplateColumns: template },
6264
6394
  children: [
6265
- selectable === `multiple` ? /* @__PURE__ */ jsx21("div", {
6395
+ selectable === `multiple` ? /* @__PURE__ */ jsx22("div", {
6266
6396
  role: "columnheader",
6267
6397
  className: "xui-table-check",
6268
- children: /* @__PURE__ */ jsx21(CheckboxPrimitive2.Root, {
6398
+ children: /* @__PURE__ */ jsx22(CheckboxPrimitive2.Root, {
6269
6399
  ...part.at(`checkbox`, `header`, allSelected && `checked`),
6270
6400
  className: `${part(`checkbox`).className} xui-Checkbox-box`,
6271
6401
  checked: allSelected ? true : someSelected ? `indeterminate` : false,
6272
6402
  "aria-label": ctx.t(`selectAll`),
6273
6403
  onCheckedChange: (next) => select(next === true ? allKeys : []),
6274
- children: /* @__PURE__ */ jsx21(CheckboxPrimitive2.Indicator, {
6404
+ children: /* @__PURE__ */ jsx22(CheckboxPrimitive2.Indicator, {
6275
6405
  className: "xui-Checkbox-check",
6276
- children: /* @__PURE__ */ jsx21(BuiltinIcon, {
6406
+ children: /* @__PURE__ */ jsx22(BuiltinIcon, {
6277
6407
  slot: "Checkbox.check"
6278
6408
  })
6279
6409
  })
@@ -6282,7 +6412,7 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6282
6412
  columns.map((c, ci) => {
6283
6413
  const active = sort?.key === c.key ? sort.direction : null;
6284
6414
  const ariaSort = active === `asc` ? `ascending` : active === `desc` ? `descending` : c.sortable ? `none` : undefined;
6285
- return /* @__PURE__ */ jsx21("div", {
6415
+ return /* @__PURE__ */ jsx22("div", {
6286
6416
  role: "columnheader",
6287
6417
  "aria-sort": ariaSort,
6288
6418
  ...part.atWith(`headerCell`, ci, { align: c.align ?? `start` }),
@@ -6292,19 +6422,19 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6292
6422
  "aria-label": phrase(ctx, active === `asc` ? `sortByDescending` : `sortByAscending`, { name: str(c.label) }, () => `${str(c.label)}: ${ctx.t(active === `asc` ? `sortDescending` : `sortAscending`)}`),
6293
6423
  onClick: () => cycle(c),
6294
6424
  children: [
6295
- /* @__PURE__ */ jsx21("span", {
6425
+ /* @__PURE__ */ jsx22("span", {
6296
6426
  children: str(c.label)
6297
6427
  }),
6298
- /* @__PURE__ */ jsx21("span", {
6428
+ /* @__PURE__ */ jsx22("span", {
6299
6429
  ...part(`sortIcon`),
6300
6430
  "data-direction": active ?? undefined,
6301
6431
  "aria-hidden": "true",
6302
- children: active ? /* @__PURE__ */ jsx21(BuiltinIcon, {
6432
+ children: active ? /* @__PURE__ */ jsx22(BuiltinIcon, {
6303
6433
  slot: `Table.sortIcon.${active}`
6304
6434
  }) : null
6305
6435
  })
6306
6436
  ]
6307
- }) : /* @__PURE__ */ jsx21("span", {
6437
+ }) : /* @__PURE__ */ jsx22("span", {
6308
6438
  children: str(c.label)
6309
6439
  })
6310
6440
  }, c.key);
@@ -6323,19 +6453,20 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6323
6453
  "data-windowed": windowed ? `true` : undefined,
6324
6454
  children: [
6325
6455
  header,
6326
- /* @__PURE__ */ jsx21("div", {
6456
+ /* @__PURE__ */ jsx22("div", {
6327
6457
  role: "rowgroup",
6328
6458
  ...part(`body`),
6329
6459
  className: `${part(`body`).className} xui-table-body`,
6460
+ style: { minWidth },
6330
6461
  ref: bodyRef,
6331
- children: rows.length === 0 ? /* @__PURE__ */ jsx21("div", {
6462
+ children: rows.length === 0 ? /* @__PURE__ */ jsx22("div", {
6332
6463
  role: "row",
6333
- children: /* @__PURE__ */ jsx21("div", {
6464
+ children: /* @__PURE__ */ jsx22("div", {
6334
6465
  role: "cell",
6335
6466
  ...part(`empty`),
6336
6467
  children: str(props.emptyText) || ctx.t(`noResults`)
6337
6468
  })
6338
- }) : windowed ? /* @__PURE__ */ jsx21(WindowedList, {
6469
+ }) : windowed ? /* @__PURE__ */ jsx22(WindowedList, {
6339
6470
  ref: windowRef,
6340
6471
  count: order.length,
6341
6472
  itemKey: (i) => keyOf(rows[order[i]], order[i]),
@@ -6344,12 +6475,12 @@ function TableNative({ node, props, rootProps, emit, scope, domId }) {
6344
6475
  renderItem: renderRow
6345
6476
  }) : order.map((_, pos) => renderRow(pos))
6346
6477
  }),
6347
- caption ? /* @__PURE__ */ jsx21("div", {
6478
+ caption ? /* @__PURE__ */ jsx22("div", {
6348
6479
  ...part(`caption`),
6349
6480
  id: `${domId}.caption`,
6350
6481
  children: caption
6351
6482
  }) : null,
6352
- selectable === `multiple` && selected.length ? /* @__PURE__ */ jsx21("span", {
6483
+ selectable === `multiple` && selected.length ? /* @__PURE__ */ jsx22("span", {
6353
6484
  className: "xui-sr-only",
6354
6485
  "aria-live": "polite",
6355
6486
  children: ctx.t(`selectedCount`, { count: selected.length })
@@ -6373,13 +6504,13 @@ function RowScope({ rowsPath, row, rowKey, index, tableId, node, onLiteralEdit }
6373
6504
  };
6374
6505
  return deriveContext(ctx, { setData }, data);
6375
6506
  }, [ctx, rowsPath, literalPath, row, rowKey, onLiteralEdit]);
6376
- return /* @__PURE__ */ jsx21(SurfaceContext.Provider, {
6507
+ return /* @__PURE__ */ jsx22(SurfaceContext.Provider, {
6377
6508
  value: view,
6378
- children: /* @__PURE__ */ jsx21(ScopeContext.Provider, {
6509
+ children: /* @__PURE__ */ jsx22(ScopeContext.Provider, {
6379
6510
  value: rowsPath ? `${rowsPath}/${index}` : literalPath,
6380
- children: /* @__PURE__ */ jsx21(InstanceContext.Provider, {
6511
+ children: /* @__PURE__ */ jsx22(InstanceContext.Provider, {
6381
6512
  value: `${outer}.${rowKey}`,
6382
- children: /* @__PURE__ */ jsx21(NodeView, {
6513
+ children: /* @__PURE__ */ jsx22(NodeView, {
6383
6514
  node
6384
6515
  })
6385
6516
  })
@@ -6391,25 +6522,25 @@ function RowScope({ rowsPath, row, rowKey, index, tableId, node, onLiteralEdit }
6391
6522
  import { displayString as displayString3 } from "@exponential_app/eui";
6392
6523
 
6393
6524
  // packages/exponential-ui-react/src/markdown.tsx
6394
- import { Fragment as Fragment6, createElement, useMemo as useMemo16 } from "react";
6525
+ import { Fragment as Fragment7, createElement, useMemo as useMemo16 } from "react";
6395
6526
  import { linkHref as linkHref3, mediaRequestOf, parseMarkdown } from "@exponential_app/eui/web";
6396
6527
  import { MAX_LINK_NESTING, MAX_LINK_DEST, MAX_BLOCK_NESTING, linkAt, wholeImage, parseList } from "@exponential_app/eui/web";
6397
- import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
6528
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
6398
6529
  function MarkdownImage({ host, src, alt }) {
6399
6530
  const media = useMediaSource(host, src);
6400
6531
  if (mediaRequestOf(host, src) === null)
6401
- return alt ? /* @__PURE__ */ jsx22("p", {
6532
+ return alt ? /* @__PURE__ */ jsx23("p", {
6402
6533
  className: "xui-Markdown-paragraph",
6403
6534
  children: alt
6404
6535
  }) : null;
6405
- return /* @__PURE__ */ jsx22("div", {
6536
+ return /* @__PURE__ */ jsx23("div", {
6406
6537
  className: "xui-Markdown-image",
6407
6538
  role: "img",
6408
6539
  "aria-label": alt,
6409
- children: media.url && !media.error ? /* @__PURE__ */ jsx22("img", {
6540
+ children: media.url && !media.error ? /* @__PURE__ */ jsx23("img", {
6410
6541
  alt: "",
6411
6542
  src: media.url
6412
- }) : /* @__PURE__ */ jsx22("span", {
6543
+ }) : /* @__PURE__ */ jsx23("span", {
6413
6544
  className: "xui-Markdown-imageAlt",
6414
6545
  children: alt
6415
6546
  })
@@ -6420,7 +6551,7 @@ function MarkdownLink({ host, href, children }) {
6420
6551
  e.preventDefault();
6421
6552
  host.openUrl(href);
6422
6553
  } : undefined;
6423
- return /* @__PURE__ */ jsx22("a", {
6554
+ return /* @__PURE__ */ jsx23("a", {
6424
6555
  className: "xui-Markdown-link",
6425
6556
  href,
6426
6557
  target: "_blank",
@@ -6435,30 +6566,30 @@ function inline(nodes, host) {
6435
6566
  return n;
6436
6567
  switch (n.type) {
6437
6568
  case `code`:
6438
- return /* @__PURE__ */ jsx22("code", {
6569
+ return /* @__PURE__ */ jsx23("code", {
6439
6570
  className: "xui-Markdown-code",
6440
6571
  children: n.text
6441
6572
  }, k);
6442
6573
  case `strong`:
6443
- return /* @__PURE__ */ jsx22("strong", {
6574
+ return /* @__PURE__ */ jsx23("strong", {
6444
6575
  children: inline(n.children, host)
6445
6576
  }, k);
6446
6577
  case `em`:
6447
- return /* @__PURE__ */ jsx22("em", {
6578
+ return /* @__PURE__ */ jsx23("em", {
6448
6579
  children: inline(n.children, host)
6449
6580
  }, k);
6450
6581
  case `del`:
6451
- return /* @__PURE__ */ jsx22("del", {
6582
+ return /* @__PURE__ */ jsx23("del", {
6452
6583
  children: n.text
6453
6584
  }, k);
6454
6585
  case `link`: {
6455
6586
  const href = linkHref3(host, n.dest);
6456
6587
  const label = inline(n.children, host);
6457
- return href ? /* @__PURE__ */ jsx22(MarkdownLink, {
6588
+ return href ? /* @__PURE__ */ jsx23(MarkdownLink, {
6458
6589
  host,
6459
6590
  href,
6460
6591
  children: label
6461
- }, k) : /* @__PURE__ */ jsx22("span", {
6592
+ }, k) : /* @__PURE__ */ jsx23("span", {
6462
6593
  className: "xui-Markdown-link",
6463
6594
  "data-denied": "",
6464
6595
  children: label
@@ -6472,49 +6603,49 @@ function renderList(list, host, key) {
6472
6603
  className: "xui-Markdown-listItem",
6473
6604
  "data-task": item.task === undefined ? undefined : item.task ? `done` : `todo`,
6474
6605
  children: [
6475
- item.task === undefined ? null : /* @__PURE__ */ jsx22("input", {
6606
+ item.task === undefined ? null : /* @__PURE__ */ jsx23("input", {
6476
6607
  type: "checkbox",
6477
6608
  checked: item.task,
6478
6609
  readOnly: true
6479
6610
  }),
6480
6611
  item.task === undefined ? null : ` `,
6481
6612
  inline(item.content, host),
6482
- item.children.map((c, ci) => /* @__PURE__ */ jsx22(Fragment6, {
6613
+ item.children.map((c, ci) => /* @__PURE__ */ jsx23(Fragment7, {
6483
6614
  children: renderList(c, host, ci)
6484
6615
  }, `c${ci}`))
6485
6616
  ]
6486
6617
  }, n));
6487
- return list.ordered ? /* @__PURE__ */ jsx22("ol", {
6618
+ return list.ordered ? /* @__PURE__ */ jsx23("ol", {
6488
6619
  children: items
6489
- }, key) : /* @__PURE__ */ jsx22("ul", {
6620
+ }, key) : /* @__PURE__ */ jsx23("ul", {
6490
6621
  children: items
6491
6622
  }, key);
6492
6623
  }
6493
6624
  function block(b, host, key) {
6494
6625
  switch (b.type) {
6495
6626
  case `paragraph`:
6496
- return /* @__PURE__ */ jsx22("p", {
6627
+ return /* @__PURE__ */ jsx23("p", {
6497
6628
  className: "xui-Markdown-paragraph",
6498
6629
  children: inline(b.children, host)
6499
6630
  }, key);
6500
6631
  case `image`:
6501
- return /* @__PURE__ */ jsx22(MarkdownImage, {
6632
+ return /* @__PURE__ */ jsx23(MarkdownImage, {
6502
6633
  host,
6503
6634
  src: b.src,
6504
6635
  alt: b.alt
6505
6636
  }, key);
6506
6637
  case `codeBlock`:
6507
- return /* @__PURE__ */ jsx22("pre", {
6638
+ return /* @__PURE__ */ jsx23("pre", {
6508
6639
  className: "xui-Markdown-codeBlock",
6509
6640
  "data-lang": b.lang,
6510
- children: /* @__PURE__ */ jsx22("code", {
6641
+ children: /* @__PURE__ */ jsx23("code", {
6511
6642
  children: b.text
6512
6643
  })
6513
6644
  }, key);
6514
6645
  case `heading`:
6515
6646
  return createElement(`h${Math.min(b.level, 6)}`, { key, className: `xui-Markdown-heading`, "data-level": b.level }, ...inline(b.children, host));
6516
6647
  case `quote`:
6517
- return /* @__PURE__ */ jsx22("blockquote", {
6648
+ return /* @__PURE__ */ jsx23("blockquote", {
6518
6649
  className: "xui-Markdown-quote",
6519
6650
  children: blocks(b.children, host)
6520
6651
  }, key);
@@ -6524,17 +6655,17 @@ function block(b, host, key) {
6524
6655
  return /* @__PURE__ */ jsxs19("table", {
6525
6656
  className: "xui-Markdown-table",
6526
6657
  children: [
6527
- /* @__PURE__ */ jsx22("thead", {
6528
- children: /* @__PURE__ */ jsx22("tr", {
6529
- children: b.head.map((h, c) => /* @__PURE__ */ jsx22("th", {
6658
+ /* @__PURE__ */ jsx23("thead", {
6659
+ children: /* @__PURE__ */ jsx23("tr", {
6660
+ children: b.head.map((h, c) => /* @__PURE__ */ jsx23("th", {
6530
6661
  style: b.align[c] ? { textAlign: b.align[c] } : undefined,
6531
6662
  children: inline(h, host)
6532
6663
  }, c))
6533
6664
  })
6534
6665
  }),
6535
- /* @__PURE__ */ jsx22("tbody", {
6536
- children: b.rows.map((r, ri) => /* @__PURE__ */ jsx22("tr", {
6537
- children: r.map((cell, c) => /* @__PURE__ */ jsx22("td", {
6666
+ /* @__PURE__ */ jsx23("tbody", {
6667
+ children: b.rows.map((r, ri) => /* @__PURE__ */ jsx23("tr", {
6668
+ children: r.map((cell, c) => /* @__PURE__ */ jsx23("td", {
6538
6669
  style: b.align[c] ? { textAlign: b.align[c] } : undefined,
6539
6670
  children: inline(cell, host)
6540
6671
  }, c))
@@ -6543,11 +6674,11 @@ function block(b, host, key) {
6543
6674
  ]
6544
6675
  }, key);
6545
6676
  case `rule`:
6546
- return /* @__PURE__ */ jsx22("hr", {}, key);
6677
+ return /* @__PURE__ */ jsx23("hr", {}, key);
6547
6678
  }
6548
6679
  }
6549
6680
  function blocks(tree, host) {
6550
- return tree.map((b, k) => /* @__PURE__ */ jsx22(Fragment6, {
6681
+ return tree.map((b, k) => /* @__PURE__ */ jsx23(Fragment7, {
6551
6682
  children: block(b, host, k)
6552
6683
  }, k));
6553
6684
  }
@@ -6556,14 +6687,14 @@ function renderMarkdown(text, host = {}) {
6556
6687
  }
6557
6688
  function BuiltinMarkdown({ text, className, host }) {
6558
6689
  const tree = useMemo16(() => renderMarkdown(text, host), [text, host]);
6559
- return /* @__PURE__ */ jsx22("div", {
6690
+ return /* @__PURE__ */ jsx23("div", {
6560
6691
  className: className ? `xui-md ${className}` : `xui-md`,
6561
6692
  children: tree
6562
6693
  });
6563
6694
  }
6564
6695
 
6565
6696
  // packages/exponential-ui-react/src/natives/text.tsx
6566
- import { jsx as jsx23 } from "react/jsx-runtime";
6697
+ import { jsx as jsx24 } from "react/jsx-runtime";
6567
6698
  function TextNative({ props, rootProps }) {
6568
6699
  const lines = num(props.lines, 0);
6569
6700
  const align = props.align === `end` ? `end` : props.align === `center` ? `center` : props.align === `start` ? `start` : undefined;
@@ -6571,7 +6702,7 @@ function TextNative({ props, rootProps }) {
6571
6702
  if (lines > 1)
6572
6703
  style.WebkitLineClamp = lines;
6573
6704
  const live = props.live === `polite` || props.live === `assertive` ? props.live : undefined;
6574
- return /* @__PURE__ */ jsx23("span", {
6705
+ return /* @__PURE__ */ jsx24("span", {
6575
6706
  ...rootProps,
6576
6707
  "aria-live": live,
6577
6708
  "aria-atomic": live ? true : undefined,
@@ -6588,14 +6719,14 @@ function MarkdownNative({ props, rootProps }) {
6588
6719
  const text = displayString3(props.text);
6589
6720
  const Host = ctx.host.Markdown;
6590
6721
  const lines = num(props.lines, 0);
6591
- return /* @__PURE__ */ jsx23("div", {
6722
+ return /* @__PURE__ */ jsx24("div", {
6592
6723
  ...rootProps,
6593
6724
  "data-lines": lines > 0 ? lines : undefined,
6594
6725
  style: mergeStyle(rootProps, lines > 0 ? { WebkitLineClamp: lines } : undefined),
6595
- children: Host ? /* @__PURE__ */ jsx23(Host, {
6726
+ children: Host ? /* @__PURE__ */ jsx24(Host, {
6596
6727
  text,
6597
6728
  className: "xui-md"
6598
- }) : /* @__PURE__ */ jsx23(BuiltinMarkdown, {
6729
+ }) : /* @__PURE__ */ jsx24(BuiltinMarkdown, {
6599
6730
  text,
6600
6731
  host: ctx.host
6601
6732
  })
@@ -6605,18 +6736,190 @@ function IconNative({ props, rootProps }) {
6605
6736
  const ctx = useSurfaceContext();
6606
6737
  const name = str(props.name, `ui-icon-placeholder`);
6607
6738
  const label = str(props.label);
6608
- return /* @__PURE__ */ jsx23("span", {
6739
+ return /* @__PURE__ */ jsx24("span", {
6609
6740
  ...rootProps,
6610
6741
  role: label ? `img` : undefined,
6611
6742
  "aria-label": label || undefined,
6612
6743
  "aria-hidden": label ? undefined : true,
6613
- children: /* @__PURE__ */ jsx23(IconGlyph, {
6744
+ children: /* @__PURE__ */ jsx24(IconGlyph, {
6614
6745
  icons: ctx.host.icons,
6615
6746
  name
6616
6747
  })
6617
6748
  });
6618
6749
  }
6619
6750
 
6751
+ // packages/exponential-ui-react/src/natives/zoomable-image.tsx
6752
+ import { useEffect as useEffect20, useMemo as useMemo17, useState as useState21 } from "react";
6753
+ import { DropdownMenu as MenuPrimitive2 } from "radix-ui";
6754
+ import { MEDIA_INTRINSIC_WIDTH as MEDIA_INTRINSIC_WIDTH2, OVERLAY_OFFSET as OVERLAY_OFFSET4, OVERLAY_PADDING as OVERLAY_PADDING4, ZOOM } from "@exponential_app/eui";
6755
+ import { ZOOMABLE_IMAGE_NATIVE_TRANSITION, zoomBoxAspect, zoomableImageLayout } from "@exponential_app/eui/web/primitives";
6756
+ import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
6757
+ var LAYOUT = zoomableImageLayout(ZOOM.pill);
6758
+ var positive = (v) => typeof v === `number` && Number.isFinite(v) && v > 0 ? v : undefined;
6759
+ function ZoomableImageNative({ node, props, rootProps, emit, scope }) {
6760
+ const ctx = useSurfaceContext();
6761
+ const part = useParts(node, props);
6762
+ const menuNode = useMemo17(() => ({ id: `${node.id}.menu`, component: `Menu`, props: {}, children: [] }), [node.id]);
6763
+ const menuPart = useParts(menuNode, menuNode.props);
6764
+ const src = str(props.src);
6765
+ const alt = str(props.alt);
6766
+ const controls = str(props.controls, `auto`);
6767
+ const media = useMediaSource(ctx.host, src);
6768
+ const [, setScale] = useBoundState(node, scope, `scale`, positive(props.scale));
6769
+ const zoom = useZoomableImage2({
6770
+ src: media.url,
6771
+ naturalWidth: positive(props.naturalWidth),
6772
+ naturalHeight: positive(props.naturalHeight),
6773
+ initial: str(props.initial, `auto`),
6774
+ maxScale: positive(props.maxScale),
6775
+ scale: positive(props.scale),
6776
+ controls,
6777
+ transition: ctx.reducedMotion ? null : ZOOMABLE_IMAGE_NATIVE_TRANSITION,
6778
+ onZoom: (scale, atFit) => {
6779
+ setScale(scale);
6780
+ emit(`zoom`, { scale, atFit }, { scale });
6781
+ },
6782
+ onTap: () => void emit(`tap`)
6783
+ });
6784
+ const [menuOpen, setMenuOpen] = useState21(false);
6785
+ useEffect20(() => zoom.controller.current?.holdPill(menuOpen), [menuOpen]);
6786
+ const styled = node.style !== undefined && (node.style.height !== undefined || node.style.aspectRatio !== undefined);
6787
+ const aspect = zoomBoxAspect(ZOOM_MATH2, zoom.natural, styled);
6788
+ const items = menuOpen ? zoom.menuItems(ctx.t(`zoomFit`)).map((item, i) => ({ kind: `checkbox`, label: item.label, value: String(i), checked: item.checked })) : [];
6789
+ const choose = (event, payload) => {
6790
+ if (event !== `select`)
6791
+ return;
6792
+ const c = zoom.controller.current;
6793
+ const f = c?.frame();
6794
+ const picked = c && f ? zoom.menuItems(ctx.t(`zoomFit`))[num(payload?.value, -1)] : undefined;
6795
+ setMenuOpen(false);
6796
+ if (!c || !picked)
6797
+ return;
6798
+ if (picked.scale === null)
6799
+ c.rest();
6800
+ else
6801
+ c.zoomScale(picked.scale);
6802
+ };
6803
+ const { pill } = zoom;
6804
+ return /* @__PURE__ */ jsxs20("div", {
6805
+ ...rootProps,
6806
+ ref: zoom.rootRef,
6807
+ role: "group",
6808
+ "aria-label": alt || undefined,
6809
+ tabIndex: 0,
6810
+ style: mergeStyle(rootProps, { ...LAYOUT.root, ...aspect !== null ? { aspectRatio: String(aspect) } : {} }),
6811
+ children: [
6812
+ /* @__PURE__ */ jsx25("img", {
6813
+ ...part(`image`),
6814
+ ref: zoom.imageRef,
6815
+ src: media.url || undefined,
6816
+ alt,
6817
+ draggable: false,
6818
+ loading: "lazy",
6819
+ decoding: "async",
6820
+ style: { ...LAYOUT.image, ...zoom.natural ? { width: zoom.natural.width, height: zoom.natural.height } : {} },
6821
+ onLoad: zoom.onImageLoad
6822
+ }),
6823
+ /* @__PURE__ */ jsx25("svg", {
6824
+ className: "xui-media-sizer",
6825
+ "aria-hidden": "true",
6826
+ width: MEDIA_INTRINSIC_WIDTH2,
6827
+ height: 1
6828
+ }),
6829
+ controls !== `none` ? /* @__PURE__ */ jsxs20("div", {
6830
+ ...part(`pill`),
6831
+ ref: zoom.pillRef,
6832
+ role: "toolbar",
6833
+ "data-state": zoom.pillVisible ? `open` : `closed`,
6834
+ style: zoom.pillVisible ? LAYOUT.pill : { ...LAYOUT.pill, ...LAYOUT.pillHidden },
6835
+ children: [
6836
+ /* @__PURE__ */ jsx25("button", {
6837
+ type: "button",
6838
+ ...part(`zoomOut`, pill.atMin && `disabled`),
6839
+ style: LAYOUT.button,
6840
+ "aria-label": ctx.t(`zoomOut`),
6841
+ disabled: pill.atMin,
6842
+ onClick: () => zoom.controller.current?.step(-1),
6843
+ children: /* @__PURE__ */ jsx25(BuiltinIcon, {
6844
+ slot: "ZoomableImage.zoomOut",
6845
+ size: 16
6846
+ })
6847
+ }),
6848
+ /* @__PURE__ */ jsxs20(MenuPrimitive2.Root, {
6849
+ open: menuOpen,
6850
+ onOpenChange: setMenuOpen,
6851
+ dir: ctx.direction,
6852
+ children: [
6853
+ /* @__PURE__ */ jsx25(MenuPrimitive2.Trigger, {
6854
+ asChild: true,
6855
+ children: /* @__PURE__ */ jsx25("button", {
6856
+ type: "button",
6857
+ ...part(`percent`, menuOpen && `open`),
6858
+ style: LAYOUT.percent,
6859
+ "aria-label": ctx.t(`zoomLevel`),
6860
+ children: pill.percent
6861
+ })
6862
+ }),
6863
+ /* @__PURE__ */ jsx25(MenuPrimitive2.Portal, {
6864
+ container: ctx.portal ?? undefined,
6865
+ children: /* @__PURE__ */ jsx25(MenuPrimitive2.Content, {
6866
+ ...menuPart(`content`, menuOpen && `open`),
6867
+ side: "top",
6868
+ align: "center",
6869
+ sideOffset: OVERLAY_OFFSET4,
6870
+ collisionPadding: OVERLAY_PADDING4,
6871
+ "data-xui-overlay": "Menu",
6872
+ "data-open-on": "press",
6873
+ children: /* @__PURE__ */ jsx25(MenuItems, {
6874
+ ns: MenuPrimitive2,
6875
+ items,
6876
+ rawItems: undefined,
6877
+ part: menuPart,
6878
+ overlay: "Menu",
6879
+ emit: choose,
6880
+ scope,
6881
+ path: "",
6882
+ close: () => setMenuOpen(false)
6883
+ })
6884
+ })
6885
+ })
6886
+ ]
6887
+ }),
6888
+ /* @__PURE__ */ jsx25("button", {
6889
+ type: "button",
6890
+ ...part(`zoomIn`, pill.atMax && `disabled`),
6891
+ style: LAYOUT.button,
6892
+ "aria-label": ctx.t(`zoomIn`),
6893
+ disabled: pill.atMax,
6894
+ onClick: () => zoom.controller.current?.step(1),
6895
+ children: /* @__PURE__ */ jsx25(BuiltinIcon, {
6896
+ slot: "ZoomableImage.zoomIn",
6897
+ size: 16
6898
+ })
6899
+ }),
6900
+ /* @__PURE__ */ jsx25("span", {
6901
+ ...part(`divider`),
6902
+ "aria-hidden": "true",
6903
+ style: LAYOUT.divider
6904
+ }),
6905
+ /* @__PURE__ */ jsx25("button", {
6906
+ type: "button",
6907
+ ...part(`fit`, pill.atRest && `selected`),
6908
+ style: LAYOUT.button,
6909
+ "aria-label": ctx.t(`zoomToFit`),
6910
+ "aria-pressed": pill.atRest,
6911
+ onClick: () => zoom.controller.current?.rest(),
6912
+ children: /* @__PURE__ */ jsx25(BuiltinIcon, {
6913
+ slot: "ZoomableImage.fit",
6914
+ size: 16
6915
+ })
6916
+ })
6917
+ ]
6918
+ }) : null
6919
+ ]
6920
+ });
6921
+ }
6922
+
6620
6923
  // packages/exponential-ui-react/src/natives/index.ts
6621
6924
  var NATIVES = {
6622
6925
  Box: BoxNative,
@@ -6626,6 +6929,7 @@ var NATIVES = {
6626
6929
  Markdown: MarkdownNative,
6627
6930
  CodeBlock: CodeBlockNative,
6628
6931
  Image: ImageNative,
6932
+ ZoomableImage: ZoomableImageNative,
6629
6933
  Icon: IconNative,
6630
6934
  Video: VideoNative,
6631
6935
  AudioPlayer: AudioPlayerNative,
@@ -6645,6 +6949,7 @@ var NATIVES = {
6645
6949
  Spinner: SpinnerNative,
6646
6950
  Skeleton: SkeletonNative,
6647
6951
  VoiceWave: VoiceWaveNative,
6952
+ Motion: MotionNative,
6648
6953
  Table: TableNative,
6649
6954
  Chart: ChartNative,
6650
6955
  Button: ButtonNative,
@@ -6675,7 +6980,7 @@ var NATIVE_NAMES = Object.keys(NATIVES);
6675
6980
 
6676
6981
  // packages/exponential-ui-react/src/node-view.tsx
6677
6982
  import { cssValue, isMacroComponent, partClass as partClass4, propAttribute as propAttribute2 } from "@exponential_app/eui/web";
6678
- import { jsx as jsx24, jsxs as jsxs20, Fragment as Fragment8 } from "react/jsx-runtime";
6983
+ import { jsx as jsx26, jsxs as jsxs21, Fragment as Fragment9 } from "react/jsx-runtime";
6679
6984
  var CONTAINERS = new Set([`Box`, `List`]);
6680
6985
  function styleIdOf(node) {
6681
6986
  return node.styleId ?? node.id;
@@ -6683,7 +6988,7 @@ function styleIdOf(node) {
6683
6988
  function useRootProps(node, props, domId = node.id, recipeProps, style) {
6684
6989
  const ctx = useSurfaceContext();
6685
6990
  const scope = useContext6(ScopeContext);
6686
- return useMemo17(() => {
6991
+ return useMemo18(() => {
6687
6992
  const macros = extensionMacroNames(ctx.extensions);
6688
6993
  const classes = [`xui-el`, nodeClass(styleIdOf(node)), ctx.compiled.scope, partClass4(node.component, `root`)];
6689
6994
  const attrs = {};
@@ -6778,13 +7083,13 @@ var NodeView = memo2(function NodeView({ node }) {
6778
7083
  return null;
6779
7084
  const own = ownDirection(node, ctx);
6780
7085
  if (own && own !== ctx.direction)
6781
- return /* @__PURE__ */ jsx24(DirectedNode, {
7086
+ return /* @__PURE__ */ jsx26(DirectedNode, {
6782
7087
  node,
6783
7088
  scope,
6784
7089
  direction: own,
6785
7090
  live
6786
7091
  });
6787
- return /* @__PURE__ */ jsx24(BoundNode, {
7092
+ return /* @__PURE__ */ jsx26(BoundNode, {
6788
7093
  node,
6789
7094
  scope,
6790
7095
  live
@@ -6798,10 +7103,10 @@ function ownDirection(node, ctx) {
6798
7103
  }
6799
7104
  function DirectedNode({ node, scope, direction, live }) {
6800
7105
  const ctx = useSurfaceContext();
6801
- const value = useMemo17(() => deriveContext(ctx, { direction }), [ctx, direction]);
6802
- return /* @__PURE__ */ jsx24(SurfaceContext.Provider, {
7106
+ const value = useMemo18(() => deriveContext(ctx, { direction }), [ctx, direction]);
7107
+ return /* @__PURE__ */ jsx26(SurfaceContext.Provider, {
6803
7108
  value,
6804
- children: /* @__PURE__ */ jsx24(BoundNode, {
7109
+ children: /* @__PURE__ */ jsx26(BoundNode, {
6805
7110
  node,
6806
7111
  scope,
6807
7112
  live
@@ -6813,8 +7118,8 @@ var BoundNode = memo2(function BoundNode({ node, scope, live }) {
6813
7118
  const instance = useContext6(InstanceContext);
6814
7119
  const domId = `${node.id}${instance}`;
6815
7120
  const data = ctx.data;
6816
- const rctx = useMemo17(() => resolveContextOf(ctx, scope), [ctx, scope, data, live]);
6817
- const props = useMemo17(() => {
7121
+ const rctx = useMemo18(() => resolveContextOf(ctx, scope), [ctx, scope, data, live]);
7122
+ const props = useMemo18(() => {
6818
7123
  const out = resolveNodeProps(node.component, node.props, rctx, ctx.extensionDefs);
6819
7124
  for (const name of responsiveProps(node.component, ctx.extensionDefs)) {
6820
7125
  const v = out[name];
@@ -6823,8 +7128,8 @@ var BoundNode = memo2(function BoundNode({ node, scope, live }) {
6823
7128
  }
6824
7129
  return out;
6825
7130
  }, [node.props, node.component, rctx, ctx.extensionDefs, ctx.breakpoint]);
6826
- const recipeProps = useMemo17(() => node.recipe ? resolveValue(node.recipe.props, rctx) : undefined, [node.recipe, rctx]);
6827
- const dynamicStyle = useMemo17(() => {
7131
+ const recipeProps = useMemo18(() => node.recipe ? resolveValue(node.recipe.props, rctx) : undefined, [node.recipe, rctx]);
7132
+ const dynamicStyle = useMemo18(() => {
6828
7133
  const entries = dynamicStyleEntries(node.style);
6829
7134
  if (entries.length === 0)
6830
7135
  return;
@@ -6842,30 +7147,30 @@ var BoundNode = memo2(function BoundNode({ node, scope, live }) {
6842
7147
  const Painter = Override ?? Native ?? NATIVES[UNKNOWN_COMPONENT];
6843
7148
  const unknown = node.component === UNKNOWN_COMPONENT || !Native && !Override;
6844
7149
  const onUnknown = ctx.host.onUnknown;
6845
- useEffect19(() => {
7150
+ useEffect21(() => {
6846
7151
  if (unknown)
6847
7152
  onUnknown?.(node);
6848
7153
  }, [unknown, onUnknown, node]);
6849
7154
  if (ctx.measure && !CONTAINERS.has(node.component)) {
6850
7155
  const size = ctx.measure(node);
6851
7156
  if (size) {
6852
- return /* @__PURE__ */ jsx24("div", {
7157
+ return /* @__PURE__ */ jsx26("div", {
6853
7158
  className: `xui-el ${nodeClass(node.id)} xui-leaf`,
6854
7159
  "data-xui-id": domId,
6855
7160
  "data-xui-c": node.component,
6856
- children: /* @__PURE__ */ jsx24("div", {
7161
+ children: /* @__PURE__ */ jsx26("div", {
6857
7162
  className: "xui-measured",
6858
7163
  style: { width: size.w, height: size.h }
6859
7164
  })
6860
7165
  });
6861
7166
  }
6862
7167
  }
6863
- const children = /* @__PURE__ */ jsxs20(Fragment8, {
7168
+ const children = /* @__PURE__ */ jsxs21(Fragment9, {
6864
7169
  children: [
6865
- node.children.map((child) => /* @__PURE__ */ jsx24(NodeView, {
7170
+ node.children.map((child) => /* @__PURE__ */ jsx26(NodeView, {
6866
7171
  node: child
6867
7172
  }, child.id)),
6868
- node.template ? /* @__PURE__ */ jsx24(TemplateChildren, {
7173
+ node.template ? /* @__PURE__ */ jsx26(TemplateChildren, {
6869
7174
  node,
6870
7175
  scope
6871
7176
  }) : null
@@ -6873,18 +7178,18 @@ var BoundNode = memo2(function BoundNode({ node, scope, live }) {
6873
7178
  });
6874
7179
  const slots = {};
6875
7180
  for (const [name, slot] of Object.entries(node.slots ?? {}))
6876
- slots[name] = /* @__PURE__ */ jsx24(NodeView, {
7181
+ slots[name] = /* @__PURE__ */ jsx26(NodeView, {
6877
7182
  node: slot
6878
7183
  }, slot.id);
6879
7184
  const painterProps = { node, props, theme: ctx.theme, mode: ctx.mode, tokens: ctx.theme.tokens, children, slots, emit, rootProps, scope, domId };
6880
7185
  if (UNGUARDED.has(node.component) && !Override)
6881
- return /* @__PURE__ */ jsx24(Painter, {
7186
+ return /* @__PURE__ */ jsx26(Painter, {
6882
7187
  ...painterProps
6883
7188
  });
6884
- return /* @__PURE__ */ jsx24(PaintBoundary, {
7189
+ return /* @__PURE__ */ jsx26(PaintBoundary, {
6885
7190
  node,
6886
7191
  domId,
6887
- children: /* @__PURE__ */ jsx24(Painter, {
7192
+ children: /* @__PURE__ */ jsx26(Painter, {
6888
7193
  ...painterProps
6889
7194
  })
6890
7195
  });
@@ -6944,7 +7249,7 @@ class PaintBoundary extends Component {
6944
7249
  render() {
6945
7250
  const { node, domId, children } = this.props;
6946
7251
  if (this.state.failed)
6947
- return /* @__PURE__ */ jsx24("div", {
7252
+ return /* @__PURE__ */ jsx26("div", {
6948
7253
  className: `xui-el ${nodeClass(node.id)}`,
6949
7254
  "data-xui-id": domId,
6950
7255
  "data-xui-c": node.component,
@@ -6970,11 +7275,11 @@ function templateItems(ctx, node, scope) {
6970
7275
  var itemInstance = (instance, key) => `${instance}.${instanceSegment(key)}`;
6971
7276
  function TemplateItemView({ tpl, item }) {
6972
7277
  const instance = useContext6(InstanceContext);
6973
- return /* @__PURE__ */ jsx24(ScopeContext.Provider, {
7278
+ return /* @__PURE__ */ jsx26(ScopeContext.Provider, {
6974
7279
  value: item.path,
6975
- children: /* @__PURE__ */ jsx24(InstanceContext.Provider, {
7280
+ children: /* @__PURE__ */ jsx26(InstanceContext.Provider, {
6976
7281
  value: itemInstance(instance, item.key),
6977
- children: /* @__PURE__ */ jsx24(NodeView, {
7282
+ children: /* @__PURE__ */ jsx26(NodeView, {
6978
7283
  node: tpl
6979
7284
  })
6980
7285
  })
@@ -6983,24 +7288,24 @@ function TemplateItemView({ tpl, item }) {
6983
7288
  function TemplateChildren({ node, scope }) {
6984
7289
  const ctx = useSurfaceContext();
6985
7290
  const t = templateItems(ctx, node, scope);
6986
- const last = useRef24({ keys: new Set, generation: 0 });
7291
+ const last = useRef25({ keys: new Set, generation: 0 });
6987
7292
  const keys = t ? t.items.map((item) => item.key) : [];
6988
7293
  let generation = last.current.generation;
6989
7294
  if (keys.length > 0 && last.current.keys.size > 0 && !keys.some((k) => last.current.keys.has(k)))
6990
7295
  generation++;
6991
- useEffect19(() => {
7296
+ useEffect21(() => {
6992
7297
  last.current = { keys: new Set(keys), generation };
6993
7298
  });
6994
7299
  if (!t)
6995
7300
  return null;
6996
- return /* @__PURE__ */ jsx24(TemplateBlock, {
7301
+ return /* @__PURE__ */ jsx26(TemplateBlock, {
6997
7302
  items: t.items,
6998
7303
  tpl: t.tpl
6999
7304
  }, generation);
7000
7305
  }
7001
7306
  function TemplateBlock({ items, tpl }) {
7002
- return /* @__PURE__ */ jsx24(Fragment8, {
7003
- children: items.map((item) => /* @__PURE__ */ jsx24(TemplateItemView, {
7307
+ return /* @__PURE__ */ jsx26(Fragment9, {
7308
+ children: items.map((item) => /* @__PURE__ */ jsx26(TemplateItemView, {
7004
7309
  tpl,
7005
7310
  item
7006
7311
  }, item.key))
@@ -7011,7 +7316,7 @@ function TemplateBlock({ items, tpl }) {
7011
7316
  import { openAllowed } from "@exponential_app/eui/web";
7012
7317
  import { compiledTheme } from "@exponential_app/eui/web";
7013
7318
  import { layoutSize as layoutSize2 } from "@exponential_app/eui/web";
7014
- import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
7319
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
7015
7320
  var resolvedCache = new Map;
7016
7321
  function resolveThemeInput(input) {
7017
7322
  if (!input)
@@ -7055,7 +7360,7 @@ function surfaceTheme(theme, density, highContrast) {
7055
7360
  var EMPTY2 = [];
7056
7361
  var NO_TEMPLATES = {};
7057
7362
  var EMPTY_HOST = {};
7058
- var useIsoLayoutEffect3 = typeof window === `undefined` ? useEffect20 : useLayoutEffect6;
7363
+ var useIsoLayoutEffect3 = typeof window === `undefined` ? useEffect22 : useLayoutEffect7;
7059
7364
  function surfaceLayout(box, inputs) {
7060
7365
  const breakpoint = activeBreakpoint(box.width, inputs.breakpoints);
7061
7366
  const height = inputs.viewportHeight ?? box.height;
@@ -7208,30 +7513,30 @@ function ExponentialSurface({
7208
7513
  const reducedMotion = useMediaQuery(`(prefers-reduced-motion: reduce)`);
7209
7514
  const hover = useMediaQuery(`(hover: hover)`, true);
7210
7515
  const mode = modeSetting === `system` ? resolveMode(`system`, prefersDark) : modeSetting;
7211
- const resolution = useMemo18(() => resolveThemeInput(themeProp), [themeProp]);
7516
+ const resolution = useMemo19(() => resolveThemeInput(themeProp), [themeProp]);
7212
7517
  const baseTheme = resolution.theme;
7213
7518
  const onThemeIssues = host?.onThemeIssues;
7214
- useEffect20(() => {
7519
+ useEffect22(() => {
7215
7520
  if (resolution.issues.length > 0)
7216
7521
  onThemeIssues?.(resolution.issues);
7217
7522
  }, [resolution, onThemeIssues]);
7218
7523
  const theme = surfaceTheme(baseTheme, density, contrast === `high` || contrast === `system` && prefersContrast);
7219
7524
  const global = useSyncExternalStore3(subscribeExtensions, registeredExtensions, registeredExtensions);
7220
- const extensions = useMemo18(() => [...global, ...extensionsProp], [global, extensionsProp]);
7221
- const extensionDefs = useMemo18(() => extensionCatalogs(extensions), [extensions]);
7222
- const macros = useMemo18(() => extensionMacroNames(extensions), [extensions]);
7223
- const compiled = useMemo18(() => compiledTheme(theme, { extensionMacros: macros }), [theme, macros]);
7525
+ const extensions = useMemo19(() => [...global, ...extensionsProp], [global, extensionsProp]);
7526
+ const extensionDefs = useMemo19(() => extensionCatalogs(extensions), [extensions]);
7527
+ const macros = useMemo19(() => extensionMacroNames(extensions), [extensions]);
7528
+ const compiled = useMemo19(() => compiledTheme(theme, { extensionMacros: macros }), [theme, macros]);
7224
7529
  const direction = directionProp ?? textDirection(locale);
7225
- const strings = useMemo18(() => stringTable(stringOverrides ?? {}), [stringOverrides]);
7530
+ const strings = useMemo19(() => stringTable(stringOverrides ?? {}), [stringOverrides]);
7226
7531
  const t = useCallback11((id, params) => formatString(strings[id] ?? id, params ?? {}), [strings]);
7227
- const [localData, setLocalData] = useState21(dataProp ?? {});
7228
- const [seenData, setSeenData] = useState21(dataProp);
7532
+ const [localData, setLocalData] = useState22(dataProp ?? {});
7533
+ const [seenData, setSeenData] = useState22(dataProp);
7229
7534
  if (dataProp !== seenData && !sameData(dataProp, seenData)) {
7230
7535
  setSeenData(dataProp);
7231
7536
  setLocalData(dataProp ?? {});
7232
7537
  }
7233
7538
  const data = surface ? surface.data : localData;
7234
- const latestSurface = useRef25(surface);
7539
+ const latestSurface = useRef26(surface);
7235
7540
  latestSurface.current = surface;
7236
7541
  const setData = useCallback11((pointer, value) => {
7237
7542
  const current = latestSurface.current;
@@ -7240,40 +7545,40 @@ function ExponentialSurface({
7240
7545
  else
7241
7546
  setLocalData((cur) => setPointer3(cur, pointer, value));
7242
7547
  }, []);
7243
- const lastTree = useRef25({ root: null, templates: NO_TEMPLATES });
7548
+ const lastTree = useRef26({ root: null, templates: NO_TEMPLATES });
7244
7549
  const rawRoot = surface ? surface.root : rootProp ?? null;
7245
- const root = useMemo18(() => lastTree.current.root = share(lastTree.current.root, rawRoot), [rawRoot]);
7550
+ const root = useMemo19(() => lastTree.current.root = share(lastTree.current.root, rawRoot), [rawRoot]);
7246
7551
  const rawTemplates = (surface ? surface.templates : templatesProp) ?? NO_TEMPLATES;
7247
- const templates = useMemo18(() => lastTree.current.templates = share(lastTree.current.templates, rawTemplates), [rawTemplates]);
7552
+ const templates = useMemo19(() => lastTree.current.templates = share(lastTree.current.templates, rawTemplates), [rawTemplates]);
7248
7553
  const templateNode = useCallback11((componentId) => templates[componentId], [templates]);
7249
- const templateRoots = useMemo18(() => Object.values(templates), [templates]);
7250
- const lastBudget = useRef25(undefined);
7251
- const budget = useMemo18(() => {
7554
+ const templateRoots = useMemo19(() => Object.values(templates), [templates]);
7555
+ const lastBudget = useRef26(undefined);
7556
+ const budget = useMemo19(() => {
7252
7557
  const next = root ? templateBudget(root, data, templateNode) : undefined;
7253
7558
  if (sameBudget(lastBudget.current, next))
7254
7559
  return lastBudget.current;
7255
7560
  return lastBudget.current = next;
7256
7561
  }, [root, data, templateNode]);
7257
- useEffect20(() => {
7562
+ useEffect22(() => {
7258
7563
  if (budget?.issue)
7259
7564
  console.warn(`[exponential-ui] ${surfaceId}: ${budget.issue.id}: ${budget.issue.message}`);
7260
7565
  }, [surfaceId, budget?.issue?.id, budget?.issue?.message]);
7261
- useEffect20(() => {
7566
+ useEffect22(() => {
7262
7567
  if (IS_DEV && root)
7263
7568
  warnMissingTemplates(surfaceId, root, templates);
7264
7569
  }, [surfaceId, root, templates]);
7265
- const sheet = useMemo18(() => root ? compileNodeSheet([root, ...templateRoots], surfaceId, theme) : { css: ``, queries: [], chunks: NO_CHUNKS }, [root, templateRoots, surfaceId, theme]);
7266
- const lastBatches = useRef25([]);
7267
- const batches = useMemo18(() => lastBatches.current = nodeSheetBatches(lastBatches.current, sheet.chunks), [sheet.chunks]);
7268
- const [rootEl, setRootEl] = useState21(null);
7269
- const [portal, setPortal] = useState21(null);
7270
- const [toastLayer, setToastLayer] = useState21(null);
7271
- const box = useRef25({ width: typeof width === `number` ? width : 0, height: undefined, measured: false });
7570
+ const sheet = useMemo19(() => root ? compileNodeSheet([root, ...templateRoots], surfaceId, theme) : { css: ``, queries: [], chunks: NO_CHUNKS }, [root, templateRoots, surfaceId, theme]);
7571
+ const lastBatches = useRef26([]);
7572
+ const batches = useMemo19(() => lastBatches.current = nodeSheetBatches(lastBatches.current, sheet.chunks), [sheet.chunks]);
7573
+ const [rootEl, setRootEl] = useState22(null);
7574
+ const [portal, setPortal] = useState22(null);
7575
+ const [toastLayer, setToastLayer] = useState22(null);
7576
+ const box = useRef26({ width: typeof width === `number` ? width : 0, height: undefined, measured: false });
7272
7577
  const layoutInputs = { breakpoints: theme.tokens.breakpoint ?? {}, queries: sheet.queries, viewportHeight, hover, reducedMotion };
7273
7578
  const { breakpoint, xq } = surfaceLayout(box.current, layoutInputs);
7274
- const inputsRef = useRef25(layoutInputs);
7579
+ const inputsRef = useRef26(layoutInputs);
7275
7580
  inputsRef.current = layoutInputs;
7276
- const [, setLayoutKey] = useState21(``);
7581
+ const [, setLayoutKey] = useState22(``);
7277
7582
  useIsoLayoutEffect3(() => {
7278
7583
  if (!rootEl)
7279
7584
  return;
@@ -7293,8 +7598,8 @@ function ExponentialSurface({
7293
7598
  ro.observe(rootEl);
7294
7599
  return () => ro.disconnect();
7295
7600
  }, [rootEl]);
7296
- const politeRef = useRef25(null);
7297
- const assertiveRef = useRef25(null);
7601
+ const politeRef = useRef26(null);
7602
+ const assertiveRef = useRef26(null);
7298
7603
  const announce = useCallback11((text, live = `polite`) => {
7299
7604
  const el = live === `assertive` ? assertiveRef.current : politeRef.current;
7300
7605
  if (!el)
@@ -7304,18 +7609,18 @@ function ExponentialSurface({
7304
7609
  el.textContent = text;
7305
7610
  }, 30);
7306
7611
  }, []);
7307
- const functions = useMemo18(() => ({ ...CLIENT_FUNCTIONS2, ...host?.functions ?? {} }), [host?.functions]);
7308
- const formatter = useMemo18(() => memoFormatter(lazyFormatter(locale, timeZone)), [locale, timeZone]);
7309
- const liveClock = useMemo18(() => usesLiveClock(root) || usesLiveClock(templateRoots), [root, templateRoots]);
7310
- const [minute, setMinute] = useState21(() => Date.now());
7311
- useEffect20(() => {
7612
+ const functions = useMemo19(() => ({ ...CLIENT_FUNCTIONS2, ...host?.functions ?? {} }), [host?.functions]);
7613
+ const formatter = useMemo19(() => memoFormatter(lazyFormatter(locale, timeZone)), [locale, timeZone]);
7614
+ const liveClock = useMemo19(() => usesLiveClock(root) || usesLiveClock(templateRoots), [root, templateRoots]);
7615
+ const [minute, setMinute] = useState22(() => Date.now());
7616
+ useEffect22(() => {
7312
7617
  if (!liveClock)
7313
7618
  return;
7314
7619
  const timer = setInterval(() => setMinute(Date.now()), 60000);
7315
7620
  return () => clearInterval(timer);
7316
7621
  }, [liveClock]);
7317
- const now = useMemo18(() => () => Date.now(), [minute]);
7318
- const scrollers = useRef25(new Map);
7622
+ const now = useMemo19(() => () => Date.now(), [minute]);
7623
+ const scrollers = useRef26(new Map);
7319
7624
  const registerScroller = useCallback11((id, scroll) => {
7320
7625
  scrollers.current.set(id, scroll);
7321
7626
  return () => {
@@ -7323,12 +7628,12 @@ function ExponentialSurface({
7323
7628
  scrollers.current.delete(id);
7324
7629
  };
7325
7630
  }, []);
7326
- const paintFailures = useRef25(new Map).current;
7631
+ const paintFailures = useRef26(new Map).current;
7327
7632
  const hostValue = host ?? EMPTY_HOST;
7328
7633
  const openUrl = useCallback11((url) => openAllowed(hostValue, url), [hostValue]);
7329
- const live = useRef25({ data, breakpoint, xq, mode });
7634
+ const live = useRef26({ data, breakpoint, xq, mode });
7330
7635
  live.current = { data, breakpoint, xq, mode };
7331
- const listeners = useRef25(new Set).current;
7636
+ const listeners = useRef26(new Set).current;
7332
7637
  const subscribe = useCallback11((listener) => {
7333
7638
  listeners.add(listener);
7334
7639
  return () => void listeners.delete(listener);
@@ -7337,7 +7642,7 @@ function ExponentialSurface({
7337
7642
  for (const listener of [...listeners])
7338
7643
  listener();
7339
7644
  }, [data, breakpoint, xq, mode, listeners]);
7340
- const ctx = useMemo18(() => withLive({
7645
+ const ctx = useMemo19(() => withLive({
7341
7646
  surfaceId,
7342
7647
  compiled,
7343
7648
  theme,
@@ -7410,9 +7715,9 @@ function ExponentialSurface({
7410
7715
  const md = theme.tokens.breakpoint?.md ?? 768;
7411
7716
  const scopeSel = `.${surfaceClass(surfaceId)}`;
7412
7717
  const layerCss = `@layer xui-base{@container xui (width >= ${md}px){${scopeSel} .xui-toast-layer{left:auto;right:var(--xui-spacing-lg);transform:none;align-items:flex-end}${scopeSel}[dir="rtl"] .xui-toast-layer{right:auto;left:var(--xui-spacing-lg)}}}`;
7413
- const themeHtml = useMemo18(() => ({ __html: `${BASE_CSS}
7718
+ const themeHtml = useMemo19(() => ({ __html: `${BASE_CSS}
7414
7719
  ${compiled.css}` }), [compiled.css]);
7415
- const nodesHtml = useMemo18(() => {
7720
+ const nodesHtml = useMemo19(() => {
7416
7721
  const list = batches.length ? batches : [{ chunks: NO_CHUNKS, css: sheet.css }];
7417
7722
  return list.map((batch, i) => {
7418
7723
  const css = i === 0 ? `${batch.css}${layerCss}` : batch.css;
@@ -7424,7 +7729,7 @@ ${compiled.css}` }), [compiled.css]);
7424
7729
  return html;
7425
7730
  });
7426
7731
  }, [batches, sheet.css, layerCss]);
7427
- return /* @__PURE__ */ jsxs21("div", {
7732
+ return /* @__PURE__ */ jsxs22("div", {
7428
7733
  ref: setRootEl,
7429
7734
  className: [`xui-surface`, compiled.scope, surfaceClass(surfaceId), className].filter(Boolean).join(` `),
7430
7735
  "data-xui-surface": surfaceId,
@@ -7436,29 +7741,29 @@ ${compiled.css}` }), [compiled.css]);
7436
7741
  dir: direction,
7437
7742
  style: width === undefined ? style : { width, ...style },
7438
7743
  children: [
7439
- /* @__PURE__ */ jsx25("style", {
7744
+ /* @__PURE__ */ jsx27("style", {
7440
7745
  "data-xui-style": "theme",
7441
7746
  dangerouslySetInnerHTML: themeHtml
7442
7747
  }),
7443
- nodesHtml.map((html, i) => /* @__PURE__ */ jsx25("style", {
7748
+ nodesHtml.map((html, i) => /* @__PURE__ */ jsx27("style", {
7444
7749
  "data-xui-style": "nodes",
7445
7750
  dangerouslySetInnerHTML: html
7446
7751
  }, i)),
7447
- /* @__PURE__ */ jsx25(SurfaceContext.Provider, {
7752
+ /* @__PURE__ */ jsx27(SurfaceContext.Provider, {
7448
7753
  value: ctx,
7449
- children: /* @__PURE__ */ jsxs21("div", {
7754
+ children: /* @__PURE__ */ jsxs22("div", {
7450
7755
  className: "xui-container",
7451
7756
  children: [
7452
- root ? /* @__PURE__ */ jsx25(NodeView, {
7757
+ root ? /* @__PURE__ */ jsx27(NodeView, {
7453
7758
  node: root
7454
7759
  }) : null,
7455
7760
  children,
7456
- /* @__PURE__ */ jsx25("div", {
7761
+ /* @__PURE__ */ jsx27("div", {
7457
7762
  ref: setPortal,
7458
7763
  className: "xui-layer",
7459
7764
  "data-xui-layer": "overlay"
7460
7765
  }),
7461
- /* @__PURE__ */ jsx25("div", {
7766
+ /* @__PURE__ */ jsx27("div", {
7462
7767
  ref: setToastLayer,
7463
7768
  className: "xui-toast-layer",
7464
7769
  "data-xui-layer": "toast"
@@ -7466,14 +7771,14 @@ ${compiled.css}` }), [compiled.css]);
7466
7771
  ]
7467
7772
  })
7468
7773
  }),
7469
- /* @__PURE__ */ jsx25("div", {
7774
+ /* @__PURE__ */ jsx27("div", {
7470
7775
  ref: politeRef,
7471
7776
  className: "xui-sr-only",
7472
7777
  "aria-live": "polite",
7473
7778
  "aria-atomic": "true",
7474
7779
  "data-xui-live": "polite"
7475
7780
  }),
7476
- /* @__PURE__ */ jsx25("div", {
7781
+ /* @__PURE__ */ jsx27("div", {
7477
7782
  ref: assertiveRef,
7478
7783
  className: "xui-sr-only",
7479
7784
  "aria-live": "assertive",
@@ -7484,21 +7789,21 @@ ${compiled.css}` }), [compiled.css]);
7484
7789
  });
7485
7790
  }
7486
7791
  // packages/exponential-ui-react/src/use-surface.ts
7487
- import { useCallback as useCallback12, useMemo as useMemo19, useRef as useRef26, useState as useState22 } from "react";
7792
+ import { useCallback as useCallback12, useMemo as useMemo20, useRef as useRef27, useState as useState23 } from "react";
7488
7793
  import { CORE_CATALOG_ID, reduceNested, reduceSurface } from "@exponential_app/eui";
7489
7794
  import { setPointer as setPointer4 } from "@exponential_app/eui/web";
7490
7795
  var NO_EXTENSIONS = [];
7491
7796
  function useSurface(options = {}) {
7492
7797
  const surfaceId = options.surfaceId ?? `main`;
7493
7798
  const extensions = options.extensions ?? NO_EXTENSIONS;
7494
- const initialRef = useRef26({
7799
+ const initialRef = useRef27({
7495
7800
  catalogId: options.catalogId ?? CORE_CATALOG_ID,
7496
7801
  components: [],
7497
7802
  nested: options.initial ?? null,
7498
7803
  data: options.data ?? {},
7499
7804
  deleted: false
7500
7805
  });
7501
- const [inner, setInner] = useState22(initialRef.current);
7806
+ const [inner, setInner] = useState23(initialRef.current);
7502
7807
  const apply = useCallback12((message) => {
7503
7808
  setInner((cur) => {
7504
7809
  if (message.createSurface) {
@@ -7535,7 +7840,7 @@ function useSurface(options = {}) {
7535
7840
  setInner((cur) => ({ ...cur, nested: tree, components: [], deleted: false }));
7536
7841
  }, []);
7537
7842
  const reset = useCallback12(() => setInner(initialRef.current), []);
7538
- const reduced = useMemo19(() => {
7843
+ const reduced = useMemo20(() => {
7539
7844
  if (inner.deleted)
7540
7845
  return { root: null, issues: [] };
7541
7846
  if (inner.nested)
@@ -7568,8 +7873,8 @@ import { BASE_CSS as BASE_CSS2 } from "@exponential_app/eui/web";
7568
7873
  import { getPointer as getPointer4, setPointer as setPointer5, absolutePath as absolutePath4, resolveValue as resolveValue2, resolveProps, resolveNodeProps as resolveNodeProps2, resolveVisible as resolveVisible2, bindTree, boundPath as boundPath5, isBinding as isBinding3, isCall as isCall2, hasDynamic, memoFormatter as memoFormatter2, CLIENT_FUNCTIONS as CLIENT_FUNCTIONS3 } from "@exponential_app/eui/web";
7569
7874
 
7570
7875
  // packages/exponential-ui-react/src/host-surface.tsx
7571
- import { useCallback as useCallback13, useMemo as useMemo20, useSyncExternalStore as useSyncExternalStore4 } from "react";
7572
- import { jsx as jsx26, Fragment as Fragment9 } from "react/jsx-runtime";
7876
+ import { useCallback as useCallback13, useMemo as useMemo21, useSyncExternalStore as useSyncExternalStore4 } from "react";
7877
+ import { jsx as jsx28, Fragment as Fragment10 } from "react/jsx-runtime";
7573
7878
  function hostPlugin(host, base = {}) {
7574
7879
  return {
7575
7880
  ...base,
@@ -7599,7 +7904,7 @@ function useHostSurfaceIds(host) {
7599
7904
  const subscribe = useCallback13((cb) => host.subscribe(cb), [host]);
7600
7905
  const key = useSyncExternalStore4(subscribe, () => host.surfaceIds().join(`
7601
7906
  `));
7602
- return useMemo20(() => key ? key.split(`
7907
+ return useMemo21(() => key ? key.split(`
7603
7908
  `) : [], [key]);
7604
7909
  }
7605
7910
  function useHostStatus(host) {
@@ -7614,7 +7919,7 @@ function useHostSurface(host, surfaceId) {
7614
7919
  const store = useSyncExternalStore4(subscribeHost, () => host.surface(surfaceId));
7615
7920
  const subscribeStore = useCallback13((cb) => store ? store.subscribe(cb) : noop(), [store]);
7616
7921
  const version = useSyncExternalStore4(subscribeStore, () => store?.version ?? -1);
7617
- return useMemo20(() => store ? stateOf(host, store) : null, [host, store, version]);
7922
+ return useMemo21(() => store ? stateOf(host, store) : null, [host, store, version]);
7618
7923
  }
7619
7924
  function stateOf(host, store) {
7620
7925
  return {
@@ -7640,12 +7945,12 @@ function stateOf(host, store) {
7640
7945
  }
7641
7946
  function HostSurface({ host, surfaceId, plugin, fallback = null, ...rest }) {
7642
7947
  const surface = useHostSurface(host, surfaceId);
7643
- const p = useMemo20(() => hostPlugin(host, plugin), [host, plugin]);
7948
+ const p = useMemo21(() => hostPlugin(host, plugin), [host, plugin]);
7644
7949
  if (!surface)
7645
- return /* @__PURE__ */ jsx26(Fragment9, {
7950
+ return /* @__PURE__ */ jsx28(Fragment10, {
7646
7951
  children: fallback
7647
7952
  });
7648
- return /* @__PURE__ */ jsx26(ExponentialSurface, {
7953
+ return /* @__PURE__ */ jsx28(ExponentialSurface, {
7649
7954
  ...rest,
7650
7955
  theme: surface.theme ?? rest.theme,
7651
7956
  id: rest.id ?? surfaceId,
@@ -7753,5 +8058,5 @@ export {
7753
8058
  walkNodes
7754
8059
  };
7755
8060
 
7756
- //# debugId=C1F40D910A8766D764756E2164756E21
8061
+ //# debugId=39A4F0FB7E01DD0264756E2164756E21
7757
8062
  //# sourceMappingURL=index.js.map