@kjun-ui/native 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/index.cjs +1038 -875
  2. package/dist/index.js +907 -741
  3. package/dist/index.web.cjs +1051 -888
  4. package/dist/index.web.js +913 -747
  5. package/dist/styles.css +73 -1
  6. package/dist/types/packages/native/src/card.d.cts +9 -2
  7. package/dist/types/packages/native/src/card.d.ts +9 -2
  8. package/dist/types/packages/native/src/collapse.d.cts +3 -1
  9. package/dist/types/packages/native/src/collapse.d.ts +3 -1
  10. package/dist/types/packages/native/src/display-primitives.d.cts +2 -1
  11. package/dist/types/packages/native/src/display-primitives.d.ts +2 -1
  12. package/dist/types/packages/native/src/drawer.d.cts +3 -1
  13. package/dist/types/packages/native/src/drawer.d.ts +3 -1
  14. package/dist/types/packages/native/src/feedback.d.cts +5 -1
  15. package/dist/types/packages/native/src/feedback.d.ts +5 -1
  16. package/dist/types/packages/native/src/layout-primitives.d.cts +5 -3
  17. package/dist/types/packages/native/src/layout-primitives.d.ts +5 -3
  18. package/dist/types/packages/native/src/list.d.cts +17 -2
  19. package/dist/types/packages/native/src/list.d.ts +17 -2
  20. package/dist/types/packages/native/src/media.d.cts +4 -2
  21. package/dist/types/packages/native/src/media.d.ts +4 -2
  22. package/dist/types/packages/native/src/modal.d.cts +3 -1
  23. package/dist/types/packages/native/src/modal.d.ts +3 -1
  24. package/dist/types/packages/native/src/navigation.d.cts +7 -1
  25. package/dist/types/packages/native/src/navigation.d.ts +7 -1
  26. package/dist/types/shared/package-runtime/layout-primitives.d.cts +1 -1
  27. package/dist/types/shared/package-runtime/layout-primitives.d.ts +1 -1
  28. package/dist/types/shared/package-runtime/progress-circle.d.cts +11 -0
  29. package/dist/types/shared/package-runtime/progress-circle.d.ts +11 -0
  30. package/dist/types/shared/package-runtime/use-after-close.d.cts +6 -0
  31. package/dist/types/shared/package-runtime/use-after-close.d.ts +6 -0
  32. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1738,6 +1738,18 @@ function KjunFormLayout({
1738
1738
  ) });
1739
1739
  }
1740
1740
 
1741
+ // shared/package-runtime/use-after-close.ts
1742
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef6 } from "react";
1743
+ function useAfterClose(present, onAfterClose, enabled = true) {
1744
+ const was = useRef6(present), callback = useRef6(onAfterClose);
1745
+ callback.current = onAfterClose;
1746
+ useEffect4(() => {
1747
+ var _a;
1748
+ if (was.current && !present && enabled) (_a = callback.current) == null ? void 0 : _a.call(callback);
1749
+ was.current = present;
1750
+ }, [present, enabled]);
1751
+ }
1752
+
1741
1753
  // shared/package-runtime/content-presence.ts
1742
1754
  import { Fragment as Fragment2, isValidElement as isValidElement2 } from "react";
1743
1755
  function hasContent(node) {
@@ -1779,8 +1791,9 @@ import {
1779
1791
  import {
1780
1792
  createContext as createContext14,
1781
1793
  useContext as useContext9,
1782
- useEffect as useEffect4,
1783
- useId as useId3
1794
+ useEffect as useEffect5,
1795
+ useId as useId3,
1796
+ useRef as useRef7
1784
1797
  } from "react";
1785
1798
  import { Platform as Platform9, View as View6 } from "react-native";
1786
1799
 
@@ -1797,13 +1810,14 @@ var FeedbackOverlayContext = createContext14(
1797
1810
  null
1798
1811
  );
1799
1812
  function ScopedNativeModal({ children, visible, ...props }) {
1800
- var _a;
1801
1813
  const layers = useLayerState(), scope = useContext9(LayerScope);
1802
1814
  const entry = scope ? layers.entries.get(scope) : void 0;
1803
- const generation = (_a = entry == null ? void 0 : entry.order) != null ? _a : 0;
1815
+ const last = useRef7(0);
1816
+ if (entry) last.current = entry.order;
1817
+ const generation = last.current;
1804
1818
  const inactive = !!scope && !layers.isActive(scope);
1805
1819
  const host = useContext9(FeedbackOverlayContext), id = "kjun-" + useId3(), register = host == null ? void 0 : host.register;
1806
- useEffect4(
1820
+ useEffect5(
1807
1821
  () => visible && register ? register(id) : void 0,
1808
1822
  [visible, register, id, generation]
1809
1823
  );
@@ -1928,6 +1942,7 @@ function KjunModal({
1928
1942
  open,
1929
1943
  onOpenChange,
1930
1944
  onClose,
1945
+ onAfterClose,
1931
1946
  onCancel,
1932
1947
  onConfirm,
1933
1948
  title = "",
@@ -1975,10 +1990,15 @@ function KjunModal({
1975
1990
  const layer = useLayer(open, motion.present, "window", () => {
1976
1991
  if (closeOnEsc) close();
1977
1992
  });
1993
+ const iosDismiss = Platform10.OS === "ios";
1994
+ useAfterClose(motion.present, onAfterClose, !iosDismiss);
1978
1995
  return /* @__PURE__ */ jsx13(LayerScope.Provider, { value: layer.id, children: /* @__PURE__ */ jsx13(
1979
1996
  ScopedNativeModal,
1980
1997
  {
1981
1998
  visible: motion.present,
1999
+ onDismiss: iosDismiss ? () => {
2000
+ if (!open) onAfterClose == null ? void 0 : onAfterClose();
2001
+ } : void 0,
1982
2002
  transparent: true,
1983
2003
  animationType: "none",
1984
2004
  onRequestClose: () => {
@@ -2155,7 +2175,11 @@ function KjunCard({
2155
2175
  border = false,
2156
2176
  dividers = false,
2157
2177
  children,
2158
- style
2178
+ style,
2179
+ pressable = false,
2180
+ disabled = false,
2181
+ ariaLabel,
2182
+ onPress
2159
2183
  }) {
2160
2184
  const { colors } = useKjunStyles();
2161
2185
  const id = "kjun-" + useId4().replace(/[^a-z0-9]/gi, "");
@@ -2166,7 +2190,7 @@ function KjunCard({
2166
2190
  const hasHeading = hasContent(header) || hasContent(title) || hasContent(subtitle);
2167
2191
  const hasHeader = hasHeading || hasContent(headerActions);
2168
2192
  const hasBody = hasContent(children), hasFooter = hasContent(footer), hasMedia = hasContent(media);
2169
- return /* @__PURE__ */ jsxs5(View8, { style: [
2193
+ const base = [
2170
2194
  {
2171
2195
  minWidth: 0,
2172
2196
  borderRadius: corner,
@@ -2175,7 +2199,8 @@ function KjunCard({
2175
2199
  },
2176
2200
  Platform11.OS === "web" && surface === "glass" ? { backdropFilter: `blur(${tokens10.card.glassBlur}px)` } : {},
2177
2201
  style
2178
- ], children: [
2202
+ ];
2203
+ const parts = /* @__PURE__ */ jsxs5(Fragment3, { children: [
2179
2204
  paint.gradientEnd && /* @__PURE__ */ jsx14(View8, { pointerEvents: "none", style: { position: "absolute", inset: 0, borderRadius: corner, overflow: "hidden" }, children: /* @__PURE__ */ jsxs5(Svg2, { width: "100%", height: "100%", children: [
2180
2205
  /* @__PURE__ */ jsx14(Defs, { children: /* @__PURE__ */ jsxs5(LinearGradient, { id, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
2181
2206
  /* @__PURE__ */ jsx14(Stop, { offset: "0", stopColor: colors[paint.background] }),
@@ -2218,6 +2243,18 @@ function KjunCard({
2218
2243
  boxShadow: [{ offsetX: 0, offsetY: 0, blurRadius: 0, spreadDistance: tokens10.card.borderWidth, inset: true, color: borderColor }]
2219
2244
  } })
2220
2245
  ] });
2246
+ return pressable ? /* @__PURE__ */ jsx14(
2247
+ AccessiblePressable,
2248
+ {
2249
+ accessibilityRole: "button",
2250
+ accessibilityLabel: ariaLabel != null ? ariaLabel : title,
2251
+ accessibilityState: { disabled },
2252
+ disabled,
2253
+ onPress,
2254
+ style: ({ pressed }) => [base, pressed ? { transform: [{ scale: 0.99 }] } : null, disabled ? { opacity: tokens10.states.opacity.disabled } : null],
2255
+ children: parts
2256
+ }
2257
+ ) : /* @__PURE__ */ jsx14(View8, { style: base, children: parts });
2221
2258
  }
2222
2259
 
2223
2260
  // shared/package-runtime/alert-live.ts
@@ -2228,8 +2265,8 @@ function alertRole(tone, live) {
2228
2265
  }
2229
2266
 
2230
2267
  // packages/native/src/display-primitives.tsx
2231
- import { tokens as tokens11 } from "@kjun-ui/tokens";
2232
- import { useContext as useContext10, useEffect as useEffect5, useRef as useRef6, useState as useState9 } from "react";
2268
+ import { tokens as tokens12 } from "@kjun-ui/tokens";
2269
+ import { useContext as useContext10, useEffect as useEffect6, useRef as useRef8, useState as useState9 } from "react";
2233
2270
  import {
2234
2271
  Animated as Animated5,
2235
2272
  Easing as Easing3,
@@ -2238,6 +2275,25 @@ import {
2238
2275
  View as View9
2239
2276
  } from "react-native";
2240
2277
  import Svg3, { Circle as Circle2, Path as Path2 } from "react-native-svg";
2278
+
2279
+ // shared/package-runtime/progress-circle.ts
2280
+ import { tokens as tokens11 } from "@kjun-ui/tokens";
2281
+ function progressCircle(size, percentage) {
2282
+ const { size: diameter, stroke } = tokens11.extensions.progress.circle[size];
2283
+ const radius = (diameter - stroke) / 2, circumference = 2 * Math.PI * radius;
2284
+ return {
2285
+ diameter,
2286
+ stroke,
2287
+ radius,
2288
+ centre: diameter / 2,
2289
+ circumference,
2290
+ offset: circumference * (1 - percentage / 100),
2291
+ // Small circles are too narrow for the centre percentage; screen readers still get the value.
2292
+ showsPercentage: size !== "sm"
2293
+ };
2294
+ }
2295
+
2296
+ // packages/native/src/display-primitives.tsx
2241
2297
  import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
2242
2298
  var badgeLayoutKeys = /* @__PURE__ */ new Set([
2243
2299
  "alignSelf",
@@ -2277,10 +2333,10 @@ function BadgeView({
2277
2333
  dot = false,
2278
2334
  children,
2279
2335
  style,
2280
- dotSize = tokens11.extensions.badge.dotSize
2336
+ dotSize = tokens12.extensions.badge.dotSize
2281
2337
  }) {
2282
2338
  const { colors, domainColors } = useKjunStyles();
2283
- const { x, y } = tokens11.extensions.badge.padding[size];
2339
+ const { x, y } = tokens12.extensions.badge.padding[size];
2284
2340
  const type = typeStyle(size === "xl" ? "controlLarge" : size === "lg" ? "control" : "controlSmall");
2285
2341
  const neutral = variant === "default" || variant === "secondary";
2286
2342
  const financial = variant.startsWith("price-");
@@ -2298,10 +2354,10 @@ function BadgeView({
2298
2354
  maxWidth: "100%",
2299
2355
  minWidth: 0,
2300
2356
  flexShrink: 1,
2301
- gap: tokens11.extensions.badge.gap,
2357
+ gap: tokens12.extensions.badge.gap,
2302
2358
  paddingHorizontal: x,
2303
2359
  paddingVertical: y,
2304
- borderRadius: tokens11.extensions.badge.radius,
2360
+ borderRadius: tokens12.extensions.badge.radius,
2305
2361
  backgroundColor: background
2306
2362
  },
2307
2363
  inner
@@ -2339,7 +2395,7 @@ function KjunEmpty({
2339
2395
  const m = useKjunMessages();
2340
2396
  text != null ? text : text = m.noData;
2341
2397
  const { colors } = useKjunStyles();
2342
- const spec = tokens11.extensions.empty;
2398
+ const spec = tokens12.extensions.empty;
2343
2399
  const stateContent = useContext10(DataStateContentContext);
2344
2400
  return /* @__PURE__ */ jsxs6(
2345
2401
  View9,
@@ -2347,7 +2403,7 @@ function KjunEmpty({
2347
2403
  style: {
2348
2404
  alignItems: "center",
2349
2405
  justifyContent: "center",
2350
- paddingVertical: stateContent === "empty" ? 0 : tokens11.dimension.value32
2406
+ paddingVertical: stateContent === "empty" ? 0 : tokens12.dimension.value32
2351
2407
  },
2352
2408
  children: [
2353
2409
  !!icon && /* @__PURE__ */ jsx15(View9, { style: { marginBottom: spec.iconGap }, children: /* @__PURE__ */ jsx15(KjunIcon, { name: icon, size: spec.iconSize, color: colors.textSecondary }) }),
@@ -2374,13 +2430,13 @@ function KjunEmpty({
2374
2430
  }
2375
2431
  function KjunSpinner({ size = "md", text }) {
2376
2432
  const m = useKjunMessages();
2377
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), rotation = useRef6(new Animated5.Value(0)).current;
2378
- useEffect5(() => {
2433
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), rotation = useRef8(new Animated5.Value(0)).current;
2434
+ useEffect6(() => {
2379
2435
  if (reduced) return;
2380
2436
  const loop = Animated5.loop(
2381
2437
  Animated5.timing(rotation, {
2382
2438
  toValue: 1,
2383
- duration: tokens11.motion.spin,
2439
+ duration: tokens12.motion.spin,
2384
2440
  easing: Easing3.linear,
2385
2441
  useNativeDriver: Platform12.OS !== "web"
2386
2442
  })
@@ -2391,8 +2447,8 @@ function KjunSpinner({ size = "md", text }) {
2391
2447
  rotation.setValue(0);
2392
2448
  };
2393
2449
  }, [reduced, rotation]);
2394
- const dimension = tokens11.extensions.spinner.sizes[size];
2395
- const stroke = tokens11.extensions.spinner.strokeWidths[size] * 24 / dimension;
2450
+ const dimension = tokens12.extensions.spinner.sizes[size];
2451
+ const stroke = tokens12.extensions.spinner.strokeWidths[size] * 24 / dimension;
2396
2452
  return /* @__PURE__ */ jsxs6(
2397
2453
  View9,
2398
2454
  {
@@ -2446,7 +2502,7 @@ function KjunSpinner({ size = "md", text }) {
2446
2502
  )
2447
2503
  }
2448
2504
  ),
2449
- !!text && /* @__PURE__ */ jsx15(KText, { style: { marginLeft: tokens11.dimension.value8, color: colors.textSecondary }, children: text })
2505
+ !!text && /* @__PURE__ */ jsx15(KText, { style: { marginLeft: tokens12.dimension.value8, color: colors.textSecondary }, children: text })
2450
2506
  ]
2451
2507
  }
2452
2508
  );
@@ -2467,8 +2523,8 @@ function KjunAlert({
2467
2523
  const [visible, setVisible] = useState9(true);
2468
2524
  if (!visible) return null;
2469
2525
  const tone = variant || (type === "error" ? "danger" : type), small = size === "sm";
2470
- const geometry2 = tokens11.extensions.alert;
2471
- const lineHeight = tokens11.typography[small ? "controlSmall" : "control"].lineHeightPx;
2526
+ const geometry2 = tokens12.extensions.alert;
2527
+ const lineHeight = tokens12.typography[small ? "controlSmall" : "control"].lineHeightPx;
2472
2528
  const titled = hasContent(title);
2473
2529
  const closeSize = small ? geometry2.sm.closeSize : geometry2.closeSize;
2474
2530
  const pick = (suffix) => tone === "primary" ? suffix === "Bg" ? colors.brandSubtleBg : suffix === "Light" ? colors.brandLight : colors.brand : colors[tone + suffix];
@@ -2479,11 +2535,11 @@ function KjunAlert({
2479
2535
  style: {
2480
2536
  flexDirection: "row",
2481
2537
  alignItems: "flex-start",
2482
- gap: tokens11.extensions.alert[small ? "sm" : "md"].gap,
2483
- borderWidth: tokens11.border.defaultWidth,
2484
- borderRadius: tokens11.extensions.alert.radius,
2485
- paddingVertical: tokens11.extensions.alert[small ? "sm" : "md"].paddingY,
2486
- paddingHorizontal: tokens11.extensions.alert[small ? "sm" : "md"].paddingX,
2538
+ gap: tokens12.extensions.alert[small ? "sm" : "md"].gap,
2539
+ borderWidth: tokens12.border.defaultWidth,
2540
+ borderRadius: tokens12.extensions.alert.radius,
2541
+ paddingVertical: tokens12.extensions.alert[small ? "sm" : "md"].paddingY,
2542
+ paddingHorizontal: tokens12.extensions.alert[small ? "sm" : "md"].paddingX,
2487
2543
  backgroundColor: pick("Bg"),
2488
2544
  borderColor: pick("Light")
2489
2545
  },
@@ -2498,7 +2554,7 @@ function KjunAlert({
2498
2554
  warning: "alert-triangle",
2499
2555
  danger: "alert-circle"
2500
2556
  }[tone],
2501
- size: tokens11.extensions.alert.iconSizes[small ? "sm" : "md"],
2557
+ size: tokens12.extensions.alert.iconSizes[small ? "sm" : "md"],
2502
2558
  color: pick("Accent")
2503
2559
  }
2504
2560
  ) }),
@@ -2515,7 +2571,7 @@ function KjunAlert({
2515
2571
  {
2516
2572
  accessibilityRole: "button",
2517
2573
  accessibilityLabel: m.close,
2518
- hitSlop: Math.max(0, (tokens11.native.minimumTouchTarget - closeSize) / 2),
2574
+ hitSlop: Math.max(0, (tokens12.native.minimumTouchTarget - closeSize) / 2),
2519
2575
  style: ({ pressed, hovered }) => ({
2520
2576
  width: closeSize,
2521
2577
  height: closeSize,
@@ -2553,11 +2609,58 @@ function KjunProgress({
2553
2609
  variant = "primary",
2554
2610
  showLabel = false,
2555
2611
  label,
2556
- subLabel
2612
+ subLabel,
2613
+ shape = "bar"
2557
2614
  }) {
2558
2615
  const m = useKjunMessages();
2559
- const { colors } = useKjunStyles();
2616
+ const { colors, numericFontFamily, fontFamily } = useKjunStyles();
2560
2617
  const percentage = Number.isFinite(value) && max > 0 ? Math.min(100, Math.max(0, Math.round(value / max * 100))) : 0;
2618
+ const name = typeof label === "string" ? label : m.progress, color = variant === "primary" ? colors.brand : colors[variant];
2619
+ const semantics = {
2620
+ accessibilityRole: "progressbar",
2621
+ accessibilityLabel: name,
2622
+ accessibilityValue: { min: 0, max: 100, now: percentage },
2623
+ "aria-valuemin": 0,
2624
+ "aria-valuemax": 100,
2625
+ "aria-valuenow": percentage
2626
+ };
2627
+ if (shape === "circle") {
2628
+ const c = progressCircle(size, percentage);
2629
+ return /* @__PURE__ */ jsxs6(View9, { style: { alignSelf: "flex-start", alignItems: "center" }, children: [
2630
+ /* @__PURE__ */ jsxs6(View9, { ...semantics, style: { width: c.diameter, height: c.diameter, alignItems: "center", justifyContent: "center" }, children: [
2631
+ /* @__PURE__ */ jsxs6(Svg3, { width: c.diameter, height: c.diameter, viewBox: `0 0 ${c.diameter} ${c.diameter}`, style: StyleSheet4.absoluteFill, children: [
2632
+ /* @__PURE__ */ jsx15(Circle2, { cx: c.centre, cy: c.centre, r: c.radius, stroke: colors.secondary, strokeWidth: c.stroke, fill: "none" }),
2633
+ percentage > 0 && /* @__PURE__ */ jsx15(
2634
+ Circle2,
2635
+ {
2636
+ cx: c.centre,
2637
+ cy: c.centre,
2638
+ r: c.radius,
2639
+ stroke: color,
2640
+ strokeWidth: c.stroke,
2641
+ fill: "none",
2642
+ strokeLinecap: "round",
2643
+ strokeDasharray: c.circumference,
2644
+ strokeDashoffset: c.offset,
2645
+ rotation: -90,
2646
+ origin: `${c.centre}, ${c.centre}`
2647
+ }
2648
+ )
2649
+ ] }),
2650
+ showLabel && c.showsPercentage && /* @__PURE__ */ jsxs6(KText, { style: {
2651
+ ...typeStyle(size === "lg" ? "numberMd" : "meta"),
2652
+ fontFamily: numericFontFamily || fontFamily,
2653
+ fontVariant: ["tabular-nums"],
2654
+ color: colors.text
2655
+ }, children: [
2656
+ percentage,
2657
+ "%"
2658
+ ] })
2659
+ ] }),
2660
+ content(label, { ...typeStyle("caption"), marginTop: tokens12.dimension.value8, color: colors.textSecondary, textAlign: "center" }),
2661
+ content(subLabel, { ...typeStyle("caption"), marginTop: tokens12.dimension.value4, color: colors.textTertiary, textAlign: "center" })
2662
+ ] });
2663
+ }
2561
2664
  return /* @__PURE__ */ jsxs6(View9, { children: [
2562
2665
  !!(label || showLabel) && /* @__PURE__ */ jsxs6(
2563
2666
  View9,
@@ -2565,7 +2668,7 @@ function KjunProgress({
2565
2668
  style: {
2566
2669
  flexDirection: "row",
2567
2670
  justifyContent: "space-between",
2568
- marginBottom: tokens11.dimension.value8
2671
+ marginBottom: tokens12.dimension.value8
2569
2672
  },
2570
2673
  children: [
2571
2674
  content(label, {
@@ -2591,13 +2694,11 @@ function KjunProgress({
2591
2694
  /* @__PURE__ */ jsx15(
2592
2695
  View9,
2593
2696
  {
2594
- accessibilityRole: "progressbar",
2595
- accessibilityLabel: typeof label === "string" ? label : m.progress,
2596
- accessibilityValue: { min: 0, max: 100, now: percentage },
2697
+ ...semantics,
2597
2698
  style: {
2598
- height: tokens11.extensions.progress.heights[size],
2699
+ height: tokens12.extensions.progress.heights[size],
2599
2700
  backgroundColor: colors.secondary,
2600
- borderRadius: tokens11.radius.radius9999,
2701
+ borderRadius: tokens12.radius.radius9999,
2601
2702
  overflow: "hidden"
2602
2703
  },
2603
2704
  children: /* @__PURE__ */ jsx15(
@@ -2606,8 +2707,8 @@ function KjunProgress({
2606
2707
  style: {
2607
2708
  width: `${percentage}%`,
2608
2709
  height: "100%",
2609
- borderRadius: tokens11.radius.radius9999,
2610
- backgroundColor: variant === "primary" ? colors.brand : colors[variant]
2710
+ borderRadius: tokens12.radius.radius9999,
2711
+ backgroundColor: color
2611
2712
  }
2612
2713
  }
2613
2714
  )
@@ -2615,15 +2716,15 @@ function KjunProgress({
2615
2716
  ),
2616
2717
  content(subLabel, {
2617
2718
  ...typeStyle("caption"),
2618
- marginTop: tokens11.dimension.value4,
2719
+ marginTop: tokens12.dimension.value4,
2619
2720
  color: colors.textTertiary
2620
2721
  })
2621
2722
  ] });
2622
2723
  }
2623
2724
 
2624
2725
  // packages/native/src/skeleton-base.tsx
2625
- import { tokens as tokens12 } from "@kjun-ui/tokens";
2626
- import { useEffect as useEffect6, useRef as useRef7 } from "react";
2726
+ import { tokens as tokens13 } from "@kjun-ui/tokens";
2727
+ import { useEffect as useEffect7, useRef as useRef9 } from "react";
2627
2728
  import {
2628
2729
  Animated as Animated6,
2629
2730
  View as View10
@@ -2638,19 +2739,19 @@ function KjunSkeleton({
2638
2739
  animated = true,
2639
2740
  rounded = true
2640
2741
  }) {
2641
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef7(new Animated6.Value(1)).current;
2642
- useEffect6(() => {
2742
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef9(new Animated6.Value(1)).current;
2743
+ useEffect7(() => {
2643
2744
  if (!animated || reduced) return;
2644
2745
  const loop = Animated6.loop(
2645
2746
  Animated6.sequence([
2646
2747
  Animated6.timing(opacity, {
2647
2748
  toValue: 0.6,
2648
- duration: tokens12.motion.shimmer / 2,
2749
+ duration: tokens13.motion.shimmer / 2,
2649
2750
  useNativeDriver: false
2650
2751
  }),
2651
2752
  Animated6.timing(opacity, {
2652
2753
  toValue: 1,
2653
- duration: tokens12.motion.shimmer / 2,
2754
+ duration: tokens13.motion.shimmer / 2,
2654
2755
  useNativeDriver: false
2655
2756
  })
2656
2757
  ])
@@ -2669,18 +2770,18 @@ function KjunSkeleton({
2669
2770
  width: w,
2670
2771
  height: h,
2671
2772
  backgroundColor: shimmer,
2672
- borderRadius: tokens12.extensions.skeleton.lineRadius,
2773
+ borderRadius: tokens13.extensions.skeleton.lineRadius,
2673
2774
  ...extra
2674
2775
  }
2675
2776
  }
2676
2777
  );
2677
2778
  const count = (n) => Array.from({ length: Math.max(0, Math.floor(n)) }, (_, i) => i + 1);
2678
- const line = (w, key, h = tokens12.extensions.skeleton.lineHeights.md) => /* @__PURE__ */ jsx16(View10, { style: { marginBottom: key === rows ? 0 : tokens12.extensions.skeleton.gap }, children: block(w, h) }, key);
2779
+ const line = (w, key, h = tokens13.extensions.skeleton.lineHeights.md) => /* @__PURE__ */ jsx16(View10, { style: { marginBottom: key === rows ? 0 : tokens13.extensions.skeleton.gap }, children: block(w, h) }, key);
2679
2780
  const frame = {
2680
- padding: tokens12.extensions.skeleton.padding,
2681
- borderWidth: tokens12.border.defaultWidth,
2781
+ padding: tokens13.extensions.skeleton.padding,
2782
+ borderWidth: tokens13.border.defaultWidth,
2682
2783
  borderColor: colors.border,
2683
- borderRadius: tokens12.extensions.skeleton.radius,
2784
+ borderRadius: tokens13.extensions.skeleton.radius,
2684
2785
  backgroundColor: colors.background
2685
2786
  };
2686
2787
  return /* @__PURE__ */ jsxs7(
@@ -2696,7 +2797,7 @@ function KjunSkeleton({
2696
2797
  i
2697
2798
  )
2698
2799
  ),
2699
- type === "avatar" && block(width || tokens12.extensions.skeleton.avatarSize, height || tokens12.extensions.skeleton.avatarSize, { borderRadius: rounded ? tokens12.radius.radius9999 : tokens12.extensions.skeleton.blockRadius }),
2800
+ type === "avatar" && block(width || tokens13.extensions.skeleton.avatarSize, height || tokens13.extensions.skeleton.avatarSize, { borderRadius: rounded ? tokens13.radius.radius9999 : tokens13.extensions.skeleton.blockRadius }),
2700
2801
  type === "card" && /* @__PURE__ */ jsxs7(View10, { style: frame, children: [
2701
2802
  /* @__PURE__ */ jsxs7(
2702
2803
  View10,
@@ -2704,19 +2805,19 @@ function KjunSkeleton({
2704
2805
  style: {
2705
2806
  flexDirection: "row",
2706
2807
  alignItems: "center",
2707
- gap: tokens12.extensions.skeleton.gap,
2708
- marginBottom: tokens12.dimension.value16
2808
+ gap: tokens13.extensions.skeleton.gap,
2809
+ marginBottom: tokens13.dimension.value16
2709
2810
  },
2710
2811
  children: [
2711
- block(tokens12.extensions.skeleton.cardAvatarSize, tokens12.extensions.skeleton.cardAvatarSize, { borderRadius: tokens12.radius.radius9999 }),
2712
- /* @__PURE__ */ jsxs7(View10, { style: { flex: 1, gap: tokens12.dimension.value8 }, children: [
2812
+ block(tokens13.extensions.skeleton.cardAvatarSize, tokens13.extensions.skeleton.cardAvatarSize, { borderRadius: tokens13.radius.radius9999 }),
2813
+ /* @__PURE__ */ jsxs7(View10, { style: { flex: 1, gap: tokens13.dimension.value8 }, children: [
2713
2814
  block("60%"),
2714
- block("40%", tokens12.extensions.skeleton.lineHeights.sm)
2815
+ block("40%", tokens13.extensions.skeleton.lineHeights.sm)
2715
2816
  ] })
2716
2817
  ]
2717
2818
  }
2718
2819
  ),
2719
- /* @__PURE__ */ jsxs7(View10, { style: { gap: tokens12.dimension.value10 }, children: [
2820
+ /* @__PURE__ */ jsxs7(View10, { style: { gap: tokens13.dimension.value10 }, children: [
2720
2821
  block("100%"),
2721
2822
  block("80%"),
2722
2823
  block("60%")
@@ -2726,9 +2827,9 @@ function KjunSkeleton({
2726
2827
  View10,
2727
2828
  {
2728
2829
  style: {
2729
- borderWidth: tokens12.border.defaultWidth,
2830
+ borderWidth: tokens13.border.defaultWidth,
2730
2831
  borderColor: colors.border,
2731
- borderRadius: tokens12.extensions.skeleton.blockRadius,
2832
+ borderRadius: tokens13.extensions.skeleton.blockRadius,
2732
2833
  overflow: "hidden"
2733
2834
  },
2734
2835
  children: [0, ...count(rows)].map((row) => /* @__PURE__ */ jsx16(
@@ -2737,7 +2838,7 @@ function KjunSkeleton({
2737
2838
  style: {
2738
2839
  flexDirection: "row",
2739
2840
  backgroundColor: row === 0 ? colors.secondary : void 0,
2740
- borderBottomWidth: row === rows ? 0 : tokens12.border.defaultWidth,
2841
+ borderBottomWidth: row === rows ? 0 : tokens13.border.defaultWidth,
2741
2842
  borderBottomColor: colors.border
2742
2843
  },
2743
2844
  children: count(columns).map((col) => /* @__PURE__ */ jsx16(
@@ -2745,8 +2846,8 @@ function KjunSkeleton({
2745
2846
  {
2746
2847
  style: {
2747
2848
  flex: 1,
2748
- paddingVertical: tokens12.dimension.value12,
2749
- paddingHorizontal: tokens12.dimension.value16
2849
+ paddingVertical: tokens13.dimension.value12,
2850
+ paddingHorizontal: tokens13.dimension.value16
2750
2851
  },
2751
2852
  children: block(
2752
2853
  row === 0 ? "70%" : [
@@ -2756,7 +2857,7 @@ function KjunSkeleton({
2756
2857
  "75%",
2757
2858
  "85%"
2758
2859
  ][(row + col) % 5],
2759
- tokens12.extensions.skeleton.tableLineHeight
2860
+ tokens13.extensions.skeleton.tableLineHeight
2760
2861
  )
2761
2862
  },
2762
2863
  col
@@ -2778,16 +2879,16 @@ function KjunSkeleton({
2778
2879
  }
2779
2880
  ],
2780
2881
  children: [
2781
- /* @__PURE__ */ jsxs7(View10, { style: { flex: 1, gap: tokens12.dimension.value8 }, children: [
2782
- block("40%", tokens12.extensions.skeleton.lineHeights.sm),
2783
- block("60%", tokens12.extensions.skeleton.lineHeights.lg),
2784
- block("30%", tokens12.extensions.skeleton.lineHeights.sm)
2882
+ /* @__PURE__ */ jsxs7(View10, { style: { flex: 1, gap: tokens13.dimension.value8 }, children: [
2883
+ block("40%", tokens13.extensions.skeleton.lineHeights.sm),
2884
+ block("60%", tokens13.extensions.skeleton.lineHeights.lg),
2885
+ block("30%", tokens13.extensions.skeleton.lineHeights.sm)
2785
2886
  ] }),
2786
- block(tokens12.extensions.skeleton.statWidth, tokens12.extensions.skeleton.statHeight)
2887
+ block(tokens13.extensions.skeleton.statWidth, tokens13.extensions.skeleton.statHeight)
2787
2888
  ]
2788
2889
  }
2789
2890
  ),
2790
- type === "block" && block(width || "100%", height != null ? height : tokens12.extensions.skeleton.blockHeight, { borderRadius: tokens12.extensions.skeleton.blockRadius })
2891
+ type === "block" && block(width || "100%", height != null ? height : tokens13.extensions.skeleton.blockHeight, { borderRadius: tokens13.extensions.skeleton.blockRadius })
2791
2892
  ]
2792
2893
  }
2793
2894
  );
@@ -2796,7 +2897,7 @@ function KjunSkeleton({
2796
2897
  // packages/native/src/layout-primitives.tsx
2797
2898
  import { Children as Children2, Fragment as Fragment4, cloneElement as cloneElement2, isValidElement as isValidElement3 } from "react";
2798
2899
  import { View as View11 } from "react-native";
2799
- import { tokens as tokens13 } from "@kjun-ui/tokens";
2900
+ import { tokens as tokens14 } from "@kjun-ui/tokens";
2800
2901
 
2801
2902
  // shared/package-runtime/layout-primitives.ts
2802
2903
  var titleVariants = ["pageTitle", "sectionTitle", "cardTitle"];
@@ -2805,15 +2906,27 @@ var isNumericVariant = (variant) => numeric.test(variant);
2805
2906
 
2806
2907
  // packages/native/src/layout-primitives.tsx
2807
2908
  import { jsx as jsx17 } from "react/jsx-runtime";
2808
- var toneRole = { default: "text", secondary: "textSecondary", tertiary: "textTertiary", disabled: "textDisabled" };
2909
+ var toneRole = {
2910
+ default: "text",
2911
+ secondary: "textSecondary",
2912
+ tertiary: "textTertiary",
2913
+ disabled: "textDisabled",
2914
+ brand: "brand",
2915
+ danger: "danger",
2916
+ success: "success",
2917
+ warning: "warning",
2918
+ inverse: "onBrand"
2919
+ };
2809
2920
  var textAlign = { start: "left", center: "center", end: "right" };
2810
- function KjunText({ variant = "body", tone = "default", align, maxLines, style, children }) {
2921
+ function KjunText({ variant = "body", tone = "default", align, maxLines, style, children, ...rest }) {
2922
+ var _a;
2811
2923
  const { colors, fontFamily, numericFontFamily } = useKjunStyles();
2812
2924
  const lines = maxLines && maxLines > 0 ? Math.floor(maxLines) : void 0;
2813
2925
  return /* @__PURE__ */ jsx17(
2814
2926
  KText,
2815
2927
  {
2816
- accessibilityRole: titleVariants.includes(variant) ? "header" : void 0,
2928
+ ...rest,
2929
+ accessibilityRole: (_a = rest.accessibilityRole) != null ? _a : titleVariants.includes(variant) ? "header" : void 0,
2817
2930
  numberOfLines: lines,
2818
2931
  ellipsizeMode: lines ? "tail" : void 0,
2819
2932
  style: [
@@ -2833,56 +2946,61 @@ function flatten(children, path = "") {
2833
2946
  return isValidElement3(child) && child.type === Fragment4 ? flatten(child.props.children, `${key}.`) : [[key, child]];
2834
2947
  });
2835
2948
  }
2836
- function items(children) {
2949
+ function items(children, childAlign) {
2837
2950
  return flatten(children).map(([key, child]) => {
2838
2951
  if (typeof child === "string" || typeof child === "number") return /* @__PURE__ */ jsx17(KText, { children: child }, key);
2839
2952
  if (isValidElement3(child) && child.type === KjunFormGroup) {
2840
2953
  const group = child;
2841
2954
  return cloneElement2(group, { key, style: [{ marginBottom: 0 }, group.props.style] });
2842
2955
  }
2956
+ if (childAlign && isValidElement3(child) && (child.type === KjunButton || child.type === KjunBadge)) {
2957
+ const control = child;
2958
+ return cloneElement2(control, { key, style: [{ alignSelf: childAlign }, control.props.style] });
2959
+ }
2843
2960
  return isValidElement3(child) ? cloneElement2(child, { key }) : child;
2844
2961
  });
2845
2962
  }
2963
+ var followed = (align) => align && align !== "stretch" ? crossAxis[align] : void 0;
2846
2964
  var stackGap = {
2847
2965
  none: 0,
2848
- sm: tokens13.space.stack.sm,
2849
- md: tokens13.space.stack.md,
2850
- lg: tokens13.space.stack.lg,
2851
- "section-sm": tokens13.space.section.sm,
2852
- "section-md": tokens13.space.section.md,
2853
- "section-lg": tokens13.space.section.lg
2966
+ sm: tokens14.space.stack.sm,
2967
+ md: tokens14.space.stack.md,
2968
+ lg: tokens14.space.stack.lg,
2969
+ "section-sm": tokens14.space.section.sm,
2970
+ "section-md": tokens14.space.section.md,
2971
+ "section-lg": tokens14.space.section.lg
2854
2972
  };
2855
2973
  var inlineGap = {
2856
2974
  none: 0,
2857
- xs: tokens13.space.inline.xs,
2858
- sm: tokens13.space.inline.sm,
2859
- md: tokens13.space.inline.md,
2860
- lg: tokens13.space.inline.lg
2975
+ xs: tokens14.space.inline.xs,
2976
+ sm: tokens14.space.inline.sm,
2977
+ md: tokens14.space.inline.md,
2978
+ lg: tokens14.space.inline.lg
2861
2979
  };
2862
2980
  var crossAxis = { stretch: "stretch", start: "flex-start", center: "center", end: "flex-end", baseline: "baseline" };
2863
2981
  var mainAxis = { start: "flex-start", center: "center", end: "flex-end", between: "space-between" };
2864
- function KjunStack({ gap = "md", align = "stretch", style, children }) {
2865
- return /* @__PURE__ */ jsx17(View11, { style: [{ flexDirection: "column", alignItems: crossAxis[align], gap: stackGap[gap], minWidth: 0 }, style], children: items(children) });
2982
+ function KjunStack({ gap = "md", align, style, children }) {
2983
+ return /* @__PURE__ */ jsx17(View11, { style: [{ flexDirection: "column", alignItems: crossAxis[align != null ? align : "stretch"], gap: stackGap[gap], minWidth: 0 }, style], children: items(children, followed(align)) });
2866
2984
  }
2867
- function KjunInline({ gap = "sm", align = "center", justify = "start", wrap = true, style, children }) {
2985
+ function KjunInline({ gap = "sm", align, justify = "start", wrap = true, style, children }) {
2868
2986
  return /* @__PURE__ */ jsx17(View11, { style: [{
2869
2987
  flexDirection: "row",
2870
2988
  flexWrap: wrap ? "wrap" : "nowrap",
2871
- alignItems: crossAxis[align],
2989
+ alignItems: crossAxis[align != null ? align : "center"],
2872
2990
  justifyContent: mainAxis[justify],
2873
2991
  gap: inlineGap[gap],
2874
2992
  minWidth: 0
2875
- }, style], children: items(children) });
2993
+ }, style], children: items(children, followed(align)) });
2876
2994
  }
2877
2995
 
2878
2996
  // shared/package-runtime/feedback-dialog.ts
2879
- import { useRef as useRef8, useState as useState10 } from "react";
2997
+ import { useRef as useRef10, useState as useState10 } from "react";
2880
2998
  function useFeedbackDialog(controller, request, messages = kjunMessagesKo) {
2881
2999
  const options = request.options;
2882
3000
  const [value, setValue] = useState10(options.initialValue || "");
2883
3001
  const [error, setError] = useState10("");
2884
3002
  const [busy, setBusy] = useState10(false);
2885
- const working = useRef8(false);
3003
+ const working = useRef10(false);
2886
3004
  const active = () => {
2887
3005
  var _a;
2888
3006
  return ((_a = controller.getSnapshot().current) == null ? void 0 : _a.id) === request.id;
@@ -2924,11 +3042,11 @@ function useFeedbackDialog(controller, request, messages = kjunMessagesKo) {
2924
3042
  }
2925
3043
 
2926
3044
  // shared/package-runtime/feedback-motion.ts
2927
- import { tokens as tokens14 } from "@kjun-ui/tokens";
2928
- import { useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState11 } from "react";
3045
+ import { tokens as tokens15 } from "@kjun-ui/tokens";
3046
+ import { useLayoutEffect as useLayoutEffect4, useRef as useRef11, useState as useState11 } from "react";
2929
3047
  function usePresentedToasts(toasts, reduced) {
2930
3048
  const [items2, setItems] = useState11([]);
2931
- const removals = useRef9(/* @__PURE__ */ new Map());
3049
+ const removals = useRef11(/* @__PURE__ */ new Map());
2932
3050
  useLayoutEffect4(() => {
2933
3051
  const ids = new Set(toasts.map((toast) => toast.id));
2934
3052
  setItems((previous) => {
@@ -2942,7 +3060,7 @@ function usePresentedToasts(toasts, reduced) {
2942
3060
  if (!removals.current.has(item.toast.id)) removals.current.set(item.toast.id, setTimeout(() => {
2943
3061
  removals.current.delete(item.toast.id);
2944
3062
  setItems((current) => current.filter((value) => value.toast.id !== item.toast.id));
2945
- }, tokens14.motion.toastExit));
3063
+ }, tokens15.motion.toastExit));
2946
3064
  }
2947
3065
  return next;
2948
3066
  });
@@ -2964,7 +3082,7 @@ function usePresentedRequest(current, reduced) {
2964
3082
  setRequest(current);
2965
3083
  return;
2966
3084
  }
2967
- const timer = setTimeout(() => setRequest(current), tokens14.motion.layerExit);
3085
+ const timer = setTimeout(() => setRequest(current), tokens15.motion.layerExit);
2968
3086
  return () => clearTimeout(timer);
2969
3087
  }, [current, request, reduced]);
2970
3088
  return { request, open: !!request && (current == null ? void 0 : current.id) === request.id };
@@ -2978,9 +3096,9 @@ function useOptionalKjunFeedback() {
2978
3096
  }
2979
3097
 
2980
3098
  // packages/native/src/toast-stack.tsx
2981
- import { useLayoutEffect as useLayoutEffect5, useRef as useRef11 } from "react";
3099
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef13 } from "react";
2982
3100
  import { Animated as Animated8, Platform as Platform13, View as View13 } from "react-native";
2983
- import { tokens as tokens16 } from "@kjun-ui/tokens";
3101
+ import { tokens as tokens17 } from "@kjun-ui/tokens";
2984
3102
 
2985
3103
  // shared/package-runtime/elevation.ts
2986
3104
  function directionalShadow(layers, direction) {
@@ -2995,8 +3113,8 @@ function shadowLayers(layers, colors) {
2995
3113
  }
2996
3114
 
2997
3115
  // packages/native/src/toast.tsx
2998
- import { tokens as tokens15 } from "@kjun-ui/tokens";
2999
- import { useEffect as useEffect7, useRef as useRef10 } from "react";
3116
+ import { tokens as tokens16 } from "@kjun-ui/tokens";
3117
+ import { useEffect as useEffect8, useRef as useRef12 } from "react";
3000
3118
  import { Animated as Animated7, View as View12 } from "react-native";
3001
3119
  import { jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
3002
3120
  function ToastView({
@@ -3004,14 +3122,14 @@ function ToastView({
3004
3122
  controller
3005
3123
  }) {
3006
3124
  const m = useKjunMessages();
3007
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), progress = useRef10(new Animated7.Value(1)).current;
3008
- const reasons = useRef10({
3125
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), progress = useRef12(new Animated7.Value(1)).current;
3126
+ const reasons = useRef12({
3009
3127
  hover: /* @__PURE__ */ Symbol("hover"),
3010
3128
  actionHover: /* @__PURE__ */ Symbol("actionHover"),
3011
3129
  closeHover: /* @__PURE__ */ Symbol("closeHover"),
3012
3130
  focus: /* @__PURE__ */ Symbol("focus")
3013
3131
  }).current;
3014
- useEffect7(() => () => {
3132
+ useEffect8(() => () => {
3015
3133
  for (const reason of Object.values(reasons)) controller.resumeToast(toast.id, reason);
3016
3134
  }, [controller, toast.id, reasons]);
3017
3135
  const tone = toast.type === "error" ? "danger" : toast.type || "info", icon = {
@@ -3020,7 +3138,7 @@ function ToastView({
3020
3138
  warning: "alert-triangle",
3021
3139
  info: "info-circle"
3022
3140
  }[tone];
3023
- useEffect7(() => {
3141
+ useEffect8(() => {
3024
3142
  progress.stopAnimation();
3025
3143
  progress.setValue(toast.duration ? toast.remaining / toast.duration : 1);
3026
3144
  if (!toast.paused && !reduced) {
@@ -3039,7 +3157,7 @@ function ToastView({
3039
3157
  accessible: false,
3040
3158
  onHoverIn: () => controller.pauseToast(toast.id, reasons.hover),
3041
3159
  onHoverOut: () => controller.resumeToast(toast.id, reasons.hover),
3042
- style: { width: "100%", maxWidth: tokens15.extensions.toast.maxWidth, alignSelf: "flex-end" },
3160
+ style: { width: "100%", maxWidth: tokens16.extensions.toast.maxWidth, alignSelf: "flex-end" },
3043
3161
  children: /* @__PURE__ */ jsxs8(
3044
3162
  View12,
3045
3163
  {
@@ -3048,19 +3166,19 @@ function ToastView({
3048
3166
  style: {
3049
3167
  flexDirection: "row",
3050
3168
  alignItems: toast.title ? "flex-start" : "center",
3051
- gap: tokens15.extensions.toast.gap,
3052
- padding: tokens15.extensions.toast.padding,
3053
- borderRadius: tokens15.extensions.toast.radius,
3169
+ gap: tokens16.extensions.toast.gap,
3170
+ padding: tokens16.extensions.toast.padding,
3171
+ borderRadius: tokens16.extensions.toast.radius,
3054
3172
  backgroundColor: colors.surface,
3055
- boxShadow: shadowLayers(tokens15.extensions.toast.elevation, colors),
3056
- borderWidth: tokens15.border.defaultWidth,
3173
+ boxShadow: shadowLayers(tokens16.extensions.toast.elevation, colors),
3174
+ borderWidth: tokens16.border.defaultWidth,
3057
3175
  borderColor: colors.border,
3058
3176
  overflow: "hidden"
3059
3177
  },
3060
3178
  children: [
3061
3179
  /* @__PURE__ */ jsx18(KjunIcon, { name: icon, color: colors[`${tone}Accent`] }),
3062
3180
  /* @__PURE__ */ jsxs8(View12, { style: { flex: 1, minWidth: 0 }, children: [
3063
- !!toast.title && /* @__PURE__ */ jsx18(KText, { style: { fontWeight: typeStyle("control").fontWeight, marginBottom: tokens15.extensions.toast.titleGap }, children: toast.title }),
3181
+ !!toast.title && /* @__PURE__ */ jsx18(KText, { style: { fontWeight: typeStyle("control").fontWeight, marginBottom: tokens16.extensions.toast.titleGap }, children: toast.title }),
3064
3182
  /* @__PURE__ */ jsx18(KText, { style: { color: colors.textSecondary }, children: toast.message }),
3065
3183
  toast.action && /* @__PURE__ */ jsx18(
3066
3184
  AccessiblePressable,
@@ -3078,7 +3196,7 @@ function ToastView({
3078
3196
  dismiss();
3079
3197
  }
3080
3198
  },
3081
- style: { minHeight: tokens15.native.minimumTouchTarget, justifyContent: "center", marginTop: tokens15.extensions.toast.actionGap },
3199
+ style: { minHeight: tokens16.native.minimumTouchTarget, justifyContent: "center", marginTop: tokens16.extensions.toast.actionGap },
3082
3200
  children: /* @__PURE__ */ jsx18(
3083
3201
  KText,
3084
3202
  {
@@ -3100,11 +3218,11 @@ function ToastView({
3100
3218
  onBlur: () => controller.resumeToast(toast.id, reasons.focus),
3101
3219
  onPress: dismiss,
3102
3220
  style: {
3103
- minWidth: Math.max(tokens15.extensions.toast.closeSize, tokens15.native.minimumTouchTarget),
3104
- minHeight: Math.max(tokens15.extensions.toast.closeSize, tokens15.native.minimumTouchTarget),
3221
+ minWidth: Math.max(tokens16.extensions.toast.closeSize, tokens16.native.minimumTouchTarget),
3222
+ minHeight: Math.max(tokens16.extensions.toast.closeSize, tokens16.native.minimumTouchTarget),
3105
3223
  alignItems: "center",
3106
3224
  justifyContent: "center",
3107
- borderRadius: tokens15.extensions.toast.closeRadius
3225
+ borderRadius: tokens16.extensions.toast.closeRadius
3108
3226
  },
3109
3227
  children: /* @__PURE__ */ jsx18(KjunIcon, { name: "x", color: colors.textTertiary })
3110
3228
  }
@@ -3117,7 +3235,7 @@ function ToastView({
3117
3235
  position: "absolute",
3118
3236
  bottom: 0,
3119
3237
  left: 0,
3120
- height: tokens15.extensions.toast.progressHeight,
3238
+ height: tokens16.extensions.toast.progressHeight,
3121
3239
  width: progress.interpolate({
3122
3240
  inputRange: [0, 1],
3123
3241
  outputRange: ["0%", "100%"]
@@ -3140,9 +3258,9 @@ function useToastReflow(_root, _reduced) {
3140
3258
  // packages/native/src/toast-stack.tsx
3141
3259
  import { jsx as jsx19 } from "react/jsx-runtime";
3142
3260
  function ToastSlot({ item, controller, boxes }) {
3143
- const born = useRef11(Math.min(tokens16.motion.toastEnter, Date.now() - item.born)).current;
3144
- const motion = useNativePresence(!item.exiting, tokens16.motion.toastEnter - born, tokens16.motion.toastExit, true, born / tokens16.motion.toastEnter);
3145
- const offset = useRef11(new Animated8.Value(0)).current;
3261
+ const born = useRef13(Math.min(tokens17.motion.toastEnter, Date.now() - item.born)).current;
3262
+ const motion = useNativePresence(!item.exiting, tokens17.motion.toastEnter - born, tokens17.motion.toastExit, true, born / tokens17.motion.toastEnter);
3263
+ const offset = useRef13(new Animated8.Value(0)).current;
3146
3264
  const box = boxes.get(item.toast.id);
3147
3265
  useLayoutEffect5(() => {
3148
3266
  if (motion.reduced) {
@@ -3162,7 +3280,7 @@ function ToastSlot({ item, controller, boxes }) {
3162
3280
  boxes.set(item.toast.id, next);
3163
3281
  if (old && old.y !== next.y && !motion.reduced) offset.stopAnimation((current) => {
3164
3282
  offset.setValue(current + old.y - next.y);
3165
- Animated8.timing(offset, { toValue: 0, duration: tokens16.motion.toastMove, easing: motionOut, useNativeDriver: nativeDriver }).start();
3283
+ Animated8.timing(offset, { toValue: 0, duration: tokens17.motion.toastMove, easing: motionOut, useNativeDriver: nativeDriver }).start();
3166
3284
  });
3167
3285
  },
3168
3286
  style: { transform: [{ translateY: offset }], ...item.exiting && box ? {
@@ -3179,7 +3297,7 @@ function ToastSlot({ item, controller, boxes }) {
3179
3297
  accessibilityElementsHidden: item.exiting,
3180
3298
  importantForAccessibility: item.exiting ? "no-hide-descendants" : "auto",
3181
3299
  ...item.exiting ? { inert: true } : {},
3182
- style: { opacity: motion.opacity, transform: [{ translateY: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [-tokens16.motionDistance.toast, 0] }) }] },
3300
+ style: { opacity: motion.opacity, transform: [{ translateY: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [-tokens17.motionDistance.toast, 0] }) }] },
3183
3301
  children: /* @__PURE__ */ jsx19(ToastView, { toast: item.toast, controller })
3184
3302
  }
3185
3303
  )
@@ -3189,16 +3307,16 @@ function ToastSlot({ item, controller, boxes }) {
3189
3307
  function ToastStack({ items: items2, controller }) {
3190
3308
  var _a;
3191
3309
  const layers = useLayerState();
3192
- const root = useRef11(null), reduced = useReducedMotion();
3310
+ const root = useRef13(null), reduced = useReducedMotion();
3193
3311
  useToastReflow(root, reduced);
3194
- const boxes = useRef11(/* @__PURE__ */ new Map()).current;
3312
+ const boxes = useRef13(/* @__PURE__ */ new Map()).current;
3195
3313
  for (const id of boxes.keys()) if (!items2.some((item) => item.toast.id === id)) boxes.delete(id);
3196
3314
  return /* @__PURE__ */ jsx19(View13, { ref: root, pointerEvents: "box-none", style: {
3197
3315
  position: "absolute",
3198
- top: tokens16.extensions.toast.inset,
3199
- right: tokens16.extensions.toast.inset,
3200
- left: tokens16.extensions.toast.inset,
3201
- gap: tokens16.extensions.toast.stackGap,
3316
+ top: tokens17.extensions.toast.inset,
3317
+ right: tokens17.extensions.toast.inset,
3318
+ left: tokens17.extensions.toast.inset,
3319
+ gap: tokens17.extensions.toast.stackGap,
3202
3320
  minHeight: items2.some((item) => item.exiting) ? Math.max(0, ...[...boxes.values()].map((box) => box.y + box.height)) : void 0,
3203
3321
  zIndex: layers.zIndex((_a = layers.topWindow()) == null ? void 0 : _a.id, "toast")
3204
3322
  }, children: items2.map((item) => /* @__PURE__ */ jsx19(ToastSlot, { item, controller, boxes }, item.toast.id)) });
@@ -3206,17 +3324,19 @@ function ToastStack({ items: items2, controller }) {
3206
3324
 
3207
3325
  // packages/native/src/feedback.tsx
3208
3326
  import {
3209
- tokens as tokens17,
3210
- createFeedbackController
3327
+ tokens as tokens18,
3328
+ createFeedbackController,
3329
+ feedbackControllerOf
3211
3330
  } from "@kjun-ui/tokens";
3212
3331
  import {
3213
- useCallback as useCallback3,
3214
- useEffect as useEffect8,
3215
- useRef as useRef12,
3332
+ useCallback as useCallback4,
3333
+ useEffect as useEffect9,
3334
+ useRef as useRef14,
3216
3335
  useState as useState12,
3217
3336
  useSyncExternalStore as useSyncExternalStore2
3218
3337
  } from "react";
3219
3338
  import { View as View14 } from "react-native";
3339
+ import { createKjunFeedback } from "@kjun-ui/tokens";
3220
3340
  import { jsx as jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
3221
3341
  function useKjunFeedback() {
3222
3342
  const value = useOptionalKjunFeedback();
@@ -3248,7 +3368,7 @@ function FeedbackDialog({
3248
3368
  onConfirm: submit,
3249
3369
  confirmVariant: options.type === "danger" ? "danger" : "primary",
3250
3370
  children: [
3251
- !!options.message && /* @__PURE__ */ jsx20(KText, { style: { marginBottom: tokens17.dimension.value16 }, children: options.message }),
3371
+ !!options.message && /* @__PURE__ */ jsx20(KText, { style: { marginBottom: tokens18.dimension.value16 }, children: options.message }),
3252
3372
  request.kind === "prompt" && /* @__PURE__ */ jsx20(
3253
3373
  KjunInput,
3254
3374
  {
@@ -3265,9 +3385,11 @@ function FeedbackDialog({
3265
3385
  }
3266
3386
  );
3267
3387
  }
3268
- function KjunFeedbackProvider({ children, style }) {
3269
- const [controller] = useState12(createFeedbackController);
3270
- const life = useRef12(0);
3388
+ function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3389
+ const [owned] = useState12(() => controllerProp ? void 0 : createFeedbackController());
3390
+ const controller = controllerProp ? feedbackControllerOf(controllerProp) : owned;
3391
+ useEffect9(() => controller.attach(), [controller]);
3392
+ const life = useRef14(0);
3271
3393
  const snapshot = useSyncExternalStore2(
3272
3394
  controller.subscribe,
3273
3395
  controller.getSnapshot,
@@ -3276,16 +3398,16 @@ function KjunFeedbackProvider({ children, style }) {
3276
3398
  const reduced = useReducedMotion();
3277
3399
  const toasts = usePresentedToasts(snapshot.toasts, reduced);
3278
3400
  const dialog = usePresentedRequest(snapshot.current, reduced);
3279
- useEffect8(() => {
3401
+ useEffect9(() => {
3280
3402
  const version = ++life.current;
3281
3403
  return () => {
3282
3404
  queueMicrotask(() => {
3283
- if (life.current === version) controller.dispose();
3405
+ if (life.current === version && !controllerProp) controller.dispose();
3284
3406
  });
3285
3407
  };
3286
3408
  }, [controller]);
3287
3409
  const [layers, setLayers] = useState12([]);
3288
- const register = useCallback3((id) => {
3410
+ const register = useCallback4((id) => {
3289
3411
  setLayers((previous) => [...previous, id]);
3290
3412
  return () => setLayers((previous) => previous.filter((item) => item !== id));
3291
3413
  }, []);
@@ -3315,13 +3437,13 @@ function KjunFeedbackProvider({ children, style }) {
3315
3437
 
3316
3438
  // packages/native/src/choice-controls.tsx
3317
3439
  import { Animated as Animated9 } from "react-native";
3318
- import { tokens as tokens18 } from "@kjun-ui/tokens";
3440
+ import { tokens as tokens19 } from "@kjun-ui/tokens";
3319
3441
  import {
3320
3442
  createContext as createContext16,
3321
3443
  useContext as useContext12,
3322
3444
  useState as useState13,
3323
- useEffect as useEffect9,
3324
- useRef as useRef13
3445
+ useEffect as useEffect10,
3446
+ useRef as useRef15
3325
3447
  } from "react";
3326
3448
  import {
3327
3449
  View as View15
@@ -3338,7 +3460,7 @@ function KjunCheckbox({
3338
3460
  onValueChange,
3339
3461
  onChange
3340
3462
  }) {
3341
- const { colors } = useKjunStyles(), checked = Array.isArray(value) ? value.includes(val) : value, dimension = tokens18.extensions.checkbox.sizes[size];
3463
+ const { colors } = useKjunStyles(), checked = Array.isArray(value) ? value.includes(val) : value, dimension = tokens19.extensions.checkbox.sizes[size];
3342
3464
  return /* @__PURE__ */ jsxs10(
3343
3465
  AccessiblePressable,
3344
3466
  {
@@ -3357,8 +3479,8 @@ function KjunCheckbox({
3357
3479
  flexDirection: "row",
3358
3480
  alignItems: "center",
3359
3481
  // Like Web's choice row on a mouse-like pointer; touch layouts keep the 44px target.
3360
- minHeight: finePointer() ? tokens18.extensions.choice.minimumHeight : tokens18.native.minimumTouchTarget,
3361
- opacity: disabled ? tokens18.states.opacity.disabled : pressed ? tokens18.states.opacity.pressed : 1
3482
+ minHeight: finePointer() ? tokens19.extensions.choice.minimumHeight : tokens19.native.minimumTouchTarget,
3483
+ opacity: disabled ? tokens19.states.opacity.disabled : pressed ? tokens19.states.opacity.pressed : 1
3362
3484
  }),
3363
3485
  children: [
3364
3486
  /* @__PURE__ */ jsx21(
@@ -3369,8 +3491,8 @@ function KjunCheckbox({
3369
3491
  justifyContent: "center",
3370
3492
  width: dimension,
3371
3493
  height: dimension,
3372
- borderRadius: tokens18.extensions.checkbox.radii[size],
3373
- borderWidth: tokens18.border.controlWidth,
3494
+ borderRadius: tokens19.extensions.checkbox.radii[size],
3495
+ borderWidth: tokens19.border.controlWidth,
3374
3496
  // Same boundary roles as Radio: strong while enabled, secondary once disabled.
3375
3497
  borderColor: checked ? colors.brand : disabled ? colors.borderSecondary : colors.borderStrong,
3376
3498
  backgroundColor: checked ? colors.brand : colors.surface
@@ -3379,14 +3501,14 @@ function KjunCheckbox({
3379
3501
  KjunIcon,
3380
3502
  {
3381
3503
  name: "check",
3382
- size: tokens18.extensions.checkbox.iconSizes[size],
3504
+ size: tokens19.extensions.checkbox.iconSizes[size],
3383
3505
  color: colors.onBrand
3384
3506
  }
3385
3507
  )
3386
3508
  }
3387
3509
  ),
3388
3510
  !!(children || label) && content(children || label, {
3389
- marginLeft: tokens18.extensions.checkbox.labelGap,
3511
+ marginLeft: tokens19.extensions.checkbox.labelGap,
3390
3512
  ...typeStyle("label")
3391
3513
  })
3392
3514
  ]
@@ -3402,7 +3524,7 @@ function useControlFocus(disabled) {
3402
3524
  onFocus: (event) => setFocused(focusVisible(event.currentTarget)),
3403
3525
  onBlur: () => setFocused(false)
3404
3526
  },
3405
- ring: focused && !disabled ? { outlineStyle: "solid", outlineWidth: tokens18.states.focus.width, outlineOffset: tokens18.states.focus.choiceOffset, outlineColor: colors.focusRing } : {}
3527
+ ring: focused && !disabled ? { outlineStyle: "solid", outlineWidth: tokens19.states.focus.width, outlineOffset: tokens19.states.focus.choiceOffset, outlineColor: colors.focusRing } : {}
3406
3528
  };
3407
3529
  }
3408
3530
  function KjunSwitch({
@@ -3417,10 +3539,10 @@ function KjunSwitch({
3417
3539
  onChange
3418
3540
  }) {
3419
3541
  const { colors } = useKjunStyles();
3420
- const width = tokens18.extensions.switch.widths[size];
3421
- const height = tokens18.extensions.switch.heights[size];
3422
- const thumb = height - 2 * tokens18.extensions.switch.padding;
3423
- const offScale = (thumb - 2 * tokens18.border.controlWidth) / thumb;
3542
+ const width = tokens19.extensions.switch.widths[size];
3543
+ const height = tokens19.extensions.switch.heights[size];
3544
+ const thumb = height - 2 * tokens19.extensions.switch.padding;
3545
+ const offScale = (thumb - 2 * tokens19.border.controlWidth) / thumb;
3424
3546
  const offset = width - height;
3425
3547
  const motion = useMotionValue(value ? 1 : 0);
3426
3548
  const focus = useControlFocus(disabled);
@@ -3449,8 +3571,8 @@ function KjunSwitch({
3449
3571
  flexDirection: "row",
3450
3572
  alignItems: "center",
3451
3573
  // Like Web's choice row on a mouse-like pointer; touch layouts keep the 44px target.
3452
- minHeight: finePointer() ? tokens18.extensions.choice.minimumHeight : tokens18.native.minimumTouchTarget,
3453
- opacity: disabled ? tokens18.states.opacity.disabled : 1
3574
+ minHeight: finePointer() ? tokens19.extensions.choice.minimumHeight : tokens19.native.minimumTouchTarget,
3575
+ opacity: disabled ? tokens19.states.opacity.disabled : 1
3454
3576
  },
3455
3577
  children: [
3456
3578
  /* @__PURE__ */ jsxs10(
@@ -3459,8 +3581,8 @@ function KjunSwitch({
3459
3581
  style: {
3460
3582
  width,
3461
3583
  height,
3462
- padding: tokens18.extensions.switch.padding,
3463
- borderRadius: tokens18.extensions.switch.radius,
3584
+ padding: tokens19.extensions.switch.padding,
3585
+ borderRadius: tokens19.extensions.switch.radius,
3464
3586
  backgroundColor: trackColor,
3465
3587
  ...focus.ring
3466
3588
  },
@@ -3472,8 +3594,8 @@ function KjunSwitch({
3472
3594
  style: {
3473
3595
  position: "absolute",
3474
3596
  inset: 0,
3475
- borderRadius: tokens18.extensions.switch.radius,
3476
- borderWidth: tokens18.border.controlWidth,
3597
+ borderRadius: tokens19.extensions.switch.radius,
3598
+ borderWidth: tokens19.border.controlWidth,
3477
3599
  // Hover turns the boundary to brand, like Checkbox on Web.
3478
3600
  borderColor: hovered && !disabled ? colors.brand : offRole,
3479
3601
  opacity: motion.interpolate({ inputRange: [0, 1], outputRange: [1, 0] })
@@ -3486,7 +3608,7 @@ function KjunSwitch({
3486
3608
  style: {
3487
3609
  width: thumb,
3488
3610
  height: thumb,
3489
- borderRadius: tokens18.extensions.switch.radius,
3611
+ borderRadius: tokens19.extensions.switch.radius,
3490
3612
  backgroundColor: thumbColor,
3491
3613
  transform: [
3492
3614
  { translateX: motion.interpolate({ inputRange: [0, 1], outputRange: [0, offset] }) },
@@ -3498,11 +3620,11 @@ function KjunSwitch({
3498
3620
  ]
3499
3621
  }
3500
3622
  ),
3501
- description ? /* @__PURE__ */ jsxs10(View15, { style: { marginLeft: tokens18.extensions.switch.labelGap, flexShrink: 1, minWidth: 0 }, children: [
3623
+ description ? /* @__PURE__ */ jsxs10(View15, { style: { marginLeft: tokens19.extensions.switch.labelGap, flexShrink: 1, minWidth: 0 }, children: [
3502
3624
  !!(children || label) && content(children || label, typeStyle("label")),
3503
- /* @__PURE__ */ jsx21(KText, { style: { ...typeStyle("caption"), marginTop: tokens18.dimension.value4, color: colors.textSecondary }, children: description })
3625
+ /* @__PURE__ */ jsx21(KText, { style: { ...typeStyle("caption"), marginTop: tokens19.dimension.value4, color: colors.textSecondary }, children: description })
3504
3626
  ] }) : !!(children || label) && content(children || label, {
3505
- marginLeft: tokens18.extensions.switch.labelGap,
3627
+ marginLeft: tokens19.extensions.switch.labelGap,
3506
3628
  ...typeStyle("label")
3507
3629
  })
3508
3630
  ]
@@ -3521,9 +3643,9 @@ function KjunRadio({
3521
3643
  onChange
3522
3644
  }) {
3523
3645
  const group = useContext12(RadioContext), { colors } = useKjunStyles(), selected = (group ? group.value : value) === val;
3524
- const geometry2 = tokens18.extensions.radio;
3646
+ const geometry2 = tokens19.extensions.radio;
3525
3647
  const [hovered, setHovered] = useState13(false);
3526
- useEffect9(() => {
3648
+ useEffect10(() => {
3527
3649
  if (disabled) setHovered(false);
3528
3650
  }, [disabled]);
3529
3651
  return /* @__PURE__ */ jsx21(
@@ -3548,8 +3670,8 @@ function KjunRadio({
3548
3670
  flexDirection: "row",
3549
3671
  alignItems: "center",
3550
3672
  // Like Web's choice row on a mouse-like pointer; touch layouts keep the 44px target.
3551
- minHeight: finePointer() ? tokens18.extensions.choice.minimumHeight : tokens18.native.minimumTouchTarget,
3552
- opacity: disabled ? tokens18.states.opacity.disabled : 1
3673
+ minHeight: finePointer() ? tokens19.extensions.choice.minimumHeight : tokens19.native.minimumTouchTarget,
3674
+ opacity: disabled ? tokens19.states.opacity.disabled : 1
3553
3675
  },
3554
3676
  children: ({ pressed }) => /* @__PURE__ */ jsxs10(Fragment5, { children: [
3555
3677
  /* @__PURE__ */ jsx21(
@@ -3559,7 +3681,7 @@ function KjunRadio({
3559
3681
  width: geometry2.size,
3560
3682
  height: geometry2.size,
3561
3683
  borderWidth: geometry2.borderWidth,
3562
- borderRadius: tokens18.radius.radius9999,
3684
+ borderRadius: tokens19.radius.radius9999,
3563
3685
  alignItems: "center",
3564
3686
  justifyContent: "center",
3565
3687
  borderColor: disabled ? selected ? colors.brand : colors.borderSecondary : pressed ? colors.brandActive : hovered ? colors.brandHover : selected ? colors.brand : colors.borderStrong,
@@ -3571,7 +3693,7 @@ function KjunRadio({
3571
3693
  style: {
3572
3694
  width: geometry2.dot,
3573
3695
  height: geometry2.dot,
3574
- borderRadius: tokens18.radius.radius9999,
3696
+ borderRadius: tokens19.radius.radius9999,
3575
3697
  backgroundColor: colors.brand
3576
3698
  }
3577
3699
  }
@@ -3595,7 +3717,7 @@ function KjunRadioGroup({
3595
3717
  onValueChange,
3596
3718
  onChange
3597
3719
  }) {
3598
- const root = useRef13(null);
3720
+ const root = useRef15(null);
3599
3721
  useRadioKeyboard(root);
3600
3722
  return /* @__PURE__ */ jsx21(
3601
3723
  RadioContext.Provider,
@@ -3616,7 +3738,7 @@ function KjunRadioGroup({
3616
3738
  style: {
3617
3739
  flexDirection: direction === "vertical" ? "column" : "row",
3618
3740
  flexWrap: direction === "vertical" ? "nowrap" : "wrap",
3619
- gap: direction === "vertical" ? tokens18.dimension.value8 : tokens18.dimension.value16
3741
+ gap: direction === "vertical" ? tokens19.dimension.value8 : tokens19.dimension.value16
3620
3742
  },
3621
3743
  children: children || options.map((option) => /* @__PURE__ */ jsx21(
3622
3744
  KjunRadio,
@@ -3634,8 +3756,8 @@ function KjunRadioGroup({
3634
3756
  }
3635
3757
 
3636
3758
  // packages/native/src/selection-groups.tsx
3637
- import { tokens as tokens20 } from "@kjun-ui/tokens";
3638
- import { useLayoutEffect as useLayoutEffect7, useRef as useRef15 } from "react";
3759
+ import { tokens as tokens21 } from "@kjun-ui/tokens";
3760
+ import { useLayoutEffect as useLayoutEffect7, useRef as useRef17 } from "react";
3639
3761
  import {
3640
3762
  Animated as Animated11,
3641
3763
  ScrollView as ScrollView2,
@@ -3644,24 +3766,24 @@ import {
3644
3766
  } from "react-native";
3645
3767
 
3646
3768
  // packages/native/src/button-group-motion.tsx
3647
- import { useCallback as useCallback4, useEffect as useEffect10, useLayoutEffect as useLayoutEffect6, useRef as useRef14, useState as useState14 } from "react";
3769
+ import { useCallback as useCallback5, useEffect as useEffect11, useLayoutEffect as useLayoutEffect6, useRef as useRef16, useState as useState14 } from "react";
3648
3770
  import { Animated as Animated10, Easing as Easing4, StyleSheet as StyleSheet5, View as View16 } from "react-native";
3649
- import { tokens as tokens19 } from "@kjun-ui/tokens";
3771
+ import { tokens as tokens20 } from "@kjun-ui/tokens";
3650
3772
  import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
3651
- var curve = tokens19.motion.easeOut.match(/-?\d*\.?\d+/g).map(Number);
3773
+ var curve = tokens20.motion.easeOut.match(/-?\d*\.?\d+/g).map(Number);
3652
3774
  var easing = Easing4.bezier(...curve);
3653
3775
  var sameBox = (a, b) => a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
3654
3776
  function useButtonGroupMotion(selected) {
3655
3777
  const reduced = useReducedMotion();
3656
3778
  const [layouts, setLayouts] = useState14(/* @__PURE__ */ new Map());
3657
- const x = useRef14(new Animated10.Value(0)).current;
3658
- const width = useRef14(new Animated10.Value(0)).current;
3659
- const previous = useRef14(null);
3779
+ const x = useRef16(new Animated10.Value(0)).current;
3780
+ const width = useRef16(new Animated10.Value(0)).current;
3781
+ const previous = useRef16(null);
3660
3782
  const layout = selected && layouts.get(selected.value);
3661
- const updateLayout = useCallback4((value, box) => {
3783
+ const updateLayout = useCallback5((value, box) => {
3662
3784
  setLayouts((old) => old.has(value) && sameBox(old.get(value), box) ? old : new Map(old).set(value, box));
3663
3785
  }, []);
3664
- const measure = useCallback4((value, event) => updateLayout(value, event.nativeEvent.layout), [updateLayout]);
3786
+ const measure = useCallback5((value, event) => updateLayout(value, event.nativeEvent.layout), [updateLayout]);
3665
3787
  useLayoutEffect6(() => {
3666
3788
  const old = previous.current;
3667
3789
  if (!selected || !layout) {
@@ -3675,8 +3797,8 @@ function useButtonGroupMotion(selected) {
3675
3797
  width.stopAnimation();
3676
3798
  if (old && old.value !== selected.value && !reduced) {
3677
3799
  Animated10.parallel([
3678
- Animated10.timing(x, { toValue: layout.x, duration: tokens19.motion.indicator, easing, useNativeDriver: false }),
3679
- Animated10.timing(width, { toValue: layout.width, duration: tokens19.motion.indicator, easing, useNativeDriver: false })
3800
+ Animated10.timing(x, { toValue: layout.x, duration: tokens20.motion.indicator, easing, useNativeDriver: false }),
3801
+ Animated10.timing(width, { toValue: layout.width, duration: tokens20.motion.indicator, easing, useNativeDriver: false })
3680
3802
  ]).start();
3681
3803
  } else {
3682
3804
  x.setValue(layout.x);
@@ -3684,7 +3806,7 @@ function useButtonGroupMotion(selected) {
3684
3806
  }
3685
3807
  previous.current = { value: selected.value, box: layout, reduced };
3686
3808
  }, [selected == null ? void 0 : selected.value, layout, reduced, x, width]);
3687
- useEffect10(() => () => {
3809
+ useEffect11(() => () => {
3688
3810
  x.stopAnimation();
3689
3811
  width.stopAnimation();
3690
3812
  }, [x, width]);
@@ -3692,12 +3814,12 @@ function useButtonGroupMotion(selected) {
3692
3814
  }
3693
3815
  function ButtonGroupLabel({ label, active, size, reduced }) {
3694
3816
  const { colors, fontFamily } = useKjunStyles();
3695
- const progress = useRef14(new Animated10.Value(active ? 1 : 0)).current;
3817
+ const progress = useRef16(new Animated10.Value(active ? 1 : 0)).current;
3696
3818
  const interpolate = typeof colors.textSecondary === "string" && typeof colors.text === "string";
3697
- useEffect10(() => {
3819
+ useEffect11(() => {
3698
3820
  progress.stopAnimation();
3699
3821
  if (reduced || !interpolate) progress.setValue(active ? 1 : 0);
3700
- else Animated10.timing(progress, { toValue: active ? 1 : 0, duration: tokens19.motion.indicator, easing, useNativeDriver: false }).start();
3822
+ else Animated10.timing(progress, { toValue: active ? 1 : 0, duration: tokens20.motion.indicator, easing, useNativeDriver: false }).start();
3701
3823
  return () => progress.stopAnimation();
3702
3824
  }, [active, reduced, interpolate, progress]);
3703
3825
  const resolveFont = useResolveFont();
@@ -3739,9 +3861,9 @@ function KjunButtonGroup({
3739
3861
  const { colors } = useKjunStyles();
3740
3862
  const selected = options.find((option) => option.value === value);
3741
3863
  const motion = useButtonGroupMotion(selected);
3742
- const padding = tokens20.buttonGroup.padding[size];
3743
- const itemRadius = tokens20.buttonGroup.itemRadii[size];
3744
- const itemRefs = useRef15(/* @__PURE__ */ new Map());
3864
+ const padding = tokens21.buttonGroup.padding[size];
3865
+ const itemRadius = tokens21.buttonGroup.itemRadii[size];
3866
+ const itemRefs = useRef17(/* @__PURE__ */ new Map());
3745
3867
  const { updateLayout } = motion;
3746
3868
  useLayoutEffect7(() => {
3747
3869
  for (const [value2, node] of itemRefs.current) {
@@ -3766,7 +3888,7 @@ function KjunButtonGroup({
3766
3888
  style: {
3767
3889
  flexDirection: "row",
3768
3890
  padding,
3769
- borderRadius: tokens20.buttonGroup.radii[size],
3891
+ borderRadius: tokens21.buttonGroup.radii[size],
3770
3892
  backgroundColor: colors.secondary,
3771
3893
  flexGrow: fullWidth ? 1 : 0
3772
3894
  },
@@ -3790,7 +3912,7 @@ function KjunButtonGroup({
3790
3912
  // Disabled options dim their own labels; the selected value stays readable. The edge keeps it
3791
3913
  // apart from the track when surface and secondary are close.
3792
3914
  backgroundColor: colors.surface,
3793
- borderWidth: tokens20.border.defaultWidth,
3915
+ borderWidth: tokens21.border.defaultWidth,
3794
3916
  borderColor: colors.border
3795
3917
  }
3796
3918
  }
@@ -3818,22 +3940,22 @@ function KjunButtonGroup({
3818
3940
  flexDirection: "row",
3819
3941
  alignItems: "center",
3820
3942
  justifyContent: "center",
3821
- gap: tokens20.dimension.value6,
3943
+ gap: tokens21.dimension.value6,
3822
3944
  flex: fullWidth ? 1 : void 0,
3823
- minWidth: tokens20.native.minimumTouchTarget,
3824
- minHeight: tokens20.native.minimumTouchTarget,
3825
- height: Math.max(tokens20.native.minimumTouchTarget, tokens20.buttonGroup.heights[size] - 2 * padding),
3826
- paddingHorizontal: tokens20.buttonGroup.itemPaddingX[size],
3945
+ minWidth: tokens21.native.minimumTouchTarget,
3946
+ minHeight: tokens21.native.minimumTouchTarget,
3947
+ height: Math.max(tokens21.native.minimumTouchTarget, tokens21.buttonGroup.heights[size] - 2 * padding),
3948
+ paddingHorizontal: tokens21.buttonGroup.itemPaddingX[size],
3827
3949
  borderRadius: itemRadius,
3828
3950
  backgroundColor: active && !motion.layout ? colors.surface : pressed && !active ? colors.hover : "transparent",
3829
- opacity: blocked ? tokens20.states.opacity.disabled : 1
3951
+ opacity: blocked ? tokens21.states.opacity.disabled : 1
3830
3952
  }),
3831
3953
  children: [
3832
3954
  !!option.icon && /* @__PURE__ */ jsx23(
3833
3955
  KjunIcon,
3834
3956
  {
3835
3957
  name: option.icon,
3836
- size: tokens20.extensions.selection.iconSize,
3958
+ size: tokens21.extensions.selection.iconSize,
3837
3959
  color: active ? colors.text : colors.textSecondary
3838
3960
  }
3839
3961
  ),
@@ -3869,7 +3991,7 @@ function KjunFilterGroup({
3869
3991
  onChange
3870
3992
  }) {
3871
3993
  const { colors } = useKjunStyles();
3872
- const wide = useWindowDimensions2().width >= tokens20.responsive.selection, roomy = wide && finePointer();
3994
+ const wide = useWindowDimensions2().width >= tokens21.responsive.selection, roomy = wide && finePointer();
3873
3995
  const selected = (v) => multiple ? Array.isArray(value) && (v === null ? value.length === 0 : value.includes(v)) : value === v;
3874
3996
  const children = /* @__PURE__ */ jsx23(
3875
3997
  View17,
@@ -3878,7 +4000,7 @@ function KjunFilterGroup({
3878
4000
  style: {
3879
4001
  flexDirection: "row",
3880
4002
  flexWrap: scroll ? "nowrap" : "wrap",
3881
- gap: tokens20.dimension.value8
4003
+ gap: tokens21.dimension.value8
3882
4004
  },
3883
4005
  children: options.map((option) => {
3884
4006
  const active = selected(option.value), blocked = disabled || option.disabled;
@@ -3895,9 +4017,9 @@ function KjunFilterGroup({
3895
4017
  onChange == null ? void 0 : onChange(next);
3896
4018
  },
3897
4019
  style: {
3898
- minHeight: roomy ? void 0 : tokens20.native.minimumTouchTarget,
4020
+ minHeight: roomy ? void 0 : tokens21.native.minimumTouchTarget,
3899
4021
  justifyContent: "center",
3900
- opacity: blocked ? tokens20.states.opacity.disabledStrong : 1
4022
+ opacity: blocked ? tokens21.states.opacity.disabledStrong : 1
3901
4023
  },
3902
4024
  children: /* @__PURE__ */ jsxs12(
3903
4025
  View17,
@@ -3906,12 +4028,12 @@ function KjunFilterGroup({
3906
4028
  flexDirection: "row",
3907
4029
  alignItems: "center",
3908
4030
  justifyContent: "center",
3909
- gap: tokens20.dimension.value4,
3910
- minHeight: roomy ? void 0 : tokens20.extensions.selection.minimumHeight,
3911
- height: roomy ? tokens20.button.heights[size] : Math.max(tokens20.extensions.selection.minimumHeight, tokens20.button.heights[size]),
3912
- paddingHorizontal: { xs: tokens20.dimension.value8, sm: tokens20.dimension.value12, md: tokens20.dimension.value12, lg: tokens20.dimension.value14, xl: tokens20.dimension.value16 }[size],
4031
+ gap: tokens21.dimension.value4,
4032
+ minHeight: roomy ? void 0 : tokens21.extensions.selection.minimumHeight,
4033
+ height: roomy ? tokens21.button.heights[size] : Math.max(tokens21.extensions.selection.minimumHeight, tokens21.button.heights[size]),
4034
+ paddingHorizontal: { xs: tokens21.dimension.value8, sm: tokens21.dimension.value12, md: tokens21.dimension.value12, lg: tokens21.dimension.value14, xl: tokens21.dimension.value16 }[size],
3913
4035
  // Corners follow the button scale with the height, so every size keeps the same shape.
3914
- borderRadius: tokens20.button.radii[size],
4036
+ borderRadius: tokens21.button.radii[size],
3915
4037
  backgroundColor: active ? colors.text : colors.secondary
3916
4038
  },
3917
4039
  children: [
@@ -3919,9 +4041,9 @@ function KjunFilterGroup({
3919
4041
  View17,
3920
4042
  {
3921
4043
  style: {
3922
- width: tokens20.extensions.selection.dotSize,
3923
- height: tokens20.extensions.selection.dotSize,
3924
- borderRadius: tokens20.radius.radius4,
4044
+ width: tokens21.extensions.selection.dotSize,
4045
+ height: tokens21.extensions.selection.dotSize,
4046
+ borderRadius: tokens21.radius.radius4,
3925
4047
  backgroundColor: option.dot
3926
4048
  }
3927
4049
  }
@@ -3930,7 +4052,7 @@ function KjunFilterGroup({
3930
4052
  KjunIcon,
3931
4053
  {
3932
4054
  name: option.icon,
3933
- size: tokens20.extensions.selection.iconSize,
4055
+ size: tokens21.extensions.selection.iconSize,
3934
4056
  color: active ? colors.inverse : colors.textSecondary
3935
4057
  }
3936
4058
  ),
@@ -3981,7 +4103,7 @@ function KjunFilterGroup({
3981
4103
  }
3982
4104
 
3983
4105
  // packages/native/src/textarea.tsx
3984
- import { tokens as tokens21 } from "@kjun-ui/tokens";
4106
+ import { tokens as tokens22 } from "@kjun-ui/tokens";
3985
4107
  import {
3986
4108
  forwardRef as forwardRef4
3987
4109
  } from "react";
@@ -4003,7 +4125,7 @@ var KjunTextarea = forwardRef4(
4003
4125
  onBlur,
4004
4126
  ...props
4005
4127
  }, ref) {
4006
- const field = useKjunField(), { colors, fontFamily } = useKjunStyles(), spec = tokens21.input[size];
4128
+ const field = useKjunField(), { colors, fontFamily } = useKjunStyles(), spec = tokens22.input[size];
4007
4129
  const invalid = error || !!(field == null ? void 0 : field.error);
4008
4130
  const surface = useFieldSurface(size, { disabled, readOnly: readonly || props.readOnly || props.editable === false, invalid });
4009
4131
  return /* @__PURE__ */ jsx24(
@@ -4044,8 +4166,8 @@ var KjunTextarea = forwardRef4(
4044
4166
  ...inputTypeStyle(size),
4045
4167
  ...surface.style,
4046
4168
  height: void 0,
4047
- minHeight: Math.max(spec.height, rows * spec.lineHeight + spec.textareaPaddingY * 2 + 2 * tokens21.border.controlWidth),
4048
- paddingHorizontal: spec.padding - tokens21.border.controlWidth,
4169
+ minHeight: Math.max(spec.height, rows * spec.lineHeight + spec.textareaPaddingY * 2 + 2 * tokens22.border.controlWidth),
4170
+ paddingHorizontal: spec.padding - tokens22.border.controlWidth,
4049
4171
  paddingVertical: spec.textareaPaddingY,
4050
4172
  textAlignVertical: "top",
4051
4173
  color: surface.ink
@@ -4058,8 +4180,8 @@ var KjunTextarea = forwardRef4(
4058
4180
  );
4059
4181
 
4060
4182
  // packages/native/src/drawer.tsx
4061
- import { tokens as tokens22 } from "@kjun-ui/tokens";
4062
- import { useEffect as useEffect11, useState as useState15 } from "react";
4183
+ import { tokens as tokens23 } from "@kjun-ui/tokens";
4184
+ import { useEffect as useEffect12, useState as useState15 } from "react";
4063
4185
  import { Animated as Animated12, Keyboard } from "react-native";
4064
4186
 
4065
4187
  // shared/package-runtime/drawer-geometry.ts
@@ -4094,7 +4216,7 @@ import {
4094
4216
  import { jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
4095
4217
  function useKeyboardOverlap(enabled, windowHeight) {
4096
4218
  const [overlap, setOverlap] = useState15(0);
4097
- useEffect11(() => {
4219
+ useEffect12(() => {
4098
4220
  var _a, _b;
4099
4221
  setOverlap(0);
4100
4222
  const events = keyboardEvents(Platform15.OS);
@@ -4115,7 +4237,7 @@ function KjunDrawer({
4115
4237
  onOpenChange,
4116
4238
  title,
4117
4239
  position = "right",
4118
- width = tokens22.extensions.drawer.width,
4240
+ width = tokens23.extensions.drawer.width,
4119
4241
  closable = true,
4120
4242
  closeOnOverlay = true,
4121
4243
  closeOnEsc = true,
@@ -4124,6 +4246,7 @@ function KjunDrawer({
4124
4246
  footer,
4125
4247
  children,
4126
4248
  onClose,
4249
+ onAfterClose,
4127
4250
  ariaLabel,
4128
4251
  safeAreaTop = 0,
4129
4252
  safeAreaBottom = 0,
@@ -4139,13 +4262,13 @@ function KjunDrawer({
4139
4262
  windowHeight: rootHeight || window2.height,
4140
4263
  safeAreaTop: Math.max(0, safeAreaTop),
4141
4264
  safeAreaBottom: Math.max(0, safeAreaBottom),
4142
- gap: tokens22.extensions.drawer.sheetGap,
4265
+ gap: tokens23.extensions.drawer.sheetGap,
4143
4266
  keyboard,
4144
4267
  maxHeight
4145
4268
  });
4146
4269
  const [panelHeight, setPanelHeight] = useState15(0);
4147
- const motion = useNativePresence(open, tokens22.motion.layerEnter, tokens22.motion.layerExit, vertical || panelHeight > 0, 0, { enterEasing: motionEmphasized });
4148
- const backdrop = useNativePresence(open, tokens22.motion.backdrop, tokens22.motion.backdropExit, true, 0, { fade: tokens22.motion.backdropExit });
4270
+ const motion = useNativePresence(open, tokens23.motion.layerEnter, tokens23.motion.layerExit, vertical || panelHeight > 0, 0, { enterEasing: motionEmphasized });
4271
+ const backdrop = useNativePresence(open, tokens23.motion.backdrop, tokens23.motion.backdropExit, true, 0, { fade: tokens23.motion.backdropExit });
4149
4272
  const close = () => {
4150
4273
  if (!open) return;
4151
4274
  onOpenChange(false);
@@ -4154,10 +4277,15 @@ function KjunDrawer({
4154
4277
  const layer = useLayer(open, motion.present, "window", () => {
4155
4278
  if (closeOnEsc) close();
4156
4279
  });
4280
+ const iosDismiss = Platform15.OS === "ios";
4281
+ useAfterClose(motion.present, onAfterClose, !iosDismiss);
4157
4282
  return /* @__PURE__ */ jsx25(LayerScope.Provider, { value: layer.id, children: /* @__PURE__ */ jsx25(
4158
4283
  ScopedNativeModal,
4159
4284
  {
4160
4285
  visible: motion.present,
4286
+ onDismiss: iosDismiss ? () => {
4287
+ if (!open) onAfterClose == null ? void 0 : onAfterClose();
4288
+ } : void 0,
4161
4289
  transparent: true,
4162
4290
  onRequestClose: () => {
4163
4291
  if (closeOnEsc) close();
@@ -4210,10 +4338,10 @@ function KjunDrawer({
4210
4338
  paddingTop: frame.paddingTop,
4211
4339
  paddingBottom: frame.paddingBottom,
4212
4340
  marginBottom: frame.lift,
4213
- borderRadius: tokens22.extensions.drawer.radius,
4214
- borderTopLeftRadius: position === "bottom" ? tokens22.extensions.drawer.bottomRadius : tokens22.extensions.drawer.radius,
4215
- borderTopRightRadius: position === "bottom" ? tokens22.extensions.drawer.bottomRadius : tokens22.extensions.drawer.radius,
4216
- boxShadow: directionalShadow(tokens22.extensions.drawer.elevation, position).map(({ colorRole, ...layer2 }) => ({ ...layer2, color: colors[colorRole] })),
4341
+ borderRadius: tokens23.extensions.drawer.radius,
4342
+ borderTopLeftRadius: position === "bottom" ? tokens23.extensions.drawer.bottomRadius : tokens23.extensions.drawer.radius,
4343
+ borderTopRightRadius: position === "bottom" ? tokens23.extensions.drawer.bottomRadius : tokens23.extensions.drawer.radius,
4344
+ boxShadow: directionalShadow(tokens23.extensions.drawer.elevation, position).map(({ colorRole, ...layer2 }) => ({ ...layer2, color: colors[colorRole] })),
4217
4345
  backgroundColor: colors.surface
4218
4346
  },
4219
4347
  children: [
@@ -4224,9 +4352,9 @@ function KjunDrawer({
4224
4352
  flexDirection: "row",
4225
4353
  alignItems: "center",
4226
4354
  justifyContent: "space-between",
4227
- paddingVertical: tokens22.extensions.drawer.paddingY,
4228
- paddingHorizontal: tokens22.extensions.drawer.paddingX,
4229
- borderBottomWidth: tokens22.border.defaultWidth,
4355
+ paddingVertical: tokens23.extensions.drawer.paddingY,
4356
+ paddingHorizontal: tokens23.extensions.drawer.paddingX,
4357
+ borderBottomWidth: tokens23.border.defaultWidth,
4230
4358
  borderBottomColor: colors.border
4231
4359
  },
4232
4360
  children: [
@@ -4244,8 +4372,8 @@ function KjunDrawer({
4244
4372
  variant: "ghost",
4245
4373
  ariaLabel: m.close,
4246
4374
  onPress: close,
4247
- style: { borderRadius: tokens22.extensions.drawer.closeRadius, width: tokens22.extensions.drawer.closeSize, height: tokens22.extensions.drawer.closeSize, paddingHorizontal: 0, paddingVertical: 0 },
4248
- children: /* @__PURE__ */ jsx25(KjunIcon, { name: "x", size: tokens22.extensions.drawer.closeIconSize })
4375
+ style: { borderRadius: tokens23.extensions.drawer.closeRadius, width: tokens23.extensions.drawer.closeSize, height: tokens23.extensions.drawer.closeSize, paddingHorizontal: 0, paddingVertical: 0 },
4376
+ children: /* @__PURE__ */ jsx25(KjunIcon, { name: "x", size: tokens23.extensions.drawer.closeIconSize })
4249
4377
  }
4250
4378
  )
4251
4379
  ]
@@ -4256,7 +4384,7 @@ function KjunDrawer({
4256
4384
  {
4257
4385
  keyboardShouldPersistTaps: "handled",
4258
4386
  style: vertical ? { flex: 1 } : { flexGrow: 0, flexShrink: 1 },
4259
- contentContainerStyle: { padding: noPadding ? 0 : tokens22.extensions.drawer.bodyPadding },
4387
+ contentContainerStyle: { padding: noPadding ? 0 : tokens23.extensions.drawer.bodyPadding },
4260
4388
  children: content(children)
4261
4389
  }
4262
4390
  ),
@@ -4264,9 +4392,9 @@ function KjunDrawer({
4264
4392
  View18,
4265
4393
  {
4266
4394
  style: {
4267
- paddingVertical: tokens22.extensions.drawer.paddingY,
4268
- paddingHorizontal: tokens22.extensions.drawer.paddingX,
4269
- borderTopWidth: tokens22.border.defaultWidth,
4395
+ paddingVertical: tokens23.extensions.drawer.paddingY,
4396
+ paddingHorizontal: tokens23.extensions.drawer.paddingX,
4397
+ borderTopWidth: tokens23.border.defaultWidth,
4270
4398
  borderTopColor: colors.border
4271
4399
  },
4272
4400
  children: content(footer)
@@ -4283,15 +4411,15 @@ function KjunDrawer({
4283
4411
  }
4284
4412
 
4285
4413
  // packages/native/src/dropdown.tsx
4286
- import { tokens as tokens25 } from "@kjun-ui/tokens";
4414
+ import { tokens as tokens26 } from "@kjun-ui/tokens";
4287
4415
  import {
4288
4416
  Children as Children3,
4289
4417
  Fragment as Fragment7,
4290
4418
  createContext as createContext17,
4291
4419
  isValidElement as isValidElement6,
4292
4420
  useContext as useContext13,
4293
- useEffect as useEffect14,
4294
- useRef as useRef18,
4421
+ useEffect as useEffect15,
4422
+ useRef as useRef20,
4295
4423
  useState as useState18
4296
4424
  } from "react";
4297
4425
  import {
@@ -4300,13 +4428,13 @@ import {
4300
4428
 
4301
4429
  // packages/native/src/floating-panel.tsx
4302
4430
  import { Animated as Animated13 } from "react-native";
4303
- import { tokens as tokens23 } from "@kjun-ui/tokens";
4431
+ import { tokens as tokens24 } from "@kjun-ui/tokens";
4304
4432
  import {
4305
4433
  cloneElement as cloneElement3,
4306
4434
  isValidElement as isValidElement4,
4307
- useEffect as useEffect12,
4435
+ useEffect as useEffect13,
4308
4436
  useLayoutEffect as useLayoutEffect8,
4309
- useRef as useRef16,
4437
+ useRef as useRef18,
4310
4438
  useState as useState16
4311
4439
  } from "react";
4312
4440
  import {
@@ -4363,11 +4491,11 @@ function FloatingPanel({
4363
4491
  const m = useKjunMessages();
4364
4492
  ariaLabel != null ? ariaLabel : ariaLabel = m.select;
4365
4493
  const [headerHeight, setHeaderHeight] = useState16(0);
4366
- const panelRef = useRef16(null);
4367
- const scroll = useRef16(null), viewport = useRef16(0);
4494
+ const panelRef = useRef18(null);
4495
+ const scroll = useRef18(null), viewport = useRef18(0);
4368
4496
  const { colors } = useKjunStyles(), window2 = useWindowDimensions4(), [anchored, setAnchored] = useState16(false), [sized, setSized] = useState16(false), [anchor, setAnchor] = useState16({ x: 0, y: 0, width: 0, height: 0 }), [panel, setPanel] = useState16({ width: 0, height: 0 });
4369
- const measurement = useRef16(0);
4370
- const motion = useNativePresence(open, tooltip ? tokens23.motion.tooltipEnter : tokens23.motion.popupEnter, tooltip ? tokens23.motion.tooltipExit : tokens23.motion.popupExit, anchored && sized);
4497
+ const measurement = useRef18(0);
4498
+ const motion = useNativePresence(open, tooltip ? tokens24.motion.tooltipEnter : tokens24.motion.popupEnter, tooltip ? tokens24.motion.tooltipExit : tokens24.motion.popupExit, anchored && sized);
4371
4499
  const layer = useLayer(open, motion.present, tooltip ? "tooltip" : "popup", () => onOpenChange(false), triggerRef);
4372
4500
  useLayoutEffect8(() => {
4373
4501
  var _a;
@@ -4388,14 +4516,14 @@ function FloatingPanel({
4388
4516
  setAnchored(false);
4389
4517
  }
4390
4518
  }, [motion.present]);
4391
- useEffect12(() => {
4519
+ useEffect13(() => {
4392
4520
  var _a;
4393
4521
  const row = reveal == null ? void 0 : reveal.current;
4394
4522
  if (!open || !anchored || !sized || !row || !viewport.current) return;
4395
- const offset = row.y + row.height + (menu || field ? tokens23.extensions.menu.padding : 0) - viewport.current;
4523
+ const offset = row.y + row.height + (menu || field ? tokens24.extensions.menu.padding : 0) - viewport.current;
4396
4524
  if (offset > 0) (_a = scroll.current) == null ? void 0 : _a.scrollTo({ y: offset, animated: false });
4397
4525
  }, [open, anchored, sized, reveal, menu, field]);
4398
- useEffect12(() => {
4526
+ useEffect13(() => {
4399
4527
  if (!open || !anchored || !sized || !focusOnOpen || !panelRef.current) return;
4400
4528
  if (Platform16.OS === "web") {
4401
4529
  const node = panelRef.current;
@@ -4405,30 +4533,30 @@ function FloatingPanel({
4405
4533
  if (tag) AccessibilityInfo3.setAccessibilityFocus(tag);
4406
4534
  }
4407
4535
  }, [open, anchored, sized, focusOnOpen]);
4408
- const gap = field ? tokens23.extensions.floating.fieldGap : tokens23.extensions.floating.anchorGap;
4536
+ const gap = field ? tokens24.extensions.floating.fieldGap : tokens24.extensions.floating.anchorGap;
4409
4537
  const contentSizedMenu = menu && !matchTriggerWidth;
4410
- const tooltipWidth = Math.min(Math.max(0, window2.width - 2 * tokens23.extensions.floating.viewportInset), tokens23.extensions.tooltip.maxWidth);
4411
- const maximumWidth = Math.max(0, window2.width - 2 * tokens23.extensions.floating.viewportInset);
4538
+ const tooltipWidth = Math.min(Math.max(0, window2.width - 2 * tokens24.extensions.floating.viewportInset), tokens24.extensions.tooltip.maxWidth);
4539
+ const maximumWidth = Math.max(0, window2.width - 2 * tokens24.extensions.floating.viewportInset);
4412
4540
  const minimumPanelWidth = Math.min(
4413
4541
  maximumWidth,
4414
- Math.max(minimumWidth, menu || field ? tokens23.extensions.menu.minimumWidth : 0)
4542
+ Math.max(minimumWidth, menu || field ? tokens24.extensions.menu.minimumWidth : 0)
4415
4543
  );
4416
4544
  const width = tooltip ? Math.min(tooltipWidth, panel.width || tooltipWidth) : Math.min(
4417
4545
  maximumWidth,
4418
- Math.max(minimumPanelWidth, contentSizedMenu ? panel.width : matchTriggerWidth ? anchor.width : tokens23.extensions.popover.width)
4546
+ Math.max(minimumPanelWidth, contentSizedMenu ? panel.width : matchTriggerWidth ? anchor.width : tokens24.extensions.popover.width)
4419
4547
  );
4420
- const available = Math.min(maxHeight != null ? maxHeight : field ? tokens23.extensions.menu.listMaxHeight : tokens23.extensions.floating.maxHeight, window2.height - 2 * tokens23.extensions.floating.viewportInset), height = Math.min(panel.height + (header != null ? headerHeight : 0), available), roomAbove = anchor.y - gap - tokens23.extensions.floating.viewportInset, roomBelow = window2.height - anchor.y - anchor.height - gap - tokens23.extensions.floating.viewportInset, above = placement.startsWith("top") ? !(flip && height > roomAbove && roomBelow > roomAbove) : flip && height > roomBelow && roomAbove > roomBelow;
4548
+ const available = Math.min(maxHeight != null ? maxHeight : field ? tokens24.extensions.menu.listMaxHeight : tokens24.extensions.floating.maxHeight, window2.height - 2 * tokens24.extensions.floating.viewportInset), height = Math.min(panel.height + (header != null ? headerHeight : 0), available), roomAbove = anchor.y - gap - tokens24.extensions.floating.viewportInset, roomBelow = window2.height - anchor.y - anchor.height - gap - tokens24.extensions.floating.viewportInset, above = placement.startsWith("top") ? !(flip && height > roomAbove && roomBelow > roomAbove) : flip && height > roomBelow && roomAbove > roomBelow;
4421
4549
  let left = placement.endsWith("end") ? anchor.x + anchor.width - width : placement === "top" || placement === "bottom" ? anchor.x + (anchor.width - width) / 2 : anchor.x, top = above ? anchor.y - height - gap : anchor.y + anchor.height + gap;
4422
4550
  if (placement === "left" || placement === "right") {
4423
4551
  left = placement === "left" ? anchor.x - width - gap : anchor.x + anchor.width + gap;
4424
4552
  top = anchor.y + (anchor.height - height) / 2;
4425
4553
  }
4426
- left = Math.max(tokens23.extensions.floating.viewportInset, Math.min(window2.width - width - tokens23.extensions.floating.viewportInset, left));
4427
- top = Math.max(tokens23.extensions.floating.viewportInset, Math.min(window2.height - height - tokens23.extensions.floating.viewportInset, top));
4554
+ left = Math.max(tokens24.extensions.floating.viewportInset, Math.min(window2.width - width - tokens24.extensions.floating.viewportInset, left));
4555
+ top = Math.max(tokens24.extensions.floating.viewportInset, Math.min(window2.height - height - tokens24.extensions.floating.viewportInset, top));
4428
4556
  if (layer.blocked) return null;
4429
4557
  if (tooltip && Platform16.OS === "web") {
4430
4558
  if (!motion.present) return null;
4431
- const arrow = tokens23.extensions.tooltip.arrowSize, corner = tokens23.radius.radius6, side = placement === "left" ? "right" : placement === "right" ? "left" : above ? "bottom" : "top", along = side === "top" || side === "bottom" ? Math.max(corner, Math.min(width - corner - arrow, anchor.x + anchor.width / 2 - left - arrow / 2)) : Math.max(corner, Math.min(height - corner - arrow, anchor.y + anchor.height / 2 - top - arrow / 2));
4559
+ const arrow = tokens24.extensions.tooltip.arrowSize, corner = tokens24.radius.radius6, side = placement === "left" ? "right" : placement === "right" ? "left" : above ? "bottom" : "top", along = side === "top" || side === "bottom" ? Math.max(corner, Math.min(width - corner - arrow, anchor.x + anchor.width / 2 - left - arrow / 2)) : Math.max(corner, Math.min(height - corner - arrow, anchor.y + anchor.height / 2 - top - arrow / 2));
4432
4560
  return /* @__PURE__ */ jsxs14(
4433
4561
  Animated13.View,
4434
4562
  {
@@ -4455,7 +4583,7 @@ function FloatingPanel({
4455
4583
  borderRadius: corner,
4456
4584
  overflow: "hidden",
4457
4585
  backgroundColor: colors.chartTooltipBg,
4458
- boxShadow: shadowLayers(tokens23.extensions.tooltip.elevation, colors)
4586
+ boxShadow: shadowLayers(tokens24.extensions.tooltip.elevation, colors)
4459
4587
  },
4460
4588
  children
4461
4589
  }
@@ -4517,8 +4645,8 @@ function FloatingPanel({
4517
4645
  style: {
4518
4646
  opacity: anchored && sized ? motion.opacity : 0,
4519
4647
  transform: tooltip ? void 0 : [
4520
- { translateX: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [placement === "left" ? tokens23.motionDistance.popup : placement === "right" ? -tokens23.motionDistance.popup : 0, 0] }) },
4521
- { translateY: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [placement === "left" || placement === "right" ? 0 : above ? tokens23.motionDistance.popup : -tokens23.motionDistance.popup, 0] }) }
4648
+ { translateX: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [placement === "left" ? tokens24.motionDistance.popup : placement === "right" ? -tokens24.motionDistance.popup : 0, 0] }) },
4649
+ { translateY: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [placement === "left" || placement === "right" ? 0 : above ? tokens24.motionDistance.popup : -tokens24.motionDistance.popup, 0] }) }
4522
4650
  ],
4523
4651
  position: "absolute",
4524
4652
  top,
@@ -4527,11 +4655,11 @@ function FloatingPanel({
4527
4655
  minWidth: contentSizedMenu ? minimumPanelWidth : void 0,
4528
4656
  maxWidth: tooltip ? tooltipWidth : maximumWidth,
4529
4657
  maxHeight: available,
4530
- borderRadius: popover ? tokens23.extensions.popover.radius : field ? tokens23.radius.radius12 : tokens23.extensions.menu.radius,
4531
- borderWidth: popover ? 0 : tokens23.border.defaultWidth,
4658
+ borderRadius: popover ? tokens24.extensions.popover.radius : field ? tokens24.radius.radius12 : tokens24.extensions.menu.radius,
4659
+ borderWidth: popover ? 0 : tokens24.border.defaultWidth,
4532
4660
  borderColor: colors.border,
4533
4661
  backgroundColor: colors.surface,
4534
- boxShadow: (tooltip ? tokens23.extensions.tooltip.elevation : popover ? tokens23.extensions.popover.elevation : tokens23.extensions.menu.elevation).map(({ colorRole, ...layer2 }) => ({ ...layer2, color: colors[colorRole] })),
4662
+ boxShadow: (tooltip ? tokens24.extensions.tooltip.elevation : popover ? tokens24.extensions.popover.elevation : tokens24.extensions.menu.elevation).map(({ colorRole, ...layer2 }) => ({ ...layer2, color: colors[colorRole] })),
4535
4663
  overflow: "hidden"
4536
4664
  },
4537
4665
  children: [
@@ -4540,10 +4668,10 @@ function FloatingPanel({
4540
4668
  {
4541
4669
  onLayout: ({ nativeEvent: { layout } }) => setHeaderHeight(layout.height),
4542
4670
  style: {
4543
- paddingTop: tokens23.extensions.popover.padding,
4544
- paddingHorizontal: tokens23.extensions.popover.padding,
4545
- paddingBottom: tokens23.extensions.popover.headerPaddingBottom,
4546
- borderBottomWidth: tokens23.border.defaultWidth,
4671
+ paddingTop: tokens24.extensions.popover.padding,
4672
+ paddingHorizontal: tokens24.extensions.popover.padding,
4673
+ paddingBottom: tokens24.extensions.popover.headerPaddingBottom,
4674
+ borderBottomWidth: tokens24.border.defaultWidth,
4547
4675
  borderBottomColor: colors.divider
4548
4676
  },
4549
4677
  children: content(header, typeStyle("cardTitle"))
@@ -4558,7 +4686,7 @@ function FloatingPanel({
4558
4686
  },
4559
4687
  keyboardShouldPersistTaps: "handled",
4560
4688
  style: { maxHeight: available - (header != null ? headerHeight : 0), flexShrink: 1 },
4561
- contentContainerStyle: { padding: menu || field ? tokens23.extensions.menu.padding : 0 },
4689
+ contentContainerStyle: { padding: menu || field ? tokens24.extensions.menu.padding : 0 },
4562
4690
  onContentSizeChange: (width2, height2) => {
4563
4691
  if (contentSizedMenu) return;
4564
4692
  setSized(true);
@@ -4583,15 +4711,15 @@ function FloatingPanel({
4583
4711
  import {
4584
4712
  cloneElement as cloneElement4,
4585
4713
  isValidElement as isValidElement5,
4586
- useEffect as useEffect13,
4587
- useRef as useRef17,
4714
+ useEffect as useEffect14,
4715
+ useRef as useRef19,
4588
4716
  useState as useState17
4589
4717
  } from "react";
4590
4718
  import {
4591
4719
  Platform as Platform17,
4592
4720
  View as View20
4593
4721
  } from "react-native";
4594
- import { tokens as tokens24 } from "@kjun-ui/tokens";
4722
+ import { tokens as tokens25 } from "@kjun-ui/tokens";
4595
4723
  import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
4596
4724
  function KjunPopover({
4597
4725
  noPadding = false,
@@ -4610,7 +4738,7 @@ function KjunPopover({
4610
4738
  children
4611
4739
  }) {
4612
4740
  const { colors } = useKjunStyles();
4613
- const [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, ref = useRef17(null);
4741
+ const [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, ref = useRef19(null);
4614
4742
  const change = (v) => {
4615
4743
  setInternal(v);
4616
4744
  onOpenChange == null ? void 0 : onOpenChange(v);
@@ -4640,7 +4768,7 @@ function KjunPopover({
4640
4768
  ariaLabel,
4641
4769
  header: header != null ? content(header, { ...typeStyle("cardTitle"), color: colors.text }) : void 0,
4642
4770
  nonModal: !modal,
4643
- children: /* @__PURE__ */ jsx27(View20, { style: { padding: noPadding ? 0 : tokens24.extensions.popover.padding, gap: noPadding ? 0 : tokens24.extensions.popover.gap }, children: content(
4771
+ children: /* @__PURE__ */ jsx27(View20, { style: { padding: noPadding ? 0 : tokens25.extensions.popover.padding, gap: noPadding ? 0 : tokens25.extensions.popover.gap }, children: content(
4644
4772
  typeof children === "function" ? children(() => change(false)) : children,
4645
4773
  Platform17.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : void 0
4646
4774
  ) })
@@ -4658,13 +4786,13 @@ function KjunTooltip({
4658
4786
  open: controlled,
4659
4787
  onOpenChange
4660
4788
  }) {
4661
- const { colors } = useKjunStyles(), [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, latest = useRef17({ open, onOpenChange }), setOpen = (value) => {
4789
+ const { colors } = useKjunStyles(), [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, latest = useRef19({ open, onOpenChange }), setOpen = (value) => {
4662
4790
  var _a, _b;
4663
4791
  if (latest.current.open === value) return;
4664
4792
  latest.current.open = value;
4665
4793
  setInternal(value);
4666
4794
  (_b = (_a = latest.current).onOpenChange) == null ? void 0 : _b.call(_a, value);
4667
- }, ref = useRef17(null), timer = useRef17(void 0);
4795
+ }, ref = useRef19(null), timer = useRef19(void 0);
4668
4796
  latest.current = { open, onOpenChange };
4669
4797
  const scopeActive = useActiveLayerScope();
4670
4798
  const hide = () => {
@@ -4676,11 +4804,11 @@ function KjunTooltip({
4676
4804
  clearTimeout(timer.current);
4677
4805
  timer.current = setTimeout(() => setOpen(true), delay);
4678
4806
  };
4679
- useEffect13(() => {
4807
+ useEffect14(() => {
4680
4808
  if (!scopeActive) hide();
4681
4809
  }, [scopeActive]);
4682
- useEffect13(() => () => clearTimeout(timer.current), []);
4683
- useEffect13(() => {
4810
+ useEffect14(() => () => clearTimeout(timer.current), []);
4811
+ useEffect14(() => {
4684
4812
  if (Platform17.OS !== "web" || !open) return;
4685
4813
  const escape = (event) => {
4686
4814
  if (event.key === "Escape") hide();
@@ -4747,9 +4875,9 @@ function KjunTooltip({
4747
4875
  View20,
4748
4876
  {
4749
4877
  style: {
4750
- paddingVertical: tokens24.extensions.tooltip.paddingY,
4751
- paddingHorizontal: tokens24.extensions.tooltip.paddingX,
4752
- maxWidth: tokens24.extensions.tooltip.maxWidth,
4878
+ paddingVertical: tokens25.extensions.tooltip.paddingY,
4879
+ paddingHorizontal: tokens25.extensions.tooltip.paddingX,
4880
+ maxWidth: tokens25.extensions.tooltip.maxWidth,
4753
4881
  backgroundColor: colors.chartTooltipBg
4754
4882
  },
4755
4883
  children: /* @__PURE__ */ jsx27(
@@ -4785,7 +4913,7 @@ function KjunDropdown({
4785
4913
  onClose
4786
4914
  }) {
4787
4915
  const m = useKjunMessages();
4788
- const [open, setOpen] = useState18(false), currentOpen = useRef18(false), ref = useRef18(null);
4916
+ const [open, setOpen] = useState18(false), currentOpen = useRef20(false), ref = useRef20(null);
4789
4917
  let control = trigger;
4790
4918
  while (isValidElement6(control) && control.type === KjunTooltip)
4791
4919
  control = control.props.children;
@@ -4797,7 +4925,7 @@ function KjunDropdown({
4797
4925
  if (v) onOpen == null ? void 0 : onOpen();
4798
4926
  else onClose == null ? void 0 : onClose();
4799
4927
  };
4800
- useEffect14(() => {
4928
+ useEffect15(() => {
4801
4929
  if (unavailable) change(false);
4802
4930
  }, [unavailable]);
4803
4931
  return /* @__PURE__ */ jsxs16(DropdownContext.Provider, { value: () => change(false), children: [
@@ -4852,18 +4980,18 @@ function KjunDropdownItem({
4852
4980
  style: ({ pressed }) => ({
4853
4981
  flexDirection: "row",
4854
4982
  alignItems: "center",
4855
- gap: tokens25.dimension.value8,
4856
- paddingVertical: tokens25.extensions.menu.optionPaddingY,
4857
- paddingHorizontal: tokens25.extensions.menu.optionPaddingX,
4858
- minHeight: tokens25.extensions.menu.optionHeight,
4859
- borderRadius: tokens25.extensions.menu.optionRadius,
4983
+ gap: tokens26.dimension.value8,
4984
+ paddingVertical: tokens26.extensions.menu.optionPaddingY,
4985
+ paddingHorizontal: tokens26.extensions.menu.optionPaddingX,
4986
+ minHeight: tokens26.extensions.menu.optionHeight,
4987
+ borderRadius: tokens26.extensions.menu.optionRadius,
4860
4988
  backgroundColor: selected ? colors.selectedBg : !disabled && (pressed || hovered) ? variant === "danger" ? colors.dangerBg : colors.hover : void 0,
4861
- opacity: disabled ? tokens25.states.opacity.disabled : 1
4989
+ opacity: disabled ? tokens26.states.opacity.disabled : 1
4862
4990
  }),
4863
4991
  children: [
4864
- icon ? /* @__PURE__ */ jsx28(KjunIcon, { name: icon, size: tokens25.extensions.menu.iconSize, color: iconColor }) : reserveIcon && /* @__PURE__ */ jsx28(View21, { style: { width: tokens25.extensions.menu.iconSize }, accessible: false }),
4865
- /* @__PURE__ */ jsx28(View21, { style: { flexGrow: 1, flexShrink: 1 }, children: content(children, { color, fontSize: tokens25.extensions.menu.optionFontSize, lineHeight: tokens25.extensions.menu.optionLineHeight }) }),
4866
- selected !== null && /* @__PURE__ */ jsx28(View21, { style: { opacity: selected ? 1 : 0 }, accessible: false, children: /* @__PURE__ */ jsx28(KjunIcon, { name: "check", size: tokens25.extensions.menu.iconSize, color: colors.brand }) })
4992
+ icon ? /* @__PURE__ */ jsx28(KjunIcon, { name: icon, size: tokens26.extensions.menu.iconSize, color: iconColor }) : reserveIcon && /* @__PURE__ */ jsx28(View21, { style: { width: tokens26.extensions.menu.iconSize }, accessible: false }),
4993
+ /* @__PURE__ */ jsx28(View21, { style: { flexGrow: 1, flexShrink: 1 }, children: content(children, { color, fontSize: tokens26.extensions.menu.optionFontSize, lineHeight: tokens26.extensions.menu.optionLineHeight }) }),
4994
+ selected !== null && /* @__PURE__ */ jsx28(View21, { style: { opacity: selected ? 1 : 0 }, accessible: false, children: /* @__PURE__ */ jsx28(KjunIcon, { name: "check", size: tokens26.extensions.menu.iconSize, color: colors.brand }) })
4867
4995
  ]
4868
4996
  }
4869
4997
  );
@@ -4874,7 +5002,7 @@ function KjunDropdownDivider() {
4874
5002
  View21,
4875
5003
  {
4876
5004
  role: "separator",
4877
- style: { height: tokens25.extensions.menu.dividerHeight, marginVertical: tokens25.dimension.value4, backgroundColor: colors.border }
5005
+ style: { height: tokens26.extensions.menu.dividerHeight, marginVertical: tokens26.dimension.value4, backgroundColor: colors.border }
4878
5006
  }
4879
5007
  );
4880
5008
  }
@@ -4933,7 +5061,7 @@ function KjunMenuButton({
4933
5061
  }
4934
5062
 
4935
5063
  // shared/package-runtime/combobox.ts
4936
- import { useEffect as useEffect15, useState as useState19 } from "react";
5064
+ import { useEffect as useEffect16, useState as useState19 } from "react";
4937
5065
 
4938
5066
  // shared/package-runtime/options.ts
4939
5067
  var optionValue = (option, key = "value") => typeof option === "object" ? option[key] : option;
@@ -5013,8 +5141,8 @@ function useComboboxModel({
5013
5141
  const selectedLabel = selected !== void 0 ? optionLabel(selected, labelKey) : "";
5014
5142
  const [query, setQuery] = useState19(selectedLabel);
5015
5143
  const [open, setOpen] = useState19(false);
5016
- useEffect15(() => setQuery(selectedLabel), [value, selectedLabel]);
5017
- useEffect15(() => {
5144
+ useEffect16(() => setQuery(selectedLabel), [value, selectedLabel]);
5145
+ useEffect16(() => {
5018
5146
  if (disabled) setOpen(false);
5019
5147
  }, [disabled]);
5020
5148
  const change = (next) => {
@@ -5047,12 +5175,12 @@ function useComboboxModel({
5047
5175
  }
5048
5176
 
5049
5177
  // packages/native/src/combobox.tsx
5050
- import { tokens as tokens27 } from "@kjun-ui/tokens";
5051
- import { useId as useId5, useRef as useRef19 } from "react";
5178
+ import { tokens as tokens28 } from "@kjun-ui/tokens";
5179
+ import { useId as useId5, useRef as useRef21 } from "react";
5052
5180
  import { Platform as Platform18, View as View23 } from "react-native";
5053
5181
 
5054
5182
  // packages/native/src/select-options.tsx
5055
- import { tokens as tokens26 } from "@kjun-ui/tokens";
5183
+ import { tokens as tokens27 } from "@kjun-ui/tokens";
5056
5184
  import { View as View22 } from "react-native";
5057
5185
  import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
5058
5186
  function OptionRow({
@@ -5075,20 +5203,20 @@ function OptionRow({
5075
5203
  onPress,
5076
5204
  onLayout,
5077
5205
  style: ({ pressed }) => ({
5078
- borderRadius: tokens26.radius.radius8,
5079
- minHeight: tokens26.extensions.menu.optionHeight,
5206
+ borderRadius: tokens27.radius.radius8,
5207
+ minHeight: tokens27.extensions.menu.optionHeight,
5080
5208
  flexDirection: "row",
5081
5209
  alignItems: "center",
5082
5210
  justifyContent: "space-between",
5083
- gap: tokens26.dimension.value8,
5084
- paddingVertical: tokens26.extensions.menu.optionPaddingY,
5085
- paddingHorizontal: tokens26.extensions.menu.optionPaddingX,
5211
+ gap: tokens27.dimension.value8,
5212
+ paddingVertical: tokens27.extensions.menu.optionPaddingY,
5213
+ paddingHorizontal: tokens27.extensions.menu.optionPaddingX,
5086
5214
  backgroundColor: selected ? colors.selectedBg : pressed ? colors.hover : void 0,
5087
- opacity: disabled ? tokens26.states.opacity.disabled : 1
5215
+ opacity: disabled ? tokens27.states.opacity.disabled : 1
5088
5216
  }),
5089
5217
  children: [
5090
- /* @__PURE__ */ jsx29(View22, { style: { flex: 1 }, children: content(children || label, { fontSize: tokens26.extensions.menu.optionFontSize, lineHeight: tokens26.extensions.menu.optionLineHeight }) }),
5091
- selected && /* @__PURE__ */ jsx29(KjunIcon, { name: "check", size: tokens26.extensions.menu.iconSize, color: colors.brand })
5218
+ /* @__PURE__ */ jsx29(View22, { style: { flex: 1 }, children: content(children || label, { fontSize: tokens27.extensions.menu.optionFontSize, lineHeight: tokens27.extensions.menu.optionLineHeight }) }),
5219
+ selected && /* @__PURE__ */ jsx29(KjunIcon, { name: "check", size: tokens27.extensions.menu.iconSize, color: colors.brand })
5092
5220
  ]
5093
5221
  }
5094
5222
  );
@@ -5178,8 +5306,8 @@ function SearchField({
5178
5306
  }) {
5179
5307
  const m = useKjunMessages();
5180
5308
  const searchId = "kjun-popup-search-" + useId5().replace(/:/g, "");
5181
- const clearing = useRef19(false);
5182
- const ref = useRef19(null), { colors } = useKjunStyles();
5309
+ const clearing = useRef21(false);
5310
+ const ref = useRef21(null), { colors } = useKjunStyles();
5183
5311
  const focusGuard = usePopupFocusGuard(ref);
5184
5312
  const openFromPress = () => {
5185
5313
  if (!disabled) {
@@ -5226,8 +5354,8 @@ function SearchField({
5226
5354
  View23,
5227
5355
  {
5228
5356
  style: {
5229
- padding: tokens27.dimension.value8,
5230
- borderBottomWidth: tokens27.border.defaultWidth,
5357
+ padding: tokens28.dimension.value8,
5358
+ borderBottomWidth: tokens28.border.defaultWidth,
5231
5359
  borderBottomColor: colors.border
5232
5360
  },
5233
5361
  children: /* @__PURE__ */ jsx30(KjunInput, { ...inputProps, nativeID: searchId, autoFocus: true })
@@ -5235,13 +5363,13 @@ function SearchField({
5235
5363
  ),
5236
5364
  loading ? (
5237
5365
  // Centered like the Select loading row on every platform.
5238
- /* @__PURE__ */ jsx30(View23, { style: { padding: tokens27.dimension.value12, alignItems: "center" }, children: /* @__PURE__ */ jsx30(KjunSpinner, { size: "sm", text: m.searching }) })
5366
+ /* @__PURE__ */ jsx30(View23, { style: { padding: tokens28.dimension.value12, alignItems: "center" }, children: /* @__PURE__ */ jsx30(KjunSpinner, { size: "sm", text: m.searching }) })
5239
5367
  ) : failed ? /* @__PURE__ */ jsx30(
5240
5368
  KText,
5241
5369
  {
5242
5370
  accessibilityRole: "alert",
5243
5371
  style: {
5244
- padding: tokens27.dimension.value12,
5372
+ padding: tokens28.dimension.value12,
5245
5373
  textAlign: "center",
5246
5374
  color: colors.danger
5247
5375
  },
@@ -5264,7 +5392,7 @@ function SearchField({
5264
5392
  KText,
5265
5393
  {
5266
5394
  style: {
5267
- padding: tokens27.dimension.value12,
5395
+ padding: tokens28.dimension.value12,
5268
5396
  textAlign: "center",
5269
5397
  color: colors.textTertiary
5270
5398
  },
@@ -5278,8 +5406,8 @@ function SearchField({
5278
5406
  }
5279
5407
 
5280
5408
  // packages/native/src/date-picker.tsx
5281
- import { tokens as tokens28 } from "@kjun-ui/tokens";
5282
- import { useRef as useRef20, useState as useState20 } from "react";
5409
+ import { tokens as tokens29 } from "@kjun-ui/tokens";
5410
+ import { useRef as useRef22, useState as useState20 } from "react";
5283
5411
  import { Platform as Platform19, View as View24 } from "react-native";
5284
5412
  import { Fragment as Fragment9, jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
5285
5413
  function displayMonth(value) {
@@ -5302,7 +5430,7 @@ function KjunDatePicker({
5302
5430
  const scope = useKjunMessageScope();
5303
5431
  placeholder != null ? placeholder : placeholder = scope.messages.datePlaceholder;
5304
5432
  const clear = clearable && !!value && !disabled;
5305
- const { colors } = useKjunStyles(), field = useKjunField(), [open, setOpen] = useState20(false), [month, setMonth] = useState20(() => displayMonth(value)), ref = useRef20(null), spec = tokens28.input[size];
5433
+ const { colors } = useKjunStyles(), field = useKjunField(), [open, setOpen] = useState20(false), [month, setMonth] = useState20(() => displayMonth(value)), ref = useRef22(null), spec = tokens29.input[size];
5306
5434
  const surface = useFieldSurface(size, { disabled, invalid: error || !!(field == null ? void 0 : field.error), open });
5307
5435
  const year = month.getFullYear(), m = month.getMonth(), first = new Date(year, m, 1).getDay(), count = new Date(year, m + 1, 0).getDate();
5308
5436
  const date = (day) => `${year}-${String(m + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
@@ -5310,7 +5438,7 @@ function KjunDatePicker({
5310
5438
  /* @__PURE__ */ jsxs19(View24, { ref, collapsable: false, ...fieldTarget(() => {
5311
5439
  setMonth(displayMonth(value));
5312
5440
  setOpen(true);
5313
- }, disabled), style: { minHeight: tokens28.native.minimumTouchTarget, justifyContent: "center" }, children: [
5441
+ }, disabled), style: { minHeight: tokens29.native.minimumTouchTarget, justifyContent: "center" }, children: [
5314
5442
  /* @__PURE__ */ jsxs19(
5315
5443
  FieldPressable,
5316
5444
  {
@@ -5336,7 +5464,7 @@ function KjunDatePicker({
5336
5464
  },
5337
5465
  style: {
5338
5466
  ...surface.style,
5339
- paddingHorizontal: spec.padding - tokens28.border.controlWidth,
5467
+ paddingHorizontal: spec.padding - tokens29.border.controlWidth,
5340
5468
  flexDirection: "row",
5341
5469
  alignItems: "center",
5342
5470
  justifyContent: "space-between"
@@ -5379,9 +5507,9 @@ function KjunDatePicker({
5379
5507
  triggerRef: ref,
5380
5508
  placement: "bottom-start",
5381
5509
  matchTriggerWidth: true,
5382
- minimumWidth: tokens28.extensions.calendar.minimumWidth,
5510
+ minimumWidth: tokens29.extensions.calendar.minimumWidth,
5383
5511
  ariaLabel: scope.messages.datePlaceholder,
5384
- children: /* @__PURE__ */ jsxs19(View24, { style: { padding: tokens28.dimension.value8 }, children: [
5512
+ children: /* @__PURE__ */ jsxs19(View24, { style: { padding: tokens29.dimension.value8 }, children: [
5385
5513
  /* @__PURE__ */ jsxs19(
5386
5514
  View24,
5387
5515
  {
@@ -5422,7 +5550,7 @@ function KjunDatePicker({
5422
5550
  style: {
5423
5551
  width: "14.2857%",
5424
5552
  textAlign: "center",
5425
- paddingVertical: tokens28.dimension.value8,
5553
+ paddingVertical: tokens29.dimension.value8,
5426
5554
  color: colors.textTertiary
5427
5555
  },
5428
5556
  children: day
@@ -5449,12 +5577,12 @@ function KjunDatePicker({
5449
5577
  },
5450
5578
  style: {
5451
5579
  width: "14.2857%",
5452
- minHeight: tokens28.native.minimumTouchTarget,
5580
+ minHeight: tokens29.native.minimumTouchTarget,
5453
5581
  alignItems: "center",
5454
5582
  justifyContent: "center",
5455
- borderRadius: tokens28.radius.radius6,
5583
+ borderRadius: tokens29.radius.radius6,
5456
5584
  backgroundColor: v === value ? colors.brand : void 0,
5457
- opacity: blocked ? tokens28.states.opacity.disabledStrong : 1
5585
+ opacity: blocked ? tokens29.states.opacity.disabledStrong : 1
5458
5586
  },
5459
5587
  children: /* @__PURE__ */ jsx31(
5460
5588
  KText,
@@ -5480,7 +5608,7 @@ function KjunDatePicker({
5480
5608
  import { useState as useState22 } from "react";
5481
5609
 
5482
5610
  // shared/package-runtime/search-input.ts
5483
- import { useEffect as useEffect16, useLayoutEffect as useLayoutEffect9, useRef as useRef21, useState as useState21 } from "react";
5611
+ import { useEffect as useEffect17, useLayoutEffect as useLayoutEffect9, useRef as useRef23, useState as useState21 } from "react";
5484
5612
  function useSearchInputModel({
5485
5613
  value,
5486
5614
  disabled = false,
@@ -5490,10 +5618,10 @@ function useSearchInputModel({
5490
5618
  onValueChange,
5491
5619
  onSearchError
5492
5620
  }, open) {
5493
- const [query, setQuery] = useState21(value), [options, setOptions] = useState21([]), [loading, setLoading] = useState21(false), [failed, setFailed] = useState21(false), version = useRef21(0), notify = useRef21(onSearchError);
5621
+ const [query, setQuery] = useState21(value), [options, setOptions] = useState21([]), [loading, setLoading] = useState21(false), [failed, setFailed] = useState21(false), version = useRef23(0), notify = useRef23(onSearchError);
5494
5622
  notify.current = onSearchError;
5495
- const timer = useRef21(void 0);
5496
- const notifyValue = useRef21(onValueChange);
5623
+ const timer = useRef23(void 0);
5624
+ const notifyValue = useRef23(onValueChange);
5497
5625
  notifyValue.current = onValueChange;
5498
5626
  useLayoutEffect9(() => {
5499
5627
  clearTimeout(timer.current);
@@ -5503,7 +5631,7 @@ function useSearchInputModel({
5503
5631
  clearTimeout(timer.current);
5504
5632
  return () => clearTimeout(timer.current);
5505
5633
  }, [disabled, debounce, !!loadOptions]);
5506
- useEffect16(() => {
5634
+ useEffect17(() => {
5507
5635
  const current = ++version.current, abort = new AbortController();
5508
5636
  setFailed(false);
5509
5637
  if (!loadOptions || !open || disabled || query.length < minChars) {
@@ -5655,22 +5783,22 @@ function KjunSearchInput({
5655
5783
  }
5656
5784
 
5657
5785
  // packages/native/src/select-control.tsx
5658
- import { tokens as tokens30 } from "@kjun-ui/tokens";
5659
- import { useContext as useContext14, useEffect as useEffect18, useRef as useRef23 } from "react";
5786
+ import { tokens as tokens31 } from "@kjun-ui/tokens";
5787
+ import { useContext as useContext14, useEffect as useEffect19, useRef as useRef25 } from "react";
5660
5788
 
5661
5789
  // packages/native/src/compound-control.tsx
5662
5790
  import { createContext as createContext18 } from "react";
5663
5791
  import { View as View25 } from "react-native";
5664
- import { tokens as tokens29 } from "@kjun-ui/tokens";
5792
+ import { tokens as tokens30 } from "@kjun-ui/tokens";
5665
5793
  import { jsx as jsx33 } from "react/jsx-runtime";
5666
5794
  var CompoundControlContext = createContext18(null);
5667
5795
  function CompoundTarget({ children, square = false }) {
5668
- const touch = finePointer() ? void 0 : tokens29.native.minimumTouchTarget;
5796
+ const touch = finePointer() ? void 0 : tokens30.native.minimumTouchTarget;
5669
5797
  return /* @__PURE__ */ jsx33(View25, { style: { minHeight: touch, minWidth: square ? touch : void 0, alignItems: "center", justifyContent: "center" }, children });
5670
5798
  }
5671
5799
 
5672
5800
  // shared/package-runtime/select.ts
5673
- import { useEffect as useEffect17, useRef as useRef22, useState as useState23 } from "react";
5801
+ import { useEffect as useEffect18, useRef as useRef24, useState as useState23 } from "react";
5674
5802
  function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5675
5803
  const [internal, setInternal] = useState23(false);
5676
5804
  const [query, setQuery] = useState23("");
@@ -5678,8 +5806,8 @@ function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5678
5806
  const [session, setSession] = useState23(0);
5679
5807
  const isControlled = typeof controlled === "boolean";
5680
5808
  const open = !disabled && (isControlled ? controlled : internal);
5681
- const previousOpen = useRef22(open);
5682
- useEffect17(() => {
5809
+ const previousOpen = useRef24(open);
5810
+ useEffect18(() => {
5683
5811
  if (disabled && !isControlled) setInternal(false);
5684
5812
  if (previousOpen.current && !open) {
5685
5813
  setQuery("");
@@ -5688,7 +5816,7 @@ function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5688
5816
  }
5689
5817
  previousOpen.current = open;
5690
5818
  }, [open, disabled, isControlled, pageSize]);
5691
- useEffect17(() => {
5819
+ useEffect18(() => {
5692
5820
  setLimit(pageSize);
5693
5821
  }, [pageSize]);
5694
5822
  const changeOpen = (next) => {
@@ -5738,14 +5866,14 @@ function KjunSelect({
5738
5866
  placeholder != null ? placeholder : placeholder = m.select;
5739
5867
  searchPlaceholder != null ? searchPlaceholder : searchPlaceholder = m.search;
5740
5868
  const { open, query, limit, changeOpen, search, showMore } = useSelectState(controlled, disabled, optionPageSize, onOpenChange);
5741
- const { colors } = useKjunStyles(), field = useKjunField(), ref = useRef23(null), spec = tokens30.input[size];
5742
- const trigger = useRef23(null);
5869
+ const { colors } = useKjunStyles(), field = useKjunField(), ref = useRef25(null), spec = tokens31.input[size];
5870
+ const trigger = useRef25(null);
5743
5871
  const compound = useContext14(CompoundControlContext);
5744
- useEffect18(() => {
5872
+ useEffect19(() => {
5745
5873
  if (compound == null ? void 0 : compound.focusRef) compound.focusRef.current = trigger.current;
5746
5874
  }, [compound == null ? void 0 : compound.focusRef]);
5747
5875
  const expanded = usePopupExpanded(open, ref);
5748
- const selectedRow = useRef23(null);
5876
+ const selectedRow = useRef25(null);
5749
5877
  const surface = useFieldSurface(size, { disabled, invalid: error || !!(field == null ? void 0 : field.error), open: expanded });
5750
5878
  const change = (v) => {
5751
5879
  onValueChange == null ? void 0 : onValueChange(v);
@@ -5770,10 +5898,10 @@ function KjunSelect({
5770
5898
  return /* @__PURE__ */ jsxs20(Fragment10, { children: [
5771
5899
  /* @__PURE__ */ jsxs20(View26, { ref, collapsable: false, ...fieldTarget(() => changeOpen(!open), disabled), style: {
5772
5900
  position: "relative",
5773
- minHeight: tokens30.native.minimumTouchTarget,
5901
+ minHeight: tokens31.native.minimumTouchTarget,
5774
5902
  justifyContent: "center",
5775
5903
  // Inside a compound field the touch target overflows so the shared surface keeps its size height.
5776
- ...compound ? { marginVertical: Math.min(0, (spec.height - tokens30.native.minimumTouchTarget) / 2) } : {}
5904
+ ...compound ? { marginVertical: Math.min(0, (spec.height - tokens31.native.minimumTouchTarget) / 2) } : {}
5777
5905
  }, children: [
5778
5906
  /* @__PURE__ */ jsxs20(
5779
5907
  FieldPressable,
@@ -5809,14 +5937,14 @@ function KjunSelect({
5809
5937
  flexDirection: "row",
5810
5938
  alignItems: "center",
5811
5939
  justifyContent: "space-between",
5812
- gap: tokens30.dimension.value8,
5940
+ gap: tokens31.dimension.value8,
5813
5941
  ...surface.style,
5814
- paddingHorizontal: spec.padding - tokens30.border.controlWidth,
5815
- paddingRight: spec.padding - tokens30.border.controlWidth,
5816
- ...compound ? { paddingHorizontal: tokens30.extensions.timePicker.segmentPadding, paddingRight: tokens30.extensions.timePicker.segmentPadding, paddingLeft: compound.leading ? spec.padding - tokens30.border.controlWidth : tokens30.extensions.timePicker.segmentPadding, gap: tokens30.extensions.timePicker.segmentPadding, backgroundColor: !disabled && (surface.active || surface.hovered) ? colors.hover : "transparent", borderColor: "transparent", outlineWidth: 0 } : {}
5942
+ paddingHorizontal: spec.padding - tokens31.border.controlWidth,
5943
+ paddingRight: spec.padding - tokens31.border.controlWidth,
5944
+ ...compound ? { paddingHorizontal: tokens31.extensions.timePicker.segmentPadding, paddingRight: tokens31.extensions.timePicker.segmentPadding, paddingLeft: compound.leading ? spec.padding - tokens31.border.controlWidth : tokens31.extensions.timePicker.segmentPadding, gap: tokens31.extensions.timePicker.segmentPadding, backgroundColor: !disabled && (surface.active || surface.hovered) ? colors.hover : "transparent", borderColor: "transparent", outlineWidth: 0 } : {}
5817
5945
  },
5818
5946
  children: [
5819
- /* @__PURE__ */ jsxs20(View26, { style: { ...compound ? { flexGrow: 1, flexShrink: 0 } : { flex: 1, minWidth: 0 }, paddingRight: clearable && label ? tokens30.native.minimumTouchTarget + spec.affixGap : 0 }, children: [
5947
+ /* @__PURE__ */ jsxs20(View26, { style: { ...compound ? { flexGrow: 1, flexShrink: 0 } : { flex: 1, minWidth: 0 }, paddingRight: clearable && label ? tokens31.native.minimumTouchTarget + spec.affixGap : 0 }, children: [
5820
5948
  compound && /* @__PURE__ */ jsx34(KText, { "aria-hidden": true, importantForAccessibility: "no-hide-descendants", style: { ...inputTypeStyle(size), fontVariant: ["tabular-nums"], opacity: 0 }, children: "00" }),
5821
5949
  (renderSelected == null ? void 0 : renderSelected(selectedOption)) || /* @__PURE__ */ jsx34(KText, { numberOfLines: 1, style: {
5822
5950
  ...inputTypeStyle(size),
@@ -5828,7 +5956,7 @@ function KjunSelect({
5828
5956
  KjunIcon,
5829
5957
  {
5830
5958
  name: "chevron-down",
5831
- size: compound ? tokens30.extensions.timePicker.iconSize : spec.iconSize,
5959
+ size: compound ? tokens31.extensions.timePicker.iconSize : spec.iconSize,
5832
5960
  color: surface.icon
5833
5961
  }
5834
5962
  ) })
@@ -5872,8 +6000,8 @@ function KjunSelect({
5872
6000
  View26,
5873
6001
  {
5874
6002
  style: {
5875
- padding: tokens30.dimension.value8,
5876
- borderBottomWidth: tokens30.border.defaultWidth,
6003
+ padding: tokens31.dimension.value8,
6004
+ borderBottomWidth: tokens31.border.defaultWidth,
5877
6005
  borderBottomColor: colors.border
5878
6006
  },
5879
6007
  children: /* @__PURE__ */ jsx34(
@@ -5893,7 +6021,7 @@ function KjunSelect({
5893
6021
  )
5894
6022
  }
5895
6023
  ),
5896
- loading ? /* @__PURE__ */ jsx34(View26, { style: { padding: tokens30.dimension.value12 }, children: /* @__PURE__ */ jsx34(KjunSpinner, { size: "sm", text: m.searching }) }) : visible.map(({ option: o, key }, index) => /* @__PURE__ */ jsx34(
6024
+ loading ? /* @__PURE__ */ jsx34(View26, { style: { padding: tokens31.dimension.value12 }, children: /* @__PURE__ */ jsx34(KjunSpinner, { size: "sm", text: m.searching }) }) : visible.map(({ option: o, key }, index) => /* @__PURE__ */ jsx34(
5897
6025
  OptionRow,
5898
6026
  {
5899
6027
  selected: selected(o),
@@ -5915,7 +6043,7 @@ function KjunSelect({
5915
6043
  KText,
5916
6044
  {
5917
6045
  style: {
5918
- padding: tokens30.dimension.value12,
6046
+ padding: tokens31.dimension.value12,
5919
6047
  textAlign: "center",
5920
6048
  color: colors.textTertiary
5921
6049
  },
@@ -5939,19 +6067,20 @@ function KjunSelect({
5939
6067
  }
5940
6068
 
5941
6069
  // packages/native/src/navigation.tsx
5942
- import { tokens as tokens33 } from "@kjun-ui/tokens";
6070
+ import { tokens as tokens34 } from "@kjun-ui/tokens";
5943
6071
 
5944
6072
  // packages/native/src/collapse.tsx
5945
- import { tokens as tokens31 } from "@kjun-ui/tokens";
5946
- import { useLayoutEffect as useLayoutEffect10, useRef as useRef24, useState as useState24 } from "react";
6073
+ import { tokens as tokens32 } from "@kjun-ui/tokens";
6074
+ import { useLayoutEffect as useLayoutEffect10, useRef as useRef26, useState as useState24 } from "react";
5947
6075
  import { Animated as Animated14, View as View27 } from "react-native";
5948
6076
  import { jsx as jsx35 } from "react/jsx-runtime";
5949
- function Collapse({ open, children }) {
6077
+ function Collapse({ open, keepMounted = false, children }) {
5950
6078
  const reduced = useReducedMotion();
5951
6079
  const [retained, setRetained] = useState24(open), [height, setHeight] = useState24(null);
5952
- const value = useRef24(new Animated14.Value(0)).current;
6080
+ const value = useRef26(new Animated14.Value(0)).current;
5953
6081
  const [settled, setSettled] = useState24(open);
5954
- const version = useRef24(0), first = useRef24(open);
6082
+ const version = useRef26(0), first = useRef26(open), opened = useRef26(open);
6083
+ if (open) opened.current = true;
5955
6084
  useLayoutEffect10(() => {
5956
6085
  const revision = ++version.current;
5957
6086
  if (open) setRetained(true);
@@ -5969,7 +6098,7 @@ function Collapse({ open, children }) {
5969
6098
  finish();
5970
6099
  } else {
5971
6100
  setSettled(false);
5972
- Animated14.timing(value, { toValue: target, duration: tokens31.motion.collapse, easing: motionOut, useNativeDriver: false }).start(({ finished }) => {
6101
+ Animated14.timing(value, { toValue: target, duration: tokens32.motion.collapse, easing: motionOut, useNativeDriver: false }).start(({ finished }) => {
5973
6102
  if (finished) finish();
5974
6103
  });
5975
6104
  }
@@ -5979,13 +6108,13 @@ function Collapse({ open, children }) {
5979
6108
  value.stopAnimation();
5980
6109
  };
5981
6110
  }, [open, height, reduced, value]);
5982
- return open || retained ? /* @__PURE__ */ jsx35(
6111
+ return open || retained || keepMounted && opened.current ? /* @__PURE__ */ jsx35(
5983
6112
  Animated14.View,
5984
6113
  {
5985
6114
  pointerEvents: open ? "auto" : "none",
5986
6115
  accessibilityElementsHidden: !open,
5987
6116
  importantForAccessibility: open ? "auto" : "no-hide-descendants",
5988
- ...!open ? { inert: true } : {},
6117
+ ...!open ? { inert: true, "aria-hidden": true } : {},
5989
6118
  style: { height: settled && open ? void 0 : value, overflow: "hidden" },
5990
6119
  children: /* @__PURE__ */ jsx35(View27, { onLayout: (event) => setHeight(event.nativeEvent.layout.height), children })
5991
6120
  }
@@ -5993,10 +6122,10 @@ function Collapse({ open, children }) {
5993
6122
  }
5994
6123
 
5995
6124
  // shared/package-runtime/navigation.ts
5996
- import { useEffect as useEffect19, useRef as useRef25, useState as useState25 } from "react";
6125
+ import { useEffect as useEffect20, useRef as useRef27, useState as useState25 } from "react";
5997
6126
  function useInitialTab(value, candidate, change) {
5998
- const requested = useRef25(/* @__PURE__ */ new Set());
5999
- useEffect19(() => {
6127
+ const requested = useRef27(/* @__PURE__ */ new Set());
6128
+ useEffect20(() => {
6000
6129
  if (value !== "") {
6001
6130
  requested.current.clear();
6002
6131
  return;
@@ -6008,7 +6137,7 @@ function useInitialTab(value, candidate, change) {
6008
6137
  }
6009
6138
  function useAccordionState(multiple) {
6010
6139
  const [opened, setOpened] = useState25(/* @__PURE__ */ new Set());
6011
- useEffect19(() => {
6140
+ useEffect20(() => {
6012
6141
  if (!multiple) setOpened((previous) => previous.size > 1 ? new Set([...previous].slice(-1)) : previous);
6013
6142
  }, [multiple]);
6014
6143
  return {
@@ -6036,15 +6165,16 @@ import {
6036
6165
  Fragment as Fragment11,
6037
6166
  createContext as createContext20,
6038
6167
  useContext as useContext16,
6039
- useEffect as useEffect20,
6168
+ useEffect as useEffect21,
6040
6169
  useId as useId7,
6170
+ useRef as useRef29,
6041
6171
  useState as useState27
6042
6172
  } from "react";
6043
6173
  import { Animated as Animated16, View as View29, useWindowDimensions as useWindowDimensions5, Platform as Platform22 } from "react-native";
6044
6174
 
6045
6175
  // packages/native/src/tabs.tsx
6046
- import { tokens as tokens32 } from "@kjun-ui/tokens";
6047
- import { Children as Children4, createContext as createContext19, isValidElement as isValidElement7, useContext as useContext15, useCallback as useCallback5, useLayoutEffect as useLayoutEffect11, useRef as useRef26, useId as useId6, useState as useState26 } from "react";
6176
+ import { tokens as tokens33 } from "@kjun-ui/tokens";
6177
+ import { Children as Children4, createContext as createContext19, isValidElement as isValidElement7, useContext as useContext15, useCallback as useCallback6, useLayoutEffect as useLayoutEffect11, useRef as useRef28, useId as useId6, useState as useState26 } from "react";
6048
6178
  import { Animated as Animated15, Platform as Platform21, ScrollView as ScrollView5, View as View28 } from "react-native";
6049
6179
 
6050
6180
  // packages/native/src/tabs-accessibility.ts
@@ -6075,29 +6205,29 @@ function KjunTabs({
6075
6205
  isValidElement7
6076
6206
  );
6077
6207
  const tabs = items2.length ? items2 : panes.filter((child) => child.type === KjunTabPane).map((child) => child.props);
6078
- const id = "kjun-" + useId6(), root = useRef26(null);
6079
- const menuState = useRef26({ tabs, onTabMenu });
6208
+ const id = "kjun-" + useId6(), root = useRef28(null);
6209
+ const menuState = useRef28({ tabs, onTabMenu });
6080
6210
  menuState.current = { tabs, onTabMenu };
6081
- const pressedMenu = useRef26(null);
6211
+ const pressedMenu = useRef28(null);
6082
6212
  useLayoutEffect11(() => {
6083
6213
  if (!onTabMenu || !tabs.some((tab) => tab.name === pressedMenu.current && !tab.disabled)) pressedMenu.current = null;
6084
6214
  }, [tabs, onTabMenu]);
6085
6215
  const panelNames = panes.filter((child) => child.type === KjunTabPane).map((child) => child.props.name);
6086
- const geometry2 = tokens32.extensions.tabs;
6216
+ const geometry2 = tokens33.extensions.tabs;
6087
6217
  const underline = variant === "underline";
6088
6218
  const [hoveredTab, setHoveredTab] = useState26(null);
6089
6219
  const singleLine = Platform21.OS === "web" ? { whiteSpace: "nowrap" } : {};
6090
6220
  const paddingX = !underline ? geometry2.pillsPaddingX : density === "compact" ? geometry2.compactPaddingX : geometry2.paddingX;
6091
6221
  const height = density === "compact" ? geometry2.compactHeight : geometry2.height;
6092
- const ringRoom = tokens32.states.focus.width + tokens32.states.focus.offset;
6093
- const slop = Math.max(0, (tokens32.native.minimumTouchTarget - height) / 2);
6222
+ const ringRoom = tokens33.states.focus.width + tokens33.states.focus.offset;
6223
+ const slop = Math.max(0, (tokens33.native.minimumTouchTarget - height) / 2);
6094
6224
  const roomX = underline ? ringRoom : 0, roomY = Math.max(underline ? ringRoom : 0, slop);
6095
6225
  const selectedTab = tabs.find((tab) => tab.name === value);
6096
6226
  const selection = useButtonGroupMotion(selectedTab ? { ...selectedTab, value: selectedTab.name } : void 0);
6097
- const tabRefs = useRef26(/* @__PURE__ */ new Map());
6227
+ const tabRefs = useRef28(/* @__PURE__ */ new Map());
6098
6228
  const { updateLayout } = selection;
6099
6229
  const firstName = (_a = tabs[0]) == null ? void 0 : _a.name;
6100
- const measureIndicator = useCallback5((name, box) => {
6230
+ const measureIndicator = useCallback6((name, box) => {
6101
6231
  const left = underline && name === firstName ? 0 : paddingX;
6102
6232
  updateLayout(name, underline ? {
6103
6233
  x: box.x + left,
@@ -6149,7 +6279,7 @@ function KjunTabs({
6149
6279
  transform: [{ translateX: selection.x }],
6150
6280
  borderRadius: underline ? geometry2.indicatorHeight / 2 : geometry2.radius,
6151
6281
  backgroundColor: variant === "underline" ? colors.brand : colors.active,
6152
- opacity: (selectedTab == null ? void 0 : selectedTab.disabled) ? tokens32.states.opacity.disabled : 1
6282
+ opacity: (selectedTab == null ? void 0 : selectedTab.disabled) ? tokens33.states.opacity.disabled : 1
6153
6283
  }
6154
6284
  }
6155
6285
  ),
@@ -6209,7 +6339,7 @@ function KjunTabs({
6209
6339
  borderRadius: geometry2.radius,
6210
6340
  // Pills answer hover with the hover surface, like ButtonGroup and Web.
6211
6341
  backgroundColor: !underline && !active && !tab.disabled && hoveredTab === tab.name ? colors.hover : void 0,
6212
- opacity: tab.disabled ? tokens32.states.opacity.disabled : 1
6342
+ opacity: tab.disabled ? tokens33.states.opacity.disabled : 1
6213
6343
  },
6214
6344
  children: [
6215
6345
  !!tab.icon && /* @__PURE__ */ jsx36(
@@ -6266,7 +6396,7 @@ function KjunTabs({
6266
6396
  }
6267
6397
  function KjunTabPane({ name, children }) {
6268
6398
  const { value, id, names } = useContext15(TabContext);
6269
- const root = useRef26(null);
6399
+ const root = useRef28(null);
6270
6400
  usePanelFocus(root);
6271
6401
  const hidden = value !== name;
6272
6402
  return /* @__PURE__ */ jsx36(
@@ -6304,7 +6434,7 @@ function KjunAccordion({
6304
6434
  View29,
6305
6435
  {
6306
6436
  style: {
6307
- borderRadius: tokens33.extensions.accordion.radius,
6437
+ borderRadius: tokens34.extensions.accordion.radius,
6308
6438
  overflow: "hidden",
6309
6439
  backgroundColor: tone === "muted" ? colors.secondary : colors.surface
6310
6440
  },
@@ -6319,14 +6449,32 @@ function KjunAccordionItem({
6319
6449
  defaultOpen = false,
6320
6450
  disabled = false,
6321
6451
  header,
6452
+ open: openProp,
6453
+ onOpenChange,
6454
+ keepMounted = false,
6322
6455
  children
6323
6456
  }) {
6324
- const { colors } = useKjunStyles(), group = useContext16(AccordionContext), id = "kjun-" + useId7(), [own, setOwn] = useState27(defaultOpen), open = group ? group.opened.has(id) : own;
6325
- const rotation = useMotionValue(open ? 1 : 0, tokens33.motion.collapse, void 0, void 0, true);
6326
- const geometry2 = tokens33.extensions.accordion;
6457
+ const controlled = openProp !== void 0, context = useContext16(AccordionContext), { colors } = useKjunStyles(), group = controlled ? null : context, id = "kjun-" + useId7(), [own, setOwn] = useState27(defaultOpen), open = controlled ? openProp : group ? group.opened.has(id) : own;
6458
+ const reported = useRef29(open), notify = useRef29(onOpenChange), registering = useRef29(!!group && defaultOpen);
6459
+ notify.current = onOpenChange;
6460
+ useEffect21(() => {
6461
+ var _a;
6462
+ if (registering.current) {
6463
+ if (open) {
6464
+ registering.current = false;
6465
+ reported.current = open;
6466
+ }
6467
+ return;
6468
+ }
6469
+ if (controlled || reported.current === open) return;
6470
+ reported.current = open;
6471
+ (_a = notify.current) == null ? void 0 : _a.call(notify, open);
6472
+ }, [open, controlled]);
6473
+ const rotation = useMotionValue(open ? 1 : 0, tokens34.motion.collapse, void 0, void 0, true);
6474
+ const geometry2 = tokens34.extensions.accordion;
6327
6475
  const [hovered, setHovered] = useState27(false);
6328
6476
  const wrapping = Platform22.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
6329
- useEffect20(() => {
6477
+ useEffect21(() => {
6330
6478
  return group == null ? void 0 : group.register(id, defaultOpen);
6331
6479
  }, []);
6332
6480
  return /* @__PURE__ */ jsxs22(View29, { children: [
@@ -6336,11 +6484,14 @@ function KjunAccordionItem({
6336
6484
  nativeID: id + "-heading",
6337
6485
  accessibilityRole: "button",
6338
6486
  focusRingInset: true,
6339
- focusRingRadius: tokens33.extensions.accordion.radius,
6487
+ focusRingRadius: tokens34.extensions.accordion.radius,
6340
6488
  accessibilityLabel: title,
6341
6489
  accessibilityState: { expanded: open, disabled },
6342
6490
  disabled,
6343
- onPress: () => group ? group.toggle(id) : setOwn(!own),
6491
+ onPress: () => {
6492
+ registering.current = false;
6493
+ controlled ? onOpenChange == null ? void 0 : onOpenChange(!open) : group ? group.toggle(id) : setOwn(!own);
6494
+ },
6344
6495
  onHoverIn: () => setHovered(true),
6345
6496
  onHoverOut: () => setHovered(false),
6346
6497
  style: ({ pressed }) => ({
@@ -6352,7 +6503,7 @@ function KjunAccordionItem({
6352
6503
  paddingVertical: geometry2.headerPaddingY,
6353
6504
  paddingHorizontal: geometry2.paddingX,
6354
6505
  backgroundColor: !disabled && (pressed || hovered) ? colors.hover : void 0,
6355
- opacity: disabled ? tokens33.states.opacity.disabled : 1
6506
+ opacity: disabled ? tokens34.states.opacity.disabled : 1
6356
6507
  }),
6357
6508
  children: [
6358
6509
  /* @__PURE__ */ jsx37(View29, { style: { flex: 1, minWidth: 0 }, children: content(header || title, { ...typeStyle("control"), ...wrapping }) }),
@@ -6360,7 +6511,7 @@ function KjunAccordionItem({
6360
6511
  ]
6361
6512
  }
6362
6513
  ),
6363
- /* @__PURE__ */ jsx37(Collapse, { open, children: /* @__PURE__ */ jsx37(
6514
+ /* @__PURE__ */ jsx37(Collapse, { open, keepMounted, children: /* @__PURE__ */ jsx37(
6364
6515
  View29,
6365
6516
  {
6366
6517
  nativeID: id + "-panel",
@@ -6387,11 +6538,11 @@ function KjunBreadcrumb({
6387
6538
  flexDirection: "row",
6388
6539
  alignItems: "center",
6389
6540
  flexWrap: "wrap",
6390
- gap: tokens33.dimension.value8
6541
+ gap: tokens34.dimension.value8
6391
6542
  },
6392
6543
  children: items2.map((item, i) => {
6393
- const label = /* @__PURE__ */ jsxs22(View29, { style: { flexDirection: "row", alignItems: "center", gap: tokens33.dimension.value4 }, children: [
6394
- !!item.icon && /* @__PURE__ */ jsx37(KjunIcon, { name: item.icon, size: tokens33.extensions.breadcrumb.iconSize, color: colors.textSecondary }),
6544
+ const label = /* @__PURE__ */ jsxs22(View29, { style: { flexDirection: "row", alignItems: "center", gap: tokens34.dimension.value4 }, children: [
6545
+ !!item.icon && /* @__PURE__ */ jsx37(KjunIcon, { name: item.icon, size: tokens34.extensions.breadcrumb.iconSize, color: colors.textSecondary }),
6395
6546
  /* @__PURE__ */ jsx37(
6396
6547
  KText,
6397
6548
  {
@@ -6408,7 +6559,7 @@ function KjunBreadcrumb({
6408
6559
  KjunIcon,
6409
6560
  {
6410
6561
  name: "chevron-right",
6411
- size: tokens33.extensions.breadcrumb.separatorSize,
6562
+ size: tokens34.extensions.breadcrumb.separatorSize,
6412
6563
  color: colors.textTertiary
6413
6564
  }
6414
6565
  ),
@@ -6418,7 +6569,7 @@ function KjunBreadcrumb({
6418
6569
  {
6419
6570
  accessibilityRole: "link",
6420
6571
  onPress: () => onNavigate == null ? void 0 : onNavigate(item),
6421
- style: { minHeight: tokens33.native.minimumTouchTarget, justifyContent: "center" },
6572
+ style: { minHeight: tokens34.native.minimumTouchTarget, justifyContent: "center" },
6422
6573
  children: label
6423
6574
  }
6424
6575
  ) : label
@@ -6447,7 +6598,7 @@ function KjunPagination({
6447
6598
  const m = useKjunMessages();
6448
6599
  const { colors } = useKjunStyles(), window2 = useWindowDimensions5(), current = Math.max(1, Math.min(totalPages, (_a = currentPage != null ? currentPage : page) != null ? _a : 1));
6449
6600
  if (totalPages <= 1 && !showSizeSelector && !(showInfo && totalRows > 0)) return null;
6450
- const compact = window2.width < tokens33.responsive.pagination;
6601
+ const compact = window2.width < tokens34.responsive.pagination;
6451
6602
  const change = (v) => {
6452
6603
  if (v < 1 || v > totalPages || v === current) return;
6453
6604
  onPageChange == null ? void 0 : onPageChange(v);
@@ -6463,12 +6614,12 @@ function KjunPagination({
6463
6614
  ]);
6464
6615
  const pages = [...visible].sort((a, b) => a - b).flatMap((v, i, all) => i && v - all[i - 1] > 1 ? ["...", v] : [v]);
6465
6616
  const pageButtonStyle = {
6466
- width: Math.max(tokens33.extensions.pagination.itemSize, tokens33.native.minimumTouchTarget),
6467
- height: Math.max(tokens33.extensions.pagination.itemSize, tokens33.native.minimumTouchTarget),
6468
- borderRadius: tokens33.extensions.pagination.radius,
6617
+ width: Math.max(tokens34.extensions.pagination.itemSize, tokens34.native.minimumTouchTarget),
6618
+ height: Math.max(tokens34.extensions.pagination.itemSize, tokens34.native.minimumTouchTarget),
6619
+ borderRadius: tokens34.extensions.pagination.radius,
6469
6620
  paddingHorizontal: 0
6470
6621
  };
6471
- const arrowSize = (_b = Object.keys(tokens33.button.iconSizes).find((size) => tokens33.button.iconSizes[size] === tokens33.extensions.pagination.iconSize)) != null ? _b : "sm";
6622
+ const arrowSize = (_b = Object.keys(tokens34.button.iconSizes).find((size) => tokens34.button.iconSizes[size] === tokens34.extensions.pagination.iconSize)) != null ? _b : "sm";
6472
6623
  const button = (target, label, icon) => /* @__PURE__ */ jsx37(
6473
6624
  KjunButton,
6474
6625
  {
@@ -6489,9 +6640,9 @@ function KjunPagination({
6489
6640
  flexDirection: compact ? "column" : "row",
6490
6641
  alignItems: compact ? "stretch" : "center",
6491
6642
  justifyContent: "space-between",
6492
- gap: tokens33.extensions.pagination.gap,
6493
- padding: tokens33.extensions.pagination.padding,
6494
- borderTopWidth: tokens33.border.defaultWidth,
6643
+ gap: tokens34.extensions.pagination.gap,
6644
+ padding: tokens34.extensions.pagination.padding,
6645
+ borderTopWidth: tokens34.border.defaultWidth,
6495
6646
  borderTopColor: colors.border
6496
6647
  },
6497
6648
  children: [
@@ -6502,11 +6653,11 @@ function KjunPagination({
6502
6653
  style: {
6503
6654
  flexDirection: "row",
6504
6655
  alignItems: "center",
6505
- gap: tokens33.extensions.pagination.itemGap,
6656
+ gap: tokens34.extensions.pagination.itemGap,
6506
6657
  flexWrap: "wrap"
6507
6658
  },
6508
6659
  children: [
6509
- showSizeSelector && /* @__PURE__ */ jsx37(View29, { style: { minWidth: tokens33.extensions.pagination.selectorMinimumWidth }, children: /* @__PURE__ */ jsx37(
6660
+ showSizeSelector && /* @__PURE__ */ jsx37(View29, { style: { minWidth: tokens34.extensions.pagination.selectorMinimumWidth }, children: /* @__PURE__ */ jsx37(
6510
6661
  KjunSelect,
6511
6662
  {
6512
6663
  size: "sm",
@@ -6523,10 +6674,10 @@ function KjunPagination({
6523
6674
  }
6524
6675
  }
6525
6676
  ) }),
6526
- totalPages > 1 && /* @__PURE__ */ jsxs22(View29, { style: { flexDirection: "row", alignItems: "center", gap: tokens33.extensions.pagination.itemGap, marginLeft: compact ? "auto" : void 0 }, children: [
6677
+ totalPages > 1 && /* @__PURE__ */ jsxs22(View29, { style: { flexDirection: "row", alignItems: "center", gap: tokens34.extensions.pagination.itemGap, marginLeft: compact ? "auto" : void 0 }, children: [
6527
6678
  !compact && showFirstLast && button(1, m.firstPage, "chevrons-left"),
6528
6679
  button(current - 1, m.previousPage, "chevron-left"),
6529
- compact ? /* @__PURE__ */ jsxs22(KText, { style: { paddingHorizontal: tokens33.extensions.pagination.labelPaddingX, color: colors.text, fontVariant: ["tabular-nums"] }, children: [
6680
+ compact ? /* @__PURE__ */ jsxs22(KText, { style: { paddingHorizontal: tokens34.extensions.pagination.labelPaddingX, color: colors.text, fontVariant: ["tabular-nums"] }, children: [
6530
6681
  /* @__PURE__ */ jsx37(KText, { style: { fontWeight: typeStyle("control").fontWeight }, children: current }),
6531
6682
  " / ",
6532
6683
  totalPages
@@ -6556,8 +6707,8 @@ function KjunPagination({
6556
6707
  }
6557
6708
 
6558
6709
  // packages/native/src/actions.tsx
6559
- import { tokens as tokens34 } from "@kjun-ui/tokens";
6560
- import { useContext as useContext17, useEffect as useEffect21, useRef as useRef27, useState as useState28 } from "react";
6710
+ import { tokens as tokens35 } from "@kjun-ui/tokens";
6711
+ import { useContext as useContext17, useEffect as useEffect22, useRef as useRef30, useState as useState28 } from "react";
6561
6712
  import { Platform as Platform23, ScrollView as ScrollView7, View as View30 } from "react-native";
6562
6713
  import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
6563
6714
  function KjunIconToggle({
@@ -6577,7 +6728,7 @@ function KjunIconToggle({
6577
6728
  }) {
6578
6729
  const { colors } = useKjunStyles();
6579
6730
  const navigation = useContext17(TopNavigationContext);
6580
- const box = navigation ? navigation.controlSize : size === "xs" ? tokens34.extensions.iconToggle.compactSize : tokens34.extensions.iconToggle.sizes[size];
6731
+ const box = navigation ? navigation.controlSize : size === "xs" ? tokens35.extensions.iconToggle.compactSize : tokens35.extensions.iconToggle.sizes[size];
6581
6732
  return /* @__PURE__ */ jsx38(KjunTooltip, { content: disabled || loading ? "" : tooltip != null ? tooltip : ariaLabel, placement: tooltipPlacement, delay: tooltipDelay, children: /* @__PURE__ */ jsx38(
6582
6733
  AccessiblePressable,
6583
6734
  {
@@ -6603,24 +6754,24 @@ function KjunIconToggle({
6603
6754
  ...Platform23.OS === "web" ? { pointerEvents: "auto" } : {},
6604
6755
  // The touch target stays 44pt; the visible square follows the icon-toggle scale.
6605
6756
  alignSelf: "flex-start",
6606
- minWidth: Math.max(tokens34.native.minimumTouchTarget, box),
6607
- minHeight: Math.max(tokens34.native.minimumTouchTarget, box),
6757
+ minWidth: Math.max(tokens35.native.minimumTouchTarget, box),
6758
+ minHeight: Math.max(tokens35.native.minimumTouchTarget, box),
6608
6759
  alignItems: "center",
6609
6760
  justifyContent: "center",
6610
6761
  ...navigation ? { width: navigation.controlSize, height: navigation.controlSize, flexShrink: 0 } : {},
6611
- borderRadius: tokens34.extensions.iconToggle.radii[size],
6762
+ borderRadius: tokens35.extensions.iconToggle.radii[size],
6612
6763
  // Loading blocks presses but stays legible; only disabled dims.
6613
- opacity: disabled ? tokens34.states.opacity.disabled : 1,
6764
+ opacity: disabled ? tokens35.states.opacity.disabled : 1,
6614
6765
  transform: [{ scale: pressed ? 0.94 : 1 }]
6615
6766
  }),
6616
6767
  children: ({ pressed, hovered }) => {
6617
6768
  var _a;
6618
- return /* @__PURE__ */ jsx38(View30, { style: { width: box, height: box, alignItems: "center", justifyContent: "center", borderRadius: tokens34.extensions.iconToggle.radii[size], backgroundColor: !disabled && !loading && (pressed || hovered) ? colors.hover : "transparent" }, children: loading ? navigation ? /* @__PURE__ */ jsx38(KjunIcon, { name: "loader-2", spin: true, size: navigation.iconSize }) : /* @__PURE__ */ jsx38(KjunSpinner, { size: "sm" }) : /* @__PURE__ */ jsx38(
6769
+ return /* @__PURE__ */ jsx38(View30, { style: { width: box, height: box, alignItems: "center", justifyContent: "center", borderRadius: tokens35.extensions.iconToggle.radii[size], backgroundColor: !disabled && !loading && (pressed || hovered) ? colors.hover : "transparent" }, children: loading ? navigation ? /* @__PURE__ */ jsx38(KjunIcon, { name: "loader-2", spin: true, size: navigation.iconSize }) : /* @__PURE__ */ jsx38(KjunSpinner, { size: "sm" }) : /* @__PURE__ */ jsx38(
6619
6770
  KjunIcon,
6620
6771
  {
6621
6772
  name: active ? activeIcon : inactiveIcon || activeIcon,
6622
6773
  filled: active,
6623
- size: (_a = navigation == null ? void 0 : navigation.iconSize) != null ? _a : tokens34.button.iconSizes[size],
6774
+ size: (_a = navigation == null ? void 0 : navigation.iconSize) != null ? _a : tokens35.button.iconSizes[size],
6624
6775
  color: active ? activeColor != null ? activeColor : colors.brand : hovered && !disabled && !loading ? colors.textSecondary : inactiveColor != null ? inactiveColor : colors.textTertiary
6625
6776
  }
6626
6777
  ) });
@@ -6642,8 +6793,8 @@ function KjunCopyButton({
6642
6793
  }) {
6643
6794
  const m = useKjunMessages();
6644
6795
  successText != null ? successText : successText = m.copied;
6645
- const feedback = useOptionalKjunFeedback(), { colors } = useKjunStyles(), [copied, setCopied] = useState28(false), [failed, setFailed] = useState28(false), busy = useRef27(false), timer = useRef27(void 0), mounted = useRef27(true);
6646
- useEffect21(() => {
6796
+ const feedback = useOptionalKjunFeedback(), { colors } = useKjunStyles(), [copied, setCopied] = useState28(false), [failed, setFailed] = useState28(false), busy = useRef30(false), timer = useRef30(void 0), mounted = useRef30(true);
6797
+ useEffect22(() => {
6647
6798
  mounted.current = true;
6648
6799
  return () => {
6649
6800
  mounted.current = false;
@@ -6681,24 +6832,24 @@ function KjunCopyButton({
6681
6832
  },
6682
6833
  style: ({ pressed }) => ({
6683
6834
  alignSelf: "flex-start",
6684
- minWidth: tokens34.native.minimumTouchTarget,
6685
- minHeight: tokens34.native.minimumTouchTarget,
6835
+ minWidth: tokens35.native.minimumTouchTarget,
6836
+ minHeight: tokens35.native.minimumTouchTarget,
6686
6837
  alignItems: "center",
6687
6838
  justifyContent: "center",
6688
6839
  flexDirection: "row",
6689
- gap: tokens34.dimension.value6,
6690
- paddingHorizontal: { xs: tokens34.dimension.value2, sm: tokens34.dimension.value8, md: tokens34.dimension.value12 }[size],
6691
- paddingVertical: { xs: tokens34.dimension.value2, sm: tokens34.dimension.value4, md: tokens34.dimension.value6 }[size],
6692
- borderRadius: tokens34.radius.radius6,
6840
+ gap: tokens35.dimension.value6,
6841
+ paddingHorizontal: { xs: tokens35.dimension.value2, sm: tokens35.dimension.value8, md: tokens35.dimension.value12 }[size],
6842
+ paddingVertical: { xs: tokens35.dimension.value2, sm: tokens35.dimension.value4, md: tokens35.dimension.value6 }[size],
6843
+ borderRadius: tokens35.radius.radius6,
6693
6844
  backgroundColor: pressed && !inline ? colors.hover : void 0,
6694
- opacity: disabled ? tokens34.states.opacity.disabled : 1
6845
+ opacity: disabled ? tokens35.states.opacity.disabled : 1
6695
6846
  }),
6696
6847
  children: [
6697
6848
  /* @__PURE__ */ jsx38(
6698
6849
  KjunIcon,
6699
6850
  {
6700
6851
  name: copied ? "check" : "copy",
6701
- size: tokens34.button.iconSizes[size],
6852
+ size: tokens35.button.iconSizes[size],
6702
6853
  color: copied ? colors.success : colors.textSecondary
6703
6854
  }
6704
6855
  ),
@@ -6773,12 +6924,12 @@ function KjunExternalLink({
6773
6924
  accessibilityRole: "link",
6774
6925
  accessibilityLabel: name ? name + m.newWindow : void 0,
6775
6926
  onPress: () => openUrl(url),
6776
- style: { alignSelf: "flex-start", minHeight: tokens34.native.minimumTouchTarget, justifyContent: "center" },
6927
+ style: { alignSelf: "flex-start", minHeight: tokens35.native.minimumTouchTarget, justifyContent: "center" },
6777
6928
  children: mode === "text" ? (
6778
6929
  // Like Web, text links show the new-window cue after the text.
6779
- /* @__PURE__ */ jsxs23(View30, { style: { flexDirection: "row", alignItems: "center", gap: tokens34.dimension.value4 }, children: [
6930
+ /* @__PURE__ */ jsxs23(View30, { style: { flexDirection: "row", alignItems: "center", gap: tokens35.dimension.value4 }, children: [
6780
6931
  body,
6781
- /* @__PURE__ */ jsx38(KjunIcon, { name: "external-link", size: tokens34.iconSizes.small, color: colors.text })
6932
+ /* @__PURE__ */ jsx38(KjunIcon, { name: "external-link", size: tokens35.iconSizes.small, color: colors.text })
6782
6933
  ] })
6783
6934
  ) : body
6784
6935
  }
@@ -6798,7 +6949,7 @@ function KjunScrollFade({ children }) {
6798
6949
 
6799
6950
  // packages/native/src/data-state.tsx
6800
6951
  import {
6801
- tokens as tokens35,
6952
+ tokens as tokens36,
6802
6953
  advanceQueryDisplay,
6803
6954
  initialQueryDisplay,
6804
6955
  queryDisplayStatus
@@ -6807,10 +6958,10 @@ import { Component, useState as useState30 } from "react";
6807
6958
  import { Platform as Platform24, View as View31 } from "react-native";
6808
6959
 
6809
6960
  // shared/package-runtime/use-loading-reveal.ts
6810
- import { useEffect as useEffect22, useState as useState29 } from "react";
6961
+ import { useEffect as useEffect23, useState as useState29 } from "react";
6811
6962
  function useLoadingReveal(active, delay = 0) {
6812
6963
  const [revealed, setRevealed] = useState29(false);
6813
- useEffect22(() => {
6964
+ useEffect23(() => {
6814
6965
  setRevealed(false);
6815
6966
  if (!active || delay <= 0) return;
6816
6967
  const timer = setTimeout(() => setRevealed(true), delay);
@@ -6861,7 +7012,7 @@ function KjunDataState({
6861
7012
  emptyText != null ? emptyText : emptyText = m.noData;
6862
7013
  loadingText != null ? loadingText : loadingText = m.loadingEllipsis;
6863
7014
  retryText != null ? retryText : retryText = m.retry;
6864
- const state = useQueryDisplay(query), blockingError = query.error && !(state.usesQueryState && state.hasCurrentResult), visibleRefreshError = refreshError || (state.usesQueryState && state.hasCurrentResult ? query.error : null), concealed = state.initialLoading || !!blockingError || empty, padding = tokens35.extensions.state.padding[size], revealed = useLoadingReveal(state.initialLoading, loadingDelay);
7015
+ const state = useQueryDisplay(query), blockingError = query.error && !(state.usesQueryState && state.hasCurrentResult), visibleRefreshError = refreshError || (state.usesQueryState && state.hasCurrentResult ? query.error : null), concealed = state.initialLoading || !!blockingError || empty, padding = tokens36.extensions.state.padding[size], revealed = useLoadingReveal(state.initialLoading, loadingDelay);
6865
7016
  const { colors } = useKjunStyles();
6866
7017
  return /* @__PURE__ */ jsxs24(
6867
7018
  View31,
@@ -6876,13 +7027,13 @@ function KjunDataState({
6876
7027
  style: {
6877
7028
  alignSelf: "flex-end",
6878
7029
  maxWidth: "100%",
6879
- marginBottom: tokens35.dimension.value12,
7030
+ marginBottom: tokens36.dimension.value12,
6880
7031
  flexDirection: "row",
6881
7032
  alignItems: "center",
6882
- gap: tokens35.dimension.value6,
6883
- paddingVertical: tokens35.dimension.value4,
6884
- paddingHorizontal: tokens35.dimension.value8,
6885
- borderRadius: tokens35.radius.radius12,
7033
+ gap: tokens36.dimension.value6,
7034
+ paddingVertical: tokens36.dimension.value4,
7035
+ paddingHorizontal: tokens36.dimension.value8,
7036
+ borderRadius: tokens36.radius.radius12,
6886
7037
  backgroundColor: colors.surface
6887
7038
  },
6888
7039
  children: [
@@ -6898,7 +7049,7 @@ function KjunDataState({
6898
7049
  "aria-hidden": revealed ? void 0 : true,
6899
7050
  importantForAccessibility: revealed ? void 0 : "no-hide-descendants",
6900
7051
  style: { paddingVertical: loadingPadding === "none" ? 0 : padding, opacity: revealed ? void 0 : 0 },
6901
- children: loadingContent || (skeleton ? /* @__PURE__ */ jsx39(View31, { style: { gap: tokens35.dimension.value12 }, children: Array.from({ length: skeletonCount }, (_, i) => /* @__PURE__ */ jsx39(KjunSkeleton, { type: skeletonType }, i)) }) : /* @__PURE__ */ jsxs24(View31, { style: { alignItems: "center", gap: tokens35.dimension.value12 }, children: [
7052
+ children: loadingContent || (skeleton ? /* @__PURE__ */ jsx39(View31, { style: { gap: tokens36.dimension.value12 }, children: Array.from({ length: skeletonCount }, (_, i) => /* @__PURE__ */ jsx39(KjunSkeleton, { type: skeletonType }, i)) }) : /* @__PURE__ */ jsxs24(View31, { style: { alignItems: "center", gap: tokens36.dimension.value12 }, children: [
6902
7053
  /* @__PURE__ */ jsx39(KjunSpinner, { size: "md" }),
6903
7054
  /* @__PURE__ */ jsx39(KText, { style: { ...typeStyle("body"), color: colors.textSecondary, textAlign: "center", maxWidth: "100%" }, children: loadingText })
6904
7055
  ] }))
@@ -6917,12 +7068,12 @@ function KjunDataState({
6917
7068
  right: 0,
6918
7069
  opacity: 0,
6919
7070
  ...Platform24.OS === "web" ? { visibility: "hidden" } : {}
6920
- } : { opacity: query.loading && !state.usesQueryState ? tokens35.states.opacity.pending : 1 },
7071
+ } : { opacity: query.loading && !state.usesQueryState ? tokens36.states.opacity.pending : 1 },
6921
7072
  children: content(children)
6922
7073
  },
6923
7074
  "content"
6924
7075
  ),
6925
- visibleRefreshError && !state.initialLoading && /* @__PURE__ */ jsx39(DataStateContentContext.Provider, { value: "message", children: /* @__PURE__ */ jsx39(View31, { style: { marginTop: tokens35.dimension.value12 }, children: /* @__PURE__ */ jsx39(KjunAlert, { type: "warning", size: "sm", actions: onRetry && /* @__PURE__ */ jsx39(KjunButton, { variant: "secondary", onPress: onRetry, children: retryText }), children: m.refreshError(String(visibleRefreshError)) }) }) })
7076
+ visibleRefreshError && !state.initialLoading && /* @__PURE__ */ jsx39(DataStateContentContext.Provider, { value: "message", children: /* @__PURE__ */ jsx39(View31, { style: { marginTop: tokens36.dimension.value12 }, children: /* @__PURE__ */ jsx39(KjunAlert, { type: "warning", size: "sm", actions: onRetry && /* @__PURE__ */ jsx39(KjunButton, { variant: "secondary", onPress: onRetry, children: retryText }), children: m.refreshError(String(visibleRefreshError)) }) }) })
6926
7077
  ]
6927
7078
  }
6928
7079
  );
@@ -6930,7 +7081,7 @@ function KjunDataState({
6930
7081
  function BoundaryDescription() {
6931
7082
  const m = useKjunMessages();
6932
7083
  const { colors } = useKjunStyles();
6933
- return /* @__PURE__ */ jsx39(KText, { style: { ...typeStyle({ ...tokens35.typography.caption, fontSizePx: tokens35.extensions.state.descriptionSize }), color: colors.textSecondary, textAlign: "center" }, children: m.retryHint });
7084
+ return /* @__PURE__ */ jsx39(KText, { style: { ...typeStyle({ ...tokens36.typography.caption, fontSizePx: tokens36.extensions.state.descriptionSize }), color: colors.textSecondary, textAlign: "center" }, children: m.retryHint });
6934
7085
  }
6935
7086
  var KjunErrorBoundary = class extends Component {
6936
7087
  constructor() {
@@ -6950,13 +7101,13 @@ var KjunErrorBoundary = class extends Component {
6950
7101
  {
6951
7102
  style: {
6952
7103
  alignItems: "center",
6953
- paddingVertical: tokens35.dimension.value64,
6954
- paddingHorizontal: tokens35.dimension.value24,
6955
- gap: tokens35.dimension.value16
7104
+ paddingVertical: tokens36.dimension.value64,
7105
+ paddingHorizontal: tokens36.dimension.value24,
7106
+ gap: tokens36.dimension.value16
6956
7107
  },
6957
7108
  children: [
6958
- /* @__PURE__ */ jsxs24(View31, { style: { gap: tokens35.dimension.value8, alignItems: "center" }, children: [
6959
- /* @__PURE__ */ jsx39(KText, { style: { ...typeStyle({ ...tokens35.typography.sectionTitle, fontSizePx: tokens35.extensions.state.titleSize }), textAlign: "center" }, children: this.props.fallbackMessage || this.context.messages.somethingWentWrong }),
7109
+ /* @__PURE__ */ jsxs24(View31, { style: { gap: tokens36.dimension.value8, alignItems: "center" }, children: [
7110
+ /* @__PURE__ */ jsx39(KText, { style: { ...typeStyle({ ...tokens36.typography.sectionTitle, fontSizePx: tokens36.extensions.state.titleSize }), textAlign: "center" }, children: this.props.fallbackMessage || this.context.messages.somethingWentWrong }),
6960
7111
  /* @__PURE__ */ jsx39(BoundaryDescription, {})
6961
7112
  ] }),
6962
7113
  /* @__PURE__ */ jsx39(
@@ -6979,8 +7130,8 @@ var KjunErrorBoundary = class extends Component {
6979
7130
  KjunErrorBoundary.contextType = KjunMessageContext;
6980
7131
 
6981
7132
  // packages/native/src/skeletons.tsx
6982
- import { tokens as tokens39 } from "@kjun-ui/tokens";
6983
- import { useEffect as useEffect23, useRef as useRef28, useState as useState32 } from "react";
7133
+ import { tokens as tokens40 } from "@kjun-ui/tokens";
7134
+ import { useEffect as useEffect24, useRef as useRef31, useState as useState32 } from "react";
6984
7135
  import { Animated as Animated17, Platform as Platform25, View as View33, useWindowDimensions as useWindowDimensions6 } from "react-native";
6985
7136
  import Svg5, { Path as Path4 } from "react-native-svg";
6986
7137
 
@@ -7003,12 +7154,12 @@ function chartSkeletonKind(kind) {
7003
7154
  }
7004
7155
 
7005
7156
  // packages/native/src/market-skeleton.tsx
7006
- import { tokens as tokens38 } from "@kjun-ui/tokens";
7157
+ import { tokens as tokens39 } from "@kjun-ui/tokens";
7007
7158
  import { ScrollView as ScrollView8, View as View32 } from "react-native";
7008
7159
 
7009
7160
  // shared/package-runtime/market-layout.ts
7010
- import { tokens as tokens36 } from "@kjun-ui/tokens";
7011
- var marketGeometry = tokens36.extensions.marketTable;
7161
+ import { tokens as tokens37 } from "@kjun-ui/tokens";
7162
+ var marketGeometry = tokens37.extensions.marketTable;
7012
7163
  var isMarketIdentity = (key) => ["stock_name", "name", "symbol"].includes(key || "");
7013
7164
  var normalizeMarketColumns = (columns) => columns.map((column) => typeof column === "string" ? { key: column, label: column } : column);
7014
7165
  var defaultWidth = (column) => isMarketIdentity(column.key) ? marketGeometry.identityWidth : marketGeometry.columnWidth;
@@ -7026,33 +7177,33 @@ function nativeMarketLayout(columns, showActions, containerWidth) {
7026
7177
  }
7027
7178
 
7028
7179
  // packages/native/src/market-layout.ts
7029
- import { tokens as tokens37 } from "@kjun-ui/tokens";
7180
+ import { tokens as tokens38 } from "@kjun-ui/tokens";
7030
7181
  import { useState as useState31 } from "react";
7031
7182
  function useMarketLayout(columns, showActions) {
7032
7183
  const [containerWidth, setContainerWidth] = useState31(0);
7033
7184
  const onLayout = (event) => setContainerWidth(event.nativeEvent.layout.width);
7034
7185
  return { ...nativeMarketLayout(columns, showActions, containerWidth), onLayout };
7035
7186
  }
7036
- var marketHeaderStyle = { minHeight: marketGeometry.headerHeight, flexDirection: "row", borderBottomWidth: tokens37.border.defaultWidth };
7037
- var marketRowStyle = { minHeight: marketGeometry.rowHeight, flexDirection: "row", borderBottomWidth: tokens37.border.defaultWidth };
7187
+ var marketHeaderStyle = { minHeight: marketGeometry.headerHeight, flexDirection: "row", borderBottomWidth: tokens38.border.defaultWidth };
7188
+ var marketRowStyle = { minHeight: marketGeometry.rowHeight, flexDirection: "row", borderBottomWidth: tokens38.border.defaultWidth };
7038
7189
 
7039
7190
  // packages/native/src/market-skeleton.tsx
7040
7191
  import { jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
7041
7192
  function KjunMarketTableSkeleton({ columns = [], rows = 8, showActions = false }) {
7042
7193
  const { colors } = useKjunStyles();
7043
7194
  const cols = normalizeMarketColumns(columns), layout = useMarketLayout(cols, showActions);
7044
- const actions = { width: marketGeometry.actionsWidth, paddingVertical: tokens38.dimension.value12, paddingHorizontal: tokens38.dimension.value4, justifyContent: "center", alignItems: "center" };
7195
+ const actions = { width: marketGeometry.actionsWidth, paddingVertical: tokens39.dimension.value12, paddingHorizontal: tokens39.dimension.value4, justifyContent: "center", alignItems: "center" };
7045
7196
  return /* @__PURE__ */ jsx40(ScrollView8, { horizontal: true, onLayout: layout.onLayout, accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: /* @__PURE__ */ jsxs25(View32, { style: { width: layout.width }, children: [
7046
7197
  /* @__PURE__ */ jsxs25(View32, { style: { ...marketHeaderStyle, borderBottomColor: colors.border }, children: [
7047
- showActions && /* @__PURE__ */ jsx40(View32, { style: actions, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: tokens38.extensions.marketTable.actionSkeletonWidth, height: tokens38.extensions.marketTable.headerSkeletonHeight }) }),
7048
- cols.map((col, i) => /* @__PURE__ */ jsx40(View32, { style: { width: layout.widths[i], padding: tokens38.dimension.value12, justifyContent: "center" }, children: /* @__PURE__ */ jsx40(KText, { style: { ...typeStyle("meta"), color: colors.textTertiary, textAlign: col.align }, children: col.label }) }, col.key || i))
7198
+ showActions && /* @__PURE__ */ jsx40(View32, { style: actions, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: tokens39.extensions.marketTable.actionSkeletonWidth, height: tokens39.extensions.marketTable.headerSkeletonHeight }) }),
7199
+ cols.map((col, i) => /* @__PURE__ */ jsx40(View32, { style: { width: layout.widths[i], padding: tokens39.dimension.value12, justifyContent: "center" }, children: /* @__PURE__ */ jsx40(KText, { style: { ...typeStyle("meta"), color: colors.textTertiary, textAlign: col.align }, children: col.label }) }, col.key || i))
7049
7200
  ] }),
7050
7201
  Array.from({ length: Math.max(0, rows) }, (_, row) => /* @__PURE__ */ jsxs25(View32, { style: { ...marketRowStyle, borderBottomColor: colors.border }, children: [
7051
- showActions && /* @__PURE__ */ jsx40(View32, { style: actions, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: tokens38.extensions.marketTable.actionSkeletonWidth, height: tokens38.extensions.financial.priceSkeletonHeight }) }),
7052
- cols.map((col, i) => /* @__PURE__ */ jsx40(View32, { style: { width: layout.widths[i], paddingVertical: tokens38.dimension.value14, paddingHorizontal: tokens38.dimension.value12, justifyContent: "center", alignItems: isMarketIdentity(col.key) ? void 0 : col.align === "right" ? "flex-end" : col.align === "center" ? "center" : "flex-start" }, children: isMarketIdentity(col.key) ? /* @__PURE__ */ jsxs25(View32, { style: { gap: tokens38.dimension.value2 }, children: [
7053
- /* @__PURE__ */ jsx40(View32, { style: { height: tokens38.typography.body.lineHeightPx, justifyContent: "center" }, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: "80%", height: tokens38.extensions.skeleton.lineHeights.md }) }),
7054
- /* @__PURE__ */ jsx40(View32, { style: { height: tokens38.typography.caption.lineHeightPx, justifyContent: "center" }, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: "60%", height: tokens38.extensions.skeleton.lineHeights.sm }) })
7055
- ] }) : /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: tokens38.extensions.financial.priceSkeletonWidth, height: tokens38.extensions.financial.priceSkeletonHeight }) }, col.key || i))
7202
+ showActions && /* @__PURE__ */ jsx40(View32, { style: actions, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: tokens39.extensions.marketTable.actionSkeletonWidth, height: tokens39.extensions.financial.priceSkeletonHeight }) }),
7203
+ cols.map((col, i) => /* @__PURE__ */ jsx40(View32, { style: { width: layout.widths[i], paddingVertical: tokens39.dimension.value14, paddingHorizontal: tokens39.dimension.value12, justifyContent: "center", alignItems: isMarketIdentity(col.key) ? void 0 : col.align === "right" ? "flex-end" : col.align === "center" ? "center" : "flex-start" }, children: isMarketIdentity(col.key) ? /* @__PURE__ */ jsxs25(View32, { style: { gap: tokens39.dimension.value2 }, children: [
7204
+ /* @__PURE__ */ jsx40(View32, { style: { height: tokens39.typography.body.lineHeightPx, justifyContent: "center" }, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: "80%", height: tokens39.extensions.skeleton.lineHeights.md }) }),
7205
+ /* @__PURE__ */ jsx40(View32, { style: { height: tokens39.typography.caption.lineHeightPx, justifyContent: "center" }, children: /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: "60%", height: tokens39.extensions.skeleton.lineHeights.sm }) })
7206
+ ] }) : /* @__PURE__ */ jsx40(KjunSkeleton, { type: "block", width: tokens39.extensions.financial.priceSkeletonWidth, height: tokens39.extensions.financial.priceSkeletonHeight }) }, col.key || i))
7056
7207
  ] }, row))
7057
7208
  ] }) });
7058
7209
  }
@@ -7063,11 +7214,11 @@ function KjunListSkeleton({
7063
7214
  rows = 8,
7064
7215
  variant = "market",
7065
7216
  avatar = true,
7066
- avatarSize = tokens39.extensions.skeleton.listAvatarSize,
7217
+ avatarSize = tokens40.extensions.skeleton.listAvatarSize,
7067
7218
  quote = true
7068
7219
  }) {
7069
7220
  const { colors } = useKjunStyles();
7070
- const market = variant === "market", narrow = useWindowDimensions6().width < tokens39.responsive.market;
7221
+ const market = variant === "market", narrow = useWindowDimensions6().width < tokens40.responsive.market;
7071
7222
  const slots = market ? [typeStyle(narrow ? "input" : "label").lineHeight, typeStyle(narrow ? "body" : "caption").lineHeight] : null;
7072
7223
  const slot = (index, child) => slots ? /* @__PURE__ */ jsx41(View33, { style: { height: slots[index], justifyContent: "center" }, children: child }) : child;
7073
7224
  return /* @__PURE__ */ jsx41(
@@ -7081,29 +7232,29 @@ function KjunListSkeleton({
7081
7232
  style: {
7082
7233
  flexDirection: "row",
7083
7234
  alignItems: "center",
7084
- gap: tokens39.extensions.skeleton.gap,
7085
- minHeight: market ? narrow ? tokens39.extensions.marketList.minimumHeight : void 0 : tokens39.extensions.skeleton.listHeights[variant],
7086
- paddingVertical: market ? narrow ? tokens39.dimension.value14 : tokens39.dimension.value16 : tokens39.extensions.skeleton.list[variant].paddingY,
7087
- paddingHorizontal: market ? narrow ? tokens39.dimension.value20 : tokens39.dimension.value16 : tokens39.extensions.skeleton.list[variant].paddingX,
7088
- borderBottomWidth: tokens39.border.defaultWidth,
7235
+ gap: tokens40.extensions.skeleton.gap,
7236
+ minHeight: market ? narrow ? tokens40.extensions.marketList.minimumHeight : void 0 : tokens40.extensions.skeleton.listHeights[variant],
7237
+ paddingVertical: market ? narrow ? tokens40.dimension.value14 : tokens40.dimension.value16 : tokens40.extensions.skeleton.list[variant].paddingY,
7238
+ paddingHorizontal: market ? narrow ? tokens40.dimension.value20 : tokens40.dimension.value16 : tokens40.extensions.skeleton.list[variant].paddingX,
7239
+ borderBottomWidth: tokens40.border.defaultWidth,
7089
7240
  borderBottomColor: colors.border
7090
7241
  },
7091
7242
  children: [
7092
7243
  avatar && /* @__PURE__ */ jsx41(KjunSkeleton, { type: "avatar", width: avatarSize, height: avatarSize }),
7093
- /* @__PURE__ */ jsxs26(View33, { style: { flex: 1, minWidth: 0, gap: market ? tokens39.dimension.value2 : tokens39.extensions.skeleton.detailGap }, children: [
7244
+ /* @__PURE__ */ jsxs26(View33, { style: { flex: 1, minWidth: 0, gap: market ? tokens40.dimension.value2 : tokens40.extensions.skeleton.detailGap }, children: [
7094
7245
  slot(0, /* @__PURE__ */ jsx41(
7095
7246
  KjunSkeleton,
7096
7247
  {
7097
7248
  type: "block",
7098
- height: tokens39.extensions.skeleton.lineHeights.md,
7249
+ height: tokens40.extensions.skeleton.lineHeights.md,
7099
7250
  width: i % 2 ? "80%" : "65%"
7100
7251
  }
7101
7252
  )),
7102
- slot(1, /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens39.extensions.skeleton.lineHeights.sm, width: "50%" }))
7253
+ slot(1, /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens40.extensions.skeleton.lineHeights.sm, width: "50%" }))
7103
7254
  ] }),
7104
- quote && /* @__PURE__ */ jsxs26(View33, { style: { alignItems: "flex-end", gap: market ? tokens39.dimension.value2 : tokens39.extensions.skeleton.detailGap }, children: [
7105
- slot(0, /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens39.extensions.skeleton.quoteHeight, width: tokens39.extensions.skeleton.quoteWidth })),
7106
- slot(1, /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens39.extensions.skeleton.lineHeights.sm, width: tokens39.extensions.skeleton.detailWidth }))
7255
+ quote && /* @__PURE__ */ jsxs26(View33, { style: { alignItems: "flex-end", gap: market ? tokens40.dimension.value2 : tokens40.extensions.skeleton.detailGap }, children: [
7256
+ slot(0, /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens40.extensions.skeleton.quoteHeight, width: tokens40.extensions.skeleton.quoteWidth })),
7257
+ slot(1, /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens40.extensions.skeleton.lineHeights.sm, width: tokens40.extensions.skeleton.detailWidth }))
7107
7258
  ] })
7108
7259
  ]
7109
7260
  },
@@ -7120,7 +7271,7 @@ function KjunFormSkeleton({
7120
7271
  }) {
7121
7272
  const { colors } = useKjunStyles();
7122
7273
  const window2 = useWindowDimensions6();
7123
- const twoColumns = columns === 2 && window2.width >= tokens39.responsive.formColumns;
7274
+ const twoColumns = columns === 2 && window2.width >= tokens40.responsive.formColumns;
7124
7275
  return /* @__PURE__ */ jsx41(
7125
7276
  View33,
7126
7277
  {
@@ -7129,13 +7280,13 @@ function KjunFormSkeleton({
7129
7280
  style: {
7130
7281
  flexDirection: twoColumns ? "row" : "column",
7131
7282
  flexWrap: twoColumns ? "wrap" : "nowrap",
7132
- gap: tokens39.extensions.skeleton.formGap
7283
+ gap: tokens40.extensions.skeleton.formGap
7133
7284
  },
7134
7285
  children: fields.map((field, i) => /* @__PURE__ */ jsxs26(
7135
7286
  View33,
7136
7287
  {
7137
7288
  style: {
7138
- gap: tokens39.extensions.skeleton.fieldGap,
7289
+ gap: tokens40.extensions.skeleton.fieldGap,
7139
7290
  minWidth: 0,
7140
7291
  flexBasis: twoColumns ? "45%" : void 0,
7141
7292
  flexGrow: 1
@@ -7143,13 +7294,13 @@ function KjunFormSkeleton({
7143
7294
  children: [
7144
7295
  field ? /* @__PURE__ */ jsx41(KText, { style: { color: colors.text, ...typeStyle("label") }, children: typeof field === "string" ? field : field.label }) : (
7145
7296
  // The bar sits in a label-line slot so the field starts where the real input will.
7146
- /* @__PURE__ */ jsx41(View33, { style: { height: typeStyle("label").lineHeight, justifyContent: "center" }, children: /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens39.extensions.skeleton.formLabelHeight, width: tokens39.extensions.skeleton.formLabelWidth }) })
7297
+ /* @__PURE__ */ jsx41(View33, { style: { height: typeStyle("label").lineHeight, justifyContent: "center" }, children: /* @__PURE__ */ jsx41(KjunSkeleton, { type: "block", height: tokens40.extensions.skeleton.formLabelHeight, width: tokens40.extensions.skeleton.formLabelWidth }) })
7147
7298
  ),
7148
- /* @__PURE__ */ jsx41(View33, { style: { borderRadius: tokens39.input[size].radius, overflow: "hidden" }, children: /* @__PURE__ */ jsx41(
7299
+ /* @__PURE__ */ jsx41(View33, { style: { borderRadius: tokens40.input[size].radius, overflow: "hidden" }, children: /* @__PURE__ */ jsx41(
7149
7300
  KjunSkeleton,
7150
7301
  {
7151
7302
  type: "block",
7152
- height: typeof field === "object" && field.height != null ? field.height : multiline ? tokens39.input[size].lineHeight * 3 + tokens39.input[size].textareaPaddingY * 2 + 2 * tokens39.border.controlWidth : tokens39.input[size].height
7303
+ height: typeof field === "object" && field.height != null ? field.height : multiline ? tokens40.input[size].lineHeight * 3 + tokens40.input[size].textareaPaddingY * 2 + 2 * tokens40.border.controlWidth : tokens40.input[size].height
7153
7304
  }
7154
7305
  ) })
7155
7306
  ]
@@ -7162,7 +7313,7 @@ function KjunFormSkeleton({
7162
7313
  var chartPart = (name) => Platform25.OS === "web" ? { dataSet: { kjunChartPart: name } } : {};
7163
7314
  function KjunChartSkeleton({
7164
7315
  kind: requestedKind = "frame",
7165
- height = tokens39.extensions.chartSkeleton.height,
7316
+ height = tokens40.extensions.chartSkeleton.height,
7166
7317
  loadingText,
7167
7318
  skeleton = true,
7168
7319
  loadingDelay = 0,
@@ -7171,13 +7322,13 @@ function KjunChartSkeleton({
7171
7322
  }) {
7172
7323
  const m = useKjunMessages();
7173
7324
  loadingText != null ? loadingText : loadingText = m.chartLoading;
7174
- const kind = chartSkeletonKind(requestedKind), { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef28(new Animated17.Value(1)).current, revealed = useLoadingReveal(true, loadingDelay), [measured, setMeasured] = useState32(0), thickness = tokens39.extensions.chartSkeleton.donutThickness, boxHeight = typeof height === "number" ? height : measured, hole = boxHeight > 0 ? chartDonutHole(boxHeight, thickness) : void 0, rowCount = chartSkeletonCount(rows), columnCount = chartSkeletonCount(columns), status = revealed && loadingText ? "status" : void 0, hidden = { "aria-hidden": true, importantForAccessibility: "no-hide-descendants" };
7175
- useEffect23(() => {
7325
+ const kind = chartSkeletonKind(requestedKind), { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef31(new Animated17.Value(1)).current, revealed = useLoadingReveal(true, loadingDelay), [measured, setMeasured] = useState32(0), thickness = tokens40.extensions.chartSkeleton.donutThickness, boxHeight = typeof height === "number" ? height : measured, hole = boxHeight > 0 ? chartDonutHole(boxHeight, thickness) : void 0, rowCount = chartSkeletonCount(rows), columnCount = chartSkeletonCount(columns), status = revealed && loadingText ? "status" : void 0, hidden = { "aria-hidden": true, importantForAccessibility: "no-hide-descendants" };
7326
+ useEffect24(() => {
7176
7327
  if (reduced || !skeleton) return;
7177
7328
  const loop = Animated17.loop(
7178
7329
  Animated17.sequence([
7179
- Animated17.timing(opacity, { toValue: 0.55, duration: tokens39.motion.shimmer / 2, useNativeDriver: true }),
7180
- Animated17.timing(opacity, { toValue: 1, duration: tokens39.motion.shimmer / 2, useNativeDriver: true })
7330
+ Animated17.timing(opacity, { toValue: 0.55, duration: tokens40.motion.shimmer / 2, useNativeDriver: true }),
7331
+ Animated17.timing(opacity, { toValue: 1, duration: tokens40.motion.shimmer / 2, useNativeDriver: true })
7181
7332
  ])
7182
7333
  );
7183
7334
  loop.start();
@@ -7194,7 +7345,7 @@ function KjunChartSkeleton({
7194
7345
  "aria-hidden": revealed ? void 0 : true,
7195
7346
  importantForAccessibility: revealed ? void 0 : "no-hide-descendants",
7196
7347
  ...Platform25.OS === "web" ? { dataSet: { kjunChartKind: kind, skeleton: skeleton ? void 0 : "false" } } : {},
7197
- children: !skeleton ? /* @__PURE__ */ jsxs26(View33, { ...chartPart("loading"), role: status, style: { alignItems: "center", gap: tokens39.dimension.value12 }, children: [
7348
+ children: !skeleton ? /* @__PURE__ */ jsxs26(View33, { ...chartPart("loading"), role: status, style: { alignItems: "center", gap: tokens40.dimension.value12 }, children: [
7198
7349
  /* @__PURE__ */ jsx41(View33, { ...hidden, children: /* @__PURE__ */ jsx41(KjunSpinner, { size: "md" }) }),
7199
7350
  !!loadingText && /* @__PURE__ */ jsx41(KText, { style: { ...typeStyle("body"), color: colors.textSecondary, textAlign: "center", maxWidth: "100%" }, children: loadingText })
7200
7351
  ] }) : /* @__PURE__ */ jsxs26(Fragment12, { children: [
@@ -7203,21 +7354,21 @@ function KjunChartSkeleton({
7203
7354
  {
7204
7355
  ...chartPart("donut"),
7205
7356
  ...hidden,
7206
- style: { height: `${chartDonutRatio * 100}%`, aspectRatio: 1, borderWidth: thickness, borderColor: colors.skeleton, borderRadius: tokens39.radius.radius9999 }
7357
+ style: { height: `${chartDonutRatio * 100}%`, aspectRatio: 1, borderWidth: thickness, borderColor: colors.skeleton, borderRadius: tokens40.radius.radius9999 }
7207
7358
  }
7208
- ) : kind === "matrix" ? /* @__PURE__ */ jsx41(View33, { ...chartPart("matrix"), ...hidden, style: { alignSelf: "stretch", flex: 1, gap: tokens39.dimension.value4 }, children: Array.from({ length: rowCount }, (_, row) => /* @__PURE__ */ jsx41(View33, { style: { flex: 1, flexDirection: "row", gap: tokens39.dimension.value4 }, children: Array.from({ length: columnCount }, (_2, column) => /* @__PURE__ */ jsx41(
7359
+ ) : kind === "matrix" ? /* @__PURE__ */ jsx41(View33, { ...chartPart("matrix"), ...hidden, style: { alignSelf: "stretch", flex: 1, gap: tokens40.dimension.value4 }, children: Array.from({ length: rowCount }, (_, row) => /* @__PURE__ */ jsx41(View33, { style: { flex: 1, flexDirection: "row", gap: tokens40.dimension.value4 }, children: Array.from({ length: columnCount }, (_2, column) => /* @__PURE__ */ jsx41(
7209
7360
  View33,
7210
7361
  {
7211
7362
  ...chartPart("cell"),
7212
7363
  style: {
7213
7364
  flex: 1,
7214
- borderRadius: tokens39.extensions.skeleton.lineRadius,
7365
+ borderRadius: tokens40.extensions.skeleton.lineRadius,
7215
7366
  backgroundColor: colors.skeleton,
7216
- opacity: chartMatrixMuted(row, column) ? tokens39.states.opacity.pending : 1
7367
+ opacity: chartMatrixMuted(row, column) ? tokens40.states.opacity.pending : 1
7217
7368
  }
7218
7369
  },
7219
7370
  column
7220
- )) }, row)) }) : /* @__PURE__ */ jsx41(View33, { ...chartPart("plot"), ...hidden, style: { alignSelf: "stretch", flex: 1 }, children: /* @__PURE__ */ jsx41(Svg5, { viewBox: chartFrameViewBox, preserveAspectRatio: "none", width: "100%", height: "100%", children: /* @__PURE__ */ jsx41(Path4, { d: chartFramePath, fill: "none", stroke: colors.chartGrid, strokeWidth: tokens39.border.defaultWidth, vectorEffect: "non-scaling-stroke" }) }) }),
7371
+ )) }, row)) }) : /* @__PURE__ */ jsx41(View33, { ...chartPart("plot"), ...hidden, style: { alignSelf: "stretch", flex: 1 }, children: /* @__PURE__ */ jsx41(Svg5, { viewBox: chartFrameViewBox, preserveAspectRatio: "none", width: "100%", height: "100%", children: /* @__PURE__ */ jsx41(Path4, { d: chartFramePath, fill: "none", stroke: colors.chartGrid, strokeWidth: tokens40.border.defaultWidth, vectorEffect: "non-scaling-stroke" }) }) }),
7221
7372
  !!loadingText && /* @__PURE__ */ jsx41(
7222
7373
  View33,
7223
7374
  {
@@ -7231,10 +7382,10 @@ function KjunChartSkeleton({
7231
7382
  {
7232
7383
  style: {
7233
7384
  ...typeStyle("body"),
7234
- paddingHorizontal: tokens39.dimension.value12,
7235
- paddingVertical: tokens39.dimension.value4,
7236
- borderRadius: tokens39.radius.radius6,
7237
- borderWidth: kind === "donut" ? 0 : tokens39.border.defaultWidth,
7385
+ paddingHorizontal: tokens40.dimension.value12,
7386
+ paddingVertical: tokens40.dimension.value4,
7387
+ borderRadius: tokens40.radius.radius6,
7388
+ borderWidth: kind === "donut" ? 0 : tokens40.border.defaultWidth,
7238
7389
  borderColor: colors.chartGrid,
7239
7390
  backgroundColor: colors.surface,
7240
7391
  color: colors.textSecondary,
@@ -7252,7 +7403,7 @@ function KjunChartSkeleton({
7252
7403
  }
7253
7404
 
7254
7405
  // packages/native/src/financial-display.tsx
7255
- import { deviationLevel, tokens as tokens42 } from "@kjun-ui/tokens";
7406
+ import { deviationLevel, tokens as tokens43 } from "@kjun-ui/tokens";
7256
7407
  import { useId as useId8 } from "react";
7257
7408
  import {
7258
7409
  View as View35
@@ -7267,13 +7418,13 @@ import Svg6, {
7267
7418
  } from "react-native-svg";
7268
7419
 
7269
7420
  // packages/native/src/number-display.tsx
7270
- import { tokens as tokens41 } from "@kjun-ui/tokens";
7421
+ import { tokens as tokens42 } from "@kjun-ui/tokens";
7271
7422
 
7272
7423
  // shared/package-runtime/use-number-motion.ts
7273
- import { useLayoutEffect as useLayoutEffect12, useRef as useRef29, useState as useState33 } from "react";
7424
+ import { useLayoutEffect as useLayoutEffect12, useRef as useRef32, useState as useState33 } from "react";
7274
7425
 
7275
7426
  // shared/package-runtime/number-motion.ts
7276
- import { tokens as tokens40 } from "@kjun-ui/tokens";
7427
+ import { tokens as tokens41 } from "@kjun-ui/tokens";
7277
7428
  function createNumberMotion(apply) {
7278
7429
  let frame = 0, revision = 0, current = 0;
7279
7430
  let previous;
@@ -7304,7 +7455,7 @@ function createNumberMotion(apply) {
7304
7455
  if (from === target) return;
7305
7456
  const tick = (now) => {
7306
7457
  if (version !== revision) return;
7307
- const progress = Math.min(1, Math.max(0, (now - started) / tokens40.motion.number));
7458
+ const progress = Math.min(1, Math.max(0, (now - started) / tokens41.motion.number));
7308
7459
  show(progress === 1 ? target : from + (target - from) * (1 - Math.pow(1 - progress, 3)));
7309
7460
  if (progress < 1) frame = requestAnimationFrame(tick);
7310
7461
  };
@@ -7317,7 +7468,7 @@ function createNumberMotion(apply) {
7317
7468
  // shared/package-runtime/use-number-motion.ts
7318
7469
  function useNumberMotion(value, animated, fromPrevious, reduced) {
7319
7470
  const [display, setDisplay] = useState33(typeof value === "string" || fromPrevious || !animated || reduced ? value : 0);
7320
- const motion = useRef29(null);
7471
+ const motion = useRef32(null);
7321
7472
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
7322
7473
  useLayoutEffect12(() => {
7323
7474
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
@@ -7393,7 +7544,7 @@ function KjunFreshness({
7393
7544
  KjunTooltip,
7394
7545
  {
7395
7546
  content: (source === "close" ? scope.messages.noRealtimeQuote : scope.messages.realtimeDelayed) + (fetchedAt ? " \xB7 " + ((formatter == null ? void 0 : formatter(fetchedAt)) || formatRelativeTime(fetchedAt, void 0, scope)) : ""),
7396
- children: /* @__PURE__ */ jsx42(AccessiblePressable, { accessibilityLabel: label, focusRingRadius: tokens41.extensions.badge.radius, children: /* @__PURE__ */ jsx42(KjunBadge, { variant: "warning", size: "xs", children: label }) })
7547
+ children: /* @__PURE__ */ jsx42(AccessiblePressable, { accessibilityLabel: label, focusRingRadius: tokens42.extensions.badge.radius, children: /* @__PURE__ */ jsx42(KjunBadge, { variant: "warning", size: "xs", children: label }) })
7397
7548
  }
7398
7549
  ) : null;
7399
7550
  }
@@ -7407,11 +7558,11 @@ function KjunPriceCell({
7407
7558
  fromPrevious = true
7408
7559
  }) {
7409
7560
  const { colors } = useKjunStyles(), quoteType = useContext18(MarketQuoteTypeContext);
7410
- return value == null ? /* @__PURE__ */ jsx42(KjunSkeleton, { type: "block", height: tokens41.extensions.financial.priceSkeletonHeight, width: tokens41.extensions.financial.priceSkeletonWidth }) : /* @__PURE__ */ jsxs27(View34, { style: { flexDirection: "row", alignItems: "center", gap: tokens41.extensions.financial.affixGap }, children: [
7561
+ return value == null ? /* @__PURE__ */ jsx42(KjunSkeleton, { type: "block", height: tokens42.extensions.financial.priceSkeletonHeight, width: tokens42.extensions.financial.priceSkeletonWidth }) : /* @__PURE__ */ jsxs27(View34, { style: { flexDirection: "row", alignItems: "center", gap: tokens42.extensions.financial.affixGap }, children: [
7411
7562
  /* @__PURE__ */ jsx42(
7412
7563
  View34,
7413
7564
  {
7414
- style: quoteType ? void 0 : { paddingVertical: tokens41.extensions.financial.pillPaddingY, paddingHorizontal: tokens41.extensions.financial.pillPaddingX, borderRadius: tokens41.radius.radius9999 },
7565
+ style: quoteType ? void 0 : { paddingVertical: tokens42.extensions.financial.pillPaddingY, paddingHorizontal: tokens42.extensions.financial.pillPaddingX, borderRadius: tokens42.radius.radius9999 },
7415
7566
  children: /* @__PURE__ */ jsx42(
7416
7567
  KjunAnimatedNumber,
7417
7568
  {
@@ -7450,14 +7601,14 @@ function KjunSignedValue({
7450
7601
  flexDirection: "row",
7451
7602
  alignItems: "center",
7452
7603
  alignSelf: "flex-start",
7453
- gap: tokens41.extensions.financial.affixGap,
7454
- paddingVertical: tone === "pill" ? tokens41.extensions.financial.pillPaddingY : 0,
7455
- paddingHorizontal: tone === "pill" ? tokens41.extensions.financial.pillPaddingX : 0,
7456
- borderRadius: tokens41.extensions.financial.pillRadius,
7604
+ gap: tokens42.extensions.financial.affixGap,
7605
+ paddingVertical: tone === "pill" ? tokens42.extensions.financial.pillPaddingY : 0,
7606
+ paddingHorizontal: tone === "pill" ? tokens42.extensions.financial.pillPaddingX : 0,
7607
+ borderRadius: tokens42.extensions.financial.pillRadius,
7457
7608
  backgroundColor: tone === "pill" && !stale && !loading && n !== null ? domainColor(domainColors, role + "Bg") : void 0
7458
7609
  },
7459
7610
  children: [
7460
- loading ? /* @__PURE__ */ jsx42(KjunSkeleton, { type: "block", width: tokens41.extensions.financial.signedSkeletonWidth, height: tokens41.extensions.financial.signedSkeletonHeight }) : /* @__PURE__ */ jsx42(
7611
+ loading ? /* @__PURE__ */ jsx42(KjunSkeleton, { type: "block", width: tokens42.extensions.financial.signedSkeletonWidth, height: tokens42.extensions.financial.signedSkeletonHeight }) : /* @__PURE__ */ jsx42(
7461
7612
  KText,
7462
7613
  {
7463
7614
  style: {
@@ -7479,7 +7630,7 @@ function KjunSignedValue({
7479
7630
 
7480
7631
  // packages/native/src/financial-display.tsx
7481
7632
  import { Fragment as Fragment13, jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
7482
- var deviationFill = { neutral: 1, low: tokens42.states.opacity.deviationLow, medium: tokens42.states.opacity.deviationMedium, strong: tokens42.states.opacity.deviationStrong };
7633
+ var deviationFill = { neutral: 1, low: tokens43.states.opacity.deviationLow, medium: tokens43.states.opacity.deviationMedium, strong: tokens43.states.opacity.deviationStrong };
7483
7634
  function KjunDeviation({
7484
7635
  value,
7485
7636
  variant = "pill",
@@ -7500,7 +7651,7 @@ function KjunDeviation({
7500
7651
  flexDirection: "row",
7501
7652
  alignItems: "center",
7502
7653
  justifyContent: "flex-end",
7503
- gap: tokens42.extensions.financial.badgeGap
7654
+ gap: tokens43.extensions.financial.badgeGap
7504
7655
  },
7505
7656
  children: [
7506
7657
  /* @__PURE__ */ jsx43(
@@ -7519,22 +7670,22 @@ function KjunDeviation({
7519
7670
  }, children: label })
7520
7671
  }
7521
7672
  ),
7522
- !signal && /* @__PURE__ */ jsx43(View35, { style: { width: tokens42.extensions.financial.warningIconSize, flexShrink: 0 } }),
7673
+ !signal && /* @__PURE__ */ jsx43(View35, { style: { width: tokens43.extensions.financial.warningIconSize, flexShrink: 0 } }),
7523
7674
  signal && /* @__PURE__ */ jsx43(Fragment13, { children: /* @__PURE__ */ jsx43(View35, { style: { alignSelf: "center" }, children: /* @__PURE__ */ jsx43(KjunTooltip, { content: m.deviationWarning(signalThreshold), children: /* @__PURE__ */ jsx43(
7524
7675
  AccessiblePressable,
7525
7676
  {
7526
7677
  accessibilityRole: "image",
7527
7678
  accessibilityLabel: m.arbitrage,
7528
7679
  focusRingInset: true,
7529
- focusRingRadius: tokens42.radius.radius4,
7680
+ focusRingRadius: tokens43.radius.radius4,
7530
7681
  style: {
7531
- width: tokens42.extensions.financial.warningTargetSize,
7532
- height: tokens42.extensions.financial.warningTargetSize,
7533
- margin: (tokens42.extensions.financial.warningIconSize - tokens42.extensions.financial.warningTargetSize) / 2,
7682
+ width: tokens43.extensions.financial.warningTargetSize,
7683
+ height: tokens43.extensions.financial.warningTargetSize,
7684
+ margin: (tokens43.extensions.financial.warningIconSize - tokens43.extensions.financial.warningTargetSize) / 2,
7534
7685
  alignItems: "center",
7535
7686
  justifyContent: "center"
7536
7687
  },
7537
- children: /* @__PURE__ */ jsx43(KjunIcon, { name: "alert-triangle", size: tokens42.extensions.financial.warningIconSize, color: colors.warning })
7688
+ children: /* @__PURE__ */ jsx43(KjunIcon, { name: "alert-triangle", size: tokens43.extensions.financial.warningIconSize, color: colors.warning })
7538
7689
  }
7539
7690
  ) }) }) })
7540
7691
  ]
@@ -7546,9 +7697,9 @@ function KjunDeviation({
7546
7697
  style: {
7547
7698
  alignSelf: "flex-start",
7548
7699
  position: "relative",
7549
- borderRadius: tokens42.extensions.financial.cellRadius,
7550
- paddingVertical: variant === "pill" ? tokens42.extensions.financial.pillPaddingY : 0,
7551
- paddingHorizontal: variant === "pill" ? tokens42.extensions.financial.pillPaddingX : 0
7700
+ borderRadius: tokens43.extensions.financial.cellRadius,
7701
+ paddingVertical: variant === "pill" ? tokens43.extensions.financial.pillPaddingY : 0,
7702
+ paddingHorizontal: variant === "pill" ? tokens43.extensions.financial.pillPaddingX : 0
7552
7703
  },
7553
7704
  children: [
7554
7705
  variant === "pill" && /* @__PURE__ */ jsx43(
@@ -7558,7 +7709,7 @@ function KjunDeviation({
7558
7709
  style: {
7559
7710
  position: "absolute",
7560
7711
  inset: 0,
7561
- borderRadius: tokens42.extensions.financial.cellRadius,
7712
+ borderRadius: tokens43.extensions.financial.cellRadius,
7562
7713
  backgroundColor: neutral ? colors.secondary : color,
7563
7714
  opacity: deviationFill[level]
7564
7715
  }
@@ -7599,9 +7750,9 @@ function KjunHeatmapCell({
7599
7750
  style: {
7600
7751
  position: "relative",
7601
7752
  alignSelf: "flex-start",
7602
- paddingVertical: tokens42.extensions.financial.pillPaddingY,
7603
- paddingHorizontal: tokens42.extensions.financial.pillPaddingX,
7604
- borderRadius: tokens42.extensions.financial.cellRadius
7753
+ paddingVertical: tokens43.extensions.financial.pillPaddingY,
7754
+ paddingHorizontal: tokens43.extensions.financial.pillPaddingX,
7755
+ borderRadius: tokens43.extensions.financial.cellRadius
7605
7756
  },
7606
7757
  children: [
7607
7758
  /* @__PURE__ */ jsx43(
@@ -7611,10 +7762,10 @@ function KjunHeatmapCell({
7611
7762
  style: {
7612
7763
  position: "absolute",
7613
7764
  inset: 0,
7614
- borderRadius: tokens42.extensions.financial.cellRadius,
7765
+ borderRadius: tokens43.extensions.financial.cellRadius,
7615
7766
  // A zero cell keeps its shape on the neutral fill; any other value starts from a visible minimum.
7616
7767
  backgroundColor: magnitude ? background : colors.secondary,
7617
- opacity: magnitude ? tokens42.states.opacity.heatMinimum + (tokens42.states.opacity.heatMaximum - tokens42.states.opacity.heatMinimum) * magnitude : 1
7768
+ opacity: magnitude ? tokens43.states.opacity.heatMinimum + (tokens43.states.opacity.heatMaximum - tokens43.states.opacity.heatMinimum) * magnitude : 1
7618
7769
  }
7619
7770
  }
7620
7771
  ),
@@ -7632,7 +7783,7 @@ function KjunProgressCell({
7632
7783
  showLabel = true,
7633
7784
  color = "auto",
7634
7785
  customColor,
7635
- height = tokens42.extensions.financial.progressHeight
7786
+ height = tokens43.extensions.financial.progressHeight
7636
7787
  }) {
7637
7788
  const { colors, numericFontFamily, fontFamily } = useKjunStyles(), percent = max > 0 && Number.isFinite(value) ? Math.min(100, Math.max(0, value / max * 100)) : 0, role = color === "auto" ? percent < 30 ? "danger" : percent < 70 ? "warning" : "success" : color;
7638
7789
  return /* @__PURE__ */ jsxs28(
@@ -7641,8 +7792,8 @@ function KjunProgressCell({
7641
7792
  style: {
7642
7793
  flexDirection: "row",
7643
7794
  alignItems: "center",
7644
- gap: tokens42.extensions.financial.progressGap,
7645
- minWidth: tokens42.extensions.financial.progressMinimumWidth
7795
+ gap: tokens43.extensions.financial.progressGap,
7796
+ minWidth: tokens43.extensions.financial.progressMinimumWidth
7646
7797
  },
7647
7798
  children: [
7648
7799
  /* @__PURE__ */ jsx43(
@@ -7652,7 +7803,7 @@ function KjunProgressCell({
7652
7803
  height,
7653
7804
  flex: 1,
7654
7805
  backgroundColor: colors.tertiary,
7655
- borderRadius: tokens42.extensions.financial.progressRadius,
7806
+ borderRadius: tokens43.extensions.financial.progressRadius,
7656
7807
  overflow: "hidden"
7657
7808
  },
7658
7809
  children: /* @__PURE__ */ jsx43(
@@ -7661,7 +7812,7 @@ function KjunProgressCell({
7661
7812
  style: {
7662
7813
  width: `${percent}%`,
7663
7814
  height: "100%",
7664
- borderRadius: tokens42.extensions.financial.progressRadius,
7815
+ borderRadius: tokens43.extensions.financial.progressRadius,
7665
7816
  backgroundColor: color === "custom" ? customColor : colors[role]
7666
7817
  }
7667
7818
  }
@@ -7674,7 +7825,7 @@ function KjunProgressCell({
7674
7825
  style: {
7675
7826
  ...typeStyle("caption"),
7676
7827
  color: colors.textSecondary,
7677
- minWidth: tokens42.extensions.financial.progressLabelWidth,
7828
+ minWidth: tokens43.extensions.financial.progressLabelWidth,
7678
7829
  textAlign: "right",
7679
7830
  fontFamily: numericFontFamily || fontFamily,
7680
7831
  fontVariant: ["tabular-nums"]
@@ -7695,7 +7846,7 @@ function KjunCollectionMark({
7695
7846
  size = "md"
7696
7847
  }) {
7697
7848
  const { colors, domainColors } = useKjunStyles();
7698
- const box = tokens42.extensions.financial.markSizes[size], glyph = kind === "interest" ? tokens42.extensions.financial.heartMarkSizes[size] : box;
7849
+ const box = tokens43.extensions.financial.markSizes[size], glyph = kind === "interest" ? tokens43.extensions.financial.heartMarkSizes[size] : box;
7699
7850
  return /* @__PURE__ */ jsx43(View35, { style: { width: box, height: box, alignItems: "center", justifyContent: "center", overflow: "visible" }, children: /* @__PURE__ */ jsx43(
7700
7851
  KjunIcon,
7701
7852
  {
@@ -7727,8 +7878,8 @@ function KjunExecutionStatusBadge({
7727
7878
  }
7728
7879
  function KjunSparkline({
7729
7880
  data = [],
7730
- width = tokens42.extensions.financial.sparklineWidth,
7731
- height = tokens42.extensions.financial.sparklineHeight,
7881
+ width = tokens43.extensions.financial.sparklineWidth,
7882
+ height = tokens43.extensions.financial.sparklineHeight,
7732
7883
  color,
7733
7884
  semantic = "price",
7734
7885
  fill = true,
@@ -7782,7 +7933,7 @@ function KjunSparkline({
7782
7933
 
7783
7934
  // shared/package-runtime/table.ts
7784
7935
  import { nextTableSort } from "@kjun-ui/tokens";
7785
- import { useEffect as useEffect25, useRef as useRef31, useState as useState35 } from "react";
7936
+ import { useEffect as useEffect26, useRef as useRef34, useState as useState35 } from "react";
7786
7937
 
7787
7938
  // shared/package-runtime/table-model.ts
7788
7939
  function getValue(row, key) {
@@ -7829,8 +7980,8 @@ function useTableModel(props) {
7829
7980
  const [internalSort, setSort] = useState35({
7830
7981
  key: "",
7831
7982
  order: "asc"
7832
- }), [internalExpanded, setExpanded] = useState35([]), [search, setSearch] = useState35(""), timer = useRef31(void 0);
7833
- useEffect25(() => () => clearTimeout(timer.current), []);
7983
+ }), [internalExpanded, setExpanded] = useState35([]), [search, setSearch] = useState35(""), timer = useRef34(void 0);
7984
+ useEffect26(() => () => clearTimeout(timer.current), []);
7834
7985
  const sort = props.sort === void 0 ? internalSort : (_a = props.sort) != null ? _a : { key: "", order: "asc" };
7835
7986
  const rows = sortTableRows(data, sort, { sortable, sortMode });
7836
7987
  const key = (row, index = 0) => tableRowKey(row, rowKey, index);
@@ -7919,7 +8070,7 @@ function tableCellValue(props, column, row, index) {
7919
8070
  }
7920
8071
 
7921
8072
  // packages/native/src/table-toolbar.tsx
7922
- import { tokens as tokens43 } from "@kjun-ui/tokens";
8073
+ import { tokens as tokens44 } from "@kjun-ui/tokens";
7923
8074
  import { View as View36 } from "react-native";
7924
8075
  import { Fragment as Fragment14, jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
7925
8076
  function TableToolbar({
@@ -7939,12 +8090,12 @@ function TableToolbar({
7939
8090
  const toolbarStyle = {
7940
8091
  flexDirection: "row",
7941
8092
  alignItems: "center",
7942
- gap: tokens43.dimension.value8,
8093
+ gap: tokens44.dimension.value8,
7943
8094
  flexWrap: "wrap",
7944
- paddingVertical: tokens43.dimension.value8,
7945
- paddingHorizontal: tokens43.dimension.value12,
8095
+ paddingVertical: tokens44.dimension.value8,
8096
+ paddingHorizontal: tokens44.dimension.value12,
7946
8097
  backgroundColor: colors.secondary,
7947
- borderBottomWidth: tokens43.border.defaultWidth,
8098
+ borderBottomWidth: tokens44.border.defaultWidth,
7948
8099
  borderBottomColor: colors.border
7949
8100
  };
7950
8101
  return /* @__PURE__ */ jsxs29(Fragment14, { children: [
@@ -7972,7 +8123,7 @@ function TableToolbar({
7972
8123
  ),
7973
8124
  (searchable || toolbar) && // Like Web: the search toolbar sits on the surface so the filled search field stands out from it.
7974
8125
  /* @__PURE__ */ jsxs29(View36, { style: { ...toolbarStyle, backgroundColor: colors.surface }, children: [
7975
- searchable && /* @__PURE__ */ jsx44(View36, { style: { width: tokens43.table.searchWidth, maxWidth: "100%" }, children: /* @__PURE__ */ jsx44(
8126
+ searchable && /* @__PURE__ */ jsx44(View36, { style: { width: tokens44.table.searchWidth, maxWidth: "100%" }, children: /* @__PURE__ */ jsx44(
7976
8127
  KjunInput,
7977
8128
  {
7978
8129
  size: "sm",
@@ -7990,7 +8141,7 @@ function TableToolbar({
7990
8141
  }
7991
8142
 
7992
8143
  // packages/native/src/table-grid.tsx
7993
- import { tokens as tokens44 } from "@kjun-ui/tokens";
8144
+ import { tokens as tokens45 } from "@kjun-ui/tokens";
7994
8145
  import { Fragment as Fragment15, useId as useId9, useState as useState36 } from "react";
7995
8146
  import Svg7, { Defs as Defs3, LinearGradient as LinearGradient3, Rect as Rect3, Stop as Stop3 } from "react-native-svg";
7996
8147
  import { ScrollView as ScrollView9, View as View37 } from "react-native";
@@ -7998,7 +8149,7 @@ import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
7998
8149
  function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }) {
7999
8150
  const m = useKjunMessages();
8000
8151
  const { colors } = useKjunStyles();
8001
- const geometry2 = tokens44.table;
8152
+ const geometry2 = tokens45.table;
8002
8153
  const [scroll, setScroll] = useState36({ viewport: 0, x: 0 }), fadeId = "kjun-table-fade-" + useId9().replace(/[^a-z0-9]/gi, "");
8003
8154
  const cellPadding = geometry2.cellPadding[compact ? "compact" : "regular"];
8004
8155
  const width = (col) => typeof col.width === "number" ? col.width : typeof col.width === "string" && /^\d+(px)?$/.test(col.width) ? parseFloat(col.width) : geometry2.columnWidth;
@@ -8031,7 +8182,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8031
8182
  style: {
8032
8183
  flexDirection: "row",
8033
8184
  backgroundColor: colors.tableHeaderBg,
8034
- borderBottomWidth: tokens44.border.defaultWidth,
8185
+ borderBottomWidth: tokens45.border.defaultWidth,
8035
8186
  borderBottomColor: colors.border
8036
8187
  },
8037
8188
  children: [
@@ -8055,13 +8206,13 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8055
8206
  onPress: () => state.sortColumn(col),
8056
8207
  style: {
8057
8208
  width: width(col),
8058
- minHeight: tokens44.native.minimumTouchTarget,
8209
+ minHeight: tokens45.native.minimumTouchTarget,
8059
8210
  paddingVertical: geometry2.headerPadding.y,
8060
8211
  paddingHorizontal: geometry2.headerPadding.x,
8061
8212
  flexDirection: "row",
8062
8213
  alignItems: "center",
8063
8214
  justifyContent: col.align === "right" ? "flex-end" : col.align === "center" ? "center" : "flex-start",
8064
- gap: tokens44.dimension.value4
8215
+ gap: tokens45.dimension.value4
8065
8216
  },
8066
8217
  children: [
8067
8218
  /* @__PURE__ */ jsx45(
@@ -8078,7 +8229,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8078
8229
  KjunIcon,
8079
8230
  {
8080
8231
  name: state.sort.order === "asc" ? "sort-ascending" : "sort-descending",
8081
- size: tokens44.table.sortIconSize,
8232
+ size: tokens45.table.sortIconSize,
8082
8233
  color: colors.text
8083
8234
  }
8084
8235
  )
@@ -8105,7 +8256,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8105
8256
  {
8106
8257
  type: "block",
8107
8258
  height: geometry2.skeletonHeight,
8108
- width: col.key === "actions" ? tokens44.table.actionColumnWidth : "75%"
8259
+ width: col.key === "actions" ? tokens45.table.actionColumnWidth : "75%"
8109
8260
  }
8110
8261
  )
8111
8262
  },
@@ -8121,7 +8272,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8121
8272
  onPress: () => onRowClick == null ? void 0 : onRowClick(row, i),
8122
8273
  style: ({ pressed }) => ({
8123
8274
  flexDirection: "row",
8124
- borderBottomWidth: tokens44.border.defaultWidth,
8275
+ borderBottomWidth: tokens45.border.defaultWidth,
8125
8276
  borderBottomColor: colors.border,
8126
8277
  backgroundColor: pressed && hoverable ? colors.tableRowHover : striped && i % 2 ? colors.secondary : void 0
8127
8278
  }),
@@ -8181,7 +8332,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8181
8332
  )
8182
8333
  }
8183
8334
  ),
8184
- fade && /* @__PURE__ */ jsx45(View37, { pointerEvents: "none", style: { position: "absolute", top: 0, right: 0, bottom: 0, width: tokens44.extensions.scrollFade.width }, children: /* @__PURE__ */ jsxs30(Svg7, { width: "100%", height: "100%", children: [
8335
+ fade && /* @__PURE__ */ jsx45(View37, { pointerEvents: "none", style: { position: "absolute", top: 0, right: 0, bottom: 0, width: tokens45.extensions.scrollFade.width }, children: /* @__PURE__ */ jsxs30(Svg7, { width: "100%", height: "100%", children: [
8185
8336
  /* @__PURE__ */ jsx45(Defs3, { children: /* @__PURE__ */ jsxs30(LinearGradient3, { id: fadeId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
8186
8337
  /* @__PURE__ */ jsx45(Stop3, { offset: "0", stopColor: colors.surface, stopOpacity: 0 }),
8187
8338
  /* @__PURE__ */ jsx45(Stop3, { offset: "1", stopColor: colors.surface, stopOpacity: 1 })
@@ -8192,14 +8343,14 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8192
8343
  }
8193
8344
 
8194
8345
  // packages/native/src/table-view.tsx
8195
- import { tokens as tokens46 } from "@kjun-ui/tokens";
8346
+ import { tokens as tokens47 } from "@kjun-ui/tokens";
8196
8347
  import {
8197
8348
  View as View39,
8198
8349
  useWindowDimensions as useWindowDimensions7
8199
8350
  } from "react-native";
8200
8351
 
8201
8352
  // packages/native/src/table-cards.tsx
8202
- import { tokens as tokens45 } from "@kjun-ui/tokens";
8353
+ import { tokens as tokens46 } from "@kjun-ui/tokens";
8203
8354
  import {
8204
8355
  View as View38
8205
8356
  } from "react-native";
@@ -8225,7 +8376,7 @@ function TableCards({
8225
8376
  return /* @__PURE__ */ jsxs31(
8226
8377
  View38,
8227
8378
  {
8228
- style: { gap: tokens45.extensions.tableCard.gap, padding: tokens45.extensions.tableCard.listPadding, opacity: skeletonHidden ? 0 : void 0 },
8379
+ style: { gap: tokens46.extensions.tableCard.gap, padding: tokens46.extensions.tableCard.listPadding, opacity: skeletonHidden ? 0 : void 0 },
8229
8380
  "aria-hidden": skeletonHidden || void 0,
8230
8381
  children: [
8231
8382
  initialLoading ? Array.from({ length: skeletonRows }, (_, i) => /* @__PURE__ */ jsx46(KjunSkeleton, { type: "card" }, i)) : state.rows.map((row, i) => /* @__PURE__ */ jsxs31(
@@ -8234,10 +8385,10 @@ function TableCards({
8234
8385
  accessible: false,
8235
8386
  onPress: () => onRowClick == null ? void 0 : onRowClick(row, i),
8236
8387
  style: ({ pressed }) => ({
8237
- padding: tokens45.extensions.tableCard.padding,
8238
- borderWidth: tokens45.border.defaultWidth,
8388
+ padding: tokens46.extensions.tableCard.padding,
8389
+ borderWidth: tokens46.border.defaultWidth,
8239
8390
  borderColor: colors.border,
8240
- borderRadius: tokens45.extensions.tableCard.radius,
8391
+ borderRadius: tokens46.extensions.tableCard.radius,
8241
8392
  backgroundColor: pressed ? colors.hover : colors.background
8242
8393
  }),
8243
8394
  children: [
@@ -8247,8 +8398,8 @@ function TableCards({
8247
8398
  style: {
8248
8399
  flexDirection: "row",
8249
8400
  alignItems: "center",
8250
- gap: tokens45.extensions.tableCard.gap,
8251
- marginBottom: tokens45.dimension.value8
8401
+ gap: tokens46.extensions.tableCard.gap,
8402
+ marginBottom: tokens46.dimension.value8
8252
8403
  },
8253
8404
  children: [
8254
8405
  /* @__PURE__ */ jsxs31(
@@ -8258,7 +8409,7 @@ function TableCards({
8258
8409
  flexDirection: "row",
8259
8410
  flex: 1,
8260
8411
  alignItems: "center",
8261
- gap: tokens45.extensions.tableCard.gap,
8412
+ gap: tokens46.extensions.tableCard.gap,
8262
8413
  minWidth: 0
8263
8414
  },
8264
8415
  children: [
@@ -8267,8 +8418,8 @@ function TableCards({
8267
8418
  ]
8268
8419
  }
8269
8420
  ),
8270
- badges.length ? /* @__PURE__ */ jsx46(View38, { style: { flexDirection: "row", gap: tokens45.extensions.tableCard.fieldGap }, children: badges.map((col) => /* @__PURE__ */ jsx46(View38, { children: cell(col, row, i) }, col.key)) }) : subtitle ? cell(subtitle, row, i) : null,
8271
- inline.length > 0 && /* @__PURE__ */ jsx46(View38, { style: { flexDirection: "row", gap: tokens45.extensions.tableCard.fieldGap }, children: inline.map((col) => /* @__PURE__ */ jsx46(View38, { children: cell(col, row, i) }, col.key)) })
8421
+ badges.length ? /* @__PURE__ */ jsx46(View38, { style: { flexDirection: "row", gap: tokens46.extensions.tableCard.fieldGap }, children: badges.map((col) => /* @__PURE__ */ jsx46(View38, { children: cell(col, row, i) }, col.key)) }) : subtitle ? cell(subtitle, row, i) : null,
8422
+ inline.length > 0 && /* @__PURE__ */ jsx46(View38, { style: { flexDirection: "row", gap: tokens46.extensions.tableCard.fieldGap }, children: inline.map((col) => /* @__PURE__ */ jsx46(View38, { children: cell(col, row, i) }, col.key)) })
8272
8423
  ]
8273
8424
  }
8274
8425
  ),
@@ -8278,10 +8429,10 @@ function TableCards({
8278
8429
  View38,
8279
8430
  {
8280
8431
  style: {
8281
- borderTopWidth: index ? tokens45.border.defaultWidth : 0,
8432
+ borderTopWidth: index ? tokens46.border.defaultWidth : 0,
8282
8433
  borderTopColor: colors.border,
8283
- paddingTop: index ? tokens45.dimension.value12 : 0,
8284
- marginTop: index ? tokens45.dimension.value12 : 0
8434
+ paddingTop: index ? tokens46.dimension.value12 : 0,
8435
+ marginTop: index ? tokens46.dimension.value12 : 0
8285
8436
  },
8286
8437
  children: [
8287
8438
  !!section.label && /* @__PURE__ */ jsx46(
@@ -8290,7 +8441,7 @@ function TableCards({
8290
8441
  style: {
8291
8442
  ...typeStyle("controlSmall"),
8292
8443
  color: colors.textTertiary,
8293
- marginBottom: tokens45.dimension.value6
8444
+ marginBottom: tokens46.dimension.value6
8294
8445
  },
8295
8446
  children: section.label
8296
8447
  }
@@ -8301,7 +8452,7 @@ function TableCards({
8301
8452
  style: {
8302
8453
  flexDirection: "row",
8303
8454
  flexWrap: "wrap",
8304
- gap: section.layout === "metrics" ? tokens45.extensions.tableCard.gap : tokens45.extensions.tableCard.metricGap
8455
+ gap: section.layout === "metrics" ? tokens46.extensions.tableCard.gap : tokens46.extensions.tableCard.metricGap
8305
8456
  },
8306
8457
  children: cols.map((col) => /* @__PURE__ */ jsxs31(
8307
8458
  View38,
@@ -8310,7 +8461,7 @@ function TableCards({
8310
8461
  flexBasis: col.fullWidthInCard || section.layout === "stack" ? "100%" : section.layout === "metrics" ? "30%" : "47%",
8311
8462
  flexGrow: 1,
8312
8463
  minWidth: 0,
8313
- gap: tokens45.extensions.tableCard.valueGap
8464
+ gap: tokens46.extensions.tableCard.valueGap
8314
8465
  },
8315
8466
  children: [
8316
8467
  /* @__PURE__ */ jsx46(
@@ -8341,10 +8492,10 @@ function TableCards({
8341
8492
  View38,
8342
8493
  {
8343
8494
  style: {
8344
- borderTopWidth: tokens45.border.defaultWidth,
8495
+ borderTopWidth: tokens46.border.defaultWidth,
8345
8496
  borderTopColor: colors.border,
8346
- paddingTop: tokens45.dimension.value8,
8347
- marginTop: tokens45.dimension.value4
8497
+ paddingTop: tokens46.dimension.value8,
8498
+ marginTop: tokens46.dimension.value4
8348
8499
  },
8349
8500
  children: content(renderExpand == null ? void 0 : renderExpand(row, i))
8350
8501
  }
@@ -8353,10 +8504,10 @@ function TableCards({
8353
8504
  View38,
8354
8505
  {
8355
8506
  style: {
8356
- borderTopWidth: tokens45.border.defaultWidth,
8507
+ borderTopWidth: tokens46.border.defaultWidth,
8357
8508
  borderTopColor: colors.border,
8358
- paddingTop: tokens45.dimension.value8,
8359
- marginTop: tokens45.dimension.value8,
8509
+ paddingTop: tokens46.dimension.value8,
8510
+ marginTop: tokens46.dimension.value8,
8360
8511
  alignItems: "flex-end"
8361
8512
  },
8362
8513
  children: /* @__PURE__ */ jsx46(View38, { style: { alignSelf: "flex-end" }, children: cell(actions, row, i) })
@@ -8366,7 +8517,7 @@ function TableCards({
8366
8517
  },
8367
8518
  state.key(row, i)
8368
8519
  )),
8369
- !initialLoading && !state.rows.length && /* @__PURE__ */ jsx46(View38, { style: { padding: tokens45.extensions.tableCard.emptyPadding, alignItems: "center" }, children: content(emptyContent || emptyText, {
8520
+ !initialLoading && !state.rows.length && /* @__PURE__ */ jsx46(View38, { style: { padding: tokens46.extensions.tableCard.emptyPadding, alignItems: "center" }, children: content(emptyContent || emptyText, {
8370
8521
  color: colors.textTertiary
8371
8522
  }) })
8372
8523
  ]
@@ -8403,7 +8554,7 @@ function KjunTable(props) {
8403
8554
  onRowClick,
8404
8555
  onRetry
8405
8556
  } = props;
8406
- const { colors, domainColors } = useKjunStyles(), state = useTableModel2(props), query = useQueryDisplay(props), revealed = useLoadingReveal(query.initialLoading, skeleton ? loadingDelay : 0), mobile = useWindowDimensions7().width < tokens46.table.mobileBreakpoint;
8557
+ const { colors, domainColors } = useKjunStyles(), state = useTableModel2(props), query = useQueryDisplay(props), revealed = useLoadingReveal(query.initialLoading, skeleton ? loadingDelay : 0), mobile = useWindowDimensions7().width < tokens47.table.mobileBreakpoint;
8407
8558
  const layout = tablePresentation(props, mobile);
8408
8559
  const { card, visible } = layout;
8409
8560
  const cell = (col, row, index, role) => {
@@ -8415,9 +8566,9 @@ function KjunTable(props) {
8415
8566
  {
8416
8567
  style: {
8417
8568
  alignSelf: "flex-start",
8418
- paddingVertical: tokens46.dimension.value2,
8419
- paddingHorizontal: tokens46.dimension.value8,
8420
- borderRadius: tokens46.radius.radius4,
8569
+ paddingVertical: tokens47.dimension.value2,
8570
+ paddingHorizontal: tokens47.dimension.value8,
8571
+ borderRadius: tokens47.radius.radius4,
8421
8572
  backgroundColor: role2 ? domainColor(domainColors, role2 + "Bg") : void 0
8422
8573
  },
8423
8574
  children: content(body, {
@@ -8520,7 +8671,7 @@ function KpiNumberLine({ prefix, suffix, prefixGap, suffixGap, style, unitStyle,
8520
8671
  }
8521
8672
 
8522
8673
  // packages/native/src/kpi-hero.tsx
8523
- import { tokens as tokens47 } from "@kjun-ui/tokens";
8674
+ import { tokens as tokens48 } from "@kjun-ui/tokens";
8524
8675
  import {
8525
8676
  View as View41,
8526
8677
  useWindowDimensions as useWindowDimensions8
@@ -8553,8 +8704,8 @@ function KjunKpiHero(props) {
8553
8704
  deltaFormatter,
8554
8705
  renderSecondary
8555
8706
  } = props;
8556
- const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), windowWidth = useWindowDimensions8().width, mobile = windowWidth <= tokens47.responsive.kpiHero, small = size === "sm", numberRole = small ? "displaySm" : mobile ? "displayMd" : "displayLg", font = typeStyle(numberRole).fontSize, unitStyle = typeStyle(small ? "numberSm" : mobile ? "numberMd" : "numberLg");
8557
- const geometry2 = tokens47.extensions.kpiHero;
8707
+ const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), windowWidth = useWindowDimensions8().width, mobile = windowWidth <= tokens48.responsive.kpiHero, small = size === "sm", numberRole = small ? "displaySm" : mobile ? "displayMd" : "displayLg", font = typeStyle(numberRole).fontSize, unitStyle = typeStyle(small ? "numberSm" : mobile ? "numberMd" : "numberLg");
8708
+ const geometry2 = tokens48.extensions.kpiHero;
8558
8709
  const spec = small ? geometry2.sm : mobile ? geometry2.mobile : geometry2.md;
8559
8710
  const numeric2 = {
8560
8711
  fontFamily: numericFontFamily || fontFamily,
@@ -8566,7 +8717,7 @@ function KjunKpiHero(props) {
8566
8717
  );
8567
8718
  const delta = (v, kind, style) => {
8568
8719
  if (deltaFormatter) return /* @__PURE__ */ jsx49(KText, { style, children: deltaFormatter(v, kind) });
8569
- const sign = v > 0 ? "+" : v < 0 ? "\u2212" : "", gap = tokens47.extensions.financial.affixGap, number = new Intl.NumberFormat(void 0, {
8720
+ const sign = v > 0 ? "+" : v < 0 ? "\u2212" : "", gap = tokens48.extensions.financial.affixGap, number = new Intl.NumberFormat(void 0, {
8570
8721
  minimumFractionDigits: kind === "absolute" ? decimals : 1,
8571
8722
  maximumFractionDigits: kind === "absolute" ? decimals : 1
8572
8723
  }).format(Math.abs(v));
@@ -8669,11 +8820,11 @@ function KjunKpiHero(props) {
8669
8820
  gap: small && mobile ? geometry2.smallMobileGap : spec.secondaryGap,
8670
8821
  marginTop: spec.secondaryMargin,
8671
8822
  paddingTop: spec.secondaryPadding,
8672
- borderTopWidth: tokens47.border.defaultWidth,
8823
+ borderTopWidth: tokens48.border.defaultWidth,
8673
8824
  borderTopColor: colors.border
8674
8825
  },
8675
8826
  children: secondary.map((item, i) => {
8676
- const columns = mobile && !small && windowWidth <= tokens47.responsive.kpiHeroSecondary && secondary.length >= 3 ? 2 : 0;
8827
+ const columns = mobile && !small && windowWidth <= tokens48.responsive.kpiHeroSecondary && secondary.length >= 3 ? 2 : 0;
8677
8828
  const first = columns ? i % columns === 0 : i === 0;
8678
8829
  const last = columns ? i % columns === columns - 1 || i === secondary.length - 1 : i === secondary.length - 1;
8679
8830
  return /* @__PURE__ */ jsxs34(
@@ -8684,7 +8835,7 @@ function KjunKpiHero(props) {
8684
8835
  minWidth: 0,
8685
8836
  paddingLeft: first ? 0 : geometry2.itemPadding,
8686
8837
  paddingRight: last ? 0 : geometry2.itemPadding,
8687
- borderLeftWidth: first ? 0 : tokens47.border.defaultWidth,
8838
+ borderLeftWidth: first ? 0 : tokens48.border.defaultWidth,
8688
8839
  borderLeftColor: colors.border
8689
8840
  } : { minWidth: 0, maxWidth: "100%", flexShrink: 1 },
8690
8841
  children: [
@@ -8749,7 +8900,7 @@ function KjunKpiHero(props) {
8749
8900
  }
8750
8901
 
8751
8902
  // packages/native/src/kpi-row.tsx
8752
- import { tokens as tokens48 } from "@kjun-ui/tokens";
8903
+ import { tokens as tokens49 } from "@kjun-ui/tokens";
8753
8904
  import { useState as useState37 } from "react";
8754
8905
  import {
8755
8906
  View as View42,
@@ -8765,8 +8916,8 @@ function KjunKpiRow({
8765
8916
  onItemClick,
8766
8917
  renderValue
8767
8918
  }) {
8768
- const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), mobile = useWindowDimensions9().width <= tokens48.responsive.kpiRow, small = size === "sm", summary = mobileSummary && mobile && !small;
8769
- const geometry2 = tokens48.extensions.kpiRow;
8919
+ const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), mobile = useWindowDimensions9().width <= tokens49.responsive.kpiRow, small = size === "sm", summary = mobileSummary && mobile && !small;
8920
+ const geometry2 = tokens49.extensions.kpiRow;
8770
8921
  const spec = small ? geometry2.sm : mobile ? geometry2.mobile : geometry2.md;
8771
8922
  const [width, setWidth] = useState37(0);
8772
8923
  const paddingX = summary ? geometry2.summary.paddingX : spec.paddingX;
@@ -8845,8 +8996,8 @@ function KjunKpiRow({
8845
8996
  minWidth: 0,
8846
8997
  paddingVertical: summary ? 0 : small && mobile ? geometry2.smallMobile.itemPaddingY : spec.itemPaddingY,
8847
8998
  paddingHorizontal: summary ? 0 : small && mobile ? geometry2.smallMobile.itemPaddingX : spec.itemPaddingX,
8848
- borderLeftWidth: summary ? 0 : mobile && !small ? i % 2 && !full ? tokens48.border.defaultWidth : 0 : i ? tokens48.border.defaultWidth : 0,
8849
- borderTopWidth: mobile && !small && !summary && i >= 2 ? tokens48.border.defaultWidth : 0,
8999
+ borderLeftWidth: summary ? 0 : mobile && !small ? i % 2 && !full ? tokens49.border.defaultWidth : 0 : i ? tokens49.border.defaultWidth : 0,
9000
+ borderTopWidth: mobile && !small && !summary && i >= 2 ? tokens49.border.defaultWidth : 0,
8850
9001
  borderColor: colors.border,
8851
9002
  borderRadius: item.clickable ? geometry2.itemRadius : 0,
8852
9003
  flexDirection: sub ? "row" : "column",
@@ -8889,7 +9040,7 @@ function KjunKpiRow({
8889
9040
  summary && seg.label && /* @__PURE__ */ jsx50(
8890
9041
  KText,
8891
9042
  {
8892
- style: { ...typeStyle("caption"), marginRight: sub ? tokens48.dimension.value4 : 0, color: colors.textTertiary },
9043
+ style: { ...typeStyle("caption"), marginRight: sub ? tokens49.dimension.value4 : 0, color: colors.textTertiary },
8893
9044
  children: seg.label
8894
9045
  }
8895
9046
  ),
@@ -8983,11 +9134,11 @@ function KjunKpiRow({
8983
9134
  }
8984
9135
 
8985
9136
  // packages/native/src/market-cards.tsx
8986
- import { tokens as tokens50 } from "@kjun-ui/tokens";
9137
+ import { tokens as tokens51 } from "@kjun-ui/tokens";
8987
9138
  import { ScrollView as ScrollView10, View as View44 } from "react-native";
8988
9139
 
8989
9140
  // shared/package-runtime/market-cards.ts
8990
- import { useEffect as useEffect26, useRef as useRef32, useState as useState38 } from "react";
9141
+ import { useEffect as useEffect27, useRef as useRef35, useState as useState38 } from "react";
8991
9142
  function useMarketCardsModel(props, persistence) {
8992
9143
  const {
8993
9144
  columns,
@@ -9004,7 +9155,7 @@ function useMarketCardsModel(props, persistence) {
9004
9155
  isDefaultSort: c.defaultSort
9005
9156
  }));
9006
9157
  const [key, setKey] = useState38(""), restoreSignature = JSON.stringify([storageNamespace, pills]);
9007
- const mounted = useRef32("");
9158
+ const mounted = useRef35("");
9008
9159
  const save = (key2) => {
9009
9160
  var _a;
9010
9161
  try {
@@ -9012,7 +9163,7 @@ function useMarketCardsModel(props, persistence) {
9012
9163
  } catch (e) {
9013
9164
  }
9014
9165
  };
9015
- useEffect26(() => {
9166
+ useEffect27(() => {
9016
9167
  var _a, _b;
9017
9168
  if (mounted.current === restoreSignature) return;
9018
9169
  mounted.current = restoreSignature;
@@ -9049,7 +9200,7 @@ function useMarketCards(props) {
9049
9200
  }
9050
9201
 
9051
9202
  // packages/native/src/market-parts.tsx
9052
- import { tokens as tokens49 } from "@kjun-ui/tokens";
9203
+ import { tokens as tokens50 } from "@kjun-ui/tokens";
9053
9204
  import { View as View43, useWindowDimensions as useWindowDimensions10 } from "react-native";
9054
9205
  import { Fragment as Fragment17, jsx as jsx51, jsxs as jsxs36 } from "react/jsx-runtime";
9055
9206
  function MarketIdentity({
@@ -9059,7 +9210,7 @@ function MarketIdentity({
9059
9210
  compact = false
9060
9211
  }) {
9061
9212
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
9062
- const { colors } = useKjunStyles(), mobile = useWindowDimensions10().width < tokens49.responsive.market && !table && !compact, label = (_c = (_a = props.primaryLabel) == null ? void 0 : _a.call(props, row)) != null ? _c : String((_b = getValue(row, "name")) != null ? _b : ""), meta = ((_d = props.subMeta) == null ? void 0 : _d.call(props, row)) || "", id = getValue(row, props.rowKey || "id");
9213
+ const { colors } = useKjunStyles(), mobile = useWindowDimensions10().width < tokens50.responsive.market && !table && !compact, label = (_c = (_a = props.primaryLabel) == null ? void 0 : _a.call(props, row)) != null ? _c : String((_b = getValue(row, "name")) != null ? _b : ""), meta = ((_d = props.subMeta) == null ? void 0 : _d.call(props, row)) || "", id = getValue(row, props.rowKey || "id");
9063
9214
  const body = /* @__PURE__ */ jsxs36(Fragment17, { children: [
9064
9215
  (_e = props.renderNamePrefix) == null ? void 0 : _e.call(props, row),
9065
9216
  /* @__PURE__ */ jsxs36(View43, { style: { flex: 1, minWidth: 0 }, children: [
@@ -9069,7 +9220,7 @@ function MarketIdentity({
9069
9220
  style: {
9070
9221
  flexDirection: "row",
9071
9222
  alignItems: "center",
9072
- gap: tokens49.dimension.value4,
9223
+ gap: tokens50.dimension.value4,
9073
9224
  minWidth: 0
9074
9225
  },
9075
9226
  children: [
@@ -9091,7 +9242,7 @@ function MarketIdentity({
9091
9242
  ]
9092
9243
  }
9093
9244
  ),
9094
- (meta || props.renderSubMeta) && /* @__PURE__ */ jsx51(View43, { style: { marginTop: tokens49.dimension.value2 }, children: ((_i = props.renderSubMeta) == null ? void 0 : _i.call(props, row)) || /* @__PURE__ */ jsx51(
9245
+ (meta || props.renderSubMeta) && /* @__PURE__ */ jsx51(View43, { style: { marginTop: tokens50.dimension.value2 }, children: ((_i = props.renderSubMeta) == null ? void 0 : _i.call(props, row)) || /* @__PURE__ */ jsx51(
9095
9246
  KText,
9096
9247
  {
9097
9248
  numberOfLines: 1,
@@ -9153,9 +9304,9 @@ function MarketFooter({
9153
9304
  flexWrap: "wrap",
9154
9305
  alignItems: "center",
9155
9306
  justifyContent: "space-between",
9156
- gap: tokens49.dimension.value8,
9157
- paddingVertical: tokens49.dimension.value12,
9158
- paddingHorizontal: tokens49.dimension.value16
9307
+ gap: tokens50.dimension.value8,
9308
+ paddingVertical: tokens50.dimension.value12,
9309
+ paddingHorizontal: tokens50.dimension.value16
9159
9310
  },
9160
9311
  children: [
9161
9312
  /* @__PURE__ */ jsx51(KText, { style: { ...typeStyle("caption"), color: colors.textTertiary }, children: calculatedAt ? m.lastUpdated + (((_a = props.formatDate) == null ? void 0 : _a.call(props, calculatedAt)) || calculatedAt) : footerNote }),
@@ -9201,9 +9352,9 @@ function KjunMarketCards(props) {
9201
9352
  showsHorizontalScrollIndicator: false,
9202
9353
  contentContainerStyle: {
9203
9354
  flexDirection: "row",
9204
- gap: tokens50.dimension.value8,
9205
- paddingVertical: tokens50.dimension.value10,
9206
- paddingHorizontal: tokens50.dimension.value16
9355
+ gap: tokens51.dimension.value8,
9356
+ paddingVertical: tokens51.dimension.value10,
9357
+ paddingHorizontal: tokens51.dimension.value16
9207
9358
  },
9208
9359
  children: state.pills.map((pill) => /* @__PURE__ */ jsxs37(
9209
9360
  AccessiblePressable,
@@ -9212,14 +9363,14 @@ function KjunMarketCards(props) {
9212
9363
  accessibilityLabel: pill.label,
9213
9364
  accessibilityState: { selected: state.key === pill.key },
9214
9365
  onPress: () => state.select(pill.key),
9215
- hitSlop: { top: (tokens50.native.minimumTouchTarget - typeStyle("label").lineHeight - 2 * tokens50.dimension.value8) / 2, bottom: (tokens50.native.minimumTouchTarget - typeStyle("label").lineHeight - 2 * tokens50.dimension.value8) / 2 },
9366
+ hitSlop: { top: (tokens51.native.minimumTouchTarget - typeStyle("label").lineHeight - 2 * tokens51.dimension.value8) / 2, bottom: (tokens51.native.minimumTouchTarget - typeStyle("label").lineHeight - 2 * tokens51.dimension.value8) / 2 },
9216
9367
  style: {
9217
9368
  flexDirection: "row",
9218
9369
  alignItems: "center",
9219
- gap: tokens50.dimension.value4,
9220
- paddingVertical: tokens50.dimension.value8,
9221
- paddingHorizontal: tokens50.dimension.value16,
9222
- borderRadius: tokens50.radius.radius9999,
9370
+ gap: tokens51.dimension.value4,
9371
+ paddingVertical: tokens51.dimension.value8,
9372
+ paddingHorizontal: tokens51.dimension.value16,
9373
+ borderRadius: tokens51.radius.radius9999,
9223
9374
  backgroundColor: state.key === pill.key ? colors.brand : colors.secondary
9224
9375
  },
9225
9376
  children: [
@@ -9255,7 +9406,7 @@ function KjunMarketCards(props) {
9255
9406
  loadingContent: props.skeleton === false ? void 0 : /* @__PURE__ */ jsx52(KjunListSkeleton, { variant: "compact" }),
9256
9407
  emptyContent: /* @__PURE__ */ jsx52(KjunEmpty, { text: emptyMessage, description: emptySubMessage }),
9257
9408
  children: /* @__PURE__ */ jsxs37(View44, { children: [
9258
- state.pill && /* @__PURE__ */ jsx52(KText, { style: { textAlign: "right", paddingHorizontal: tokens50.dimension.value16, paddingVertical: tokens50.dimension.value8, ...typeStyle("caption"), color: colors.textSecondary }, children: state.pill.label }),
9409
+ state.pill && /* @__PURE__ */ jsx52(KText, { style: { textAlign: "right", paddingHorizontal: tokens51.dimension.value16, paddingVertical: tokens51.dimension.value8, ...typeStyle("caption"), color: colors.textSecondary }, children: state.pill.label }),
9259
9410
  rows.map((row, i) => {
9260
9411
  var _a, _b, _c;
9261
9412
  return /* @__PURE__ */ jsxs37(
@@ -9270,22 +9421,22 @@ function KjunMarketCards(props) {
9270
9421
  flexDirection: "row",
9271
9422
  alignItems: "center",
9272
9423
  justifyContent: "space-between",
9273
- paddingVertical: tokens50.dimension.value10,
9274
- paddingHorizontal: tokens50.dimension.value16,
9275
- borderBottomWidth: tokens50.border.defaultWidth,
9424
+ paddingVertical: tokens51.dimension.value10,
9425
+ paddingHorizontal: tokens51.dimension.value16,
9426
+ borderBottomWidth: tokens51.border.defaultWidth,
9276
9427
  borderBottomColor: colors.border,
9277
9428
  backgroundColor: pressed ? colors.hover : void 0
9278
9429
  }),
9279
9430
  children: [
9280
9431
  /* @__PURE__ */ jsx52(MarketIdentity, { row, props, compact: true }),
9281
- /* @__PURE__ */ jsx52(View44, { style: { marginLeft: tokens50.dimension.value12, alignItems: "flex-end" }, children: ((_b = state.pill) == null ? void 0 : _b.format) === "sparkline" ? /* @__PURE__ */ jsx52(
9432
+ /* @__PURE__ */ jsx52(View44, { style: { marginLeft: tokens51.dimension.value12, alignItems: "flex-end" }, children: ((_b = state.pill) == null ? void 0 : _b.format) === "sparkline" ? /* @__PURE__ */ jsx52(
9282
9433
  KjunSparkline,
9283
9434
  {
9284
9435
  data: getValue(row, state.key) || [],
9285
- width: tokens50.extensions.marketTable.sparklineWidth,
9286
- height: tokens50.extensions.marketTable.sparklineHeight
9436
+ width: tokens51.extensions.marketTable.sparklineWidth,
9437
+ height: tokens51.extensions.marketTable.sparklineHeight
9287
9438
  }
9288
- ) : state.pill ? /* @__PURE__ */ jsx52(Fragment18, { children: metricLoading(row, state.key) ? /* @__PURE__ */ jsx52(KjunSkeleton, { type: "block", height: tokens50.extensions.marketTable.valueSkeletonHeight, width: tokens50.extensions.marketTable.valueSkeletonWidth }) : isChange && getValue(row, state.key) != null ? /* @__PURE__ */ jsx52(
9439
+ ) : state.pill ? /* @__PURE__ */ jsx52(Fragment18, { children: metricLoading(row, state.key) ? /* @__PURE__ */ jsx52(KjunSkeleton, { type: "block", height: tokens51.extensions.marketTable.valueSkeletonHeight, width: tokens51.extensions.marketTable.valueSkeletonWidth }) : isChange && getValue(row, state.key) != null ? /* @__PURE__ */ jsx52(
9289
9440
  KjunSignedValue,
9290
9441
  {
9291
9442
  value: finiteNumber(getValue(row, state.key)),
@@ -9293,14 +9444,14 @@ function KjunMarketCards(props) {
9293
9444
  stale: !!getValue(row, "stale"),
9294
9445
  tone: "pill"
9295
9446
  }
9296
- ) : isPrice && getValue(row, state.key) == null ? /* @__PURE__ */ jsx52(KjunSkeleton, { type: "block", height: tokens50.extensions.financial.priceSkeletonHeight, width: tokens50.extensions.financial.priceSkeletonWidth }) : /* @__PURE__ */ jsxs37(
9447
+ ) : isPrice && getValue(row, state.key) == null ? /* @__PURE__ */ jsx52(KjunSkeleton, { type: "block", height: tokens51.extensions.financial.priceSkeletonHeight, width: tokens51.extensions.financial.priceSkeletonWidth }) : /* @__PURE__ */ jsxs37(
9297
9448
  View44,
9298
9449
  {
9299
9450
  style: {
9300
9451
  flexDirection: "row",
9301
9452
  alignItems: "center",
9302
9453
  justifyContent: "flex-end",
9303
- gap: tokens50.dimension.value4
9454
+ gap: tokens51.dimension.value4
9304
9455
  },
9305
9456
  children: [
9306
9457
  (_c = props.renderMetricPrefix) == null ? void 0 : _c.call(
@@ -9337,7 +9488,7 @@ function KjunMarketCards(props) {
9337
9488
  }
9338
9489
 
9339
9490
  // packages/native/src/market-list.tsx
9340
- import { tokens as tokens51 } from "@kjun-ui/tokens";
9491
+ import { tokens as tokens52 } from "@kjun-ui/tokens";
9341
9492
  import { View as View45, useWindowDimensions as useWindowDimensions11 } from "react-native";
9342
9493
  import { jsx as jsx53, jsxs as jsxs38 } from "react/jsx-runtime";
9343
9494
  var changeWeight = { fontWeight: typeStyle("label").fontWeight };
@@ -9355,7 +9506,7 @@ function KjunMarketSimpleList(props) {
9355
9506
  closingPrice = false,
9356
9507
  emptyMessage = m.noItems,
9357
9508
  emptySubMessage = ""
9358
- } = props, { colors } = useKjunStyles(), mobile = useWindowDimensions11().width < tokens51.responsive.market;
9509
+ } = props, { colors } = useKjunStyles(), mobile = useWindowDimensions11().width < tokens52.responsive.market;
9359
9510
  return /* @__PURE__ */ jsxs38(View45, { children: [
9360
9511
  /* @__PURE__ */ jsx53(
9361
9512
  KjunDataState,
@@ -9381,11 +9532,11 @@ function KjunMarketSimpleList(props) {
9381
9532
  flexDirection: "row",
9382
9533
  alignItems: "center",
9383
9534
  justifyContent: "space-between",
9384
- paddingVertical: mobile ? tokens51.dimension.value14 : tokens51.dimension.value16,
9385
- paddingHorizontal: mobile ? tokens51.dimension.value20 : tokens51.dimension.value16,
9535
+ paddingVertical: mobile ? tokens52.dimension.value14 : tokens52.dimension.value16,
9536
+ paddingHorizontal: mobile ? tokens52.dimension.value20 : tokens52.dimension.value16,
9386
9537
  // Like Web, the minimum height belongs to the narrow layout only.
9387
- minHeight: mobile ? tokens51.extensions.marketList.minimumHeight : void 0,
9388
- borderBottomWidth: tokens51.border.defaultWidth,
9538
+ minHeight: mobile ? tokens52.extensions.marketList.minimumHeight : void 0,
9539
+ borderBottomWidth: tokens52.border.defaultWidth,
9389
9540
  borderBottomColor: colors.border,
9390
9541
  backgroundColor: pressed ? colors.hover : void 0
9391
9542
  }),
@@ -9395,8 +9546,8 @@ function KjunMarketSimpleList(props) {
9395
9546
  View45,
9396
9547
  {
9397
9548
  style: {
9398
- marginLeft: tokens51.dimension.value12,
9399
- minWidth: mobile ? tokens51.extensions.marketList.mobileQuoteMinimumWidth : void 0,
9549
+ marginLeft: tokens52.dimension.value12,
9550
+ minWidth: mobile ? tokens52.extensions.marketList.mobileQuoteMinimumWidth : void 0,
9400
9551
  maxWidth: "50%",
9401
9552
  alignItems: "flex-end"
9402
9553
  },
@@ -9418,8 +9569,8 @@ function KjunMarketSimpleList(props) {
9418
9569
  flexWrap: "wrap",
9419
9570
  alignItems: "center",
9420
9571
  justifyContent: "flex-end",
9421
- gap: tokens51.dimension.value6,
9422
- marginTop: tokens51.dimension.value2
9572
+ gap: tokens52.dimension.value6,
9573
+ marginTop: tokens52.dimension.value2
9423
9574
  },
9424
9575
  children: [
9425
9576
  price !== null && ((_b = props.renderPricePrefix) == null ? void 0 : _b.call(props, row)),
@@ -9431,7 +9582,7 @@ function KjunMarketSimpleList(props) {
9431
9582
  fetchedAt
9432
9583
  }
9433
9584
  )),
9434
- changeLoading(row) ? /* @__PURE__ */ jsx53(KjunSkeleton, { type: "block", height: tokens51.extensions.marketList.changeSkeletonHeight, width: tokens51.extensions.marketList.changeSkeletonWidth }) : change !== null ? /* @__PURE__ */ jsx53(
9585
+ changeLoading(row) ? /* @__PURE__ */ jsx53(KjunSkeleton, { type: "block", height: tokens52.extensions.marketList.changeSkeletonHeight, width: tokens52.extensions.marketList.changeSkeletonWidth }) : change !== null ? /* @__PURE__ */ jsx53(
9435
9586
  KjunSignedValue,
9436
9587
  {
9437
9588
  value: change,
@@ -9465,7 +9616,7 @@ function KjunMarketSimpleList(props) {
9465
9616
  }
9466
9617
 
9467
9618
  // packages/native/src/market-panel.tsx
9468
- import { tokens as tokens52 } from "@kjun-ui/tokens";
9619
+ import { tokens as tokens53 } from "@kjun-ui/tokens";
9469
9620
  import { View as View46 } from "react-native";
9470
9621
  import { jsx as jsx54, jsxs as jsxs39 } from "react/jsx-runtime";
9471
9622
  function KjunMarketListPanel({
@@ -9479,8 +9630,8 @@ function KjunMarketListPanel({
9479
9630
  View46,
9480
9631
  {
9481
9632
  style: {
9482
- marginTop: tokens52.dimension.value16,
9483
- borderTopWidth: tokens52.border.defaultWidth,
9633
+ marginTop: tokens53.dimension.value16,
9634
+ borderTopWidth: tokens53.border.defaultWidth,
9484
9635
  borderTopColor: colors.border
9485
9636
  },
9486
9637
  children
@@ -9490,7 +9641,7 @@ function KjunMarketListPanel({
9490
9641
  }
9491
9642
 
9492
9643
  // packages/native/src/market-table.tsx
9493
- import { tokens as tokens53 } from "@kjun-ui/tokens";
9644
+ import { tokens as tokens54 } from "@kjun-ui/tokens";
9494
9645
  import { useId as useId10, useState as useState39 } from "react";
9495
9646
  import { ScrollView as ScrollView11, View as View47 } from "react-native";
9496
9647
  import Svg8, { Defs as Defs4, LinearGradient as LinearGradient4, Rect as Rect4, Stop as Stop4 } from "react-native-svg";
@@ -9518,7 +9669,7 @@ function KjunMarketTable(props) {
9518
9669
  const render = (row, col) => {
9519
9670
  const value = getValue(row, col.key), stale = !!getValue(row, "stale");
9520
9671
  if (cellLoading(row, col))
9521
- return /* @__PURE__ */ jsx55(KjunSkeleton, { type: "block", height: tokens53.extensions.marketTable.valueSkeletonHeight, width: tokens53.extensions.marketTable.valueSkeletonWidth });
9672
+ return /* @__PURE__ */ jsx55(KjunSkeleton, { type: "block", height: tokens54.extensions.marketTable.valueSkeletonHeight, width: tokens54.extensions.marketTable.valueSkeletonWidth });
9522
9673
  if (renderCell) return content(renderCell(row, col));
9523
9674
  if (["stock_name", "name", "symbol"].includes(col.key))
9524
9675
  return /* @__PURE__ */ jsx55(MarketIdentity, { row, props, table: true });
@@ -9527,8 +9678,8 @@ function KjunMarketTable(props) {
9527
9678
  KjunSparkline,
9528
9679
  {
9529
9680
  data: Array.isArray(value) ? value : [],
9530
- width: tokens53.extensions.marketTable.sparklineWidth,
9531
- height: tokens53.extensions.marketTable.sparklineHeight
9681
+ width: tokens54.extensions.marketTable.sparklineWidth,
9682
+ height: tokens54.extensions.marketTable.sparklineHeight
9532
9683
  }
9533
9684
  );
9534
9685
  if (col.type === "price")
@@ -9586,7 +9737,7 @@ function KjunMarketTable(props) {
9586
9737
  onLayout: layout.onLayout,
9587
9738
  style: {
9588
9739
  backgroundColor: embedded ? void 0 : colors.surface,
9589
- borderRadius: embedded ? 0 : tokens53.radius.radius12
9740
+ borderRadius: embedded ? 0 : tokens54.radius.radius12
9590
9741
  },
9591
9742
  children: [
9592
9743
  /* @__PURE__ */ jsx55(
@@ -9626,13 +9777,13 @@ function KjunMarketTable(props) {
9626
9777
  {
9627
9778
  style: {
9628
9779
  width: marketGeometry.actionsWidth,
9629
- paddingVertical: tokens53.dimension.value12,
9630
- paddingHorizontal: tokens53.dimension.value4,
9780
+ paddingVertical: tokens54.dimension.value12,
9781
+ paddingHorizontal: tokens54.dimension.value4,
9631
9782
  flexDirection: "row",
9632
9783
  alignItems: "center",
9633
9784
  justifyContent: "center"
9634
9785
  },
9635
- children: ["interest", "favorite"].map((kind) => /* @__PURE__ */ jsx55(View47, { style: { width: Math.max(tokens53.native.minimumTouchTarget, tokens53.extensions.iconToggle.sizes.xs), alignItems: "center" }, children: /* @__PURE__ */ jsx55(KjunCollectionMark, { kind, size: "md" }) }, kind))
9786
+ children: ["interest", "favorite"].map((kind) => /* @__PURE__ */ jsx55(View47, { style: { width: Math.max(tokens54.native.minimumTouchTarget, tokens54.extensions.iconToggle.sizes.xs), alignItems: "center" }, children: /* @__PURE__ */ jsx55(KjunCollectionMark, { kind, size: "md" }) }, kind))
9636
9787
  }
9637
9788
  ),
9638
9789
  columns.map((col, columnIndex) => /* @__PURE__ */ jsxs40(
@@ -9647,11 +9798,11 @@ function KjunMarketTable(props) {
9647
9798
  },
9648
9799
  style: {
9649
9800
  width: layout.widths[columnIndex],
9650
- padding: tokens53.dimension.value12,
9801
+ padding: tokens54.dimension.value12,
9651
9802
  flexDirection: "row",
9652
9803
  alignItems: "center",
9653
9804
  justifyContent: col.align === "right" ? "flex-end" : col.align === "center" ? "center" : "flex-start",
9654
- gap: tokens53.dimension.value4
9805
+ gap: tokens54.dimension.value4
9655
9806
  },
9656
9807
  children: [
9657
9808
  /* @__PURE__ */ jsx55(
@@ -9668,7 +9819,7 @@ function KjunMarketTable(props) {
9668
9819
  KjunIcon,
9669
9820
  {
9670
9821
  name: sortKey === col.key ? sortOrder === "asc" ? "sort-ascending" : "sort-descending" : "arrows-sort",
9671
- size: tokens53.extensions.marketTable.sortIconSize,
9822
+ size: tokens54.extensions.marketTable.sortIconSize,
9672
9823
  color: sortKey === col.key ? colors.brand : colors.textTertiary
9673
9824
  }
9674
9825
  )
@@ -9703,8 +9854,8 @@ function KjunMarketTable(props) {
9703
9854
  {
9704
9855
  style: {
9705
9856
  width: marketGeometry.actionsWidth,
9706
- paddingVertical: tokens53.dimension.value12,
9707
- paddingHorizontal: tokens53.dimension.value4,
9857
+ paddingVertical: tokens54.dimension.value12,
9858
+ paddingHorizontal: tokens54.dimension.value4,
9708
9859
  flexDirection: "row",
9709
9860
  alignItems: "center",
9710
9861
  justifyContent: "center"
@@ -9748,8 +9899,8 @@ function KjunMarketTable(props) {
9748
9899
  {
9749
9900
  style: {
9750
9901
  width: layout.widths[columnIndex],
9751
- paddingVertical: tokens53.dimension.value14,
9752
- paddingHorizontal: tokens53.dimension.value12,
9902
+ paddingVertical: tokens54.dimension.value14,
9903
+ paddingHorizontal: tokens54.dimension.value12,
9753
9904
  justifyContent: "center",
9754
9905
  alignItems: col.align === "right" ? "flex-end" : col.align === "center" ? "center" : void 0
9755
9906
  },
@@ -9775,7 +9926,7 @@ function KjunMarketTable(props) {
9775
9926
  ] })
9776
9927
  }
9777
9928
  ),
9778
- layout.width - scroll.viewport - scroll.x > 1 && /* @__PURE__ */ jsx55(View47, { pointerEvents: "none", style: { position: "absolute", top: 0, right: 0, bottom: 0, width: tokens53.extensions.scrollFade.width }, children: /* @__PURE__ */ jsxs40(Svg8, { width: "100%", height: "100%", children: [
9929
+ layout.width - scroll.viewport - scroll.x > 1 && /* @__PURE__ */ jsx55(View47, { pointerEvents: "none", style: { position: "absolute", top: 0, right: 0, bottom: 0, width: tokens54.extensions.scrollFade.width }, children: /* @__PURE__ */ jsxs40(Svg8, { width: "100%", height: "100%", children: [
9779
9930
  /* @__PURE__ */ jsx55(Defs4, { children: /* @__PURE__ */ jsxs40(LinearGradient4, { id: fadeId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
9780
9931
  /* @__PURE__ */ jsx55(Stop4, { offset: "0", stopColor: colors.surface, stopOpacity: 0 }),
9781
9932
  /* @__PURE__ */ jsx55(Stop4, { offset: "1", stopColor: colors.surface, stopOpacity: 1 })
@@ -9792,50 +9943,62 @@ function KjunMarketTable(props) {
9792
9943
  }
9793
9944
 
9794
9945
  // packages/native/src/list.tsx
9795
- import { tokens as tokens54 } from "@kjun-ui/tokens";
9946
+ import { tokens as tokens55 } from "@kjun-ui/tokens";
9796
9947
  import { Children as Children5, createContext as createContext22, useContext as useContext19 } from "react";
9797
9948
  import { View as View48, Platform as Platform26 } from "react-native";
9798
9949
  import { Fragment as Fragment19, jsx as jsx56, jsxs as jsxs41 } from "react/jsx-runtime";
9799
9950
  var ListRowContext = createContext22({ divider: true, compact: false });
9800
- function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, onPress }) {
9951
+ function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, destructive = false, chevron = false, onPress, ariaLabel, children }) {
9801
9952
  const { colors } = useKjunStyles(), { divider, compact } = useContext19(ListRowContext);
9802
9953
  const parts = /* @__PURE__ */ jsxs41(Fragment19, { children: [
9803
9954
  hasContent(leading) && /* @__PURE__ */ jsx56(View48, { children: content(leading) }),
9804
9955
  /* @__PURE__ */ jsxs41(View48, { style: { flex: 1, minWidth: 0 }, children: [
9805
- /* @__PURE__ */ jsx56(KText, { style: { ...typeStyle("label") }, children: title }),
9806
- !!description && /* @__PURE__ */ jsx56(KText, { style: { marginTop: tokens54.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9956
+ /* @__PURE__ */ jsx56(KText, { style: { ...typeStyle("label"), ...destructive ? { color: colors.danger } : {} }, children: title }),
9957
+ !!description && /* @__PURE__ */ jsx56(KText, { style: { marginTop: tokens55.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description }),
9958
+ hasContent(children) && /* @__PURE__ */ jsx56(View48, { style: { marginTop: tokens55.extensions.list.descriptionGap }, children: content(children) })
9807
9959
  ] }),
9808
- hasContent(trailing) && /* @__PURE__ */ jsx56(View48, { style: { maxWidth: "35%" }, children: content(trailing) })
9960
+ hasContent(trailing) && /* @__PURE__ */ jsx56(View48, { style: { maxWidth: "35%" }, children: content(trailing) }),
9961
+ chevron && /* @__PURE__ */ jsx56(View48, { accessible: false, importantForAccessibility: "no-hide-descendants", accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx56(KjunIcon, { name: "chevron-right", size: tokens55.iconSizes.default, color: colors.textTertiary }) })
9809
9962
  ] });
9810
- const style = { flex: 1, minWidth: 0, minHeight: compact ? tokens54.extensions.list.compactMinimumHeight : tokens54.extensions.list.minimumHeight, flexDirection: "row", alignItems: "center", gap: tokens54.extensions.list.gap, padding: tokens54.extensions.list.padding, ...compact ? { paddingVertical: tokens54.extensions.list.compactPaddingY } : {} };
9811
- return /* @__PURE__ */ jsxs41(View48, { role: "listitem", style: { flexDirection: "row", alignItems: "center", gap: tokens54.extensions.list.gap, borderBottomWidth: divider ? tokens54.border.defaultWidth : 0, borderBottomColor: colors.divider }, children: [
9812
- onPress || href ? /* @__PURE__ */ jsx56(AccessiblePressable, { ...Platform26.OS === "web" && href && !disabled ? { href } : {}, accessibilityRole: href ? "link" : "button", accessibilityLabel: title + (description ? ", " + description : ""), disabled, accessibilityState: { disabled }, onPress, style: ({ pressed }) => ({ ...style, opacity: disabled ? tokens54.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ jsx56(View48, { style, children: parts }),
9813
- hasContent(actions) && /* @__PURE__ */ jsx56(View48, { pointerEvents: disabled ? "none" : "auto", ...disabled && Platform26.OS === "web" ? { inert: true } : {}, style: { maxWidth: "45%", flexDirection: "row", flexWrap: "wrap", gap: tokens54.extensions.list.actionsGap, paddingRight: tokens54.extensions.list.actionsPadding, opacity: disabled ? tokens54.states.opacity.disabled : 1 }, children: content(actions) })
9963
+ const style = { flex: 1, minWidth: 0, minHeight: compact ? tokens55.extensions.list.compactMinimumHeight : tokens55.extensions.list.minimumHeight, flexDirection: "row", alignItems: "center", gap: tokens55.extensions.list.gap, padding: tokens55.extensions.list.padding, ...compact ? { paddingVertical: tokens55.extensions.list.compactPaddingY } : {} };
9964
+ return /* @__PURE__ */ jsxs41(View48, { role: "listitem", style: { flexDirection: "row", alignItems: "center", gap: tokens55.extensions.list.gap, borderBottomWidth: divider ? tokens55.border.defaultWidth : 0, borderBottomColor: colors.divider }, children: [
9965
+ onPress || href ? /* @__PURE__ */ jsx56(AccessiblePressable, { ...Platform26.OS === "web" && href && !disabled ? { href } : {}, accessibilityRole: href ? "link" : "button", accessibilityLabel: ariaLabel != null ? ariaLabel : title + (description ? ", " + description : ""), disabled, accessibilityState: { disabled }, onPress, style: ({ pressed }) => ({ ...style, opacity: disabled ? tokens55.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ jsx56(View48, { style, children: parts }),
9966
+ hasContent(actions) && /* @__PURE__ */ jsx56(View48, { pointerEvents: disabled ? "none" : "auto", ...disabled && Platform26.OS === "web" ? { inert: true } : {}, style: { maxWidth: "45%", flexDirection: "row", flexWrap: "wrap", gap: tokens55.extensions.list.actionsGap, paddingRight: tokens55.extensions.list.actionsPadding, opacity: disabled ? tokens55.states.opacity.disabled : 1 }, children: content(actions) })
9814
9967
  ] });
9815
9968
  }
9816
- function KjunListSection({ title, description, actions, children, ariaLabel, divider = true, density = "default" }) {
9969
+ function KjunListSection({ title, description, actions, children, ariaLabel, surface = true, divider = true, density = "default" }) {
9817
9970
  const { colors } = useKjunStyles();
9818
- return /* @__PURE__ */ jsxs41(View48, { style: { minWidth: 0, backgroundColor: colors.surface }, children: [
9819
- !!(title || description || actions) && /* @__PURE__ */ jsxs41(View48, { style: { flexDirection: "row", alignItems: "center", gap: tokens54.extensions.list.gap, padding: tokens54.extensions.list.padding }, children: [
9971
+ return /* @__PURE__ */ jsxs41(View48, { style: { minWidth: 0, backgroundColor: surface ? colors.surface : "transparent" }, children: [
9972
+ !!(title || description || actions) && /* @__PURE__ */ jsxs41(View48, { style: { flexDirection: "row", alignItems: "center", gap: tokens55.extensions.list.gap, padding: tokens55.extensions.list.padding }, children: [
9820
9973
  /* @__PURE__ */ jsxs41(View48, { style: { flex: 1 }, children: [
9821
9974
  !!title && /* @__PURE__ */ jsx56(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle") }, children: title }),
9822
- !!description && /* @__PURE__ */ jsx56(KText, { style: { marginTop: tokens54.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9975
+ !!description && /* @__PURE__ */ jsx56(KText, { style: { marginTop: tokens55.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9823
9976
  ] }),
9824
9977
  content(actions)
9825
9978
  ] }),
9826
9979
  /* @__PURE__ */ jsx56(View48, { role: "list", accessibilityLabel: ariaLabel || title, children: Children5.toArray(children).map((row, i, rows) => /* @__PURE__ */ jsx56(ListRowContext.Provider, { value: { divider: divider && i < rows.length - 1, compact: density === "compact" }, children: row }, i)) })
9827
9980
  ] });
9828
9981
  }
9982
+ function KjunListItem({ children }) {
9983
+ const { colors } = useKjunStyles(), { divider, compact } = useContext19(ListRowContext);
9984
+ return /* @__PURE__ */ jsx56(View48, { role: "listitem", style: {
9985
+ padding: tokens55.extensions.list.padding,
9986
+ ...compact ? { paddingVertical: tokens55.extensions.list.compactPaddingY } : {},
9987
+ borderBottomWidth: divider ? tokens55.border.defaultWidth : 0,
9988
+ borderBottomColor: colors.divider,
9989
+ minWidth: 0
9990
+ }, children: content(children) });
9991
+ }
9829
9992
 
9830
9993
  // packages/native/src/app-navigation.tsx
9831
- import { tokens as tokens55 } from "@kjun-ui/tokens";
9994
+ import { tokens as tokens56 } from "@kjun-ui/tokens";
9832
9995
  import { Children as Children6, Fragment as Fragment20, isValidElement as isValidElement8, useState as useState40 } from "react";
9833
9996
  import { View as View49, Platform as Platform27 } from "react-native";
9834
9997
  import { jsx as jsx57, jsxs as jsxs42 } from "react/jsx-runtime";
9835
9998
  function KjunTopNavigation({ title, description, leading, actions, safeAreaTop = 0 }) {
9836
9999
  const { colors } = useKjunStyles();
9837
- const geometry2 = tokens55.extensions.topNavigation;
9838
- const titleInset = Math.max(0, (geometry2.controlSize - tokens55.typography.sectionTitle.lineHeightPx) / 2);
10000
+ const geometry2 = tokens56.extensions.topNavigation;
10001
+ const titleInset = Math.max(0, (geometry2.controlSize - tokens56.typography.sectionTitle.lineHeightPx) / 2);
9839
10002
  const wrapping = Platform27.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
9840
10003
  const edgeInset = (geometry2.controlSize - geometry2.iconSize) / 2;
9841
10004
  const [iconEdges, setIconEdges] = useState40({ leading: false, trailing: false });
@@ -9859,13 +10022,13 @@ function KjunBottomNavigation({ items: items2, value, ariaLabel, safeAreaBottom
9859
10022
  const m = useKjunMessages();
9860
10023
  ariaLabel != null ? ariaLabel : ariaLabel = m.mainNavigation;
9861
10024
  const { colors } = useKjunStyles();
9862
- const geometry2 = tokens55.extensions.bottomNavigation;
10025
+ const geometry2 = tokens56.extensions.bottomNavigation;
9863
10026
  const hasIcons = items2.some((item) => item.icon);
9864
10027
  if (keyboardVisible && hideOnKeyboard) return null;
9865
10028
  return /* @__PURE__ */ jsx57(View49, { role: "navigation", accessibilityLabel: ariaLabel, style: { flexShrink: 0, flexDirection: "row", backgroundColor: colors.surface, paddingBottom: Math.max(0, safeAreaBottom) }, children: items2.map((item) => {
9866
10029
  const selected = item.key === value;
9867
10030
  const ink = selected ? colors.brand : colors.textSecondary;
9868
- const ring = tokens55.border.controlWidth;
10031
+ const ring = tokens56.border.controlWidth;
9869
10032
  const badge = item.badge != null && /* @__PURE__ */ jsx57(View49, { pointerEvents: "none", "aria-hidden": true, style: {
9870
10033
  position: "absolute",
9871
10034
  top: -geometry2.badgeOffset - ring,
@@ -9900,7 +10063,7 @@ function KjunBottomNavigation({ items: items2, value, ariaLabel, safeAreaBottom
9900
10063
  gap: geometry2.itemGap,
9901
10064
  paddingHorizontal: geometry2.itemPaddingX,
9902
10065
  paddingVertical: geometry2.itemPaddingY,
9903
- opacity: item.disabled ? tokens55.states.opacity.disabled : 1
10066
+ opacity: item.disabled ? tokens56.states.opacity.disabled : 1
9904
10067
  },
9905
10068
  children: [
9906
10069
  hasIcons && /* @__PURE__ */ jsxs42(View49, { style: { width: geometry2.iconSize, height: geometry2.iconSize, flexShrink: 0 }, children: [
@@ -9921,8 +10084,8 @@ function KjunBottomNavigation({ items: items2, value, ariaLabel, safeAreaBottom
9921
10084
  function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboardVisible = false, hideOnKeyboard = false }) {
9922
10085
  const { colors } = useKjunStyles();
9923
10086
  const [width, setWidth] = useState40(0);
9924
- const geometry2 = tokens55.extensions.navigation;
9925
- const wide = width >= tokens55.responsive.bottomAction + geometry2.padding * 2;
10087
+ const geometry2 = tokens56.extensions.navigation;
10088
+ const wide = width >= tokens56.responsive.bottomAction + geometry2.padding * 2;
9926
10089
  const wrapping = Platform27.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
9927
10090
  if (keyboardVisible && hideOnKeyboard) return null;
9928
10091
  return /* @__PURE__ */ jsx57(BottomActionBarContext.Provider, { value: !wide, children: /* @__PURE__ */ jsxs42(View49, { onLayout: (event) => setWidth(event.nativeEvent.layout.width), style: {
@@ -9942,52 +10105,53 @@ function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboa
9942
10105
  }
9943
10106
 
9944
10107
  // packages/native/src/media.tsx
9945
- import { useRef as useRef33, useState as useState41 } from "react";
10108
+ import { createContext as createContext23, useContext as useContext20, useRef as useRef36, useState as useState41 } from "react";
9946
10109
  import { Image, View as View50 } from "react-native";
9947
- import { tokens as tokens56 } from "@kjun-ui/tokens";
10110
+ import { tokens as tokens57 } from "@kjun-ui/tokens";
9948
10111
  import { jsx as jsx58 } from "react/jsx-runtime";
10112
+ var ImageBackgroundContext = createContext23(void 0);
9949
10113
  function KjunImage({ src, source, alt, decorative = false, aspectRatio = 1, fit = "cover", fallback: fallback2, onLoad, onError }) {
9950
- const { colors } = useKjunStyles();
9951
- const request = JSON.stringify(source != null ? source : src), current = useRef33({ request, version: 0 });
10114
+ const { colors } = useKjunStyles(), background = useContext20(ImageBackgroundContext);
10115
+ const request = JSON.stringify(source != null ? source : src), current = useRef36({ request, version: 0 });
9952
10116
  if (current.current.request !== request) current.current = { request, version: current.current.version + 1 };
9953
10117
  const version = current.current.version;
9954
10118
  const [failed, setFailed] = useState41(null);
9955
10119
  const missing = !source && !src;
9956
- return /* @__PURE__ */ jsx58(View50, { accessibilityElementsHidden: decorative, importantForAccessibility: decorative ? "no-hide-descendants" : "auto", "aria-hidden": decorative || void 0, style: { width: "100%", aspectRatio: aspectRatio > 0 ? aspectRatio : 1, overflow: "hidden", backgroundColor: colors.secondary }, children: !missing && failed !== version ? /* @__PURE__ */ jsx58(Image, { source: source != null ? source : { uri: src }, accessible: !decorative, accessibilityLabel: decorative ? void 0 : alt, resizeMode: fit, style: { position: "absolute", inset: 0, width: "100%", height: "100%" }, onLoad: () => {
10120
+ return /* @__PURE__ */ jsx58(View50, { accessibilityElementsHidden: decorative, importantForAccessibility: decorative ? "no-hide-descendants" : "auto", "aria-hidden": decorative || void 0, style: { width: "100%", aspectRatio: aspectRatio > 0 ? aspectRatio : 1, overflow: "hidden", backgroundColor: background != null ? background : colors.secondary }, children: !missing && failed !== version ? /* @__PURE__ */ jsx58(Image, { source: source != null ? source : { uri: src }, accessible: !decorative, accessibilityLabel: decorative ? void 0 : alt, resizeMode: fit, style: { position: "absolute", inset: 0, width: "100%", height: "100%" }, onLoad: () => {
9957
10121
  if (version === current.current.version) onLoad == null ? void 0 : onLoad();
9958
10122
  }, onError: () => {
9959
10123
  if (version === current.current.version) {
9960
10124
  setFailed(version);
9961
10125
  onError == null ? void 0 : onError();
9962
10126
  }
9963
- } }, version) : /* @__PURE__ */ jsx58(View50, { accessible: !decorative, accessibilityRole: "image", accessibilityLabel: decorative ? void 0 : alt, "aria-hidden": decorative || void 0, style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: content(fallback2 != null ? fallback2 : /* @__PURE__ */ jsx58(KjunIcon, { name: "image", size: tokens56.extensions.image.fallbackIconSize, color: colors.textSecondary }), { color: colors.textSecondary, fontWeight: typeStyle("control").fontWeight, textAlign: "center" }) }) });
10127
+ } }, version) : /* @__PURE__ */ jsx58(View50, { accessible: !decorative, accessibilityRole: "image", accessibilityLabel: decorative ? void 0 : alt, "aria-hidden": decorative || void 0, style: { flex: 1, alignItems: "center", justifyContent: "center" }, children: content(fallback2 != null ? fallback2 : /* @__PURE__ */ jsx58(KjunIcon, { name: "image", size: tokens57.extensions.image.fallbackIconSize, color: colors.textSecondary }), { color: colors.textSecondary, fontWeight: typeStyle("control").fontWeight, textAlign: "center" }) }) });
9964
10128
  }
9965
- function KjunAvatar({ src, source, name = "", alt, decorative = false, size = "md", shape = "circle", fallback: fallback2, onLoad, onError }) {
10129
+ function KjunAvatar({ src, source, name = "", alt, decorative = false, size = "md", shape = "circle", color, textColor, fallback: fallback2, onLoad, onError }) {
9966
10130
  const m = useKjunMessages();
9967
10131
  const { colors } = useKjunStyles(), initial = Array.from(name.trim())[0];
9968
- return /* @__PURE__ */ jsx58(View50, { style: { width: tokens56.extensions.avatar[size], height: tokens56.extensions.avatar[size], borderRadius: shape === "circle" ? tokens56.radius.radius9999 : tokens56.radius.radius8, overflow: "hidden", flexShrink: 0 }, children: /* @__PURE__ */ jsx58(KjunImage, { src, source, alt: alt || name || m.user, decorative, fallback: fallback2 != null ? fallback2 : initial ? /* @__PURE__ */ jsx58(KText, { style: { ...typeStyle(size === "sm" ? "control" : size === "lg" ? "sectionTitle" : "input"), fontWeight: typeStyle("control").fontWeight, color: colors.textSecondary }, children: initial.toLocaleUpperCase() }) : /* @__PURE__ */ jsx58(KjunIcon, { name: "user", size: tokens56.extensions.avatar.fallbackIconSizes[size] }), onLoad, onError }) });
10132
+ return /* @__PURE__ */ jsx58(View50, { style: { width: tokens57.extensions.avatar[size], height: tokens57.extensions.avatar[size], borderRadius: shape === "circle" ? tokens57.radius.radius9999 : tokens57.radius.radius8, overflow: "hidden", flexShrink: 0 }, children: /* @__PURE__ */ jsx58(ImageBackgroundContext.Provider, { value: color, children: /* @__PURE__ */ jsx58(KjunImage, { src, source, alt: alt || name || m.user, decorative, fallback: fallback2 != null ? fallback2 : initial ? /* @__PURE__ */ jsx58(KText, { style: { ...typeStyle(size === "sm" ? "control" : size === "lg" ? "sectionTitle" : "input"), fontWeight: typeStyle("control").fontWeight, color: textColor != null ? textColor : colors.textSecondary }, children: initial.toLocaleUpperCase() }) : /* @__PURE__ */ jsx58(KjunIcon, { name: "user", size: tokens57.extensions.avatar.fallbackIconSizes[size], color: textColor }), onLoad, onError }) }) });
9969
10133
  }
9970
10134
 
9971
10135
  // packages/native/src/chip.tsx
9972
10136
  import { View as View51 } from "react-native";
9973
- import { tokens as tokens57 } from "@kjun-ui/tokens";
10137
+ import { tokens as tokens58 } from "@kjun-ui/tokens";
9974
10138
  import { jsx as jsx59, jsxs as jsxs43 } from "react/jsx-runtime";
9975
10139
  function KjunChip({ label, icon, removable = false, disabled = false, size = "md", removeLabel, onRemove }) {
9976
10140
  const m = useKjunMessages();
9977
10141
  const { colors } = useKjunStyles();
9978
- return /* @__PURE__ */ jsxs43(View51, { style: { alignSelf: "flex-start", maxWidth: "100%", minWidth: 0, flexShrink: 1, flexDirection: "row", alignItems: "center", gap: tokens57.extensions.chip.gap, minHeight: removable ? tokens57.extensions.chip.nativeRemoveSize : tokens57.extensions.chip[size], paddingVertical: removable ? 0 : tokens57.extensions.chip.paddingY, paddingLeft: tokens57.extensions.chip.paddingX, paddingRight: removable ? 0 : tokens57.extensions.chip.paddingX, borderRadius: tokens57.extensions.chip.radius, backgroundColor: colors.secondary, opacity: disabled ? tokens57.states.opacity.disabled : 1 }, children: [
9979
- !!icon && /* @__PURE__ */ jsx59(KjunIcon, { name: icon, size: tokens57.extensions.chip.iconSizes[size] }),
9980
- /* @__PURE__ */ jsx59(KText, { style: { ...typeStyle(tokens57.extensions.chip.typography[size]), flexShrink: 1, minWidth: 0 }, children: label }),
9981
- removable && /* @__PURE__ */ jsx59(AccessiblePressable, { accessibilityRole: "button", accessibilityLabel: removeLabel || m.remove(label), disabled, accessibilityState: { disabled }, onPress: onRemove, style: { width: tokens57.extensions.chip.nativeRemoveSize, height: tokens57.extensions.chip.nativeRemoveSize, borderRadius: tokens57.extensions.chip.radius, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx59(KjunIcon, { name: "x", size: tokens57.extensions.chip.removeIconSizes[size] }) })
10142
+ return /* @__PURE__ */ jsxs43(View51, { style: { alignSelf: "flex-start", maxWidth: "100%", minWidth: 0, flexShrink: 1, flexDirection: "row", alignItems: "center", gap: tokens58.extensions.chip.gap, minHeight: removable ? tokens58.extensions.chip.nativeRemoveSize : tokens58.extensions.chip[size], paddingVertical: removable ? 0 : tokens58.extensions.chip.paddingY, paddingLeft: tokens58.extensions.chip.paddingX, paddingRight: removable ? 0 : tokens58.extensions.chip.paddingX, borderRadius: tokens58.extensions.chip.radius, backgroundColor: colors.secondary, opacity: disabled ? tokens58.states.opacity.disabled : 1 }, children: [
10143
+ !!icon && /* @__PURE__ */ jsx59(KjunIcon, { name: icon, size: tokens58.extensions.chip.iconSizes[size] }),
10144
+ /* @__PURE__ */ jsx59(KText, { style: { ...typeStyle(tokens58.extensions.chip.typography[size]), flexShrink: 1, minWidth: 0 }, children: label }),
10145
+ removable && /* @__PURE__ */ jsx59(AccessiblePressable, { accessibilityRole: "button", accessibilityLabel: removeLabel || m.remove(label), disabled, accessibilityState: { disabled }, onPress: onRemove, style: { width: tokens58.extensions.chip.nativeRemoveSize, height: tokens58.extensions.chip.nativeRemoveSize, borderRadius: tokens58.extensions.chip.radius, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx59(KjunIcon, { name: "x", size: tokens58.extensions.chip.removeIconSizes[size] }) })
9982
10146
  ] });
9983
10147
  }
9984
10148
 
9985
10149
  // packages/native/src/fab.tsx
9986
- import { tokens as tokens58 } from "@kjun-ui/tokens";
10150
+ import { tokens as tokens59 } from "@kjun-ui/tokens";
9987
10151
  import { jsx as jsx60 } from "react/jsx-runtime";
9988
10152
  function KjunFab({ icon, ariaLabel, disabled = false, safeAreaBottom = 0, offsetBottom = 0, onPress }) {
9989
10153
  const { colors } = useKjunStyles();
9990
- const { size, inset, iconSize } = tokens58.extensions.fab;
10154
+ const { size, inset, iconSize } = tokens59.extensions.fab;
9991
10155
  return /* @__PURE__ */ jsx60(
9992
10156
  AccessiblePressable,
9993
10157
  {
@@ -10000,15 +10164,15 @@ function KjunFab({ icon, ariaLabel, disabled = false, safeAreaBottom = 0, offset
10000
10164
  position: "absolute",
10001
10165
  right: inset,
10002
10166
  bottom: inset + Math.max(0, safeAreaBottom) + Math.max(0, offsetBottom),
10003
- zIndex: tokens58.layers.page.navigation,
10167
+ zIndex: tokens59.layers.page.navigation,
10004
10168
  width: size,
10005
10169
  height: size,
10006
10170
  borderRadius: size / 2,
10007
10171
  alignItems: "center",
10008
10172
  justifyContent: "center",
10009
10173
  backgroundColor: pressed ? colors.brandActive : colors.brand,
10010
- opacity: disabled ? tokens58.states.opacity.disabled : 1,
10011
- boxShadow: shadowLayers(tokens58.elevation.floating, colors)
10174
+ opacity: disabled ? tokens59.states.opacity.disabled : 1,
10175
+ boxShadow: shadowLayers(tokens59.elevation.floating, colors)
10012
10176
  }),
10013
10177
  children: /* @__PURE__ */ jsx60(KjunIcon, { name: icon, size: iconSize, color: colors.onBrand })
10014
10178
  }
@@ -10016,12 +10180,12 @@ function KjunFab({ icon, ariaLabel, disabled = false, safeAreaBottom = 0, offset
10016
10180
  }
10017
10181
 
10018
10182
  // packages/native/src/range-input.tsx
10019
- import { useEffect as useEffect27, useMemo as useMemo3, useRef as useRef34, useState as useState42 } from "react";
10183
+ import { useEffect as useEffect28, useMemo as useMemo3, useRef as useRef37, useState as useState42 } from "react";
10020
10184
  import { PanResponder, Platform as Platform28, Pressable as Pressable3, View as View52 } from "react-native";
10021
- import { tokens as tokens59, createSliderDomain, sliderKey } from "@kjun-ui/tokens";
10185
+ import { tokens as tokens60, createSliderDomain, sliderKey } from "@kjun-ui/tokens";
10022
10186
  import { jsx as jsx61, jsxs as jsxs44 } from "react/jsx-runtime";
10023
- var geometry = tokens59.extensions.slider;
10024
- var targetSize = tokens59.native.minimumTouchTarget;
10187
+ var geometry = tokens60.extensions.slider;
10188
+ var targetSize = tokens60.native.minimumTouchTarget;
10025
10189
  var trackFocus = { tabIndex: -1 };
10026
10190
  function RangeInput({
10027
10191
  value,
@@ -10044,15 +10208,15 @@ function RangeInput({
10044
10208
  const [hovered, setHovered] = useState42(null);
10045
10209
  const [dragging, setDragging] = useState42(null);
10046
10210
  const [focused, setFocused] = useState42(null);
10047
- const track = useRef34(null), measured = useRef34({ x: 0, width: 1 }), selected = useRef34(0), dirty = useRef34(false);
10048
- const latest = useRef34(values);
10211
+ const track = useRef37(null), measured = useRef37({ x: 0, width: 1 }), selected = useRef37(0), dirty = useRef37(false);
10212
+ const latest = useRef37(values);
10049
10213
  latest.current = values;
10050
- const callbacks = useRef34({ onValueChange, onChangeCommit });
10214
+ const callbacks = useRef37({ onValueChange, onChangeCommit });
10051
10215
  callbacks.current = { onValueChange, onChangeCommit };
10052
- useEffect27(() => {
10216
+ useEffect28(() => {
10053
10217
  if (!valid) console.warn("KJUN Slider: \uBC94\uC704\xB7step\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10054
10218
  }, [valid]);
10055
- useEffect27(() => {
10219
+ useEffect28(() => {
10056
10220
  if (blocked) {
10057
10221
  setDragging(null);
10058
10222
  setHovered(null);
@@ -10121,10 +10285,10 @@ function RangeInput({
10121
10285
  View52,
10122
10286
  {
10123
10287
  style: {
10124
- minWidth: tokens59.extensions.slider.minimumWidth,
10288
+ minWidth: tokens60.extensions.slider.minimumWidth,
10125
10289
  width: "100%",
10126
- gap: tokens59.dimension.value4,
10127
- opacity: blocked ? tokens59.states.opacity.disabled : 1
10290
+ gap: tokens60.dimension.value4,
10291
+ opacity: blocked ? tokens60.states.opacity.disabled : 1
10128
10292
  },
10129
10293
  children: [
10130
10294
  /* @__PURE__ */ jsxs44(
@@ -10134,7 +10298,7 @@ function RangeInput({
10134
10298
  flexDirection: "row",
10135
10299
  alignItems: "baseline",
10136
10300
  justifyContent: "space-between",
10137
- gap: tokens59.dimension.value12,
10301
+ gap: tokens60.dimension.value12,
10138
10302
  minWidth: 0
10139
10303
  },
10140
10304
  children: [
@@ -10195,7 +10359,7 @@ function RangeInput({
10195
10359
  {
10196
10360
  style: {
10197
10361
  height: geometry.track,
10198
- borderRadius: tokens59.radius.radius9999,
10362
+ borderRadius: tokens60.radius.radius9999,
10199
10363
  backgroundColor: colors.border
10200
10364
  }
10201
10365
  }
@@ -10210,7 +10374,7 @@ function RangeInput({
10210
10374
  position: "absolute",
10211
10375
  top: (targetSize - geometry.track) / 2,
10212
10376
  height: geometry.track,
10213
- borderRadius: tokens59.radius.radius9999,
10377
+ borderRadius: tokens60.radius.radius9999,
10214
10378
  left: pct(values.length === 2 ? percent(values[0]) : 0),
10215
10379
  width: pct(
10216
10380
  percent(values[values.length - 1]) - (values.length === 2 ? percent(values[0]) : 0)
@@ -10286,14 +10450,14 @@ function RangeInput({
10286
10450
  style: {
10287
10451
  width: geometry.thumb,
10288
10452
  height: geometry.thumb,
10289
- borderRadius: tokens59.radius.radius9999,
10290
- borderWidth: tokens59.border.controlWidth,
10453
+ borderRadius: tokens60.radius.radius9999,
10454
+ borderWidth: tokens60.border.controlWidth,
10291
10455
  borderColor: !blocked && dragging === index ? colors.brandActive : !blocked && hovered === index ? colors.brandHover : colors.brand,
10292
10456
  backgroundColor: colors.surface,
10293
10457
  ...Platform28.OS === "web" && !blocked && focused === index ? {
10294
10458
  outlineStyle: "solid",
10295
- outlineWidth: tokens59.states.focus.width,
10296
- outlineOffset: tokens59.states.focus.choiceOffset,
10459
+ outlineWidth: tokens60.states.focus.width,
10460
+ outlineOffset: tokens60.states.focus.choiceOffset,
10297
10461
  outlineColor: colors.focusRing
10298
10462
  } : {}
10299
10463
  }
@@ -10317,9 +10481,9 @@ function KjunRangeSlider(props) {
10317
10481
  }
10318
10482
 
10319
10483
  // packages/native/src/quantity-stepper.tsx
10320
- import { useEffect as useEffect28, useRef as useRef35, useState as useState43 } from "react";
10484
+ import { useEffect as useEffect29, useRef as useRef38, useState as useState43 } from "react";
10321
10485
  import { Platform as Platform29, View as View53 } from "react-native";
10322
- import { createNumberDomain, quantityKeyAction, tokens as tokens60 } from "@kjun-ui/tokens";
10486
+ import { createNumberDomain, quantityKeyAction, tokens as tokens61 } from "@kjun-ui/tokens";
10323
10487
 
10324
10488
  // shared/package-runtime/component-icons.ts
10325
10489
  import minus from "@kjun-ui/icons/icons/minus";
@@ -10333,23 +10497,23 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10333
10497
  const field = useKjunField();
10334
10498
  const invalid = error || !!(field == null ? void 0 : field.error);
10335
10499
  const labelledBy = !ariaLabel && (field == null ? void 0 : field.label) && !field.labelHidden ? field.id + "-label" : void 0;
10336
- const geometry2 = tokens60.extensions.compound;
10337
- const buttonStyle = { width: tokens60.input[size].height, paddingHorizontal: 0 };
10338
- const outer = tokens60.input[size].radius;
10500
+ const geometry2 = tokens61.extensions.compound;
10501
+ const buttonStyle = { width: tokens61.input[size].height, paddingHorizontal: 0 };
10502
+ const outer = tokens61.input[size].radius;
10339
10503
  const decreaseStyle = { ...buttonStyle, borderRadius: 0, borderTopLeftRadius: outer, borderBottomLeftRadius: outer };
10340
10504
  const increaseStyle = { ...buttonStyle, borderRadius: 0, borderTopRightRadius: outer, borderBottomRightRadius: outer };
10341
10505
  const domain = createNumberDomain({ min, max, step, precision }), valid = domain.valid && domain.accepts(value), blocked = disabled || !valid;
10342
10506
  const surface = useFieldSurface(size, { disabled: blocked, invalid });
10343
10507
  const [draft, setDraft] = useState43(String(value));
10344
- const inputRef = useRef35(null);
10345
- const composing = useRef35(false), dirty = useRef35(false), accepted = useRef35(value);
10346
- const cancelledEscape = useRef35(false);
10347
- useEffect28(() => {
10508
+ const inputRef = useRef38(null);
10509
+ const composing = useRef38(false), dirty = useRef38(false), accepted = useRef38(value);
10510
+ const cancelledEscape = useRef38(false);
10511
+ useEffect29(() => {
10348
10512
  setDraft(String(value));
10349
10513
  accepted.current = value;
10350
10514
  dirty.current = false;
10351
10515
  }, [value, precision, min, max, step]);
10352
- useEffect28(() => {
10516
+ useEffect29(() => {
10353
10517
  if (!valid) console.warn("KJUN QuantityStepper: \uBC94\uC704\xB7step\xB7\uC815\uBC00\uB3C4\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10354
10518
  }, [valid]);
10355
10519
  const emit = (next) => {
@@ -10386,7 +10550,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10386
10550
  } else if (action === "commit") commit();
10387
10551
  else move(action === "increment" ? 1 : -1);
10388
10552
  };
10389
- const handlers = useRef35({ key, edit: (text) => {
10553
+ const handlers = useRef38({ key, edit: (text) => {
10390
10554
  dirty.current = true;
10391
10555
  setDraft(text);
10392
10556
  } });
@@ -10394,7 +10558,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10394
10558
  dirty.current = true;
10395
10559
  setDraft(text);
10396
10560
  } };
10397
- useEffect28(() => {
10561
+ useEffect29(() => {
10398
10562
  if (Platform29.OS !== "web") return;
10399
10563
  const input = inputRef.current;
10400
10564
  const keydown = (event) => handlers.current.key(event);
@@ -10423,12 +10587,12 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10423
10587
  input.removeEventListener("compositionend", end);
10424
10588
  };
10425
10589
  }, []);
10426
- const surfaceBox = { position: "absolute", left: 0, right: 0, top: "50%", height: tokens60.input[size].height, marginTop: -tokens60.input[size].height / 2, borderRadius: surface.spec.radius };
10590
+ const surfaceBox = { position: "absolute", left: 0, right: 0, top: "50%", height: tokens61.input[size].height, marginTop: -tokens61.input[size].height / 2, borderRadius: surface.spec.radius };
10427
10591
  const hug = Platform29.OS === "web" && !block ? { width: "fit-content" } : {};
10428
10592
  return /* @__PURE__ */ jsx62(IconFallbacks, { icons: componentIcons, children: /* @__PURE__ */ jsxs45(View53, { style: { flexDirection: "row", alignItems: "center", alignSelf: block ? "stretch" : "flex-start", maxWidth: "100%", borderRadius: surface.spec.radius, ...hug }, children: [
10429
10593
  /* @__PURE__ */ jsx62(View53, { pointerEvents: "none", "aria-hidden": true, style: { ...surfaceBox, backgroundColor: colors.inputBg } }),
10430
10594
  /* @__PURE__ */ jsx62(CompoundTarget, { square: true, children: /* @__PURE__ */ jsx62(KjunButton, { size, style: decreaseStyle, variant: "ghost", ariaLabel: m.decreaseQuantity, disabled: blocked || value <= min, onPress: () => move(-1), prefixIcon: "minus" }) }),
10431
- /* @__PURE__ */ jsx62(View53, { style: { flex: block ? 1 : void 0, width: block ? void 0 : geometry2.valueWidth, minWidth: 0, minHeight: finePointer() ? void 0 : tokens60.native.minimumTouchTarget, justifyContent: "center" }, ...fieldTarget(() => {
10595
+ /* @__PURE__ */ jsx62(View53, { style: { flex: block ? 1 : void 0, width: block ? void 0 : geometry2.valueWidth, minWidth: 0, minHeight: finePointer() ? void 0 : tokens61.native.minimumTouchTarget, justifyContent: "center" }, ...fieldTarget(() => {
10432
10596
  var _a;
10433
10597
  return (_a = inputRef.current) == null ? void 0 : _a.focus();
10434
10598
  }, blocked), children: /* @__PURE__ */ jsx62(
@@ -10457,30 +10621,30 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10457
10621
  },
10458
10622
  onSubmitEditing: Platform29.OS === "web" ? void 0 : commit,
10459
10623
  ...Platform29.OS === "web" ? { "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": value, "aria-labelledby": labelledBy, "aria-describedby": field == null ? void 0 : field.describedBy, "aria-invalid": invalid || void 0, "aria-required": (field == null ? void 0 : field.required) || void 0 } : { onKeyPress: key },
10460
- style: { width: "100%", minWidth: 0, ...surface.style, borderRadius: 0, borderTopColor: "transparent", borderBottomColor: "transparent", borderLeftColor: "transparent", borderRightColor: "transparent", backgroundColor: !blocked && (surface.active || surface.hovered) ? colors.hover : "transparent", outlineWidth: 0, color: surface.ink, fontFamily, ...inputTypeStyle(size), textAlign: "center", paddingHorizontal: surface.spec.padding - tokens60.border.controlWidth, paddingVertical: 0 }
10624
+ style: { width: "100%", minWidth: 0, ...surface.style, borderRadius: 0, borderTopColor: "transparent", borderBottomColor: "transparent", borderLeftColor: "transparent", borderRightColor: "transparent", backgroundColor: !blocked && (surface.active || surface.hovered) ? colors.hover : "transparent", outlineWidth: 0, color: surface.ink, fontFamily, ...inputTypeStyle(size), textAlign: "center", paddingHorizontal: surface.spec.padding - tokens61.border.controlWidth, paddingVertical: 0 }
10461
10625
  }
10462
10626
  ) }),
10463
10627
  /* @__PURE__ */ jsx62(CompoundTarget, { square: true, children: /* @__PURE__ */ jsx62(KjunButton, { size, style: increaseStyle, variant: "ghost", ariaLabel: m.increaseQuantity, disabled: blocked || max !== void 0 && value >= max, onPress: () => move(1), prefixIcon: "plus" }) }),
10464
- (invalid || surface.active) && /* @__PURE__ */ jsx62(View53, { pointerEvents: "none", "aria-hidden": true, style: { ...surfaceBox, borderWidth: invalid ? tokens60.border.controlWidth : tokens60.states.focus.width, borderColor: invalid ? colors.danger : colors.focusRing } })
10628
+ (invalid || surface.active) && /* @__PURE__ */ jsx62(View53, { pointerEvents: "none", "aria-hidden": true, style: { ...surfaceBox, borderWidth: invalid ? tokens61.border.controlWidth : tokens61.states.focus.width, borderColor: invalid ? colors.danger : colors.focusRing } })
10465
10629
  ] }) });
10466
10630
  }
10467
10631
 
10468
10632
  // packages/native/src/time-picker.tsx
10469
- import { Fragment as Fragment21, useEffect as useEffect29, useId as useId11, useMemo as useMemo4, useRef as useRef36, useState as useState44 } from "react";
10633
+ import { Fragment as Fragment21, useEffect as useEffect30, useId as useId11, useMemo as useMemo4, useRef as useRef39, useState as useState44 } from "react";
10470
10634
  import { View as View54 } from "react-native";
10471
- import { createTimeDomain, tokens as tokens61 } from "@kjun-ui/tokens";
10635
+ import { createTimeDomain, tokens as tokens62 } from "@kjun-ui/tokens";
10472
10636
  import { jsx as jsx63, jsxs as jsxs46 } from "react/jsx-runtime";
10473
10637
  function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1, secondStep = 1, disabled = false, error = false, clearable = true, size = "md", ariaLabel, onValueChange, onChangeCommit }) {
10474
10638
  const m = useKjunMessages();
10475
10639
  ariaLabel != null ? ariaLabel : ariaLabel = m.time;
10476
- const geometry2 = tokens61.extensions.timePicker, spec = tokens61.input[size];
10640
+ const geometry2 = tokens62.extensions.timePicker, spec = tokens62.input[size];
10477
10641
  const { colors } = useKjunStyles();
10478
- const first = useRef36(null);
10642
+ const first = useRef39(null);
10479
10643
  const [focused, setFocused] = useState44(false), [opened, setOpened] = useState44(null);
10480
10644
  const field = useKjunField(), uid = useId11();
10481
10645
  const fieldId = (field == null ? void 0 : field.id) || `kjun-time-${uid}`;
10482
10646
  const domain = useMemo4(() => createTimeDomain({ precision, min, max, minuteStep, secondStep }), [precision, min, max, minuteStep, secondStep]), valid = domain.valid && domain.accepts(value);
10483
- useEffect29(() => {
10647
+ useEffect30(() => {
10484
10648
  if (!valid) console.warn("KJUN TimePicker: \uC2DC\uAC01 \uBC94\uC704\xB7\uAC04\uACA9\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10485
10649
  }, [valid]);
10486
10650
  const change = (next) => {
@@ -10497,12 +10661,12 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
10497
10661
  if (typeof next === "number") change(domain.select(value, index, next));
10498
10662
  }, onOpenChange: (open) => setOpened(open ? index : null), ariaLabel: ((field == null ? void 0 : field.label) || ariaLabel) + " " + label, placeholder: label, disabled: disabled || !valid, error, size, clearable: false, searchable: false }) }) }) })
10499
10663
  ] }, label)) }),
10500
- clearable && value !== null && /* @__PURE__ */ jsx63(View54, { style: { marginVertical: Math.min(0, (spec.height - tokens61.native.minimumTouchTarget) / 2) }, children: /* @__PURE__ */ jsx63(FieldClear, { size, label: m.clearValue(ariaLabel), disabled: disabled || !valid, onPress: () => {
10664
+ clearable && value !== null && /* @__PURE__ */ jsx63(View54, { style: { marginVertical: Math.min(0, (spec.height - tokens62.native.minimumTouchTarget) / 2) }, children: /* @__PURE__ */ jsx63(FieldClear, { size, label: m.clearValue(ariaLabel), disabled: disabled || !valid, onPress: () => {
10501
10665
  var _a;
10502
10666
  change(null);
10503
10667
  (_a = first.current) == null ? void 0 : _a.focus();
10504
10668
  } }) }),
10505
- !!(error || !!(field == null ? void 0 : field.error) || focused || opened !== null) && /* @__PURE__ */ jsx63(View54, { pointerEvents: "none", "aria-hidden": true, style: { position: "absolute", inset: 0, borderRadius: spec.radius, borderWidth: error || !!(field == null ? void 0 : field.error) ? tokens61.border.controlWidth : tokens61.states.focus.width, borderColor: error || (field == null ? void 0 : field.error) ? colors.danger : colors.focusRing } })
10669
+ !!(error || !!(field == null ? void 0 : field.error) || focused || opened !== null) && /* @__PURE__ */ jsx63(View54, { pointerEvents: "none", "aria-hidden": true, style: { position: "absolute", inset: 0, borderRadius: spec.radius, borderWidth: error || !!(field == null ? void 0 : field.error) ? tokens62.border.controlWidth : tokens62.states.focus.width, borderColor: error || (field == null ? void 0 : field.error) ? colors.danger : colors.focusRing } })
10506
10670
  ] });
10507
10671
  }
10508
10672
  export {
@@ -10551,6 +10715,7 @@ export {
10551
10715
  KjunInput,
10552
10716
  KjunKpiHero,
10553
10717
  KjunKpiRow,
10718
+ KjunListItem,
10554
10719
  KjunListRow,
10555
10720
  KjunListSection,
10556
10721
  KjunListSkeleton,
@@ -10590,6 +10755,7 @@ export {
10590
10755
  KjunTimePicker,
10591
10756
  KjunTooltip,
10592
10757
  KjunTopNavigation,
10758
+ createKjunFeedback,
10593
10759
  kjunMessagesEn,
10594
10760
  kjunMessagesKo,
10595
10761
  useKjunFeedback,