@ng-prism/core 22.4.0 → 22.5.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 (47) hide show
  1. package/README.md +1 -1
  2. package/dist/app/canvas/prism-canvas-toolbar.component.d.ts +12 -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 +55 -21
  5. package/dist/app/discovery-manifest.d.ts.map +1 -1
  6. package/dist/app/discovery-manifest.js +8 -2
  7. package/dist/app/overview/prism-overview-cell.component.d.ts +6 -0
  8. package/dist/app/overview/prism-overview-cell.component.d.ts.map +1 -1
  9. package/dist/app/overview/prism-overview-cell.component.js +14 -2
  10. package/dist/app/pseudo/pseudo-selector.d.ts +24 -0
  11. package/dist/app/pseudo/pseudo-selector.d.ts.map +1 -0
  12. package/dist/app/pseudo/pseudo-selector.js +136 -0
  13. package/dist/app/pseudo/pseudo-state-marker.d.ts +44 -0
  14. package/dist/app/pseudo/pseudo-state-marker.d.ts.map +1 -0
  15. package/dist/app/pseudo/pseudo-state-marker.js +149 -0
  16. package/dist/app/pseudo/pseudo-stylesheets.d.ts +49 -0
  17. package/dist/app/pseudo/pseudo-stylesheets.d.ts.map +1 -0
  18. package/dist/app/pseudo/pseudo-stylesheets.js +137 -0
  19. package/dist/app/renderer/prism-renderer.component.d.ts +11 -1
  20. package/dist/app/renderer/prism-renderer.component.d.ts.map +1 -1
  21. package/dist/app/renderer/prism-renderer.component.js +39 -15
  22. package/dist/app/renderer/rendered-key.d.ts +24 -0
  23. package/dist/app/renderer/rendered-key.d.ts.map +1 -0
  24. package/dist/app/renderer/rendered-key.js +17 -0
  25. package/dist/app/services/prism-capture.service.d.ts +2 -0
  26. package/dist/app/services/prism-capture.service.d.ts.map +1 -1
  27. package/dist/app/services/prism-capture.service.js +25 -0
  28. package/dist/app/services/prism-pseudo-state.service.d.ts +48 -0
  29. package/dist/app/services/prism-pseudo-state.service.d.ts.map +1 -0
  30. package/dist/app/services/prism-pseudo-state.service.js +98 -0
  31. package/dist/app/shell/prism-shell.component.js +2 -2
  32. package/dist/builder/scanner/component.scanner.d.ts.map +1 -1
  33. package/dist/builder/scanner/component.scanner.js +8 -0
  34. package/dist/builder/scanner/pseudo-states.d.ts +11 -0
  35. package/dist/builder/scanner/pseudo-states.d.ts.map +1 -0
  36. package/dist/builder/scanner/pseudo-states.js +58 -0
  37. package/dist/decorator/showcase.types.d.ts +10 -0
  38. package/dist/decorator/showcase.types.d.ts.map +1 -1
  39. package/dist/plugin/index.d.ts +2 -0
  40. package/dist/plugin/index.d.ts.map +1 -1
  41. package/dist/plugin/index.js +1 -0
  42. package/dist/plugin/plugin.types.d.ts +9 -2
  43. package/dist/plugin/plugin.types.d.ts.map +1 -1
  44. package/dist/shared/pseudo-state.type.d.ts +22 -0
  45. package/dist/shared/pseudo-state.type.d.ts.map +1 -0
  46. package/dist/shared/pseudo-state.type.js +2 -0
  47. package/package.json +4 -4
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.5+-3178c6)](https://www.typescriptlang.org)
7
7
  [![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
8
8
 
9
- **[Live Demo](https://dyingangel666.github.io/ng-prism/demo/?component=ButtonComponent)** · **[Documentation](https://dyingangel666.github.io/ng-prism/)**
9
+ **[Live Demo](https://ng-prism.github.io/ng-prism/demo/?component=ButtonComponent)** · **[Documentation](https://ng-prism.github.io/ng-prism/)**
10
10
 
11
11
  ## Features
12
12
 
@@ -1,13 +1,15 @@
1
1
  import { type CanvasBg } from '../../shared/canvas-bg.type.js';
2
+ import { type PseudoState } from '../../shared/pseudo-state.type.js';
2
3
  import { PrismCanvasService } from '../services/prism-canvas.service.js';
4
+ import { PrismPseudoStateService } from '../services/prism-pseudo-state.service.js';
3
5
  import { PrismVariantBgService } from '../services/prism-variant-bg.service.js';
4
6
  import * as i0 from "@angular/core";
5
7
  /**
6
8
  * The canvas tools, as a rail floating over the canvas.
7
9
  *
8
10
  * Things you toggle constantly (guides, rulers, the viewport constraint) get
9
- * their own button; things you set once (background, zoom, viewport width) live
10
- * in the menu. The template is a view rather than a setting and keeps its own
11
+ * their own button; things you set once (background, forced state, zoom,
12
+ * viewport width) live in the menu. The template is a view rather than a setting and keeps its own
11
13
  * button. Zoom and the active viewport width are shown as readouts; the width
12
14
  * only appears while the viewport constraint is on.
13
15
  *
@@ -20,6 +22,14 @@ import * as i0 from "@angular/core";
20
22
  export declare class PrismCanvasToolbarComponent {
21
23
  protected readonly canvas: PrismCanvasService;
22
24
  protected readonly variantBg: PrismVariantBgService;
25
+ protected readonly pseudoState: PrismPseudoStateService;
26
+ /**
27
+ * The pseudo states the canvas can force, as toggles. Several can be on at
28
+ * once (`:hover` with `:focus-visible`). The active ones carry `is-on`, the
29
+ * ones the variant declares the `is-rec` edge, as in the Canvas group.
30
+ */
31
+ protected readonly states: readonly PseudoState[];
32
+ protected stateTitle(state: PseudoState): string;
23
33
  /** Angular templates resolve names against the component, not the global scope. */
24
34
  protected readonly Math: Math;
25
35
  protected setBg(bg: CanvasBg): void;
@@ -1 +1 @@
1
- {"version":3,"file":"prism-canvas-toolbar.component.d.ts","sourceRoot":"","sources":["../../../src/app/canvas/prism-canvas-toolbar.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAG3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;;AAEhF;;;;;;;;;;;;;;GAcG;AACH,qBAQa,2BAA2B;IACpC,SAAS,CAAC,QAAQ,CAAC,MAAM,qBAA8B;IACvD,SAAS,CAAC,QAAQ,CAAC,SAAS,wBAAiC;IAE7D,mFAAmF;IACnF,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAQ;IAE/B,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAQnC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,QAAQ,CAAC,GAAG,sBAAc;IAEpC;;;;;;;OAOG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAY9C,SAAS,CAAC,QAAQ,CAAC,KAAK;;;QAKtB;IAEF;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,oBAAkB;IAE9C,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;yCA/D9B,2BAA2B;2CAA3B,2BAA2B;CAkEvC"}
1
+ {"version":3,"file":"prism-canvas-toolbar.component.d.ts","sourceRoot":"","sources":["../../../src/app/canvas/prism-canvas-toolbar.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAGpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;;AAEhF;;;;;;;;;;;;;;GAcG;AACH,qBAQa,2BAA2B;IACpC,SAAS,CAAC,QAAQ,CAAC,MAAM,qBAA8B;IACvD,SAAS,CAAC,QAAQ,CAAC,SAAS,wBAAiC;IAC7D,SAAS,CAAC,QAAQ,CAAC,WAAW,0BAAmC;IAEjE;;;;OAIG;IACH,SAAS,CAAC,QAAQ,CAAC,MAAM,yBAAiB;IAE1C,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;IAIhD,mFAAmF;IACnF,SAAS,CAAC,QAAQ,CAAC,IAAI,OAAQ;IAE/B,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAQnC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,QAAQ,CAAC,GAAG,sBAAc;IAEpC;;;;;;;OAOG;IACH,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAY9C,SAAS,CAAC,QAAQ,CAAC,KAAK;;;QAKtB;IAEF;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,oBAAkB;IAE9C,SAAS,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;yCA3E9B,2BAA2B;2CAA3B,2BAA2B;CA8EvC"}
@@ -1,8 +1,10 @@
1
1
  import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
2
2
  import { CANVAS_BGS } from '../../shared/canvas-bg.type.js';
3
+ import { PSEUDO_STATES } from '../../shared/pseudo-state.type.js';
3
4
  import { VIEWPORT_SNAPS } from '../../shared/viewport.type.js';
4
5
  import { PrismIconComponent } from '../icons/prism-icon.component.js';
5
6
  import { PrismCanvasService } from '../services/prism-canvas.service.js';
7
+ import { PrismPseudoStateService } from '../services/prism-pseudo-state.service.js';
6
8
  import { PrismVariantBgService } from '../services/prism-variant-bg.service.js';
7
9
  import * as i0 from "@angular/core";
8
10
  const _forTrack0 = ($index, $item) => $item.value;
@@ -32,35 +34,49 @@ function PrismCanvasToolbarComponent_For_22_Template(rf, ctx) { if (rf & 1) {
32
34
  function PrismCanvasToolbarComponent_For_27_Template(rf, ctx) { if (rf & 1) {
33
35
  const _r4 = i0.ɵɵgetCurrentView();
34
36
  i0.ɵɵelementStart(0, "button", 21);
35
- i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_For_27_Template_button_click_0_listener() { const z_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.canvas.setZoom(z_r5.value)); });
37
+ i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_For_27_Template_button_click_0_listener() { const state_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.pseudoState.toggle(state_r5)); });
36
38
  i0.ɵɵtext(1);
37
39
  i0.ɵɵelementEnd();
38
40
  } if (rf & 2) {
39
- const z_r5 = ctx.$implicit;
41
+ const state_r5 = ctx.$implicit;
40
42
  const ctx_r0 = i0.ɵɵnextContext();
41
- i0.ɵɵclassProp("is-on", ctx_r0.canvas.zoom() === z_r5.value);
43
+ i0.ɵɵclassProp("is-on", ctx_r0.pseudoState.isForced(state_r5))("is-rec", ctx_r0.pseudoState.isDeclared(state_r5));
44
+ i0.ɵɵattribute("aria-pressed", ctx_r0.pseudoState.isForced(state_r5))("title", ctx_r0.stateTitle(state_r5));
42
45
  i0.ɵɵadvance();
43
- i0.ɵɵtextInterpolate1(" ", z_r5.label, " ");
46
+ i0.ɵɵtextInterpolate1(" :", state_r5, " ");
44
47
  } }
45
- function PrismCanvasToolbarComponent_For_34_Template(rf, ctx) { if (rf & 1) {
48
+ function PrismCanvasToolbarComponent_For_32_Template(rf, ctx) { if (rf & 1) {
46
49
  const _r6 = i0.ɵɵgetCurrentView();
47
50
  i0.ɵɵelementStart(0, "button", 21);
48
- i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_For_34_Template_button_click_0_listener() { const w_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.canvas.setViewportWidth(w_r7)); });
51
+ i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_For_32_Template_button_click_0_listener() { const z_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.canvas.setZoom(z_r7.value)); });
49
52
  i0.ɵɵtext(1);
50
53
  i0.ɵɵelementEnd();
51
54
  } if (rf & 2) {
52
- const w_r7 = ctx.$implicit;
55
+ const z_r7 = ctx.$implicit;
53
56
  const ctx_r0 = i0.ɵɵnextContext();
54
- i0.ɵɵclassProp("is-on", ctx_r0.canvas.viewportWidth() === w_r7);
57
+ i0.ɵɵclassProp("is-on", ctx_r0.canvas.zoom() === z_r7.value);
55
58
  i0.ɵɵadvance();
56
- i0.ɵɵtextInterpolate1(" ", w_r7, " ");
59
+ i0.ɵɵtextInterpolate1(" ", z_r7.label, " ");
60
+ } }
61
+ function PrismCanvasToolbarComponent_For_39_Template(rf, ctx) { if (rf & 1) {
62
+ const _r8 = i0.ɵɵgetCurrentView();
63
+ i0.ɵɵelementStart(0, "button", 21);
64
+ i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_For_39_Template_button_click_0_listener() { const w_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.canvas.setViewportWidth(w_r9)); });
65
+ i0.ɵɵtext(1);
66
+ i0.ɵɵelementEnd();
67
+ } if (rf & 2) {
68
+ const w_r9 = ctx.$implicit;
69
+ const ctx_r0 = i0.ɵɵnextContext();
70
+ i0.ɵɵclassProp("is-on", ctx_r0.canvas.viewportWidth() === w_r9);
71
+ i0.ɵɵadvance();
72
+ i0.ɵɵtextInterpolate1(" ", w_r9, " ");
57
73
  } }
58
74
  /**
59
75
  * The canvas tools, as a rail floating over the canvas.
60
76
  *
61
77
  * Things you toggle constantly (guides, rulers, the viewport constraint) get
62
- * their own button; things you set once (background, zoom, viewport width) live
63
- * in the menu. The template is a view rather than a setting and keeps its own
78
+ * their own button; things you set once (background, forced state, zoom,
79
+ * viewport width) live in the menu. The template is a view rather than a setting and keeps its own
64
80
  * button. Zoom and the active viewport width are shown as readouts; the width
65
81
  * only appears while the viewport constraint is on.
66
82
  *
@@ -73,6 +89,16 @@ function PrismCanvasToolbarComponent_For_34_Template(rf, ctx) { if (rf & 1) {
73
89
  export class PrismCanvasToolbarComponent {
74
90
  canvas = inject(PrismCanvasService);
75
91
  variantBg = inject(PrismVariantBgService);
92
+ pseudoState = inject(PrismPseudoStateService);
93
+ /**
94
+ * The pseudo states the canvas can force, as toggles. Several can be on at
95
+ * once (`:hover` with `:focus-visible`). The active ones carry `is-on`, the
96
+ * ones the variant declares the `is-rec` edge, as in the Canvas group.
97
+ */
98
+ states = PSEUDO_STATES;
99
+ stateTitle(state) {
100
+ return this.pseudoState.isDeclared(state) ? `:${state} is forced by this variant` : `Force :${state} on the whole component`;
101
+ }
76
102
  /** Angular templates resolve names against the component, not the global scope. */
77
103
  Math = Math;
78
104
  setBg(bg) {
@@ -132,7 +158,7 @@ export class PrismCanvasToolbarComponent {
132
158
  return s.charAt(0).toUpperCase() + s.slice(1);
133
159
  }
134
160
  static ɵfac = function PrismCanvasToolbarComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PrismCanvasToolbarComponent)(); };
135
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PrismCanvasToolbarComponent, selectors: [["prism-canvas-toolbar"]], decls: 35, vars: 24, consts: [[1, "prism-toolrail"], [1, "prism-toolrail__zoom"], [1, "prism-toolrail__vp"], ["type", "button", "title", "Toggle guides", "aria-label", "Toggle guides", 1, "prism-toolrail__btn", 3, "click"], ["name", "crosshair", 3, "size"], ["type", "button", "title", "Toggle rulers", "aria-label", "Toggle rulers", 1, "prism-toolrail__btn", 3, "click"], ["name", "move", 3, "size"], ["type", "button", "title", "Toggle viewport width", "aria-label", "Toggle viewport width", 1, "prism-toolrail__btn", 3, "click"], ["name", "ruler-dimension", 3, "size"], ["type", "button", "title", "Toggle measure tool", "aria-label", "Toggle measure tool", 1, "prism-toolrail__btn", 3, "click"], ["name", "ruler", 3, "size"], ["type", "button", "popovertarget", "prism-tools", "title", "Canvas, zoom and width", "aria-label", "Canvas, zoom and width", 1, "prism-toolrail__btn"], ["name", "sliders-horizontal", 3, "size"], [1, "prism-toolrail__sep"], ["type", "button", "popovertarget", "prism-template", "title", "Toggle Angular template", "aria-label", "Toggle Angular template", 1, "prism-toolrail__btn"], ["name", "code", 3, "size"], ["popover", "", "id", "prism-tools", "role", "dialog", "aria-label", "Canvas, zoom and width", 1, "prism-toolmenu"], [1, "prism-toolmenu__lbl"], [1, "prism-toolmenu__row"], ["type", "button", 3, "is-on", "is-rec"], ["type", "button", 3, "is-on"], ["type", "button", 3, "click"]], template: function PrismCanvasToolbarComponent_Template(rf, ctx) { if (rf & 1) {
161
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PrismCanvasToolbarComponent, selectors: [["prism-canvas-toolbar"]], decls: 40, vars: 24, consts: [[1, "prism-toolrail"], [1, "prism-toolrail__zoom"], [1, "prism-toolrail__vp"], ["type", "button", "title", "Toggle guides", "aria-label", "Toggle guides", 1, "prism-toolrail__btn", 3, "click"], ["name", "crosshair", 3, "size"], ["type", "button", "title", "Toggle rulers", "aria-label", "Toggle rulers", 1, "prism-toolrail__btn", 3, "click"], ["name", "move", 3, "size"], ["type", "button", "title", "Toggle viewport width", "aria-label", "Toggle viewport width", 1, "prism-toolrail__btn", 3, "click"], ["name", "ruler-dimension", 3, "size"], ["type", "button", "title", "Toggle measure tool", "aria-label", "Toggle measure tool", 1, "prism-toolrail__btn", 3, "click"], ["name", "ruler", 3, "size"], ["type", "button", "popovertarget", "prism-tools", "title", "Canvas, state, zoom and width", "aria-label", "Canvas, state, zoom and width", 1, "prism-toolrail__btn"], ["name", "sliders-horizontal", 3, "size"], [1, "prism-toolrail__sep"], ["type", "button", "popovertarget", "prism-template", "title", "Toggle Angular template", "aria-label", "Toggle Angular template", 1, "prism-toolrail__btn"], ["name", "code", 3, "size"], ["popover", "", "id", "prism-tools", "role", "dialog", "aria-label", "Canvas, state, zoom and width", 1, "prism-toolmenu"], [1, "prism-toolmenu__lbl"], [1, "prism-toolmenu__row"], ["type", "button", 3, "is-on", "is-rec"], ["type", "button", 3, "is-on"], ["type", "button", 3, "click"]], template: function PrismCanvasToolbarComponent_Template(rf, ctx) { if (rf & 1) {
136
162
  i0.ɵɵelementStart(0, "div", 0)(1, "span", 1);
137
163
  i0.ɵɵtext(2);
138
164
  i0.ɵɵconditionalCreate(3, PrismCanvasToolbarComponent_Conditional_3_Template, 2, 1, "span", 2);
@@ -167,19 +193,25 @@ export class PrismCanvasToolbarComponent {
167
193
  i0.ɵɵrepeaterCreate(21, PrismCanvasToolbarComponent_For_22_Template, 2, 6, "button", 19, i0.ɵɵrepeaterTrackByIdentity);
168
194
  i0.ɵɵelementEnd();
169
195
  i0.ɵɵelementStart(23, "span", 17);
170
- i0.ɵɵtext(24, "Zoom");
196
+ i0.ɵɵtext(24, "State");
171
197
  i0.ɵɵelementEnd();
172
198
  i0.ɵɵelementStart(25, "div", 18);
173
- i0.ɵɵrepeaterCreate(26, PrismCanvasToolbarComponent_For_27_Template, 2, 3, "button", 20, _forTrack0);
199
+ i0.ɵɵrepeaterCreate(26, PrismCanvasToolbarComponent_For_27_Template, 2, 7, "button", 19, i0.ɵɵrepeaterTrackByIdentity);
174
200
  i0.ɵɵelementEnd();
175
201
  i0.ɵɵelementStart(28, "span", 17);
176
- i0.ɵɵtext(29, "Width");
202
+ i0.ɵɵtext(29, "Zoom");
177
203
  i0.ɵɵelementEnd();
178
- i0.ɵɵelementStart(30, "div", 18)(31, "button", 21);
179
- i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_Template_button_click_31_listener() { return ctx.canvas.setViewportWidth(null); });
180
- i0.ɵɵtext(32, " Auto ");
204
+ i0.ɵɵelementStart(30, "div", 18);
205
+ i0.ɵɵrepeaterCreate(31, PrismCanvasToolbarComponent_For_32_Template, 2, 3, "button", 20, _forTrack0);
181
206
  i0.ɵɵelementEnd();
182
- i0.ɵɵrepeaterCreate(33, PrismCanvasToolbarComponent_For_34_Template, 2, 3, "button", 20, i0.ɵɵrepeaterTrackByIdentity);
207
+ i0.ɵɵelementStart(33, "span", 17);
208
+ i0.ɵɵtext(34, "Width");
209
+ i0.ɵɵelementEnd();
210
+ i0.ɵɵelementStart(35, "div", 18)(36, "button", 21);
211
+ i0.ɵɵlistener("click", function PrismCanvasToolbarComponent_Template_button_click_36_listener() { return ctx.canvas.setViewportWidth(null); });
212
+ i0.ɵɵtext(37, " Auto ");
213
+ i0.ɵɵelementEnd();
214
+ i0.ɵɵrepeaterCreate(38, PrismCanvasToolbarComponent_For_39_Template, 2, 3, "button", 20, i0.ɵɵrepeaterTrackByIdentity);
183
215
  i0.ɵɵelementEnd()();
184
216
  } if (rf & 2) {
185
217
  i0.ɵɵclassProp("has-rulers", ctx.canvas.rulers());
@@ -214,6 +246,8 @@ export class PrismCanvasToolbarComponent {
214
246
  i0.ɵɵadvance(5);
215
247
  i0.ɵɵrepeater(ctx.bgs);
216
248
  i0.ɵɵadvance(5);
249
+ i0.ɵɵrepeater(ctx.states);
250
+ i0.ɵɵadvance(5);
217
251
  i0.ɵɵrepeater(ctx.zooms);
218
252
  i0.ɵɵadvance(5);
219
253
  i0.ɵɵclassProp("is-on", ctx.canvas.viewportWidth() === null);
@@ -223,6 +257,6 @@ export class PrismCanvasToolbarComponent {
223
257
  }
224
258
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrismCanvasToolbarComponent, [{
225
259
  type: Component,
226
- args: [{ selector: 'prism-canvas-toolbar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [PrismIconComponent], template: "<!-- Anchored in .prism-canvas-wrap, absolute, not fixed:\n a viewport-fixed rail would float over the sidebar and the panel, stay\n put while those are resized, and sit on top of running text in the API\n view where it has no business being. -->\n<div\n class=\"prism-toolrail\"\n [class.has-rulers]=\"canvas.rulers()\">\n <span class=\"prism-toolrail__zoom\">\n {{ Math.round(canvas.zoom() * 100) }}%\n @if (canvas.viewportWidth() !== null) {\n <span class=\"prism-toolrail__vp\">{{ canvas.viewportWidth() }}px</span>\n }\n </span>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.guides()\"\n (click)=\"canvas.toggleGuides()\"\n title=\"Toggle guides\"\n aria-label=\"Toggle guides\"\n [attr.aria-pressed]=\"canvas.guides()\">\n <prism-icon\n name=\"crosshair\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.rulers()\"\n (click)=\"canvas.toggleRulers()\"\n title=\"Toggle rulers\"\n aria-label=\"Toggle rulers\"\n [attr.aria-pressed]=\"canvas.rulers()\">\n <prism-icon\n name=\"move\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.viewportWidth() !== null\"\n (click)=\"canvas.toggleViewport()\"\n title=\"Toggle viewport width\"\n aria-label=\"Toggle viewport width\"\n [attr.aria-pressed]=\"canvas.viewportWidth() !== null\">\n <prism-icon\n name=\"ruler-dimension\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.measure()\"\n (click)=\"canvas.toggleMeasure()\"\n title=\"Toggle measure tool\"\n aria-label=\"Toggle measure tool\"\n [attr.aria-pressed]=\"canvas.measure()\">\n <prism-icon\n name=\"ruler\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n popovertarget=\"prism-tools\"\n title=\"Canvas, zoom and width\"\n aria-label=\"Canvas, zoom and width\">\n <prism-icon\n name=\"sliders-horizontal\"\n [size]=\"14\" />\n </button>\n\n <span class=\"prism-toolrail__sep\"></span>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n popovertarget=\"prism-template\"\n title=\"Toggle Angular template\"\n aria-label=\"Toggle Angular template\">\n <prism-icon\n name=\"code\"\n [size]=\"14\" />\n </button>\n</div>\n\n<!-- Only the three choosers. The toggles stay outside: you flip guides,\n rulers and the viewport constraint constantly while working, and a\n toggle two clicks deep is the classic mistake. What you only ever\n set may live in a menu. -->\n<div\n popover\n id=\"prism-tools\"\n class=\"prism-toolmenu\"\n role=\"dialog\"\n aria-label=\"Canvas, zoom and width\">\n <span class=\"prism-toolmenu__lbl\">Canvas</span>\n <div class=\"prism-toolmenu__row\">\n @for (bg of bgs; track bg) {\n <button\n type=\"button\"\n [class.is-on]=\"variantBg.effective() === bg\"\n [class.is-rec]=\"variantBg.recommended() === bg\"\n [attr.title]=\"bgTitle(bg)\"\n (click)=\"setBg(bg)\">\n {{ capitalize(bg) }}\n </button>\n }\n </div>\n\n <span class=\"prism-toolmenu__lbl\">Zoom</span>\n <div class=\"prism-toolmenu__row\">\n @for (z of zooms; track z.value) {\n <button\n type=\"button\"\n [class.is-on]=\"canvas.zoom() === z.value\"\n (click)=\"canvas.setZoom(z.value)\">\n {{ z.label }}\n </button>\n }\n </div>\n\n <span class=\"prism-toolmenu__lbl\">Width</span>\n <div class=\"prism-toolmenu__row\">\n <button\n type=\"button\"\n [class.is-on]=\"canvas.viewportWidth() === null\"\n (click)=\"canvas.setViewportWidth(null)\">\n Auto\n </button>\n @for (w of viewports; track w) {\n <button\n type=\"button\"\n [class.is-on]=\"canvas.viewportWidth() === w\"\n (click)=\"canvas.setViewportWidth(w)\">\n {{ w }}\n </button>\n }\n </div>\n</div>\n", styles: [":host {\n display: contents;\n}\n\n/* Canvas overlays sit at --prism-canvas-overlay-*, which the stage grows\n when the rulers claim its top and left edges (see the\n .prism-canvas-stage[data-rulers] rule in prism-renderer.component.ts).\n prism-canvas-bg-pill simply inherits those; this rail cannot, because\n capture mode requires it to be a direct child of .prism-canvas-wrap\n outside the stage. So it mirrors the same values off canvas.rulers()\n instead, so keep the two in step.\n\n z-index outranks the rulers' 4 rather than matching it: the rail is a\n control and they are chrome, and the toolbar renders before the\n renderer in the shell, so an equal z-index let the rulers paint over\n the buttons. */\n.prism-toolrail {\n position: absolute;\n top: var(--prism-canvas-overlay-top, 12px);\n right: var(--prism-canvas-overlay-inline, 20px);\n z-index: 5;\n display: flex;\n flex-direction: column;\n gap: var(--sp-1);\n align-items: center;\n padding: var(--sp-2);\n anchor-name: --prism-toolrail;\n background: var(--prism-bg-elevated);\n border: 1px solid var(--prism-border-strong);\n border-radius: var(--radius-md);\n box-shadow: 0 4px 16px -6px rgb(0 0 0 / 40%);\n}\n\n.prism-toolrail.has-rulers {\n --prism-canvas-overlay-top: 28px;\n --prism-canvas-overlay-inline: 28px;\n}\n\n.prism-toolrail__zoom {\n width: 100%;\n padding-bottom: var(--sp-1);\n font-family: var(--font-mono);\n font-size: 9px;\n color: var(--prism-text-ghost);\n text-align: center;\n border-bottom: 1px solid var(--prism-border);\n}\n\n/* The one number on this rail that is not a percentage, so it takes the\n measurement colour the theme already reserves for rulers and guides\n rather than a second neutral that would read as a second zoom. */\n.prism-toolrail__vp {\n display: block;\n color: var(--prism-measure);\n}\n\n.prism-toolrail__btn {\n display: grid;\n place-items: center;\n width: 26px;\n height: 26px;\n padding: 0;\n color: var(--prism-text-muted);\n cursor: pointer;\n background: transparent;\n border: 0;\n border-radius: var(--radius-xs);\n}\n\n.prism-toolrail__btn:hover {\n color: var(--prism-text);\n}\n\n.prism-toolrail__btn:focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 1px;\n}\n\n.prism-toolrail__btn.is-on {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 18%, transparent);\n}\n\n.prism-toolrail__sep {\n width: 14px;\n height: 1px;\n margin: var(--sp-1) 0;\n background: var(--prism-border);\n}\n\n.prism-toolmenu {\n inset: auto;\n gap: var(--sp-2);\n padding: var(--sp-3);\n margin: 0;\n margin-inline-end: var(--sp-2);\n position-area: inline-start;\n position-anchor: --prism-toolrail;\n position-try-fallbacks: flip-inline;\n background: var(--prism-bg-elevated);\n border: 1px solid var(--prism-border-strong);\n border-radius: var(--radius-md);\n box-shadow: 0 8px 28px -10px rgb(0 0 0 / 45%);\n}\n\n/* display belongs on :popover-open and nowhere else (see the note in\n prism-template-popover.component.ts). An author display on the base\n rule outranks the UA's [popover]:not(:popover-open) { display: none }\n and pins the menu open. */\n.prism-toolmenu:popover-open {\n display: flex;\n flex-direction: column;\n}\n\n.prism-toolmenu__lbl {\n font-size: var(--fs-xs);\n color: var(--prism-text-ghost);\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.prism-toolmenu__row {\n display: flex;\n flex-wrap: wrap;\n gap: var(--sp-1);\n}\n\n.prism-toolmenu__row button {\n padding: 2px var(--sp-3);\n font-size: var(--fs-md);\n color: var(--prism-text-2);\n white-space: nowrap;\n cursor: pointer;\n background: transparent;\n border: 1px solid var(--prism-border);\n border-radius: var(--radius-xs);\n}\n\n.prism-toolmenu__row button.is-on {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 16%, transparent);\n border-color: color-mix(in srgb, var(--prism-primary) 38%, transparent);\n}\n\n.prism-toolmenu__row button.is-rec {\n border-color: color-mix(in srgb, var(--prism-primary) 30%, transparent);\n}\n"] }]
260
+ args: [{ selector: 'prism-canvas-toolbar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [PrismIconComponent], template: "<!-- Anchored in .prism-canvas-wrap, absolute, not fixed:\n a viewport-fixed rail would float over the sidebar and the panel, stay\n put while those are resized, and sit on top of running text in the API\n view where it has no business being. -->\n<div\n class=\"prism-toolrail\"\n [class.has-rulers]=\"canvas.rulers()\">\n <span class=\"prism-toolrail__zoom\">\n {{ Math.round(canvas.zoom() * 100) }}%\n @if (canvas.viewportWidth() !== null) {\n <span class=\"prism-toolrail__vp\">{{ canvas.viewportWidth() }}px</span>\n }\n </span>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.guides()\"\n (click)=\"canvas.toggleGuides()\"\n title=\"Toggle guides\"\n aria-label=\"Toggle guides\"\n [attr.aria-pressed]=\"canvas.guides()\">\n <prism-icon\n name=\"crosshair\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.rulers()\"\n (click)=\"canvas.toggleRulers()\"\n title=\"Toggle rulers\"\n aria-label=\"Toggle rulers\"\n [attr.aria-pressed]=\"canvas.rulers()\">\n <prism-icon\n name=\"move\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.viewportWidth() !== null\"\n (click)=\"canvas.toggleViewport()\"\n title=\"Toggle viewport width\"\n aria-label=\"Toggle viewport width\"\n [attr.aria-pressed]=\"canvas.viewportWidth() !== null\">\n <prism-icon\n name=\"ruler-dimension\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n [class.is-on]=\"canvas.measure()\"\n (click)=\"canvas.toggleMeasure()\"\n title=\"Toggle measure tool\"\n aria-label=\"Toggle measure tool\"\n [attr.aria-pressed]=\"canvas.measure()\">\n <prism-icon\n name=\"ruler\"\n [size]=\"14\" />\n </button>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n popovertarget=\"prism-tools\"\n title=\"Canvas, state, zoom and width\"\n aria-label=\"Canvas, state, zoom and width\">\n <prism-icon\n name=\"sliders-horizontal\"\n [size]=\"14\" />\n </button>\n\n <span class=\"prism-toolrail__sep\"></span>\n\n <button\n type=\"button\"\n class=\"prism-toolrail__btn\"\n popovertarget=\"prism-template\"\n title=\"Toggle Angular template\"\n aria-label=\"Toggle Angular template\">\n <prism-icon\n name=\"code\"\n [size]=\"14\" />\n </button>\n</div>\n\n<!-- Only the choosers. The toggles stay outside: you flip guides,\n rulers and the viewport constraint constantly while working, and a\n toggle two clicks deep is the classic mistake. What you only ever\n set may live in a menu. The states are toggles too, but set once per\n variant and dropped with it, like the background. -->\n<div\n popover\n id=\"prism-tools\"\n class=\"prism-toolmenu\"\n role=\"dialog\"\n aria-label=\"Canvas, state, zoom and width\">\n <span class=\"prism-toolmenu__lbl\">Canvas</span>\n <div class=\"prism-toolmenu__row\">\n @for (bg of bgs; track bg) {\n <button\n type=\"button\"\n [class.is-on]=\"variantBg.effective() === bg\"\n [class.is-rec]=\"variantBg.recommended() === bg\"\n [attr.title]=\"bgTitle(bg)\"\n (click)=\"setBg(bg)\">\n {{ capitalize(bg) }}\n </button>\n }\n </div>\n\n <span class=\"prism-toolmenu__lbl\">State</span>\n <div class=\"prism-toolmenu__row\">\n @for (state of states; track state) {\n <button\n type=\"button\"\n [class.is-on]=\"pseudoState.isForced(state)\"\n [class.is-rec]=\"pseudoState.isDeclared(state)\"\n [attr.aria-pressed]=\"pseudoState.isForced(state)\"\n [attr.title]=\"stateTitle(state)\"\n (click)=\"pseudoState.toggle(state)\">\n :{{ state }}\n </button>\n }\n </div>\n\n <span class=\"prism-toolmenu__lbl\">Zoom</span>\n <div class=\"prism-toolmenu__row\">\n @for (z of zooms; track z.value) {\n <button\n type=\"button\"\n [class.is-on]=\"canvas.zoom() === z.value\"\n (click)=\"canvas.setZoom(z.value)\">\n {{ z.label }}\n </button>\n }\n </div>\n\n <span class=\"prism-toolmenu__lbl\">Width</span>\n <div class=\"prism-toolmenu__row\">\n <button\n type=\"button\"\n [class.is-on]=\"canvas.viewportWidth() === null\"\n (click)=\"canvas.setViewportWidth(null)\">\n Auto\n </button>\n @for (w of viewports; track w) {\n <button\n type=\"button\"\n [class.is-on]=\"canvas.viewportWidth() === w\"\n (click)=\"canvas.setViewportWidth(w)\">\n {{ w }}\n </button>\n }\n </div>\n</div>\n", styles: [":host {\n display: contents;\n}\n\n/* Canvas overlays sit at --prism-canvas-overlay-*, which the stage grows\n when the rulers claim its top and left edges (see the\n .prism-canvas-stage[data-rulers] rule in prism-renderer.component.ts).\n prism-canvas-bg-pill simply inherits those; this rail cannot, because\n capture mode requires it to be a direct child of .prism-canvas-wrap\n outside the stage. So it mirrors the same values off canvas.rulers()\n instead, so keep the two in step.\n\n z-index outranks the rulers' 4 rather than matching it: the rail is a\n control and they are chrome, and the toolbar renders before the\n renderer in the shell, so an equal z-index let the rulers paint over\n the buttons. */\n.prism-toolrail {\n position: absolute;\n top: var(--prism-canvas-overlay-top, 12px);\n right: var(--prism-canvas-overlay-inline, 20px);\n z-index: 5;\n display: flex;\n flex-direction: column;\n gap: var(--sp-1);\n align-items: center;\n padding: var(--sp-2);\n anchor-name: --prism-toolrail;\n background: var(--prism-bg-elevated);\n border: 1px solid var(--prism-border-strong);\n border-radius: var(--radius-md);\n box-shadow: 0 4px 16px -6px rgb(0 0 0 / 40%);\n}\n\n.prism-toolrail.has-rulers {\n --prism-canvas-overlay-top: 28px;\n --prism-canvas-overlay-inline: 28px;\n}\n\n.prism-toolrail__zoom {\n width: 100%;\n padding-bottom: var(--sp-1);\n font-family: var(--font-mono);\n font-size: 9px;\n color: var(--prism-text-ghost);\n text-align: center;\n border-bottom: 1px solid var(--prism-border);\n}\n\n/* The one number on this rail that is not a percentage, so it takes the\n measurement colour the theme already reserves for rulers and guides\n rather than a second neutral that would read as a second zoom. */\n.prism-toolrail__vp {\n display: block;\n color: var(--prism-measure);\n}\n\n.prism-toolrail__btn {\n display: grid;\n place-items: center;\n width: 26px;\n height: 26px;\n padding: 0;\n color: var(--prism-text-muted);\n cursor: pointer;\n background: transparent;\n border: 0;\n border-radius: var(--radius-xs);\n}\n\n.prism-toolrail__btn:hover {\n color: var(--prism-text);\n}\n\n.prism-toolrail__btn:focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 1px;\n}\n\n.prism-toolrail__btn.is-on {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 18%, transparent);\n}\n\n.prism-toolrail__sep {\n width: 14px;\n height: 1px;\n margin: var(--sp-1) 0;\n background: var(--prism-border);\n}\n\n.prism-toolmenu {\n inset: auto;\n gap: var(--sp-2);\n padding: var(--sp-3);\n margin: 0;\n margin-inline-end: var(--sp-2);\n position-area: inline-start;\n position-anchor: --prism-toolrail;\n position-try-fallbacks: flip-inline;\n background: var(--prism-bg-elevated);\n border: 1px solid var(--prism-border-strong);\n border-radius: var(--radius-md);\n box-shadow: 0 8px 28px -10px rgb(0 0 0 / 45%);\n}\n\n/* display belongs on :popover-open and nowhere else (see the note in\n prism-template-popover.component.ts). An author display on the base\n rule outranks the UA's [popover]:not(:popover-open) { display: none }\n and pins the menu open. */\n.prism-toolmenu:popover-open {\n display: flex;\n flex-direction: column;\n}\n\n.prism-toolmenu__lbl {\n font-size: var(--fs-xs);\n color: var(--prism-text-ghost);\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.prism-toolmenu__row {\n display: flex;\n flex-wrap: wrap;\n gap: var(--sp-1);\n}\n\n.prism-toolmenu__row button {\n padding: 2px var(--sp-3);\n font-size: var(--fs-md);\n color: var(--prism-text-2);\n white-space: nowrap;\n cursor: pointer;\n background: transparent;\n border: 1px solid var(--prism-border);\n border-radius: var(--radius-xs);\n}\n\n.prism-toolmenu__row button.is-on {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 16%, transparent);\n border-color: color-mix(in srgb, var(--prism-primary) 38%, transparent);\n}\n\n.prism-toolmenu__row button.is-rec {\n border-color: color-mix(in srgb, var(--prism-primary) 30%, transparent);\n}\n"] }]
227
261
  }], null, null); })();
228
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismCanvasToolbarComponent, { className: "PrismCanvasToolbarComponent", filePath: "app/canvas/prism-canvas-toolbar.component.ts", lineNumber: 31 }); })();
262
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismCanvasToolbarComponent, { className: "PrismCanvasToolbarComponent", filePath: "app/canvas/prism-canvas-toolbar.component.ts", lineNumber: 33 }); })();
@@ -1 +1 @@
1
- {"version":3,"file":"discovery-manifest.d.ts","sourceRoot":"","sources":["../../src/app/discovery-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,iBAAiB,EAAoB,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAuD1H,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAM/G;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,iBAAiB,CAsCnF"}
1
+ {"version":3,"file":"discovery-manifest.d.ts","sourceRoot":"","sources":["../../src/app/discovery-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,iBAAiB,EAAoB,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAyD1H,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAM/G;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,iBAAiB,CAyCnF"}
@@ -1,4 +1,5 @@
1
1
  import { resolveVariantBg } from '../shared/variant-bg.js';
2
+ import { forcesAnyState } from './pseudo/pseudo-state-marker.js';
2
3
  /**
3
4
  * External tooling reads `__PRISM_MANIFEST__` through a structured-clone bridge
4
5
  * (Playwright's `page.evaluate()`, `postMessage`, devtools). `ShowcaseConfig.meta`
@@ -75,8 +76,13 @@ export function buildDiscoveryManifest(manifest) {
75
76
  const variants = declared.length
76
77
  ? declared.map((variant, index) => {
77
78
  const meta = serializableMeta(variant.meta);
78
- const bg = resolveVariantBg(showcaseConfig, index);
79
- return meta ? { name: variant.name, index, bg, meta } : { name: variant.name, index, bg };
79
+ const pseudo = forcesAnyState(variant.pseudo) ? serializableMeta(variant.pseudo) : undefined;
80
+ const discovered = { name: variant.name, index, bg: resolveVariantBg(showcaseConfig, index) };
81
+ if (meta)
82
+ discovered.meta = meta;
83
+ if (pseudo)
84
+ discovered.pseudo = pseudo;
85
+ return discovered;
80
86
  })
81
87
  : [
82
88
  {
@@ -10,12 +10,18 @@ import * as i0 from "@angular/core";
10
10
  * writing to any of them would corrupt what they mean. `data-prism-rendered`
11
11
  * matters most: it is the selector external screenshot runners key on (see
12
12
  * `docs/guide/external-tooling.md`), and this component never emits it.
13
+ *
14
+ * Forced pseudo states are the variant's own, applied by a marker of the
15
+ * cell's own, so a hovered cell never hovers its neighbour. The tools menu's
16
+ * state toggle does not reach here: like every other control, it belongs to
17
+ * the Playground.
13
18
  */
14
19
  export declare class PrismOverviewCellComponent {
15
20
  readonly component: import("@angular/core").InputSignal<RuntimeComponent>;
16
21
  readonly index: import("@angular/core").InputSignal<number>;
17
22
  private readonly injector;
18
23
  private readonly destroyRef;
24
+ private readonly pseudoMarker;
19
25
  private readonly outlet;
20
26
  /** Never null: `resolveVariantBg` falls back to `DEFAULT_VARIANT_BG`. */
21
27
  protected readonly bg: import("@angular/core").Signal<import("../services/prism-canvas.service.js").CanvasBg>;
@@ -1 +1 @@
1
- {"version":3,"file":"prism-overview-cell.component.d.ts","sourceRoot":"","sources":["../../../src/app/overview/prism-overview-cell.component.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;;AAOrE;;;;;;;;;;GAUG;AACH,qBAYa,0BAA0B;IACnC,QAAQ,CAAC,SAAS,wDAAsC;IACxD,QAAQ,CAAC,KAAK,8CAA4B;IAE1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAEpB;IAEH,yEAAyE;IACzE,SAAS,CAAC,QAAQ,CAAC,EAAE,yFAAwF;IAE7G,SAAS,CAAC,QAAQ,CAAC,OAAO,yCAUvB;IAEH,SAAS,CAAC,QAAQ,CAAC,MAAM,0CAKtB;;IAmBH,OAAO,CAAC,KAAK;yCAjDJ,0BAA0B;2CAA1B,0BAA0B;CAyFtC"}
1
+ {"version":3,"file":"prism-overview-cell.component.d.ts","sourceRoot":"","sources":["../../../src/app/overview/prism-overview-cell.component.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;;AAQrE;;;;;;;;;;;;;;;GAeG;AACH,qBAYa,0BAA0B;IACnC,QAAQ,CAAC,SAAS,wDAAsC;IACxD,QAAQ,CAAC,KAAK,8CAA4B;IAE1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkD;IAC/E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAEpB;IAEH,yEAAyE;IACzE,SAAS,CAAC,QAAQ,CAAC,EAAE,yFAAwF;IAE7G,SAAS,CAAC,QAAQ,CAAC,OAAO,yCAUvB;IAEH,SAAS,CAAC,QAAQ,CAAC,MAAM,0CAKtB;;IAsBH,OAAO,CAAC,KAAK;yCArDJ,0BAA0B;2CAA1B,0BAA0B;CA+FtC"}
@@ -3,6 +3,7 @@ import { resolveVariantBg } from '../../shared/variant-bg.js';
3
3
  import { CANVAS_BG_STYLES } from '../canvas/canvas-bg.styles.js';
4
4
  import { buildKnownInputs } from '../renderer/known-inputs.js';
5
5
  import { parseContentToNodes } from '../renderer/projectable-content.js';
6
+ import { PrismPseudoStateService } from '../services/prism-pseudo-state.service.js';
6
7
  import { computeVariantState } from '../services/prism-renderer.service.js';
7
8
  import * as i0 from "@angular/core";
8
9
  const _c0 = ["outlet"];
@@ -16,6 +17,11 @@ const _c0 = ["outlet"];
16
17
  * writing to any of them would corrupt what they mean. `data-prism-rendered`
17
18
  * matters most: it is the selector external screenshot runners key on (see
18
19
  * `docs/guide/external-tooling.md`), and this component never emits it.
20
+ *
21
+ * Forced pseudo states are the variant's own, applied by a marker of the
22
+ * cell's own, so a hovered cell never hovers its neighbour. The tools menu's
23
+ * state toggle does not reach here: like every other control, it belongs to
24
+ * the Playground.
19
25
  */
20
26
  export class PrismOverviewCellComponent {
21
27
  component = input.required(/* @ts-ignore */
@@ -24,6 +30,7 @@ export class PrismOverviewCellComponent {
24
30
  ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
25
31
  injector = inject(Injector);
26
32
  destroyRef = inject(DestroyRef);
33
+ pseudoMarker = inject(PrismPseudoStateService).createMarker();
27
34
  outlet = viewChild.required('outlet', { ...(ngDevMode ? { debugName: "outlet" } : /* istanbul ignore next */ {}), read: ViewContainerRef });
28
35
  /** Never null: `resolveVariantBg` falls back to `DEFAULT_VARIANT_BG`. */
29
36
  bg = computed(() => resolveVariantBg(this.component().meta.showcaseConfig, this.index()), /* @ts-ignore */
@@ -51,7 +58,10 @@ export class PrismOverviewCellComponent {
51
58
  const index = this.index();
52
59
  untracked(() => this.mount(component, index));
53
60
  });
54
- this.destroyRef.onDestroy(() => this.outlet().clear());
61
+ this.destroyRef.onDestroy(() => {
62
+ this.pseudoMarker.clear();
63
+ this.outlet().clear();
64
+ });
55
65
  }
56
66
  // The Playground lets a variant that throws on construction propagate: one
57
67
  // broken instance, and the user navigates away from it. The Overview
@@ -82,6 +92,7 @@ export class PrismOverviewCellComponent {
82
92
  ref.setInput(key, value);
83
93
  }
84
94
  ref.changeDetectorRef.detectChanges();
95
+ this.pseudoMarker.apply(ref.location.nativeElement, component.meta.showcaseConfig.variants?.[index]?.pseudo);
85
96
  }
86
97
  catch (error) {
87
98
  // `createComponent` attaches the host element and its structural DOM
@@ -92,6 +103,7 @@ export class PrismOverviewCellComponent {
92
103
  // a caught cell actually show an empty stage with its caption still in
93
104
  // place, which shows "this variant failed" instead of a broken grid
94
105
  // with no indication of which cell caused it.
106
+ this.pseudoMarker.clear();
95
107
  this.outlet().clear();
96
108
  console.error(`[ng-prism] Variant ${index} of ${component.meta.className} failed to render:`, error);
97
109
  }
@@ -125,4 +137,4 @@ export class PrismOverviewCellComponent {
125
137
  }], () => [], { component: [{ type: i0.Input, args: [{ isSignal: true, alias: "component", required: true }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: true }] }], outlet: [{ type: i0.ViewChild, args: ['outlet', { ...{
126
138
  read: ViewContainerRef
127
139
  }, isSignal: true }] }] }); })();
128
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismOverviewCellComponent, { className: "PrismOverviewCellComponent", filePath: "app/overview/prism-overview-cell.component.ts", lineNumber: 32 }); })();
140
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismOverviewCellComponent, { className: "PrismOverviewCellComponent", filePath: "app/overview/prism-overview-cell.component.ts", lineNumber: 38 }); })();
@@ -0,0 +1,24 @@
1
+ import { type PseudoState } from '../../shared/pseudo-state.type.js';
2
+ /** Prefix of the classes that stand in for a forced pseudo-class. */
3
+ export declare const PSEUDO_CLASS_PREFIX = "prism-pseudo--";
4
+ /** The class that stands in for `state`, e.g. `prism-pseudo--focus-visible`. */
5
+ export declare function pseudoStateClass(state: PseudoState): string;
6
+ /**
7
+ * The selector with every forced pseudo-class `:x` widened to
8
+ * `:is(:x, .prism-pseudo--x)` ({@link pseudoStateClass}), or `null` when it
9
+ * uses none or has been widened before.
10
+ *
11
+ * Without the class on any element the widened selector matches exactly what
12
+ * the original matched, with the same specificity: `:is()` takes the highest
13
+ * of its arguments, and a class weighs what a pseudo-class weighs. With the
14
+ * class, an element counts as being in the state whether it is forced or real,
15
+ * which keeps `:not(:hover)` exact in both directions and lets a forced state
16
+ * combine with a real one in the same selector.
17
+ *
18
+ * Tokenised rather than string-replaced. An escaped colon (`.md\:hover`) and an
19
+ * attribute value (`[title=":hover"]`) are left alone, and a state that follows
20
+ * a pseudo-element (`::part(x):hover`) is kept as it is, because `:is()` is not
21
+ * allowed there.
22
+ */
23
+ export declare function rewritePseudoSelector(selectorText: string): string | null;
24
+ //# sourceMappingURL=pseudo-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pseudo-selector.d.ts","sourceRoot":"","sources":["../../../src/app/pseudo/pseudo-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEpF,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE3D;AAWD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgDzE"}
@@ -0,0 +1,136 @@
1
+ import { PSEUDO_STATES } from '../../shared/pseudo-state.type.js';
2
+ /** Prefix of the classes that stand in for a forced pseudo-class. */
3
+ export const PSEUDO_CLASS_PREFIX = 'prism-pseudo--';
4
+ /** The class that stands in for `state`, e.g. `prism-pseudo--focus-visible`. */
5
+ export function pseudoStateClass(state) {
6
+ return `${PSEUDO_CLASS_PREFIX}${state}`;
7
+ }
8
+ const FORCEABLE = new Set(PSEUDO_STATES);
9
+ /** CSS 2 pseudo-elements, which still parse with a single colon. */
10
+ const LEGACY_PSEUDO_ELEMENTS = new Set(['before', 'after', 'first-line', 'first-letter']);
11
+ const HEX_DIGIT = /[0-9a-f]/i;
12
+ const WHITESPACE = /[ \t\n\r\f]/;
13
+ const IDENT_CHAR = /[a-z0-9_-]/i;
14
+ /**
15
+ * The selector with every forced pseudo-class `:x` widened to
16
+ * `:is(:x, .prism-pseudo--x)` ({@link pseudoStateClass}), or `null` when it
17
+ * uses none or has been widened before.
18
+ *
19
+ * Without the class on any element the widened selector matches exactly what
20
+ * the original matched, with the same specificity: `:is()` takes the highest
21
+ * of its arguments, and a class weighs what a pseudo-class weighs. With the
22
+ * class, an element counts as being in the state whether it is forced or real,
23
+ * which keeps `:not(:hover)` exact in both directions and lets a forced state
24
+ * combine with a real one in the same selector.
25
+ *
26
+ * Tokenised rather than string-replaced. An escaped colon (`.md\:hover`) and an
27
+ * attribute value (`[title=":hover"]`) are left alone, and a state that follows
28
+ * a pseudo-element (`::part(x):hover`) is kept as it is, because `:is()` is not
29
+ * allowed there.
30
+ */
31
+ export function rewritePseudoSelector(selectorText) {
32
+ const s = selectorText;
33
+ if (s.includes(PSEUDO_CLASS_PREFIX))
34
+ return null;
35
+ let out = '';
36
+ let changed = false;
37
+ // One entry per nesting level: whether the compound being read follows a pseudo-element.
38
+ const afterPseudoElement = [false];
39
+ let i = 0;
40
+ while (i < s.length) {
41
+ const ch = s[i];
42
+ const level = afterPseudoElement.length - 1;
43
+ let end = i + 1;
44
+ if (ch === '\\') {
45
+ end = escapeEnd(s, i);
46
+ }
47
+ else if (ch === '"' || ch === "'") {
48
+ end = stringEnd(s, i);
49
+ }
50
+ else if (ch === '[') {
51
+ end = attributeEnd(s, i);
52
+ }
53
+ else if (ch === '(') {
54
+ afterPseudoElement.push(false);
55
+ }
56
+ else if (ch === ')') {
57
+ if (level > 0)
58
+ afterPseudoElement.pop();
59
+ }
60
+ else if (ch === ',' || ch === '>' || ch === '+' || ch === '~' || WHITESPACE.test(ch)) {
61
+ afterPseudoElement[level] = false;
62
+ }
63
+ else if (ch === ':') {
64
+ const isElement = s[i + 1] === ':';
65
+ const nameStart = i + (isElement ? 2 : 1);
66
+ end = identEnd(s, nameStart);
67
+ const name = s.slice(nameStart, end).toLowerCase();
68
+ if (!isElement && FORCEABLE.has(name) && s[end] !== '(' && !afterPseudoElement[level]) {
69
+ out += `:is(${s.slice(i, end)}, .${PSEUDO_CLASS_PREFIX}${name})`;
70
+ changed = true;
71
+ i = end;
72
+ continue;
73
+ }
74
+ if (isElement || LEGACY_PSEUDO_ELEMENTS.has(name))
75
+ afterPseudoElement[level] = true;
76
+ }
77
+ out += s.slice(i, end);
78
+ i = end;
79
+ }
80
+ return changed ? out : null;
81
+ }
82
+ /** End of the escape starting at `start`: a hex escape takes up to six digits and one whitespace character. */
83
+ function escapeEnd(s, start) {
84
+ let i = start + 1;
85
+ if (i >= s.length)
86
+ return i;
87
+ if (!HEX_DIGIT.test(s[i]))
88
+ return i + 1;
89
+ while (i < s.length && i < start + 7 && HEX_DIGIT.test(s[i]))
90
+ i++;
91
+ if (s[i] === '\r' && s[i + 1] === '\n')
92
+ return i + 2;
93
+ return i < s.length && WHITESPACE.test(s[i]) ? i + 1 : i;
94
+ }
95
+ function identEnd(s, start) {
96
+ let i = start;
97
+ while (i < s.length) {
98
+ if (s[i] === '\\') {
99
+ i = escapeEnd(s, i);
100
+ }
101
+ else if (IDENT_CHAR.test(s[i]) || s.charCodeAt(i) >= 0x80) {
102
+ i++;
103
+ }
104
+ else {
105
+ break;
106
+ }
107
+ }
108
+ return i;
109
+ }
110
+ function stringEnd(s, start) {
111
+ const quote = s[start];
112
+ let i = start + 1;
113
+ while (i < s.length) {
114
+ if (s[i] === '\\')
115
+ i += 2;
116
+ else if (s[i] === quote)
117
+ return i + 1;
118
+ else
119
+ i++;
120
+ }
121
+ return i;
122
+ }
123
+ function attributeEnd(s, start) {
124
+ let i = start + 1;
125
+ while (i < s.length) {
126
+ if (s[i] === '\\')
127
+ i = escapeEnd(s, i);
128
+ else if (s[i] === '"' || s[i] === "'")
129
+ i = stringEnd(s, i);
130
+ else if (s[i] === ']')
131
+ return i + 1;
132
+ else
133
+ i++;
134
+ }
135
+ return i;
136
+ }
@@ -0,0 +1,44 @@
1
+ import { type ForcedPseudoStates } from '../../shared/pseudo-state.type.js';
2
+ import type { PseudoStyleSheets } from './pseudo-stylesheets.js';
3
+ /** The element a marker forces states in, and the states it forces there. */
4
+ export interface AppliedPseudoStates {
5
+ root: Element;
6
+ states: ForcedPseudoStates;
7
+ }
8
+ /** True when `states` forces at least one state on at least one target. */
9
+ export declare function forcesAnyState(states: ForcedPseudoStates | null | undefined): states is ForcedPseudoStates;
10
+ /**
11
+ * Forces a variant's pseudo states on one rendered component.
12
+ *
13
+ * Puts the stand-in class of each state ({@link pseudoStateClass}) on the
14
+ * targeted elements, and holds the document's {@link PseudoStyleSheets} so that
15
+ * every selector using the pseudo-class also matches that class. The
16
+ * component's own CSS then applies, with no special case for sibling
17
+ * combinators, pseudo-elements, `:has()` or `:not()`.
18
+ *
19
+ * The root is watched while states are forced: an element rendered later
20
+ * (`@if`), or one whose classes or attributes change so that it starts or
21
+ * stops matching a selector (`button:not([disabled])`), is marked again.
22
+ *
23
+ * One marker per rendered component: the Playground canvas has one, each
24
+ * Overview cell has its own, so a state never leaks into a neighbouring cell.
25
+ */
26
+ export declare class PseudoStateMarker {
27
+ private readonly stylesheets;
28
+ private readonly _applied;
29
+ private observer;
30
+ /**
31
+ * What the marks are in place for, `null` while nothing is forced. A
32
+ * signal, so the renderer can hold back `data-prism-rendered` until the
33
+ * states it reports are the ones on screen.
34
+ */
35
+ readonly applied: import("@angular/core").Signal<AppliedPseudoStates | null>;
36
+ constructor(stylesheets: PseudoStyleSheets);
37
+ /** Forces `states` under `root`, replacing whatever this marker forced before. */
38
+ apply(root: Element | null, states: ForcedPseudoStates | null | undefined): void;
39
+ /** Removes every mark, stops watching, and releases the stylesheets. */
40
+ clear(): void;
41
+ private observe;
42
+ private mark;
43
+ }
44
+ //# sourceMappingURL=pseudo-state-marker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pseudo-state-marker.d.ts","sourceRoot":"","sources":["../../../src/app/pseudo/pseudo-state-marker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,kBAAkB,EAAoC,MAAM,mCAAmC,CAAC;AAE9G,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;CAC9B;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,IAAI,kBAAkB,CAE1G;AA8CD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,iBAAiB;IAWd,OAAO,CAAC,QAAQ,CAAC,WAAW;IAVxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IACrE,OAAO,CAAC,QAAQ,CAAiC;IAEjD;;;;OAIG;IACH,QAAQ,CAAC,OAAO,6DAA8B;gBAEjB,WAAW,EAAE,iBAAiB;IAE3D,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAqBhF,wEAAwE;IACxE,KAAK,IAAI,IAAI;IAab,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,IAAI;CAoBf"}