@ng-prism/core 22.4.1 → 22.6.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.
Files changed (131) hide show
  1. package/README.md +2 -0
  2. package/dist/app/canvas/prism-canvas-toolbar.component.d.ts +33 -2
  3. package/dist/app/canvas/prism-canvas-toolbar.component.d.ts.map +1 -1
  4. package/dist/app/canvas/prism-canvas-toolbar.component.js +135 -28
  5. package/dist/app/canvas/state-chips.d.ts +50 -0
  6. package/dist/app/canvas/state-chips.d.ts.map +1 -0
  7. package/dist/app/canvas/state-chips.js +40 -0
  8. package/dist/app/component-head/prism-component-head.component.d.ts +1 -0
  9. package/dist/app/component-head/prism-component-head.component.d.ts.map +1 -1
  10. package/dist/app/component-head/prism-component-head.component.js +11 -6
  11. package/dist/app/component-head/prism-head-info.component.d.ts +2 -1
  12. package/dist/app/component-head/prism-head-info.component.d.ts.map +1 -1
  13. package/dist/app/component-head/prism-head-info.component.js +30 -7
  14. package/dist/app/directives/resize-value.d.ts +1 -1
  15. package/dist/app/directives/resize-value.js +1 -1
  16. package/dist/app/discovery-manifest.d.ts +2 -2
  17. package/dist/app/discovery-manifest.d.ts.map +1 -1
  18. package/dist/app/discovery-manifest.js +22 -4
  19. package/dist/app/overview/open-in-playground.d.ts +11 -0
  20. package/dist/app/overview/open-in-playground.d.ts.map +1 -0
  21. package/dist/app/overview/open-in-playground.js +12 -0
  22. package/dist/app/overview/overview-matrix.d.ts +79 -0
  23. package/dist/app/overview/overview-matrix.d.ts.map +1 -0
  24. package/dist/app/overview/overview-matrix.js +98 -0
  25. package/dist/app/overview/overview-visibility.d.ts +10 -2
  26. package/dist/app/overview/overview-visibility.d.ts.map +1 -1
  27. package/dist/app/overview/overview-visibility.js +14 -3
  28. package/dist/app/overview/prism-overview-cell.component.d.ts +29 -2
  29. package/dist/app/overview/prism-overview-cell.component.d.ts.map +1 -1
  30. package/dist/app/overview/prism-overview-cell.component.js +145 -27
  31. package/dist/app/overview/prism-overview-matrix.component.d.ts +29 -0
  32. package/dist/app/overview/prism-overview-matrix.component.d.ts.map +1 -0
  33. package/dist/app/overview/prism-overview-matrix.component.js +164 -0
  34. package/dist/app/overview/prism-overview.component.d.ts +4 -0
  35. package/dist/app/overview/prism-overview.component.d.ts.map +1 -1
  36. package/dist/app/overview/prism-overview.component.js +37 -14
  37. package/dist/app/panels/a11y/a11y-core.plugin.d.ts.map +1 -1
  38. package/dist/app/panels/a11y/a11y-core.plugin.js +0 -1
  39. package/dist/app/panels/controls/controls-plugin.d.ts.map +1 -1
  40. package/dist/app/panels/controls/controls-plugin.js +1 -2
  41. package/dist/app/panels/events/events-plugin.d.ts.map +1 -1
  42. package/dist/app/panels/events/events-plugin.js +1 -2
  43. package/dist/app/pseudo/pseudo-selector.d.ts +24 -0
  44. package/dist/app/pseudo/pseudo-selector.d.ts.map +1 -0
  45. package/dist/app/pseudo/pseudo-selector.js +136 -0
  46. package/dist/app/pseudo/pseudo-state-marker.d.ts +66 -0
  47. package/dist/app/pseudo/pseudo-state-marker.d.ts.map +1 -0
  48. package/dist/app/pseudo/pseudo-state-marker.js +165 -0
  49. package/dist/app/pseudo/pseudo-stylesheets.d.ts +49 -0
  50. package/dist/app/pseudo/pseudo-stylesheets.d.ts.map +1 -0
  51. package/dist/app/pseudo/pseudo-stylesheets.js +137 -0
  52. package/dist/app/pseudo/pseudo-targets.d.ts +11 -0
  53. package/dist/app/pseudo/pseudo-targets.d.ts.map +1 -0
  54. package/dist/app/pseudo/pseudo-targets.js +46 -0
  55. package/dist/app/pseudo/state-fit.d.ts +28 -0
  56. package/dist/app/pseudo/state-fit.d.ts.map +1 -0
  57. package/dist/app/pseudo/state-fit.js +97 -0
  58. package/dist/app/renderer/input-bindings.d.ts +16 -0
  59. package/dist/app/renderer/input-bindings.d.ts.map +1 -0
  60. package/dist/app/renderer/input-bindings.js +21 -0
  61. package/dist/app/renderer/known-inputs.d.ts +8 -1
  62. package/dist/app/renderer/known-inputs.d.ts.map +1 -1
  63. package/dist/app/renderer/known-inputs.js +13 -5
  64. package/dist/app/renderer/prism-renderer.component.d.ts +18 -1
  65. package/dist/app/renderer/prism-renderer.component.d.ts.map +1 -1
  66. package/dist/app/renderer/prism-renderer.component.js +68 -22
  67. package/dist/app/renderer/projectable-content.d.ts +8 -1
  68. package/dist/app/renderer/projectable-content.d.ts.map +1 -1
  69. package/dist/app/renderer/projectable-content.js +40 -29
  70. package/dist/app/renderer/rendered-key.d.ts +38 -0
  71. package/dist/app/renderer/rendered-key.d.ts.map +1 -0
  72. package/dist/app/renderer/rendered-key.js +34 -0
  73. package/dist/app/renderer/snippet-generator.js +7 -5
  74. package/dist/app/services/prism-capture.service.d.ts +2 -0
  75. package/dist/app/services/prism-capture.service.d.ts.map +1 -1
  76. package/dist/app/services/prism-capture.service.js +25 -0
  77. package/dist/app/services/prism-pseudo-state.service.d.ts +93 -0
  78. package/dist/app/services/prism-pseudo-state.service.d.ts.map +1 -0
  79. package/dist/app/services/prism-pseudo-state.service.js +155 -0
  80. package/dist/app/services/prism-renderer.service.d.ts +17 -0
  81. package/dist/app/services/prism-renderer.service.d.ts.map +1 -1
  82. package/dist/app/services/prism-renderer.service.js +37 -2
  83. package/dist/app/services/prism-url-state.service.d.ts.map +1 -1
  84. package/dist/app/services/prism-url-state.service.js +39 -8
  85. package/dist/app/theme/prism-default-theme.d.ts.map +1 -1
  86. package/dist/app/theme/prism-default-theme.js +6 -5
  87. package/dist/builder/config-loader/deprecated-options.d.ts +7 -0
  88. package/dist/builder/config-loader/deprecated-options.d.ts.map +1 -0
  89. package/dist/builder/config-loader/deprecated-options.js +23 -0
  90. package/dist/builder/manifest/runtime-manifest.generator.d.ts.map +1 -1
  91. package/dist/builder/manifest/runtime-manifest.generator.js +3 -2
  92. package/dist/builder/scanner/component.scanner.d.ts.map +1 -1
  93. package/dist/builder/scanner/component.scanner.js +27 -0
  94. package/dist/builder/scanner/entry-point-discovery.d.ts +5 -0
  95. package/dist/builder/scanner/entry-point-discovery.d.ts.map +1 -1
  96. package/dist/builder/scanner/entry-point-discovery.js +14 -0
  97. package/dist/builder/scanner/entry-point.scanner.d.ts +3 -1
  98. package/dist/builder/scanner/entry-point.scanner.d.ts.map +1 -1
  99. package/dist/builder/scanner/entry-point.scanner.js +7 -6
  100. package/dist/builder/scanner/input.extractor.d.ts.map +1 -1
  101. package/dist/builder/scanner/input.extractor.js +22 -3
  102. package/dist/builder/scanner/pseudo-states.d.ts +12 -0
  103. package/dist/builder/scanner/pseudo-states.d.ts.map +1 -0
  104. package/dist/builder/scanner/pseudo-states.js +58 -0
  105. package/dist/builder/scanner/scanner.d.ts +2 -2
  106. package/dist/builder/scanner/scanner.d.ts.map +1 -1
  107. package/dist/builder/scanner/scanner.js +16 -6
  108. package/dist/builder/scanner/showcase-diagnostics.js +9 -9
  109. package/dist/builder/scanner/showcase-states.d.ts +17 -0
  110. package/dist/builder/scanner/showcase-states.d.ts.map +1 -0
  111. package/dist/builder/scanner/showcase-states.js +58 -0
  112. package/dist/builder/scanner/source-file-cache.d.ts +26 -0
  113. package/dist/builder/scanner/source-file-cache.d.ts.map +1 -0
  114. package/dist/builder/scanner/source-file-cache.js +60 -0
  115. package/dist/builder/shared/prism-pipeline.d.ts.map +1 -1
  116. package/dist/builder/shared/prism-pipeline.js +28 -13
  117. package/dist/decorator/index.d.ts +1 -1
  118. package/dist/decorator/index.d.ts.map +1 -1
  119. package/dist/decorator/showcase.types.d.ts +33 -0
  120. package/dist/decorator/showcase.types.d.ts.map +1 -1
  121. package/dist/plugin/index.d.ts +3 -1
  122. package/dist/plugin/index.d.ts.map +1 -1
  123. package/dist/plugin/index.js +1 -0
  124. package/dist/plugin/plugin.types.d.ts +53 -7
  125. package/dist/plugin/plugin.types.d.ts.map +1 -1
  126. package/dist/shared/pseudo-state.type.d.ts +22 -0
  127. package/dist/shared/pseudo-state.type.d.ts.map +1 -0
  128. package/dist/shared/pseudo-state.type.js +2 -0
  129. package/package.json +1 -1
  130. package/src/builder/build/schema.json +6 -6
  131. package/src/builder/serve/schema.json +6 -6
@@ -1,6 +1,7 @@
1
1
  import ts from 'typescript';
2
2
  import { scanComponents } from './component.scanner.js';
3
3
  import { resolveEntryPointExports } from './entry-point.scanner.js';
4
+ import { createSourceFileCache } from './source-file-cache.js';
4
5
  const DEFAULT_COMPILER_OPTIONS = {
5
6
  target: ts.ScriptTarget.ES2022,
6
7
  module: ts.ModuleKind.ES2022,
@@ -22,38 +23,47 @@ const DEFAULT_COMPILER_OPTIONS = {
22
23
  * transitive type graph (Angular framework typings, etc.) is parsed once and shared via
23
24
  * the program's `TypeChecker`, instead of N programs that each load Material/CDK/RxJS.
24
25
  *
25
- * TypeScript reuses parsed SourceFile objects from the old program on rebuild, making
26
- * incremental scans fast.
26
+ * On rebuild, the source-file cache hands TypeScript the already parsed SourceFile of
27
+ * every unchanged file, so only the changed files are parsed again.
27
28
  */
28
29
  export function createScanner(options) {
29
30
  const compilerOptions = {
30
31
  ...DEFAULT_COMPILER_OPTIONS,
31
32
  ...options.compilerOptions
32
33
  };
34
+ const sourceFiles = createSourceFileCache(compilerOptions);
33
35
  let previousProgram;
34
36
  return {
35
37
  scan() {
36
- const { program, entries } = resolveEntryPointExports(options.entryPoints, compilerOptions, previousProgram);
38
+ const { program, entries } = resolveEntryPointExports(options.entryPoints, compilerOptions, previousProgram, sourceFiles.host);
37
39
  previousProgram = program;
40
+ sourceFiles.prune(program);
38
41
  const checker = program.getTypeChecker();
39
42
  const allComponents = [];
40
43
  const diagnostics = [];
41
44
  const notices = new Set();
42
- for (const { exports, importPath } of entries) {
45
+ const fromPrimary = new Set();
46
+ for (const { exports, importPath, primary } of entries) {
43
47
  const components = scanComponents(exports, checker, diagnostics, notices);
44
- for (const c of components)
48
+ for (const c of components) {
45
49
  c.importPath = importPath;
50
+ if (primary)
51
+ fromPrimary.add(c);
52
+ }
46
53
  allComponents.push(...components);
47
54
  }
48
55
  // Dedupe by (filePath, className): if a component class is re-exported from
49
56
  // multiple entry points (e.g. atoms/button + barrel index.ts), we keep the first
50
57
  // occurrence. The duplicate would otherwise produce duplicate imports in the
51
- // generated manifest and a runtime collision in the Prism shell.
58
+ // generated manifest and a runtime collision in the Prism shell. The primary
59
+ // entry point comes last and re-exporting its secondaries is normal there.
52
60
  const seen = new Set();
53
61
  const unique = [];
54
62
  for (const c of allComponents) {
55
63
  const key = `${c.filePath}::${c.className}`;
56
64
  if (seen.has(key)) {
65
+ if (fromPrimary.has(c))
66
+ continue;
57
67
  console.warn(`⚠ ng-prism: ${c.className} is exported by multiple entry points; ` +
58
68
  `keeping the first occurrence (importPath: ${unique.find((u) => u.className === c.className && u.filePath === c.filePath)?.importPath}).`);
59
69
  continue;
@@ -49,14 +49,14 @@ export function describeUnreadableBase(className, base) {
49
49
  return (`${className} inherits ${base.inputs.join(', ')} from ${baseName}, which only exists as a declaration (${location(base.classDecl)}); ` +
50
50
  `without its source these inputs cannot be read, so they are missing from the manifest and variants cannot set them.`);
51
51
  }
52
- /** A variant is named by its `name` as well as its index, since that is what the styleguide shows. */
52
+ /** A variant or a state is named by its `name` as well as its index, since that is what the styleguide shows. */
53
53
  function formatShowcasePath(path, config) {
54
54
  const [head, index, ...rest] = path;
55
- if (head !== 'variants' || typeof index !== 'number')
55
+ if ((head !== 'variants' && head !== 'states') || typeof index !== 'number')
56
56
  return formatPath(path);
57
- const name = variantName(config, index);
58
- const variant = name === undefined ? `variants[${index}]` : `variants[${index}] ${JSON.stringify(name)}`;
59
- return rest.length === 0 ? variant : `${variant} › ${formatPath(rest)}`;
57
+ const name = elementName(config, head, index);
58
+ const element = name === undefined ? `${head}[${index}]` : `${head}[${index}] ${JSON.stringify(name)}`;
59
+ return rest.length === 0 ? element : `${element} › ${formatPath(rest)}`;
60
60
  }
61
61
  function formatPath(path) {
62
62
  return path
@@ -70,10 +70,10 @@ function formatPath(path) {
70
70
  .join('');
71
71
  }
72
72
  /** Read from the source, because the evaluated array has already lost the elements before the index. */
73
- function variantName(config, index) {
74
- const variants = ts.isObjectLiteralExpression(config) ? findInitializer(config, 'variants') : undefined;
75
- const variant = variants && ts.isArrayLiteralExpression(variants) ? variants.elements[index] : undefined;
76
- const name = variant && ts.isObjectLiteralExpression(variant) ? findInitializer(variant, 'name') : undefined;
73
+ function elementName(config, key, index) {
74
+ const elements = ts.isObjectLiteralExpression(config) ? findInitializer(config, key) : undefined;
75
+ const element = elements && ts.isArrayLiteralExpression(elements) ? elements.elements[index] : undefined;
76
+ const name = element && ts.isObjectLiteralExpression(element) ? findInitializer(element, 'name') : undefined;
77
77
  const value = name && evaluateExpression(name);
78
78
  return typeof value === 'string' ? value : undefined;
79
79
  }
@@ -0,0 +1,17 @@
1
+ import type { ShowcaseState } from '../../decorator/showcase.types.js';
2
+ /**
3
+ * `ShowcaseConfig.states` as the scanner evaluated it, with everything it
4
+ * cannot use reported. `undefined` when it is no list, or an empty one.
5
+ *
6
+ * Every slot of the list survives, because a state is identified by its
7
+ * position (the URL, the marker and the discovery manifest use it): an
8
+ * unusable entry becomes a state without pseudo states, which the styleguide
9
+ * shows as an empty column, instead of shifting the entries behind it.
10
+ * A state without a usable name is called `State <position>`.
11
+ *
12
+ * `unevaluable` holds the source positions of the entries the evaluator could
13
+ * not read at all. They are missing from `value`, so an empty slot goes back
14
+ * in at each of them, without a message of its own.
15
+ */
16
+ export declare function readShowcaseStates(value: unknown, className: string, report: (message: string) => void, unevaluable?: ReadonlySet<number>): ShowcaseState[] | undefined;
17
+ //# sourceMappingURL=showcase-states.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showcase-states.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/showcase-states.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAUvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EACjC,WAAW,GAAE,WAAW,CAAC,MAAM,CAAa,GAC7C,aAAa,EAAE,GAAG,SAAS,CA4C7B"}
@@ -0,0 +1,58 @@
1
+ import { describeValue, readPseudoStates } from './pseudo-states.js';
2
+ function isEmptyObject(value) {
3
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;
4
+ }
5
+ /** Stands in for a state the evaluator dropped, which its own diagnostic already explains. */
6
+ const GAP = Symbol('unevaluable state');
7
+ /**
8
+ * `ShowcaseConfig.states` as the scanner evaluated it, with everything it
9
+ * cannot use reported. `undefined` when it is no list, or an empty one.
10
+ *
11
+ * Every slot of the list survives, because a state is identified by its
12
+ * position (the URL, the marker and the discovery manifest use it): an
13
+ * unusable entry becomes a state without pseudo states, which the styleguide
14
+ * shows as an empty column, instead of shifting the entries behind it.
15
+ * A state without a usable name is called `State <position>`.
16
+ *
17
+ * `unevaluable` holds the source positions of the entries the evaluator could
18
+ * not read at all. They are missing from `value`, so an empty slot goes back
19
+ * in at each of them, without a message of its own.
20
+ */
21
+ export function readShowcaseStates(value, className, report, unevaluable = new Set()) {
22
+ if (!Array.isArray(value)) {
23
+ report(`${className} declares invalid states ${describeValue(value)}, expected a list of { name, pseudo }. Skipping.`);
24
+ return undefined;
25
+ }
26
+ const entries = [...value];
27
+ // Ascending, so that each position is already the one the source gives it once the earlier gaps are back.
28
+ for (const index of [...unevaluable].sort((a, b) => a - b))
29
+ entries.splice(index, 0, GAP);
30
+ if (entries.length === 0)
31
+ return undefined;
32
+ const firstIndexOfName = new Map();
33
+ return entries.map((entry, index) => {
34
+ const state = typeof entry === 'object' && entry !== null && !Array.isArray(entry) ? entry : undefined;
35
+ const declaredName = state?.['name'];
36
+ const hasName = typeof declaredName === 'string' && declaredName.trim() !== '';
37
+ if (state && !hasName)
38
+ report(`${className} states[${index}] has no name, expected a non-empty string. Calling it "State ${index + 1}".`);
39
+ else if (!state && entry !== GAP)
40
+ report(`${className} states[${index}] is ${describeValue(entry)}, expected { name, pseudo }. Its column stays empty.`);
41
+ const name = hasName ? declaredName : `State ${index + 1}`;
42
+ const first = firstIndexOfName.get(name);
43
+ if (first !== undefined) {
44
+ report(`${className} state "${name}" repeats the name of states[${first}]; only the first one is used. Its column stays empty.`);
45
+ return { name, pseudo: {} };
46
+ }
47
+ firstIndexOfName.set(name, index);
48
+ if (!state)
49
+ return { name, pseudo: {} };
50
+ const pseudo = state['pseudo'];
51
+ // `readPseudoStates` reports what it drops, but an empty object has nothing to drop.
52
+ if (pseudo === undefined || isEmptyObject(pseudo)) {
53
+ report(`${className} state "${name}" declares no pseudo states. Its column stays empty.`);
54
+ return { name, pseudo: {} };
55
+ }
56
+ return { name, pseudo: readPseudoStates(pseudo, `${className} state "${name}"`, report) ?? {} };
57
+ });
58
+ }
@@ -0,0 +1,26 @@
1
+ import ts from 'typescript';
2
+ export interface SourceFileCache {
3
+ /** Pass to `ts.createProgram` together with the previous program. */
4
+ host: ts.CompilerHost;
5
+ /** Drop every cached file the given program no longer contains. */
6
+ prune(program: ts.Program): void;
7
+ }
8
+ /**
9
+ * A compiler host that hands out the same `SourceFile` for a file that has
10
+ * not changed since it was last parsed.
11
+ *
12
+ * `ts.createProgram(…, oldProgram)` only reuses a file from the old program
13
+ * when the host returns the identical object. The default host reads and
14
+ * parses on every call, so without this cache each rebuild re-parses the
15
+ * whole program, Angular's typings included.
16
+ *
17
+ * A file counts as unchanged while its mtime and size are. An edit that keeps
18
+ * the size and lands within the file system's mtime resolution goes unseen;
19
+ * APFS and ext4 record nanoseconds, so in practice that does not happen.
20
+ *
21
+ * Module resolutions are recomputed on every program. Reusing them would
22
+ * miss a file created after an import of it had already failed to resolve,
23
+ * because the importing file itself has not changed.
24
+ */
25
+ export declare function createSourceFileCache(compilerOptions: ts.CompilerOptions): SourceFileCache;
26
+ //# sourceMappingURL=source-file-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-file-cache.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/source-file-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC5B,qEAAqE;IACrE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC;IACtB,mEAAmE;IACnE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC;CACpC;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,EAAE,CAAC,eAAe,GAAG,eAAe,CAmC1F"}
@@ -0,0 +1,60 @@
1
+ import { statSync } from 'fs';
2
+ import ts from 'typescript';
3
+ /**
4
+ * A compiler host that hands out the same `SourceFile` for a file that has
5
+ * not changed since it was last parsed.
6
+ *
7
+ * `ts.createProgram(…, oldProgram)` only reuses a file from the old program
8
+ * when the host returns the identical object. The default host reads and
9
+ * parses on every call, so without this cache each rebuild re-parses the
10
+ * whole program, Angular's typings included.
11
+ *
12
+ * A file counts as unchanged while its mtime and size are. An edit that keeps
13
+ * the size and lands within the file system's mtime resolution goes unseen;
14
+ * APFS and ext4 record nanoseconds, so in practice that does not happen.
15
+ *
16
+ * Module resolutions are recomputed on every program. Reusing them would
17
+ * miss a file created after an import of it had already failed to resolve,
18
+ * because the importing file itself has not changed.
19
+ */
20
+ export function createSourceFileCache(compilerOptions) {
21
+ const host = ts.createCompilerHost(compilerOptions);
22
+ const parse = host.getSourceFile.bind(host);
23
+ const cache = new Map();
24
+ host.getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
25
+ const stamp = readStamp(fileName);
26
+ if (stamp === undefined) {
27
+ cache.delete(fileName);
28
+ return undefined;
29
+ }
30
+ const cached = cache.get(fileName);
31
+ if (cached?.stamp === stamp && !shouldCreateNewSourceFile)
32
+ return cached.sourceFile;
33
+ const sourceFile = parse(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
34
+ if (sourceFile)
35
+ cache.set(fileName, { stamp, sourceFile });
36
+ else
37
+ cache.delete(fileName);
38
+ return sourceFile;
39
+ };
40
+ host.hasInvalidatedResolutions = () => true;
41
+ return {
42
+ host,
43
+ prune(program) {
44
+ const live = new Set(program.getSourceFiles().map((sf) => sf.fileName));
45
+ for (const fileName of cache.keys()) {
46
+ if (!live.has(fileName))
47
+ cache.delete(fileName);
48
+ }
49
+ }
50
+ };
51
+ }
52
+ function readStamp(fileName) {
53
+ try {
54
+ const { mtimeMs, size } = statSync(fileName);
55
+ return `${mtimeMs}:${size}`;
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"prism-pipeline.d.ts","sourceRoot":"","sources":["../../../src/builder/shared/prism-pipeline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAShE,OAAO,EAAiB,KAAK,OAAO,EAAmB,MAAM,uBAAuB,CAAC;AAErF,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,mGAAmG;IACnG,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,mGAAmG;IACnG,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,mBAAmB,IAAI,kBAAkB,CAExD;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuFtJ"}
1
+ {"version":3,"file":"prism-pipeline.d.ts","sourceRoot":"","sources":["../../../src/builder/shared/prism-pipeline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAUhE,OAAO,EAAiB,KAAK,OAAO,EAAmB,MAAM,uBAAuB,CAAC;AAErF,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,mGAAmG;IACnG,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,mGAAmG;IACnG,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,mBAAmB,IAAI,kBAAkB,CAExD;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA2FtJ"}
@@ -3,9 +3,10 @@ import { dirname, join } from 'path';
3
3
  import ts from 'typescript';
4
4
  import { checkA11yThresholds, DEFAULT_A11Y_REPORT_PATH, readA11yForComponents, readA11yMeta } from '../a11y/a11y-report-reader.js';
5
5
  import { loadConfig } from '../config-loader/config-loader.js';
6
+ import { describeDeprecatedOptions } from '../config-loader/deprecated-options.js';
6
7
  import { generateRuntimeManifest } from '../manifest/runtime-manifest.generator.js';
7
8
  import { runPluginHooks } from '../plugin-runner/plugin-runner.js';
8
- import { discoverSecondaryEntryPoints } from '../scanner/entry-point-discovery.js';
9
+ import { discoverSecondaryEntryPoints, findPrimaryEntryFile } from '../scanner/entry-point-discovery.js';
9
10
  import { createScanner } from '../scanner/scanner.js';
10
11
  export function createPipelineState() {
11
12
  return { scanner: undefined, lastEntrySetKey: undefined };
@@ -17,6 +18,9 @@ export async function runPrismPipeline(options, context, state) {
17
18
  workspaceRoot,
18
19
  configFileName: options.configFile
19
20
  });
21
+ for (const notice of describeDeprecatedOptions(config, options.configFile)) {
22
+ console.warn(`⚠ ng-prism: ${notice}`);
23
+ }
20
24
  context.reportStatus('Scanning components...');
21
25
  const { components, diagnostics } = scanEntryPoints(workspaceRoot, options, state);
22
26
  if (config.strictShowcase && diagnostics.length > 0) {
@@ -115,6 +119,18 @@ function findLibraryRoot(filePath) {
115
119
  }
116
120
  return undefined;
117
121
  }
122
+ /**
123
+ * Reads config files, `extends` included, but lists no directories. Only
124
+ * `paths` and `baseUrl` are taken from the config, so enumerating the files it
125
+ * includes would only cost time: with no `include`, that is every source file
126
+ * below the config, on every rebuild.
127
+ */
128
+ const CONFIG_HOST = {
129
+ useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
130
+ fileExists: ts.sys.fileExists,
131
+ readFile: ts.sys.readFile,
132
+ readDirectory: () => []
133
+ };
118
134
  function resolveTsconfigPaths(entryPointDir) {
119
135
  const configPath = ts.findConfigFile(entryPointDir, ts.sys.fileExists, 'tsconfig.json');
120
136
  if (!configPath)
@@ -122,7 +138,7 @@ function resolveTsconfigPaths(entryPointDir) {
122
138
  const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
123
139
  if (configFile.error)
124
140
  return {};
125
- const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, dirname(configPath));
141
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, CONFIG_HOST, dirname(configPath));
126
142
  const result = {};
127
143
  if (parsed.options.paths)
128
144
  result.paths = parsed.options.paths;
@@ -136,18 +152,17 @@ function resolveEntryPoints(workspaceRoot, options) {
136
152
  const entryIsDirectory = isDirectory(absoluteEntryPoint);
137
153
  const libraryRoot = entryIsDirectory ? absoluteEntryPoint : findLibraryRoot(absoluteEntryPoint);
138
154
  const discovered = libraryRoot ? discoverSecondaryEntryPoints(libraryRoot, options.libraryImportPath) : [];
139
- // Fallback to a direct file scan when:
140
- // - the entry is a file and no ng-package.json was found above it, OR
141
- // - the entry is a file with an ng-package.json above it but discovery found nothing
142
- // (e.g. primary-only library, root ng-package.json carries `dest`).
143
- const entryPoints = discovered.length === 0 && !entryIsDirectory
144
- ? [
145
- {
146
- entryFile: absoluteEntryPoint,
147
- importPath: options.libraryImportPath
148
- }
149
- ]
155
+ // The primary entry point is scanned after the secondary ones: a file entryPoint is
156
+ // the primary itself, a directory names it in its ng-package.json. A root
157
+ // ng-package.json without `dest` is already among the discovered ones.
158
+ const primaryEntryFile = entryIsDirectory ? findPrimaryEntryFile(absoluteEntryPoint) : absoluteEntryPoint;
159
+ const entryPoints = primaryEntryFile && !discovered.some((e) => e.entryFile === primaryEntryFile)
160
+ ? [...discovered, { entryFile: primaryEntryFile, importPath: options.libraryImportPath, primary: true }]
150
161
  : discovered;
162
+ if (entryPoints.length === 0) {
163
+ console.warn(`⚠ ng-prism: entryPoint "${options.entryPoint}" resolves to no entry file: no ng-package.json with a lib.entryFile ` +
164
+ `that exists, and no secondary entry points below it. Point entryPoint at the library's barrel file.`);
165
+ }
151
166
  return { entryPoints, compilerOptions };
152
167
  }
153
168
  function scanEntryPoints(workspaceRoot, options, state) {
@@ -1,3 +1,3 @@
1
- export type { ComponentStatus, InputsOf, ShowcaseConfig, Variant } from './showcase.types.js';
1
+ export type { ComponentStatus, InputsOf, ShowcaseConfig, ShowcaseState, Variant } from './showcase.types.js';
2
2
  export { Showcase } from './showcase.decorator.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorator/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorator/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import type { InputSignalWithTransform, Provider } from '@angular/core';
2
2
  import type { CanvasBg } from '../shared/canvas-bg.type.js';
3
3
  import type { CanvasLayout } from '../shared/canvas-layout.type.js';
4
+ import type { ForcedPseudoStates } from '../shared/pseudo-state.type.js';
4
5
  export type ComponentStatus = 'stable' | 'beta' | 'wip' | 'deprecated';
5
6
  export interface DirectiveHost {
6
7
  selector: string;
@@ -23,6 +24,17 @@ type UnwrapSignalInput<S> = S extends InputSignalWithTransform<any, infer WriteT
23
24
  export type InputsOf<T> = [unknown] extends [T] ? Record<string, unknown> : {
24
25
  [K in keyof T as T[K] extends InputSignalWithTransform<any, any> ? K : never]: UnwrapSignalInput<T[K]>;
25
26
  };
27
+ /**
28
+ * A named combination of forced pseudo states, combined with every variant of
29
+ * the component that does not opt out with `Variant.states: false`, and forced
30
+ * where it fits: only on targets the browser could put into the state.
31
+ */
32
+ export interface ShowcaseState {
33
+ /** Column title in the Overview, chip label in the tools menu. Unique within the component. */
34
+ name: string;
35
+ /** Same shape and semantics as `Variant.pseudo`. */
36
+ pseudo: ForcedPseudoStates;
37
+ }
26
38
  export interface ShowcaseConfig<T = unknown> {
27
39
  /** Display name in the ng-prism UI */
28
40
  title: string;
@@ -48,6 +60,16 @@ export interface ShowcaseConfig<T = unknown> {
48
60
  sectionOrder?: number;
49
61
  /** Predefined variants shown as tabs */
50
62
  variants?: Variant<T>[];
63
+ /**
64
+ * Named pseudo-state combinations, e.g. `{ name: 'Hover', pseudo: { hover: '.btn' } }`.
65
+ * Each one is combined with every variant and forced where it fits, so the Overview shows
66
+ * a column per state and a variant can be viewed in any of them. A variant opts out with
67
+ * `states: false`.
68
+ * Not combinable with `renderPage`: a component page has no Overview.
69
+ *
70
+ * The position in the list identifies a state, so keep the order stable.
71
+ */
72
+ states?: ShowcaseState[];
51
73
  /** Tags for search and filtering */
52
74
  tags?: string[];
53
75
  /**
@@ -107,6 +129,17 @@ export interface Variant<T = unknown> {
107
129
  bg?: CanvasBg;
108
130
  /** Canvas layout mode for this variant. Overrides `ShowcaseConfig.canvasLayout`. See `ShowcaseConfig.canvasLayout` for semantics. */
109
131
  canvasLayout?: CanvasLayout;
132
+ /**
133
+ * Pseudo states forced on while this variant renders, e.g.
134
+ * `{ 'focus-visible': '.btn' }` or `{ hover: true }`.
135
+ * - `true`: the state is forced on every element of the rendered component, the host included.
136
+ * - A selector, or a list of them: only on the matching elements, resolved against the host and everything inside it.
137
+ *
138
+ * The component's own CSS applies: every selector using the pseudo-class is widened to also match a stand-in class on the targeted elements.
139
+ */
140
+ pseudo?: ForcedPseudoStates;
141
+ /** `false` keeps this variant out of every combination with the component's `states`: it renders in its own pseudo states only, as a single cell in the Overview. */
142
+ states?: false;
110
143
  }
111
144
  export {};
112
145
  //# sourceMappingURL=showcase.types.d.ts.map
@@ -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;IAC1B,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;CACpC;AAOD,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,wBAAwB,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC;AAEnG;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB;KACK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACzG,CAAC;AAER,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACvC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,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;;;;;;OAMG;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;CAC5B;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAChC,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;CAC/B"}
1
+ {"version":3,"file":"showcase.types.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.types.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
- export type { ControlDefinition, DiscoveryComponent, DiscoveryManifest, DiscoveryPage, DiscoveryVariant, HeaderWidgetDefinition, InputMeta, NavigationDecoration, NavigationDecorationDefinition, NgPrismConfig, NgPrismPlugin, OutputMeta, PanelBadge, PanelDefinition, PrismManifest, RuntimeComponent, RuntimeManifest, ScannedComponent } from './plugin.types.js';
1
+ export type { ControlDefinition, DiscoveryComponent, DiscoveryManifest, DiscoveryPage, DiscoveryState, DiscoveryVariant, HeaderWidgetDefinition, InputMeta, NavigationDecoration, NavigationDecorationDefinition, NgPrismConfig, NgPrismPlugin, OutputMeta, PanelBadge, PanelDefinition, PrismManifest, RuntimeComponent, RuntimeManifest, ScannedComponent } from './plugin.types.js';
2
2
  export type { ComponentPage, CustomPage, StyleguidePage } from './page.types.js';
3
3
  export type { CanvasBg } from '../shared/canvas-bg.type.js';
4
4
  export { CANVAS_BGS } from '../shared/canvas-bg.type.js';
5
5
  export { DEFAULT_VARIANT_BG, resolveVariantBg } from '../shared/variant-bg.js';
6
6
  export type { VariantBgSource } from '../shared/variant-bg.js';
7
+ export type { ForcedPseudoStates, PseudoState, PseudoTarget } from '../shared/pseudo-state.type.js';
8
+ export { PSEUDO_STATES } from '../shared/pseudo-state.type.js';
7
9
  export { componentPage, customPage } from './page-helpers.js';
8
10
  export type { ComponentPageOptions } from './page-helpers.js';
9
11
  export { defineConfig } from './define-config.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AACA,YAAY,EACR,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,oBAAoB,EACpB,8BAA8B,EAC9B,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKjF,YAAY,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACnG,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AACA,YAAY,EACR,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,oBAAoB,EACpB,8BAA8B,EAC9B,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKjF,YAAY,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK/D,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACpG,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACnG,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export { CANVAS_BGS } from '../shared/canvas-bg.type.js';
2
2
  export { DEFAULT_VARIANT_BG, resolveVariantBg } from '../shared/variant-bg.js';
3
+ export { PSEUDO_STATES } from '../shared/pseudo-state.type.js';
3
4
  export { componentPage, customPage } from './page-helpers.js';
4
5
  export { defineConfig } from './define-config.js';
5
6
  // Imported from the dependency-free registry module, not from
@@ -1,5 +1,6 @@
1
1
  import type { Provider, Type } from '@angular/core';
2
2
  import type { CanvasBg } from '../shared/canvas-bg.type.js';
3
+ import type { ForcedPseudoStates } from '../shared/pseudo-state.type.js';
3
4
  import type { StyleguidePage } from './page.types.js';
4
5
  export interface NgPrismPlugin {
5
6
  /** Unique plugin name, used for debugging and conflict detection */
@@ -13,7 +14,7 @@ export interface NgPrismPlugin {
13
14
  headerWidgets?: HeaderWidgetDefinition[];
14
15
  /** Markers contributed to each component's navigation item. */
15
16
  navigationDecorations?: NavigationDecorationDefinition[];
16
- /** Angular standalone component that wraps each rendered component */
17
+ /** @deprecated Deprecated since 22.6.0, removed in 23.0.0. It has never had an effect: nothing reads it. */
17
18
  wrapComponent?: Type<unknown>;
18
19
  }
19
20
  export interface HeaderWidgetDefinition {
@@ -82,8 +83,9 @@ export interface PanelDefinition {
82
83
  overlayComponent?: Type<unknown>;
83
84
  loadOverlayComponent?: () => Promise<Type<unknown>>;
84
85
  icon?: string;
86
+ /** @deprecated Deprecated since 22.6.0, removed in 23.0.0. It has never had an effect: nothing reads it. Where a panel appears is `placement`. */
85
87
  position?: 'bottom' | 'right';
86
- /** Where this panel appears: 'addon' (bottom/right tabbar) or 'view' (top view toolbar). Default: 'addon' */
88
+ /** Where this panel appears: 'addon' (the tab bar below the canvas) or 'view' (top view toolbar). Default: 'addon' */
87
89
  placement?: 'addon' | 'view';
88
90
  /** Providers injected into a child EnvironmentInjector scoped to this panel */
89
91
  providers?: Provider[];
@@ -147,7 +149,10 @@ export interface ScannedComponent {
147
149
  meta?: Record<string, unknown>;
148
150
  }
149
151
  export interface InputMeta {
152
+ /** The class member. Variants and controls use this name. */
150
153
  name: string;
154
+ /** The public name Angular binds the input by, when an `alias` makes it differ from `name`. */
155
+ alias?: string;
151
156
  type: 'string' | 'number' | 'boolean' | 'union' | 'array' | 'object' | 'unknown';
152
157
  rawType?: string;
153
158
  values?: string[];
@@ -156,7 +161,10 @@ export interface InputMeta {
156
161
  doc?: string;
157
162
  }
158
163
  export interface OutputMeta {
164
+ /** The class member. */
159
165
  name: string;
166
+ /** The public event name, when an `alias` makes it differ from `name`. */
167
+ alias?: string;
160
168
  doc?: string;
161
169
  }
162
170
  export interface RuntimeManifest {
@@ -173,9 +181,10 @@ export interface RuntimeComponent {
173
181
  * The shape external tooling reads from `globalThis.__PRISM_MANIFEST__`.
174
182
  *
175
183
  * A thin, JSON-safe projection of the runtime manifest: enough to enumerate and
176
- * address every variant, plus the `@Showcase` metadata a tool needs to decide how
177
- * to treat one. It carries no Angular class references, and `meta` values that
178
- * cannot survive a structured clone are dropped rather than half-serialised.
184
+ * address every variant and component-level state, plus the `@Showcase` metadata
185
+ * a tool needs to decide how to treat one. It carries no Angular class
186
+ * references, and `meta` values that cannot survive a structured clone are
187
+ * dropped rather than half-serialised.
179
188
  */
180
189
  export interface DiscoveryManifest {
181
190
  components: DiscoveryComponent[];
@@ -186,6 +195,16 @@ export interface DiscoveryComponent {
186
195
  /** `ShowcaseConfig.title`, i.e. the display name, not the class name. */
187
196
  title: string;
188
197
  variants: DiscoveryVariant[];
198
+ /**
199
+ * `ShowcaseConfig.states`: the component-level states, one entry per declared
200
+ * slot. Omitted when the component declares none. A component without
201
+ * `variants` lists them next to its single `Default` variant.
202
+ *
203
+ * Whether a state fits a variant is not part of the manifest, because that is
204
+ * only known once the variant renders; the render marker reports it
205
+ * (`data-prism-excluded`).
206
+ */
207
+ states?: DiscoveryState[];
189
208
  /** Sanitised `ShowcaseConfig.meta`. Omitted when empty. */
190
209
  meta?: Record<string, unknown>;
191
210
  }
@@ -204,6 +223,29 @@ export interface DiscoveryVariant {
204
223
  bg: CanvasBg;
205
224
  /** Sanitised `Variant.meta`. Omitted when empty. */
206
225
  meta?: Record<string, unknown>;
226
+ /**
227
+ * `Variant.pseudo`: the pseudo states the variant forces. Omitted when it
228
+ * forces none. The render marker waits for them, so a capture shows them
229
+ * without any action on the runner's side.
230
+ */
231
+ pseudo?: ForcedPseudoStates;
232
+ /**
233
+ * `false` when the variant opts out of the component's `states` (`Variant.states`).
234
+ * Omitted otherwise. Nothing is forced for a state on such a variant, and the
235
+ * render marker still reports its cell as excluded.
236
+ */
237
+ states?: false;
238
+ }
239
+ export interface DiscoveryState {
240
+ name: string;
241
+ /** 0-based index into the `states` array (the `?state=` URL value). */
242
+ index: number;
243
+ /**
244
+ * The pseudo states the state forces, exactly as declared. An empty object
245
+ * for a slot that forces nothing, for example one the scanner could not
246
+ * evaluate: the slot stays listed so the indices behind it keep their value.
247
+ */
248
+ pseudo: ForcedPseudoStates;
207
249
  }
208
250
  export interface DiscoveryPage {
209
251
  title: string;
@@ -222,7 +264,9 @@ export interface NgPrismConfig {
222
264
  };
223
265
  title?: string;
224
266
  subtitle?: string;
267
+ /** @deprecated Deprecated since 22.6.0, removed in 23.0.0. It has never had an effect: nothing reads it. */
225
268
  themeStylesheet?: string;
269
+ /** @deprecated Deprecated since 22.6.0, removed in 23.0.0. It has never had an effect: nothing reads it. */
226
270
  ui?: {
227
271
  header?: Type<unknown>;
228
272
  sidebar?: Type<unknown>;
@@ -232,7 +276,9 @@ export interface NgPrismConfig {
232
276
  eventsPanel?: Type<unknown>;
233
277
  footer?: Type<unknown>;
234
278
  };
279
+ /** @deprecated Deprecated since 22.6.0, removed in 23.0.0. It has never had an effect: nothing reads it. */
235
280
  headless?: boolean;
281
+ /** @deprecated Deprecated since 22.6.0, removed in 23.0.0. It has never had an effect: nothing reads it. */
236
282
  appComponent?: Type<unknown>;
237
283
  /** When false, disables URL state sync (default: true). */
238
284
  urlState?: boolean;
@@ -247,8 +293,8 @@ export interface NgPrismConfig {
247
293
  /**
248
294
  * When true, the build fails instead of warning whenever the scanner has
249
295
  * to drop a `@Showcase` value: one it cannot evaluate statically, an
250
- * invalid `bg`, `status` or `canvasLayout`, a missing `title`, or the
251
- * deprecated `providers`, which never reach the styleguide.
296
+ * invalid `bg`, `status`, `canvasLayout` or `pseudo`, a missing `title`,
297
+ * or the deprecated `providers`, which never reach the styleguide.
252
298
  * Default: `false`.
253
299
  */
254
300
  strictShowcase?: boolean;