@visuno/angular 0.0.0-stage → 0.1.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 (175) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +56 -2
  3. package/account-table/account-table.component.d.ts +72 -0
  4. package/action-log/action-log.component.d.ts +41 -0
  5. package/activity-heatmap/activity-heatmap.component.d.ts +67 -0
  6. package/agent-inbox/agent-inbox.component.d.ts +75 -0
  7. package/agent-lanes/agent-lanes.component.d.ts +152 -0
  8. package/agent-phases/agent-phases.component.d.ts +62 -0
  9. package/agent-run-timeline/agent-run-timeline.component.d.ts +113 -0
  10. package/agent-tree/agent-tree.component.d.ts +80 -0
  11. package/answer-action-bar/answer-action-bar.component.d.ts +110 -0
  12. package/artifact-card/artifact-card.component.d.ts +145 -0
  13. package/attachment-tray/attachment-tray.component.d.ts +84 -0
  14. package/badge/badge.component.d.ts +25 -0
  15. package/bar-chart/bar-chart.component.d.ts +87 -0
  16. package/browser-session/browser-session.component.d.ts +70 -0
  17. package/buttons/buttons.component.d.ts +63 -0
  18. package/card/card.component.d.ts +21 -0
  19. package/change-review/change-review.component.d.ts +97 -0
  20. package/citation-hover-card/citation-hover-card.component.d.ts +95 -0
  21. package/code-viewer/code-viewer.component.d.ts +86 -0
  22. package/composer/composer.component.d.ts +114 -0
  23. package/context-meter/context-meter.component.d.ts +60 -0
  24. package/core/icon.component.d.ts +10 -0
  25. package/core/reduced-motion.service.d.ts +15 -0
  26. package/decision-prompt/decision-prompt.component.d.ts +56 -0
  27. package/design-review/design-review.component.d.ts +108 -0
  28. package/design-tuner/design-tuner.component.d.ts +75 -0
  29. package/details-panel/details-panel.component.d.ts +150 -0
  30. package/donut-chart/donut-chart.component.d.ts +63 -0
  31. package/draft-review/draft-review.component.d.ts +128 -0
  32. package/error-recovery/error-recovery.component.d.ts +59 -0
  33. package/esm2022/account-table/account-table.component.mjs +399 -0
  34. package/esm2022/action-log/action-log.component.mjs +177 -0
  35. package/esm2022/activity-heatmap/activity-heatmap.component.mjs +285 -0
  36. package/esm2022/agent-inbox/agent-inbox.component.mjs +284 -0
  37. package/esm2022/agent-lanes/agent-lanes.component.mjs +600 -0
  38. package/esm2022/agent-phases/agent-phases.component.mjs +300 -0
  39. package/esm2022/agent-run-timeline/agent-run-timeline.component.mjs +412 -0
  40. package/esm2022/agent-tree/agent-tree.component.mjs +393 -0
  41. package/esm2022/answer-action-bar/answer-action-bar.component.mjs +636 -0
  42. package/esm2022/artifact-card/artifact-card.component.mjs +916 -0
  43. package/esm2022/attachment-tray/attachment-tray.component.mjs +402 -0
  44. package/esm2022/badge/badge.component.mjs +97 -0
  45. package/esm2022/bar-chart/bar-chart.component.mjs +300 -0
  46. package/esm2022/browser-session/browser-session.component.mjs +352 -0
  47. package/esm2022/buttons/buttons.component.mjs +215 -0
  48. package/esm2022/card/card.component.mjs +107 -0
  49. package/esm2022/change-review/change-review.component.mjs +398 -0
  50. package/esm2022/citation-hover-card/citation-hover-card.component.mjs +360 -0
  51. package/esm2022/code-viewer/code-viewer.component.mjs +291 -0
  52. package/esm2022/composer/composer.component.mjs +743 -0
  53. package/esm2022/context-meter/context-meter.component.mjs +275 -0
  54. package/esm2022/core/icon.component.mjs +111 -0
  55. package/esm2022/core/reduced-motion.service.mjs +34 -0
  56. package/esm2022/decision-prompt/decision-prompt.component.mjs +259 -0
  57. package/esm2022/design-review/design-review.component.mjs +428 -0
  58. package/esm2022/design-tuner/design-tuner.component.mjs +341 -0
  59. package/esm2022/details-panel/details-panel.component.mjs +537 -0
  60. package/esm2022/donut-chart/donut-chart.component.mjs +240 -0
  61. package/esm2022/draft-review/draft-review.component.mjs +549 -0
  62. package/esm2022/error-recovery/error-recovery.component.mjs +231 -0
  63. package/esm2022/eval-results/eval-results.component.mjs +368 -0
  64. package/esm2022/feedback-sheet/feedback-sheet.component.mjs +411 -0
  65. package/esm2022/field-extraction/field-extraction.component.mjs +368 -0
  66. package/esm2022/funnel-chart/funnel-chart.component.mjs +258 -0
  67. package/esm2022/grid/grid.component.mjs +66 -0
  68. package/esm2022/health-score/health-score.component.mjs +420 -0
  69. package/esm2022/human-handoff/human-handoff.component.mjs +676 -0
  70. package/esm2022/image-generation/image-generation.component.mjs +1028 -0
  71. package/esm2022/inline-text-diff/inline-text-diff.component.mjs +390 -0
  72. package/esm2022/launch-checklist/launch-checklist.component.mjs +229 -0
  73. package/esm2022/line-chart/line-chart.component.mjs +417 -0
  74. package/esm2022/live-answer/live-answer.component.mjs +411 -0
  75. package/esm2022/metric-insight/metric-insight.component.mjs +511 -0
  76. package/esm2022/modal/modal.component.mjs +202 -0
  77. package/esm2022/model-picker/model-picker.component.mjs +491 -0
  78. package/esm2022/permission-gate/permission-gate.component.mjs +498 -0
  79. package/esm2022/plan-review/plan-review.component.mjs +432 -0
  80. package/esm2022/progress/progress.component.mjs +503 -0
  81. package/esm2022/prompt-library/prompt-library.component.mjs +453 -0
  82. package/esm2022/prompt-starters/prompt-starters.component.mjs +272 -0
  83. package/esm2022/proposal-card/proposal-card.component.mjs +402 -0
  84. package/esm2022/public-api.mjs +88 -0
  85. package/esm2022/radar-chart/radar-chart.component.mjs +500 -0
  86. package/esm2022/radial-goals/radial-goals.component.mjs +418 -0
  87. package/esm2022/reasoning-trail/reasoning-trail.component.mjs +284 -0
  88. package/esm2022/response-versions/response-versions.component.mjs +288 -0
  89. package/esm2022/rewrite-toolbar/rewrite-toolbar.component.mjs +397 -0
  90. package/esm2022/rich-text-editor/rich-text-editor.component.mjs +1755 -0
  91. package/esm2022/run-cost/run-cost.component.mjs +215 -0
  92. package/esm2022/run-queue/run-queue.component.mjs +481 -0
  93. package/esm2022/run-summary/run-summary.component.mjs +331 -0
  94. package/esm2022/scatter-chart/scatter-chart.component.mjs +705 -0
  95. package/esm2022/score-breakdown/score-breakdown.component.mjs +460 -0
  96. package/esm2022/segmented-control/segmented-control.component.mjs +180 -0
  97. package/esm2022/source-stack/source-stack.component.mjs +245 -0
  98. package/esm2022/stat-cards/stat-cards.component.mjs +258 -0
  99. package/esm2022/status-pill/status-pill.component.mjs +305 -0
  100. package/esm2022/steering/steering.component.mjs +343 -0
  101. package/esm2022/step-loader/step-loader.component.mjs +209 -0
  102. package/esm2022/task-table/task-table.component.mjs +534 -0
  103. package/esm2022/terminal-stream/terminal-stream.component.mjs +583 -0
  104. package/esm2022/thinking/thinking.component.mjs +276 -0
  105. package/esm2022/thinking-states/thinking-states.component.mjs +333 -0
  106. package/esm2022/thread-panel/thread-panel.component.mjs +271 -0
  107. package/esm2022/toast/toast.component.mjs +195 -0
  108. package/esm2022/toast-stack/toast-stack.component.mjs +301 -0
  109. package/esm2022/tool-call/tool-call.component.mjs +273 -0
  110. package/esm2022/tooltip/tooltip.component.mjs +417 -0
  111. package/esm2022/top-pages/top-pages.component.mjs +240 -0
  112. package/esm2022/trace-view/trace-view.component.mjs +440 -0
  113. package/esm2022/visuno-angular.mjs +5 -0
  114. package/esm2022/voice-capture/voice-capture.component.mjs +650 -0
  115. package/esm2022/voice-orb/voice-orb.component.mjs +538 -0
  116. package/esm2022/web-search/web-search.component.mjs +374 -0
  117. package/eval-results/eval-results.component.d.ts +67 -0
  118. package/feedback-sheet/feedback-sheet.component.d.ts +74 -0
  119. package/fesm2022/visuno-angular.mjs +31992 -0
  120. package/fesm2022/visuno-angular.mjs.map +1 -0
  121. package/field-extraction/field-extraction.component.d.ts +82 -0
  122. package/funnel-chart/funnel-chart.component.d.ts +70 -0
  123. package/grid/grid.component.d.ts +22 -0
  124. package/health-score/health-score.component.d.ts +87 -0
  125. package/human-handoff/human-handoff.component.d.ts +125 -0
  126. package/image-generation/image-generation.component.d.ts +253 -0
  127. package/index.d.ts +5 -0
  128. package/inline-text-diff/inline-text-diff.component.d.ts +76 -0
  129. package/launch-checklist/launch-checklist.component.d.ts +46 -0
  130. package/line-chart/line-chart.component.d.ts +89 -0
  131. package/live-answer/live-answer.component.d.ts +110 -0
  132. package/metric-insight/metric-insight.component.d.ts +110 -0
  133. package/modal/modal.component.d.ts +37 -0
  134. package/model-picker/model-picker.component.d.ts +97 -0
  135. package/package.json +51 -4
  136. package/permission-gate/permission-gate.component.d.ts +100 -0
  137. package/plan-review/plan-review.component.d.ts +86 -0
  138. package/progress/progress.component.d.ts +91 -0
  139. package/prompt-library/prompt-library.component.d.ts +121 -0
  140. package/prompt-starters/prompt-starters.component.d.ts +65 -0
  141. package/proposal-card/proposal-card.component.d.ts +101 -0
  142. package/public-api.d.ts +82 -0
  143. package/radar-chart/radar-chart.component.d.ts +110 -0
  144. package/radial-goals/radial-goals.component.d.ts +90 -0
  145. package/reasoning-trail/reasoning-trail.component.d.ts +73 -0
  146. package/response-versions/response-versions.component.d.ts +54 -0
  147. package/rewrite-toolbar/rewrite-toolbar.component.d.ts +92 -0
  148. package/rich-text-editor/rich-text-editor.component.d.ts +180 -0
  149. package/run-cost/run-cost.component.d.ts +43 -0
  150. package/run-queue/run-queue.component.d.ts +93 -0
  151. package/run-summary/run-summary.component.d.ts +81 -0
  152. package/scatter-chart/scatter-chart.component.d.ts +139 -0
  153. package/score-breakdown/score-breakdown.component.d.ts +107 -0
  154. package/segmented-control/segmented-control.component.d.ts +44 -0
  155. package/source-stack/source-stack.component.d.ts +60 -0
  156. package/stat-cards/stat-cards.component.d.ts +86 -0
  157. package/status-pill/status-pill.component.d.ts +64 -0
  158. package/steering/steering.component.d.ts +75 -0
  159. package/step-loader/step-loader.component.d.ts +40 -0
  160. package/styles.css +424 -0
  161. package/task-table/task-table.component.d.ts +114 -0
  162. package/terminal-stream/terminal-stream.component.d.ts +110 -0
  163. package/thinking/thinking.component.d.ts +63 -0
  164. package/thinking-states/thinking-states.component.d.ts +51 -0
  165. package/thread-panel/thread-panel.component.d.ts +75 -0
  166. package/toast/toast.component.d.ts +56 -0
  167. package/toast-stack/toast-stack.component.d.ts +72 -0
  168. package/tokens.css +424 -0
  169. package/tool-call/tool-call.component.d.ts +61 -0
  170. package/tooltip/tooltip.component.d.ts +89 -0
  171. package/top-pages/top-pages.component.d.ts +75 -0
  172. package/trace-view/trace-view.component.d.ts +95 -0
  173. package/voice-capture/voice-capture.component.d.ts +103 -0
  174. package/voice-orb/voice-orb.component.d.ts +78 -0
  175. package/web-search/web-search.component.d.ts +77 -0
@@ -0,0 +1,258 @@
1
+ // framework/angular/funnel-chart/funnel-chart.component.ts
2
+ //
3
+ // Native Angular port of framework/react/funnel-chart/FunnelChart.tsx.
4
+ // How many people reach each stage, with the biggest drop marked and a note
5
+ // from the agent. The bars draw a moment after the funnel appears, then redraw
6
+ // top to bottom on every view switch; the note crossfades on a switch. Inputs
7
+ // mirror the React props. Behaviour ported from the vanilla JS (funnel-chart.js):
8
+ // a staggered glide of each bar's width (and its count's position), the worst
9
+ // drop marked, and a blur-swap note.
10
+ //
11
+ // Icon: uses `spark` (the only available match for the React `spark` glyph).
12
+ import { Component, EventEmitter, Input, Output, ViewEncapsulation, } from '@angular/core';
13
+ import { VoIconComponent } from '../core/icon.component';
14
+ import * as i0 from "@angular/core";
15
+ import * as i1 from "../core/reduced-motion.service";
16
+ export class FunnelChartComponent {
17
+ /** Key of the view shown. Leave it out to let the switch change it. */
18
+ set view(value) {
19
+ this.controlled = value !== undefined;
20
+ if (value !== undefined && value !== this.cur) {
21
+ this.cur = value;
22
+ if (this.ready) {
23
+ this.placeKnob();
24
+ this.draw(this.cur);
25
+ }
26
+ }
27
+ }
28
+ constructor(reduced, cdr, host) {
29
+ this.reduced = reduced;
30
+ this.cdr = cdr;
31
+ this.host = host;
32
+ /** Like "Signup to paid". */
33
+ this.title = '';
34
+ /** The stages in order, like "Signed up" then "Opened a file". */
35
+ this.stages = [];
36
+ /** One set of numbers per view. With more than one, a switch picks between them. */
37
+ this.views = [];
38
+ /** Ends a stage's tip, like "of signups" in "51.8% of signups". */
39
+ this.shareLabel = 'of the first stage';
40
+ /** The first stage's tip. */
41
+ this.startLabel = 'Starting point';
42
+ /** Writes a count. Defaults to whole numbers like 12,400. */
43
+ this.format = (n) => Math.round(n).toLocaleString('en-US');
44
+ this.viewChange = new EventEmitter();
45
+ this.cur = '';
46
+ this.rows = [];
47
+ this.knobLeft = 0;
48
+ this.knobWidth = 0;
49
+ this.note = '';
50
+ this.noteOut = false;
51
+ this.hasInsight = false;
52
+ this.controlled = false;
53
+ this.ready = false;
54
+ this.noteId = 0;
55
+ this.timers = [];
56
+ }
57
+ ngAfterViewInit() {
58
+ if (!this.controlled)
59
+ this.cur = this.defaultView ?? this.views[0]?.key ?? '';
60
+ this.hasInsight = this.views.some((v) => v.insight !== undefined);
61
+ const last = Math.max(1, this.stages.length - 1);
62
+ this.rows = this.stages.map((stage, index) => ({
63
+ stage,
64
+ index,
65
+ fc: `color-mix(in oklab,var(--vo-c1) ${Math.round(100 - (index * 100) / last)}%,var(--vo-c2))`,
66
+ width: 0,
67
+ count: '',
68
+ out: false,
69
+ drop: false,
70
+ change: '',
71
+ tip: '',
72
+ }));
73
+ this.ready = true;
74
+ this.cdr.detectChanges();
75
+ this.placeKnob();
76
+ // the first draw starts a moment after the funnel appears, and its note fades in after it
77
+ this.later(() => this.draw(this.cur), 280);
78
+ this.note = this.byKey(this.cur)?.insight ?? '';
79
+ }
80
+ select(key) {
81
+ if (!this.controlled) {
82
+ this.cur = key;
83
+ this.placeKnob();
84
+ this.draw(key);
85
+ }
86
+ this.viewChange.emit(key);
87
+ }
88
+ byKey(key) {
89
+ return this.views.find((v) => v.key === key);
90
+ }
91
+ draw(key) {
92
+ const shown = this.byKey(key);
93
+ const d = shown?.values ?? [];
94
+ // the stage that loses the largest share of the one before it
95
+ let worst = -1;
96
+ let ratio = 1;
97
+ d.forEach((n, i) => {
98
+ if (i && n / d[i - 1] < ratio) {
99
+ ratio = n / d[i - 1];
100
+ worst = i;
101
+ }
102
+ });
103
+ this.rows.forEach((row, i) => {
104
+ const w = d.length ? Math.max(6, (d[i] / d[0]) * 100) : 0;
105
+ row.width = w;
106
+ row.out = w < 24;
107
+ row.count = shown ? this.format(d[i]) : '';
108
+ row.change = shown ? (i ? '−' + Math.round((1 - d[i] / d[i - 1]) * 100) + '%' : '100%') : '';
109
+ row.drop = i === worst;
110
+ row.tip = shown
111
+ ? i
112
+ ? `${Math.round((d[i] / d[0]) * 1000) / 10}% ${this.shareLabel}`
113
+ : this.startLabel
114
+ : '';
115
+ });
116
+ this.say(shown?.insight ?? '');
117
+ this.cdr.markForCheck();
118
+ }
119
+ // the note crossfades on a switch; the newest note is the one that lands
120
+ say(text) {
121
+ const id = ++this.noteId;
122
+ if (this.note === text && !this.noteOut)
123
+ return;
124
+ this.noteOut = true;
125
+ this.later(() => {
126
+ if (id !== this.noteId)
127
+ return;
128
+ this.note = text;
129
+ this.noteOut = false;
130
+ this.cdr.markForCheck();
131
+ }, this.reduced.reduce() ? 0 : 170);
132
+ }
133
+ placeKnob() {
134
+ const btns = this.host.nativeElement.querySelectorAll('.vo-fnx-sg button');
135
+ const idx = this.views.findIndex((v) => v.key === this.cur);
136
+ const b = btns[idx];
137
+ if (b) {
138
+ this.knobLeft = b.offsetLeft;
139
+ this.knobWidth = b.offsetWidth;
140
+ this.cdr.markForCheck();
141
+ }
142
+ }
143
+ later(fn, ms) {
144
+ this.timers.push(setTimeout(fn, ms));
145
+ }
146
+ ngOnDestroy() {
147
+ this.timers.forEach(clearTimeout);
148
+ this.timers = [];
149
+ }
150
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FunnelChartComponent, deps: [{ token: i1.ReducedMotionService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
151
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: FunnelChartComponent, isStandalone: true, selector: "vo-funnel-chart", inputs: { title: "title", stages: "stages", views: "views", view: "view", defaultView: "defaultView", shareLabel: "shareLabel", startLabel: "startLabel", format: "format" }, outputs: { viewChange: "viewChange" }, ngImport: i0, template: `
152
+ <div data-vo="" class="vo-fnx vo-panel">
153
+ <div class="vo-fnx-h">
154
+ <b>{{ title }}</b>
155
+ @if (views.length > 1) {
156
+ <div class="vo-seg2 vo-fnx-sg" role="group" aria-label="Segment">
157
+ <span class="vo-knob" [style.left.px]="knobLeft" [style.width.px]="knobWidth"></span>
158
+ @for (v of views; track v.key) {
159
+ <button
160
+ type="button"
161
+ [attr.aria-pressed]="v.key === cur"
162
+ (click)="select(v.key)"
163
+ >{{ v.label }}</button>
164
+ }
165
+ </div>
166
+ }
167
+ </div>
168
+ <div class="vo-fnx-rows">
169
+ @for (r of rows; track r.index) {
170
+ <div class="vo-fnx-r" [class.vo-drop]="r.drop" [style.--vo-fc]="r.fc" [attr.title]="r.tip">
171
+ <span class="vo-k">{{ r.stage }}</span>
172
+ <div class="vo-tr">
173
+ <div class="vo-bar" [style.width.%]="r.width"></div>
174
+ <span
175
+ class="vo-n vo-num"
176
+ [class.vo-out]="r.out"
177
+ [style.left]="r.out ? 'calc(' + r.width + '% + 8px)' : '10px'"
178
+ >{{ r.count }}</span>
179
+ </div>
180
+ <span class="vo-v vo-num">{{ r.change }}</span>
181
+ </div>
182
+ }
183
+ </div>
184
+ @if (hasInsight) {
185
+ <div class="vo-fnx-ins">
186
+ <span class="vo-fnx-ic"><vo-icon name="spark" size="xs"></vo-icon></span>
187
+ <span class="vo-sw vo-fnx-t" [class.vo-out]="noteOut">{{ note }}</span>
188
+ </div>
189
+ }
190
+ </div>
191
+ `, isInline: true, styles: [".vo-fnx{padding:var(--vo-s-4);display:flex;flex-direction:column;gap:var(--vo-s-3)}.vo-fnx-h{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:13.5px;flex-wrap:wrap}.vo-fnx-h b{font-weight:500}.vo-fnx-sg button{font-size:12px;height:26px;padding:0 9px}.vo-fnx-rows{display:flex;flex-direction:column;gap:6px}.vo-fnx-r{display:grid;grid-template-columns:118px 1fr 48px;align-items:center;gap:10px;font-size:12.5px;padding:2px 0;border-radius:var(--vo-r-sm)}.vo-fnx-r .vo-k{color:var(--vo-fg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.vo-fnx-r .vo-tr{height:26px;border-radius:var(--vo-r-sm);background:var(--vo-chip);position:relative;overflow:hidden}.vo-fnx-r .vo-bar{position:absolute;inset:0 auto 0 0;border-radius:var(--vo-r-sm);background:var(--vo-accent);box-shadow:inset 0 0 0 1px var(--vo-accent-mark,var(--vo-accent));transition:width .9s var(--vo-ease),opacity .3s}.vo-fnx-r .vo-n{position:absolute;left:10px;top:0;bottom:0;display:flex;align-items:center;color:var(--vo-on-accent);font-size:11.5px;font-weight:500;transition:left .9s var(--vo-ease),color .3s}.vo-fnx-r .vo-n.vo-out{color:var(--vo-fg2)}.vo-fnx-r .vo-bar{background:var(--vo-fc,var(--vo-accent));box-shadow:none}:root:not([data-style=soft]) .vo-fnx-r .vo-bar:not(:where([data-style=soft],[data-style=soft] *)){background:var(--vo-accent);box-shadow:inset 0 0 0 1px var(--vo-accent-mark,var(--vo-accent))}.vo-fnx-r .vo-v{text-align:right;color:var(--vo-muted);font-size:12px}.vo-fnx-r.vo-drop .vo-v{color:var(--vo-bad);font-weight:500}@media (hover:hover) and (pointer:fine){.vo-fnx-rows:hover .vo-fnx-r:not(:hover) .vo-bar{opacity:.35}}.vo-fnx-ins{display:flex;gap:var(--vo-s-2);font-size:12.5px;line-height:1.5;color:var(--vo-fg2);padding:10px var(--vo-s-3);border-radius:var(--vo-r-in);background:var(--vo-accent-bg)}.vo-fnx-ic{color:var(--vo-accent-fg,var(--vo-accent));display:grid;margin-top:2px}.vo-panel{background:var(--vo-surface);border-radius:var(--vo-r-card);box-shadow:var(--vo-shadow);position:relative}.vo-num{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.vo-sw{display:inline-block;transition:opacity .17s var(--vo-ease),filter .17s var(--vo-ease),transform .17s var(--vo-ease)}.vo-sw.vo-out{opacity:0;filter:blur(3px);transform:translateY(3px)}@media (prefers-reduced-motion:reduce){.vo-sw{transition:none}}.vo-seg2{display:inline-flex;padding:2px;background:var(--vo-chip);border-radius:var(--vo-r-pill);position:relative}.vo-seg2 button{position:relative;z-index:1;height:26px;padding:0 11px;border-radius:var(--vo-r-pill);font-size:12.5px;color:var(--vo-fg2);cursor:pointer;transition:color var(--vo-t-fast)}.vo-seg2 button[aria-pressed=true]{color:var(--vo-fg)}.vo-seg2 .vo-knob{position:absolute;top:2px;bottom:2px;border-radius:var(--vo-r-pill);background:var(--vo-surface);box-shadow:0 1px 2px #00000014;transition:left var(--vo-t) var(--vo-ease),width var(--vo-t) var(--vo-ease)}.vo-seg2 button:focus-visible{outline-offset:-2px;border-radius:var(--vo-r-pill)}:root:not([data-style=soft]) .vo-seg2 .vo-knob:not(:where([data-style=soft],[data-style=soft] *)){box-shadow:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent)}\n"], dependencies: [{ kind: "component", type: VoIconComponent, selector: "vo-icon", inputs: ["name", "size"] }], encapsulation: i0.ViewEncapsulation.None }); }
192
+ }
193
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FunnelChartComponent, decorators: [{
194
+ type: Component,
195
+ args: [{ selector: 'vo-funnel-chart', standalone: true, encapsulation: ViewEncapsulation.None, imports: [VoIconComponent], template: `
196
+ <div data-vo="" class="vo-fnx vo-panel">
197
+ <div class="vo-fnx-h">
198
+ <b>{{ title }}</b>
199
+ @if (views.length > 1) {
200
+ <div class="vo-seg2 vo-fnx-sg" role="group" aria-label="Segment">
201
+ <span class="vo-knob" [style.left.px]="knobLeft" [style.width.px]="knobWidth"></span>
202
+ @for (v of views; track v.key) {
203
+ <button
204
+ type="button"
205
+ [attr.aria-pressed]="v.key === cur"
206
+ (click)="select(v.key)"
207
+ >{{ v.label }}</button>
208
+ }
209
+ </div>
210
+ }
211
+ </div>
212
+ <div class="vo-fnx-rows">
213
+ @for (r of rows; track r.index) {
214
+ <div class="vo-fnx-r" [class.vo-drop]="r.drop" [style.--vo-fc]="r.fc" [attr.title]="r.tip">
215
+ <span class="vo-k">{{ r.stage }}</span>
216
+ <div class="vo-tr">
217
+ <div class="vo-bar" [style.width.%]="r.width"></div>
218
+ <span
219
+ class="vo-n vo-num"
220
+ [class.vo-out]="r.out"
221
+ [style.left]="r.out ? 'calc(' + r.width + '% + 8px)' : '10px'"
222
+ >{{ r.count }}</span>
223
+ </div>
224
+ <span class="vo-v vo-num">{{ r.change }}</span>
225
+ </div>
226
+ }
227
+ </div>
228
+ @if (hasInsight) {
229
+ <div class="vo-fnx-ins">
230
+ <span class="vo-fnx-ic"><vo-icon name="spark" size="xs"></vo-icon></span>
231
+ <span class="vo-sw vo-fnx-t" [class.vo-out]="noteOut">{{ note }}</span>
232
+ </div>
233
+ }
234
+ </div>
235
+ `, styles: [".vo-fnx{padding:var(--vo-s-4);display:flex;flex-direction:column;gap:var(--vo-s-3)}.vo-fnx-h{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:13.5px;flex-wrap:wrap}.vo-fnx-h b{font-weight:500}.vo-fnx-sg button{font-size:12px;height:26px;padding:0 9px}.vo-fnx-rows{display:flex;flex-direction:column;gap:6px}.vo-fnx-r{display:grid;grid-template-columns:118px 1fr 48px;align-items:center;gap:10px;font-size:12.5px;padding:2px 0;border-radius:var(--vo-r-sm)}.vo-fnx-r .vo-k{color:var(--vo-fg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.vo-fnx-r .vo-tr{height:26px;border-radius:var(--vo-r-sm);background:var(--vo-chip);position:relative;overflow:hidden}.vo-fnx-r .vo-bar{position:absolute;inset:0 auto 0 0;border-radius:var(--vo-r-sm);background:var(--vo-accent);box-shadow:inset 0 0 0 1px var(--vo-accent-mark,var(--vo-accent));transition:width .9s var(--vo-ease),opacity .3s}.vo-fnx-r .vo-n{position:absolute;left:10px;top:0;bottom:0;display:flex;align-items:center;color:var(--vo-on-accent);font-size:11.5px;font-weight:500;transition:left .9s var(--vo-ease),color .3s}.vo-fnx-r .vo-n.vo-out{color:var(--vo-fg2)}.vo-fnx-r .vo-bar{background:var(--vo-fc,var(--vo-accent));box-shadow:none}:root:not([data-style=soft]) .vo-fnx-r .vo-bar:not(:where([data-style=soft],[data-style=soft] *)){background:var(--vo-accent);box-shadow:inset 0 0 0 1px var(--vo-accent-mark,var(--vo-accent))}.vo-fnx-r .vo-v{text-align:right;color:var(--vo-muted);font-size:12px}.vo-fnx-r.vo-drop .vo-v{color:var(--vo-bad);font-weight:500}@media (hover:hover) and (pointer:fine){.vo-fnx-rows:hover .vo-fnx-r:not(:hover) .vo-bar{opacity:.35}}.vo-fnx-ins{display:flex;gap:var(--vo-s-2);font-size:12.5px;line-height:1.5;color:var(--vo-fg2);padding:10px var(--vo-s-3);border-radius:var(--vo-r-in);background:var(--vo-accent-bg)}.vo-fnx-ic{color:var(--vo-accent-fg,var(--vo-accent));display:grid;margin-top:2px}.vo-panel{background:var(--vo-surface);border-radius:var(--vo-r-card);box-shadow:var(--vo-shadow);position:relative}.vo-num{font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\" 1}.vo-sw{display:inline-block;transition:opacity .17s var(--vo-ease),filter .17s var(--vo-ease),transform .17s var(--vo-ease)}.vo-sw.vo-out{opacity:0;filter:blur(3px);transform:translateY(3px)}@media (prefers-reduced-motion:reduce){.vo-sw{transition:none}}.vo-seg2{display:inline-flex;padding:2px;background:var(--vo-chip);border-radius:var(--vo-r-pill);position:relative}.vo-seg2 button{position:relative;z-index:1;height:26px;padding:0 11px;border-radius:var(--vo-r-pill);font-size:12.5px;color:var(--vo-fg2);cursor:pointer;transition:color var(--vo-t-fast)}.vo-seg2 button[aria-pressed=true]{color:var(--vo-fg)}.vo-seg2 .vo-knob{position:absolute;top:2px;bottom:2px;border-radius:var(--vo-r-pill);background:var(--vo-surface);box-shadow:0 1px 2px #00000014;transition:left var(--vo-t) var(--vo-ease),width var(--vo-t) var(--vo-ease)}.vo-seg2 button:focus-visible{outline-offset:-2px;border-radius:var(--vo-r-pill)}:root:not([data-style=soft]) .vo-seg2 .vo-knob:not(:where([data-style=soft],[data-style=soft] *)){box-shadow:0 0 0 1px color-mix(in srgb,var(--vo-rail) 50%,transparent)}\n"] }]
236
+ }], ctorParameters: () => [{ type: i1.ReducedMotionService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { title: [{
237
+ type: Input,
238
+ args: [{ required: true }]
239
+ }], stages: [{
240
+ type: Input,
241
+ args: [{ required: true }]
242
+ }], views: [{
243
+ type: Input,
244
+ args: [{ required: true }]
245
+ }], view: [{
246
+ type: Input
247
+ }], defaultView: [{
248
+ type: Input
249
+ }], shareLabel: [{
250
+ type: Input
251
+ }], startLabel: [{
252
+ type: Input
253
+ }], format: [{
254
+ type: Input
255
+ }], viewChange: [{
256
+ type: Output
257
+ }] } });
258
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVubmVsLWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2Z1bm5lbC1jaGFydC9mdW5uZWwtY2hhcnQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDJEQUEyRDtBQUMzRCxFQUFFO0FBQ0YsdUVBQXVFO0FBQ3ZFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLGtGQUFrRjtBQUNsRiw4RUFBOEU7QUFDOUUscUNBQXFDO0FBQ3JDLEVBQUU7QUFDRiw2RUFBNkU7QUFFN0UsT0FBTyxFQUdMLFNBQVMsRUFFVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDOzs7QUEyRXpELE1BQU0sT0FBTyxvQkFBb0I7SUFPL0IsdUVBQXVFO0lBQ3ZFLElBQWEsSUFBSSxDQUFDLEtBQXlCO1FBQ3pDLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxLQUFLLFNBQVMsQ0FBQztRQUN0QyxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUM5QyxJQUFJLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQztZQUNqQixJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDZixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3RCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQXlCRCxZQUNtQixPQUE2QixFQUM3QixHQUFzQixFQUN0QixJQUE2QjtRQUY3QixZQUFPLEdBQVAsT0FBTyxDQUFzQjtRQUM3QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQUN0QixTQUFJLEdBQUosSUFBSSxDQUF5QjtR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SSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUMxQixDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxFQUFjLEVBQUUsRUFBVTtRQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNuQixDQUFDOytHQWhKVSxvQkFBb0I7bUdBQXBCLG9CQUFvQixnU0EzQ3JCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0NULDRzR0F6Q1MsZUFBZTs7NEZBNENkLG9CQUFvQjtrQkFoRGhDLFNBQVM7K0JBQ0UsaUJBQWlCLGNBQ2YsSUFBSSxpQkFDRCxpQkFBaUIsQ0FBQyxJQUFJLFdBQzVCLENBQUMsZUFBZSxDQUFDLFlBQ2hCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0NUO2tKQUswQixLQUFLO3NCQUEvQixLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFFRSxNQUFNO3NCQUFoQyxLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFFRSxLQUFLO3NCQUEvQixLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFFWixJQUFJO3NCQUFoQixLQUFLO2dCQVdHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFFSSxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZnJhbWV3b3JrL2FuZ3VsYXIvZnVubmVsLWNoYXJ0L2Z1bm5lbC1jaGFydC5jb21wb25lbnQudHNcbi8vXG4vLyBOYXRpdmUgQW5ndWxhciBwb3J0IG9mIGZyYW1ld29yay9yZWFjdC9mdW5uZWwtY2hhcnQvRnVubmVsQ2hhcnQudHN4LlxuLy8gSG93IG1hbnkgcGVvcGxlIHJlYWNoIGVhY2ggc3RhZ2UsIHdpdGggdGhlIGJpZ2dlc3QgZHJvcCBtYXJrZWQgYW5kIGEgbm90ZVxuLy8gZnJvbSB0aGUgYWdlbnQuIFRoZSBiYXJzIGRyYXcgYSBtb21lbnQgYWZ0ZXIgdGhlIGZ1bm5lbCBhcHBlYXJzLCB0aGVuIHJlZHJhd1xuLy8gdG9wIHRvIGJvdHRvbSBvbiBldmVyeSB2aWV3IHN3aXRjaDsgdGhlIG5vdGUgY3Jvc3NmYWRlcyBvbiBhIHN3aXRjaC4gSW5wdXRzXG4vLyBtaXJyb3IgdGhlIFJlYWN0IHByb3BzLiBCZWhhdmlvdXIgcG9ydGVkIGZyb20gdGhlIHZhbmlsbGEgSlMgKGZ1bm5lbC1jaGFydC5qcyk6XG4vLyBhIHN0YWdnZXJlZCBnbGlkZSBvZiBlYWNoIGJhcidzIHdpZHRoIChhbmQgaXRzIGNvdW50J3MgcG9zaXRpb24pLCB0aGUgd29yc3Rcbi8vIGRyb3AgbWFya2VkLCBhbmQgYSBibHVyLXN3YXAgbm90ZS5cbi8vXG4vLyBJY29uOiB1c2VzIGBzcGFya2AgKHRoZSBvbmx5IGF2YWlsYWJsZSBtYXRjaCBmb3IgdGhlIFJlYWN0IGBzcGFya2AgZ2x5cGgpLlxuXG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVm9JY29uQ29tcG9uZW50IH0gZnJvbSAnLi4vY29yZS9pY29uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBSZWR1Y2VkTW90aW9uU2VydmljZSB9IGZyb20gJy4uL2NvcmUvcmVkdWNlZC1tb3Rpb24uc2VydmljZSc7XG5cbi8qKiBPbmUgc2V0IG9mIG51bWJlcnMsIHBpY2tlZCBieSB0aGUgc3dpdGNoLiAqL1xuZXhwb3J0IGludGVyZmFjZSBGdW5uZWxDaGFydFZpZXcge1xuICBrZXk6IHN0cmluZztcbiAgLyoqIE9uIHRoZSBzd2l0Y2gsIGxpa2UgXCJUZWFtc1wiLiAqL1xuICBsYWJlbDogc3RyaW5nO1xuICAvKiogSG93IG1hbnkgcmVhY2hlZCBlYWNoIHN0YWdlLCBpbiBvcmRlci4gKi9cbiAgdmFsdWVzOiBudW1iZXJbXTtcbiAgLyoqIFRoZSBhZ2VudCdzIG5vdGUgdW5kZXIgdGhlIGZ1bm5lbCBmb3IgdGhpcyB2aWV3LiAqL1xuICBpbnNpZ2h0Pzogc3RyaW5nO1xufVxuXG4vKiogSW50ZXJuYWwgcGVyLXN0YWdlIHJlbmRlciBzdGF0ZS4gKi9cbmludGVyZmFjZSBSb3dWaWV3IHtcbiAgc3RhZ2U6IHN0cmluZztcbiAgaW5kZXg6IG51bWJlcjtcbiAgZmM6IHN0cmluZztcbiAgd2lkdGg6IG51bWJlcjtcbiAgY291bnQ6IHN0cmluZztcbiAgb3V0OiBib29sZWFuO1xuICBkcm9wOiBib29sZWFuO1xuICBjaGFuZ2U6IHN0cmluZztcbiAgdGlwOiBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZvLWZ1bm5lbC1jaGFydCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGltcG9ydHM6IFtWb0ljb25Db21wb25lbnRdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgZGF0YS12bz1cIlwiIGNsYXNzPVwidm8tZm54IHZvLXBhbmVsXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwidm8tZm54LWhcIj5cbiAgICAgICAgPGI+e3sgdGl0bGUgfX08L2I+XG4gICAgICAgIEBpZiAodmlld3MubGVuZ3RoID4gMSkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ2by1zZWcyIHZvLWZueC1zZ1wiIHJvbGU9XCJncm91cFwiIGFyaWEtbGFiZWw9XCJTZWdtZW50XCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInZvLWtub2JcIiBbc3R5bGUubGVmdC5weF09XCJrbm9iTGVmdFwiIFtzdHlsZS53aWR0aC5weF09XCJrbm9iV2lkdGhcIj48L3NwYW4+XG4gICAgICAgICAgICBAZm9yICh2IG9mIHZpZXdzOyB0cmFjayB2LmtleSkge1xuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1wcmVzc2VkXT1cInYua2V5ID09PSBjdXJcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3Qodi5rZXkpXCJcbiAgICAgICAgICAgICAgPnt7IHYubGFiZWwgfX08L2J1dHRvbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwidm8tZm54LXJvd3NcIj5cbiAgICAgICAgQGZvciAociBvZiByb3dzOyB0cmFjayByLmluZGV4KSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInZvLWZueC1yXCIgW2NsYXNzLnZvLWRyb3BdPVwici5kcm9wXCIgW3N0eWxlLi0tdm8tZmNdPVwici5mY1wiIFthdHRyLnRpdGxlXT1cInIudGlwXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInZvLWtcIj57eyByLnN0YWdlIH19PC9zcGFuPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInZvLXRyXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ2by1iYXJcIiBbc3R5bGUud2lkdGguJV09XCJyLndpZHRoXCI+PC9kaXY+XG4gICAgICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ2by1uIHZvLW51bVwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLnZvLW91dF09XCJyLm91dFwiXG4gICAgICAgICAgICAgICAgW3N0eWxlLmxlZnRdPVwici5vdXQgPyAnY2FsYygnICsgci53aWR0aCArICclICsgOHB4KScgOiAnMTBweCdcIlxuICAgICAgICAgICAgICA+e3sgci5jb3VudCB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ2by12IHZvLW51bVwiPnt7IHIuY2hhbmdlIH19PC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICAgIEBpZiAoaGFzSW5zaWdodCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidm8tZm54LWluc1wiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidm8tZm54LWljXCI+PHZvLWljb24gbmFtZT1cInNwYXJrXCIgc2l6ZT1cInhzXCI+PC92by1pY29uPjwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInZvLXN3IHZvLWZueC10XCIgW2NsYXNzLnZvLW91dF09XCJub3RlT3V0XCI+e3sgbm90ZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlVXJsOiAnLi9mdW5uZWwtY2hhcnQuY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgRnVubmVsQ2hhcnRDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICAvKiogTGlrZSBcIlNpZ251cCB0byBwYWlkXCIuICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIHRpdGxlID0gJyc7XG4gIC8qKiBUaGUgc3RhZ2VzIGluIG9yZGVyLCBsaWtlIFwiU2lnbmVkIHVwXCIgdGhlbiBcIk9wZW5lZCBhIGZpbGVcIi4gKi9cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgc3RhZ2VzOiBzdHJpbmdbXSA9IFtdO1xuICAvKiogT25lIHNldCBvZiBudW1iZXJzIHBlciB2aWV3LiBXaXRoIG1vcmUgdGhhbiBvbmUsIGEgc3dpdGNoIHBpY2tzIGJldHdlZW4gdGhlbS4gKi9cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgdmlld3M6IEZ1bm5lbENoYXJ0Vmlld1tdID0gW107XG4gIC8qKiBLZXkgb2YgdGhlIHZpZXcgc2hvd24uIExlYXZlIGl0IG91dCB0byBsZXQgdGhlIHN3aXRjaCBjaGFuZ2UgaXQuICovXG4gIEBJbnB1dCgpIHNldCB2aWV3KHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmNvbnRyb2xsZWQgPSB2YWx1ZSAhPT0gdW5kZWZpbmVkO1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSB0aGlzLmN1cikge1xuICAgICAgdGhpcy5jdXIgPSB2YWx1ZTtcbiAgICAgIGlmICh0aGlzLnJlYWR5KSB7XG4gICAgICAgIHRoaXMucGxhY2VLbm9iKCk7XG4gICAgICAgIHRoaXMuZHJhdyh0aGlzLmN1cik7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIC8qKiBEZWZhdWx0cyB0byB0aGUgZmlyc3Qgdmlldy4gKi9cbiAgQElucHV0KCkgZGVmYXVsdFZpZXc/OiBzdHJpbmc7XG4gIC8qKiBFbmRzIGEgc3RhZ2UncyB0aXAsIGxpa2UgXCJvZiBzaWdudXBzXCIgaW4gXCI1MS44JSBvZiBzaWdudXBzXCIuICovXG4gIEBJbnB1dCgpIHNoYXJlTGFiZWwgPSAnb2YgdGhlIGZpcnN0IHN0YWdlJztcbiAgLyoqIFRoZSBmaXJzdCBzdGFnZSdzIHRpcC4gKi9cbiAgQElucHV0KCkgc3RhcnRMYWJlbCA9ICdTdGFydGluZyBwb2ludCc7XG4gIC8qKiBXcml0ZXMgYSBjb3VudC4gRGVmYXVsdHMgdG8gd2hvbGUgbnVtYmVycyBsaWtlIDEyLDQwMC4gKi9cbiAgQElucHV0KCkgZm9ybWF0OiAobjogbnVtYmVyKSA9PiBzdHJpbmcgPSAobikgPT4gTWF0aC5yb3VuZChuKS50b0xvY2FsZVN0cmluZygnZW4tVVMnKTtcblxuICBAT3V0cHV0KCkgdmlld0NoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIGN1ciA9ICcnO1xuICByb3dzOiBSb3dWaWV3W10gPSBbXTtcbiAga25vYkxlZnQgPSAwO1xuICBrbm9iV2lkdGggPSAwO1xuICBub3RlID0gJyc7XG4gIG5vdGVPdXQgPSBmYWxzZTtcbiAgaGFzSW5zaWdodCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgY29udHJvbGxlZCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWR5ID0gZmFsc2U7XG4gIHByaXZhdGUgbm90ZUlkID0gMDtcbiAgcHJpdmF0ZSB0aW1lcnM6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+W10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlZHVjZWQ6IFJlZHVjZWRNb3Rpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhvc3Q6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICApIHt9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb250cm9sbGVkKSB0aGlzLmN1ciA9IHRoaXMuZGVmYXVsdFZpZXcgPz8gdGhpcy52aWV3c1swXT8ua2V5ID8/ICcnO1xuICAgIHRoaXMuaGFzSW5zaWdodCA9IHRoaXMudmlld3Muc29tZSgodikgPT4gdi5pbnNpZ2h0ICE9PSB1bmRlZmluZWQpO1xuICAgIGNvbnN0IGxhc3QgPSBNYXRoLm1heCgxLCB0aGlzLnN0YWdlcy5sZW5ndGggLSAxKTtcbiAgICB0aGlzLnJvd3MgPSB0aGlzLnN0YWdlcy5tYXAoKHN0YWdlLCBpbmRleCkgPT4gKHtcbiAgICAgIHN0YWdlLFxuICAgICAgaW5kZXgsXG4gICAgICBmYzogYGNvbG9yLW1peChpbiBva2xhYix2YXIoLS12by1jMSkgJHtNYXRoLnJvdW5kKDEwMCAtIChpbmRleCAqIDEwMCkgLyBsYXN0KX0lLHZhcigtLXZvLWMyKSlgLFxuICAgICAgd2lkdGg6IDAsXG4gICAgICBjb3VudDogJycsXG4gICAgICBvdXQ6IGZhbHNlLFxuICAgICAgZHJvcDogZmFsc2UsXG4gICAgICBjaGFuZ2U6ICcnLFxuICAgICAgdGlwOiAnJyxcbiAgICB9KSk7XG4gICAgdGhpcy5yZWFkeSA9IHRydWU7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIHRoaXMucGxhY2VLbm9iKCk7XG4gICAgLy8gdGhlIGZpcnN0IGRyYXcgc3RhcnRzIGEgbW9tZW50IGFmdGVyIHRoZSBmdW5uZWwgYXBwZWFycywgYW5kIGl0cyBub3RlIGZhZGVzIGluIGFmdGVyIGl0XG4gICAgdGhpcy5sYXRlcigoKSA9PiB0aGlzLmRyYXcodGhpcy5jdXIpLCAyODApO1xuICAgIHRoaXMubm90ZSA9IHRoaXMuYnlLZXkodGhpcy5jdXIpPy5pbnNpZ2h0ID8/ICcnO1xuICB9XG5cbiAgc2VsZWN0KGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbnRyb2xsZWQpIHtcbiAgICAgIHRoaXMuY3VyID0ga2V5O1xuICAgICAgdGhpcy5wbGFjZUtub2IoKTtcbiAgICAgIHRoaXMuZHJhdyhrZXkpO1xuICAgIH1cbiAgICB0aGlzLnZpZXdDaGFuZ2UuZW1pdChrZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBieUtleShrZXk6IHN0cmluZyk6IEZ1bm5lbENoYXJ0VmlldyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMudmlld3MuZmluZCgodikgPT4gdi5rZXkgPT09IGtleSk7XG4gIH1cblxuICBwcml2YXRlIGRyYXcoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBzaG93biA9IHRoaXMuYnlLZXkoa2V5KTtcbiAgICBjb25zdCBkID0gc2hvd24/LnZhbHVlcyA/PyBbXTtcbiAgICAvLyB0aGUgc3RhZ2UgdGhhdCBsb3NlcyB0aGUgbGFyZ2VzdCBzaGFyZSBvZiB0aGUgb25lIGJlZm9yZSBpdFxuICAgIGxldCB3b3JzdCA9IC0xO1xuICAgIGxldCByYXRpbyA9IDE7XG4gICAgZC5mb3JFYWNoKChuLCBpKSA9PiB7XG4gICAgICBpZiAoaSAmJiBuIC8gZFtpIC0gMV0gPCByYXRpbykge1xuICAgICAgICByYXRpbyA9IG4gLyBkW2kgLSAxXTtcbiAgICAgICAgd29yc3QgPSBpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMucm93cy5mb3JFYWNoKChyb3csIGkpID0+IHtcbiAgICAgIGNvbnN0IHcgPSBkLmxlbmd0aCA/IE1hdGgubWF4KDYsIChkW2ldIC8gZFswXSkgKiAxMDApIDogMDtcbiAgICAgIHJvdy53aWR0aCA9IHc7XG4gICAgICByb3cub3V0ID0gdyA8IDI0O1xuICAgICAgcm93LmNvdW50ID0gc2hvd24gPyB0aGlzLmZvcm1hdChkW2ldKSA6ICcnO1xuICAgICAgcm93LmNoYW5nZSA9IHNob3duID8gKGkgPyAn4oiSJyArIE1hdGgucm91bmQoKDEgLSBkW2ldIC8gZFtpIC0gMV0pICogMTAwKSArICclJyA6ICcxMDAlJykgOiAnJztcbiAgICAgIHJvdy5kcm9wID0gaSA9PT0gd29yc3Q7XG4gICAgICByb3cudGlwID0gc2hvd25cbiAgICAgICAgPyBpXG4gICAgICAgICAgPyBgJHtNYXRoLnJvdW5kKChkW2ldIC8gZFswXSkgKiAxMDAwKSAvIDEwfSUgJHt0aGlzLnNoYXJlTGFiZWx9YFxuICAgICAgICAgIDogdGhpcy5zdGFydExhYmVsXG4gICAgICAgIDogJyc7XG4gICAgfSk7XG4gICAgdGhpcy5zYXkoc2hvd24/Lmluc2lnaHQgPz8gJycpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLy8gdGhlIG5vdGUgY3Jvc3NmYWRlcyBvbiBhIHN3aXRjaDsgdGhlIG5ld2VzdCBub3RlIGlzIHRoZSBvbmUgdGhhdCBsYW5kc1xuICBwcml2YXRlIHNheSh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBpZCA9ICsrdGhpcy5ub3RlSWQ7XG4gICAgaWYgKHRoaXMubm90ZSA9PT0gdGV4dCAmJiAhdGhpcy5ub3RlT3V0KSByZXR1cm47XG4gICAgdGhpcy5ub3RlT3V0ID0gdHJ1ZTtcbiAgICB0aGlzLmxhdGVyKCgpID0+IHtcbiAgICAgIGlmIChpZCAhPT0gdGhpcy5ub3RlSWQpIHJldHVybjtcbiAgICAgIHRoaXMubm90ZSA9IHRleHQ7XG4gICAgICB0aGlzLm5vdGVPdXQgPSBmYWxzZTtcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH0sIHRoaXMucmVkdWNlZC5yZWR1Y2UoKSA/IDAgOiAxNzApO1xuICB9XG5cbiAgcHJpdmF0ZSBwbGFjZUtub2IoKTogdm9pZCB7XG4gICAgY29uc3QgYnRucyA9IHRoaXMuaG9zdC5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KCcudm8tZm54LXNnIGJ1dHRvbicpO1xuICAgIGNvbnN0IGlkeCA9IHRoaXMudmlld3MuZmluZEluZGV4KCh2KSA9PiB2LmtleSA9PT0gdGhpcy5jdXIpO1xuICAgIGNvbnN0IGIgPSBidG5zW2lkeF07XG4gICAgaWYgKGIpIHtcbiAgICAgIHRoaXMua25vYkxlZnQgPSBiLm9mZnNldExlZnQ7XG4gICAgICB0aGlzLmtub2JXaWR0aCA9IGIub2Zmc2V0V2lkdGg7XG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGxhdGVyKGZuOiAoKSA9PiB2b2lkLCBtczogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy50aW1lcnMucHVzaChzZXRUaW1lb3V0KGZuLCBtcykpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy50aW1lcnMuZm9yRWFjaChjbGVhclRpbWVvdXQpO1xuICAgIHRoaXMudGltZXJzID0gW107XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,66 @@
1
+ // framework/angular/grid/grid.component.ts
2
+ //
3
+ // Native Angular port of framework/react/grid/Grid.tsx.
4
+ // A responsive grid you drop cards or any other components into. Inputs mirror
5
+ // the React props. Use the `voGridItem` directive on a child to span columns.
6
+ //
7
+ // The grid class and CSS vars live on the host element itself (not a wrapper),
8
+ // so projected children are direct children of `.vo-grd` and the `>` span
9
+ // selectors apply.
10
+ import { Component, Directive, Input, ViewEncapsulation } from '@angular/core';
11
+ import * as i0 from "@angular/core";
12
+ export class GridComponent {
13
+ constructor() {
14
+ /** A fixed column count. Ignored when `fit` is set. 3 by default. */
15
+ this.cols = 3;
16
+ /** Pack as many columns as fit at `min` width, reflowing with no column count. */
17
+ this.fit = false;
18
+ /** Minimum column width when `fit` is set. '200px' by default. */
19
+ this.min = '200px';
20
+ /** The gutter: a core spacing step (1–8) or a raw CSS length. 4 by default. */
21
+ this.gap = 4;
22
+ }
23
+ get gapVar() {
24
+ return typeof this.gap === 'number' ? `var(--vo-s-${this.gap})` : this.gap;
25
+ }
26
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
27
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: GridComponent, isStandalone: true, selector: "vo-grid", inputs: { cols: "cols", fit: "fit", min: "min", gap: "gap" }, host: { properties: { "attr.data-fit": "fit ? 'true' : null", "style.--grd-cols": "cols", "style.--grd-gap": "gapVar", "style.--grd-min": "min" }, classAttribute: "vo-grd" }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true, styles: [".vo-grd{--grd-cols:3;--grd-gap:var(--vo-s-4);--grd-min:200px;display:grid;gap:var(--grd-gap);grid-template-columns:repeat(var(--grd-cols),minmax(0,1fr));min-width:0;container:grd/inline-size}.vo-grd[data-fit=true]{grid-template-columns:repeat(auto-fit,minmax(min(var(--grd-min),100%),1fr))}.vo-grd>[data-span=\"2\"]{grid-column:span 2}.vo-grd>[data-span=\"3\"]{grid-column:span 3}.vo-grd>[data-span=\"4\"]{grid-column:span 4}.vo-grd>[data-span=full]{grid-column:1 / -1}@container grd (max-width:420px){.vo-grd:not([data-fit=true]){grid-template-columns:minmax(0,1fr)}.vo-grd>[data-span]{grid-column:auto}}\n"], encapsulation: i0.ViewEncapsulation.None }); }
28
+ }
29
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridComponent, decorators: [{
30
+ type: Component,
31
+ args: [{ selector: 'vo-grid', standalone: true, encapsulation: ViewEncapsulation.None, host: {
32
+ class: 'vo-grd',
33
+ '[attr.data-fit]': "fit ? 'true' : null",
34
+ '[style.--grd-cols]': 'cols',
35
+ '[style.--grd-gap]': 'gapVar',
36
+ '[style.--grd-min]': 'min',
37
+ }, template: `<ng-content></ng-content>`, styles: [".vo-grd{--grd-cols:3;--grd-gap:var(--vo-s-4);--grd-min:200px;display:grid;gap:var(--grd-gap);grid-template-columns:repeat(var(--grd-cols),minmax(0,1fr));min-width:0;container:grd/inline-size}.vo-grd[data-fit=true]{grid-template-columns:repeat(auto-fit,minmax(min(var(--grd-min),100%),1fr))}.vo-grd>[data-span=\"2\"]{grid-column:span 2}.vo-grd>[data-span=\"3\"]{grid-column:span 3}.vo-grd>[data-span=\"4\"]{grid-column:span 4}.vo-grd>[data-span=full]{grid-column:1 / -1}@container grd (max-width:420px){.vo-grd:not([data-fit=true]){grid-template-columns:minmax(0,1fr)}.vo-grd>[data-span]{grid-column:auto}}\n"] }]
38
+ }], propDecorators: { cols: [{
39
+ type: Input
40
+ }], fit: [{
41
+ type: Input
42
+ }], min: [{
43
+ type: Input
44
+ }], gap: [{
45
+ type: Input
46
+ }] } });
47
+ /** A grid child that spans more than one column (2, 3, 4) or the full row ('full'). */
48
+ export class GridItemDirective {
49
+ constructor() {
50
+ this.span = '';
51
+ }
52
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
53
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: GridItemDirective, isStandalone: true, selector: "[voGridItem]", inputs: { span: ["voGridItem", "span"] }, host: { properties: { "attr.data-span": "span || null" } }, ngImport: i0 }); }
54
+ }
55
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridItemDirective, decorators: [{
56
+ type: Directive,
57
+ args: [{
58
+ selector: '[voGridItem]',
59
+ standalone: true,
60
+ host: { '[attr.data-span]': 'span || null' },
61
+ }]
62
+ }], propDecorators: { span: [{
63
+ type: Input,
64
+ args: ['voGridItem']
65
+ }] } });
66
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9ncmlkL2dyaWQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDJDQUEyQztBQUMzQyxFQUFFO0FBQ0Ysd0RBQXdEO0FBQ3hELCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsbUJBQW1CO0FBRW5CLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFtQi9FLE1BQU0sT0FBTyxhQUFhO0lBZDFCO1FBZUUscUVBQXFFO1FBQzVELFNBQUksR0FBRyxDQUFDLENBQUM7UUFDbEIsa0ZBQWtGO1FBQ3pFLFFBQUcsR0FBRyxLQUFLLENBQUM7UUFDckIsa0VBQWtFO1FBQ3pELFFBQUcsR0FBRyxPQUFPLENBQUM7UUFDdkIsK0VBQStFO1FBQ3RFLFFBQUcsR0FBWSxDQUFDLENBQUM7S0FLM0I7SUFIQyxJQUFJLE1BQU07UUFDUixPQUFPLE9BQU8sSUFBSSxDQUFDLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLGNBQWMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQzdFLENBQUM7K0dBWlUsYUFBYTttR0FBYixhQUFhLGdUQUhkLDJCQUEyQjs7NEZBRzFCLGFBQWE7a0JBZHpCLFNBQVM7K0JBQ0UsU0FBUyxjQUNQLElBQUksaUJBQ0QsaUJBQWlCLENBQUMsSUFBSSxRQUMvQjt3QkFDSixLQUFLLEVBQUUsUUFBUTt3QkFDZixpQkFBaUIsRUFBRSxxQkFBcUI7d0JBQ3hDLG9CQUFvQixFQUFFLE1BQU07d0JBQzVCLG1CQUFtQixFQUFFLFFBQVE7d0JBQzdCLG1CQUFtQixFQUFFLEtBQUs7cUJBQzNCLFlBQ1MsMkJBQTJCOzhCQUs1QixJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsR0FBRztzQkFBWCxLQUFLO2dCQUVHLEdBQUc7c0JBQVgsS0FBSztnQkFFRyxHQUFHO3NCQUFYLEtBQUs7O0FBT1IsdUZBQXVGO0FBTXZGLE1BQU0sT0FBTyxpQkFBaUI7SUFMOUI7UUFNdUIsU0FBSSxHQUE0QixFQUFFLENBQUM7S0FDekQ7K0dBRlksaUJBQWlCO21HQUFqQixpQkFBaUI7OzRGQUFqQixpQkFBaUI7a0JBTDdCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGNBQWM7b0JBQ3hCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixJQUFJLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUU7aUJBQzdDOzhCQUVzQixJQUFJO3NCQUF4QixLQUFLO3VCQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBmcmFtZXdvcmsvYW5ndWxhci9ncmlkL2dyaWQuY29tcG9uZW50LnRzXG4vL1xuLy8gTmF0aXZlIEFuZ3VsYXIgcG9ydCBvZiBmcmFtZXdvcmsvcmVhY3QvZ3JpZC9HcmlkLnRzeC5cbi8vIEEgcmVzcG9uc2l2ZSBncmlkIHlvdSBkcm9wIGNhcmRzIG9yIGFueSBvdGhlciBjb21wb25lbnRzIGludG8uIElucHV0cyBtaXJyb3Jcbi8vIHRoZSBSZWFjdCBwcm9wcy4gVXNlIHRoZSBgdm9HcmlkSXRlbWAgZGlyZWN0aXZlIG9uIGEgY2hpbGQgdG8gc3BhbiBjb2x1bW5zLlxuLy9cbi8vIFRoZSBncmlkIGNsYXNzIGFuZCBDU1MgdmFycyBsaXZlIG9uIHRoZSBob3N0IGVsZW1lbnQgaXRzZWxmIChub3QgYSB3cmFwcGVyKSxcbi8vIHNvIHByb2plY3RlZCBjaGlsZHJlbiBhcmUgZGlyZWN0IGNoaWxkcmVuIG9mIGAudm8tZ3JkYCBhbmQgdGhlIGA+YCBzcGFuXG4vLyBzZWxlY3RvcnMgYXBwbHkuXG5cbmltcG9ydCB7IENvbXBvbmVudCwgRGlyZWN0aXZlLCBJbnB1dCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLyoqIEEgY29yZSBzcGFjaW5nIHRva2VuICgx4oCTOCkgZm9yIHRoZSBndXR0ZXIsIG9yIGEgcmF3IENTUyBsZW5ndGguICovXG5leHBvcnQgdHlwZSBHcmlkR2FwID0gMSB8IDIgfCAzIHwgNCB8IDUgfCA2IHwgOCB8IHN0cmluZztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndm8tZ3JpZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGhvc3Q6IHtcbiAgICBjbGFzczogJ3ZvLWdyZCcsXG4gICAgJ1thdHRyLmRhdGEtZml0XSc6IFwiZml0ID8gJ3RydWUnIDogbnVsbFwiLFxuICAgICdbc3R5bGUuLS1ncmQtY29sc10nOiAnY29scycsXG4gICAgJ1tzdHlsZS4tLWdyZC1nYXBdJzogJ2dhcFZhcicsXG4gICAgJ1tzdHlsZS4tLWdyZC1taW5dJzogJ21pbicsXG4gIH0sXG4gIHRlbXBsYXRlOiBgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PmAsXG4gIHN0eWxlVXJsOiAnLi9ncmlkLmNzcycsXG59KVxuZXhwb3J0IGNsYXNzIEdyaWRDb21wb25lbnQge1xuICAvKiogQSBmaXhlZCBjb2x1bW4gY291bnQuIElnbm9yZWQgd2hlbiBgZml0YCBpcyBzZXQuIDMgYnkgZGVmYXVsdC4gKi9cbiAgQElucHV0KCkgY29scyA9IDM7XG4gIC8qKiBQYWNrIGFzIG1hbnkgY29sdW1ucyBhcyBmaXQgYXQgYG1pbmAgd2lkdGgsIHJlZmxvd2luZyB3aXRoIG5vIGNvbHVtbiBjb3VudC4gKi9cbiAgQElucHV0KCkgZml0ID0gZmFsc2U7XG4gIC8qKiBNaW5pbXVtIGNvbHVtbiB3aWR0aCB3aGVuIGBmaXRgIGlzIHNldC4gJzIwMHB4JyBieSBkZWZhdWx0LiAqL1xuICBASW5wdXQoKSBtaW4gPSAnMjAwcHgnO1xuICAvKiogVGhlIGd1dHRlcjogYSBjb3JlIHNwYWNpbmcgc3RlcCAoMeKAkzgpIG9yIGEgcmF3IENTUyBsZW5ndGguIDQgYnkgZGVmYXVsdC4gKi9cbiAgQElucHV0KCkgZ2FwOiBHcmlkR2FwID0gNDtcblxuICBnZXQgZ2FwVmFyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHR5cGVvZiB0aGlzLmdhcCA9PT0gJ251bWJlcicgPyBgdmFyKC0tdm8tcy0ke3RoaXMuZ2FwfSlgIDogdGhpcy5nYXA7XG4gIH1cbn1cblxuLyoqIEEgZ3JpZCBjaGlsZCB0aGF0IHNwYW5zIG1vcmUgdGhhbiBvbmUgY29sdW1uICgyLCAzLCA0KSBvciB0aGUgZnVsbCByb3cgKCdmdWxsJykuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbdm9HcmlkSXRlbV0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBob3N0OiB7ICdbYXR0ci5kYXRhLXNwYW5dJzogJ3NwYW4gfHwgbnVsbCcgfSxcbn0pXG5leHBvcnQgY2xhc3MgR3JpZEl0ZW1EaXJlY3RpdmUge1xuICBASW5wdXQoJ3ZvR3JpZEl0ZW0nKSBzcGFuOiAyIHwgMyB8IDQgfCAnZnVsbCcgfCAnJyA9ICcnO1xufVxuIl19