@kjun-ui/native 0.10.0 → 0.11.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.cjs CHANGED
@@ -916,7 +916,7 @@ function KjunButton(input) {
916
916
  opacity: overlayLoading ? 0 : 1,
917
917
  ...multiline || navigation ? { flexShrink: 1, minWidth: 0, textAlign: "center" } : {}
918
918
  }, children }),
919
- suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native3.View, { style: { opacity: busy && prefixIcon ? 0 : 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
919
+ !!suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native3.View, { style: { opacity: busy && prefixIcon ? 0 : 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
920
920
  KjunIcon,
921
921
  {
922
922
  name: busy && !prefixIcon ? "loader-2" : suffixIcon,
@@ -1177,7 +1177,7 @@ function KjunFormGroup({
1177
1177
  describedBy: mergeIds(hint ? fieldId + "-hint" : void 0, error ? fieldId + "-error" : void 0)
1178
1178
  },
1179
1179
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: [{ minWidth: 0, marginBottom: import_tokens9.tokens.extensions.form.itemGap }, style], children: [
1180
- label && !labelHidden && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1180
+ !!label && !labelHidden && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1181
1181
  import_react_native8.Text,
1182
1182
  {
1183
1183
  nativeID: fieldId + "-label",
@@ -1269,6 +1269,7 @@ var KjunInput = (0, import_react16.forwardRef)(function KjunInput2({
1269
1269
  const invalid = !!(error || errorMessage || (field == null ? void 0 : field.error));
1270
1270
  const canEdit = !disabled && !readOnly && editable;
1271
1271
  const surface = useFieldSurface(size, { disabled, readOnly: !!readOnly || !editable, invalid, open: props["aria-expanded"] === true });
1272
+ const affixText = { ...inputTypeStyle(size), color: surface.icon };
1272
1273
  const showClear = clearable && !!value;
1273
1274
  const [prefixWidth, setPrefixWidth] = (0, import_react16.useState)(0);
1274
1275
  const [affixWidth, setAffixWidth] = (0, import_react16.useState)(0);
@@ -1330,7 +1331,7 @@ var KjunInput = (0, import_react16.forwardRef)(function KjunInput2({
1330
1331
  ]
1331
1332
  }
1332
1333
  ),
1333
- (prefix || prefixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1334
+ !!(prefix || prefixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1334
1335
  import_react_native8.View,
1335
1336
  {
1336
1337
  onLayout: (event) => setPrefixWidth(event.nativeEvent.layout.width),
@@ -1342,7 +1343,7 @@ var KjunInput = (0, import_react16.forwardRef)(function KjunInput2({
1342
1343
  bottom: 0,
1343
1344
  justifyContent: "center"
1344
1345
  },
1345
- children: prefix || /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1346
+ children: prefix ? content(prefix, affixText) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1346
1347
  KjunIcon,
1347
1348
  {
1348
1349
  name: prefixIcon,
@@ -1352,7 +1353,7 @@ var KjunInput = (0, import_react16.forwardRef)(function KjunInput2({
1352
1353
  )
1353
1354
  }
1354
1355
  ),
1355
- (showClear || suffix || suffixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1356
+ !!(showClear || suffix || suffixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1356
1357
  import_react_native8.View,
1357
1358
  {
1358
1359
  onLayout: (event) => setAffixWidth(event.nativeEvent.layout.width),
@@ -1373,7 +1374,7 @@ var KjunInput = (0, import_react16.forwardRef)(function KjunInput2({
1373
1374
  onClear == null ? void 0 : onClear();
1374
1375
  (_a = input.current) == null ? void 0 : _a.focus();
1375
1376
  } }),
1376
- suffix || suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1377
+ suffix ? content(suffix, affixText) : !!suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1377
1378
  KjunIcon,
1378
1379
  {
1379
1380
  name: suffixIcon,
@@ -1413,6 +1414,17 @@ function KjunFormLayout({
1413
1414
  ) });
1414
1415
  }
1415
1416
 
1417
+ // shared/package-runtime/content-presence.ts
1418
+ var import_react17 = require("react");
1419
+ function hasContent(node) {
1420
+ if (node == null || typeof node === "boolean") return false;
1421
+ if (typeof node === "string") return node.trim().length > 0;
1422
+ if (Array.isArray(node)) return node.some(hasContent);
1423
+ if ((0, import_react17.isValidElement)(node) && node.type === import_react17.Fragment)
1424
+ return hasContent(node.props.children);
1425
+ return true;
1426
+ }
1427
+
1416
1428
  // packages/native/src/layer-backdrop.tsx
1417
1429
  var import_react_native9 = require("react-native");
1418
1430
  var import_jsx_runtime9 = require("react/jsx-runtime");
@@ -1421,7 +1433,7 @@ function LayerBackdrop({ onPress, style }) {
1421
1433
  }
1422
1434
 
1423
1435
  // packages/native/src/modal.tsx
1424
- var import_react18 = require("react");
1436
+ var import_react19 = require("react");
1425
1437
 
1426
1438
  // shared/package-runtime/form-actions.ts
1427
1439
  function formActionsNeedStack(width, widths, gap) {
@@ -1434,7 +1446,7 @@ var import_tokens10 = require("@kjun-ui/tokens");
1434
1446
  var import_react_native13 = require("react-native");
1435
1447
 
1436
1448
  // packages/native/src/overlay-host.tsx
1437
- var import_react17 = require("react");
1449
+ var import_react18 = require("react");
1438
1450
  var import_react_native11 = require("react-native");
1439
1451
 
1440
1452
  // packages/native/src/modal-window.tsx
@@ -1450,17 +1462,17 @@ var import_jsx_runtime11 = (
1450
1462
  // a new window even when an interrupted exit retained the old surface.
1451
1463
  require("react/jsx-runtime")
1452
1464
  );
1453
- var FeedbackOverlayContext = (0, import_react17.createContext)(
1465
+ var FeedbackOverlayContext = (0, import_react18.createContext)(
1454
1466
  null
1455
1467
  );
1456
1468
  function ScopedNativeModal({ children, visible, ...props }) {
1457
1469
  var _a;
1458
- const layers = useLayerState(), scope = (0, import_react17.useContext)(LayerScope);
1470
+ const layers = useLayerState(), scope = (0, import_react18.useContext)(LayerScope);
1459
1471
  const entry = scope ? layers.entries.get(scope) : void 0;
1460
1472
  const generation = (_a = entry == null ? void 0 : entry.order) != null ? _a : 0;
1461
1473
  const inactive = !!scope && !layers.isActive(scope);
1462
- const host = (0, import_react17.useContext)(FeedbackOverlayContext), id = "kjun-" + (0, import_react17.useId)(), register = host == null ? void 0 : host.register;
1463
- (0, import_react17.useEffect)(
1474
+ const host = (0, import_react18.useContext)(FeedbackOverlayContext), id = "kjun-" + (0, import_react18.useId)(), register = host == null ? void 0 : host.register;
1475
+ (0, import_react18.useEffect)(
1464
1476
  () => visible && register ? register(id) : void 0,
1465
1477
  [visible, register, id, generation]
1466
1478
  );
@@ -1506,7 +1518,7 @@ function KjunFormActions({
1506
1518
  onConfirm
1507
1519
  }) {
1508
1520
  const { fontFamily } = useKjunStyles();
1509
- const [width, setWidth] = (0, import_react18.useState)(0), [measurements, setMeasurements] = (0, import_react18.useState)({});
1521
+ const [width, setWidth] = (0, import_react19.useState)(0), [measurements, setMeasurements] = (0, import_react19.useState)({});
1510
1522
  const labels = [showCancel && { text: cancelText }, showConfirm && { text: confirmText }].filter(Boolean);
1511
1523
  const keyFor = (text) => `${fontFamily}:${size}:${text}`;
1512
1524
  const widths = labels.map((label) => measurements[keyFor(label.text)] === void 0 ? 0 : Math.max(import_tokens10.tokens.button.minWidths[size], measurements[keyFor(label.text)] + import_tokens10.tokens.button.paddingX[size] * 2));
@@ -1607,7 +1619,7 @@ function KjunModal({
1607
1619
  const motion = useNativePresence(open, import_tokens10.tokens.motion.layerEnter, import_tokens10.tokens.motion.layerExit, true, 0, { fade: import_tokens10.tokens.motion.backdropExit });
1608
1620
  const offset = useMotionValue(open ? 0 : import_tokens10.tokens.motionDistance.modalExit, open ? import_tokens10.tokens.motion.layerEnter : import_tokens10.tokens.motion.layerExit, import_tokens10.tokens.motionDistance.modalEnter, open ? motionOut : motionIn, true);
1609
1621
  const backdrop = useNativePresence(open, import_tokens10.tokens.motion.backdrop, import_tokens10.tokens.motion.backdropExit, true, 0, { fade: import_tokens10.tokens.motion.backdropExit });
1610
- (0, import_react18.useLayoutEffect)(() => {
1622
+ (0, import_react19.useLayoutEffect)(() => {
1611
1623
  if (!motion.present) {
1612
1624
  offset.stopAnimation();
1613
1625
  offset.setValue(import_tokens10.tokens.motionDistance.modalEnter);
@@ -1697,7 +1709,7 @@ function KjunModal({
1697
1709
  borderBottomColor: c.border
1698
1710
  },
1699
1711
  children: [
1700
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.View, { style: { flex: 1, paddingRight: import_tokens10.tokens.modal.titleActionGap }, children: header || /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1712
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native13.View, { style: { flex: 1, paddingRight: import_tokens10.tokens.modal.titleActionGap }, children: hasContent(header) ? content(header) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1701
1713
  import_react_native13.Text,
1702
1714
  {
1703
1715
  accessibilityRole: "header",
@@ -1737,7 +1749,7 @@ function KjunModal({
1737
1749
  children
1738
1750
  }
1739
1751
  ),
1740
- (showFooter || footer) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1752
+ (showFooter || hasContent(footer)) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1741
1753
  import_react_native13.View,
1742
1754
  {
1743
1755
  style: {
@@ -1750,7 +1762,7 @@ function KjunModal({
1750
1762
  borderTopWidth: import_tokens10.tokens.border.defaultWidth,
1751
1763
  borderTopColor: c.border
1752
1764
  },
1753
- children: footer || /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1765
+ children: hasContent(footer) ? content(footer) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1754
1766
  KjunFormActions,
1755
1767
  {
1756
1768
  size: footerSize,
@@ -1786,19 +1798,6 @@ var import_tokens11 = require("@kjun-ui/tokens");
1786
1798
  var import_react20 = require("react");
1787
1799
  var import_react_native14 = require("react-native");
1788
1800
  var import_react_native_svg2 = __toESM(require("react-native-svg"), 1);
1789
-
1790
- // shared/package-runtime/content-presence.ts
1791
- var import_react19 = require("react");
1792
- function hasContent(node) {
1793
- if (node == null || typeof node === "boolean") return false;
1794
- if (typeof node === "string") return node.trim().length > 0;
1795
- if (Array.isArray(node)) return node.some(hasContent);
1796
- if ((0, import_react19.isValidElement)(node) && node.type === import_react19.Fragment)
1797
- return hasContent(node.props.children);
1798
- return true;
1799
- }
1800
-
1801
- // packages/native/src/card.tsx
1802
1801
  var import_jsx_runtime13 = require("react/jsx-runtime");
1803
1802
  function KjunCard({
1804
1803
  title,
@@ -1859,8 +1858,8 @@ function KjunCard({
1859
1858
  borderBottomColor: borderColor
1860
1859
  }, children: [
1861
1860
  hasHeading && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native14.View, { style: { flexGrow: 1, flexShrink: 1, minWidth: 0, maxWidth: "100%" }, children: hasContent(header) ? content(header, { color: foreground }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1862
- title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle"), color: foreground }, children: title }),
1863
- subtitle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { style: { ...typeStyle("caption"), marginTop: import_tokens11.tokens.card.subtitleGap, color: colors[paint.description] }, children: subtitle })
1861
+ !!title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle"), color: foreground }, children: title }),
1862
+ !!subtitle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { style: { ...typeStyle("caption"), marginTop: import_tokens11.tokens.card.subtitleGap, color: colors[paint.description] }, children: subtitle })
1864
1863
  ] }) }),
1865
1864
  hasContent(headerActions) && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardActionsContext.Provider, { value: true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native14.View, { style: { flexDirection: "row", flexWrap: "wrap", minWidth: 0, maxWidth: "100%", marginStart: "auto", alignItems: "center", justifyContent: "flex-end", gap: import_tokens11.tokens.card.titleGap }, children: content(headerActions, { color: foreground }) }) })
1866
1865
  ] }),
@@ -1973,9 +1972,9 @@ function KjunEmpty({
1973
1972
  paddingVertical: stateContent === "empty" ? 0 : import_tokens12.tokens.dimension.value32
1974
1973
  },
1975
1974
  children: [
1976
- icon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { marginBottom: spec.iconGap }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KjunIcon, { name: icon, size: spec.iconSize, color: colors.textSecondary }) }),
1975
+ !!icon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { marginBottom: spec.iconGap }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KjunIcon, { name: icon, size: spec.iconSize, color: colors.textSecondary }) }),
1977
1976
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KText, { style: { ...typeStyle("cardTitle"), color: colors.text, fontSize: spec.titleSize, lineHeight: spec.titleLineHeight, textAlign: "center", maxWidth: spec.textMaxWidth }, children: text }),
1978
- description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1977
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1979
1978
  KText,
1980
1979
  {
1981
1980
  style: {
@@ -1990,7 +1989,7 @@ function KjunEmpty({
1990
1989
  children: description
1991
1990
  }
1992
1991
  ),
1993
- children && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { marginTop: spec.actionGap, maxWidth: "100%" }, children: content(children) })
1992
+ hasContent(children) && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { marginTop: spec.actionGap, maxWidth: "100%" }, children: content(children) })
1994
1993
  ]
1995
1994
  }
1996
1995
  );
@@ -2068,7 +2067,7 @@ function KjunSpinner({ size = "md", text }) {
2068
2067
  )
2069
2068
  }
2070
2069
  ),
2071
- text && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KText, { style: { marginLeft: import_tokens12.tokens.dimension.value8, color: colors.textSecondary }, children: text })
2070
+ !!text && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KText, { style: { marginLeft: import_tokens12.tokens.dimension.value8, color: colors.textSecondary }, children: text })
2072
2071
  ]
2073
2072
  }
2074
2073
  );
@@ -2129,7 +2128,7 @@ function KjunAlert({
2129
2128
  ...typeStyle(small ? "caption" : "body"),
2130
2129
  color: colors.textSecondary
2131
2130
  }) }),
2132
- hasContent(actions) && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ActionSizeContext.Provider, { value: alertActionSizes[small ? "sm" : "md"], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AlertActionsContext.Provider, { value: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { flexDirection: "row", flexWrap: "wrap", alignItems: "center", gap: geometry2.actionsGap, marginTop: geometry2[small ? "sm" : "md"].actionGap }, children: actions }) }) })
2131
+ hasContent(actions) && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ActionSizeContext.Provider, { value: alertActionSizes[small ? "sm" : "md"], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AlertActionsContext.Provider, { value: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { flexDirection: "row", flexWrap: "wrap", alignItems: "center", gap: geometry2.actionsGap, marginTop: geometry2[small ? "sm" : "md"].actionGap }, children: content(actions) }) }) })
2133
2132
  ] }),
2134
2133
  closable && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2135
2134
  AccessiblePressable,
@@ -2179,7 +2178,7 @@ function KjunProgress({
2179
2178
  const { colors } = useKjunStyles();
2180
2179
  const percentage = Number.isFinite(value) && max > 0 ? Math.min(100, Math.max(0, Math.round(value / max * 100))) : 0;
2181
2180
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native15.View, { children: [
2182
- (label || showLabel) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2181
+ !!(label || showLabel) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2183
2182
  import_react_native15.View,
2184
2183
  {
2185
2184
  style: {
@@ -2594,7 +2593,7 @@ function ToastView({
2594
2593
  children: [
2595
2594
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KjunIcon, { name: icon, color: colors[`${tone}Accent`] }),
2596
2595
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native17.View, { style: { flex: 1, minWidth: 0 }, children: [
2597
- toast.title && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KText, { style: { fontWeight: typeStyle("control").fontWeight, marginBottom: import_tokens15.tokens.extensions.toast.titleGap }, children: toast.title }),
2596
+ !!toast.title && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KText, { style: { fontWeight: typeStyle("control").fontWeight, marginBottom: import_tokens15.tokens.extensions.toast.titleGap }, children: toast.title }),
2598
2597
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KText, { style: { color: colors.textSecondary }, children: toast.message }),
2599
2598
  toast.action && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2600
2599
  AccessiblePressable,
@@ -2772,7 +2771,7 @@ function FeedbackDialog({
2772
2771
  onConfirm: submit,
2773
2772
  confirmVariant: options.type === "danger" ? "danger" : "primary",
2774
2773
  children: [
2775
- options.message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(KText, { style: { marginBottom: import_tokens17.tokens.dimension.value16 }, children: options.message }),
2774
+ !!options.message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(KText, { style: { marginBottom: import_tokens17.tokens.dimension.value16 }, children: options.message }),
2776
2775
  request.kind === "prompt" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2777
2776
  KjunInput,
2778
2777
  {
@@ -2789,7 +2788,7 @@ function FeedbackDialog({
2789
2788
  }
2790
2789
  );
2791
2790
  }
2792
- function KjunFeedbackProvider({ children }) {
2791
+ function KjunFeedbackProvider({ children, style }) {
2793
2792
  const [controller] = (0, import_react28.useState)(import_tokens17.createFeedbackController);
2794
2793
  const life = (0, import_react28.useRef)(0);
2795
2794
  const snapshot = (0, import_react28.useSyncExternalStore)(
@@ -2819,7 +2818,7 @@ function KjunFeedbackProvider({ children }) {
2819
2818
  {
2820
2819
  value: { top: layers[layers.length - 1], register, render: renderToasts },
2821
2820
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(KjunFeedbackContext.Provider, { value: controller.api, children: [
2822
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native19.View, { style: { position: "relative" }, children: [
2821
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native19.View, { style: [{ position: "relative", flexGrow: 1, flexShrink: 1, alignSelf: "stretch" }, style], children: [
2823
2822
  children,
2824
2823
  layers.length === 0 && renderToasts()
2825
2824
  ] }),
@@ -2901,7 +2900,7 @@ function KjunCheckbox({
2901
2900
  )
2902
2901
  }
2903
2902
  ),
2904
- (children || label) && content(children || label, {
2903
+ !!(children || label) && content(children || label, {
2905
2904
  marginLeft: import_tokens18.tokens.extensions.checkbox.labelGap,
2906
2905
  ...typeStyle("label")
2907
2906
  })
@@ -3012,7 +3011,7 @@ function KjunSwitch({
3012
3011
  ]
3013
3012
  }
3014
3013
  ),
3015
- (children || label) && content(children || label, {
3014
+ !!(children || label) && content(children || label, {
3016
3015
  marginLeft: import_tokens18.tokens.extensions.switch.labelGap,
3017
3016
  ...typeStyle("label")
3018
3017
  })
@@ -3089,7 +3088,7 @@ function KjunRadio({
3089
3088
  )
3090
3089
  }
3091
3090
  ),
3092
- (children || label) && content(children || label, {
3091
+ !!(children || label) && content(children || label, {
3093
3092
  marginLeft: geometry2.labelGap,
3094
3093
  ...typeStyle("label")
3095
3094
  })
@@ -3332,7 +3331,7 @@ function KjunButtonGroup({
3332
3331
  opacity: blocked ? import_tokens20.tokens.states.opacity.disabled : 1
3333
3332
  }),
3334
3333
  children: [
3335
- option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3334
+ !!option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3336
3335
  KjunIcon,
3337
3336
  {
3338
3337
  name: option.icon,
@@ -3429,7 +3428,7 @@ function KjunFilterGroup({
3429
3428
  }
3430
3429
  }
3431
3430
  ),
3432
- option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3431
+ !!option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3433
3432
  KjunIcon,
3434
3433
  {
3435
3434
  name: option.icon,
@@ -3560,8 +3559,50 @@ var KjunTextarea = (0, import_react32.forwardRef)(
3560
3559
  var import_tokens22 = require("@kjun-ui/tokens");
3561
3560
  var import_react33 = require("react");
3562
3561
  var import_react_native25 = require("react-native");
3562
+
3563
+ // shared/package-runtime/drawer-geometry.ts
3564
+ function keyboardEvents(os) {
3565
+ return os === "ios" ? { show: "keyboardWillShow", hide: "keyboardWillHide" } : null;
3566
+ }
3567
+ function keyboardOverlap(windowHeight, keyboardScreenY) {
3568
+ return Math.max(0, windowHeight - keyboardScreenY);
3569
+ }
3570
+ function drawerFrame({ position, windowHeight, safeAreaTop, safeAreaBottom, gap, keyboard, maxHeight }) {
3571
+ const visible = windowHeight - keyboard;
3572
+ const bottomInset = keyboard > 0 ? 0 : safeAreaBottom;
3573
+ if (position === "left" || position === "right")
3574
+ return { maxHeight: visible, height: visible, paddingTop: safeAreaTop, paddingBottom: bottomInset, lift: 0 };
3575
+ const sheet = maxHeight != null ? maxHeight : visible - (position === "bottom" ? safeAreaTop : bottomInset) - gap;
3576
+ return {
3577
+ maxHeight: Math.max(0, Math.min(sheet, visible)),
3578
+ height: void 0,
3579
+ paddingTop: position === "top" ? safeAreaTop : 0,
3580
+ paddingBottom: position === "bottom" ? bottomInset : 0,
3581
+ lift: position === "bottom" ? keyboard : 0
3582
+ };
3583
+ }
3584
+
3585
+ // packages/native/src/drawer.tsx
3563
3586
  var import_react_native26 = require("react-native");
3564
3587
  var import_jsx_runtime23 = require("react/jsx-runtime");
3588
+ function useKeyboardOverlap(enabled, windowHeight) {
3589
+ const [overlap, setOverlap] = (0, import_react33.useState)(0);
3590
+ (0, import_react33.useEffect)(() => {
3591
+ var _a, _b;
3592
+ setOverlap(0);
3593
+ const events = keyboardEvents(import_react_native26.Platform.OS);
3594
+ if (!enabled || !events) return;
3595
+ const metrics = (_b = (_a = import_react_native25.Keyboard).metrics) == null ? void 0 : _b.call(_a);
3596
+ if (metrics) setOverlap(keyboardOverlap(windowHeight, metrics.screenY));
3597
+ const show = import_react_native25.Keyboard.addListener(events.show, (event) => setOverlap(keyboardOverlap(windowHeight, event.endCoordinates.screenY)));
3598
+ const hide = import_react_native25.Keyboard.addListener(events.hide, () => setOverlap(0));
3599
+ return () => {
3600
+ show.remove();
3601
+ hide.remove();
3602
+ };
3603
+ }, [enabled, windowHeight]);
3604
+ return overlap;
3605
+ }
3565
3606
  function KjunDrawer({
3566
3607
  open,
3567
3608
  onOpenChange,
@@ -3576,9 +3617,24 @@ function KjunDrawer({
3576
3617
  footer,
3577
3618
  children,
3578
3619
  onClose,
3579
- ariaLabel
3620
+ ariaLabel,
3621
+ safeAreaTop = 0,
3622
+ safeAreaBottom = 0,
3623
+ maxHeight,
3624
+ avoidKeyboard = true
3580
3625
  }) {
3581
3626
  const { colors } = useKjunStyles(), window2 = (0, import_react_native26.useWindowDimensions)(), vertical = position === "left" || position === "right";
3627
+ const [rootHeight, setRootHeight] = (0, import_react33.useState)(0);
3628
+ const keyboard = useKeyboardOverlap(open && avoidKeyboard, window2.height);
3629
+ const frame = drawerFrame({
3630
+ position,
3631
+ windowHeight: rootHeight || window2.height,
3632
+ safeAreaTop: Math.max(0, safeAreaTop),
3633
+ safeAreaBottom: Math.max(0, safeAreaBottom),
3634
+ gap: import_tokens22.tokens.extensions.drawer.sheetGap,
3635
+ keyboard,
3636
+ maxHeight
3637
+ });
3582
3638
  const [panelHeight, setPanelHeight] = (0, import_react33.useState)(0);
3583
3639
  const motion = useNativePresence(open, import_tokens22.tokens.motion.layerEnter, import_tokens22.tokens.motion.layerExit, vertical || panelHeight > 0, 0, { enterEasing: motionEmphasized });
3584
3640
  const backdrop = useNativePresence(open, import_tokens22.tokens.motion.backdrop, import_tokens22.tokens.motion.backdropExit, true, 0, { fade: import_tokens22.tokens.motion.backdropExit });
@@ -3602,6 +3658,7 @@ function KjunDrawer({
3602
3658
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3603
3659
  import_react_native26.View,
3604
3660
  {
3661
+ onLayout: (event) => setRootHeight(event.nativeEvent.layout.height),
3605
3662
  style: {
3606
3663
  flex: 1,
3607
3664
  justifyContent: position === "bottom" ? "flex-end" : "flex-start",
@@ -3640,8 +3697,11 @@ function KjunDrawer({
3640
3697
  opacity: vertical || panelHeight > 0 ? 1 : 0,
3641
3698
  transform: vertical ? [{ translateX: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [(position === "left" ? -1 : 1) * Math.min(width, window2.width), 0] }) }] : [{ translateY: motion.progress.interpolate({ inputRange: [0, 1], outputRange: [(position === "top" ? -1 : 1) * panelHeight, 0] }) }],
3642
3699
  width: vertical ? Math.min(width, window2.width) : window2.width,
3643
- height: vertical ? window2.height : void 0,
3644
- maxHeight: window2.height,
3700
+ height: frame.height,
3701
+ maxHeight: frame.maxHeight,
3702
+ paddingTop: frame.paddingTop,
3703
+ paddingBottom: frame.paddingBottom,
3704
+ marginBottom: frame.lift,
3645
3705
  borderRadius: import_tokens22.tokens.extensions.drawer.radius,
3646
3706
  borderTopLeftRadius: position === "bottom" ? import_tokens22.tokens.extensions.drawer.bottomRadius : import_tokens22.tokens.extensions.drawer.radius,
3647
3707
  borderTopRightRadius: position === "bottom" ? import_tokens22.tokens.extensions.drawer.bottomRadius : import_tokens22.tokens.extensions.drawer.radius,
@@ -3649,7 +3709,7 @@ function KjunDrawer({
3649
3709
  backgroundColor: colors.surface
3650
3710
  },
3651
3711
  children: [
3652
- (title || header || closable) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3712
+ !!(title || header || closable) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3653
3713
  import_react_native26.View,
3654
3714
  {
3655
3715
  style: {
@@ -3662,7 +3722,7 @@ function KjunDrawer({
3662
3722
  borderBottomColor: colors.border
3663
3723
  },
3664
3724
  children: [
3665
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native26.View, { style: { flex: 1 }, children: header || /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3725
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native26.View, { style: { flex: 1 }, children: hasContent(header) ? content(header) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3666
3726
  KText,
3667
3727
  {
3668
3728
  style: { ...typeStyle("sectionTitle") },
@@ -3687,12 +3747,12 @@ function KjunDrawer({
3687
3747
  import_react_native26.ScrollView,
3688
3748
  {
3689
3749
  keyboardShouldPersistTaps: "handled",
3690
- style: vertical ? { flex: 1 } : { flexGrow: 0 },
3750
+ style: vertical ? { flex: 1 } : { flexGrow: 0, flexShrink: 1 },
3691
3751
  contentContainerStyle: { padding: noPadding ? 0 : import_tokens22.tokens.extensions.drawer.bodyPadding },
3692
3752
  children: content(children)
3693
3753
  }
3694
3754
  ),
3695
- footer && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3755
+ hasContent(footer) && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3696
3756
  import_react_native26.View,
3697
3757
  {
3698
3758
  style: {
@@ -3950,7 +4010,7 @@ function FloatingPanel({
3950
4010
  borderBottomWidth: import_tokens23.tokens.border.defaultWidth,
3951
4011
  borderBottomColor: colors.divider
3952
4012
  },
3953
- children: header
4013
+ children: content(header, typeStyle("cardTitle"))
3954
4014
  }
3955
4015
  ),
3956
4016
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
@@ -5578,7 +5638,7 @@ function KjunTabs({
5578
5638
  opacity: tab.disabled ? import_tokens32.tokens.states.opacity.disabled : 1
5579
5639
  },
5580
5640
  children: [
5581
- tab.icon && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
5641
+ !!tab.icon && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
5582
5642
  KjunIcon,
5583
5643
  {
5584
5644
  name: tab.icon,
@@ -5623,11 +5683,11 @@ function KjunTabs({
5623
5683
  tab.name
5624
5684
  );
5625
5685
  }),
5626
- actions
5686
+ content(actions)
5627
5687
  ]
5628
5688
  }
5629
5689
  ),
5630
- children && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native37.View, { style: { marginTop: geometry2.contentGap }, children })
5690
+ hasContent(children) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native37.View, { style: { marginTop: geometry2.contentGap }, children: content(children) })
5631
5691
  ] }) });
5632
5692
  }
5633
5693
  function KjunTabPane({ name, children }) {
@@ -5755,7 +5815,7 @@ function KjunBreadcrumb({
5755
5815
  },
5756
5816
  children: items.map((item, i) => {
5757
5817
  const label = /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens33.tokens.dimension.value4 }, children: [
5758
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(KjunIcon, { name: item.icon, size: import_tokens33.tokens.extensions.breadcrumb.iconSize, color: colors.textSecondary }),
5818
+ !!item.icon && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(KjunIcon, { name: item.icon, size: import_tokens33.tokens.extensions.breadcrumb.iconSize, color: colors.textSecondary }),
5759
5819
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
5760
5820
  KText,
5761
5821
  {
@@ -6071,7 +6131,7 @@ function KjunCopyButton({
6071
6131
  color: copied ? colors.success : colors.textSecondary
6072
6132
  }
6073
6133
  ),
6074
- text && !inline && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6134
+ !!text && !inline && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6075
6135
  KText,
6076
6136
  {
6077
6137
  style: {
@@ -6259,7 +6319,7 @@ function KjunDataState({
6259
6319
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KText, { style: { ...typeStyle("body"), color: colors.textSecondary, textAlign: "center", maxWidth: "100%" }, children: loadingText })
6260
6320
  ] }))
6261
6321
  }
6262
- ) : blockingError ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DataStateContentContext.Provider, { value: "message", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native40.View, { style: { paddingVertical: padding }, children: errorContent || /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunAlert, { type: "danger", title: "\uC624\uB958 \uBC1C\uC0DD", actions: onRetry && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunButton, { variant: "secondary", onPress: onRetry, children: retryText }), children: query.error }) }) }) : empty ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DataStateContentContext.Provider, { value: "empty", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native40.View, { style: { paddingVertical: padding }, children: emptyContent || /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunEmpty, { text: emptyText, icon: emptyIcon, children: emptyActionText && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunButton, { onPress: onEmptyAction, children: emptyActionText }) }) }) }) : null,
6322
+ ) : blockingError ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DataStateContentContext.Provider, { value: "message", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native40.View, { style: { paddingVertical: padding }, children: errorContent || /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunAlert, { type: "danger", title: "\uC624\uB958 \uBC1C\uC0DD", actions: onRetry && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunButton, { variant: "secondary", onPress: onRetry, children: retryText }), children: query.error }) }) }) : empty ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DataStateContentContext.Provider, { value: "empty", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native40.View, { style: { paddingVertical: padding }, children: emptyContent || /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunEmpty, { text: emptyText, icon: emptyIcon, children: !!emptyActionText && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunButton, { onPress: onEmptyAction, children: emptyActionText }) }) }) }) : null,
6263
6323
  (!concealed || preserveContent && state.hasQueryResult) && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6264
6324
  import_react_native40.View,
6265
6325
  {
@@ -6732,12 +6792,12 @@ function KjunAnimatedNumber({
6732
6792
  style
6733
6793
  ],
6734
6794
  children: [
6735
- prefix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
6795
+ !!prefix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
6736
6796
  prefix,
6737
6797
  " "
6738
6798
  ] }),
6739
6799
  typeof n === "string" ? n : formatter ? formatter(n) : format(n, decimals),
6740
- suffix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
6800
+ !!suffix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
6741
6801
  " ",
6742
6802
  suffix
6743
6803
  ] })
@@ -7620,7 +7680,7 @@ function TableCards({
7620
7680
  },
7621
7681
  children: [
7622
7682
  selectable && checkbox(row, i),
7623
- title && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flex: 1, minWidth: 0 }, children: cell(title, row, i, "title") })
7683
+ !!title && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flex: 1, minWidth: 0 }, children: cell(title, row, i, "title") })
7624
7684
  ]
7625
7685
  }
7626
7686
  ),
@@ -7641,7 +7701,7 @@ function TableCards({
7641
7701
  marginTop: index ? import_tokens46.tokens.dimension.value12 : 0
7642
7702
  },
7643
7703
  children: [
7644
- section.label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7704
+ !!section.label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7645
7705
  KText,
7646
7706
  {
7647
7707
  style: {
@@ -7706,7 +7766,7 @@ function TableCards({
7706
7766
  children: content(renderExpand == null ? void 0 : renderExpand(row, i))
7707
7767
  }
7708
7768
  ),
7709
- actions && !actions.inlineInCard && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7769
+ !!actions && !actions.inlineInCard && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7710
7770
  import_react_native47.View,
7711
7771
  {
7712
7772
  style: {
@@ -7995,7 +8055,7 @@ function KjunKpiHero(props) {
7995
8055
  children: loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(KjunSkeleton, { type: "block", height: typeStyle("numberMd").lineHeight, width: geometry2.deltaSkeletonWidth }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
7996
8056
  deltaAbsolute !== null && delta(deltaAbsolute, "absolute", { ...numeric, color: direction(deltaAbsolute), ...typeStyle("numberMd") }),
7997
8057
  deltaPercent !== null && delta(deltaPercent, "percent", { ...numeric, color: direction(deltaPercent), ...typeStyle("numberMd"), opacity: 0.9 }),
7998
- deltaDescription && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8058
+ !!deltaDescription && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7999
8059
  KText,
8000
8060
  {
8001
8061
  style: {
@@ -8009,7 +8069,7 @@ function KjunKpiHero(props) {
8009
8069
  }
8010
8070
  )
8011
8071
  ] }),
8012
- aside && !mobile && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native50.View, { children: aside })
8072
+ hasContent(aside) && !mobile && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native50.View, { children: content(aside) })
8013
8073
  ]
8014
8074
  }
8015
8075
  ),
@@ -8071,7 +8131,7 @@ function KjunKpiHero(props) {
8071
8131
  children: kpiFormat(item)
8072
8132
  }
8073
8133
  ),
8074
- item.desc && (loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8134
+ !!item.desc && (loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8075
8135
  KjunSkeleton,
8076
8136
  {
8077
8137
  type: "block",
@@ -8278,7 +8338,7 @@ function KjunKpiRow({
8278
8338
  {
8279
8339
  style: [valueStyle, { flexShrink: 1, minWidth: 0 }],
8280
8340
  children: [
8281
- item.prefix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8341
+ !!item.prefix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8282
8342
  import_react_native51.Text,
8283
8343
  {
8284
8344
  style: {
@@ -8296,7 +8356,7 @@ function KjunKpiRow({
8296
8356
  style: [valueStyle, { flexShrink: 1, minWidth: 0 }]
8297
8357
  }
8298
8358
  ) : kpiFormat(item),
8299
- item.suffix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8359
+ !!item.suffix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8300
8360
  import_react_native51.Text,
8301
8361
  {
8302
8362
  style: {
@@ -8312,7 +8372,7 @@ function KjunKpiRow({
8312
8372
  ]
8313
8373
  }
8314
8374
  ),
8315
- item.desc && (busy ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(KjunSkeleton, { type: "block", height: typeStyle("caption").lineHeight, width: geometry2.descriptionSkeletonWidth }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8375
+ !!item.desc && (busy ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(KjunSkeleton, { type: "block", height: typeStyle("caption").lineHeight, width: geometry2.descriptionSkeletonWidth }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8316
8376
  KText,
8317
8377
  {
8318
8378
  style: {
@@ -9158,26 +9218,26 @@ var LastListRow = (0, import_react62.createContext)(false);
9158
9218
  function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, onPress }) {
9159
9219
  const { colors } = useKjunStyles(), last = (0, import_react62.useContext)(LastListRow);
9160
9220
  const parts = /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
9161
- leading && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { children: content(leading) }),
9221
+ hasContent(leading) && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { children: content(leading) }),
9162
9222
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flex: 1, minWidth: 0 }, children: [
9163
9223
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { ...typeStyle("label") }, children: title }),
9164
- description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens55.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9224
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens55.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9165
9225
  ] }),
9166
- trailing && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { style: { maxWidth: "35%" }, children: content(trailing) })
9226
+ hasContent(trailing) && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { style: { maxWidth: "35%" }, children: content(trailing) })
9167
9227
  ] });
9168
9228
  const style = { flex: 1, minWidth: 0, minHeight: import_tokens55.tokens.extensions.list.minimumHeight, flexDirection: "row", alignItems: "center", gap: import_tokens55.tokens.extensions.list.gap, padding: import_tokens55.tokens.extensions.list.padding };
9169
9229
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { role: "listitem", style: { flexDirection: "row", alignItems: "center", gap: import_tokens55.tokens.extensions.list.gap, borderBottomWidth: last ? 0 : import_tokens55.tokens.border.defaultWidth, borderBottomColor: colors.divider }, children: [
9170
9230
  onPress || href ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(AccessiblePressable, { ...import_react_native57.Platform.OS === "web" && href && !disabled ? { href } : {}, accessibilityRole: href ? "link" : "button", accessibilityLabel: title + (description ? ", " + description : ""), disabled, accessibilityState: { disabled }, onPress, style: ({ pressed }) => ({ ...style, opacity: disabled ? import_tokens55.tokens.states.opacity.disabled : 1, backgroundColor: pressed ? colors.hover : "transparent" }), children: parts }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { style, children: parts }),
9171
- actions && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { pointerEvents: disabled ? "none" : "auto", ...disabled && import_react_native57.Platform.OS === "web" ? { inert: true } : {}, style: { maxWidth: "45%", flexDirection: "row", flexWrap: "wrap", gap: import_tokens55.tokens.extensions.list.actionsGap, paddingRight: import_tokens55.tokens.extensions.list.actionsPadding, opacity: disabled ? import_tokens55.tokens.states.opacity.disabled : 1 }, children: content(actions) })
9231
+ hasContent(actions) && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { pointerEvents: disabled ? "none" : "auto", ...disabled && import_react_native57.Platform.OS === "web" ? { inert: true } : {}, style: { maxWidth: "45%", flexDirection: "row", flexWrap: "wrap", gap: import_tokens55.tokens.extensions.list.actionsGap, paddingRight: import_tokens55.tokens.extensions.list.actionsPadding, opacity: disabled ? import_tokens55.tokens.states.opacity.disabled : 1 }, children: content(actions) })
9172
9232
  ] });
9173
9233
  }
9174
9234
  function KjunListSection({ title, description, actions, children, ariaLabel }) {
9175
9235
  const { colors } = useKjunStyles();
9176
9236
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { minWidth: 0, backgroundColor: colors.surface }, children: [
9177
- (title || description || actions) && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens55.tokens.extensions.list.gap, padding: import_tokens55.tokens.extensions.list.padding }, children: [
9237
+ !!(title || description || actions) && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens55.tokens.extensions.list.gap, padding: import_tokens55.tokens.extensions.list.padding }, children: [
9178
9238
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flex: 1 }, children: [
9179
- title && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle") }, children: title }),
9180
- description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens55.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9239
+ !!title && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle") }, children: title }),
9240
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens55.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9181
9241
  ] }),
9182
9242
  content(actions)
9183
9243
  ] }),
@@ -9205,12 +9265,12 @@ function KjunTopNavigation({ title, description, leading, actions, safeAreaTop =
9205
9265
  const flatten = (node) => import_react63.Children.toArray(node).flatMap((child) => (0, import_react63.isValidElement)(child) && child.type === import_react63.Fragment ? flatten(child.props.children) : [child]);
9206
9266
  const actionList = flatten(actions);
9207
9267
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TopNavigationContext.Provider, { value: geometry2, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { style: { flexShrink: 0, paddingTop: Math.max(0, safeAreaTop), backgroundColor: colors.surface }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { minHeight: geometry2.minimumHeight, flexDirection: "row", flexWrap: "wrap", alignItems: "flex-start", gap: geometry2.gap, paddingVertical: geometry2.paddingY, paddingHorizontal: geometry2.paddingX }, children: [
9208
- leading && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TopNavigationContext.Provider, { value: { ...geometry2, slot: "leading" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { onLayout: square("leading"), style: { minHeight: geometry2.controlSize, minWidth: 0, maxWidth: "40%", flexShrink: 1, justifyContent: "center", marginLeft: iconEdges.leading ? -edgeInset : 0 }, children: content(leading) }) }),
9268
+ hasContent(leading) && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TopNavigationContext.Provider, { value: { ...geometry2, slot: "leading" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { onLayout: square("leading"), style: { minHeight: geometry2.controlSize, minWidth: 0, maxWidth: "40%", flexShrink: 1, justifyContent: "center", marginLeft: iconEdges.leading ? -edgeInset : 0 }, children: content(leading) }) }),
9209
9269
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { flexGrow: 1, flexShrink: 1, flexBasis: geometry2.titleMinimumWidth, minWidth: 0, paddingVertical: titleInset }, children: [
9210
9270
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { accessibilityRole: "header", style: { ...wrapping, ...typeStyle("sectionTitle"), fontWeight: typeStyle("control").fontWeight }, children: title }),
9211
- description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...wrapping, marginTop: geometry2.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9271
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...wrapping, marginTop: geometry2.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9212
9272
  ] }),
9213
- actions && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TopNavigationContext.Provider, { value: { ...geometry2, slot: "actions" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { style: { minHeight: geometry2.controlSize, minWidth: 0, maxWidth: "100%", marginLeft: "auto", flexShrink: 1, flexDirection: "row", flexWrap: "wrap", alignItems: "center", justifyContent: "flex-end", gap: geometry2.actionsGap }, children: actionList.map((action, index) => index < actionList.length - 1 ? content(action) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { onLayout: square("trailing"), style: { flexShrink: 1, minWidth: 0, maxWidth: "100%", marginRight: iconEdges.trailing ? -edgeInset : 0 }, children: content(action) }, "trailing")) }) })
9273
+ hasContent(actions) && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TopNavigationContext.Provider, { value: { ...geometry2, slot: "actions" }, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { style: { minHeight: geometry2.controlSize, minWidth: 0, maxWidth: "100%", marginLeft: "auto", flexShrink: 1, flexDirection: "row", flexWrap: "wrap", alignItems: "center", justifyContent: "flex-end", gap: geometry2.actionsGap }, children: actionList.map((action, index) => index < actionList.length - 1 ? content(action) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { onLayout: square("trailing"), style: { flexShrink: 1, minWidth: 0, maxWidth: "100%", marginRight: iconEdges.trailing ? -edgeInset : 0 }, children: content(action) }, "trailing")) }) })
9214
9274
  ] }) }) });
9215
9275
  }
9216
9276
  function KjunBottomNavigation({ items, value, ariaLabel = "\uC8FC\uC694 \uD0D0\uC0C9", safeAreaBottom = 0, keyboardVisible = false, hideOnKeyboard = true, onNavigate }) {
@@ -9260,7 +9320,7 @@ function KjunBottomNavigation({ items, value, ariaLabel = "\uC8FC\uC694 \uD0D0\u
9260
9320
  },
9261
9321
  children: [
9262
9322
  hasIcons && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { width: geometry2.iconSize, height: geometry2.iconSize, flexShrink: 0 }, children: [
9263
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KjunIcon, { name: item.icon, size: geometry2.iconSize, color: ink }),
9323
+ !!item.icon && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KjunIcon, { name: item.icon, size: geometry2.iconSize, color: ink }),
9264
9324
  badge
9265
9325
  ] }),
9266
9326
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { maxWidth: "100%" }, children: [
@@ -9292,7 +9352,7 @@ function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboa
9292
9352
  flexDirection: wide ? "row" : "column",
9293
9353
  alignItems: wide ? "center" : "stretch"
9294
9354
  }, children: [
9295
- description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...typeStyle("body"), ...wrapping, color: colors.textSecondary, flex: wide ? 1 : void 0, minWidth: 0 }, children: description }),
9355
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...typeStyle("body"), ...wrapping, color: colors.textSecondary, flex: wide ? 1 : void 0, minWidth: 0 }, children: description }),
9296
9356
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_react_native58.View, { style: { flexDirection: "row", flexWrap: "wrap", justifyContent: "flex-end", alignItems: "center", gap: geometry2.actionsGap, minWidth: 0, maxWidth: "100%", flexShrink: 1 }, children: content(children) })
9297
9357
  ] }) });
9298
9358
  }
@@ -9330,7 +9390,7 @@ var import_jsx_runtime57 = require("react/jsx-runtime");
9330
9390
  function KjunChip({ label, icon, removable = false, disabled = false, size = "md", removeLabel, onRemove }) {
9331
9391
  const { colors } = useKjunStyles();
9332
9392
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react_native60.View, { style: { alignSelf: "flex-start", maxWidth: "100%", minWidth: 0, flexShrink: 1, flexDirection: "row", alignItems: "center", gap: import_tokens58.tokens.extensions.chip.gap, minHeight: removable ? import_tokens58.tokens.extensions.chip.nativeRemoveSize : import_tokens58.tokens.extensions.chip[size], paddingVertical: removable ? 0 : import_tokens58.tokens.extensions.chip.paddingY, paddingLeft: import_tokens58.tokens.extensions.chip.paddingX, paddingRight: removable ? 0 : import_tokens58.tokens.extensions.chip.paddingX, borderRadius: import_tokens58.tokens.extensions.chip.radius, backgroundColor: colors.secondary, opacity: disabled ? import_tokens58.tokens.states.opacity.disabled : 1 }, children: [
9333
- icon && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KjunIcon, { name: icon, size: import_tokens58.tokens.extensions.chip.iconSizes[size] }),
9393
+ !!icon && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KjunIcon, { name: icon, size: import_tokens58.tokens.extensions.chip.iconSizes[size] }),
9334
9394
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KText, { style: { ...typeStyle(import_tokens58.tokens.extensions.chip.typography[size]), flexShrink: 1, minWidth: 0 }, children: label }),
9335
9395
  removable && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AccessiblePressable, { accessibilityRole: "button", accessibilityLabel: removeLabel || label + " \uC0AD\uC81C", disabled, accessibilityState: { disabled }, onPress: onRemove, style: { width: import_tokens58.tokens.extensions.chip.nativeRemoveSize, height: import_tokens58.tokens.extensions.chip.nativeRemoveSize, borderRadius: import_tokens58.tokens.extensions.chip.radius, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KjunIcon, { name: "x", size: import_tokens58.tokens.extensions.chip.removeIconSizes[size] }) })
9336
9396
  ] });
@@ -9458,7 +9518,7 @@ function RangeInput({
9458
9518
  minWidth: 0
9459
9519
  },
9460
9520
  children: [
9461
- label && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9521
+ !!label && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9462
9522
  KText,
9463
9523
  {
9464
9524
  style: {
@@ -9819,6 +9879,6 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
9819
9879
  change(null);
9820
9880
  (_a = first.current) == null ? void 0 : _a.focus();
9821
9881
  } }) }),
9822
- (error || !!(field == null ? void 0 : field.error) || focused || opened !== null) && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_native63.View, { pointerEvents: "none", "aria-hidden": true, style: { position: "absolute", inset: 0, borderRadius: spec.radius, borderWidth: error || !!(field == null ? void 0 : field.error) ? import_tokens61.tokens.border.controlWidth : import_tokens61.tokens.states.focus.width, borderColor: error || (field == null ? void 0 : field.error) ? colors.danger : colors.focusRing } })
9882
+ !!(error || !!(field == null ? void 0 : field.error) || focused || opened !== null) && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_native63.View, { pointerEvents: "none", "aria-hidden": true, style: { position: "absolute", inset: 0, borderRadius: spec.radius, borderWidth: error || !!(field == null ? void 0 : field.error) ? import_tokens61.tokens.border.controlWidth : import_tokens61.tokens.states.focus.width, borderColor: error || (field == null ? void 0 : field.error) ? colors.danger : colors.focusRing } })
9823
9883
  ] });
9824
9884
  }