@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.
package/dist/index.js CHANGED
@@ -1738,6 +1738,18 @@ function KjunFormLayout({
1738
1738
  ) });
1739
1739
  }
1740
1740
 
1741
+ // shared/package-runtime/use-after-close.ts
1742
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef6 } from "react";
1743
+ function useAfterClose(present, onAfterClose, enabled = true) {
1744
+ const was = useRef6(present), callback = useRef6(onAfterClose);
1745
+ callback.current = onAfterClose;
1746
+ useEffect4(() => {
1747
+ var _a;
1748
+ if (was.current && !present && enabled) (_a = callback.current) == null ? void 0 : _a.call(callback);
1749
+ was.current = present;
1750
+ }, [present, enabled]);
1751
+ }
1752
+
1741
1753
  // shared/package-runtime/content-presence.ts
1742
1754
  import { Fragment as Fragment2, isValidElement as isValidElement2 } from "react";
1743
1755
  function hasContent(node) {
@@ -1779,8 +1791,9 @@ import {
1779
1791
  import {
1780
1792
  createContext as createContext14,
1781
1793
  useContext as useContext9,
1782
- useEffect as useEffect4,
1783
- useId as useId3
1794
+ useEffect as useEffect5,
1795
+ useId as useId3,
1796
+ useRef as useRef7
1784
1797
  } from "react";
1785
1798
  import { Platform as Platform9, View as View6 } from "react-native";
1786
1799
 
@@ -1797,13 +1810,14 @@ var FeedbackOverlayContext = createContext14(
1797
1810
  null
1798
1811
  );
1799
1812
  function ScopedNativeModal({ children, visible, ...props }) {
1800
- var _a;
1801
1813
  const layers = useLayerState(), scope = useContext9(LayerScope);
1802
1814
  const entry = scope ? layers.entries.get(scope) : void 0;
1803
- const generation = (_a = entry == null ? void 0 : entry.order) != null ? _a : 0;
1815
+ const last = useRef7(0);
1816
+ if (entry) last.current = entry.order;
1817
+ const generation = last.current;
1804
1818
  const inactive = !!scope && !layers.isActive(scope);
1805
1819
  const host = useContext9(FeedbackOverlayContext), id = "kjun-" + useId3(), register = host == null ? void 0 : host.register;
1806
- useEffect4(
1820
+ useEffect5(
1807
1821
  () => visible && register ? register(id) : void 0,
1808
1822
  [visible, register, id, generation]
1809
1823
  );
@@ -1928,6 +1942,7 @@ function KjunModal({
1928
1942
  open,
1929
1943
  onOpenChange,
1930
1944
  onClose,
1945
+ onAfterClose,
1931
1946
  onCancel,
1932
1947
  onConfirm,
1933
1948
  title = "",
@@ -1975,10 +1990,15 @@ function KjunModal({
1975
1990
  const layer = useLayer(open, motion.present, "window", () => {
1976
1991
  if (closeOnEsc) close();
1977
1992
  });
1993
+ const iosDismiss = Platform10.OS === "ios";
1994
+ useAfterClose(motion.present, onAfterClose, !iosDismiss);
1978
1995
  return /* @__PURE__ */ jsx13(LayerScope.Provider, { value: layer.id, children: /* @__PURE__ */ jsx13(
1979
1996
  ScopedNativeModal,
1980
1997
  {
1981
1998
  visible: motion.present,
1999
+ onDismiss: iosDismiss ? () => {
2000
+ if (!open) onAfterClose == null ? void 0 : onAfterClose();
2001
+ } : void 0,
1982
2002
  transparent: true,
1983
2003
  animationType: "none",
1984
2004
  onRequestClose: () => {
@@ -2246,7 +2266,7 @@ function alertRole(tone, live) {
2246
2266
 
2247
2267
  // packages/native/src/display-primitives.tsx
2248
2268
  import { tokens as tokens12 } from "@kjun-ui/tokens";
2249
- import { useContext as useContext10, useEffect as useEffect5, useRef as useRef6, useState as useState9 } from "react";
2269
+ import { useContext as useContext10, useEffect as useEffect6, useRef as useRef8, useState as useState9 } from "react";
2250
2270
  import {
2251
2271
  Animated as Animated5,
2252
2272
  Easing as Easing3,
@@ -2410,8 +2430,8 @@ function KjunEmpty({
2410
2430
  }
2411
2431
  function KjunSpinner({ size = "md", text }) {
2412
2432
  const m = useKjunMessages();
2413
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), rotation = useRef6(new Animated5.Value(0)).current;
2414
- useEffect5(() => {
2433
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), rotation = useRef8(new Animated5.Value(0)).current;
2434
+ useEffect6(() => {
2415
2435
  if (reduced) return;
2416
2436
  const loop = Animated5.loop(
2417
2437
  Animated5.timing(rotation, {
@@ -2704,7 +2724,7 @@ function KjunProgress({
2704
2724
 
2705
2725
  // packages/native/src/skeleton-base.tsx
2706
2726
  import { tokens as tokens13 } from "@kjun-ui/tokens";
2707
- import { useEffect as useEffect6, useRef as useRef7 } from "react";
2727
+ import { useEffect as useEffect7, useRef as useRef9 } from "react";
2708
2728
  import {
2709
2729
  Animated as Animated6,
2710
2730
  View as View10
@@ -2719,8 +2739,8 @@ function KjunSkeleton({
2719
2739
  animated = true,
2720
2740
  rounded = true
2721
2741
  }) {
2722
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef7(new Animated6.Value(1)).current;
2723
- useEffect6(() => {
2742
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef9(new Animated6.Value(1)).current;
2743
+ useEffect7(() => {
2724
2744
  if (!animated || reduced) return;
2725
2745
  const loop = Animated6.loop(
2726
2746
  Animated6.sequence([
@@ -2898,13 +2918,15 @@ var toneRole = {
2898
2918
  inverse: "onBrand"
2899
2919
  };
2900
2920
  var textAlign = { start: "left", center: "center", end: "right" };
2901
- function KjunText({ variant = "body", tone = "default", align, maxLines, style, children }) {
2921
+ function KjunText({ variant = "body", tone = "default", align, maxLines, style, children, ...rest }) {
2922
+ var _a;
2902
2923
  const { colors, fontFamily, numericFontFamily } = useKjunStyles();
2903
2924
  const lines = maxLines && maxLines > 0 ? Math.floor(maxLines) : void 0;
2904
2925
  return /* @__PURE__ */ jsx17(
2905
2926
  KText,
2906
2927
  {
2907
- accessibilityRole: titleVariants.includes(variant) ? "header" : void 0,
2928
+ ...rest,
2929
+ accessibilityRole: (_a = rest.accessibilityRole) != null ? _a : titleVariants.includes(variant) ? "header" : void 0,
2908
2930
  numberOfLines: lines,
2909
2931
  ellipsizeMode: lines ? "tail" : void 0,
2910
2932
  style: [
@@ -2972,13 +2994,13 @@ function KjunInline({ gap = "sm", align, justify = "start", wrap = true, style,
2972
2994
  }
2973
2995
 
2974
2996
  // shared/package-runtime/feedback-dialog.ts
2975
- import { useRef as useRef8, useState as useState10 } from "react";
2997
+ import { useRef as useRef10, useState as useState10 } from "react";
2976
2998
  function useFeedbackDialog(controller, request, messages = kjunMessagesKo) {
2977
2999
  const options = request.options;
2978
3000
  const [value, setValue] = useState10(options.initialValue || "");
2979
3001
  const [error, setError] = useState10("");
2980
3002
  const [busy, setBusy] = useState10(false);
2981
- const working = useRef8(false);
3003
+ const working = useRef10(false);
2982
3004
  const active = () => {
2983
3005
  var _a;
2984
3006
  return ((_a = controller.getSnapshot().current) == null ? void 0 : _a.id) === request.id;
@@ -3021,10 +3043,10 @@ function useFeedbackDialog(controller, request, messages = kjunMessagesKo) {
3021
3043
 
3022
3044
  // shared/package-runtime/feedback-motion.ts
3023
3045
  import { tokens as tokens15 } from "@kjun-ui/tokens";
3024
- import { useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState11 } from "react";
3046
+ import { useLayoutEffect as useLayoutEffect4, useRef as useRef11, useState as useState11 } from "react";
3025
3047
  function usePresentedToasts(toasts, reduced) {
3026
3048
  const [items2, setItems] = useState11([]);
3027
- const removals = useRef9(/* @__PURE__ */ new Map());
3049
+ const removals = useRef11(/* @__PURE__ */ new Map());
3028
3050
  useLayoutEffect4(() => {
3029
3051
  const ids = new Set(toasts.map((toast) => toast.id));
3030
3052
  setItems((previous) => {
@@ -3074,7 +3096,7 @@ function useOptionalKjunFeedback() {
3074
3096
  }
3075
3097
 
3076
3098
  // packages/native/src/toast-stack.tsx
3077
- import { useLayoutEffect as useLayoutEffect5, useRef as useRef11 } from "react";
3099
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef13 } from "react";
3078
3100
  import { Animated as Animated8, Platform as Platform13, View as View13 } from "react-native";
3079
3101
  import { tokens as tokens17 } from "@kjun-ui/tokens";
3080
3102
 
@@ -3092,7 +3114,7 @@ function shadowLayers(layers, colors) {
3092
3114
 
3093
3115
  // packages/native/src/toast.tsx
3094
3116
  import { tokens as tokens16 } from "@kjun-ui/tokens";
3095
- import { useEffect as useEffect7, useRef as useRef10 } from "react";
3117
+ import { useEffect as useEffect8, useRef as useRef12 } from "react";
3096
3118
  import { Animated as Animated7, View as View12 } from "react-native";
3097
3119
  import { jsx as jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
3098
3120
  function ToastView({
@@ -3100,14 +3122,14 @@ function ToastView({
3100
3122
  controller
3101
3123
  }) {
3102
3124
  const m = useKjunMessages();
3103
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), progress = useRef10(new Animated7.Value(1)).current;
3104
- const reasons = useRef10({
3125
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), progress = useRef12(new Animated7.Value(1)).current;
3126
+ const reasons = useRef12({
3105
3127
  hover: /* @__PURE__ */ Symbol("hover"),
3106
3128
  actionHover: /* @__PURE__ */ Symbol("actionHover"),
3107
3129
  closeHover: /* @__PURE__ */ Symbol("closeHover"),
3108
3130
  focus: /* @__PURE__ */ Symbol("focus")
3109
3131
  }).current;
3110
- useEffect7(() => () => {
3132
+ useEffect8(() => () => {
3111
3133
  for (const reason of Object.values(reasons)) controller.resumeToast(toast.id, reason);
3112
3134
  }, [controller, toast.id, reasons]);
3113
3135
  const tone = toast.type === "error" ? "danger" : toast.type || "info", icon = {
@@ -3116,7 +3138,7 @@ function ToastView({
3116
3138
  warning: "alert-triangle",
3117
3139
  info: "info-circle"
3118
3140
  }[tone];
3119
- useEffect7(() => {
3141
+ useEffect8(() => {
3120
3142
  progress.stopAnimation();
3121
3143
  progress.setValue(toast.duration ? toast.remaining / toast.duration : 1);
3122
3144
  if (!toast.paused && !reduced) {
@@ -3236,9 +3258,9 @@ function useToastReflow(_root, _reduced) {
3236
3258
  // packages/native/src/toast-stack.tsx
3237
3259
  import { jsx as jsx19 } from "react/jsx-runtime";
3238
3260
  function ToastSlot({ item, controller, boxes }) {
3239
- const born = useRef11(Math.min(tokens17.motion.toastEnter, Date.now() - item.born)).current;
3261
+ const born = useRef13(Math.min(tokens17.motion.toastEnter, Date.now() - item.born)).current;
3240
3262
  const motion = useNativePresence(!item.exiting, tokens17.motion.toastEnter - born, tokens17.motion.toastExit, true, born / tokens17.motion.toastEnter);
3241
- const offset = useRef11(new Animated8.Value(0)).current;
3263
+ const offset = useRef13(new Animated8.Value(0)).current;
3242
3264
  const box = boxes.get(item.toast.id);
3243
3265
  useLayoutEffect5(() => {
3244
3266
  if (motion.reduced) {
@@ -3285,9 +3307,9 @@ function ToastSlot({ item, controller, boxes }) {
3285
3307
  function ToastStack({ items: items2, controller }) {
3286
3308
  var _a;
3287
3309
  const layers = useLayerState();
3288
- const root = useRef11(null), reduced = useReducedMotion();
3310
+ const root = useRef13(null), reduced = useReducedMotion();
3289
3311
  useToastReflow(root, reduced);
3290
- const boxes = useRef11(/* @__PURE__ */ new Map()).current;
3312
+ const boxes = useRef13(/* @__PURE__ */ new Map()).current;
3291
3313
  for (const id of boxes.keys()) if (!items2.some((item) => item.toast.id === id)) boxes.delete(id);
3292
3314
  return /* @__PURE__ */ jsx19(View13, { ref: root, pointerEvents: "box-none", style: {
3293
3315
  position: "absolute",
@@ -3307,9 +3329,9 @@ import {
3307
3329
  feedbackControllerOf
3308
3330
  } from "@kjun-ui/tokens";
3309
3331
  import {
3310
- useCallback as useCallback3,
3311
- useEffect as useEffect8,
3312
- useRef as useRef12,
3332
+ useCallback as useCallback4,
3333
+ useEffect as useEffect9,
3334
+ useRef as useRef14,
3313
3335
  useState as useState12,
3314
3336
  useSyncExternalStore as useSyncExternalStore2
3315
3337
  } from "react";
@@ -3366,8 +3388,8 @@ function FeedbackDialog({
3366
3388
  function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3367
3389
  const [owned] = useState12(() => controllerProp ? void 0 : createFeedbackController());
3368
3390
  const controller = controllerProp ? feedbackControllerOf(controllerProp) : owned;
3369
- useEffect8(() => controller.attach(), [controller]);
3370
- const life = useRef12(0);
3391
+ useEffect9(() => controller.attach(), [controller]);
3392
+ const life = useRef14(0);
3371
3393
  const snapshot = useSyncExternalStore2(
3372
3394
  controller.subscribe,
3373
3395
  controller.getSnapshot,
@@ -3376,7 +3398,7 @@ function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3376
3398
  const reduced = useReducedMotion();
3377
3399
  const toasts = usePresentedToasts(snapshot.toasts, reduced);
3378
3400
  const dialog = usePresentedRequest(snapshot.current, reduced);
3379
- useEffect8(() => {
3401
+ useEffect9(() => {
3380
3402
  const version = ++life.current;
3381
3403
  return () => {
3382
3404
  queueMicrotask(() => {
@@ -3385,7 +3407,7 @@ function KjunFeedbackProvider({ children, style, controller: controllerProp }) {
3385
3407
  };
3386
3408
  }, [controller]);
3387
3409
  const [layers, setLayers] = useState12([]);
3388
- const register = useCallback3((id) => {
3410
+ const register = useCallback4((id) => {
3389
3411
  setLayers((previous) => [...previous, id]);
3390
3412
  return () => setLayers((previous) => previous.filter((item) => item !== id));
3391
3413
  }, []);
@@ -3420,8 +3442,8 @@ import {
3420
3442
  createContext as createContext16,
3421
3443
  useContext as useContext12,
3422
3444
  useState as useState13,
3423
- useEffect as useEffect9,
3424
- useRef as useRef13
3445
+ useEffect as useEffect10,
3446
+ useRef as useRef15
3425
3447
  } from "react";
3426
3448
  import {
3427
3449
  View as View15
@@ -3623,7 +3645,7 @@ function KjunRadio({
3623
3645
  const group = useContext12(RadioContext), { colors } = useKjunStyles(), selected = (group ? group.value : value) === val;
3624
3646
  const geometry2 = tokens19.extensions.radio;
3625
3647
  const [hovered, setHovered] = useState13(false);
3626
- useEffect9(() => {
3648
+ useEffect10(() => {
3627
3649
  if (disabled) setHovered(false);
3628
3650
  }, [disabled]);
3629
3651
  return /* @__PURE__ */ jsx21(
@@ -3695,7 +3717,7 @@ function KjunRadioGroup({
3695
3717
  onValueChange,
3696
3718
  onChange
3697
3719
  }) {
3698
- const root = useRef13(null);
3720
+ const root = useRef15(null);
3699
3721
  useRadioKeyboard(root);
3700
3722
  return /* @__PURE__ */ jsx21(
3701
3723
  RadioContext.Provider,
@@ -3735,7 +3757,7 @@ function KjunRadioGroup({
3735
3757
 
3736
3758
  // packages/native/src/selection-groups.tsx
3737
3759
  import { tokens as tokens21 } from "@kjun-ui/tokens";
3738
- import { useLayoutEffect as useLayoutEffect7, useRef as useRef15 } from "react";
3760
+ import { useLayoutEffect as useLayoutEffect7, useRef as useRef17 } from "react";
3739
3761
  import {
3740
3762
  Animated as Animated11,
3741
3763
  ScrollView as ScrollView2,
@@ -3744,7 +3766,7 @@ import {
3744
3766
  } from "react-native";
3745
3767
 
3746
3768
  // packages/native/src/button-group-motion.tsx
3747
- import { useCallback as useCallback4, useEffect as useEffect10, useLayoutEffect as useLayoutEffect6, useRef as useRef14, useState as useState14 } from "react";
3769
+ import { useCallback as useCallback5, useEffect as useEffect11, useLayoutEffect as useLayoutEffect6, useRef as useRef16, useState as useState14 } from "react";
3748
3770
  import { Animated as Animated10, Easing as Easing4, StyleSheet as StyleSheet5, View as View16 } from "react-native";
3749
3771
  import { tokens as tokens20 } from "@kjun-ui/tokens";
3750
3772
  import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
@@ -3754,14 +3776,14 @@ var sameBox = (a, b) => a.x === b.x && a.y === b.y && a.width === b.width && a.h
3754
3776
  function useButtonGroupMotion(selected) {
3755
3777
  const reduced = useReducedMotion();
3756
3778
  const [layouts, setLayouts] = useState14(/* @__PURE__ */ new Map());
3757
- const x = useRef14(new Animated10.Value(0)).current;
3758
- const width = useRef14(new Animated10.Value(0)).current;
3759
- const previous = useRef14(null);
3779
+ const x = useRef16(new Animated10.Value(0)).current;
3780
+ const width = useRef16(new Animated10.Value(0)).current;
3781
+ const previous = useRef16(null);
3760
3782
  const layout = selected && layouts.get(selected.value);
3761
- const updateLayout = useCallback4((value, box) => {
3783
+ const updateLayout = useCallback5((value, box) => {
3762
3784
  setLayouts((old) => old.has(value) && sameBox(old.get(value), box) ? old : new Map(old).set(value, box));
3763
3785
  }, []);
3764
- const measure = useCallback4((value, event) => updateLayout(value, event.nativeEvent.layout), [updateLayout]);
3786
+ const measure = useCallback5((value, event) => updateLayout(value, event.nativeEvent.layout), [updateLayout]);
3765
3787
  useLayoutEffect6(() => {
3766
3788
  const old = previous.current;
3767
3789
  if (!selected || !layout) {
@@ -3784,7 +3806,7 @@ function useButtonGroupMotion(selected) {
3784
3806
  }
3785
3807
  previous.current = { value: selected.value, box: layout, reduced };
3786
3808
  }, [selected == null ? void 0 : selected.value, layout, reduced, x, width]);
3787
- useEffect10(() => () => {
3809
+ useEffect11(() => () => {
3788
3810
  x.stopAnimation();
3789
3811
  width.stopAnimation();
3790
3812
  }, [x, width]);
@@ -3792,9 +3814,9 @@ function useButtonGroupMotion(selected) {
3792
3814
  }
3793
3815
  function ButtonGroupLabel({ label, active, size, reduced }) {
3794
3816
  const { colors, fontFamily } = useKjunStyles();
3795
- const progress = useRef14(new Animated10.Value(active ? 1 : 0)).current;
3817
+ const progress = useRef16(new Animated10.Value(active ? 1 : 0)).current;
3796
3818
  const interpolate = typeof colors.textSecondary === "string" && typeof colors.text === "string";
3797
- useEffect10(() => {
3819
+ useEffect11(() => {
3798
3820
  progress.stopAnimation();
3799
3821
  if (reduced || !interpolate) progress.setValue(active ? 1 : 0);
3800
3822
  else Animated10.timing(progress, { toValue: active ? 1 : 0, duration: tokens20.motion.indicator, easing, useNativeDriver: false }).start();
@@ -3841,7 +3863,7 @@ function KjunButtonGroup({
3841
3863
  const motion = useButtonGroupMotion(selected);
3842
3864
  const padding = tokens21.buttonGroup.padding[size];
3843
3865
  const itemRadius = tokens21.buttonGroup.itemRadii[size];
3844
- const itemRefs = useRef15(/* @__PURE__ */ new Map());
3866
+ const itemRefs = useRef17(/* @__PURE__ */ new Map());
3845
3867
  const { updateLayout } = motion;
3846
3868
  useLayoutEffect7(() => {
3847
3869
  for (const [value2, node] of itemRefs.current) {
@@ -4159,7 +4181,7 @@ var KjunTextarea = forwardRef4(
4159
4181
 
4160
4182
  // packages/native/src/drawer.tsx
4161
4183
  import { tokens as tokens23 } from "@kjun-ui/tokens";
4162
- import { useEffect as useEffect11, useState as useState15 } from "react";
4184
+ import { useEffect as useEffect12, useState as useState15 } from "react";
4163
4185
  import { Animated as Animated12, Keyboard } from "react-native";
4164
4186
 
4165
4187
  // shared/package-runtime/drawer-geometry.ts
@@ -4194,7 +4216,7 @@ import {
4194
4216
  import { jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
4195
4217
  function useKeyboardOverlap(enabled, windowHeight) {
4196
4218
  const [overlap, setOverlap] = useState15(0);
4197
- useEffect11(() => {
4219
+ useEffect12(() => {
4198
4220
  var _a, _b;
4199
4221
  setOverlap(0);
4200
4222
  const events = keyboardEvents(Platform15.OS);
@@ -4224,6 +4246,7 @@ function KjunDrawer({
4224
4246
  footer,
4225
4247
  children,
4226
4248
  onClose,
4249
+ onAfterClose,
4227
4250
  ariaLabel,
4228
4251
  safeAreaTop = 0,
4229
4252
  safeAreaBottom = 0,
@@ -4254,10 +4277,15 @@ function KjunDrawer({
4254
4277
  const layer = useLayer(open, motion.present, "window", () => {
4255
4278
  if (closeOnEsc) close();
4256
4279
  });
4280
+ const iosDismiss = Platform15.OS === "ios";
4281
+ useAfterClose(motion.present, onAfterClose, !iosDismiss);
4257
4282
  return /* @__PURE__ */ jsx25(LayerScope.Provider, { value: layer.id, children: /* @__PURE__ */ jsx25(
4258
4283
  ScopedNativeModal,
4259
4284
  {
4260
4285
  visible: motion.present,
4286
+ onDismiss: iosDismiss ? () => {
4287
+ if (!open) onAfterClose == null ? void 0 : onAfterClose();
4288
+ } : void 0,
4261
4289
  transparent: true,
4262
4290
  onRequestClose: () => {
4263
4291
  if (closeOnEsc) close();
@@ -4390,8 +4418,8 @@ import {
4390
4418
  createContext as createContext17,
4391
4419
  isValidElement as isValidElement6,
4392
4420
  useContext as useContext13,
4393
- useEffect as useEffect14,
4394
- useRef as useRef18,
4421
+ useEffect as useEffect15,
4422
+ useRef as useRef20,
4395
4423
  useState as useState18
4396
4424
  } from "react";
4397
4425
  import {
@@ -4404,9 +4432,9 @@ import { tokens as tokens24 } from "@kjun-ui/tokens";
4404
4432
  import {
4405
4433
  cloneElement as cloneElement3,
4406
4434
  isValidElement as isValidElement4,
4407
- useEffect as useEffect12,
4435
+ useEffect as useEffect13,
4408
4436
  useLayoutEffect as useLayoutEffect8,
4409
- useRef as useRef16,
4437
+ useRef as useRef18,
4410
4438
  useState as useState16
4411
4439
  } from "react";
4412
4440
  import {
@@ -4463,10 +4491,10 @@ function FloatingPanel({
4463
4491
  const m = useKjunMessages();
4464
4492
  ariaLabel != null ? ariaLabel : ariaLabel = m.select;
4465
4493
  const [headerHeight, setHeaderHeight] = useState16(0);
4466
- const panelRef = useRef16(null);
4467
- const scroll = useRef16(null), viewport = useRef16(0);
4494
+ const panelRef = useRef18(null);
4495
+ const scroll = useRef18(null), viewport = useRef18(0);
4468
4496
  const { colors } = useKjunStyles(), window2 = useWindowDimensions4(), [anchored, setAnchored] = useState16(false), [sized, setSized] = useState16(false), [anchor, setAnchor] = useState16({ x: 0, y: 0, width: 0, height: 0 }), [panel, setPanel] = useState16({ width: 0, height: 0 });
4469
- const measurement = useRef16(0);
4497
+ const measurement = useRef18(0);
4470
4498
  const motion = useNativePresence(open, tooltip ? tokens24.motion.tooltipEnter : tokens24.motion.popupEnter, tooltip ? tokens24.motion.tooltipExit : tokens24.motion.popupExit, anchored && sized);
4471
4499
  const layer = useLayer(open, motion.present, tooltip ? "tooltip" : "popup", () => onOpenChange(false), triggerRef);
4472
4500
  useLayoutEffect8(() => {
@@ -4488,14 +4516,14 @@ function FloatingPanel({
4488
4516
  setAnchored(false);
4489
4517
  }
4490
4518
  }, [motion.present]);
4491
- useEffect12(() => {
4519
+ useEffect13(() => {
4492
4520
  var _a;
4493
4521
  const row = reveal == null ? void 0 : reveal.current;
4494
4522
  if (!open || !anchored || !sized || !row || !viewport.current) return;
4495
4523
  const offset = row.y + row.height + (menu || field ? tokens24.extensions.menu.padding : 0) - viewport.current;
4496
4524
  if (offset > 0) (_a = scroll.current) == null ? void 0 : _a.scrollTo({ y: offset, animated: false });
4497
4525
  }, [open, anchored, sized, reveal, menu, field]);
4498
- useEffect12(() => {
4526
+ useEffect13(() => {
4499
4527
  if (!open || !anchored || !sized || !focusOnOpen || !panelRef.current) return;
4500
4528
  if (Platform16.OS === "web") {
4501
4529
  const node = panelRef.current;
@@ -4683,8 +4711,8 @@ function FloatingPanel({
4683
4711
  import {
4684
4712
  cloneElement as cloneElement4,
4685
4713
  isValidElement as isValidElement5,
4686
- useEffect as useEffect13,
4687
- useRef as useRef17,
4714
+ useEffect as useEffect14,
4715
+ useRef as useRef19,
4688
4716
  useState as useState17
4689
4717
  } from "react";
4690
4718
  import {
@@ -4710,7 +4738,7 @@ function KjunPopover({
4710
4738
  children
4711
4739
  }) {
4712
4740
  const { colors } = useKjunStyles();
4713
- const [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, ref = useRef17(null);
4741
+ const [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, ref = useRef19(null);
4714
4742
  const change = (v) => {
4715
4743
  setInternal(v);
4716
4744
  onOpenChange == null ? void 0 : onOpenChange(v);
@@ -4758,13 +4786,13 @@ function KjunTooltip({
4758
4786
  open: controlled,
4759
4787
  onOpenChange
4760
4788
  }) {
4761
- const { colors } = useKjunStyles(), [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, latest = useRef17({ open, onOpenChange }), setOpen = (value) => {
4789
+ const { colors } = useKjunStyles(), [internal, setInternal] = useState17(false), open = controlled != null ? controlled : internal, latest = useRef19({ open, onOpenChange }), setOpen = (value) => {
4762
4790
  var _a, _b;
4763
4791
  if (latest.current.open === value) return;
4764
4792
  latest.current.open = value;
4765
4793
  setInternal(value);
4766
4794
  (_b = (_a = latest.current).onOpenChange) == null ? void 0 : _b.call(_a, value);
4767
- }, ref = useRef17(null), timer = useRef17(void 0);
4795
+ }, ref = useRef19(null), timer = useRef19(void 0);
4768
4796
  latest.current = { open, onOpenChange };
4769
4797
  const scopeActive = useActiveLayerScope();
4770
4798
  const hide = () => {
@@ -4776,11 +4804,11 @@ function KjunTooltip({
4776
4804
  clearTimeout(timer.current);
4777
4805
  timer.current = setTimeout(() => setOpen(true), delay);
4778
4806
  };
4779
- useEffect13(() => {
4807
+ useEffect14(() => {
4780
4808
  if (!scopeActive) hide();
4781
4809
  }, [scopeActive]);
4782
- useEffect13(() => () => clearTimeout(timer.current), []);
4783
- useEffect13(() => {
4810
+ useEffect14(() => () => clearTimeout(timer.current), []);
4811
+ useEffect14(() => {
4784
4812
  if (Platform17.OS !== "web" || !open) return;
4785
4813
  const escape = (event) => {
4786
4814
  if (event.key === "Escape") hide();
@@ -4885,7 +4913,7 @@ function KjunDropdown({
4885
4913
  onClose
4886
4914
  }) {
4887
4915
  const m = useKjunMessages();
4888
- const [open, setOpen] = useState18(false), currentOpen = useRef18(false), ref = useRef18(null);
4916
+ const [open, setOpen] = useState18(false), currentOpen = useRef20(false), ref = useRef20(null);
4889
4917
  let control = trigger;
4890
4918
  while (isValidElement6(control) && control.type === KjunTooltip)
4891
4919
  control = control.props.children;
@@ -4897,7 +4925,7 @@ function KjunDropdown({
4897
4925
  if (v) onOpen == null ? void 0 : onOpen();
4898
4926
  else onClose == null ? void 0 : onClose();
4899
4927
  };
4900
- useEffect14(() => {
4928
+ useEffect15(() => {
4901
4929
  if (unavailable) change(false);
4902
4930
  }, [unavailable]);
4903
4931
  return /* @__PURE__ */ jsxs16(DropdownContext.Provider, { value: () => change(false), children: [
@@ -5033,7 +5061,7 @@ function KjunMenuButton({
5033
5061
  }
5034
5062
 
5035
5063
  // shared/package-runtime/combobox.ts
5036
- import { useEffect as useEffect15, useState as useState19 } from "react";
5064
+ import { useEffect as useEffect16, useState as useState19 } from "react";
5037
5065
 
5038
5066
  // shared/package-runtime/options.ts
5039
5067
  var optionValue = (option, key = "value") => typeof option === "object" ? option[key] : option;
@@ -5113,8 +5141,8 @@ function useComboboxModel({
5113
5141
  const selectedLabel = selected !== void 0 ? optionLabel(selected, labelKey) : "";
5114
5142
  const [query, setQuery] = useState19(selectedLabel);
5115
5143
  const [open, setOpen] = useState19(false);
5116
- useEffect15(() => setQuery(selectedLabel), [value, selectedLabel]);
5117
- useEffect15(() => {
5144
+ useEffect16(() => setQuery(selectedLabel), [value, selectedLabel]);
5145
+ useEffect16(() => {
5118
5146
  if (disabled) setOpen(false);
5119
5147
  }, [disabled]);
5120
5148
  const change = (next) => {
@@ -5148,7 +5176,7 @@ function useComboboxModel({
5148
5176
 
5149
5177
  // packages/native/src/combobox.tsx
5150
5178
  import { tokens as tokens28 } from "@kjun-ui/tokens";
5151
- import { useId as useId5, useRef as useRef19 } from "react";
5179
+ import { useId as useId5, useRef as useRef21 } from "react";
5152
5180
  import { Platform as Platform18, View as View23 } from "react-native";
5153
5181
 
5154
5182
  // packages/native/src/select-options.tsx
@@ -5278,8 +5306,8 @@ function SearchField({
5278
5306
  }) {
5279
5307
  const m = useKjunMessages();
5280
5308
  const searchId = "kjun-popup-search-" + useId5().replace(/:/g, "");
5281
- const clearing = useRef19(false);
5282
- const ref = useRef19(null), { colors } = useKjunStyles();
5309
+ const clearing = useRef21(false);
5310
+ const ref = useRef21(null), { colors } = useKjunStyles();
5283
5311
  const focusGuard = usePopupFocusGuard(ref);
5284
5312
  const openFromPress = () => {
5285
5313
  if (!disabled) {
@@ -5379,7 +5407,7 @@ function SearchField({
5379
5407
 
5380
5408
  // packages/native/src/date-picker.tsx
5381
5409
  import { tokens as tokens29 } from "@kjun-ui/tokens";
5382
- import { useRef as useRef20, useState as useState20 } from "react";
5410
+ import { useRef as useRef22, useState as useState20 } from "react";
5383
5411
  import { Platform as Platform19, View as View24 } from "react-native";
5384
5412
  import { Fragment as Fragment9, jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
5385
5413
  function displayMonth(value) {
@@ -5402,7 +5430,7 @@ function KjunDatePicker({
5402
5430
  const scope = useKjunMessageScope();
5403
5431
  placeholder != null ? placeholder : placeholder = scope.messages.datePlaceholder;
5404
5432
  const clear = clearable && !!value && !disabled;
5405
- const { colors } = useKjunStyles(), field = useKjunField(), [open, setOpen] = useState20(false), [month, setMonth] = useState20(() => displayMonth(value)), ref = useRef20(null), spec = tokens29.input[size];
5433
+ const { colors } = useKjunStyles(), field = useKjunField(), [open, setOpen] = useState20(false), [month, setMonth] = useState20(() => displayMonth(value)), ref = useRef22(null), spec = tokens29.input[size];
5406
5434
  const surface = useFieldSurface(size, { disabled, invalid: error || !!(field == null ? void 0 : field.error), open });
5407
5435
  const year = month.getFullYear(), m = month.getMonth(), first = new Date(year, m, 1).getDay(), count = new Date(year, m + 1, 0).getDate();
5408
5436
  const date = (day) => `${year}-${String(m + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
@@ -5580,7 +5608,7 @@ function KjunDatePicker({
5580
5608
  import { useState as useState22 } from "react";
5581
5609
 
5582
5610
  // shared/package-runtime/search-input.ts
5583
- import { useEffect as useEffect16, useLayoutEffect as useLayoutEffect9, useRef as useRef21, useState as useState21 } from "react";
5611
+ import { useEffect as useEffect17, useLayoutEffect as useLayoutEffect9, useRef as useRef23, useState as useState21 } from "react";
5584
5612
  function useSearchInputModel({
5585
5613
  value,
5586
5614
  disabled = false,
@@ -5590,10 +5618,10 @@ function useSearchInputModel({
5590
5618
  onValueChange,
5591
5619
  onSearchError
5592
5620
  }, open) {
5593
- const [query, setQuery] = useState21(value), [options, setOptions] = useState21([]), [loading, setLoading] = useState21(false), [failed, setFailed] = useState21(false), version = useRef21(0), notify = useRef21(onSearchError);
5621
+ const [query, setQuery] = useState21(value), [options, setOptions] = useState21([]), [loading, setLoading] = useState21(false), [failed, setFailed] = useState21(false), version = useRef23(0), notify = useRef23(onSearchError);
5594
5622
  notify.current = onSearchError;
5595
- const timer = useRef21(void 0);
5596
- const notifyValue = useRef21(onValueChange);
5623
+ const timer = useRef23(void 0);
5624
+ const notifyValue = useRef23(onValueChange);
5597
5625
  notifyValue.current = onValueChange;
5598
5626
  useLayoutEffect9(() => {
5599
5627
  clearTimeout(timer.current);
@@ -5603,7 +5631,7 @@ function useSearchInputModel({
5603
5631
  clearTimeout(timer.current);
5604
5632
  return () => clearTimeout(timer.current);
5605
5633
  }, [disabled, debounce, !!loadOptions]);
5606
- useEffect16(() => {
5634
+ useEffect17(() => {
5607
5635
  const current = ++version.current, abort = new AbortController();
5608
5636
  setFailed(false);
5609
5637
  if (!loadOptions || !open || disabled || query.length < minChars) {
@@ -5756,7 +5784,7 @@ function KjunSearchInput({
5756
5784
 
5757
5785
  // packages/native/src/select-control.tsx
5758
5786
  import { tokens as tokens31 } from "@kjun-ui/tokens";
5759
- import { useContext as useContext14, useEffect as useEffect18, useRef as useRef23 } from "react";
5787
+ import { useContext as useContext14, useEffect as useEffect19, useRef as useRef25 } from "react";
5760
5788
 
5761
5789
  // packages/native/src/compound-control.tsx
5762
5790
  import { createContext as createContext18 } from "react";
@@ -5770,7 +5798,7 @@ function CompoundTarget({ children, square = false }) {
5770
5798
  }
5771
5799
 
5772
5800
  // shared/package-runtime/select.ts
5773
- import { useEffect as useEffect17, useRef as useRef22, useState as useState23 } from "react";
5801
+ import { useEffect as useEffect18, useRef as useRef24, useState as useState23 } from "react";
5774
5802
  function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5775
5803
  const [internal, setInternal] = useState23(false);
5776
5804
  const [query, setQuery] = useState23("");
@@ -5778,8 +5806,8 @@ function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5778
5806
  const [session, setSession] = useState23(0);
5779
5807
  const isControlled = typeof controlled === "boolean";
5780
5808
  const open = !disabled && (isControlled ? controlled : internal);
5781
- const previousOpen = useRef22(open);
5782
- useEffect17(() => {
5809
+ const previousOpen = useRef24(open);
5810
+ useEffect18(() => {
5783
5811
  if (disabled && !isControlled) setInternal(false);
5784
5812
  if (previousOpen.current && !open) {
5785
5813
  setQuery("");
@@ -5788,7 +5816,7 @@ function useSelectState(controlled, disabled, pageSize, onOpenChange) {
5788
5816
  }
5789
5817
  previousOpen.current = open;
5790
5818
  }, [open, disabled, isControlled, pageSize]);
5791
- useEffect17(() => {
5819
+ useEffect18(() => {
5792
5820
  setLimit(pageSize);
5793
5821
  }, [pageSize]);
5794
5822
  const changeOpen = (next) => {
@@ -5838,14 +5866,14 @@ function KjunSelect({
5838
5866
  placeholder != null ? placeholder : placeholder = m.select;
5839
5867
  searchPlaceholder != null ? searchPlaceholder : searchPlaceholder = m.search;
5840
5868
  const { open, query, limit, changeOpen, search, showMore } = useSelectState(controlled, disabled, optionPageSize, onOpenChange);
5841
- const { colors } = useKjunStyles(), field = useKjunField(), ref = useRef23(null), spec = tokens31.input[size];
5842
- const trigger = useRef23(null);
5869
+ const { colors } = useKjunStyles(), field = useKjunField(), ref = useRef25(null), spec = tokens31.input[size];
5870
+ const trigger = useRef25(null);
5843
5871
  const compound = useContext14(CompoundControlContext);
5844
- useEffect18(() => {
5872
+ useEffect19(() => {
5845
5873
  if (compound == null ? void 0 : compound.focusRef) compound.focusRef.current = trigger.current;
5846
5874
  }, [compound == null ? void 0 : compound.focusRef]);
5847
5875
  const expanded = usePopupExpanded(open, ref);
5848
- const selectedRow = useRef23(null);
5876
+ const selectedRow = useRef25(null);
5849
5877
  const surface = useFieldSurface(size, { disabled, invalid: error || !!(field == null ? void 0 : field.error), open: expanded });
5850
5878
  const change = (v) => {
5851
5879
  onValueChange == null ? void 0 : onValueChange(v);
@@ -6043,15 +6071,16 @@ import { tokens as tokens34 } from "@kjun-ui/tokens";
6043
6071
 
6044
6072
  // packages/native/src/collapse.tsx
6045
6073
  import { tokens as tokens32 } from "@kjun-ui/tokens";
6046
- import { useLayoutEffect as useLayoutEffect10, useRef as useRef24, useState as useState24 } from "react";
6074
+ import { useLayoutEffect as useLayoutEffect10, useRef as useRef26, useState as useState24 } from "react";
6047
6075
  import { Animated as Animated14, View as View27 } from "react-native";
6048
6076
  import { jsx as jsx35 } from "react/jsx-runtime";
6049
- function Collapse({ open, children }) {
6077
+ function Collapse({ open, keepMounted = false, children }) {
6050
6078
  const reduced = useReducedMotion();
6051
6079
  const [retained, setRetained] = useState24(open), [height, setHeight] = useState24(null);
6052
- const value = useRef24(new Animated14.Value(0)).current;
6080
+ const value = useRef26(new Animated14.Value(0)).current;
6053
6081
  const [settled, setSettled] = useState24(open);
6054
- const version = useRef24(0), first = useRef24(open);
6082
+ const version = useRef26(0), first = useRef26(open), opened = useRef26(open);
6083
+ if (open) opened.current = true;
6055
6084
  useLayoutEffect10(() => {
6056
6085
  const revision = ++version.current;
6057
6086
  if (open) setRetained(true);
@@ -6079,13 +6108,13 @@ function Collapse({ open, children }) {
6079
6108
  value.stopAnimation();
6080
6109
  };
6081
6110
  }, [open, height, reduced, value]);
6082
- return open || retained ? /* @__PURE__ */ jsx35(
6111
+ return open || retained || keepMounted && opened.current ? /* @__PURE__ */ jsx35(
6083
6112
  Animated14.View,
6084
6113
  {
6085
6114
  pointerEvents: open ? "auto" : "none",
6086
6115
  accessibilityElementsHidden: !open,
6087
6116
  importantForAccessibility: open ? "auto" : "no-hide-descendants",
6088
- ...!open ? { inert: true } : {},
6117
+ ...!open ? { inert: true, "aria-hidden": true } : {},
6089
6118
  style: { height: settled && open ? void 0 : value, overflow: "hidden" },
6090
6119
  children: /* @__PURE__ */ jsx35(View27, { onLayout: (event) => setHeight(event.nativeEvent.layout.height), children })
6091
6120
  }
@@ -6093,10 +6122,10 @@ function Collapse({ open, children }) {
6093
6122
  }
6094
6123
 
6095
6124
  // shared/package-runtime/navigation.ts
6096
- import { useEffect as useEffect19, useRef as useRef25, useState as useState25 } from "react";
6125
+ import { useEffect as useEffect20, useRef as useRef27, useState as useState25 } from "react";
6097
6126
  function useInitialTab(value, candidate, change) {
6098
- const requested = useRef25(/* @__PURE__ */ new Set());
6099
- useEffect19(() => {
6127
+ const requested = useRef27(/* @__PURE__ */ new Set());
6128
+ useEffect20(() => {
6100
6129
  if (value !== "") {
6101
6130
  requested.current.clear();
6102
6131
  return;
@@ -6108,7 +6137,7 @@ function useInitialTab(value, candidate, change) {
6108
6137
  }
6109
6138
  function useAccordionState(multiple) {
6110
6139
  const [opened, setOpened] = useState25(/* @__PURE__ */ new Set());
6111
- useEffect19(() => {
6140
+ useEffect20(() => {
6112
6141
  if (!multiple) setOpened((previous) => previous.size > 1 ? new Set([...previous].slice(-1)) : previous);
6113
6142
  }, [multiple]);
6114
6143
  return {
@@ -6136,15 +6165,16 @@ import {
6136
6165
  Fragment as Fragment11,
6137
6166
  createContext as createContext20,
6138
6167
  useContext as useContext16,
6139
- useEffect as useEffect20,
6168
+ useEffect as useEffect21,
6140
6169
  useId as useId7,
6170
+ useRef as useRef29,
6141
6171
  useState as useState27
6142
6172
  } from "react";
6143
6173
  import { Animated as Animated16, View as View29, useWindowDimensions as useWindowDimensions5, Platform as Platform22 } from "react-native";
6144
6174
 
6145
6175
  // packages/native/src/tabs.tsx
6146
6176
  import { tokens as tokens33 } from "@kjun-ui/tokens";
6147
- import { Children as Children4, createContext as createContext19, isValidElement as isValidElement7, useContext as useContext15, useCallback as useCallback5, useLayoutEffect as useLayoutEffect11, useRef as useRef26, useId as useId6, useState as useState26 } from "react";
6177
+ import { Children as Children4, createContext as createContext19, isValidElement as isValidElement7, useContext as useContext15, useCallback as useCallback6, useLayoutEffect as useLayoutEffect11, useRef as useRef28, useId as useId6, useState as useState26 } from "react";
6148
6178
  import { Animated as Animated15, Platform as Platform21, ScrollView as ScrollView5, View as View28 } from "react-native";
6149
6179
 
6150
6180
  // packages/native/src/tabs-accessibility.ts
@@ -6175,10 +6205,10 @@ function KjunTabs({
6175
6205
  isValidElement7
6176
6206
  );
6177
6207
  const tabs = items2.length ? items2 : panes.filter((child) => child.type === KjunTabPane).map((child) => child.props);
6178
- const id = "kjun-" + useId6(), root = useRef26(null);
6179
- const menuState = useRef26({ tabs, onTabMenu });
6208
+ const id = "kjun-" + useId6(), root = useRef28(null);
6209
+ const menuState = useRef28({ tabs, onTabMenu });
6180
6210
  menuState.current = { tabs, onTabMenu };
6181
- const pressedMenu = useRef26(null);
6211
+ const pressedMenu = useRef28(null);
6182
6212
  useLayoutEffect11(() => {
6183
6213
  if (!onTabMenu || !tabs.some((tab) => tab.name === pressedMenu.current && !tab.disabled)) pressedMenu.current = null;
6184
6214
  }, [tabs, onTabMenu]);
@@ -6194,10 +6224,10 @@ function KjunTabs({
6194
6224
  const roomX = underline ? ringRoom : 0, roomY = Math.max(underline ? ringRoom : 0, slop);
6195
6225
  const selectedTab = tabs.find((tab) => tab.name === value);
6196
6226
  const selection = useButtonGroupMotion(selectedTab ? { ...selectedTab, value: selectedTab.name } : void 0);
6197
- const tabRefs = useRef26(/* @__PURE__ */ new Map());
6227
+ const tabRefs = useRef28(/* @__PURE__ */ new Map());
6198
6228
  const { updateLayout } = selection;
6199
6229
  const firstName = (_a = tabs[0]) == null ? void 0 : _a.name;
6200
- const measureIndicator = useCallback5((name, box) => {
6230
+ const measureIndicator = useCallback6((name, box) => {
6201
6231
  const left = underline && name === firstName ? 0 : paddingX;
6202
6232
  updateLayout(name, underline ? {
6203
6233
  x: box.x + left,
@@ -6366,7 +6396,7 @@ function KjunTabs({
6366
6396
  }
6367
6397
  function KjunTabPane({ name, children }) {
6368
6398
  const { value, id, names } = useContext15(TabContext);
6369
- const root = useRef26(null);
6399
+ const root = useRef28(null);
6370
6400
  usePanelFocus(root);
6371
6401
  const hidden = value !== name;
6372
6402
  return /* @__PURE__ */ jsx36(
@@ -6419,14 +6449,32 @@ function KjunAccordionItem({
6419
6449
  defaultOpen = false,
6420
6450
  disabled = false,
6421
6451
  header,
6452
+ open: openProp,
6453
+ onOpenChange,
6454
+ keepMounted = false,
6422
6455
  children
6423
6456
  }) {
6424
- const { colors } = useKjunStyles(), group = useContext16(AccordionContext), id = "kjun-" + useId7(), [own, setOwn] = useState27(defaultOpen), open = group ? group.opened.has(id) : own;
6457
+ const controlled = openProp !== void 0, context = useContext16(AccordionContext), { colors } = useKjunStyles(), group = controlled ? null : context, id = "kjun-" + useId7(), [own, setOwn] = useState27(defaultOpen), open = controlled ? openProp : group ? group.opened.has(id) : own;
6458
+ const reported = useRef29(open), notify = useRef29(onOpenChange), registering = useRef29(!!group && defaultOpen);
6459
+ notify.current = onOpenChange;
6460
+ useEffect21(() => {
6461
+ var _a;
6462
+ if (registering.current) {
6463
+ if (open) {
6464
+ registering.current = false;
6465
+ reported.current = open;
6466
+ }
6467
+ return;
6468
+ }
6469
+ if (controlled || reported.current === open) return;
6470
+ reported.current = open;
6471
+ (_a = notify.current) == null ? void 0 : _a.call(notify, open);
6472
+ }, [open, controlled]);
6425
6473
  const rotation = useMotionValue(open ? 1 : 0, tokens34.motion.collapse, void 0, void 0, true);
6426
6474
  const geometry2 = tokens34.extensions.accordion;
6427
6475
  const [hovered, setHovered] = useState27(false);
6428
6476
  const wrapping = Platform22.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
6429
- useEffect20(() => {
6477
+ useEffect21(() => {
6430
6478
  return group == null ? void 0 : group.register(id, defaultOpen);
6431
6479
  }, []);
6432
6480
  return /* @__PURE__ */ jsxs22(View29, { children: [
@@ -6440,7 +6488,10 @@ function KjunAccordionItem({
6440
6488
  accessibilityLabel: title,
6441
6489
  accessibilityState: { expanded: open, disabled },
6442
6490
  disabled,
6443
- onPress: () => group ? group.toggle(id) : setOwn(!own),
6491
+ onPress: () => {
6492
+ registering.current = false;
6493
+ controlled ? onOpenChange == null ? void 0 : onOpenChange(!open) : group ? group.toggle(id) : setOwn(!own);
6494
+ },
6444
6495
  onHoverIn: () => setHovered(true),
6445
6496
  onHoverOut: () => setHovered(false),
6446
6497
  style: ({ pressed }) => ({
@@ -6460,7 +6511,7 @@ function KjunAccordionItem({
6460
6511
  ]
6461
6512
  }
6462
6513
  ),
6463
- /* @__PURE__ */ jsx37(Collapse, { open, children: /* @__PURE__ */ jsx37(
6514
+ /* @__PURE__ */ jsx37(Collapse, { open, keepMounted, children: /* @__PURE__ */ jsx37(
6464
6515
  View29,
6465
6516
  {
6466
6517
  nativeID: id + "-panel",
@@ -6657,7 +6708,7 @@ function KjunPagination({
6657
6708
 
6658
6709
  // packages/native/src/actions.tsx
6659
6710
  import { tokens as tokens35 } from "@kjun-ui/tokens";
6660
- import { useContext as useContext17, useEffect as useEffect21, useRef as useRef27, useState as useState28 } from "react";
6711
+ import { useContext as useContext17, useEffect as useEffect22, useRef as useRef30, useState as useState28 } from "react";
6661
6712
  import { Platform as Platform23, ScrollView as ScrollView7, View as View30 } from "react-native";
6662
6713
  import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
6663
6714
  function KjunIconToggle({
@@ -6742,8 +6793,8 @@ function KjunCopyButton({
6742
6793
  }) {
6743
6794
  const m = useKjunMessages();
6744
6795
  successText != null ? successText : successText = m.copied;
6745
- const feedback = useOptionalKjunFeedback(), { colors } = useKjunStyles(), [copied, setCopied] = useState28(false), [failed, setFailed] = useState28(false), busy = useRef27(false), timer = useRef27(void 0), mounted = useRef27(true);
6746
- useEffect21(() => {
6796
+ const feedback = useOptionalKjunFeedback(), { colors } = useKjunStyles(), [copied, setCopied] = useState28(false), [failed, setFailed] = useState28(false), busy = useRef30(false), timer = useRef30(void 0), mounted = useRef30(true);
6797
+ useEffect22(() => {
6747
6798
  mounted.current = true;
6748
6799
  return () => {
6749
6800
  mounted.current = false;
@@ -6907,10 +6958,10 @@ import { Component, useState as useState30 } from "react";
6907
6958
  import { Platform as Platform24, View as View31 } from "react-native";
6908
6959
 
6909
6960
  // shared/package-runtime/use-loading-reveal.ts
6910
- import { useEffect as useEffect22, useState as useState29 } from "react";
6961
+ import { useEffect as useEffect23, useState as useState29 } from "react";
6911
6962
  function useLoadingReveal(active, delay = 0) {
6912
6963
  const [revealed, setRevealed] = useState29(false);
6913
- useEffect22(() => {
6964
+ useEffect23(() => {
6914
6965
  setRevealed(false);
6915
6966
  if (!active || delay <= 0) return;
6916
6967
  const timer = setTimeout(() => setRevealed(true), delay);
@@ -7080,7 +7131,7 @@ KjunErrorBoundary.contextType = KjunMessageContext;
7080
7131
 
7081
7132
  // packages/native/src/skeletons.tsx
7082
7133
  import { tokens as tokens40 } from "@kjun-ui/tokens";
7083
- import { useEffect as useEffect23, useRef as useRef28, useState as useState32 } from "react";
7134
+ import { useEffect as useEffect24, useRef as useRef31, useState as useState32 } from "react";
7084
7135
  import { Animated as Animated17, Platform as Platform25, View as View33, useWindowDimensions as useWindowDimensions6 } from "react-native";
7085
7136
  import Svg5, { Path as Path4 } from "react-native-svg";
7086
7137
 
@@ -7271,8 +7322,8 @@ function KjunChartSkeleton({
7271
7322
  }) {
7272
7323
  const m = useKjunMessages();
7273
7324
  loadingText != null ? loadingText : loadingText = m.chartLoading;
7274
- const kind = chartSkeletonKind(requestedKind), { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef28(new Animated17.Value(1)).current, revealed = useLoadingReveal(true, loadingDelay), [measured, setMeasured] = useState32(0), thickness = tokens40.extensions.chartSkeleton.donutThickness, boxHeight = typeof height === "number" ? height : measured, hole = boxHeight > 0 ? chartDonutHole(boxHeight, thickness) : void 0, rowCount = chartSkeletonCount(rows), columnCount = chartSkeletonCount(columns), status = revealed && loadingText ? "status" : void 0, hidden = { "aria-hidden": true, importantForAccessibility: "no-hide-descendants" };
7275
- useEffect23(() => {
7325
+ const kind = chartSkeletonKind(requestedKind), { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = useRef31(new Animated17.Value(1)).current, revealed = useLoadingReveal(true, loadingDelay), [measured, setMeasured] = useState32(0), thickness = tokens40.extensions.chartSkeleton.donutThickness, boxHeight = typeof height === "number" ? height : measured, hole = boxHeight > 0 ? chartDonutHole(boxHeight, thickness) : void 0, rowCount = chartSkeletonCount(rows), columnCount = chartSkeletonCount(columns), status = revealed && loadingText ? "status" : void 0, hidden = { "aria-hidden": true, importantForAccessibility: "no-hide-descendants" };
7326
+ useEffect24(() => {
7276
7327
  if (reduced || !skeleton) return;
7277
7328
  const loop = Animated17.loop(
7278
7329
  Animated17.sequence([
@@ -7370,7 +7421,7 @@ import Svg6, {
7370
7421
  import { tokens as tokens42 } from "@kjun-ui/tokens";
7371
7422
 
7372
7423
  // shared/package-runtime/use-number-motion.ts
7373
- import { useLayoutEffect as useLayoutEffect12, useRef as useRef29, useState as useState33 } from "react";
7424
+ import { useLayoutEffect as useLayoutEffect12, useRef as useRef32, useState as useState33 } from "react";
7374
7425
 
7375
7426
  // shared/package-runtime/number-motion.ts
7376
7427
  import { tokens as tokens41 } from "@kjun-ui/tokens";
@@ -7417,7 +7468,7 @@ function createNumberMotion(apply) {
7417
7468
  // shared/package-runtime/use-number-motion.ts
7418
7469
  function useNumberMotion(value, animated, fromPrevious, reduced) {
7419
7470
  const [display, setDisplay] = useState33(typeof value === "string" || fromPrevious || !animated || reduced ? value : 0);
7420
- const motion = useRef29(null);
7471
+ const motion = useRef32(null);
7421
7472
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
7422
7473
  useLayoutEffect12(() => {
7423
7474
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
@@ -7882,7 +7933,7 @@ function KjunSparkline({
7882
7933
 
7883
7934
  // shared/package-runtime/table.ts
7884
7935
  import { nextTableSort } from "@kjun-ui/tokens";
7885
- import { useEffect as useEffect25, useRef as useRef31, useState as useState35 } from "react";
7936
+ import { useEffect as useEffect26, useRef as useRef34, useState as useState35 } from "react";
7886
7937
 
7887
7938
  // shared/package-runtime/table-model.ts
7888
7939
  function getValue(row, key) {
@@ -7929,8 +7980,8 @@ function useTableModel(props) {
7929
7980
  const [internalSort, setSort] = useState35({
7930
7981
  key: "",
7931
7982
  order: "asc"
7932
- }), [internalExpanded, setExpanded] = useState35([]), [search, setSearch] = useState35(""), timer = useRef31(void 0);
7933
- useEffect25(() => () => clearTimeout(timer.current), []);
7983
+ }), [internalExpanded, setExpanded] = useState35([]), [search, setSearch] = useState35(""), timer = useRef34(void 0);
7984
+ useEffect26(() => () => clearTimeout(timer.current), []);
7934
7985
  const sort = props.sort === void 0 ? internalSort : (_a = props.sort) != null ? _a : { key: "", order: "asc" };
7935
7986
  const rows = sortTableRows(data, sort, { sortable, sortMode });
7936
7987
  const key = (row, index = 0) => tableRowKey(row, rowKey, index);
@@ -9087,7 +9138,7 @@ import { tokens as tokens51 } from "@kjun-ui/tokens";
9087
9138
  import { ScrollView as ScrollView10, View as View44 } from "react-native";
9088
9139
 
9089
9140
  // shared/package-runtime/market-cards.ts
9090
- import { useEffect as useEffect26, useRef as useRef32, useState as useState38 } from "react";
9141
+ import { useEffect as useEffect27, useRef as useRef35, useState as useState38 } from "react";
9091
9142
  function useMarketCardsModel(props, persistence) {
9092
9143
  const {
9093
9144
  columns,
@@ -9104,7 +9155,7 @@ function useMarketCardsModel(props, persistence) {
9104
9155
  isDefaultSort: c.defaultSort
9105
9156
  }));
9106
9157
  const [key, setKey] = useState38(""), restoreSignature = JSON.stringify([storageNamespace, pills]);
9107
- const mounted = useRef32("");
9158
+ const mounted = useRef35("");
9108
9159
  const save = (key2) => {
9109
9160
  var _a;
9110
9161
  try {
@@ -9112,7 +9163,7 @@ function useMarketCardsModel(props, persistence) {
9112
9163
  } catch (e) {
9113
9164
  }
9114
9165
  };
9115
- useEffect26(() => {
9166
+ useEffect27(() => {
9116
9167
  var _a, _b;
9117
9168
  if (mounted.current === restoreSignature) return;
9118
9169
  mounted.current = restoreSignature;
@@ -9897,20 +9948,21 @@ import { Children as Children5, createContext as createContext22, useContext as
9897
9948
  import { View as View48, Platform as Platform26 } from "react-native";
9898
9949
  import { Fragment as Fragment19, jsx as jsx56, jsxs as jsxs41 } from "react/jsx-runtime";
9899
9950
  var ListRowContext = createContext22({ divider: true, compact: false });
9900
- function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, destructive = false, chevron = false, onPress }) {
9951
+ function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, destructive = false, chevron = false, onPress, ariaLabel, children }) {
9901
9952
  const { colors } = useKjunStyles(), { divider, compact } = useContext19(ListRowContext);
9902
9953
  const parts = /* @__PURE__ */ jsxs41(Fragment19, { children: [
9903
9954
  hasContent(leading) && /* @__PURE__ */ jsx56(View48, { children: content(leading) }),
9904
9955
  /* @__PURE__ */ jsxs41(View48, { style: { flex: 1, minWidth: 0 }, children: [
9905
9956
  /* @__PURE__ */ jsx56(KText, { style: { ...typeStyle("label"), ...destructive ? { color: colors.danger } : {} }, children: title }),
9906
- !!description && /* @__PURE__ */ jsx56(KText, { style: { marginTop: tokens55.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9957
+ !!description && /* @__PURE__ */ jsx56(KText, { style: { marginTop: tokens55.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description }),
9958
+ hasContent(children) && /* @__PURE__ */ jsx56(View48, { style: { marginTop: tokens55.extensions.list.descriptionGap }, children: content(children) })
9907
9959
  ] }),
9908
9960
  hasContent(trailing) && /* @__PURE__ */ jsx56(View48, { style: { maxWidth: "35%" }, children: content(trailing) }),
9909
9961
  chevron && /* @__PURE__ */ jsx56(View48, { accessible: false, importantForAccessibility: "no-hide-descendants", accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx56(KjunIcon, { name: "chevron-right", size: tokens55.iconSizes.default, color: colors.textTertiary }) })
9910
9962
  ] });
9911
9963
  const style = { flex: 1, minWidth: 0, minHeight: compact ? tokens55.extensions.list.compactMinimumHeight : tokens55.extensions.list.minimumHeight, flexDirection: "row", alignItems: "center", gap: tokens55.extensions.list.gap, padding: tokens55.extensions.list.padding, ...compact ? { paddingVertical: tokens55.extensions.list.compactPaddingY } : {} };
9912
9964
  return /* @__PURE__ */ jsxs41(View48, { role: "listitem", style: { flexDirection: "row", alignItems: "center", gap: tokens55.extensions.list.gap, borderBottomWidth: divider ? tokens55.border.defaultWidth : 0, borderBottomColor: colors.divider }, children: [
9913
- onPress || href ? /* @__PURE__ */ jsx56(AccessiblePressable, { ...Platform26.OS === "web" && href && !disabled ? { href } : {}, accessibilityRole: href ? "link" : "button", accessibilityLabel: title + (description ? ", " + description : ""), disabled, accessibilityState: { disabled }, onPress, style: ({ pressed }) => ({ ...style, opacity: disabled ? tokens55.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ jsx56(View48, { style, children: parts }),
9965
+ onPress || href ? /* @__PURE__ */ jsx56(AccessiblePressable, { ...Platform26.OS === "web" && href && !disabled ? { href } : {}, accessibilityRole: href ? "link" : "button", accessibilityLabel: ariaLabel != null ? ariaLabel : title + (description ? ", " + description : ""), disabled, accessibilityState: { disabled }, onPress, style: ({ pressed }) => ({ ...style, opacity: disabled ? tokens55.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ jsx56(View48, { style, children: parts }),
9914
9966
  hasContent(actions) && /* @__PURE__ */ jsx56(View48, { pointerEvents: disabled ? "none" : "auto", ...disabled && Platform26.OS === "web" ? { inert: true } : {}, style: { maxWidth: "45%", flexDirection: "row", flexWrap: "wrap", gap: tokens55.extensions.list.actionsGap, paddingRight: tokens55.extensions.list.actionsPadding, opacity: disabled ? tokens55.states.opacity.disabled : 1 }, children: content(actions) })
9915
9967
  ] });
9916
9968
  }
@@ -10053,14 +10105,14 @@ function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboa
10053
10105
  }
10054
10106
 
10055
10107
  // packages/native/src/media.tsx
10056
- import { createContext as createContext23, useContext as useContext20, useRef as useRef33, useState as useState41 } from "react";
10108
+ import { createContext as createContext23, useContext as useContext20, useRef as useRef36, useState as useState41 } from "react";
10057
10109
  import { Image, View as View50 } from "react-native";
10058
10110
  import { tokens as tokens57 } from "@kjun-ui/tokens";
10059
10111
  import { jsx as jsx58 } from "react/jsx-runtime";
10060
10112
  var ImageBackgroundContext = createContext23(void 0);
10061
10113
  function KjunImage({ src, source, alt, decorative = false, aspectRatio = 1, fit = "cover", fallback: fallback2, onLoad, onError }) {
10062
10114
  const { colors } = useKjunStyles(), background = useContext20(ImageBackgroundContext);
10063
- const request = JSON.stringify(source != null ? source : src), current = useRef33({ request, version: 0 });
10115
+ const request = JSON.stringify(source != null ? source : src), current = useRef36({ request, version: 0 });
10064
10116
  if (current.current.request !== request) current.current = { request, version: current.current.version + 1 };
10065
10117
  const version = current.current.version;
10066
10118
  const [failed, setFailed] = useState41(null);
@@ -10128,7 +10180,7 @@ function KjunFab({ icon, ariaLabel, disabled = false, safeAreaBottom = 0, offset
10128
10180
  }
10129
10181
 
10130
10182
  // packages/native/src/range-input.tsx
10131
- import { useEffect as useEffect27, useMemo as useMemo3, useRef as useRef34, useState as useState42 } from "react";
10183
+ import { useEffect as useEffect28, useMemo as useMemo3, useRef as useRef37, useState as useState42 } from "react";
10132
10184
  import { PanResponder, Platform as Platform28, Pressable as Pressable3, View as View52 } from "react-native";
10133
10185
  import { tokens as tokens60, createSliderDomain, sliderKey } from "@kjun-ui/tokens";
10134
10186
  import { jsx as jsx61, jsxs as jsxs44 } from "react/jsx-runtime";
@@ -10156,15 +10208,15 @@ function RangeInput({
10156
10208
  const [hovered, setHovered] = useState42(null);
10157
10209
  const [dragging, setDragging] = useState42(null);
10158
10210
  const [focused, setFocused] = useState42(null);
10159
- const track = useRef34(null), measured = useRef34({ x: 0, width: 1 }), selected = useRef34(0), dirty = useRef34(false);
10160
- const latest = useRef34(values);
10211
+ const track = useRef37(null), measured = useRef37({ x: 0, width: 1 }), selected = useRef37(0), dirty = useRef37(false);
10212
+ const latest = useRef37(values);
10161
10213
  latest.current = values;
10162
- const callbacks = useRef34({ onValueChange, onChangeCommit });
10214
+ const callbacks = useRef37({ onValueChange, onChangeCommit });
10163
10215
  callbacks.current = { onValueChange, onChangeCommit };
10164
- useEffect27(() => {
10216
+ useEffect28(() => {
10165
10217
  if (!valid) console.warn("KJUN Slider: \uBC94\uC704\xB7step\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10166
10218
  }, [valid]);
10167
- useEffect27(() => {
10219
+ useEffect28(() => {
10168
10220
  if (blocked) {
10169
10221
  setDragging(null);
10170
10222
  setHovered(null);
@@ -10429,7 +10481,7 @@ function KjunRangeSlider(props) {
10429
10481
  }
10430
10482
 
10431
10483
  // packages/native/src/quantity-stepper.tsx
10432
- import { useEffect as useEffect28, useRef as useRef35, useState as useState43 } from "react";
10484
+ import { useEffect as useEffect29, useRef as useRef38, useState as useState43 } from "react";
10433
10485
  import { Platform as Platform29, View as View53 } from "react-native";
10434
10486
  import { createNumberDomain, quantityKeyAction, tokens as tokens61 } from "@kjun-ui/tokens";
10435
10487
 
@@ -10453,15 +10505,15 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10453
10505
  const domain = createNumberDomain({ min, max, step, precision }), valid = domain.valid && domain.accepts(value), blocked = disabled || !valid;
10454
10506
  const surface = useFieldSurface(size, { disabled: blocked, invalid });
10455
10507
  const [draft, setDraft] = useState43(String(value));
10456
- const inputRef = useRef35(null);
10457
- const composing = useRef35(false), dirty = useRef35(false), accepted = useRef35(value);
10458
- const cancelledEscape = useRef35(false);
10459
- useEffect28(() => {
10508
+ const inputRef = useRef38(null);
10509
+ const composing = useRef38(false), dirty = useRef38(false), accepted = useRef38(value);
10510
+ const cancelledEscape = useRef38(false);
10511
+ useEffect29(() => {
10460
10512
  setDraft(String(value));
10461
10513
  accepted.current = value;
10462
10514
  dirty.current = false;
10463
10515
  }, [value, precision, min, max, step]);
10464
- useEffect28(() => {
10516
+ useEffect29(() => {
10465
10517
  if (!valid) console.warn("KJUN QuantityStepper: \uBC94\uC704\xB7step\xB7\uC815\uBC00\uB3C4\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10466
10518
  }, [valid]);
10467
10519
  const emit = (next) => {
@@ -10498,7 +10550,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10498
10550
  } else if (action === "commit") commit();
10499
10551
  else move(action === "increment" ? 1 : -1);
10500
10552
  };
10501
- const handlers = useRef35({ key, edit: (text) => {
10553
+ const handlers = useRef38({ key, edit: (text) => {
10502
10554
  dirty.current = true;
10503
10555
  setDraft(text);
10504
10556
  } });
@@ -10506,7 +10558,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10506
10558
  dirty.current = true;
10507
10559
  setDraft(text);
10508
10560
  } };
10509
- useEffect28(() => {
10561
+ useEffect29(() => {
10510
10562
  if (Platform29.OS !== "web") return;
10511
10563
  const input = inputRef.current;
10512
10564
  const keydown = (event) => handlers.current.key(event);
@@ -10578,7 +10630,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
10578
10630
  }
10579
10631
 
10580
10632
  // packages/native/src/time-picker.tsx
10581
- import { Fragment as Fragment21, useEffect as useEffect29, useId as useId11, useMemo as useMemo4, useRef as useRef36, useState as useState44 } from "react";
10633
+ import { Fragment as Fragment21, useEffect as useEffect30, useId as useId11, useMemo as useMemo4, useRef as useRef39, useState as useState44 } from "react";
10582
10634
  import { View as View54 } from "react-native";
10583
10635
  import { createTimeDomain, tokens as tokens62 } from "@kjun-ui/tokens";
10584
10636
  import { jsx as jsx63, jsxs as jsxs46 } from "react/jsx-runtime";
@@ -10587,12 +10639,12 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
10587
10639
  ariaLabel != null ? ariaLabel : ariaLabel = m.time;
10588
10640
  const geometry2 = tokens62.extensions.timePicker, spec = tokens62.input[size];
10589
10641
  const { colors } = useKjunStyles();
10590
- const first = useRef36(null);
10642
+ const first = useRef39(null);
10591
10643
  const [focused, setFocused] = useState44(false), [opened, setOpened] = useState44(null);
10592
10644
  const field = useKjunField(), uid = useId11();
10593
10645
  const fieldId = (field == null ? void 0 : field.id) || `kjun-time-${uid}`;
10594
10646
  const domain = useMemo4(() => createTimeDomain({ precision, min, max, minuteStep, secondStep }), [precision, min, max, minuteStep, secondStep]), valid = domain.valid && domain.accepts(value);
10595
- useEffect29(() => {
10647
+ useEffect30(() => {
10596
10648
  if (!valid) console.warn("KJUN TimePicker: \uC2DC\uAC01 \uBC94\uC704\xB7\uAC04\uACA9\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
10597
10649
  }, [valid]);
10598
10650
  const change = (next) => {