@kjun-ui/native 0.14.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.
@@ -1898,13 +1898,25 @@ function KjunFormLayout({
1898
1898
  ) });
1899
1899
  }
1900
1900
 
1901
- // shared/package-runtime/content-presence.ts
1901
+ // shared/package-runtime/use-after-close.ts
1902
1902
  var import_react19 = require("react");
1903
+ function useAfterClose(present, onAfterClose, enabled2 = true) {
1904
+ const was = (0, import_react19.useRef)(present), callback = (0, import_react19.useRef)(onAfterClose);
1905
+ callback.current = onAfterClose;
1906
+ (0, import_react19.useEffect)(() => {
1907
+ var _a;
1908
+ if (was.current && !present && enabled2) (_a = callback.current) == null ? void 0 : _a.call(callback);
1909
+ was.current = present;
1910
+ }, [present, enabled2]);
1911
+ }
1912
+
1913
+ // shared/package-runtime/content-presence.ts
1914
+ var import_react20 = require("react");
1903
1915
  function hasContent(node) {
1904
1916
  if (node == null || typeof node === "boolean") return false;
1905
1917
  if (typeof node === "string") return node.trim().length > 0;
1906
1918
  if (Array.isArray(node)) return node.some(hasContent);
1907
- if ((0, import_react19.isValidElement)(node) && node.type === import_react19.Fragment)
1919
+ if ((0, import_react20.isValidElement)(node) && node.type === import_react20.Fragment)
1908
1920
  return hasContent(node.props.children);
1909
1921
  return true;
1910
1922
  }
@@ -1917,7 +1929,7 @@ function LayerBackdrop({ onPress, style }) {
1917
1929
  }
1918
1930
 
1919
1931
  // packages/native/src/modal.tsx
1920
- var import_react22 = require("react");
1932
+ var import_react23 = require("react");
1921
1933
 
1922
1934
  // shared/package-runtime/form-actions.ts
1923
1935
  function formActionsNeedStack(width, widths, gap) {
@@ -1930,17 +1942,17 @@ var import_tokens11 = require("@kjun-ui/tokens");
1930
1942
  var import_react_native14 = require("react-native");
1931
1943
 
1932
1944
  // packages/native/src/overlay-host.tsx
1933
- var import_react21 = require("react");
1945
+ var import_react22 = require("react");
1934
1946
  var import_react_native12 = require("react-native");
1935
1947
 
1936
1948
  // packages/native/src/modal-window.web.tsx
1937
- var import_react20 = require("react");
1949
+ var import_react21 = require("react");
1938
1950
  var import_react_dom = require("react-dom");
1939
1951
  var import_react_native11 = require("react-native");
1940
1952
  var import_jsx_runtime11 = require("react/jsx-runtime");
1941
1953
  function ModalWindow({ generation, children, visible, ...props }) {
1942
- const [container, setContainer] = (0, import_react20.useState)(null);
1943
- (0, import_react20.useLayoutEffect)(() => {
1954
+ const [container, setContainer] = (0, import_react21.useState)(null);
1955
+ (0, import_react21.useLayoutEffect)(() => {
1944
1956
  const element = document.createElement("div");
1945
1957
  element.style.display = "contents";
1946
1958
  setContainer(element);
@@ -1961,17 +1973,18 @@ var import_jsx_runtime12 = (
1961
1973
  // a new window even when an interrupted exit retained the old surface.
1962
1974
  require("react/jsx-runtime")
1963
1975
  );
1964
- var FeedbackOverlayContext = (0, import_react21.createContext)(
1976
+ var FeedbackOverlayContext = (0, import_react22.createContext)(
1965
1977
  null
1966
1978
  );
1967
1979
  function ScopedNativeModal({ children, visible, ...props }) {
1968
- var _a;
1969
- const layers = useLayerState(), scope = (0, import_react21.useContext)(LayerScope);
1980
+ const layers = useLayerState(), scope = (0, import_react22.useContext)(LayerScope);
1970
1981
  const entry = scope ? layers.entries.get(scope) : void 0;
1971
- const generation = (_a = entry == null ? void 0 : entry.order) != null ? _a : 0;
1982
+ const last = (0, import_react22.useRef)(0);
1983
+ if (entry) last.current = entry.order;
1984
+ const generation = last.current;
1972
1985
  const inactive = !!scope && !layers.isActive(scope);
1973
- const host = (0, import_react21.useContext)(FeedbackOverlayContext), id = "kjun-" + (0, import_react21.useId)(), register = host == null ? void 0 : host.register;
1974
- (0, import_react21.useEffect)(
1986
+ const host = (0, import_react22.useContext)(FeedbackOverlayContext), id = "kjun-" + (0, import_react22.useId)(), register = host == null ? void 0 : host.register;
1987
+ (0, import_react22.useEffect)(
1975
1988
  () => visible && register ? register(id) : void 0,
1976
1989
  [visible, register, id, generation]
1977
1990
  );
@@ -2020,7 +2033,7 @@ function KjunFormActions({
2020
2033
  cancelText != null ? cancelText : cancelText = m.cancel;
2021
2034
  confirmText != null ? confirmText : confirmText = m.save;
2022
2035
  const { fontFamily } = useKjunStyles();
2023
- const [width, setWidth] = (0, import_react22.useState)(0), [measurements, setMeasurements] = (0, import_react22.useState)({});
2036
+ const [width, setWidth] = (0, import_react23.useState)(0), [measurements, setMeasurements] = (0, import_react23.useState)({});
2024
2037
  const labels = [showCancel && { text: cancelText }, showConfirm && { text: confirmText }].filter(Boolean);
2025
2038
  const keyFor = (text) => `${fontFamily}:${size}:${text}`;
2026
2039
  const widths = labels.map((label) => measurements[keyFor(label.text)] === void 0 ? 0 : Math.max(import_tokens11.tokens.button.minWidths[size], measurements[keyFor(label.text)] + import_tokens11.tokens.button.paddingX[size] * 2));
@@ -2092,6 +2105,7 @@ function KjunModal({
2092
2105
  open,
2093
2106
  onOpenChange,
2094
2107
  onClose,
2108
+ onAfterClose,
2095
2109
  onCancel,
2096
2110
  onConfirm,
2097
2111
  title = "",
@@ -2124,7 +2138,7 @@ function KjunModal({
2124
2138
  const motion = useNativePresence(open, import_tokens11.tokens.motion.layerEnter, import_tokens11.tokens.motion.layerExit, true, 0, { fade: import_tokens11.tokens.motion.backdropExit });
2125
2139
  const offset = useMotionValue(open ? 0 : import_tokens11.tokens.motionDistance.modalExit, open ? import_tokens11.tokens.motion.layerEnter : import_tokens11.tokens.motion.layerExit, import_tokens11.tokens.motionDistance.modalEnter, open ? motionOut : motionIn, true);
2126
2140
  const backdrop = useNativePresence(open, import_tokens11.tokens.motion.backdrop, import_tokens11.tokens.motion.backdropExit, true, 0, { fade: import_tokens11.tokens.motion.backdropExit });
2127
- (0, import_react22.useLayoutEffect)(() => {
2141
+ (0, import_react23.useLayoutEffect)(() => {
2128
2142
  if (!motion.present) {
2129
2143
  offset.stopAnimation();
2130
2144
  offset.setValue(import_tokens11.tokens.motionDistance.modalEnter);
@@ -2139,10 +2153,15 @@ function KjunModal({
2139
2153
  const layer = useLayer(open, motion.present, "window", () => {
2140
2154
  if (closeOnEsc) close();
2141
2155
  });
2156
+ const iosDismiss = import_react_native14.Platform.OS === "ios";
2157
+ useAfterClose(motion.present, onAfterClose, !iosDismiss);
2142
2158
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LayerScope.Provider, { value: layer.id, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2143
2159
  ScopedNativeModal,
2144
2160
  {
2145
2161
  visible: motion.present,
2162
+ onDismiss: iosDismiss ? () => {
2163
+ if (!open) onAfterClose == null ? void 0 : onAfterClose();
2164
+ } : void 0,
2146
2165
  transparent: true,
2147
2166
  animationType: "none",
2148
2167
  onRequestClose: () => {
@@ -2300,7 +2319,7 @@ function KjunModal({
2300
2319
 
2301
2320
  // packages/native/src/card.tsx
2302
2321
  var import_tokens12 = require("@kjun-ui/tokens");
2303
- var import_react23 = require("react");
2322
+ var import_react24 = require("react");
2304
2323
  var import_react_native15 = require("react-native");
2305
2324
  var import_react_native_svg2 = __toESM(require("react-native-svg"), 1);
2306
2325
  var import_jsx_runtime14 = require("react/jsx-runtime");
@@ -2326,7 +2345,7 @@ function KjunCard({
2326
2345
  onPress
2327
2346
  }) {
2328
2347
  const { colors } = useKjunStyles();
2329
- const id = "kjun-" + (0, import_react23.useId)().replace(/[^a-z0-9]/gi, "");
2348
+ const id = "kjun-" + (0, import_react24.useId)().replace(/[^a-z0-9]/gi, "");
2330
2349
  const inset = import_tokens12.tokens.card.padding[padding], bodyInset = import_tokens12.tokens.card.padding[bodyPadding];
2331
2350
  const corner = import_tokens12.tokens.card.radii[radius];
2332
2351
  const paint = import_tokens12.tokens.cardSurfaces[surface];
@@ -2410,7 +2429,7 @@ function alertRole(tone, live) {
2410
2429
 
2411
2430
  // packages/native/src/display-primitives.tsx
2412
2431
  var import_tokens14 = require("@kjun-ui/tokens");
2413
- var import_react24 = require("react");
2432
+ var import_react25 = require("react");
2414
2433
  var import_react_native16 = require("react-native");
2415
2434
  var import_react_native_svg3 = __toESM(require("react-native-svg"), 1);
2416
2435
 
@@ -2534,7 +2553,7 @@ function KjunEmpty({
2534
2553
  text != null ? text : text = m.noData;
2535
2554
  const { colors } = useKjunStyles();
2536
2555
  const spec = import_tokens14.tokens.extensions.empty;
2537
- const stateContent = (0, import_react24.useContext)(DataStateContentContext);
2556
+ const stateContent = (0, import_react25.useContext)(DataStateContentContext);
2538
2557
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2539
2558
  import_react_native16.View,
2540
2559
  {
@@ -2568,8 +2587,8 @@ function KjunEmpty({
2568
2587
  }
2569
2588
  function KjunSpinner({ size = "md", text }) {
2570
2589
  const m = useKjunMessages();
2571
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), rotation = (0, import_react24.useRef)(new import_react_native16.Animated.Value(0)).current;
2572
- (0, import_react24.useEffect)(() => {
2590
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), rotation = (0, import_react25.useRef)(new import_react_native16.Animated.Value(0)).current;
2591
+ (0, import_react25.useEffect)(() => {
2573
2592
  if (reduced) return;
2574
2593
  const loop = import_react_native16.Animated.loop(
2575
2594
  import_react_native16.Animated.timing(rotation, {
@@ -2658,7 +2677,7 @@ function KjunAlert({
2658
2677
  }) {
2659
2678
  const m = useKjunMessages();
2660
2679
  const { colors } = useKjunStyles();
2661
- const [visible, setVisible] = (0, import_react24.useState)(true);
2680
+ const [visible, setVisible] = (0, import_react25.useState)(true);
2662
2681
  if (!visible) return null;
2663
2682
  const tone = variant || (type === "error" ? "danger" : type), small = size === "sm";
2664
2683
  const geometry2 = import_tokens14.tokens.extensions.alert;
@@ -2862,7 +2881,7 @@ function KjunProgress({
2862
2881
 
2863
2882
  // packages/native/src/skeleton-base.tsx
2864
2883
  var import_tokens15 = require("@kjun-ui/tokens");
2865
- var import_react25 = require("react");
2884
+ var import_react26 = require("react");
2866
2885
  var import_react_native17 = require("react-native");
2867
2886
  var import_jsx_runtime16 = require("react/jsx-runtime");
2868
2887
  function KjunSkeleton({
@@ -2874,8 +2893,8 @@ function KjunSkeleton({
2874
2893
  animated = true,
2875
2894
  rounded = true
2876
2895
  }) {
2877
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = (0, import_react25.useRef)(new import_react_native17.Animated.Value(1)).current;
2878
- (0, import_react25.useEffect)(() => {
2896
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = (0, import_react26.useRef)(new import_react_native17.Animated.Value(1)).current;
2897
+ (0, import_react26.useEffect)(() => {
2879
2898
  if (!animated || reduced) return;
2880
2899
  const loop = import_react_native17.Animated.loop(
2881
2900
  import_react_native17.Animated.sequence([
@@ -3030,7 +3049,7 @@ function KjunSkeleton({
3030
3049
  }
3031
3050
 
3032
3051
  // packages/native/src/layout-primitives.tsx
3033
- var import_react26 = require("react");
3052
+ var import_react27 = require("react");
3034
3053
  var import_react_native18 = require("react-native");
3035
3054
  var import_tokens16 = require("@kjun-ui/tokens");
3036
3055
 
@@ -3053,13 +3072,15 @@ var toneRole = {
3053
3072
  inverse: "onBrand"
3054
3073
  };
3055
3074
  var textAlign = { start: "left", center: "center", end: "right" };
3056
- function KjunText({ variant = "body", tone = "default", align, maxLines, style, children }) {
3075
+ function KjunText({ variant = "body", tone = "default", align, maxLines, style, children, ...rest }) {
3076
+ var _a;
3057
3077
  const { colors, fontFamily, numericFontFamily } = useKjunStyles();
3058
3078
  const lines = maxLines && maxLines > 0 ? Math.floor(maxLines) : void 0;
3059
3079
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3060
3080
  KText,
3061
3081
  {
3062
- accessibilityRole: titleVariants.includes(variant) ? "header" : void 0,
3082
+ ...rest,
3083
+ accessibilityRole: (_a = rest.accessibilityRole) != null ? _a : titleVariants.includes(variant) ? "header" : void 0,
3063
3084
  numberOfLines: lines,
3064
3085
  ellipsizeMode: lines ? "tail" : void 0,
3065
3086
  style: [
@@ -3074,23 +3095,23 @@ function KjunText({ variant = "body", tone = "default", align, maxLines, style,
3074
3095
  );
3075
3096
  }
3076
3097
  function flatten(children, path = "") {
3077
- return import_react26.Children.toArray(children).flatMap((child, i) => {
3098
+ return import_react27.Children.toArray(children).flatMap((child, i) => {
3078
3099
  const key = `${path}${i}`;
3079
- return (0, import_react26.isValidElement)(child) && child.type === import_react26.Fragment ? flatten(child.props.children, `${key}.`) : [[key, child]];
3100
+ return (0, import_react27.isValidElement)(child) && child.type === import_react27.Fragment ? flatten(child.props.children, `${key}.`) : [[key, child]];
3080
3101
  });
3081
3102
  }
3082
3103
  function items(children, childAlign) {
3083
3104
  return flatten(children).map(([key, child]) => {
3084
3105
  if (typeof child === "string" || typeof child === "number") return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(KText, { children: child }, key);
3085
- if ((0, import_react26.isValidElement)(child) && child.type === KjunFormGroup) {
3106
+ if ((0, import_react27.isValidElement)(child) && child.type === KjunFormGroup) {
3086
3107
  const group = child;
3087
- return (0, import_react26.cloneElement)(group, { key, style: [{ marginBottom: 0 }, group.props.style] });
3108
+ return (0, import_react27.cloneElement)(group, { key, style: [{ marginBottom: 0 }, group.props.style] });
3088
3109
  }
3089
- if (childAlign && (0, import_react26.isValidElement)(child) && (child.type === KjunButton || child.type === KjunBadge)) {
3110
+ if (childAlign && (0, import_react27.isValidElement)(child) && (child.type === KjunButton || child.type === KjunBadge)) {
3090
3111
  const control = child;
3091
- return (0, import_react26.cloneElement)(control, { key, style: [{ alignSelf: childAlign }, control.props.style] });
3112
+ return (0, import_react27.cloneElement)(control, { key, style: [{ alignSelf: childAlign }, control.props.style] });
3092
3113
  }
3093
- return (0, import_react26.isValidElement)(child) ? (0, import_react26.cloneElement)(child, { key }) : child;
3114
+ return (0, import_react27.isValidElement)(child) ? (0, import_react27.cloneElement)(child, { key }) : child;
3094
3115
  });
3095
3116
  }
3096
3117
  var followed = (align) => align && align !== "stretch" ? crossAxis[align] : void 0;
@@ -3127,13 +3148,13 @@ function KjunInline({ gap = "sm", align, justify = "start", wrap = true, style,
3127
3148
  }
3128
3149
 
3129
3150
  // shared/package-runtime/feedback-dialog.ts
3130
- var import_react27 = require("react");
3151
+ var import_react28 = require("react");
3131
3152
  function useFeedbackDialog(controller, request, messages = kjunMessagesKo) {
3132
3153
  const options = request.options;
3133
- const [value, setValue] = (0, import_react27.useState)(options.initialValue || "");
3134
- const [error, setError] = (0, import_react27.useState)("");
3135
- const [busy, setBusy] = (0, import_react27.useState)(false);
3136
- const working = (0, import_react27.useRef)(false);
3154
+ const [value, setValue] = (0, import_react28.useState)(options.initialValue || "");
3155
+ const [error, setError] = (0, import_react28.useState)("");
3156
+ const [busy, setBusy] = (0, import_react28.useState)(false);
3157
+ const working = (0, import_react28.useRef)(false);
3137
3158
  const active = () => {
3138
3159
  var _a;
3139
3160
  return ((_a = controller.getSnapshot().current) == null ? void 0 : _a.id) === request.id;
@@ -3176,11 +3197,11 @@ function useFeedbackDialog(controller, request, messages = kjunMessagesKo) {
3176
3197
 
3177
3198
  // shared/package-runtime/feedback-motion.ts
3178
3199
  var import_tokens17 = require("@kjun-ui/tokens");
3179
- var import_react28 = require("react");
3200
+ var import_react29 = require("react");
3180
3201
  function usePresentedToasts(toasts, reduced) {
3181
- const [items2, setItems] = (0, import_react28.useState)([]);
3182
- const removals = (0, import_react28.useRef)(/* @__PURE__ */ new Map());
3183
- (0, import_react28.useLayoutEffect)(() => {
3202
+ const [items2, setItems] = (0, import_react29.useState)([]);
3203
+ const removals = (0, import_react29.useRef)(/* @__PURE__ */ new Map());
3204
+ (0, import_react29.useLayoutEffect)(() => {
3184
3205
  const ids = new Set(toasts.map((toast) => toast.id));
3185
3206
  setItems((previous) => {
3186
3207
  const old = new Map(previous.map((item) => [item.toast.id, item]));
@@ -3202,15 +3223,15 @@ function usePresentedToasts(toasts, reduced) {
3202
3223
  removals.current.clear();
3203
3224
  }
3204
3225
  }, [toasts, reduced]);
3205
- (0, import_react28.useLayoutEffect)(() => () => {
3226
+ (0, import_react29.useLayoutEffect)(() => () => {
3206
3227
  for (const timer of removals.current.values()) clearTimeout(timer);
3207
3228
  removals.current.clear();
3208
3229
  }, []);
3209
3230
  return items2;
3210
3231
  }
3211
3232
  function usePresentedRequest(current, reduced) {
3212
- const [request, setRequest] = (0, import_react28.useState)(current);
3213
- (0, import_react28.useLayoutEffect)(() => {
3233
+ const [request, setRequest] = (0, import_react29.useState)(current);
3234
+ (0, import_react29.useLayoutEffect)(() => {
3214
3235
  if (!request || request.id === (current == null ? void 0 : current.id) || reduced) {
3215
3236
  setRequest(current);
3216
3237
  return;
@@ -3222,14 +3243,14 @@ function usePresentedRequest(current, reduced) {
3222
3243
  }
3223
3244
 
3224
3245
  // packages/native/src/feedback-context.ts
3225
- var import_react29 = require("react");
3226
- var KjunFeedbackContext = (0, import_react29.createContext)(null);
3246
+ var import_react30 = require("react");
3247
+ var KjunFeedbackContext = (0, import_react30.createContext)(null);
3227
3248
  function useOptionalKjunFeedback() {
3228
- return (0, import_react29.useContext)(KjunFeedbackContext);
3249
+ return (0, import_react30.useContext)(KjunFeedbackContext);
3229
3250
  }
3230
3251
 
3231
3252
  // packages/native/src/toast-stack.tsx
3232
- var import_react32 = require("react");
3253
+ var import_react33 = require("react");
3233
3254
  var import_react_native20 = require("react-native");
3234
3255
  var import_tokens20 = require("@kjun-ui/tokens");
3235
3256
 
@@ -3247,7 +3268,7 @@ function shadowLayers(layers, colors) {
3247
3268
 
3248
3269
  // packages/native/src/toast.tsx
3249
3270
  var import_tokens18 = require("@kjun-ui/tokens");
3250
- var import_react30 = require("react");
3271
+ var import_react31 = require("react");
3251
3272
  var import_react_native19 = require("react-native");
3252
3273
  var import_jsx_runtime18 = require("react/jsx-runtime");
3253
3274
  function ToastView({
@@ -3255,14 +3276,14 @@ function ToastView({
3255
3276
  controller
3256
3277
  }) {
3257
3278
  const m = useKjunMessages();
3258
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), progress = (0, import_react30.useRef)(new import_react_native19.Animated.Value(1)).current;
3259
- const reasons = (0, import_react30.useRef)({
3279
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), progress = (0, import_react31.useRef)(new import_react_native19.Animated.Value(1)).current;
3280
+ const reasons = (0, import_react31.useRef)({
3260
3281
  hover: /* @__PURE__ */ Symbol("hover"),
3261
3282
  actionHover: /* @__PURE__ */ Symbol("actionHover"),
3262
3283
  closeHover: /* @__PURE__ */ Symbol("closeHover"),
3263
3284
  focus: /* @__PURE__ */ Symbol("focus")
3264
3285
  }).current;
3265
- (0, import_react30.useEffect)(() => () => {
3286
+ (0, import_react31.useEffect)(() => () => {
3266
3287
  for (const reason of Object.values(reasons)) controller.resumeToast(toast.id, reason);
3267
3288
  }, [controller, toast.id, reasons]);
3268
3289
  const tone = toast.type === "error" ? "danger" : toast.type || "info", icon = {
@@ -3271,7 +3292,7 @@ function ToastView({
3271
3292
  warning: "alert-triangle",
3272
3293
  info: "info-circle"
3273
3294
  }[tone];
3274
- (0, import_react30.useEffect)(() => {
3295
+ (0, import_react31.useEffect)(() => {
3275
3296
  progress.stopAnimation();
3276
3297
  progress.setValue(toast.duration ? toast.remaining / toast.duration : 1);
3277
3298
  if (!toast.paused && !reduced) {
@@ -3385,7 +3406,7 @@ function ToastView({
3385
3406
  }
3386
3407
 
3387
3408
  // packages/native/src/toast-reflow.web.ts
3388
- var import_react31 = require("react");
3409
+ var import_react32 = require("react");
3389
3410
 
3390
3411
  // shared/package-runtime/toast-layout.ts
3391
3412
  var import_tokens19 = require("@kjun-ui/tokens");
@@ -3448,27 +3469,27 @@ function createToastLayout() {
3448
3469
 
3449
3470
  // packages/native/src/toast-reflow.web.ts
3450
3471
  function useToastReflow(root, reduced) {
3451
- const layout = (0, import_react31.useRef)(createToastLayout()).current;
3452
- (0, import_react31.useLayoutEffect)(() => {
3472
+ const layout = (0, import_react32.useRef)(createToastLayout()).current;
3473
+ (0, import_react32.useLayoutEffect)(() => {
3453
3474
  if (root.current) layout.update(root.current, reduced);
3454
3475
  });
3455
- (0, import_react31.useLayoutEffect)(() => () => layout.destroy(), [layout]);
3476
+ (0, import_react32.useLayoutEffect)(() => () => layout.destroy(), [layout]);
3456
3477
  }
3457
3478
 
3458
3479
  // packages/native/src/toast-stack.tsx
3459
3480
  var import_jsx_runtime19 = require("react/jsx-runtime");
3460
3481
  function ToastSlot({ item, controller, boxes }) {
3461
- const born = (0, import_react32.useRef)(Math.min(import_tokens20.tokens.motion.toastEnter, Date.now() - item.born)).current;
3482
+ const born = (0, import_react33.useRef)(Math.min(import_tokens20.tokens.motion.toastEnter, Date.now() - item.born)).current;
3462
3483
  const motion = useNativePresence(!item.exiting, import_tokens20.tokens.motion.toastEnter - born, import_tokens20.tokens.motion.toastExit, true, born / import_tokens20.tokens.motion.toastEnter);
3463
- const offset = (0, import_react32.useRef)(new import_react_native20.Animated.Value(0)).current;
3484
+ const offset = (0, import_react33.useRef)(new import_react_native20.Animated.Value(0)).current;
3464
3485
  const box = boxes.get(item.toast.id);
3465
- (0, import_react32.useLayoutEffect)(() => {
3486
+ (0, import_react33.useLayoutEffect)(() => {
3466
3487
  if (motion.reduced) {
3467
3488
  offset.stopAnimation();
3468
3489
  offset.setValue(0);
3469
3490
  }
3470
3491
  }, [motion.reduced, offset]);
3471
- (0, import_react32.useLayoutEffect)(() => () => offset.stopAnimation(), [offset]);
3492
+ (0, import_react33.useLayoutEffect)(() => () => offset.stopAnimation(), [offset]);
3472
3493
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3473
3494
  import_react_native20.Animated.View,
3474
3495
  {
@@ -3507,9 +3528,9 @@ function ToastSlot({ item, controller, boxes }) {
3507
3528
  function ToastStack({ items: items2, controller }) {
3508
3529
  var _a;
3509
3530
  const layers = useLayerState();
3510
- const root = (0, import_react32.useRef)(null), reduced = useReducedMotion();
3531
+ const root = (0, import_react33.useRef)(null), reduced = useReducedMotion();
3511
3532
  useToastReflow(root, reduced);
3512
- const boxes = (0, import_react32.useRef)(/* @__PURE__ */ new Map()).current;
3533
+ const boxes = (0, import_react33.useRef)(/* @__PURE__ */ new Map()).current;
3513
3534
  for (const id of boxes.keys()) if (!items2.some((item) => item.toast.id === id)) boxes.delete(id);
3514
3535
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_native20.View, { ref: root, pointerEvents: "box-none", style: {
3515
3536
  position: "absolute",
@@ -3524,7 +3545,7 @@ function ToastStack({ items: items2, controller }) {
3524
3545
 
3525
3546
  // packages/native/src/feedback.tsx
3526
3547
  var import_tokens21 = require("@kjun-ui/tokens");
3527
- var import_react33 = require("react");
3548
+ var import_react34 = require("react");
3528
3549
  var import_react_native21 = require("react-native");
3529
3550
  var import_tokens22 = require("@kjun-ui/tokens");
3530
3551
  var import_jsx_runtime20 = require("react/jsx-runtime");
@@ -3576,11 +3597,11 @@ function FeedbackDialog({
3576
3597
  );
3577
3598
  }
3578
3599
  function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3579
- const [owned] = (0, import_react33.useState)(() => controllerProp ? void 0 : (0, import_tokens21.createFeedbackController)());
3600
+ const [owned] = (0, import_react34.useState)(() => controllerProp ? void 0 : (0, import_tokens21.createFeedbackController)());
3580
3601
  const controller = controllerProp ? (0, import_tokens21.feedbackControllerOf)(controllerProp) : owned;
3581
- (0, import_react33.useEffect)(() => controller.attach(), [controller]);
3582
- const life = (0, import_react33.useRef)(0);
3583
- const snapshot = (0, import_react33.useSyncExternalStore)(
3602
+ (0, import_react34.useEffect)(() => controller.attach(), [controller]);
3603
+ const life = (0, import_react34.useRef)(0);
3604
+ const snapshot = (0, import_react34.useSyncExternalStore)(
3584
3605
  controller.subscribe,
3585
3606
  controller.getSnapshot,
3586
3607
  controller.getSnapshot
@@ -3588,7 +3609,7 @@ function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3588
3609
  const reduced = useReducedMotion();
3589
3610
  const toasts = usePresentedToasts(snapshot.toasts, reduced);
3590
3611
  const dialog = usePresentedRequest(snapshot.current, reduced);
3591
- (0, import_react33.useEffect)(() => {
3612
+ (0, import_react34.useEffect)(() => {
3592
3613
  const version = ++life.current;
3593
3614
  return () => {
3594
3615
  queueMicrotask(() => {
@@ -3596,8 +3617,8 @@ function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3596
3617
  });
3597
3618
  };
3598
3619
  }, [controller]);
3599
- const [layers, setLayers] = (0, import_react33.useState)([]);
3600
- const register = (0, import_react33.useCallback)((id) => {
3620
+ const [layers, setLayers] = (0, import_react34.useState)([]);
3621
+ const register = (0, import_react34.useCallback)((id) => {
3601
3622
  setLayers((previous) => [...previous, id]);
3602
3623
  return () => setLayers((previous) => previous.filter((item) => item !== id));
3603
3624
  }, []);
@@ -3628,7 +3649,7 @@ function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3628
3649
  // packages/native/src/choice-controls.tsx
3629
3650
  var import_react_native22 = require("react-native");
3630
3651
  var import_tokens23 = require("@kjun-ui/tokens");
3631
- var import_react34 = require("react");
3652
+ var import_react35 = require("react");
3632
3653
  var import_react_native23 = require("react-native");
3633
3654
  var import_jsx_runtime21 = require("react/jsx-runtime");
3634
3655
  function KjunCheckbox({
@@ -3699,7 +3720,7 @@ function KjunCheckbox({
3699
3720
  }
3700
3721
  function useControlFocus(disabled) {
3701
3722
  const { colors } = useKjunStyles();
3702
- const [focused, setFocused] = (0, import_react34.useState)(false);
3723
+ const [focused, setFocused] = (0, import_react35.useState)(false);
3703
3724
  return {
3704
3725
  handlers: {
3705
3726
  focusRing: false,
@@ -3728,7 +3749,7 @@ function KjunSwitch({
3728
3749
  const offset = width - height;
3729
3750
  const motion = useMotionValue(value ? 1 : 0);
3730
3751
  const focus = useControlFocus(disabled);
3731
- const [hovered, setHovered] = (0, import_react34.useState)(false);
3752
+ const [hovered, setHovered] = (0, import_react35.useState)(false);
3732
3753
  const trackColor = typeof colors.active === "string" && typeof colors.brand === "string" ? motion.interpolate({ inputRange: [0, 1], outputRange: [colors.active, colors.brand] }) : value ? colors.brand : colors.active;
3733
3754
  const offRole = disabled ? colors.borderSecondary : colors.borderStrong;
3734
3755
  const thumbColor = typeof offRole === "string" && typeof colors.switchThumbOn === "string" ? motion.interpolate({ inputRange: [0, 1], outputRange: [offRole, colors.switchThumbOn] }) : value ? colors.switchThumbOn : offRole;
@@ -3813,7 +3834,7 @@ function KjunSwitch({
3813
3834
  }
3814
3835
  );
3815
3836
  }
3816
- var RadioContext = (0, import_react34.createContext)(null);
3837
+ var RadioContext = (0, import_react35.createContext)(null);
3817
3838
  function KjunRadio({
3818
3839
  value,
3819
3840
  val,
@@ -3824,10 +3845,10 @@ function KjunRadio({
3824
3845
  onValueChange,
3825
3846
  onChange
3826
3847
  }) {
3827
- const group = (0, import_react34.useContext)(RadioContext), { colors } = useKjunStyles(), selected = (group ? group.value : value) === val;
3848
+ const group = (0, import_react35.useContext)(RadioContext), { colors } = useKjunStyles(), selected = (group ? group.value : value) === val;
3828
3849
  const geometry2 = import_tokens23.tokens.extensions.radio;
3829
- const [hovered, setHovered] = (0, import_react34.useState)(false);
3830
- (0, import_react34.useEffect)(() => {
3850
+ const [hovered, setHovered] = (0, import_react35.useState)(false);
3851
+ (0, import_react35.useEffect)(() => {
3831
3852
  if (disabled) setHovered(false);
3832
3853
  }, [disabled]);
3833
3854
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
@@ -3899,7 +3920,7 @@ function KjunRadioGroup({
3899
3920
  onValueChange,
3900
3921
  onChange
3901
3922
  }) {
3902
- const root = (0, import_react34.useRef)(null);
3923
+ const root = (0, import_react35.useRef)(null);
3903
3924
  useRadioKeyboard(root);
3904
3925
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3905
3926
  RadioContext.Provider,
@@ -3939,11 +3960,11 @@ function KjunRadioGroup({
3939
3960
 
3940
3961
  // packages/native/src/selection-groups.tsx
3941
3962
  var import_tokens25 = require("@kjun-ui/tokens");
3942
- var import_react36 = require("react");
3963
+ var import_react37 = require("react");
3943
3964
  var import_react_native25 = require("react-native");
3944
3965
 
3945
3966
  // packages/native/src/button-group-motion.tsx
3946
- var import_react35 = require("react");
3967
+ var import_react36 = require("react");
3947
3968
  var import_react_native24 = require("react-native");
3948
3969
  var import_tokens24 = require("@kjun-ui/tokens");
3949
3970
  var import_jsx_runtime22 = require("react/jsx-runtime");
@@ -3952,16 +3973,16 @@ var easing = import_react_native24.Easing.bezier(...curve);
3952
3973
  var sameBox = (a, b) => a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
3953
3974
  function useButtonGroupMotion(selected) {
3954
3975
  const reduced = useReducedMotion();
3955
- const [layouts, setLayouts] = (0, import_react35.useState)(/* @__PURE__ */ new Map());
3956
- const x = (0, import_react35.useRef)(new import_react_native24.Animated.Value(0)).current;
3957
- const width = (0, import_react35.useRef)(new import_react_native24.Animated.Value(0)).current;
3958
- const previous = (0, import_react35.useRef)(null);
3976
+ const [layouts, setLayouts] = (0, import_react36.useState)(/* @__PURE__ */ new Map());
3977
+ const x = (0, import_react36.useRef)(new import_react_native24.Animated.Value(0)).current;
3978
+ const width = (0, import_react36.useRef)(new import_react_native24.Animated.Value(0)).current;
3979
+ const previous = (0, import_react36.useRef)(null);
3959
3980
  const layout = selected && layouts.get(selected.value);
3960
- const updateLayout = (0, import_react35.useCallback)((value, box) => {
3981
+ const updateLayout = (0, import_react36.useCallback)((value, box) => {
3961
3982
  setLayouts((old) => old.has(value) && sameBox(old.get(value), box) ? old : new Map(old).set(value, box));
3962
3983
  }, []);
3963
- const measure = (0, import_react35.useCallback)((value, event) => updateLayout(value, event.nativeEvent.layout), [updateLayout]);
3964
- (0, import_react35.useLayoutEffect)(() => {
3984
+ const measure = (0, import_react36.useCallback)((value, event) => updateLayout(value, event.nativeEvent.layout), [updateLayout]);
3985
+ (0, import_react36.useLayoutEffect)(() => {
3965
3986
  const old = previous.current;
3966
3987
  if (!selected || !layout) {
3967
3988
  previous.current = null;
@@ -3983,7 +4004,7 @@ function useButtonGroupMotion(selected) {
3983
4004
  }
3984
4005
  previous.current = { value: selected.value, box: layout, reduced };
3985
4006
  }, [selected == null ? void 0 : selected.value, layout, reduced, x, width]);
3986
- (0, import_react35.useEffect)(() => () => {
4007
+ (0, import_react36.useEffect)(() => () => {
3987
4008
  x.stopAnimation();
3988
4009
  width.stopAnimation();
3989
4010
  }, [x, width]);
@@ -3991,9 +4012,9 @@ function useButtonGroupMotion(selected) {
3991
4012
  }
3992
4013
  function ButtonGroupLabel({ label, active, size, reduced }) {
3993
4014
  const { colors, fontFamily } = useKjunStyles();
3994
- const progress = (0, import_react35.useRef)(new import_react_native24.Animated.Value(active ? 1 : 0)).current;
4015
+ const progress = (0, import_react36.useRef)(new import_react_native24.Animated.Value(active ? 1 : 0)).current;
3995
4016
  const interpolate = typeof colors.textSecondary === "string" && typeof colors.text === "string";
3996
- (0, import_react35.useEffect)(() => {
4017
+ (0, import_react36.useEffect)(() => {
3997
4018
  progress.stopAnimation();
3998
4019
  if (reduced || !interpolate) progress.setValue(active ? 1 : 0);
3999
4020
  else import_react_native24.Animated.timing(progress, { toValue: active ? 1 : 0, duration: import_tokens24.tokens.motion.indicator, easing, useNativeDriver: false }).start();
@@ -4040,9 +4061,9 @@ function KjunButtonGroup({
4040
4061
  const motion = useButtonGroupMotion(selected);
4041
4062
  const padding = import_tokens25.tokens.buttonGroup.padding[size];
4042
4063
  const itemRadius = import_tokens25.tokens.buttonGroup.itemRadii[size];
4043
- const itemRefs = (0, import_react36.useRef)(/* @__PURE__ */ new Map());
4064
+ const itemRefs = (0, import_react37.useRef)(/* @__PURE__ */ new Map());
4044
4065
  const { updateLayout } = motion;
4045
- (0, import_react36.useLayoutEffect)(() => {
4066
+ (0, import_react37.useLayoutEffect)(() => {
4046
4067
  for (const [value2, node] of itemRefs.current) {
4047
4068
  node.measure((x, y, width, height) => updateLayout(value2, { x, y, width, height }));
4048
4069
  }
@@ -4281,10 +4302,10 @@ function KjunFilterGroup({
4281
4302
 
4282
4303
  // packages/native/src/textarea.tsx
4283
4304
  var import_tokens26 = require("@kjun-ui/tokens");
4284
- var import_react37 = require("react");
4305
+ var import_react38 = require("react");
4285
4306
  var import_react_native26 = require("react-native");
4286
4307
  var import_jsx_runtime24 = require("react/jsx-runtime");
4287
- var KjunTextarea = (0, import_react37.forwardRef)(
4308
+ var KjunTextarea = (0, import_react38.forwardRef)(
4288
4309
  function KjunTextarea2({
4289
4310
  value,
4290
4311
  size = "md",
@@ -4354,7 +4375,7 @@ var KjunTextarea = (0, import_react37.forwardRef)(
4354
4375
 
4355
4376
  // packages/native/src/drawer.tsx
4356
4377
  var import_tokens27 = require("@kjun-ui/tokens");
4357
- var import_react38 = require("react");
4378
+ var import_react39 = require("react");
4358
4379
  var import_react_native27 = require("react-native");
4359
4380
 
4360
4381
  // shared/package-runtime/drawer-geometry.ts
@@ -4383,8 +4404,8 @@ function drawerFrame({ position, windowHeight, safeAreaTop, safeAreaBottom, gap,
4383
4404
  var import_react_native28 = require("react-native");
4384
4405
  var import_jsx_runtime25 = require("react/jsx-runtime");
4385
4406
  function useKeyboardOverlap(enabled2, windowHeight) {
4386
- const [overlap, setOverlap] = (0, import_react38.useState)(0);
4387
- (0, import_react38.useEffect)(() => {
4407
+ const [overlap, setOverlap] = (0, import_react39.useState)(0);
4408
+ (0, import_react39.useEffect)(() => {
4388
4409
  var _a, _b;
4389
4410
  setOverlap(0);
4390
4411
  const events = keyboardEvents(import_react_native28.Platform.OS);
@@ -4414,6 +4435,7 @@ function KjunDrawer({
4414
4435
  footer,
4415
4436
  children,
4416
4437
  onClose,
4438
+ onAfterClose,
4417
4439
  ariaLabel,
4418
4440
  safeAreaTop = 0,
4419
4441
  safeAreaBottom = 0,
@@ -4422,7 +4444,7 @@ function KjunDrawer({
4422
4444
  }) {
4423
4445
  const m = useKjunMessages();
4424
4446
  const { colors } = useKjunStyles(), window2 = (0, import_react_native28.useWindowDimensions)(), vertical = position === "left" || position === "right";
4425
- const [rootHeight, setRootHeight] = (0, import_react38.useState)(0);
4447
+ const [rootHeight, setRootHeight] = (0, import_react39.useState)(0);
4426
4448
  const keyboard = useKeyboardOverlap(open && avoidKeyboard, window2.height);
4427
4449
  const frame = drawerFrame({
4428
4450
  position,
@@ -4433,7 +4455,7 @@ function KjunDrawer({
4433
4455
  keyboard,
4434
4456
  maxHeight
4435
4457
  });
4436
- const [panelHeight, setPanelHeight] = (0, import_react38.useState)(0);
4458
+ const [panelHeight, setPanelHeight] = (0, import_react39.useState)(0);
4437
4459
  const motion = useNativePresence(open, import_tokens27.tokens.motion.layerEnter, import_tokens27.tokens.motion.layerExit, vertical || panelHeight > 0, 0, { enterEasing: motionEmphasized });
4438
4460
  const backdrop = useNativePresence(open, import_tokens27.tokens.motion.backdrop, import_tokens27.tokens.motion.backdropExit, true, 0, { fade: import_tokens27.tokens.motion.backdropExit });
4439
4461
  const close = () => {
@@ -4444,10 +4466,15 @@ function KjunDrawer({
4444
4466
  const layer = useLayer(open, motion.present, "window", () => {
4445
4467
  if (closeOnEsc) close();
4446
4468
  });
4469
+ const iosDismiss = import_react_native28.Platform.OS === "ios";
4470
+ useAfterClose(motion.present, onAfterClose, !iosDismiss);
4447
4471
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LayerScope.Provider, { value: layer.id, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4448
4472
  ScopedNativeModal,
4449
4473
  {
4450
4474
  visible: motion.present,
4475
+ onDismiss: iosDismiss ? () => {
4476
+ if (!open) onAfterClose == null ? void 0 : onAfterClose();
4477
+ } : void 0,
4451
4478
  transparent: true,
4452
4479
  onRequestClose: () => {
4453
4480
  if (closeOnEsc) close();
@@ -4574,13 +4601,13 @@ function KjunDrawer({
4574
4601
 
4575
4602
  // packages/native/src/dropdown.tsx
4576
4603
  var import_tokens30 = require("@kjun-ui/tokens");
4577
- var import_react41 = require("react");
4604
+ var import_react42 = require("react");
4578
4605
  var import_react_native32 = require("react-native");
4579
4606
 
4580
4607
  // packages/native/src/floating-panel.tsx
4581
4608
  var import_react_native29 = require("react-native");
4582
4609
  var import_tokens28 = require("@kjun-ui/tokens");
4583
- var import_react39 = require("react");
4610
+ var import_react40 = require("react");
4584
4611
  var import_react_native30 = require("react-native");
4585
4612
  var import_react_native_svg4 = __toESM(require("react-native-svg"), 1);
4586
4613
  var import_jsx_runtime26 = require("react/jsx-runtime");
@@ -4589,9 +4616,9 @@ function LayerTrigger({
4589
4616
  onPress,
4590
4617
  disabled = false
4591
4618
  }) {
4592
- if ((0, import_react39.isValidElement)(trigger)) {
4619
+ if ((0, import_react40.isValidElement)(trigger)) {
4593
4620
  const child = trigger;
4594
- return (0, import_react39.cloneElement)(child, {
4621
+ return (0, import_react40.cloneElement)(child, {
4595
4622
  disabled: disabled || child.props.disabled,
4596
4623
  onPress: () => {
4597
4624
  var _a, _b;
@@ -4626,14 +4653,14 @@ function FloatingPanel({
4626
4653
  }) {
4627
4654
  const m = useKjunMessages();
4628
4655
  ariaLabel != null ? ariaLabel : ariaLabel = m.select;
4629
- const [headerHeight, setHeaderHeight] = (0, import_react39.useState)(0);
4630
- const panelRef = (0, import_react39.useRef)(null);
4631
- const scroll = (0, import_react39.useRef)(null), viewport = (0, import_react39.useRef)(0);
4632
- const { colors } = useKjunStyles(), window2 = (0, import_react_native30.useWindowDimensions)(), [anchored, setAnchored] = (0, import_react39.useState)(false), [sized, setSized] = (0, import_react39.useState)(false), [anchor, setAnchor] = (0, import_react39.useState)({ x: 0, y: 0, width: 0, height: 0 }), [panel, setPanel] = (0, import_react39.useState)({ width: 0, height: 0 });
4633
- const measurement = (0, import_react39.useRef)(0);
4656
+ const [headerHeight, setHeaderHeight] = (0, import_react40.useState)(0);
4657
+ const panelRef = (0, import_react40.useRef)(null);
4658
+ const scroll = (0, import_react40.useRef)(null), viewport = (0, import_react40.useRef)(0);
4659
+ const { colors } = useKjunStyles(), window2 = (0, import_react_native30.useWindowDimensions)(), [anchored, setAnchored] = (0, import_react40.useState)(false), [sized, setSized] = (0, import_react40.useState)(false), [anchor, setAnchor] = (0, import_react40.useState)({ x: 0, y: 0, width: 0, height: 0 }), [panel, setPanel] = (0, import_react40.useState)({ width: 0, height: 0 });
4660
+ const measurement = (0, import_react40.useRef)(0);
4634
4661
  const motion = useNativePresence(open, tooltip ? import_tokens28.tokens.motion.tooltipEnter : import_tokens28.tokens.motion.popupEnter, tooltip ? import_tokens28.tokens.motion.tooltipExit : import_tokens28.tokens.motion.popupExit, anchored && sized);
4635
4662
  const layer = useLayer(open, motion.present, tooltip ? "tooltip" : "popup", () => onOpenChange(false), triggerRef);
4636
- (0, import_react39.useLayoutEffect)(() => {
4663
+ (0, import_react40.useLayoutEffect)(() => {
4637
4664
  var _a;
4638
4665
  const revision = ++measurement.current;
4639
4666
  if (open) setAnchored(false);
@@ -4646,20 +4673,20 @@ function FloatingPanel({
4646
4673
  measurement.current++;
4647
4674
  };
4648
4675
  }, [open, window2.width, window2.height, triggerRef]);
4649
- (0, import_react39.useLayoutEffect)(() => {
4676
+ (0, import_react40.useLayoutEffect)(() => {
4650
4677
  if (!motion.present) {
4651
4678
  setSized(false);
4652
4679
  setAnchored(false);
4653
4680
  }
4654
4681
  }, [motion.present]);
4655
- (0, import_react39.useEffect)(() => {
4682
+ (0, import_react40.useEffect)(() => {
4656
4683
  var _a;
4657
4684
  const row = reveal == null ? void 0 : reveal.current;
4658
4685
  if (!open || !anchored || !sized || !row || !viewport.current) return;
4659
4686
  const offset = row.y + row.height + (menu || field ? import_tokens28.tokens.extensions.menu.padding : 0) - viewport.current;
4660
4687
  if (offset > 0) (_a = scroll.current) == null ? void 0 : _a.scrollTo({ y: offset, animated: false });
4661
4688
  }, [open, anchored, sized, reveal, menu, field]);
4662
- (0, import_react39.useEffect)(() => {
4689
+ (0, import_react40.useEffect)(() => {
4663
4690
  if (!open || !anchored || !sized || !focusOnOpen || !panelRef.current) return;
4664
4691
  if (import_react_native30.Platform.OS === "web") {
4665
4692
  const node = panelRef.current;
@@ -4844,7 +4871,7 @@ function FloatingPanel({
4844
4871
  }
4845
4872
 
4846
4873
  // packages/native/src/popover.tsx
4847
- var import_react40 = require("react");
4874
+ var import_react41 = require("react");
4848
4875
  var import_react_native31 = require("react-native");
4849
4876
  var import_tokens29 = require("@kjun-ui/tokens");
4850
4877
  var import_jsx_runtime27 = require("react/jsx-runtime");
@@ -4865,7 +4892,7 @@ function KjunPopover({
4865
4892
  children
4866
4893
  }) {
4867
4894
  const { colors } = useKjunStyles();
4868
- const [internal, setInternal] = (0, import_react40.useState)(false), open = controlled != null ? controlled : internal, ref = (0, import_react40.useRef)(null);
4895
+ const [internal, setInternal] = (0, import_react41.useState)(false), open = controlled != null ? controlled : internal, ref = (0, import_react41.useRef)(null);
4869
4896
  const change = (v) => {
4870
4897
  setInternal(v);
4871
4898
  onOpenChange == null ? void 0 : onOpenChange(v);
@@ -4913,13 +4940,13 @@ function KjunTooltip({
4913
4940
  open: controlled,
4914
4941
  onOpenChange
4915
4942
  }) {
4916
- const { colors } = useKjunStyles(), [internal, setInternal] = (0, import_react40.useState)(false), open = controlled != null ? controlled : internal, latest = (0, import_react40.useRef)({ open, onOpenChange }), setOpen = (value) => {
4943
+ const { colors } = useKjunStyles(), [internal, setInternal] = (0, import_react41.useState)(false), open = controlled != null ? controlled : internal, latest = (0, import_react41.useRef)({ open, onOpenChange }), setOpen = (value) => {
4917
4944
  var _a, _b;
4918
4945
  if (latest.current.open === value) return;
4919
4946
  latest.current.open = value;
4920
4947
  setInternal(value);
4921
4948
  (_b = (_a = latest.current).onOpenChange) == null ? void 0 : _b.call(_a, value);
4922
- }, ref = (0, import_react40.useRef)(null), timer = (0, import_react40.useRef)(void 0);
4949
+ }, ref = (0, import_react41.useRef)(null), timer = (0, import_react41.useRef)(void 0);
4923
4950
  latest.current = { open, onOpenChange };
4924
4951
  const scopeActive = useActiveLayerScope();
4925
4952
  const hide = () => {
@@ -4931,11 +4958,11 @@ function KjunTooltip({
4931
4958
  clearTimeout(timer.current);
4932
4959
  timer.current = setTimeout(() => setOpen(true), delay);
4933
4960
  };
4934
- (0, import_react40.useEffect)(() => {
4961
+ (0, import_react41.useEffect)(() => {
4935
4962
  if (!scopeActive) hide();
4936
4963
  }, [scopeActive]);
4937
- (0, import_react40.useEffect)(() => () => clearTimeout(timer.current), []);
4938
- (0, import_react40.useEffect)(() => {
4964
+ (0, import_react41.useEffect)(() => () => clearTimeout(timer.current), []);
4965
+ (0, import_react41.useEffect)(() => {
4939
4966
  if (import_react_native31.Platform.OS !== "web" || !open) return;
4940
4967
  const escape = (event) => {
4941
4968
  if (event.key === "Escape") hide();
@@ -4943,7 +4970,7 @@ function KjunTooltip({
4943
4970
  document.addEventListener("keydown", escape);
4944
4971
  return () => document.removeEventListener("keydown", escape);
4945
4972
  }, [open]);
4946
- const child = (0, import_react40.isValidElement)(children) ? children : null;
4973
+ const child = (0, import_react41.isValidElement)(children) ? children : null;
4947
4974
  const childProps = child == null ? void 0 : child.props;
4948
4975
  const handlers = {
4949
4976
  // A hint that repeats the trigger's name would be read twice (icon-only RefreshButton, IconToggle).
@@ -4988,7 +5015,7 @@ function KjunTooltip({
4988
5015
  }
4989
5016
  };
4990
5017
  return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
4991
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native31.View, { ref, collapsable: false, style: { alignSelf: (childProps == null ? void 0 : childProps.block) ? "stretch" : "flex-start" }, children: child ? (0, import_react40.cloneElement)(child, handlers) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AccessiblePressable, { ...handlers, children }) }),
5018
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_native31.View, { ref, collapsable: false, style: { alignSelf: (childProps == null ? void 0 : childProps.block) ? "stretch" : "flex-start" }, children: child ? (0, import_react41.cloneElement)(child, handlers) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AccessiblePressable, { ...handlers, children }) }),
4992
5019
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4993
5020
  FloatingPanel,
4994
5021
  {
@@ -5026,10 +5053,10 @@ function KjunTooltip({
5026
5053
 
5027
5054
  // packages/native/src/dropdown.tsx
5028
5055
  var import_jsx_runtime28 = require("react/jsx-runtime");
5029
- var DropdownContext = (0, import_react41.createContext)(null);
5030
- var MenuIconSlotContext = (0, import_react41.createContext)(false);
5056
+ var DropdownContext = (0, import_react42.createContext)(null);
5057
+ var MenuIconSlotContext = (0, import_react42.createContext)(false);
5031
5058
  function hasLeadingIcon(node) {
5032
- return import_react41.Children.toArray(node).some((child) => (0, import_react41.isValidElement)(child) && (child.type === import_react41.Fragment ? hasLeadingIcon(child.props.children) : child.type === KjunDropdownItem && !!child.props.icon));
5059
+ return import_react42.Children.toArray(node).some((child) => (0, import_react42.isValidElement)(child) && (child.type === import_react42.Fragment ? hasLeadingIcon(child.props.children) : child.type === KjunDropdownItem && !!child.props.icon));
5033
5060
  }
5034
5061
  function KjunDropdown({
5035
5062
  disabled = false,
@@ -5040,11 +5067,11 @@ function KjunDropdown({
5040
5067
  onClose
5041
5068
  }) {
5042
5069
  const m = useKjunMessages();
5043
- const [open, setOpen] = (0, import_react41.useState)(false), currentOpen = (0, import_react41.useRef)(false), ref = (0, import_react41.useRef)(null);
5070
+ const [open, setOpen] = (0, import_react42.useState)(false), currentOpen = (0, import_react42.useRef)(false), ref = (0, import_react42.useRef)(null);
5044
5071
  let control = trigger;
5045
- while ((0, import_react41.isValidElement)(control) && control.type === KjunTooltip)
5072
+ while ((0, import_react42.isValidElement)(control) && control.type === KjunTooltip)
5046
5073
  control = control.props.children;
5047
- const unavailable = disabled || (0, import_react41.isValidElement)(control) && !!(control.props.disabled || control.props.loading);
5074
+ const unavailable = disabled || (0, import_react42.isValidElement)(control) && !!(control.props.disabled || control.props.loading);
5048
5075
  const change = (v) => {
5049
5076
  if (v === currentOpen.current || v && unavailable) return;
5050
5077
  currentOpen.current = v;
@@ -5052,7 +5079,7 @@ function KjunDropdown({
5052
5079
  if (v) onOpen == null ? void 0 : onOpen();
5053
5080
  else onClose == null ? void 0 : onClose();
5054
5081
  };
5055
- (0, import_react41.useEffect)(() => {
5082
+ (0, import_react42.useEffect)(() => {
5056
5083
  if (unavailable) change(false);
5057
5084
  }, [unavailable]);
5058
5085
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(DropdownContext.Provider, { value: () => change(false), children: [
@@ -5086,8 +5113,8 @@ function KjunDropdownItem({
5086
5113
  children,
5087
5114
  onPress
5088
5115
  }) {
5089
- const { colors } = useKjunStyles(), close = (0, import_react41.useContext)(DropdownContext), color = variant === "danger" ? colors.danger : colors.text, iconColor = variant === "danger" ? colors.danger : colors.textSecondary, reserveIcon = (0, import_react41.useContext)(MenuIconSlotContext);
5090
- const [hovered, setHovered] = (0, import_react41.useState)(false);
5116
+ const { colors } = useKjunStyles(), close = (0, import_react42.useContext)(DropdownContext), color = variant === "danger" ? colors.danger : colors.text, iconColor = variant === "danger" ? colors.danger : colors.textSecondary, reserveIcon = (0, import_react42.useContext)(MenuIconSlotContext);
5117
+ const [hovered, setHovered] = (0, import_react42.useState)(false);
5091
5118
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5092
5119
  AccessiblePressable,
5093
5120
  {
@@ -5148,7 +5175,7 @@ function KjunMenuButton({
5148
5175
  ...props
5149
5176
  }) {
5150
5177
  const m = useKjunMessages();
5151
- const [open, setOpen] = (0, import_react41.useState)(false);
5178
+ const [open, setOpen] = (0, import_react42.useState)(false);
5152
5179
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5153
5180
  KjunDropdown,
5154
5181
  {
@@ -5188,7 +5215,7 @@ function KjunMenuButton({
5188
5215
  }
5189
5216
 
5190
5217
  // shared/package-runtime/combobox.ts
5191
- var import_react42 = require("react");
5218
+ var import_react43 = require("react");
5192
5219
 
5193
5220
  // shared/package-runtime/options.ts
5194
5221
  var optionValue = (option, key = "value") => typeof option === "object" ? option[key] : option;
@@ -5266,10 +5293,10 @@ function useComboboxModel({
5266
5293
  }) {
5267
5294
  const selected = options.find((option) => optionValue(option, valueKey) === value);
5268
5295
  const selectedLabel = selected !== void 0 ? optionLabel(selected, labelKey) : "";
5269
- const [query, setQuery] = (0, import_react42.useState)(selectedLabel);
5270
- const [open, setOpen] = (0, import_react42.useState)(false);
5271
- (0, import_react42.useEffect)(() => setQuery(selectedLabel), [value, selectedLabel]);
5272
- (0, import_react42.useEffect)(() => {
5296
+ const [query, setQuery] = (0, import_react43.useState)(selectedLabel);
5297
+ const [open, setOpen] = (0, import_react43.useState)(false);
5298
+ (0, import_react43.useEffect)(() => setQuery(selectedLabel), [value, selectedLabel]);
5299
+ (0, import_react43.useEffect)(() => {
5273
5300
  if (disabled) setOpen(false);
5274
5301
  }, [disabled]);
5275
5302
  const change = (next) => {
@@ -5303,7 +5330,7 @@ function useComboboxModel({
5303
5330
 
5304
5331
  // packages/native/src/combobox.tsx
5305
5332
  var import_tokens32 = require("@kjun-ui/tokens");
5306
- var import_react43 = require("react");
5333
+ var import_react44 = require("react");
5307
5334
  var import_react_native34 = require("react-native");
5308
5335
 
5309
5336
  // packages/native/src/select-options.tsx
@@ -5432,9 +5459,9 @@ function SearchField({
5432
5459
  onEnter
5433
5460
  }) {
5434
5461
  const m = useKjunMessages();
5435
- const searchId = "kjun-popup-search-" + (0, import_react43.useId)().replace(/:/g, "");
5436
- const clearing = (0, import_react43.useRef)(false);
5437
- const ref = (0, import_react43.useRef)(null), { colors } = useKjunStyles();
5462
+ const searchId = "kjun-popup-search-" + (0, import_react44.useId)().replace(/:/g, "");
5463
+ const clearing = (0, import_react44.useRef)(false);
5464
+ const ref = (0, import_react44.useRef)(null), { colors } = useKjunStyles();
5438
5465
  const focusGuard = usePopupFocusGuard(ref);
5439
5466
  const openFromPress = () => {
5440
5467
  if (!disabled) {
@@ -5534,7 +5561,7 @@ function SearchField({
5534
5561
 
5535
5562
  // packages/native/src/date-picker.tsx
5536
5563
  var import_tokens33 = require("@kjun-ui/tokens");
5537
- var import_react44 = require("react");
5564
+ var import_react45 = require("react");
5538
5565
  var import_react_native35 = require("react-native");
5539
5566
  var import_jsx_runtime31 = require("react/jsx-runtime");
5540
5567
  function displayMonth(value) {
@@ -5557,7 +5584,7 @@ function KjunDatePicker({
5557
5584
  const scope = useKjunMessageScope();
5558
5585
  placeholder != null ? placeholder : placeholder = scope.messages.datePlaceholder;
5559
5586
  const clear = clearable && !!value && !disabled;
5560
- const { colors } = useKjunStyles(), field = useKjunField(), [open, setOpen] = (0, import_react44.useState)(false), [month, setMonth] = (0, import_react44.useState)(() => displayMonth(value)), ref = (0, import_react44.useRef)(null), spec = import_tokens33.tokens.input[size];
5587
+ const { colors } = useKjunStyles(), field = useKjunField(), [open, setOpen] = (0, import_react45.useState)(false), [month, setMonth] = (0, import_react45.useState)(() => displayMonth(value)), ref = (0, import_react45.useRef)(null), spec = import_tokens33.tokens.input[size];
5561
5588
  const surface = useFieldSurface(size, { disabled, invalid: error || !!(field == null ? void 0 : field.error), open });
5562
5589
  const year = month.getFullYear(), m = month.getMonth(), first = new Date(year, m, 1).getDay(), count = new Date(year, m + 1, 0).getDate();
5563
5590
  const date = (day) => `${year}-${String(m + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
@@ -5732,10 +5759,10 @@ function KjunDatePicker({
5732
5759
  }
5733
5760
 
5734
5761
  // packages/native/src/search-input.tsx
5735
- var import_react46 = require("react");
5762
+ var import_react47 = require("react");
5736
5763
 
5737
5764
  // shared/package-runtime/search-input.ts
5738
- var import_react45 = require("react");
5765
+ var import_react46 = require("react");
5739
5766
  function useSearchInputModel({
5740
5767
  value,
5741
5768
  disabled = false,
@@ -5745,20 +5772,20 @@ function useSearchInputModel({
5745
5772
  onValueChange,
5746
5773
  onSearchError
5747
5774
  }, open) {
5748
- const [query, setQuery] = (0, import_react45.useState)(value), [options, setOptions] = (0, import_react45.useState)([]), [loading, setLoading] = (0, import_react45.useState)(false), [failed, setFailed] = (0, import_react45.useState)(false), version = (0, import_react45.useRef)(0), notify = (0, import_react45.useRef)(onSearchError);
5775
+ const [query, setQuery] = (0, import_react46.useState)(value), [options, setOptions] = (0, import_react46.useState)([]), [loading, setLoading] = (0, import_react46.useState)(false), [failed, setFailed] = (0, import_react46.useState)(false), version = (0, import_react46.useRef)(0), notify = (0, import_react46.useRef)(onSearchError);
5749
5776
  notify.current = onSearchError;
5750
- const timer = (0, import_react45.useRef)(void 0);
5751
- const notifyValue = (0, import_react45.useRef)(onValueChange);
5777
+ const timer = (0, import_react46.useRef)(void 0);
5778
+ const notifyValue = (0, import_react46.useRef)(onValueChange);
5752
5779
  notifyValue.current = onValueChange;
5753
- (0, import_react45.useLayoutEffect)(() => {
5780
+ (0, import_react46.useLayoutEffect)(() => {
5754
5781
  clearTimeout(timer.current);
5755
5782
  setQuery(value);
5756
5783
  }, [value]);
5757
- (0, import_react45.useLayoutEffect)(() => {
5784
+ (0, import_react46.useLayoutEffect)(() => {
5758
5785
  clearTimeout(timer.current);
5759
5786
  return () => clearTimeout(timer.current);
5760
5787
  }, [disabled, debounce, !!loadOptions]);
5761
- (0, import_react45.useEffect)(() => {
5788
+ (0, import_react46.useEffect)(() => {
5762
5789
  const current = ++version.current, abort = new AbortController();
5763
5790
  setFailed(false);
5764
5791
  if (!loadOptions || !open || disabled || query.length < minChars) {
@@ -5849,7 +5876,7 @@ function KjunSearchInput({
5849
5876
  placeholder != null ? placeholder : placeholder = m.search;
5850
5877
  emptyText != null ? emptyText : emptyText = m.noResults;
5851
5878
  errorText != null ? errorText : errorText = m.searchFailed;
5852
- const [open, setOpen] = (0, import_react46.useState)(false);
5879
+ const [open, setOpen] = (0, import_react47.useState)(false);
5853
5880
  const model = useSearchInputModel({ value, disabled, debounce, loadOptions, minChars, onValueChange, onSearchError }, open);
5854
5881
  const { query, options, loading, failed } = model;
5855
5882
  const update = (value2) => {
@@ -5911,30 +5938,30 @@ function KjunSearchInput({
5911
5938
 
5912
5939
  // packages/native/src/select-control.tsx
5913
5940
  var import_tokens35 = require("@kjun-ui/tokens");
5914
- var import_react49 = require("react");
5941
+ var import_react50 = require("react");
5915
5942
 
5916
5943
  // packages/native/src/compound-control.tsx
5917
- var import_react47 = require("react");
5944
+ var import_react48 = require("react");
5918
5945
  var import_react_native36 = require("react-native");
5919
5946
  var import_tokens34 = require("@kjun-ui/tokens");
5920
5947
  var import_jsx_runtime33 = require("react/jsx-runtime");
5921
- var CompoundControlContext = (0, import_react47.createContext)(null);
5948
+ var CompoundControlContext = (0, import_react48.createContext)(null);
5922
5949
  function CompoundTarget({ children, square = false }) {
5923
5950
  const touch = finePointer() ? void 0 : import_tokens34.tokens.native.minimumTouchTarget;
5924
5951
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react_native36.View, { style: { minHeight: touch, minWidth: square ? touch : void 0, alignItems: "center", justifyContent: "center" }, children });
5925
5952
  }
5926
5953
 
5927
5954
  // shared/package-runtime/select.ts
5928
- var import_react48 = require("react");
5955
+ var import_react49 = require("react");
5929
5956
  function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5930
- const [internal, setInternal] = (0, import_react48.useState)(false);
5931
- const [query, setQuery] = (0, import_react48.useState)("");
5932
- const [limit, setLimit] = (0, import_react48.useState)(pageSize);
5933
- const [session, setSession] = (0, import_react48.useState)(0);
5957
+ const [internal, setInternal] = (0, import_react49.useState)(false);
5958
+ const [query, setQuery] = (0, import_react49.useState)("");
5959
+ const [limit, setLimit] = (0, import_react49.useState)(pageSize);
5960
+ const [session, setSession] = (0, import_react49.useState)(0);
5934
5961
  const isControlled = typeof controlled === "boolean";
5935
5962
  const open = !disabled && (isControlled ? controlled : internal);
5936
- const previousOpen = (0, import_react48.useRef)(open);
5937
- (0, import_react48.useEffect)(() => {
5963
+ const previousOpen = (0, import_react49.useRef)(open);
5964
+ (0, import_react49.useEffect)(() => {
5938
5965
  if (disabled && !isControlled) setInternal(false);
5939
5966
  if (previousOpen.current && !open) {
5940
5967
  setQuery("");
@@ -5943,7 +5970,7 @@ function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5943
5970
  }
5944
5971
  previousOpen.current = open;
5945
5972
  }, [open, disabled, isControlled, pageSize]);
5946
- (0, import_react48.useEffect)(() => {
5973
+ (0, import_react49.useEffect)(() => {
5947
5974
  setLimit(pageSize);
5948
5975
  }, [pageSize]);
5949
5976
  const changeOpen = (next) => {
@@ -5993,14 +6020,14 @@ function KjunSelect({
5993
6020
  placeholder != null ? placeholder : placeholder = m.select;
5994
6021
  searchPlaceholder != null ? searchPlaceholder : searchPlaceholder = m.search;
5995
6022
  const { open, query, limit, changeOpen, search, showMore } = useSelectState(controlled, disabled, optionPageSize, onOpenChange);
5996
- const { colors } = useKjunStyles(), field = useKjunField(), ref = (0, import_react49.useRef)(null), spec = import_tokens35.tokens.input[size];
5997
- const trigger = (0, import_react49.useRef)(null);
5998
- const compound = (0, import_react49.useContext)(CompoundControlContext);
5999
- (0, import_react49.useEffect)(() => {
6023
+ const { colors } = useKjunStyles(), field = useKjunField(), ref = (0, import_react50.useRef)(null), spec = import_tokens35.tokens.input[size];
6024
+ const trigger = (0, import_react50.useRef)(null);
6025
+ const compound = (0, import_react50.useContext)(CompoundControlContext);
6026
+ (0, import_react50.useEffect)(() => {
6000
6027
  if (compound == null ? void 0 : compound.focusRef) compound.focusRef.current = trigger.current;
6001
6028
  }, [compound == null ? void 0 : compound.focusRef]);
6002
6029
  const expanded = usePopupExpanded(open, ref);
6003
- const selectedRow = (0, import_react49.useRef)(null);
6030
+ const selectedRow = (0, import_react50.useRef)(null);
6004
6031
  const surface = useFieldSurface(size, { disabled, invalid: error || !!(field == null ? void 0 : field.error), open: expanded });
6005
6032
  const change = (v) => {
6006
6033
  onValueChange == null ? void 0 : onValueChange(v);
@@ -6198,16 +6225,17 @@ var import_tokens38 = require("@kjun-ui/tokens");
6198
6225
 
6199
6226
  // packages/native/src/collapse.tsx
6200
6227
  var import_tokens36 = require("@kjun-ui/tokens");
6201
- var import_react50 = require("react");
6228
+ var import_react51 = require("react");
6202
6229
  var import_react_native38 = require("react-native");
6203
6230
  var import_jsx_runtime35 = require("react/jsx-runtime");
6204
- function Collapse({ open, children }) {
6231
+ function Collapse({ open, keepMounted = false, children }) {
6205
6232
  const reduced = useReducedMotion();
6206
- const [retained, setRetained] = (0, import_react50.useState)(open), [height, setHeight] = (0, import_react50.useState)(null);
6207
- const value = (0, import_react50.useRef)(new import_react_native38.Animated.Value(0)).current;
6208
- const [settled, setSettled] = (0, import_react50.useState)(open);
6209
- const version = (0, import_react50.useRef)(0), first = (0, import_react50.useRef)(open);
6210
- (0, import_react50.useLayoutEffect)(() => {
6233
+ const [retained, setRetained] = (0, import_react51.useState)(open), [height, setHeight] = (0, import_react51.useState)(null);
6234
+ const value = (0, import_react51.useRef)(new import_react_native38.Animated.Value(0)).current;
6235
+ const [settled, setSettled] = (0, import_react51.useState)(open);
6236
+ const version = (0, import_react51.useRef)(0), first = (0, import_react51.useRef)(open), opened = (0, import_react51.useRef)(open);
6237
+ if (open) opened.current = true;
6238
+ (0, import_react51.useLayoutEffect)(() => {
6211
6239
  const revision = ++version.current;
6212
6240
  if (open) setRetained(true);
6213
6241
  if (height === null) return;
@@ -6234,13 +6262,13 @@ function Collapse({ open, children }) {
6234
6262
  value.stopAnimation();
6235
6263
  };
6236
6264
  }, [open, height, reduced, value]);
6237
- return open || retained ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6265
+ return open || retained || keepMounted && opened.current ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6238
6266
  import_react_native38.Animated.View,
6239
6267
  {
6240
6268
  pointerEvents: open ? "auto" : "none",
6241
6269
  accessibilityElementsHidden: !open,
6242
6270
  importantForAccessibility: open ? "auto" : "no-hide-descendants",
6243
- ...!open ? { inert: true } : {},
6271
+ ...!open ? { inert: true, "aria-hidden": true } : {},
6244
6272
  style: { height: settled && open ? void 0 : value, overflow: "hidden" },
6245
6273
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react_native38.View, { onLayout: (event) => setHeight(event.nativeEvent.layout.height), children })
6246
6274
  }
@@ -6248,10 +6276,10 @@ function Collapse({ open, children }) {
6248
6276
  }
6249
6277
 
6250
6278
  // shared/package-runtime/navigation.ts
6251
- var import_react51 = require("react");
6279
+ var import_react52 = require("react");
6252
6280
  function useInitialTab(value, candidate, change) {
6253
- const requested = (0, import_react51.useRef)(/* @__PURE__ */ new Set());
6254
- (0, import_react51.useEffect)(() => {
6281
+ const requested = (0, import_react52.useRef)(/* @__PURE__ */ new Set());
6282
+ (0, import_react52.useEffect)(() => {
6255
6283
  if (value !== "") {
6256
6284
  requested.current.clear();
6257
6285
  return;
@@ -6262,8 +6290,8 @@ function useInitialTab(value, candidate, change) {
6262
6290
  }, [value, candidate, change]);
6263
6291
  }
6264
6292
  function useAccordionState(multiple) {
6265
- const [opened, setOpened] = (0, import_react51.useState)(/* @__PURE__ */ new Set());
6266
- (0, import_react51.useEffect)(() => {
6293
+ const [opened, setOpened] = (0, import_react52.useState)(/* @__PURE__ */ new Set());
6294
+ (0, import_react52.useEffect)(() => {
6267
6295
  if (!multiple) setOpened((previous) => previous.size > 1 ? new Set([...previous].slice(-1)) : previous);
6268
6296
  }, [multiple]);
6269
6297
  return {
@@ -6287,16 +6315,16 @@ function useAccordionState(multiple) {
6287
6315
  }
6288
6316
 
6289
6317
  // packages/native/src/navigation.tsx
6290
- var import_react54 = require("react");
6318
+ var import_react55 = require("react");
6291
6319
  var import_react_native40 = require("react-native");
6292
6320
 
6293
6321
  // packages/native/src/tabs.tsx
6294
6322
  var import_tokens37 = require("@kjun-ui/tokens");
6295
- var import_react53 = require("react");
6323
+ var import_react54 = require("react");
6296
6324
  var import_react_native39 = require("react-native");
6297
6325
 
6298
6326
  // packages/native/src/tabs-accessibility.web.ts
6299
- var import_react52 = require("react");
6327
+ var import_react53 = require("react");
6300
6328
 
6301
6329
  // shared/package-runtime/tab-keyboard.ts
6302
6330
  function manageTabList(list, select, keyboard = true) {
@@ -6379,16 +6407,16 @@ function panelNeedsFocus(panel) {
6379
6407
 
6380
6408
  // packages/native/src/tabs-accessibility.web.ts
6381
6409
  function useTabKeyboard(root, select) {
6382
- const callback = (0, import_react52.useRef)(select);
6410
+ const callback = (0, import_react53.useRef)(select);
6383
6411
  callback.current = select;
6384
- (0, import_react52.useLayoutEffect)(() => {
6412
+ (0, import_react53.useLayoutEffect)(() => {
6385
6413
  var _a;
6386
6414
  const list = (_a = root.current) == null ? void 0 : _a.querySelector('[role="tablist"]');
6387
6415
  if (list) return manageTabList(list, (name) => callback.current(name));
6388
6416
  }, [root]);
6389
6417
  }
6390
6418
  function usePanelFocus(root) {
6391
- (0, import_react52.useLayoutEffect)(() => {
6419
+ (0, import_react53.useLayoutEffect)(() => {
6392
6420
  const panel = root.current;
6393
6421
  if (panel) panel.tabIndex = panelNeedsFocus(panel) ? 0 : -1;
6394
6422
  });
@@ -6396,7 +6424,7 @@ function usePanelFocus(root) {
6396
6424
 
6397
6425
  // packages/native/src/tabs.tsx
6398
6426
  var import_jsx_runtime36 = require("react/jsx-runtime");
6399
- var TabContext = (0, import_react53.createContext)({ value: "", id: "", names: [] });
6427
+ var TabContext = (0, import_react54.createContext)({ value: "", id: "", names: [] });
6400
6428
  function KjunTabs({
6401
6429
  value,
6402
6430
  items: items2 = [],
@@ -6412,21 +6440,21 @@ function KjunTabs({
6412
6440
  var _a, _b;
6413
6441
  const m = useKjunMessages();
6414
6442
  ariaLabel != null ? ariaLabel : ariaLabel = m.tabs;
6415
- const { colors } = useKjunStyles(), panes = import_react53.Children.toArray(children).filter(
6416
- import_react53.isValidElement
6443
+ const { colors } = useKjunStyles(), panes = import_react54.Children.toArray(children).filter(
6444
+ import_react54.isValidElement
6417
6445
  );
6418
6446
  const tabs = items2.length ? items2 : panes.filter((child) => child.type === KjunTabPane).map((child) => child.props);
6419
- const id = "kjun-" + (0, import_react53.useId)(), root = (0, import_react53.useRef)(null);
6420
- const menuState = (0, import_react53.useRef)({ tabs, onTabMenu });
6447
+ const id = "kjun-" + (0, import_react54.useId)(), root = (0, import_react54.useRef)(null);
6448
+ const menuState = (0, import_react54.useRef)({ tabs, onTabMenu });
6421
6449
  menuState.current = { tabs, onTabMenu };
6422
- const pressedMenu = (0, import_react53.useRef)(null);
6423
- (0, import_react53.useLayoutEffect)(() => {
6450
+ const pressedMenu = (0, import_react54.useRef)(null);
6451
+ (0, import_react54.useLayoutEffect)(() => {
6424
6452
  if (!onTabMenu || !tabs.some((tab) => tab.name === pressedMenu.current && !tab.disabled)) pressedMenu.current = null;
6425
6453
  }, [tabs, onTabMenu]);
6426
6454
  const panelNames = panes.filter((child) => child.type === KjunTabPane).map((child) => child.props.name);
6427
6455
  const geometry2 = import_tokens37.tokens.extensions.tabs;
6428
6456
  const underline = variant === "underline";
6429
- const [hoveredTab, setHoveredTab] = (0, import_react53.useState)(null);
6457
+ const [hoveredTab, setHoveredTab] = (0, import_react54.useState)(null);
6430
6458
  const singleLine = import_react_native39.Platform.OS === "web" ? { whiteSpace: "nowrap" } : {};
6431
6459
  const paddingX = !underline ? geometry2.pillsPaddingX : density === "compact" ? geometry2.compactPaddingX : geometry2.paddingX;
6432
6460
  const height = density === "compact" ? geometry2.compactHeight : geometry2.height;
@@ -6435,10 +6463,10 @@ function KjunTabs({
6435
6463
  const roomX = underline ? ringRoom : 0, roomY = Math.max(underline ? ringRoom : 0, slop);
6436
6464
  const selectedTab = tabs.find((tab) => tab.name === value);
6437
6465
  const selection = useButtonGroupMotion(selectedTab ? { ...selectedTab, value: selectedTab.name } : void 0);
6438
- const tabRefs = (0, import_react53.useRef)(/* @__PURE__ */ new Map());
6466
+ const tabRefs = (0, import_react54.useRef)(/* @__PURE__ */ new Map());
6439
6467
  const { updateLayout } = selection;
6440
6468
  const firstName = (_a = tabs[0]) == null ? void 0 : _a.name;
6441
- const measureIndicator = (0, import_react53.useCallback)((name, box) => {
6469
+ const measureIndicator = (0, import_react54.useCallback)((name, box) => {
6442
6470
  const left = underline && name === firstName ? 0 : paddingX;
6443
6471
  updateLayout(name, underline ? {
6444
6472
  x: box.x + left,
@@ -6447,7 +6475,7 @@ function KjunTabs({
6447
6475
  height: geometry2.indicatorHeight
6448
6476
  } : box);
6449
6477
  }, [underline, paddingX, firstName, updateLayout, geometry2]);
6450
- (0, import_react53.useLayoutEffect)(() => {
6478
+ (0, import_react54.useLayoutEffect)(() => {
6451
6479
  for (const [name, node] of tabRefs.current) {
6452
6480
  node.measure((x, y, width, height2) => measureIndicator(name, { x, y, width, height: height2 }));
6453
6481
  }
@@ -6606,8 +6634,8 @@ function KjunTabs({
6606
6634
  ] }) });
6607
6635
  }
6608
6636
  function KjunTabPane({ name, children }) {
6609
- const { value, id, names } = (0, import_react53.useContext)(TabContext);
6610
- const root = (0, import_react53.useRef)(null);
6637
+ const { value, id, names } = (0, import_react54.useContext)(TabContext);
6638
+ const root = (0, import_react54.useRef)(null);
6611
6639
  usePanelFocus(root);
6612
6640
  const hidden = value !== name;
6613
6641
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -6630,7 +6658,7 @@ function KjunTabPane({ name, children }) {
6630
6658
 
6631
6659
  // packages/native/src/navigation.tsx
6632
6660
  var import_jsx_runtime37 = require("react/jsx-runtime");
6633
- var AccordionContext = (0, import_react54.createContext)(null);
6661
+ var AccordionContext = (0, import_react55.createContext)(null);
6634
6662
  function KjunAccordion({
6635
6663
  multiple = false,
6636
6664
  tone = "card",
@@ -6660,14 +6688,32 @@ function KjunAccordionItem({
6660
6688
  defaultOpen = false,
6661
6689
  disabled = false,
6662
6690
  header,
6691
+ open: openProp,
6692
+ onOpenChange,
6693
+ keepMounted = false,
6663
6694
  children
6664
6695
  }) {
6665
- const { colors } = useKjunStyles(), group = (0, import_react54.useContext)(AccordionContext), id = "kjun-" + (0, import_react54.useId)(), [own, setOwn] = (0, import_react54.useState)(defaultOpen), open = group ? group.opened.has(id) : own;
6696
+ const controlled = openProp !== void 0, context = (0, import_react55.useContext)(AccordionContext), { colors } = useKjunStyles(), group = controlled ? null : context, id = "kjun-" + (0, import_react55.useId)(), [own, setOwn] = (0, import_react55.useState)(defaultOpen), open = controlled ? openProp : group ? group.opened.has(id) : own;
6697
+ const reported = (0, import_react55.useRef)(open), notify = (0, import_react55.useRef)(onOpenChange), registering = (0, import_react55.useRef)(!!group && defaultOpen);
6698
+ notify.current = onOpenChange;
6699
+ (0, import_react55.useEffect)(() => {
6700
+ var _a;
6701
+ if (registering.current) {
6702
+ if (open) {
6703
+ registering.current = false;
6704
+ reported.current = open;
6705
+ }
6706
+ return;
6707
+ }
6708
+ if (controlled || reported.current === open) return;
6709
+ reported.current = open;
6710
+ (_a = notify.current) == null ? void 0 : _a.call(notify, open);
6711
+ }, [open, controlled]);
6666
6712
  const rotation = useMotionValue(open ? 1 : 0, import_tokens38.tokens.motion.collapse, void 0, void 0, true);
6667
6713
  const geometry2 = import_tokens38.tokens.extensions.accordion;
6668
- const [hovered, setHovered] = (0, import_react54.useState)(false);
6714
+ const [hovered, setHovered] = (0, import_react55.useState)(false);
6669
6715
  const wrapping = import_react_native40.Platform.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
6670
- (0, import_react54.useEffect)(() => {
6716
+ (0, import_react55.useEffect)(() => {
6671
6717
  return group == null ? void 0 : group.register(id, defaultOpen);
6672
6718
  }, []);
6673
6719
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react_native40.View, { children: [
@@ -6681,7 +6727,10 @@ function KjunAccordionItem({
6681
6727
  accessibilityLabel: title,
6682
6728
  accessibilityState: { expanded: open, disabled },
6683
6729
  disabled,
6684
- onPress: () => group ? group.toggle(id) : setOwn(!own),
6730
+ onPress: () => {
6731
+ registering.current = false;
6732
+ controlled ? onOpenChange == null ? void 0 : onOpenChange(!open) : group ? group.toggle(id) : setOwn(!own);
6733
+ },
6685
6734
  onHoverIn: () => setHovered(true),
6686
6735
  onHoverOut: () => setHovered(false),
6687
6736
  style: ({ pressed }) => ({
@@ -6701,7 +6750,7 @@ function KjunAccordionItem({
6701
6750
  ]
6702
6751
  }
6703
6752
  ),
6704
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Collapse, { open, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6753
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Collapse, { open, keepMounted, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6705
6754
  import_react_native40.View,
6706
6755
  {
6707
6756
  nativeID: id + "-panel",
@@ -6744,7 +6793,7 @@ function KjunBreadcrumb({
6744
6793
  }
6745
6794
  )
6746
6795
  ] });
6747
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react54.Fragment, { children: [
6796
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react55.Fragment, { children: [
6748
6797
  i > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6749
6798
  KjunIcon,
6750
6799
  {
@@ -6898,7 +6947,7 @@ function KjunPagination({
6898
6947
 
6899
6948
  // packages/native/src/actions.tsx
6900
6949
  var import_tokens39 = require("@kjun-ui/tokens");
6901
- var import_react55 = require("react");
6950
+ var import_react56 = require("react");
6902
6951
  var import_react_native41 = require("react-native");
6903
6952
  var import_jsx_runtime38 = require("react/jsx-runtime");
6904
6953
  function KjunIconToggle({
@@ -6917,7 +6966,7 @@ function KjunIconToggle({
6917
6966
  onToggle
6918
6967
  }) {
6919
6968
  const { colors } = useKjunStyles();
6920
- const navigation = (0, import_react55.useContext)(TopNavigationContext);
6969
+ const navigation = (0, import_react56.useContext)(TopNavigationContext);
6921
6970
  const box = navigation ? navigation.controlSize : size === "xs" ? import_tokens39.tokens.extensions.iconToggle.compactSize : import_tokens39.tokens.extensions.iconToggle.sizes[size];
6922
6971
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(KjunTooltip, { content: disabled || loading ? "" : tooltip != null ? tooltip : ariaLabel, placement: tooltipPlacement, delay: tooltipDelay, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
6923
6972
  AccessiblePressable,
@@ -6983,8 +7032,8 @@ function KjunCopyButton({
6983
7032
  }) {
6984
7033
  const m = useKjunMessages();
6985
7034
  successText != null ? successText : successText = m.copied;
6986
- const feedback = useOptionalKjunFeedback(), { colors } = useKjunStyles(), [copied, setCopied] = (0, import_react55.useState)(false), [failed, setFailed] = (0, import_react55.useState)(false), busy = (0, import_react55.useRef)(false), timer = (0, import_react55.useRef)(void 0), mounted = (0, import_react55.useRef)(true);
6987
- (0, import_react55.useEffect)(() => {
7035
+ const feedback = useOptionalKjunFeedback(), { colors } = useKjunStyles(), [copied, setCopied] = (0, import_react56.useState)(false), [failed, setFailed] = (0, import_react56.useState)(false), busy = (0, import_react56.useRef)(false), timer = (0, import_react56.useRef)(void 0), mounted = (0, import_react56.useRef)(true);
7036
+ (0, import_react56.useEffect)(() => {
6988
7037
  mounted.current = true;
6989
7038
  return () => {
6990
7039
  mounted.current = false;
@@ -7139,14 +7188,14 @@ function KjunScrollFade({ children }) {
7139
7188
 
7140
7189
  // packages/native/src/data-state.tsx
7141
7190
  var import_tokens40 = require("@kjun-ui/tokens");
7142
- var import_react57 = require("react");
7191
+ var import_react58 = require("react");
7143
7192
  var import_react_native42 = require("react-native");
7144
7193
 
7145
7194
  // shared/package-runtime/use-loading-reveal.ts
7146
- var import_react56 = require("react");
7195
+ var import_react57 = require("react");
7147
7196
  function useLoadingReveal(active, delay = 0) {
7148
- const [revealed, setRevealed] = (0, import_react56.useState)(false);
7149
- (0, import_react56.useEffect)(() => {
7197
+ const [revealed, setRevealed] = (0, import_react57.useState)(false);
7198
+ (0, import_react57.useEffect)(() => {
7150
7199
  setRevealed(false);
7151
7200
  if (!active || delay <= 0) return;
7152
7201
  const timer = setTimeout(() => setRevealed(true), delay);
@@ -7159,7 +7208,7 @@ function useLoadingReveal(active, delay = 0) {
7159
7208
  var import_jsx_runtime39 = require("react/jsx-runtime");
7160
7209
  function useQueryDisplay(props) {
7161
7210
  var _a;
7162
- const [state, setState] = (0, import_react57.useState)(() => (0, import_tokens40.initialQueryDisplay)(props));
7211
+ const [state, setState] = (0, import_react58.useState)(() => (0, import_tokens40.initialQueryDisplay)(props));
7163
7212
  let next = state;
7164
7213
  if (state.queryKey !== ((_a = props.queryKey) != null ? _a : null) || state.resultKey !== props.resultKey || state.loading !== !!props.loading) {
7165
7214
  next = (0, import_tokens40.advanceQueryDisplay)(state, props);
@@ -7268,7 +7317,7 @@ function BoundaryDescription() {
7268
7317
  const { colors } = useKjunStyles();
7269
7318
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(KText, { style: { ...typeStyle({ ...import_tokens40.tokens.typography.caption, fontSizePx: import_tokens40.tokens.extensions.state.descriptionSize }), color: colors.textSecondary, textAlign: "center" }, children: m.retryHint });
7270
7319
  }
7271
- var KjunErrorBoundary = class extends import_react57.Component {
7320
+ var KjunErrorBoundary = class extends import_react58.Component {
7272
7321
  constructor() {
7273
7322
  super(...arguments);
7274
7323
  this.state = { error: false };
@@ -7316,7 +7365,7 @@ KjunErrorBoundary.contextType = KjunMessageContext;
7316
7365
 
7317
7366
  // packages/native/src/skeletons.tsx
7318
7367
  var import_tokens44 = require("@kjun-ui/tokens");
7319
- var import_react59 = require("react");
7368
+ var import_react60 = require("react");
7320
7369
  var import_react_native44 = require("react-native");
7321
7370
  var import_react_native_svg5 = __toESM(require("react-native-svg"), 1);
7322
7371
 
@@ -7363,9 +7412,9 @@ function nativeMarketLayout(columns, showActions, containerWidth) {
7363
7412
 
7364
7413
  // packages/native/src/market-layout.ts
7365
7414
  var import_tokens42 = require("@kjun-ui/tokens");
7366
- var import_react58 = require("react");
7415
+ var import_react59 = require("react");
7367
7416
  function useMarketLayout(columns, showActions) {
7368
- const [containerWidth, setContainerWidth] = (0, import_react58.useState)(0);
7417
+ const [containerWidth, setContainerWidth] = (0, import_react59.useState)(0);
7369
7418
  const onLayout = (event) => setContainerWidth(event.nativeEvent.layout.width);
7370
7419
  return { ...nativeMarketLayout(columns, showActions, containerWidth), onLayout };
7371
7420
  }
@@ -7507,8 +7556,8 @@ function KjunChartSkeleton({
7507
7556
  }) {
7508
7557
  const m = useKjunMessages();
7509
7558
  loadingText != null ? loadingText : loadingText = m.chartLoading;
7510
- const kind = chartSkeletonKind(requestedKind), { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = (0, import_react59.useRef)(new import_react_native44.Animated.Value(1)).current, revealed = useLoadingReveal(true, loadingDelay), [measured, setMeasured] = (0, import_react59.useState)(0), thickness = import_tokens44.tokens.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" };
7511
- (0, import_react59.useEffect)(() => {
7559
+ const kind = chartSkeletonKind(requestedKind), { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = (0, import_react60.useRef)(new import_react_native44.Animated.Value(1)).current, revealed = useLoadingReveal(true, loadingDelay), [measured, setMeasured] = (0, import_react60.useState)(0), thickness = import_tokens44.tokens.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" };
7560
+ (0, import_react60.useEffect)(() => {
7512
7561
  if (reduced || !skeleton) return;
7513
7562
  const loop = import_react_native44.Animated.loop(
7514
7563
  import_react_native44.Animated.sequence([
@@ -7589,7 +7638,7 @@ function KjunChartSkeleton({
7589
7638
 
7590
7639
  // packages/native/src/financial-display.tsx
7591
7640
  var import_tokens47 = require("@kjun-ui/tokens");
7592
- var import_react62 = require("react");
7641
+ var import_react63 = require("react");
7593
7642
  var import_react_native46 = require("react-native");
7594
7643
  var import_react_native_svg6 = __toESM(require("react-native-svg"), 1);
7595
7644
 
@@ -7597,7 +7646,7 @@ var import_react_native_svg6 = __toESM(require("react-native-svg"), 1);
7597
7646
  var import_tokens46 = require("@kjun-ui/tokens");
7598
7647
 
7599
7648
  // shared/package-runtime/use-number-motion.ts
7600
- var import_react60 = require("react");
7649
+ var import_react61 = require("react");
7601
7650
 
7602
7651
  // shared/package-runtime/number-motion.ts
7603
7652
  var import_tokens45 = require("@kjun-ui/tokens");
@@ -7643,14 +7692,14 @@ function createNumberMotion(apply) {
7643
7692
 
7644
7693
  // shared/package-runtime/use-number-motion.ts
7645
7694
  function useNumberMotion(value, animated, fromPrevious, reduced) {
7646
- const [display, setDisplay] = (0, import_react60.useState)(typeof value === "string" || fromPrevious || !animated || reduced ? value : 0);
7647
- const motion = (0, import_react60.useRef)(null);
7695
+ const [display, setDisplay] = (0, import_react61.useState)(typeof value === "string" || fromPrevious || !animated || reduced ? value : 0);
7696
+ const motion = (0, import_react61.useRef)(null);
7648
7697
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
7649
- (0, import_react60.useLayoutEffect)(() => {
7698
+ (0, import_react61.useLayoutEffect)(() => {
7650
7699
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
7651
7700
  motion.current.update(value, animated, fromPrevious, reduced);
7652
7701
  }, [value, animated, fromPrevious, reduced]);
7653
- (0, import_react60.useLayoutEffect)(() => () => {
7702
+ (0, import_react61.useLayoutEffect)(() => () => {
7654
7703
  var _a;
7655
7704
  (_a = motion.current) == null ? void 0 : _a.cancel();
7656
7705
  motion.current = null;
@@ -7659,7 +7708,7 @@ function useNumberMotion(value, animated, fromPrevious, reduced) {
7659
7708
  }
7660
7709
 
7661
7710
  // packages/native/src/number-display.tsx
7662
- var import_react61 = require("react");
7711
+ var import_react62 = require("react");
7663
7712
  var import_react_native45 = require("react-native");
7664
7713
  var import_jsx_runtime42 = require("react/jsx-runtime");
7665
7714
  var finiteNumber = (value) => value == null || typeof value === "boolean" || typeof value === "string" && !value.trim() || !["number", "string"].includes(typeof value) || !Number.isFinite(Number(value)) ? null : Number(value) || 0;
@@ -7670,7 +7719,7 @@ var format = (value, decimals = 0) => new Intl.NumberFormat(void 0, {
7670
7719
  function useCountUp(value, animated, fromPrevious) {
7671
7720
  return useNumberMotion(value, animated, fromPrevious, useReducedMotion());
7672
7721
  }
7673
- var MarketQuoteTypeContext = (0, import_react61.createContext)(null);
7722
+ var MarketQuoteTypeContext = (0, import_react62.createContext)(null);
7674
7723
  function KjunAnimatedNumber({
7675
7724
  value,
7676
7725
  decimals = 0,
@@ -7731,7 +7780,7 @@ function KjunPriceCell({
7731
7780
  fetchedAt,
7732
7781
  fromPrevious = true
7733
7782
  }) {
7734
- const { colors } = useKjunStyles(), quoteType = (0, import_react61.useContext)(MarketQuoteTypeContext);
7783
+ const { colors } = useKjunStyles(), quoteType = (0, import_react62.useContext)(MarketQuoteTypeContext);
7735
7784
  return value == null ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(KjunSkeleton, { type: "block", height: import_tokens46.tokens.extensions.financial.priceSkeletonHeight, width: import_tokens46.tokens.extensions.financial.priceSkeletonWidth }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react_native45.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens46.tokens.extensions.financial.affixGap }, children: [
7736
7785
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7737
7786
  import_react_native45.View,
@@ -7765,7 +7814,7 @@ function KjunSignedValue({
7765
7814
  showFreshness = true,
7766
7815
  formatter
7767
7816
  }) {
7768
- const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), quoteType = (0, import_react61.useContext)(MarketQuoteTypeContext), n = finiteNumber(value), role = n === null || n === 0 ? "priceNeutral" : n > 0 ? "priceUp" : "priceDown", color = loading || n === null ? colors.textSecondary : stale ? colors.textTertiary : domainColor(domainColors, role);
7817
+ const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), quoteType = (0, import_react62.useContext)(MarketQuoteTypeContext), n = finiteNumber(value), role = n === null || n === 0 ? "priceNeutral" : n > 0 ? "priceUp" : "priceDown", color = loading || n === null ? colors.textSecondary : stale ? colors.textTertiary : domainColor(domainColors, role);
7769
7818
  const display = n === null ? "\u2014" : formatter ? formatter(n) : prefix + (showSign && n > 0 ? "+" : "") + format(kind === "percent" && !isRaw ? n * 100 : n, decimals) + (kind === "percent" ? "%" : "") + suffix;
7770
7819
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
7771
7820
  import_react_native45.View,
@@ -8061,7 +8110,7 @@ function KjunSparkline({
8061
8110
  stretch = false,
8062
8111
  ariaLabel
8063
8112
  }) {
8064
- const { colors, domainColors } = useKjunStyles(), id = "kjun-" + (0, import_react62.useId)().replace(/:/g, ""), values = data.filter(Number.isFinite), min = Math.min(...values), max = Math.max(...values), range = max - min || 1, points = values.map(
8113
+ const { colors, domainColors } = useKjunStyles(), id = "kjun-" + (0, import_react63.useId)().replace(/:/g, ""), values = data.filter(Number.isFinite), min = Math.min(...values), max = Math.max(...values), range = max - min || 1, points = values.map(
8065
8114
  (v, i) => `${2 + i / Math.max(1, values.length - 1) * (width - 4)},${2 + height - 4 - (v - min) / range * (height - 4)}`
8066
8115
  ).join(" "), change = values.length > 1 ? values[values.length - 1] - values[0] : 0, line = color || (change === 0 ? colors.textTertiary : semantic === "status" ? change > 0 ? colors.success : colors.danger : domainColor(domainColors, change > 0 ? "priceUp" : "priceDown"));
8067
8116
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
@@ -8107,7 +8156,7 @@ function KjunSparkline({
8107
8156
 
8108
8157
  // shared/package-runtime/table.ts
8109
8158
  var import_tokens48 = require("@kjun-ui/tokens");
8110
- var import_react63 = require("react");
8159
+ var import_react64 = require("react");
8111
8160
 
8112
8161
  // shared/package-runtime/table-model.ts
8113
8162
  function getValue(row, key) {
@@ -8151,11 +8200,11 @@ function useTableModel(props) {
8151
8200
  expandSingle = false,
8152
8201
  onExpandedRowsChange
8153
8202
  } = props;
8154
- const [internalSort, setSort] = (0, import_react63.useState)({
8203
+ const [internalSort, setSort] = (0, import_react64.useState)({
8155
8204
  key: "",
8156
8205
  order: "asc"
8157
- }), [internalExpanded, setExpanded] = (0, import_react63.useState)([]), [search, setSearch] = (0, import_react63.useState)(""), timer = (0, import_react63.useRef)(void 0);
8158
- (0, import_react63.useEffect)(() => () => clearTimeout(timer.current), []);
8206
+ }), [internalExpanded, setExpanded] = (0, import_react64.useState)([]), [search, setSearch] = (0, import_react64.useState)(""), timer = (0, import_react64.useRef)(void 0);
8207
+ (0, import_react64.useEffect)(() => () => clearTimeout(timer.current), []);
8159
8208
  const sort = props.sort === void 0 ? internalSort : (_a = props.sort) != null ? _a : { key: "", order: "asc" };
8160
8209
  const rows = sortTableRows(data, sort, { sortable, sortMode });
8161
8210
  const key = (row, index = 0) => tableRowKey(row, rowKey, index);
@@ -8316,7 +8365,7 @@ function TableToolbar({
8316
8365
 
8317
8366
  // packages/native/src/table-grid.tsx
8318
8367
  var import_tokens50 = require("@kjun-ui/tokens");
8319
- var import_react64 = require("react");
8368
+ var import_react65 = require("react");
8320
8369
  var import_react_native_svg7 = __toESM(require("react-native-svg"), 1);
8321
8370
  var import_react_native48 = require("react-native");
8322
8371
  var import_jsx_runtime45 = require("react/jsx-runtime");
@@ -8324,7 +8373,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8324
8373
  const m = useKjunMessages();
8325
8374
  const { colors } = useKjunStyles();
8326
8375
  const geometry2 = import_tokens50.tokens.table;
8327
- const [scroll, setScroll] = (0, import_react64.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-table-fade-" + (0, import_react64.useId)().replace(/[^a-z0-9]/gi, "");
8376
+ const [scroll, setScroll] = (0, import_react65.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-table-fade-" + (0, import_react65.useId)().replace(/[^a-z0-9]/gi, "");
8328
8377
  const cellPadding = geometry2.cellPadding[compact ? "compact" : "regular"];
8329
8378
  const width = (col) => typeof col.width === "number" ? col.width : typeof col.width === "string" && /^\d+(px)?$/.test(col.width) ? parseFloat(col.width) : geometry2.columnWidth;
8330
8379
  const totalWidth = visible.reduce((sum, col) => sum + width(col), 0) + (selectable ? geometry2.actionColumnWidth : 0) + (expandable ? geometry2.actionColumnWidth : 0);
@@ -8438,7 +8487,7 @@ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowC
8438
8487
  ))
8439
8488
  ] }, i)) : !state.rows.length ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react_native48.View, { style: { paddingVertical: geometry2.emptyPadding.y, paddingHorizontal: geometry2.emptyPadding.x, alignItems: "center" }, children: content(emptyContent || emptyText, {
8440
8489
  color: colors.textSecondary
8441
- }) }) : state.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react64.Fragment, { children: [
8490
+ }) }) : state.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_react65.Fragment, { children: [
8442
8491
  /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
8443
8492
  AccessiblePressable,
8444
8493
  {
@@ -9067,7 +9116,7 @@ function KjunKpiHero(props) {
9067
9116
 
9068
9117
  // packages/native/src/kpi-row.tsx
9069
9118
  var import_tokens54 = require("@kjun-ui/tokens");
9070
- var import_react65 = require("react");
9119
+ var import_react66 = require("react");
9071
9120
  var import_react_native53 = require("react-native");
9072
9121
  var import_jsx_runtime50 = require("react/jsx-runtime");
9073
9122
  function KjunKpiRow({
@@ -9082,7 +9131,7 @@ function KjunKpiRow({
9082
9131
  const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), mobile = (0, import_react_native53.useWindowDimensions)().width <= import_tokens54.tokens.responsive.kpiRow, small = size === "sm", summary = mobileSummary && mobile && !small;
9083
9132
  const geometry2 = import_tokens54.tokens.extensions.kpiRow;
9084
9133
  const spec = small ? geometry2.sm : mobile ? geometry2.mobile : geometry2.md;
9085
- const [width, setWidth] = (0, import_react65.useState)(0);
9134
+ const [width, setWidth] = (0, import_react66.useState)(0);
9086
9135
  const paddingX = summary ? geometry2.summary.paddingX : spec.paddingX;
9087
9136
  const gapX = summary ? geometry2.summary.gapX : 0;
9088
9137
  const explicit = items2.some(
@@ -9301,7 +9350,7 @@ var import_tokens56 = require("@kjun-ui/tokens");
9301
9350
  var import_react_native55 = require("react-native");
9302
9351
 
9303
9352
  // shared/package-runtime/market-cards.ts
9304
- var import_react66 = require("react");
9353
+ var import_react67 = require("react");
9305
9354
  function useMarketCardsModel(props, persistence) {
9306
9355
  const {
9307
9356
  columns,
@@ -9317,8 +9366,8 @@ function useMarketCardsModel(props, persistence) {
9317
9366
  sortKey: c.sortable ? metricConfig[c.key].sortKey : null,
9318
9367
  isDefaultSort: c.defaultSort
9319
9368
  }));
9320
- const [key, setKey] = (0, import_react66.useState)(""), restoreSignature = JSON.stringify([storageNamespace, pills]);
9321
- const mounted = (0, import_react66.useRef)("");
9369
+ const [key, setKey] = (0, import_react67.useState)(""), restoreSignature = JSON.stringify([storageNamespace, pills]);
9370
+ const mounted = (0, import_react67.useRef)("");
9322
9371
  const save = (key2) => {
9323
9372
  var _a;
9324
9373
  try {
@@ -9326,7 +9375,7 @@ function useMarketCardsModel(props, persistence) {
9326
9375
  } catch (e) {
9327
9376
  }
9328
9377
  };
9329
- (0, import_react66.useEffect)(() => {
9378
+ (0, import_react67.useEffect)(() => {
9330
9379
  var _a, _b;
9331
9380
  if (mounted.current === restoreSignature) return;
9332
9381
  mounted.current = restoreSignature;
@@ -9805,7 +9854,7 @@ function KjunMarketListPanel({
9805
9854
 
9806
9855
  // packages/native/src/market-table.tsx
9807
9856
  var import_tokens59 = require("@kjun-ui/tokens");
9808
- var import_react67 = require("react");
9857
+ var import_react68 = require("react");
9809
9858
  var import_react_native58 = require("react-native");
9810
9859
  var import_react_native_svg8 = __toESM(require("react-native-svg"), 1);
9811
9860
  var import_jsx_runtime55 = require("react/jsx-runtime");
@@ -9892,7 +9941,7 @@ function KjunMarketTable(props) {
9892
9941
  );
9893
9942
  };
9894
9943
  const layout = useMarketLayout(columns, showActions);
9895
- const [scroll, setScroll] = (0, import_react67.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-market-fade-" + (0, import_react67.useId)().replace(/[^a-z0-9]/gi, "");
9944
+ const [scroll, setScroll] = (0, import_react68.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-market-fade-" + (0, import_react68.useId)().replace(/[^a-z0-9]/gi, "");
9896
9945
  const tableQuote = { price: {}, change: { fontWeight: typeStyle("body").fontWeight } };
9897
9946
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
9898
9947
  import_react_native58.View,
@@ -10107,24 +10156,25 @@ function KjunMarketTable(props) {
10107
10156
 
10108
10157
  // packages/native/src/list.tsx
10109
10158
  var import_tokens60 = require("@kjun-ui/tokens");
10110
- var import_react68 = require("react");
10159
+ var import_react69 = require("react");
10111
10160
  var import_react_native59 = require("react-native");
10112
10161
  var import_jsx_runtime56 = require("react/jsx-runtime");
10113
- var ListRowContext = (0, import_react68.createContext)({ divider: true, compact: false });
10114
- function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, destructive = false, chevron = false, onPress }) {
10115
- const { colors } = useKjunStyles(), { divider, compact } = (0, import_react68.useContext)(ListRowContext);
10162
+ var ListRowContext = (0, import_react69.createContext)({ divider: true, compact: false });
10163
+ function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, destructive = false, chevron = false, onPress, ariaLabel, children }) {
10164
+ const { colors } = useKjunStyles(), { divider, compact } = (0, import_react69.useContext)(ListRowContext);
10116
10165
  const parts = /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
10117
10166
  hasContent(leading) && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { children: content(leading) }),
10118
10167
  /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native59.View, { style: { flex: 1, minWidth: 0 }, children: [
10119
10168
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(KText, { style: { ...typeStyle("label"), ...destructive ? { color: colors.danger } : {} }, children: title }),
10120
- !!description && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(KText, { style: { marginTop: import_tokens60.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
10169
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(KText, { style: { marginTop: import_tokens60.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description }),
10170
+ hasContent(children) && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { style: { marginTop: import_tokens60.tokens.extensions.list.descriptionGap }, children: content(children) })
10121
10171
  ] }),
10122
10172
  hasContent(trailing) && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { style: { maxWidth: "35%" }, children: content(trailing) }),
10123
10173
  chevron && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { accessible: false, importantForAccessibility: "no-hide-descendants", accessibilityElementsHidden: true, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(KjunIcon, { name: "chevron-right", size: import_tokens60.tokens.iconSizes.default, color: colors.textTertiary }) })
10124
10174
  ] });
10125
10175
  const style = { flex: 1, minWidth: 0, minHeight: compact ? import_tokens60.tokens.extensions.list.compactMinimumHeight : import_tokens60.tokens.extensions.list.minimumHeight, flexDirection: "row", alignItems: "center", gap: import_tokens60.tokens.extensions.list.gap, padding: import_tokens60.tokens.extensions.list.padding, ...compact ? { paddingVertical: import_tokens60.tokens.extensions.list.compactPaddingY } : {} };
10126
10176
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_react_native59.View, { role: "listitem", style: { flexDirection: "row", alignItems: "center", gap: import_tokens60.tokens.extensions.list.gap, borderBottomWidth: divider ? import_tokens60.tokens.border.defaultWidth : 0, borderBottomColor: colors.divider }, children: [
10127
- onPress || href ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(AccessiblePressable, { ...import_react_native59.Platform.OS === "web" && href && !disabled ? { href } : {}, accessibilityRole: href ? "link" : "button", accessibilityLabel: title + (description ? ", " + description : ""), disabled, accessibilityState: { disabled }, onPress, style: ({ pressed }) => ({ ...style, opacity: disabled ? import_tokens60.tokens.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { style, children: parts }),
10177
+ onPress || href ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(AccessiblePressable, { ...import_react_native59.Platform.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 ? import_tokens60.tokens.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { style, children: parts }),
10128
10178
  hasContent(actions) && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { pointerEvents: disabled ? "none" : "auto", ...disabled && import_react_native59.Platform.OS === "web" ? { inert: true } : {}, style: { maxWidth: "45%", flexDirection: "row", flexWrap: "wrap", gap: import_tokens60.tokens.extensions.list.actionsGap, paddingRight: import_tokens60.tokens.extensions.list.actionsPadding, opacity: disabled ? import_tokens60.tokens.states.opacity.disabled : 1 }, children: content(actions) })
10129
10179
  ] });
10130
10180
  }
@@ -10138,11 +10188,11 @@ function KjunListSection({ title, description, actions, children, ariaLabel, sur
10138
10188
  ] }),
10139
10189
  content(actions)
10140
10190
  ] }),
10141
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { role: "list", accessibilityLabel: ariaLabel || title, children: import_react68.Children.toArray(children).map((row, i, rows) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ListRowContext.Provider, { value: { divider: divider && i < rows.length - 1, compact: density === "compact" }, children: row }, i)) })
10191
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { role: "list", accessibilityLabel: ariaLabel || title, children: import_react69.Children.toArray(children).map((row, i, rows) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ListRowContext.Provider, { value: { divider: divider && i < rows.length - 1, compact: density === "compact" }, children: row }, i)) })
10142
10192
  ] });
10143
10193
  }
10144
10194
  function KjunListItem({ children }) {
10145
- const { colors } = useKjunStyles(), { divider, compact } = (0, import_react68.useContext)(ListRowContext);
10195
+ const { colors } = useKjunStyles(), { divider, compact } = (0, import_react69.useContext)(ListRowContext);
10146
10196
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { role: "listitem", style: {
10147
10197
  padding: import_tokens60.tokens.extensions.list.padding,
10148
10198
  ...compact ? { paddingVertical: import_tokens60.tokens.extensions.list.compactPaddingY } : {},
@@ -10154,7 +10204,7 @@ function KjunListItem({ children }) {
10154
10204
 
10155
10205
  // packages/native/src/app-navigation.tsx
10156
10206
  var import_tokens61 = require("@kjun-ui/tokens");
10157
- var import_react69 = require("react");
10207
+ var import_react70 = require("react");
10158
10208
  var import_react_native60 = require("react-native");
10159
10209
  var import_jsx_runtime57 = require("react/jsx-runtime");
10160
10210
  function KjunTopNavigation({ title, description, leading, actions, safeAreaTop = 0 }) {
@@ -10163,13 +10213,13 @@ function KjunTopNavigation({ title, description, leading, actions, safeAreaTop =
10163
10213
  const titleInset = Math.max(0, (geometry2.controlSize - import_tokens61.tokens.typography.sectionTitle.lineHeightPx) / 2);
10164
10214
  const wrapping = import_react_native60.Platform.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
10165
10215
  const edgeInset = (geometry2.controlSize - geometry2.iconSize) / 2;
10166
- const [iconEdges, setIconEdges] = (0, import_react69.useState)({ leading: false, trailing: false });
10216
+ const [iconEdges, setIconEdges] = (0, import_react70.useState)({ leading: false, trailing: false });
10167
10217
  const square = (key) => (event) => {
10168
10218
  const { width, height } = event.nativeEvent.layout;
10169
10219
  const next = Math.abs(width - height) < 1 && Math.abs(height - geometry2.controlSize) < 1;
10170
10220
  setIconEdges((current) => current[key] === next ? current : { ...current, [key]: next });
10171
10221
  };
10172
- const flatten2 = (node) => import_react69.Children.toArray(node).flatMap((child) => (0, import_react69.isValidElement)(child) && child.type === import_react69.Fragment ? flatten2(child.props.children) : [child]);
10222
+ const flatten2 = (node) => import_react70.Children.toArray(node).flatMap((child) => (0, import_react70.isValidElement)(child) && child.type === import_react70.Fragment ? flatten2(child.props.children) : [child]);
10173
10223
  const actionList = flatten2(actions);
10174
10224
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TopNavigationContext.Provider, { value: geometry2, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native60.View, { style: { flexShrink: 0, paddingTop: Math.max(0, safeAreaTop), backgroundColor: colors.surface }, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native60.View, { style: { minHeight: geometry2.minimumHeight, flexDirection: "row", flexWrap: "wrap", alignItems: "flex-start", gap: geometry2.gap, paddingVertical: geometry2.paddingY, paddingHorizontal: geometry2.paddingX }, children: [
10175
10225
  hasContent(leading) && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TopNavigationContext.Provider, { value: { ...geometry2, slot: "leading" }, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_react_native60.View, { onLayout: square("leading"), style: { minHeight: geometry2.controlSize, minWidth: 0, maxWidth: "40%", flexShrink: 1, justifyContent: "center", marginLeft: iconEdges.leading ? -edgeInset : 0 }, children: content(leading) }) }),
@@ -10245,7 +10295,7 @@ function KjunBottomNavigation({ items: items2, value, ariaLabel, safeAreaBottom
10245
10295
  }
10246
10296
  function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboardVisible = false, hideOnKeyboard = false }) {
10247
10297
  const { colors } = useKjunStyles();
10248
- const [width, setWidth] = (0, import_react69.useState)(0);
10298
+ const [width, setWidth] = (0, import_react70.useState)(0);
10249
10299
  const geometry2 = import_tokens61.tokens.extensions.navigation;
10250
10300
  const wide = width >= import_tokens61.tokens.responsive.bottomAction + geometry2.padding * 2;
10251
10301
  const wrapping = import_react_native60.Platform.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
@@ -10267,17 +10317,17 @@ function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboa
10267
10317
  }
10268
10318
 
10269
10319
  // packages/native/src/media.tsx
10270
- var import_react70 = require("react");
10320
+ var import_react71 = require("react");
10271
10321
  var import_react_native61 = require("react-native");
10272
10322
  var import_tokens62 = require("@kjun-ui/tokens");
10273
10323
  var import_jsx_runtime58 = require("react/jsx-runtime");
10274
- var ImageBackgroundContext = (0, import_react70.createContext)(void 0);
10324
+ var ImageBackgroundContext = (0, import_react71.createContext)(void 0);
10275
10325
  function KjunImage({ src, source, alt, decorative = false, aspectRatio = 1, fit = "cover", fallback: fallback2, onLoad, onError }) {
10276
- const { colors } = useKjunStyles(), background = (0, import_react70.useContext)(ImageBackgroundContext);
10277
- const request = JSON.stringify(source != null ? source : src), current = (0, import_react70.useRef)({ request, version: 0 });
10326
+ const { colors } = useKjunStyles(), background = (0, import_react71.useContext)(ImageBackgroundContext);
10327
+ const request = JSON.stringify(source != null ? source : src), current = (0, import_react71.useRef)({ request, version: 0 });
10278
10328
  if (current.current.request !== request) current.current = { request, version: current.current.version + 1 };
10279
10329
  const version = current.current.version;
10280
- const [failed, setFailed] = (0, import_react70.useState)(null);
10330
+ const [failed, setFailed] = (0, import_react71.useState)(null);
10281
10331
  const missing = !source && !src;
10282
10332
  return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_react_native61.View, { 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__ */ (0, import_jsx_runtime58.jsx)(import_react_native61.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: () => {
10283
10333
  if (version === current.current.version) onLoad == null ? void 0 : onLoad();
@@ -10342,7 +10392,7 @@ function KjunFab({ icon, ariaLabel, disabled = false, safeAreaBottom = 0, offset
10342
10392
  }
10343
10393
 
10344
10394
  // packages/native/src/range-input.tsx
10345
- var import_react71 = require("react");
10395
+ var import_react72 = require("react");
10346
10396
  var import_react_native63 = require("react-native");
10347
10397
  var import_tokens65 = require("@kjun-ui/tokens");
10348
10398
  var import_jsx_runtime61 = require("react/jsx-runtime");
@@ -10367,18 +10417,18 @@ function RangeInput({
10367
10417
  const valid = domain.valid && (!Array.isArray(value) || value.length === 2) && values.every(domain.accepts) && (values.length === 1 || values[0] <= values[1]);
10368
10418
  const blocked = disabled || !valid;
10369
10419
  const effectiveMax = valid ? domain.snap(max) : min;
10370
- const [hovered, setHovered] = (0, import_react71.useState)(null);
10371
- const [dragging, setDragging] = (0, import_react71.useState)(null);
10372
- const [focused, setFocused] = (0, import_react71.useState)(null);
10373
- const track = (0, import_react71.useRef)(null), measured = (0, import_react71.useRef)({ x: 0, width: 1 }), selected = (0, import_react71.useRef)(0), dirty = (0, import_react71.useRef)(false);
10374
- const latest = (0, import_react71.useRef)(values);
10420
+ const [hovered, setHovered] = (0, import_react72.useState)(null);
10421
+ const [dragging, setDragging] = (0, import_react72.useState)(null);
10422
+ const [focused, setFocused] = (0, import_react72.useState)(null);
10423
+ const track = (0, import_react72.useRef)(null), measured = (0, import_react72.useRef)({ x: 0, width: 1 }), selected = (0, import_react72.useRef)(0), dirty = (0, import_react72.useRef)(false);
10424
+ const latest = (0, import_react72.useRef)(values);
10375
10425
  latest.current = values;
10376
- const callbacks = (0, import_react71.useRef)({ onValueChange, onChangeCommit });
10426
+ const callbacks = (0, import_react72.useRef)({ onValueChange, onChangeCommit });
10377
10427
  callbacks.current = { onValueChange, onChangeCommit };
10378
- (0, import_react71.useEffect)(() => {
10428
+ (0, import_react72.useEffect)(() => {
10379
10429
  if (!valid) console.warn("KJUN Slider: \uBC94\uC704\xB7step\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10380
10430
  }, [valid]);
10381
- (0, import_react71.useEffect)(() => {
10431
+ (0, import_react72.useEffect)(() => {
10382
10432
  if (blocked) {
10383
10433
  setDragging(null);
10384
10434
  setHovered(null);
@@ -10418,7 +10468,7 @@ function RangeInput({
10418
10468
  measured.current = { x: pageX, width: Math.max(1, width) };
10419
10469
  });
10420
10470
  };
10421
- const responder = (0, import_react71.useMemo)(
10471
+ const responder = (0, import_react72.useMemo)(
10422
10472
  () => import_react_native63.PanResponder.create({
10423
10473
  onStartShouldSetPanResponderCapture: () => !disabled && valid,
10424
10474
  onMoveShouldSetPanResponderCapture: (_event, gesture) => !disabled && valid && Math.abs(gesture.dx) > 3 && Math.abs(gesture.dx) > Math.abs(gesture.dy),
@@ -10643,7 +10693,7 @@ function KjunRangeSlider(props) {
10643
10693
  }
10644
10694
 
10645
10695
  // packages/native/src/quantity-stepper.tsx
10646
- var import_react72 = require("react");
10696
+ var import_react73 = require("react");
10647
10697
  var import_react_native64 = require("react-native");
10648
10698
  var import_tokens66 = require("@kjun-ui/tokens");
10649
10699
 
@@ -10666,16 +10716,16 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10666
10716
  const increaseStyle = { ...buttonStyle, borderRadius: 0, borderTopRightRadius: outer, borderBottomRightRadius: outer };
10667
10717
  const domain = (0, import_tokens66.createNumberDomain)({ min, max, step, precision }), valid = domain.valid && domain.accepts(value), blocked = disabled || !valid;
10668
10718
  const surface = useFieldSurface(size, { disabled: blocked, invalid });
10669
- const [draft, setDraft] = (0, import_react72.useState)(String(value));
10670
- const inputRef = (0, import_react72.useRef)(null);
10671
- const composing = (0, import_react72.useRef)(false), dirty = (0, import_react72.useRef)(false), accepted = (0, import_react72.useRef)(value);
10672
- const cancelledEscape = (0, import_react72.useRef)(false);
10673
- (0, import_react72.useEffect)(() => {
10719
+ const [draft, setDraft] = (0, import_react73.useState)(String(value));
10720
+ const inputRef = (0, import_react73.useRef)(null);
10721
+ const composing = (0, import_react73.useRef)(false), dirty = (0, import_react73.useRef)(false), accepted = (0, import_react73.useRef)(value);
10722
+ const cancelledEscape = (0, import_react73.useRef)(false);
10723
+ (0, import_react73.useEffect)(() => {
10674
10724
  setDraft(String(value));
10675
10725
  accepted.current = value;
10676
10726
  dirty.current = false;
10677
10727
  }, [value, precision, min, max, step]);
10678
- (0, import_react72.useEffect)(() => {
10728
+ (0, import_react73.useEffect)(() => {
10679
10729
  if (!valid) console.warn("KJUN QuantityStepper: \uBC94\uC704\xB7step\xB7\uC815\uBC00\uB3C4\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10680
10730
  }, [valid]);
10681
10731
  const emit = (next) => {
@@ -10712,7 +10762,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10712
10762
  } else if (action === "commit") commit();
10713
10763
  else move(action === "increment" ? 1 : -1);
10714
10764
  };
10715
- const handlers = (0, import_react72.useRef)({ key, edit: (text) => {
10765
+ const handlers = (0, import_react73.useRef)({ key, edit: (text) => {
10716
10766
  dirty.current = true;
10717
10767
  setDraft(text);
10718
10768
  } });
@@ -10720,7 +10770,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10720
10770
  dirty.current = true;
10721
10771
  setDraft(text);
10722
10772
  } };
10723
- (0, import_react72.useEffect)(() => {
10773
+ (0, import_react73.useEffect)(() => {
10724
10774
  if (import_react_native64.Platform.OS !== "web") return;
10725
10775
  const input = inputRef.current;
10726
10776
  const keydown = (event) => handlers.current.key(event);
@@ -10792,7 +10842,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10792
10842
  }
10793
10843
 
10794
10844
  // packages/native/src/time-picker.tsx
10795
- var import_react73 = require("react");
10845
+ var import_react74 = require("react");
10796
10846
  var import_react_native65 = require("react-native");
10797
10847
  var import_tokens67 = require("@kjun-ui/tokens");
10798
10848
  var import_jsx_runtime63 = require("react/jsx-runtime");
@@ -10801,12 +10851,12 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
10801
10851
  ariaLabel != null ? ariaLabel : ariaLabel = m.time;
10802
10852
  const geometry2 = import_tokens67.tokens.extensions.timePicker, spec = import_tokens67.tokens.input[size];
10803
10853
  const { colors } = useKjunStyles();
10804
- const first = (0, import_react73.useRef)(null);
10805
- const [focused, setFocused] = (0, import_react73.useState)(false), [opened, setOpened] = (0, import_react73.useState)(null);
10806
- const field = useKjunField(), uid = (0, import_react73.useId)();
10854
+ const first = (0, import_react74.useRef)(null);
10855
+ const [focused, setFocused] = (0, import_react74.useState)(false), [opened, setOpened] = (0, import_react74.useState)(null);
10856
+ const field = useKjunField(), uid = (0, import_react74.useId)();
10807
10857
  const fieldId = (field == null ? void 0 : field.id) || `kjun-time-${uid}`;
10808
- const domain = (0, import_react73.useMemo)(() => (0, import_tokens67.createTimeDomain)({ precision, min, max, minuteStep, secondStep }), [precision, min, max, minuteStep, secondStep]), valid = domain.valid && domain.accepts(value);
10809
- (0, import_react73.useEffect)(() => {
10858
+ const domain = (0, import_react74.useMemo)(() => (0, import_tokens67.createTimeDomain)({ precision, min, max, minuteStep, secondStep }), [precision, min, max, minuteStep, secondStep]), valid = domain.valid && domain.accepts(value);
10859
+ (0, import_react74.useEffect)(() => {
10810
10860
  if (!valid) console.warn("KJUN TimePicker: \uC2DC\uAC01 \uBC94\uC704\xB7\uAC04\uACA9\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10811
10861
  }, [valid]);
10812
10862
  const change = (next) => {
@@ -10817,7 +10867,7 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
10817
10867
  };
10818
10868
  const time = value === null ? null : domain.parse(value);
10819
10869
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_react_native65.View, { accessibilityLabel: ariaLabel, style: { flexDirection: "row", alignItems: "center", maxWidth: "100%", minWidth: 0, backgroundColor: colors.inputBg, borderRadius: spec.radius }, children: [
10820
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_react_native65.View, { style: { flex: 1, flexDirection: "row", alignItems: "center", minWidth: 0 }, children: [m.hour, m.minute, m.second].slice(0, precision === "second" ? 3 : 2).map((label, index) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_react73.Fragment, { children: [
10870
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_react_native65.View, { style: { flex: 1, flexDirection: "row", alignItems: "center", minWidth: 0 }, children: [m.hour, m.minute, m.second].slice(0, precision === "second" ? 3 : 2).map((label, index) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_react74.Fragment, { children: [
10821
10871
  index > 0 && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(KText, { "aria-hidden": true, style: { ...inputTypeStyle(size), width: geometry2.separatorWidth, textAlign: "center", color: disabled || !valid ? colors.textDisabled : colors.textSecondary }, children: ":" }),
10822
10872
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(FieldContext.Provider, { value: { ...field, id: index === 0 ? fieldId : `${fieldId}-${index}` }, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(CompoundControlContext.Provider, { value: { size, focusRef: index === 0 ? first : void 0, onFocusChange: setFocused, leading: index === 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_react_native65.View, { style: { flexShrink: 0, minWidth: geometry2.segmentMinimumWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(KjunSelect, { value: time === null ? null : domain.part(time, index), options: domain.options(value, index).map((n) => ({ value: n, label: String(n).padStart(2, "0") })), onValueChange: (next) => {
10823
10873
  if (typeof next === "number") change(domain.select(value, index, next));