@ng-prism/core 22.0.1 → 22.1.0

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.
@@ -0,0 +1,9 @@
1
+ import type { RuntimeComponent } from '../../plugin/plugin.types.js';
2
+ /** Synthetic input the manifest generator emits on directive wrapper classes
3
+ * to project per-variant `content` text into the host element. The directive
4
+ * itself doesn't declare it, so it isn't in `meta.inputs` — code that
5
+ * validates / filters inputs against that list must allow this key through.
6
+ */
7
+ export declare const PRISM_CONTENT_INPUT = "__prismContent__";
8
+ export declare function buildKnownInputs(comp: RuntimeComponent): Set<string>;
9
+ //# sourceMappingURL=known-inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"known-inputs.d.ts","sourceRoot":"","sources":["../../../src/app/renderer/known-inputs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AAEtD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,GAAG,CAAC,MAAM,CAAC,CAMpE"}
@@ -0,0 +1,13 @@
1
+ /** Synthetic input the manifest generator emits on directive wrapper classes
2
+ * to project per-variant `content` text into the host element. The directive
3
+ * itself doesn't declare it, so it isn't in `meta.inputs` — code that
4
+ * validates / filters inputs against that list must allow this key through.
5
+ */
6
+ export const PRISM_CONTENT_INPUT = '__prismContent__';
7
+ export function buildKnownInputs(comp) {
8
+ const known = new Set(comp.meta.inputs.map((i) => i.name));
9
+ if (comp.meta.componentMeta.isDirective) {
10
+ known.add(PRISM_CONTENT_INPUT);
11
+ }
12
+ return known;
13
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"prism-renderer.component.d.ts","sourceRoot":"","sources":["../../../src/app/renderer/prism-renderer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,QAAQ,EAER,KAAK,IAAI,EAIV,MAAM,eAAe,CAAC;AAYvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AAGjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;;AAIhF,qBA8Ia,sBAAsB;IACjC,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAQ;IAC/B,SAAS,CAAC,QAAQ,CAAC,iBAAiB,yBAAkC;IACtE,SAAS,CAAC,QAAQ,CAAC,eAAe,uBAAgC;IAClE,SAAS,CAAC,QAAQ,CAAC,aAAa,qBAA8B;IAC9D,SAAS,CAAC,QAAQ,CAAC,SAAS,wBAAiC;IAC7D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAE3B;IAEH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;IAE5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAEpB;IACH,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,mBAAmB,CAAsC;IACjE,OAAO,CAAC,oBAAoB,CAChB;IACZ,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoC;IACjE,QAAQ,CAAC,aAAa,+DAAsC;IAC5D,wFAAwF;IACxF,SAAS,CAAC,QAAQ,CAAC,WAAW,gDAQ3B;IACH,6GAA6G;IAC7G,SAAS,CAAC,QAAQ,CAAC,YAAY,4FAU5B;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa;;MAA6C;IAC7E,SAAS,CAAC,QAAQ,CAAC,eAAe,yFAG/B;;IA0FH,OAAO,CAAC,eAAe;IA6FvB,OAAO,CAAC,OAAO;yCA9OJ,sBAAsB;2CAAtB,sBAAsB;CA4PlC"}
1
+ {"version":3,"file":"prism-renderer.component.d.ts","sourceRoot":"","sources":["../../../src/app/renderer/prism-renderer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,QAAQ,EAER,KAAK,IAAI,EAIV,MAAM,eAAe,CAAC;AAYvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AAGjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;;AAKhF,qBA8Ia,sBAAsB;IACjC,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAQ;IAC/B,SAAS,CAAC,QAAQ,CAAC,iBAAiB,yBAAkC;IACtE,SAAS,CAAC,QAAQ,CAAC,eAAe,uBAAgC;IAClE,SAAS,CAAC,QAAQ,CAAC,aAAa,qBAA8B;IAC9D,SAAS,CAAC,QAAQ,CAAC,SAAS,wBAAiC;IAC7D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAE3B;IAEH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;IAE5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAEpB;IACH,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,mBAAmB,CAAsC;IACjE,OAAO,CAAC,oBAAoB,CAChB;IACZ,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoC;IACjE,QAAQ,CAAC,aAAa,+DAAsC;IAC5D,wFAAwF;IACxF,SAAS,CAAC,QAAQ,CAAC,WAAW,gDAQ3B;IACH,6GAA6G;IAC7G,SAAS,CAAC,QAAQ,CAAC,YAAY,4FAU5B;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa;;MAA6C;IAC7E,SAAS,CAAC,QAAQ,CAAC,eAAe,yFAG/B;;IA0FH,OAAO,CAAC,eAAe;IA6FvB,OAAO,CAAC,OAAO;yCA9OJ,sBAAsB;2CAAtB,sBAAsB;CA4PlC"}
@@ -12,6 +12,7 @@ import { PrismCanvasService } from '../services/prism-canvas.service.js';
12
12
  import { PrismVariantBgService } from '../services/prism-variant-bg.service.js';
13
13
  import { PrismCanvasRulersComponent } from '../canvas/prism-canvas-rulers.component.js';
14
14
  import { PrismCanvasBgPillComponent } from '../canvas/prism-canvas-bg-pill.component.js';
15
+ import { buildKnownInputs } from './known-inputs.js';
15
16
  import * as i0 from "@angular/core";
16
17
  const _c0 = ["outlet"];
17
18
  function PrismRendererComponent_Conditional_10_ng_container_0_Template(rf, ctx) { if (rf & 1) {
@@ -104,7 +105,7 @@ export class PrismRendererComponent {
104
105
  return;
105
106
  }
106
107
  performance.mark('prism:rerender:start');
107
- const knownInputs = new Set(comp.meta.inputs.map((i) => i.name));
108
+ const knownInputs = buildKnownInputs(comp);
108
109
  for (const [key, value] of Object.entries(inputs)) {
109
110
  if (!knownInputs.has(key)) {
110
111
  console.warn(`[ng-prism] Unknown input "${key}" on <${comp.meta.componentMeta.selector}> — skipping. Remove it from @Showcase variants.`);
@@ -196,7 +197,7 @@ export class PrismRendererComponent {
196
197
  this.outputSubscriptions.push(sub);
197
198
  }
198
199
  }
199
- const knownInputs = new Set(comp.meta.inputs.map((i) => i.name));
200
+ const knownInputs = buildKnownInputs(comp);
200
201
  for (const [key, value] of Object.entries(this.rendererService.inputValues())) {
201
202
  if (!knownInputs.has(key)) {
202
203
  console.warn(`[ng-prism] Unknown input "${key}" on <${selector}> — skipping. Remove it from @Showcase variants.`);
@@ -299,7 +300,7 @@ export class PrismRendererComponent {
299
300
  }], () => [], { outlet: [{ type: i0.ViewChild, args: ['outlet', { ...{
300
301
  read: ViewContainerRef,
301
302
  }, isSignal: true }] }] }); })();
302
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismRendererComponent, { className: "PrismRendererComponent", filePath: "app/renderer/prism-renderer.component.ts", lineNumber: 179 }); })();
303
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismRendererComponent, { className: "PrismRendererComponent", filePath: "app/renderer/prism-renderer.component.ts", lineNumber: 180 }); })();
303
304
  function parseContentToNodes(content) {
304
305
  if (typeof content === 'string') {
305
306
  return [htmlToNodes(content)];
@@ -1 +1 @@
1
- {"version":3,"file":"snippet-generator.d.ts","sourceRoot":"","sources":["../../../src/app/renderer/snippet-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;CAC/B;AAoBD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,EAAE,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,gBAAgB,CAAC,EAAE,uBAAuB,GACzC,MAAM,CA2DR"}
1
+ {"version":3,"file":"snippet-generator.d.ts","sourceRoot":"","sources":["../../../src/app/renderer/snippet-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;CAC/B;AAwBD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,EAAE,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,gBAAgB,CAAC,EAAE,uBAAuB,GACzC,MAAM,CAmER"}
@@ -76,7 +76,9 @@ function directiveSelectorToAttr(selector) {
76
76
  return match ? match[1] : selector;
77
77
  }
78
78
  function parseHostStringSimple(host) {
79
- const match = host.trim().match(/^<\s*([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^>]*?)?)\s*\/?\s*>$/);
79
+ const match = host
80
+ .trim()
81
+ .match(/^<\s*([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^>]*?)?)\s*\/?\s*>$/);
80
82
  if (!match)
81
83
  return { tag: 'div', attrs: '' };
82
84
  return { tag: match[1], attrs: match[2].trim() };
@@ -100,7 +102,7 @@ function generateDirectiveSnippet(selector, inputs, values, explicitKeys, conten
100
102
  }
101
103
  }
102
104
  const attributes = [];
103
- const processed = new Set();
105
+ const processed = new Set(['__prismContent__']);
104
106
  for (const input of inputs) {
105
107
  processed.add(input.name);
106
108
  const value = values[input.name];
@@ -123,15 +125,21 @@ function generateDirectiveSnippet(selector, inputs, values, explicitKeys, conten
123
125
  continue;
124
126
  pushAttribute(attributes, name, value);
125
127
  }
128
+ const projectedContent = content ??
129
+ (typeof values['__prismContent__'] === 'string'
130
+ ? values['__prismContent__']
131
+ : undefined);
126
132
  const allAttrs = [...hostAttrs, directiveAttr, ...attributes].join(' ');
127
- const contentHtml = resolveContentHtml(content);
133
+ const contentHtml = resolveContentHtml(projectedContent);
128
134
  if (!contentHtml) {
129
135
  if (!allAttrs)
130
136
  return `<${tag} />`;
131
137
  const singleLine = `<${tag} ${allAttrs} />`;
132
138
  if (singleLine.length <= 80)
133
139
  return singleLine;
134
- const indented = [...hostAttrs, directiveAttr, ...attributes].map((a) => ` ${a}`).join('\n');
140
+ const indented = [...hostAttrs, directiveAttr, ...attributes]
141
+ .map((a) => ` ${a}`)
142
+ .join('\n');
135
143
  return `<${tag}\n${indented} />`;
136
144
  }
137
145
  const openTag = `<${tag} ${allAttrs}>`;
@@ -1,14 +1,25 @@
1
- import type { RuntimeComponent } from '../../plugin/plugin.types.js';
1
+ import type { RuntimeComponent, ScannedComponent } from '../../plugin/plugin.types.js';
2
2
  import type { StyleguidePage } from '../../plugin/page.types.js';
3
3
  import type { NavigationItem } from './navigation-item.types.js';
4
4
  import * as i0 from "@angular/core";
5
+ export interface CategoryNode {
6
+ name: string;
7
+ items: NavigationItem[];
8
+ }
9
+ export interface SectionNode {
10
+ name: string;
11
+ order: number;
12
+ totalCount: number;
13
+ categories: CategoryNode[];
14
+ }
15
+ export declare function resolveSection(c: ScannedComponent): string;
5
16
  export declare class PrismNavigationService {
6
17
  private readonly searchService;
7
18
  private readonly manifestService;
8
19
  readonly activeItem: import("@angular/core").WritableSignal<NavigationItem | null>;
9
20
  readonly activeComponent: import("@angular/core").Signal<RuntimeComponent | null>;
10
21
  readonly activePage: import("@angular/core").Signal<StyleguidePage | null>;
11
- readonly categoryTree: import("@angular/core").Signal<Map<string, NavigationItem[]>>;
22
+ readonly sectionTree: import("@angular/core").Signal<SectionNode[]>;
12
23
  select(comp: RuntimeComponent): void;
13
24
  selectPage(page: StyleguidePage): void;
14
25
  selectFirst(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"prism-navigation.service.d.ts","sourceRoot":"","sources":["../../../src/app/services/prism-navigation.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;;AAIjE,qBACa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;IAC5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAEhE,QAAQ,CAAC,UAAU,gEAAuC;IAE1D,QAAQ,CAAC,eAAe,0DAQrB;IAEH,QAAQ,CAAC,UAAU,wDAQhB;IAEH,QAAQ,CAAC,YAAY,gEA0DlB;IAEH,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAIpC,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAItC,WAAW,IAAI,IAAI;yCA9FR,sBAAsB;6CAAtB,sBAAsB;CA2GlC"}
1
+ {"version":3,"file":"prism-navigation.service.d.ts","sourceRoot":"","sources":["../../../src/app/services/prism-navigation.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;;AAWjE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,YAAY,EAAE,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAG1D;AAeD,qBACa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;IAC5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAEhE,QAAQ,CAAC,UAAU,gEAAuC;IAE1D,QAAQ,CAAC,eAAe,0DAQrB;IAEH,QAAQ,CAAC,UAAU,wDAQhB;IAEH,QAAQ,CAAC,WAAW,gDAiFjB;IAEH,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAIpC,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAItC,WAAW,IAAI,IAAI;yCArHR,sBAAsB;6CAAtB,sBAAsB;CAkIlC"}
@@ -2,6 +2,30 @@ import { computed, inject, Injectable, signal } from '@angular/core';
2
2
  import { PrismManifestService } from './prism-manifest.service.js';
3
3
  import { PrismSearchService } from './prism-search.service.js';
4
4
  import * as i0 from "@angular/core";
5
+ const DEFAULT_SECTION_ORDER = {
6
+ Components: 0,
7
+ Directives: 10,
8
+ };
9
+ const SECTION_TIEBREAK = ['Components', 'Directives'];
10
+ export function resolveSection(c) {
11
+ if (c.showcaseConfig.section)
12
+ return c.showcaseConfig.section;
13
+ return c.componentMeta.isDirective ? 'Directives' : 'Components';
14
+ }
15
+ function defaultSectionOrder(name) {
16
+ return DEFAULT_SECTION_ORDER[name] ?? 100;
17
+ }
18
+ function sectionTiebreak(a, b) {
19
+ const ia = SECTION_TIEBREAK.indexOf(a);
20
+ const ib = SECTION_TIEBREAK.indexOf(b);
21
+ if (ia !== -1 && ib !== -1)
22
+ return ia - ib;
23
+ if (ia !== -1)
24
+ return -1;
25
+ if (ib !== -1)
26
+ return 1;
27
+ return a.localeCompare(b);
28
+ }
5
29
  export class PrismNavigationService {
6
30
  searchService = inject(PrismSearchService);
7
31
  manifestService = inject(PrismManifestService);
@@ -25,55 +49,66 @@ export class PrismNavigationService {
25
49
  return relinked ?? null;
26
50
  }, /* @ts-ignore */
27
51
  ...(ngDevMode ? [{ debugName: "activePage" }] : /* istanbul ignore next */ []));
28
- categoryTree = computed(() => {
29
- const map = new Map();
30
- for (const comp of this.searchService.filteredComponents()) {
31
- const cat = comp.meta.showcaseConfig.category ?? 'Uncategorized';
32
- const list = map.get(cat) ?? [];
33
- list.push({ kind: 'component', data: comp });
34
- map.set(cat, list);
35
- }
36
- for (const page of this.searchService.filteredPages()) {
37
- const cat = page.category ?? 'Uncategorized';
38
- const list = map.get(cat) ?? [];
39
- list.push({ kind: 'page', data: page });
40
- map.set(cat, list);
52
+ sectionTree = computed(() => {
53
+ const comps = this.searchService.filteredComponents();
54
+ const sections = new Map();
55
+ const sectionOrders = new Map();
56
+ for (const comp of comps) {
57
+ const section = resolveSection(comp.meta);
58
+ const category = comp.meta.showcaseConfig.category ?? 'Uncategorized';
59
+ const catMap = sections.get(section) ?? new Map();
60
+ const items = catMap.get(category) ?? [];
61
+ items.push({ kind: 'component', data: comp });
62
+ catMap.set(category, items);
63
+ sections.set(section, catMap);
64
+ const explicit = comp.meta.showcaseConfig.sectionOrder;
65
+ const current = sectionOrders.get(section);
66
+ if (explicit !== undefined) {
67
+ sectionOrders.set(section, current === undefined ? explicit : Math.min(current, explicit));
68
+ }
41
69
  }
42
- for (const items of map.values()) {
43
- items.sort((a, b) => {
44
- const orderA = a.kind === 'component'
45
- ? a.data.meta.showcaseConfig.componentOrder ?? Infinity
46
- : a.data.order ?? Infinity;
47
- const orderB = b.kind === 'component'
48
- ? b.data.meta.showcaseConfig.componentOrder ?? Infinity
49
- : b.data.order ?? Infinity;
50
- if (orderA !== orderB)
51
- return orderA - orderB;
52
- const labelA = a.kind === 'component'
53
- ? a.data.meta.showcaseConfig.title
54
- : a.data.title;
55
- const labelB = b.kind === 'component'
56
- ? b.data.meta.showcaseConfig.title
57
- : b.data.title;
58
- return labelA.localeCompare(labelB);
70
+ const result = [];
71
+ for (const [name, catMap] of sections.entries()) {
72
+ const order = sectionOrders.get(name) ?? defaultSectionOrder(name);
73
+ const categories = [];
74
+ for (const [catName, items] of catMap.entries()) {
75
+ items.sort((a, b) => {
76
+ const oa = a.kind === 'component'
77
+ ? a.data.meta.showcaseConfig.componentOrder ?? Infinity
78
+ : Infinity;
79
+ const ob = b.kind === 'component'
80
+ ? b.data.meta.showcaseConfig.componentOrder ?? Infinity
81
+ : Infinity;
82
+ if (oa !== ob)
83
+ return oa - ob;
84
+ const la = a.kind === 'component' ? a.data.meta.showcaseConfig.title : '';
85
+ const lb = b.kind === 'component' ? b.data.meta.showcaseConfig.title : '';
86
+ return la.localeCompare(lb);
87
+ });
88
+ categories.push({ name: catName, items });
89
+ }
90
+ categories.sort((a, b) => {
91
+ const oa = Math.min(...a.items.map((i) => i.kind === 'component'
92
+ ? i.data.meta.showcaseConfig.categoryOrder ?? Infinity
93
+ : Infinity));
94
+ const ob = Math.min(...b.items.map((i) => i.kind === 'component'
95
+ ? i.data.meta.showcaseConfig.categoryOrder ?? Infinity
96
+ : Infinity));
97
+ if (oa !== ob)
98
+ return oa - ob;
99
+ return a.name.localeCompare(b.name);
59
100
  });
101
+ const totalCount = categories.reduce((sum, c) => sum + c.items.length, 0);
102
+ result.push({ name, order, totalCount, categories });
60
103
  }
61
- const sorted = [...map.entries()].sort(([catA, itemsA], [catB, itemsB]) => {
62
- const catOrders = itemsA.map((i) => i.kind === 'component'
63
- ? i.data.meta.showcaseConfig.categoryOrder ?? Infinity
64
- : i.data.categoryOrder ?? Infinity);
65
- const orderA = Math.min(...catOrders);
66
- const catOrdersB = itemsB.map((i) => i.kind === 'component'
67
- ? i.data.meta.showcaseConfig.categoryOrder ?? Infinity
68
- : i.data.categoryOrder ?? Infinity);
69
- const orderB = Math.min(...catOrdersB);
70
- if (orderA !== orderB)
71
- return orderA - orderB;
72
- return catA.localeCompare(catB);
104
+ result.sort((a, b) => {
105
+ if (a.order !== b.order)
106
+ return a.order - b.order;
107
+ return sectionTiebreak(a.name, b.name);
73
108
  });
74
- return new Map(sorted);
109
+ return result;
75
110
  }, /* @ts-ignore */
76
- ...(ngDevMode ? [{ debugName: "categoryTree" }] : /* istanbul ignore next */ []));
111
+ ...(ngDevMode ? [{ debugName: "sectionTree" }] : /* istanbul ignore next */ []));
77
112
  select(comp) {
78
113
  this.activeItem.set({ kind: 'component', data: comp });
79
114
  }
@@ -11,14 +11,22 @@ interface SidebarCategory {
11
11
  export declare class PrismSidebarComponent {
12
12
  protected readonly navigationService: PrismNavigationService;
13
13
  protected readonly searchService: PrismSearchService;
14
- private readonly manifestService;
15
14
  private readonly filterInput;
16
15
  protected onGlobalKey(e: KeyboardEvent): void;
17
16
  private readonly collapsedSet;
18
17
  protected readonly totalPages: import("@angular/core").Signal<number>;
19
18
  protected readonly pageCategories: import("@angular/core").Signal<SidebarCategory[]>;
20
- protected readonly componentCategories: import("@angular/core").Signal<SidebarCategory[]>;
21
- protected readonly totalComponents: import("@angular/core").Signal<number>;
19
+ protected readonly componentSections: import("@angular/core").Signal<{
20
+ name: string;
21
+ icon: string;
22
+ color: string;
23
+ totalCount: number;
24
+ categories: {
25
+ name: string;
26
+ color: string;
27
+ items: NavigationItem[];
28
+ }[];
29
+ }[]>;
22
30
  protected isCollapsed(key: string): boolean;
23
31
  protected toggleCollapse(key: string): void;
24
32
  protected itemKey(item: NavigationItem): string;
@@ -1 +1 @@
1
- {"version":3,"file":"prism-sidebar.component.d.ts","sourceRoot":"","sources":["../../../src/app/sidebar/prism-sidebar.component.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;;AAuBzE,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,qBAkTa,qBAAqB;IAChC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,yBAAkC;IACtE,SAAS,CAAC,QAAQ,CAAC,aAAa,qBAA8B;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0D;IAGtF,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAQ7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6C;IAE1E,SAAS,CAAC,QAAQ,CAAC,UAAU,yCAE1B;IAEH,SAAS,CAAC,QAAQ,CAAC,cAAc,oDAc9B;IAEH,SAAS,CAAC,QAAQ,CAAC,mBAAmB,oDAanC;IAEH,SAAS,CAAC,QAAQ,CAAC,eAAe,yCAEhC;IAEF,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI3C,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAU3C,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAM/C,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAMjD,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,GAAG,SAAS;IAMvE,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAO1D,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO;IAWjD,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAQ9C,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,aAAa;yCA3HV,qBAAqB;2CAArB,qBAAqB;CAgIjC"}
1
+ {"version":3,"file":"prism-sidebar.component.d.ts","sourceRoot":"","sources":["../../../src/app/sidebar/prism-sidebar.component.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;;AAiCzE,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,qBA0Ta,qBAAqB;IAChC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,yBAAkC;IACtE,SAAS,CAAC,QAAQ,CAAC,aAAa,qBAA8B;IAC9D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAC6B;IAGzD,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI;IAa7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6C;IAE1E,SAAS,CAAC,QAAQ,CAAC,UAAU,yCAE1B;IAEH,SAAS,CAAC,QAAQ,CAAC,cAAc,oDAc9B;IAEH,SAAS,CAAC,QAAQ,CAAC,iBAAiB;;;;;;;;;;SAYjC;IAEH,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI3C,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAU3C,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAM/C,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAMjD,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,GAAG,SAAS;IAMvE,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAO1D,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO;IAWjD,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAQ9C,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,aAAa;yCA3HV,qBAAqB;2CAArB,qBAAqB;CAgIjC"}
@@ -2,7 +2,6 @@ import { Component, computed, inject, signal, viewChild, HostListener, ChangeDet
2
2
  import { PrismIconComponent } from '../icons/prism-icon.component.js';
3
3
  import { PrismNavigationService } from '../services/prism-navigation.service.js';
4
4
  import { PrismSearchService } from '../services/prism-search.service.js';
5
- import { PrismManifestService } from '../services/prism-manifest.service.js';
6
5
  import * as i0 from "@angular/core";
7
6
  const _c0 = ["filterInput"];
8
7
  const _forTrack0 = ($index, $item) => $item.name;
@@ -10,9 +9,9 @@ function _forTrack1($index, $item) { /* @ts-ignore */
10
9
  return this.itemKey($item); }
11
10
  function PrismSidebarComponent_Conditional_8_For_8_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
12
11
  const _r4 = i0.ɵɵgetCurrentView();
13
- i0.ɵɵelementStart(0, "button", 18);
12
+ i0.ɵɵelementStart(0, "button", 17);
14
13
  i0.ɵɵlistener("click", function PrismSidebarComponent_Conditional_8_For_8_Conditional_5_For_2_Template_button_click_0_listener() { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.onSelect(item_r5)); });
15
- i0.ɵɵelementStart(1, "span", 19);
14
+ i0.ɵɵelementStart(1, "span", 18);
16
15
  i0.ɵɵtext(2);
17
16
  i0.ɵɵelementEnd()();
18
17
  } if (rf & 2) {
@@ -23,8 +22,8 @@ function PrismSidebarComponent_Conditional_8_For_8_Conditional_5_For_2_Template(
23
22
  i0.ɵɵtextInterpolate(ctx_r2.itemLabel(item_r5));
24
23
  } }
25
24
  function PrismSidebarComponent_Conditional_8_For_8_Conditional_5_Template(rf, ctx) { if (rf & 1) {
26
- i0.ɵɵelementStart(0, "div", 16);
27
- i0.ɵɵrepeaterCreate(1, PrismSidebarComponent_Conditional_8_For_8_Conditional_5_For_2_Template, 3, 3, "button", 17, _forTrack1, true);
25
+ i0.ɵɵelementStart(0, "div", 15);
26
+ i0.ɵɵrepeaterCreate(1, PrismSidebarComponent_Conditional_8_For_8_Conditional_5_For_2_Template, 3, 3, "button", 16, _forTrack1, true);
28
27
  i0.ɵɵelementEnd();
29
28
  } if (rf & 2) {
30
29
  const cat_r2 = i0.ɵɵnextContext().$implicit;
@@ -33,12 +32,12 @@ function PrismSidebarComponent_Conditional_8_For_8_Conditional_5_Template(rf, ct
33
32
  } }
34
33
  function PrismSidebarComponent_Conditional_8_For_8_Template(rf, ctx) { if (rf & 1) {
35
34
  const _r1 = i0.ɵɵgetCurrentView();
36
- i0.ɵɵelementStart(0, "div", 12)(1, "button", 13);
35
+ i0.ɵɵelementStart(0, "div", 11)(1, "button", 12);
37
36
  i0.ɵɵlistener("click", function PrismSidebarComponent_Conditional_8_For_8_Template_button_click_1_listener() { const cat_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleCollapse("page:" + cat_r2.name)); });
38
- i0.ɵɵelement(2, "prism-icon", 14)(3, "span", 15);
37
+ i0.ɵɵelement(2, "prism-icon", 13)(3, "span", 14);
39
38
  i0.ɵɵtext(4);
40
39
  i0.ɵɵelementEnd();
41
- i0.ɵɵconditionalCreate(5, PrismSidebarComponent_Conditional_8_For_8_Conditional_5_Template, 3, 0, "div", 16);
40
+ i0.ɵɵconditionalCreate(5, PrismSidebarComponent_Conditional_8_For_8_Conditional_5_Template, 3, 0, "div", 15);
42
41
  i0.ɵɵelementEnd();
43
42
  } if (rf & 2) {
44
43
  const cat_r2 = ctx.$implicit;
@@ -56,14 +55,14 @@ function PrismSidebarComponent_Conditional_8_For_8_Template(rf, ctx) { if (rf &
56
55
  i0.ɵɵconditional(!ctx_r2.isCollapsed("page:" + cat_r2.name) ? 5 : -1);
57
56
  } }
58
57
  function PrismSidebarComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
59
- i0.ɵɵelementStart(0, "div", 6)(1, "div", 9)(2, "span", 10);
60
- i0.ɵɵelement(3, "prism-icon", 11);
58
+ i0.ɵɵelementStart(0, "div", 6)(1, "div", 7)(2, "span", 8);
59
+ i0.ɵɵelement(3, "prism-icon", 9);
61
60
  i0.ɵɵtext(4, " Pages ");
62
61
  i0.ɵɵelementEnd();
63
62
  i0.ɵɵelementStart(5, "span");
64
63
  i0.ɵɵtext(6);
65
64
  i0.ɵɵelementEnd()();
66
- i0.ɵɵrepeaterCreate(7, PrismSidebarComponent_Conditional_8_For_8_Template, 6, 8, "div", 8, _forTrack0);
65
+ i0.ɵɵrepeaterCreate(7, PrismSidebarComponent_Conditional_8_For_8_Template, 6, 8, "div", 10, _forTrack0);
67
66
  i0.ɵɵelementEnd();
68
67
  } if (rf & 2) {
69
68
  const ctx_r2 = i0.ɵɵnextContext();
@@ -74,74 +73,60 @@ function PrismSidebarComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
74
73
  i0.ɵɵadvance();
75
74
  i0.ɵɵrepeater(ctx_r2.pageCategories());
76
75
  } }
77
- function PrismSidebarComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
78
- i0.ɵɵelementStart(0, "div", 7)(1, "span", 20);
79
- i0.ɵɵelement(2, "prism-icon", 21);
80
- i0.ɵɵtext(3, " Components ");
81
- i0.ɵɵelementEnd();
82
- i0.ɵɵelementStart(4, "span");
83
- i0.ɵɵtext(5);
84
- i0.ɵɵelementEnd()();
85
- } if (rf & 2) {
86
- const ctx_r2 = i0.ɵɵnextContext();
87
- i0.ɵɵadvance(2);
88
- i0.ɵɵproperty("size", 10);
89
- i0.ɵɵadvance(3);
90
- i0.ɵɵtextInterpolate(ctx_r2.totalComponents());
91
- } }
92
- function PrismSidebarComponent_For_11_Conditional_7_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
76
+ function PrismSidebarComponent_For_10_For_7_Conditional_7_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
93
77
  i0.ɵɵelementStart(0, "span", 25);
94
78
  i0.ɵɵelement(1, "span", 26);
95
79
  i0.ɵɵelementEnd();
96
80
  } }
97
- function PrismSidebarComponent_For_11_Conditional_7_For_2_Template(rf, ctx) { if (rf & 1) {
98
- const _r8 = i0.ɵɵgetCurrentView();
99
- i0.ɵɵelementStart(0, "button", 18);
100
- i0.ɵɵlistener("click", function PrismSidebarComponent_For_11_Conditional_7_For_2_Template_button_click_0_listener() { const item_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onSelect(item_r9)); });
81
+ function PrismSidebarComponent_For_10_For_7_Conditional_7_For_2_Template(rf, ctx) { if (rf & 1) {
82
+ const _r9 = i0.ɵɵgetCurrentView();
83
+ i0.ɵɵelementStart(0, "button", 17);
84
+ i0.ɵɵlistener("click", function PrismSidebarComponent_For_10_For_7_Conditional_7_For_2_Template_button_click_0_listener() { const item_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.onSelect(item_r10)); });
101
85
  i0.ɵɵelement(1, "prism-icon", 24);
102
- i0.ɵɵelementStart(2, "span", 19);
86
+ i0.ɵɵelementStart(2, "span", 18);
103
87
  i0.ɵɵtext(3);
104
88
  i0.ɵɵelementEnd();
105
- i0.ɵɵconditionalCreate(4, PrismSidebarComponent_For_11_Conditional_7_For_2_Conditional_4_Template, 2, 0, "span", 25);
89
+ i0.ɵɵconditionalCreate(4, PrismSidebarComponent_For_10_For_7_Conditional_7_For_2_Conditional_4_Template, 2, 0, "span", 25);
106
90
  i0.ɵɵelementEnd();
107
91
  } if (rf & 2) {
108
- const item_r9 = ctx.$implicit;
109
- const ctx_r2 = i0.ɵɵnextContext(3);
110
- i0.ɵɵclassProp("sb-item--active", ctx_r2.isActive(item_r9))("sb-item--deprecated", ctx_r2.itemStatus(item_r9) === "deprecated");
111
- i0.ɵɵattribute("title", ctx_r2.itemTooltip(item_r9));
92
+ const item_r10 = ctx.$implicit;
93
+ const ctx_r2 = i0.ɵɵnextContext(4);
94
+ i0.ɵɵclassProp("sb-item--active", ctx_r2.isActive(item_r10))("sb-item--deprecated", ctx_r2.itemStatus(item_r10) === "deprecated");
95
+ i0.ɵɵattribute("title", ctx_r2.itemTooltip(item_r10));
112
96
  i0.ɵɵadvance();
113
97
  i0.ɵɵproperty("size", 12);
114
98
  i0.ɵɵadvance(2);
115
- i0.ɵɵtextInterpolate(ctx_r2.itemLabel(item_r9));
99
+ i0.ɵɵtextInterpolate(ctx_r2.itemLabel(item_r10));
116
100
  i0.ɵɵadvance();
117
- i0.ɵɵconditional(ctx_r2.itemStatus(item_r9) === "wip" ? 4 : -1);
101
+ i0.ɵɵconditional(ctx_r2.itemStatus(item_r10) === "wip" ? 4 : -1);
118
102
  } }
119
- function PrismSidebarComponent_For_11_Conditional_7_Template(rf, ctx) { if (rf & 1) {
120
- i0.ɵɵelementStart(0, "div", 16);
121
- i0.ɵɵrepeaterCreate(1, PrismSidebarComponent_For_11_Conditional_7_For_2_Template, 5, 8, "button", 23, _forTrack1, true);
103
+ function PrismSidebarComponent_For_10_For_7_Conditional_7_Template(rf, ctx) { if (rf & 1) {
104
+ i0.ɵɵelementStart(0, "div", 15);
105
+ i0.ɵɵrepeaterCreate(1, PrismSidebarComponent_For_10_For_7_Conditional_7_For_2_Template, 5, 8, "button", 23, _forTrack1, true);
122
106
  i0.ɵɵelementEnd();
123
107
  } if (rf & 2) {
124
108
  const cat_r7 = i0.ɵɵnextContext().$implicit;
125
109
  i0.ɵɵadvance();
126
110
  i0.ɵɵrepeater(cat_r7.items);
127
111
  } }
128
- function PrismSidebarComponent_For_11_Template(rf, ctx) { if (rf & 1) {
112
+ function PrismSidebarComponent_For_10_For_7_Template(rf, ctx) { if (rf & 1) {
129
113
  const _r6 = i0.ɵɵgetCurrentView();
130
- i0.ɵɵelementStart(0, "div", 12)(1, "button", 13);
131
- i0.ɵɵlistener("click", function PrismSidebarComponent_For_11_Template_button_click_1_listener() { const cat_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleCollapse("comp:" + cat_r7.name)); });
132
- i0.ɵɵelement(2, "prism-icon", 14)(3, "span", 15);
114
+ i0.ɵɵelementStart(0, "div", 11)(1, "button", 12);
115
+ i0.ɵɵlistener("click", function PrismSidebarComponent_For_10_For_7_Template_button_click_1_listener() { const cat_r7 = i0.ɵɵrestoreView(_r6).$implicit; const section_r8 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleCollapse("sec:" + section_r8.name + ":" + cat_r7.name)); });
116
+ i0.ɵɵelement(2, "prism-icon", 13)(3, "span", 14);
133
117
  i0.ɵɵtext(4);
134
118
  i0.ɵɵelementStart(5, "span", 22);
135
119
  i0.ɵɵtext(6);
136
120
  i0.ɵɵelementEnd()();
137
- i0.ɵɵconditionalCreate(7, PrismSidebarComponent_For_11_Conditional_7_Template, 3, 0, "div", 16);
121
+ i0.ɵɵconditionalCreate(7, PrismSidebarComponent_For_10_For_7_Conditional_7_Template, 3, 0, "div", 15);
138
122
  i0.ɵɵelementEnd();
139
123
  } if (rf & 2) {
140
124
  const cat_r7 = ctx.$implicit;
125
+ const section_r8 = i0.ɵɵnextContext().$implicit;
141
126
  const ctx_r2 = i0.ɵɵnextContext();
142
- i0.ɵɵclassProp("sb-group--collapsed", ctx_r2.isCollapsed("comp:" + cat_r7.name));
127
+ i0.ɵɵclassProp("sb-group--collapsed", ctx_r2.isCollapsed("sec:" + section_r8.name + ":" + cat_r7.name));
143
128
  i0.ɵɵadvance();
144
- i0.ɵɵattribute("aria-expanded", !ctx_r2.isCollapsed("comp:" + cat_r7.name));
129
+ i0.ɵɵattribute("aria-expanded", !ctx_r2.isCollapsed("sec:" + section_r8.name + ":" + cat_r7.name));
145
130
  i0.ɵɵadvance();
146
131
  i0.ɵɵproperty("size", 10);
147
132
  i0.ɵɵadvance();
@@ -151,7 +136,27 @@ function PrismSidebarComponent_For_11_Template(rf, ctx) { if (rf & 1) {
151
136
  i0.ɵɵadvance(2);
152
137
  i0.ɵɵtextInterpolate(cat_r7.items.length);
153
138
  i0.ɵɵadvance();
154
- i0.ɵɵconditional(!ctx_r2.isCollapsed("comp:" + cat_r7.name) ? 7 : -1);
139
+ i0.ɵɵconditional(!ctx_r2.isCollapsed("sec:" + section_r8.name + ":" + cat_r7.name) ? 7 : -1);
140
+ } }
141
+ function PrismSidebarComponent_For_10_Template(rf, ctx) { if (rf & 1) {
142
+ i0.ɵɵelementStart(0, "div", 19)(1, "span", 20);
143
+ i0.ɵɵelement(2, "prism-icon", 21);
144
+ i0.ɵɵtext(3);
145
+ i0.ɵɵelementEnd();
146
+ i0.ɵɵelementStart(4, "span");
147
+ i0.ɵɵtext(5);
148
+ i0.ɵɵelementEnd()();
149
+ i0.ɵɵrepeaterCreate(6, PrismSidebarComponent_For_10_For_7_Template, 8, 9, "div", 10, _forTrack0);
150
+ } if (rf & 2) {
151
+ const section_r8 = ctx.$implicit;
152
+ i0.ɵɵadvance(2);
153
+ i0.ɵɵproperty("name", section_r8.icon)("size", 10);
154
+ i0.ɵɵadvance();
155
+ i0.ɵɵtextInterpolate1(" ", section_r8.name, " ");
156
+ i0.ɵɵadvance(2);
157
+ i0.ɵɵtextInterpolate(section_r8.totalCount);
158
+ i0.ɵɵadvance();
159
+ i0.ɵɵrepeater(section_r8.categories);
155
160
  } }
156
161
  const STORAGE_KEY = 'ng-prism-sidebar-collapsed';
157
162
  const CATEGORY_COLORS = {
@@ -163,6 +168,14 @@ const CATEGORY_COLORS = {
163
168
  Overlay: '#c084fc',
164
169
  Directives: '#ec4899',
165
170
  };
171
+ const SECTION_ICONS = {
172
+ Components: 'box',
173
+ Directives: 'zap',
174
+ };
175
+ const DEFAULT_SECTION_ICON = 'box-select';
176
+ function sectionIcon(name) {
177
+ return SECTION_ICONS[name] ?? DEFAULT_SECTION_ICON;
178
+ }
166
179
  function categoryColor(name) {
167
180
  if (CATEGORY_COLORS[name])
168
181
  return CATEGORY_COLORS[name];
@@ -175,14 +188,15 @@ function categoryColor(name) {
175
188
  export class PrismSidebarComponent {
176
189
  navigationService = inject(PrismNavigationService);
177
190
  searchService = inject(PrismSearchService);
178
- manifestService = inject(PrismManifestService);
179
191
  filterInput = viewChild('filterInput', /* @ts-ignore */
180
192
  ...(ngDevMode ? [{ debugName: "filterInput" }] : /* istanbul ignore next */ []));
181
193
  onGlobalKey(e) {
182
194
  if (e.key !== '/' || e.ctrlKey || e.metaKey || e.altKey)
183
195
  return;
184
196
  const tag = e.target.tagName;
185
- if (tag === 'INPUT' || tag === 'TEXTAREA' || e.target.isContentEditable)
197
+ if (tag === 'INPUT' ||
198
+ tag === 'TEXTAREA' ||
199
+ e.target.isContentEditable)
186
200
  return;
187
201
  e.preventDefault();
188
202
  this.filterInput()?.nativeElement.focus();
@@ -209,24 +223,20 @@ export class PrismSidebarComponent {
209
223
  }));
210
224
  }, /* @ts-ignore */
211
225
  ...(ngDevMode ? [{ debugName: "pageCategories" }] : /* istanbul ignore next */ []));
212
- componentCategories = computed(() => {
213
- const tree = this.navigationService.categoryTree();
214
- const result = [];
215
- for (const [catName, items] of tree.entries()) {
216
- const compItems = items.filter((i) => i.kind === 'component');
217
- if (compItems.length === 0)
218
- continue;
219
- result.push({
220
- name: catName,
221
- color: categoryColor(catName),
222
- items: compItems,
223
- });
224
- }
225
- return result;
226
+ componentSections = computed(() => {
227
+ return this.navigationService.sectionTree().map((section) => ({
228
+ name: section.name,
229
+ icon: sectionIcon(section.name),
230
+ color: categoryColor(section.name),
231
+ totalCount: section.totalCount,
232
+ categories: section.categories.map((cat) => ({
233
+ name: cat.name,
234
+ color: categoryColor(cat.name),
235
+ items: cat.items,
236
+ })),
237
+ }));
226
238
  }, /* @ts-ignore */
227
- ...(ngDevMode ? [{ debugName: "componentCategories" }] : /* istanbul ignore next */ []));
228
- totalComponents = computed(() => this.manifestService.manifest().components.length, /* @ts-ignore */
229
- ...(ngDevMode ? [{ debugName: "totalComponents" }] : /* istanbul ignore next */ []));
239
+ ...(ngDevMode ? [{ debugName: "componentSections" }] : /* istanbul ignore next */ []));
230
240
  isCollapsed(key) {
231
241
  return this.collapsedSet().has(key);
232
242
  }
@@ -303,7 +313,7 @@ export class PrismSidebarComponent {
303
313
  i0.ɵɵqueryAdvance();
304
314
  } }, hostBindings: function PrismSidebarComponent_HostBindings(rf, ctx) { if (rf & 1) {
305
315
  i0.ɵɵlistener("keydown", function PrismSidebarComponent_keydown_HostBindingHandler($event) { return ctx.onGlobalKey($event); }, i0.ɵɵresolveDocument);
306
- } }, decls: 12, vars: 4, consts: [["filterInput", ""], [1, "prism-sidebar"], [1, "sb-filter"], ["name", "search", 3, "size"], ["placeholder", "Filter components\u2026", 3, "input", "value"], [1, "sb-scroll"], [1, "sb-pinned"], [1, "sb-section-head"], [1, "sb-group", 3, "sb-group--collapsed"], [1, "sb-pinned-head"], [1, "sb-pinned-head-l"], ["name", "pin", 1, "sb-pinned-pin", 3, "size"], [1, "sb-group"], [1, "sb-group-head", 3, "click"], ["name", "chevron-down", 3, "size"], [1, "sb-group-chip"], [1, "sb-group-body"], [1, "sb-item", 3, "sb-item--active"], [1, "sb-item", 3, "click"], [1, "sb-item-name"], [1, "sb-section-head-l"], ["name", "box", 1, "sb-section-icon", 3, "size"], [1, "sb-group-count"], [1, "sb-item", 3, "sb-item--active", "sb-item--deprecated"], ["name", "box", 1, "sb-item-icon", 3, "size"], ["title", "Work in progress", 1, "sb-item-status"], [1, "sb-item-status-dot"]], template: function PrismSidebarComponent_Template(rf, ctx) { if (rf & 1) {
316
+ } }, decls: 11, vars: 3, consts: [["filterInput", ""], [1, "prism-sidebar"], [1, "sb-filter"], ["name", "search", 3, "size"], ["placeholder", "Filter components\u2026", 3, "input", "value"], [1, "sb-scroll"], [1, "sb-pinned"], [1, "sb-pinned-head"], [1, "sb-pinned-head-l"], ["name", "pin", 1, "sb-pinned-pin", 3, "size"], [1, "sb-group", 3, "sb-group--collapsed"], [1, "sb-group"], [1, "sb-group-head", 3, "click"], ["name", "chevron-down", 3, "size"], [1, "sb-group-chip"], [1, "sb-group-body"], [1, "sb-item", 3, "sb-item--active"], [1, "sb-item", 3, "click"], [1, "sb-item-name"], [1, "sb-section-head"], [1, "sb-section-head-l"], [1, "sb-section-icon", 3, "name", "size"], [1, "sb-group-count"], [1, "sb-item", 3, "sb-item--active", "sb-item--deprecated"], ["name", "box", 1, "sb-item-icon", 3, "size"], ["title", "Work in progress", 1, "sb-item-status"], [1, "sb-item-status-dot"]], template: function PrismSidebarComponent_Template(rf, ctx) { if (rf & 1) {
307
317
  i0.ɵɵelementStart(0, "nav", 1)(1, "div", 2);
308
318
  i0.ɵɵelement(2, "prism-icon", 3);
309
319
  i0.ɵɵelementStart(3, "input", 4, 0);
@@ -314,8 +324,7 @@ export class PrismSidebarComponent {
314
324
  i0.ɵɵelementEnd()();
315
325
  i0.ɵɵelementStart(7, "div", 5);
316
326
  i0.ɵɵconditionalCreate(8, PrismSidebarComponent_Conditional_8_Template, 9, 2, "div", 6);
317
- i0.ɵɵconditionalCreate(9, PrismSidebarComponent_Conditional_9_Template, 6, 2, "div", 7);
318
- i0.ɵɵrepeaterCreate(10, PrismSidebarComponent_For_11_Template, 8, 9, "div", 8, _forTrack0);
327
+ i0.ɵɵrepeaterCreate(9, PrismSidebarComponent_For_10_Template, 8, 4, null, null, _forTrack0);
319
328
  i0.ɵɵelementEnd()();
320
329
  } if (rf & 2) {
321
330
  i0.ɵɵadvance(2);
@@ -325,9 +334,7 @@ export class PrismSidebarComponent {
325
334
  i0.ɵɵadvance(5);
326
335
  i0.ɵɵconditional(ctx.pageCategories().length > 0 ? 8 : -1);
327
336
  i0.ɵɵadvance();
328
- i0.ɵɵconditional(ctx.componentCategories().length > 0 ? 9 : -1);
329
- i0.ɵɵadvance();
330
- i0.ɵɵrepeater(ctx.componentCategories());
337
+ i0.ɵɵrepeater(ctx.componentSections());
331
338
  } }, dependencies: [PrismIconComponent], styles: [".prism-sidebar[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n }\n\n .sb-filter[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px;\n padding: 0 10px;\n height: 30px;\n background: var(--prism-input-bg);\n border: 1px solid var(--prism-border);\n border-radius: 6px;\n color: var(--prism-text-muted);\n }\n .sb-filter[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n background: transparent;\n border: 0;\n outline: none;\n font-size: var(--fs-md);\n color: var(--prism-text);\n font-family: var(--font-sans);\n }\n .sb-filter[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--prism-text-muted); }\n .sb-filter[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--prism-text-ghost);\n padding: 1px 5px;\n border: 1px solid var(--prism-border);\n border-radius: 3px;\n }\n\n .sb-scroll[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 10px 0 16px;\n padding-top: 0;\n }\n .sb-scroll[_ngcontent-%COMP%]::-webkit-scrollbar { width: 8px; }\n .sb-scroll[_ngcontent-%COMP%]::-webkit-scrollbar-thumb { background: var(--prism-border-strong); border-radius: 4px; }\n .sb-scroll[_ngcontent-%COMP%]::-webkit-scrollbar-track { background: transparent; }\n\n .sb-pinned[_ngcontent-%COMP%] {\n padding: 0 0 10px;\n margin-bottom: 4px;\n border-bottom: 1px solid var(--prism-border);\n border-top: 1px solid var(--prism-border);\n }\n .sb-section-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px 6px;\n font-size: 10.5px;\n font-weight: 700;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n color: var(--prism-text-ghost);\n margin-top: 6px;\n }\n .sb-section-head-l[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 6px; }\n .sb-section-icon[_ngcontent-%COMP%] { color: var(--prism-primary); }\n .sb-pinned-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px 6px;\n margin-top: 6px;\n font-size: 10.5px;\n font-weight: 700;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n color: var(--prism-text-ghost);\n }\n .sb-pinned-head-l[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 6px; }\n .sb-pinned-pin[_ngcontent-%COMP%] { color: var(--prism-accent); }\n\n .sb-group[_ngcontent-%COMP%] { margin-bottom: 4px; }\n .sb-group-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 8px 14px 6px;\n font-size: 10.5px;\n font-weight: 700;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n color: var(--prism-text-ghost);\n cursor: pointer;\n user-select: none;\n background: none;\n border: none;\n text-align: left;\n font-family: var(--font-sans);\n }\n .sb-group-head[_ngcontent-%COMP%] prism-icon[_ngcontent-%COMP%] {\n transition: transform var(--dur-fast);\n color: var(--prism-text-ghost);\n }\n .sb-group--collapsed[_ngcontent-%COMP%] .sb-group-head[_ngcontent-%COMP%] prism-icon[_ngcontent-%COMP%] { transform: rotate(-90deg); }\n\n .sb-group-chip[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 2px;\n background: var(--chip, var(--prism-primary));\n box-shadow: 0 0 6px var(--chip, var(--prism-primary));\n }\n .sb-group-count[_ngcontent-%COMP%] {\n margin-left: auto;\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--prism-text-ghost);\n font-weight: 500;\n }\n\n .sb-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n height: 30px;\n padding: 0 14px 0 28px;\n font-size: 13px;\n color: var(--prism-text-2);\n cursor: pointer;\n border: none;\n border-left: 2px solid transparent;\n background: none;\n position: relative;\n transition: background var(--dur-fast), color var(--dur-fast);\n text-align: left;\n font-family: var(--font-sans);\n }\n .sb-item[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--prism-primary) 5%, transparent);\n color: var(--prism-text);\n }\n .sb-item--active[_ngcontent-%COMP%] {\n border-left-color: var(--prism-primary);\n background: color-mix(in srgb, var(--prism-primary) 12%, transparent);\n color: var(--prism-text);\n font-weight: 500;\n }\n .sb-item--active[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: -1px;\n top: 0;\n bottom: 0;\n width: 3px;\n background: linear-gradient(180deg, var(--prism-primary-from), var(--prism-primary-to));\n }\n .sb-item-icon[_ngcontent-%COMP%] { flex: 0 0 12px; opacity: 0.7; }\n .sb-item-name[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sb-item-status[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n margin-left: auto;\n display: flex;\n align-items: center;\n }\n .sb-item-status-dot[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--prism-warn);\n }\n\n .sb-item--deprecated[_ngcontent-%COMP%] .sb-item-name[_ngcontent-%COMP%] {\n text-decoration: line-through;\n text-decoration-thickness: 1px;\n color: var(--prism-text-ghost);\n opacity: 0.7;\n }\n\n\n [_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 2px;\n }"] });
332
339
  }
333
340
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrismSidebarComponent, [{
@@ -385,30 +392,38 @@ export class PrismSidebarComponent {
385
392
  </div>
386
393
  }
387
394
  </div>
388
- } @if (componentCategories().length > 0) {
395
+ } @for (section of componentSections(); track section.name) {
389
396
  <div class="sb-section-head">
390
397
  <span class="sb-section-head-l">
391
- <prism-icon name="box" [size]="10" class="sb-section-icon" />
392
- Components
398
+ <prism-icon
399
+ [name]="section.icon"
400
+ [size]="10"
401
+ class="sb-section-icon"
402
+ />
403
+ {{ section.name }}
393
404
  </span>
394
- <span>{{ totalComponents() }}</span>
405
+ <span>{{ section.totalCount }}</span>
395
406
  </div>
396
- } @for (cat of componentCategories(); track cat.name) {
407
+ @for (cat of section.categories; track cat.name) {
397
408
  <div
398
409
  class="sb-group"
399
- [class.sb-group--collapsed]="isCollapsed('comp:' + cat.name)"
410
+ [class.sb-group--collapsed]="
411
+ isCollapsed('sec:' + section.name + ':' + cat.name)
412
+ "
400
413
  >
401
414
  <button
402
415
  class="sb-group-head"
403
- (click)="toggleCollapse('comp:' + cat.name)"
404
- [attr.aria-expanded]="!isCollapsed('comp:' + cat.name)"
416
+ (click)="toggleCollapse('sec:' + section.name + ':' + cat.name)"
417
+ [attr.aria-expanded]="
418
+ !isCollapsed('sec:' + section.name + ':' + cat.name)
419
+ "
405
420
  >
406
421
  <prism-icon name="chevron-down" [size]="10" />
407
422
  <span class="sb-group-chip" [style.--chip]="cat.color"></span>
408
423
  {{ cat.name }}
409
424
  <span class="sb-group-count">{{ cat.items.length }}</span>
410
425
  </button>
411
- @if (!isCollapsed('comp:' + cat.name)) {
426
+ @if (!isCollapsed('sec:' + section.name + ':' + cat.name)) {
412
427
  <div class="sb-group-body">
413
428
  @for (item of cat.items; track itemKey(item)) {
414
429
  <button
@@ -430,7 +445,7 @@ export class PrismSidebarComponent {
430
445
  </div>
431
446
  }
432
447
  </div>
433
- }
448
+ } }
434
449
  </div>
435
450
  </nav>
436
451
  `, styles: ["\n .prism-sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n }\n\n .sb-filter {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px;\n padding: 0 10px;\n height: 30px;\n background: var(--prism-input-bg);\n border: 1px solid var(--prism-border);\n border-radius: 6px;\n color: var(--prism-text-muted);\n }\n .sb-filter input {\n flex: 1;\n min-width: 0;\n background: transparent;\n border: 0;\n outline: none;\n font-size: var(--fs-md);\n color: var(--prism-text);\n font-family: var(--font-sans);\n }\n .sb-filter input::placeholder { color: var(--prism-text-muted); }\n .sb-filter kbd {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--prism-text-ghost);\n padding: 1px 5px;\n border: 1px solid var(--prism-border);\n border-radius: 3px;\n }\n\n .sb-scroll {\n flex: 1;\n overflow-y: auto;\n padding: 10px 0 16px;\n padding-top: 0;\n }\n .sb-scroll::-webkit-scrollbar { width: 8px; }\n .sb-scroll::-webkit-scrollbar-thumb { background: var(--prism-border-strong); border-radius: 4px; }\n .sb-scroll::-webkit-scrollbar-track { background: transparent; }\n\n .sb-pinned {\n padding: 0 0 10px;\n margin-bottom: 4px;\n border-bottom: 1px solid var(--prism-border);\n border-top: 1px solid var(--prism-border);\n }\n .sb-section-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px 6px;\n font-size: 10.5px;\n font-weight: 700;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n color: var(--prism-text-ghost);\n margin-top: 6px;\n }\n .sb-section-head-l { display: flex; align-items: center; gap: 6px; }\n .sb-section-icon { color: var(--prism-primary); }\n .sb-pinned-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 14px 6px;\n margin-top: 6px;\n font-size: 10.5px;\n font-weight: 700;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n color: var(--prism-text-ghost);\n }\n .sb-pinned-head-l { display: flex; align-items: center; gap: 6px; }\n .sb-pinned-pin { color: var(--prism-accent); }\n\n .sb-group { margin-bottom: 4px; }\n .sb-group-head {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 8px 14px 6px;\n font-size: 10.5px;\n font-weight: 700;\n letter-spacing: 0.09em;\n text-transform: uppercase;\n color: var(--prism-text-ghost);\n cursor: pointer;\n user-select: none;\n background: none;\n border: none;\n text-align: left;\n font-family: var(--font-sans);\n }\n .sb-group-head prism-icon {\n transition: transform var(--dur-fast);\n color: var(--prism-text-ghost);\n }\n .sb-group--collapsed .sb-group-head prism-icon { transform: rotate(-90deg); }\n\n .sb-group-chip {\n width: 6px;\n height: 6px;\n border-radius: 2px;\n background: var(--chip, var(--prism-primary));\n box-shadow: 0 0 6px var(--chip, var(--prism-primary));\n }\n .sb-group-count {\n margin-left: auto;\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--prism-text-ghost);\n font-weight: 500;\n }\n\n .sb-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n height: 30px;\n padding: 0 14px 0 28px;\n font-size: 13px;\n color: var(--prism-text-2);\n cursor: pointer;\n border: none;\n border-left: 2px solid transparent;\n background: none;\n position: relative;\n transition: background var(--dur-fast), color var(--dur-fast);\n text-align: left;\n font-family: var(--font-sans);\n }\n .sb-item:hover {\n background: color-mix(in srgb, var(--prism-primary) 5%, transparent);\n color: var(--prism-text);\n }\n .sb-item--active {\n border-left-color: var(--prism-primary);\n background: color-mix(in srgb, var(--prism-primary) 12%, transparent);\n color: var(--prism-text);\n font-weight: 500;\n }\n .sb-item--active::before {\n content: '';\n position: absolute;\n left: -1px;\n top: 0;\n bottom: 0;\n width: 3px;\n background: linear-gradient(180deg, var(--prism-primary-from), var(--prism-primary-to));\n }\n .sb-item-icon { flex: 0 0 12px; opacity: 0.7; }\n .sb-item-name {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sb-item-status {\n flex: 0 0 auto;\n margin-left: auto;\n display: flex;\n align-items: center;\n }\n .sb-item-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--prism-warn);\n }\n\n .sb-item--deprecated .sb-item-name {\n text-decoration: line-through;\n text-decoration-thickness: 1px;\n color: var(--prism-text-ghost);\n opacity: 0.7;\n }\n\n\n :focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 2px;\n }\n "] }]
@@ -438,4 +453,4 @@ export class PrismSidebarComponent {
438
453
  type: HostListener,
439
454
  args: ['document:keydown', ['$event']]
440
455
  }] }); })();
441
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismSidebarComponent, { className: "PrismSidebarComponent", filePath: "app/sidebar/prism-sidebar.component.ts", lineNumber: 351 }); })();
456
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismSidebarComponent, { className: "PrismSidebarComponent", filePath: "app/sidebar/prism-sidebar.component.ts", lineNumber: 368 }); })();
@@ -1,6 +1,7 @@
1
1
  export interface ParsedHost {
2
2
  tag: string;
3
3
  attrs: string;
4
+ content?: string;
4
5
  }
5
6
  export declare function parseHostString(host: string): ParsedHost | null;
6
7
  //# sourceMappingURL=host-parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-parser.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest/host-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAS/D"}
1
+ {"version":3,"file":"host-parser.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest/host-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CA4B/D"}
@@ -1,9 +1,20 @@
1
1
  export function parseHostString(host) {
2
2
  const trimmed = host.trim();
3
- const match = trimmed.match(/^<\s*([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^>]*?)?)\s*\/?\s*>$/);
4
- if (!match)
5
- return null;
6
- const tag = match[1];
7
- const attrs = match[2].trim();
8
- return { tag, attrs };
3
+ const open = trimmed.match(/^<\s*([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^>]*?)?)\s*\/?\s*>$/);
4
+ if (open) {
5
+ return { tag: open[1], attrs: open[2].trim() };
6
+ }
7
+ const wrapped = trimmed.match(/^<\s*([a-zA-Z][a-zA-Z0-9-]*)((?:\s+[^>]*?)?)\s*>([\s\S]*?)<\/\s*\1\s*>$/);
8
+ if (wrapped) {
9
+ return {
10
+ tag: wrapped[1],
11
+ attrs: wrapped[2].trim(),
12
+ content: wrapped[3],
13
+ };
14
+ }
15
+ if (trimmed.length > 0) {
16
+ console.warn(`[ng-prism] @Showcase host="${host}" could not be parsed and will fall back to <div>. ` +
17
+ `Supported forms: "<tag>", "<tag attrs>", "<tag />", or "<tag>text</tag>".`);
18
+ }
19
+ return null;
9
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-manifest.generator.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest/runtime-manifest.generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAa,MAAM,8BAA8B,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAIjE,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAiID,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,sBAAsB,GAC9B,MAAM,CAmFR"}
1
+ {"version":3,"file":"runtime-manifest.generator.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest/runtime-manifest.generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAa,MAAM,8BAA8B,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAIjE,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAqID,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,sBAAsB,GAC9B,MAAM,CAmFR"}
@@ -51,10 +51,12 @@ function generateWrapperClass(comp) {
51
51
  let tag;
52
52
  let attrs;
53
53
  let importsArray;
54
+ let hostContentDefault = '';
54
55
  if (typeof host === 'string') {
55
56
  const parsed = parseHostString(host);
56
57
  tag = parsed?.tag ?? 'div';
57
58
  attrs = parsed?.attrs ? ` ${parsed.attrs}` : '';
59
+ hostContentDefault = parsed?.content ?? '';
58
60
  importsArray = `[${comp.className}]`;
59
61
  }
60
62
  else if (host && typeof host === 'object') {
@@ -85,7 +87,7 @@ function generateWrapperClass(comp) {
85
87
  for (const o of comp.outputs) {
86
88
  members.push(` ${o.name} = output();`);
87
89
  }
88
- members.push(` __prismContent__ = input('');`);
90
+ members.push(` __prismContent__ = input(${JSON.stringify(hostContentDefault)});`);
89
91
  const lines = [
90
92
  `@Component({`,
91
93
  ` standalone: true,`,
@@ -86,6 +86,11 @@ function extractShowcaseConfig(decorator, className) {
86
86
  config.description = obj['description'];
87
87
  if (obj['category'])
88
88
  config.category = obj['category'];
89
+ if (obj['section'])
90
+ config.section = obj['section'];
91
+ if (typeof obj['sectionOrder'] === 'number') {
92
+ config.sectionOrder = obj['sectionOrder'];
93
+ }
89
94
  if (obj['tags'])
90
95
  config.tags = obj['tags'];
91
96
  if (obj['meta'])
@@ -34,6 +34,18 @@ export interface ShowcaseConfig<T = unknown> {
34
34
  categoryOrder?: number;
35
35
  /** Controls the order of this component within its category (lower = higher). Components without this sort alphabetically after ordered ones. */
36
36
  componentOrder?: number;
37
+ /**
38
+ * Top-level section in the sidebar. Auto-detected if omitted:
39
+ * `@Directive` → 'Directives', otherwise 'Components'. Free-form string —
40
+ * any value creates a new top-level section (e.g. 'Pipes', 'Utilities').
41
+ */
42
+ section?: string;
43
+ /**
44
+ * Sort order of this section in the sidebar (lower = higher in list).
45
+ * The section's effective order is the minimum `sectionOrder` of all its items.
46
+ * Defaults: 'Components' → 0, 'Directives' → 10, all others → 100.
47
+ */
48
+ sectionOrder?: number;
37
49
  /** Predefined variants shown as tabs */
38
50
  variants?: Variant<T>[];
39
51
  /** Tags for search and filtering */
@@ -1 +1 @@
1
- {"version":3,"file":"showcase.types.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAOD,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,wBAAwB,CAC5D,GAAG,EACH,MAAM,MAAM,CACb,GACG,MAAM,GACN,KAAK,CAAC;AAEV;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAC3C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB;KACG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,GAC5D,CAAC,GACD,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACpC,CAAC;AAEN,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2IAA2I;IAC3I,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iJAAiJ;IACjJ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACxB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;;;OAKG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,6HAA6H;IAC7H,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,mPAAmP;IACnP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,0IAA0I;IAC1I,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,qFAAqF;IACrF,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,qIAAqI;IACrI,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B"}
1
+ {"version":3,"file":"showcase.types.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAOD,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,wBAAwB,CAC5D,GAAG,EACH,MAAM,MAAM,CACb,GACG,MAAM,GACN,KAAK,CAAC;AAEV;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAC3C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB;KACG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,GAC5D,CAAC,GACD,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACpC,CAAC;AAEN,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2IAA2I;IAC3I,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iJAAiJ;IACjJ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACxB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;;;OAKG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,6HAA6H;IAC7H,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,mPAAmP;IACnP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,0IAA0I;IAC1I,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,qFAAqF;IACrF,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,qIAAqI;IACrI,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-prism/core",
3
- "version": "22.0.1",
3
+ "version": "22.1.0",
4
4
  "description": "ng-prism — the Angular-native Storybook alternative. Lightweight component showcase with @Showcase decorator, no story files needed.",
5
5
  "keywords": [
6
6
  "ng-prism",