@kerfjs/ui 5.0.0-beta.102 → 5.0.0-beta.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/ai/component-catalog.json +10 -5
- package/ai/component-composition-rules.json +2 -1
- package/ai/component-composition.json +8 -1
- package/ai/components/README.md +1 -1
- package/ai/components/chip.md +7 -4
- package/ai/components/token-search-field.md +1 -0
- package/ai/public-api-signatures-v1.md +40 -10
- package/ai/skill.md +3 -3
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/catalog.js +1 -1
- package/dist/chip.d.ts +36 -6
- package/dist/chip.js +1 -1
- package/dist/{chunk-PKL6QJKK.js → chunk-CR5U5FV6.js} +2 -2
- package/dist/{chunk-PKL6QJKK.js.map → chunk-CR5U5FV6.js.map} +1 -1
- package/dist/{chunk-34U4ANDJ.js → chunk-N7MBGONH.js} +30 -2
- package/dist/chunk-N7MBGONH.js.map +1 -0
- package/dist/{chunk-IM3GKYOG.js → chunk-T5BJBMW7.js} +48 -28
- package/dist/chunk-T5BJBMW7.js.map +1 -0
- package/dist/{chunk-MF6ZUUJZ.js → chunk-ZJC5ND3M.js} +4 -6
- package/dist/chunk-ZJC5ND3M.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/styles/chip.css +38 -12
- package/dist/styles/components/actions/toolbar/toolbar.css +15 -0
- package/dist/styles/components/feedback/chip/chip.css +38 -12
- package/dist/styles/toolbar.css +15 -0
- package/dist/token-search-field.d.ts +1 -1
- package/dist/token-search-field.js +1 -1
- package/dist/{token-search-model-aYR0YAei.d.ts → token-search-model-JA1i8z4D.d.ts} +26 -2
- package/dist/token-search-model.d.ts +1 -1
- package/dist/token-search-model.js +1 -1
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-token-search-fields.d.ts +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/docs/accessibility.md +1 -1
- package/docs/component-selection.md +46 -2
- package/docs/design/templates/chip/action-filters-dark.svg +1 -0
- package/docs/design/templates/chip/action-filters.svg +1 -0
- package/docs/design/templates/chip/tags-dark.svg +1 -0
- package/docs/design/templates/chip/tags.svg +1 -0
- package/docs/design/templates/chip-dark.svg +1 -0
- package/docs/design/templates/chip.svg +1 -0
- package/llms.txt +12 -0
- package/package.json +1 -1
- package/dist/chunk-34U4ANDJ.js.map +0 -1
- package/dist/chunk-IM3GKYOG.js.map +0 -1
- package/dist/chunk-MF6ZUUJZ.js.map +0 -1
package/README.md
CHANGED
|
@@ -311,6 +311,9 @@ when it adds useful context. Set `responsive="wrap"` on a heading whose title
|
|
|
311
311
|
must stay whole: it keeps one row while everything fits and otherwise moves the
|
|
312
312
|
trailing actions below the title instead of truncating it.
|
|
313
313
|
|
|
314
|
+
A toolbar with a single zone gives it the whole content box, so content set to
|
|
315
|
+
fill the row reaches both insets; an absent zone leaves no empty track or gap.
|
|
316
|
+
|
|
314
317
|
A toolbar never clips an action. Its trailing zone wraps whole control groups
|
|
315
318
|
onto another trailing-aligned row under every `responsive` policy, and a
|
|
316
319
|
`responsive="stack"` toolbar wraps its stacked center and trailing groups the
|
|
@@ -778,7 +781,12 @@ pass it as the field's `model`, and register it under the field id in
|
|
|
778
781
|
their optional `suggest` function supplies selectable completions. The model
|
|
779
782
|
commits valid expressions on whitespace or Enter, owns chips and clear/edit/
|
|
780
783
|
remove actions, and exposes `state`, `suggestions`, and the latest `result` as
|
|
781
|
-
signals.
|
|
784
|
+
signals. The field subscribes only to `model.structure`, which changes when a
|
|
785
|
+
token is committed or removed, the text becomes empty or non-empty, or the
|
|
786
|
+
editor revision changes, so typing plain text never re-runs the host render.
|
|
787
|
+
Keep it that way in the host: read `model.state.peek()` in render, and bind
|
|
788
|
+
`model.result` (or a `computed`) as a fine-grained signal hole rather than
|
|
789
|
+
reading `model.state.value`. Omit the model to retain full manual control. Use `readTokenSearchField()`
|
|
782
790
|
after browser input to recover text plus token offsets, and
|
|
783
791
|
`placeTokenSearchCaret()` when restoring focus after a controlled update.
|
|
784
792
|
Call `wireTokenSearchFields()` once at a stable root to make Enter submit through
|
|
@@ -84,26 +84,29 @@
|
|
|
84
84
|
"category": "Foundation",
|
|
85
85
|
"kind": "component",
|
|
86
86
|
"source": "kerf",
|
|
87
|
-
"description": "A short tag with semantic or inherited tone, an optional accessible remove button,
|
|
87
|
+
"description": "A short tag with semantic or inherited tone, an optional accessible remove button, a native link and download form, or a native action button, including compact and disabled variants.",
|
|
88
88
|
"uses": [],
|
|
89
|
-
"purpose": "Render removable tags
|
|
89
|
+
"purpose": "Render removable tags, file or link chips, and activatable action chips without application rules on Web Awesome internals or anchor and button chrome.",
|
|
90
90
|
"publicExports": [
|
|
91
91
|
"Chip"
|
|
92
92
|
],
|
|
93
93
|
"useWhen": [
|
|
94
94
|
"Show a short tag that the application can remove through a delegated action, including a compact or disabled tag.",
|
|
95
|
-
"Show a downloadable file or a short link with chip geometry, such as the referenced files of a chat message; set tone inherit inside a brand-loud or neutral ContentItem bubble."
|
|
95
|
+
"Show a downloadable file or a short link with chip geometry, such as the referenced files of a chat message; set tone inherit inside a brand-loud or neutral ContentItem bubble.",
|
|
96
|
+
"Offer a short value the user can activate to apply it, such as a filter token in a search syntax help popover that inserts itself into the query: set action (and itemId) so the whole chip is a native button."
|
|
96
97
|
],
|
|
97
98
|
"avoidWhen": [
|
|
98
99
|
"Use Badge for non-interactive status and count metadata.",
|
|
99
100
|
"Do not use the remove button without a specific accessible name.",
|
|
100
|
-
"Use ListItemLink for a navigation row and ToolbarActionLink for a toolbar link."
|
|
101
|
+
"Use ListItemLink for a navigation row and ToolbarActionLink for a toolbar link.",
|
|
102
|
+
"Use ChoiceChips when the chips choose a persistent value with radio or checkbox state; an action chip fires a one-shot command."
|
|
101
103
|
],
|
|
102
104
|
"alternatives": [],
|
|
103
105
|
"appOwns": [
|
|
104
106
|
"tag text and identity",
|
|
105
107
|
"remove action and list update",
|
|
106
108
|
"link destination and download file name",
|
|
109
|
+
"action handler and its effect",
|
|
107
110
|
"disabled policy"
|
|
108
111
|
],
|
|
109
112
|
"variants": [
|
|
@@ -111,12 +114,13 @@
|
|
|
111
114
|
"quiet, solid, or outline appearance",
|
|
112
115
|
"pill or rounded shape",
|
|
113
116
|
"compact or default size",
|
|
114
|
-
"removable, link, or plain, enabled or disabled"
|
|
117
|
+
"removable, link, action, or plain, enabled or disabled"
|
|
115
118
|
],
|
|
116
119
|
"accessibility": [
|
|
117
120
|
"The remove control is a native button and requires an action and a specific removeLabel. A disabled chip disables that button and removes it from keyboard interaction.",
|
|
118
121
|
"A link chip is a native anchor named by its visible label; external adds a safe rel, a new tab, and an \"(opens in new tab)\" name suffix, and a disabled link chip drops its destination and leaves the tab order.",
|
|
119
122
|
"The inherit tone paints no fill, so its label keeps the surrounding text contrast, and its focus ring follows the surrounding foreground.",
|
|
123
|
+
"An action chip is one native button (type button) named by its visible label or by actionLabel, which should include that label; Enter and Space activate it, it shows the focus ring on keyboard focus, and a disabled action chip is a disabled button that leaves the tab order. It cannot also be a link or carry a remove button.",
|
|
120
124
|
"Keep meaningful tag text visible because tone is supplementary."
|
|
121
125
|
],
|
|
122
126
|
"geometry": {
|
|
@@ -5363,6 +5367,7 @@
|
|
|
5363
5367
|
],
|
|
5364
5368
|
"appOwns": [
|
|
5365
5369
|
"the grammar and evaluation callback when using the optional managed model, or parsing, suggestions, tokens, and query execution in manual mode",
|
|
5370
|
+
"reading the managed model without subscribing per keystroke: TokenSearchField subscribes only to model.structure (committed tokens, empty or non-empty text, editor revision) and model.suggestions, so plain typing never re-runs the host render; in the host's own render, read model.state.peek() or bind model.result (or a computed) as a fine-grained signal hole instead of reading model.state.value",
|
|
5366
5371
|
"results",
|
|
5367
5372
|
"the revision that rebuilds the DOM-owned editor for a programmatic text replacement",
|
|
5368
5373
|
"optional override of the collapsible expand/collapse/focus, which wireTokenSearchFields manages by default (adopt an app expanded signal, opt out per behavior, or drive it via the returned handle)",
|
|
@@ -307,7 +307,8 @@
|
|
|
307
307
|
"helpers": ["wireTokenSearchFields"],
|
|
308
308
|
"obligations": [
|
|
309
309
|
"Retain and invoke the disposer.",
|
|
310
|
-
"Use readTokenSearchField for DOM-owned text."
|
|
310
|
+
"Use readTokenSearchField for DOM-owned text.",
|
|
311
|
+
"With a managed model, read model.state.peek() (never model.state.value) in the host render and bind model.result as a signal hole; the field itself re-renders only when model.structure changes, not per keystroke."
|
|
311
312
|
]
|
|
312
313
|
},
|
|
313
314
|
"diagnostics": [
|
|
@@ -88,6 +88,11 @@
|
|
|
88
88
|
"owner": "application",
|
|
89
89
|
"required": false
|
|
90
90
|
},
|
|
91
|
+
{
|
|
92
|
+
"id": "action handler and its effect",
|
|
93
|
+
"owner": "application",
|
|
94
|
+
"required": false
|
|
95
|
+
},
|
|
91
96
|
{ "id": "disabled policy", "owner": "application", "required": false }
|
|
92
97
|
],
|
|
93
98
|
"wiring": {
|
|
@@ -106,6 +111,7 @@
|
|
|
106
111
|
"The remove control is a native button and requires an action and a specific removeLabel. A disabled chip disables that button and removes it from keyboard interaction.",
|
|
107
112
|
"A link chip is a native anchor named by its visible label; external adds a safe rel, a new tab, and an \"(opens in new tab)\" name suffix, and a disabled link chip drops its destination and leaves the tab order.",
|
|
108
113
|
"The inherit tone paints no fill, so its label keeps the surrounding text contrast, and its focus ring follows the surrounding foreground.",
|
|
114
|
+
"An action chip is one native button (type button) named by its visible label or by actionLabel, which should include that label; Enter and Space activate it, it shows the focus ring on keyboard focus, and a disabled action chip is a disabled button that leaves the tab order. It cannot also be a link or carry a remove button.",
|
|
109
115
|
"Keep meaningful tag text visible because tone is supplementary."
|
|
110
116
|
]
|
|
111
117
|
},
|
|
@@ -4387,7 +4393,8 @@
|
|
|
4387
4393
|
"helpers": ["wireTokenSearchFields"],
|
|
4388
4394
|
"obligations": [
|
|
4389
4395
|
"Retain and invoke the disposer.",
|
|
4390
|
-
"Use readTokenSearchField for DOM-owned text."
|
|
4396
|
+
"Use readTokenSearchField for DOM-owned text.",
|
|
4397
|
+
"With a managed model, read model.state.peek() (never model.state.value) in the host render and bind model.result as a signal hole; the field itself re-renders only when model.structure changes, not per keystroke."
|
|
4391
4398
|
],
|
|
4392
4399
|
"stateAttributes": [
|
|
4393
4400
|
{
|
package/ai/components/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
|
|
|
9
9
|
## Kerf UI — Foundation
|
|
10
10
|
|
|
11
11
|
- [Badge](./badge.md) — Present compact metadata without application-authored badge CSS or consumer styling of component internals.
|
|
12
|
-
- [Chip](./chip.md) — Render removable tags
|
|
12
|
+
- [Chip](./chip.md) — Render removable tags, file or link chips, and activatable action chips without application rules on Web Awesome internals or anchor and button chrome.
|
|
13
13
|
- [LucideIcon](./lucide-icon.md) — Decorative and meaningfully labeled Lucide-compatible icons.
|
|
14
14
|
- [DisclosureArrow](./disclosure-arrow.md) — Indicate whether a disclosure control is open with an overridable 18px root-scaled visual and shortest-path rotation behavior.
|
|
15
15
|
- [Foundation Tokens](./foundation.md) — Provide the shared semantic token foundation for application themes and every styled Kerf UI component.
|
package/ai/components/chip.md
CHANGED
|
@@ -4,20 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
`@kerfjs/ui:chip` · Kerf UI · component · Foundation
|
|
6
6
|
|
|
7
|
-
A short tag with semantic or inherited tone, an optional accessible remove button,
|
|
7
|
+
A short tag with semantic or inherited tone, an optional accessible remove button, a native link and download form, or a native action button, including compact and disabled variants.
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
10
10
|
|
|
11
|
-
Render removable tags
|
|
11
|
+
Render removable tags, file or link chips, and activatable action chips without application rules on Web Awesome internals or anchor and button chrome.
|
|
12
12
|
|
|
13
13
|
- Show a short tag that the application can remove through a delegated action, including a compact or disabled tag.
|
|
14
14
|
- Show a downloadable file or a short link with chip geometry, such as the referenced files of a chat message; set tone inherit inside a brand-loud or neutral ContentItem bubble.
|
|
15
|
+
- Offer a short value the user can activate to apply it, such as a filter token in a search syntax help popover that inserts itself into the query: set action (and itemId) so the whole chip is a native button.
|
|
15
16
|
|
|
16
17
|
**Not when:**
|
|
17
18
|
|
|
18
19
|
- Use Badge for non-interactive status and count metadata.
|
|
19
20
|
- Do not use the remove button without a specific accessible name.
|
|
20
21
|
- Use ListItemLink for a navigation row and ToolbarActionLink for a toolbar link.
|
|
22
|
+
- Use ChoiceChips when the chips choose a persistent value with radio or checkbox state; an action chip fires a one-shot command.
|
|
21
23
|
|
|
22
24
|
## Imports
|
|
23
25
|
|
|
@@ -35,7 +37,7 @@ Exact prop names and types: [`@kerfjs/ui/chip`](../public-api-signatures-v1.md#k
|
|
|
35
37
|
- quiet, solid, or outline appearance
|
|
36
38
|
- pill or rounded shape
|
|
37
39
|
- compact or default size
|
|
38
|
-
- removable, link, or plain, enabled or disabled
|
|
40
|
+
- removable, link, action, or plain, enabled or disabled
|
|
39
41
|
|
|
40
42
|
## Composition
|
|
41
43
|
|
|
@@ -45,7 +47,7 @@ Exact prop names and types: [`@kerfjs/ui/chip`](../public-api-signatures-v1.md#k
|
|
|
45
47
|
|
|
46
48
|
## State and wiring
|
|
47
49
|
|
|
48
|
-
**The app owns:** tag text and identity; remove action and list update; link destination and download file name; disabled policy.
|
|
50
|
+
**The app owns:** tag text and identity; remove action and list update; link destination and download file name; action handler and its effect; disabled policy.
|
|
49
51
|
|
|
50
52
|
No wiring helper.
|
|
51
53
|
|
|
@@ -58,6 +60,7 @@ Margin: none · border: self · padding: self (layout role: foundation). `self`
|
|
|
58
60
|
- The remove control is a native button and requires an action and a specific removeLabel. A disabled chip disables that button and removes it from keyboard interaction.
|
|
59
61
|
- A link chip is a native anchor named by its visible label; external adds a safe rel, a new tab, and an "(opens in new tab)" name suffix, and a disabled link chip drops its destination and leaves the tab order.
|
|
60
62
|
- The inherit tone paints no fill, so its label keeps the surrounding text contrast, and its focus ring follows the surrounding foreground.
|
|
63
|
+
- An action chip is one native button (type button) named by its visible label or by actionLabel, which should include that label; Enter and Space activate it, it shows the focus ring on keyboard focus, and a disabled action chip is a disabled button that leaves the tab order. It cannot also be a link or carry a remove button.
|
|
61
64
|
- Keep meaningful tag text visible because tone is supplementary.
|
|
62
65
|
|
|
63
66
|
## Styling boundary
|
|
@@ -65,6 +65,7 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
|
|
|
65
65
|
|
|
66
66
|
- Retain and invoke the disposer.
|
|
67
67
|
- Use readTokenSearchField for DOM-owned text.
|
|
68
|
+
- With a managed model, read model.state.peek() (never model.state.value) in the host render and bind model.result as a signal hole; the field itself re-renders only when model.structure changes, not per keystroke.
|
|
68
69
|
|
|
69
70
|
**Wiring-owned state attributes** — never render, remove, or branch on these as app state:
|
|
70
71
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public API signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.104` and `kerfjs@5.0.0-beta.104`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
|
|
4
4
|
|
|
5
5
|
## `@kerfjs/ui/css-values`
|
|
6
6
|
|
|
@@ -3836,7 +3836,7 @@ export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape, ensureSunken
|
|
|
3836
3836
|
## `@kerfjs/ui/token-search-field`
|
|
3837
3837
|
|
|
3838
3838
|
```ts
|
|
3839
|
-
export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue,
|
|
3839
|
+
export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, k as TokenSearchToken, l as TokenSearchTrailingAction, m as TokenSearchTrailingActionAttributes, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-model-JA1i8z4D.js';
|
|
3840
3840
|
import 'kerfjs';
|
|
3841
3841
|
import './semantic-content-BbzjvSu9.js';
|
|
3842
3842
|
```
|
|
@@ -3845,7 +3845,7 @@ import './semantic-content-BbzjvSu9.js';
|
|
|
3845
3845
|
|
|
3846
3846
|
```ts
|
|
3847
3847
|
import { Signal } from 'kerfjs';
|
|
3848
|
-
import { d as TokenSearchModel } from './token-search-model-
|
|
3848
|
+
import { d as TokenSearchModel } from './token-search-model-JA1i8z4D.js';
|
|
3849
3849
|
import './semantic-content-BbzjvSu9.js';
|
|
3850
3850
|
|
|
3851
3851
|
interface TokenSearchSubmit {
|
|
@@ -4166,6 +4166,31 @@ interface ChipNoLinkProps {
|
|
|
4166
4166
|
download?: never;
|
|
4167
4167
|
external?: never;
|
|
4168
4168
|
}
|
|
4169
|
+
interface ChipNoActionProps {
|
|
4170
|
+
action?: never;
|
|
4171
|
+
actionLabel?: never;
|
|
4172
|
+
}
|
|
4173
|
+
/**
|
|
4174
|
+
* An action chip renders its whole root as a native
|
|
4175
|
+
* `<button type="button">` carrying `data-action` (and `data-item-id`) for an
|
|
4176
|
+
* application delegated handler. It cannot also be a link or carry a remove
|
|
4177
|
+
* button, because nested interactive content is invalid.
|
|
4178
|
+
*/
|
|
4179
|
+
interface ChipActionProps {
|
|
4180
|
+
/** Delegated action name; the chip renders as a native `<button>`. */
|
|
4181
|
+
action: string;
|
|
4182
|
+
/**
|
|
4183
|
+
* Accessible name when the visible label alone is unclear, such as
|
|
4184
|
+
* "Insert filter is:mine". Start it with, or include, the visible label so
|
|
4185
|
+
* speech input still matches.
|
|
4186
|
+
*/
|
|
4187
|
+
actionLabel?: string;
|
|
4188
|
+
href?: never;
|
|
4189
|
+
download?: never;
|
|
4190
|
+
external?: never;
|
|
4191
|
+
removeAction?: never;
|
|
4192
|
+
removeLabel?: never;
|
|
4193
|
+
}
|
|
4169
4194
|
/**
|
|
4170
4195
|
* A link chip renders a native `<a>` with Chip geometry. It cannot also carry
|
|
4171
4196
|
* a remove button, because a button inside a link is invalid.
|
|
@@ -4179,23 +4204,28 @@ interface ChipLinkProps {
|
|
|
4179
4204
|
external?: boolean;
|
|
4180
4205
|
removeAction?: never;
|
|
4181
4206
|
removeLabel?: never;
|
|
4207
|
+
action?: never;
|
|
4208
|
+
actionLabel?: never;
|
|
4182
4209
|
}
|
|
4183
4210
|
/**
|
|
4184
4211
|
* A plain chip, a removable chip (a delegated action plus a specific
|
|
4185
|
-
* accessible name),
|
|
4212
|
+
* accessible name), a link chip (`href`, optional `download`/`external`), or
|
|
4213
|
+
* an action chip (`action`, optional `actionLabel`) whose whole body is a
|
|
4214
|
+
* native button.
|
|
4186
4215
|
*/
|
|
4187
4216
|
type ChipProps = ChipCommonProps & ChipLabelProps & (({
|
|
4188
4217
|
removeAction: string;
|
|
4189
4218
|
removeLabel: string;
|
|
4190
|
-
} & ChipNoLinkProps) | ({
|
|
4219
|
+
} & ChipNoLinkProps & ChipNoActionProps) | ({
|
|
4191
4220
|
removeAction?: never;
|
|
4192
4221
|
removeLabel?: never;
|
|
4193
|
-
} & ChipNoLinkProps) | ChipLinkProps);
|
|
4222
|
+
} & ChipNoLinkProps & ChipNoActionProps) | ChipLinkProps | ChipActionProps);
|
|
4194
4223
|
/**
|
|
4195
|
-
* A short label with an optional native remove button,
|
|
4196
|
-
* `href` is set
|
|
4224
|
+
* A short label with an optional native remove button, a native link when
|
|
4225
|
+
* `href` is set, or a native button when `action` is set. The application
|
|
4226
|
+
* owns removal, the link destination, and the action handler.
|
|
4197
4227
|
*/
|
|
4198
|
-
declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, href, download, external, removeAction, removeLabel, }: ChipProps): SafeHtml;
|
|
4228
|
+
declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, href, download, external, removeAction, removeLabel, action, actionLabel, }: ChipProps): SafeHtml;
|
|
4199
4229
|
|
|
4200
4230
|
export { Chip, type ChipProps, type ChipTone };
|
|
4201
4231
|
```
|
|
@@ -5042,7 +5072,7 @@ export { CssLength, Spacer, type SpacerProps, UiSpaceName };
|
|
|
5042
5072
|
## `@kerfjs/ui/token-search-model`
|
|
5043
5073
|
|
|
5044
5074
|
```ts
|
|
5045
|
-
export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion,
|
|
5075
|
+
export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchStructure, j as TokenSearchSuggestion, n as createTokenSearchModel } from './token-search-model-JA1i8z4D.js';
|
|
5046
5076
|
import 'kerfjs';
|
|
5047
5077
|
import './semantic-content-BbzjvSu9.js';
|
|
5048
5078
|
```
|
package/ai/skill.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kerf-ui
|
|
3
3
|
description: Build interfaces with kerfjs and the @kerfjs/ui production component package. Use whenever code imports @kerfjs/ui or a task asks for Kerf UI components.
|
|
4
|
-
kerf-ui-skill-version: 1.
|
|
4
|
+
kerf-ui-skill-version: 1.62.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Building with @kerfjs/ui
|
|
@@ -368,7 +368,7 @@ Hard rules:
|
|
|
368
368
|
8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence. `handleIcon` replaces decorative dormant glyph content only. Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition exposes the pane as its only inline track; the component fills that track and hides its dormant separator. For compact overlays, set `presentation="overlay"` and the overlay maximum variables. A lone child (normally a `Pane`) fills the region and owns scrolling; several children stack at natural height. Do not add descendant width/height overrides.
|
|
369
369
|
9. Use controlled `SegmentedControl` for a small exclusive choice set. Select `appearance="toolbar"` when nesting it inside `ToolbarControlGroup`; use rounded or pill shapes for standalone contexts. The package derives inset hover/selection radii from the owning outer shape through `--kui-layout-highlight-inset`; do not restyle an inner highlight to an independent radius. Handle its action, update `value`, keep meaningful choice labels, and preserve every enabled native button in sequential Tab order.
|
|
370
370
|
10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. For a tab-local action followed by a separately pinned workspace action, set `trailingPlacement="adjacent"`, put the local action in `trailing`, and the workspace action in `end`; each action zone accepts one `ToolbarControlGroup` or a standalone `wa-button` when the action needs its own Web Awesome chrome. TabBar owns the shrinking/scrolling tabs and fixed action geometry, so do not add descendant flex overrides. Arrow/Home/End select on move by default and restore focus by bar/tab identity when controlled activation replaces the strip; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
|
|
371
|
-
11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes; to replace the text programmatically (reseeding a persistent dialog's field on reopen, applying a saved search) change the field's `revision` along with `query` for an unmanaged field, or call `model.replace({ query, tokens })` for a model-managed field; never re-key a wrapper. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. For automatic parsing, chips, suggestions, and evaluation, use createTokenSearchModel with grammar rules, pass it as TokenSearchField.model, and register it in wireTokenSearchFields models; a rule's `suggest(input, state)` receives committed tokens so it can exclude selected values. Otherwise the app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. `clearIcon` replaces the clear action's glyph (its `clearLabel` still names it). For a compact icon button beside the clear button (a search-syntax help glyph), pass `trailingAction: { icon, label, action, expanded?, pressed?, controls?, haspopup?, attributes? }` — it matches the clear button's size, hover, focus, and cursor in every presentation; set `expanded` for a disclosure or `pressed` for a toggle, never both, and never hand-style a button into `trailing`. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, a clear-button mousedown guard, or reopening after controlled clear or Select All deletion — the helper keeps the replacement editor open and focused. Clear and deletion restoration finish at the replacement mutation checkpoint before the next input task, so shortcut-letter typing cannot escape to the page and delayed animation frames cannot overwrite a later selection. Persist both query and tokens returned by the DOM read. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
|
|
371
|
+
11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes; to replace the text programmatically (reseeding a persistent dialog's field on reopen, applying a saved search) change the field's `revision` along with `query` for an unmanaged field, or call `model.replace({ query, tokens })` for a model-managed field; never re-key a wrapper. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. For automatic parsing, chips, suggestions, and evaluation, use createTokenSearchModel with grammar rules, pass it as TokenSearchField.model, and register it in wireTokenSearchFields models; a rule's `suggest(input, state)` receives committed tokens so it can exclude selected values. The field subscribes only to `model.structure` (committed tokens, empty or non-empty text, editor revision), so plain typing never re-runs the host render; in the host's own render read `model.state.peek()` and bind `model.result` (or a `computed`) as a signal hole — reading `model.state.value` there re-renders the host on every keystroke. Otherwise the app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. `clearIcon` replaces the clear action's glyph (its `clearLabel` still names it). For a compact icon button beside the clear button (a search-syntax help glyph), pass `trailingAction: { icon, label, action, expanded?, pressed?, controls?, haspopup?, attributes? }` — it matches the clear button's size, hover, focus, and cursor in every presentation; set `expanded` for a disclosure or `pressed` for a toggle, never both, and never hand-style a button into `trailing`. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, a clear-button mousedown guard, or reopening after controlled clear or Select All deletion — the helper keeps the replacement editor open and focused. Clear and deletion restoration finish at the replacement mutation checkpoint before the next input task, so shortcut-letter typing cannot escape to the page and delayed animation frames cannot overwrite a later selection. Persist both query and tokens returned by the DOM read. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
|
|
372
372
|
An application helper can call `model.commit(value)` for the active `name:` prefix when it computes a valid value outside suggestions; invalid values and missing prefixes leave the query unchanged.
|
|
373
373
|
12. Demo work uses public production component subpaths and their browser-selected CSS. Focused demos and recipes have no local stylesheet, inline style, or styling-only class; use public components and `CatalogExample.viewport` for unavoidable specimen constraints (a recipe declares its frame through its exported `presentation`). To preview a top-layer specimen that production anchors with CSS anchor positioning, name the frame with `viewport.anchorName` (a dashed-ident such as `"--app-shell-main"`) and center in-flow content with `viewport.contentWidth` + `contentAlign: "center"` instead of wrapping the specimen in a stage element. When a recipe needs a capability no component offers, report the component gap instead of adding CSS. Use exactly three demo kinds: a `component` is one component with variants/states, a `composition` is a focused container of components commonly used together, and a `recipe` is the recommended production approach to a task. Organize catalog routes into product-important functional groups; within each group put all components before compositions, order each kind by importance with display-name alphabetical tie-breaking, and put recipes after every component/composition group. Show `Composition` as an entry tag instead of repeating the word in its name. Give every public visual component its own category-grouped catalog route; list themed third-party components under a clearly labeled collapsible ecosystem section, with a focused route for each. For the complete taxonomy, focused/composition decision, `CatalogExample` / `CatalogExampleStack` row/group nesting, specimen structure and metadata ownership, follow the single [Catalog demo authoring contract](../docs/catalog.md#catalog-demo-authoring-contract), discovered machine-readably through [`catalog-authoring.json`](./catalog-authoring.json). Never infer structure from private `kui-catalog-*` classes. Project each component's deterministic repository-relative demo source and existing documentation path so the detail can expose `View demo source` and `Read guidance` links without a runtime export; also derive first-party component implementation paths from their canonical browser imports, and label Web Awesome documentation as Kerf integration guidance. Declare direct `uses` relationships so `Used by` stays derivable, and theme shell chrome through the same semantic tokens as the stage instead of drawing a substitute. Enable `wireCatalog({ revealSelection: true })` for long desktop sidebars so controlled selections remain visible without moving focus; keep its default compact media guard unless compact scrolling is an explicit product behavior, and use `revealCatalogEntry` for an initial deep link.
|
|
374
374
|
13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes. Its non-field chrome uses `--kui-wa-control-inset` (8px controls/items), `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside Accordion, Card, Details, Callout, and Include), and `--kui-wa-container-inset` (16px Tab Panel content and framed disclosure regions). Plain Details use the 8px surface inset on the trigger and keep the body flush; plain Accordion items use it on both trigger and body. Outlined and sunken Details use the 16px container inset on the trigger and 8px on the body; framed Accordion items use 16px on both. Dialog maps its body to the 8px surface tier and its footer to the 16px container tier independently of `--spacing`. Override those tiers instead of restyling individual parts. Filled badges use each variant's quiet fill with normal text so their compact copy stays WCAG-AA readable; override the pair with `--kui-wa-badge-filled-background` / `--kui-wa-badge-filled-foreground`, not host selectors. The theme draws a dialog's or drawer's built-in close control as the same 40px borderless circle a single `ToolbarControlGroup` button uses, so do not restyle it. When a dialog provides another dismissal affordance, put `hide-actions` on the `wa-dialog` host to hide its directly exported `header-actions` part; never chain `::part()` selectors through internal parts. Checkbox and Radio Group option regions, the Color Picker trigger, and Slider's complete interactive region receive the shared 8px logical inline outer inset because those controls have no bordered field shell. Known Date field captions and bordered text-like field hints align with values at the 9px border-plus-padding inset. OTP Input's label uses the same uppercase xs/650 treatment as other field labels, and both its label and hint use that 9px inset.
|
|
@@ -470,7 +470,7 @@ For prominent content text, use `Text size="large"`; use `size="xlarge"` for dis
|
|
|
470
470
|
|
|
471
471
|
For an exclusive choice among several visible options that must wrap (a labeled color palette), use `ChoiceChips` from `@kerfjs/ui/choice-chips`: separate pills backed by native radios, so the group is one Tab stop, arrow keys select, and the checked radio submits under `name`. Name it with `label` or `labelledBy` (a visible `FieldLabel`), lead choices with `swatch` (a `CssColor` such as `fillColor('#3b82f6')`, or `'transparent'` for the struck-through no-color dot) or `icon`, and handle the delegated `action` on `change`. Never wrap a `SegmentedControl` or button-appearance `wa-radio` set instead. Set `multiple` with a `readonly Value[]` `value` when any number of the options may be on (label filters, annotation intents): the pills become native checkboxes in a `role="group"`, each its own Tab stop that Space toggles, and every checked value submits under `name` (read the checked boxes by name in the change handler). A multiple group takes no `required`. On dark inverse chrome, put the chips in a dark appearance scope (`.wa-dark` or any `color-scheme: dark` ancestor) instead of restyling them.
|
|
472
472
|
|
|
473
|
-
For removable tags use `Chip`, with `removeAction` for delegated handling and a specific `removeLabel` for the native button. `itemId` identifies the tag; the app owns removal. `size="compact"` and `disabled` replace app styling of raw `wa-tag` internals. Use `Badge` for non-interactive metadata. For a downloadable file or a short link, give `Chip` an `href` (optional `download`, `true` or a file name, and `external`) instead of styling an `<a>`: it renders a native link with chip geometry, icon, truncation, focus ring, and hover feedback, and cannot also carry a remove button. Inside a `brand-loud` or `neutral` ContentItem bubble set `tone="inherit"`, which follows the bubble's foreground with a currentColor border and no fill.
|
|
473
|
+
For removable tags use `Chip`, with `removeAction` for delegated handling and a specific `removeLabel` for the native button. `itemId` identifies the tag; the app owns removal. `size="compact"` and `disabled` replace app styling of raw `wa-tag` internals. Use `Badge` for non-interactive metadata. For a downloadable file or a short link, give `Chip` an `href` (optional `download`, `true` or a file name, and `external`) instead of styling an `<a>`: it renders a native link with chip geometry, icon, truncation, focus ring, and hover feedback, and cannot also carry a remove button. Inside a `brand-loud` or `neutral` ContentItem bubble set `tone="inherit"`, which follows the bubble's foreground with a currentColor border and no fill. For a short value the user activates once (a filter token in a search help popover that inserts itself into the query), give `Chip` an `action` and `itemId`: the whole chip becomes a native `<button type="button" data-action data-item-id>` with hover, press, focus-ring, and disabled states, and an optional `actionLabel` that contains the visible label. It cannot also take `href` or `removeAction`. A compact rounded action chip keeps a compact `Badge`'s height in a compact `ValueTable` cell, so use it there instead of a `Badge` the app makes clickable.
|
|
474
474
|
|
|
475
475
|
For a chat message or assistant prompt, use `Composer` from `@kerfjs/ui/composer`: a raised frame whose border turns brand while focus is within, a borderless textarea that grows between `minRows` (default 1) and `maxRows` (default 8) lines and then scrolls, and an action row with an optional quiet `hint` and trailing `actions` (a brand Send `wa-button`). Name it with a title-style `label` and give it an `id` so the hint describes the field; the app reads and clears the textarea in its send action. For Enter-to-send, set `submitOnEnter` and call `wireComposers(root)` from `@kerfjs/ui/wire-composers` once; Enter or Cmd/Ctrl+Enter clicks the first trailing action, Shift+Enter inserts a newline, and an IME composition commit or an empty message never sends. Never hand-roll that keydown handler. In a chat dialog, slot it into a `DialogSurface` with `footerPresentation="floating"` and `footerInset="none"`. Never wrap a `wa-textarea` and a button in app-styled composer chrome.
|
|
476
476
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Web Awesome JSX signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from the emitted `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from the emitted `@kerfjs/ui@5.0.0-beta.104` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { KerfCustomElement } from 'kerfjs/jsx-runtime';
|
package/dist/catalog.js
CHANGED
|
@@ -3,7 +3,7 @@ import { uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
|
|
|
3
3
|
export { UX_REVIEW_PROJECT_PATH, loadUxReviewProject, uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import { TokenSearchField } from './chunk-
|
|
6
|
+
import { TokenSearchField } from './chunk-ZJC5ND3M.js';
|
|
7
7
|
|
|
8
8
|
import { Row } from './chunk-YQ2AC4E2.js';
|
|
9
9
|
import { ListItem } from './chunk-ZYU5WRC3.js';
|
package/dist/chip.d.ts
CHANGED
|
@@ -35,6 +35,31 @@ interface ChipNoLinkProps {
|
|
|
35
35
|
download?: never;
|
|
36
36
|
external?: never;
|
|
37
37
|
}
|
|
38
|
+
interface ChipNoActionProps {
|
|
39
|
+
action?: never;
|
|
40
|
+
actionLabel?: never;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* An action chip renders its whole root as a native
|
|
44
|
+
* `<button type="button">` carrying `data-action` (and `data-item-id`) for an
|
|
45
|
+
* application delegated handler. It cannot also be a link or carry a remove
|
|
46
|
+
* button, because nested interactive content is invalid.
|
|
47
|
+
*/
|
|
48
|
+
interface ChipActionProps {
|
|
49
|
+
/** Delegated action name; the chip renders as a native `<button>`. */
|
|
50
|
+
action: string;
|
|
51
|
+
/**
|
|
52
|
+
* Accessible name when the visible label alone is unclear, such as
|
|
53
|
+
* "Insert filter is:mine". Start it with, or include, the visible label so
|
|
54
|
+
* speech input still matches.
|
|
55
|
+
*/
|
|
56
|
+
actionLabel?: string;
|
|
57
|
+
href?: never;
|
|
58
|
+
download?: never;
|
|
59
|
+
external?: never;
|
|
60
|
+
removeAction?: never;
|
|
61
|
+
removeLabel?: never;
|
|
62
|
+
}
|
|
38
63
|
/**
|
|
39
64
|
* A link chip renders a native `<a>` with Chip geometry. It cannot also carry
|
|
40
65
|
* a remove button, because a button inside a link is invalid.
|
|
@@ -48,22 +73,27 @@ interface ChipLinkProps {
|
|
|
48
73
|
external?: boolean;
|
|
49
74
|
removeAction?: never;
|
|
50
75
|
removeLabel?: never;
|
|
76
|
+
action?: never;
|
|
77
|
+
actionLabel?: never;
|
|
51
78
|
}
|
|
52
79
|
/**
|
|
53
80
|
* A plain chip, a removable chip (a delegated action plus a specific
|
|
54
|
-
* accessible name),
|
|
81
|
+
* accessible name), a link chip (`href`, optional `download`/`external`), or
|
|
82
|
+
* an action chip (`action`, optional `actionLabel`) whose whole body is a
|
|
83
|
+
* native button.
|
|
55
84
|
*/
|
|
56
85
|
type ChipProps = ChipCommonProps & ChipLabelProps & (({
|
|
57
86
|
removeAction: string;
|
|
58
87
|
removeLabel: string;
|
|
59
|
-
} & ChipNoLinkProps) | ({
|
|
88
|
+
} & ChipNoLinkProps & ChipNoActionProps) | ({
|
|
60
89
|
removeAction?: never;
|
|
61
90
|
removeLabel?: never;
|
|
62
|
-
} & ChipNoLinkProps) | ChipLinkProps);
|
|
91
|
+
} & ChipNoLinkProps & ChipNoActionProps) | ChipLinkProps | ChipActionProps);
|
|
63
92
|
/**
|
|
64
|
-
* A short label with an optional native remove button,
|
|
65
|
-
* `href` is set
|
|
93
|
+
* A short label with an optional native remove button, a native link when
|
|
94
|
+
* `href` is set, or a native button when `action` is set. The application
|
|
95
|
+
* owns removal, the link destination, and the action handler.
|
|
66
96
|
*/
|
|
67
|
-
declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, href, download, external, removeAction, removeLabel, }: ChipProps): SafeHtml;
|
|
97
|
+
declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, href, download, external, removeAction, removeLabel, action, actionLabel, }: ChipProps): SafeHtml;
|
|
68
98
|
|
|
69
99
|
export { Chip, type ChipProps, type ChipTone };
|
package/dist/chip.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readTokenSearchField, placeTokenSearchCaret } from './chunk-
|
|
1
|
+
import { readTokenSearchField, placeTokenSearchCaret } from './chunk-ZJC5ND3M.js';
|
|
2
2
|
import { autoUpdate, computePosition, offset, flip, shift, size } from '@floating-ui/dom';
|
|
3
3
|
import { delegate, delegateCapture, signal } from 'kerfjs';
|
|
4
4
|
|
|
@@ -832,4 +832,4 @@ function wireTokenSearchFields(root, {
|
|
|
832
832
|
|
|
833
833
|
export { wireTokenSearchFields };
|
|
834
834
|
|
|
835
|
-
//# sourceMappingURL=chunk-
|
|
835
|
+
//# sourceMappingURL=chunk-CR5U5FV6.js.map
|