@kerfjs/ui 5.0.0-beta.60 → 5.0.0-beta.61

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 (95) hide show
  1. package/README.md +1 -0
  2. package/ai/component-catalog.json +129 -19
  3. package/ai/component-composition-rules.json +8 -0
  4. package/ai/component-composition.d.ts +10 -0
  5. package/ai/component-composition.json +109 -7
  6. package/ai/component-composition.schema.json +21 -0
  7. package/ai/components/README.md +5 -4
  8. package/ai/components/chip.md +72 -0
  9. package/ai/components/grid.md +10 -7
  10. package/ai/components/list-item.md +10 -7
  11. package/ai/components/select.md +5 -2
  12. package/ai/components/tabs.md +8 -4
  13. package/ai/components/toolbar.md +3 -2
  14. package/ai/public-api-signatures-v1.md +90 -14
  15. package/ai/skill.md +21 -3
  16. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  17. package/dist/app-tab.d.ts +12 -2
  18. package/dist/app-tab.js +1 -1
  19. package/dist/browser/chip.js +3 -0
  20. package/dist/catalog.js +6 -6
  21. package/dist/chip.d.ts +29 -0
  22. package/dist/chip.js +3 -0
  23. package/dist/chip.js.map +1 -0
  24. package/dist/{chunk-F7F7KRO2.js → chunk-4SQK27MR.js} +33 -18
  25. package/dist/chunk-4SQK27MR.js.map +1 -0
  26. package/dist/{chunk-46263QLK.js → chunk-C4OYOKWX.js} +18 -6
  27. package/dist/chunk-C4OYOKWX.js.map +1 -0
  28. package/dist/chunk-EAC4CDY7.js +57 -0
  29. package/dist/chunk-EAC4CDY7.js.map +1 -0
  30. package/dist/{chunk-T57AXDFM.js → chunk-NYL63PSD.js} +2 -2
  31. package/dist/{chunk-T57AXDFM.js.map → chunk-NYL63PSD.js.map} +1 -1
  32. package/dist/{chunk-T66UNBXL.js → chunk-Q6YU3BT7.js} +11 -2
  33. package/dist/chunk-Q6YU3BT7.js.map +1 -0
  34. package/dist/chunk-SWVW56CV.js +188 -0
  35. package/dist/chunk-SWVW56CV.js.map +1 -0
  36. package/dist/{chunk-WPLIO5WJ.js → chunk-TEYARRAK.js} +37 -5
  37. package/dist/chunk-TEYARRAK.js.map +1 -0
  38. package/dist/{chunk-AGXQQFKZ.js → chunk-UCKKT6KO.js} +13 -4
  39. package/dist/chunk-UCKKT6KO.js.map +1 -0
  40. package/dist/{chunk-UWONG4QE.js → chunk-VCBTX62E.js} +11 -3
  41. package/dist/chunk-VCBTX62E.js.map +1 -0
  42. package/dist/{chunk-2OXQHM7I.js → chunk-Y74NWGQW.js} +3 -3
  43. package/dist/{chunk-2OXQHM7I.js.map → chunk-Y74NWGQW.js.map} +1 -1
  44. package/dist/collapsible-panel.js +2 -2
  45. package/dist/grid.d.ts +13 -5
  46. package/dist/grid.js +1 -1
  47. package/dist/index.d.ts +4 -3
  48. package/dist/index.js +14 -13
  49. package/dist/list-item.d.ts +11 -1
  50. package/dist/list-item.js +1 -1
  51. package/dist/popup-menu.d.ts +2 -2
  52. package/dist/popup-menu.js +1 -1
  53. package/dist/select-register.js +46 -0
  54. package/dist/select-register.js.map +1 -1
  55. package/dist/select.d.ts +14 -0
  56. package/dist/select.js +1 -1
  57. package/dist/styles/app-tab.css +35 -0
  58. package/dist/styles/chip.css +118 -0
  59. package/dist/styles/grid.css +7 -0
  60. package/dist/styles/list-item.css +14 -9
  61. package/dist/styles/popup-menu.css +2 -1
  62. package/dist/styles/segmented-control.css +2 -1
  63. package/dist/styles/select.css +30 -0
  64. package/dist/styles/styles.css +1 -0
  65. package/dist/styles/toolbar.css +8 -5
  66. package/dist/{token-search-field-CCke1yvQ.d.ts → token-search-field-DvgFLhLL.d.ts} +6 -2
  67. package/dist/token-search-field.d.ts +1 -1
  68. package/dist/token-search-model.d.ts +1 -1
  69. package/dist/token-search-model.js +1 -1
  70. package/dist/wire-catalog.js +1 -1
  71. package/dist/wire-tab-bars.js +1 -1
  72. package/dist/wire-token-search-fields.d.ts +1 -1
  73. package/dist/workbench.js +1 -1
  74. package/docs/accessibility.md +29 -3
  75. package/docs/component-contract.md +5 -0
  76. package/docs/component-selection.md +66 -4
  77. package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
  78. package/docs/design/templates/segmented-control/equal.svg +1 -1
  79. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
  80. package/docs/design/templates/segmented-control/pill-small.svg +1 -1
  81. package/docs/design/templates/segmented-control-dark.svg +1 -1
  82. package/docs/design/templates/segmented-control.svg +1 -1
  83. package/docs/layout.md +20 -9
  84. package/docs/sunken-panel.md +5 -0
  85. package/docs/webawesome-theme.md +32 -0
  86. package/llms.txt +36 -8
  87. package/package.json +7 -1
  88. package/dist/chunk-46263QLK.js.map +0 -1
  89. package/dist/chunk-5I7OHCIP.js +0 -96
  90. package/dist/chunk-5I7OHCIP.js.map +0 -1
  91. package/dist/chunk-AGXQQFKZ.js.map +0 -1
  92. package/dist/chunk-F7F7KRO2.js.map +0 -1
  93. package/dist/chunk-T66UNBXL.js.map +0 -1
  94. package/dist/chunk-UWONG4QE.js.map +0 -1
  95. package/dist/chunk-WPLIO5WJ.js.map +0 -1
package/dist/select.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Select } from './chunk-WPLIO5WJ.js';
1
+ export { Select } from './chunk-TEYARRAK.js';
2
2
 
3
3
 
4
4
 
@@ -13,6 +13,9 @@
13
13
  transparent
14
14
  );
15
15
  --kui-app-tab-drop-indicator: var(--kui-color-brand-border-normal);
16
+ --kui-app-tab-drop-target-background: var(--kui-color-brand-fill-quiet);
17
+ --kui-app-tab-drop-target-ring: var(--kui-color-brand-border-normal);
18
+ --kui-app-tab-drop-target-color: var(--kui-color-brand-on-quiet);
16
19
  position: relative;
17
20
  display: flex;
18
21
  width: max-content;
@@ -26,6 +29,28 @@
26
29
  align-items: center;
27
30
  flex: none;
28
31
  }
32
+ .kui-app-tab[data-pinned="true"] {
33
+ position: sticky;
34
+ z-index: 1;
35
+ inset-inline-start: 0;
36
+ background: var(
37
+ --kui-app-tab-pinned-background,
38
+ var(--_kui-app-tab-pinned-default-background, var(--kui-color-surface))
39
+ );
40
+ }
41
+ .kui-tab-bar[data-presentation="segmented"] .kui-app-tab[data-pinned="true"],
42
+ .kui-tab-bar[data-presentation="inspector"] .kui-app-tab[data-pinned="true"] {
43
+ --_kui-app-tab-pinned-default-background: var(
44
+ --kui-tab-bar-strip-background,
45
+ var(--kui-color-neutral-fill-quiet)
46
+ );
47
+ }
48
+ .kui-app-tab[data-pinned="true"]:not([data-selected="true"]):hover {
49
+ background: var(
50
+ --kui-app-tab-pinned-hover-background,
51
+ var(--kui-color-neutral-fill-quiet)
52
+ );
53
+ }
29
54
  .kui-app-tab[data-size="compact"] {
30
55
  height: 2rem;
31
56
  }
@@ -43,6 +68,11 @@
43
68
  background: var(--kui-app-tab-selected-background);
44
69
  box-shadow: var(--kui-shadow-s);
45
70
  }
71
+ .kui-app-tab[data-drop-target="true"] {
72
+ color: var(--kui-app-tab-drop-target-color);
73
+ background: var(--kui-app-tab-drop-target-background);
74
+ box-shadow: inset 0 0 0 2px var(--kui-app-tab-drop-target-ring);
75
+ }
46
76
  .kui-app-tab[data-tab-dragging="true"] {
47
77
  opacity: 0.55;
48
78
  }
@@ -106,6 +136,11 @@
106
136
  text-overflow: ellipsis;
107
137
  white-space: nowrap;
108
138
  }
139
+ .kui-app-tab[data-name-overflow="visible"] .kui-app-tab__name {
140
+ max-width: none;
141
+ overflow: visible;
142
+ text-overflow: clip;
143
+ }
109
144
  .kui-app-tab[data-attention="true"] .kui-app-tab__name {
110
145
  color: var(--kui-app-tab-attention-color, var(--kui-color-warning-on-quiet));
111
146
  }
@@ -0,0 +1,118 @@
1
+ .kui-chip {
2
+ --_kui-chip-fill-quiet: var(--kui-color-neutral-fill-quiet);
3
+ --_kui-chip-fill-solid: var(--kui-color-neutral-on-normal);
4
+ --_kui-chip-border: var(--kui-color-neutral-border-normal);
5
+ --_kui-chip-on-quiet: var(--kui-color-neutral-on-quiet);
6
+ --_kui-chip-on-solid: var(--kui-color-surface);
7
+
8
+ display: inline-flex;
9
+ min-width: 0;
10
+ min-height: 1.75rem;
11
+ padding-inline: 0.5rem;
12
+ box-sizing: border-box;
13
+ border: 1px solid transparent;
14
+ border-radius: var(--kui-layout-pill-radius, calc(1px + 1.3125rem));
15
+ color: var(--_kui-chip-on-quiet);
16
+ background: var(--_kui-chip-fill-quiet);
17
+ align-items: center;
18
+ gap: 0.25rem;
19
+ font-size: var(--kui-font-xs);
20
+ font-weight: 650;
21
+ line-height: 1;
22
+ white-space: nowrap;
23
+ }
24
+
25
+ .kui-chip[data-tone="brand"] {
26
+ --_kui-chip-fill-quiet: var(--kui-color-brand-fill-quiet);
27
+ --_kui-chip-fill-solid: var(--kui-color-brand-on-fill);
28
+ --_kui-chip-border: var(--kui-color-brand-border-normal);
29
+ --_kui-chip-on-quiet: var(--kui-color-brand-on-fill);
30
+ }
31
+
32
+ .kui-chip[data-tone="pop"] {
33
+ --_kui-chip-fill-quiet: var(--kui-color-pop-fill-quiet);
34
+ --_kui-chip-fill-solid: var(--kui-color-pop-on-fill);
35
+ --_kui-chip-border: var(--kui-color-pop-border-normal);
36
+ --_kui-chip-on-quiet: var(--kui-color-pop-on-fill);
37
+ }
38
+
39
+ .kui-chip[data-tone="success"] {
40
+ --_kui-chip-fill-quiet: var(--kui-color-success-fill-quiet);
41
+ --_kui-chip-fill-solid: var(--kui-color-success-on-fill);
42
+ --_kui-chip-border: var(--kui-color-success-border-normal);
43
+ --_kui-chip-on-quiet: var(--kui-color-success-on-fill);
44
+ }
45
+
46
+ .kui-chip[data-tone="warning"] {
47
+ --_kui-chip-fill-quiet: var(--kui-color-warning-fill-quiet);
48
+ --_kui-chip-fill-solid: var(--kui-color-warning-on-fill);
49
+ --_kui-chip-border: var(--kui-color-warning-border-normal);
50
+ --_kui-chip-on-quiet: var(--kui-color-warning-on-fill);
51
+ }
52
+
53
+ .kui-chip[data-tone="danger"] {
54
+ --_kui-chip-fill-quiet: var(--kui-color-danger-fill-quiet);
55
+ --_kui-chip-fill-solid: var(--kui-color-danger-on-fill);
56
+ --_kui-chip-border: var(--kui-color-danger-border-normal);
57
+ --_kui-chip-on-quiet: var(--kui-color-danger-on-fill);
58
+ }
59
+
60
+ .kui-chip[data-appearance="solid"] {
61
+ color: var(--_kui-chip-on-solid);
62
+ background: var(--_kui-chip-fill-solid);
63
+ }
64
+
65
+ .kui-chip[data-appearance="outline"] {
66
+ border-color: var(--_kui-chip-border);
67
+ background: transparent;
68
+ }
69
+
70
+ .kui-chip[data-shape="rounded"] {
71
+ border-radius: var(--kui-radius-s);
72
+ }
73
+
74
+ .kui-chip[data-size="compact"] {
75
+ min-height: 1.25rem;
76
+ padding-inline: 0.3125rem;
77
+ font-size: var(--kui-font-2xs);
78
+ }
79
+
80
+ .kui-chip[data-disabled] {
81
+ opacity: 0.5;
82
+ pointer-events: none;
83
+ }
84
+
85
+ .kui-chip__label {
86
+ min-width: 0;
87
+ overflow: hidden;
88
+ text-overflow: ellipsis;
89
+ }
90
+
91
+ .kui-chip__remove {
92
+ display: inline-grid;
93
+ width: 1.25rem;
94
+ height: 1.25rem;
95
+ padding: 0;
96
+ border: 0;
97
+ border-radius: 50%;
98
+ color: inherit;
99
+ background: transparent;
100
+ align-items: center;
101
+ justify-items: center;
102
+ cursor: pointer;
103
+ flex: none;
104
+ }
105
+
106
+ .kui-chip[data-size="compact"] .kui-chip__remove {
107
+ width: 1rem;
108
+ height: 1rem;
109
+ }
110
+
111
+ .kui-chip__remove:hover {
112
+ background: color-mix(in srgb, currentColor 12%, transparent);
113
+ }
114
+
115
+ .kui-chip__remove:focus-visible {
116
+ outline: var(--kui-focus-ring);
117
+ outline-offset: 1px;
118
+ }
@@ -14,6 +14,13 @@
14
14
  gap: var(--_kui-grid-gap, var(--kui-grid-gap));
15
15
  }
16
16
 
17
+ .kui-grid[data-min-column-width="true"] {
18
+ grid-template-columns: repeat(
19
+ auto-fit,
20
+ minmax(min(100%, var(--_kui-grid-min-column-width)), 1fr)
21
+ );
22
+ }
23
+
17
24
  /* `fill`: the layout root of a definite-height parent (an app root or a
18
25
  fixed-height frame) takes its full height. Inside a flex layout use `flex`. */
19
26
  .kui-grid[data-fill="true"] {
@@ -1,12 +1,8 @@
1
1
  .kui-list-item {
2
2
  --kui-list-group-divider-color: var(--kui-color-neutral-border-quiet);
3
3
  --kui-list-item-color: var(--kui-color-neutral-on-normal);
4
- --kui-list-item-border: transparent;
5
- --kui-list-item-background: transparent;
6
- --kui-list-item-hover-border: var(--kui-color-neutral-border-normal);
7
4
  --kui-list-item-hover-background: var(--kui-color-neutral-fill-quiet);
8
5
  --kui-list-item-selected-color: var(--kui-color-neutral-on-normal);
9
- --kui-list-item-selected-border: var(--kui-color-brand-border-quiet);
10
6
  --kui-list-item-selected-background: var(--kui-color-brand-fill-normal);
11
7
  display: grid;
12
8
  width: calc(100% - (2 * var(--kui-layout-inline-margin, 0.5rem)));
@@ -23,19 +19,20 @@
23
19
  );
24
20
  box-sizing: border-box;
25
21
  border: var(--kui-list-item-border-width, 1px) solid
26
- var(--kui-list-item-border);
22
+ var(--kui-list-item-border, transparent);
27
23
  border-radius: var(
28
24
  --kui-list-item-radius,
29
25
  var(--kui-layout-rounded-radius, calc(1px + 0.6875rem))
30
26
  );
31
27
  color: var(--kui-list-item-color);
32
- background: var(--kui-list-item-background);
28
+ background: var(--kui-list-item-background, transparent);
33
29
  cursor: pointer;
34
30
  grid-template-columns: var(--kui-list-item-columns, minmax(0, 1fr) auto);
35
31
  align-items: var(--kui-list-item-align-items, center);
36
32
  column-gap: var(--kui-list-item-gap, var(--kui-layout-item-gap, 0.5rem));
37
33
  font: inherit;
38
34
  text-align: start;
35
+ text-decoration: none;
39
36
  }
40
37
 
41
38
  .kui-list-item[data-density="compact"] {
@@ -98,7 +95,10 @@
98
95
  }
99
96
 
100
97
  .kui-list-item:hover:not([data-placeholder="true"]) {
101
- border-color: var(--kui-list-item-hover-border);
98
+ border-color: var(
99
+ --kui-list-item-hover-border,
100
+ var(--kui-color-neutral-border-normal)
101
+ );
102
102
  background: var(--kui-list-item-hover-background);
103
103
  }
104
104
 
@@ -112,13 +112,18 @@
112
112
  opacity: 0.58;
113
113
  }
114
114
 
115
- .kui-list-item:disabled:not([data-placeholder="true"]) {
115
+ .kui-list-item:is(:disabled, [aria-disabled="true"]):not(
116
+ [data-placeholder="true"]
117
+ ) {
116
118
  cursor: not-allowed;
117
119
  }
118
120
 
119
121
  .kui-list-item[aria-current="page"],
120
122
  .kui-list-item[aria-pressed="true"] {
121
- border-color: var(--kui-list-item-selected-border);
123
+ border-color: var(
124
+ --kui-list-item-selected-border,
125
+ var(--kui-color-brand-border-quiet)
126
+ );
122
127
  color: var(--kui-list-item-selected-color);
123
128
  background: var(--kui-list-item-selected-background);
124
129
  font-weight: 650;
@@ -54,7 +54,8 @@
54
54
  color: var(--_kui-popup-row-current-color);
55
55
  background-color: var(--_kui-popup-row-current-background);
56
56
  }
57
- .kui-popup-menu > wa-divider {
57
+ .kui-popup-menu > wa-divider,
58
+ .kui-popup-menu wa-divider[slot="submenu"] {
58
59
  --spacing: 0.5em;
59
60
  }
60
61
 
@@ -1,7 +1,7 @@
1
1
  .kui-segmented-control {
2
2
  --kui-segmented-background: var(--kui-color-neutral-fill-normal);
3
3
  --kui-segmented-border: transparent;
4
- --kui-segmented-foreground: var(--kui-color-neutral-on-quiet);
4
+ --kui-segmented-foreground: var(--kui-color-neutral-on-normal);
5
5
  --kui-segmented-hover-background: var(--kui-color-surface);
6
6
  --kui-segmented-hover-border: var(--kui-color-neutral-border-normal);
7
7
  --kui-segmented-selected-background: var(--kui-color-surface);
@@ -38,6 +38,7 @@
38
38
  .kui-segmented-control[data-appearance="outlined"] {
39
39
  --kui-segmented-border: var(--kui-color-neutral-border-normal);
40
40
  --kui-segmented-background: var(--kui-color-surface);
41
+ --kui-segmented-foreground: var(--kui-color-neutral-on-quiet);
41
42
  }
42
43
 
43
44
  .kui-segmented-control[data-appearance="toolbar"] {
@@ -233,6 +233,36 @@
233
233
  text-transform: uppercase;
234
234
  }
235
235
 
236
+ .kui-select__actions {
237
+ display: flex;
238
+ gap: 0.25rem;
239
+ margin-block-start: 0.25rem;
240
+ padding-block-start: 0.5rem;
241
+ border-block-start: 1px solid var(--kui-color-neutral-border-quiet);
242
+ }
243
+
244
+ .kui-select__action {
245
+ flex: 1 1 auto;
246
+ min-width: 0;
247
+ min-height: 2.25rem;
248
+ padding-inline: 0.5rem;
249
+ border: 0;
250
+ border-radius: var(--kui-radius-s);
251
+ color: var(--kui-color-neutral-on-quiet);
252
+ background: transparent;
253
+ font: inherit;
254
+ cursor: pointer;
255
+ }
256
+
257
+ .kui-select__action:hover {
258
+ background: var(--kui-color-neutral-fill-quiet);
259
+ }
260
+
261
+ .kui-select__action:focus-visible {
262
+ outline: var(--kui-focus-ring);
263
+ outline-offset: -2px;
264
+ }
265
+
236
266
  /* Loading placeholder: a static box that mirrors the closed combobox (label
237
267
  above, a value skeleton and a dormant chevron inside a 44px control box).
238
268
  Rendered instead of the interactive wa-select, so it needs no registration. */
@@ -1,6 +1,7 @@
1
1
  @import "./foundation.css";
2
2
  @import "./layout.css";
3
3
  @import "./badge.css";
4
+ @import "./chip.css";
4
5
  @import "./lucide-icon.css";
5
6
  @import "./disclosure-arrow.css";
6
7
  @import "./toolbar.css";
@@ -35,21 +35,24 @@
35
35
  column shrinks still keeps a whole control row clear of the unsafe area. */
36
36
  min-height: calc(
37
37
  var(--kui-toolbar-group-size, calc(2px + 2.625rem)) +
38
- (2 * var(--kui-toolbar-gap, 0.5rem)) +
38
+ (2 * var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem))) +
39
39
  var(--_kui-toolbar-safe-block-start) + var(--_kui-toolbar-safe-block-end)
40
40
  );
41
41
  padding-block: calc(
42
- var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-block-start)
42
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
43
+ var(--_kui-toolbar-safe-block-start)
43
44
  )
44
45
  calc(
45
- var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-block-end)
46
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
47
+ var(--_kui-toolbar-safe-block-end)
46
48
  );
47
49
  padding-inline: calc(
48
- var(--kui-toolbar-gap, 0.5rem) +
50
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
49
51
  var(--_kui-toolbar-safe-inline-start)
50
52
  )
51
53
  calc(
52
- var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-inline-end)
54
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
55
+ var(--_kui-toolbar-safe-inline-end)
53
56
  );
54
57
  }
55
58
 
@@ -8,8 +8,8 @@ interface TokenSearchRule {
8
8
  parse?: (input: string) => string | undefined;
9
9
  /** Label for a committed chip. Defaults to `name:input`. */
10
10
  label?: (value: string, input: string) => string;
11
- /** Suggestions for the unfinished value after `name:`. */
12
- suggest?: (input: string) => readonly (string | {
11
+ /** Suggestions for the unfinished value after `name:`, with current committed tokens. */
12
+ suggest?: (input: string, state: TokenSearchState) => readonly (string | {
13
13
  value: string;
14
14
  label: string;
15
15
  })[];
@@ -33,8 +33,12 @@ interface TokenSearchModel<Result = unknown> {
33
33
  suggestions: Signal<readonly TokenSearchSuggestion[]>;
34
34
  result: Signal<Result | undefined>;
35
35
  edit(value: TokenSearchFieldValue, commit?: boolean): void;
36
+ /** Replace app-owned search state and rebuild the DOM-owned editor text. */
37
+ replace(value: TokenSearchFieldValue): void;
36
38
  submit(value: TokenSearchFieldValue): void;
37
39
  choose(value: string): void;
40
+ /** Commit a value for the active `name:` prefix, even when it is not suggested. */
41
+ commit(value: string): void;
38
42
  expandToken(value: string): void;
39
43
  remove(value: string): void;
40
44
  clear(): void;
@@ -1,3 +1,3 @@
1
1
  import 'kerfjs';
2
2
  import './semantic-content-BbzjvSu9.js';
3
- export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, j as TokenSearchToken, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-field-CCke1yvQ.js';
3
+ export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, j as TokenSearchToken, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-field-DvgFLhLL.js';
@@ -1,3 +1,3 @@
1
1
  import 'kerfjs';
2
- export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion, k as createTokenSearchModel } from './token-search-field-CCke1yvQ.js';
2
+ export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion, k as createTokenSearchModel } from './token-search-field-DvgFLhLL.js';
3
3
  import './semantic-content-BbzjvSu9.js';
@@ -1,3 +1,3 @@
1
- export { createTokenSearchModel } from './chunk-F7F7KRO2.js';
1
+ export { createTokenSearchModel } from './chunk-4SQK27MR.js';
2
2
 
3
3
  //# sourceMappingURL=token-search-model.js.map
@@ -1,6 +1,6 @@
1
1
  import { wireWorkbench } from './chunk-NNMLEDMD.js';
2
- import { wireScrollDividers } from './chunk-JCV4GXWB.js';
3
2
 
3
+ import { wireScrollDividers } from './chunk-JCV4GXWB.js';
4
4
 
5
5
 
6
6
  import { delegate } from 'kerfjs';
@@ -1,3 +1,3 @@
1
- export { reorderTabs, wireTabBars } from './chunk-46263QLK.js';
1
+ export { reorderTabs, wireTabBars } from './chunk-C4OYOKWX.js';
2
2
 
3
3
  //# sourceMappingURL=wire-tab-bars.js.map
@@ -1,5 +1,5 @@
1
1
  import { Signal } from 'kerfjs';
2
- import { d as TokenSearchModel } from './token-search-field-CCke1yvQ.js';
2
+ import { d as TokenSearchModel } from './token-search-field-DvgFLhLL.js';
3
3
  import './semantic-content-BbzjvSu9.js';
4
4
 
5
5
  interface TokenSearchSubmit {
package/dist/workbench.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Workbench } from './chunk-2OXQHM7I.js';
1
+ export { Workbench } from './chunk-Y74NWGQW.js';
2
2
 
3
3
 
4
4
 
@@ -7,6 +7,7 @@ These are normative contracts for package components and consuming applications.
7
7
  - All controls have accessible names and visible `:focus-visible` treatment.
8
8
  - Decorative `LucideIcon` output is `aria-hidden`; pass `label` only when the SVG itself conveys meaning.
9
9
  - `ListItem` uses native button Enter/Space behavior. `selected` maps to `aria-current="page"`; `pressed` maps to `aria-pressed`. Selected rows keep the normal foreground over their brand-tinted fill so text retains WCAG AA contrast in light and dark themes. Its leading icon visual is 18px while the row retains its 44px minimum target; multiline icons align to the first text line. Its `trailing` content is dormant and must not contain controls. Its `rootAttributes` slot accepts only application `data-*` metadata and deliberately cannot emit `role="menuitem"` in isolation—a true ARIA menu must own arrow, Home/End, Escape, and focus behavior as one widget.
10
+ - `ListItemLink` shares that row content and geometry but uses native anchor Enter behavior and requires `href`. It has no `action` or `pressed` state. `external` opens a new tab with `rel="noopener noreferrer"`; the default accessible name announces the new tab for a string label, so an explicit `accessibleLabel` should do the same. Disabled and loading links omit `href`, expose `aria-disabled`, and leave the tab order. Its trailing content remains dormant.
10
11
  - `ListHeader` owns action naming, disabled state, and disclosure `aria-expanded`. Toggle mode supplies one decorative 18px `DisclosureArrow` when `actionIcon` is omitted; it mirrors `expanded` while the native button's accessible name stays stable. The application must update that controlled state and reveal or hide real content. A valid `count` is visually rendered in an `aria-hidden` neutral pill while the required localized `countLabel` becomes part of the owning heading or disclosure button's accessible name; zero remains a real count. Its narrow `triggerAttributes` slot may describe a native popover or controlled-content relationship with `popoverTarget`, `popoverTargetAction`, `aria-controls`, and `aria-haspopup`; the application owns the target surface and its focus/dismissal behavior.
11
12
  - Dispose `wireTabBars` and `wireTokenSearchFields` with their owning view. Disposal cancels queued controlled-render focus restoration, so a torn-down view cannot reclaim focus from its successor.
12
13
  - `wireNavStack` moves focus into every newly active top view and remembers the last focused descendant of each mounted view for pop restoration. Mark a preferred initial heading or control with `data-nav-focus` (and `tabindex="-1"` when it is not normally tabbable); otherwise the helper uses the first enabled focusable descendant, then a programmatically focusable view-container fallback.
@@ -14,6 +15,7 @@ These are normative contracts for package components and consuming applications.
14
15
  - `LoadingSpinner` is either labeled (`role="img"`) or hidden. Its rotation stops for reduced motion.
15
16
  - An unlabeled `Skeleton` (including the value slots a component's `placeholder` prop renders) is decorative loading chrome: it is `aria-hidden`, conveys no information a user needs to act on, and is deliberately exempt from the WCAG 3:1 non-text-contrast target. Inside a solid `Badge` it stays subtle (about 2.1–4.4:1 in light, 2.4–2.8:1 in dark, depending on tone); `tests/browser/tone-contrast.spec.ts` holds those values as a regression floor rather than an accessibility threshold. Announce loading through a labeled `Skeleton`, `LoadingSpinner`, or `aria-busy` on the owning region, never through the skeleton's visibility.
16
17
  - `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure. Its optional `badge` is persistent inline status/count content beside the title and is announced as part of the banner; keep it terse and do not rely on color alone for its meaning.
18
+ - A removable `Chip` has a native button with a specific `removeLabel`, such as "Remove Urgent tag". The button is absent for a plain chip and disabled for a disabled chip. Tag text remains visible because tone does not convey meaning alone.
17
19
  - `EmptyState` reports busy state through `aria-busy` and never relies on an illustration as its label.
18
20
  - `Select` follows the Web Awesome host's standard `input`/`change` events. Application tests verify the live `value`, focus, and events—not attributes alone. Its decorative option icons and value-dependent selected content remain present after controlled rerenders, so the visible choice does not silently lose its non-text cue.
19
21
  - `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may resize it with the typed `size` prop without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
@@ -38,6 +40,12 @@ chosen option shows its check, and the closed control reads the chosen labels
38
40
  in choice order as one short localized list (the `placeholderText` when none
39
41
  are chosen) instead of a removable tag per choice. `change` and `input` report
40
42
  the value array; in a form, every chosen value is submitted under `name`.
43
+ Disabled choices remain visible with `aria-disabled` and cannot be selected;
44
+ `disabledReason` adds a native tooltip. For a multiple Select, opt-in
45
+ `selectAllLabel` and `clearLabel` render named footer buttons. They keep the
46
+ popup open, select only enabled choices or clear the selection, and emit the
47
+ ordinary `input` and `change` events only when the value changes. Their labels
48
+ come from the application so they can be localized.
41
49
 
42
50
  A toolbar filter menu (a "Filter by label" funnel) is a multiple Select with
43
51
  `selectedPresentation="icon-only"` and a fixed `triggerIcon`; the types accept
@@ -196,7 +204,8 @@ with the Select's current-option fill rather than a second focus ring inside the
196
204
  open popup. A disabled item stays in the menu but cannot be
197
205
  chosen; disable the whole trigger only when every command is unavailable.
198
206
  Nested items use Web Awesome's submenu pointer and Left/Right arrow routing;
199
- checked items expose checkbox menu semantics. `details` supplies optional
207
+ headings and dividers can separate nested groups without becoming keyboard
208
+ choices. Checked items expose checkbox menu semantics. `details` supplies optional
200
209
  trailing visual content without changing a command's accessible label. A
201
210
  `context` menu's invisible anchor is outside the accessibility tree and normal
202
211
  Tab order; opening the menu moves focus into its commands and Escape dismisses
@@ -317,7 +326,11 @@ trailing, and end actions remain visible and do not shrink. The component owns
317
326
  that geometry; applications must not override its anatomy to create the split.
318
327
  `AppTab` provides compact 32px, segmented, truncating-label, and icon-only
319
328
  presentations. Icon-only tabs keep the required `name` as the tab button's
320
- accessible name while visually hiding the duplicate label. A `pending` tab (known,
329
+ accessible name while visually hiding the duplicate label. The default name
330
+ overflow is an ellipsis; `nameOverflow="visible"` lets an inline loading
331
+ treatment show the whole name, without changing the accessible name. The app
332
+ sets `dropTarget` during a content drag-over to paint a brand highlight;
333
+ selection and tab focus stay independent of that visual state. A `pending` tab (known,
321
334
  still opening) keeps its visible name as the tab button's accessible name, so a
322
335
  trailing spinner's own label is not folded into it. It is `aria-busy` and stays
323
336
  selectable (in the roving tab order like a live tab), so the application can
@@ -330,6 +343,12 @@ filtering rejects roles plus case variants of component- or wiring-owned
330
343
  action, identity, selection, drag, drop, and component attributes. An optional
331
344
  `closeIcon` is decorative dormant content inside the already named close button
332
345
  and must not contain interactive descendants.
346
+ The first `AppTab` can set `pinned` to stay at the inline start while its peers
347
+ scroll. It remains a normal tab within the same tablist and roving-focus order;
348
+ focus and controlled selection reveal peers beyond the pinned tab. Pin only the
349
+ leading tab of a strip.
350
+ WebKit currently moves a pinned tab outside an RTL strip as it scrolls;
351
+ `KF-MYFQAS` tracks the browser correction.
333
352
  `wireTabBars()` adds Left/Right wrapping, Home/End, Delete/Backspace close
334
353
  activation, same-bar pointer reordering, `Alt+Shift+ArrowLeft/ArrowRight`
335
354
  reordering, focus restoration, scroll-into-view, and pointer-proximity
@@ -363,7 +382,8 @@ stays in sequential Tab order, matching Hot Sheet 2's compact view and inspector
363
382
  controls; Enter and Space use native button activation. The application handles
364
383
  the supplied `data-action`, reads `data-segment-value`, updates `value`, and
365
384
  re-renders. Keep labels unique and meaningful even when `content` shows only an
366
- icon. Use tabs—not a segmented control—when choices switch page regions that
385
+ icon. The filled track uses the normal neutral text role for readable unselected
386
+ labels in light and dark themes. Use tabs—not a segmented control—when choices switch page regions that
367
387
  need `tab`/`tabpanel` semantics.
368
388
 
369
389
  ## TokenSearchField
@@ -390,6 +410,12 @@ trailing controls share the first text line's fixed vertical center and remain
390
410
  there as the editor wraps. In `collapsible` mode, the closed state is one named
391
411
  iconic search button and the open state is the same named searchbox, whether
392
412
  the field stands alone or is composed inside `ToolbarControlGroup`.
413
+
414
+ For an app-driven query replacement with an unmanaged field, change its
415
+ `revision` along with `query` so the editor text rebuilds. For a model-managed
416
+ field, call `model.replace({ query, tokens })`: it parses the supplied state and
417
+ advances `editorRevision` even when the tokens did not change.
418
+
393
419
  Applications set `expanded` while the field is focused, move focus from the
394
420
  trigger into the revealed editor, and clear `expanded` only after focus leaves
395
421
  the complete component. Text or tokens keep the field expanded even when that
@@ -52,6 +52,11 @@ CSS boundaries, diagnostics, and provenance. A wrapper entry may add
52
52
  composition checks treat its elements as each root rather than as an unknown
53
53
  child. A placement with listed parent constraints produces one `KUI-L201`
54
54
  diagnostic even when both the wrapper and a rendered root reject that parent.
55
+ When one catalog entry exports another JSX component with different placement,
56
+ `jsxExports` gives that export its own parent contract. The extra export does
57
+ not stand for the entry's root when a parent zone is checked.
58
+ Generated `boundaries.rootClass` prefers the public `kui-<entry-id>` class when
59
+ present, so a sibling export's class cannot become the entry's root class.
55
60
 
56
61
  `boundaries.placeableClasses` names the subset of `publicClasses` an
57
62
  application may write onto its own elements (layout utilities, the document