@kerfjs/ui 5.0.0-beta.18 → 5.0.0-beta.22

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 (170) hide show
  1. package/README.md +114 -3
  2. package/ai/application-ui-diagnostic-ids-v1.json +92 -0
  3. package/ai/application-ui-profile-sync.cjs +529 -0
  4. package/ai/application-ui-profile.d.mts +1 -0
  5. package/ai/application-ui-profile.d.ts +102 -0
  6. package/ai/application-ui-profile.defaults.json +41 -0
  7. package/ai/application-ui-profile.mjs +626 -0
  8. package/ai/application-ui-profile.schema.json +130 -0
  9. package/ai/catalog-authoring.json +25 -0
  10. package/ai/catalog-authoring.schema.json +61 -0
  11. package/ai/compile-time-contracts-v1.json +101 -0
  12. package/ai/compile-time-contracts-v1.schema.json +49 -0
  13. package/ai/component-catalog-extension-v2.d.ts +7 -0
  14. package/ai/component-catalog-extension-v2.schema.json +7 -0
  15. package/ai/component-catalog-v2-overrides.json +326 -0
  16. package/ai/component-catalog-v2.d.ts +67 -0
  17. package/ai/component-catalog-v2.json +4441 -0
  18. package/ai/component-catalog-v2.schema.json +246 -0
  19. package/ai/component-catalog.json +150 -6
  20. package/ai/public-api-signatures-v1.md +294 -64
  21. package/ai/skill.md +41 -5
  22. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  23. package/analyzer/cli.mjs +46 -0
  24. package/analyzer/index.d.mts +45 -0
  25. package/analyzer/index.mjs +743 -0
  26. package/analyzer/report.schema.json +66 -0
  27. package/dist/browser/pane.js +3 -0
  28. package/dist/browser/sunken-panel.js +3 -0
  29. package/dist/catalog-resources.d.ts +34 -0
  30. package/dist/catalog-resources.js +22 -0
  31. package/dist/catalog-resources.js.map +1 -0
  32. package/dist/catalog.d.ts +21 -3
  33. package/dist/catalog.js +239 -210
  34. package/dist/catalog.js.map +1 -1
  35. package/dist/{chunk-ZK2G3VR5.js → chunk-5VTB2BKP.js} +1 -1
  36. package/dist/chunk-5VTB2BKP.js.map +1 -0
  37. package/dist/{chunk-S3HKPI7I.js → chunk-7KEUJIIC.js} +1 -1
  38. package/dist/chunk-7KEUJIIC.js.map +1 -0
  39. package/dist/{chunk-NVWXKU37.js → chunk-AASLYRGE.js} +1 -1
  40. package/dist/chunk-AASLYRGE.js.map +1 -0
  41. package/dist/{chunk-QIRXYKCE.js → chunk-DSNIYOZ3.js} +3 -2
  42. package/dist/chunk-DSNIYOZ3.js.map +1 -0
  43. package/dist/{chunk-ENVTNLYC.js → chunk-GP5DP5DL.js} +55 -15
  44. package/dist/chunk-GP5DP5DL.js.map +1 -0
  45. package/dist/chunk-JRKSK2HX.js +79 -0
  46. package/dist/chunk-JRKSK2HX.js.map +1 -0
  47. package/dist/{chunk-U5IFGQCD.js → chunk-K57KRAOV.js} +1 -1
  48. package/dist/chunk-K57KRAOV.js.map +1 -0
  49. package/dist/{chunk-ZVI5YST2.js → chunk-M7JBER5U.js} +1 -1
  50. package/dist/chunk-M7JBER5U.js.map +1 -0
  51. package/dist/{chunk-43FUQH35.js → chunk-OHU6CI22.js} +2 -2
  52. package/dist/{chunk-43FUQH35.js.map → chunk-OHU6CI22.js.map} +1 -1
  53. package/dist/{chunk-4TRDV6RL.js → chunk-OZWU5ZPZ.js} +1 -1
  54. package/dist/chunk-OZWU5ZPZ.js.map +1 -0
  55. package/dist/{chunk-JTHUXDN2.js → chunk-RYRIFZCT.js} +3 -3
  56. package/dist/chunk-RYRIFZCT.js.map +1 -0
  57. package/dist/{chunk-6ETZKKAE.js → chunk-VLYV65LK.js} +1 -1
  58. package/dist/chunk-VLYV65LK.js.map +1 -0
  59. package/dist/chunk-W4CXQYSG.js +23 -0
  60. package/dist/chunk-W4CXQYSG.js.map +1 -0
  61. package/dist/{chunk-S3PCZ7NV.js → chunk-W7YD6E4N.js} +1 -1
  62. package/dist/chunk-W7YD6E4N.js.map +1 -0
  63. package/dist/index.d.ts +6 -4
  64. package/dist/index.js +14 -12
  65. package/dist/list-header.d.ts +29 -8
  66. package/dist/list-header.js +1 -1
  67. package/dist/nav-stack.js +1 -1
  68. package/dist/pane.d.ts +49 -0
  69. package/dist/pane.js +4 -0
  70. package/dist/pane.js.map +1 -0
  71. package/dist/panel-header.d.ts +9 -3
  72. package/dist/panel-header.js +1 -1
  73. package/dist/segmented-control.d.ts +6 -6
  74. package/dist/segmented-control.js +1 -1
  75. package/dist/select.d.ts +10 -4
  76. package/dist/select.js +1 -1
  77. package/dist/split-view.js +2 -2
  78. package/dist/state-banner.d.ts +3 -2
  79. package/dist/state-banner.js +1 -1
  80. package/dist/styles/catalog.css +6 -6
  81. package/dist/styles/layout.css +2 -20
  82. package/dist/styles/pane.css +62 -0
  83. package/dist/styles/segmented-control.css +3 -7
  84. package/dist/styles/sunken-panel.css +18 -0
  85. package/dist/sunken-panel.d.ts +16 -0
  86. package/dist/sunken-panel.js +3 -0
  87. package/dist/sunken-panel.js.map +1 -0
  88. package/dist/tab-bar.d.ts +3 -2
  89. package/dist/tab-bar.js +1 -1
  90. package/dist/tab-scaffold.d.ts +6 -6
  91. package/dist/tab-scaffold.js.map +1 -1
  92. package/dist/token-search-field.d.ts +25 -9
  93. package/dist/token-search-field.js +1 -1
  94. package/dist/toolbar-control-group.d.ts +9 -5
  95. package/dist/toolbar-control-group.js +1 -1
  96. package/dist/toolbar-text.d.ts +10 -11
  97. package/dist/toolbar-text.js +1 -1
  98. package/dist/wire-tab-bars.d.ts +5 -2
  99. package/dist/wire-tab-bars.js +1 -1
  100. package/dist/wire-token-search-fields.d.ts +11 -6
  101. package/dist/wire-token-search-fields.js +1 -1
  102. package/docs/catalog.md +186 -67
  103. package/docs/component-contract.md +102 -5
  104. package/docs/component-selection.md +9 -5
  105. package/docs/design/templates/panel-header/icon-actions-dark.svg +1 -1
  106. package/docs/design/templates/panel-header/icon-actions.svg +1 -1
  107. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +1 -1
  108. package/docs/design/templates/panel-header/icon-summary-actions.svg +1 -1
  109. package/docs/design/templates/panel-header/no-icon-dark.svg +1 -1
  110. package/docs/design/templates/panel-header/no-icon.svg +1 -1
  111. package/docs/design/templates/panel-header/page-heading-dark.svg +1 -1
  112. package/docs/design/templates/panel-header/page-heading.svg +1 -1
  113. package/docs/design/templates/panel-header/title-only-dark.svg +1 -1
  114. package/docs/design/templates/panel-header/title-only.svg +1 -1
  115. package/docs/design/templates/panel-header-dark.svg +5 -5
  116. package/docs/design/templates/panel-header.svg +5 -5
  117. package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
  118. package/docs/design/templates/segmented-control/equal.svg +1 -1
  119. package/docs/design/templates/segmented-control-dark.svg +1 -1
  120. package/docs/design/templates/segmented-control.svg +1 -1
  121. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
  122. package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
  123. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  124. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  125. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  126. package/docs/design/templates/toolbar-control-group.svg +1 -1
  127. package/docs/design/templates/toolbar-dark.svg +1 -1
  128. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  129. package/docs/design/templates/toolbar-text/default.svg +1 -1
  130. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  131. package/docs/design/templates/toolbar-text/large.svg +1 -1
  132. package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
  133. package/docs/design/templates/toolbar-text/small.svg +1 -1
  134. package/docs/design/templates/toolbar-text-dark.svg +3 -3
  135. package/docs/design/templates/toolbar-text.svg +3 -3
  136. package/docs/design/templates/toolbar.svg +1 -1
  137. package/docs/design/templates.md +11 -6
  138. package/docs/design-philosophy.md +2 -4
  139. package/docs/examples/application-ui-profile.json +60 -0
  140. package/docs/examples/component-catalog-extension-v2.json +81 -0
  141. package/docs/layout.md +42 -23
  142. package/docs/sunken-panel.md +43 -0
  143. package/docs/type-contracts.md +99 -0
  144. package/docs/ui-analyzer.md +81 -0
  145. package/docs/ui-doctor.md +77 -0
  146. package/docs/ui-evaluator.md +122 -0
  147. package/doctor/cli.mjs +115 -0
  148. package/doctor/config.schema.json +68 -0
  149. package/doctor/index.d.mts +116 -0
  150. package/doctor/index.mjs +1256 -0
  151. package/doctor/report.schema.json +118 -0
  152. package/evaluator/cli.mjs +89 -0
  153. package/evaluator/index.d.mts +90 -0
  154. package/evaluator/index.mjs +1138 -0
  155. package/evaluator/report.schema.json +152 -0
  156. package/llms.txt +40 -3
  157. package/package.json +66 -8
  158. package/ux-demo/recipes/compact-toolbar.tsx +2 -2
  159. package/ux-demo/recipes/composer-form.tsx +1 -1
  160. package/dist/chunk-4TRDV6RL.js.map +0 -1
  161. package/dist/chunk-6ETZKKAE.js.map +0 -1
  162. package/dist/chunk-ENVTNLYC.js.map +0 -1
  163. package/dist/chunk-JTHUXDN2.js.map +0 -1
  164. package/dist/chunk-NVWXKU37.js.map +0 -1
  165. package/dist/chunk-QIRXYKCE.js.map +0 -1
  166. package/dist/chunk-S3HKPI7I.js.map +0 -1
  167. package/dist/chunk-S3PCZ7NV.js.map +0 -1
  168. package/dist/chunk-U5IFGQCD.js.map +0 -1
  169. package/dist/chunk-ZK2G3VR5.js.map +0 -1
  170. package/dist/chunk-ZVI5YST2.js.map +0 -1
@@ -1,17 +1,18 @@
1
1
  import { SafeHtml } from 'kerfjs';
2
2
 
3
3
  type StateBannerTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';
4
+ type StateBannerUrgency = 'status' | 'alert';
4
5
  interface StateBannerProps {
5
6
  title: string;
6
7
  detail?: string;
7
8
  icon?: SafeHtml;
8
9
  action?: SafeHtml;
9
10
  tone?: StateBannerTone;
10
- urgency?: 'status' | 'alert';
11
+ urgency?: StateBannerUrgency;
11
12
  className?: string;
12
13
  /** Render the title and detail as unanimated loading skeletons, keeping the icon and tone. */
13
14
  placeholder?: boolean;
14
15
  }
15
16
  declare function StateBanner({ title, detail, icon, action, tone, urgency, className, placeholder, }: StateBannerProps): SafeHtml;
16
17
 
17
- export { StateBanner, type StateBannerProps, type StateBannerTone };
18
+ export { StateBanner, type StateBannerProps, type StateBannerTone, type StateBannerUrgency };
@@ -1,4 +1,4 @@
1
- export { StateBanner } from './chunk-6ETZKKAE.js';
1
+ export { StateBanner } from './chunk-VLYV65LK.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=state-banner.js.map
@@ -23,15 +23,14 @@
23
23
  padding: 0;
24
24
  overflow: hidden;
25
25
  justify-self: start;
26
- border-inline-end: 1px solid var(--kui-color-border);
27
26
  background: var(--kui-color-surface);
28
27
  transition:
29
28
  transform 200ms ease,
30
29
  visibility 0s linear 0s;
31
30
  }
32
31
 
33
- .kui-catalog[data-sidebar-collapsed="true"] .kui-catalog__sidebar {
34
- border-inline-end: 0;
32
+ .kui-catalog[data-sidebar-collapsed="true"] .kui-catalog__sidebar.kui-pane {
33
+ --kui-pane-separator-inline-end-width: 0;
35
34
  /* Slide out first, then hide, so the panel animates offscreen and only then
36
35
  leaves the tab order rather than snapping invisible mid-slide. */
37
36
  transform: translateX(-100%);
@@ -510,15 +509,16 @@
510
509
  .kui-catalog[data-sidebar-collapsed="true"] .kui-catalog__sidebar {
511
510
  display: none;
512
511
  }
513
- .kui-catalog__sidebar {
512
+ .kui-catalog .kui-catalog__sidebar.kui-pane {
513
+ --kui-pane-separator-block-end-width: var(--kui-pane-separator-width, 1px);
514
+ --kui-pane-separator-inline-end-width: 0;
515
+
514
516
  width: 100%;
515
517
  min-width: 0;
516
518
  height: auto;
517
519
  justify-self: stretch;
518
520
  /* Narrow layout collapses via display:none, not the desktop slide. */
519
521
  transform: none;
520
- border-inline-end: 0;
521
- border-block-end: 1px solid var(--kui-color-border);
522
522
  }
523
523
  .kui-catalog__detail {
524
524
  height: auto;
@@ -1,24 +1,6 @@
1
- /* Shared application geometry: unpadded panes containing toolbars and content. */
2
- .kui-pane {
3
- display: grid;
4
- min-width: 0;
5
- min-height: 0;
6
- padding: 0;
7
- grid-template-rows: auto minmax(0, 1fr) auto;
8
- }
9
-
10
- .kui-pane__toolbar,
11
- .kui-pane__footer {
12
- min-width: 0;
13
- }
1
+ @import "./pane.css";
14
2
 
15
- .kui-pane__content {
16
- min-width: 0;
17
- min-height: 0;
18
- padding: 0;
19
- overflow: auto;
20
- overscroll-behavior: contain;
21
- }
3
+ /* Shared application content geometry for Pane children and standalone stacks. */
22
4
 
23
5
  .kui-content {
24
6
  display: flex;
@@ -0,0 +1,62 @@
1
+ .kui-pane {
2
+ --kui-pane-separator-block-start-width: 0;
3
+ --kui-pane-separator-block-end-width: 0;
4
+ --kui-pane-separator-inline-start-width: 0;
5
+ --kui-pane-separator-inline-end-width: 0;
6
+
7
+ display: grid;
8
+ min-width: 0;
9
+ min-height: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ border: 0 solid var(--kui-pane-separator-color, var(--kui-color-border));
13
+ border-block-start-width: var(--kui-pane-separator-block-start-width);
14
+ border-block-end-width: var(--kui-pane-separator-block-end-width);
15
+ border-inline-start-width: var(--kui-pane-separator-inline-start-width);
16
+ border-inline-end-width: var(--kui-pane-separator-inline-end-width);
17
+ grid-template-areas:
18
+ "header"
19
+ "content"
20
+ "footer";
21
+ grid-template-rows: auto minmax(0, 1fr) auto;
22
+ }
23
+
24
+ .kui-pane[data-separator-block-start="true"] {
25
+ --kui-pane-separator-block-start-width: var(--kui-pane-separator-width, 1px);
26
+ }
27
+
28
+ .kui-pane[data-separator-block-end="true"] {
29
+ --kui-pane-separator-block-end-width: var(--kui-pane-separator-width, 1px);
30
+ }
31
+
32
+ .kui-pane[data-separator-inline-start="true"] {
33
+ --kui-pane-separator-inline-start-width: var(--kui-pane-separator-width, 1px);
34
+ }
35
+
36
+ .kui-pane[data-separator-inline-end="true"] {
37
+ --kui-pane-separator-inline-end-width: var(--kui-pane-separator-width, 1px);
38
+ }
39
+
40
+ .kui-pane__header,
41
+ .kui-pane__toolbar {
42
+ display: flex;
43
+ min-width: 0;
44
+ flex-direction: column;
45
+ grid-area: header;
46
+ }
47
+
48
+ .kui-pane__content {
49
+ min-width: 0;
50
+ min-height: 0;
51
+ padding: 0;
52
+ overflow: auto;
53
+ grid-area: content;
54
+ overscroll-behavior: contain;
55
+ }
56
+
57
+ .kui-pane__footer {
58
+ display: flex;
59
+ min-width: 0;
60
+ flex-direction: column;
61
+ grid-area: footer;
62
+ }
@@ -12,9 +12,9 @@
12
12
  --kui-layout-rounded-radius,
13
13
  calc(1px + 0.6875rem)
14
14
  );
15
- --kui-segmented-item-radius: var(
16
- --kui-layout-rounded-radius,
17
- calc(1px + 0.6875rem)
15
+ --kui-segmented-item-radius: max(
16
+ 0px,
17
+ calc(var(--kui-segmented-radius) - 2px)
18
18
  );
19
19
  display: inline-flex;
20
20
  max-width: 100%;
@@ -82,10 +82,6 @@
82
82
  --kui-layout-pill-radius,
83
83
  calc(1px + 1.3125rem)
84
84
  );
85
- --kui-segmented-item-radius: var(
86
- --kui-layout-pill-radius,
87
- calc(1px + 1.3125rem)
88
- );
89
85
  }
90
86
 
91
87
  .kui-segmented-control[data-layout="equal"] {
@@ -0,0 +1,18 @@
1
+ .kui-sunken-panel {
2
+ display: flex;
3
+ min-width: 0;
4
+ min-height: 0;
5
+ padding: var(--kui-sunken-panel-padding, 0.5rem);
6
+ box-sizing: border-box;
7
+ border-radius: var(
8
+ --kui-sunken-panel-radius,
9
+ var(--kui-layout-rounded-radius, calc(1px + 0.6875rem))
10
+ );
11
+ color: var(--kui-sunken-panel-foreground, var(--kui-color-text));
12
+ background: var(
13
+ --kui-sunken-panel-background,
14
+ var(--kui-color-surface-lowered)
15
+ );
16
+ flex-direction: column;
17
+ gap: var(--kui-sunken-panel-gap, 0.5rem);
18
+ }
@@ -0,0 +1,16 @@
1
+ import { SafeHtml } from 'kerfjs';
2
+
3
+ interface SunkenPanelProps {
4
+ children?: SafeHtml | readonly SafeHtml[];
5
+ /** Optional accessible landmark name for a distinct application region. */
6
+ ariaLabel?: string;
7
+ className?: string;
8
+ }
9
+ /**
10
+ * A lowered application surface with one compact inset and a vertical content
11
+ * stack. The panel owns its background and padding; children own their own
12
+ * borders and internal geometry.
13
+ */
14
+ declare function SunkenPanel({ children, ariaLabel, className, }: SunkenPanelProps): SafeHtml;
15
+
16
+ export { SunkenPanel, type SunkenPanelProps };
@@ -0,0 +1,3 @@
1
+ export { SunkenPanel } from './chunk-W4CXQYSG.js';
2
+
3
+ //# sourceMappingURL=sunken-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"sunken-panel.js"}
package/dist/tab-bar.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { SafeHtml } from 'kerfjs';
2
2
 
3
+ type TabActivation = 'automatic' | 'manual';
3
4
  interface TabBarProps {
4
5
  id: string;
5
6
  label: string;
@@ -13,9 +14,9 @@ interface TabBarProps {
13
14
  * selects on arrow / Home / End; `'manual'` moves roving focus only and the user
14
15
  * selects with Enter / Space / click — use it when selecting a tab is a heavy action.
15
16
  */
16
- activation?: 'automatic' | 'manual';
17
+ activation?: TabActivation;
17
18
  }
18
19
  /** Render a controlled tab strip. The application owns selection, order, and persistence. */
19
20
  declare function TabBar({ id, label, children, leading, trailing, className, activation, }: TabBarProps): SafeHtml;
20
21
 
21
- export { TabBar, type TabBarProps };
22
+ export { type TabActivation, TabBar, type TabBarProps };
package/dist/tab-bar.js CHANGED
@@ -1,3 +1,3 @@
1
- export { TabBar } from './chunk-ZVI5YST2.js';
1
+ export { TabBar } from './chunk-M7JBER5U.js';
2
2
 
3
3
  //# sourceMappingURL=tab-bar.js.map
@@ -1,20 +1,20 @@
1
1
  import { SafeHtml } from 'kerfjs';
2
2
 
3
- interface TabScaffoldTab {
4
- id: string;
3
+ interface TabScaffoldTab<Id extends string = string> {
4
+ id: Id;
5
5
  label: string;
6
6
  /** Decorative icon shown above the label in the bottom bar. */
7
7
  icon?: SafeHtml;
8
8
  /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
9
9
  content: SafeHtml;
10
10
  }
11
- interface TabScaffoldProps {
11
+ interface TabScaffoldProps<Id extends string = string> {
12
12
  id: string;
13
13
  /** Accessible name for the tab bar. */
14
14
  label: string;
15
- tabs: TabScaffoldTab[];
15
+ tabs: readonly TabScaffoldTab<Id>[];
16
16
  /** The controlled active tab id (the app owns selection). */
17
- active: string;
17
+ active: NoInfer<Id>;
18
18
  className?: string;
19
19
  }
20
20
  /**
@@ -25,6 +25,6 @@ interface TabScaffoldProps {
25
25
  * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
26
26
  * a bottom bar. See `docs/23-app-layouts.md` §3.4.
27
27
  */
28
- declare function TabScaffold({ id, label, tabs, active, className, }: TabScaffoldProps): SafeHtml;
28
+ declare function TabScaffold<Id extends string>({ id, label, tabs, active, className, }: TabScaffoldProps<Id>): SafeHtml;
29
29
 
30
30
  export { TabScaffold, type TabScaffoldProps, type TabScaffoldTab };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tab-scaffold.tsx"],"names":[],"mappings":";;;AA6BO,SAAS,WAAA,CAAY;AAAA,EAC1B,EAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,EAAqB;AACnB,EAAA,uBACE,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC5C,EAAA;AAAA,MACA,gBAAA,EAAe,cAAA;AAAA,MACf,sBAAA,EAAsB,EAAA;AAAA,MAEtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,SAAI,KAAA,EAAM,0BAAA,EACR,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,yBAAA;AAAA,YACN,2BAAyB,GAAA,CAAI,EAAA;AAAA,YAC7B,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YACrC,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YAEpC,QAAA,EAAA,GAAA,CAAI;AAAA;AAAA,SAER,CAAA,EACH,CAAA;AAAA,wBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAwB,IAAA,EAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAC3D,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,IAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,uBAAA;AAAA,YACN,IAAA,EAAK,KAAA;AAAA,YACL,yBAAuB,GAAA,CAAI,EAAA;AAAA,YAC3B,eAAA,EAAe,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YACvC,QAAA,EAAU,GAAA,CAAI,EAAA,KAAO,MAAA,GAAS,GAAA,GAAM,IAAA;AAAA,YAEnC,QAAA,EAAA;AAAA,cAAA,GAAA,CAAI,IAAA,wBACF,MAAA,EAAA,EAAK,KAAA,EAAM,8BAA6B,aAAA,EAAY,MAAA,EAClD,cAAI,IAAA,EACP,CAAA;AAAA,8BAEF,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,6BAAA,EAA+B,cAAI,KAAA,EAAM;AAAA;AAAA;AAAA,SAExD,CAAA,EACH;AAAA;AAAA;AAAA,GACF;AAEJ","file":"tab-scaffold.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface TabScaffoldTab {\n id: string;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: SafeHtml;\n}\n\nexport interface TabScaffoldProps {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: TabScaffoldTab[];\n /** The controlled active tab id (the app owns selection). */\n active: string;\n className?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab scaffold: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-scaffold`'s `wireTabScaffold`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabScaffold({\n id,\n label,\n tabs,\n active,\n className = '',\n}: TabScaffoldProps) {\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n aria-hidden={String(tab.id !== active)}\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n >\n {tab.icon && (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n </span>\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n ))}\n </nav>\n </section>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/tab-scaffold.tsx"],"names":[],"mappings":";;;AA6BO,SAAS,WAAA,CAA+B;AAAA,EAC7C,EAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,EAAyB;AACvB,EAAA,uBACE,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC5C,EAAA;AAAA,MACA,gBAAA,EAAe,cAAA;AAAA,MACf,sBAAA,EAAsB,EAAA;AAAA,MAEtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,SAAI,KAAA,EAAM,0BAAA,EACR,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,yBAAA;AAAA,YACN,2BAAyB,GAAA,CAAI,EAAA;AAAA,YAC7B,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YACrC,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YAEpC,QAAA,EAAA,GAAA,CAAI;AAAA;AAAA,SAER,CAAA,EACH,CAAA;AAAA,wBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAwB,IAAA,EAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAC3D,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,IAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,uBAAA;AAAA,YACN,IAAA,EAAK,KAAA;AAAA,YACL,yBAAuB,GAAA,CAAI,EAAA;AAAA,YAC3B,eAAA,EAAe,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YACvC,QAAA,EAAU,GAAA,CAAI,EAAA,KAAO,MAAA,GAAS,GAAA,GAAM,IAAA;AAAA,YAEnC,QAAA,EAAA;AAAA,cAAA,GAAA,CAAI,IAAA,wBACF,MAAA,EAAA,EAAK,KAAA,EAAM,8BAA6B,aAAA,EAAY,MAAA,EAClD,cAAI,IAAA,EACP,CAAA;AAAA,8BAEF,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,6BAAA,EAA+B,cAAI,KAAA,EAAM;AAAA;AAAA;AAAA,SAExD,CAAA,EACH;AAAA;AAAA;AAAA,GACF;AAEJ","file":"tab-scaffold.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface TabScaffoldTab<Id extends string = string> {\n id: Id;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: SafeHtml;\n}\n\nexport interface TabScaffoldProps<Id extends string = string> {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: readonly TabScaffoldTab<Id>[];\n /** The controlled active tab id (the app owns selection). */\n active: NoInfer<Id>;\n className?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab scaffold: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-scaffold`'s `wireTabScaffold`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabScaffold<Id extends string>({\n id,\n label,\n tabs,\n active,\n className = '',\n}: TabScaffoldProps<Id>) {\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n aria-hidden={String(tab.id !== active)}\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n >\n {tab.icon && (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n </span>\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n ))}\n </nav>\n </section>\n );\n}\n"]}
@@ -6,7 +6,15 @@ interface TokenSearchToken {
6
6
  offset?: number;
7
7
  accessibleLabel?: string;
8
8
  }
9
- interface TokenSearchFieldProps {
9
+ type TokenSearchEditorAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
10
+ 'data-component'?: never;
11
+ 'data-key'?: never;
12
+ 'data-morph-skip'?: never;
13
+ 'data-token-search-editor'?: never;
14
+ 'data-token-count'?: never;
15
+ 'data-placeholder'?: never;
16
+ }>;
17
+ interface TokenSearchFieldBaseProps {
10
18
  id: string;
11
19
  label: string;
12
20
  query?: string;
@@ -15,12 +23,6 @@ interface TokenSearchFieldProps {
15
23
  tokenPlaceholder?: string;
16
24
  disabled?: boolean;
17
25
  autofocus?: boolean;
18
- /** Allow an empty field to render as one iconic action. */
19
- collapsible?: boolean;
20
- /** Keep an empty collapsible field open while the application owns focus. */
21
- expanded?: boolean;
22
- expandAction?: string;
23
- expandLabel?: string;
24
26
  leading?: SafeHtml;
25
27
  trailing?: SafeHtml;
26
28
  editAction?: string;
@@ -28,8 +30,22 @@ interface TokenSearchFieldProps {
28
30
  clearAction?: string;
29
31
  clearLabel?: string;
30
32
  className?: string;
31
- editorAttributes?: Readonly<Record<`data-${string}`, string>>;
33
+ editorAttributes?: TokenSearchEditorAttributes;
32
34
  }
35
+ type TokenSearchCollapsibleProps = {
36
+ /** Allow an empty field to render as one iconic action. */
37
+ collapsible: true;
38
+ /** Keep an empty collapsible field open while the application owns focus. */
39
+ expanded?: boolean;
40
+ expandAction?: string;
41
+ expandLabel?: string;
42
+ } | {
43
+ collapsible?: false;
44
+ expanded?: never;
45
+ expandAction?: never;
46
+ expandLabel?: never;
47
+ };
48
+ type TokenSearchFieldProps = TokenSearchFieldBaseProps & TokenSearchCollapsibleProps;
33
49
  interface TokenSearchFieldValue {
34
50
  query: string;
35
51
  tokens: TokenSearchToken[];
@@ -40,4 +56,4 @@ declare function readTokenSearchField(editor: HTMLElement, knownTokens?: readonl
40
56
  /** Focus an editor and place its caret at a text offset, skipping atomic token chips. */
41
57
  declare function placeTokenSearchCaret(editor: HTMLElement, offset?: number): void;
42
58
 
43
- export { TokenSearchField, type TokenSearchFieldProps, type TokenSearchFieldValue, type TokenSearchToken, placeTokenSearchCaret, readTokenSearchField };
59
+ export { type TokenSearchEditorAttributes, TokenSearchField, type TokenSearchFieldProps, type TokenSearchFieldValue, type TokenSearchToken, placeTokenSearchCaret, readTokenSearchField };
@@ -1,4 +1,4 @@
1
- export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-S3HKPI7I.js';
1
+ export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-7KEUJIIC.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=token-search-field.js.map
@@ -1,17 +1,21 @@
1
1
  import { SafeHtml } from 'kerfjs';
2
2
 
3
+ type ToolbarControlGroupAppearance = 'contained' | 'borderless';
4
+ type ToolbarControlGroupTone = 'default' | 'dark';
5
+ type ToolbarControlGroupButtonAppearance = 'plain' | 'push';
6
+ type ToolbarControlGroupShape = 'pill' | 'rounded';
3
7
  interface ToolbarControlGroupProps {
4
8
  children: SafeHtml | SafeHtml[];
5
9
  label?: string;
6
10
  className?: string;
7
11
  expanded?: boolean;
8
12
  single?: boolean;
9
- appearance?: 'contained' | 'borderless';
10
- tone?: 'default' | 'dark';
11
- buttonAppearance?: 'plain' | 'push';
13
+ appearance?: ToolbarControlGroupAppearance;
14
+ tone?: ToolbarControlGroupTone;
15
+ buttonAppearance?: ToolbarControlGroupButtonAppearance;
12
16
  /** Corner shape: fully round `pill` (default) or a softer `rounded` rectangle. */
13
- shape?: 'pill' | 'rounded';
17
+ shape?: ToolbarControlGroupShape;
14
18
  }
15
19
  declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, }: ToolbarControlGroupProps): SafeHtml;
16
20
 
17
- export { ToolbarControlGroup, type ToolbarControlGroupProps };
21
+ export { ToolbarControlGroup, type ToolbarControlGroupAppearance, type ToolbarControlGroupButtonAppearance, type ToolbarControlGroupProps, type ToolbarControlGroupShape, type ToolbarControlGroupTone };
@@ -1,3 +1,3 @@
1
- export { ToolbarControlGroup } from './chunk-ZK2G3VR5.js';
1
+ export { ToolbarControlGroup } from './chunk-5VTB2BKP.js';
2
2
 
3
3
  //# sourceMappingURL=toolbar-control-group.js.map
@@ -3,7 +3,7 @@ import * as kerfjs from 'kerfjs';
3
3
  type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small';
4
4
  /** ARIA heading level for a title exposed as a heading landmark. */
5
5
  type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
6
- interface ToolbarTextProps {
6
+ interface ToolbarTextBaseProps {
7
7
  text: string;
8
8
  size?: ToolbarTextSize;
9
9
  className?: string;
@@ -17,23 +17,22 @@ interface ToolbarTextProps {
17
17
  headingLevel?: HeadingLevel;
18
18
  /** Render the text as an unanimated loading skeleton instead of its value. */
19
19
  placeholder?: boolean;
20
- /**
21
- * Wrap onto multiple lines when the text does not fit, instead of the default
22
- * single line. Combine with `maxLines` to cap the number of lines. Default false.
23
- */
24
- wrap?: boolean;
25
20
  /**
26
21
  * Show a trailing ellipsis (…) where the text is truncated — on the single line
27
22
  * (default), or at the `maxLines` boundary when wrapping. Set false to hard-clip
28
23
  * instead. Default true.
29
24
  */
30
25
  ellipsis?: boolean;
31
- /**
32
- * Cap wrapped text to this many lines, truncating past it. Only takes effect with
33
- * `wrap`; ignored on a single line. `null`/omitted wraps without a line cap. Default null.
34
- */
35
- maxLines?: number | null;
36
26
  }
27
+ type ToolbarTextWrappingProps = {
28
+ /** Wrap onto multiple lines; combine with `maxLines` to cap them. */
29
+ wrap: true;
30
+ maxLines?: number | null;
31
+ } | {
32
+ wrap?: false;
33
+ maxLines?: never;
34
+ };
35
+ type ToolbarTextProps = ToolbarTextBaseProps & ToolbarTextWrappingProps;
37
36
  declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, }: ToolbarTextProps): kerfjs.SafeHtml;
38
37
 
39
38
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
@@ -1,4 +1,4 @@
1
- export { ToolbarText } from './chunk-S3PCZ7NV.js';
1
+ export { ToolbarText } from './chunk-W7YD6E4N.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=toolbar-text.js.map
@@ -1,3 +1,6 @@
1
+ import { TabActivation } from './tab-bar.js';
2
+ import 'kerfjs';
3
+
1
4
  type TabReorderSource = 'pointer' | 'keyboard';
2
5
  type TabDropPosition = 'before' | 'after';
3
6
  interface TabReorder {
@@ -7,7 +10,7 @@ interface TabReorder {
7
10
  position: TabDropPosition;
8
11
  source: TabReorderSource;
9
12
  }
10
- type TabActivation = 'automatic' | 'manual';
13
+
11
14
  interface WireTabBarsOptions {
12
15
  onReorder: (change: TabReorder) => void;
13
16
  /**
@@ -27,4 +30,4 @@ declare function reorderTabs<T>(items: readonly T[], getId: (item: T) => string,
27
30
  /** Wire reordering and keyboard navigation while leaving controlled state in the application. */
28
31
  declare function wireTabBars(root: HTMLElement | Document, { onReorder, activation }: WireTabBarsOptions): () => void;
29
32
 
30
- export { type TabActivation, type TabDropPosition, type TabReorder, type TabReorderSource, type WireTabBarsOptions, reorderTabs, wireTabBars };
33
+ export { TabActivation, type TabDropPosition, type TabReorder, type TabReorderSource, type WireTabBarsOptions, reorderTabs, wireTabBars };
@@ -1,3 +1,3 @@
1
- export { reorderTabs, wireTabBars } from './chunk-NVWXKU37.js';
1
+ export { reorderTabs, wireTabBars } from './chunk-AASLYRGE.js';
2
2
 
3
3
  //# sourceMappingURL=wire-tab-bars.js.map
@@ -29,21 +29,26 @@ interface TokenSearchTokenRemoval {
29
29
  * for the caller to apply, while caret movement past a chip is a pure ephemeral
30
30
  * mechanic the helper performs itself.
31
31
  */
32
- interface TokenSearchKeyboardOptions {
32
+ interface TokenSearchKeyboardBaseOptions {
33
33
  /**
34
34
  * From a collapsed caret with no selection, Backspace removes the token
35
35
  * immediately before it and Delete the token immediately after — reported via
36
36
  * `onRemoveToken` — instead of deleting a character. Default: true.
37
37
  */
38
- removeAdjacentToken?: boolean;
39
38
  /**
40
39
  * ArrowRight moves the caret past a trailing atomic token so text typed next
41
40
  * lands after the chip. Default: true.
42
41
  */
43
42
  moveCaretPastToken?: boolean;
44
- /** Apply the reported removal to your controlled state, then re-render. */
45
- onRemoveToken?: (removal: TokenSearchTokenRemoval) => void;
46
43
  }
44
+ type TokenSearchKeyboardOptions = TokenSearchKeyboardBaseOptions & ({
45
+ removeAdjacentToken?: true;
46
+ /** Apply the reported removal to your controlled state, then re-render. */
47
+ onRemoveToken: (removal: TokenSearchTokenRemoval) => void;
48
+ } | {
49
+ removeAdjacentToken: false;
50
+ onRemoveToken?: never;
51
+ });
47
52
  /**
48
53
  * Managed collapsible behavior for the iconic TokenSearchField. Every piece is on
49
54
  * by default; disable a specific one to own it in the app. Provide `signals` to
@@ -76,8 +81,8 @@ interface WireTokenSearchFieldsOptions {
76
81
  onEdit?: (edit: TokenSearchEdit) => void;
77
82
  /** Managed collapsible transient behavior. `true`/omitted = on with defaults; `false` = fully off. */
78
83
  collapsible?: boolean | TokenSearchCollapsibleOptions;
79
- /** Opt-in atomic-chip keyboard behavior (off by default). `true` = on with defaults. */
80
- keyboard?: boolean | TokenSearchKeyboardOptions;
84
+ /** Opt-in atomic-chip keyboard behavior (off by default). */
85
+ keyboard?: false | TokenSearchKeyboardOptions;
81
86
  }
82
87
  /**
83
88
  * The value returned from {@link wireTokenSearchFields}: call it (or `dispose()`) to
@@ -1,4 +1,4 @@
1
- export { wireTokenSearchFields } from './chunk-ENVTNLYC.js';
1
+ export { wireTokenSearchFields } from './chunk-GP5DP5DL.js';
2
2
 
3
3
 
4
4