@kjun-ui/native 0.6.1 → 0.8.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.
Files changed (30) hide show
  1. package/dist/index.cjs +413 -411
  2. package/dist/index.js +408 -406
  3. package/dist/index.web.cjs +413 -411
  4. package/dist/index.web.js +408 -406
  5. package/dist/styles.css +70 -52
  6. package/dist/types/packages/native/src/data-state.d.cts +3 -1
  7. package/dist/types/packages/native/src/data-state.d.ts +3 -1
  8. package/dist/types/packages/native/src/kpi-hero.d.cts +2 -0
  9. package/dist/types/packages/native/src/kpi-hero.d.ts +2 -0
  10. package/dist/types/packages/native/src/kpi-row.d.cts +3 -1
  11. package/dist/types/packages/native/src/kpi-row.d.ts +3 -1
  12. package/dist/types/packages/native/src/market-model.d.cts +5 -0
  13. package/dist/types/packages/native/src/market-model.d.ts +5 -0
  14. package/dist/types/packages/native/src/skeleton-base.d.cts +1 -1
  15. package/dist/types/packages/native/src/skeleton-base.d.ts +1 -1
  16. package/dist/types/packages/native/src/skeletons.d.cts +8 -3
  17. package/dist/types/packages/native/src/skeletons.d.ts +8 -3
  18. package/dist/types/packages/native/src/table-cards.d.cts +1 -1
  19. package/dist/types/packages/native/src/table-cards.d.ts +1 -1
  20. package/dist/types/packages/native/src/table-grid.d.cts +1 -1
  21. package/dist/types/packages/native/src/table-grid.d.ts +1 -1
  22. package/dist/types/shared/package-runtime/chart-skeleton.d.cts +12 -0
  23. package/dist/types/shared/package-runtime/chart-skeleton.d.ts +12 -0
  24. package/dist/types/shared/package-runtime/table-presentation.d.cts +2 -0
  25. package/dist/types/shared/package-runtime/table-presentation.d.ts +2 -0
  26. package/dist/types/shared/package-runtime/table.d.cts +5 -0
  27. package/dist/types/shared/package-runtime/table.d.ts +5 -0
  28. package/dist/types/shared/package-runtime/use-loading-reveal.d.cts +2 -0
  29. package/dist/types/shared/package-runtime/use-loading-reveal.d.ts +2 -0
  30. package/package.json +3 -3
package/dist/styles.css CHANGED
@@ -482,9 +482,6 @@
482
482
  --_kjun-extension-skeleton-avatar-size: 48px;
483
483
  --_kjun-extension-skeleton-card-avatar-size: 40px;
484
484
  --_kjun-extension-skeleton-table-line-height: 14px;
485
- --_kjun-extension-skeleton-chart-height: 200px;
486
- --_kjun-extension-skeleton-chart-bar-max-width: 40px;
487
- --_kjun-extension-skeleton-chart-axis-height: 2px;
488
485
  --_kjun-extension-skeleton-stat-width: 80px;
489
486
  --_kjun-extension-skeleton-stat-height: 40px;
490
487
  --_kjun-extension-skeleton-block-height: 100px;
@@ -678,14 +675,15 @@
678
675
  --_kjun-extension-market-list-change-skeleton-height: 14px;
679
676
  --_kjun-extension-chart-skeleton-height: 240px;
680
677
  --_kjun-extension-chart-skeleton-donut-thickness: 22px;
681
- --_kjun-extension-chart-skeleton-donut-label-width: 76px;
682
- --_kjun-extension-chart-skeleton-donut-label-height: 14px;
683
678
  --_kjun-state-opacity-disabled: 0.5;
684
679
  --_kjun-state-opacity-disabled-strong: 0.4;
685
680
  --_kjun-state-opacity-pressed: 0.8;
686
681
  --_kjun-state-opacity-pending: 0.55;
687
682
  --_kjun-state-opacity-heat-minimum: 0.08;
688
683
  --_kjun-state-opacity-heat-maximum: 0.4;
684
+ --_kjun-state-opacity-deviation-low: 0.08;
685
+ --_kjun-state-opacity-deviation-medium: 0.14;
686
+ --_kjun-state-opacity-deviation-strong: 0.22;
689
687
  --_kjun-state-focus-width: 2px;
690
688
  --_kjun-state-focus-offset: 2px;
691
689
  --_kjun-state-focus-choice-offset: 3px;
@@ -1137,7 +1135,6 @@
1137
1135
  .kjun-scope .kjun-field--suffix { padding-right: calc(var(--_kjun-field-padding) + var(--_kjun-field-clear-size) + var(--_kjun-field-affix-gap) - var(--_kjun-border-control-width)); }
1138
1136
  .kjun-scope .kjun-input-native.kjun-field--prefix { padding-left: calc(var(--_kjun-field-padding) + var(--_kjun-input-prefix-width) + var(--_kjun-field-affix-gap) - var(--_kjun-border-control-width)); }
1139
1137
  .kjun-scope .kjun-input-native.kjun-field--suffix { padding-right: calc(var(--_kjun-field-padding) + var(--_kjun-input-suffix-width) + var(--_kjun-field-affix-gap) - var(--_kjun-border-control-width)); }
1140
- .kjun-scope .kjun-field--clearable > .kj-truncate { padding-right: calc(var(--_kjun-field-clear-size) + var(--_kjun-field-affix-gap)); }
1141
1138
  .kjun-scope .kjun-field--select { display: flex; align-items: center; justify-content: space-between; text-align: left; gap: var(--_kjun-geometry-dimension-value8); }
1142
1139
  .kjun-scope .kjun-field--textarea { height: auto; padding-top: var(--_kjun-field-textarea-padding-y); padding-bottom: var(--_kjun-field-textarea-padding-y); }
1143
1140
  .kjun-scope .kjun-field-shell { position: relative; min-width: 0; --_kjun-input-prefix-width: 0px; --_kjun-input-suffix-width: 0px; }
@@ -1160,7 +1157,7 @@
1160
1157
  .kjun-scope .kjun-form-group { margin-bottom: var(--_kjun-extension-form-item-gap); min-width: 0; }
1161
1158
  .kjun-scope .kjun-form-group:last-child { margin-bottom: 0; }
1162
1159
  /* 그리드·툴바는 부모 gap을 사용하고, 일반 문서 흐름의 기존 폼만 기본 간격을 유지한다. */
1163
- .kjun-scope :where(.kj-flex, .kj-inline-flex, .kj-grid, .kj-inline-grid, [data-kjun-layout="form"]) > .kjun-form-group { margin-bottom: 0; }
1160
+ .kjun-scope :where([data-kjun-layout="form"]) > .kjun-form-group { margin-bottom: 0; }
1164
1161
  .kjun-scope .kjun-field-menu {
1165
1162
  padding: var(--_kjun-extension-menu-padding);
1166
1163
  border: var(--_kjun-border-default-width) solid var(--_kjun-border-primary);
@@ -1382,12 +1379,12 @@
1382
1379
  .kjun-scope .kjun-type-control-large { font-size: var(--_kjun-type-control-large-size); line-height: var(--_kjun-type-control-large-line); font-weight: var(--_kjun-type-control-large-weight); letter-spacing: var(--_kjun-type-control-large-tracking); }
1383
1380
  .kjun-scope .kjun-type-section-title { font-size: var(--_kjun-type-section-title-size); line-height: var(--_kjun-type-section-title-line); font-weight: var(--_kjun-type-section-title-weight); letter-spacing: var(--_kjun-type-section-title-tracking); }
1384
1381
  .kjun-scope .kjun-type-page-title { font-size: var(--_kjun-type-page-title-size); line-height: var(--_kjun-type-page-title-line); font-weight: var(--_kjun-type-page-title-weight); letter-spacing: var(--_kjun-type-page-title-tracking); }
1385
- .kjun-scope .kjun-type-number-sm { font-size: var(--_kjun-type-number-sm-size); line-height: var(--_kjun-type-number-sm-line); font-weight: var(--_kjun-type-number-sm-weight); letter-spacing: var(--_kjun-type-number-sm-tracking); font-family: var(--font-numeric); font-variant-numeric: tabular-nums; }
1386
- .kjun-scope .kjun-type-number-md { font-size: var(--_kjun-type-number-md-size); line-height: var(--_kjun-type-number-md-line); font-weight: var(--_kjun-type-number-md-weight); letter-spacing: var(--_kjun-type-number-md-tracking); font-family: var(--font-numeric); font-variant-numeric: tabular-nums; }
1387
- .kjun-scope .kjun-type-number-lg { font-size: var(--_kjun-type-number-lg-size); line-height: var(--_kjun-type-number-lg-line); font-weight: var(--_kjun-type-number-lg-weight); letter-spacing: var(--_kjun-type-number-lg-tracking); font-family: var(--font-numeric); font-variant-numeric: tabular-nums; }
1388
- .kjun-scope .kjun-type-display-sm { font-size: var(--_kjun-type-display-sm-size); line-height: var(--_kjun-type-display-sm-line); font-weight: var(--_kjun-type-display-sm-weight); letter-spacing: var(--_kjun-type-display-sm-tracking); font-family: var(--font-numeric); font-variant-numeric: tabular-nums; }
1389
- .kjun-scope .kjun-type-display-md { font-size: var(--_kjun-type-display-md-size); line-height: var(--_kjun-type-display-md-line); font-weight: var(--_kjun-type-display-md-weight); letter-spacing: var(--_kjun-type-display-md-tracking); font-family: var(--font-numeric); font-variant-numeric: tabular-nums; }
1390
- .kjun-scope .kjun-type-display-lg { font-size: var(--_kjun-type-display-lg-size); line-height: var(--_kjun-type-display-lg-line); font-weight: var(--_kjun-type-display-lg-weight); letter-spacing: var(--_kjun-type-display-lg-tracking); font-family: var(--font-numeric); font-variant-numeric: tabular-nums; }
1382
+ .kjun-scope .kjun-type-number-sm { font-size: var(--_kjun-type-number-sm-size); line-height: var(--_kjun-type-number-sm-line); font-weight: var(--_kjun-type-number-sm-weight); letter-spacing: var(--_kjun-type-number-sm-tracking); font-family: var(--_kjun-font-numeric); font-variant-numeric: tabular-nums; }
1383
+ .kjun-scope .kjun-type-number-md { font-size: var(--_kjun-type-number-md-size); line-height: var(--_kjun-type-number-md-line); font-weight: var(--_kjun-type-number-md-weight); letter-spacing: var(--_kjun-type-number-md-tracking); font-family: var(--_kjun-font-numeric); font-variant-numeric: tabular-nums; }
1384
+ .kjun-scope .kjun-type-number-lg { font-size: var(--_kjun-type-number-lg-size); line-height: var(--_kjun-type-number-lg-line); font-weight: var(--_kjun-type-number-lg-weight); letter-spacing: var(--_kjun-type-number-lg-tracking); font-family: var(--_kjun-font-numeric); font-variant-numeric: tabular-nums; }
1385
+ .kjun-scope .kjun-type-display-sm { font-size: var(--_kjun-type-display-sm-size); line-height: var(--_kjun-type-display-sm-line); font-weight: var(--_kjun-type-display-sm-weight); letter-spacing: var(--_kjun-type-display-sm-tracking); font-family: var(--_kjun-font-numeric); font-variant-numeric: tabular-nums; }
1386
+ .kjun-scope .kjun-type-display-md { font-size: var(--_kjun-type-display-md-size); line-height: var(--_kjun-type-display-md-line); font-weight: var(--_kjun-type-display-md-weight); letter-spacing: var(--_kjun-type-display-md-tracking); font-family: var(--_kjun-font-numeric); font-variant-numeric: tabular-nums; }
1387
+ .kjun-scope .kjun-type-display-lg { font-size: var(--_kjun-type-display-lg-size); line-height: var(--_kjun-type-display-lg-line); font-weight: var(--_kjun-type-display-lg-weight); letter-spacing: var(--_kjun-type-display-lg-tracking); font-family: var(--_kjun-font-numeric); font-variant-numeric: tabular-nums; }
1391
1388
 
1392
1389
  @keyframes kjun-price-flash-up {
1393
1390
  0%, 20% {
@@ -1948,37 +1945,6 @@
1948
1945
  height: var(--_kjun-extension-skeleton-table-line-height);
1949
1946
  }
1950
1947
 
1951
- /* Chart */
1952
- .kjun-skeleton-chart {
1953
- display: flex;
1954
- flex-direction: column;
1955
- padding: var(--_kjun-extension-skeleton-padding);
1956
- border: var(--_kjun-border-default-width) solid var(--_kjun-border-primary);
1957
- border-radius: var(--_kjun-extension-skeleton-radius);
1958
- background: var(--_kjun-bg-primary);
1959
- }
1960
-
1961
- .kjun-skeleton-chart-bars {
1962
- flex: 1;
1963
- display: flex;
1964
- align-items: flex-end;
1965
- justify-content: space-around;
1966
- gap: var(--_kjun-extension-skeleton-gap);
1967
- /* Bars stand on the axis line, like ChartSkeleton. */
1968
- }
1969
-
1970
- .kjun-skeleton-chart-bar {
1971
- flex: 1;
1972
- max-width: var(--_kjun-extension-skeleton-chart-bar-max-width);
1973
- background: var(--_kjun-skeleton);
1974
- border-radius: var(--_kjun-extension-skeleton-line-radius) var(--_kjun-geometry-radius-radius4) 0 0;
1975
- }
1976
-
1977
- .kjun-skeleton-chart-axis {
1978
- height: var(--_kjun-extension-skeleton-chart-axis-height);
1979
- background: var(--_kjun-border-primary);
1980
- }
1981
-
1982
1948
  /* Stat Card */
1983
1949
  .kjun-skeleton-stat {
1984
1950
  display: flex;
@@ -2019,7 +1985,6 @@
2019
1985
  /* Animation */
2020
1986
  .kjun-skeleton-animated .kjun-skeleton-line,
2021
1987
  .kjun-skeleton-animated .kjun-skeleton-avatar,
2022
- .kjun-skeleton-animated .kjun-skeleton-chart-bar,
2023
1988
  .kjun-skeleton-animated .kjun-skeleton-sparkline,
2024
1989
  .kjun-skeleton-animated .kjun-skeleton-block {
2025
1990
  background: linear-gradient(
@@ -2954,12 +2919,14 @@
2954
2919
  opacity: var(--_kjun-state-opacity-disabled);
2955
2920
  cursor: not-allowed;
2956
2921
  }
2957
- .kjun-icon-toggle svg {
2922
+ .kjun-icon-toggle svg:not([data-kjun-color-class]) {
2958
2923
  color: var(--_kjun-icon-toggle-color, currentColor);
2924
+ }
2925
+ .kjun-icon-toggle svg {
2959
2926
  transition: color var(--_kjun-motion-control) var(--_kjun-ease-out), transform var(--_kjun-motion-control) var(--_kjun-ease-out);
2960
2927
  }
2961
2928
  /* Like RefreshButton, an inactive icon darkens on hover; the selected color stays as set. */
2962
- .kjun-icon-toggle[aria-pressed="false"]:hover:not(:disabled) svg {
2929
+ .kjun-icon-toggle[aria-pressed="false"]:hover:not(:disabled) svg:not([data-kjun-color-class]) {
2963
2930
  color: var(--_kjun-color-text-secondary);
2964
2931
  }
2965
2932
  .kjun-icon-toggle:hover:not(:disabled) svg {
@@ -3112,7 +3079,7 @@
3112
3079
  }
3113
3080
  }
3114
3081
  .kjun-chart-skeleton {
3115
- position:relative;
3082
+ position: relative;
3116
3083
  display: flex;
3117
3084
  align-items: center;
3118
3085
  justify-content: center;
@@ -3120,6 +3087,14 @@
3120
3087
  min-width: 0;
3121
3088
  animation: kjun-chart-pulse var(--_kjun-motion-shimmer) ease-in-out infinite;
3122
3089
  }
3090
+ .kjun-chart-skeleton[data-kjun-chart-kind="donut"] {
3091
+ /* Only the donut label measures the hole against this box's height; size containment elsewhere would
3092
+ drop the frame's intrinsic width inside shrink-to-fit parents. */
3093
+ container-type: size;
3094
+ }
3095
+ .kjun-chart-skeleton[data-skeleton="false"] {
3096
+ animation: none;
3097
+ }
3123
3098
  .kjun-chart-skeleton-plot {
3124
3099
  width: 100%;
3125
3100
  height: 100%;
@@ -3129,9 +3104,19 @@
3129
3104
  aspect-ratio: 1;
3130
3105
  border: var(--_kjun-extension-chart-skeleton-donut-thickness) solid var(--_kjun-color-skeleton);
3131
3106
  border-radius: 50%;
3132
- display: flex;
3133
- align-items: center;
3134
- justify-content: center;
3107
+ }
3108
+ .kjun-chart-skeleton-matrix {
3109
+ display: grid;
3110
+ width: 100%;
3111
+ height: 100%;
3112
+ gap: var(--_kjun-geometry-dimension-value4);
3113
+ }
3114
+ .kjun-chart-skeleton-cell {
3115
+ background: var(--_kjun-color-skeleton);
3116
+ border-radius: var(--_kjun-extension-skeleton-line-radius);
3117
+ }
3118
+ .kjun-chart-skeleton-cell[data-muted] {
3119
+ opacity: var(--_kjun-state-opacity-pending);
3135
3120
  }
3136
3121
  @keyframes kjun-chart-pulse {
3137
3122
  50% {
@@ -3149,7 +3134,8 @@
3149
3134
  .kjun-error-fallback p { margin:var(--_kjun-geometry-dimension-value8) 0 var(--_kjun-geometry-dimension-value16); font-size:var(--_kjun-extension-state-description-size); line-height:var(--_kjun-type-caption-line); color:var(--_kjun-color-text-secondary); font-weight:var(--_kjun-type-caption-weight);letter-spacing:var(--_kjun-type-caption-tracking);}
3150
3135
 
3151
3136
  .kjun-chart-skeleton-status { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--_kjun-extension-skeleton-gap); pointer-events:none; }
3152
- .kjun-chart-skeleton-status>span { max-width:90%; padding:var(--_kjun-geometry-dimension-value4) var(--_kjun-geometry-dimension-value12); border-radius:var(--_kjun-geometry-radius-radius6); font-size:var(--_kjun-type-body-size); text-align:center; overflow-wrap:anywhere; background:var(--_kjun-color-surface); color:var(--_kjun-color-text-secondary); line-height: var(--_kjun-type-body-line); font-weight: var(--_kjun-type-body-weight); letter-spacing: var(--_kjun-type-body-tracking); }
3137
+ .kjun-chart-skeleton-status>span { max-width:90%; padding:var(--_kjun-geometry-dimension-value4) var(--_kjun-geometry-dimension-value12); border-radius:var(--_kjun-geometry-radius-radius6); font-size:var(--_kjun-type-body-size); text-align:center; overflow-wrap:anywhere; background:var(--_kjun-color-surface); color:var(--_kjun-color-text-secondary); line-height: var(--_kjun-type-body-line); font-weight: var(--_kjun-type-body-weight); letter-spacing: var(--_kjun-type-body-tracking); border:var(--_kjun-border-default-width) solid var(--_kjun-color-chart-grid); }
3138
+ .kjun-chart-skeleton[data-kjun-chart-kind="donut"] .kjun-chart-skeleton-status>span { border:0; max-width:calc(80cqh - 2 * var(--_kjun-extension-chart-skeleton-donut-thickness)); }
3153
3139
 
3154
3140
  .kjun-data-status > .kjun-spinner { flex-shrink: 0; }
3155
3141
  .kjun-data-status > span:last-child { min-width: 0; overflow-wrap: anywhere; }
@@ -4126,6 +4112,22 @@
4126
4112
  }
4127
4113
  }
4128
4114
 
4115
+ /* 좁은 화면에서 보조 지표가 셋 이상이면 두 열로 감싼다. 한 줄에 몰아 숫자가 자릿수 사이에서 끊기지 않게 한다. */
4116
+ @media (width <= 400px) {
4117
+ .kjun-kpi-hero:not(.kjun-kpi-hero--sm) .kjun-kpi-hero__secondary:has(> .kjun-kpi-hero__sec-item:nth-child(3)) {
4118
+ display: grid;
4119
+ grid-template-columns: repeat(2, minmax(0, 1fr));
4120
+ row-gap: var(--_kjun-extension-kpi-hero-mobile-secondary-padding);
4121
+ }
4122
+ .kjun-kpi-hero:not(.kjun-kpi-hero--sm) .kjun-kpi-hero__secondary:has(> .kjun-kpi-hero__sec-item:nth-child(3)) > .kjun-kpi-hero__sec-item:nth-child(odd) {
4123
+ padding-left: 0;
4124
+ border-left: none;
4125
+ }
4126
+ .kjun-kpi-hero:not(.kjun-kpi-hero--sm) .kjun-kpi-hero__secondary:has(> .kjun-kpi-hero__sec-item:nth-child(3)) > .kjun-kpi-hero__sec-item:nth-child(even) {
4127
+ padding-right: 0;
4128
+ }
4129
+ }
4130
+
4129
4131
  /* size=sm — 모달, 컴팩트 카드 내부용 */
4130
4132
  .kjun-kpi-hero--sm {
4131
4133
  padding: var(--_kjun-extension-kpi-hero-sm-padding-y) var(--_kjun-extension-kpi-hero-sm-padding-x);
@@ -4167,6 +4169,14 @@
4167
4169
  }
4168
4170
  }
4169
4171
 
4172
+ /* surface="none": 앱의 카드·모달·전폭 목록 안에서는 자체 카드 표면을 그리지 않는다. 미디어 규칙보다 뒤에 두어 좁은 화면에서도 이긴다. */
4173
+ /* 클래스를 겹쳐 모바일 규칙(.kjun-kpi-hero:not(.kjun-kpi-hero--sm))보다 명시도를 높인다. */
4174
+ .kjun-kpi-hero.kjun-kpi-hero[data-surface="none"] {
4175
+ padding: 0;
4176
+ background: transparent;
4177
+ border-radius: 0;
4178
+ }
4179
+
4170
4180
  .kjun-kpi-row {
4171
4181
  display: flex;
4172
4182
  padding: var(--_kjun-extension-kpi-row-md-padding-y) var(--_kjun-extension-kpi-row-md-padding-x);
@@ -4455,6 +4465,14 @@
4455
4465
  }
4456
4466
  }
4457
4467
 
4468
+ /* surface="none": 앱의 카드·모달·전폭 목록 안에서는 자체 카드 표면을 그리지 않는다. 미디어 규칙보다 뒤에 두어 좁은 화면에서도 이긴다. */
4469
+ /* 클래스를 겹쳐 모바일 요약 규칙(.kjun-kpi-row.kjun-kpi-row--mobile-summary:not(...))과 같은 명시도로 맞춘다. */
4470
+ .kjun-kpi-row.kjun-kpi-row[data-surface="none"] {
4471
+ padding: 0;
4472
+ background: transparent;
4473
+ border-radius: 0;
4474
+ }
4475
+
4458
4476
  .kjun-card {
4459
4477
  position: relative;
4460
4478
  min-width: 0;
@@ -19,6 +19,8 @@ export interface KjunDataStateProps extends QueryDisplayProps {
19
19
  emptyIcon?: string;
20
20
  emptyActionText?: string;
21
21
  loadingText?: string;
22
+ /** Milliseconds a first load must last before its loading display shows; the box keeps its space meanwhile. */
23
+ loadingDelay?: number;
22
24
  retryText?: string;
23
25
  size?: "sm" | "md" | "lg";
24
26
  skeleton?: boolean;
@@ -31,7 +33,7 @@ export interface KjunDataStateProps extends QueryDisplayProps {
31
33
  onRetry?: () => void;
32
34
  onEmptyAction?: () => void;
33
35
  }
34
- export declare function KjunDataState({ preserveContent, refreshing, refreshError, refreshingText, loadingPadding, empty, emptyText, emptyIcon, emptyActionText, loadingText, retryText, size, skeleton, skeletonType, skeletonCount, children, loadingContent, emptyContent, errorContent, onRetry, onEmptyAction, ...query }: KjunDataStateProps): import("react/jsx-runtime").JSX.Element;
36
+ export declare function KjunDataState({ preserveContent, refreshing, refreshError, refreshingText, loadingPadding, empty, emptyText, emptyIcon, emptyActionText, loadingText, loadingDelay, retryText, size, skeleton, skeletonType, skeletonCount, children, loadingContent, emptyContent, errorContent, onRetry, onEmptyAction, ...query }: KjunDataStateProps): import("react/jsx-runtime").JSX.Element;
35
37
  export interface KjunErrorBoundaryProps {
36
38
  children: ReactNode;
37
39
  fallbackMessage?: string;
@@ -19,6 +19,8 @@ export interface KjunDataStateProps extends QueryDisplayProps {
19
19
  emptyIcon?: string;
20
20
  emptyActionText?: string;
21
21
  loadingText?: string;
22
+ /** Milliseconds a first load must last before its loading display shows; the box keeps its space meanwhile. */
23
+ loadingDelay?: number;
22
24
  retryText?: string;
23
25
  size?: "sm" | "md" | "lg";
24
26
  skeleton?: boolean;
@@ -31,7 +33,7 @@ export interface KjunDataStateProps extends QueryDisplayProps {
31
33
  onRetry?: () => void;
32
34
  onEmptyAction?: () => void;
33
35
  }
34
- export declare function KjunDataState({ preserveContent, refreshing, refreshError, refreshingText, loadingPadding, empty, emptyText, emptyIcon, emptyActionText, loadingText, retryText, size, skeleton, skeletonType, skeletonCount, children, loadingContent, emptyContent, errorContent, onRetry, onEmptyAction, ...query }: KjunDataStateProps): import("react/jsx-runtime").JSX.Element;
36
+ export declare function KjunDataState({ preserveContent, refreshing, refreshError, refreshingText, loadingPadding, empty, emptyText, emptyIcon, emptyActionText, loadingText, loadingDelay, retryText, size, skeleton, skeletonType, skeletonCount, children, loadingContent, emptyContent, errorContent, onRetry, onEmptyAction, ...query }: KjunDataStateProps): import("react/jsx-runtime").JSX.Element;
35
37
  export interface KjunErrorBoundaryProps {
36
38
  children: ReactNode;
37
39
  fallbackMessage?: string;
@@ -27,6 +27,8 @@ export interface KjunKpiHeroProps {
27
27
  secondary?: KpiValue[];
28
28
  animated?: boolean;
29
29
  size?: "md" | "sm";
30
+ /** "none" drops the card background, padding and radius, for a KPI placed inside a card, modal or full-width list. */
31
+ surface?: "card" | "none";
30
32
  aside?: ReactNode;
31
33
  formatter?: (value: number) => string;
32
34
  deltaFormatter?: (value: number, kind: "absolute" | "percent") => string;
@@ -27,6 +27,8 @@ export interface KjunKpiHeroProps {
27
27
  secondary?: KpiValue[];
28
28
  animated?: boolean;
29
29
  size?: "md" | "sm";
30
+ /** "none" drops the card background, padding and radius, for a KPI placed inside a card, modal or full-width list. */
31
+ surface?: "card" | "none";
30
32
  aside?: ReactNode;
31
33
  formatter?: (value: number) => string;
32
34
  deltaFormatter?: (value: number, kind: "absolute" | "percent") => string;
@@ -25,8 +25,10 @@ export interface KjunKpiRowProps {
25
25
  loading?: boolean;
26
26
  items: KpiRowItem[];
27
27
  size?: "md" | "sm";
28
+ /** "none" drops the card background, padding and radius, for a KPI placed inside a card, modal or full-width list. */
29
+ surface?: "card" | "none";
28
30
  mobileSummary?: boolean;
29
31
  onItemClick?: (item: KpiRowItem, index: number) => void;
30
32
  renderValue?: (item: KpiRowItem, index: number) => ReactNode;
31
33
  }
32
- export declare function KjunKpiRow({ loading, items, size, mobileSummary, onItemClick, renderValue, }: KjunKpiRowProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function KjunKpiRow({ loading, items, size, surface, mobileSummary, onItemClick, renderValue, }: KjunKpiRowProps): import("react/jsx-runtime").JSX.Element;
@@ -25,8 +25,10 @@ export interface KjunKpiRowProps {
25
25
  loading?: boolean;
26
26
  items: KpiRowItem[];
27
27
  size?: "md" | "sm";
28
+ /** "none" drops the card background, padding and radius, for a KPI placed inside a card, modal or full-width list. */
29
+ surface?: "card" | "none";
28
30
  mobileSummary?: boolean;
29
31
  onItemClick?: (item: KpiRowItem, index: number) => void;
30
32
  renderValue?: (item: KpiRowItem, index: number) => ReactNode;
31
33
  }
32
- export declare function KjunKpiRow({ loading, items, size, mobileSummary, onItemClick, renderValue, }: KjunKpiRowProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function KjunKpiRow({ loading, items, size, surface, mobileSummary, onItemClick, renderValue, }: KjunKpiRowProps): import("react/jsx-runtime").JSX.Element;
@@ -17,6 +17,11 @@ export interface MarketBaseProps<Row extends object> extends QueryDisplayProps {
17
17
  subMeta?: (row: Row) => string;
18
18
  emptyMessage?: string;
19
19
  emptySubMessage?: string;
20
+ /** false shows the shared spinner and loadingText instead of the skeleton. Default true. */
21
+ skeleton?: boolean;
22
+ loadingText?: string;
23
+ /** Milliseconds a first load must last before its loading display shows. */
24
+ loadingDelay?: number;
20
25
  showFooter?: boolean;
21
26
  calculatedAt?: string | null;
22
27
  footerNote?: string;
@@ -17,6 +17,11 @@ export interface MarketBaseProps<Row extends object> extends QueryDisplayProps {
17
17
  subMeta?: (row: Row) => string;
18
18
  emptyMessage?: string;
19
19
  emptySubMessage?: string;
20
+ /** false shows the shared spinner and loadingText instead of the skeleton. Default true. */
21
+ skeleton?: boolean;
22
+ loadingText?: string;
23
+ /** Milliseconds a first load must last before its loading display shows. */
24
+ loadingDelay?: number;
20
25
  showFooter?: boolean;
21
26
  calculatedAt?: string | null;
22
27
  footerNote?: string;
@@ -1,6 +1,6 @@
1
1
  import { type DimensionValue } from "react-native";
2
2
  export interface KjunSkeletonProps {
3
- type?: "text" | "avatar" | "card" | "table" | "chart" | "stat" | "block";
3
+ type?: "text" | "avatar" | "card" | "table" | "stat" | "block";
4
4
  rows?: number;
5
5
  columns?: number;
6
6
  height?: DimensionValue;
@@ -1,6 +1,6 @@
1
1
  import { type DimensionValue } from "react-native";
2
2
  export interface KjunSkeletonProps {
3
- type?: "text" | "avatar" | "card" | "table" | "chart" | "stat" | "block";
3
+ type?: "text" | "avatar" | "card" | "table" | "stat" | "block";
4
4
  rows?: number;
5
5
  columns?: number;
6
6
  height?: DimensionValue;
@@ -1,5 +1,6 @@
1
1
  import { type InputSize } from "@kjun-ui/tokens";
2
2
  import { type DimensionValue } from "react-native";
3
+ import { type KjunChartSkeletonKind } from "../../../shared/package-runtime/chart-skeleton.cjs";
3
4
  export interface KjunListSkeletonProps {
4
5
  rows?: number;
5
6
  variant?: "market" | "compact" | "notification";
@@ -19,10 +20,14 @@ export interface KjunFormSkeletonProps {
19
20
  }
20
21
  export declare function KjunFormSkeleton({ fields, columns, multiline, size, }: KjunFormSkeletonProps): import("react/jsx-runtime").JSX.Element;
21
22
  export interface KjunChartSkeletonProps {
22
- loadingText?: string;
23
- kind?: "grid" | "line" | "bar" | "donut" | "candle" | "matrix";
23
+ kind?: KjunChartSkeletonKind;
24
24
  height?: DimensionValue;
25
+ loadingText?: string;
26
+ skeleton?: boolean;
27
+ loadingDelay?: number;
28
+ rows?: number;
29
+ columns?: number;
25
30
  }
26
- export declare function KjunChartSkeleton({ loadingText, kind, height, }: KjunChartSkeletonProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function KjunChartSkeleton({ kind, height, loadingText, skeleton, loadingDelay, rows, columns, }: KjunChartSkeletonProps): import("react/jsx-runtime").JSX.Element;
27
32
  export { KjunMarketTableSkeleton } from "./market-skeleton.cjs";
28
33
  export type { KjunMarketTableSkeletonProps } from "./market-skeleton.cjs";
@@ -1,5 +1,6 @@
1
1
  import { type InputSize } from "@kjun-ui/tokens";
2
2
  import { type DimensionValue } from "react-native";
3
+ import { type KjunChartSkeletonKind } from "../../../shared/package-runtime/chart-skeleton.js";
3
4
  export interface KjunListSkeletonProps {
4
5
  rows?: number;
5
6
  variant?: "market" | "compact" | "notification";
@@ -19,10 +20,14 @@ export interface KjunFormSkeletonProps {
19
20
  }
20
21
  export declare function KjunFormSkeleton({ fields, columns, multiline, size, }: KjunFormSkeletonProps): import("react/jsx-runtime").JSX.Element;
21
22
  export interface KjunChartSkeletonProps {
22
- loadingText?: string;
23
- kind?: "grid" | "line" | "bar" | "donut" | "candle" | "matrix";
23
+ kind?: KjunChartSkeletonKind;
24
24
  height?: DimensionValue;
25
+ loadingText?: string;
26
+ skeleton?: boolean;
27
+ loadingDelay?: number;
28
+ rows?: number;
29
+ columns?: number;
25
30
  }
26
- export declare function KjunChartSkeleton({ loadingText, kind, height, }: KjunChartSkeletonProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function KjunChartSkeleton({ kind, height, loadingText, skeleton, loadingDelay, rows, columns, }: KjunChartSkeletonProps): import("react/jsx-runtime").JSX.Element;
27
32
  export { KjunMarketTableSkeleton } from "./market-skeleton.js";
28
33
  export type { KjunMarketTableSkeletonProps } from "./market-skeleton.js";
@@ -1,2 +1,2 @@
1
1
  import type { TableCardsProps } from "../../../shared/package-runtime/table-presentation.cjs";
2
- export declare function TableCards<Row extends object>({ initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, layout }: TableCardsProps<Row>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function TableCards<Row extends object>({ initialLoading, skeletonRows, skeletonHidden, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, layout }: TableCardsProps<Row>): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { TableCardsProps } from "../../../shared/package-runtime/table-presentation.js";
2
- export declare function TableCards<Row extends object>({ initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, layout }: TableCardsProps<Row>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function TableCards<Row extends object>({ initialLoading, skeletonRows, skeletonHidden, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, layout }: TableCardsProps<Row>): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { TableGridProps } from "../../../shared/package-runtime/table-presentation.cjs";
2
- export declare function TableGrid<Row extends object>({ initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }: TableGridProps<Row, number>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function TableGrid<Row extends object>({ initialLoading, skeletonRows, skeletonHidden, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }: TableGridProps<Row, number>): import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
1
  import type { TableGridProps } from "../../../shared/package-runtime/table-presentation.js";
2
- export declare function TableGrid<Row extends object>({ initialLoading, skeletonRows, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }: TableGridProps<Row, number>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function TableGrid<Row extends object>({ initialLoading, skeletonRows, skeletonHidden, state, onRowClick, selectable, checkbox, cell, expandable, expand, renderExpand, emptyContent, emptyText, visible, maxHeight, stickyHeader, sortable, compact, striped, hoverable }: TableGridProps<Row, number>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ export type KjunChartSkeletonKind = "frame" | "donut" | "matrix";
2
+ /** Axes plus three horizontal grid lines in the frame's 600×240 viewBox. */
3
+ export declare const chartFrameViewBox = "0 0 600 240";
4
+ export declare const chartFramePath = "M20 10V220H590 M20 65H590 M20 120H590 M20 175H590";
5
+ /** Upper bound for matrix rows and columns, so counts derived from data never render an unbounded grid. */
6
+ export declare const chartSkeletonMaxCount = 100;
7
+ /** Matrix rows and columns: finite values floor into 1–100; anything else is 1. */
8
+ export declare function chartSkeletonCount(value: number): number;
9
+ /** Every third diagonal cell is drawn at the pending opacity so the matrix reads as a heatmap. */
10
+ export declare function chartMatrixMuted(row: number, column: number): boolean;
11
+ /** Inner diameter of the donut ring, which is 80% of the skeleton height. */
12
+ export declare function chartDonutHole(height: number, thickness: number): number;
@@ -0,0 +1,12 @@
1
+ export type KjunChartSkeletonKind = "frame" | "donut" | "matrix";
2
+ /** Axes plus three horizontal grid lines in the frame's 600×240 viewBox. */
3
+ export declare const chartFrameViewBox = "0 0 600 240";
4
+ export declare const chartFramePath = "M20 10V220H590 M20 65H590 M20 120H590 M20 175H590";
5
+ /** Upper bound for matrix rows and columns, so counts derived from data never render an unbounded grid. */
6
+ export declare const chartSkeletonMaxCount = 100;
7
+ /** Matrix rows and columns: finite values floor into 1–100; anything else is 1. */
8
+ export declare function chartSkeletonCount(value: number): number;
9
+ /** Every third diagonal cell is drawn at the pending opacity so the matrix reads as a heatmap. */
10
+ export declare function chartMatrixMuted(row: number, column: number): boolean;
11
+ /** Inner diameter of the donut ring, which is 80% of the skeleton height. */
12
+ export declare function chartDonutHole(height: number, thickness: number): number;
@@ -18,6 +18,8 @@ export declare function tableCellValue<Row extends object>(props: TableProps<Row
18
18
  export interface TableRowsProps<Row extends object> {
19
19
  initialLoading: boolean;
20
20
  skeletonRows: number;
21
+ /** A loadingDelay is still running: the skeleton keeps its space but stays out of sight. */
22
+ skeletonHidden?: boolean;
21
23
  state: Pick<ReturnType<typeof useTableModel<Row>>, "rows" | "key" | "expanded" | "selectedRow">;
22
24
  onRowClick: TableProps<Row>["onRowClick"];
23
25
  selectable: boolean;
@@ -18,6 +18,8 @@ export declare function tableCellValue<Row extends object>(props: TableProps<Row
18
18
  export interface TableRowsProps<Row extends object> {
19
19
  initialLoading: boolean;
20
20
  skeletonRows: number;
21
+ /** A loadingDelay is still running: the skeleton keeps its space but stays out of sight. */
22
+ skeletonHidden?: boolean;
21
23
  state: Pick<ReturnType<typeof useTableModel<Row>>, "rows" | "key" | "expanded" | "selectedRow">;
22
24
  onRowClick: TableProps<Row>["onRowClick"];
23
25
  selectable: boolean;
@@ -38,6 +38,11 @@ export interface TableProps<Row extends object = Record<string, unknown>, MaxHei
38
38
  data?: Row[];
39
39
  rowKey?: string;
40
40
  skeletonRows?: number;
41
+ /** false shows the shared spinner and loadingText instead of skeleton rows. Default true. */
42
+ skeleton?: boolean;
43
+ loadingText?: string;
44
+ /** Milliseconds a first load must last before its loading display shows. */
45
+ loadingDelay?: number;
41
46
  emptyText?: string;
42
47
  sortable?: boolean;
43
48
  sort?: TableSort | null;
@@ -38,6 +38,11 @@ export interface TableProps<Row extends object = Record<string, unknown>, MaxHei
38
38
  data?: Row[];
39
39
  rowKey?: string;
40
40
  skeletonRows?: number;
41
+ /** false shows the shared spinner and loadingText instead of skeleton rows. Default true. */
42
+ skeleton?: boolean;
43
+ loadingText?: string;
44
+ /** Milliseconds a first load must last before its loading display shows. */
45
+ loadingDelay?: number;
41
46
  emptyText?: string;
42
47
  sortable?: boolean;
43
48
  sort?: TableSort | null;
@@ -0,0 +1,2 @@
1
+ /** True once a loading state has lasted `delay` ms, so a fast result never flashes the loading display. Always true without a delay. */
2
+ export declare function useLoadingReveal(active: boolean, delay?: number): boolean;
@@ -0,0 +1,2 @@
1
+ /** True once a loading state has lasted `delay` ms, so a fast result never flashes the loading display. Always true without a delay. */
2
+ export declare function useLoadingReveal(active: boolean, delay?: number): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kjun-ui/native",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "homepage": "https://ui.kjun.dev",
6
6
  "repository": {
@@ -47,8 +47,8 @@
47
47
  "./package.json": "./package.json"
48
48
  },
49
49
  "dependencies": {
50
- "@kjun-ui/tokens": "0.6.1",
51
- "@kjun-ui/icons": "0.6.1"
50
+ "@kjun-ui/tokens": "0.8.0",
51
+ "@kjun-ui/icons": "0.8.0"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "react": "^19.2.3",