@ng-prism/plugin-perf 21.0.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 (43) hide show
  1. package/dist/bundle/bundle-scanner.d.ts +3 -0
  2. package/dist/bundle/bundle-scanner.d.ts.map +1 -0
  3. package/dist/bundle/bundle-scanner.js +85 -0
  4. package/dist/bundle/bundle-section.component.d.ts +23 -0
  5. package/dist/bundle/bundle-section.component.d.ts.map +1 -0
  6. package/dist/bundle/bundle-section.component.js +321 -0
  7. package/dist/index.browser.d.ts +5 -0
  8. package/dist/index.browser.d.ts.map +1 -0
  9. package/dist/index.browser.js +3 -0
  10. package/dist/index.d.ts +5 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +3 -0
  13. package/dist/memory/memory-section.component.d.ts +14 -0
  14. package/dist/memory/memory-section.component.d.ts.map +1 -0
  15. package/dist/memory/memory-section.component.js +323 -0
  16. package/dist/memory/perf-memory.service.d.ts +26 -0
  17. package/dist/memory/perf-memory.service.d.ts.map +1 -0
  18. package/dist/memory/perf-memory.service.js +62 -0
  19. package/dist/perf-config.token.d.ts +4 -0
  20. package/dist/perf-config.token.d.ts.map +1 -0
  21. package/dist/perf-config.token.js +2 -0
  22. package/dist/perf-panel.component.d.ts +18 -0
  23. package/dist/perf-panel.component.d.ts.map +1 -0
  24. package/dist/perf-panel.component.js +247 -0
  25. package/dist/perf-plugin.browser.d.ts +4 -0
  26. package/dist/perf-plugin.browser.d.ts.map +1 -0
  27. package/dist/perf-plugin.browser.js +14 -0
  28. package/dist/perf-plugin.d.ts +4 -0
  29. package/dist/perf-plugin.d.ts.map +1 -0
  30. package/dist/perf-plugin.js +27 -0
  31. package/dist/perf.types.d.ts +31 -0
  32. package/dist/perf.types.d.ts.map +1 -0
  33. package/dist/perf.types.js +8 -0
  34. package/dist/render/perf-render.service.d.ts +19 -0
  35. package/dist/render/perf-render.service.d.ts.map +1 -0
  36. package/dist/render/perf-render.service.js +73 -0
  37. package/dist/render/render-section.component.d.ts +13 -0
  38. package/dist/render/render-section.component.d.ts.map +1 -0
  39. package/dist/render/render-section.component.js +205 -0
  40. package/dist/render/sparkline.component.d.ts +23 -0
  41. package/dist/render/sparkline.component.d.ts.map +1 -0
  42. package/dist/render/sparkline.component.js +165 -0
  43. package/package.json +49 -0
@@ -0,0 +1,205 @@
1
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
2
+ import { SparklineComponent } from './sparkline.component.js';
3
+ import * as i0 from "@angular/core";
4
+ function RenderSectionComponent_Conditional_0_Conditional_0_Conditional_39_Template(rf, ctx) { if (rf & 1) {
5
+ i0.ɵɵelementStart(0, "div", 10)(1, "div", 11)(2, "span", 3);
6
+ i0.ɵɵtext(3);
7
+ i0.ɵɵelementEnd();
8
+ i0.ɵɵelementStart(4, "div", 12);
9
+ i0.ɵɵtext(5, " avg ");
10
+ i0.ɵɵelementStart(6, "span");
11
+ i0.ɵɵtext(7);
12
+ i0.ɵɵelementEnd();
13
+ i0.ɵɵtext(8, " \u00B7 max ");
14
+ i0.ɵɵelementStart(9, "span");
15
+ i0.ɵɵtext(10);
16
+ i0.ɵɵelementEnd()()();
17
+ i0.ɵɵelement(11, "perf-sparkline", 13);
18
+ i0.ɵɵelementEnd();
19
+ } if (rf & 2) {
20
+ const svc_r1 = i0.ɵɵnextContext(2);
21
+ const ctx_r1 = i0.ɵɵnextContext();
22
+ i0.ɵɵadvance(3);
23
+ i0.ɵɵtextInterpolate1("Render Time Trace \u2014 last ", svc_r1.sampleCount(), " samples");
24
+ i0.ɵɵadvance(4);
25
+ i0.ɵɵtextInterpolate1("", ctx_r1.formatMs(svc_r1.avgRerender()), " ms");
26
+ i0.ɵɵadvance(2);
27
+ i0.ɵɵstyleProp("color", ctx_r1.colorFor(svc_r1.maxRerender()));
28
+ i0.ɵɵadvance();
29
+ i0.ɵɵtextInterpolate1("", ctx_r1.formatMs(svc_r1.maxRerender()), " ms");
30
+ i0.ɵɵadvance();
31
+ i0.ɵɵproperty("samples", svc_r1.rerenders())("thresholdWarn", ctx_r1.warnMs());
32
+ } }
33
+ function RenderSectionComponent_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
34
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3);
35
+ i0.ɵɵtext(3, "Initial Render");
36
+ i0.ɵɵelementEnd();
37
+ i0.ɵɵelementStart(4, "div", 4);
38
+ i0.ɵɵtext(5);
39
+ i0.ɵɵelementStart(6, "span", 5);
40
+ i0.ɵɵtext(7, "ms");
41
+ i0.ɵɵelementEnd()()();
42
+ i0.ɵɵelementStart(8, "div", 6)(9, "div", 7)(10, "span", 3);
43
+ i0.ɵɵtext(11, "Avg Re-render");
44
+ i0.ɵɵelementEnd();
45
+ i0.ɵɵelementStart(12, "span", 8);
46
+ i0.ɵɵtext(13);
47
+ i0.ɵɵelementStart(14, "span", 5);
48
+ i0.ɵɵtext(15, " ms");
49
+ i0.ɵɵelementEnd()();
50
+ i0.ɵɵelementStart(16, "span", 9);
51
+ i0.ɵɵtext(17);
52
+ i0.ɵɵelementEnd()();
53
+ i0.ɵɵelementStart(18, "div", 7)(19, "span", 3);
54
+ i0.ɵɵtext(20, "Slowest");
55
+ i0.ɵɵelementEnd();
56
+ i0.ɵɵelementStart(21, "span", 8);
57
+ i0.ɵɵtext(22);
58
+ i0.ɵɵelementStart(23, "span", 5);
59
+ i0.ɵɵtext(24, " ms");
60
+ i0.ɵɵelementEnd()()();
61
+ i0.ɵɵelementStart(25, "div", 7)(26, "span", 3);
62
+ i0.ɵɵtext(27, "p95");
63
+ i0.ɵɵelementEnd();
64
+ i0.ɵɵelementStart(28, "span", 8);
65
+ i0.ɵɵtext(29);
66
+ i0.ɵɵelementStart(30, "span", 5);
67
+ i0.ɵɵtext(31, " ms");
68
+ i0.ɵɵelementEnd()()();
69
+ i0.ɵɵelementStart(32, "div", 7)(33, "span", 3);
70
+ i0.ɵɵtext(34, "Last Render");
71
+ i0.ɵɵelementEnd();
72
+ i0.ɵɵelementStart(35, "span", 8);
73
+ i0.ɵɵtext(36);
74
+ i0.ɵɵelementStart(37, "span", 5);
75
+ i0.ɵɵtext(38, " ms");
76
+ i0.ɵɵelementEnd()()()()();
77
+ i0.ɵɵconditionalCreate(39, RenderSectionComponent_Conditional_0_Conditional_0_Conditional_39_Template, 12, 7, "div", 10);
78
+ } if (rf & 2) {
79
+ const svc_r1 = i0.ɵɵnextContext();
80
+ const ctx_r1 = i0.ɵɵnextContext();
81
+ i0.ɵɵadvance(4);
82
+ i0.ɵɵclassMap(ctx_r1.initialClass());
83
+ i0.ɵɵadvance();
84
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.formatMs(svc_r1.initialRender()));
85
+ i0.ɵɵadvance(8);
86
+ i0.ɵɵtextInterpolate(ctx_r1.formatMs(svc_r1.avgRerender()));
87
+ i0.ɵɵadvance(4);
88
+ i0.ɵɵtextInterpolate1("", svc_r1.sampleCount(), " samples");
89
+ i0.ɵɵadvance(4);
90
+ i0.ɵɵstyleProp("color", ctx_r1.colorFor(svc_r1.maxRerender()));
91
+ i0.ɵɵadvance();
92
+ i0.ɵɵtextInterpolate(ctx_r1.formatMs(svc_r1.maxRerender()));
93
+ i0.ɵɵadvance(7);
94
+ i0.ɵɵtextInterpolate(ctx_r1.formatMs(svc_r1.p95Rerender()));
95
+ i0.ɵɵadvance(7);
96
+ i0.ɵɵtextInterpolate(ctx_r1.formatMs(svc_r1.lastRerender()));
97
+ i0.ɵɵadvance(3);
98
+ i0.ɵɵconditional(svc_r1.rerenders().length > 1 ? 39 : -1);
99
+ } }
100
+ function RenderSectionComponent_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
101
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 14);
102
+ i0.ɵɵtext(2, "\u23F1");
103
+ i0.ɵɵelementEnd();
104
+ i0.ɵɵelementStart(3, "div", 15);
105
+ i0.ɵɵtext(4, "No profiling data yet");
106
+ i0.ɵɵelementEnd();
107
+ i0.ɵɵelementStart(5, "div", 16);
108
+ i0.ɵɵtext(6, "Click Profile to start recording render times");
109
+ i0.ɵɵelementEnd()();
110
+ } }
111
+ function RenderSectionComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
112
+ i0.ɵɵconditionalCreate(0, RenderSectionComponent_Conditional_0_Conditional_0_Template, 40, 11)(1, RenderSectionComponent_Conditional_0_Conditional_1_Template, 7, 0, "div", 0);
113
+ } if (rf & 2) {
114
+ const svc_r1 = ctx;
115
+ i0.ɵɵconditional(svc_r1.initialRender() !== null || svc_r1.rerenders().length > 0 ? 0 : 1);
116
+ } }
117
+ export class RenderSectionComponent {
118
+ renderService = input.required(...(ngDevMode ? [{ debugName: "renderService" }] : []));
119
+ warnMs = input(5, ...(ngDevMode ? [{ debugName: "warnMs" }] : []));
120
+ critMs = input(16, ...(ngDevMode ? [{ debugName: "critMs" }] : []));
121
+ initialClass = computed(() => {
122
+ const v = this.renderService().initialRender();
123
+ if (v === null)
124
+ return '';
125
+ if (v >= this.critMs())
126
+ return 'crit';
127
+ if (v >= this.warnMs())
128
+ return 'warn';
129
+ return '';
130
+ }, ...(ngDevMode ? [{ debugName: "initialClass" }] : []));
131
+ formatMs(value) {
132
+ if (value === null)
133
+ return '—';
134
+ return value < 10 ? value.toFixed(2) : value.toFixed(1);
135
+ }
136
+ colorFor(value) {
137
+ if (value >= this.critMs())
138
+ return 'var(--perf-crit, #f87171)';
139
+ if (value >= this.warnMs())
140
+ return 'var(--perf-warn, #fbbf24)';
141
+ return 'var(--prism-text, #ede9f8)';
142
+ }
143
+ static ɵfac = function RenderSectionComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RenderSectionComponent)(); };
144
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RenderSectionComponent, selectors: [["perf-render-section"]], inputs: { renderService: [1, "renderService"], warnMs: [1, "warnMs"], critMs: [1, "critMs"] }, decls: 1, vars: 1, consts: [[1, "prism-perf-empty"], [1, "prism-perf-render-hero"], [1, "prism-perf-render-hero-main"], [1, "prism-perf-label"], [1, "prism-perf-render-hero-value"], [1, "prism-perf-unit"], [1, "prism-perf-render-stats-grid"], [1, "prism-perf-render-stat"], [1, "prism-perf-render-stat-value"], [1, "prism-perf-sub"], [1, "prism-perf-sparkline-section"], [1, "prism-perf-sparkline-header"], [1, "prism-perf-sparkline-legend"], [3, "samples", "thresholdWarn"], [1, "prism-perf-empty-icon"], [1, "prism-perf-empty-text"], [1, "prism-perf-empty-hint"]], template: function RenderSectionComponent_Template(rf, ctx) { if (rf & 1) {
145
+ i0.ɵɵconditionalCreate(0, RenderSectionComponent_Conditional_0_Template, 2, 1);
146
+ } if (rf & 2) {
147
+ let tmp_0_0;
148
+ i0.ɵɵconditional((tmp_0_0 = ctx.renderService()) ? 0 : -1, tmp_0_0);
149
+ } }, dependencies: [SparklineComponent], styles: [".prism-perf-render-hero[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n border-bottom: 1px solid var(--prism-border, rgba(255,255,255,0.08));\n }\n .prism-perf-render-hero-main[_ngcontent-%COMP%] {\n padding: 16px 20px;\n border-right: 1px solid var(--prism-border, rgba(255,255,255,0.08));\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n .prism-perf-render-hero-value[_ngcontent-%COMP%] {\n font-size: 34px;\n font-family: var(--prism-font-mono, monospace);\n font-weight: 600;\n color: var(--perf-ok, #4ade80);\n line-height: 1;\n letter-spacing: -0.02em;\n }\n .prism-perf-render-hero-value.warn[_ngcontent-%COMP%] { color: var(--perf-warn, #fbbf24); }\n .prism-perf-render-hero-value.crit[_ngcontent-%COMP%] { color: var(--perf-crit, #f87171); }\n .prism-perf-render-stats-grid[_ngcontent-%COMP%] {\n padding: 12px 16px;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 14px 20px;\n }\n .prism-perf-render-stat[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n .prism-perf-render-stat-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-family: var(--prism-font-mono, monospace);\n font-weight: 600;\n color: var(--prism-text, #ede9f8);\n line-height: 1.1;\n }\n .prism-perf-sparkline-section[_ngcontent-%COMP%] {\n padding: 12px 16px 14px;\n border-top: 1px solid var(--prism-border, rgba(255,255,255,0.08));\n }\n .prism-perf-sparkline-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 10px;\n }\n .prism-perf-sparkline-legend[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 10px;\n font-family: var(--prism-font-mono, monospace);\n color: var(--prism-text-ghost, #6a5d87);\n }\n .prism-perf-sparkline-legend[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n color: var(--prism-primary, #a78bfa);\n }\n .prism-perf-label[_ngcontent-%COMP%] {\n font-size: 9px;\n font-weight: 600;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--prism-text-ghost, #6a5d87);\n }\n .prism-perf-unit[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 400;\n color: var(--prism-text-muted, #8476a2);\n margin-left: 4px;\n }\n .prism-perf-sub[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--prism-text-ghost, #6a5d87);\n font-family: var(--prism-font-mono, monospace);\n }\n .prism-perf-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n height: 100%;\n min-height: 180px;\n }\n .prism-perf-empty-icon[_ngcontent-%COMP%] { font-size: 28px; opacity: 0.2; }\n .prism-perf-empty-text[_ngcontent-%COMP%] { font-size: 12px; color: var(--prism-text-ghost, #6a5d87); }\n .prism-perf-empty-hint[_ngcontent-%COMP%] { font-size: 11px; color: var(--prism-text-ghost, #6a5d87); opacity: 0.6; }"], changeDetection: 0 });
150
+ }
151
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RenderSectionComponent, [{
152
+ type: Component,
153
+ args: [{ selector: 'perf-render-section', standalone: true, imports: [SparklineComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
154
+ @if (renderService(); as svc) {
155
+ @if (svc.initialRender() !== null || svc.rerenders().length > 0) {
156
+ <div class="prism-perf-render-hero">
157
+ <div class="prism-perf-render-hero-main">
158
+ <div class="prism-perf-label">Initial Render</div>
159
+ <div class="prism-perf-render-hero-value" [class]="initialClass()">
160
+ {{ formatMs(svc.initialRender()) }}<span class="prism-perf-unit">ms</span>
161
+ </div>
162
+ </div>
163
+ <div class="prism-perf-render-stats-grid">
164
+ <div class="prism-perf-render-stat">
165
+ <span class="prism-perf-label">Avg Re-render</span>
166
+ <span class="prism-perf-render-stat-value">{{ formatMs(svc.avgRerender()) }}<span class="prism-perf-unit"> ms</span></span>
167
+ <span class="prism-perf-sub">{{ svc.sampleCount() }} samples</span>
168
+ </div>
169
+ <div class="prism-perf-render-stat">
170
+ <span class="prism-perf-label">Slowest</span>
171
+ <span class="prism-perf-render-stat-value" [style.color]="colorFor(svc.maxRerender())">{{ formatMs(svc.maxRerender()) }}<span class="prism-perf-unit"> ms</span></span>
172
+ </div>
173
+ <div class="prism-perf-render-stat">
174
+ <span class="prism-perf-label">p95</span>
175
+ <span class="prism-perf-render-stat-value">{{ formatMs(svc.p95Rerender()) }}<span class="prism-perf-unit"> ms</span></span>
176
+ </div>
177
+ <div class="prism-perf-render-stat">
178
+ <span class="prism-perf-label">Last Render</span>
179
+ <span class="prism-perf-render-stat-value">{{ formatMs(svc.lastRerender()) }}<span class="prism-perf-unit"> ms</span></span>
180
+ </div>
181
+ </div>
182
+ </div>
183
+
184
+ @if (svc.rerenders().length > 1) {
185
+ <div class="prism-perf-sparkline-section">
186
+ <div class="prism-perf-sparkline-header">
187
+ <span class="prism-perf-label">Render Time Trace — last {{ svc.sampleCount() }} samples</span>
188
+ <div class="prism-perf-sparkline-legend">
189
+ avg <span>{{ formatMs(svc.avgRerender()) }} ms</span> · max <span [style.color]="colorFor(svc.maxRerender())">{{ formatMs(svc.maxRerender()) }} ms</span>
190
+ </div>
191
+ </div>
192
+ <perf-sparkline [samples]="svc.rerenders()" [thresholdWarn]="warnMs()" />
193
+ </div>
194
+ }
195
+ } @else {
196
+ <div class="prism-perf-empty">
197
+ <div class="prism-perf-empty-icon">&#9201;</div>
198
+ <div class="prism-perf-empty-text">No profiling data yet</div>
199
+ <div class="prism-perf-empty-hint">Click Profile to start recording render times</div>
200
+ </div>
201
+ }
202
+ }
203
+ `, styles: ["\n .prism-perf-render-hero {\n display: grid;\n grid-template-columns: 1fr 1fr;\n border-bottom: 1px solid var(--prism-border, rgba(255,255,255,0.08));\n }\n .prism-perf-render-hero-main {\n padding: 16px 20px;\n border-right: 1px solid var(--prism-border, rgba(255,255,255,0.08));\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n .prism-perf-render-hero-value {\n font-size: 34px;\n font-family: var(--prism-font-mono, monospace);\n font-weight: 600;\n color: var(--perf-ok, #4ade80);\n line-height: 1;\n letter-spacing: -0.02em;\n }\n .prism-perf-render-hero-value.warn { color: var(--perf-warn, #fbbf24); }\n .prism-perf-render-hero-value.crit { color: var(--perf-crit, #f87171); }\n .prism-perf-render-stats-grid {\n padding: 12px 16px;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 14px 20px;\n }\n .prism-perf-render-stat {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n .prism-perf-render-stat-value {\n font-size: 16px;\n font-family: var(--prism-font-mono, monospace);\n font-weight: 600;\n color: var(--prism-text, #ede9f8);\n line-height: 1.1;\n }\n .prism-perf-sparkline-section {\n padding: 12px 16px 14px;\n border-top: 1px solid var(--prism-border, rgba(255,255,255,0.08));\n }\n .prism-perf-sparkline-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 10px;\n }\n .prism-perf-sparkline-legend {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 10px;\n font-family: var(--prism-font-mono, monospace);\n color: var(--prism-text-ghost, #6a5d87);\n }\n .prism-perf-sparkline-legend span {\n color: var(--prism-primary, #a78bfa);\n }\n .prism-perf-label {\n font-size: 9px;\n font-weight: 600;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--prism-text-ghost, #6a5d87);\n }\n .prism-perf-unit {\n font-size: 12px;\n font-weight: 400;\n color: var(--prism-text-muted, #8476a2);\n margin-left: 4px;\n }\n .prism-perf-sub {\n font-size: 10px;\n color: var(--prism-text-ghost, #6a5d87);\n font-family: var(--prism-font-mono, monospace);\n }\n .prism-perf-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n height: 100%;\n min-height: 180px;\n }\n .prism-perf-empty-icon { font-size: 28px; opacity: 0.2; }\n .prism-perf-empty-text { font-size: 12px; color: var(--prism-text-ghost, #6a5d87); }\n .prism-perf-empty-hint { font-size: 11px; color: var(--prism-text-ghost, #6a5d87); opacity: 0.6; }\n "] }]
204
+ }], null, { renderService: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderService", required: true }] }], warnMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "warnMs", required: false }] }], critMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "critMs", required: false }] }] }); })();
205
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RenderSectionComponent, { className: "RenderSectionComponent", filePath: "render/render-section.component.ts", lineNumber: 155 }); })();
@@ -0,0 +1,23 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class SparklineComponent {
3
+ readonly samples: import("@angular/core").InputSignal<number[]>;
4
+ readonly thresholdWarn: import("@angular/core").InputSignal<number>;
5
+ readonly height: import("@angular/core").InputSignal<number>;
6
+ private readonly points;
7
+ readonly linePath: import("@angular/core").Signal<string>;
8
+ readonly areaPath: import("@angular/core").Signal<string>;
9
+ readonly warnY: import("@angular/core").Signal<number | null>;
10
+ readonly peakPoint: import("@angular/core").Signal<{
11
+ x: number;
12
+ y: number;
13
+ value: number;
14
+ } | null>;
15
+ readonly currentPoint: import("@angular/core").Signal<{
16
+ x: number;
17
+ y: number;
18
+ value: number;
19
+ } | null>;
20
+ static ɵfac: i0.ɵɵFactoryDeclaration<SparklineComponent, never>;
21
+ static ɵcmp: i0.ɵɵComponentDeclaration<SparklineComponent, "perf-sparkline", never, { "samples": { "alias": "samples"; "required": false; "isSignal": true; }; "thresholdWarn": { "alias": "thresholdWarn"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
22
+ }
23
+ //# sourceMappingURL=sparkline.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sparkline.component.d.ts","sourceRoot":"","sources":["../../src/render/sparkline.component.ts"],"names":[],"mappings":";AAEA,qBAoDa,kBAAkB;IAC7B,QAAQ,CAAC,OAAO,gDAAuB;IACvC,QAAQ,CAAC,aAAa,8CAAY;IAClC,QAAQ,CAAC,MAAM,8CAAa;IAE5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAapB;IAEH,QAAQ,CAAC,QAAQ,yCAId;IAEH,QAAQ,CAAC,QAAQ,yCAMd;IAEH,QAAQ,CAAC,KAAK,gDAMX;IAEH,QAAQ,CAAC,SAAS;;;;cAQf;IAEH,QAAQ,CAAC,YAAY;;;;cAGlB;yCAvDQ,kBAAkB;2CAAlB,kBAAkB;CAwD9B"}
@@ -0,0 +1,165 @@
1
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ function SparklineComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
4
+ i0.ɵɵnamespaceSVG();
5
+ i0.ɵɵdomElement(0, "line", 12);
6
+ i0.ɵɵdomElementStart(1, "text", 13);
7
+ i0.ɵɵtext(2);
8
+ i0.ɵɵdomElementEnd();
9
+ } if (rf & 2) {
10
+ const ctx_r0 = i0.ɵɵnextContext();
11
+ i0.ɵɵattribute("x1", 0)("y1", ctx_r0.warnY())("x2", 600)("y2", ctx_r0.warnY());
12
+ i0.ɵɵadvance();
13
+ i0.ɵɵattribute("x", 3)("y", ctx_r0.warnY() - 3);
14
+ i0.ɵɵadvance();
15
+ i0.ɵɵtextInterpolate1("", ctx_r0.thresholdWarn(), "ms");
16
+ } }
17
+ function SparklineComponent_Conditional_14_Template(rf, ctx) { if (rf & 1) {
18
+ i0.ɵɵnamespaceSVG();
19
+ i0.ɵɵdomElement(0, "circle", 11);
20
+ } if (rf & 2) {
21
+ const peak_r2 = ctx;
22
+ i0.ɵɵattribute("cx", peak_r2.x)("cy", peak_r2.y);
23
+ } }
24
+ function SparklineComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
25
+ i0.ɵɵnamespaceSVG();
26
+ i0.ɵɵdomElement(0, "circle", 14);
27
+ i0.ɵɵdomElementStart(1, "circle", 15);
28
+ i0.ɵɵdomElement(2, "animate", 16)(3, "animate", 17);
29
+ i0.ɵɵdomElementEnd();
30
+ } if (rf & 2) {
31
+ const current_r3 = ctx;
32
+ i0.ɵɵattribute("cx", current_r3.x)("cy", current_r3.y);
33
+ i0.ɵɵadvance();
34
+ i0.ɵɵattribute("cx", current_r3.x)("cy", current_r3.y);
35
+ } }
36
+ export class SparklineComponent {
37
+ samples = input([], ...(ngDevMode ? [{ debugName: "samples" }] : []));
38
+ thresholdWarn = input(5, ...(ngDevMode ? [{ debugName: "thresholdWarn" }] : []));
39
+ height = input(52, ...(ngDevMode ? [{ debugName: "height" }] : []));
40
+ points = computed(() => {
41
+ const data = this.samples();
42
+ const h = this.height();
43
+ if (data.length === 0)
44
+ return [];
45
+ const max = Math.max(...data, this.thresholdWarn() * 1.2);
46
+ const step = data.length > 1 ? 600 / (data.length - 1) : 300;
47
+ return data.map((v, i) => ({
48
+ x: i * step,
49
+ y: h - 4 - ((v / max) * (h - 8)),
50
+ value: v,
51
+ }));
52
+ }, ...(ngDevMode ? [{ debugName: "points" }] : []));
53
+ linePath = computed(() => {
54
+ const pts = this.points();
55
+ if (pts.length === 0)
56
+ return '';
57
+ return 'M' + pts.map((p) => `${p.x},${p.y}`).join(' L');
58
+ }, ...(ngDevMode ? [{ debugName: "linePath" }] : []));
59
+ areaPath = computed(() => {
60
+ const pts = this.points();
61
+ const h = this.height();
62
+ if (pts.length === 0)
63
+ return '';
64
+ const line = pts.map((p) => `${p.x},${p.y}`).join(' L');
65
+ return `M${pts[0].x},${h} L${line} L${pts[pts.length - 1].x},${h} Z`;
66
+ }, ...(ngDevMode ? [{ debugName: "areaPath" }] : []));
67
+ warnY = computed(() => {
68
+ const data = this.samples();
69
+ const h = this.height();
70
+ if (data.length === 0)
71
+ return null;
72
+ const max = Math.max(...data, this.thresholdWarn() * 1.2);
73
+ return h - 4 - ((this.thresholdWarn() / max) * (h - 8));
74
+ }, ...(ngDevMode ? [{ debugName: "warnY" }] : []));
75
+ peakPoint = computed(() => {
76
+ const pts = this.points();
77
+ if (pts.length < 2)
78
+ return null;
79
+ let peak = pts[0];
80
+ for (const p of pts) {
81
+ if (p.value > peak.value)
82
+ peak = p;
83
+ }
84
+ return peak.value > this.thresholdWarn() ? peak : null;
85
+ }, ...(ngDevMode ? [{ debugName: "peakPoint" }] : []));
86
+ currentPoint = computed(() => {
87
+ const pts = this.points();
88
+ return pts.length > 0 ? pts[pts.length - 1] : null;
89
+ }, ...(ngDevMode ? [{ debugName: "currentPoint" }] : []));
90
+ static ɵfac = function SparklineComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SparklineComponent)(); };
91
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SparklineComponent, selectors: [["perf-sparkline"]], inputs: { samples: [1, "samples"], thresholdWarn: [1, "thresholdWarn"], height: [1, "height"] }, decls: 16, vars: 6, consts: [[1, "prism-perf-sparkline-wrap"], ["preserveAspectRatio", "none", "xmlns", "http://www.w3.org/2000/svg", 1, "prism-perf-sparkline-svg"], ["id", "perf-sparkg", "x1", "0", "y1", "0", "x2", "0", "y2", "1"], ["offset", "0%", "stop-color", "#a78bfa", "stop-opacity", "0.35"], ["offset", "100%", "stop-color", "#a78bfa", "stop-opacity", "0.0"], ["id", "perf-glow"], ["stdDeviation", "1.5", "result", "coloredBlur"], ["in", "coloredBlur"], ["in", "SourceGraphic"], ["fill", "url(#perf-sparkg)"], ["fill", "none", "stroke", "#a78bfa", "stroke-width", "1.5", "filter", "url(#perf-glow)"], ["r", "3", "fill", "#fbbf24", "filter", "url(#perf-glow)"], ["stroke", "#fbbf24", "stroke-width", "0.8", "stroke-dasharray", "4 4", "opacity", "0.4"], ["font-size", "8", "fill", "#fbbf24", "opacity", "0.5", "font-family", "monospace"], ["r", "2.5", "fill", "#a78bfa"], ["r", "5", "fill", "none", "stroke", "#a78bfa", "stroke-width", "1", "opacity", "0.4"], ["attributeName", "r", "values", "3;7", "dur", "1.5s", "repeatCount", "indefinite"], ["attributeName", "opacity", "values", "0.4;0", "dur", "1.5s", "repeatCount", "indefinite"]], template: function SparklineComponent_Template(rf, ctx) { if (rf & 1) {
92
+ i0.ɵɵdomElementStart(0, "div", 0);
93
+ i0.ɵɵnamespaceSVG();
94
+ i0.ɵɵdomElementStart(1, "svg", 1)(2, "defs")(3, "linearGradient", 2);
95
+ i0.ɵɵdomElement(4, "stop", 3)(5, "stop", 4);
96
+ i0.ɵɵdomElementEnd();
97
+ i0.ɵɵdomElementStart(6, "filter", 5);
98
+ i0.ɵɵdomElement(7, "feGaussianBlur", 6);
99
+ i0.ɵɵdomElementStart(8, "feMerge");
100
+ i0.ɵɵdomElement(9, "feMergeNode", 7)(10, "feMergeNode", 8);
101
+ i0.ɵɵdomElementEnd()()();
102
+ i0.ɵɵconditionalCreate(11, SparklineComponent_Conditional_11_Template, 3, 7);
103
+ i0.ɵɵdomElement(12, "path", 9)(13, "path", 10);
104
+ i0.ɵɵconditionalCreate(14, SparklineComponent_Conditional_14_Template, 1, 2, ":svg:circle", 11);
105
+ i0.ɵɵconditionalCreate(15, SparklineComponent_Conditional_15_Template, 4, 4);
106
+ i0.ɵɵdomElementEnd()();
107
+ } if (rf & 2) {
108
+ let tmp_4_0;
109
+ let tmp_5_0;
110
+ i0.ɵɵadvance();
111
+ i0.ɵɵattribute("viewBox", "0 0 600 " + ctx.height());
112
+ i0.ɵɵadvance(10);
113
+ i0.ɵɵconditional(ctx.warnY() !== null ? 11 : -1);
114
+ i0.ɵɵadvance();
115
+ i0.ɵɵattribute("d", ctx.areaPath());
116
+ i0.ɵɵadvance();
117
+ i0.ɵɵattribute("d", ctx.linePath());
118
+ i0.ɵɵadvance();
119
+ i0.ɵɵconditional((tmp_4_0 = ctx.peakPoint()) ? 14 : -1, tmp_4_0);
120
+ i0.ɵɵadvance();
121
+ i0.ɵɵconditional((tmp_5_0 = ctx.currentPoint()) ? 15 : -1, tmp_5_0);
122
+ } }, styles: [".prism-perf-sparkline-wrap[_ngcontent-%COMP%] {\n position: relative;\n }\n .prism-perf-sparkline-svg[_ngcontent-%COMP%] {\n width: 100%;\n height: 52px;\n }"], changeDetection: 0 });
123
+ }
124
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SparklineComponent, [{
125
+ type: Component,
126
+ args: [{ selector: 'perf-sparkline', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
127
+ <div class="prism-perf-sparkline-wrap">
128
+ <svg class="prism-perf-sparkline-svg" [attr.viewBox]="'0 0 600 ' + height()" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
129
+ <defs>
130
+ <linearGradient id="perf-sparkg" x1="0" y1="0" x2="0" y2="1">
131
+ <stop offset="0%" stop-color="#a78bfa" stop-opacity="0.35"/>
132
+ <stop offset="100%" stop-color="#a78bfa" stop-opacity="0.0"/>
133
+ </linearGradient>
134
+ <filter id="perf-glow">
135
+ <feGaussianBlur stdDeviation="1.5" result="coloredBlur"/>
136
+ <feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge>
137
+ </filter>
138
+ </defs>
139
+
140
+ @if (warnY() !== null) {
141
+ <line [attr.x1]="0" [attr.y1]="warnY()" [attr.x2]="600" [attr.y2]="warnY()"
142
+ stroke="#fbbf24" stroke-width="0.8" stroke-dasharray="4 4" opacity="0.4"/>
143
+ <text [attr.x]="3" [attr.y]="warnY()! - 3" font-size="8" fill="#fbbf24" opacity="0.5"
144
+ font-family="monospace">{{ thresholdWarn() }}ms</text>
145
+ }
146
+
147
+ <path [attr.d]="areaPath()" fill="url(#perf-sparkg)"/>
148
+ <path [attr.d]="linePath()" fill="none" stroke="#a78bfa" stroke-width="1.5" filter="url(#perf-glow)"/>
149
+
150
+ @if (peakPoint(); as peak) {
151
+ <circle [attr.cx]="peak.x" [attr.cy]="peak.y" r="3" fill="#fbbf24" filter="url(#perf-glow)"/>
152
+ }
153
+
154
+ @if (currentPoint(); as current) {
155
+ <circle [attr.cx]="current.x" [attr.cy]="current.y" r="2.5" fill="#a78bfa"/>
156
+ <circle [attr.cx]="current.x" [attr.cy]="current.y" r="5" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.4">
157
+ <animate attributeName="r" values="3;7" dur="1.5s" repeatCount="indefinite"/>
158
+ <animate attributeName="opacity" values="0.4;0" dur="1.5s" repeatCount="indefinite"/>
159
+ </circle>
160
+ }
161
+ </svg>
162
+ </div>
163
+ `, styles: ["\n .prism-perf-sparkline-wrap {\n position: relative;\n }\n .prism-perf-sparkline-svg {\n width: 100%;\n height: 52px;\n }\n "] }]
164
+ }], null, { samples: [{ type: i0.Input, args: [{ isSignal: true, alias: "samples", required: false }] }], thresholdWarn: [{ type: i0.Input, args: [{ isSignal: true, alias: "thresholdWarn", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] }); })();
165
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SparklineComponent, { className: "SparklineComponent", filePath: "render/sparkline.component.ts", lineNumber: 55 }); })();
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@ng-prism/plugin-perf",
3
+ "version": "21.0.0",
4
+ "description": "Performance profiling panel for ng-prism — bundle size, render time, memory footprint.",
5
+ "keywords": [
6
+ "@ng-prism/core",
7
+ "performance",
8
+ "profiling",
9
+ "plugin",
10
+ "angular",
11
+ "styleguide"
12
+ ],
13
+ "license": "MIT",
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ "./package.json": "./package.json",
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "browser": "./dist/index.browser.js",
23
+ "import": "./dist/index.js",
24
+ "default": "./dist/index.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "!**/*.tsbuildinfo"
30
+ ],
31
+ "peerDependencies": {
32
+ "@angular/core": ">=20.0.0",
33
+ "typescript": ">=5.0.0",
34
+ "@ng-prism/core": ">=21.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@ng-prism/core": "*"
38
+ },
39
+ "dependencies": {
40
+ "tslib": "^2.3.0"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/dyingangel666/ng-prism.git",
45
+ "directory": "packages/plugin-perf"
46
+ },
47
+ "homepage": "https://dyingangel666.github.io/ng-prism/",
48
+ "bugs": "https://github.com/dyingangel666/ng-prism/issues"
49
+ }