@kjun-ui/native 0.6.1 → 0.7.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
@@ -6082,12 +6082,27 @@ function KjunScrollFade({ children }) {
6082
6082
 
6083
6083
  // packages/native/src/data-state.tsx
6084
6084
  var import_tokens35 = require("@kjun-ui/tokens");
6085
- var import_react50 = require("react");
6085
+ var import_react51 = require("react");
6086
6086
  var import_react_native40 = require("react-native");
6087
+
6088
+ // shared/package-runtime/use-loading-reveal.ts
6089
+ var import_react50 = require("react");
6090
+ function useLoadingReveal(active, delay = 0) {
6091
+ const [revealed, setRevealed] = (0, import_react50.useState)(false);
6092
+ (0, import_react50.useEffect)(() => {
6093
+ setRevealed(false);
6094
+ if (!active || delay <= 0) return;
6095
+ const timer = setTimeout(() => setRevealed(true), delay);
6096
+ return () => clearTimeout(timer);
6097
+ }, [active, delay]);
6098
+ return delay <= 0 || revealed;
6099
+ }
6100
+
6101
+ // packages/native/src/data-state.tsx
6087
6102
  var import_jsx_runtime37 = require("react/jsx-runtime");
6088
6103
  function useQueryDisplay(props) {
6089
6104
  var _a;
6090
- const [state, setState] = (0, import_react50.useState)(() => (0, import_tokens35.initialQueryDisplay)(props));
6105
+ const [state, setState] = (0, import_react51.useState)(() => (0, import_tokens35.initialQueryDisplay)(props));
6091
6106
  let next = state;
6092
6107
  if (state.queryKey !== ((_a = props.queryKey) != null ? _a : null) || state.resultKey !== props.resultKey || state.loading !== !!props.loading) {
6093
6108
  next = (0, import_tokens35.advanceQueryDisplay)(state, props);
@@ -6106,6 +6121,7 @@ function KjunDataState({
6106
6121
  emptyIcon,
6107
6122
  emptyActionText,
6108
6123
  loadingText = "\uB85C\uB529 \uC911...",
6124
+ loadingDelay = 0,
6109
6125
  retryText = "\uB2E4\uC2DC \uC2DC\uB3C4",
6110
6126
  size = "md",
6111
6127
  skeleton = false,
@@ -6119,7 +6135,7 @@ function KjunDataState({
6119
6135
  onEmptyAction,
6120
6136
  ...query
6121
6137
  }) {
6122
- const state = useQueryDisplay(query), blockingError = query.error && !(state.usesQueryState && state.hasCurrentResult), visibleRefreshError = refreshError || (state.usesQueryState && state.hasCurrentResult ? query.error : null), concealed = state.initialLoading || !!blockingError || empty, padding = import_tokens35.tokens.extensions.state.padding[size];
6138
+ const state = useQueryDisplay(query), blockingError = query.error && !(state.usesQueryState && state.hasCurrentResult), visibleRefreshError = refreshError || (state.usesQueryState && state.hasCurrentResult ? query.error : null), concealed = state.initialLoading || !!blockingError || empty, padding = import_tokens35.tokens.extensions.state.padding[size], revealed = useLoadingReveal(state.initialLoading, loadingDelay);
6123
6139
  const { colors } = useKjunStyles();
6124
6140
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
6125
6141
  import_react_native40.View,
@@ -6152,8 +6168,10 @@ function KjunDataState({
6152
6168
  state.initialLoading ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6153
6169
  import_react_native40.View,
6154
6170
  {
6155
- accessibilityLabel: loadingText,
6156
- style: { paddingVertical: loadingPadding === "none" ? 0 : padding },
6171
+ accessibilityLabel: revealed ? loadingText : void 0,
6172
+ "aria-hidden": revealed ? void 0 : true,
6173
+ importantForAccessibility: revealed ? void 0 : "no-hide-descendants",
6174
+ style: { paddingVertical: loadingPadding === "none" ? 0 : padding, opacity: revealed ? void 0 : 0 },
6157
6175
  children: loadingContent || (skeleton ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react_native40.View, { style: { gap: import_tokens35.tokens.dimension.value12 }, children: Array.from({ length: skeletonCount }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunSkeleton, { type: skeletonType }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react_native40.View, { style: { alignItems: "center", gap: import_tokens35.tokens.dimension.value12 }, children: [
6158
6176
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KjunSpinner, { size: "md" }),
6159
6177
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KText, { style: { ...typeStyle("body"), color: colors.textSecondary, textAlign: "center", maxWidth: "100%" }, children: loadingText })
@@ -6187,7 +6205,7 @@ function BoundaryDescription() {
6187
6205
  const { colors } = useKjunStyles();
6188
6206
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KText, { style: { ...typeStyle({ ...import_tokens35.tokens.typography.caption, fontSizePx: import_tokens35.tokens.extensions.state.descriptionSize }), color: colors.textSecondary, textAlign: "center" }, children: "\uB2E4\uC2DC \uC2DC\uB3C4\uD558\uBA74 \uBB38\uC81C\uAC00 \uD574\uACB0\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4." });
6189
6207
  }
6190
- var KjunErrorBoundary = class extends import_react50.Component {
6208
+ var KjunErrorBoundary = class extends import_react51.Component {
6191
6209
  constructor() {
6192
6210
  super(...arguments);
6193
6211
  this.state = { error: false };
@@ -6234,7 +6252,7 @@ var KjunErrorBoundary = class extends import_react50.Component {
6234
6252
 
6235
6253
  // packages/native/src/skeletons.tsx
6236
6254
  var import_tokens39 = require("@kjun-ui/tokens");
6237
- var import_react52 = require("react");
6255
+ var import_react53 = require("react");
6238
6256
  var import_react_native42 = require("react-native");
6239
6257
  var import_react_native_svg5 = __toESM(require("react-native-svg"), 1);
6240
6258
 
@@ -6263,9 +6281,9 @@ function nativeMarketLayout(columns, showActions, containerWidth) {
6263
6281
 
6264
6282
  // packages/native/src/market-layout.ts
6265
6283
  var import_tokens37 = require("@kjun-ui/tokens");
6266
- var import_react51 = require("react");
6284
+ var import_react52 = require("react");
6267
6285
  function useMarketLayout(columns, showActions) {
6268
- const [containerWidth, setContainerWidth] = (0, import_react51.useState)(0);
6286
+ const [containerWidth, setContainerWidth] = (0, import_react52.useState)(0);
6269
6287
  const onLayout = (event) => setContainerWidth(event.nativeEvent.layout.width);
6270
6288
  return { ...nativeMarketLayout(columns, showActions, containerWidth), onLayout };
6271
6289
  }
@@ -6400,8 +6418,8 @@ function KjunChartSkeleton({
6400
6418
  kind = "line",
6401
6419
  height = import_tokens39.tokens.extensions.chartSkeleton.height
6402
6420
  }) {
6403
- const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = (0, import_react52.useRef)(new import_react_native42.Animated.Value(1)).current;
6404
- (0, import_react52.useEffect)(() => {
6421
+ const { colors } = useKjunStyles(), reduced = useReducedMotion(), opacity = (0, import_react53.useRef)(new import_react_native42.Animated.Value(1)).current;
6422
+ (0, import_react53.useEffect)(() => {
6405
6423
  if (reduced) return;
6406
6424
  const loop = import_react_native42.Animated.loop(
6407
6425
  import_react_native42.Animated.sequence([
@@ -6481,7 +6499,7 @@ function KjunChartSkeleton({
6481
6499
  opacity: (row + col + 2) % 3 === 0 ? 0.55 : 1
6482
6500
  },
6483
6501
  col
6484
- )) }, row)) : (kind === "bar" || kind === "candle") && [60, 100, 85, 140, 110, 165, 180].map((h, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react52.Fragment, { children: [
6502
+ )) }, row)) : (kind === "bar" || kind === "candle") && [60, 100, 85, 140, 110, 165, 180].map((h, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react53.Fragment, { children: [
6485
6503
  kind === "candle" && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6486
6504
  import_react_native_svg5.Path,
6487
6505
  {
@@ -6514,7 +6532,7 @@ function KjunChartSkeleton({
6514
6532
 
6515
6533
  // packages/native/src/financial-display.tsx
6516
6534
  var import_tokens42 = require("@kjun-ui/tokens");
6517
- var import_react55 = require("react");
6535
+ var import_react56 = require("react");
6518
6536
  var import_react_native44 = require("react-native");
6519
6537
  var import_react_native_svg6 = __toESM(require("react-native-svg"), 1);
6520
6538
 
@@ -6522,7 +6540,7 @@ var import_react_native_svg6 = __toESM(require("react-native-svg"), 1);
6522
6540
  var import_tokens41 = require("@kjun-ui/tokens");
6523
6541
 
6524
6542
  // shared/package-runtime/use-number-motion.ts
6525
- var import_react53 = require("react");
6543
+ var import_react54 = require("react");
6526
6544
 
6527
6545
  // shared/package-runtime/number-motion.ts
6528
6546
  var import_tokens40 = require("@kjun-ui/tokens");
@@ -6568,14 +6586,14 @@ function createNumberMotion(apply) {
6568
6586
 
6569
6587
  // shared/package-runtime/use-number-motion.ts
6570
6588
  function useNumberMotion(value, animated, fromPrevious, reduced) {
6571
- const [display, setDisplay] = (0, import_react53.useState)(typeof value === "string" || fromPrevious || !animated || reduced ? value : 0);
6572
- const motion = (0, import_react53.useRef)(null);
6589
+ const [display, setDisplay] = (0, import_react54.useState)(typeof value === "string" || fromPrevious || !animated || reduced ? value : 0);
6590
+ const motion = (0, import_react54.useRef)(null);
6573
6591
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
6574
- (0, import_react53.useLayoutEffect)(() => {
6592
+ (0, import_react54.useLayoutEffect)(() => {
6575
6593
  if (!motion.current) motion.current = createNumberMotion(setDisplay);
6576
6594
  motion.current.update(value, animated, fromPrevious, reduced);
6577
6595
  }, [value, animated, fromPrevious, reduced]);
6578
- (0, import_react53.useLayoutEffect)(() => () => {
6596
+ (0, import_react54.useLayoutEffect)(() => () => {
6579
6597
  var _a;
6580
6598
  (_a = motion.current) == null ? void 0 : _a.cancel();
6581
6599
  motion.current = null;
@@ -6584,7 +6602,7 @@ function useNumberMotion(value, animated, fromPrevious, reduced) {
6584
6602
  }
6585
6603
 
6586
6604
  // packages/native/src/number-display.tsx
6587
- var import_react54 = require("react");
6605
+ var import_react55 = require("react");
6588
6606
  var import_react_native43 = require("react-native");
6589
6607
 
6590
6608
  // shared/package-runtime/relative-time.ts
@@ -6618,7 +6636,7 @@ var format = (value, decimals = 0) => new Intl.NumberFormat(void 0, {
6618
6636
  function useCountUp(value, animated, fromPrevious) {
6619
6637
  return useNumberMotion(value, animated, fromPrevious, useReducedMotion());
6620
6638
  }
6621
- var MarketQuoteTypeContext = (0, import_react54.createContext)(null);
6639
+ var MarketQuoteTypeContext = (0, import_react55.createContext)(null);
6622
6640
  function KjunAnimatedNumber({
6623
6641
  value,
6624
6642
  decimals = 0,
@@ -6678,7 +6696,7 @@ function KjunPriceCell({
6678
6696
  fetchedAt,
6679
6697
  fromPrevious = true
6680
6698
  }) {
6681
- const { colors } = useKjunStyles(), quoteType = (0, import_react54.useContext)(MarketQuoteTypeContext);
6699
+ const { colors } = useKjunStyles(), quoteType = (0, import_react55.useContext)(MarketQuoteTypeContext);
6682
6700
  return value == null ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(KjunSkeleton, { type: "block", height: import_tokens41.tokens.extensions.financial.priceSkeletonHeight, width: import_tokens41.tokens.extensions.financial.priceSkeletonWidth }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_react_native43.View, { style: { flexDirection: "row", alignItems: "center", gap: import_tokens41.tokens.extensions.financial.affixGap }, children: [
6683
6701
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
6684
6702
  import_react_native43.View,
@@ -6712,7 +6730,7 @@ function KjunSignedValue({
6712
6730
  showFreshness = true,
6713
6731
  formatter
6714
6732
  }) {
6715
- const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), quoteType = (0, import_react54.useContext)(MarketQuoteTypeContext), n = finiteNumber(value), role = n === null || n === 0 ? "priceNeutral" : n > 0 ? "priceUp" : "priceDown", color = loading || n === null ? colors.textSecondary : stale ? colors.textTertiary : domainColor(domainColors, role);
6733
+ const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), quoteType = (0, import_react55.useContext)(MarketQuoteTypeContext), n = finiteNumber(value), role = n === null || n === 0 ? "priceNeutral" : n > 0 ? "priceUp" : "priceDown", color = loading || n === null ? colors.textSecondary : stale ? colors.textTertiary : domainColor(domainColors, role);
6716
6734
  const display = n === null ? "\u2014" : formatter ? formatter(n) : prefix + (showSign && n > 0 ? "+" : "") + format(kind === "percent" && !isRaw ? n * 100 : n, decimals) + (kind === "percent" ? "%" : "") + suffix;
6717
6735
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
6718
6736
  import_react_native43.View,
@@ -6751,6 +6769,7 @@ function KjunSignedValue({
6751
6769
 
6752
6770
  // packages/native/src/financial-display.tsx
6753
6771
  var import_jsx_runtime41 = require("react/jsx-runtime");
6772
+ var deviationFill = { neutral: 1, low: import_tokens42.tokens.states.opacity.deviationLow, medium: import_tokens42.tokens.states.opacity.deviationMedium, strong: import_tokens42.tokens.states.opacity.deviationStrong };
6754
6773
  function KjunDeviation({
6755
6774
  value,
6756
6775
  variant = "pill",
@@ -6761,7 +6780,7 @@ function KjunDeviation({
6761
6780
  const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), n = finiteNumber(value);
6762
6781
  if (n === null)
6763
6782
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(KText, { style: { color: colors.textDisabled }, children: "-" });
6764
- const abs = Math.abs(n), signal = abs >= signalThreshold, neutral = abs < 0.1, color = neutral ? colors.textSecondary : domainColor(domainColors, n > 0 ? "priceUp" : "priceDown"), label = formatter ? formatter(n) : (n > 0 ? "+" : "") + format(n, decimals) + "%";
6783
+ const abs = Math.abs(n), signal = abs >= signalThreshold, level = (0, import_tokens42.deviationLevel)(n), neutral = level === "neutral", color = neutral ? colors.textSecondary : domainColor(domainColors, n > 0 ? "priceUp" : "priceDown"), label = formatter ? formatter(n) : (n > 0 ? "+" : "") + format(n, decimals) + "%";
6765
6784
  if (variant === "badge")
6766
6785
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
6767
6786
  import_react_native44.View,
@@ -6830,7 +6849,7 @@ function KjunDeviation({
6830
6849
  inset: 0,
6831
6850
  borderRadius: import_tokens42.tokens.extensions.financial.cellRadius,
6832
6851
  backgroundColor: neutral ? colors.secondary : color,
6833
- opacity: neutral ? 1 : abs < 0.5 ? 0.08 : abs < 1 ? 0.14 : 0.22
6852
+ opacity: deviationFill[level]
6834
6853
  }
6835
6854
  }
6836
6855
  ),
@@ -6843,7 +6862,7 @@ function KjunDeviation({
6843
6862
  fontVariant: ["tabular-nums"],
6844
6863
  ...typeStyle("body"),
6845
6864
  // Like Web: control weight, stronger once the deviation reaches 1%.
6846
- fontWeight: abs >= 1 ? typeStyle("numberLg").fontWeight : typeStyle("control").fontWeight
6865
+ fontWeight: level === "strong" ? typeStyle("numberLg").fontWeight : typeStyle("control").fontWeight
6847
6866
  },
6848
6867
  children: label
6849
6868
  }
@@ -7005,7 +7024,7 @@ function KjunSparkline({
7005
7024
  stretch = false,
7006
7025
  ariaLabel
7007
7026
  }) {
7008
- const { colors, domainColors } = useKjunStyles(), id = "kjun-" + (0, import_react55.useId)().replace(/:/g, ""), values = data.filter(Number.isFinite), min = Math.min(...values), max = Math.max(...values), range = max - min || 1, points = values.map(
7027
+ const { colors, domainColors } = useKjunStyles(), id = "kjun-" + (0, import_react56.useId)().replace(/:/g, ""), values = data.filter(Number.isFinite), min = Math.min(...values), max = Math.max(...values), range = max - min || 1, points = values.map(
7009
7028
  (v, i) => `${2 + i / Math.max(1, values.length - 1) * (width - 4)},${2 + height - 4 - (v - min) / range * (height - 4)}`
7010
7029
  ).join(" "), change = values.length > 1 ? values[values.length - 1] - values[0] : 0, line = color || (change === 0 ? colors.textTertiary : semantic === "status" ? change > 0 ? colors.success : colors.danger : domainColor(domainColors, change > 0 ? "priceUp" : "priceDown"));
7011
7030
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
@@ -7051,7 +7070,7 @@ function KjunSparkline({
7051
7070
 
7052
7071
  // shared/package-runtime/table.ts
7053
7072
  var import_tokens43 = require("@kjun-ui/tokens");
7054
- var import_react56 = require("react");
7073
+ var import_react57 = require("react");
7055
7074
 
7056
7075
  // shared/package-runtime/table-model.ts
7057
7076
  function getValue(row, key) {
@@ -7095,11 +7114,11 @@ function useTableModel(props) {
7095
7114
  expandSingle = false,
7096
7115
  onExpandedRowsChange
7097
7116
  } = props;
7098
- const [internalSort, setSort] = (0, import_react56.useState)({
7117
+ const [internalSort, setSort] = (0, import_react57.useState)({
7099
7118
  key: "",
7100
7119
  order: "asc"
7101
- }), [internalExpanded, setExpanded] = (0, import_react56.useState)([]), [search, setSearch] = (0, import_react56.useState)(""), timer = (0, import_react56.useRef)(void 0);
7102
- (0, import_react56.useEffect)(() => () => clearTimeout(timer.current), []);
7120
+ }), [internalExpanded, setExpanded] = (0, import_react57.useState)([]), [search, setSearch] = (0, import_react57.useState)(""), timer = (0, import_react57.useRef)(void 0);
7121
+ (0, import_react57.useEffect)(() => () => clearTimeout(timer.current), []);
7103
7122
  const sort = props.sort === void 0 ? internalSort : (_a = props.sort) != null ? _a : { key: "", order: "asc" };
7104
7123
  const rows = sortTableRows(data, sort, { sortable, sortMode });
7105
7124
  const key = (row, index = 0) => tableRowKey(row, rowKey, index);
@@ -7253,19 +7272,19 @@ function TableToolbar({
7253
7272
 
7254
7273
  // packages/native/src/table-grid.tsx
7255
7274
  var import_tokens45 = require("@kjun-ui/tokens");
7256
- var import_react57 = require("react");
7275
+ var import_react58 = require("react");
7257
7276
  var import_react_native_svg7 = __toESM(require("react-native-svg"), 1);
7258
7277
  var import_react_native46 = require("react-native");
7259
7278
  var import_jsx_runtime43 = require("react/jsx-runtime");
7260
- function TableGrid({ initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }) {
7279
+ function TableGrid({ initialLoading, skeletonRows, skeletonHidden, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }) {
7261
7280
  const { colors } = useKjunStyles();
7262
7281
  const geometry2 = import_tokens45.tokens.table;
7263
- const [scroll, setScroll] = (0, import_react57.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-table-fade-" + (0, import_react57.useId)().replace(/[^a-z0-9]/gi, "");
7282
+ const [scroll, setScroll] = (0, import_react58.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-table-fade-" + (0, import_react58.useId)().replace(/[^a-z0-9]/gi, "");
7264
7283
  const cellPadding = geometry2.cellPadding[compact ? "compact" : "regular"];
7265
7284
  const width = (col) => typeof col.width === "number" ? col.width : typeof col.width === "string" && /^\d+(px)?$/.test(col.width) ? parseFloat(col.width) : geometry2.columnWidth;
7266
7285
  const totalWidth = visible.reduce((sum, col) => sum + width(col), 0) + (selectable ? geometry2.actionColumnWidth : 0) + (expandable ? geometry2.actionColumnWidth : 0);
7267
7286
  const fade = totalWidth - scroll.viewport - scroll.x > 1;
7268
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native46.View, { style: { position: "relative", minWidth: 0 }, children: [
7287
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react_native46.View, { style: { position: "relative", minWidth: 0, opacity: skeletonHidden ? 0 : void 0 }, "aria-hidden": skeletonHidden || void 0, children: [
7269
7288
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7270
7289
  import_react_native46.ScrollView,
7271
7290
  {
@@ -7374,7 +7393,7 @@ function TableGrid({ initialLoading, skeletonRows, state, onRowClick, selectable
7374
7393
  ))
7375
7394
  ] }, i)) : !state.rows.length ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_native46.View, { style: { paddingVertical: geometry2.emptyPadding.y, paddingHorizontal: geometry2.emptyPadding.x, alignItems: "center" }, children: content(emptyContent || emptyText, {
7376
7395
  color: colors.textSecondary
7377
- }) }) : state.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react57.Fragment, { children: [
7396
+ }) }) : state.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_react58.Fragment, { children: [
7378
7397
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7379
7398
  AccessiblePressable,
7380
7399
  {
@@ -7463,6 +7482,7 @@ var import_jsx_runtime44 = require("react/jsx-runtime");
7463
7482
  function TableCards({
7464
7483
  initialLoading,
7465
7484
  skeletonRows,
7485
+ skeletonHidden,
7466
7486
  state,
7467
7487
  onRowClick,
7468
7488
  selectable,
@@ -7477,149 +7497,156 @@ function TableCards({
7477
7497
  }) {
7478
7498
  const { colors } = useKjunStyles();
7479
7499
  const { title, subtitle, badges, inline, sections, actions, columnsForSection } = layout;
7480
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react_native47.View, { style: { gap: import_tokens46.tokens.extensions.tableCard.gap, padding: import_tokens46.tokens.extensions.tableCard.listPadding }, children: [
7481
- initialLoading ? Array.from({ length: skeletonRows }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(KjunSkeleton, { type: "card" }, i)) : state.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7482
- AccessiblePressable,
7483
- {
7484
- accessible: false,
7485
- onPress: () => onRowClick == null ? void 0 : onRowClick(row, i),
7486
- style: ({ pressed }) => ({
7487
- padding: import_tokens46.tokens.extensions.tableCard.padding,
7488
- borderWidth: import_tokens46.tokens.border.defaultWidth,
7489
- borderColor: colors.border,
7490
- borderRadius: import_tokens46.tokens.extensions.tableCard.radius,
7491
- backgroundColor: pressed ? colors.hover : colors.background
7492
- }),
7493
- children: [
7494
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7495
- import_react_native47.View,
7496
- {
7497
- style: {
7498
- flexDirection: "row",
7499
- alignItems: "center",
7500
- gap: import_tokens46.tokens.extensions.tableCard.gap,
7501
- marginBottom: import_tokens46.tokens.dimension.value8
7502
- },
7503
- children: [
7504
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7500
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7501
+ import_react_native47.View,
7502
+ {
7503
+ style: { gap: import_tokens46.tokens.extensions.tableCard.gap, padding: import_tokens46.tokens.extensions.tableCard.listPadding, opacity: skeletonHidden ? 0 : void 0 },
7504
+ "aria-hidden": skeletonHidden || void 0,
7505
+ children: [
7506
+ initialLoading ? Array.from({ length: skeletonRows }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(KjunSkeleton, { type: "card" }, i)) : state.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7507
+ AccessiblePressable,
7508
+ {
7509
+ accessible: false,
7510
+ onPress: () => onRowClick == null ? void 0 : onRowClick(row, i),
7511
+ style: ({ pressed }) => ({
7512
+ padding: import_tokens46.tokens.extensions.tableCard.padding,
7513
+ borderWidth: import_tokens46.tokens.border.defaultWidth,
7514
+ borderColor: colors.border,
7515
+ borderRadius: import_tokens46.tokens.extensions.tableCard.radius,
7516
+ backgroundColor: pressed ? colors.hover : colors.background
7517
+ }),
7518
+ children: [
7519
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7520
+ import_react_native47.View,
7521
+ {
7522
+ style: {
7523
+ flexDirection: "row",
7524
+ alignItems: "center",
7525
+ gap: import_tokens46.tokens.extensions.tableCard.gap,
7526
+ marginBottom: import_tokens46.tokens.dimension.value8
7527
+ },
7528
+ children: [
7529
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7530
+ import_react_native47.View,
7531
+ {
7532
+ style: {
7533
+ flexDirection: "row",
7534
+ flex: 1,
7535
+ alignItems: "center",
7536
+ gap: import_tokens46.tokens.extensions.tableCard.gap,
7537
+ minWidth: 0
7538
+ },
7539
+ children: [
7540
+ selectable && checkbox(row, i),
7541
+ title && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flex: 1, minWidth: 0 }, children: cell(title, row, i, "title") })
7542
+ ]
7543
+ }
7544
+ ),
7545
+ badges.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flexDirection: "row", gap: import_tokens46.tokens.extensions.tableCard.fieldGap }, children: badges.map((col) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { children: cell(col, row, i) }, col.key)) }) : subtitle ? cell(subtitle, row, i) : null,
7546
+ inline.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flexDirection: "row", gap: import_tokens46.tokens.extensions.tableCard.fieldGap }, children: inline.map((col) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { children: cell(col, row, i) }, col.key)) })
7547
+ ]
7548
+ }
7549
+ ),
7550
+ sections.map((section, index) => {
7551
+ const cols = columnsForSection(row, section);
7552
+ return cols.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7505
7553
  import_react_native47.View,
7506
7554
  {
7507
7555
  style: {
7508
- flexDirection: "row",
7509
- flex: 1,
7510
- alignItems: "center",
7511
- gap: import_tokens46.tokens.extensions.tableCard.gap,
7512
- minWidth: 0
7556
+ borderTopWidth: index ? import_tokens46.tokens.border.defaultWidth : 0,
7557
+ borderTopColor: colors.border,
7558
+ paddingTop: index ? import_tokens46.tokens.dimension.value12 : 0,
7559
+ marginTop: index ? import_tokens46.tokens.dimension.value12 : 0
7513
7560
  },
7514
7561
  children: [
7515
- selectable && checkbox(row, i),
7516
- title && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flex: 1, minWidth: 0 }, children: cell(title, row, i, "title") })
7517
- ]
7518
- }
7519
- ),
7520
- badges.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flexDirection: "row", gap: import_tokens46.tokens.extensions.tableCard.fieldGap }, children: badges.map((col) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { children: cell(col, row, i) }, col.key)) }) : subtitle ? cell(subtitle, row, i) : null,
7521
- inline.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { flexDirection: "row", gap: import_tokens46.tokens.extensions.tableCard.fieldGap }, children: inline.map((col) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { children: cell(col, row, i) }, col.key)) })
7522
- ]
7523
- }
7524
- ),
7525
- sections.map((section, index) => {
7526
- const cols = columnsForSection(row, section);
7527
- return cols.length ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7528
- import_react_native47.View,
7529
- {
7530
- style: {
7531
- borderTopWidth: index ? import_tokens46.tokens.border.defaultWidth : 0,
7532
- borderTopColor: colors.border,
7533
- paddingTop: index ? import_tokens46.tokens.dimension.value12 : 0,
7534
- marginTop: index ? import_tokens46.tokens.dimension.value12 : 0
7535
- },
7536
- children: [
7537
- section.label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7538
- KText,
7539
- {
7540
- style: {
7541
- ...typeStyle("controlSmall"),
7542
- color: colors.textTertiary,
7543
- marginBottom: import_tokens46.tokens.dimension.value6
7544
- },
7545
- children: section.label
7546
- }
7547
- ),
7548
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7549
- import_react_native47.View,
7550
- {
7551
- style: {
7552
- flexDirection: "row",
7553
- flexWrap: "wrap",
7554
- gap: section.layout === "metrics" ? import_tokens46.tokens.extensions.tableCard.gap : import_tokens46.tokens.extensions.tableCard.metricGap
7555
- },
7556
- children: cols.map((col) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7562
+ section.label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7563
+ KText,
7564
+ {
7565
+ style: {
7566
+ ...typeStyle("controlSmall"),
7567
+ color: colors.textTertiary,
7568
+ marginBottom: import_tokens46.tokens.dimension.value6
7569
+ },
7570
+ children: section.label
7571
+ }
7572
+ ),
7573
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7557
7574
  import_react_native47.View,
7558
7575
  {
7559
7576
  style: {
7560
- flexBasis: col.fullWidthInCard || section.layout === "stack" ? "100%" : section.layout === "metrics" ? "30%" : "47%",
7561
- flexGrow: 1,
7562
- minWidth: 0,
7563
- gap: import_tokens46.tokens.extensions.tableCard.valueGap
7577
+ flexDirection: "row",
7578
+ flexWrap: "wrap",
7579
+ gap: section.layout === "metrics" ? import_tokens46.tokens.extensions.tableCard.gap : import_tokens46.tokens.extensions.tableCard.metricGap
7564
7580
  },
7565
- children: [
7566
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7567
- KText,
7568
- {
7569
- style: {
7570
- ...typeStyle("meta"),
7571
- color: colors.textTertiary,
7572
- textAlign: section.labelAlign
7573
- },
7574
- children: col.label
7575
- }
7576
- ),
7577
- cell(col, row, i)
7578
- ]
7579
- },
7580
- col.key
7581
- ))
7582
- }
7583
- )
7584
- ]
7585
- },
7586
- section.key || index
7587
- ) : null;
7588
- }),
7589
- expandable && expand(row, i),
7590
- expandable && state.expanded.includes(state.key(row, i)) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7591
- import_react_native47.View,
7592
- {
7593
- style: {
7594
- borderTopWidth: import_tokens46.tokens.border.defaultWidth,
7595
- borderTopColor: colors.border,
7596
- paddingTop: import_tokens46.tokens.dimension.value8,
7597
- marginTop: import_tokens46.tokens.dimension.value4
7598
- },
7599
- children: content(renderExpand == null ? void 0 : renderExpand(row, i))
7600
- }
7601
- ),
7602
- actions && !actions.inlineInCard && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7603
- import_react_native47.View,
7604
- {
7605
- style: {
7606
- borderTopWidth: import_tokens46.tokens.border.defaultWidth,
7607
- borderTopColor: colors.border,
7608
- paddingTop: import_tokens46.tokens.dimension.value8,
7609
- marginTop: import_tokens46.tokens.dimension.value8,
7610
- alignItems: "flex-end"
7611
- },
7612
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { alignSelf: "flex-end" }, children: cell(actions, row, i) })
7613
- }
7614
- )
7615
- ]
7616
- },
7617
- state.key(row, i)
7618
- )),
7619
- !initialLoading && !state.rows.length && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { padding: import_tokens46.tokens.extensions.tableCard.emptyPadding, alignItems: "center" }, children: content(emptyContent || emptyText, {
7620
- color: colors.textTertiary
7621
- }) })
7622
- ] });
7581
+ children: cols.map((col) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
7582
+ import_react_native47.View,
7583
+ {
7584
+ style: {
7585
+ flexBasis: col.fullWidthInCard || section.layout === "stack" ? "100%" : section.layout === "metrics" ? "30%" : "47%",
7586
+ flexGrow: 1,
7587
+ minWidth: 0,
7588
+ gap: import_tokens46.tokens.extensions.tableCard.valueGap
7589
+ },
7590
+ children: [
7591
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7592
+ KText,
7593
+ {
7594
+ style: {
7595
+ ...typeStyle("meta"),
7596
+ color: colors.textTertiary,
7597
+ textAlign: section.labelAlign
7598
+ },
7599
+ children: col.label
7600
+ }
7601
+ ),
7602
+ cell(col, row, i)
7603
+ ]
7604
+ },
7605
+ col.key
7606
+ ))
7607
+ }
7608
+ )
7609
+ ]
7610
+ },
7611
+ section.key || index
7612
+ ) : null;
7613
+ }),
7614
+ expandable && expand(row, i),
7615
+ expandable && state.expanded.includes(state.key(row, i)) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7616
+ import_react_native47.View,
7617
+ {
7618
+ style: {
7619
+ borderTopWidth: import_tokens46.tokens.border.defaultWidth,
7620
+ borderTopColor: colors.border,
7621
+ paddingTop: import_tokens46.tokens.dimension.value8,
7622
+ marginTop: import_tokens46.tokens.dimension.value4
7623
+ },
7624
+ children: content(renderExpand == null ? void 0 : renderExpand(row, i))
7625
+ }
7626
+ ),
7627
+ actions && !actions.inlineInCard && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
7628
+ import_react_native47.View,
7629
+ {
7630
+ style: {
7631
+ borderTopWidth: import_tokens46.tokens.border.defaultWidth,
7632
+ borderTopColor: colors.border,
7633
+ paddingTop: import_tokens46.tokens.dimension.value8,
7634
+ marginTop: import_tokens46.tokens.dimension.value8,
7635
+ alignItems: "flex-end"
7636
+ },
7637
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { alignSelf: "flex-end" }, children: cell(actions, row, i) })
7638
+ }
7639
+ )
7640
+ ]
7641
+ },
7642
+ state.key(row, i)
7643
+ )),
7644
+ !initialLoading && !state.rows.length && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_native47.View, { style: { padding: import_tokens46.tokens.extensions.tableCard.emptyPadding, alignItems: "center" }, children: content(emptyContent || emptyText, {
7645
+ color: colors.textTertiary
7646
+ }) })
7647
+ ]
7648
+ }
7649
+ );
7623
7650
  }
7624
7651
 
7625
7652
  // packages/native/src/table-view.tsx
@@ -7627,6 +7654,9 @@ var import_jsx_runtime45 = require("react/jsx-runtime");
7627
7654
  function KjunTable(props) {
7628
7655
  const {
7629
7656
  skeletonRows = 8,
7657
+ skeleton = true,
7658
+ loadingText = "\uB85C\uB529 \uC911...",
7659
+ loadingDelay = 0,
7630
7660
  emptyText = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4",
7631
7661
  hoverable = true,
7632
7662
  searchable = false,
@@ -7647,7 +7677,7 @@ function KjunTable(props) {
7647
7677
  onRowClick,
7648
7678
  onRetry
7649
7679
  } = props;
7650
- const { colors, domainColors } = useKjunStyles(), state = useTableModel2(props), query = useQueryDisplay(props), mobile = (0, import_react_native48.useWindowDimensions)().width < import_tokens47.tokens.table.mobileBreakpoint;
7680
+ const { colors, domainColors } = useKjunStyles(), state = useTableModel2(props), query = useQueryDisplay(props), revealed = useLoadingReveal(query.initialLoading, skeleton ? loadingDelay : 0), mobile = (0, import_react_native48.useWindowDimensions)().width < import_tokens47.tokens.table.mobileBreakpoint;
7651
7681
  const layout = tablePresentation(props, mobile);
7652
7682
  const { card, visible } = layout;
7653
7683
  const cell = (col, row, index, role) => {
@@ -7726,8 +7756,11 @@ function KjunTable(props) {
7726
7756
  refreshing: query.queryRefreshing,
7727
7757
  loadingPadding: "none",
7728
7758
  onRetry,
7759
+ loading: skeleton ? void 0 : props.loading,
7760
+ loadingText,
7761
+ loadingDelay: skeleton ? 0 : loadingDelay,
7729
7762
  children: [
7730
- card ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TableCards, { ...{ initialLoading: query.initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, layout } }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TableGrid, { ...{ initialLoading: query.initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, compact, striped, hoverable }, sortable: props.sortable }),
7763
+ card ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TableCards, { ...{ initialLoading: query.initialLoading, skeletonRows, skeletonHidden: query.initialLoading && !revealed, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, layout } }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TableGrid, { ...{ initialLoading: query.initialLoading, skeletonRows, skeletonHidden: query.initialLoading && !revealed, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, compact, striped, hoverable }, sortable: props.sortable }),
7731
7764
  pagination && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
7732
7765
  KjunPagination,
7733
7766
  {
@@ -7785,12 +7818,13 @@ function KjunKpiHero(props) {
7785
7818
  secondary = [],
7786
7819
  animated = true,
7787
7820
  size = "md",
7821
+ surface = "card",
7788
7822
  aside,
7789
7823
  formatter,
7790
7824
  deltaFormatter,
7791
7825
  renderSecondary
7792
7826
  } = props;
7793
- const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), mobile = (0, import_react_native50.useWindowDimensions)().width <= import_tokens48.tokens.responsive.kpiHero, small = size === "sm", numberRole = small ? "displaySm" : mobile ? "displayMd" : "displayLg", font = typeStyle(numberRole).fontSize, unitStyle = typeStyle(small ? "numberSm" : mobile ? "numberMd" : "numberLg");
7827
+ const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), windowWidth = (0, import_react_native50.useWindowDimensions)().width, mobile = windowWidth <= import_tokens48.tokens.responsive.kpiHero, small = size === "sm", numberRole = small ? "displaySm" : mobile ? "displayMd" : "displayLg", font = typeStyle(numberRole).fontSize, unitStyle = typeStyle(small ? "numberSm" : mobile ? "numberMd" : "numberLg");
7794
7828
  const geometry2 = import_tokens48.tokens.extensions.kpiHero;
7795
7829
  const spec = small ? geometry2.sm : mobile ? geometry2.mobile : geometry2.md;
7796
7830
  const numeric = {
@@ -7820,10 +7854,13 @@ function KjunKpiHero(props) {
7820
7854
  {
7821
7855
  accessibilityState: { busy: loading },
7822
7856
  style: {
7823
- paddingVertical: spec.paddingY,
7824
- paddingHorizontal: spec.paddingX,
7825
- backgroundColor: colors.surface,
7826
- borderRadius: geometry2.radius
7857
+ // surface="none" sits inside the app's own card or list, so it drops its own card box.
7858
+ ...surface === "none" ? {} : {
7859
+ paddingVertical: spec.paddingY,
7860
+ paddingHorizontal: spec.paddingX,
7861
+ backgroundColor: colors.surface,
7862
+ borderRadius: geometry2.radius
7863
+ }
7827
7864
  },
7828
7865
  children: [
7829
7866
  /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
@@ -7906,70 +7943,75 @@ function KjunKpiHero(props) {
7906
7943
  borderTopWidth: import_tokens48.tokens.border.defaultWidth,
7907
7944
  borderTopColor: colors.border
7908
7945
  },
7909
- children: secondary.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
7910
- import_react_native50.View,
7911
- {
7912
- style: mobile && !small ? {
7913
- flex: 1,
7914
- minWidth: 0,
7915
- paddingLeft: i ? geometry2.itemPadding : 0,
7916
- paddingRight: i === secondary.length - 1 ? 0 : geometry2.itemPadding,
7917
- borderLeftWidth: i ? import_tokens48.tokens.border.defaultWidth : 0,
7918
- borderLeftColor: colors.border
7919
- } : { minWidth: 0, maxWidth: "100%", flexShrink: 1 },
7920
- children: [
7921
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7922
- KText,
7923
- {
7924
- style: {
7925
- color: colors.textTertiary,
7926
- ...typeStyle("caption"),
7927
- marginBottom: spec.secondaryLabelGap
7928
- },
7929
- children: item.label
7930
- }
7931
- ),
7932
- loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7933
- KjunSkeleton,
7934
- {
7935
- type: "block",
7936
- height: typeStyle("numberMd").lineHeight,
7937
- width: geometry2.secondarySkeletonWidth
7938
- }
7939
- ) : (renderSecondary == null ? void 0 : renderSecondary(item, i)) || /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7940
- KpiNumberLine,
7941
- {
7942
- prefix: item.prefix,
7943
- suffix: item.suffix,
7944
- prefixGap: geometry2.secondaryAffixGap,
7945
- suffixGap: geometry2.secondaryAffixGap,
7946
- unitStyle: typeStyle("caption"),
7947
- style: { ...numeric, ...typeStyle("numberMd"), color: item.valueColor || (item.semantic === "price" && Number(item.value) !== 0 ? direction(Number(item.value)) : colors.text) },
7948
- children: kpiFormat(item)
7949
- }
7950
- ),
7951
- item.desc && (loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7952
- KjunSkeleton,
7953
- {
7954
- type: "block",
7955
- width: geometry2.descriptionSkeletonWidth,
7956
- height: typeStyle("caption").lineHeight
7957
- }
7958
- ) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7959
- KText,
7960
- {
7961
- style: {
7962
- ...typeStyle("caption"),
7963
- marginTop: small ? geometry2.sm.descriptionGap : geometry2.md.descriptionGap,
7964
- color: item.descColor || colors.textTertiary
7965
- },
7966
- children: item.desc
7967
- }
7968
- ))
7969
- ]
7970
- },
7971
- i
7972
- ))
7946
+ children: secondary.map((item, i) => {
7947
+ const columns = mobile && !small && windowWidth <= import_tokens48.tokens.responsive.kpiHeroSecondary && secondary.length >= 3 ? 2 : 0;
7948
+ const first = columns ? i % columns === 0 : i === 0;
7949
+ const last = columns ? i % columns === columns - 1 || i === secondary.length - 1 : i === secondary.length - 1;
7950
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
7951
+ import_react_native50.View,
7952
+ {
7953
+ style: mobile && !small ? {
7954
+ ...columns ? { width: `${100 / columns}%`, marginTop: i >= columns ? spec.secondaryPadding : 0 } : { flex: 1 },
7955
+ minWidth: 0,
7956
+ paddingLeft: first ? 0 : geometry2.itemPadding,
7957
+ paddingRight: last ? 0 : geometry2.itemPadding,
7958
+ borderLeftWidth: first ? 0 : import_tokens48.tokens.border.defaultWidth,
7959
+ borderLeftColor: colors.border
7960
+ } : { minWidth: 0, maxWidth: "100%", flexShrink: 1 },
7961
+ children: [
7962
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7963
+ KText,
7964
+ {
7965
+ style: {
7966
+ color: colors.textTertiary,
7967
+ ...typeStyle("caption"),
7968
+ marginBottom: spec.secondaryLabelGap
7969
+ },
7970
+ children: item.label
7971
+ }
7972
+ ),
7973
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7974
+ KjunSkeleton,
7975
+ {
7976
+ type: "block",
7977
+ height: typeStyle("numberMd").lineHeight,
7978
+ width: geometry2.secondarySkeletonWidth
7979
+ }
7980
+ ) : (renderSecondary == null ? void 0 : renderSecondary(item, i)) || /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7981
+ KpiNumberLine,
7982
+ {
7983
+ prefix: item.prefix,
7984
+ suffix: item.suffix,
7985
+ prefixGap: geometry2.secondaryAffixGap,
7986
+ suffixGap: geometry2.secondaryAffixGap,
7987
+ unitStyle: typeStyle("caption"),
7988
+ style: { ...numeric, ...typeStyle("numberMd"), color: item.valueColor || (item.semantic === "price" && Number(item.value) !== 0 ? direction(Number(item.value)) : colors.text) },
7989
+ children: kpiFormat(item)
7990
+ }
7991
+ ),
7992
+ item.desc && (loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
7993
+ KjunSkeleton,
7994
+ {
7995
+ type: "block",
7996
+ width: geometry2.descriptionSkeletonWidth,
7997
+ height: typeStyle("caption").lineHeight
7998
+ }
7999
+ ) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8000
+ KText,
8001
+ {
8002
+ style: {
8003
+ ...typeStyle("caption"),
8004
+ marginTop: small ? geometry2.sm.descriptionGap : geometry2.md.descriptionGap,
8005
+ color: item.descColor || colors.textTertiary
8006
+ },
8007
+ children: item.desc
8008
+ }
8009
+ ))
8010
+ ]
8011
+ },
8012
+ i
8013
+ );
8014
+ })
7973
8015
  }
7974
8016
  )
7975
8017
  ]
@@ -7979,13 +8021,14 @@ function KjunKpiHero(props) {
7979
8021
 
7980
8022
  // packages/native/src/kpi-row.tsx
7981
8023
  var import_tokens49 = require("@kjun-ui/tokens");
7982
- var import_react58 = require("react");
8024
+ var import_react59 = require("react");
7983
8025
  var import_react_native51 = require("react-native");
7984
8026
  var import_jsx_runtime48 = require("react/jsx-runtime");
7985
8027
  function KjunKpiRow({
7986
8028
  loading = false,
7987
8029
  items,
7988
8030
  size = "md",
8031
+ surface = "card",
7989
8032
  mobileSummary = true,
7990
8033
  onItemClick,
7991
8034
  renderValue
@@ -7993,7 +8036,7 @@ function KjunKpiRow({
7993
8036
  const { colors, domainColors, numericFontFamily, fontFamily } = useKjunStyles(), mobile = (0, import_react_native51.useWindowDimensions)().width <= import_tokens49.tokens.responsive.kpiRow, small = size === "sm", summary = mobileSummary && mobile && !small;
7994
8037
  const geometry2 = import_tokens49.tokens.extensions.kpiRow;
7995
8038
  const spec = small ? geometry2.sm : mobile ? geometry2.mobile : geometry2.md;
7996
- const [width, setWidth] = (0, import_react58.useState)(0);
8039
+ const [width, setWidth] = (0, import_react59.useState)(0);
7997
8040
  const paddingX = summary ? geometry2.summary.paddingX : spec.paddingX;
7998
8041
  const gapX = summary ? geometry2.summary.gapX : 0;
7999
8042
  const explicit = items.some(
@@ -8034,10 +8077,13 @@ function KjunKpiRow({
8034
8077
  style: {
8035
8078
  flexDirection: "row",
8036
8079
  flexWrap: mobile ? "wrap" : "nowrap",
8037
- paddingVertical: summary ? geometry2.summary.paddingY : spec.paddingY,
8038
- paddingHorizontal: paddingX,
8039
- borderRadius: geometry2.radius,
8040
- backgroundColor: colors.surface,
8080
+ // surface="none" sits inside the app's own card or list, so it drops its own card box.
8081
+ ...surface === "none" ? {} : {
8082
+ paddingVertical: summary ? geometry2.summary.paddingY : spec.paddingY,
8083
+ paddingHorizontal: paddingX,
8084
+ borderRadius: geometry2.radius,
8085
+ backgroundColor: colors.surface
8086
+ },
8041
8087
  rowGap: summary ? geometry2.summary.gapY : 0,
8042
8088
  columnGap: gapX
8043
8089
  },
@@ -8209,7 +8255,7 @@ var import_tokens51 = require("@kjun-ui/tokens");
8209
8255
  var import_react_native53 = require("react-native");
8210
8256
 
8211
8257
  // shared/package-runtime/market-cards.ts
8212
- var import_react59 = require("react");
8258
+ var import_react60 = require("react");
8213
8259
  function useMarketCardsModel(props, persistence) {
8214
8260
  const {
8215
8261
  columns,
@@ -8225,8 +8271,8 @@ function useMarketCardsModel(props, persistence) {
8225
8271
  sortKey: c.sortable ? metricConfig[c.key].sortKey : null,
8226
8272
  isDefaultSort: c.defaultSort
8227
8273
  }));
8228
- const [key, setKey] = (0, import_react59.useState)(""), restoreSignature = JSON.stringify([storageNamespace, pills]);
8229
- const mounted = (0, import_react59.useRef)("");
8274
+ const [key, setKey] = (0, import_react60.useState)(""), restoreSignature = JSON.stringify([storageNamespace, pills]);
8275
+ const mounted = (0, import_react60.useRef)("");
8230
8276
  const save = (key2) => {
8231
8277
  var _a;
8232
8278
  try {
@@ -8234,7 +8280,7 @@ function useMarketCardsModel(props, persistence) {
8234
8280
  } catch (e) {
8235
8281
  }
8236
8282
  };
8237
- (0, import_react59.useEffect)(() => {
8283
+ (0, import_react60.useEffect)(() => {
8238
8284
  var _a, _b;
8239
8285
  if (mounted.current === restoreSignature) return;
8240
8286
  mounted.current = restoreSignature;
@@ -8476,7 +8522,7 @@ function KjunMarketCards(props) {
8476
8522
  ...props,
8477
8523
  loadingPadding: "none",
8478
8524
  empty: !rows.length,
8479
- loadingContent: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(KjunListSkeleton, { variant: "compact" }),
8525
+ loadingContent: props.skeleton === false ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(KjunListSkeleton, { variant: "compact" }),
8480
8526
  emptyContent: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(KjunEmpty, { text: emptyMessage, description: emptySubMessage }),
8481
8527
  children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_react_native53.View, { children: [
8482
8528
  state.pill && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(KText, { style: { textAlign: "right", paddingHorizontal: import_tokens51.tokens.dimension.value16, paddingVertical: import_tokens51.tokens.dimension.value8, ...typeStyle("caption"), color: colors.textSecondary }, children: state.pill.label }),
@@ -8587,7 +8633,7 @@ function KjunMarketSimpleList(props) {
8587
8633
  loadingPadding: "none",
8588
8634
  empty: !rows.length,
8589
8635
  emptyText: emptyMessage,
8590
- loadingContent: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(KjunListSkeleton, {}),
8636
+ loadingContent: props.skeleton === false ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(KjunListSkeleton, {}),
8591
8637
  emptyContent: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(KjunEmpty, { text: emptyMessage, description: emptySubMessage }),
8592
8638
  children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_react_native54.View, { children: rows.map((row, i) => {
8593
8639
  var _a, _b;
@@ -8714,7 +8760,7 @@ function KjunMarketListPanel({
8714
8760
 
8715
8761
  // packages/native/src/market-table.tsx
8716
8762
  var import_tokens54 = require("@kjun-ui/tokens");
8717
- var import_react60 = require("react");
8763
+ var import_react61 = require("react");
8718
8764
  var import_react_native56 = require("react-native");
8719
8765
  var import_react_native_svg8 = __toESM(require("react-native-svg"), 1);
8720
8766
  var import_jsx_runtime53 = require("react/jsx-runtime");
@@ -8800,7 +8846,7 @@ function KjunMarketTable(props) {
8800
8846
  );
8801
8847
  };
8802
8848
  const layout = useMarketLayout(columns, showActions);
8803
- const [scroll, setScroll] = (0, import_react60.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-market-fade-" + (0, import_react60.useId)().replace(/[^a-z0-9]/gi, "");
8849
+ const [scroll, setScroll] = (0, import_react61.useState)({ viewport: 0, x: 0 }), fadeId = "kjun-market-fade-" + (0, import_react61.useId)().replace(/[^a-z0-9]/gi, "");
8804
8850
  const tableQuote = { price: {}, change: { fontWeight: typeStyle("body").fontWeight } };
8805
8851
  return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
8806
8852
  import_react_native56.View,
@@ -8818,7 +8864,7 @@ function KjunMarketTable(props) {
8818
8864
  loadingPadding: "none",
8819
8865
  empty: !rows.length,
8820
8866
  emptyText: emptyMessage,
8821
- loadingContent: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(KjunMarketTableSkeleton, { columns, showActions }),
8867
+ loadingContent: props.skeleton === false ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(KjunMarketTableSkeleton, { columns, showActions }),
8822
8868
  emptyContent: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(KjunEmpty, { text: emptyMessage, description: emptySubMessage }),
8823
8869
  children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(MarketQuoteTypeContext.Provider, { value: tableQuote, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_react_native56.View, { style: { position: "relative", minWidth: 0 }, children: [
8824
8870
  /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
@@ -9023,12 +9069,12 @@ function KjunMarketTable(props) {
9023
9069
 
9024
9070
  // packages/native/src/list.tsx
9025
9071
  var import_tokens55 = require("@kjun-ui/tokens");
9026
- var import_react61 = require("react");
9072
+ var import_react62 = require("react");
9027
9073
  var import_react_native57 = require("react-native");
9028
9074
  var import_jsx_runtime54 = require("react/jsx-runtime");
9029
- var LastListRow = (0, import_react61.createContext)(false);
9075
+ var LastListRow = (0, import_react62.createContext)(false);
9030
9076
  function KjunListRow({ title, description, leading, trailing, actions, href, disabled = false, onPress }) {
9031
- const { colors } = useKjunStyles(), last = (0, import_react61.useContext)(LastListRow);
9077
+ const { colors } = useKjunStyles(), last = (0, import_react62.useContext)(LastListRow);
9032
9078
  const parts = /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
9033
9079
  leading && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { children: content(leading) }),
9034
9080
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react_native57.View, { style: { flex: 1, minWidth: 0 }, children: [
@@ -9053,13 +9099,13 @@ function KjunListSection({ title, description, actions, children, ariaLabel }) {
9053
9099
  ] }),
9054
9100
  content(actions)
9055
9101
  ] }),
9056
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { role: "list", accessibilityLabel: ariaLabel || title, children: import_react61.Children.toArray(children).map((row, i, rows) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(LastListRow.Provider, { value: i === rows.length - 1, children: row }, i)) })
9102
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_react_native57.View, { role: "list", accessibilityLabel: ariaLabel || title, children: import_react62.Children.toArray(children).map((row, i, rows) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(LastListRow.Provider, { value: i === rows.length - 1, children: row }, i)) })
9057
9103
  ] });
9058
9104
  }
9059
9105
 
9060
9106
  // packages/native/src/app-navigation.tsx
9061
9107
  var import_tokens56 = require("@kjun-ui/tokens");
9062
- var import_react62 = require("react");
9108
+ var import_react63 = require("react");
9063
9109
  var import_react_native58 = require("react-native");
9064
9110
  var import_jsx_runtime55 = require("react/jsx-runtime");
9065
9111
  function KjunTopNavigation({ title, description, leading, actions, safeAreaTop = 0 }) {
@@ -9068,13 +9114,13 @@ function KjunTopNavigation({ title, description, leading, actions, safeAreaTop =
9068
9114
  const titleInset = Math.max(0, (geometry2.controlSize - import_tokens56.tokens.typography.sectionTitle.lineHeightPx) / 2);
9069
9115
  const wrapping = import_react_native58.Platform.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
9070
9116
  const edgeInset = (geometry2.controlSize - geometry2.iconSize) / 2;
9071
- const [iconEdges, setIconEdges] = (0, import_react62.useState)({ leading: false, trailing: false });
9117
+ const [iconEdges, setIconEdges] = (0, import_react63.useState)({ leading: false, trailing: false });
9072
9118
  const square = (key) => (event) => {
9073
9119
  const { width, height } = event.nativeEvent.layout;
9074
9120
  const next = Math.abs(width - height) < 1 && Math.abs(height - geometry2.controlSize) < 1;
9075
9121
  setIconEdges((current) => current[key] === next ? current : { ...current, [key]: next });
9076
9122
  };
9077
- const flatten = (node) => import_react62.Children.toArray(node).flatMap((child) => (0, import_react62.isValidElement)(child) && child.type === import_react62.Fragment ? flatten(child.props.children) : [child]);
9123
+ 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]);
9078
9124
  const actionList = flatten(actions);
9079
9125
  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: [
9080
9126
  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) }) }),
@@ -9148,7 +9194,7 @@ function KjunBottomNavigation({ items, value, ariaLabel = "\uC8FC\uC694 \uD0D0\u
9148
9194
  }
9149
9195
  function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboardVisible = false, hideOnKeyboard = false }) {
9150
9196
  const { colors } = useKjunStyles();
9151
- const [width, setWidth] = (0, import_react62.useState)(0);
9197
+ const [width, setWidth] = (0, import_react63.useState)(0);
9152
9198
  const geometry2 = import_tokens56.tokens.extensions.navigation;
9153
9199
  const wide = width >= import_tokens56.tokens.responsive.bottomAction + geometry2.padding * 2;
9154
9200
  const wrapping = import_react_native58.Platform.OS === "web" ? { wordBreak: "keep-all", overflowWrap: "anywhere" } : {};
@@ -9170,16 +9216,16 @@ function KjunBottomActionBar({ description, children, safeAreaBottom = 0, keyboa
9170
9216
  }
9171
9217
 
9172
9218
  // packages/native/src/media.tsx
9173
- var import_react63 = require("react");
9219
+ var import_react64 = require("react");
9174
9220
  var import_react_native59 = require("react-native");
9175
9221
  var import_tokens57 = require("@kjun-ui/tokens");
9176
9222
  var import_jsx_runtime56 = require("react/jsx-runtime");
9177
9223
  function KjunImage({ src, source, alt, decorative = false, aspectRatio = 1, fit = "cover", fallback: fallback2, onLoad, onError }) {
9178
9224
  const { colors } = useKjunStyles();
9179
- const request = JSON.stringify(source != null ? source : src), current = (0, import_react63.useRef)({ request, version: 0 });
9225
+ const request = JSON.stringify(source != null ? source : src), current = (0, import_react64.useRef)({ request, version: 0 });
9180
9226
  if (current.current.request !== request) current.current = { request, version: current.current.version + 1 };
9181
9227
  const version = current.current.version;
9182
- const [failed, setFailed] = (0, import_react63.useState)(null);
9228
+ const [failed, setFailed] = (0, import_react64.useState)(null);
9183
9229
  const missing = !source && !src;
9184
9230
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.View, { accessibilityElementsHidden: decorative, importantForAccessibility: decorative ? "no-hide-descendants" : "auto", "aria-hidden": decorative || void 0, style: { width: "100%", aspectRatio: aspectRatio > 0 ? aspectRatio : 1, overflow: "hidden", backgroundColor: colors.secondary }, children: !missing && failed !== version ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_react_native59.Image, { source: source != null ? source : { uri: src }, accessible: !decorative, accessibilityLabel: decorative ? void 0 : alt, resizeMode: fit, style: { position: "absolute", inset: 0, width: "100%", height: "100%" }, onLoad: () => {
9185
9231
  if (version === current.current.version) onLoad == null ? void 0 : onLoad();
@@ -9209,7 +9255,7 @@ function KjunChip({ label, icon, removable = false, disabled = false, size = "md
9209
9255
  }
9210
9256
 
9211
9257
  // packages/native/src/range-input.tsx
9212
- var import_react64 = require("react");
9258
+ var import_react65 = require("react");
9213
9259
  var import_react_native61 = require("react-native");
9214
9260
  var import_tokens59 = require("@kjun-ui/tokens");
9215
9261
  var import_jsx_runtime58 = require("react/jsx-runtime");
@@ -9233,18 +9279,18 @@ function RangeInput({
9233
9279
  const valid = domain.valid && (!Array.isArray(value) || value.length === 2) && values.every(domain.accepts) && (values.length === 1 || values[0] <= values[1]);
9234
9280
  const blocked = disabled || !valid;
9235
9281
  const effectiveMax = valid ? domain.snap(max) : min;
9236
- const [hovered, setHovered] = (0, import_react64.useState)(null);
9237
- const [dragging, setDragging] = (0, import_react64.useState)(null);
9238
- const [focused, setFocused] = (0, import_react64.useState)(null);
9239
- const track = (0, import_react64.useRef)(null), measured = (0, import_react64.useRef)({ x: 0, width: 1 }), selected = (0, import_react64.useRef)(0), dirty = (0, import_react64.useRef)(false);
9240
- const latest = (0, import_react64.useRef)(values);
9282
+ const [hovered, setHovered] = (0, import_react65.useState)(null);
9283
+ const [dragging, setDragging] = (0, import_react65.useState)(null);
9284
+ const [focused, setFocused] = (0, import_react65.useState)(null);
9285
+ const track = (0, import_react65.useRef)(null), measured = (0, import_react65.useRef)({ x: 0, width: 1 }), selected = (0, import_react65.useRef)(0), dirty = (0, import_react65.useRef)(false);
9286
+ const latest = (0, import_react65.useRef)(values);
9241
9287
  latest.current = values;
9242
- const callbacks = (0, import_react64.useRef)({ onValueChange, onChangeCommit });
9288
+ const callbacks = (0, import_react65.useRef)({ onValueChange, onChangeCommit });
9243
9289
  callbacks.current = { onValueChange, onChangeCommit };
9244
- (0, import_react64.useEffect)(() => {
9290
+ (0, import_react65.useEffect)(() => {
9245
9291
  if (!valid) console.warn("KJUN Slider: \uBC94\uC704\xB7step\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
9246
9292
  }, [valid]);
9247
- (0, import_react64.useEffect)(() => {
9293
+ (0, import_react65.useEffect)(() => {
9248
9294
  if (blocked) {
9249
9295
  setDragging(null);
9250
9296
  setHovered(null);
@@ -9284,7 +9330,7 @@ function RangeInput({
9284
9330
  measured.current = { x: pageX, width: Math.max(1, width) };
9285
9331
  });
9286
9332
  };
9287
- const responder = (0, import_react64.useMemo)(
9333
+ const responder = (0, import_react65.useMemo)(
9288
9334
  () => import_react_native61.PanResponder.create({
9289
9335
  onStartShouldSetPanResponderCapture: () => !disabled && valid,
9290
9336
  onMoveShouldSetPanResponderCapture: (_event, gesture) => !disabled && valid && Math.abs(gesture.dx) > 3 && Math.abs(gesture.dx) > Math.abs(gesture.dy),
@@ -9509,7 +9555,7 @@ function KjunRangeSlider(props) {
9509
9555
  }
9510
9556
 
9511
9557
  // packages/native/src/quantity-stepper.tsx
9512
- var import_react65 = require("react");
9558
+ var import_react66 = require("react");
9513
9559
  var import_react_native62 = require("react-native");
9514
9560
  var import_tokens60 = require("@kjun-ui/tokens");
9515
9561
 
@@ -9531,16 +9577,16 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
9531
9577
  const increaseStyle = { ...buttonStyle, borderRadius: 0, borderTopRightRadius: outer, borderBottomRightRadius: outer };
9532
9578
  const domain = (0, import_tokens60.createNumberDomain)({ min, max, step, precision }), valid = domain.valid && domain.accepts(value), blocked = disabled || !valid;
9533
9579
  const surface = useFieldSurface(size, { disabled: blocked, invalid });
9534
- const [draft, setDraft] = (0, import_react65.useState)(String(value));
9535
- const inputRef = (0, import_react65.useRef)(null);
9536
- const composing = (0, import_react65.useRef)(false), dirty = (0, import_react65.useRef)(false), accepted = (0, import_react65.useRef)(value);
9537
- const cancelledEscape = (0, import_react65.useRef)(false);
9538
- (0, import_react65.useEffect)(() => {
9580
+ const [draft, setDraft] = (0, import_react66.useState)(String(value));
9581
+ const inputRef = (0, import_react66.useRef)(null);
9582
+ const composing = (0, import_react66.useRef)(false), dirty = (0, import_react66.useRef)(false), accepted = (0, import_react66.useRef)(value);
9583
+ const cancelledEscape = (0, import_react66.useRef)(false);
9584
+ (0, import_react66.useEffect)(() => {
9539
9585
  setDraft(String(value));
9540
9586
  accepted.current = value;
9541
9587
  dirty.current = false;
9542
9588
  }, [value, precision, min, max, step]);
9543
- (0, import_react65.useEffect)(() => {
9589
+ (0, import_react66.useEffect)(() => {
9544
9590
  if (!valid) console.warn("KJUN QuantityStepper: \uBC94\uC704\xB7step\xB7\uC815\uBC00\uB3C4\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
9545
9591
  }, [valid]);
9546
9592
  const emit = (next) => {
@@ -9577,7 +9623,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
9577
9623
  } else if (action === "commit") commit();
9578
9624
  else move(action === "increment" ? 1 : -1);
9579
9625
  };
9580
- const handlers = (0, import_react65.useRef)({ key, edit: (text) => {
9626
+ const handlers = (0, import_react66.useRef)({ key, edit: (text) => {
9581
9627
  dirty.current = true;
9582
9628
  setDraft(text);
9583
9629
  } });
@@ -9585,7 +9631,7 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
9585
9631
  dirty.current = true;
9586
9632
  setDraft(text);
9587
9633
  } };
9588
- (0, import_react65.useEffect)(() => {
9634
+ (0, import_react66.useEffect)(() => {
9589
9635
  if (import_react_native62.Platform.OS !== "web") return;
9590
9636
  const input = inputRef.current;
9591
9637
  const keydown = (event) => handlers.current.key(event);
@@ -9657,19 +9703,19 @@ function KjunQuantityStepper({ value, min = 0, max, step = 1, precision = 0, dis
9657
9703
  }
9658
9704
 
9659
9705
  // packages/native/src/time-picker.tsx
9660
- var import_react66 = require("react");
9706
+ var import_react67 = require("react");
9661
9707
  var import_react_native63 = require("react-native");
9662
9708
  var import_tokens61 = require("@kjun-ui/tokens");
9663
9709
  var import_jsx_runtime60 = require("react/jsx-runtime");
9664
9710
  function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1, secondStep = 1, disabled = false, error = false, clearable = true, size = "md", ariaLabel = "\uC2DC\uAC04", onValueChange, onChangeCommit }) {
9665
9711
  const geometry2 = import_tokens61.tokens.extensions.timePicker, spec = import_tokens61.tokens.input[size];
9666
9712
  const { colors } = useKjunStyles();
9667
- const first = (0, import_react66.useRef)(null);
9668
- const [focused, setFocused] = (0, import_react66.useState)(false), [opened, setOpened] = (0, import_react66.useState)(null);
9669
- const field = useKjunField(), uid = (0, import_react66.useId)();
9713
+ const first = (0, import_react67.useRef)(null);
9714
+ const [focused, setFocused] = (0, import_react67.useState)(false), [opened, setOpened] = (0, import_react67.useState)(null);
9715
+ const field = useKjunField(), uid = (0, import_react67.useId)();
9670
9716
  const fieldId = (field == null ? void 0 : field.id) || `kjun-time-${uid}`;
9671
- const domain = (0, import_react66.useMemo)(() => (0, import_tokens61.createTimeDomain)({ precision, min, max, minuteStep, secondStep }), [precision, min, max, minuteStep, secondStep]), valid = domain.valid && domain.accepts(value);
9672
- (0, import_react66.useEffect)(() => {
9717
+ const domain = (0, import_react67.useMemo)(() => (0, import_tokens61.createTimeDomain)({ precision, min, max, minuteStep, secondStep }), [precision, min, max, minuteStep, secondStep]), valid = domain.valid && domain.accepts(value);
9718
+ (0, import_react67.useEffect)(() => {
9673
9719
  if (!valid) console.warn("KJUN TimePicker: \uC2DC\uAC01 \uBC94\uC704\xB7\uAC04\uACA9\xB7\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694.");
9674
9720
  }, [valid]);
9675
9721
  const change = (next) => {
@@ -9680,7 +9726,7 @@ function KjunTimePicker({ value, precision = "minute", min, max, minuteStep = 1,
9680
9726
  };
9681
9727
  const time = value === null ? null : domain.parse(value);
9682
9728
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react_native63.View, { accessibilityLabel: ariaLabel, style: { flexDirection: "row", alignItems: "center", maxWidth: "100%", minWidth: 0, backgroundColor: colors.inputBg, borderRadius: spec.radius }, children: [
9683
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_native63.View, { style: { flex: 1, flexDirection: "row", alignItems: "center", minWidth: 0 }, children: ["\uC2DC", "\uBD84", "\uCD08"].slice(0, precision === "second" ? 3 : 2).map((label, index) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react66.Fragment, { children: [
9729
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_native63.View, { style: { flex: 1, flexDirection: "row", alignItems: "center", minWidth: 0 }, children: ["\uC2DC", "\uBD84", "\uCD08"].slice(0, precision === "second" ? 3 : 2).map((label, index) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_react67.Fragment, { children: [
9684
9730
  index > 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(KText, { "aria-hidden": true, style: { ...inputTypeStyle(size), width: geometry2.separatorWidth, textAlign: "center", color: disabled || !valid ? colors.textDisabled : colors.textSecondary }, children: ":" }),
9685
9731
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(FieldContext.Provider, { value: { ...field, id: index === 0 ? fieldId : `${fieldId}-${index}` }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CompoundControlContext.Provider, { value: { size, focusRef: index === 0 ? first : void 0, onFocusChange: setFocused, leading: index === 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_react_native63.View, { style: { flexShrink: 0, minWidth: geometry2.segmentMinimumWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(KjunSelect, { value: time === null ? null : domain.part(time, index), options: domain.options(value, index).map((n) => ({ value: n, label: String(n).padStart(2, "0") })), onValueChange: (next) => {
9686
9732
  if (typeof next === "number") change(domain.select(value, index, next));