@kerfjs/ui 5.0.0-beta.92 → 5.0.0-beta.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -373,11 +373,18 @@ guidance, public hooks, and explicit geometry ownership; then concatenate its
373
373
  `entries` with Kerf's shipped `entries` in the AI context. Keep package/source
374
374
  identity alongside each input when ids could collide. This makes a combined
375
375
  tool reason about both sides of a composition using one vocabulary without
376
- pretending app-local components are `@kerfjs/ui` exports.
376
+ pretending app-local components are `@kerfjs/ui` exports. A package that
377
+ keeps a `kerf.components.json` generates this extension with
378
+ `kerf-component-catalog` by setting `kerfComponentCatalog.selectionOutput`
379
+ instead of maintaining a second JSON by hand.
377
380
  For a consumer UX demo, `@kerfjs/ui/catalog-projection` derives rows and
378
381
  relationships from that extension; `kerf-catalog-demo --write` emits a typed
379
382
  module and `--check` catches drift. See the [catalog guide](./docs/catalog.md)
380
- for repository base and source path configuration.
383
+ for repository base and source path configuration. To offer the catalog's
384
+ **Capture region** link to UX Review on a local server, add the Node-only
385
+ `uxReviewPlugin` from `@kerfjs/ui/vite-ux-review` to the Vite config and pass
386
+ `wireCatalog`'s `onUxReviewProject` result to `Catalog`'s `uxReview` (the
387
+ [catalog guide](./docs/catalog.md#ux-review-capture) has the wiring).
381
388
 
382
389
  Composition-aware consumers use
383
390
  [`component-composition-extension.schema.json`](./ai/component-composition-extension.schema.json),
@@ -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.92` and `kerfjs@5.0.0-beta.92`. 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.94` and `kerfjs@5.0.0-beta.94`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
4
4
 
5
5
  ## `@kerfjs/ui/css-values`
6
6
 
@@ -2414,8 +2414,8 @@ export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type Dev
2414
2414
  ```ts
2415
2415
  import * as kerfjs from 'kerfjs';
2416
2416
  import { SafeHtml } from 'kerfjs';
2417
- import { b as CatalogProps } from './types-oLe_N1w0.js';
2418
- export { a as CatalogBackgroundStyle, c as CatalogBrand, d as CatalogEntry, e as CatalogRelated, C as CatalogResource, f as CatalogSecondaryGroup, g as CatalogSection, h as CatalogStageRootAttributes } from './types-oLe_N1w0.js';
2417
+ import { b as CatalogProps } from './types-CVgIwSdq.js';
2418
+ export { a as CatalogBackgroundStyle, c as CatalogBrand, d as CatalogEntry, e as CatalogRelated, C as CatalogResource, f as CatalogSecondaryGroup, g as CatalogSection, h as CatalogSettingsConfig, i as CatalogStageRootAttributes, j as CatalogUxReview } from './types-CVgIwSdq.js';
2419
2419
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2420
2420
  import './toolbar.js';
2421
2421
  import './sides-BPSWde0A.js';
@@ -2437,8 +2437,10 @@ import './resizable-region.js';
2437
2437
  * toolbar, description, preview stage, and resource footer. The sidebar's
2438
2438
  * standard toggle moves into the entry toolbar while it is collapsed, and on
2439
2439
  * a small screen the sidebar overlays the stage like any Workbench rail.
2440
+ * An entry's `settings` render in a right-rail settings pane beside the stage,
2441
+ * with the same toggle relocation and small-screen overlay.
2440
2442
  */
2441
- declare function Catalog({ id, brand, sections, active, content, collapsed, theme, increasedContrast, reducedMotion, backgroundControl, headerActions, secondarySections, sidebarFooter, status, backgroundStyle, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleContrastAction, toggleMotionAction, selectBackgroundAction, toggleSecondaryAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2443
+ declare function Catalog({ id, brand, sections, active, content, collapsed, theme, increasedContrast, reducedMotion, backgroundControl, headerActions, settings, settingsCollapsed, settingsPanel, uxReview, secondarySections, sidebarFooter, status, backgroundStyle, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleContrastAction, toggleMotionAction, selectBackgroundAction, toggleSecondaryAction, toggleSettingsAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2442
2444
 
2443
2445
  /** How a specimen aligns its visible edge with its `ListHeader` label. */
2444
2446
  type CatalogExampleAlign = 'glyph' | 'inline-control' | 'text-trigger' | 'none';
@@ -2503,13 +2505,39 @@ interface CatalogExampleStackProps {
2503
2505
  /** A vertically stacked group of catalog examples. */
2504
2506
  declare function CatalogExampleStack({ label, rootAttributes, className, children, slot, }: CatalogExampleStackProps): kerfjs.SafeHtml;
2505
2507
 
2506
- export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleProps, CatalogExampleStack, type CatalogExampleStackProps, type CatalogExampleViewport, CatalogProps };
2508
+ /**
2509
+ * Browser helpers for UX Review region captures from a catalog. The local
2510
+ * project directory comes from `uxReviewPlugin` (`@kerfjs/ui/vite-ux-review`),
2511
+ * which serves it to the catalog page on a Vite dev or preview server; static
2512
+ * hosting has no such endpoint, so a catalog there shows no capture link.
2513
+ */
2514
+ /** Where `uxReviewPlugin` serves `{ projectDirectory }`, relative to the catalog page. */
2515
+ declare const UX_REVIEW_PROJECT_PATH = "__ux-review/project.json";
2516
+ /** What a UX Review region capture is preset with. */
2517
+ interface UxReviewCapture {
2518
+ /** The absolute project directory UX Review files the review under. */
2519
+ projectDirectory: string;
2520
+ /** The review title. */
2521
+ title: string;
2522
+ /** Review context: what was selected and where. */
2523
+ context: string;
2524
+ }
2525
+ /** A `uxreview://capture` link that starts a region screenshot for a project. */
2526
+ declare function uxReviewCaptureUrl({ projectDirectory, title, context, }: UxReviewCapture): string;
2527
+ /**
2528
+ * Ask the server that served `pageUrl` for its UX Review project directory.
2529
+ * Resolves `null` when there is none (static hosting, a server without the
2530
+ * plugin, a malformed answer, or a network failure); never rejects.
2531
+ */
2532
+ declare function loadUxReviewProject(pageUrl: string | URL, fetchImpl?: typeof globalThis.fetch): Promise<string | null>;
2533
+
2534
+ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleProps, CatalogExampleStack, type CatalogExampleStackProps, type CatalogExampleViewport, CatalogProps, UX_REVIEW_PROJECT_PATH, type UxReviewCapture, loadUxReviewProject, uxReviewCaptureUrl };
2507
2535
  ```
2508
2536
 
2509
2537
  ## `@kerfjs/ui/catalog-resources`
2510
2538
 
2511
2539
  ```ts
2512
- import { C as CatalogResource } from './types-oLe_N1w0.js';
2540
+ import { C as CatalogResource } from './types-CVgIwSdq.js';
2513
2541
  import './toolbar.js';
2514
2542
  import 'kerfjs';
2515
2543
  import './semantic-content-BbzjvSu9.js';
@@ -2563,7 +2591,7 @@ export { type CatalogGuidanceKind, type CatalogResourceKind, type CatalogResourc
2563
2591
 
2564
2592
  ```ts
2565
2593
  import { Signal } from 'kerfjs';
2566
- import { a as CatalogBackgroundStyle } from './types-oLe_N1w0.js';
2594
+ import { a as CatalogBackgroundStyle } from './types-CVgIwSdq.js';
2567
2595
  import './toolbar.js';
2568
2596
  import './semantic-content-BbzjvSu9.js';
2569
2597
  import './sides-BPSWde0A.js';
@@ -2592,6 +2620,11 @@ interface WireCatalogOptions {
2592
2620
  onToggleMotion?: () => void;
2593
2621
  /** Report a preview background choice; the app updates `backgroundStyle`. */
2594
2622
  onSelectBackground?: (style: CatalogBackgroundStyle) => void;
2623
+ /**
2624
+ * Invoked when the settings pane toggle is activated. With
2625
+ * `settingsCollapsed`, `wireCatalog` has already flipped the signal.
2626
+ */
2627
+ onToggleSettings?: () => void;
2595
2628
  /** Invoked when the secondary (ecosystem) group's disclosure toggle is activated. */
2596
2629
  onToggleSecondary?: () => void;
2597
2630
  /** When set, `?<urlParam>=<id>` is written on select via `history.replaceState`. */
@@ -2608,6 +2641,7 @@ interface WireCatalogOptions {
2608
2641
  toggleMotionAction?: string;
2609
2642
  selectBackgroundAction?: string;
2610
2643
  toggleSecondaryAction?: string;
2644
+ toggleSettingsAction?: string;
2611
2645
  /**
2612
2646
  * The sidebar's app-owned collapsed flag. With it, the catalog's Workbench
2613
2647
  * sidebar is wired like any Workbench rail: it becomes a transient overlay
@@ -2627,8 +2661,34 @@ interface WireCatalogOptions {
2627
2661
  * catalog remembers the user's sidebar width.
2628
2662
  */
2629
2663
  sidebarStorageKey?: string;
2664
+ /**
2665
+ * The settings pane's app-owned collapsed flag, rendered as the Catalog's
2666
+ * `settingsCollapsed`. With it, `wireCatalog` owns the pane's toggle (each
2667
+ * press flips the signal) and wires the pane like any Workbench rail: a
2668
+ * transient overlay on a small screen (collapsed as the breakpoint applies,
2669
+ * closed on Escape or a press outside, focus handed back).
2670
+ */
2671
+ settingsCollapsed?: Signal<boolean>;
2672
+ /**
2673
+ * The app-owned settings pane width signal for a Catalog rendered with
2674
+ * `settingsPanel={{ resizable: true, size: settingsSize.value }}`. Each
2675
+ * committed drag or keyboard resize is written to it.
2676
+ */
2677
+ settingsSize?: Signal<number>;
2678
+ /**
2679
+ * With `settingsSize`, load and save the width under this storage key so
2680
+ * the catalog remembers the user's settings pane width.
2681
+ */
2682
+ settingsStorageKey?: string;
2630
2683
  /** The Catalog's `id`, when it is not the default `kui-catalog`. */
2631
2684
  id?: string;
2685
+ /**
2686
+ * Ask the page's server once for its UX Review project directory (served by
2687
+ * `uxReviewPlugin` from `@kerfjs/ui/vite-ux-review`) and report it, so the
2688
+ * app can render the Catalog with `uxReview`. Never called on static
2689
+ * hosting or a server without the plugin.
2690
+ */
2691
+ onUxReviewProject?: (projectDirectory: string) => void;
2632
2692
  }
2633
2693
  interface CatalogRevealOptions {
2634
2694
  /** Scroll alignment within the sidebar. Default `'nearest'`. */
@@ -2650,14 +2710,14 @@ interface CatalogRevealOptions {
2650
2710
  declare function revealCatalogEntry(root: HTMLElement, id: string, { block, inline, behavior, media, }?: CatalogRevealOptions): () => void;
2651
2711
  /**
2652
2712
  * Wire a {@link Catalog}'s interactions with one delegated listener set: sidebar
2653
- * item selection (and the related-entry popup menu), the sidebar collapse toggle, and
2654
- * the theme toggle. The app owns the `active`/`collapsed`/`theme` signals and updates
2713
+ * item selection (and the related-entry popup menu), the sidebar collapse toggle,
2714
+ * the settings pane toggle, and the theme toggle. The app owns the `active`/`collapsed`/`theme` signals and updates
2655
2715
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
2656
2716
  * It also wires the scroll dividers below root (`wireScrollDividers`), so the
2657
2717
  * catalog's panes and every example in it show their chrome dividers only
2658
2718
  * while scrolled. Returns a disposer.
2659
2719
  */
2660
- declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleContrast, onToggleMotion, onSelectBackground, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleContrastAction, toggleMotionAction, selectBackgroundAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
2720
+ declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleContrast, onToggleMotion, onSelectBackground, onToggleSecondary, onToggleSettings, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleContrastAction, toggleMotionAction, selectBackgroundAction, toggleSecondaryAction, toggleSettingsAction, collapsed, sidebarSize, sidebarStorageKey, settingsCollapsed, settingsSize, settingsStorageKey, id: catalogId, onUxReviewProject, }: WireCatalogOptions): () => void;
2661
2721
 
2662
2722
  export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog };
2663
2723
  ```
package/ai/skill.md CHANGED
@@ -136,10 +136,19 @@ second, package-qualified input beside `./component-catalog.json`: search both,
136
136
  preserve their source identity, and use the shared `geometry` vocabulary across
137
137
  their composition boundary. An extension entry's optional `uses` ids resolve
138
138
  against both catalogs; its `source` and `demoSource` are repository-relative
139
- files for consumer catalog links. When a consuming project has reusable visual
139
+ files for consumer catalog links. A project with `kerf.components.json` generates
140
+ that extension with `kerf-component-catalog` (`kerfComponentCatalog.selectionOutput`
141
+ plus per-component `selection` blocks) rather than hand-writing it. When a consuming project has reusable visual
140
142
  components, derive demo rows with `@kerfjs/ui/catalog-projection` or
141
143
  `kerf-catalog-demo --write`, then guard drift with `--check`; see
142
- `../docs/catalog.md`. Prefer its generated `component-composition.json`. A package
144
+ `../docs/catalog.md`. For a local catalog's UX Review **Capture region** link,
145
+ add `uxReviewPlugin()` from the Node-only `@kerfjs/ui/vite-ux-review` to the
146
+ Vite config, report the project with `wireCatalog`'s `onUxReviewProject`, and
147
+ render `Catalog` with `uxReview={{ projectDirectory }}`; never hand-roll the
148
+ endpoint or the `uxreview://` link. For per-entry variant/state controls, pass
149
+ them as `Catalog`'s `settings` (with `settingsCollapsed` and the same signal as
150
+ `wireCatalog`'s `settingsCollapsed`); never build a separate settings aside and
151
+ toggle. Prefer its generated `component-composition.json`. A package
143
152
  scaffolded by `create-kerf-component` owns the decisions in
144
153
  `kerf.components.json`; run `npm run catalog:check` before using its output. If
145
154
  no generated extension exists, start from the checked examples and require the
@@ -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.92` 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.94` 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';
@@ -1,4 +1,4 @@
1
- import { C as CatalogResource } from './types-oLe_N1w0.js';
1
+ import { C as CatalogResource } from './types-CVgIwSdq.js';
2
2
  import './toolbar.js';
3
3
  import 'kerfjs';
4
4
  import './semantic-content-BbzjvSu9.js';
package/dist/catalog.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
  import { SafeHtml } from 'kerfjs';
3
- import { b as CatalogProps } from './types-oLe_N1w0.js';
4
- export { a as CatalogBackgroundStyle, c as CatalogBrand, d as CatalogEntry, e as CatalogRelated, C as CatalogResource, f as CatalogSecondaryGroup, g as CatalogSection, h as CatalogStageRootAttributes } from './types-oLe_N1w0.js';
3
+ import { b as CatalogProps } from './types-CVgIwSdq.js';
4
+ export { a as CatalogBackgroundStyle, c as CatalogBrand, d as CatalogEntry, e as CatalogRelated, C as CatalogResource, f as CatalogSecondaryGroup, g as CatalogSection, h as CatalogSettingsConfig, i as CatalogStageRootAttributes, j as CatalogUxReview } from './types-CVgIwSdq.js';
5
5
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
6
6
  import './toolbar.js';
7
7
  import './sides-BPSWde0A.js';
@@ -23,8 +23,10 @@ import './resizable-region.js';
23
23
  * toolbar, description, preview stage, and resource footer. The sidebar's
24
24
  * standard toggle moves into the entry toolbar while it is collapsed, and on
25
25
  * a small screen the sidebar overlays the stage like any Workbench rail.
26
+ * An entry's `settings` render in a right-rail settings pane beside the stage,
27
+ * with the same toggle relocation and small-screen overlay.
26
28
  */
27
- declare function Catalog({ id, brand, sections, active, content, collapsed, theme, increasedContrast, reducedMotion, backgroundControl, headerActions, secondarySections, sidebarFooter, status, backgroundStyle, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleContrastAction, toggleMotionAction, selectBackgroundAction, toggleSecondaryAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
29
+ declare function Catalog({ id, brand, sections, active, content, collapsed, theme, increasedContrast, reducedMotion, backgroundControl, headerActions, settings, settingsCollapsed, settingsPanel, uxReview, secondarySections, sidebarFooter, status, backgroundStyle, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleContrastAction, toggleMotionAction, selectBackgroundAction, toggleSecondaryAction, toggleSettingsAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
28
30
 
29
31
  /** How a specimen aligns its visible edge with its `ListHeader` label. */
30
32
  type CatalogExampleAlign = 'glyph' | 'inline-control' | 'text-trigger' | 'none';
@@ -89,4 +91,30 @@ interface CatalogExampleStackProps {
89
91
  /** A vertically stacked group of catalog examples. */
90
92
  declare function CatalogExampleStack({ label, rootAttributes, className, children, slot, }: CatalogExampleStackProps): kerfjs.SafeHtml;
91
93
 
92
- export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleProps, CatalogExampleStack, type CatalogExampleStackProps, type CatalogExampleViewport, CatalogProps };
94
+ /**
95
+ * Browser helpers for UX Review region captures from a catalog. The local
96
+ * project directory comes from `uxReviewPlugin` (`@kerfjs/ui/vite-ux-review`),
97
+ * which serves it to the catalog page on a Vite dev or preview server; static
98
+ * hosting has no such endpoint, so a catalog there shows no capture link.
99
+ */
100
+ /** Where `uxReviewPlugin` serves `{ projectDirectory }`, relative to the catalog page. */
101
+ declare const UX_REVIEW_PROJECT_PATH = "__ux-review/project.json";
102
+ /** What a UX Review region capture is preset with. */
103
+ interface UxReviewCapture {
104
+ /** The absolute project directory UX Review files the review under. */
105
+ projectDirectory: string;
106
+ /** The review title. */
107
+ title: string;
108
+ /** Review context: what was selected and where. */
109
+ context: string;
110
+ }
111
+ /** A `uxreview://capture` link that starts a region screenshot for a project. */
112
+ declare function uxReviewCaptureUrl({ projectDirectory, title, context, }: UxReviewCapture): string;
113
+ /**
114
+ * Ask the server that served `pageUrl` for its UX Review project directory.
115
+ * Resolves `null` when there is none (static hosting, a server without the
116
+ * plugin, a malformed answer, or a network failure); never rejects.
117
+ */
118
+ declare function loadUxReviewProject(pageUrl: string | URL, fetchImpl?: typeof globalThis.fetch): Promise<string | null>;
119
+
120
+ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleProps, CatalogExampleStack, type CatalogExampleStackProps, type CatalogExampleViewport, CatalogProps, UX_REVIEW_PROJECT_PATH, type UxReviewCapture, loadUxReviewProject, uxReviewCaptureUrl };
package/dist/catalog.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { Workbench } from './chunk-QCLLBMLA.js';
2
+ import { uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
3
+ export { UX_REVIEW_PROJECT_PATH, loadUxReviewProject, uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
2
4
 
3
5
 
4
6
  import { TokenSearchField } from './chunk-ROZLJULF.js';
@@ -27,7 +29,7 @@ import { LucideIcon } from './chunk-UKKRPP56.js';
27
29
 
28
30
 
29
31
  import { filterDataAttributes } from './chunk-LAZLBC2Q.js';
30
- import { Contrast, ZapOff, Moon, Sun, X, Waypoints, ExternalLink } from 'lucide';
32
+ import { Contrast, ZapOff, Moon, Sun, X, Waypoints, ExternalLink, Scan } from 'lucide';
31
33
  import { jsx, jsxs, Fragment } from 'kerfjs/jsx-runtime';
32
34
 
33
35
  function relatedMenuItems(related, selectAction) {
@@ -269,9 +271,40 @@ function CatalogStage({
269
271
  }
270
272
  );
271
273
  }
274
+ function CatalogUxReviewLink({
275
+ uxReview: { projectDirectory, name },
276
+ entry,
277
+ category
278
+ }) {
279
+ return /* @__PURE__ */ jsx(
280
+ ToolbarControlGroup,
281
+ {
282
+ appearance: "borderless",
283
+ single: true,
284
+ size: "compact",
285
+ content: "mixed",
286
+ buttonAppearance: "push",
287
+ children: /* @__PURE__ */ jsx(
288
+ ToolbarActionLink,
289
+ {
290
+ href: uxReviewCaptureUrl({
291
+ projectDirectory,
292
+ title: `${name}: ${entry.name}`,
293
+ context: `${name} catalog
294
+ Selected ${category}: ${entry.name} (${entry.id})`
295
+ }),
296
+ label: "Capture region",
297
+ ariaLabel: `Capture ${entry.name} in UX Review`,
298
+ icon: /* @__PURE__ */ jsx(LucideIcon, { icon: Scan, name: "scan" })
299
+ }
300
+ )
301
+ }
302
+ );
303
+ }
272
304
  function findEntry(sections, id) {
273
305
  for (const section of sections) {
274
- for (const entry of section.entries) if (entry.id === id) return entry;
306
+ for (const entry of section.entries)
307
+ if (entry.id === id) return { entry, category: section.category };
275
308
  }
276
309
  return void 0;
277
310
  }
@@ -287,6 +320,10 @@ function Catalog({
287
320
  reducedMotion,
288
321
  backgroundControl = false,
289
322
  headerActions,
323
+ settings,
324
+ settingsCollapsed = false,
325
+ settingsPanel = {},
326
+ uxReview,
290
327
  secondarySections,
291
328
  sidebarFooter,
292
329
  status,
@@ -299,6 +336,7 @@ function Catalog({
299
336
  toggleMotionAction = "catalog-toggle-motion",
300
337
  selectBackgroundAction = "catalog-select-background",
301
338
  toggleSecondaryAction = "catalog-toggle-secondary",
339
+ toggleSettingsAction = "catalog-toggle-settings",
302
340
  headerPlacement = "auto",
303
341
  footerPlacement = "auto",
304
342
  sidebar = {},
@@ -307,17 +345,21 @@ function Catalog({
307
345
  className = "",
308
346
  slot
309
347
  }) {
310
- const selected = findEntry(sections, active) ?? (secondarySections ? findEntry(secondarySections.sections, active) : void 0);
348
+ const found = findEntry(sections, active) ?? (secondarySections ? findEntry(secondarySections.sections, active) : void 0);
349
+ const selected = found?.entry;
311
350
  const name = selected?.name ?? "";
312
351
  const nextTheme = theme === "dark" ? "light" : "dark";
313
352
  const catalogName = `${brand.title} catalog`;
314
353
  const displayControls = increasedContrast !== void 0 || reducedMotion !== void 0 || backgroundControl || theme !== void 0;
354
+ const hasSettings = settings !== void 0 && settings !== null && settings !== false;
355
+ const settingsTitle = settingsPanel.title ?? "Settings";
315
356
  return /* @__PURE__ */ jsx(
316
357
  "main",
317
358
  {
318
359
  class: `kui-catalog ${className}`.trim(),
319
360
  "data-component": "catalog",
320
361
  "data-sidebar-collapsed": String(collapsed),
362
+ "data-settings-collapsed": hasSettings ? String(settingsCollapsed) : void 0,
321
363
  slot,
322
364
  children: /* @__PURE__ */ jsx(
323
365
  Workbench,
@@ -380,6 +422,29 @@ function Catalog({
380
422
  }
381
423
  )
382
424
  },
425
+ rightRail: hasSettings ? {
426
+ label: name ? `${name} ${settingsTitle}` : settingsTitle,
427
+ size: settingsPanel.size ?? 288,
428
+ resizable: settingsPanel.resizable,
429
+ separator: settingsPanel.separator,
430
+ collapseMotion: settingsPanel.collapseMotion,
431
+ presentation: settingsPanel.presentation,
432
+ responsiveOverlayAt: settingsPanel.responsiveOverlayAt,
433
+ compactOverlay: settingsPanel.compactOverlay,
434
+ collapsed: settingsCollapsed,
435
+ toolbar: {
436
+ ...settingsPanel.toolbar,
437
+ label: `${settingsTitle} header`,
438
+ // A peripheral rail beside the xl entry title takes the
439
+ // default title size, so it never truncates at 288px.
440
+ title: /* @__PURE__ */ jsx(ToolbarText, { text: settingsTitle, headingLevel: 2 }),
441
+ toggle: {
442
+ action: toggleSettingsAction,
443
+ name: settingsTitle.toLocaleLowerCase()
444
+ }
445
+ },
446
+ content: settings
447
+ } : void 0,
383
448
  mainToolbar: {
384
449
  ...mainToolbar,
385
450
  label: `${name} header`,
@@ -388,6 +453,14 @@ function Catalog({
388
453
  title: /* @__PURE__ */ jsx(ToolbarText, { text: name, size: "xlarge", headingLevel: 2 }),
389
454
  trailing: /* @__PURE__ */ jsxs(Fragment, { children: [
390
455
  headerActions,
456
+ uxReview && found ? /* @__PURE__ */ jsx(
457
+ CatalogUxReviewLink,
458
+ {
459
+ uxReview: { ...uxReview, name: uxReview.name ?? brand.title },
460
+ entry: found.entry,
461
+ category: found.category
462
+ }
463
+ ) : null,
391
464
  displayControls ? /* @__PURE__ */ jsxs(
392
465
  ToolbarControlGroup,
393
466
  {