@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.
@@ -996,7 +996,7 @@ function KjunButton(input) {
996
996
  opacity: overlayLoading ? 0 : 1,
997
997
  ...multiline || navigation ? { flexShrink: 1, minWidth: 0, textAlign: "center" } : {}
998
998
  }, children }),
999
- suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native3.View, { style: { opacity: busy && prefixIcon ? 0 : 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
999
+ !!suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native3.View, { style: { opacity: busy && prefixIcon ? 0 : 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1000
1000
  KjunIcon,
1001
1001
  {
1002
1002
  name: busy && !prefixIcon ? "loader-2" : suffixIcon,
@@ -1257,7 +1257,7 @@ function KjunFormGroup({
1257
1257
  describedBy: mergeIds(hint ? fieldId + "-hint" : void 0, error ? fieldId + "-error" : void 0)
1258
1258
  },
1259
1259
  children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: [{ minWidth: 0, marginBottom: import_tokens9.tokens.extensions.form.itemGap }, style], children: [
1260
- label && !labelHidden && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1260
+ !!label && !labelHidden && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1261
1261
  import_react_native8.Text,
1262
1262
  {
1263
1263
  nativeID: fieldId + "-label",
@@ -1349,6 +1349,7 @@ var KjunInput = (0, import_react17.forwardRef)(function KjunInput2({
1349
1349
  const invalid = !!(error || errorMessage || (field == null ? void 0 : field.error));
1350
1350
  const canEdit = !disabled && !readOnly && editable;
1351
1351
  const surface = useFieldSurface(size, { disabled, readOnly: !!readOnly || !editable, invalid, open: props["aria-expanded"] === true });
1352
+ const affixText = { ...inputTypeStyle(size), color: surface.icon };
1352
1353
  const showClear = clearable && !!value;
1353
1354
  const [prefixWidth, setPrefixWidth] = (0, import_react17.useState)(0);
1354
1355
  const [affixWidth, setAffixWidth] = (0, import_react17.useState)(0);
@@ -1410,7 +1411,7 @@ var KjunInput = (0, import_react17.forwardRef)(function KjunInput2({
1410
1411
  ]
1411
1412
  }
1412
1413
  ),
1413
- (prefix || prefixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1414
+ !!(prefix || prefixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1414
1415
  import_react_native8.View,
1415
1416
  {
1416
1417
  onLayout: (event) => setPrefixWidth(event.nativeEvent.layout.width),
@@ -1422,7 +1423,7 @@ var KjunInput = (0, import_react17.forwardRef)(function KjunInput2({
1422
1423
  bottom: 0,
1423
1424
  justifyContent: "center"
1424
1425
  },
1425
- children: prefix || /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1426
+ children: prefix ? content(prefix, affixText) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1426
1427
  KjunIcon,
1427
1428
  {
1428
1429
  name: prefixIcon,
@@ -1432,7 +1433,7 @@ var KjunInput = (0, import_react17.forwardRef)(function KjunInput2({
1432
1433
  )
1433
1434
  }
1434
1435
  ),
1435
- (showClear || suffix || suffixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1436
+ !!(showClear || suffix || suffixIcon) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1436
1437
  import_react_native8.View,
1437
1438
  {
1438
1439
  onLayout: (event) => setAffixWidth(event.nativeEvent.layout.width),
@@ -1453,7 +1454,7 @@ var KjunInput = (0, import_react17.forwardRef)(function KjunInput2({
1453
1454
  onClear == null ? void 0 : onClear();
1454
1455
  (_a = input.current) == null ? void 0 : _a.focus();
1455
1456
  } }),
1456
- suffix || suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1457
+ suffix ? content(suffix, affixText) : !!suffixIcon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1457
1458
  KjunIcon,
1458
1459
  {
1459
1460
  name: suffixIcon,
@@ -1493,6 +1494,17 @@ function KjunFormLayout({
1493
1494
  ) });
1494
1495
  }
1495
1496
 
1497
+ // shared/package-runtime/content-presence.ts
1498
+ var import_react18 = require("react");
1499
+ function hasContent(node) {
1500
+ if (node == null || typeof node === "boolean") return false;
1501
+ if (typeof node === "string") return node.trim().length > 0;
1502
+ if (Array.isArray(node)) return node.some(hasContent);
1503
+ if ((0, import_react18.isValidElement)(node) && node.type === import_react18.Fragment)
1504
+ return hasContent(node.props.children);
1505
+ return true;
1506
+ }
1507
+
1496
1508
  // packages/native/src/layer-backdrop.tsx
1497
1509
  var import_react_native9 = require("react-native");
1498
1510
  var import_jsx_runtime9 = require("react/jsx-runtime");
@@ -1501,7 +1513,7 @@ function LayerBackdrop({ onPress, style }) {
1501
1513
  }
1502
1514
 
1503
1515
  // packages/native/src/modal.tsx
1504
- var import_react20 = require("react");
1516
+ var import_react21 = require("react");
1505
1517
 
1506
1518
  // shared/package-runtime/form-actions.ts
1507
1519
  function formActionsNeedStack(width, widths, gap) {
@@ -1514,17 +1526,17 @@ var import_tokens10 = require("@kjun-ui/tokens");
1514
1526
  var import_react_native13 = require("react-native");
1515
1527
 
1516
1528
  // packages/native/src/overlay-host.tsx
1517
- var import_react19 = require("react");
1529
+ var import_react20 = require("react");
1518
1530
  var import_react_native11 = require("react-native");
1519
1531
 
1520
1532
  // packages/native/src/modal-window.web.tsx
1521
- var import_react18 = require("react");
1533
+ var import_react19 = require("react");
1522
1534
  var import_react_dom = require("react-dom");
1523
1535
  var import_react_native10 = require("react-native");
1524
1536
  var import_jsx_runtime10 = require("react/jsx-runtime");
1525
1537
  function ModalWindow({ generation, children, visible, ...props }) {
1526
- const [container, setContainer] = (0, import_react18.useState)(null);
1527
- (0, import_react18.useLayoutEffect)(() => {
1538
+ const [container, setContainer] = (0, import_react19.useState)(null);
1539
+ (0, import_react19.useLayoutEffect)(() => {
1528
1540
  const element = document.createElement("div");
1529
1541
  element.style.display = "contents";
1530
1542
  setContainer(element);
@@ -1545,17 +1557,17 @@ var import_jsx_runtime11 = (
1545
1557
  // a new window even when an interrupted exit retained the old surface.
1546
1558
  require("react/jsx-runtime")
1547
1559
  );
1548
- var FeedbackOverlayContext = (0, import_react19.createContext)(
1560
+ var FeedbackOverlayContext = (0, import_react20.createContext)(
1549
1561
  null
1550
1562
  );
1551
1563
  function ScopedNativeModal({ children, visible, ...props }) {
1552
1564
  var _a;
1553
- const layers = useLayerState(), scope = (0, import_react19.useContext)(LayerScope);
1565
+ const layers = useLayerState(), scope = (0, import_react20.useContext)(LayerScope);
1554
1566
  const entry = scope ? layers.entries.get(scope) : void 0;
1555
1567
  const generation = (_a = entry == null ? void 0 : entry.order) != null ? _a : 0;
1556
1568
  const inactive = !!scope && !layers.isActive(scope);
1557
- const host = (0, import_react19.useContext)(FeedbackOverlayContext), id = "kjun-" + (0, import_react19.useId)(), register = host == null ? void 0 : host.register;
1558
- (0, import_react19.useEffect)(
1569
+ const host = (0, import_react20.useContext)(FeedbackOverlayContext), id = "kjun-" + (0, import_react20.useId)(), register = host == null ? void 0 : host.register;
1570
+ (0, import_react20.useEffect)(
1559
1571
  () => visible && register ? register(id) : void 0,
1560
1572
  [visible, register, id, generation]
1561
1573
  );
@@ -1601,7 +1613,7 @@ function KjunFormActions({
1601
1613
  onConfirm
1602
1614
  }) {
1603
1615
  const { fontFamily } = useKjunStyles();
1604
- const [width, setWidth] = (0, import_react20.useState)(0), [measurements, setMeasurements] = (0, import_react20.useState)({});
1616
+ const [width, setWidth] = (0, import_react21.useState)(0), [measurements, setMeasurements] = (0, import_react21.useState)({});
1605
1617
  const labels = [showCancel && { text: cancelText }, showConfirm && { text: confirmText }].filter(Boolean);
1606
1618
  const keyFor = (text) => `${fontFamily}:${size}:${text}`;
1607
1619
  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));
@@ -1702,7 +1714,7 @@ function KjunModal({
1702
1714
  const motion = useNativePresence(open, import_tokens10.tokens.motion.layerEnter, import_tokens10.tokens.motion.layerExit, true, 0, { fade: import_tokens10.tokens.motion.backdropExit });
1703
1715
  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);
1704
1716
  const backdrop = useNativePresence(open, import_tokens10.tokens.motion.backdrop, import_tokens10.tokens.motion.backdropExit, true, 0, { fade: import_tokens10.tokens.motion.backdropExit });
1705
- (0, import_react20.useLayoutEffect)(() => {
1717
+ (0, import_react21.useLayoutEffect)(() => {
1706
1718
  if (!motion.present) {
1707
1719
  offset.stopAnimation();
1708
1720
  offset.setValue(import_tokens10.tokens.motionDistance.modalEnter);
@@ -1792,7 +1804,7 @@ function KjunModal({
1792
1804
  borderBottomColor: c.border
1793
1805
  },
1794
1806
  children: [
1795
- /* @__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)(
1807
+ /* @__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)(
1796
1808
  import_react_native13.Text,
1797
1809
  {
1798
1810
  accessibilityRole: "header",
@@ -1832,7 +1844,7 @@ function KjunModal({
1832
1844
  children
1833
1845
  }
1834
1846
  ),
1835
- (showFooter || footer) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1847
+ (showFooter || hasContent(footer)) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1836
1848
  import_react_native13.View,
1837
1849
  {
1838
1850
  style: {
@@ -1845,7 +1857,7 @@ function KjunModal({
1845
1857
  borderTopWidth: import_tokens10.tokens.border.defaultWidth,
1846
1858
  borderTopColor: c.border
1847
1859
  },
1848
- children: footer || /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1860
+ children: hasContent(footer) ? content(footer) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1849
1861
  KjunFormActions,
1850
1862
  {
1851
1863
  size: footerSize,
@@ -1881,19 +1893,6 @@ var import_tokens11 = require("@kjun-ui/tokens");
1881
1893
  var import_react22 = require("react");
1882
1894
  var import_react_native14 = require("react-native");
1883
1895
  var import_react_native_svg2 = __toESM(require("react-native-svg"), 1);
1884
-
1885
- // shared/package-runtime/content-presence.ts
1886
- var import_react21 = require("react");
1887
- function hasContent(node) {
1888
- if (node == null || typeof node === "boolean") return false;
1889
- if (typeof node === "string") return node.trim().length > 0;
1890
- if (Array.isArray(node)) return node.some(hasContent);
1891
- if ((0, import_react21.isValidElement)(node) && node.type === import_react21.Fragment)
1892
- return hasContent(node.props.children);
1893
- return true;
1894
- }
1895
-
1896
- // packages/native/src/card.tsx
1897
1896
  var import_jsx_runtime13 = require("react/jsx-runtime");
1898
1897
  function KjunCard({
1899
1898
  title,
@@ -1954,8 +1953,8 @@ function KjunCard({
1954
1953
  borderBottomColor: borderColor
1955
1954
  }, children: [
1956
1955
  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: [
1957
- title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle"), color: foreground }, children: title }),
1958
- subtitle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { style: { ...typeStyle("caption"), marginTop: import_tokens11.tokens.card.subtitleGap, color: colors[paint.description] }, children: subtitle })
1956
+ !!title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle"), color: foreground }, children: title }),
1957
+ !!subtitle && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(KText, { style: { ...typeStyle("caption"), marginTop: import_tokens11.tokens.card.subtitleGap, color: colors[paint.description] }, children: subtitle })
1959
1958
  ] }) }),
1960
1959
  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 }) }) })
1961
1960
  ] }),
@@ -2068,9 +2067,9 @@ function KjunEmpty({
2068
2067
  paddingVertical: stateContent === "empty" ? 0 : import_tokens12.tokens.dimension.value32
2069
2068
  },
2070
2069
  children: [
2071
- 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 }) }),
2070
+ !!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 }) }),
2072
2071
  /* @__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 }),
2073
- description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2072
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2074
2073
  KText,
2075
2074
  {
2076
2075
  style: {
@@ -2085,7 +2084,7 @@ function KjunEmpty({
2085
2084
  children: description
2086
2085
  }
2087
2086
  ),
2088
- children && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { marginTop: spec.actionGap, maxWidth: "100%" }, children: content(children) })
2087
+ hasContent(children) && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native15.View, { style: { marginTop: spec.actionGap, maxWidth: "100%" }, children: content(children) })
2089
2088
  ]
2090
2089
  }
2091
2090
  );
@@ -2163,7 +2162,7 @@ function KjunSpinner({ size = "md", text }) {
2163
2162
  )
2164
2163
  }
2165
2164
  ),
2166
- text && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KText, { style: { marginLeft: import_tokens12.tokens.dimension.value8, color: colors.textSecondary }, children: text })
2165
+ !!text && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(KText, { style: { marginLeft: import_tokens12.tokens.dimension.value8, color: colors.textSecondary }, children: text })
2167
2166
  ]
2168
2167
  }
2169
2168
  );
@@ -2224,7 +2223,7 @@ function KjunAlert({
2224
2223
  ...typeStyle(small ? "caption" : "body"),
2225
2224
  color: colors.textSecondary
2226
2225
  }) }),
2227
- 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 }) }) })
2226
+ 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) }) }) })
2228
2227
  ] }),
2229
2228
  closable && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2230
2229
  AccessiblePressable,
@@ -2274,7 +2273,7 @@ function KjunProgress({
2274
2273
  const { colors } = useKjunStyles();
2275
2274
  const percentage = Number.isFinite(value) && max > 0 ? Math.min(100, Math.max(0, Math.round(value / max * 100))) : 0;
2276
2275
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native15.View, { children: [
2277
- (label || showLabel) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2276
+ !!(label || showLabel) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2278
2277
  import_react_native15.View,
2279
2278
  {
2280
2279
  style: {
@@ -2689,7 +2688,7 @@ function ToastView({
2689
2688
  children: [
2690
2689
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KjunIcon, { name: icon, color: colors[`${tone}Accent`] }),
2691
2690
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native17.View, { style: { flex: 1, minWidth: 0 }, children: [
2692
- toast.title && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KText, { style: { fontWeight: typeStyle("control").fontWeight, marginBottom: import_tokens15.tokens.extensions.toast.titleGap }, children: toast.title }),
2691
+ !!toast.title && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KText, { style: { fontWeight: typeStyle("control").fontWeight, marginBottom: import_tokens15.tokens.extensions.toast.titleGap }, children: toast.title }),
2693
2692
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KText, { style: { color: colors.textSecondary }, children: toast.message }),
2694
2693
  toast.action && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2695
2694
  AccessiblePressable,
@@ -2934,7 +2933,7 @@ function FeedbackDialog({
2934
2933
  onConfirm: submit,
2935
2934
  confirmVariant: options.type === "danger" ? "danger" : "primary",
2936
2935
  children: [
2937
- options.message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(KText, { style: { marginBottom: import_tokens18.tokens.dimension.value16 }, children: options.message }),
2936
+ !!options.message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(KText, { style: { marginBottom: import_tokens18.tokens.dimension.value16 }, children: options.message }),
2938
2937
  request.kind === "prompt" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2939
2938
  KjunInput,
2940
2939
  {
@@ -2951,7 +2950,7 @@ function FeedbackDialog({
2951
2950
  }
2952
2951
  );
2953
2952
  }
2954
- function KjunFeedbackProvider({ children }) {
2953
+ function KjunFeedbackProvider({ children, style }) {
2955
2954
  const [controller] = (0, import_react31.useState)(import_tokens18.createFeedbackController);
2956
2955
  const life = (0, import_react31.useRef)(0);
2957
2956
  const snapshot = (0, import_react31.useSyncExternalStore)(
@@ -2981,7 +2980,7 @@ function KjunFeedbackProvider({ children }) {
2981
2980
  {
2982
2981
  value: { top: layers[layers.length - 1], register, render: renderToasts },
2983
2982
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(KjunFeedbackContext.Provider, { value: controller.api, children: [
2984
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native19.View, { style: { position: "relative" }, children: [
2983
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native19.View, { style: [{ position: "relative", flexGrow: 1, flexShrink: 1, alignSelf: "stretch" }, style], children: [
2985
2984
  children,
2986
2985
  layers.length === 0 && renderToasts()
2987
2986
  ] }),
@@ -3063,7 +3062,7 @@ function KjunCheckbox({
3063
3062
  )
3064
3063
  }
3065
3064
  ),
3066
- (children || label) && content(children || label, {
3065
+ !!(children || label) && content(children || label, {
3067
3066
  marginLeft: import_tokens19.tokens.extensions.checkbox.labelGap,
3068
3067
  ...typeStyle("label")
3069
3068
  })
@@ -3174,7 +3173,7 @@ function KjunSwitch({
3174
3173
  ]
3175
3174
  }
3176
3175
  ),
3177
- (children || label) && content(children || label, {
3176
+ !!(children || label) && content(children || label, {
3178
3177
  marginLeft: import_tokens19.tokens.extensions.switch.labelGap,
3179
3178
  ...typeStyle("label")
3180
3179
  })
@@ -3251,7 +3250,7 @@ function KjunRadio({
3251
3250
  )
3252
3251
  }
3253
3252
  ),
3254
- (children || label) && content(children || label, {
3253
+ !!(children || label) && content(children || label, {
3255
3254
  marginLeft: geometry2.labelGap,
3256
3255
  ...typeStyle("label")
3257
3256
  })
@@ -3494,7 +3493,7 @@ function KjunButtonGroup({
3494
3493
  opacity: blocked ? import_tokens21.tokens.states.opacity.disabled : 1
3495
3494
  }),
3496
3495
  children: [
3497
- option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3496
+ !!option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3498
3497
  KjunIcon,
3499
3498
  {
3500
3499
  name: option.icon,
@@ -3591,7 +3590,7 @@ function KjunFilterGroup({
3591
3590
  }
3592
3591
  }
3593
3592
  ),
3594
- option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3593
+ !!option.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3595
3594
  KjunIcon,
3596
3595
  {
3597
3596
  name: option.icon,
@@ -3722,8 +3721,50 @@ var KjunTextarea = (0, import_react35.forwardRef)(
3722
3721
  var import_tokens23 = require("@kjun-ui/tokens");
3723
3722
  var import_react36 = require("react");
3724
3723
  var import_react_native25 = require("react-native");
3724
+
3725
+ // shared/package-runtime/drawer-geometry.ts
3726
+ function keyboardEvents(os) {
3727
+ return os === "ios" ? { show: "keyboardWillShow", hide: "keyboardWillHide" } : null;
3728
+ }
3729
+ function keyboardOverlap(windowHeight, keyboardScreenY) {
3730
+ return Math.max(0, windowHeight - keyboardScreenY);
3731
+ }
3732
+ function drawerFrame({ position, windowHeight, safeAreaTop, safeAreaBottom, gap, keyboard, maxHeight }) {
3733
+ const visible = windowHeight - keyboard;
3734
+ const bottomInset = keyboard > 0 ? 0 : safeAreaBottom;
3735
+ if (position === "left" || position === "right")
3736
+ return { maxHeight: visible, height: visible, paddingTop: safeAreaTop, paddingBottom: bottomInset, lift: 0 };
3737
+ const sheet = maxHeight != null ? maxHeight : visible - (position === "bottom" ? safeAreaTop : bottomInset) - gap;
3738
+ return {
3739
+ maxHeight: Math.max(0, Math.min(sheet, visible)),
3740
+ height: void 0,
3741
+ paddingTop: position === "top" ? safeAreaTop : 0,
3742
+ paddingBottom: position === "bottom" ? bottomInset : 0,
3743
+ lift: position === "bottom" ? keyboard : 0
3744
+ };
3745
+ }
3746
+
3747
+ // packages/native/src/drawer.tsx
3725
3748
  var import_react_native26 = require("react-native");
3726
3749
  var import_jsx_runtime23 = require("react/jsx-runtime");
3750
+ function useKeyboardOverlap(enabled2, windowHeight) {
3751
+ const [overlap, setOverlap] = (0, import_react36.useState)(0);
3752
+ (0, import_react36.useEffect)(() => {
3753
+ var _a, _b;
3754
+ setOverlap(0);
3755
+ const events = keyboardEvents(import_react_native26.Platform.OS);
3756
+ if (!enabled2 || !events) return;
3757
+ const metrics = (_b = (_a = import_react_native25.Keyboard).metrics) == null ? void 0 : _b.call(_a);
3758
+ if (metrics) setOverlap(keyboardOverlap(windowHeight, metrics.screenY));
3759
+ const show = import_react_native25.Keyboard.addListener(events.show, (event) => setOverlap(keyboardOverlap(windowHeight, event.endCoordinates.screenY)));
3760
+ const hide = import_react_native25.Keyboard.addListener(events.hide, () => setOverlap(0));
3761
+ return () => {
3762
+ show.remove();
3763
+ hide.remove();
3764
+ };
3765
+ }, [enabled2, windowHeight]);
3766
+ return overlap;
3767
+ }
3727
3768
  function KjunDrawer({
3728
3769
  open,
3729
3770
  onOpenChange,
@@ -3738,9 +3779,24 @@ function KjunDrawer({
3738
3779
  footer,
3739
3780
  children,
3740
3781
  onClose,
3741
- ariaLabel
3782
+ ariaLabel,
3783
+ safeAreaTop = 0,
3784
+ safeAreaBottom = 0,
3785
+ maxHeight,
3786
+ avoidKeyboard = true
3742
3787
  }) {
3743
3788
  const { colors } = useKjunStyles(), window2 = (0, import_react_native26.useWindowDimensions)(), vertical = position === "left" || position === "right";
3789
+ const [rootHeight, setRootHeight] = (0, import_react36.useState)(0);
3790
+ const keyboard = useKeyboardOverlap(open && avoidKeyboard, window2.height);
3791
+ const frame = drawerFrame({
3792
+ position,
3793
+ windowHeight: rootHeight || window2.height,
3794
+ safeAreaTop: Math.max(0, safeAreaTop),
3795
+ safeAreaBottom: Math.max(0, safeAreaBottom),
3796
+ gap: import_tokens23.tokens.extensions.drawer.sheetGap,
3797
+ keyboard,
3798
+ maxHeight
3799
+ });
3744
3800
  const [panelHeight, setPanelHeight] = (0, import_react36.useState)(0);
3745
3801
  const motion = useNativePresence(open, import_tokens23.tokens.motion.layerEnter, import_tokens23.tokens.motion.layerExit, vertical || panelHeight > 0, 0, { enterEasing: motionEmphasized });
3746
3802
  const backdrop = useNativePresence(open, import_tokens23.tokens.motion.backdrop, import_tokens23.tokens.motion.backdropExit, true, 0, { fade: import_tokens23.tokens.motion.backdropExit });
@@ -3764,6 +3820,7 @@ function KjunDrawer({
3764
3820
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3765
3821
  import_react_native26.View,
3766
3822
  {
3823
+ onLayout: (event) => setRootHeight(event.nativeEvent.layout.height),
3767
3824
  style: {
3768
3825
  flex: 1,
3769
3826
  justifyContent: position === "bottom" ? "flex-end" : "flex-start",
@@ -3802,8 +3859,11 @@ function KjunDrawer({
3802
3859
  opacity: vertical || panelHeight > 0 ? 1 : 0,
3803
3860
  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] }) }],
3804
3861
  width: vertical ? Math.min(width, window2.width) : window2.width,
3805
- height: vertical ? window2.height : void 0,
3806
- maxHeight: window2.height,
3862
+ height: frame.height,
3863
+ maxHeight: frame.maxHeight,
3864
+ paddingTop: frame.paddingTop,
3865
+ paddingBottom: frame.paddingBottom,
3866
+ marginBottom: frame.lift,
3807
3867
  borderRadius: import_tokens23.tokens.extensions.drawer.radius,
3808
3868
  borderTopLeftRadius: position === "bottom" ? import_tokens23.tokens.extensions.drawer.bottomRadius : import_tokens23.tokens.extensions.drawer.radius,
3809
3869
  borderTopRightRadius: position === "bottom" ? import_tokens23.tokens.extensions.drawer.bottomRadius : import_tokens23.tokens.extensions.drawer.radius,
@@ -3811,7 +3871,7 @@ function KjunDrawer({
3811
3871
  backgroundColor: colors.surface
3812
3872
  },
3813
3873
  children: [
3814
- (title || header || closable) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3874
+ !!(title || header || closable) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3815
3875
  import_react_native26.View,
3816
3876
  {
3817
3877
  style: {
@@ -3824,7 +3884,7 @@ function KjunDrawer({
3824
3884
  borderBottomColor: colors.border
3825
3885
  },
3826
3886
  children: [
3827
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native26.View, { style: { flex: 1 }, children: header || /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3887
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native26.View, { style: { flex: 1 }, children: hasContent(header) ? content(header) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3828
3888
  KText,
3829
3889
  {
3830
3890
  style: { ...typeStyle("sectionTitle") },
@@ -3849,12 +3909,12 @@ function KjunDrawer({
3849
3909
  import_react_native26.ScrollView,
3850
3910
  {
3851
3911
  keyboardShouldPersistTaps: "handled",
3852
- style: vertical ? { flex: 1 } : { flexGrow: 0 },
3912
+ style: vertical ? { flex: 1 } : { flexGrow: 0, flexShrink: 1 },
3853
3913
  contentContainerStyle: { padding: noPadding ? 0 : import_tokens23.tokens.extensions.drawer.bodyPadding },
3854
3914
  children: content(children)
3855
3915
  }
3856
3916
  ),
3857
- footer && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3917
+ hasContent(footer) && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3858
3918
  import_react_native26.View,
3859
3919
  {
3860
3920
  style: {
@@ -4112,7 +4172,7 @@ function FloatingPanel({
4112
4172
  borderBottomWidth: import_tokens24.tokens.border.defaultWidth,
4113
4173
  borderBottomColor: colors.divider
4114
4174
  },
4115
- children: header
4175
+ children: content(header, typeStyle("cardTitle"))
4116
4176
  }
4117
4177
  ),
4118
4178
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
@@ -5833,7 +5893,7 @@ function KjunTabs({
5833
5893
  opacity: tab.disabled ? import_tokens33.tokens.states.opacity.disabled : 1
5834
5894
  },
5835
5895
  children: [
5836
- tab.icon && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
5896
+ !!tab.icon && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
5837
5897
  KjunIcon,
5838
5898
  {
5839
5899
  name: tab.icon,
@@ -5878,11 +5938,11 @@ function KjunTabs({
5878
5938
  tab.name
5879
5939
  );
5880
5940
  }),
5881
- actions
5941
+ content(actions)
5882
5942
  ]
5883
5943
  }
5884
5944
  ),
5885
- children && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native37.View, { style: { marginTop: geometry2.contentGap }, children })
5945
+ hasContent(children) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react_native37.View, { style: { marginTop: geometry2.contentGap }, children: content(children) })
5886
5946
  ] }) });
5887
5947
  }
5888
5948
  function KjunTabPane({ name, children }) {
@@ -6010,7 +6070,7 @@ function KjunBreadcrumb({
6010
6070
  },
6011
6071
  children: items.map((item, i) => {
6012
6072
  const label = /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react_native38.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens34.tokens.dimension.value4 }, children: [
6013
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(KjunIcon, { name: item.icon, size: import_tokens34.tokens.extensions.breadcrumb.iconSize, color: colors.textSecondary }),
6073
+ !!item.icon && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(KjunIcon, { name: item.icon, size: import_tokens34.tokens.extensions.breadcrumb.iconSize, color: colors.textSecondary }),
6014
6074
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6015
6075
  KText,
6016
6076
  {
@@ -6326,7 +6386,7 @@ function KjunCopyButton({
6326
6386
  color: copied ? colors.success : colors.textSecondary
6327
6387
  }
6328
6388
  ),
6329
- text && !inline && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6389
+ !!text && !inline && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6330
6390
  KText,
6331
6391
  {
6332
6392
  style: {
@@ -6514,7 +6574,7 @@ function KjunDataState({
6514
6574
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KText, { style: { ...typeStyle("body"), color: colors.textSecondary, textAlign: "center", maxWidth: "100%" }, children: loadingText })
6515
6575
  ] }))
6516
6576
  }
6517
- ) : 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,
6577
+ ) : 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,
6518
6578
  (!concealed || preserveContent && state.hasQueryResult) && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6519
6579
  import_react_native40.View,
6520
6580
  {
@@ -6987,12 +7047,12 @@ function KjunAnimatedNumber({
6987
7047
  style
6988
7048
  ],
6989
7049
  children: [
6990
- prefix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
7050
+ !!prefix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
6991
7051
  prefix,
6992
7052
  " "
6993
7053
  ] }),
6994
7054
  typeof n === "string" ? n : formatter ? formatter(n) : format(n, decimals),
6995
- suffix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
7055
+ !!suffix && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.Text, { style: typeStyle("caption"), children: [
6996
7056
  " ",
6997
7057
  suffix
6998
7058
  ] })
@@ -7875,7 +7935,7 @@ function TableCards({
7875
7935
  },
7876
7936
  children: [
7877
7937
  selectable && checkbox(row, i),
7878
- title && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flex: 1, minWidth: 0 }, children: cell(title, row, i, "title") })
7938
+ !!title && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flex: 1, minWidth: 0 }, children: cell(title, row, i, "title") })
7879
7939
  ]
7880
7940
  }
7881
7941
  ),
@@ -7896,7 +7956,7 @@ function TableCards({
7896
7956
  marginTop: index ? import_tokens47.tokens.dimension.value12 : 0
7897
7957
  },
7898
7958
  children: [
7899
- section.label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7959
+ !!section.label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7900
7960
  KText,
7901
7961
  {
7902
7962
  style: {
@@ -7961,7 +8021,7 @@ function TableCards({
7961
8021
  children: content(renderExpand == null ? void 0 : renderExpand(row, i))
7962
8022
  }
7963
8023
  ),
7964
- actions && !actions.inlineInCard && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8024
+ !!actions && !actions.inlineInCard && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7965
8025
  import_react_native47.View,
7966
8026
  {
7967
8027
  style: {
@@ -8250,7 +8310,7 @@ function KjunKpiHero(props) {
8250
8310
  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: [
8251
8311
  deltaAbsolute !== null && delta(deltaAbsolute, "absolute", { ...numeric, color: direction(deltaAbsolute), ...typeStyle("numberMd") }),
8252
8312
  deltaPercent !== null && delta(deltaPercent, "percent", { ...numeric, color: direction(deltaPercent), ...typeStyle("numberMd"), opacity: 0.9 }),
8253
- deltaDescription && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8313
+ !!deltaDescription && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8254
8314
  KText,
8255
8315
  {
8256
8316
  style: {
@@ -8264,7 +8324,7 @@ function KjunKpiHero(props) {
8264
8324
  }
8265
8325
  )
8266
8326
  ] }),
8267
- aside && !mobile && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native50.View, { children: aside })
8327
+ hasContent(aside) && !mobile && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react_native50.View, { children: content(aside) })
8268
8328
  ]
8269
8329
  }
8270
8330
  ),
@@ -8326,7 +8386,7 @@ function KjunKpiHero(props) {
8326
8386
  children: kpiFormat(item)
8327
8387
  }
8328
8388
  ),
8329
- item.desc && (loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8389
+ !!item.desc && (loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8330
8390
  KjunSkeleton,
8331
8391
  {
8332
8392
  type: "block",
@@ -8533,7 +8593,7 @@ function KjunKpiRow({
8533
8593
  {
8534
8594
  style: [valueStyle, { flexShrink: 1, minWidth: 0 }],
8535
8595
  children: [
8536
- item.prefix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8596
+ !!item.prefix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8537
8597
  import_react_native51.Text,
8538
8598
  {
8539
8599
  style: {
@@ -8551,7 +8611,7 @@ function KjunKpiRow({
8551
8611
  style: [valueStyle, { flexShrink: 1, minWidth: 0 }]
8552
8612
  }
8553
8613
  ) : kpiFormat(item),
8554
- item.suffix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8614
+ !!item.suffix && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
8555
8615
  import_react_native51.Text,
8556
8616
  {
8557
8617
  style: {
@@ -8567,7 +8627,7 @@ function KjunKpiRow({
8567
8627
  ]
8568
8628
  }
8569
8629
  ),
8570
- 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)(
8630
+ !!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)(
8571
8631
  KText,
8572
8632
  {
8573
8633
  style: {
@@ -9413,26 +9473,26 @@ var LastListRow = (0, import_react66.createContext)(false);
9413
9473
  function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, onPress }) {
9414
9474
  const { colors } = useKjunStyles(), last = (0, import_react66.useContext)(LastListRow);
9415
9475
  const parts = /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
9416
- leading && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { children: content(leading) }),
9476
+ hasContent(leading) && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { children: content(leading) }),
9417
9477
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flex: 1, minWidth: 0 }, children: [
9418
9478
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { ...typeStyle("label") }, children: title }),
9419
- description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens56.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9479
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens56.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9420
9480
  ] }),
9421
- trailing && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { style: { maxWidth: "35%" }, children: content(trailing) })
9481
+ hasContent(trailing) && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { style: { maxWidth: "35%" }, children: content(trailing) })
9422
9482
  ] });
9423
9483
  const style = { flex: 1, minWidth: 0, minHeight: import_tokens56.tokens.extensions.list.minimumHeight, flexDirection: "row", alignItems: "center", gap: import_tokens56.tokens.extensions.list.gap, padding: import_tokens56.tokens.extensions.list.padding };
9424
9484
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { role: "listitem", style: { flexDirection: "row", alignItems: "center", gap: import_tokens56.tokens.extensions.list.gap, borderBottomWidth: last ? 0 : import_tokens56.tokens.border.defaultWidth, borderBottomColor: colors.divider }, children: [
9425
9485
  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_tokens56.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 }),
9426
- 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_tokens56.tokens.extensions.list.actionsGap, paddingRight: import_tokens56.tokens.extensions.list.actionsPadding, opacity: disabled ? import_tokens56.tokens.states.opacity.disabled : 1 }, children: content(actions) })
9486
+ 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_tokens56.tokens.extensions.list.actionsGap, paddingRight: import_tokens56.tokens.extensions.list.actionsPadding, opacity: disabled ? import_tokens56.tokens.states.opacity.disabled : 1 }, children: content(actions) })
9427
9487
  ] });
9428
9488
  }
9429
9489
  function KjunListSection({ title, description, actions, children, ariaLabel }) {
9430
9490
  const { colors } = useKjunStyles();
9431
9491
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { minWidth: 0, backgroundColor: colors.surface }, children: [
9432
- (title || description || actions) && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens56.tokens.extensions.list.gap, padding: import_tokens56.tokens.extensions.list.padding }, children: [
9492
+ !!(title || description || actions) && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens56.tokens.extensions.list.gap, padding: import_tokens56.tokens.extensions.list.padding }, children: [
9433
9493
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flex: 1 }, children: [
9434
- title && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle") }, children: title }),
9435
- description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens56.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9494
+ !!title && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { accessibilityRole: "header", style: { ...typeStyle("cardTitle") }, children: title }),
9495
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(KText, { style: { marginTop: import_tokens56.tokens.extensions.list.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9436
9496
  ] }),
9437
9497
  content(actions)
9438
9498
  ] }),
@@ -9460,12 +9520,12 @@ function KjunTopNavigation({ title, description, leading, actions, safeAreaTop =
9460
9520
  const flatten = (node) => import_react67.Children.toArray(node).flatMap((child) => (0, import_react67.isValidElement)(child) && child.type === import_react67.Fragment ? flatten(child.props.children) : [child]);
9461
9521
  const actionList = flatten(actions);
9462
9522
  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: [
9463
- 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) }) }),
9523
+ 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) }) }),
9464
9524
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { flexGrow: 1, flexShrink: 1, flexBasis: geometry2.titleMinimumWidth, minWidth: 0, paddingVertical: titleInset }, children: [
9465
9525
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { accessibilityRole: "header", style: { ...wrapping, ...typeStyle("sectionTitle"), fontWeight: typeStyle("control").fontWeight }, children: title }),
9466
- description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...wrapping, marginTop: geometry2.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9526
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...wrapping, marginTop: geometry2.descriptionGap, color: colors.textSecondary, ...typeStyle("caption") }, children: description })
9467
9527
  ] }),
9468
- 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")) }) })
9528
+ 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")) }) })
9469
9529
  ] }) }) });
9470
9530
  }
9471
9531
  function KjunBottomNavigation({ items, value, ariaLabel = "\uC8FC\uC694 \uD0D0\uC0C9", safeAreaBottom = 0, keyboardVisible = false, hideOnKeyboard = true, onNavigate }) {
@@ -9515,7 +9575,7 @@ function KjunBottomNavigation({ items, value, ariaLabel = "\uC8FC\uC694 \uD0D0\u
9515
9575
  },
9516
9576
  children: [
9517
9577
  hasIcons && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { width: geometry2.iconSize, height: geometry2.iconSize, flexShrink: 0 }, children: [
9518
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KjunIcon, { name: item.icon, size: geometry2.iconSize, color: ink }),
9578
+ !!item.icon && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KjunIcon, { name: item.icon, size: geometry2.iconSize, color: ink }),
9519
9579
  badge
9520
9580
  ] }),
9521
9581
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_react_native58.View, { style: { maxWidth: "100%" }, children: [
@@ -9547,7 +9607,7 @@ function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboa
9547
9607
  flexDirection: wide ? "row" : "column",
9548
9608
  alignItems: wide ? "center" : "stretch"
9549
9609
  }, children: [
9550
- description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...typeStyle("body"), ...wrapping, color: colors.textSecondary, flex: wide ? 1 : void 0, minWidth: 0 }, children: description }),
9610
+ !!description && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(KText, { style: { ...typeStyle("body"), ...wrapping, color: colors.textSecondary, flex: wide ? 1 : void 0, minWidth: 0 }, children: description }),
9551
9611
  /* @__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) })
9552
9612
  ] }) });
9553
9613
  }
@@ -9585,7 +9645,7 @@ var import_jsx_runtime57 = require("react/jsx-runtime");
9585
9645
  function KjunChip({ label, icon, removable = false, disabled = false, size = "md", removeLabel, onRemove }) {
9586
9646
  const { colors } = useKjunStyles();
9587
9647
  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_tokens59.tokens.extensions.chip.gap, minHeight: removable ? import_tokens59.tokens.extensions.chip.nativeRemoveSize : import_tokens59.tokens.extensions.chip[size], paddingVertical: removable ? 0 : import_tokens59.tokens.extensions.chip.paddingY, paddingLeft: import_tokens59.tokens.extensions.chip.paddingX, paddingRight: removable ? 0 : import_tokens59.tokens.extensions.chip.paddingX, borderRadius: import_tokens59.tokens.extensions.chip.radius, backgroundColor: colors.secondary, opacity: disabled ? import_tokens59.tokens.states.opacity.disabled : 1 }, children: [
9588
- icon && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KjunIcon, { name: icon, size: import_tokens59.tokens.extensions.chip.iconSizes[size] }),
9648
+ !!icon && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KjunIcon, { name: icon, size: import_tokens59.tokens.extensions.chip.iconSizes[size] }),
9589
9649
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KText, { style: { ...typeStyle(import_tokens59.tokens.extensions.chip.typography[size]), flexShrink: 1, minWidth: 0 }, children: label }),
9590
9650
  removable && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AccessiblePressable, { accessibilityRole: "button", accessibilityLabel: removeLabel || label + " \uC0AD\uC81C", disabled, accessibilityState: { disabled }, onPress: onRemove, style: { width: import_tokens59.tokens.extensions.chip.nativeRemoveSize, height: import_tokens59.tokens.extensions.chip.nativeRemoveSize, borderRadius: import_tokens59.tokens.extensions.chip.radius, alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(KjunIcon, { name: "x", size: import_tokens59.tokens.extensions.chip.removeIconSizes[size] }) })
9591
9651
  ] });
@@ -9713,7 +9773,7 @@ function RangeInput({
9713
9773
  minWidth: 0
9714
9774
  },
9715
9775
  children: [
9716
- label && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9776
+ !!label && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
9717
9777
  KText,
9718
9778
  {
9719
9779
  style: {
@@ -10074,6 +10134,6 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
10074
10134
  change(null);
10075
10135
  (_a = first.current) == null ? void 0 : _a.focus();
10076
10136
  } }) }),
10077
- (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_tokens62.tokens.border.controlWidth : import_tokens62.tokens.states.focus.width, borderColor: error || (field == null ? void 0 : field.error) ? colors.danger : colors.focusRing } })
10137
+ !!(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_tokens62.tokens.border.controlWidth : import_tokens62.tokens.states.focus.width, borderColor: error || (field == null ? void 0 : field.error) ? colors.danger : colors.focusRing } })
10078
10138
  ] });
10079
10139
  }