@kerfjs/ui 5.0.0-beta.107 → 5.0.0-beta.109

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 (125) hide show
  1. package/ai/component-catalog.json +26 -13
  2. package/ai/component-composition-rules.json +2 -2
  3. package/ai/component-composition.json +10 -4
  4. package/ai/components/button.md +5 -5
  5. package/ai/components/chip.md +1 -0
  6. package/ai/components/foundation.md +1 -1
  7. package/ai/components/list.md +1 -1
  8. package/ai/components/segmented-control.md +1 -0
  9. package/ai/components/surface-scaffold.md +1 -0
  10. package/ai/components/tab-bar.md +5 -5
  11. package/ai/components/text-field.md +3 -1
  12. package/ai/components/toolbar-control-group.md +1 -0
  13. package/ai/components/toolbar.md +1 -1
  14. package/ai/public-api-signatures-v1.md +66 -15
  15. package/ai/skill.md +13 -7
  16. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  17. package/dist/button.d.ts +3 -3
  18. package/dist/button.js +1 -1
  19. package/dist/catalog.js +4 -4
  20. package/dist/chip.d.ts +20 -2
  21. package/dist/chip.js +2 -1
  22. package/dist/{chunk-23PPPNH6.js → chunk-4OV272LF.js} +2 -2
  23. package/dist/{chunk-23PPPNH6.js.map → chunk-4OV272LF.js.map} +1 -1
  24. package/dist/{chunk-2PXZBFEC.js → chunk-5J6Z4BWY.js} +1 -1
  25. package/dist/{chunk-2PXZBFEC.js.map → chunk-5J6Z4BWY.js.map} +1 -1
  26. package/dist/{chunk-G4DRH4A5.js → chunk-6CDILXF4.js} +3 -1
  27. package/dist/chunk-6CDILXF4.js.map +1 -0
  28. package/dist/{chunk-RFLW4FPL.js → chunk-7AK5I7U7.js} +1 -1
  29. package/dist/chunk-7AK5I7U7.js.map +1 -0
  30. package/dist/{chunk-NLMEDZRM.js → chunk-CPSGUGAY.js} +5 -5
  31. package/dist/{chunk-NLMEDZRM.js.map → chunk-CPSGUGAY.js.map} +1 -1
  32. package/dist/{chunk-TXRKCGT3.js → chunk-KPINJHIC.js} +1 -1
  33. package/dist/chunk-KPINJHIC.js.map +1 -0
  34. package/dist/{chunk-N7MBGONH.js → chunk-LMHN2TJL.js} +22 -2
  35. package/dist/chunk-LMHN2TJL.js.map +1 -0
  36. package/dist/{chunk-NS2TBYM4.js → chunk-LZUUUHNH.js} +7 -3
  37. package/dist/chunk-LZUUUHNH.js.map +1 -0
  38. package/dist/{chunk-OY2MXIBB.js → chunk-NB6POCFH.js} +3 -1
  39. package/dist/chunk-NB6POCFH.js.map +1 -0
  40. package/dist/{chunk-AZ3WT77F.js → chunk-P7EJ4CAD.js} +2 -2
  41. package/dist/{chunk-AZ3WT77F.js.map → chunk-P7EJ4CAD.js.map} +1 -1
  42. package/dist/{chunk-Z4DS77U2.js → chunk-SOFPUW3O.js} +4 -4
  43. package/dist/{chunk-Z4DS77U2.js.map → chunk-SOFPUW3O.js.map} +1 -1
  44. package/dist/{chunk-QLA25V2K.js → chunk-WPNIKZMJ.js} +15 -1
  45. package/dist/chunk-WPNIKZMJ.js.map +1 -0
  46. package/dist/{chunk-DNWWF6UN.js → chunk-WSEJ2FDE.js} +4 -4
  47. package/dist/{chunk-DNWWF6UN.js.map → chunk-WSEJ2FDE.js.map} +1 -1
  48. package/dist/{chunk-WU57BYYM.js → chunk-YVZCKXR3.js} +8 -2
  49. package/dist/chunk-YVZCKXR3.js.map +1 -0
  50. package/dist/{chunk-CMLPFIC5.js → chunk-ZN7KUMPY.js} +3 -1
  51. package/dist/chunk-ZN7KUMPY.js.map +1 -0
  52. package/dist/collapsible-panel.js +2 -2
  53. package/dist/index.js +10 -10
  54. package/dist/list-detail-dialog.js +4 -4
  55. package/dist/list.d.ts +7 -1
  56. package/dist/list.js +1 -1
  57. package/dist/message-composer.js +1 -1
  58. package/dist/nav-stack.js +1 -1
  59. package/dist/segmented-control.d.ts +3 -1
  60. package/dist/segmented-control.js +1 -1
  61. package/dist/split-view.js +1 -1
  62. package/dist/styles/button.css +28 -2
  63. package/dist/styles/components/actions/button/button.css +28 -2
  64. package/dist/styles/components/actions/toolbar/toolbar.css +9 -0
  65. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +29 -1
  66. package/dist/styles/components/collections/framed-list/framed-list.css +2 -0
  67. package/dist/styles/components/layout/pane/pane.css +15 -0
  68. package/dist/styles/components/navigation/nav-stack/nav-stack.css +13 -0
  69. package/dist/styles/components/navigation/tab-bar/tab-bar.css +6 -0
  70. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +16 -0
  71. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +2 -0
  72. package/dist/styles/foundation.css +63 -19
  73. package/dist/styles/framed-list.css +2 -0
  74. package/dist/styles/nav-stack.css +13 -0
  75. package/dist/styles/pane.css +15 -0
  76. package/dist/styles/surface-scaffold.css +2 -0
  77. package/dist/styles/tab-bar.css +6 -0
  78. package/dist/styles/tab-navigator.css +16 -0
  79. package/dist/styles/toolbar-control-group.css +29 -1
  80. package/dist/styles/toolbar.css +9 -0
  81. package/dist/styles/webawesome.css +11 -3
  82. package/dist/surface-scaffold.d.ts +9 -1
  83. package/dist/surface-scaffold.js +1 -1
  84. package/dist/tab-bar.d.ts +2 -2
  85. package/dist/tab-bar.js +1 -1
  86. package/dist/text-field.d.ts +7 -1
  87. package/dist/text-field.js +1 -1
  88. package/dist/toolbar-control-group.d.ts +8 -2
  89. package/dist/toolbar-control-group.js +1 -1
  90. package/dist/toolbar.d.ts +6 -1
  91. package/dist/toolbar.js +1 -1
  92. package/dist/wire-catalog.js +1 -1
  93. package/dist/wire-workbench.js +1 -1
  94. package/dist/workbench-dialog.js +3 -3
  95. package/dist/workbench.js +1 -1
  96. package/docs/accessibility.md +29 -11
  97. package/docs/component-contract.md +19 -6
  98. package/docs/component-selection.md +38 -12
  99. package/docs/design/templates/button/tones-dark.svg +1 -1
  100. package/docs/design/templates/button/tones.svg +1 -1
  101. package/docs/design/templates/button-dark.svg +1 -1
  102. package/docs/design/templates/button.svg +1 -1
  103. package/docs/design/templates/split-button/states-dark.svg +1 -1
  104. package/docs/design/templates/split-button/states.svg +1 -1
  105. package/docs/design/templates/split-button-dark.svg +1 -1
  106. package/docs/design/templates/split-button.svg +1 -1
  107. package/docs/design/templates/text-field/number-dark.svg +1 -0
  108. package/docs/design/templates/text-field/number.svg +1 -0
  109. package/docs/design/templates/text-field-dark.svg +1 -1
  110. package/docs/design/templates/text-field.svg +1 -1
  111. package/docs/layout.md +16 -5
  112. package/docs/webawesome-migration.md +2 -0
  113. package/docs/webawesome-theme.md +8 -2
  114. package/docs/workbench.md +7 -1
  115. package/llms.txt +19 -7
  116. package/package.json +1 -1
  117. package/dist/chunk-CMLPFIC5.js.map +0 -1
  118. package/dist/chunk-G4DRH4A5.js.map +0 -1
  119. package/dist/chunk-N7MBGONH.js.map +0 -1
  120. package/dist/chunk-NS2TBYM4.js.map +0 -1
  121. package/dist/chunk-OY2MXIBB.js.map +0 -1
  122. package/dist/chunk-QLA25V2K.js.map +0 -1
  123. package/dist/chunk-RFLW4FPL.js.map +0 -1
  124. package/dist/chunk-TXRKCGT3.js.map +0 -1
  125. package/dist/chunk-WU57BYYM.js.map +0 -1
package/ai/skill.md CHANGED
@@ -369,8 +369,8 @@ Hard rules:
369
369
  6. `Select` is pure until the app explicitly imports `@kerfjs/ui/select/register`; once registered, an icon-only `Select` (and, via `@kerfjs/ui/popup-menu/register`, an icon-only `PopupMenu`) shows an `aria-hidden` help tag repeating its accessible name (and a Select's current choice) on hover and keyboard focus, hidden while its popup is open — never add a `title` or your own tooltip to these triggers. The same installer tags an icon-only `<button>` or link in a `ToolbarControlGroup` named by `aria-label` (no visible text, no `title`); a toolbar with such buttons but no registered Select or PopupMenu imports `@kerfjs/ui/help-tags/register` once. Name those buttons with `aria-label`, not `title`: a `title` keeps the browser tooltip and skips the tag. Do not import Web Awesome's full registration bundle. When an app writes direct `wa-*` JSX, add `import type {} from '@kerfjs/ui/webawesome'` for the catalog-supported intrinsic-element declarations, import the CSS-only `@kerfjs/ui/webawesome.css` theme once, and keep importing individual Web Awesome component modules so their JavaScript remains tree-shakeable. The type boundary emits no code and registers nothing. Pass icon-bearing `choices` and `renderSelected` content normally: `Select` preserves its option icons across Kerf rerenders and keys selected content by the controlled value, so app wrappers must not add competing morph-control attributes. Give it a visible `label` or an `ariaLabel` for a visually hidden name; the nonempty visible label takes precedence and the package names its native trigger, including with `renderSelected`, without adding label geometry. Use `hint` for persistent supporting text below the control and `placeholderText` only for the empty value inside the closed control; loading placeholders retain the hint. For any number of choices set `multiple` with an array `value`: the popup stays open while choices toggle and closes on an outside press or Escape, the closed control summarizes the chosen labels, and `change` reports the value array; do not add app code to keep it open or to render tags. For a toolbar filter menu, add `selectedPresentation="icon-only"` plus a fixed `triggerIcon` (such as a funnel `LucideIcon`): the trigger shows that icon, a count badge while any choice is chosen, and ends its accessible name with the chosen labels ("Filter by label: Bug, Docs"); do not render your own count badge or rewrite the name. When testing name or description, target the element with the `combobox` role (the native trigger) rather than the `kui-select` root; the hint is already its `aria-description`, so do not add another.
370
370
  7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. When the app detects a low-power device, it sets `data-kui-effects="static"` on the root element to turn backdrop materials opaque and stop scroll-driven animations; `@media (update: slow)` does the same automatically. `DisclosureArrow` defaults to an 18px root-scaled visual; size it with its typed `size` prop (`size={remify(24)}`); it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`; an icon-only toolbar Select may set `caret={false}` for a round trigger while preserving its help tag and keyboard listbox, and a custom `renderSelected` icon stays centered.
371
371
  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.
372
- 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.
373
- 10. Compose `TabBarItem` 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.
372
+ 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. Set `disabled` to make the whole control unavailable (its selection stays visible); a choice's own `disabled` disables just that segment.
373
+ 10. Compose `TabBarItem` 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`, a standalone Kerf `Button`, or a standalone `wa-button` for an exceptional Web Awesome use. 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.
374
374
  11. Use token-controlled `SearchField` 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 createSearchFieldModel with grammar rules, pass it as SearchField.model, and register it in wireSearchFields 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 `readSearchField()` on input, empty `textContent` on clear, use `placeSearchFieldCaret()` after explicit controlled focus changes, and call `wireSearchFields()` 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 `wireSearchFields()` 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-search-field-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.
375
375
  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.
376
376
  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.
@@ -380,7 +380,8 @@ Hard rules:
380
380
  15a. Use `Text` from `@kerfjs/ui/text` for ordinary headings, paragraphs, and inline secondary text outside toolbar title zones. Omit `variant` for the default `p`, pass `h1`–`h6` according to the document outline, or use `variant="span"` inside a row, label, or table cell; ordinary native attributes pass through. Express supporting, error, compact, or code text with the independent finite `tone="quiet|danger"`, `size="compact"`, and `font="monospace"` props instead of global utility classes or appearance-only heading choices. Block Text variants own a transparent 1px border and the standard item padding; `span` owns no box geometry. Keep toolbar identity/title content on `ToolbarText` and list-aligned bare prose on `ListInsetText`. `ToolbarText` below `xlarge` is intentionally quiet identity text in default tone; a normal-color subsection title is `Text` with an `h2`–`h6` variant (or `ListHeader` for a list or menu section), never a recolored `ToolbarText`. Use `controlMargins` with canonical physical Sides for an exterior 8px control gutter without a Row wrapper; avoid stacking parent insets, and remember spans retain native inline margin behavior.
381
381
 
382
382
  16. Keep a visible collapsible pane's collapse control in its own toolbar. When hidden, move its restore control into the adjacent main toolbar on the corresponding logical edge: leading for an inline-start sidebar and trailing for an inline-end inspector. Collapse the pane completely; do not preserve an empty icon-only rail.
383
- 16a. Dividers between pinned chrome and scrolling content are component chrome: a `Toolbar` draws none by default (`dividerSides` is for a permanent edge only). Call `wireScrollDividers(appRoot)` from `@kerfjs/ui/wire-scroll-dividers` once and retain its disposer; a plain `Pane` with `chromeDividers="scroll"` draws the line under its header only while content is scrolled beneath it and over its footer only while more content lies below (never when the content fits), every `NavStack`'s top chrome and bottom toolbar and every `TabNavigator` bar do the same around the active view or scene (keyed on whatever actually scrolls there, including a sole `Pane`'s content), and every `TabBar` marks each side of its strip with tabs scrolled out of view. Configure a pane with `chromeDividers` (`scroll` by default for plain panes, `always` by default for sunken panes, or explicit `scroll`, `always`, `none`, also via `PaneConfig`); `always` draws both lines even when content fits. A `NavStack` or `TabNavigator` has its own `chromeDividers` (same values: `always` draws the chrome lines without the wiring, `none` never, even when wired; a `SplitView` forwards it through `compactStack`); a `toolbarConfig.dividerSides` edge stays the Toolbar's own. Name app-owned chrome by id in `targets`. The wiring writes only `data-scroll-overflow` / `data-scroll-divider` state; never write a border onto a component to show a divider. For a header that floats over its scrolling content on translucent material, set `headerPresentation="overlay"` on the `Pane` (also in `PaneConfig`). The same wiring measures the header and publishes its height as block-start scroll clearance, which the content clears without a `scrollClearance` prop. Never set `--kui-scroll-clearance-block-start`, `--kui-pane-scrollbar-inline-size`, or a header height yourself; the header leaves a classic scrollbar uncovered on its own. An untoned `ToolbarText` keeps AA there by itself (normal-color title, lifted description); put other quiet secondary copy in the content. For an iOS-style translucent stack bar, set `chromePresentation="overlay"` on the `NavStack` (a `SplitView` forwards it through `compactStack`, a Workbench panel through `navStack`): `wireNavStack` measures the live top chrome and hands its height, top safe area included, to the views as their block-start inset, so a plain view or a sole `Pane` rests its first item below the bar with no prop; never pad a view to clear the bar yourself. An untoned `ToolbarText` in that chrome lifts its own title and description to AA, as in an overlay Pane header. For an iOS-style translucent bottom toolbar, set `bottomToolbarPresentation="overlay"` (a separate prop; `chromePresentation` covers only the top chrome, and `compactStack` / `navStack` forward both): `wireNavStack` measures the live bottom toolbar and hands its height, bottom safe area included, to the views as their block-end inset, so a plain view's or a sole `Pane`'s last item (or the Pane's footer) rests just above it with no prop. A default-tone `ToolbarControlGroup` in either overlaid bar lifts its controls to the normal text color by itself; never recolor them.
383
+ 16a. Dividers between pinned chrome and scrolling content are component chrome: a `Toolbar` draws none by default (`dividerSides` is for a permanent edge only). Call `wireScrollDividers(appRoot)` from `@kerfjs/ui/wire-scroll-dividers` once and retain its disposer; a plain `Pane` with `chromeDividers="scroll"` draws the line under its header only while content is scrolled beneath it and over its footer only while more content lies below (never when the content fits), every `NavStack`'s top chrome and bottom toolbar and every `TabNavigator` bar do the same around the active view or scene (keyed on whatever actually scrolls there, including a sole `Pane`'s content), and every `TabBar` marks each side of its strip with tabs scrolled out of view. Outside a `Pane`, give the `Toolbar` and the scrolling `List` an `id` and pair them in `wireScrollDividers(appRoot, { targets: [{ scroller: 'list-id', top: 'toolbar-id' }] })` instead of a permanent `dividerSides`. Configure a pane with `chromeDividers` (`scroll` by default for plain panes, `always` by default for sunken panes, or explicit `scroll`, `always`, `none`, also via `PaneConfig`); `always` draws both lines even when content fits. A `NavStack` or `TabNavigator` has its own `chromeDividers` (same values: `always` draws the chrome lines without the wiring, `none` never, even when wired; a `SplitView` forwards it through `compactStack`); a `toolbarConfig.dividerSides` edge stays the Toolbar's own. Name app-owned chrome by id in `targets`. The wiring writes only `data-scroll-overflow` / `data-scroll-divider` state; never write a border onto a component to show a divider. For a header that floats over its scrolling content on translucent material, set `headerPresentation="overlay"` on the `Pane` (also in `PaneConfig`). The same wiring measures the header and publishes its height as block-start scroll clearance, which the content clears without a `scrollClearance` prop. Never set `--kui-scroll-clearance-block-start`, `--kui-pane-scrollbar-inline-size`, or a header height yourself; the header leaves a classic scrollbar uncovered on its own. An untoned `ToolbarText` keeps AA there by itself (normal-color title, lifted description); put other quiet secondary copy in the content. For an iOS-style translucent stack bar, set `chromePresentation="overlay"` on the `NavStack` (a `SplitView` forwards it through `compactStack`, a Workbench panel through `navStack`): `wireNavStack` measures the live top chrome and hands its height, top safe area included, to the views as their block-start inset, so a plain view or a sole `Pane` rests its first item below the bar with no prop; never pad a view to clear the bar yourself. An untoned `ToolbarText` in that chrome lifts its own title and description to AA, as in an overlay Pane header. For an iOS-style translucent bottom toolbar, set `bottomToolbarPresentation="overlay"` (a separate prop; `chromePresentation` covers only the top chrome, and `compactStack` / `navStack` forward both): `wireNavStack` measures the live bottom toolbar and hands its height, bottom safe area included, to the views as their block-end inset, so a plain view's or a sole `Pane`'s last item (or the Pane's footer) rests just above it with no prop. A default-tone `ToolbarControlGroup` in either overlaid bar lifts its controls to the normal text color by itself; never recolor them.
384
+ 16b. Change the application's brand with `--kui-color-brand` on `:root` (any color; Kerf derives the fill, brand text, text on brand fills, and the focus ring at WCAG AA, and Web Awesome's brand tokens follow). Never override `--kui-color-brand-fill-loud` alone: brand text and the focus ring stay the default blue. A green brand makes `info` read like `success`; pick a hue apart from the status tones.
384
385
  17. Each `Toolbar` zone accepts `KerfUiContent` directly, including status content, native controls, and application markup. Put identity/title text directly in the zone as `ToolbarText`; use `ToolbarControlGroup` when related controls need shared toolbar chrome, sizing, hover treatment, or overflow behavior. Bare controls keep their own styling and accessibility responsibilities. A standalone primary `wa-button` in trailing keeps its own Web Awesome chrome. `SegmentedControl`, `Select`, and `SearchField` can live inside a group when they need that shared presentation. Configure zone behavior with `Toolbar.centerAlign` and its `responsive` / `responsiveAt` policy instead of selecting toolbar zone classes. No policy clips an action: trailing (and stacked center) zones wrap whole groups onto another row, and the center zone never compresses below its content (a leading title too long for the row truncates with an ellipsis instead), so never hide or shrink a toolbar control to make it fit; use `responsive="wrap"` for a heading whose title must stay whole, and move genuinely lower-priority commands into an app-owned "More" popup menu. For an ordinary icon/action control inside a group, use a plain `<button>` (the group styles `> button` fully) — that is the default; reach for `wa-button` only when you need a Web Awesome feature. A popup menu in a toolbar is a `PopupMenu` (`@kerfjs/ui/popup-menu`, registered once via `@kerfjs/ui/popup-menu/register`) in a `single` group with `nestedDropdown` and a `menuInset`: give it typed `items` (commands with `action`s, `heading`s, `divider`s) and a trigger `icon` plus visible `text` or an accessible `label`; never hand-write `wa-dropdown` / `wa-dropdown-item` markup for a menu. Let the group size that trigger from its icon, localized text, and caret; do not force a width on the menu or button. By default a group stays on one row: each icon sits beside its label, and the toolbar's `responsive` policy relocates whole groups when needed. Set `overflow="wrap"` only for independent links that should move as whole actions to another row within the group; use `overflow="scroll"` for a bounded one-row action strip. A `ToolbarText` is one line ending in an ellipsis by default; opt into `wrap` (capped by `maxLines`) or `ellipsis={false}` deliberately. Inside a group, a `Select` or `PopupMenu` trigger drops its focus ring while its popup is open (the open popup and its current row show where focus is) and the ring returns when the popup closes; a ring follows the control's shape (a pill for an icon-and-caret trigger, a circle for a compact icon button) — set `focusRingOwner="group"` on a Select whose group paints the composed ring, and never add CSS to show, hide, or reshape a ring. For a compact mixed group, keep the standard item padding and raised selected chrome; the selected item paints over the outer border without an internal separator. For an avatar control, set `content="avatar"` and `avatarImage` on the group instead of inserting an `img`: a lone control paints the contained image on the outer group and a multi-button group paints it only on the pressed selection highlight. Compose panel/dialog/page headings with a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and short supporting copy as the `ToolbarText` `description` (quiet, one line, aligned under the title, with `descriptionId` for `aria-describedby`; longer copy stays app-owned content below). A non-interactive heading icon is an icon tile: put the `LucideIcon` directly in its `ToolbarControlGroup` (it takes an icon button's 40px slot and centers), never inside a `<button>` that does nothing. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Each zone item sits in the toolbar's top 44px control band, centered by its own size; a taller item (a wrapped title, a second trailing row) starts at the band's top and grows down without moving the others, so a wrapped `ToolbarText` keeps trailing controls beside its first line — do not add alignment CSS for this. Split dormant and interactive regions: `ListHeader` fills the available inline width by default; set `width="content"` to shrink-wrap while retaining its normal geometry, or `inline` when it belongs in surrounding text without outer margin, border, or padding. It keeps its label and either a semantic count or independent `badge` and `status` indicators together, with an independent logical-end action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square whose transparent hit layer keeps the pointer target at least 44px (44px wide by the 36px row in `density="compact"`); never shrink the target to match the visual, and never force the button to 44px. Pass a sole non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a bare number in `badge`. For a contextual phrase such as "3 lines unpriced", `badge` can appear beside `status`, and either may be `undefined`. `ListItem.trailing` is dormant; use `ListActionRow` when primary and trailing actions need sibling native buttons. Its `label`, `icon`, and `trailingActionIcon` slots are also dormant and cannot contain controls. Let panes relocate at narrow widths instead of shrinking targets. Dividers are chrome and earn their place: a `Toolbar` draws none by default, and the line between pinned chrome and scrolling content comes from scroll state (rule 16a), so never add a border, a permanent `dividerSides`, or a margin to fake or adjust one.
385
386
  For a toolbar heading that must remain at the 20px `--kui-font-l` step, use `ToolbarText size="xlarge-fixed"`; `xlarge` retains the responsive page-title clamp. Pass `headingLevel` when it is a section landmark.
386
387
 
@@ -422,8 +423,9 @@ clips focus painting; never restyle Select's parts from application CSS.
422
423
  `Button` and `SplitButton` take the same `focusRingInset` for a clipping
423
424
  ancestor: the ring moves inside the box, two-tone with a surface-colored line
424
425
  inside it so it stays visible on a loud fill; never re-offset their outline.
425
- The line follows the surface context that sunken, quiet, and raised kerf
426
- surfaces publish (`--kui-color-surface-current`, `-region`, `-tint`); an
426
+ The line follows the surface context that sunken, quiet, raised, and
427
+ highlighted kerf surfaces, app `background` colors, and glass chrome publish
428
+ (`--kui-color-surface-current`, `-region`, `-tint`); an
427
429
  app-owned surface that paints its own background sets them on its own root.
428
430
 
429
431
  For a full-width primary action (a form's or a narrow sheet's one main button),
@@ -466,6 +468,10 @@ For a read-only field preview that replaces a Web Awesome input, use `FieldLabel
466
468
 
467
469
  `ListItem`, `ListItemLink`, and `ListActionRow` take `iconTile` to present their leading `icon` in a filled 32px rounded tile holding an 18px glyph, for settings or command rows that identify each entry by color. Pass a tone (`neutral`, `brand`, `success`, `warning`, or `danger`) for the same quiet fill, matching quiet border, and on-quiet foreground as `ToolbarControlGroup.tileTone`, or `{ color, foreground? }` for an application color: `color` is a `CssColor` (`uiColor()`, `colorVar()`, or `fillColor('#e5484d')`) and `foreground` a `CssForegroundColor`; without one, the glyph is black or white, whichever contrasts with the fill. The tile sits 6px clear of a standard 44px row (a compact row is at least 42px tall), moves the label to the tile's edge, and keeps its colors when the row is hovered or selected. Never wrap the icon in your own tile or resize the row's icon slot.
468
470
 
471
+ For exact numeric entry, use `TextField` with `type="number"` and pass native
472
+ `min`, `max`, and `step` as numbers or strings (`step="any"` permits arbitrary
473
+ decimals). Those attributes reach the inner input only for numeric fields.
474
+
469
475
  Common mistakes:
470
476
 
471
477
  | Mistake | Fix |
@@ -548,7 +554,7 @@ For a tab scene with drill-down, place a `NavStack` directly in `TabNavigatorTab
548
554
  Use `Pane.deepInset` (also in `PaneConfig`) or `TabNavigatorTab.deepInset` for a plain scene when its scrolling content needs an extra 8px on all four sides, giving ordinary items a 16px inline gutter. The extra 8px is applied to the scroll surface, while nested Row/List/Grid item margins stay 8px. When a tab scene is a sole Pane or NavStack, configure deep inset on that child's Pane; the tab bar and top toolbar stay full width.
549
555
  An edge-to-edge table or similar Pane child can read `--kui-pane-content-inset-inline-start` and `--kui-pane-content-inset-inline-end`: negate them for the child's logical margins, then add them to the child's text padding. The inherited values include routed safe areas and `deepInset`; keep the child in the Pane's single scroll slot. See `docs/app-layouts.md` for the CSS recipe.
550
556
 
551
- Do not grow a collapsible search past the room beside its sibling groups: when it does not fit, the siblings wrap onto a new row while it opens. Size the expanded search to fit (`--kui-search-field-expanded-width`, or `sizing="grow"` with a fitting `growBasis`), and if a useful search still cannot fit, set aside the other controls while it is open, with `visibility="yield-to-expanded-sibling"` on those groups (they leave a 480px-or-narrower toolbar while a sibling is expanded) or behind a "…" `PopupMenu` overflow group; the app chooses which controls yield. Expanded search groups accept `expandedOverflow="visible"` to anchor app-owned suggestion/date/help surfaces below their relative root; collapsed/default groups retain existing clipping. Apps own surface placement/dismissal and use `data-search-field-keep-open` or `collapsible.keepOpenOn` for focus.
557
+ Do not grow a collapsible search past the room beside its sibling groups: when it does not fit, the siblings wrap onto a new row while it opens. Size the expanded search to fit (`--kui-search-field-expanded-width`, or `sizing="grow"` with a fitting `growBasis`), and if a useful search still cannot fit, set aside the other controls while it is open, with `visibility="yield-to-expanded-sibling"` on those groups (they leave a 480px-or-narrower toolbar while a sibling is expanded), with `visibility="yield-to-priority-row"` in a `responsive="trailing-priority"` Toolbar (they leave exactly while the expanded control has its own row at the Toolbar's `responsiveAt`; never restate that width with `hideBelow`, which is strict where the Toolbar's widths are inclusive), or behind a "…" `PopupMenu` overflow group; the app chooses which controls yield. Expanded search groups accept `expandedOverflow="visible"` to anchor app-owned suggestion/date/help surfaces below their relative root; collapsed/default groups retain existing clipping. Apps own surface placement/dismissal and use `data-search-field-keep-open` or `collapsible.keepOpenOn` for focus.
552
558
 
553
559
  `ToolbarText` and `ToolbarControlGroup` accept typed `hideBelow`/`showBelow`
554
560
  lengths (for example `px(416)`). Wire `wireToolbarVisibility(root)` from
@@ -565,6 +571,6 @@ Select menus use native viewport shifting with 10px gutters: default menus grow
565
571
 
566
572
  Give sibling `DialogSurface`s that render conditionally a stable `rootAttributes={{ "data-key": "…" }}` so a re-render morphs each dialog into itself (structurally identical roots otherwise match by position and swap names and open state); never wrap one in a keyed app `div`. Modal `DialogSurface` accepts a typed `preferredWidth` (`CssLength`) that overrides `size` while retaining the viewport width cap. Typed `viewportGutter` and `maxHeight` (`CssLength` or `"viewport"`) bound the modal; explicit height caps stay within the dynamic viewport minus both gutters. Omitted props keep the default caps (20px clear of each edge, 80% of the viewport height at 420px wide or narrower). Side-sheet/fullscreen geometry, application responsive choices, and preview layout remain separately owned. `height` (`CssLength` or `"viewport"`) gives the modal a definite bounded size, and `bodyLayout="fill"` hands the whole body to one child (a `SplitView` or `Pane`) that owns its scrolling. For a chat-style dialog, `bodyLayout="fill-last"` keeps leading rows (a notice) at their height and gives the last child (a `scrollable` `List` transcript) the rest, and `footerPresentation="floating"` lays the composer footer over the body, a typed `footerOffset` (default 16px) from the panel edges on a transparent background; the body reserves the measured footer height, so never add `::part(footer)` or `::part(body)` rules for it. To let the transcript scroll visibly beneath the floating composer, give the transcript `scrollClearance="block-end"` (on a `scrollable` `List` or a `Pane`): the body then publishes the footer's clearance as the inherited `--kui-scroll-clearance-block-end`, and the transcript adds it inside its own scroll area, so its last message still rests above the composer. Chrome that overlays a region's edge publishes `--kui-scroll-clearance-block-start` / `-end` the same way, and only the one scroller reaching that edge opts in (a composed Pane opts in through `PaneConfig.scrollClearance`: a Workbench `mainPane` or panel `pane`, a `CollapsiblePanel` `pane`, or a `NavStack` view's `pane`); never pad a transcript yourself to clear a footer. `headerPresentation="floating"` lays the dialog's title bar over the body's block start on the translucent `--kui-chrome-material-raised` (opaque under reduced transparency, increased contrast, forced colors, or without `backdrop-filter`); the open dialog measures it and the body reserves it. To let a transcript scroll beneath both the title bar and a floating composer, make it the body's only child (`bodyLayout="fill"`) with `scrollClearance="both"`: the body publishes the header's height as `--kui-scroll-clearance-block-start`. A `ToolbarText` as the `heading` keeps AA on the title bar by itself (normal-color title, lifted description); keep other quiet copy in the body. `presentation="bottom-sheet"` attaches the dialog to the bottom edge (iOS-style sheet): the top corners keep the dialog radius, the bottom corners are square, and the panel runs behind the home indicator and virtual keyboard while a block-end padding (the larger of `--kui-safe-area-block-end`, the `visualViewport` keyboard overlap `openDialog` measures, and `env(keyboard-inset-height)`) keeps content above them; `height` is its opening visible height and `maxHeight` its cap (the dynamic viewport minus the top safe area and one gutter). `resizable` adds a top grabber (a focusable "Resize sheet" separator; drag, arrows, Page Up/Down, Home/End) bounded by `minHeight` (default 160px) and the cap, restarting at `height` on each opening. It slides up on open and down on dismiss by default (`enterMotion` / `exitMotion` = `"standard"` keeps the dialog's scale-and-fade), with no motion under reduced motion. Never position a dialog at the bottom with your own CSS or add your own keyboard padding. For a non-modal, light-dismiss dialog use `PopoverDialogSurface` from the same subpath (native `popover="auto"`, `role="dialog"`, Kerf chrome, the same size/gutter/height/fill props, and `presentation="embedded"` for an in-flow catalog or inline preview) instead of a hand-built popover with app CSS. Name it with `label` or `labelledBy`, and describe it with `describedBy` (its `aria-describedby`), usually a title `ToolbarText`'s `descriptionId`.
567
573
 
568
- Render a modal dialog as `DialogSurface` itself, a native `<dialog>`: `label` (or `labelledBy` with a `heading`, such as an xl `ToolbarText` with a description) names it, `describedBy` (the heading ToolbarText's `descriptionId`, or app-owned summary copy) describes it as `aria-describedby`, `children` is its body, `footer` holds its buttons, and `headerActions` sit before its close button (`withoutHeader` drops the header for content that owns its heading and close control). Open it with `openDialog(dialog)` and close it with `closeDialog(dialog)` from `@kerfjs/ui/surface-scaffold`; never toggle its `open` attribute. The close button, any `data-dialog-close` element inside (a Cancel button), Escape, and, with `lightDismiss`, a backdrop press dispatch a cancelable `kui-request-close` (`detail.source`: `close-button`, `escape`, or `backdrop`); cancel it to keep the dialog open (the panel pulses). The native `close` event fires once it closes. `openDialog` installs the listeners and, while the dialog is open, measures its floating header/footer, follows a bottom sheet's keyboard and grabber, and keeps that state across re-renders; import `@kerfjs/ui/surface-scaffold/register` only when a dialog may open some other way. Do not write `wa-dialog` inside a `DialogSurface`.
574
+ Render a modal dialog as `DialogSurface` itself, a native `<dialog>` (set `alert` for a confirmation before a destructive action, which renders `role="alertdialog"`; pair it with `describedBy` on the message and leave `lightDismiss` off): `label` (or `labelledBy` with a `heading`, such as an xl `ToolbarText` with a description) names it, `describedBy` (the heading ToolbarText's `descriptionId`, or app-owned summary copy) describes it as `aria-describedby`, `children` is its body, `footer` holds its buttons, and `headerActions` sit before its close button (`withoutHeader` drops the header for content that owns its heading and close control). Open it with `openDialog(dialog)` and close it with `closeDialog(dialog)` from `@kerfjs/ui/surface-scaffold`; never toggle its `open` attribute. The close button, any `data-dialog-close` element inside (a Cancel button), Escape, and, with `lightDismiss`, a backdrop press dispatch a cancelable `kui-request-close` (`detail.source`: `close-button`, `escape`, or `backdrop`); cancel it to keep the dialog open (the panel pulses). The native `close` event fires once it closes. `openDialog` installs the listeners and, while the dialog is open, measures its floating header/footer, follows a bottom sheet's keyboard and grabber, and keeps that state across re-renders; import `@kerfjs/ui/surface-scaffold/register` only when a dialog may open some other way. Do not write `wa-dialog` inside a `DialogSurface`.
569
575
 
570
576
  Toolbar visibility measurement probes and invisible state children are helper-owned and survive Kerf rerenders through `data-morph-preserve`. Actual CSS visibility stays stable while rendering removes transient parent markers, preventing geometry-driven render feedback and repeated probe recreation. Toolbar replacement, explicit internal-node removal and disposal retain their existing behavior.
@@ -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.107` 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.
3
+ Generated from the emitted `@kerfjs/ui@5.0.0-beta.109` 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/button.d.ts CHANGED
@@ -4,8 +4,8 @@ import { BadgeTone } from './badge.js';
4
4
  import './css-values.js';
5
5
  import './semantic-tone-CdW013KF.js';
6
6
 
7
- /** The color family: `neutral` (default), `brand` for the main action, `danger` for a destructive one. */
8
- type ButtonTone = 'neutral' | 'brand' | 'danger';
7
+ /** The color family: `neutral` (default), `brand` for the main action, `success` for a positive one, `danger` for a destructive one. */
8
+ type ButtonTone = 'neutral' | 'brand' | 'success' | 'danger';
9
9
  /**
10
10
  * How loudly it asks: `primary` (default) fills the button, `secondary`
11
11
  * outlines it, and `plain` shows only its text until hovered.
@@ -108,7 +108,7 @@ interface ButtonOptions {
108
108
  }
109
109
  /**
110
110
  * A standalone action button: a native `<button>` (or a link with `href`)
111
- * in one of three tones and three emphases, at the 44px control height or
111
+ * in one of four tones and three emphases, at the 44px control height or
112
112
  * compact, with a label or as an icon-only square, rounded or pill-shaped,
113
113
  * sized to its label or filling its parent's width, and optionally a
114
114
  * `pressed` toggle. Inside a
package/dist/button.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Button } from './chunk-TXRKCGT3.js';
1
+ export { Button } from './chunk-KPINJHIC.js';
2
2
 
3
3
 
4
4
 
package/dist/catalog.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Workbench } from './chunk-NLMEDZRM.js';
1
+ import { Workbench } from './chunk-CPSGUGAY.js';
2
2
  import { uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
3
3
  export { UX_REVIEW_PROJECT_PATH, loadUxReviewProject, uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
4
4
 
@@ -22,12 +22,12 @@ import { PopupMenu } from './chunk-OQP3PFKQ.js';
22
22
 
23
23
 
24
24
 
25
- import { ToolbarControlGroup, ToolbarActionLink } from './chunk-2PXZBFEC.js';
26
- import { Toolbar } from './chunk-CMLPFIC5.js';
25
+ import { ToolbarControlGroup, ToolbarActionLink } from './chunk-5J6Z4BWY.js';
26
+ import { Toolbar } from './chunk-ZN7KUMPY.js';
27
27
 
28
28
 
29
29
  import { ensureSunkenTexture } from './chunk-IKS72C6P.js';
30
- import { List } from './chunk-OY2MXIBB.js';
30
+ import { List } from './chunk-NB6POCFH.js';
31
31
 
32
32
 
33
33
 
package/dist/chip.d.ts CHANGED
@@ -9,6 +9,19 @@ import './css-values.js';
9
9
  * and derives its fill, border, and focus ring from `currentColor`.
10
10
  */
11
11
  type ChipTone = SemanticTone | 'inherit';
12
+ /** Safe `data-*` identity on a Chip root; Chip-owned attributes are protected. */
13
+ type ChipRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
14
+ 'data-component'?: never;
15
+ 'data-tone'?: never;
16
+ 'data-appearance'?: never;
17
+ 'data-shape'?: never;
18
+ 'data-size'?: never;
19
+ 'data-disabled'?: never;
20
+ 'data-truncate'?: never;
21
+ 'data-item-id'?: never;
22
+ 'data-link'?: never;
23
+ 'data-action'?: never;
24
+ }>;
12
25
  interface ChipCommonProps {
13
26
  /** Decorative leading icon, normally an unsized LucideIcon. */
14
27
  icon?: SafeHtml;
@@ -19,6 +32,11 @@ interface ChipCommonProps {
19
32
  disabled?: boolean;
20
33
  /** Record identifier available to an application delegated action handler. */
21
34
  itemId?: string;
35
+ /**
36
+ * Safe `data-*` identity on the chip root (a plain, link, or action chip),
37
+ * for tests and delegated handlers; use `itemId` for the record id.
38
+ */
39
+ rootAttributes?: ChipRootAttributes;
22
40
  className?: string;
23
41
  /** Native named-slot assignment when composed inside a web component. */
24
42
  slot?: string;
@@ -94,6 +112,6 @@ type ChipProps = ChipCommonProps & ChipLabelProps & (({
94
112
  * `href` is set, or a native button when `action` is set. The application
95
113
  * owns removal, the link destination, and the action handler.
96
114
  */
97
- declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, className, slot, href, download, external, removeAction, removeLabel, action, actionLabel, }: ChipProps): SafeHtml;
115
+ declare function Chip({ children, icon, truncate, tone, appearance, shape, size, disabled, itemId, rootAttributes, className, slot, href, download, external, removeAction, removeLabel, action, actionLabel, }: ChipProps): SafeHtml;
98
116
 
99
- export { Chip, type ChipProps, type ChipTone };
117
+ export { Chip, type ChipProps, type ChipRootAttributes, type ChipTone };
package/dist/chip.js CHANGED
@@ -1,3 +1,4 @@
1
- export { Chip } from './chunk-N7MBGONH.js';
1
+ export { Chip } from './chunk-LMHN2TJL.js';
2
+
2
3
 
3
4
  //# sourceMappingURL=chip.js.map
@@ -1,5 +1,5 @@
1
1
  import { Text } from './chunk-7K6U6FCN.js';
2
- import { Toolbar } from './chunk-CMLPFIC5.js';
2
+ import { Toolbar } from './chunk-ZN7KUMPY.js';
3
3
  import { filterDataAttributes } from './chunk-KH4KEMSP.js';
4
4
  import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
5
5
 
@@ -90,4 +90,4 @@ function MessageComposer({
90
90
 
91
91
  export { MessageComposer };
92
92
 
93
- //# sourceMappingURL=chunk-23PPPNH6.js.map
93
+ //# sourceMappingURL=chunk-4OV272LF.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/forms/message-composer/message-composer.tsx"],"names":[],"mappings":"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","file":"chunk-23PPPNH6.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport { Toolbar } from '../../actions/toolbar/toolbar.js';\nimport { Text } from '../../typography/text/text.js';\n\n/**\n * Application `data-*` identity on the MessageComposer root, such as `data-key`;\n * the composer's own configuration attributes stay protected.\n */\nexport type MessageComposerRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\nexport interface MessageComposerProps {\n /** The message field's accessible name, in title style (\"Message\"). */\n label: string;\n /** Native textarea `name`: the form field the message submits under. */\n name: string;\n /**\n * The textarea id. With a `hint`, the hint takes `<id>-hint` and becomes\n * the field's accessible description.\n */\n id?: string;\n /** The field's text: a draft to restore, or `''` after sending. */\n value?: string;\n /** Sentence-style example of what to write (\"Ask about this build\"). */\n placeholder?: string;\n /**\n * Visible lines while the field is empty or short (default 1). The field\n * grows with its content from here.\n */\n minRows?: number;\n /**\n * Lines the field grows to before it scrolls (default 8). At least\n * `minRows`.\n */\n maxRows?: number;\n /**\n * Quiet, sentence-style supporting copy in the action row's leading zone,\n * after any `leading` controls.\n */\n hint?: string;\n /**\n * Controls at the start of the action row, such as an attach button or a\n * model `Select`, normally in a `ToolbarControlGroup`.\n */\n leading?: KerfUiContent;\n /** Trailing controls in the action row, normally one brand Send button. */\n trailing: KerfUiContent;\n /** Disable the field; the app disables its own actions. */\n disabled?: boolean;\n /**\n * Opt in to Enter-to-send: with `wireMessageComposers` running over an ancestor,\n * Enter (or Cmd/Ctrl+Enter) in the field activates the first trailing\n * action, Shift+Enter inserts a newline, and an Enter that commits an IME\n * composition or meets an empty message does not send. The field announces\n * the shortcut with `aria-keyshortcuts`.\n */\n submitOnEnter?: boolean;\n /** Safe `data-*` identity on the root. */\n rootAttributes?: MessageComposerRootAttributes;\n className?: string;\n /** Native named-slot assignment, such as a `wa-dialog`'s `footer`. */\n slot?: string;\n}\n\nconst COMPOSER_PROTECTED = new Set([\n 'data-component',\n 'data-disabled',\n 'data-submit-on-enter',\n]);\n\nfunction rowCount(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1)\n throw new RangeError(`MessageComposer ${name} must be a positive integer.`);\n return value;\n}\n\n/**\n * A chat or prompt composer: a raised frame whose border turns brand while\n * focus is within, holding a borderless message field that grows with its\n * content between `minRows` and `maxRows` lines, above a compact `Toolbar`\n * action row: optional `leading` controls and `hint`, then `trailing` actions. The app owns the value and sending;\n * `submitOnEnter` with `wireMessageComposers` adds Enter-to-send.\n */\nexport function MessageComposer({\n label,\n name,\n id,\n value = '',\n placeholder,\n minRows = 1,\n maxRows = 8,\n hint,\n leading,\n trailing,\n disabled = false,\n submitOnEnter = false,\n rootAttributes = {},\n className = '',\n slot,\n}: MessageComposerProps) {\n const min = rowCount(minRows, 'minRows');\n const max = rowCount(maxRows, 'maxRows');\n if (max < min)\n throw new RangeError('MessageComposer maxRows must be at least minRows.');\n const hintId = hint !== undefined && id !== undefined ? `${id}-hint` : '';\n return (\n <div\n {...filterDataAttributes(rootAttributes, COMPOSER_PROTECTED)}\n class={`kui-message-composer ${className}`.trim()}\n data-component=\"message-composer\"\n data-disabled={disabled ? 'true' : undefined}\n data-submit-on-enter={submitOnEnter ? 'true' : undefined}\n style={`--_kui-message-composer-min-rows:${min};--_kui-message-composer-max-rows:${max}`}\n slot={slot}\n >\n <textarea\n class=\"kui-message-composer__field\"\n id={id}\n name={name}\n rows={min}\n aria-label={label}\n aria-describedby={hintId || undefined}\n aria-keyshortcuts={submitOnEnter ? 'Enter' : undefined}\n placeholder={placeholder}\n disabled={disabled}\n >\n {value}\n </textarea>\n <Toolbar\n position=\"footer\"\n density=\"compact\"\n label={`${label} Actions`}\n leading={\n leading === undefined && hint === undefined ? undefined : (\n <>\n {leading}\n {hint === undefined ? null : (\n <Text\n variant=\"span\"\n tone=\"quiet\"\n size=\"compact\"\n id={hintId || undefined}\n >\n {hint}\n </Text>\n )}\n </>\n )\n }\n trailing={trailing}\n />\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/forms/message-composer/message-composer.tsx"],"names":[],"mappings":"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","file":"chunk-4OV272LF.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport { Toolbar } from '../../actions/toolbar/toolbar.js';\nimport { Text } from '../../typography/text/text.js';\n\n/**\n * Application `data-*` identity on the MessageComposer root, such as `data-key`;\n * the composer's own configuration attributes stay protected.\n */\nexport type MessageComposerRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\nexport interface MessageComposerProps {\n /** The message field's accessible name, in title style (\"Message\"). */\n label: string;\n /** Native textarea `name`: the form field the message submits under. */\n name: string;\n /**\n * The textarea id. With a `hint`, the hint takes `<id>-hint` and becomes\n * the field's accessible description.\n */\n id?: string;\n /** The field's text: a draft to restore, or `''` after sending. */\n value?: string;\n /** Sentence-style example of what to write (\"Ask about this build\"). */\n placeholder?: string;\n /**\n * Visible lines while the field is empty or short (default 1). The field\n * grows with its content from here.\n */\n minRows?: number;\n /**\n * Lines the field grows to before it scrolls (default 8). At least\n * `minRows`.\n */\n maxRows?: number;\n /**\n * Quiet, sentence-style supporting copy in the action row's leading zone,\n * after any `leading` controls.\n */\n hint?: string;\n /**\n * Controls at the start of the action row, such as an attach button or a\n * model `Select`, normally in a `ToolbarControlGroup`.\n */\n leading?: KerfUiContent;\n /** Trailing controls in the action row, normally one brand Send button. */\n trailing: KerfUiContent;\n /** Disable the field; the app disables its own actions. */\n disabled?: boolean;\n /**\n * Opt in to Enter-to-send: with `wireMessageComposers` running over an ancestor,\n * Enter (or Cmd/Ctrl+Enter) in the field activates the first trailing\n * action, Shift+Enter inserts a newline, and an Enter that commits an IME\n * composition or meets an empty message does not send. The field announces\n * the shortcut with `aria-keyshortcuts`.\n */\n submitOnEnter?: boolean;\n /** Safe `data-*` identity on the root. */\n rootAttributes?: MessageComposerRootAttributes;\n className?: string;\n /** Native named-slot assignment, such as a `wa-dialog`'s `footer`. */\n slot?: string;\n}\n\nconst COMPOSER_PROTECTED = new Set([\n 'data-component',\n 'data-disabled',\n 'data-submit-on-enter',\n]);\n\nfunction rowCount(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1)\n throw new RangeError(`MessageComposer ${name} must be a positive integer.`);\n return value;\n}\n\n/**\n * A chat or prompt composer: a raised frame whose border turns brand while\n * focus is within, holding a borderless message field that grows with its\n * content between `minRows` and `maxRows` lines, above a compact `Toolbar`\n * action row: optional `leading` controls and `hint`, then `trailing` actions. The app owns the value and sending;\n * `submitOnEnter` with `wireMessageComposers` adds Enter-to-send.\n */\nexport function MessageComposer({\n label,\n name,\n id,\n value = '',\n placeholder,\n minRows = 1,\n maxRows = 8,\n hint,\n leading,\n trailing,\n disabled = false,\n submitOnEnter = false,\n rootAttributes = {},\n className = '',\n slot,\n}: MessageComposerProps) {\n const min = rowCount(minRows, 'minRows');\n const max = rowCount(maxRows, 'maxRows');\n if (max < min)\n throw new RangeError('MessageComposer maxRows must be at least minRows.');\n const hintId = hint !== undefined && id !== undefined ? `${id}-hint` : '';\n return (\n <div\n {...filterDataAttributes(rootAttributes, COMPOSER_PROTECTED)}\n class={`kui-message-composer ${className}`.trim()}\n data-component=\"message-composer\"\n data-disabled={disabled ? 'true' : undefined}\n data-submit-on-enter={submitOnEnter ? 'true' : undefined}\n style={`--_kui-message-composer-min-rows:${min};--_kui-message-composer-max-rows:${max}`}\n slot={slot}\n >\n <textarea\n class=\"kui-message-composer__field\"\n id={id}\n name={name}\n rows={min}\n aria-label={label}\n aria-describedby={hintId || undefined}\n aria-keyshortcuts={submitOnEnter ? 'Enter' : undefined}\n placeholder={placeholder}\n disabled={disabled}\n >\n {value}\n </textarea>\n <Toolbar\n position=\"footer\"\n density=\"compact\"\n label={`${label} Actions`}\n leading={\n leading === undefined && hint === undefined ? undefined : (\n <>\n {leading}\n {hint === undefined ? null : (\n <Text\n variant=\"span\"\n tone=\"quiet\"\n size=\"compact\"\n id={hintId || undefined}\n >\n {hint}\n </Text>\n )}\n </>\n )\n }\n trailing={trailing}\n />\n </div>\n );\n}\n"]}
@@ -138,4 +138,4 @@ function ToolbarControlGroup({
138
138
 
139
139
  export { ToolbarActionLink, ToolbarControlGroup, isRelocatableGroup };
140
140
 
141
- //# sourceMappingURL=chunk-2PXZBFEC.js.map
141
+ //# sourceMappingURL=chunk-5J6Z4BWY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/panels/panel-toolbar-group.ts","../src/components/actions/toolbar-control-group/toolbar-control-group.tsx"],"names":[],"mappings":"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","file":"chunk-2PXZBFEC.js","sourcesContent":["import { isSafeHtml, type SafeHtml } from 'kerfjs';\n\n// A render-time annotation, shared across separately bundled UI subpaths.\n// It never appears in the DOM or changes the group's visual treatment.\nconst RELOCATE_ON_COLLAPSE = Symbol.for(\n '@kerfjs/ui.ToolbarControlGroup.relocateOnCollapse',\n);\n\nexport function markRelocatableGroup(group: SafeHtml): SafeHtml {\n Object.defineProperty(group, RELOCATE_ON_COLLAPSE, { value: true });\n return group;\n}\n\nexport function isRelocatableGroup(value: unknown): value is SafeHtml {\n return (\n isSafeHtml(value) &&\n (value as SafeHtml & { [RELOCATE_ON_COLLAPSE]?: boolean })[\n RELOCATE_ON_COLLAPSE\n ] === true\n );\n}\n","import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { markRelocatableGroup } from '../../../shared/panels/panel-toolbar-group.js';\nimport type { CssLength } from '../../../shared/styles/css-values.js';\nimport { LoadingSpinner } from '../../feedback/loading-spinner/loading-spinner.js';\n\nexport type ToolbarControlGroupAppearance = 'contained' | 'borderless';\nexport type ToolbarControlGroupTone = 'default' | 'dark';\n/** Surface material: the opaque `solid` fill (default) or translucent `glass`. */\nexport type ToolbarControlGroupMaterial = 'solid' | 'glass';\n/** Quiet palette for a contained, single decorative icon tile. */\nexport type ToolbarControlGroupTileTone =\n 'neutral' | 'brand' | 'success' | 'warning' | 'danger';\nexport type ToolbarControlGroupButtonAppearance = 'plain' | 'push';\nexport type ToolbarControlGroupShape = 'pill' | 'rounded';\nexport type ToolbarControlGroupSize = 'default' | 'compact';\nexport type ToolbarControlGroupDensity = 'comfortable' | 'tight';\nexport type ToolbarControlGroupContent =\n 'icon' | 'text' | 'mixed' | 'avatar' | 'search';\nexport type ToolbarControlGroupFocusRing = 'control' | 'outline' | 'halo';\nexport type ToolbarControlGroupSelectedChrome =\n 'raised' | 'filled' | 'outline' | 'none';\nexport type ToolbarControlGroupSelectedTone = 'brand' | 'neutral' | 'pop';\nexport type ToolbarControlGroupOverflow = 'visible' | 'scroll' | 'wrap';\nexport type ToolbarControlGroupExpandedOverflow = 'clip' | 'visible';\nexport type ToolbarControlGroupMenuInset = 'standard' | 'compact' | 'list-zero';\nexport type ToolbarControlGroupVisibility =\n | 'always'\n | 'compact-only'\n | 'hide-collapsed-tiny'\n | 'yield-to-expanded-sibling';\nexport type ToolbarControlGroupSizing = 'content' | 'grow' | 'fill';\nexport type ToolbarControlGroupPlacement = 'start' | 'end';\n\nexport interface ToolbarActionLinkProps {\n href: string;\n label: string;\n icon?: KerfUiContent;\n /** Optional machine-readable detail hidden visually but included in the default accessible name. */\n detail?: string;\n /** Override the accessible name when surrounding context is needed. */\n ariaLabel?: string;\n /** Open in a new tab with a safe rel and announce that behavior. */\n external?: boolean;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** A semantic anchor with ToolbarControlGroup-owned action geometry. */\nexport function ToolbarActionLink({\n href,\n label,\n icon,\n detail,\n ariaLabel,\n external = false,\n className = '',\n slot,\n}: ToolbarActionLinkProps) {\n const accessibleLabel =\n ariaLabel ??\n `${label}${detail ? `, ${detail}` : ''}${external ? ' (opens in new tab)' : ''}`;\n return (\n <a\n class={`kui-toolbar-action-link ${className}`.trim()}\n data-component=\"toolbar-action-link\"\n href={href}\n target={external ? '_blank' : undefined}\n rel={external ? 'noopener noreferrer' : undefined}\n aria-label={accessibleLabel}\n slot={slot}\n >\n {icon}\n <span>{label}</span>\n {detail ? <code aria-hidden=\"true\">{detail}</code> : null}\n </a>\n );\n}\n\nexport interface ToolbarControlGroupProps {\n children: KerfUiContent;\n label?: string;\n className?: string;\n expanded?: boolean;\n single?: boolean;\n appearance?: ToolbarControlGroupAppearance;\n tone?: ToolbarControlGroupTone;\n /**\n * `glass` paints the group on the translucent chrome material (backdrop\n * blur and saturation) with a specular edge and a soft shadow, for a group\n * floating over imagery or a clear toolbar. Controls take the normal text\n * color so they keep AA over any content; the fill turns opaque under\n * reduced transparency, increased contrast, static effects, or without\n * backdrop-filter support. A borderless group has no surface and ignores it.\n */\n material?: ToolbarControlGroupMaterial;\n /** Quiet fill, matching border and foreground for a contained single group whose only child is a decorative SVG. Ignored for interactive or mixed content. */\n tileTone?: ToolbarControlGroupTileTone;\n buttonAppearance?: ToolbarControlGroupButtonAppearance;\n /** Corner shape: fully round `pill` (default) or a softer `rounded` rectangle. */\n shape?: ToolbarControlGroupShape;\n size?: ToolbarControlGroupSize;\n density?: ToolbarControlGroupDensity;\n content?: ToolbarControlGroupContent;\n /** Whether controls paint focus individually or the group paints an outline/halo on focus-within. */\n focusRing?: ToolbarControlGroupFocusRing;\n /**\n * Chrome a pressed (`aria-pressed=\"true\"`) control paints. `none` keeps a\n * pressed control looking like its neighbors, for an icon-state toggle whose\n * glyph already shows the state (an empty or filled star); hover and the\n * focus ring are unchanged. One control can opt out alone with\n * `data-selected-chrome=\"none\"` on its own button.\n */\n selectedChrome?: ToolbarControlGroupSelectedChrome;\n selectedTone?: ToolbarControlGroupSelectedTone;\n /** Size a nested Web Awesome dropdown trigger as part of this group. */\n nestedDropdown?: boolean;\n /** Configure the nested dropdown menu inset without consumer ::part() CSS. */\n menuInset?: ToolbarControlGroupMenuInset;\n /** Keep an overlong row inside the available width by scrolling or wrapping. */\n overflow?: ToolbarControlGroupOverflow;\n /** Let app-owned anchored surfaces extend outside an expanded search group. Collapsed searches retain their clipping. */\n expandedOverflow?: ToolbarControlGroupExpandedOverflow;\n /** Responsive visibility owned by the enclosing Toolbar container. */\n visibility?: ToolbarControlGroupVisibility;\n /** Hide below this Toolbar content width; requires wireToolbarVisibility. */\n hideBelow?: CssLength;\n /** Show only below this Toolbar content width; requires wireToolbarVisibility. */\n showBelow?: CssLength;\n /** Intrinsic (default), grow from a basis, or occupy a full wrapping row. */\n sizing?: ToolbarControlGroupSizing;\n /** Place this group at the end of its flex row in a wrapping Toolbar zone. */\n placement?: ToolbarControlGroupPlacement;\n /** CSS length used as the minimum width and flex basis for `sizing=\"grow\"`; defaults to 19rem. */\n growBasis?: string;\n /** Move this group into the work-area toolbar when its panel collapses. */\n relocateOnCollapse?: boolean;\n /** Add contrast behind photo-backed avatar content. */\n scrim?: boolean;\n /** Block the group's controls and show a spinner without changing its dimensions. */\n busy?: boolean;\n /** Announced status while busy; defaults to “Working”. */\n busyLabel?: string;\n /**\n * Avatar image URL. A single-control group paints it on the group; a\n * multi-control group paints it only on the pressed selection highlight.\n */\n avatarImage?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nexport function ToolbarControlGroup({\n children,\n label,\n className = '',\n expanded = false,\n single = false,\n appearance = 'contained',\n tone = 'default',\n material = 'solid',\n tileTone,\n buttonAppearance = 'plain',\n shape = 'pill',\n size = 'default',\n density = 'comfortable',\n content = 'icon',\n focusRing = 'control',\n selectedChrome = 'raised',\n selectedTone = 'brand',\n nestedDropdown = false,\n menuInset = 'standard',\n overflow = 'visible',\n expandedOverflow = 'clip',\n visibility = 'always',\n hideBelow,\n showBelow,\n sizing = 'content',\n placement = 'start',\n growBasis,\n relocateOnCollapse = false,\n scrim = false,\n busy = false,\n busyLabel = 'Working',\n avatarImage,\n slot,\n}: ToolbarControlGroupProps) {\n const inlineStyles = [\n avatarImage\n ? `--kui-toolbar-avatar-image:url(${JSON.stringify(avatarImage)})`\n : '',\n growBasis ? `--kui-toolbar-group-grow-basis:${growBasis}` : '',\n ].filter(Boolean);\n const group = (\n <div\n class={`kui-toolbar-control-group ${className}`.trim()}\n data-component=\"toolbar-control-group\"\n role={label ? 'group' : undefined}\n aria-label={label}\n data-appearance={appearance}\n data-tone={tone}\n data-material={material === 'glass' ? 'glass' : undefined}\n data-tile-tone={tileTone}\n data-button-appearance={buttonAppearance}\n data-expanded={String(expanded)}\n data-single={String(single)}\n data-shape={shape}\n data-size={size}\n data-density={density}\n data-content={content}\n data-focus-ring={focusRing}\n data-selected-chrome={selectedChrome}\n data-selected-tone={selectedTone}\n data-nested-dropdown={String(nestedDropdown)}\n data-menu-inset={menuInset}\n data-overflow={overflow}\n data-expanded-overflow={\n expandedOverflow === 'visible' ? 'visible' : undefined\n }\n data-visibility={visibility}\n data-hide-below={hideBelow}\n data-show-below={showBelow}\n data-sizing={sizing}\n data-placement={placement}\n data-scrim={String(scrim)}\n data-busy={String(busy)}\n aria-busy={busy ? 'true' : undefined}\n inert={busy}\n style={inlineStyles.length ? inlineStyles.join(';') : undefined}\n slot={slot}\n >\n {children}\n {busy ? (\n <span\n class=\"kui-toolbar-control-group__busy-spinner\"\n aria-hidden=\"true\"\n >\n <LoadingSpinner />\n </span>\n ) : null}\n </div>\n );\n const renderedGroup = busy ? (\n <>\n {group}\n <span class=\"kui-toolbar-control-group__busy-status\" role=\"status\">\n {busyLabel}\n </span>\n </>\n ) : (\n group\n );\n return relocateOnCollapse\n ? markRelocatableGroup(renderedGroup)\n : renderedGroup;\n}\n"]}
1
+ {"version":3,"sources":["../src/shared/panels/panel-toolbar-group.ts","../src/components/actions/toolbar-control-group/toolbar-control-group.tsx"],"names":[],"mappings":"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","file":"chunk-5J6Z4BWY.js","sourcesContent":["import { isSafeHtml, type SafeHtml } from 'kerfjs';\n\n// A render-time annotation, shared across separately bundled UI subpaths.\n// It never appears in the DOM or changes the group's visual treatment.\nconst RELOCATE_ON_COLLAPSE = Symbol.for(\n '@kerfjs/ui.ToolbarControlGroup.relocateOnCollapse',\n);\n\nexport function markRelocatableGroup(group: SafeHtml): SafeHtml {\n Object.defineProperty(group, RELOCATE_ON_COLLAPSE, { value: true });\n return group;\n}\n\nexport function isRelocatableGroup(value: unknown): value is SafeHtml {\n return (\n isSafeHtml(value) &&\n (value as SafeHtml & { [RELOCATE_ON_COLLAPSE]?: boolean })[\n RELOCATE_ON_COLLAPSE\n ] === true\n );\n}\n","import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { markRelocatableGroup } from '../../../shared/panels/panel-toolbar-group.js';\nimport type { CssLength } from '../../../shared/styles/css-values.js';\nimport { LoadingSpinner } from '../../feedback/loading-spinner/loading-spinner.js';\n\nexport type ToolbarControlGroupAppearance = 'contained' | 'borderless';\nexport type ToolbarControlGroupTone = 'default' | 'dark';\n/** Surface material: the opaque `solid` fill (default) or translucent `glass`. */\nexport type ToolbarControlGroupMaterial = 'solid' | 'glass';\n/** Quiet palette for a contained, single decorative icon tile. */\nexport type ToolbarControlGroupTileTone =\n 'neutral' | 'brand' | 'success' | 'warning' | 'danger';\nexport type ToolbarControlGroupButtonAppearance = 'plain' | 'push';\nexport type ToolbarControlGroupShape = 'pill' | 'rounded';\nexport type ToolbarControlGroupSize = 'default' | 'compact';\nexport type ToolbarControlGroupDensity = 'comfortable' | 'tight';\nexport type ToolbarControlGroupContent =\n 'icon' | 'text' | 'mixed' | 'avatar' | 'search';\nexport type ToolbarControlGroupFocusRing = 'control' | 'outline' | 'halo';\nexport type ToolbarControlGroupSelectedChrome =\n 'raised' | 'filled' | 'outline' | 'none';\nexport type ToolbarControlGroupSelectedTone = 'brand' | 'neutral' | 'pop';\nexport type ToolbarControlGroupOverflow = 'visible' | 'scroll' | 'wrap';\nexport type ToolbarControlGroupExpandedOverflow = 'clip' | 'visible';\nexport type ToolbarControlGroupMenuInset = 'standard' | 'compact' | 'list-zero';\nexport type ToolbarControlGroupVisibility =\n | 'always'\n | 'compact-only'\n | 'hide-collapsed-tiny'\n | 'yield-to-expanded-sibling'\n | 'yield-to-priority-row';\nexport type ToolbarControlGroupSizing = 'content' | 'grow' | 'fill';\nexport type ToolbarControlGroupPlacement = 'start' | 'end';\n\nexport interface ToolbarActionLinkProps {\n href: string;\n label: string;\n icon?: KerfUiContent;\n /** Optional machine-readable detail hidden visually but included in the default accessible name. */\n detail?: string;\n /** Override the accessible name when surrounding context is needed. */\n ariaLabel?: string;\n /** Open in a new tab with a safe rel and announce that behavior. */\n external?: boolean;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** A semantic anchor with ToolbarControlGroup-owned action geometry. */\nexport function ToolbarActionLink({\n href,\n label,\n icon,\n detail,\n ariaLabel,\n external = false,\n className = '',\n slot,\n}: ToolbarActionLinkProps) {\n const accessibleLabel =\n ariaLabel ??\n `${label}${detail ? `, ${detail}` : ''}${external ? ' (opens in new tab)' : ''}`;\n return (\n <a\n class={`kui-toolbar-action-link ${className}`.trim()}\n data-component=\"toolbar-action-link\"\n href={href}\n target={external ? '_blank' : undefined}\n rel={external ? 'noopener noreferrer' : undefined}\n aria-label={accessibleLabel}\n slot={slot}\n >\n {icon}\n <span>{label}</span>\n {detail ? <code aria-hidden=\"true\">{detail}</code> : null}\n </a>\n );\n}\n\nexport interface ToolbarControlGroupProps {\n children: KerfUiContent;\n label?: string;\n className?: string;\n expanded?: boolean;\n single?: boolean;\n appearance?: ToolbarControlGroupAppearance;\n tone?: ToolbarControlGroupTone;\n /**\n * `glass` paints the group on the translucent chrome material (backdrop\n * blur and saturation) with a specular edge and a soft shadow, for a group\n * floating over imagery or a clear toolbar. Controls take the normal text\n * color so they keep AA over any content; the fill turns opaque under\n * reduced transparency, increased contrast, static effects, or without\n * backdrop-filter support. A borderless group has no surface and ignores it.\n */\n material?: ToolbarControlGroupMaterial;\n /** Quiet fill, matching border and foreground for a contained single group whose only child is a decorative SVG. Ignored for interactive or mixed content. */\n tileTone?: ToolbarControlGroupTileTone;\n buttonAppearance?: ToolbarControlGroupButtonAppearance;\n /** Corner shape: fully round `pill` (default) or a softer `rounded` rectangle. */\n shape?: ToolbarControlGroupShape;\n size?: ToolbarControlGroupSize;\n density?: ToolbarControlGroupDensity;\n content?: ToolbarControlGroupContent;\n /** Whether controls paint focus individually or the group paints an outline/halo on focus-within. */\n focusRing?: ToolbarControlGroupFocusRing;\n /**\n * Chrome a pressed (`aria-pressed=\"true\"`) control paints. `none` keeps a\n * pressed control looking like its neighbors, for an icon-state toggle whose\n * glyph already shows the state (an empty or filled star); hover and the\n * focus ring are unchanged. One control can opt out alone with\n * `data-selected-chrome=\"none\"` on its own button.\n */\n selectedChrome?: ToolbarControlGroupSelectedChrome;\n selectedTone?: ToolbarControlGroupSelectedTone;\n /** Size a nested Web Awesome dropdown trigger as part of this group. */\n nestedDropdown?: boolean;\n /** Configure the nested dropdown menu inset without consumer ::part() CSS. */\n menuInset?: ToolbarControlGroupMenuInset;\n /** Keep an overlong row inside the available width by scrolling or wrapping. */\n overflow?: ToolbarControlGroupOverflow;\n /** Let app-owned anchored surfaces extend outside an expanded search group. Collapsed searches retain their clipping. */\n expandedOverflow?: ToolbarControlGroupExpandedOverflow;\n /**\n * Responsive visibility owned by the enclosing Toolbar container.\n * `yield-to-priority-row` hides this trailing group exactly while its\n * Toolbar's `responsive=\"trailing-priority\"` row is active (an expanded\n * trailing sibling at the Toolbar's `responsiveAt` width), so the app never\n * restates that breakpoint with `hideBelow`.\n */\n visibility?: ToolbarControlGroupVisibility;\n /** Hide below this Toolbar content width; requires wireToolbarVisibility. */\n hideBelow?: CssLength;\n /** Show only below this Toolbar content width; requires wireToolbarVisibility. */\n showBelow?: CssLength;\n /** Intrinsic (default), grow from a basis, or occupy a full wrapping row. */\n sizing?: ToolbarControlGroupSizing;\n /** Place this group at the end of its flex row in a wrapping Toolbar zone. */\n placement?: ToolbarControlGroupPlacement;\n /** CSS length used as the minimum width and flex basis for `sizing=\"grow\"`; defaults to 19rem. */\n growBasis?: string;\n /** Move this group into the work-area toolbar when its panel collapses. */\n relocateOnCollapse?: boolean;\n /** Add contrast behind photo-backed avatar content. */\n scrim?: boolean;\n /** Block the group's controls and show a spinner without changing its dimensions. */\n busy?: boolean;\n /** Announced status while busy; defaults to “Working”. */\n busyLabel?: string;\n /**\n * Avatar image URL. A single-control group paints it on the group; a\n * multi-control group paints it only on the pressed selection highlight.\n */\n avatarImage?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nexport function ToolbarControlGroup({\n children,\n label,\n className = '',\n expanded = false,\n single = false,\n appearance = 'contained',\n tone = 'default',\n material = 'solid',\n tileTone,\n buttonAppearance = 'plain',\n shape = 'pill',\n size = 'default',\n density = 'comfortable',\n content = 'icon',\n focusRing = 'control',\n selectedChrome = 'raised',\n selectedTone = 'brand',\n nestedDropdown = false,\n menuInset = 'standard',\n overflow = 'visible',\n expandedOverflow = 'clip',\n visibility = 'always',\n hideBelow,\n showBelow,\n sizing = 'content',\n placement = 'start',\n growBasis,\n relocateOnCollapse = false,\n scrim = false,\n busy = false,\n busyLabel = 'Working',\n avatarImage,\n slot,\n}: ToolbarControlGroupProps) {\n const inlineStyles = [\n avatarImage\n ? `--kui-toolbar-avatar-image:url(${JSON.stringify(avatarImage)})`\n : '',\n growBasis ? `--kui-toolbar-group-grow-basis:${growBasis}` : '',\n ].filter(Boolean);\n const group = (\n <div\n class={`kui-toolbar-control-group ${className}`.trim()}\n data-component=\"toolbar-control-group\"\n role={label ? 'group' : undefined}\n aria-label={label}\n data-appearance={appearance}\n data-tone={tone}\n data-material={material === 'glass' ? 'glass' : undefined}\n data-tile-tone={tileTone}\n data-button-appearance={buttonAppearance}\n data-expanded={String(expanded)}\n data-single={String(single)}\n data-shape={shape}\n data-size={size}\n data-density={density}\n data-content={content}\n data-focus-ring={focusRing}\n data-selected-chrome={selectedChrome}\n data-selected-tone={selectedTone}\n data-nested-dropdown={String(nestedDropdown)}\n data-menu-inset={menuInset}\n data-overflow={overflow}\n data-expanded-overflow={\n expandedOverflow === 'visible' ? 'visible' : undefined\n }\n data-visibility={visibility}\n data-hide-below={hideBelow}\n data-show-below={showBelow}\n data-sizing={sizing}\n data-placement={placement}\n data-scrim={String(scrim)}\n data-busy={String(busy)}\n aria-busy={busy ? 'true' : undefined}\n inert={busy}\n style={inlineStyles.length ? inlineStyles.join(';') : undefined}\n slot={slot}\n >\n {children}\n {busy ? (\n <span\n class=\"kui-toolbar-control-group__busy-spinner\"\n aria-hidden=\"true\"\n >\n <LoadingSpinner />\n </span>\n ) : null}\n </div>\n );\n const renderedGroup = busy ? (\n <>\n {group}\n <span class=\"kui-toolbar-control-group__busy-status\" role=\"status\">\n {busyLabel}\n </span>\n </>\n ) : (\n group\n );\n return relocateOnCollapse\n ? markRelocatableGroup(renderedGroup)\n : renderedGroup;\n}\n"]}
@@ -27,6 +27,7 @@ function DialogSurface({
27
27
  label,
28
28
  labelledBy,
29
29
  describedBy,
30
+ alert = false,
30
31
  heading,
31
32
  headerActions,
32
33
  footer,
@@ -68,6 +69,7 @@ function DialogSurface({
68
69
  ...filterDataAttributes(rootAttributes, DIALOG_SURFACE_PROTECTED),
69
70
  id,
70
71
  class: `kui-dialog-surface ${className}`.trim(),
72
+ role: alert ? "alertdialog" : void 0,
71
73
  "aria-label": label,
72
74
  "aria-labelledby": labelledBy,
73
75
  "aria-describedby": describedBy,
@@ -199,4 +201,4 @@ function PopupSurface({
199
201
 
200
202
  export { DialogSurface, PopoverDialogSurface, PopupSurface };
201
203
 
202
- //# sourceMappingURL=chunk-G4DRH4A5.js.map
204
+ //# sourceMappingURL=chunk-6CDILXF4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/surfaces/surface-scaffold/surface-scaffold.tsx"],"names":[],"mappings":"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","file":"chunk-6CDILXF4.js","sourcesContent":["import { X } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport type { CssLength } from '../../../shared/styles/css-values.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\n\nexport {\n closeDialog,\n type DialogCloseSource,\n type DialogRequestCloseDetail,\n openDialog,\n} from './internal/dialog-surface-controller.js';\n\nexport type DialogSurfaceSize = 'small' | 'medium' | 'large';\n/**\n * How the dialog is presented: `modal` (default) centered on the screen,\n * `side-sheet` against the inline end, `fullscreen`, or `bottom-sheet`\n * attached to the bottom edge (square bottom corners, safe-area and\n * virtual-keyboard clearance, optionally user-resizable).\n */\nexport type DialogSurfacePresentation =\n 'modal' | 'side-sheet' | 'fullscreen' | 'bottom-sheet';\n/**\n * How a bottom sheet appears or leaves: `slide` (default) moves the panel in\n * from, or out to, the bottom edge; `standard` keeps the dialog's\n * scale-and-fade. Both honor `prefers-reduced-motion`.\n */\nexport type DialogSurfaceSheetMotion = 'slide' | 'standard';\nexport type SurfaceInset = 'none' | 'compact' | 'comfortable';\nexport type DialogSurfaceMaxHeight = CssLength | 'viewport';\n/** A definite modal height: a length or the full viewport, minus both gutters. */\nexport type DialogSurfaceHeight = CssLength | 'viewport';\n/**\n * How the dialog body lays out its children: `flow` (default) scrolls ordinary\n * content in the body; `fill` gives one child the body's whole height and\n * lets it own scrolling (a SplitView, a Pane, an editor); `fill-last` stacks\n * the leading children at their natural height and gives the last child the\n * remaining height to own its scrolling (a heading and notices above a\n * scrolling transcript).\n */\nexport type DialogSurfaceBodyLayout = 'flow' | 'fill' | 'fill-last';\n/**\n * Where the dialog footer sits: `docked` (default) below the body, or\n * `floating` over the body's block end, inset from the panel's inline and\n * block-end edges on a transparent background (a chat composer).\n */\nexport type DialogSurfaceFooterPresentation = 'docked' | 'floating';\n/**\n * Where the dialog header sits: `docked` (default) above the body, or\n * `floating` over the body's block-start edge on the translucent chrome\n * material, so content scrolls visibly beneath the title bar.\n */\nexport type DialogSurfaceHeaderPresentation = 'docked' | 'floating';\n\n/**\n * Application `data-*` identity on the DialogSurface root, such as\n * `data-key`; the surface's own configuration attributes stay protected.\n */\nexport type DialogSurfaceRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\nconst DIALOG_SURFACE_PROTECTED = new Set([\n 'data-component',\n 'data-size',\n 'data-presentation',\n 'data-preferred-width',\n 'data-body-inset',\n 'data-footer-inset',\n 'data-viewport-gutter',\n 'data-max-height',\n 'data-height',\n 'data-body-layout',\n 'data-footer-presentation',\n 'data-header-presentation',\n 'data-min-height',\n 'data-resizable',\n 'data-enter-motion',\n 'data-exit-motion',\n 'data-light-dismiss',\n]);\n\n/**\n * The dialog's accessible name: its `label` text (also the default title), or\n * the id of an element that names it, such as a `heading` ToolbarText.\n */\nexport type DialogSurfaceName =\n { label: string; labelledBy?: never } | { label?: never; labelledBy: string };\n\nexport type DialogSurfaceProps = DialogSurfaceName & DialogSurfaceOptions;\n\nexport interface DialogSurfaceOptions {\n /** The dialog's id, for `openDialog(document.getElementById(id))`. */\n id?: string;\n /**\n * Id of the element whose text is the dialog's accessible description,\n * such as the `heading` ToolbarText's `descriptionId` or app-owned summary\n * copy in the body; rendered as `aria-describedby` on the `<dialog>`.\n */\n describedBy?: string;\n /**\n * An alert dialog: a confirmation that interrupts the person to report\n * something urgent or ask before a destructive action (\"Delete this\n * topic?\"). Renders `role=\"alertdialog\"` on the `<dialog>`; set\n * `describedBy` to the element holding the message, and leave\n * `lightDismiss` off so the person answers it.\n */\n alert?: boolean;\n /** The body content. */\n children: KerfUiContent;\n /**\n * Header title content in place of the `label` text, such as an xl\n * `ToolbarText` with a description. The dialog keeps its `label` (or\n * `labelledBy`) name.\n */\n heading?: KerfUiContent;\n /** Controls before the close button in the header. */\n headerActions?: KerfUiContent;\n /** The footer, below the body (or floating over it); usually its buttons. */\n footer?: KerfUiContent;\n /**\n * Render no header: no title and no close button. The content then owns its\n * heading and a way to close (an element with `data-dialog-close`).\n */\n withoutHeader?: boolean;\n /** Close on a press on the backdrop; otherwise the panel pulses. */\n lightDismiss?: boolean;\n /** The close button's accessible name (default `Close`). */\n closeLabel?: string;\n size?: DialogSurfaceSize;\n presentation?: DialogSurfacePresentation;\n /** Modal preferred width. Takes precedence over size, within the viewport cap. */\n preferredWidth?: CssLength;\n bodyInset?: SurfaceInset;\n footerInset?: SurfaceInset;\n /** Modal edge clearance. Omit to retain Web Awesome's default viewport cap. */\n viewportGutter?: CssLength;\n /**\n * Modal height cap, bounded by the dynamic viewport minus both gutters. On a\n * bottom sheet, the cap (and the resize ceiling), bounded by the dynamic\n * viewport minus the top safe area and one gutter.\n */\n maxHeight?: DialogSurfaceMaxHeight;\n /**\n * Modal definite height, bounded the same way, so a filling child has a\n * height to fill. Takes precedence over `maxHeight`. On a bottom sheet, the\n * height it opens at (the visible height above the safe area or keyboard).\n */\n height?: DialogSurfaceHeight;\n /**\n * A resizable bottom sheet's resize floor (default 160px), the visible\n * height above the safe area or keyboard.\n */\n minHeight?: CssLength;\n /**\n * Let the person resize a bottom sheet by its top grabber (drag, or the\n * arrow, Page Up/Down, Home and End keys) between `minHeight` and the\n * sheet's cap. Needs the `/register` entry; each opening starts at `height`\n * (or the content height). Ignored by other presentations.\n */\n resizable?: boolean;\n /** How a bottom sheet appears (default `slide` up from the bottom edge). */\n enterMotion?: DialogSurfaceSheetMotion;\n /** How a bottom sheet is dismissed (default `slide` down off the bottom edge). */\n exitMotion?: DialogSurfaceSheetMotion;\n /**\n * Body layout (default `flow`); `fill` lets one child own the body and\n * `fill-last` stacks fixed rows above one filling last child.\n */\n bodyLayout?: DialogSurfaceBodyLayout;\n /**\n * Header placement (default `docked`); `floating` lays the dialog's header\n * (its title and close control) over the body's block-start edge on the\n * translucent chrome material (`--kui-chrome-material-raised`, opaque under\n * `prefers-reduced-transparency`, increased contrast, forced colors, or\n * without `backdrop-filter`). The `/register` entry measures the header;\n * the body reserves that height before its own inset, so its first content\n * rests below the title bar. A `fill`/`fill-last` child that is the body's\n * only child and opts into block-start `scrollClearance` (a `List` or\n * `Pane`) takes the clearance inside its own scroll area instead, published\n * as `--kui-scroll-clearance-block-start`, so its content scrolls visibly\n * beneath the header. Unmeasured (without the register), the header stays\n * docked. Keep header text in the normal text color: quiet text can fall\n * below AA over the content passing beneath it.\n */\n headerPresentation?: DialogSurfaceHeaderPresentation;\n /**\n * Footer placement (default `docked`); `floating` lays the footer over the\n * body's block end. The body reserves the footer's measured height so its\n * last content is never hidden beneath it. A `fill`/`fill-last` child that\n * opts into block-end `scrollClearance` (a `List` or `Pane`) takes that\n * clearance inside its own scroll area instead, published as\n * `--kui-scroll-clearance-block-end`, so its content scrolls visibly beneath\n * the transparent footer.\n */\n footerPresentation?: DialogSurfaceFooterPresentation;\n /**\n * A floating footer's clearance from the panel's inline and block-end edges\n * (default the 16px container inset). Choose a phone value such as\n * `remify(8)` from `deviceClass()`; the scaffold adds no breakpoint.\n */\n footerOffset?: CssLength;\n /**\n * Safe `data-*` identity on the root. Give sibling dialogs distinct\n * `data-key`s so a re-render morphs each surface into itself instead of\n * reusing one dialog's element for another (structurally identical roots\n * are otherwise matched by position).\n */\n rootAttributes?: DialogSurfaceRootAttributes;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A modal dialog: a native `<dialog>` with Kerf's header, body, and footer\n * chrome, sized and presented by its props. Render it closed, then open it\n * with `openDialog()` and close it with `closeDialog()`, the close button, an\n * element with `data-dialog-close`, Escape, or (with `lightDismiss`) a press\n * on the backdrop. Import `@kerfjs/ui/surface-scaffold/register` for the\n * floating header and footer measurement, the bottom sheet's keyboard\n * clearance and grabber, and re-render resilience while open.\n */\nexport function DialogSurface({\n id,\n label,\n labelledBy,\n describedBy,\n alert = false,\n heading,\n headerActions,\n footer,\n withoutHeader = false,\n lightDismiss = false,\n closeLabel = 'Close',\n children,\n size = 'medium',\n presentation = 'modal',\n preferredWidth,\n bodyInset = 'compact',\n footerInset = 'comfortable',\n viewportGutter,\n maxHeight,\n height,\n minHeight,\n resizable = false,\n enterMotion = 'slide',\n exitMotion = 'slide',\n bodyLayout = 'flow',\n headerPresentation = 'docked',\n footerPresentation = 'docked',\n footerOffset,\n rootAttributes = {},\n className = '',\n slot,\n}: DialogSurfaceProps) {\n const style = [\n preferredWidth === undefined\n ? ''\n : `--_kui-dialog-surface-preferred-width:${preferredWidth}`,\n viewportGutter === undefined\n ? ''\n : `--_kui-dialog-surface-gutter:${viewportGutter}`,\n maxHeight === undefined || maxHeight === 'viewport'\n ? ''\n : `--_kui-dialog-surface-max-height:${maxHeight}`,\n height === undefined || height === 'viewport'\n ? ''\n : `--_kui-dialog-surface-height:${height}`,\n footerOffset === undefined\n ? ''\n : `--_kui-dialog-surface-footer-offset:${footerOffset}`,\n minHeight === undefined\n ? ''\n : `--_kui-dialog-surface-min-height:${minHeight}`,\n ]\n .filter(Boolean)\n .join(';');\n return (\n <dialog\n {...filterDataAttributes(rootAttributes, DIALOG_SURFACE_PROTECTED)}\n id={id}\n class={`kui-dialog-surface ${className}`.trim()}\n role={alert ? 'alertdialog' : undefined}\n aria-label={label}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n tabindex={-1}\n data-light-dismiss={lightDismiss ? '' : undefined}\n data-component=\"dialog-surface\"\n data-size={size}\n data-presentation={presentation}\n data-preferred-width={preferredWidth === undefined ? undefined : ''}\n data-body-inset={bodyInset}\n data-footer-inset={footerInset}\n data-viewport-gutter={viewportGutter === undefined ? undefined : ''}\n data-max-height={maxHeight === undefined ? undefined : ''}\n data-height={height === undefined ? undefined : ''}\n data-body-layout={bodyLayout === 'flow' ? undefined : bodyLayout}\n data-header-presentation={\n headerPresentation === 'floating' ? 'floating' : undefined\n }\n data-footer-presentation={\n footerPresentation === 'floating' ? 'floating' : undefined\n }\n data-min-height={minHeight === undefined ? undefined : ''}\n data-resizable={resizable ? '' : undefined}\n data-enter-motion={enterMotion === 'slide' ? undefined : enterMotion}\n data-exit-motion={exitMotion === 'slide' ? undefined : exitMotion}\n style={style || undefined}\n slot={slot}\n >\n {withoutHeader ? null : (\n <header class=\"kui-dialog-surface__header\">\n {heading === undefined ? (\n <h2 class=\"kui-dialog-surface__title\">{label}</h2>\n ) : (\n <div class=\"kui-dialog-surface__title\">{heading}</div>\n )}\n <div class=\"kui-dialog-surface__header-actions\">\n {headerActions}\n <button\n type=\"button\"\n class=\"kui-dialog-surface__close\"\n aria-label={closeLabel}\n data-dialog-close=\"\"\n >\n <LucideIcon icon={X} name=\"x\" size=\"l\" />\n </button>\n </div>\n </header>\n )}\n {presentation === 'bottom-sheet' && resizable ? (\n <div\n class=\"kui-dialog-surface__sheet-handle\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n aria-label=\"Resize sheet\"\n tabindex={0}\n />\n ) : null}\n <div class=\"kui-dialog-surface__body\">{children}</div>\n {footer === undefined ? null : (\n <footer class=\"kui-dialog-surface__footer\">{footer}</footer>\n )}\n {/* Where kerfjs/overlay hosts a popover or tooltip opened inside the\n modal dialog, so it stays interactive above the inert page. */}\n <div data-kerf-overlay-host data-morph-skip style=\"display:contents\" />\n </dialog>\n );\n}\n\n/** Where a PopoverDialogSurface appears: the top layer, or in flow. */\nexport type PopoverDialogSurfacePresentation = 'overlay' | 'embedded';\n\n/** Application `data-*` metadata on the surface root. */\nexport type PopoverDialogSurfaceDataAttributes = Readonly<\n Record<`data-${string}`, string>\n>;\n\ntype PopoverDialogSurfaceName =\n { label: string; labelledBy?: never } | { label?: never; labelledBy: string };\n\nexport type PopoverDialogSurfaceProps = PopoverDialogSurfaceName & {\n /** The root id: what an opening control's `popovertarget` names. */\n id?: string;\n /**\n * Id of the element whose text is the dialog's accessible description,\n * such as a title `ToolbarText`'s `descriptionId`; rendered as\n * `aria-describedby` on the `role=\"dialog\"` root.\n */\n describedBy?: string;\n children: KerfUiContent;\n /**\n * `overlay` (default) is a native `popover=\"auto\"` in the top layer:\n * non-modal, light dismiss (Escape or a press outside), nothing inert.\n * `embedded` renders the same surface in flow for a catalog or inline use.\n */\n presentation?: PopoverDialogSurfacePresentation;\n /** Preferred width preset: 400px, 560px (default), or 800px. */\n size?: DialogSurfaceSize;\n /** Preferred width; takes precedence over `size`, within the viewport cap. */\n preferredWidth?: CssLength;\n /** Definite height, bounded by the dynamic viewport minus both gutters. */\n height?: DialogSurfaceHeight;\n /** Height cap, bounded the same way, for a surface that sizes to content. */\n maxHeight?: DialogSurfaceMaxHeight;\n /** Edge clearance on each side of the viewport (default 16px). */\n viewportGutter?: CssLength;\n /**\n * Body layout (default `flow`); `fill` lets one child own the surface and\n * `fill-last` stacks fixed rows above one filling last child.\n */\n bodyLayout?: DialogSurfaceBodyLayout;\n rootAttributes?: PopoverDialogSurfaceDataAttributes;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n};\n\nconst POPOVER_DIALOG_PROTECTED = new Set([\n 'data-component',\n 'data-presentation',\n 'data-size',\n 'data-height',\n 'data-max-height',\n 'data-body-layout',\n]);\n\n/**\n * A non-modal dialog surface on the native Popover API: Kerf's dialog chrome,\n * viewport-bounded size, and single-child fill without application CSS.\n * Open it with a `popovertarget` control or `showPopover()`; it light\n * dismisses and leaves the page interactive. Use `DialogSurface` when the\n * task must block the page.\n */\nexport function PopoverDialogSurface({\n id,\n children,\n label,\n labelledBy,\n describedBy,\n presentation = 'overlay',\n size = 'medium',\n preferredWidth,\n height,\n maxHeight,\n viewportGutter,\n bodyLayout = 'flow',\n rootAttributes = {},\n className = '',\n slot,\n}: PopoverDialogSurfaceProps) {\n const style = [\n preferredWidth === undefined\n ? ''\n : `--_kui-popover-dialog-surface-preferred-width:${preferredWidth}`,\n viewportGutter === undefined\n ? ''\n : `--_kui-popover-dialog-surface-gutter:${viewportGutter}`,\n height === undefined || height === 'viewport'\n ? ''\n : `--_kui-popover-dialog-surface-height:${height}`,\n maxHeight === undefined || maxHeight === 'viewport'\n ? ''\n : `--_kui-popover-dialog-surface-max-height:${maxHeight}`,\n ]\n .filter(Boolean)\n .join(';');\n return (\n <section\n {...filterDataAttributes(rootAttributes, POPOVER_DIALOG_PROTECTED)}\n id={id}\n class={`kui-popover-dialog-surface ${className}`.trim()}\n data-component=\"popover-dialog-surface\"\n data-presentation={presentation}\n data-size={size}\n data-height={height === undefined ? undefined : ''}\n data-max-height={maxHeight === undefined ? undefined : ''}\n data-body-layout={bodyLayout === 'flow' ? undefined : bodyLayout}\n popover={presentation === 'overlay' ? 'auto' : undefined}\n role=\"dialog\"\n aria-label={label}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n style={style || undefined}\n slot={slot}\n >\n {children}\n </section>\n );\n}\n\nexport type PopupSurfaceInset = 'standard' | 'compact' | 'list-zero';\n\nexport interface PopupSurfaceProps {\n children: KerfUiContent;\n inset?: PopupSurfaceInset;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** Configure recurring Web Awesome dropdown-menu geometry without consumer ::part() CSS. */\nexport function PopupSurface({\n children,\n inset = 'standard',\n className = '',\n slot,\n}: PopupSurfaceProps) {\n return (\n <span\n class={`kui-popup-surface ${className}`.trim()}\n data-component=\"popup-surface\"\n data-inset={inset}\n slot={slot}\n >\n {children}\n </span>\n );\n}\n"]}
@@ -52,4 +52,4 @@ function TabBar({
52
52
 
53
53
  export { TabBar };
54
54
 
55
- //# sourceMappingURL=chunk-RFLW4FPL.js.map
55
+ //# sourceMappingURL=chunk-7AK5I7U7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/navigation/tab-bar/tab-bar.tsx"],"names":[],"mappings":";;;AA6CO,SAAS,MAAA,CAAO;AAAA,EACrB,EAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,UAAA;AAAA,EACA,UAAA,GAAa,WAAA;AAAA,EACb,YAAA,GAAe,MAAA;AAAA,EACf,UAAA;AAAA,EACA,iBAAA,GAAoB,UAAA;AAAA,EACpB,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,EAAgB;AACd,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MACvC,gBAAA,EAAe,SAAA;AAAA,MACf,iBAAA,EAAiB,EAAA;AAAA,MACjB,qBAAA,EAAqB,UAAA;AAAA,MACrB,iBAAA,EAAiB,UAAA;AAAA,MACjB,mBAAA,EAAmB,YAAA;AAAA,MACnB,mBAAA,EAAmB,UAAA;AAAA,MACnB,yBAAA,EAAyB,iBAAA;AAAA,MACzB,YAAA,EAAY,KAAA;AAAA,MACZ,IAAA;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,sBAAA,EAAwB,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,wBACvD,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,mBAAA;AAAA,YACN,IAAA,EAAK,SAAA;AAAA,YACL,YAAA,EAAY,KAAA;AAAA,YACZ,mBAAA,EAAiB,IAAA;AAAA,YACjB,gBAAA,EAAgB,WAAW,MAAA,GAAS,MAAA;AAAA,YAEnC;AAAA;AAAA,SACH;AAAA,QACC,QAAA,oBAAY,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAyB,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,QACzD,GAAA,oBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,oBAAoB,QAAA,EAAA,GAAA,EAAI;AAAA;AAAA;AAAA,GAC7C;AAEJ","file":"chunk-7AK5I7U7.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\n\nexport type TabActivation = 'automatic' | 'manual';\nexport type TabBarAllocation = 'intrinsic' | 'fill';\nexport type TabBarPresentation = 'rail' | 'segmented' | 'inspector';\nexport type TabBarTrailingPlacement = 'separate' | 'adjacent';\n/** Tablist width where segmented TabBarItems switch to icon-only. */\nexport type TabBarIconOnlyAt = 'wide' | 'narrow' | 'compact';\n\nexport interface TabBarProps {\n id: string;\n label: string;\n children: KerfUiContent;\n leading?: KerfUiContent;\n /** Tab-local action: one ToolbarControlGroup, Kerf Button, or Web Awesome button. */\n trailing?: KerfUiContent;\n /**\n * Action pinned to the far edge of the bar. Combine with an adjacent `trailing`\n * action when the tab-local and workspace-level actions must remain distinct.\n * Accepts one ToolbarControlGroup, Kerf Button, or Web Awesome button.\n */\n end?: KerfUiContent;\n className?: string;\n /**\n * Keyboard activation mode for this strip, emitted as `data-tab-activation` for\n * `wireTabBars` to read (overrides its `activation` option). `'automatic'` (default)\n * selects on arrow / Home / End; `'manual'` moves roving focus only and the user\n * selects with Enter / Space / click — use it when selecting a tab is a heavy action.\n */\n activation?: TabActivation;\n /** How available strip width is allocated across child TabBarItems. */\n allocation?: TabBarAllocation;\n /** Named strip chrome for application rails, segmented tabs, or inspectors. */\n presentation?: TabBarPresentation;\n /** Switch segmented TabBarItems to icon-only at tablist widths of 832, 704, or 448px. Each tab needs a leading icon. */\n iconOnlyAt?: TabBarIconOnlyAt;\n /** Keep a trailing action beside the final tab or at the far edge of the bar. */\n trailingPlacement?: TabBarTrailingPlacement;\n /** Settle scrolling peers at whole-tab starts; wireTabBars measures a pinned leading tab's inset. */\n snapTabs?: boolean;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** Render a controlled tab strip. The application owns selection, order, and persistence. */\nexport function TabBar({\n id,\n label,\n children,\n leading,\n trailing,\n end,\n className = '',\n activation,\n allocation = 'intrinsic',\n presentation = 'rail',\n iconOnlyAt,\n trailingPlacement = 'separate',\n snapTabs = false,\n slot,\n}: TabBarProps) {\n return (\n <nav\n class={`kui-tab-bar ${className}`.trim()}\n data-component=\"tab-bar\"\n data-tab-bar-id={id}\n data-tab-activation={activation}\n data-allocation={allocation}\n data-presentation={presentation}\n data-icon-only-at={iconOnlyAt}\n data-trailing-placement={trailingPlacement}\n aria-label={label}\n slot={slot}\n >\n {leading && <div class=\"kui-tab-bar__leading\">{leading}</div>}\n <div\n class=\"kui-tab-bar__tabs\"\n role=\"tablist\"\n aria-label={label}\n data-kui-tab-list\n data-snap-tabs={snapTabs ? 'true' : undefined}\n >\n {children}\n </div>\n {trailing && <div class=\"kui-tab-bar__trailing\">{trailing}</div>}\n {end && <div class=\"kui-tab-bar__end\">{end}</div>}\n </nav>\n );\n}\n"]}
@@ -1,13 +1,13 @@
1
1
  import { WORKBENCH_MAIN_MIN_SIZE, WORKBENCH_MAIN_MIN_HEIGHT, workbenchRegionId, WORKBENCH_RESIZE_DEFAULTS } from './chunk-S4ZGTDSG.js';
2
- import { NavStack } from './chunk-Z4DS77U2.js';
2
+ import { NavStack } from './chunk-SOFPUW3O.js';
3
3
  import { clampRegionSize, ResizeGrip } from './chunk-Y6KT7ZTR.js';
4
4
  import { FloatingToolbar } from './chunk-S3ECMF23.js';
5
- import { panelToggleGroup, groupSizeFor, composedPanelBody, relocatedPanelGroups } from './chunk-DNWWF6UN.js';
5
+ import { panelToggleGroup, groupSizeFor, composedPanelBody, relocatedPanelGroups } from './chunk-WSEJ2FDE.js';
6
6
  import { paneConfigProps } from './chunk-CTQUDCY5.js';
7
- import { Toolbar } from './chunk-CMLPFIC5.js';
7
+ import { Toolbar } from './chunk-ZN7KUMPY.js';
8
8
  import { Pane } from './chunk-HQZG3OFL.js';
9
9
  import { ensureSunkenTexture } from './chunk-IKS72C6P.js';
10
- import { List } from './chunk-OY2MXIBB.js';
10
+ import { List } from './chunk-NB6POCFH.js';
11
11
  import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
12
12
 
13
13
  var SIDES = {
@@ -524,4 +524,4 @@ function Workbench({
524
524
 
525
525
  export { Workbench };
526
526
 
527
- //# sourceMappingURL=chunk-NLMEDZRM.js.map
527
+ //# sourceMappingURL=chunk-CPSGUGAY.js.map