@kerfjs/ui 5.0.0-beta.15 → 5.0.0-beta.17

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 (42) hide show
  1. package/README.md +3 -2
  2. package/ai/component-catalog.json +2 -1
  3. package/ai/public-api-signatures-v1.md +30 -3
  4. package/ai/skill.md +2 -2
  5. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  6. package/dist/catalog.d.ts +2 -0
  7. package/dist/catalog.js +6 -2
  8. package/dist/catalog.js.map +1 -1
  9. package/dist/{chunk-LCOBDOCC.js → chunk-6NLRBSVX.js} +32 -3
  10. package/dist/chunk-6NLRBSVX.js.map +1 -0
  11. package/dist/chunk-AHQI52QO.js +11 -0
  12. package/dist/chunk-AHQI52QO.js.map +1 -0
  13. package/dist/{chunk-BLK3UEEI.js → chunk-WRTAQ7BZ.js} +2 -2
  14. package/dist/{chunk-BLK3UEEI.js.map → chunk-WRTAQ7BZ.js.map} +1 -1
  15. package/dist/chunk-WXMGNX2Y.js +38 -0
  16. package/dist/chunk-WXMGNX2Y.js.map +1 -0
  17. package/dist/{chunk-XE5ZLPCC.js → chunk-ZQQ6P4SV.js} +2 -2
  18. package/dist/{chunk-XE5ZLPCC.js.map → chunk-ZQQ6P4SV.js.map} +1 -1
  19. package/dist/index.js +4 -4
  20. package/dist/list-inset-text.d.ts +10 -1
  21. package/dist/list-inset-text.js +1 -1
  22. package/dist/nav-stack.js +1 -1
  23. package/dist/panel-header.js +1 -1
  24. package/dist/split-view.js +1 -1
  25. package/dist/styles/catalog.css +22 -1
  26. package/dist/styles/list-inset-text.css +9 -0
  27. package/dist/styles/toolbar-text.css +54 -2
  28. package/dist/styles/webawesome.css +131 -0
  29. package/dist/toolbar-text.d.ts +17 -1
  30. package/dist/toolbar-text.js +1 -1
  31. package/dist/wire-token-search-fields.js +1 -1
  32. package/docs/catalog.md +4 -3
  33. package/docs/component-selection.md +6 -3
  34. package/docs/ux-demo.md +2 -2
  35. package/docs/webawesome-theme.md +65 -0
  36. package/llms.txt +16 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-LCOBDOCC.js.map +0 -1
  39. package/dist/chunk-RUNWEPR4.js +0 -10
  40. package/dist/chunk-RUNWEPR4.js.map +0 -1
  41. package/dist/chunk-XE4OX6AZ.js +0 -10
  42. package/dist/chunk-XE4OX6AZ.js.map +0 -1
package/README.md CHANGED
@@ -330,8 +330,9 @@ after browser input to recover text plus token offsets, and
330
330
  Call `wireTokenSearchFields()` once at a stable root to make Enter submit through
331
331
  `onSubmit` without inserting a contenteditable line break and to preserve focus
332
332
  plus the text-relative caret when keyboard deletion of a chip causes controlled
333
- rendering to replace the editor. Text still wraps visually when it reaches the
334
- field edge.
333
+ rendering to replace the editor. A select-all deletion is normalized to a truly
334
+ empty editor even when the browser leaves an atomic chip or line break behind.
335
+ Text still wraps visually when it reaches the field edge.
335
336
  Clear actions should empty the editor's `textContent` before clearing app state.
336
337
  The leading icon, first text line, clear action, and trailing slot share one
337
338
  fixed alignment row; when text wraps, those controls stay pinned to that first
@@ -1198,7 +1198,8 @@
1198
1198
  },
1199
1199
  "wiring": [],
1200
1200
  "publicClasses": [
1201
- "kui-list-inset-text"
1201
+ "kui-list-inset-text",
1202
+ "kui-list-inset-text--horizontal"
1202
1203
  ],
1203
1204
  "publicTokens": [],
1204
1205
  "links": {
@@ -1,6 +1,6 @@
1
1
  # Public API signatures for the UI authoring corpus
2
2
 
3
- Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.15` and `kerfjs@5.0.0-beta.15`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
3
+ Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.17` and `kerfjs@5.0.0-beta.17`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
4
4
 
5
5
  ## `@kerfjs/ui/disclosure-arrow`
6
6
 
@@ -61,8 +61,24 @@ interface ToolbarTextProps {
61
61
  headingLevel?: HeadingLevel;
62
62
  /** Render the text as an unanimated loading skeleton instead of its value. */
63
63
  placeholder?: boolean;
64
+ /**
65
+ * Wrap onto multiple lines when the text does not fit, instead of the default
66
+ * single line. Combine with `maxLines` to cap the number of lines. Default false.
67
+ */
68
+ wrap?: boolean;
69
+ /**
70
+ * Show a trailing ellipsis (…) where the text is truncated — on the single line
71
+ * (default), or at the `maxLines` boundary when wrapping. Set false to hard-clip
72
+ * instead. Default true.
73
+ */
74
+ ellipsis?: boolean;
75
+ /**
76
+ * Cap wrapped text to this many lines, truncating past it. Only takes effect with
77
+ * `wrap`; ignored on a single line. `null`/omitted wraps without a line cap. Default null.
78
+ */
79
+ maxLines?: number | null;
64
80
  }
65
- declare function ToolbarText({ text, size, className, id, headingLevel, placeholder }: ToolbarTextProps): kerfjs.SafeHtml;
81
+ declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, }: ToolbarTextProps): kerfjs.SafeHtml;
66
82
 
67
83
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
68
84
  ```
@@ -294,6 +310,13 @@ import { SafeHtml } from 'kerfjs';
294
310
  interface ListInsetTextProps {
295
311
  /** Text (or inline content) that carries no margin, border, or padding of its own. */
296
312
  children: SafeHtml | SafeHtml[] | string;
313
+ /**
314
+ * Keep only the horizontal geometry (inline margin, left/right border, and
315
+ * left/right padding) and drop the vertical margin, border, and padding. Use it
316
+ * when the text edge must still align with bordered items but the line should not
317
+ * add its own vertical box space — tight text layout inside a content region.
318
+ */
319
+ horizontalOnly?: boolean;
297
320
  className?: string;
298
321
  }
299
322
  /**
@@ -301,8 +324,10 @@ interface ListInsetTextProps {
301
324
  * transparent border, and 8px padding — so a plain string lines up with
302
325
  * bordered `.kui-content` items (its text edge lands at the same 17px inset).
303
326
  * Use it for text elements that have no margin, border, or padding of their own.
327
+ * Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box
328
+ * space for tight text layout.
304
329
  */
305
- declare function ListInsetText({ children, className }: ListInsetTextProps): SafeHtml;
330
+ declare function ListInsetText({ children, horizontalOnly, className }: ListInsetTextProps): SafeHtml;
306
331
 
307
332
  export { ListInsetText, type ListInsetTextProps };
308
333
  ```
@@ -925,6 +950,8 @@ interface CatalogEntry {
925
950
  id: string;
926
951
  name: string;
927
952
  description?: string;
953
+ /** Short metadata tags shown at the trailing edge of the sidebar row. */
954
+ tags?: readonly string[];
928
955
  resources?: readonly CatalogResource[];
929
956
  related?: readonly CatalogRelated[];
930
957
  }
package/ai/skill.md CHANGED
@@ -59,8 +59,8 @@ Hard rules:
59
59
  10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. Arrow/Home/End select on move by default; 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.
60
60
  11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. The app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, or a clear-button mousedown guard — the helper owns them. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
61
61
  12. Demo work uses public production component subpaths and their browser-selected CSS. 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. Project its 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.
62
- 13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes.
63
- 14. Treat the complete Web Awesome catalog as support coverage, not a recommendation list. Consider Popup when it replaces custom anchored positioning. Prefer Kerf `Select` over direct Dropdown/Dropdown Item/Select/Option composition, `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over Split Panel. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame.
62
+ 13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes. Its non-field chrome uses `--kui-wa-control-inset` (8px controls/items), `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside Accordion, Card, Details, Callout, and Include), and `--kui-wa-container-inset` (16px Tab Panel content); override those tiers instead of restyling individual parts. Checkbox and Radio Group option regions, the Color Picker trigger, and Slider's complete interactive region receive the shared 8px logical inline outer inset because those controls have no bordered field shell. Known Date field captions and bordered text-like field hints align with values at the 9px border-plus-padding inset. OTP Input's label uses the same uppercase xs/650 treatment as other field labels, and both its label and hint use that 9px inset.
63
+ 14. Treat the complete Web Awesome catalog as support coverage, not a recommendation list. Its UX sidebar marks superseded and exceptional entries `Discouraged`. Consider Popup when it replaces custom anchored positioning. Prefer Kerf `Select` over direct Dropdown/Dropdown Item/Select/Option composition, `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over Split Panel. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame.
64
64
  15. Build sidebars, main areas, inspectors, and dialogs from `@kerfjs/ui/layout.css`: an unpadded `.kui-pane`, optional `.kui-pane__toolbar`, one scrolling `.kui-pane__content`, and optional `.kui-pane__footer`. Add `.kui-content` for 24px major vertical separation and `.kui-content-item` for a child-owned 8px inline margin, 1px transparent-or-visible border, 8px padding, and 12px radius. Use the pill modifier for 22px. Do not pad pane shells or duplicate item geometry in wrappers.
65
65
  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.
66
66
  16. The only direct children of a `Toolbar` zone (`leading`/`center`/`trailing`) are `ToolbarText` (identity/title text) and `ToolbarControlGroup`; never drop bare buttons, inputs, links, or arbitrary markup straight into a zone. `SegmentedControl`, `Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live inside a `ToolbarControlGroup`. 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, chiefly a `wa-dropdown` popup trigger. A popup menu in a toolbar is a `single` `ToolbarControlGroup` wrapping a `wa-dropdown` whose `slot="trigger"` `wa-button` is the toolbar button and whose `wa-dropdown-item`s are the menu, with the dropdown kept under `data-morph-skip-children`. `PanelHeader` composes these for you as a panel/dialog/page heading. Wrap every toolbar item, including dormant text, in `ToolbarControlGroup`. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Split dormant and interactive regions: `ListHeader` fills the available inline width and keeps its label and mutually exclusive semantic count or non-count `badge` together, with an independent logical-end 44px action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-list-header-action-icon-size`; never shrink the target to match it. Pass every non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a number in `badge`. `ListItem.trailing` is dormant; use `ListActionRow` when primary and trailing actions need sibling 44px 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.
@@ -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.15` 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.17` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
4
4
 
5
5
  ```ts
6
6
  import { KerfCustomElement } from 'kerfjs/jsx-runtime';
package/dist/catalog.d.ts CHANGED
@@ -18,6 +18,8 @@ interface CatalogEntry {
18
18
  id: string;
19
19
  name: string;
20
20
  description?: string;
21
+ /** Short metadata tags shown at the trailing edge of the sidebar row. */
22
+ tags?: readonly string[];
21
23
  resources?: readonly CatalogResource[];
22
24
  related?: readonly CatalogRelated[];
23
25
  }
package/dist/catalog.js CHANGED
@@ -15,6 +15,10 @@ function findEntry(sections, id) {
15
15
  }
16
16
  return void 0;
17
17
  }
18
+ function catalogEntryTags(tags) {
19
+ if (!tags?.length) return void 0;
20
+ return /* @__PURE__ */ jsx("span", { class: "kui-catalog__tags", children: tags.map((tag) => /* @__PURE__ */ jsx("span", { class: "kui-catalog__tag", children: tag })) });
21
+ }
18
22
  function relatedMenuItems(related, selectAction) {
19
23
  const groups = [];
20
24
  for (const entry of related) if (!groups.includes(entry.group)) groups.push(entry.group);
@@ -70,13 +74,13 @@ function Catalog({
70
74
  /* @__PURE__ */ jsxs("nav", { class: "kui-pane__content kui-content", "aria-label": `${brand.title} components`, children: [
71
75
  sections.map((section) => /* @__PURE__ */ jsxs("section", { class: "kui-catalog__group", children: [
72
76
  /* @__PURE__ */ jsx(ListHeader, { label: section.category }),
73
- /* @__PURE__ */ jsx("div", { class: "kui-catalog__items", children: section.entries.map((entry) => /* @__PURE__ */ jsx(ListItem, { action: selectAction, itemId: entry.id, label: entry.name, selected: active === entry.id, title: entry.description, multiline: true })) })
77
+ /* @__PURE__ */ jsx("div", { class: "kui-catalog__items", children: section.entries.map((entry) => /* @__PURE__ */ jsx(ListItem, { action: selectAction, itemId: entry.id, label: entry.name, trailing: catalogEntryTags(entry.tags), selected: active === entry.id, title: entry.description, multiline: true })) })
74
78
  ] })),
75
79
  secondarySections ? /* @__PURE__ */ jsxs("section", { class: "kui-catalog__group kui-catalog__group--secondary", children: [
76
80
  /* @__PURE__ */ jsx(ListHeader, { label: secondarySections.label, toggle: secondarySections.collapsible, expanded: secondarySections.collapsible ? Boolean(secondarySections.expanded) : void 0, action: secondarySections.collapsible ? toggleSecondaryAction : void 0 }),
77
81
  !secondarySections.collapsible || secondarySections.expanded ? /* @__PURE__ */ jsx("div", { class: "kui-catalog__secondary", "data-catalog-secondary": true, children: secondarySections.sections.map((section) => /* @__PURE__ */ jsxs("section", { class: "kui-catalog__secondary-group", children: [
78
82
  /* @__PURE__ */ jsx("h3", { class: "kui-catalog__secondary-heading", children: section.category }),
79
- /* @__PURE__ */ jsx("div", { class: "kui-catalog__items", children: section.entries.map((entry) => /* @__PURE__ */ jsx(ListItem, { action: selectAction, itemId: entry.id, label: entry.name, selected: active === entry.id, title: entry.description, multiline: true })) })
83
+ /* @__PURE__ */ jsx("div", { class: "kui-catalog__items", children: section.entries.map((entry) => /* @__PURE__ */ jsx(ListItem, { action: selectAction, itemId: entry.id, label: entry.name, trailing: catalogEntryTags(entry.tags), selected: active === entry.id, title: entry.description, multiline: true })) })
80
84
  ] })) }) : /* @__PURE__ */ jsx(Fragment, {})
81
85
  ] }) : /* @__PURE__ */ jsx(Fragment, {}),
82
86
  sidebarFooter
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/catalog.tsx"],"names":[],"mappings":"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","file":"catalog.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport { ExternalLink, Moon, PanelLeftClose, PanelLeftOpen, Sun, Waypoints } from 'lucide';\n\nimport { ListHeader } from './list-header.js';\nimport { ListItem } from './list-item.js';\nimport { LucideIcon } from './lucide-icon.js';\nimport { Toolbar } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\n\n/** A reference link shown in the detail footer for the active entry. */\nexport interface CatalogResource {\n label: string;\n href: string;\n /** Optional monospace detail (e.g. a file path) shown after the label. */\n detail?: string;\n}\n\n/** A related entry offered in the detail footer's \"Related entries\" popup menu. */\nexport interface CatalogRelated {\n id: string;\n name: string;\n /** Group heading in the menu, e.g. \"Uses\" / \"Used by\". */\n group: string;\n}\n\nexport interface CatalogEntry {\n id: string;\n name: string;\n description?: string;\n resources?: readonly CatalogResource[];\n related?: readonly CatalogRelated[];\n}\n\nexport interface CatalogSection {\n category: string;\n entries: readonly CatalogEntry[];\n}\n\n/**\n * A secondary group of sections shown below the primary sidebar sections with a\n * quieter \"ecosystem\" treatment (e.g. third-party components). Optionally\n * collapsible — the app owns `expanded` and toggles it from `wireCatalog`'s\n * `onToggleSecondary`.\n */\nexport interface CatalogSecondaryGroup {\n label: string;\n sections: readonly CatalogSection[];\n /** When true, the group's label is a disclosure toggle controlling `expanded`. */\n collapsible?: boolean;\n /** Whether the group is expanded (controlled). Ignored unless `collapsible`. */\n expanded?: boolean;\n}\n\nexport interface CatalogBrand {\n title: string;\n subtitle?: string;\n /** Logo image URL (rendered decorative). Omit for a text-only brand. */\n logoUrl?: string;\n}\n\nexport interface CatalogProps {\n brand: CatalogBrand;\n sections: readonly CatalogSection[];\n /** The controlled active entry id — the app owns this signal. */\n active: string;\n /** The rendered preview for the active entry; the app computes it from `active`. */\n content: SafeHtml;\n /** Whether the sidebar is collapsed (controlled). */\n collapsed?: boolean;\n /** Current theme; when set, a theme toggle is shown that switches to the opposite. Omit to hide it. */\n theme?: 'light' | 'dark';\n /** Extra header controls placed before the theme toggle (each a `ToolbarControlGroup`). */\n headerActions?: SafeHtml;\n /** A secondary \"ecosystem\" group of sections below the primary category groups. */\n secondarySections?: CatalogSecondaryGroup;\n /** Extra sidebar content below the category groups (and the secondary group). */\n sidebarFooter?: SafeHtml;\n /** Status line content shown at the start of the detail footer. */\n status?: SafeHtml;\n selectAction?: string;\n toggleSidebarAction?: string;\n toggleThemeAction?: string;\n /** Action fired by the secondary group's disclosure toggle (when collapsible). */\n toggleSecondaryAction?: string;\n className?: string;\n}\n\nfunction findEntry(sections: readonly CatalogSection[], id: string): CatalogEntry | undefined {\n for (const section of sections) {\n for (const entry of section.entries) if (entry.id === id) return entry;\n }\n return undefined;\n}\n\n/**\n * Render the related entries as a `wa-dropdown` popup-menu body: a heading per\n * `group` (first-seen order) followed by that group's entries, each a navigable\n * item carrying the same `selectAction` the sidebar items use, so a chosen entry\n * routes through the one `wireCatalog` select handler.\n */\nfunction relatedMenuItems(related: readonly CatalogRelated[], selectAction: string): SafeHtml[] {\n const groups: string[] = [];\n for (const entry of related) if (!groups.includes(entry.group)) groups.push(entry.group);\n const nodes: SafeHtml[] = [];\n groups.forEach((group, index) => {\n if (index > 0) nodes.push(<wa-divider></wa-divider>);\n nodes.push(<small class=\"kui-catalog__related-heading\">{group}</small>);\n for (const entry of related) {\n if (entry.group === group) nodes.push(<wa-dropdown-item data-action={selectAction} data-item-id={entry.id}>{entry.name}</wa-dropdown-item>);\n }\n });\n return nodes;\n}\n\n/**\n * A reusable component-catalog shell: a collapsible category sidebar, a titled\n * detail stage that renders the active entry's preview, and a footer with\n * reference links and a related-entry popup menu. Built entirely from public\n * `@kerfjs/ui` primitives. Controlled and stateless — the app owns the `active`,\n * `collapsed`, and `theme` signals and computes `content` from `active` in its own\n * render; wire the sidebar/collapse/theme actions with `wireCatalog`.\n */\nexport function Catalog({\n brand,\n sections,\n active,\n content,\n collapsed = false,\n theme,\n headerActions,\n secondarySections,\n sidebarFooter,\n status,\n selectAction = 'catalog-select',\n toggleSidebarAction = 'catalog-toggle-sidebar',\n toggleThemeAction = 'catalog-toggle-theme',\n toggleSecondaryAction = 'catalog-toggle-secondary',\n className = '',\n}: CatalogProps) {\n const selected = findEntry(sections, active) ?? (secondarySections ? findEntry(secondarySections.sections, active) : undefined);\n const name = selected?.name ?? '';\n const nextTheme = theme === 'dark' ? 'light' : 'dark';\n const resources = selected?.resources ?? [];\n const related = selected?.related ?? [];\n\n return <main class={`kui-catalog ${className}`.trim()} data-component=\"catalog\" data-sidebar-collapsed={String(collapsed)}>\n <aside class=\"kui-catalog__sidebar kui-pane\" aria-label={`${brand.title} catalog`}>\n <header class=\"kui-catalog__brand kui-pane__toolbar\">\n <Toolbar\n label={`${brand.title} catalog header`}\n divider={false}\n leading={<ToolbarControlGroup appearance=\"borderless\" className=\"kui-catalog__identity\">{brand.logoUrl ? <img class=\"kui-catalog__mark\" src={brand.logoUrl} alt=\"\" /> : <></>}<h1>{brand.title}</h1></ToolbarControlGroup>}\n trailing={<ToolbarControlGroup appearance=\"borderless\" single><button type=\"button\" data-action={toggleSidebarAction} aria-label={`Collapse ${brand.title} catalog`}><LucideIcon icon={PanelLeftClose} name=\"panel-left-close\" /></button></ToolbarControlGroup>}\n />\n {brand.subtitle ? <p class=\"kui-catalog__subtitle\">{brand.subtitle}</p> : <></>}\n </header>\n <nav class=\"kui-pane__content kui-content\" aria-label={`${brand.title} components`}>\n {sections.map((section) => <section class=\"kui-catalog__group\">\n <ListHeader label={section.category} />\n <div class=\"kui-catalog__items\">\n {section.entries.map((entry) => <ListItem action={selectAction} itemId={entry.id} label={entry.name} selected={active === entry.id} title={entry.description} multiline />)}\n </div>\n </section>)}\n {secondarySections ? <section class=\"kui-catalog__group kui-catalog__group--secondary\">\n <ListHeader label={secondarySections.label} toggle={secondarySections.collapsible} expanded={secondarySections.collapsible ? Boolean(secondarySections.expanded) : undefined} action={secondarySections.collapsible ? toggleSecondaryAction : undefined} />\n {!secondarySections.collapsible || secondarySections.expanded\n ? <div class=\"kui-catalog__secondary\" data-catalog-secondary>\n {secondarySections.sections.map((section) => <section class=\"kui-catalog__secondary-group\">\n <h3 class=\"kui-catalog__secondary-heading\">{section.category}</h3>\n <div class=\"kui-catalog__items\">\n {section.entries.map((entry) => <ListItem action={selectAction} itemId={entry.id} label={entry.name} selected={active === entry.id} title={entry.description} multiline />)}\n </div>\n </section>)}\n </div>\n : <></>}\n </section> : <></>}\n {sidebarFooter}\n </nav>\n </aside>\n <article class=\"kui-catalog__detail kui-pane\">\n <header class=\"kui-catalog__header kui-pane__toolbar\">\n <Toolbar\n label={`${name} header`}\n divider={false}\n leading={<>{collapsed ? <ToolbarControlGroup appearance=\"borderless\" single><button type=\"button\" data-action={toggleSidebarAction} aria-label={`Expand ${brand.title} catalog`}><LucideIcon icon={PanelLeftOpen} name=\"panel-left-open\" /></button></ToolbarControlGroup> : <></>}<ToolbarControlGroup appearance=\"borderless\" className=\"kui-catalog__title\"><h2>{name}</h2></ToolbarControlGroup></>}\n trailing={<div class=\"kui-catalog__header-actions\">{headerActions}{theme ? <ToolbarControlGroup className=\"kui-catalog__settings\" label=\"Catalog display\"><button type=\"button\" data-action={toggleThemeAction} aria-label={`Use ${nextTheme} theme`} data-theme-preview={theme}>{nextTheme === 'dark' ? <LucideIcon icon={Moon} name=\"moon\" /> : <LucideIcon icon={Sun} name=\"sun\" />}<span>{nextTheme === 'dark' ? 'Dark' : 'Light'}</span></button></ToolbarControlGroup> : <></>}</div>}\n />\n {selected?.description ? <p class=\"kui-catalog__description kui-content-item\">{selected.description}</p> : <></>}\n </header>\n <section class=\"kui-catalog__stage kui-pane__content\" aria-label={`${name} preview`}>\n <div class=\"kui-catalog__canvas\">{content}</div>\n </section>\n <footer class=\"kui-catalog__footer kui-pane__footer\">\n {status ? <div class=\"kui-catalog__status\">{status}</div> : <></>}\n <Toolbar\n label={`${name} resources`}\n divider={false}\n leading={resources.length > 0\n ? <nav class=\"kui-catalog__resources\" aria-label={`${name} resources`}><ToolbarControlGroup className=\"kui-catalog__resource-group\" label={`${name} resources`}>{resources.map((resource) => <a class=\"kui-catalog__resource\" href={resource.href} target=\"_blank\" rel=\"noopener noreferrer\" aria-label={`${name}: ${resource.label} (opens in new tab)`}><LucideIcon icon={ExternalLink} name=\"external-link\" /><span>{resource.label}</span>{resource.detail ? <code>{resource.detail}</code> : <></>}</a>)}</ToolbarControlGroup></nav>\n : <></>}\n trailing={related.length > 0\n ? <div class=\"kui-catalog__related\" data-catalog-related><ToolbarControlGroup single className=\"kui-catalog__related-group\" label=\"Related entries\"><wa-dropdown class=\"kui-catalog__related-menu\" placement=\"top-end\" data-key={`kui-catalog-related-${active}`} data-morph-skip-children><wa-button slot=\"trigger\" appearance=\"plain\" with-caret><span class=\"kui-catalog__related-trigger\"><LucideIcon icon={Waypoints} name=\"waypoints\" /><span class=\"kui-catalog__related-label\">Component</span></span></wa-button>{relatedMenuItems(related, selectAction)}</wa-dropdown></ToolbarControlGroup></div>\n : <></>}\n />\n </footer>\n </article>\n </main>;\n}\n\n/**\n * How a {@link CatalogExample}'s content aligns its visible left edge with the\n * example's `ListHeader` label (which sits 16px in — 8px title + 8px label):\n * - `'glyph'` — a bare glyph/text specimen with no inline geometry insets the full 16px.\n * - `'inline-control'` — a control that already carries ~8px of its own inline padding insets 8px so its content lands on the same line.\n * - `'none'` — a content-item / composition that owns its geometry and already aligns; no inset (default).\n */\nexport type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';\n\nexport interface CatalogExampleProps {\n /** The example's label, shown as a `ListHeader` above the specimen. Omit for a bare specimen. */\n label?: string;\n /** Optional explanatory note between the label and the specimen. */\n note?: SafeHtml | string;\n /** Alignment inset for the specimen — see {@link CatalogExampleAlign}. Default `'none'`. */\n align?: CatalogExampleAlign;\n className?: string;\n children?: SafeHtml | readonly SafeHtml[];\n}\n\n/**\n * One labeled example in a catalog preview: a `ListHeader` label, an optional\n * note, and the specimen. `align` insets the specimen so its visible left edge\n * lines up with the label text, encoding the catalog's alignment rules as a\n * first-class prop instead of per-demo CSS. The inset is published as the\n * `--kui-catalog-example-align` custom property so a debug overlay can exclude it\n * from a specimen's measured margin.\n */\nexport function CatalogExample({ label, note, align = 'none', className = '', children }: CatalogExampleProps) {\n return <section class={`kui-catalog-example ${className}`.trim()} data-catalog-example data-align={align}>\n {label !== undefined ? <ListHeader label={label} /> : <></>}\n {note !== undefined ? <p class=\"kui-catalog-example__note\">{note}</p> : <></>}\n {children}\n </section>;\n}\n\nexport interface CatalogExampleStackProps {\n /** Accessible label for the stack region. */\n label?: string;\n className?: string;\n children?: SafeHtml | readonly SafeHtml[];\n}\n\n/** A vertically-stacked group of {@link CatalogExample}s with the catalog's example rhythm. */\nexport function CatalogExampleStack({ label, className = '', children }: CatalogExampleStackProps) {\n return <div class={`kui-catalog-example-stack ${className}`.trim()} data-catalog-example-stack aria-label={label}>{children}</div>;\n}\n"]}
1
+ {"version":3,"sources":["../src/catalog.tsx"],"names":[],"mappings":"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","file":"catalog.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport { ExternalLink, Moon, PanelLeftClose, PanelLeftOpen, Sun, Waypoints } from 'lucide';\n\nimport { ListHeader } from './list-header.js';\nimport { ListItem } from './list-item.js';\nimport { LucideIcon } from './lucide-icon.js';\nimport { Toolbar } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\n\n/** A reference link shown in the detail footer for the active entry. */\nexport interface CatalogResource {\n label: string;\n href: string;\n /** Optional monospace detail (e.g. a file path) shown after the label. */\n detail?: string;\n}\n\n/** A related entry offered in the detail footer's \"Related entries\" popup menu. */\nexport interface CatalogRelated {\n id: string;\n name: string;\n /** Group heading in the menu, e.g. \"Uses\" / \"Used by\". */\n group: string;\n}\n\nexport interface CatalogEntry {\n id: string;\n name: string;\n description?: string;\n /** Short metadata tags shown at the trailing edge of the sidebar row. */\n tags?: readonly string[];\n resources?: readonly CatalogResource[];\n related?: readonly CatalogRelated[];\n}\n\nexport interface CatalogSection {\n category: string;\n entries: readonly CatalogEntry[];\n}\n\n/**\n * A secondary group of sections shown below the primary sidebar sections with a\n * quieter \"ecosystem\" treatment (e.g. third-party components). Optionally\n * collapsible — the app owns `expanded` and toggles it from `wireCatalog`'s\n * `onToggleSecondary`.\n */\nexport interface CatalogSecondaryGroup {\n label: string;\n sections: readonly CatalogSection[];\n /** When true, the group's label is a disclosure toggle controlling `expanded`. */\n collapsible?: boolean;\n /** Whether the group is expanded (controlled). Ignored unless `collapsible`. */\n expanded?: boolean;\n}\n\nexport interface CatalogBrand {\n title: string;\n subtitle?: string;\n /** Logo image URL (rendered decorative). Omit for a text-only brand. */\n logoUrl?: string;\n}\n\nexport interface CatalogProps {\n brand: CatalogBrand;\n sections: readonly CatalogSection[];\n /** The controlled active entry id — the app owns this signal. */\n active: string;\n /** The rendered preview for the active entry; the app computes it from `active`. */\n content: SafeHtml;\n /** Whether the sidebar is collapsed (controlled). */\n collapsed?: boolean;\n /** Current theme; when set, a theme toggle is shown that switches to the opposite. Omit to hide it. */\n theme?: 'light' | 'dark';\n /** Extra header controls placed before the theme toggle (each a `ToolbarControlGroup`). */\n headerActions?: SafeHtml;\n /** A secondary \"ecosystem\" group of sections below the primary category groups. */\n secondarySections?: CatalogSecondaryGroup;\n /** Extra sidebar content below the category groups (and the secondary group). */\n sidebarFooter?: SafeHtml;\n /** Status line content shown at the start of the detail footer. */\n status?: SafeHtml;\n selectAction?: string;\n toggleSidebarAction?: string;\n toggleThemeAction?: string;\n /** Action fired by the secondary group's disclosure toggle (when collapsible). */\n toggleSecondaryAction?: string;\n className?: string;\n}\n\nfunction findEntry(sections: readonly CatalogSection[], id: string): CatalogEntry | undefined {\n for (const section of sections) {\n for (const entry of section.entries) if (entry.id === id) return entry;\n }\n return undefined;\n}\n\nfunction catalogEntryTags(tags: readonly string[] | undefined): SafeHtml | undefined {\n if (!tags?.length) return undefined;\n return <span class=\"kui-catalog__tags\">{tags.map((tag) => <span class=\"kui-catalog__tag\">{tag}</span>)}</span>;\n}\n\n/**\n * Render the related entries as a `wa-dropdown` popup-menu body: a heading per\n * `group` (first-seen order) followed by that group's entries, each a navigable\n * item carrying the same `selectAction` the sidebar items use, so a chosen entry\n * routes through the one `wireCatalog` select handler.\n */\nfunction relatedMenuItems(related: readonly CatalogRelated[], selectAction: string): SafeHtml[] {\n const groups: string[] = [];\n for (const entry of related) if (!groups.includes(entry.group)) groups.push(entry.group);\n const nodes: SafeHtml[] = [];\n groups.forEach((group, index) => {\n if (index > 0) nodes.push(<wa-divider></wa-divider>);\n nodes.push(<small class=\"kui-catalog__related-heading\">{group}</small>);\n for (const entry of related) {\n if (entry.group === group) nodes.push(<wa-dropdown-item data-action={selectAction} data-item-id={entry.id}>{entry.name}</wa-dropdown-item>);\n }\n });\n return nodes;\n}\n\n/**\n * A reusable component-catalog shell: a collapsible category sidebar, a titled\n * detail stage that renders the active entry's preview, and a footer with\n * reference links and a related-entry popup menu. Built entirely from public\n * `@kerfjs/ui` primitives. Controlled and stateless — the app owns the `active`,\n * `collapsed`, and `theme` signals and computes `content` from `active` in its own\n * render; wire the sidebar/collapse/theme actions with `wireCatalog`.\n */\nexport function Catalog({\n brand,\n sections,\n active,\n content,\n collapsed = false,\n theme,\n headerActions,\n secondarySections,\n sidebarFooter,\n status,\n selectAction = 'catalog-select',\n toggleSidebarAction = 'catalog-toggle-sidebar',\n toggleThemeAction = 'catalog-toggle-theme',\n toggleSecondaryAction = 'catalog-toggle-secondary',\n className = '',\n}: CatalogProps) {\n const selected = findEntry(sections, active) ?? (secondarySections ? findEntry(secondarySections.sections, active) : undefined);\n const name = selected?.name ?? '';\n const nextTheme = theme === 'dark' ? 'light' : 'dark';\n const resources = selected?.resources ?? [];\n const related = selected?.related ?? [];\n\n return <main class={`kui-catalog ${className}`.trim()} data-component=\"catalog\" data-sidebar-collapsed={String(collapsed)}>\n <aside class=\"kui-catalog__sidebar kui-pane\" aria-label={`${brand.title} catalog`}>\n <header class=\"kui-catalog__brand kui-pane__toolbar\">\n <Toolbar\n label={`${brand.title} catalog header`}\n divider={false}\n leading={<ToolbarControlGroup appearance=\"borderless\" className=\"kui-catalog__identity\">{brand.logoUrl ? <img class=\"kui-catalog__mark\" src={brand.logoUrl} alt=\"\" /> : <></>}<h1>{brand.title}</h1></ToolbarControlGroup>}\n trailing={<ToolbarControlGroup appearance=\"borderless\" single><button type=\"button\" data-action={toggleSidebarAction} aria-label={`Collapse ${brand.title} catalog`}><LucideIcon icon={PanelLeftClose} name=\"panel-left-close\" /></button></ToolbarControlGroup>}\n />\n {brand.subtitle ? <p class=\"kui-catalog__subtitle\">{brand.subtitle}</p> : <></>}\n </header>\n <nav class=\"kui-pane__content kui-content\" aria-label={`${brand.title} components`}>\n {sections.map((section) => <section class=\"kui-catalog__group\">\n <ListHeader label={section.category} />\n <div class=\"kui-catalog__items\">\n {section.entries.map((entry) => <ListItem action={selectAction} itemId={entry.id} label={entry.name} trailing={catalogEntryTags(entry.tags)} selected={active === entry.id} title={entry.description} multiline />)}\n </div>\n </section>)}\n {secondarySections ? <section class=\"kui-catalog__group kui-catalog__group--secondary\">\n <ListHeader label={secondarySections.label} toggle={secondarySections.collapsible} expanded={secondarySections.collapsible ? Boolean(secondarySections.expanded) : undefined} action={secondarySections.collapsible ? toggleSecondaryAction : undefined} />\n {!secondarySections.collapsible || secondarySections.expanded\n ? <div class=\"kui-catalog__secondary\" data-catalog-secondary>\n {secondarySections.sections.map((section) => <section class=\"kui-catalog__secondary-group\">\n <h3 class=\"kui-catalog__secondary-heading\">{section.category}</h3>\n <div class=\"kui-catalog__items\">\n {section.entries.map((entry) => <ListItem action={selectAction} itemId={entry.id} label={entry.name} trailing={catalogEntryTags(entry.tags)} selected={active === entry.id} title={entry.description} multiline />)}\n </div>\n </section>)}\n </div>\n : <></>}\n </section> : <></>}\n {sidebarFooter}\n </nav>\n </aside>\n <article class=\"kui-catalog__detail kui-pane\">\n <header class=\"kui-catalog__header kui-pane__toolbar\">\n <Toolbar\n label={`${name} header`}\n divider={false}\n leading={<>{collapsed ? <ToolbarControlGroup appearance=\"borderless\" single><button type=\"button\" data-action={toggleSidebarAction} aria-label={`Expand ${brand.title} catalog`}><LucideIcon icon={PanelLeftOpen} name=\"panel-left-open\" /></button></ToolbarControlGroup> : <></>}<ToolbarControlGroup appearance=\"borderless\" className=\"kui-catalog__title\"><h2>{name}</h2></ToolbarControlGroup></>}\n trailing={<div class=\"kui-catalog__header-actions\">{headerActions}{theme ? <ToolbarControlGroup className=\"kui-catalog__settings\" label=\"Catalog display\"><button type=\"button\" data-action={toggleThemeAction} aria-label={`Use ${nextTheme} theme`} data-theme-preview={theme}>{nextTheme === 'dark' ? <LucideIcon icon={Moon} name=\"moon\" /> : <LucideIcon icon={Sun} name=\"sun\" />}<span>{nextTheme === 'dark' ? 'Dark' : 'Light'}</span></button></ToolbarControlGroup> : <></>}</div>}\n />\n {selected?.description ? <p class=\"kui-catalog__description kui-content-item\">{selected.description}</p> : <></>}\n </header>\n <section class=\"kui-catalog__stage kui-pane__content\" aria-label={`${name} preview`}>\n <div class=\"kui-catalog__canvas\">{content}</div>\n </section>\n <footer class=\"kui-catalog__footer kui-pane__footer\">\n {status ? <div class=\"kui-catalog__status\">{status}</div> : <></>}\n <Toolbar\n label={`${name} resources`}\n divider={false}\n leading={resources.length > 0\n ? <nav class=\"kui-catalog__resources\" aria-label={`${name} resources`}><ToolbarControlGroup className=\"kui-catalog__resource-group\" label={`${name} resources`}>{resources.map((resource) => <a class=\"kui-catalog__resource\" href={resource.href} target=\"_blank\" rel=\"noopener noreferrer\" aria-label={`${name}: ${resource.label} (opens in new tab)`}><LucideIcon icon={ExternalLink} name=\"external-link\" /><span>{resource.label}</span>{resource.detail ? <code>{resource.detail}</code> : <></>}</a>)}</ToolbarControlGroup></nav>\n : <></>}\n trailing={related.length > 0\n ? <div class=\"kui-catalog__related\" data-catalog-related><ToolbarControlGroup single className=\"kui-catalog__related-group\" label=\"Related entries\"><wa-dropdown class=\"kui-catalog__related-menu\" placement=\"top-end\" data-key={`kui-catalog-related-${active}`} data-morph-skip-children><wa-button slot=\"trigger\" appearance=\"plain\" with-caret><span class=\"kui-catalog__related-trigger\"><LucideIcon icon={Waypoints} name=\"waypoints\" /><span class=\"kui-catalog__related-label\">Component</span></span></wa-button>{relatedMenuItems(related, selectAction)}</wa-dropdown></ToolbarControlGroup></div>\n : <></>}\n />\n </footer>\n </article>\n </main>;\n}\n\n/**\n * How a {@link CatalogExample}'s content aligns its visible left edge with the\n * example's `ListHeader` label (which sits 16px in — 8px title + 8px label):\n * - `'glyph'` — a bare glyph/text specimen with no inline geometry insets the full 16px.\n * - `'inline-control'` — a control that already carries ~8px of its own inline padding insets 8px so its content lands on the same line.\n * - `'none'` — a content-item / composition that owns its geometry and already aligns; no inset (default).\n */\nexport type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';\n\nexport interface CatalogExampleProps {\n /** The example's label, shown as a `ListHeader` above the specimen. Omit for a bare specimen. */\n label?: string;\n /** Optional explanatory note between the label and the specimen. */\n note?: SafeHtml | string;\n /** Alignment inset for the specimen — see {@link CatalogExampleAlign}. Default `'none'`. */\n align?: CatalogExampleAlign;\n className?: string;\n children?: SafeHtml | readonly SafeHtml[];\n}\n\n/**\n * One labeled example in a catalog preview: a `ListHeader` label, an optional\n * note, and the specimen. `align` insets the specimen so its visible left edge\n * lines up with the label text, encoding the catalog's alignment rules as a\n * first-class prop instead of per-demo CSS. The inset is published as the\n * `--kui-catalog-example-align` custom property so a debug overlay can exclude it\n * from a specimen's measured margin.\n */\nexport function CatalogExample({ label, note, align = 'none', className = '', children }: CatalogExampleProps) {\n return <section class={`kui-catalog-example ${className}`.trim()} data-catalog-example data-align={align}>\n {label !== undefined ? <ListHeader label={label} /> : <></>}\n {note !== undefined ? <p class=\"kui-catalog-example__note\">{note}</p> : <></>}\n {children}\n </section>;\n}\n\nexport interface CatalogExampleStackProps {\n /** Accessible label for the stack region. */\n label?: string;\n className?: string;\n children?: SafeHtml | readonly SafeHtml[];\n}\n\n/** A vertically-stacked group of {@link CatalogExample}s with the catalog's example rhythm. */\nexport function CatalogExampleStack({ label, className = '', children }: CatalogExampleStackProps) {\n return <div class={`kui-catalog-example-stack ${className}`.trim()} data-catalog-example-stack aria-label={label}>{children}</div>;\n}\n"]}
@@ -26,9 +26,36 @@ function editorIsEmpty(editor) {
26
26
  const value = readTokenSearchField(editor);
27
27
  return value.query.length === 0 && value.tokens.length === 0;
28
28
  }
29
+ function selectionCoversEditor(editor) {
30
+ const selected = editor.ownerDocument.getSelection().getRangeAt(0);
31
+ if (selected.collapsed || !editor.contains(selected.commonAncestorContainer)) return false;
32
+ const contents = editor.ownerDocument.createRange();
33
+ contents.selectNodeContents(editor);
34
+ const RangeCtor = editor.ownerDocument.defaultView.Range;
35
+ return selected.compareBoundaryPoints(RangeCtor.START_TO_START, contents) <= 0 && selected.compareBoundaryPoints(RangeCtor.END_TO_END, contents) >= 0;
36
+ }
29
37
  var TOKEN_SELECTOR = '[data-component="token-search-token"]';
30
38
  var TEXT_SELECTOR = "[data-token-search-text]";
31
39
  var stripZwsp = (text) => text.replaceAll("\u200B", "");
40
+ function normalizeEmptiedEditor(editor, selectedAll = false) {
41
+ const lineBreaks = editor.querySelectorAll("br");
42
+ if (lineBreaks.length === 0 && !selectedAll) return;
43
+ for (const lineBreak of lineBreaks) lineBreak.remove();
44
+ if (!selectedAll && editor.querySelector(TOKEN_SELECTOR)) return;
45
+ if (!selectedAll && stripZwsp(editor.textContent ?? "") !== "") return;
46
+ const doc = editor.ownerDocument;
47
+ const span = doc.createElement("span");
48
+ span.setAttribute("data-token-search-text", "");
49
+ span.setAttribute("data-empty", "true");
50
+ editor.replaceChildren(span);
51
+ if (doc.activeElement !== editor) return;
52
+ const selection = doc.getSelection();
53
+ const range = doc.createRange();
54
+ range.setStart(span, 0);
55
+ range.collapse(true);
56
+ selection.removeAllRanges();
57
+ selection.addRange(range);
58
+ }
32
59
  function collapsedCaret(editor) {
33
60
  const selection = editor.ownerDocument.getSelection();
34
61
  if (!selection || selection.rangeCount === 0) return;
@@ -149,18 +176,20 @@ function wireTokenSearchFields(root, { onSubmit, onEdit, collapsible = true, key
149
176
  pending.set(editor, {
150
177
  id,
151
178
  offset,
152
- tokenCount: editor.querySelectorAll('[data-component="token-search-token"]').length
179
+ tokenCount: editor.querySelectorAll('[data-component="token-search-token"]').length,
180
+ selectedAll: selectionCoversEditor(editor)
153
181
  });
154
182
  };
155
183
  const onInput = (event) => {
156
184
  const editor = editorFromEvent(root, event);
157
185
  if (!editor) return;
186
+ const deletion = pending.get(editor);
187
+ if (event.inputType?.startsWith("delete")) normalizeEmptiedEditor(editor, deletion?.selectedAll);
158
188
  if (onEdit) {
159
189
  const field = editor.closest('[data-component="token-search-field"]');
160
190
  const id = field?.dataset.tokenSearchId;
161
191
  if (id && field?.dataset.disabled !== "true") onEdit({ id, editor, event });
162
192
  }
163
- const deletion = pending.get(editor);
164
193
  pending.delete(editor);
165
194
  if (!deletion || editor.querySelectorAll('[data-component="token-search-token"]').length >= deletion.tokenCount) return;
166
195
  editor.ownerDocument.defaultView.requestAnimationFrame(() => {
@@ -262,4 +291,4 @@ function wireTokenSearchFields(root, { onSubmit, onEdit, collapsible = true, key
262
291
 
263
292
  export { wireTokenSearchFields };
264
293
 
265
- //# sourceMappingURL=chunk-LCOBDOCC.js.map
294
+ //# sourceMappingURL=chunk-6NLRBSVX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wire-token-search-fields.ts"],"names":["block"],"mappings":"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","file":"chunk-6NLRBSVX.js","sourcesContent":["import { delegate, type Signal,signal } from 'kerfjs';\n\nimport { placeTokenSearchCaret, readTokenSearchField } from './token-search-field.js';\n\nexport interface TokenSearchSubmit {\n id: string;\n editor: HTMLElement;\n}\n\n/** Reported to {@link WireTokenSearchFieldsOptions.onEdit} on every editor input. */\nexport interface TokenSearchEdit extends TokenSearchSubmit {\n /**\n * The `InputEvent` that mutated the editor — read `event.inputType` / `event.data`\n * to gate commit behavior (e.g. only parse a chip on whitespace-terminated input)\n * without keeping a separate `input` listener.\n */\n event: InputEvent;\n}\n\n/** Reported when adjacent-token keyboard deletion asks the app to drop a chip. */\nexport interface TokenSearchTokenRemoval {\n id: string;\n /** The `data-token-value` of the token the app should remove from its state. */\n value: string;\n editor: HTMLElement;\n /** `'backward'` = the token before the caret (Backspace); `'forward'` = after (Delete). */\n direction: 'backward' | 'forward';\n}\n\n/**\n * Opt-in keyboard behavior for the atomic token chips. Off unless `keyboard` is\n * set; each piece defaults on once opted in. The helper never mutates app state:\n * a removal is reported through {@link TokenSearchKeyboardOptions.onRemoveToken}\n * for the caller to apply, while caret movement past a chip is a pure ephemeral\n * mechanic the helper performs itself.\n */\nexport interface TokenSearchKeyboardOptions {\n /**\n * From a collapsed caret with no selection, Backspace removes the token\n * immediately before it and Delete the token immediately after — reported via\n * `onRemoveToken` — instead of deleting a character. Default: true.\n */\n removeAdjacentToken?: boolean;\n /**\n * ArrowRight moves the caret past a trailing atomic token so text typed next\n * lands after the chip. Default: true.\n */\n moveCaretPastToken?: boolean;\n /** Apply the reported removal to your controlled state, then re-render. */\n onRemoveToken?: (removal: TokenSearchTokenRemoval) => void;\n}\n\n/**\n * Managed collapsible behavior for the iconic TokenSearchField. Every piece is on\n * by default; disable a specific one to own it in the app. Provide `signals` to\n * drive app-owned `expanded` signals per field id instead of helper-created ones.\n */\nexport interface TokenSearchCollapsibleOptions {\n /** Expand the field and focus its editor when the iconic trigger is activated. Default: true. */\n expandOnActivate?: boolean;\n /** Collapse the field when focus leaves it while it is empty. Default: true. */\n collapseOnEmptyBlur?: boolean;\n /** Collapse an empty field on Escape and restore focus to its trigger. Default: true. */\n collapseOnEscape?: boolean;\n /** Focus the editor on expand and the trigger on Escape-collapse. Default: true. */\n manageFocus?: boolean;\n /**\n * Keep an empty field expanded when focus moves to a caller-owned surface\n * rendered outside the field — a suggestions dropdown, date picker, or help\n * popover shown beside it. Return true for any focus target that must NOT\n * trigger collapse-on-empty-blur. An element carrying `data-token-search-keep-open`\n * (or any node inside one) is always exempt, so this predicate is only needed\n * for surfaces you cannot mark declaratively.\n */\n keepOpenOn?: (target: Node | null) => boolean;\n /** App-owned `expanded` signals keyed by field id; adopted instead of helper-created. */\n signals?: Readonly<Record<string, Signal<boolean>>>;\n}\n\nexport interface WireTokenSearchFieldsOptions {\n onSubmit?: (submission: TokenSearchSubmit) => void;\n /** Fired on every editor `input`, after the browser mutates it, so a caller can drop its own `input` listener. */\n onEdit?: (edit: TokenSearchEdit) => void;\n /** Managed collapsible transient behavior. `true`/omitted = on with defaults; `false` = fully off. */\n collapsible?: boolean | TokenSearchCollapsibleOptions;\n /** Opt-in atomic-chip keyboard behavior (off by default). `true` = on with defaults. */\n keyboard?: boolean | TokenSearchKeyboardOptions;\n}\n\n/**\n * The value returned from {@link wireTokenSearchFields}: call it (or `dispose()`) to\n * tear down. When collapsible behavior is managed, it also exposes the transient\n * `expanded` state per field id so the app can read it in render, hand in its own\n * signal, or drive it imperatively.\n */\nexport interface TokenSearchFieldsHandle {\n (): void;\n dispose(): void;\n /** The managed `expanded` signal for a field id (adopted or helper-created); undefined when unmanaged. */\n expanded(id: string): Signal<boolean> | undefined;\n /** Expand the field (and, when focus is managed, focus its editor). */\n open(id: string): void;\n /** Collapse the field (and, when focus is managed, restore focus to its trigger). */\n close(id: string): void;\n}\n\ninterface PendingTokenDeletion {\n id: string;\n offset: number;\n tokenCount: number;\n selectedAll: boolean;\n}\n\nfunction editorFromEvent(root: HTMLElement, event: Event): HTMLElement | undefined {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const editor = target.closest<HTMLElement>('[data-token-search-editor]');\n return editor && root.contains(editor) ? editor : undefined;\n}\n\nfunction caretQueryOffset(editor: HTMLElement): number | undefined {\n const selection = editor.ownerDocument.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n const selectionRange = selection.getRangeAt(0);\n if (!editor.contains(selectionRange.startContainer)) return;\n const prefixRange = editor.ownerDocument.createRange();\n prefixRange.selectNodeContents(editor);\n prefixRange.setEnd(selectionRange.startContainer, selectionRange.startOffset);\n const prefix = editor.ownerDocument.createElement('div');\n prefix.append(prefixRange.cloneContents());\n return readTokenSearchField(prefix).query.length;\n}\n\nfunction replacementEditor(root: HTMLElement, id: string): HTMLElement | undefined {\n return [...root.querySelectorAll<HTMLElement>('[data-token-search-editor]')]\n .find((editor) => editor.dataset.tokenSearchEditor === id);\n}\n\nfunction editorIsEmpty(editor: HTMLElement): boolean {\n const value = readTokenSearchField(editor);\n return value.query.length === 0 && value.tokens.length === 0;\n}\n\n/** Whether the active selection covers every child of the editing host. */\nfunction selectionCoversEditor(editor: HTMLElement): boolean {\n // onBeforeInput calls this only after caretQueryOffset verified a live range.\n const selected = editor.ownerDocument.getSelection()!.getRangeAt(0);\n if (selected.collapsed || !editor.contains(selected.commonAncestorContainer)) return false;\n const contents = editor.ownerDocument.createRange();\n contents.selectNodeContents(editor);\n const RangeCtor = editor.ownerDocument.defaultView!.Range;\n return selected.compareBoundaryPoints(RangeCtor.START_TO_START, contents) <= 0\n && selected.compareBoundaryPoints(RangeCtor.END_TO_END, contents) >= 0;\n}\n\nconst TOKEN_SELECTOR = '[data-component=\"token-search-token\"]';\nconst TEXT_SELECTOR = '[data-token-search-text]';\nconst stripZwsp = (text: string): string => text.replaceAll('​', '');\n\n/**\n * A `contenteditable` host emptied by select-all + Delete (or Backspace) leaves a\n * bogus `<br>` in every engine: it renders as a stray newline and `readTokenSearchField`\n * reads it back as a space. Strip those line breaks after a delete, and when the field\n * is otherwise empty (no chips, no visible text) restore the canonical empty text span\n * and place the caret in it so typing resumes cleanly. Called only after the browser has\n * applied the delete, so an ordinary partial delete is never touched.\n */\nfunction normalizeEmptiedEditor(editor: HTMLElement, selectedAll = false): void {\n const lineBreaks = editor.querySelectorAll('br');\n if (lineBreaks.length === 0 && !selectedAll) return;\n for (const lineBreak of lineBreaks) lineBreak.remove();\n if (!selectedAll && editor.querySelector(TOKEN_SELECTOR)) return;\n if (!selectedAll && stripZwsp(editor.textContent ?? '') !== '') return;\n const doc = editor.ownerDocument;\n const span = doc.createElement('span');\n span.setAttribute('data-token-search-text', '');\n span.setAttribute('data-empty', 'true');\n editor.replaceChildren(span);\n if (doc.activeElement !== editor) return;\n // The editor is the focused, connected editing host, so a selection exists.\n const selection = doc.getSelection()!;\n const range = doc.createRange();\n range.setStart(span, 0);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n}\n\n/** The collapsed, in-editor caret range, or undefined when there is a selection or none. */\nfunction collapsedCaret(editor: HTMLElement): Range | undefined {\n const selection = editor.ownerDocument.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n const range = selection.getRangeAt(0);\n if (!range.collapsed || !editor.contains(range.startContainer)) return;\n return range;\n}\n\n/** The direct child of `editor` that contains `node` (or `node` itself), else null. */\nfunction topBlock(editor: HTMLElement, node: Node): Node | null {\n let current: Node = node;\n while (current.parentNode && current.parentNode !== editor) current = current.parentNode;\n return current.parentNode === editor ? current : null;\n}\n\n/** A text node or text span holding no visible character (only zero-width spacers). */\nfunction isBlankText(node: Node): boolean {\n if (node.nodeType === Node.TEXT_NODE) return stripZwsp((node as CharacterData).data) === '';\n return node instanceof Element && node.matches(TEXT_SELECTOR) && stripZwsp(node.textContent ?? '') === '';\n}\n\n/** The nearest sibling block on `direction`, skipping blank text spacers. */\nfunction meaningfulSibling(block: Node, direction: 'backward' | 'forward'): Node | null {\n let sibling = direction === 'backward' ? block.previousSibling : block.nextSibling;\n while (sibling && isBlankText(sibling)) sibling = direction === 'backward' ? sibling.previousSibling : sibling.nextSibling;\n return sibling;\n}\n\n/** The node immediately on `direction` of the caret, only when no visible character separates them. */\nfunction caretSideNode(editor: HTMLElement, range: Range, direction: 'backward' | 'forward'): Node | null {\n const { startContainer: container, startOffset: offset } = range;\n if (container.nodeType === Node.TEXT_NODE) {\n const text = (container as CharacterData).data;\n const side = direction === 'backward' ? text.slice(0, offset) : text.slice(offset);\n if (stripZwsp(side).length > 0) return null;\n // An in-editor text node always has a top block (itself or its wrapping span).\n return meaningfulSibling(topBlock(editor, container)!, direction);\n }\n const child = container.childNodes[direction === 'backward' ? offset - 1 : offset] as Node | undefined;\n if (child) {\n // `child` is a descendant of the in-editor caret container, so it has a top block.\n const block = topBlock(editor, child)!;\n return isBlankText(child) ? meaningfulSibling(block, direction) : block;\n }\n const block = topBlock(editor, container);\n return block ? meaningfulSibling(block, direction) : null;\n}\n\n/** The atomic token chip adjacent to a collapsed caret on `direction`, if any. */\nfunction adjacentToken(editor: HTMLElement, direction: 'backward' | 'forward'): HTMLElement | undefined {\n const range = collapsedCaret(editor);\n if (!range) return;\n const node = caretSideNode(editor, range, direction);\n if (!node) return;\n const base = node instanceof Element ? node : node.parentElement;\n const chip = base?.closest<HTMLElement>(TOKEN_SELECTOR) ?? null;\n return chip && editor.contains(chip) ? chip : undefined;\n}\n\n/** Move the caret to just after an atomic token chip so typed text lands after it.\n * Only reached after {@link collapsedCaret} already found a live selection, and the\n * chip is a direct block of the editor. */\nfunction placeCaretAfterToken(editor: HTMLElement, chip: HTMLElement): void {\n const selection = editor.ownerDocument.getSelection()!;\n const range = editor.ownerDocument.createRange();\n range.setStartAfter(topBlock(editor, chip)!);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n editor.focus({ preventScroll: true });\n}\n\n/**\n * Wire every TokenSearchField under `root`: submit on Enter, preserve the caret across\n * controlled token deletion, and (by default) manage the collapsible field's transient\n * expand/collapse/focus. Returns a {@link TokenSearchFieldsHandle} — a disposer that also\n * exposes the managed `expanded` state per field id.\n */\nexport function wireTokenSearchFields(\n root: HTMLElement,\n { onSubmit, onEdit, collapsible = true, keyboard = false }: WireTokenSearchFieldsOptions = {},\n): TokenSearchFieldsHandle {\n const managed = collapsible !== false;\n const config = typeof collapsible === 'object' ? collapsible : {};\n const expandOnActivate = managed && (config.expandOnActivate ?? true);\n const collapseOnEmptyBlur = managed && (config.collapseOnEmptyBlur ?? true);\n const collapseOnEscape = managed && (config.collapseOnEscape ?? true);\n const manageFocus = managed && (config.manageFocus ?? true);\n const keepOpenOn = config.keepOpenOn;\n const keyboardOn = keyboard !== false;\n const keyboardConfig = typeof keyboard === 'object' ? keyboard : {};\n const removeAdjacentToken = keyboardOn && (keyboardConfig.removeAdjacentToken ?? true);\n const moveCaretPastToken = keyboardOn && (keyboardConfig.moveCaretPastToken ?? true);\n const onRemoveToken = keyboardConfig.onRemoveToken;\n const adopted = config.signals ?? {};\n const created = new Map<string, Signal<boolean>>();\n\n /** True when focus moving to `element` should keep an empty field expanded. */\n const isExemptTarget = (element: Element | null): boolean => {\n if (!element) return false;\n if (element.closest('[data-token-search-keep-open]')) return true;\n return keepOpenOn ? keepOpenOn(element) : false;\n };\n\n const signalFor = (id: string): Signal<boolean> => {\n const own = adopted[id];\n if (own) return own;\n let field = created.get(id);\n if (!field) {\n field = signal(false);\n created.set(id, field);\n }\n return field;\n };\n const setExpanded = (id: string, next: boolean) => {\n const state = signalFor(id);\n if (state.value !== next) state.value = next;\n };\n const view = () => root.ownerDocument.defaultView!;\n const focusAfterRender = (id: string, selector: string) => {\n view().requestAnimationFrame(() => {\n const target = root.querySelector<HTMLElement>(\n `[data-component=\"token-search-field\"][data-token-search-id=\"${CSS.escape(id)}\"] ${selector}`,\n );\n if (!target) return;\n if (target.matches('[data-token-search-editor]')) placeTokenSearchCaret(target);\n else target.focus();\n });\n };\n const openField = (id: string) => {\n setExpanded(id, true);\n if (manageFocus) focusAfterRender(id, '[data-token-search-editor]');\n };\n const closeField = (id: string) => {\n setExpanded(id, false);\n if (manageFocus) focusAfterRender(id, '.kui-token-search__expand');\n };\n\n const pending = new WeakMap<HTMLElement, PendingTokenDeletion>();\n const onBeforeInput = (event: Event) => {\n const inputEvent = event as InputEvent;\n const editor = editorFromEvent(root, event);\n if (!editor || !inputEvent.inputType.startsWith('delete') || editor.ownerDocument.activeElement !== editor) return;\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n const offset = caretQueryOffset(editor);\n if (!id || offset === undefined || field?.dataset.disabled === 'true') return;\n pending.set(editor, {\n id,\n offset,\n tokenCount: editor.querySelectorAll('[data-component=\"token-search-token\"]').length,\n selectedAll: selectionCoversEditor(editor),\n });\n };\n const onInput = (event: Event) => {\n const editor = editorFromEvent(root, event);\n if (!editor) return;\n const deletion = pending.get(editor);\n if ((event as InputEvent).inputType?.startsWith('delete')) normalizeEmptiedEditor(editor, deletion?.selectedAll);\n if (onEdit) {\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (id && field?.dataset.disabled !== 'true') onEdit({ id, editor, event: event as InputEvent });\n }\n pending.delete(editor);\n if (!deletion || editor.querySelectorAll('[data-component=\"token-search-token\"]').length >= deletion.tokenCount) return;\n editor.ownerDocument.defaultView!.requestAnimationFrame(() => {\n const replacement = replacementEditor(root, deletion.id);\n if (!replacement) return;\n const active = replacement.ownerDocument.activeElement;\n if (active !== editor && active !== replacement && active !== replacement.ownerDocument.body) return;\n placeTokenSearchCaret(replacement, deletion.offset);\n });\n };\n root.addEventListener('beforeinput', onBeforeInput, true);\n root.addEventListener('input', onInput, true);\n\n const disposers: Array<() => void> = [\n () => root.removeEventListener('beforeinput', onBeforeInput, true),\n () => root.removeEventListener('input', onInput, true),\n ];\n\n disposers.push(\n delegate(root, 'keydown', '[data-token-search-editor]', (event, element) => {\n const keyboardEvent = event as KeyboardEvent;\n const editor = element as HTMLElement;\n if (keyboardEvent.isComposing) return;\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (!id || field?.dataset.disabled === 'true') return;\n if (keyboardEvent.key === 'Enter') {\n keyboardEvent.preventDefault();\n onSubmit?.({ id, editor });\n return;\n }\n if (removeAdjacentToken && (keyboardEvent.key === 'Backspace' || keyboardEvent.key === 'Delete')) {\n const direction = keyboardEvent.key === 'Backspace' ? 'backward' : 'forward';\n const chip = adjacentToken(editor, direction);\n if (chip) {\n keyboardEvent.preventDefault();\n onRemoveToken?.({ id, value: chip.dataset.tokenValue ?? '', editor, direction });\n return;\n }\n }\n if (moveCaretPastToken && keyboardEvent.key === 'ArrowRight') {\n const chip = adjacentToken(editor, 'forward');\n if (chip) {\n keyboardEvent.preventDefault();\n placeCaretAfterToken(editor, chip);\n return;\n }\n }\n if (collapseOnEscape && keyboardEvent.key === 'Escape' && field?.dataset.collapsible === 'true' && editorIsEmpty(editor)) {\n keyboardEvent.preventDefault();\n closeField(id);\n }\n }),\n );\n\n if (expandOnActivate) {\n disposers.push(\n delegate(root, 'click', '.kui-token-search__expand', (_event, element) => {\n // The selector guarantees a collapsible field ancestor; only skip a disabled one.\n const field = (element as HTMLElement).closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (id && field?.dataset.disabled !== 'true') openField(id);\n }),\n );\n }\n\n if (collapseOnEmptyBlur) {\n // Pressing an in-field control (clear, trailing, token, or the trigger) must not\n // blur the editor — otherwise the transient blur would collapse the field before\n // the control's own handler runs. Keeping focus also keeps the click firing.\n disposers.push(\n delegate(root, 'mousedown', '[data-component=\"token-search-field\"][data-collapsible=\"true\"] button', (event) => {\n event.preventDefault();\n }),\n );\n disposers.push(\n delegate(root, 'focusout', '[data-token-search-editor]', (event, element) => {\n const editor = element as HTMLElement;\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (!id || field?.dataset.collapsible !== 'true' || field.dataset.disabled === 'true') return;\n const next = (event as FocusEvent).relatedTarget;\n if (next instanceof Node && field.contains(next)) return;\n if (isExemptTarget(next instanceof Element ? next : null)) return;\n if (!editorIsEmpty(editor)) return;\n view().queueMicrotask(() => {\n const active = field.ownerDocument.activeElement;\n if (!field.contains(active) && !isExemptTarget(active)) setExpanded(id, false);\n });\n }),\n );\n }\n\n const dispose = () => {\n for (const stop of disposers.splice(0)) stop();\n };\n const handle = (() => dispose()) as TokenSearchFieldsHandle;\n handle.dispose = dispose;\n handle.expanded = (id) => (managed ? signalFor(id) : undefined);\n handle.open = (id) => {\n if (managed) openField(id);\n };\n handle.close = (id) => {\n if (managed) closeField(id);\n };\n return handle;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { jsx } from 'kerfjs/jsx-runtime';
2
+
3
+ // src/list-inset-text.tsx
4
+ function ListInsetText({ children, horizontalOnly = false, className = "" }) {
5
+ const cls = `kui-list-inset-text${horizontalOnly ? " kui-list-inset-text--horizontal" : ""} ${className}`.trim();
6
+ return /* @__PURE__ */ jsx("div", { class: cls, "data-component": "list-inset-text", children });
7
+ }
8
+
9
+ export { ListInsetText };
10
+
11
+ //# sourceMappingURL=chunk-AHQI52QO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/list-inset-text.tsx"],"names":[],"mappings":";;;AAuBO,SAAS,cAAc,EAAE,QAAA,EAAU,iBAAiB,KAAA,EAAO,SAAA,GAAY,IAAG,EAAuB;AACtG,EAAA,MAAM,GAAA,GAAM,sBAAsB,cAAA,GAAiB,kCAAA,GAAqC,EAAE,CAAA,CAAA,EAAI,SAAS,GAAG,IAAA,EAAK;AAC/G,EAAA,2BAAQ,KAAA,EAAA,EAAI,KAAA,EAAO,GAAA,EAAK,gBAAA,EAAe,mBAAmB,QAAA,EAAS,CAAA;AACrE","file":"chunk-AHQI52QO.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface ListInsetTextProps {\n /** Text (or inline content) that carries no margin, border, or padding of its own. */\n children: SafeHtml | SafeHtml[] | string;\n /**\n * Keep only the horizontal geometry (inline margin, left/right border, and\n * left/right padding) and drop the vertical margin, border, and padding. Use it\n * when the text edge must still align with bordered items but the line should not\n * add its own vertical box space — tight text layout inside a content region.\n */\n horizontalOnly?: boolean;\n className?: string;\n}\n\n/**\n * Gives bare text the content-item geometry — an 8px inline margin, a 1px\n * transparent border, and 8px padding — so a plain string lines up with\n * bordered `.kui-content` items (its text edge lands at the same 17px inset).\n * Use it for text elements that have no margin, border, or padding of their own.\n * Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box\n * space for tight text layout.\n */\nexport function ListInsetText({ children, horizontalOnly = false, className = '' }: ListInsetTextProps) {\n const cls = `kui-list-inset-text${horizontalOnly ? ' kui-list-inset-text--horizontal' : ''} ${className}`.trim();\n return <div class={cls} data-component=\"list-inset-text\">{children}</div>;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { ToolbarText } from './chunk-RUNWEPR4.js';
1
+ import { ToolbarText } from './chunk-WXMGNX2Y.js';
2
2
  import { jsxs, jsx } from 'kerfjs/jsx-runtime';
3
3
 
4
4
  function NavStack({ id, label, views, backLabel = "Back", hideToolbar = false, bottomToolbar, className = "" }) {
@@ -20,4 +20,4 @@ function NavStack({ id, label, views, backLabel = "Back", hideToolbar = false, b
20
20
 
21
21
  export { NavStack };
22
22
 
23
- //# sourceMappingURL=chunk-BLK3UEEI.js.map
23
+ //# sourceMappingURL=chunk-WRTAQ7BZ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/nav-stack.tsx"],"names":[],"mappings":";;;AAuCO,SAAS,QAAA,CAAS,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,SAAA,GAAY,MAAA,EAAQ,WAAA,GAAc,KAAA,EAAO,aAAA,EAAe,SAAA,GAAY,EAAA,EAAG,EAAkB;AACpI,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,GAAS,CAAA;AAChC,EAAA,MAAM,GAAA,GAAM,MAAM,QAAQ,CAAA;AAC1B,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,GAAS,CAAA;AAC9B,EAAA,4BAAQ,SAAA,EAAA,EAAQ,KAAA,EAAO,iBAAiB,SAAS,CAAA,CAAA,CAAG,MAAK,EAAG,EAAA,EAAQ,kBAAe,WAAA,EAAY,mBAAA,EAAmB,IAAI,YAAA,EAAY,MAAA,CAAO,MAAM,MAAM,CAAA,EAAG,cAAY,KAAA,EACjK,QAAA,EAAA;AAAA,IAAA,CAAC,+BAAe,IAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,uBAAA,EAAwB,yBAAqB,IAAA,EAC1E,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,OAAM,qBAAA,EACR,QAAA,EAAA;AAAA,QAAA,MAAA,wBAAW,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,KAAA,EAAM,uBAAsB,eAAA,EAAa,IAAA,EAAC,YAAA,EAAY,SAAA,EACrF,8BAAC,KAAA,EAAA,EAAI,KAAA,EAAM,0BAAA,EAA2B,OAAA,EAAQ,aAAY,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,eAAY,MAAA,EAAO,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,gBAAe,cAAA,EAAa,GAAA,EAAI,gBAAA,EAAe,OAAA,EAAQ,mBAAgB,OAAA,EAAQ,QAAA,kBAAA,GAAA,CAAC,UAAK,CAAA,EAAE,gBAAA,EAAiB,GAAE,CAAA,EACnO,CAAA;AAAA,wBACA,GAAA,CAAC,eAAY,IAAA,EAAM,GAAA,EAAK,SAAS,EAAA,EAAI,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,sBAAA,EAAuB;AAAA,OAAA,EACrF,CAAA;AAAA,MACC,KAAK,OAAA,oBAAW,GAAA,CAAC,SAAI,KAAA,EAAM,wBAAA,EAA0B,cAAI,OAAA,EAAQ;AAAA,KAAA,EACpE,CAAA;AAAA,oBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAA,EAA0B,2BAAuB,IAAA,EACzD,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,MAAM,KAAA,qBAAU,GAAA,CAAC,SAAA,EAAA,EAAQ,KAAA,EAAM,uBAAsB,UAAA,EAAU,IAAA,CAAK,GAAA,EAAK,cAAA,EAAc,IAAA,CAAK,GAAA,EAAK,iBAAA,EAAiB,MAAA,CAAO,UAAU,QAAQ,CAAA,EAAG,aAAA,EAAa,MAAA,CAAO,UAAU,QAAQ,CAAA,EAAI,QAAA,EAAA,IAAA,CAAK,OAAA,EAAQ,CAAU,CAAA,EAC7N,CAAA;AAAA,IACC,iCAAiB,GAAA,CAAC,QAAA,EAAA,EAAO,OAAM,uBAAA,EAAwB,uBAAA,EAAqB,MAAE,QAAA,EAAA,aAAA,EAAc;AAAA,GAAA,EAC/F,CAAA;AACF","file":"chunk-BLK3UEEI.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { ToolbarText } from './toolbar-text.js';\n\n/**\n * One entry in a {@link NavStack}. The app owns the stack as an array (usually a\n * signal); `NavStack` renders it and `wireNavStack` animates the transitions.\n */\nexport interface NavStackView {\n /** Stable identity for keyed reconcile and transition direction. */\n key: string;\n content: SafeHtml;\n /** Title shown in the top toolbar for this view. */\n title?: string;\n /** Trailing actions for this view's top toolbar. */\n toolbar?: SafeHtml;\n}\n\nexport interface NavStackProps {\n id: string;\n /** Accessible name for the stack region. */\n label: string;\n /** The stack, root first; the last entry is the active top view. */\n views: NavStackView[];\n /** Accessible label for the back control (default \"Back\"). */\n backLabel?: string;\n /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */\n hideToolbar?: boolean;\n /** Optional persistent bottom toolbar. */\n bottomToolbar?: SafeHtml;\n className?: string;\n}\n\n/**\n * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last\n * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and\n * cross-fades the chrome across a change. A single-pane layout is a `NavStack`\n * with one entry. See `docs/23-app-layouts.md` §3.1.\n */\nexport function NavStack({ id, label, views, backLabel = 'Back', hideToolbar = false, bottomToolbar, className = '' }: NavStackProps) {\n const topIndex = views.length - 1;\n const top = views[topIndex];\n const canPop = views.length > 1;\n return <section class={`kui-nav-stack ${className}`.trim()} id={id} data-component=\"nav-stack\" data-nav-stack-id={id} data-depth={String(views.length)} aria-label={label}>\n {!hideToolbar && <header class=\"kui-nav-stack__chrome\" data-nav-stack-chrome>\n <div class=\"kui-nav-stack__lead\">\n {canPop && <button type=\"button\" class=\"kui-nav-stack__back\" data-nav-back aria-label={backLabel}>\n <svg class=\"kui-nav-stack__back-icon\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m15 18-6-6 6-6\" /></svg>\n </button>}\n <ToolbarText text={top?.title ?? ''} size=\"large\" className=\"kui-nav-stack__title\" />\n </div>\n {top?.toolbar && <div class=\"kui-nav-stack__actions\">{top.toolbar}</div>}\n </header>}\n <div class=\"kui-nav-stack__viewport\" data-nav-stack-viewport>\n {views.map((view, index) => <article class=\"kui-nav-stack__view\" data-key={view.key} data-nav-key={view.key} data-nav-active={String(index === topIndex)} aria-hidden={String(index !== topIndex)}>{view.content}</article>)}\n </div>\n {bottomToolbar && <footer class=\"kui-nav-stack__bottom\" data-nav-stack-bottom>{bottomToolbar}</footer>}\n </section>;\n}\n"]}
1
+ {"version":3,"sources":["../src/nav-stack.tsx"],"names":[],"mappings":";;;AAuCO,SAAS,QAAA,CAAS,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,SAAA,GAAY,MAAA,EAAQ,WAAA,GAAc,KAAA,EAAO,aAAA,EAAe,SAAA,GAAY,EAAA,EAAG,EAAkB;AACpI,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,GAAS,CAAA;AAChC,EAAA,MAAM,GAAA,GAAM,MAAM,QAAQ,CAAA;AAC1B,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,GAAS,CAAA;AAC9B,EAAA,4BAAQ,SAAA,EAAA,EAAQ,KAAA,EAAO,iBAAiB,SAAS,CAAA,CAAA,CAAG,MAAK,EAAG,EAAA,EAAQ,kBAAe,WAAA,EAAY,mBAAA,EAAmB,IAAI,YAAA,EAAY,MAAA,CAAO,MAAM,MAAM,CAAA,EAAG,cAAY,KAAA,EACjK,QAAA,EAAA;AAAA,IAAA,CAAC,+BAAe,IAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,uBAAA,EAAwB,yBAAqB,IAAA,EAC1E,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,OAAM,qBAAA,EACR,QAAA,EAAA;AAAA,QAAA,MAAA,wBAAW,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,KAAA,EAAM,uBAAsB,eAAA,EAAa,IAAA,EAAC,YAAA,EAAY,SAAA,EACrF,8BAAC,KAAA,EAAA,EAAI,KAAA,EAAM,0BAAA,EAA2B,OAAA,EAAQ,aAAY,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,eAAY,MAAA,EAAO,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,gBAAe,cAAA,EAAa,GAAA,EAAI,gBAAA,EAAe,OAAA,EAAQ,mBAAgB,OAAA,EAAQ,QAAA,kBAAA,GAAA,CAAC,UAAK,CAAA,EAAE,gBAAA,EAAiB,GAAE,CAAA,EACnO,CAAA;AAAA,wBACA,GAAA,CAAC,eAAY,IAAA,EAAM,GAAA,EAAK,SAAS,EAAA,EAAI,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,sBAAA,EAAuB;AAAA,OAAA,EACrF,CAAA;AAAA,MACC,KAAK,OAAA,oBAAW,GAAA,CAAC,SAAI,KAAA,EAAM,wBAAA,EAA0B,cAAI,OAAA,EAAQ;AAAA,KAAA,EACpE,CAAA;AAAA,oBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAA,EAA0B,2BAAuB,IAAA,EACzD,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,MAAM,KAAA,qBAAU,GAAA,CAAC,SAAA,EAAA,EAAQ,KAAA,EAAM,uBAAsB,UAAA,EAAU,IAAA,CAAK,GAAA,EAAK,cAAA,EAAc,IAAA,CAAK,GAAA,EAAK,iBAAA,EAAiB,MAAA,CAAO,UAAU,QAAQ,CAAA,EAAG,aAAA,EAAa,MAAA,CAAO,UAAU,QAAQ,CAAA,EAAI,QAAA,EAAA,IAAA,CAAK,OAAA,EAAQ,CAAU,CAAA,EAC7N,CAAA;AAAA,IACC,iCAAiB,GAAA,CAAC,QAAA,EAAA,EAAO,OAAM,uBAAA,EAAwB,uBAAA,EAAqB,MAAE,QAAA,EAAA,aAAA,EAAc;AAAA,GAAA,EAC/F,CAAA;AACF","file":"chunk-WRTAQ7BZ.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { ToolbarText } from './toolbar-text.js';\n\n/**\n * One entry in a {@link NavStack}. The app owns the stack as an array (usually a\n * signal); `NavStack` renders it and `wireNavStack` animates the transitions.\n */\nexport interface NavStackView {\n /** Stable identity for keyed reconcile and transition direction. */\n key: string;\n content: SafeHtml;\n /** Title shown in the top toolbar for this view. */\n title?: string;\n /** Trailing actions for this view's top toolbar. */\n toolbar?: SafeHtml;\n}\n\nexport interface NavStackProps {\n id: string;\n /** Accessible name for the stack region. */\n label: string;\n /** The stack, root first; the last entry is the active top view. */\n views: NavStackView[];\n /** Accessible label for the back control (default \"Back\"). */\n backLabel?: string;\n /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */\n hideToolbar?: boolean;\n /** Optional persistent bottom toolbar. */\n bottomToolbar?: SafeHtml;\n className?: string;\n}\n\n/**\n * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last\n * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and\n * cross-fades the chrome across a change. A single-pane layout is a `NavStack`\n * with one entry. See `docs/23-app-layouts.md` §3.1.\n */\nexport function NavStack({ id, label, views, backLabel = 'Back', hideToolbar = false, bottomToolbar, className = '' }: NavStackProps) {\n const topIndex = views.length - 1;\n const top = views[topIndex];\n const canPop = views.length > 1;\n return <section class={`kui-nav-stack ${className}`.trim()} id={id} data-component=\"nav-stack\" data-nav-stack-id={id} data-depth={String(views.length)} aria-label={label}>\n {!hideToolbar && <header class=\"kui-nav-stack__chrome\" data-nav-stack-chrome>\n <div class=\"kui-nav-stack__lead\">\n {canPop && <button type=\"button\" class=\"kui-nav-stack__back\" data-nav-back aria-label={backLabel}>\n <svg class=\"kui-nav-stack__back-icon\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m15 18-6-6 6-6\" /></svg>\n </button>}\n <ToolbarText text={top?.title ?? ''} size=\"large\" className=\"kui-nav-stack__title\" />\n </div>\n {top?.toolbar && <div class=\"kui-nav-stack__actions\">{top.toolbar}</div>}\n </header>}\n <div class=\"kui-nav-stack__viewport\" data-nav-stack-viewport>\n {views.map((view, index) => <article class=\"kui-nav-stack__view\" data-key={view.key} data-nav-key={view.key} data-nav-active={String(index === topIndex)} aria-hidden={String(index !== topIndex)}>{view.content}</article>)}\n </div>\n {bottomToolbar && <footer class=\"kui-nav-stack__bottom\" data-nav-stack-bottom>{bottomToolbar}</footer>}\n </section>;\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { Skeleton } from './chunk-B24C4A6T.js';
2
+ import { jsx } from 'kerfjs/jsx-runtime';
3
+
4
+ function ToolbarText({
5
+ text,
6
+ size = "default",
7
+ className = "",
8
+ id,
9
+ headingLevel,
10
+ placeholder = false,
11
+ wrap = false,
12
+ ellipsis = true,
13
+ maxLines = null
14
+ }) {
15
+ const capped = wrap && maxLines != null && maxLines > 0;
16
+ return /* @__PURE__ */ jsx(
17
+ "span",
18
+ {
19
+ class: `kui-toolbar-text ${className}`.trim(),
20
+ "data-component": "toolbar-text",
21
+ "data-size": size,
22
+ "data-wrap": wrap ? "true" : void 0,
23
+ "data-ellipsis": ellipsis ? void 0 : "false",
24
+ "data-max-lines": capped ? String(maxLines) : void 0,
25
+ style: capped ? `--kui-toolbar-text-max-lines:${maxLines}` : void 0,
26
+ "data-placeholder": placeholder ? "true" : void 0,
27
+ id,
28
+ role: headingLevel ? "heading" : void 0,
29
+ "aria-level": headingLevel ? String(headingLevel) : void 0,
30
+ "aria-busy": placeholder ? "true" : void 0,
31
+ children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "8em" }) : /* @__PURE__ */ jsx("span", { class: "kui-toolbar-text__text", children: text })
32
+ }
33
+ );
34
+ }
35
+
36
+ export { ToolbarText };
37
+
38
+ //# sourceMappingURL=chunk-WXMGNX2Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/toolbar-text.tsx"],"names":[],"mappings":";;;AAuCO,SAAS,WAAA,CAAY;AAAA,EAC1B,IAAA;AAAA,EACA,IAAA,GAAO,SAAA;AAAA,EACP,SAAA,GAAY,EAAA;AAAA,EACZ,EAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA,GAAc,KAAA;AAAA,EACd,IAAA,GAAO,KAAA;AAAA,EACP,QAAA,GAAW,IAAA;AAAA,EACX,QAAA,GAAW;AACb,CAAA,EAAqB;AACnB,EAAA,MAAM,MAAA,GAAS,IAAA,IAAQ,QAAA,IAAY,IAAA,IAAQ,QAAA,GAAW,CAAA;AACtD,EAAA,uBAAO,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACN,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC5C,gBAAA,EAAe,cAAA;AAAA,MACf,WAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAW,OAAO,MAAA,GAAS,MAAA;AAAA,MAC3B,eAAA,EAAe,WAAW,MAAA,GAAY,OAAA;AAAA,MACtC,gBAAA,EAAgB,MAAA,GAAS,MAAA,CAAO,QAAQ,CAAA,GAAI,MAAA;AAAA,MAC5C,KAAA,EAAO,MAAA,GAAS,CAAA,6BAAA,EAAgC,QAAQ,CAAA,CAAA,GAAK,MAAA;AAAA,MAC7D,kBAAA,EAAkB,cAAc,MAAA,GAAS,MAAA;AAAA,MACzC,EAAA;AAAA,MACA,IAAA,EAAM,eAAe,SAAA,GAAY,MAAA;AAAA,MACjC,YAAA,EAAY,YAAA,GAAe,MAAA,CAAO,YAAY,CAAA,GAAI,MAAA;AAAA,MAClD,WAAA,EAAW,cAAc,MAAA,GAAS,MAAA;AAAA,MAClC,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,KAAA,EAAM,oBAAK,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,wBAAA,EAA0B,QAAA,EAAA,IAAA,EAAK;AAAA;AAAA,GAAQ;AAChG","file":"chunk-WXMGNX2Y.js","sourcesContent":["import { Skeleton } from './skeleton.js';\n\nexport type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small';\n\n/** ARIA heading level for a title exposed as a heading landmark. */\nexport type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\nexport interface ToolbarTextProps {\n text: string;\n size?: ToolbarTextSize;\n className?: string;\n /** Optional id, e.g. so a dialog can reference the title via aria-labelledby. */\n id?: string;\n /**\n * Expose heading semantics (`role=\"heading\"` + `aria-level`) so the text acts as\n * a heading landmark — e.g. a page's primary title. Omit to keep the plain span\n * (the default), which suits a dialog title referenced via `aria-labelledby`.\n */\n headingLevel?: HeadingLevel;\n /** Render the text as an unanimated loading skeleton instead of its value. */\n placeholder?: boolean;\n /**\n * Wrap onto multiple lines when the text does not fit, instead of the default\n * single line. Combine with `maxLines` to cap the number of lines. Default false.\n */\n wrap?: boolean;\n /**\n * Show a trailing ellipsis (…) where the text is truncated — on the single line\n * (default), or at the `maxLines` boundary when wrapping. Set false to hard-clip\n * instead. Default true.\n */\n ellipsis?: boolean;\n /**\n * Cap wrapped text to this many lines, truncating past it. Only takes effect with\n * `wrap`; ignored on a single line. `null`/omitted wraps without a line cap. Default null.\n */\n maxLines?: number | null;\n}\n\nexport function ToolbarText({\n text,\n size = 'default',\n className = '',\n id,\n headingLevel,\n placeholder = false,\n wrap = false,\n ellipsis = true,\n maxLines = null,\n}: ToolbarTextProps) {\n const capped = wrap && maxLines != null && maxLines > 0;\n return <span\n class={`kui-toolbar-text ${className}`.trim()}\n data-component=\"toolbar-text\"\n data-size={size}\n data-wrap={wrap ? 'true' : undefined}\n data-ellipsis={ellipsis ? undefined : 'false'}\n data-max-lines={capped ? String(maxLines) : undefined}\n style={capped ? `--kui-toolbar-text-max-lines:${maxLines}` : undefined}\n data-placeholder={placeholder ? 'true' : undefined}\n id={id}\n role={headingLevel ? 'heading' : undefined}\n aria-level={headingLevel ? String(headingLevel) : undefined}\n aria-busy={placeholder ? 'true' : undefined}\n >{placeholder ? <Skeleton width=\"8em\" /> : <span class=\"kui-toolbar-text__text\">{text}</span>}</span>;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { ToolbarText } from './chunk-RUNWEPR4.js';
1
+ import { ToolbarText } from './chunk-WXMGNX2Y.js';
2
2
  import { ToolbarControlGroup } from './chunk-RNPGFQ33.js';
3
3
  import { Toolbar } from './chunk-DAFFDO33.js';
4
4
  import { Skeleton } from './chunk-B24C4A6T.js';
@@ -17,4 +17,4 @@ function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName =
17
17
 
18
18
  export { PanelHeader };
19
19
 
20
- //# sourceMappingURL=chunk-XE5ZLPCC.js.map
20
+ //# sourceMappingURL=chunk-ZQQ6P4SV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/panel-header.tsx"],"names":[],"mappings":";;;;;;AAsCO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,aAAA,GAAgB,EAAA,EAAI,OAAA,EAAS,YAAA,EAAc,WAAA,GAAc,OAAM,EAAqB;AAC1J,EAAA,MAAM,2BAAW,IAAA,CAAA,QAAA,EAAA,EACd,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAM,IAAA,EAAC,SAAA,EAAW,0BAA0B,aAAa,CAAA,CAAA,CAAG,IAAA,EAAK,EAAI,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACxG,GAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK,QAAA,EAAS,EAAA,EAAI,OAAA,EAAS,SAAA,EAAU,yBAAA,EAA0B,YAAA,EAA4B,WAAA,EAA0B;AAAA,GAAA,EACjJ,CAAA;AAEA,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,kBAAA,EAAmB,gBAAA,EAAe,cAAA,EAAe,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,kBAAA,EAAkB,WAAA,GAAc,MAAA,GAAS,MAAA,EACxO,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAQ,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,OAAA,EAAS,SAAS,KAAA,EAAO,CAAA;AAAA,IAC9D,OAAA,oBAAW,GAAA,CAAC,GAAA,EAAA,EAAE,KAAA,EAAM,2BAAA,EAA4B,EAAA,EAAI,SAAA,EAAY,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,MAAA,EAAO,IAAK,OAAA,EAAQ;AAAA,GAAA,EACrH,CAAA;AACF","file":"chunk-XE5ZLPCC.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Skeleton } from './skeleton.js';\nimport { Toolbar } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\nimport { type HeadingLevel, ToolbarText } from './toolbar-text.js';\n\nexport interface PanelHeaderProps {\n title: string;\n titleId: string;\n summary?: string;\n summaryId?: string;\n icon?: SafeHtml;\n iconClassName?: string;\n actions?: SafeHtml;\n /**\n * Expose the title as a heading landmark (`role=\"heading\"` + `aria-level`). Set it\n * for a PAGE or view heading so screen-reader heading navigation works and the view\n * has a primary heading; omit it (the default) for a dialog title, which is instead\n * referenced via `aria-labelledby={titleId}` and needs no heading landmark.\n */\n headingLevel?: HeadingLevel;\n /** Render the title and summary as unanimated loading skeletons, keeping the icon and actions. */\n placeholder?: boolean;\n}\n\n/**\n * The heading of a panel, dialog, or page: a plain `Toolbar` whose leading zone\n * holds an optional icon control group and the title as extra-large `ToolbarText`,\n * whose trailing zone holds the app's action controls, and with an optional\n * subtitle on its own row, left-aligned with the title.\n *\n * PanelHeader overrides no Toolbar styles — it is just a Toolbar with an xl title.\n * The only styling it adds is the icon group's fill/border color and the subtitle.\n * When no icon is provided, the icon group is omitted entirely. The `actions` slot\n * is passed straight into the toolbar's trailing zone; the app supplies whatever\n * trailing controls it needs (typically a `ToolbarControlGroup`).\n */\nexport function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName = '', actions, headingLevel, placeholder = false }: PanelHeaderProps) {\n const identity = <>\n {icon && <ToolbarControlGroup single className={`kui-panel-header__icon ${iconClassName}`.trim()}>{icon}</ToolbarControlGroup>}\n <ToolbarText text={title} size=\"xlarge\" id={titleId} className=\"kui-panel-header__title\" headingLevel={headingLevel} placeholder={placeholder} />\n </>;\n\n return <div class=\"kui-panel-header\" data-component=\"panel-header\" data-has-icon={String(Boolean(icon))} data-has-actions={String(Boolean(actions))} data-has-summary={String(Boolean(summary))} data-placeholder={placeholder ? 'true' : undefined}>\n <Toolbar leading={identity} trailing={actions} divider={false} />\n {summary && <p class=\"kui-panel-header__summary\" id={summaryId}>{placeholder ? <Skeleton width=\"18em\" /> : summary}</p>}\n </div>;\n}\n"]}
1
+ {"version":3,"sources":["../src/panel-header.tsx"],"names":[],"mappings":";;;;;;AAsCO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,aAAA,GAAgB,EAAA,EAAI,OAAA,EAAS,YAAA,EAAc,WAAA,GAAc,OAAM,EAAqB;AAC1J,EAAA,MAAM,2BAAW,IAAA,CAAA,QAAA,EAAA,EACd,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAM,IAAA,EAAC,SAAA,EAAW,0BAA0B,aAAa,CAAA,CAAA,CAAG,IAAA,EAAK,EAAI,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACxG,GAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK,QAAA,EAAS,EAAA,EAAI,OAAA,EAAS,SAAA,EAAU,yBAAA,EAA0B,YAAA,EAA4B,WAAA,EAA0B;AAAA,GAAA,EACjJ,CAAA;AAEA,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,kBAAA,EAAmB,gBAAA,EAAe,cAAA,EAAe,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,kBAAA,EAAkB,WAAA,GAAc,MAAA,GAAS,MAAA,EACxO,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAQ,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,OAAA,EAAS,SAAS,KAAA,EAAO,CAAA;AAAA,IAC9D,OAAA,oBAAW,GAAA,CAAC,GAAA,EAAA,EAAE,KAAA,EAAM,2BAAA,EAA4B,EAAA,EAAI,SAAA,EAAY,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,MAAA,EAAO,IAAK,OAAA,EAAQ;AAAA,GAAA,EACrH,CAAA;AACF","file":"chunk-ZQQ6P4SV.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Skeleton } from './skeleton.js';\nimport { Toolbar } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\nimport { type HeadingLevel, ToolbarText } from './toolbar-text.js';\n\nexport interface PanelHeaderProps {\n title: string;\n titleId: string;\n summary?: string;\n summaryId?: string;\n icon?: SafeHtml;\n iconClassName?: string;\n actions?: SafeHtml;\n /**\n * Expose the title as a heading landmark (`role=\"heading\"` + `aria-level`). Set it\n * for a PAGE or view heading so screen-reader heading navigation works and the view\n * has a primary heading; omit it (the default) for a dialog title, which is instead\n * referenced via `aria-labelledby={titleId}` and needs no heading landmark.\n */\n headingLevel?: HeadingLevel;\n /** Render the title and summary as unanimated loading skeletons, keeping the icon and actions. */\n placeholder?: boolean;\n}\n\n/**\n * The heading of a panel, dialog, or page: a plain `Toolbar` whose leading zone\n * holds an optional icon control group and the title as extra-large `ToolbarText`,\n * whose trailing zone holds the app's action controls, and with an optional\n * subtitle on its own row, left-aligned with the title.\n *\n * PanelHeader overrides no Toolbar styles — it is just a Toolbar with an xl title.\n * The only styling it adds is the icon group's fill/border color and the subtitle.\n * When no icon is provided, the icon group is omitted entirely. The `actions` slot\n * is passed straight into the toolbar's trailing zone; the app supplies whatever\n * trailing controls it needs (typically a `ToolbarControlGroup`).\n */\nexport function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName = '', actions, headingLevel, placeholder = false }: PanelHeaderProps) {\n const identity = <>\n {icon && <ToolbarControlGroup single className={`kui-panel-header__icon ${iconClassName}`.trim()}>{icon}</ToolbarControlGroup>}\n <ToolbarText text={title} size=\"xlarge\" id={titleId} className=\"kui-panel-header__title\" headingLevel={headingLevel} placeholder={placeholder} />\n </>;\n\n return <div class=\"kui-panel-header\" data-component=\"panel-header\" data-has-icon={String(Boolean(icon))} data-has-actions={String(Boolean(actions))} data-has-summary={String(Boolean(summary))} data-placeholder={placeholder ? 'true' : undefined}>\n <Toolbar leading={identity} trailing={actions} divider={false} />\n {summary && <p class=\"kui-panel-header__summary\" id={summaryId}>{placeholder ? <Skeleton width=\"18em\" /> : summary}</p>}\n </div>;\n}\n"]}