@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,4 +1,4 @@
1
- import { computed, inject, Injectable, signal } from '@angular/core';
1
+ import { computed, effect, inject, Injectable, signal, untracked } from '@angular/core';
2
2
  import { PrismNavigationService } from './prism-navigation.service.js';
3
3
  import * as i0 from "@angular/core";
4
4
  export function computeVariantState(comp, index, options = {}) {
@@ -57,6 +57,13 @@ export class PrismRendererService {
57
57
  navigationService = inject(PrismNavigationService);
58
58
  activeVariantIndex = signal(0, /* @ts-ignore */
59
59
  ...(ngDevMode ? [{ debugName: "activeVariantIndex" }] : /* istanbul ignore next */ []));
60
+ /**
61
+ * Position in `ShowcaseConfig.states` of the component-level state on the
62
+ * canvas, `null` for none. Part of the addressed cell next to the variant:
63
+ * it survives a variant change and goes with the component.
64
+ */
65
+ activeStateIndex = signal(null, /* @ts-ignore */
66
+ ...(ngDevMode ? [{ debugName: "activeStateIndex" }] : /* istanbul ignore next */ []));
60
67
  inputValues = signal({}, /* @ts-ignore */
61
68
  ...(ngDevMode ? [{ debugName: "inputValues" }] : /* istanbul ignore next */ []));
62
69
  activeContent = signal(undefined, /* @ts-ignore */
@@ -78,20 +85,45 @@ export class PrismRendererService {
78
85
  return count;
79
86
  }, /* @ts-ignore */
80
87
  ...(ngDevMode ? [{ debugName: "dirtyInputCount" }] : /* istanbul ignore next */ []));
88
+ /** The component the variant, the state and the inputs belong to, `null` before the first. */
81
89
  _lastClassName = null;
90
+ constructor() {
91
+ // The variant and the state go with the component in every view, so the reset on a switch follows
92
+ // navigation, not the renderer: the shell mounts `<prism-renderer>` in the Playground only, and the Overview
93
+ // keeps its view when the sidebar picks another component. A root effect, created before the URL service's,
94
+ // so it runs first in the same flush and the URL never sees the previous component's cell on the new one.
95
+ effect(() => {
96
+ const comp = this.navigationService.activeComponent();
97
+ if (comp)
98
+ untracked(() => this.reconcileForComponent(comp));
99
+ });
100
+ }
82
101
  resetForComponent(comp) {
83
102
  this._lastClassName = comp.meta.className;
84
103
  this.activeVariantIndex.set(0);
104
+ this.activeStateIndex.set(null);
85
105
  this.applyVariant(0, comp);
86
106
  }
107
+ /**
108
+ * Brings the variant, the state and the inputs in line with `comp`: a full
109
+ * reset when it is another component than the last one, else the variant
110
+ * and the state clamped to what it still declares and the inputs kept.
111
+ * Runs on every navigation and again when the renderer mounts, which then
112
+ * finds the component current and keeps what an Overview cell or a restore
113
+ * selected.
114
+ */
87
115
  reconcileForComponent(comp) {
88
116
  const prev = this._lastClassName;
89
117
  this._lastClassName = comp.meta.className;
90
118
  if (prev !== null && prev !== comp.meta.className) {
91
119
  this.activeVariantIndex.set(0);
120
+ this.activeStateIndex.set(null);
92
121
  this.applyVariant(0, comp);
93
122
  return;
94
123
  }
124
+ const stateIndex = this.activeStateIndex();
125
+ if (stateIndex !== null && stateIndex >= (comp.meta.showcaseConfig.states?.length ?? 0))
126
+ this.activeStateIndex.set(null);
95
127
  const variants = comp.meta.showcaseConfig.variants ?? [];
96
128
  const maxIndex = Math.max(0, variants.length - 1);
97
129
  const preservedIndex = Math.min(this.activeVariantIndex(), maxIndex);
@@ -125,6 +157,9 @@ export class PrismRendererService {
125
157
  if (comp)
126
158
  this.applyVariant(index, comp);
127
159
  }
160
+ selectState(index) {
161
+ this.activeStateIndex.set(index);
162
+ }
128
163
  updateInput(name, value) {
129
164
  this.inputValues.update((prev) => ({ ...prev, [name]: value }));
130
165
  }
@@ -147,4 +182,4 @@ export class PrismRendererService {
147
182
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrismRendererService, [{
148
183
  type: Injectable,
149
184
  args: [{ providedIn: 'root' }]
150
- }], null, null); })();
185
+ }], () => [], null); })();
@@ -1 +1 @@
1
- {"version":3,"file":"prism-url-state.service.d.ts","sourceRoot":"","sources":["../../../src/app/services/prism-url-state.service.ts"],"names":[],"mappings":";AAgBA,qBACa,oBAAoB;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,OAAO,CAAC,YAAY,CAAS;IAE7B,IAAI,IAAI,IAAI;IAqBZ,OAAO,CAAC,cAAc;IA2CtB,OAAO,CAAC,UAAU;yCA1ET,oBAAoB;;CA+GhC"}
1
+ {"version":3,"file":"prism-url-state.service.d.ts","sourceRoot":"","sources":["../../../src/app/services/prism-url-state.service.ts"],"names":[],"mappings":";AAiCA,qBACa,oBAAoB;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAE7C,OAAO,CAAC,YAAY,CAAS;IAE7B,IAAI,IAAI,IAAI;IAsBZ,OAAO,CAAC,cAAc;IA2DtB,OAAO,CAAC,UAAU;yCA3FT,oBAAoB;;CAmIhC"}
@@ -8,10 +8,25 @@ import * as i0 from "@angular/core";
8
8
  const PARAM_COMPONENT = 'component';
9
9
  const PARAM_PAGE = 'page';
10
10
  const PARAM_VARIANT = 'variant';
11
+ const PARAM_STATE = 'state';
11
12
  const PARAM_VIEW = 'view';
12
13
  const DEFAULT_VIEW = 'renderer';
13
14
  const PARAM_PANEL = 'panel';
14
15
  const DEFAULT_PANEL = 'controls';
16
+ /** The index a `variant` parameter addresses in a list of `count` variants, `0` for anything that is not one. */
17
+ function parseVariantIndex(param, count) {
18
+ if (param === null)
19
+ return 0;
20
+ const index = parseInt(param, 10);
21
+ return !Number.isNaN(index) && index >= 0 && index < count ? index : 0;
22
+ }
23
+ /** The index a `state` parameter addresses in a list of `count` states, `null` for anything that is not one. */
24
+ function parseStateIndex(param, count) {
25
+ if (param === null || !/^\d+$/.test(param))
26
+ return null;
27
+ const index = Number(param);
28
+ return index < count ? index : null;
29
+ }
15
30
  export class PrismUrlStateService {
16
31
  manifestService = inject(PrismManifestService);
17
32
  navigationService = inject(PrismNavigationService);
@@ -27,11 +42,12 @@ export class PrismUrlStateService {
27
42
  effect(() => {
28
43
  const item = this.navigationService.activeItem();
29
44
  const variantIndex = this.rendererService.activeVariantIndex();
45
+ const stateIndex = this.rendererService.activeStateIndex();
30
46
  const viewId = this.panelService.activeViewId();
31
47
  const panelId = this.panelService.activePanelId();
32
48
  if (this.suppressSync)
33
49
  return;
34
- this.writeToUrl(item, variantIndex, viewId, panelId);
50
+ this.writeToUrl(item, variantIndex, stateIndex, viewId, panelId);
35
51
  }, { injector: this.injector });
36
52
  window.addEventListener('popstate', () => this.restoreFromUrl());
37
53
  }
@@ -40,21 +56,32 @@ export class PrismUrlStateService {
40
56
  const componentClassName = params.get(PARAM_COMPONENT);
41
57
  const pageTitle = params.get(PARAM_PAGE);
42
58
  const variantParam = params.get(PARAM_VARIANT);
59
+ const stateParam = params.get(PARAM_STATE);
43
60
  const viewId = params.get(PARAM_VIEW);
44
61
  const panelId = params.get(PARAM_PANEL);
62
+ let stateIndex = null;
45
63
  this.suppressSync = true;
46
64
  try {
47
65
  if (componentClassName) {
48
66
  const comp = this.manifestService.components().find((c) => c.meta.className === componentClassName);
49
67
  if (comp) {
68
+ const previousClassName = this.navigationService.activeComponent()?.meta.className;
50
69
  this.navigationService.select(comp);
51
- if (variantParam !== null) {
52
- const index = parseInt(variantParam, 10);
53
- const maxIndex = (comp.meta.showcaseConfig.variants?.length ?? 1) - 1;
54
- if (!Number.isNaN(index) && index >= 0 && index <= maxIndex) {
55
- this.rendererService.activeVariantIndex.set(index);
56
- }
70
+ // Switching to another component resets the variant and the state
71
+ // once `PrismRendererService` follows the navigation, after this
72
+ // restore. Starting the component here makes it the current one
73
+ // before the indexes below are set, so that reset, and the renderer
74
+ // mounting it, keep them (a popstate between components). Not for
75
+ // the component already on screen: a popstate that addresses it (a
76
+ // hash link inside it fires one) must keep the control overrides.
77
+ if (previousClassName !== comp.meta.className) {
78
+ this.rendererService.resetForComponent(comp);
57
79
  }
80
+ const variantIndex = parseVariantIndex(variantParam, comp.meta.showcaseConfig.variants?.length ?? 1);
81
+ if (variantIndex !== this.rendererService.activeVariantIndex()) {
82
+ this.rendererService.selectVariant(variantIndex);
83
+ }
84
+ stateIndex = parseStateIndex(stateParam, comp.meta.showcaseConfig.states?.length ?? 0);
58
85
  }
59
86
  }
60
87
  else if (pageTitle) {
@@ -63,6 +90,7 @@ export class PrismUrlStateService {
63
90
  this.navigationService.selectPage(page);
64
91
  }
65
92
  }
93
+ this.rendererService.selectState(stateIndex);
66
94
  if (viewId) {
67
95
  this.panelService.activeViewId.set(viewId);
68
96
  }
@@ -74,7 +102,7 @@ export class PrismUrlStateService {
74
102
  this.suppressSync = false;
75
103
  }
76
104
  }
77
- writeToUrl(item, variantIndex, viewId, panelId) {
105
+ writeToUrl(item, variantIndex, stateIndex, viewId, panelId) {
78
106
  // Built from scratch, never from the current search string: parameters the
79
107
  // app does not own must not survive a navigation. `?capture=1` relies on
80
108
  // this; the "capture flag" specs pin the guarantee.
@@ -84,6 +112,9 @@ export class PrismUrlStateService {
84
112
  if (variantIndex > 0) {
85
113
  params.set(PARAM_VARIANT, String(variantIndex));
86
114
  }
115
+ if (stateIndex !== null) {
116
+ params.set(PARAM_STATE, String(stateIndex));
117
+ }
87
118
  }
88
119
  else if (item?.kind === 'page') {
89
120
  params.set(PARAM_PAGE, item.data.title);
@@ -1 +1 @@
1
- {"version":3,"file":"prism-default-theme.d.ts","sourceRoot":"","sources":["../../../src/app/theme/prism-default-theme.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyCnD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyCpD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA0DpD,CAAC;AAEF,eAAO,MAAM,mBAAmB,wBAAmB,CAAC"}
1
+ {"version":3,"file":"prism-default-theme.d.ts","sourceRoot":"","sources":["../../../src/app/theme/prism-default-theme.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyCnD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyCpD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA2DpD,CAAC;AAEF,eAAO,MAAM,mBAAmB,wBAAmB,CAAC"}
@@ -91,13 +91,14 @@ export const PRISM_BASE_TOKENS = {
91
91
  '--dur-base': '0.2s',
92
92
  '--dur-slow': '0.3s',
93
93
  /**
94
- * Chrome density. Set on the shell host, so a consuming app can compact or
95
- * loosen the entire interface from CSS alone:
94
+ * Chrome density. A consuming app compacts or loosens the entire interface
95
+ * with one token in ng-prism.config.ts:
96
96
  *
97
- * prism-shell { --density: .8 }
97
+ * theme: { '--density': '0.8' }
98
98
  *
99
- * There is no signal, service or menu behind this. The whole
100
- * control surface is the custom property.
99
+ * The band heights below resolve it on <html>, where every token is set,
100
+ * so a --density on a descendant such as prism-shell doesn't reach them.
101
+ * There is no signal, service or menu behind this.
101
102
  */
102
103
  '--density': '1',
103
104
  '--band-header': 'calc(40px * var(--density))',
@@ -0,0 +1,7 @@
1
+ import type { NgPrismConfig } from '../../plugin/plugin.types.js';
2
+ /**
3
+ * One notice per deprecated option the config or one of its plugins sets.
4
+ * They never had an effect, so the notice only asks to remove them.
5
+ */
6
+ export declare function describeDeprecatedOptions(config: NgPrismConfig, configFile: string): string[];
7
+ //# sourceMappingURL=deprecated-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deprecated-options.d.ts","sourceRoot":"","sources":["../../../src/builder/config-loader/deprecated-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAOlE;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAe7F"}
@@ -0,0 +1,23 @@
1
+ /** Config options declared since the first release that nothing has ever read. */
2
+ const DEPRECATED_CONFIG_OPTIONS = ['ui', 'themeStylesheet', 'headless', 'appComponent'];
3
+ const NEVER_HAD_AN_EFFECT = 'which is deprecated and will be removed in 23.0.0. It has never had an effect; remove it.';
4
+ /**
5
+ * One notice per deprecated option the config or one of its plugins sets.
6
+ * They never had an effect, so the notice only asks to remove them.
7
+ */
8
+ export function describeDeprecatedOptions(config, configFile) {
9
+ const notices = [];
10
+ for (const option of DEPRECATED_CONFIG_OPTIONS) {
11
+ if (config[option] !== undefined)
12
+ notices.push(`${configFile} sets "${option}", ${NEVER_HAD_AN_EFFECT}`);
13
+ }
14
+ for (const plugin of config.plugins ?? []) {
15
+ if (plugin.wrapComponent !== undefined)
16
+ notices.push(`plugin "${plugin.name}" sets wrapComponent, ${NEVER_HAD_AN_EFFECT}`);
17
+ for (const panel of plugin.panels ?? []) {
18
+ if (panel.position !== undefined)
19
+ notices.push(`plugin "${plugin.name}" sets position on panel "${panel.id}", ${NEVER_HAD_AN_EFFECT}`);
20
+ }
21
+ }
22
+ return notices;
23
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-manifest.generator.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest/runtime-manifest.generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhF,MAAM,WAAW,sBAAsB;IACnC,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;CAClC;AAoHD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAkF/E"}
1
+ {"version":3,"file":"runtime-manifest.generator.d.ts","sourceRoot":"","sources":["../../../src/builder/manifest/runtime-manifest.generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhF,MAAM,WAAW,sBAAsB;IACnC,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;CAClC;AAqHD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAkF/E"}
@@ -68,8 +68,9 @@ function generateWrapperClass(comp) {
68
68
  attrs = '';
69
69
  importsArray = `[${comp.className}]`;
70
70
  }
71
- const inputBindings = bindableInputs.map((i) => ` [${i.name}]="${i.name}()"`).join('');
72
- const outputBindings = comp.outputs.map((o) => ` (${o.name})="${o.name}.emit($event)"`).join('');
71
+ // The wrapper declares its inputs and outputs under the member names and binds the directive's public ones.
72
+ const inputBindings = bindableInputs.map((i) => ` [${i.alias ?? i.name}]="${i.name}()"`).join('');
73
+ const outputBindings = comp.outputs.map((o) => ` (${o.alias ?? o.name})="${o.name}.emit($event)"`).join('');
73
74
  const template = `<${tag}${attrs} ${directiveAttr}${inputBindings}${outputBindings}>{{ __prismContent__() }}</${tag}>`;
74
75
  const members = [];
75
76
  for (const i of bindableInputs) {
@@ -1 +1 @@
1
- {"version":3,"file":"component.scanner.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/component.scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAgDrE;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,WAAW,GAAE,MAAM,EAAO,EAAE,OAAO,cAAoB,GAAG,gBAAgB,EAAE,CAsEzJ"}
1
+ {"version":3,"file":"component.scanner.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/component.scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAkDrE;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,WAAW,GAAE,MAAM,EAAO,EAAE,OAAO,cAAoB,GAAG,gBAAgB,EAAE,CAsEzJ"}
@@ -4,7 +4,9 @@ import { CANVAS_LAYOUTS } from '../../shared/canvas-layout.type.js';
4
4
  import { evaluateExpression, evaluateStatic, findDecorator, getDecoratorArgument, UNEVALUABLE } from './ast-utils.js';
5
5
  import { getClassHierarchy } from './class-hierarchy.js';
6
6
  import { extractInputs, extractOutputs } from './input.extractor.js';
7
+ import { describeValue, readPseudoStates } from './pseudo-states.js';
7
8
  import { describeDeprecatedProviders, describeUnevaluable, describeUnreadableBase } from './showcase-diagnostics.js';
9
+ import { readShowcaseStates } from './showcase-states.js';
8
10
  const COMPONENT_STATUSES = ['stable', 'beta', 'wip', 'deprecated'];
9
11
  function isComponentStatus(value) {
10
12
  return typeof value === 'string' && COMPONENT_STATUSES.includes(value);
@@ -122,6 +124,8 @@ function extractShowcaseConfig(decorator, className, report, checker) {
122
124
  return undefined;
123
125
  // Reported once for the whole field below, wherever it came from: the literal, a spread or a constant.
124
126
  let providers;
127
+ // A state the evaluator dropped whole leaves no element behind, so its position is noted to keep the later states where the source has them.
128
+ const unevaluableStates = new Set();
125
129
  const raw = evaluateStatic(arg, {
126
130
  checker,
127
131
  report: (issue) => {
@@ -129,6 +133,8 @@ function extractShowcaseConfig(decorator, className, report, checker) {
129
133
  providers ??= issue.node;
130
134
  return;
131
135
  }
136
+ if (issue.path[0] === 'states' && issue.path.length === 2 && typeof issue.path[1] === 'number')
137
+ unevaluableStates.add(issue.path[1]);
132
138
  report(describeUnevaluable(className, arg, issue));
133
139
  }
134
140
  });
@@ -168,6 +174,16 @@ function extractShowcaseConfig(decorator, className, report, checker) {
168
174
  config.host = obj['host'];
169
175
  if (obj['renderPage'])
170
176
  config.renderPage = obj['renderPage'];
177
+ if (obj['states'] !== undefined) {
178
+ if (config.renderPage) {
179
+ report(`${className} declares states together with renderPage; a component page has no Overview to show them in. Skipping states.`);
180
+ }
181
+ else {
182
+ const states = readShowcaseStates(obj['states'], className, report, unevaluableStates);
183
+ if (states)
184
+ config.states = states;
185
+ }
186
+ }
171
187
  if (obj['status'] !== undefined) {
172
188
  if (isComponentStatus(obj['status'])) {
173
189
  config.status = obj['status'];
@@ -210,6 +226,17 @@ function extractShowcaseConfig(decorator, className, report, checker) {
210
226
  `invalid canvasLayout "${String(variant['canvasLayout'])}", expected one of: ${CANVAS_LAYOUTS.join(', ')}. Skipping.`);
211
227
  delete cleaned['canvasLayout'];
212
228
  }
229
+ if (variant['pseudo'] !== undefined) {
230
+ const pseudo = readPseudoStates(variant['pseudo'], `${className} variant "${String(variant['name'])}"`, report);
231
+ if (pseudo)
232
+ cleaned['pseudo'] = pseudo;
233
+ else
234
+ delete cleaned['pseudo'];
235
+ }
236
+ if (variant['states'] !== undefined && variant['states'] !== false) {
237
+ report(`${className} variant "${String(variant['name'])}" declares invalid states ${describeValue(variant['states'])}, expected false. Skipping.`);
238
+ delete cleaned['states'];
239
+ }
213
240
  return cleaned;
214
241
  });
215
242
  }
@@ -3,4 +3,9 @@ export interface DiscoveredEntryPoint {
3
3
  importPath: string;
4
4
  }
5
5
  export declare function discoverSecondaryEntryPoints(libraryRoot: string, baseImportPath: string): DiscoveredEntryPoint[];
6
+ /**
7
+ * The primary entry file of the library at `libraryRoot`: `lib.entryFile` of its
8
+ * own `ng-package.json`, or `undefined` when there is no such file.
9
+ */
10
+ export declare function findPrimaryEntryFile(libraryRoot: string): string | undefined;
6
11
  //# sourceMappingURL=entry-point-discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-point-discovery.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/entry-point-discovery.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAKhH"}
1
+ {"version":3,"file":"entry-point-discovery.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/entry-point-discovery.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAKhH;AAKD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS5E"}
@@ -5,6 +5,20 @@ export function discoverSecondaryEntryPoints(libraryRoot, baseImportPath) {
5
5
  findNgPackageJsons(libraryRoot, libraryRoot, baseImportPath, entryPoints);
6
6
  return entryPoints;
7
7
  }
8
+ /** ng-packagr's default for `lib.entryFile`. */
9
+ const NG_PACKAGR_DEFAULT_ENTRY_FILE = 'src/public_api.ts';
10
+ /**
11
+ * The primary entry file of the library at `libraryRoot`: `lib.entryFile` of its
12
+ * own `ng-package.json`, or `undefined` when there is no such file.
13
+ */
14
+ export function findPrimaryEntryFile(libraryRoot) {
15
+ const ngPackagePath = join(libraryRoot, 'ng-package.json');
16
+ if (!existsSync(ngPackagePath))
17
+ return undefined;
18
+ const ngPackage = JSON.parse(readFileSync(ngPackagePath, 'utf-8'));
19
+ const entryFilePath = join(libraryRoot, ngPackage.lib?.entryFile ?? NG_PACKAGR_DEFAULT_ENTRY_FILE);
20
+ return existsSync(entryFilePath) ? entryFilePath : undefined;
21
+ }
8
22
  function findNgPackageJsons(dir, libraryRoot, baseImportPath, result) {
9
23
  const isLibraryRoot = dir === libraryRoot;
10
24
  const ngPackagePath = join(dir, 'ng-package.json');
@@ -2,6 +2,8 @@ import ts from 'typescript';
2
2
  export interface EntryPointInput {
3
3
  entryFile: string;
4
4
  importPath: string;
5
+ /** The library's primary entry point. A component it re-exports from a secondary one keeps that one, silently. */
6
+ primary?: boolean;
5
7
  }
6
8
  export interface ResolvedEntryPoint extends EntryPointInput {
7
9
  exports: ts.Symbol[];
@@ -18,5 +20,5 @@ export interface MultiEntryResult {
18
20
  *
19
21
  * Re-exports (`export * from '...'`) are resolved automatically by TypeScript.
20
22
  */
21
- export declare function resolveEntryPointExports(entryPoints: ReadonlyArray<EntryPointInput>, compilerOptions: ts.CompilerOptions, previousProgram?: ts.Program): MultiEntryResult;
23
+ export declare function resolveEntryPointExports(entryPoints: ReadonlyArray<EntryPointInput>, compilerOptions: ts.CompilerOptions, previousProgram?: ts.Program, host?: ts.CompilerHost): MultiEntryResult;
22
24
  //# sourceMappingURL=entry-point.scanner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry-point.scanner.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/entry-point.scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACvD,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;IACpB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,WAAW,EAAE,aAAa,CAAC,eAAe,CAAC,EAC3C,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,eAAe,CAAC,EAAE,EAAE,CAAC,OAAO,GAC7B,gBAAgB,CA4BlB"}
1
+ {"version":3,"file":"entry-point.scanner.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/entry-point.scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,kHAAkH;IAClH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACvD,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;IACpB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,WAAW,EAAE,aAAa,CAAC,eAAe,CAAC,EAC3C,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,eAAe,CAAC,EAAE,EAAE,CAAC,OAAO,EAC5B,IAAI,CAAC,EAAE,EAAE,CAAC,YAAY,GACvB,gBAAgB,CA8BlB"}
@@ -7,23 +7,24 @@ import ts from 'typescript';
7
7
  *
8
8
  * Re-exports (`export * from '...'`) are resolved automatically by TypeScript.
9
9
  */
10
- export function resolveEntryPointExports(entryPoints, compilerOptions, previousProgram) {
11
- const program = ts.createProgram(entryPoints.map((e) => e.entryFile), compilerOptions, undefined, previousProgram);
10
+ export function resolveEntryPointExports(entryPoints, compilerOptions, previousProgram, host) {
11
+ const program = ts.createProgram(entryPoints.map((e) => e.entryFile), compilerOptions, host, previousProgram);
12
12
  const checker = program.getTypeChecker();
13
- const entries = entryPoints.map(({ entryFile, importPath }) => {
13
+ const entries = entryPoints.map((entryPoint) => {
14
+ const { entryFile } = entryPoint;
14
15
  try {
15
16
  const sourceFile = program.getSourceFile(entryFile);
16
17
  if (!sourceFile) {
17
18
  console.warn(`⚠ ng-prism: source file not found for entry point ${entryFile}, skipping.`);
18
- return { entryFile, importPath, exports: [] };
19
+ return { ...entryPoint, exports: [] };
19
20
  }
20
21
  const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
21
22
  const exports = moduleSymbol ? checker.getExportsOfModule(moduleSymbol) : [];
22
- return { entryFile, importPath, exports };
23
+ return { ...entryPoint, exports };
23
24
  }
24
25
  catch (err) {
25
26
  console.error(`⚠ ng-prism: failed to resolve exports for ${entryFile}: ${err instanceof Error ? err.message : String(err)}`);
26
- return { entryFile, importPath, exports: [] };
27
+ return { ...entryPoint, exports: [] };
27
28
  }
28
29
  });
29
30
  return { program, entries };
@@ -1 +1 @@
1
- {"version":3,"file":"input.extractor.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/input.extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAI1E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,gDAAwC,GAAG,SAAS,EAAE,CAuCrJ;AAsED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,gDAAwC,GAAG,UAAU,EAAE,CAuBvJ"}
1
+ {"version":3,"file":"input.extractor.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/input.extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAI1E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,gDAAwC,GAAG,SAAS,EAAE,CAuCrJ;AAwFD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,gBAAgB,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,gDAAwC,GAAG,UAAU,EAAE,CA4BvJ"}
@@ -1,5 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { evaluateStatic, findDecorator, getDecoratorArgument, getJsDocComment } from './ast-utils.js';
2
+ import { evaluateExpression, evaluateStatic, findDecorator, getDecoratorArgument, getJsDocComment } from './ast-utils.js';
3
3
  import { getClassHierarchy } from './class-hierarchy.js';
4
4
  /**
5
5
  * Extract all @Input(), input() and model() signal metadata from a class
@@ -58,12 +58,14 @@ function readInput(member, name, checker, owner, subclass) {
58
58
  const inputDecorator = findDecorator(member, 'Input');
59
59
  if (inputDecorator) {
60
60
  const required = isDecoratorInputRequired(inputDecorator);
61
+ const alias = readAlias(getDecoratorArgument(inputDecorator), name, checker);
61
62
  const defaultValue = readInitialValue(member, checker);
62
63
  const doc = getJsDocComment(member, checker);
63
64
  const instantiated = subclass && usesTypeParameters(member.type ?? member.initializer, owner, checker) ? getInstantiatedType(name, subclass, checker) : undefined;
64
65
  const { type, values, rawType } = instantiated ? mapType(instantiated, checker) : resolveDecoratorInputType(member, checker);
65
66
  return {
66
67
  name,
68
+ ...(alias && { alias }),
67
69
  type,
68
70
  rawType,
69
71
  required,
@@ -76,6 +78,8 @@ function readInput(member, name, checker, owner, subclass) {
76
78
  if (!signalCall)
77
79
  return undefined;
78
80
  const required = isSignalInputRequired(signalCall);
81
+ // `input(initial, options)`, but `input.required(options)`.
82
+ const alias = readAlias(signalCall.arguments[required ? 0 : 1], name, checker);
79
83
  const defaultValue = readInitialValue(member, checker);
80
84
  const doc = getJsDocComment(member, checker);
81
85
  const declaredType = signalCall.typeArguments?.[0] ?? signalCall.arguments[0];
@@ -84,6 +88,7 @@ function readInput(member, name, checker, owner, subclass) {
84
88
  const { type, values, rawType } = instantiated ? mapType(instantiated, checker) : resolveSignalInputType(signalCall, checker);
85
89
  return {
86
90
  name,
91
+ ...(alias && { alias }),
87
92
  type,
88
93
  rawType,
89
94
  required,
@@ -92,6 +97,17 @@ function readInput(member, name, checker, owner, subclass) {
92
97
  ...(doc && { doc })
93
98
  };
94
99
  }
100
+ /**
101
+ * The `alias` of an input or output, from a decorator argument (`'x'` or
102
+ * `{ alias: 'x' }`) or the options of `input()`, `model()` and `output()`.
103
+ * It counts when the builder can evaluate it statically to a string (a literal
104
+ * or a constant) that differs from the member name.
105
+ */
106
+ function readAlias(arg, name, checker) {
107
+ const value = arg ? evaluateExpression(arg, checker) : undefined;
108
+ const alias = typeof value === 'object' && value !== null ? value['alias'] : value;
109
+ return typeof alias === 'string' && alias !== name ? alias : undefined;
110
+ }
95
111
  /**
96
112
  * Extract all @Output() and output() signal metadata from a class declaration
97
113
  * and the base classes Angular inherits outputs from.
@@ -108,11 +124,14 @@ export function extractOutputs(classDecl, checker, hierarchy = getClassHierarchy
108
124
  const name = member.name && ts.isIdentifier(member.name) ? member.name.text : undefined;
109
125
  if (!name || seen.has(name))
110
126
  continue;
111
- if (!findDecorator(member, 'Output') && !isOutputSignal(member))
127
+ const outputDecorator = findDecorator(member, 'Output');
128
+ if (!outputDecorator && !isOutputSignal(member))
112
129
  continue;
113
130
  const doc = getJsDocComment(member, checker);
131
+ const options = outputDecorator ? getDecoratorArgument(outputDecorator) : member.initializer.arguments[0];
132
+ const alias = readAlias(options, name, checker);
114
133
  seen.add(name);
115
- outputs.push({ name, ...(doc && { doc }) });
134
+ outputs.push({ name, ...(alias && { alias }), ...(doc && { doc }) });
116
135
  }
117
136
  }
118
137
  return outputs;
@@ -0,0 +1,12 @@
1
+ import { type ForcedPseudoStates } from '../../shared/pseudo-state.type.js';
2
+ export declare function describeValue(value: unknown): string;
3
+ /**
4
+ * `Variant.pseudo` as the scanner evaluated it, with everything it cannot use
5
+ * reported and dropped: a value that is no object, an unknown state, and a
6
+ * target that is neither `true` nor selectors. `undefined` when nothing is left.
7
+ *
8
+ * Selectors are checked to be non-empty strings only. Whether one parses is up
9
+ * to the browser, which warns about it once the variant renders.
10
+ */
11
+ export declare function readPseudoStates(value: unknown, where: string, report: (message: string) => void): ForcedPseudoStates | undefined;
12
+ //# sourceMappingURL=pseudo-states.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pseudo-states.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/pseudo-states.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAsD,MAAM,mCAAmC,CAAC;AAUhI,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGpD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,kBAAkB,GAAG,SAAS,CAmBjI"}
@@ -0,0 +1,58 @@
1
+ import { PSEUDO_STATES } from '../../shared/pseudo-state.type.js';
2
+ function isPseudoState(value) {
3
+ return PSEUDO_STATES.includes(value);
4
+ }
5
+ function isSelector(value) {
6
+ return typeof value === 'string' && value.trim() !== '';
7
+ }
8
+ export function describeValue(value) {
9
+ if (typeof value === 'string' || (typeof value === 'object' && value !== null))
10
+ return JSON.stringify(value) ?? String(value);
11
+ return String(value);
12
+ }
13
+ /**
14
+ * `Variant.pseudo` as the scanner evaluated it, with everything it cannot use
15
+ * reported and dropped: a value that is no object, an unknown state, and a
16
+ * target that is neither `true` nor selectors. `undefined` when nothing is left.
17
+ *
18
+ * Selectors are checked to be non-empty strings only. Whether one parses is up
19
+ * to the browser, which warns about it once the variant renders.
20
+ */
21
+ export function readPseudoStates(value, where, report) {
22
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
23
+ report(`${where} declares invalid pseudo ${describeValue(value)}, expected an object mapping pseudo states to true or selectors. Skipping.`);
24
+ return undefined;
25
+ }
26
+ const states = {};
27
+ for (const [state, target] of Object.entries(value)) {
28
+ if (!isPseudoState(state)) {
29
+ report(`${where} declares unknown pseudo state "${state}", expected one of: ${PSEUDO_STATES.join(', ')}. Skipping.`);
30
+ continue;
31
+ }
32
+ const read = readTarget(target, `${where} declares pseudo state "${state}"`, report);
33
+ if (read !== undefined)
34
+ states[state] = read;
35
+ }
36
+ return Object.keys(states).length > 0 ? states : undefined;
37
+ }
38
+ function readTarget(target, where, report) {
39
+ if (target === true || isSelector(target))
40
+ return target;
41
+ if (typeof target === 'string') {
42
+ report(`${where} with an empty selector. Skipping.`);
43
+ return undefined;
44
+ }
45
+ if (Array.isArray(target)) {
46
+ const selectors = target.filter(isSelector);
47
+ const invalid = target.filter((entry) => !isSelector(entry));
48
+ if (invalid.length > 0) {
49
+ report(`${where} with ${invalid.map(describeValue).join(', ')} in its selector list, expected non-empty strings. Skipping ${invalid.length === 1 ? 'it' : 'them'}.`);
50
+ }
51
+ else if (selectors.length === 0) {
52
+ report(`${where} with an empty selector list. Skipping.`);
53
+ }
54
+ return selectors.length > 0 ? selectors : undefined;
55
+ }
56
+ report(`${where} with invalid target ${describeValue(target)}, expected true, a selector or a list of selectors. Skipping.`);
57
+ return undefined;
58
+ }
@@ -20,8 +20,8 @@ export interface Scanner {
20
20
  * transitive type graph (Angular framework typings, etc.) is parsed once and shared via
21
21
  * the program's `TypeChecker`, instead of N programs that each load Material/CDK/RxJS.
22
22
  *
23
- * TypeScript reuses parsed SourceFile objects from the old program on rebuild, making
24
- * incremental scans fast.
23
+ * On rebuild, the source-file cache hands TypeScript the already parsed SourceFile of
24
+ * every unchanged file, so only the changed files are parsed again.
25
25
  */
26
26
  export declare function createScanner(options: CreateScannerOptions): Scanner;
27
27
  //# sourceMappingURL=scanner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,KAAK,eAAe,EAA4B,MAAM,0BAA0B,CAAC;AAE1F,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC5C,eAAe,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACvB,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,0FAA0F;IAC1F,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACpB,kFAAkF;IAClF,IAAI,IAAI,UAAU,CAAC;CACtB;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAiDpE"}
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/builder/scanner/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,KAAK,eAAe,EAA4B,MAAM,0BAA0B,CAAC;AAG1F,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC5C,eAAe,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACvB,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,0FAA0F;IAC1F,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,OAAO;IACpB,kFAAkF;IAClF,IAAI,IAAI,UAAU,CAAC;CACtB;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CA0DpE"}