@kjun-ui/native 0.12.2 → 0.14.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 (58) hide show
  1. package/dist/index.cjs +2822 -2219
  2. package/dist/index.js +2236 -1635
  3. package/dist/index.web.cjs +2839 -2236
  4. package/dist/index.web.js +2238 -1637
  5. package/dist/styles.css +102 -3
  6. package/dist/types/packages/native/src/button.d.cts +2 -0
  7. package/dist/types/packages/native/src/button.d.ts +2 -0
  8. package/dist/types/packages/native/src/card.d.cts +9 -2
  9. package/dist/types/packages/native/src/card.d.ts +9 -2
  10. package/dist/types/packages/native/src/choice-controls.d.cts +3 -1
  11. package/dist/types/packages/native/src/choice-controls.d.ts +3 -1
  12. package/dist/types/packages/native/src/data-state.d.cts +3 -0
  13. package/dist/types/packages/native/src/data-state.d.ts +3 -0
  14. package/dist/types/packages/native/src/date-picker.d.cts +3 -1
  15. package/dist/types/packages/native/src/date-picker.d.ts +3 -1
  16. package/dist/types/packages/native/src/display-primitives.d.cts +2 -1
  17. package/dist/types/packages/native/src/display-primitives.d.ts +2 -1
  18. package/dist/types/packages/native/src/fab.d.cts +14 -0
  19. package/dist/types/packages/native/src/fab.d.ts +14 -0
  20. package/dist/types/packages/native/src/feedback.d.cts +5 -1
  21. package/dist/types/packages/native/src/feedback.d.ts +5 -1
  22. package/dist/types/packages/native/src/field-surface.d.cts +1 -0
  23. package/dist/types/packages/native/src/field-surface.d.ts +1 -0
  24. package/dist/types/packages/native/src/financial-display.d.cts +8 -8
  25. package/dist/types/packages/native/src/financial-display.d.ts +8 -8
  26. package/dist/types/packages/native/src/fonts.d.cts +14 -0
  27. package/dist/types/packages/native/src/fonts.d.ts +14 -0
  28. package/dist/types/packages/native/src/index.d.cts +2 -0
  29. package/dist/types/packages/native/src/index.d.ts +2 -0
  30. package/dist/types/packages/native/src/input.d.cts +3 -1
  31. package/dist/types/packages/native/src/input.d.ts +3 -1
  32. package/dist/types/packages/native/src/internal.d.cts +4 -0
  33. package/dist/types/packages/native/src/internal.d.ts +4 -0
  34. package/dist/types/packages/native/src/list.d.cts +17 -2
  35. package/dist/types/packages/native/src/list.d.ts +17 -2
  36. package/dist/types/packages/native/src/media.d.cts +4 -2
  37. package/dist/types/packages/native/src/media.d.ts +4 -2
  38. package/dist/types/packages/native/src/provider.d.cts +14 -2
  39. package/dist/types/packages/native/src/provider.d.ts +14 -2
  40. package/dist/types/shared/package-runtime/feedback-dialog.d.cts +2 -1
  41. package/dist/types/shared/package-runtime/feedback-dialog.d.ts +2 -1
  42. package/dist/types/shared/package-runtime/layout-primitives.d.cts +1 -1
  43. package/dist/types/shared/package-runtime/layout-primitives.d.ts +1 -1
  44. package/dist/types/shared/package-runtime/messages/en.d.cts +2 -0
  45. package/dist/types/shared/package-runtime/messages/en.d.ts +2 -0
  46. package/dist/types/shared/package-runtime/messages/index.d.cts +26 -0
  47. package/dist/types/shared/package-runtime/messages/index.d.ts +26 -0
  48. package/dist/types/shared/package-runtime/messages/ko.d.cts +116 -0
  49. package/dist/types/shared/package-runtime/messages/ko.d.ts +116 -0
  50. package/dist/types/shared/package-runtime/messages-context.d.cts +124 -0
  51. package/dist/types/shared/package-runtime/messages-context.d.ts +124 -0
  52. package/dist/types/shared/package-runtime/options.d.cts +4 -2
  53. package/dist/types/shared/package-runtime/options.d.ts +4 -2
  54. package/dist/types/shared/package-runtime/progress-circle.d.cts +11 -0
  55. package/dist/types/shared/package-runtime/progress-circle.d.ts +11 -0
  56. package/dist/types/shared/package-runtime/relative-time.d.cts +1 -1
  57. package/dist/types/shared/package-runtime/relative-time.d.ts +1 -1
  58. package/package.json +3 -3
package/dist/styles.css CHANGED
@@ -78,6 +78,7 @@
78
78
  --_kjun-color-brand-light: var(--kjun-brand-light, var(--kjun-border));
79
79
  --_kjun-color-selected-bg: var(--kjun-selected-bg, var(--kjun-active));
80
80
  --_kjun-color-on-brand: var(--kjun-on-brand, var(--kjun-inverse));
81
+ --_kjun-color-switch-thumb-on: var(--kjun-switch-thumb-on, var(--kjun-on-brand, var(--kjun-inverse)));
81
82
  --_kjun-color-on-danger: var(--kjun-on-danger, var(--kjun-inverse));
82
83
  --_kjun-color-on-success: var(--kjun-on-success, var(--kjun-inverse));
83
84
  --_kjun-color-on-warning: var(--kjun-on-warning, var(--kjun-inverse));
@@ -180,6 +181,7 @@
180
181
  --_kjun-brand-light: var(--_kjun-color-brand-light);
181
182
  --_kjun-selected-bg: var(--_kjun-color-selected-bg);
182
183
  --_kjun-on-brand: var(--_kjun-color-on-brand);
184
+ --_kjun-switch-thumb-on: var(--_kjun-color-switch-thumb-on);
183
185
  --_kjun-on-danger: var(--_kjun-color-on-danger);
184
186
  --_kjun-on-success: var(--_kjun-color-on-success);
185
187
  --_kjun-on-warning: var(--_kjun-color-on-warning);
@@ -256,9 +258,14 @@
256
258
  --_kjun-extension-state-padding-sm: 24px;
257
259
  --_kjun-extension-state-padding-md: 48px;
258
260
  --_kjun-extension-state-padding-lg: 80px;
261
+ --_kjun-extension-fab-size: 56px;
262
+ --_kjun-extension-fab-inset: 16px;
263
+ --_kjun-extension-fab-icon-size: 24px;
259
264
  --_kjun-extension-list-padding: 16px;
260
265
  --_kjun-extension-list-gap: 12px;
261
266
  --_kjun-extension-list-minimum-height: 56px;
267
+ --_kjun-extension-list-compact-minimum-height: 44px;
268
+ --_kjun-extension-list-compact-padding-y: 12px;
262
269
  --_kjun-extension-list-description-gap: 4px;
263
270
  --_kjun-extension-list-actions-gap: 8px;
264
271
  --_kjun-extension-list-actions-padding: 16px;
@@ -647,6 +654,12 @@
647
654
  --_kjun-extension-progress-heights-sm: 4px;
648
655
  --_kjun-extension-progress-heights-md: 8px;
649
656
  --_kjun-extension-progress-heights-lg: 12px;
657
+ --_kjun-extension-progress-circle-sm-size: 24px;
658
+ --_kjun-extension-progress-circle-sm-stroke: 4px;
659
+ --_kjun-extension-progress-circle-md-size: 48px;
660
+ --_kjun-extension-progress-circle-md-stroke: 4px;
661
+ --_kjun-extension-progress-circle-lg-size: 64px;
662
+ --_kjun-extension-progress-circle-lg-stroke: 6px;
650
663
  --_kjun-extension-icon-toggle-compact-size: 24px;
651
664
  --_kjun-extension-icon-toggle-sizes-xs: 24px;
652
665
  --_kjun-extension-icon-toggle-sizes-sm: 24px;
@@ -1255,6 +1268,11 @@
1255
1268
  .kjun-scope .kjun-choice:not(.kjun-choice--disabled):active .kjun-radio,
1256
1269
  .kjun-scope .kjun-choice:not(.kjun-choice--disabled) input:active + .kjun-radio { border-color: var(--_kjun-brand-active); }
1257
1270
  .kjun-scope .kjun-switch + .kjun-choice-label { margin-left: var(--_kjun-extension-switch-label-gap); }
1271
+ /* A switch description sits under its label and starts where the label starts. */
1272
+ .kjun-scope .kjun-choice-text { display: flex; flex-direction: column; min-width: 0; }
1273
+ .kjun-scope .kjun-switch + .kjun-choice-text { margin-left: var(--_kjun-extension-switch-label-gap); }
1274
+ .kjun-scope .kjun-choice-text > .kjun-choice-label { margin-left: 0; }
1275
+ .kjun-scope .kjun-choice-description { margin-top: var(--_kjun-geometry-dimension-value4); font-size: var(--_kjun-type-caption-size); line-height: var(--_kjun-type-caption-line); font-weight: var(--_kjun-type-caption-weight); letter-spacing: var(--_kjun-type-caption-tracking); color: var(--_kjun-color-text-secondary); }
1258
1276
  .kjun-scope .kjun-switch {
1259
1277
  position: relative;
1260
1278
  flex-shrink: 0;
@@ -1289,7 +1307,7 @@
1289
1307
  .kjun-scope .kjun-switch--on .kjun-switch-thumb {
1290
1308
  --_kjun-switch-thumb-inset: var(--_kjun-extension-switch-padding);
1291
1309
  margin: 0;
1292
- background: var(--_kjun-on-brand);
1310
+ background: var(--_kjun-switch-thumb-on);
1293
1311
  transform: translateX(calc(var(--_kjun-switch-width) - var(--_kjun-switch-height)));
1294
1312
  }
1295
1313
 
@@ -1506,6 +1524,10 @@
1506
1524
  .kjun-button[data-variant="secondary"]:active:not(:disabled) {
1507
1525
  background: var(--_kjun-color-button-secondary-active);
1508
1526
  }
1527
+ /* A link button hugs its text: no fill, no inset, the brand ink, underlined on hover and keyboard focus. */
1528
+ .kjun-button[data-variant="link"] { background: transparent; color: var(--_kjun-color-brand); }
1529
+ .kjun-button[data-variant="link"]:is(:hover, [data-focus-visible], :focus-visible):not(:disabled) { text-decoration: underline; }
1530
+ .kjun-button[data-variant="link"]:active:not(:disabled) { color: var(--_kjun-color-brand-active); }
1509
1531
  .kjun-button[data-variant="ghost"],
1510
1532
  .kjun-button[data-variant="danger-ghost"] {
1511
1533
  background: transparent;
@@ -1592,6 +1614,7 @@
1592
1614
  .kjun-form-group:last-child {
1593
1615
  margin-bottom: 0;
1594
1616
  }
1617
+ .kjun-form-optional { color: var(--_kjun-color-text-tertiary); font-weight: var(--_kjun-type-caption-weight); }
1595
1618
  .kjun-form-label {
1596
1619
  display: block;
1597
1620
  font-size: var(--_kjun-type-label-size);
@@ -2211,8 +2234,50 @@
2211
2234
  font-weight: var(--_kjun-type-caption-weight);
2212
2235
  letter-spacing: var(--_kjun-type-caption-tracking);
2213
2236
  }
2237
+ /* Circle progress: circle, then label and subLabel centred below it. */
2238
+ .kjun-progress[data-shape="circle"] {
2239
+ display: inline-flex;
2240
+ flex-direction: column;
2241
+ align-items: center;
2242
+ text-align: center;
2243
+ }
2244
+ .kjun-progress-circle {
2245
+ position: relative;
2246
+ display: flex;
2247
+ align-items: center;
2248
+ justify-content: center;
2249
+ flex-shrink: 0;
2250
+ }
2251
+ .kjun-progress-circle > svg { position: absolute; inset: 0; display: block; }
2252
+ .kjun-progress-circle-track { stroke: var(--_kjun-color-secondary); }
2253
+ .kjun-progress-circle-value { transition: stroke-dashoffset var(--_kjun-motion-progress) var(--_kjun-ease-out); }
2254
+ .kjun-progress-circle-percent {
2255
+ position: relative;
2256
+ font-family: var(--_kjun-font-numeric);
2257
+ font-variant-numeric: tabular-nums;
2258
+ color: var(--_kjun-color-text);
2259
+ font-size: var(--_kjun-type-meta-size);
2260
+ line-height: var(--_kjun-type-meta-line);
2261
+ font-weight: var(--_kjun-type-meta-weight);
2262
+ letter-spacing: var(--_kjun-type-meta-tracking);
2263
+ }
2264
+ .kjun-progress[data-size="lg"] .kjun-progress-circle-percent {
2265
+ font-size: var(--_kjun-type-number-md-size);
2266
+ line-height: var(--_kjun-type-number-md-line);
2267
+ font-weight: var(--_kjun-type-number-md-weight);
2268
+ letter-spacing: var(--_kjun-type-number-md-tracking);
2269
+ }
2270
+ .kjun-progress-circle-label {
2271
+ margin-top: var(--_kjun-geometry-dimension-value8);
2272
+ font-size: var(--_kjun-type-caption-size);
2273
+ color: var(--_kjun-color-text-secondary);
2274
+ line-height: var(--_kjun-type-caption-line);
2275
+ font-weight: var(--_kjun-type-caption-weight);
2276
+ letter-spacing: var(--_kjun-type-caption-tracking);
2277
+ }
2214
2278
  @media (prefers-reduced-motion: reduce) {
2215
2279
  .kjun-progress-track > div,
2280
+ .kjun-progress-circle-value,
2216
2281
  .kjun-card {
2217
2282
  transition: none;
2218
2283
  }
@@ -2273,18 +2338,22 @@
2273
2338
  cursor: pointer;
2274
2339
  transition: color var(--_kjun-motion-indicator) var(--_kjun-ease-out);
2275
2340
  }
2341
+ /* The selected segment carries an inset edge so it reads apart from the track even when surface and
2342
+ secondary are close (light palettes). Inset keeps the segment's size. */
2276
2343
  .kjun-button-group button[aria-pressed="true"] {
2277
2344
  background: var(--_kjun-color-surface);
2345
+ box-shadow: inset 0 0 0 var(--_kjun-border-default-width) var(--_kjun-color-border);
2278
2346
  color: var(--_kjun-color-text);
2279
2347
  font-weight: var(--_kjun-type-control-weight);
2280
2348
  }
2281
- .kjun-button-group[data-indicator] button[aria-pressed="true"] { background: transparent; }
2349
+ .kjun-button-group[data-indicator] button[aria-pressed="true"] { background: transparent; box-shadow: none; }
2282
2350
  .kjun-button-group-indicator {
2283
2351
  position: absolute;
2284
2352
  left: 0;
2285
2353
  pointer-events: none;
2286
2354
  border-radius: var(--_kjun-geometry-button-group-item-radii-md);
2287
2355
  background: var(--_kjun-color-surface);
2356
+ box-shadow: inset 0 0 0 var(--_kjun-border-default-width) var(--_kjun-color-border);
2288
2357
  }
2289
2358
  .kjun-button-group-indicator[data-animate="true"] {
2290
2359
  transition: transform var(--_kjun-motion-indicator) var(--_kjun-ease-out), width var(--_kjun-motion-indicator) var(--_kjun-ease-out);
@@ -4574,6 +4643,13 @@
4574
4643
  .kjun-card[data-dividers="false"] > .kjun-card-header + .kjun-card-footer { padding-top: 0; }
4575
4644
  .kjun-card[data-dividers="true"] > .kjun-card-header:has(+ .kjun-card-body) { border-bottom: var(--_kjun-border-default-width) solid var(--_kjun-card-border); }
4576
4645
  .kjun-card[data-dividers="true"] > .kjun-card-footer:not(:first-child) { border-top: var(--_kjun-border-default-width) solid var(--_kjun-card-border); }
4646
+ /* A pressable card is one button: it lifts on hover, presses in on activation and shows the focus ring. */
4647
+ .kjun-card[data-pressable] { box-shadow: var(--_kjun-card-shadow); cursor: pointer; transition: box-shadow var(--_kjun-motion-control) var(--_kjun-ease-out), transform var(--_kjun-motion-control) var(--_kjun-ease-out); }
4648
+ .kjun-card[data-pressable]:hover:not([aria-disabled="true"]) { box-shadow: var(--_kjun-elevation-floating); }
4649
+ .kjun-card[data-pressable]:active:not([aria-disabled="true"]) { transform: scale(0.99); }
4650
+ .kjun-card[data-pressable]:focus-visible { outline: var(--_kjun-state-focus-width) solid var(--_kjun-color-focus-ring); outline-offset: var(--_kjun-state-focus-offset); }
4651
+ .kjun-card[data-pressable][aria-disabled="true"] { cursor: not-allowed; opacity: var(--_kjun-state-opacity-disabled); }
4652
+ @media (prefers-reduced-motion: reduce) { .kjun-card[data-pressable] { transition: none; } .kjun-card[data-pressable]:active { transform: none; } }
4577
4653
 
4578
4654
  .kjun-toast-stack {
4579
4655
  position: fixed;
@@ -4724,7 +4800,7 @@
4724
4800
 
4725
4801
  .kjun-list-section,.kjun-top-navigation,.kjun-bottom-navigation,.kjun-bottom-action-bar{min-width:0;max-width:100%;color:var(--_kjun-color-text);background:var(--_kjun-color-surface)}
4726
4802
  .kjun-list-heading{display:flex;align-items:center;justify-content:space-between;gap:var(--_kjun-extension-list-gap);padding:var(--_kjun-extension-list-padding)}.kjun-list-heading h3{font-size:var(--_kjun-type-card-title-size);margin:0;line-height:var(--_kjun-type-card-title-line);font-weight:var(--_kjun-type-card-title-weight);letter-spacing:var(--_kjun-type-card-title-tracking)}.kjun-list-heading p{margin:var(--_kjun-geometry-dimension-value4) 0 0;font-size:var(--_kjun-type-caption-size);color:var(--_kjun-color-text-secondary);overflow-wrap:anywhere;line-height:var(--_kjun-type-caption-line);font-weight:var(--_kjun-type-caption-weight);letter-spacing:var(--_kjun-type-caption-tracking)}
4727
- .kjun-list{list-style:none;padding:0;margin:0}.kjun-list-row{display:flex;align-items:center;gap:var(--_kjun-extension-list-gap);border-bottom:var(--_kjun-border-default-width) solid var(--_kjun-color-divider);min-width:0}.kjun-list-row:last-child{border-bottom:0}.kjun-list-main{display:flex;align-items:center;gap:var(--_kjun-extension-list-gap);flex:1;min-width:0;min-height:var(--_kjun-extension-list-minimum-height);padding:var(--_kjun-extension-list-padding);text-align:start;color:inherit;text-decoration:none;background:transparent;border:0;font:inherit}.kjun-list-main:is(button,a):hover{background:var(--_kjun-color-hover)}.kjun-list-body{flex:1;min-width:0}.kjun-list-title,.kjun-list-description{display:block;overflow-wrap:anywhere;line-height:1.5}.kjun-list-title{font-size:var(--_kjun-type-label-size);line-height:var(--_kjun-type-label-line);font-weight:var(--_kjun-type-label-weight);letter-spacing:var(--_kjun-type-label-tracking)}.kjun-list-description{font-size:var(--_kjun-type-caption-size);color:var(--_kjun-color-text-secondary);line-height:var(--_kjun-type-caption-line);font-weight:var(--_kjun-type-caption-weight);letter-spacing:var(--_kjun-type-caption-tracking)}.kjun-list-leading{flex-shrink:0}.kjun-list-trailing{overflow-wrap:anywhere;max-width:35%}.kjun-list-actions{display:flex;flex-wrap:wrap;gap:var(--_kjun-extension-list-actions-gap);padding-inline-end:var(--_kjun-extension-list-actions-padding);max-width:45%}
4803
+ .kjun-list{list-style:none;padding:0;margin:0}.kjun-list-row{display:flex;align-items:center;gap:var(--_kjun-extension-list-gap);border-bottom:var(--_kjun-border-default-width) solid var(--_kjun-color-divider);min-width:0}.kjun-list-row:last-child{border-bottom:0}.kjun-list[data-divider=false]>.kjun-list-row{border-bottom:0}.kjun-list[data-density=compact] .kjun-list-main{min-height:var(--_kjun-extension-list-compact-minimum-height);padding-block:var(--_kjun-extension-list-compact-padding-y)}.kjun-list-main{display:flex;align-items:center;gap:var(--_kjun-extension-list-gap);flex:1;min-width:0;min-height:var(--_kjun-extension-list-minimum-height);padding:var(--_kjun-extension-list-padding);text-align:start;color:inherit;text-decoration:none;background:transparent;border:0;font:inherit}.kjun-list-main:is(button,a):hover{background:var(--_kjun-color-hover)}.kjun-list-body{flex:1;min-width:0}.kjun-list-title,.kjun-list-description{display:block;overflow-wrap:anywhere;line-height:1.5}.kjun-list-title{font-size:var(--_kjun-type-label-size);line-height:var(--_kjun-type-label-line);font-weight:var(--_kjun-type-label-weight);letter-spacing:var(--_kjun-type-label-tracking)}.kjun-list-description{font-size:var(--_kjun-type-caption-size);color:var(--_kjun-color-text-secondary);line-height:var(--_kjun-type-caption-line);font-weight:var(--_kjun-type-caption-weight);letter-spacing:var(--_kjun-type-caption-tracking)}.kjun-list-leading{flex-shrink:0}.kjun-list-trailing{overflow-wrap:anywhere;max-width:35%}.kjun-list-actions{display:flex;flex-wrap:wrap;gap:var(--_kjun-extension-list-actions-gap);padding-inline-end:var(--_kjun-extension-list-actions-padding);max-width:45%}
4728
4804
  /* A disabled row disables its actions too, so the row never reads as partly available. */
4729
4805
  .kjun-list-actions[data-disabled]{opacity:var(--_kjun-state-opacity-disabled)}
4730
4806
  .kjun-navigation-actions{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:var(--_kjun-extension-navigation-actions-gap);min-width:0}
@@ -4733,6 +4809,8 @@
4733
4809
  .kjun-avatar .kjun-image-fallback{text-transform:uppercase;font-size:var(--_kjun-type-input-size);line-height:var(--_kjun-type-input-line)}
4734
4810
  .kjun-avatar[data-size=sm] .kjun-image-fallback{font-size:var(--_kjun-type-control-size);line-height:var(--_kjun-type-control-line)}
4735
4811
  .kjun-avatar[data-size=lg] .kjun-image-fallback{font-size:var(--_kjun-type-section-title-size);line-height:var(--_kjun-type-section-title-line)}.kjun-avatar[data-shape=square]{border-radius:var(--_kjun-geometry-radius-radius8)}
4812
+ /* App colors (color/textColor) arrive as private custom properties; without them the image roles stay. */
4813
+ .kjun-avatar .kjun-image{background:var(--_kjun-avatar-color,var(--_kjun-color-secondary))}.kjun-avatar .kjun-image-fallback{color:var(--_kjun-avatar-text-color,var(--_kjun-color-text-secondary))}
4736
4814
  .kjun-chip{--_kjun-chip-remove-icon:var(--_kjun-extension-chip-remove-icon-sizes-md);display:inline-flex;max-width:100%;align-items:center;gap:var(--_kjun-extension-chip-gap);min-height:var(--_kjun-extension-chip-md);padding:var(--_kjun-extension-chip-padding-y) var(--_kjun-extension-chip-padding-x);border-radius:var(--_kjun-extension-chip-radius);background:var(--_kjun-color-secondary);font-size:var(--_kjun-extension-chip-typography-md-font-size-px);line-height:var(--_kjun-extension-chip-typography-md-line-height-px);font-weight:var(--_kjun-extension-chip-typography-md-font-weight);letter-spacing:var(--_kjun-extension-chip-typography-md-letter-spacing-em)}
4737
4815
  .kjun-chip>span{overflow-wrap:anywhere;min-width:0}
4738
4816
  .kjun-chip[data-size=sm]{--_kjun-chip-remove-icon:var(--_kjun-extension-chip-remove-icon-sizes-sm);min-height:var(--_kjun-extension-chip-sm);font-size:var(--_kjun-extension-chip-typography-sm-font-size-px);line-height:var(--_kjun-extension-chip-typography-sm-line-height-px);font-weight:var(--_kjun-extension-chip-typography-sm-font-weight);letter-spacing:var(--_kjun-extension-chip-typography-sm-letter-spacing-em)}
@@ -4937,6 +5015,21 @@
4937
5015
 
4938
5016
  .kjun-list-heading > div { flex:1; min-width:0; overflow-wrap:anywhere; }
4939
5017
 
5018
+ /* KjunFab: a round action pinned to the viewport's bottom end, above page content and clear of the safe area. */
5019
+ .kjun-fab{position:fixed;right:var(--_kjun-extension-fab-inset);z-index:var(--_kjun-layer-page-navigation);display:inline-flex;align-items:center;justify-content:center;width:var(--_kjun-extension-fab-size);height:var(--_kjun-extension-fab-size);padding:0;border:0;border-radius:50%;background:var(--_kjun-color-brand);color:var(--_kjun-color-on-brand);box-shadow:var(--_kjun-elevation-floating);cursor:pointer}
5020
+ .kjun-fab:hover:not(:disabled){background:var(--_kjun-color-brand-hover)}.kjun-fab:active:not(:disabled){background:var(--_kjun-color-brand-active)}
5021
+ .kjun-fab:focus-visible{outline:var(--_kjun-state-focus-width) solid var(--_kjun-color-focus-ring);outline-offset:var(--_kjun-state-focus-offset)}
5022
+ .kjun-fab:disabled{opacity:var(--_kjun-state-opacity-disabled);cursor:not-allowed}
5023
+
5024
+ /* 0.14.0: plain sections, destructive rows, decorative chevrons and non-row list items share the row inset. */
5025
+ .kjun-list-section[data-surface="false"]{background:transparent}
5026
+ .kjun-list-row[data-destructive] .kjun-list-title{color:var(--_kjun-color-danger)}
5027
+ .kjun-list-chevron{flex-shrink:0;color:var(--_kjun-color-text-tertiary)}
5028
+ .kjun-list-item{padding:var(--_kjun-extension-list-padding);border-bottom:var(--_kjun-border-default-width) solid var(--_kjun-color-divider);min-width:0}
5029
+ .kjun-list-item:last-child{border-bottom:0}
5030
+ .kjun-list[data-divider=false]>.kjun-list-item{border-bottom:0}
5031
+ .kjun-list[data-density=compact]>.kjun-list-item{padding-block:var(--_kjun-extension-list-compact-padding-y)}
5032
+
4940
5033
  /* Compound fields share input geometry; buttons retain their own size contract. */
4941
5034
  .kjun-quantity,.kjun-time-picker {
4942
5035
  --_kjun-compound-height: var(--_kjun-geometry-input-md-height);
@@ -5133,6 +5226,12 @@
5133
5226
  .kjun-text.kjun-text[data-tone="secondary"] { color: var(--_kjun-color-text-secondary); }
5134
5227
  .kjun-text.kjun-text[data-tone="tertiary"] { color: var(--_kjun-color-text-tertiary); }
5135
5228
  .kjun-text.kjun-text[data-tone="disabled"] { color: var(--_kjun-color-text-disabled); }
5229
+ .kjun-text.kjun-text[data-tone="brand"] { color: var(--_kjun-color-brand); }
5230
+ .kjun-text.kjun-text[data-tone="danger"] { color: var(--_kjun-color-danger); }
5231
+ .kjun-text.kjun-text[data-tone="success"] { color: var(--_kjun-color-success); }
5232
+ .kjun-text.kjun-text[data-tone="warning"] { color: var(--_kjun-color-warning); }
5233
+ /* inverse is text on the brand surface. */
5234
+ .kjun-text.kjun-text[data-tone="inverse"] { color: var(--_kjun-color-on-brand); }
5136
5235
  .kjun-text[data-align="start"] { text-align: start; }
5137
5236
  .kjun-text[data-align="center"] { text-align: center; }
5138
5237
  .kjun-text[data-align="end"] { text-align: end; }
@@ -12,6 +12,8 @@ export interface KjunButtonProps extends Omit<PressableProps, "children" | "styl
12
12
  children?: ReactNode;
13
13
  variant?: ButtonVariant;
14
14
  size?: ButtonSize;
15
+ /** "circle" makes an icon-only button round: as wide as its height with a full radius. */
16
+ shape?: "default" | "circle";
15
17
  loading?: boolean;
16
18
  block?: boolean;
17
19
  /** Long labels wrap: the size's height becomes a minimum and the button grows instead of overflowing. */
@@ -12,6 +12,8 @@ export interface KjunButtonProps extends Omit<PressableProps, "children" | "styl
12
12
  children?: ReactNode;
13
13
  variant?: ButtonVariant;
14
14
  size?: ButtonSize;
15
+ /** "circle" makes an icon-only button round: as wide as its height with a full radius. */
16
+ shape?: "default" | "circle";
15
17
  loading?: boolean;
16
18
  block?: boolean;
17
19
  /** Long labels wrap: the size's height becomes a minimum and the button grows instead of overflowing. */
@@ -1,6 +1,6 @@
1
1
  import { type CardElevation, type CardPadding, type CardRadius, type CardSurface } from "@kjun-ui/tokens";
2
2
  import { type ReactNode } from "react";
3
- import { type StyleProp, type ViewStyle } from "react-native";
3
+ import { type GestureResponderEvent, type StyleProp, type ViewStyle } from "react-native";
4
4
  export interface KjunCardProps {
5
5
  title?: string;
6
6
  subtitle?: string;
@@ -17,5 +17,12 @@ export interface KjunCardProps {
17
17
  dividers?: boolean;
18
18
  children?: ReactNode;
19
19
  style?: StyleProp<ViewStyle>;
20
+ /** Makes the whole card one button (onPress). Do not put buttons or links inside a pressable card. */
21
+ pressable?: boolean;
22
+ /** Blocks a pressable card and dims it. */
23
+ disabled?: boolean;
24
+ /** Button name of a pressable card; defaults to the title. */
25
+ ariaLabel?: string;
26
+ onPress?: (event: GestureResponderEvent) => void;
20
27
  }
21
- export declare function KjunCard({ title, subtitle, header, headerActions, media, footer, padding, bodyPadding, radius, surface, elevation, border, dividers, children, style, }: KjunCardProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function KjunCard({ title, subtitle, header, headerActions, media, footer, padding, bodyPadding, radius, surface, elevation, border, dividers, children, style, pressable, disabled, ariaLabel, onPress, }: KjunCardProps): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,6 @@
1
1
  import { type CardElevation, type CardPadding, type CardRadius, type CardSurface } from "@kjun-ui/tokens";
2
2
  import { type ReactNode } from "react";
3
- import { type StyleProp, type ViewStyle } from "react-native";
3
+ import { type GestureResponderEvent, type StyleProp, type ViewStyle } from "react-native";
4
4
  export interface KjunCardProps {
5
5
  title?: string;
6
6
  subtitle?: string;
@@ -17,5 +17,12 @@ export interface KjunCardProps {
17
17
  dividers?: boolean;
18
18
  children?: ReactNode;
19
19
  style?: StyleProp<ViewStyle>;
20
+ /** Makes the whole card one button (onPress). Do not put buttons or links inside a pressable card. */
21
+ pressable?: boolean;
22
+ /** Blocks a pressable card and dims it. */
23
+ disabled?: boolean;
24
+ /** Button name of a pressable card; defaults to the title. */
25
+ ariaLabel?: string;
26
+ onPress?: (event: GestureResponderEvent) => void;
20
27
  }
21
- export declare function KjunCard({ title, subtitle, header, headerActions, media, footer, padding, bodyPadding, radius, surface, elevation, border, dividers, children, style, }: KjunCardProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function KjunCard({ title, subtitle, header, headerActions, media, footer, padding, bodyPadding, radius, surface, elevation, border, dividers, children, style, pressable, disabled, ariaLabel, onPress, }: KjunCardProps): import("react/jsx-runtime").JSX.Element;
@@ -27,11 +27,13 @@ export interface KjunSwitchProps {
27
27
  ariaLabel?: string;
28
28
  disabled?: boolean;
29
29
  size?: InputSize;
30
+ /** Supporting text under the label; screen readers hear it as the hint. */
31
+ description?: string;
30
32
  children?: ReactNode;
31
33
  onValueChange?: (value: boolean) => void;
32
34
  onChange?: (value: boolean) => void;
33
35
  }
34
- export declare function KjunSwitch({ value, label, ariaLabel, disabled, size, children, onValueChange, onChange, }: KjunSwitchProps): import("react/jsx-runtime").JSX.Element;
36
+ export declare function KjunSwitch({ value, label, ariaLabel, disabled, size, description, children, onValueChange, onChange, }: KjunSwitchProps): import("react/jsx-runtime").JSX.Element;
35
37
  export declare const RadioContext: import("react").Context<{
36
38
  value: ChoiceValue;
37
39
  change: (v: ChoiceValue) => void;
@@ -27,11 +27,13 @@ export interface KjunSwitchProps {
27
27
  ariaLabel?: string;
28
28
  disabled?: boolean;
29
29
  size?: InputSize;
30
+ /** Supporting text under the label; screen readers hear it as the hint. */
31
+ description?: string;
30
32
  children?: ReactNode;
31
33
  onValueChange?: (value: boolean) => void;
32
34
  onChange?: (value: boolean) => void;
33
35
  }
34
- export declare function KjunSwitch({ value, label, ariaLabel, disabled, size, children, onValueChange, onChange, }: KjunSwitchProps): import("react/jsx-runtime").JSX.Element;
36
+ export declare function KjunSwitch({ value, label, ariaLabel, disabled, size, description, children, onValueChange, onChange, }: KjunSwitchProps): import("react/jsx-runtime").JSX.Element;
35
37
  export declare const RadioContext: import("react").Context<{
36
38
  value: ChoiceValue;
37
39
  change: (v: ChoiceValue) => void;
@@ -1,3 +1,4 @@
1
+ import type { KjunMessageScope } from "../../../shared/package-runtime/messages/index.cjs";
1
2
  import { type QueryDisplayProps } from "@kjun-ui/tokens";
2
3
  import { Component, type ErrorInfo, type ReactNode } from "react";
3
4
  import { type KjunSkeletonProps } from "./display.cjs";
@@ -44,6 +45,8 @@ export interface KjunErrorBoundaryProps {
44
45
  export declare class KjunErrorBoundary extends Component<KjunErrorBoundaryProps, {
45
46
  error: boolean;
46
47
  }> {
48
+ static contextType: import("react").Context<KjunMessageScope>;
49
+ context: KjunMessageScope;
47
50
  state: {
48
51
  error: boolean;
49
52
  };
@@ -1,3 +1,4 @@
1
+ import type { KjunMessageScope } from "../../../shared/package-runtime/messages/index.js";
1
2
  import { type QueryDisplayProps } from "@kjun-ui/tokens";
2
3
  import { Component, type ErrorInfo, type ReactNode } from "react";
3
4
  import { type KjunSkeletonProps } from "./display.js";
@@ -44,6 +45,8 @@ export interface KjunErrorBoundaryProps {
44
45
  export declare class KjunErrorBoundary extends Component<KjunErrorBoundaryProps, {
45
46
  error: boolean;
46
47
  }> {
48
+ static contextType: import("react").Context<KjunMessageScope>;
49
+ context: KjunMessageScope;
47
50
  state: {
48
51
  error: boolean;
49
52
  };
@@ -1,6 +1,8 @@
1
1
  import { type InputSize } from "@kjun-ui/tokens";
2
2
  export interface KjunDatePickerProps {
3
3
  value: string;
4
+ /** Shows a clear button while there is a value; it reports an empty string. */
5
+ clearable?: boolean;
4
6
  min?: string;
5
7
  max?: string;
6
8
  placeholder?: string;
@@ -11,4 +13,4 @@ export interface KjunDatePickerProps {
11
13
  onValueChange?: (v: string) => void;
12
14
  onChange?: (v: string) => void;
13
15
  }
14
- export declare function KjunDatePicker({ value, min, max, placeholder, size, disabled, ariaLabel, error, onValueChange, onChange, }: KjunDatePickerProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function KjunDatePicker({ value, min, max, clearable, placeholder, size, disabled, ariaLabel, error, onValueChange, onChange, }: KjunDatePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,8 @@
1
1
  import { type InputSize } from "@kjun-ui/tokens";
2
2
  export interface KjunDatePickerProps {
3
3
  value: string;
4
+ /** Shows a clear button while there is a value; it reports an empty string. */
5
+ clearable?: boolean;
4
6
  min?: string;
5
7
  max?: string;
6
8
  placeholder?: string;
@@ -11,4 +13,4 @@ export interface KjunDatePickerProps {
11
13
  onValueChange?: (v: string) => void;
12
14
  onChange?: (v: string) => void;
13
15
  }
14
- export declare function KjunDatePicker({ value, min, max, placeholder, size, disabled, ariaLabel, error, onValueChange, onChange, }: KjunDatePickerProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function KjunDatePicker({ value, min, max, clearable, placeholder, size, disabled, ariaLabel, error, onValueChange, onChange, }: KjunDatePickerProps): import("react/jsx-runtime").JSX.Element;
@@ -49,5 +49,6 @@ export interface KjunProgressProps {
49
49
  showLabel?: boolean;
50
50
  label?: ReactNode;
51
51
  subLabel?: ReactNode;
52
+ shape?: "bar" | "circle";
52
53
  }
53
- export declare function KjunProgress({ value, max, size, variant, showLabel, label, subLabel, }: KjunProgressProps): import("react/jsx-runtime").JSX.Element;
54
+ export declare function KjunProgress({ value, max, size, variant, showLabel, label, subLabel, shape, }: KjunProgressProps): import("react/jsx-runtime").JSX.Element;
@@ -49,5 +49,6 @@ export interface KjunProgressProps {
49
49
  showLabel?: boolean;
50
50
  label?: ReactNode;
51
51
  subLabel?: ReactNode;
52
+ shape?: "bar" | "circle";
52
53
  }
53
- export declare function KjunProgress({ value, max, size, variant, showLabel, label, subLabel, }: KjunProgressProps): import("react/jsx-runtime").JSX.Element;
54
+ export declare function KjunProgress({ value, max, size, variant, showLabel, label, subLabel, shape, }: KjunProgressProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import type { GestureResponderEvent } from "react-native";
2
+ export interface KjunFabProps {
3
+ icon: string;
4
+ /** The FAB has no visible text, so it needs a name. */
5
+ ariaLabel: string;
6
+ disabled?: boolean;
7
+ /** Bottom safe area (pt) the FAB stays above. */
8
+ safeAreaBottom?: number;
9
+ /** Extra space below, e.g. a bottom navigation's height. */
10
+ offsetBottom?: number;
11
+ onPress?: (event: GestureResponderEvent) => void;
12
+ }
13
+ /** A round primary action at the bottom end of its parent (place it in the screen's root view). */
14
+ export declare function KjunFab({ icon, ariaLabel, disabled, safeAreaBottom, offsetBottom, onPress }: KjunFabProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import type { GestureResponderEvent } from "react-native";
2
+ export interface KjunFabProps {
3
+ icon: string;
4
+ /** The FAB has no visible text, so it needs a name. */
5
+ ariaLabel: string;
6
+ disabled?: boolean;
7
+ /** Bottom safe area (pt) the FAB stays above. */
8
+ safeAreaBottom?: number;
9
+ /** Extra space below, e.g. a bottom navigation's height. */
10
+ offsetBottom?: number;
11
+ onPress?: (event: GestureResponderEvent) => void;
12
+ }
13
+ /** A round primary action at the bottom end of its parent (place it in the screen's root view). */
14
+ export declare function KjunFab({ icon, ariaLabel, disabled, safeAreaBottom, offsetBottom, onPress }: KjunFabProps): import("react/jsx-runtime").JSX.Element;
@@ -5,6 +5,10 @@ export declare function useKjunFeedback(): KjunFeedback;
5
5
  export interface KjunFeedbackProviderProps {
6
6
  children: ReactNode;
7
7
  style?: StyleProp<ViewStyle>;
8
+ /** A feedback API from createKjunFeedback(), for calls outside components. */
9
+ controller?: KjunFeedback;
8
10
  }
9
- export declare function KjunFeedbackProvider({ children, style }: KjunFeedbackProviderProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function KjunFeedbackProvider({ children, style, controller: controllerProp }: KjunFeedbackProviderProps): import("react/jsx-runtime").JSX.Element;
10
12
  export type { ConfirmOptions, KjunFeedback, PromptOptions, ToastOptions } from "@kjun-ui/tokens";
13
+ /** An app-owned feedback API that plain functions can call; pass it to KjunFeedbackProvider controller. */
14
+ export { createKjunFeedback } from "@kjun-ui/tokens";
@@ -5,6 +5,10 @@ export declare function useKjunFeedback(): KjunFeedback;
5
5
  export interface KjunFeedbackProviderProps {
6
6
  children: ReactNode;
7
7
  style?: StyleProp<ViewStyle>;
8
+ /** A feedback API from createKjunFeedback(), for calls outside components. */
9
+ controller?: KjunFeedback;
8
10
  }
9
- export declare function KjunFeedbackProvider({ children, style }: KjunFeedbackProviderProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function KjunFeedbackProvider({ children, style, controller: controllerProp }: KjunFeedbackProviderProps): import("react/jsx-runtime").JSX.Element;
10
12
  export type { ConfirmOptions, KjunFeedback, PromptOptions, ToastOptions } from "@kjun-ui/tokens";
13
+ /** An app-owned feedback API that plain functions can call; pass it to KjunFeedbackProvider controller. */
14
+ export { createKjunFeedback } from "@kjun-ui/tokens";
@@ -1,5 +1,6 @@
1
1
  import { Animated, TextInput, type ViewStyle } from "react-native";
2
2
  import { type InputSize } from "@kjun-ui/tokens";
3
+ /** Field text input whose font family follows the Provider's weight maps, like KText. */
3
4
  export declare const FieldTextInput: typeof TextInput;
4
5
  export declare const FieldPressable: import("react").ForwardRefExoticComponent<import("react-native").PressableProps & {
5
6
  focusRingInset?: boolean;
@@ -1,5 +1,6 @@
1
1
  import { Animated, TextInput, type ViewStyle } from "react-native";
2
2
  import { type InputSize } from "@kjun-ui/tokens";
3
+ /** Field text input whose font family follows the Provider's weight maps, like KText. */
3
4
  export declare const FieldTextInput: typeof TextInput;
4
5
  export declare const FieldPressable: import("react").ForwardRefExoticComponent<import("react-native").PressableProps & {
5
6
  focusRingInset?: boolean;
@@ -36,35 +36,35 @@ export declare function KjunCollectionMark({ kind, active, size, }: KjunCollecti
36
36
  export declare const executionStates: {
37
37
  readonly queued: readonly [
38
38
  "secondary",
39
- "대기 중"
39
+ "statusQueued"
40
40
  ];
41
41
  readonly starting: readonly [
42
42
  "primary",
43
- "시작 중"
43
+ "statusStarting"
44
44
  ];
45
45
  readonly running: readonly [
46
46
  "primary",
47
- "실행 중"
47
+ "statusRunning"
48
48
  ];
49
49
  readonly stopping: readonly [
50
50
  "warning",
51
- "중단 중"
51
+ "statusStopping"
52
52
  ];
53
53
  readonly stopped: readonly [
54
54
  "secondary",
55
- "중단됨"
55
+ "statusStopped"
56
56
  ];
57
57
  readonly completed: readonly [
58
58
  "success",
59
- "완료"
59
+ "statusCompleted"
60
60
  ];
61
61
  readonly completed_with_errors: readonly [
62
62
  "warning",
63
- "완료 (오류)"
63
+ "statusCompletedWithErrors"
64
64
  ];
65
65
  readonly failed: readonly [
66
66
  "danger",
67
- "실패"
67
+ "statusFailed"
68
68
  ];
69
69
  };
70
70
  export interface KjunExecutionStatusBadgeProps {
@@ -36,35 +36,35 @@ export declare function KjunCollectionMark({ kind, active, size, }: KjunCollecti
36
36
  export declare const executionStates: {
37
37
  readonly queued: readonly [
38
38
  "secondary",
39
- "대기 중"
39
+ "statusQueued"
40
40
  ];
41
41
  readonly starting: readonly [
42
42
  "primary",
43
- "시작 중"
43
+ "statusStarting"
44
44
  ];
45
45
  readonly running: readonly [
46
46
  "primary",
47
- "실행 중"
47
+ "statusRunning"
48
48
  ];
49
49
  readonly stopping: readonly [
50
50
  "warning",
51
- "중단 중"
51
+ "statusStopping"
52
52
  ];
53
53
  readonly stopped: readonly [
54
54
  "secondary",
55
- "중단됨"
55
+ "statusStopped"
56
56
  ];
57
57
  readonly completed: readonly [
58
58
  "success",
59
- "완료"
59
+ "statusCompleted"
60
60
  ];
61
61
  readonly completed_with_errors: readonly [
62
62
  "warning",
63
- "완료 (오류)"
63
+ "statusCompletedWithErrors"
64
64
  ];
65
65
  readonly failed: readonly [
66
66
  "danger",
67
- "실패"
67
+ "statusFailed"
68
68
  ];
69
69
  };
70
70
  export interface KjunExecutionStatusBadgeProps {
@@ -0,0 +1,14 @@
1
+ import { type StyleProp, type TextStyle } from "react-native";
2
+ export type KjunFontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
3
+ /** Font names by weight, for platforms (Android, Expo) that load every weight as its own family. */
4
+ export type KjunFontWeights = Partial<Record<KjunFontWeight, string>>;
5
+ export type KjunFontFamily = string | KjunFontWeights;
6
+ /** Every face name of a weight map points back to its map, so a style naming any face can be re-resolved. */
7
+ export type KjunFontFaces = Record<string, KjunFontWeights>;
8
+ /** The face closest to `weight`; a tie takes the heavier face. */
9
+ export declare function nearestFace(faces: KjunFontWeights, weight: number): string | undefined;
10
+ /** The family name components use as their base: the string itself, or the face closest to 400. */
11
+ export declare const baseFontFamily: (family?: KjunFontFamily) => string | undefined;
12
+ export declare function fontFacesOf(family?: KjunFontFamily): KjunFontFaces;
13
+ /** Swaps the family for the face matching the final fontWeight. Native then draws that face at its own weight. */
14
+ export declare function resolveFontStyle<S extends StyleProp<TextStyle>>(style: S, faces: KjunFontFaces, base?: string): S | StyleProp<TextStyle>;
@@ -0,0 +1,14 @@
1
+ import { type StyleProp, type TextStyle } from "react-native";
2
+ export type KjunFontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
3
+ /** Font names by weight, for platforms (Android, Expo) that load every weight as its own family. */
4
+ export type KjunFontWeights = Partial<Record<KjunFontWeight, string>>;
5
+ export type KjunFontFamily = string | KjunFontWeights;
6
+ /** Every face name of a weight map points back to its map, so a style naming any face can be re-resolved. */
7
+ export type KjunFontFaces = Record<string, KjunFontWeights>;
8
+ /** The face closest to `weight`; a tie takes the heavier face. */
9
+ export declare function nearestFace(faces: KjunFontWeights, weight: number): string | undefined;
10
+ /** The family name components use as their base: the string itself, or the face closest to 400. */
11
+ export declare const baseFontFamily: (family?: KjunFontFamily) => string | undefined;
12
+ export declare function fontFacesOf(family?: KjunFontFamily): KjunFontFaces;
13
+ /** Swaps the family for the face matching the final fontWeight. Native then draws that face at its own weight. */
14
+ export declare function resolveFontStyle<S extends StyleProp<TextStyle>>(style: S, faces: KjunFontFaces, base?: string): S | StyleProp<TextStyle>;
@@ -34,7 +34,9 @@ export * from "./list.cjs";
34
34
  export * from "./app-navigation.cjs";
35
35
  export * from "./media.cjs";
36
36
  export * from "./chip.cjs";
37
+ export * from "./fab.cjs";
37
38
  export * from "./range-input.cjs";
38
39
  export * from "./quantity-stepper.cjs";
39
40
  export * from "./time-picker.cjs";
40
41
  export type { ShadowLayer, ElevationRole, CardElevation } from "@kjun-ui/tokens";
42
+ export { kjunMessagesKo, kjunMessagesEn, type KjunMessages } from "../../../shared/package-runtime/messages/index.cjs";
@@ -34,7 +34,9 @@ export * from "./list.js";
34
34
  export * from "./app-navigation.js";
35
35
  export * from "./media.js";
36
36
  export * from "./chip.js";
37
+ export * from "./fab.js";
37
38
  export * from "./range-input.js";
38
39
  export * from "./quantity-stepper.js";
39
40
  export * from "./time-picker.js";
40
41
  export type { ShadowLayer, ElevationRole, CardElevation } from "@kjun-ui/tokens";
42
+ export { kjunMessagesKo, kjunMessagesEn, type KjunMessages } from "../../../shared/package-runtime/messages/index.js";