@ng-prism/core 21.11.0 → 21.12.0-beta.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.
@@ -3,7 +3,10 @@ import * as i0 from "@angular/core";
3
3
  export declare class PrismVariantRibbonComponent {
4
4
  private readonly navigationService;
5
5
  protected readonly rendererService: PrismRendererService;
6
- protected readonly variants: import("@angular/core").Signal<import("../../index.js").Variant[]>;
6
+ private readonly tabsContainer;
7
+ private readonly tabButtons;
8
+ protected readonly variants: import("@angular/core").Signal<import("../../index.js").Variant<unknown>[]>;
9
+ constructor();
7
10
  protected variantColor(name: string, index: number): string;
8
11
  protected prev(): void;
9
12
  protected next(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"prism-variant-ribbon.component.d.ts","sourceRoot":"","sources":["../../../src/app/variant-ribbon/prism-variant-ribbon.component.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;;AAgB7E,qBAkJa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,SAAS,CAAC,QAAQ,CAAC,eAAe,uBAAgC;IAElE,SAAS,CAAC,QAAQ,CAAC,QAAQ,qEAGxB;IAEH,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAI3D,SAAS,CAAC,IAAI,IAAI,IAAI;IAKtB,SAAS,CAAC,IAAI,IAAI,IAAI;yCAlBX,2BAA2B;2CAA3B,2BAA2B;CAuBvC"}
1
+ {"version":3,"file":"prism-variant-ribbon.component.d.ts","sourceRoot":"","sources":["../../../src/app/variant-ribbon/prism-variant-ribbon.component.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;;AAgB7E,qBA8Ja,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkC;IACpE,SAAS,CAAC,QAAQ,CAAC,eAAe,uBAAgC;IAElE,OAAO,CAAC,QAAQ,CAAC,aAAa,CACwB;IACtD,OAAO,CAAC,QAAQ,CAAC,UAAU,CACgC;IAE3D,SAAS,CAAC,QAAQ,CAAC,QAAQ,8EAGxB;;IAsBH,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAI3D,SAAS,CAAC,IAAI,IAAI,IAAI;IAKtB,SAAS,CAAC,IAAI,IAAI,IAAI;yCA3CX,2BAA2B;2CAA3B,2BAA2B;CAgDvC"}
@@ -1,40 +1,43 @@
1
- import { Component, inject, computed, ChangeDetectionStrategy, } from '@angular/core';
1
+ import { Component, inject, computed, effect, viewChild, viewChildren, ChangeDetectionStrategy, } from '@angular/core';
2
2
  import { PrismIconComponent } from '../icons/prism-icon.component.js';
3
3
  import { PrismNavigationService } from '../services/prism-navigation.service.js';
4
4
  import { PrismRendererService } from '../services/prism-renderer.service.js';
5
5
  import * as i0 from "@angular/core";
6
+ const _c0 = ["tabsContainer"];
7
+ const _c1 = ["tabButton"];
6
8
  const _forTrack0 = ($index, $item) => $item.name;
7
- function PrismVariantRibbonComponent_Conditional_0_For_2_Template(rf, ctx) { if (rf & 1) {
9
+ function PrismVariantRibbonComponent_Conditional_0_For_4_Template(rf, ctx) { if (rf & 1) {
8
10
  const _r2 = i0.ɵɵgetCurrentView();
9
- i0.ɵɵelementStart(0, "button", 7);
10
- i0.ɵɵlistener("click", function PrismVariantRibbonComponent_Conditional_0_For_2_Template_button_click_0_listener() { const ɵ$index_4_r3 = i0.ɵɵrestoreView(_r2).$index; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.rendererService.selectVariant(ɵ$index_4_r3)); });
11
- i0.ɵɵelement(1, "span", 8);
12
- i0.ɵɵtext(2);
11
+ i0.ɵɵelementStart(0, "button", 10, 1);
12
+ i0.ɵɵlistener("click", function PrismVariantRibbonComponent_Conditional_0_For_4_Template_button_click_0_listener() { const ɵ$index_6_r3 = i0.ɵɵrestoreView(_r2).$index; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.rendererService.selectVariant(ɵ$index_6_r3)); });
13
+ i0.ɵɵelement(2, "span", 11);
14
+ i0.ɵɵtext(3);
13
15
  i0.ɵɵelementEnd();
14
16
  } if (rf & 2) {
15
17
  const v_r5 = ctx.$implicit;
16
- const ɵ$index_4_r3 = ctx.$index;
18
+ const ɵ$index_6_r3 = ctx.$index;
17
19
  const ctx_r3 = i0.ɵɵnextContext(2);
18
- i0.ɵɵstyleProp("--vc", ctx_r3.variantColor(v_r5.name, ɵ$index_4_r3));
19
- i0.ɵɵclassProp("v-tab--active", ctx_r3.rendererService.activeVariantIndex() === ɵ$index_4_r3);
20
- i0.ɵɵadvance(2);
20
+ i0.ɵɵstyleProp("--vc", ctx_r3.variantColor(v_r5.name, ɵ$index_6_r3));
21
+ i0.ɵɵclassProp("v-tab--active", ctx_r3.rendererService.activeVariantIndex() === ɵ$index_6_r3);
22
+ i0.ɵɵadvance(3);
21
23
  i0.ɵɵtextInterpolate1(" ", v_r5.name, " ");
22
24
  } }
23
25
  function PrismVariantRibbonComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
24
26
  const _r1 = i0.ɵɵgetCurrentView();
25
- i0.ɵɵelementStart(0, "nav", 0);
26
- i0.ɵɵrepeaterCreate(1, PrismVariantRibbonComponent_Conditional_0_For_2_Template, 3, 5, "button", 1, _forTrack0);
27
- i0.ɵɵelementStart(3, "div", 2)(4, "button", 3);
28
- i0.ɵɵlistener("click", function PrismVariantRibbonComponent_Conditional_0_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.prev()); });
29
- i0.ɵɵelement(5, "prism-icon", 4);
27
+ i0.ɵɵelementStart(0, "nav", 2)(1, "div", 3, 0);
28
+ i0.ɵɵrepeaterCreate(3, PrismVariantRibbonComponent_Conditional_0_For_4_Template, 4, 5, "button", 4, _forTrack0);
29
+ i0.ɵɵelementEnd();
30
+ i0.ɵɵelementStart(5, "div", 5)(6, "button", 6);
31
+ i0.ɵɵlistener("click", function PrismVariantRibbonComponent_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.prev()); });
32
+ i0.ɵɵelement(7, "prism-icon", 7);
30
33
  i0.ɵɵelementEnd();
31
- i0.ɵɵelementStart(6, "button", 5);
32
- i0.ɵɵlistener("click", function PrismVariantRibbonComponent_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.next()); });
33
- i0.ɵɵelement(7, "prism-icon", 6);
34
+ i0.ɵɵelementStart(8, "button", 8);
35
+ i0.ɵɵlistener("click", function PrismVariantRibbonComponent_Conditional_0_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r1); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.next()); });
36
+ i0.ɵɵelement(9, "prism-icon", 9);
34
37
  i0.ɵɵelementEnd()()();
35
38
  } if (rf & 2) {
36
39
  const ctx_r3 = i0.ɵɵnextContext();
37
- i0.ɵɵadvance();
40
+ i0.ɵɵadvance(3);
38
41
  i0.ɵɵrepeater(ctx_r3.variants());
39
42
  i0.ɵɵadvance(3);
40
43
  i0.ɵɵproperty("disabled", ctx_r3.rendererService.activeVariantIndex() === 0);
@@ -61,10 +64,31 @@ function variantColor(name, index) {
61
64
  export class PrismVariantRibbonComponent {
62
65
  navigationService = inject(PrismNavigationService);
63
66
  rendererService = inject(PrismRendererService);
67
+ tabsContainer = viewChild('tabsContainer', ...(ngDevMode ? [{ debugName: "tabsContainer" }] : []));
68
+ tabButtons = viewChildren('tabButton', ...(ngDevMode ? [{ debugName: "tabButtons" }] : []));
64
69
  variants = computed(() => {
65
70
  const comp = this.navigationService.activeComponent();
66
71
  return comp?.meta.showcaseConfig.variants ?? [];
67
72
  }, ...(ngDevMode ? [{ debugName: "variants" }] : []));
73
+ constructor() {
74
+ effect(() => {
75
+ const idx = this.rendererService.activeVariantIndex();
76
+ const container = this.tabsContainer()?.nativeElement;
77
+ const button = this.tabButtons()[idx]?.nativeElement;
78
+ if (!container || !button)
79
+ return;
80
+ const buttonLeft = button.offsetLeft;
81
+ const buttonRight = buttonLeft + button.offsetWidth;
82
+ const viewLeft = container.scrollLeft;
83
+ const viewRight = viewLeft + container.clientWidth;
84
+ if (buttonLeft < viewLeft) {
85
+ container.scrollLeft = buttonLeft;
86
+ }
87
+ else if (buttonRight > viewRight) {
88
+ container.scrollLeft = buttonRight - container.clientWidth;
89
+ }
90
+ });
91
+ }
68
92
  variantColor(name, index) {
69
93
  return variantColor(name, index);
70
94
  }
@@ -79,28 +103,35 @@ export class PrismVariantRibbonComponent {
79
103
  this.rendererService.selectVariant(idx + 1);
80
104
  }
81
105
  static ɵfac = function PrismVariantRibbonComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PrismVariantRibbonComponent)(); };
82
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PrismVariantRibbonComponent, selectors: [["prism-variant-ribbon"]], decls: 1, vars: 1, consts: [[1, "variant-ribbon"], [1, "v-tab", 3, "v-tab--active", "--vc"], [1, "variant-ribbon-right"], ["title", "Previous variant", "aria-label", "Previous variant", 1, "tool-btn", 3, "click", "disabled"], ["name", "chevron-right", 2, "transform", "rotate(180deg)", 3, "size"], ["title", "Next variant", "aria-label", "Next variant", 1, "tool-btn", 3, "click", "disabled"], ["name", "chevron-right", 3, "size"], [1, "v-tab", 3, "click"], [1, "v-dot"]], template: function PrismVariantRibbonComponent_Template(rf, ctx) { if (rf & 1) {
83
- i0.ɵɵconditionalCreate(0, PrismVariantRibbonComponent_Conditional_0_Template, 8, 4, "nav", 0);
106
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PrismVariantRibbonComponent, selectors: [["prism-variant-ribbon"]], viewQuery: function PrismVariantRibbonComponent_Query(rf, ctx) { if (rf & 1) {
107
+ i0.ɵɵviewQuerySignal(ctx.tabsContainer, _c0, 5)(ctx.tabButtons, _c1, 5);
108
+ } if (rf & 2) {
109
+ i0.ɵɵqueryAdvance(2);
110
+ } }, decls: 1, vars: 1, consts: [["tabsContainer", ""], ["tabButton", ""], [1, "variant-ribbon"], [1, "variant-ribbon-tabs"], [1, "v-tab", 3, "v-tab--active", "--vc"], [1, "variant-ribbon-right"], ["title", "Previous variant", "aria-label", "Previous variant", 1, "tool-btn", 3, "click", "disabled"], ["name", "chevron-right", 2, "transform", "rotate(180deg)", 3, "size"], ["title", "Next variant", "aria-label", "Next variant", 1, "tool-btn", 3, "click", "disabled"], ["name", "chevron-right", 3, "size"], [1, "v-tab", 3, "click"], [1, "v-dot"]], template: function PrismVariantRibbonComponent_Template(rf, ctx) { if (rf & 1) {
111
+ i0.ɵɵconditionalCreate(0, PrismVariantRibbonComponent_Conditional_0_Template, 10, 4, "nav", 2);
84
112
  } if (rf & 2) {
85
113
  i0.ɵɵconditional(ctx.variants().length > 0 ? 0 : -1);
86
- } }, dependencies: [PrismIconComponent], styles: ["[_nghost-%COMP%] { display: block; flex-shrink: 0; }\n\n .variant-ribbon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 0 28px;\n background: var(--prism-bg);\n border-bottom: 1px solid var(--prism-border);\n height: 42px;\n gap: 2px;\n overflow-x: auto;\n scrollbar-width: none;\n }\n .variant-ribbon[_ngcontent-%COMP%]::-webkit-scrollbar { display: none; }\n\n .v-tab[_ngcontent-%COMP%] {\n position: relative;\n height: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 13px;\n font-weight: 500;\n color: var(--prism-text-muted);\n white-space: nowrap;\n transition: color var(--dur-fast);\n background: none;\n border: none;\n cursor: pointer;\n font-family: var(--font-sans);\n }\n .v-tab[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n left: 10px;\n right: 10px;\n bottom: 0;\n height: 2px;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n opacity: 0;\n transition: opacity var(--dur-fast);\n border-radius: 1px 1px 0 0;\n }\n .v-tab[_ngcontent-%COMP%]:hover { color: var(--prism-text-2); }\n .v-tab--active[_ngcontent-%COMP%] { color: var(--prism-text); }\n .v-tab--active[_ngcontent-%COMP%]::after { opacity: 1; }\n\n .v-dot[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 2px;\n background: var(--vc, var(--prism-primary));\n opacity: 0.6;\n }\n .v-tab--active[_ngcontent-%COMP%] .v-dot[_ngcontent-%COMP%] {\n opacity: 1;\n box-shadow: 0 0 6px var(--vc);\n }\n\n .variant-ribbon-right[_ngcontent-%COMP%] {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 8px;\n padding-left: 12px;\n border-left: 1px solid var(--prism-border);\n height: 24px;\n }\n\n .tool-btn[_ngcontent-%COMP%] {\n height: 24px;\n width: 24px;\n display: grid;\n place-items: center;\n border-radius: var(--radius-sm);\n color: var(--prism-text-muted);\n background: none;\n border: none;\n cursor: pointer;\n transition: all var(--dur-fast);\n }\n .tool-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 8%, transparent);\n }\n .tool-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n [_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 2px;\n }"], changeDetection: 0 });
114
+ } }, dependencies: [PrismIconComponent], styles: ["[_nghost-%COMP%] { display: block; flex-shrink: 0; }\n\n .variant-ribbon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 0 28px;\n background: var(--prism-bg);\n border-bottom: 1px solid var(--prism-border);\n height: 42px;\n }\n\n .variant-ribbon-tabs[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n height: 100%;\n overflow-x: auto;\n scrollbar-width: none;\n }\n .variant-ribbon-tabs[_ngcontent-%COMP%]::-webkit-scrollbar { display: none; }\n\n .v-tab[_ngcontent-%COMP%] {\n position: relative;\n height: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 13px;\n font-weight: 500;\n color: var(--prism-text-muted);\n white-space: nowrap;\n transition: color var(--dur-fast);\n background: none;\n border: none;\n cursor: pointer;\n font-family: var(--font-sans);\n }\n .v-tab[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n left: 10px;\n right: 10px;\n bottom: 0;\n height: 2px;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n opacity: 0;\n transition: opacity var(--dur-fast);\n border-radius: 1px 1px 0 0;\n }\n .v-tab[_ngcontent-%COMP%]:hover { color: var(--prism-text-2); }\n .v-tab--active[_ngcontent-%COMP%] { color: var(--prism-text); }\n .v-tab--active[_ngcontent-%COMP%]::after { opacity: 1; }\n\n .v-dot[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 2px;\n background: var(--vc, var(--prism-primary));\n opacity: 0.6;\n }\n .v-tab--active[_ngcontent-%COMP%] .v-dot[_ngcontent-%COMP%] {\n opacity: 1;\n box-shadow: 0 0 6px var(--vc);\n }\n\n .variant-ribbon-right[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n padding-left: 12px;\n margin-left: 12px;\n border-left: 1px solid var(--prism-border);\n height: 24px;\n }\n\n .tool-btn[_ngcontent-%COMP%] {\n height: 24px;\n width: 24px;\n display: grid;\n place-items: center;\n border-radius: var(--radius-sm);\n color: var(--prism-text-muted);\n background: none;\n border: none;\n cursor: pointer;\n transition: all var(--dur-fast);\n }\n .tool-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 8%, transparent);\n }\n .tool-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n [_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 2px;\n }"], changeDetection: 0 });
87
115
  }
88
116
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrismVariantRibbonComponent, [{
89
117
  type: Component,
90
118
  args: [{ selector: 'prism-variant-ribbon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [PrismIconComponent], template: `
91
119
  @if (variants().length > 0) {
92
120
  <nav class="variant-ribbon">
93
- @for (v of variants(); track v.name; let i = $index) {
94
- <button
95
- class="v-tab"
96
- [class.v-tab--active]="rendererService.activeVariantIndex() === i"
97
- [style.--vc]="variantColor(v.name, i)"
98
- (click)="rendererService.selectVariant(i)"
99
- >
100
- <span class="v-dot"></span>
101
- {{ v.name }}
102
- </button>
103
- }
121
+ <div class="variant-ribbon-tabs" #tabsContainer>
122
+ @for (v of variants(); track v.name; let i = $index) {
123
+ <button
124
+ #tabButton
125
+ class="v-tab"
126
+ [class.v-tab--active]="rendererService.activeVariantIndex() === i"
127
+ [style.--vc]="variantColor(v.name, i)"
128
+ (click)="rendererService.selectVariant(i)"
129
+ >
130
+ <span class="v-dot"></span>
131
+ {{ v.name }}
132
+ </button>
133
+ }
134
+ </div>
104
135
  <div class="variant-ribbon-right">
105
136
  <button
106
137
  class="tool-btn"
@@ -129,6 +160,6 @@ export class PrismVariantRibbonComponent {
129
160
  </div>
130
161
  </nav>
131
162
  }
132
- `, styles: ["\n :host { display: block; flex-shrink: 0; }\n\n .variant-ribbon {\n display: flex;\n align-items: center;\n padding: 0 28px;\n background: var(--prism-bg);\n border-bottom: 1px solid var(--prism-border);\n height: 42px;\n gap: 2px;\n overflow-x: auto;\n scrollbar-width: none;\n }\n .variant-ribbon::-webkit-scrollbar { display: none; }\n\n .v-tab {\n position: relative;\n height: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 13px;\n font-weight: 500;\n color: var(--prism-text-muted);\n white-space: nowrap;\n transition: color var(--dur-fast);\n background: none;\n border: none;\n cursor: pointer;\n font-family: var(--font-sans);\n }\n .v-tab::after {\n content: '';\n position: absolute;\n left: 10px;\n right: 10px;\n bottom: 0;\n height: 2px;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n opacity: 0;\n transition: opacity var(--dur-fast);\n border-radius: 1px 1px 0 0;\n }\n .v-tab:hover { color: var(--prism-text-2); }\n .v-tab--active { color: var(--prism-text); }\n .v-tab--active::after { opacity: 1; }\n\n .v-dot {\n width: 6px;\n height: 6px;\n border-radius: 2px;\n background: var(--vc, var(--prism-primary));\n opacity: 0.6;\n }\n .v-tab--active .v-dot {\n opacity: 1;\n box-shadow: 0 0 6px var(--vc);\n }\n\n .variant-ribbon-right {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 8px;\n padding-left: 12px;\n border-left: 1px solid var(--prism-border);\n height: 24px;\n }\n\n .tool-btn {\n height: 24px;\n width: 24px;\n display: grid;\n place-items: center;\n border-radius: var(--radius-sm);\n color: var(--prism-text-muted);\n background: none;\n border: none;\n cursor: pointer;\n transition: all var(--dur-fast);\n }\n .tool-btn:hover:not(:disabled) {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 8%, transparent);\n }\n .tool-btn:disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n :focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 2px;\n }\n "] }]
133
- }], null, null); })();
134
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismVariantRibbonComponent, { className: "PrismVariantRibbonComponent", filePath: "app/variant-ribbon/prism-variant-ribbon.component.ts", lineNumber: 171 }); })();
163
+ `, styles: ["\n :host { display: block; flex-shrink: 0; }\n\n .variant-ribbon {\n display: flex;\n align-items: center;\n padding: 0 28px;\n background: var(--prism-bg);\n border-bottom: 1px solid var(--prism-border);\n height: 42px;\n }\n\n .variant-ribbon-tabs {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n height: 100%;\n overflow-x: auto;\n scrollbar-width: none;\n }\n .variant-ribbon-tabs::-webkit-scrollbar { display: none; }\n\n .v-tab {\n position: relative;\n height: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 14px;\n font-size: 13px;\n font-weight: 500;\n color: var(--prism-text-muted);\n white-space: nowrap;\n transition: color var(--dur-fast);\n background: none;\n border: none;\n cursor: pointer;\n font-family: var(--font-sans);\n }\n .v-tab::after {\n content: '';\n position: absolute;\n left: 10px;\n right: 10px;\n bottom: 0;\n height: 2px;\n background: linear-gradient(90deg, var(--prism-primary-from), var(--prism-primary-to));\n opacity: 0;\n transition: opacity var(--dur-fast);\n border-radius: 1px 1px 0 0;\n }\n .v-tab:hover { color: var(--prism-text-2); }\n .v-tab--active { color: var(--prism-text); }\n .v-tab--active::after { opacity: 1; }\n\n .v-dot {\n width: 6px;\n height: 6px;\n border-radius: 2px;\n background: var(--vc, var(--prism-primary));\n opacity: 0.6;\n }\n .v-tab--active .v-dot {\n opacity: 1;\n box-shadow: 0 0 6px var(--vc);\n }\n\n .variant-ribbon-right {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n padding-left: 12px;\n margin-left: 12px;\n border-left: 1px solid var(--prism-border);\n height: 24px;\n }\n\n .tool-btn {\n height: 24px;\n width: 24px;\n display: grid;\n place-items: center;\n border-radius: var(--radius-sm);\n color: var(--prism-text-muted);\n background: none;\n border: none;\n cursor: pointer;\n transition: all var(--dur-fast);\n }\n .tool-btn:hover:not(:disabled) {\n color: var(--prism-text);\n background: color-mix(in srgb, var(--prism-primary) 8%, transparent);\n }\n .tool-btn:disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n :focus-visible {\n outline: 2px solid var(--prism-primary);\n outline-offset: 2px;\n }\n "] }]
164
+ }], () => [], { tabsContainer: [{ type: i0.ViewChild, args: ['tabsContainer', { isSignal: true }] }], tabButtons: [{ type: i0.ViewChildren, args: ['tabButton', { isSignal: true }] }] }); })();
165
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PrismVariantRibbonComponent, { className: "PrismVariantRibbonComponent", filePath: "app/variant-ribbon/prism-variant-ribbon.component.ts", lineNumber: 187 }); })();
@@ -1,3 +1,3 @@
1
- export type { ShowcaseConfig, Variant, ComponentStatus } from './showcase.types.js';
1
+ export type { ShowcaseConfig, Variant, ComponentStatus, InputsOf } from './showcase.types.js';
2
2
  export { Showcase } from './showcase.decorator.js';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorator/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorator/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import type { ShowcaseConfig } from './showcase.types.js';
2
- export declare function Showcase(_config: ShowcaseConfig): ClassDecorator;
2
+ export declare function Showcase<T = unknown>(_config: ShowcaseConfig<T>): ClassDecorator;
3
3
  //# sourceMappingURL=showcase.decorator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"showcase.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,wBAAgB,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAEhE"}
1
+ {"version":3,"file":"showcase.decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,wBAAgB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,CAEhF"}
@@ -1,4 +1,4 @@
1
- import type { Provider } from '@angular/core';
1
+ import type { InputSignalWithTransform, Provider } from '@angular/core';
2
2
  import type { CanvasBg } from '../shared/canvas-bg.type.js';
3
3
  export type ComponentStatus = 'stable' | 'beta' | 'wip' | 'deprecated';
4
4
  export interface DirectiveHost {
@@ -9,7 +9,20 @@ export interface DirectiveHost {
9
9
  };
10
10
  inputs?: Record<string, unknown>;
11
11
  }
12
- export interface ShowcaseConfig {
12
+ type UnwrapSignalInput<S> = S extends InputSignalWithTransform<any, infer WriteT> ? WriteT : never;
13
+ /**
14
+ * Maps a component class `T` to a record of its signal-input properties
15
+ * (`input()`, `input.required()`, `model()`), unwrapping each to its value type.
16
+ * `output()` and other properties are excluded.
17
+ *
18
+ * When `T` is `unknown` (the default — no generic argument given), falls back
19
+ * to `Record<string, unknown>` so existing call sites without a generic param
20
+ * keep working.
21
+ */
22
+ export type InputsOf<T> = [unknown] extends [T] ? Record<string, unknown> : {
23
+ [K in keyof T as T[K] extends InputSignalWithTransform<any, any> ? K : never]: UnwrapSignalInput<T[K]>;
24
+ };
25
+ export interface ShowcaseConfig<T = unknown> {
13
26
  /** Display name in the ng-prism UI */
14
27
  title: string;
15
28
  /** Description text — Markdown supported */
@@ -21,7 +34,7 @@ export interface ShowcaseConfig {
21
34
  /** Controls the order of this component within its category (lower = higher). Components without this sort alphabetically after ordered ones. */
22
35
  componentOrder?: number;
23
36
  /** Predefined variants shown as tabs */
24
- variants?: Variant[];
37
+ variants?: Variant<T>[];
25
38
  /** Tags for search and filtering */
26
39
  tags?: string[];
27
40
  /**
@@ -51,11 +64,11 @@ export interface ShowcaseConfig {
51
64
  */
52
65
  status?: ComponentStatus;
53
66
  }
54
- export interface Variant {
67
+ export interface Variant<T = unknown> {
55
68
  /** Tab label */
56
69
  name: string;
57
- /** @Input() values for this variant */
58
- inputs?: Record<string, unknown>;
70
+ /** Signal input values for this variant. Pass a component type to `@Showcase<MyComponent>` to get autocomplete and type-checking here. */
71
+ inputs?: Partial<InputsOf<T>>;
59
72
  /**
60
73
  * Content projected into <ng-content>.
61
74
  * - string → projected into the default (unnamed) slot
@@ -69,4 +82,5 @@ export interface Variant {
69
82
  /** Recommended canvas background for this variant. Overrides `ShowcaseConfig.bg`. */
70
83
  bg?: CanvasBg;
71
84
  }
85
+ export {};
72
86
  //# sourceMappingURL=showcase.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"showcase.types.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2IAA2I;IAC3I,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iJAAiJ;IACjJ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;;;OAKG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,6HAA6H;IAC7H,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,mPAAmP;IACnP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO;IACtB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,qFAAqF;IACrF,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf"}
1
+ {"version":3,"file":"showcase.types.d.ts","sourceRoot":"","sources":["../../src/decorator/showcase.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAOD,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,wBAAwB,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC,GAC7E,MAAM,GACN,KAAK,CAAC;AAEV;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAC3C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB;KACG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,GAC5D,CAAC,GACD,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACpC,CAAC;AAEN,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2IAA2I;IAC3I,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iJAAiJ;IACjJ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACxB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;;;OAKG;IACH,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,6HAA6H;IAC7H,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,mPAAmP;IACnP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,0IAA0I;IAC1I,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,qFAAqF;IACrF,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-prism/core",
3
- "version": "21.11.0",
3
+ "version": "21.12.0-beta.0",
4
4
  "description": "ng-prism — the Angular-native Storybook alternative. Lightweight component showcase with @Showcase decorator, no story files needed.",
5
5
  "keywords": [
6
6
  "ng-prism",