@vespera-ui/angular 0.1.0 → 0.2.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.
@@ -0,0 +1,1825 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Input, Component, EventEmitter, Output } from '@angular/core';
3
+
4
+ class VspButton {
5
+ variant = 'ghost';
6
+ size;
7
+ loading = false;
8
+ disabled = false;
9
+ get cls() {
10
+ return ['btn', `btn-${this.variant}`, this.size === 'sm' ? 'btn-sm' : '']
11
+ .filter(Boolean)
12
+ .join(' ');
13
+ }
14
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
15
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspButton, isStandalone: true, selector: "vsp-button", inputs: { variant: "variant", size: "size", loading: "loading", disabled: "disabled" }, ngImport: i0, template: `<button [class]="cls" [disabled]="disabled || loading">
16
+ @if (loading) {
17
+ <span class="ui-spinner" aria-hidden="true"></span>
18
+ }
19
+ <ng-content />
20
+ </button>`, isInline: true });
21
+ }
22
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspButton, decorators: [{
23
+ type: Component,
24
+ args: [{
25
+ selector: 'vsp-button',
26
+ template: `<button [class]="cls" [disabled]="disabled || loading">
27
+ @if (loading) {
28
+ <span class="ui-spinner" aria-hidden="true"></span>
29
+ }
30
+ <ng-content />
31
+ </button>`,
32
+ }]
33
+ }], propDecorators: { variant: [{
34
+ type: Input
35
+ }], size: [{
36
+ type: Input
37
+ }], loading: [{
38
+ type: Input
39
+ }], disabled: [{
40
+ type: Input
41
+ }] } });
42
+
43
+ class VspBadge {
44
+ tone = 'muted';
45
+ dot = false;
46
+ get cls() {
47
+ return `badge badge-${this.tone}`;
48
+ }
49
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
50
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspBadge, isStandalone: true, selector: "vsp-badge", inputs: { tone: "tone", dot: "dot" }, ngImport: i0, template: `<span [class]="cls">
51
+ @if (dot) {
52
+ <i></i>
53
+ }
54
+ <ng-content />
55
+ </span>`, isInline: true });
56
+ }
57
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBadge, decorators: [{
58
+ type: Component,
59
+ args: [{
60
+ selector: 'vsp-badge',
61
+ template: `<span [class]="cls">
62
+ @if (dot) {
63
+ <i></i>
64
+ }
65
+ <ng-content />
66
+ </span>`,
67
+ }]
68
+ }], propDecorators: { tone: [{
69
+ type: Input
70
+ }], dot: [{
71
+ type: Input
72
+ }] } });
73
+
74
+ class VspTag {
75
+ remove = new EventEmitter();
76
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTag, deps: [], target: i0.ɵɵFactoryTarget.Component });
77
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspTag, isStandalone: true, selector: "vsp-tag", outputs: { remove: "remove" }, ngImport: i0, template: `<span class="ui-tag">
78
+ <ng-content />
79
+ <button type="button" aria-label="Remove" (click)="remove.emit()">×</button>
80
+ </span>`, isInline: true });
81
+ }
82
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTag, decorators: [{
83
+ type: Component,
84
+ args: [{
85
+ selector: 'vsp-tag',
86
+ template: `<span class="ui-tag">
87
+ <ng-content />
88
+ <button type="button" aria-label="Remove" (click)="remove.emit()">×</button>
89
+ </span>`,
90
+ }]
91
+ }], propDecorators: { remove: [{
92
+ type: Output
93
+ }] } });
94
+ class VspKbd {
95
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspKbd, deps: [], target: i0.ɵɵFactoryTarget.Component });
96
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspKbd, isStandalone: true, selector: "vsp-kbd", ngImport: i0, template: `<kbd class="ui-kbd"><ng-content /></kbd>`, isInline: true });
97
+ }
98
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspKbd, decorators: [{
99
+ type: Component,
100
+ args: [{
101
+ selector: 'vsp-kbd',
102
+ template: `<kbd class="ui-kbd"><ng-content /></kbd>`,
103
+ }]
104
+ }] });
105
+ class VspDivider {
106
+ vertical = false;
107
+ get cls() {
108
+ return this.vertical ? 'ui-divider v' : 'ui-divider';
109
+ }
110
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspDivider, deps: [], target: i0.ɵɵFactoryTarget.Component });
111
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspDivider, isStandalone: true, selector: "vsp-divider", inputs: { vertical: "vertical" }, ngImport: i0, template: `<hr [class]="cls" />`, isInline: true });
112
+ }
113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspDivider, decorators: [{
114
+ type: Component,
115
+ args: [{
116
+ selector: 'vsp-divider',
117
+ template: `<hr [class]="cls" />`,
118
+ }]
119
+ }], propDecorators: { vertical: [{
120
+ type: Input
121
+ }] } });
122
+
123
+ class VspAvatar {
124
+ name = '';
125
+ hue = 0;
126
+ size = 34;
127
+ get initials() {
128
+ return this.name
129
+ .split(' ')
130
+ .map((s) => s.charAt(0))
131
+ .slice(0, 2)
132
+ .join('')
133
+ .toUpperCase();
134
+ }
135
+ get bg() {
136
+ return `linear-gradient(140deg, oklch(0.62 0.16 ${this.hue}), oklch(0.55 0.17 ${(this.hue + 50) % 360}))`;
137
+ }
138
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
139
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspAvatar, isStandalone: true, selector: "vsp-avatar", inputs: { name: "name", hue: "hue", size: "size" }, ngImport: i0, template: `<span
140
+ class="vsp-avatar"
141
+ [style.width.px]="size"
142
+ [style.height.px]="size"
143
+ [style.fontSize.px]="size * 0.38"
144
+ [style.background]="bg"
145
+ >{{ initials }}</span
146
+ >`, isInline: true });
147
+ }
148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAvatar, decorators: [{
149
+ type: Component,
150
+ args: [{
151
+ selector: 'vsp-avatar',
152
+ template: `<span
153
+ class="vsp-avatar"
154
+ [style.width.px]="size"
155
+ [style.height.px]="size"
156
+ [style.fontSize.px]="size * 0.38"
157
+ [style.background]="bg"
158
+ >{{ initials }}</span
159
+ >`,
160
+ }]
161
+ }], propDecorators: { name: [{
162
+ type: Input
163
+ }], hue: [{
164
+ type: Input
165
+ }], size: [{
166
+ type: Input
167
+ }] } });
168
+ class VspAvatarGroup {
169
+ people = [];
170
+ max = 4;
171
+ size = 32;
172
+ get shown() {
173
+ return this.people.slice(0, this.max);
174
+ }
175
+ get extra() {
176
+ return this.people.length - this.shown.length;
177
+ }
178
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAvatarGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
179
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspAvatarGroup, isStandalone: true, selector: "vsp-avatar-group", inputs: { people: "people", max: "max", size: "size" }, ngImport: i0, template: `<div style="display: flex; align-items: center">
180
+ @for (p of shown; track $index) {
181
+ <span
182
+ [style.marginLeft.px]="$index ? -10 : 0"
183
+ [style.zIndex]="shown.length - $index"
184
+ style="border: 2px solid var(--surface-1); border-radius: 50%; position: relative"
185
+ >
186
+ <vsp-avatar [name]="p.name" [hue]="p.hue ?? 0" [size]="size" />
187
+ </span>
188
+ }
189
+ @if (extra > 0) {
190
+ <span
191
+ [style.width.px]="size"
192
+ [style.height.px]="size"
193
+ [style.fontSize.px]="size * 0.34"
194
+ style="margin-left: -10px; border-radius: 50%; display: grid; place-items: center; background: var(--surface-3); border: 2px solid var(--surface-1); font-weight: 700; color: var(--text-dim)"
195
+ >+{{ extra }}</span
196
+ >
197
+ }
198
+ </div>`, isInline: true, dependencies: [{ kind: "component", type: VspAvatar, selector: "vsp-avatar", inputs: ["name", "hue", "size"] }] });
199
+ }
200
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAvatarGroup, decorators: [{
201
+ type: Component,
202
+ args: [{
203
+ selector: 'vsp-avatar-group',
204
+ imports: [VspAvatar],
205
+ template: `<div style="display: flex; align-items: center">
206
+ @for (p of shown; track $index) {
207
+ <span
208
+ [style.marginLeft.px]="$index ? -10 : 0"
209
+ [style.zIndex]="shown.length - $index"
210
+ style="border: 2px solid var(--surface-1); border-radius: 50%; position: relative"
211
+ >
212
+ <vsp-avatar [name]="p.name" [hue]="p.hue ?? 0" [size]="size" />
213
+ </span>
214
+ }
215
+ @if (extra > 0) {
216
+ <span
217
+ [style.width.px]="size"
218
+ [style.height.px]="size"
219
+ [style.fontSize.px]="size * 0.34"
220
+ style="margin-left: -10px; border-radius: 50%; display: grid; place-items: center; background: var(--surface-3); border: 2px solid var(--surface-1); font-weight: 700; color: var(--text-dim)"
221
+ >+{{ extra }}</span
222
+ >
223
+ }
224
+ </div>`,
225
+ }]
226
+ }], propDecorators: { people: [{
227
+ type: Input
228
+ }], max: [{
229
+ type: Input
230
+ }], size: [{
231
+ type: Input
232
+ }] } });
233
+ class VspSegmented {
234
+ value;
235
+ valueChange = new EventEmitter();
236
+ options = [];
237
+ pick(o) {
238
+ this.value = o;
239
+ this.valueChange.emit(o);
240
+ }
241
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSegmented, deps: [], target: i0.ɵɵFactoryTarget.Component });
242
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspSegmented, isStandalone: true, selector: "vsp-segmented", inputs: { value: "value", options: "options" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<div class="ui-seg">
243
+ @for (o of options; track o) {
244
+ <button type="button" [class.on]="value === o" (click)="pick(o)">{{ o }}</button>
245
+ }
246
+ </div>`, isInline: true });
247
+ }
248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSegmented, decorators: [{
249
+ type: Component,
250
+ args: [{
251
+ selector: 'vsp-segmented',
252
+ template: `<div class="ui-seg">
253
+ @for (o of options; track o) {
254
+ <button type="button" [class.on]="value === o" (click)="pick(o)">{{ o }}</button>
255
+ }
256
+ </div>`,
257
+ }]
258
+ }], propDecorators: { value: [{
259
+ type: Input
260
+ }], valueChange: [{
261
+ type: Output
262
+ }], options: [{
263
+ type: Input
264
+ }] } });
265
+
266
+ class VspSpinner {
267
+ size;
268
+ get cls() {
269
+ return this.size === 'lg' ? 'ui-spinner lg' : 'ui-spinner';
270
+ }
271
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSpinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
272
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspSpinner, isStandalone: true, selector: "vsp-spinner", inputs: { size: "size" }, ngImport: i0, template: `<span [class]="cls" aria-hidden="true"></span>`, isInline: true });
273
+ }
274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSpinner, decorators: [{
275
+ type: Component,
276
+ args: [{
277
+ selector: 'vsp-spinner',
278
+ template: `<span [class]="cls" aria-hidden="true"></span>`,
279
+ }]
280
+ }], propDecorators: { size: [{
281
+ type: Input
282
+ }] } });
283
+ class VspIconButton {
284
+ label;
285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspIconButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
286
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspIconButton, isStandalone: true, selector: "vsp-icon-button", inputs: { label: "label" }, ngImport: i0, template: `<button type="button" class="vsp-icon-btn" [attr.aria-label]="label">
287
+ <ng-content />
288
+ </button>`, isInline: true });
289
+ }
290
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspIconButton, decorators: [{
291
+ type: Component,
292
+ args: [{
293
+ selector: 'vsp-icon-button',
294
+ template: `<button type="button" class="vsp-icon-btn" [attr.aria-label]="label">
295
+ <ng-content />
296
+ </button>`,
297
+ }]
298
+ }], propDecorators: { label: [{
299
+ type: Input
300
+ }] } });
301
+ class VspProgress {
302
+ value = 0;
303
+ tone;
304
+ height = 6;
305
+ get clamped() {
306
+ return Math.min(100, this.value);
307
+ }
308
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
309
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspProgress, isStandalone: true, selector: "vsp-progress", inputs: { value: "value", tone: "tone", height: "height" }, ngImport: i0, template: `<div class="meter" [style.height.px]="height">
310
+ <i [style.width.%]="clamped" [style.background]="tone" style="transition: width 0.3s"></i>
311
+ </div>`, isInline: true });
312
+ }
313
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspProgress, decorators: [{
314
+ type: Component,
315
+ args: [{
316
+ selector: 'vsp-progress',
317
+ template: `<div class="meter" [style.height.px]="height">
318
+ <i [style.width.%]="clamped" [style.background]="tone" style="transition: width 0.3s"></i>
319
+ </div>`,
320
+ }]
321
+ }], propDecorators: { value: [{
322
+ type: Input
323
+ }], tone: [{
324
+ type: Input
325
+ }], height: [{
326
+ type: Input
327
+ }] } });
328
+ class VspSkeleton {
329
+ w = '100%';
330
+ h = 12;
331
+ r = 7;
332
+ px(v) {
333
+ return typeof v === 'number' ? `${v}px` : v;
334
+ }
335
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
336
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspSkeleton, isStandalone: true, selector: "vsp-skeleton", inputs: { w: "w", h: "h", r: "r" }, ngImport: i0, template: `<div
337
+ class="skel"
338
+ [style.width]="px(w)"
339
+ [style.height]="px(h)"
340
+ [style.borderRadius]="px(r)"
341
+ ></div>`, isInline: true });
342
+ }
343
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSkeleton, decorators: [{
344
+ type: Component,
345
+ args: [{
346
+ selector: 'vsp-skeleton',
347
+ template: `<div
348
+ class="skel"
349
+ [style.width]="px(w)"
350
+ [style.height]="px(h)"
351
+ [style.borderRadius]="px(r)"
352
+ ></div>`,
353
+ }]
354
+ }], propDecorators: { w: [{
355
+ type: Input
356
+ }], h: [{
357
+ type: Input
358
+ }], r: [{
359
+ type: Input
360
+ }] } });
361
+
362
+ class VspCard {
363
+ pad = false;
364
+ get cls() {
365
+ return this.pad ? 'card card-pad' : 'card';
366
+ }
367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
368
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspCard, isStandalone: true, selector: "vsp-card", inputs: { pad: "pad" }, ngImport: i0, template: `<div [class]="cls"><ng-content /></div>`, isInline: true });
369
+ }
370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCard, decorators: [{
371
+ type: Component,
372
+ args: [{
373
+ selector: 'vsp-card',
374
+ template: `<div [class]="cls"><ng-content /></div>`,
375
+ }]
376
+ }], propDecorators: { pad: [{
377
+ type: Input
378
+ }] } });
379
+ class VspCardHead {
380
+ title;
381
+ desc;
382
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCardHead, deps: [], target: i0.ɵɵFactoryTarget.Component });
383
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspCardHead, isStandalone: true, selector: "vsp-card-head", inputs: { title: "title", desc: "desc" }, ngImport: i0, template: `<div class="card-head">
384
+ <div style="min-width: 0">
385
+ <div class="ttl">{{ title }}</div>
386
+ @if (desc) {
387
+ <div class="eyebrow" style="margin-top: 3px">{{ desc }}</div>
388
+ }
389
+ </div>
390
+ <div class="vsp-top-spacer"></div>
391
+ <ng-content select="[slot=right]" />
392
+ </div>`, isInline: true });
393
+ }
394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCardHead, decorators: [{
395
+ type: Component,
396
+ args: [{
397
+ selector: 'vsp-card-head',
398
+ template: `<div class="card-head">
399
+ <div style="min-width: 0">
400
+ <div class="ttl">{{ title }}</div>
401
+ @if (desc) {
402
+ <div class="eyebrow" style="margin-top: 3px">{{ desc }}</div>
403
+ }
404
+ </div>
405
+ <div class="vsp-top-spacer"></div>
406
+ <ng-content select="[slot=right]" />
407
+ </div>`,
408
+ }]
409
+ }], propDecorators: { title: [{
410
+ type: Input
411
+ }], desc: [{
412
+ type: Input
413
+ }] } });
414
+
415
+ class VspAlert {
416
+ tone = 'info';
417
+ title;
418
+ get cls() {
419
+ return `ui-alert ${this.tone}`;
420
+ }
421
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
422
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspAlert, isStandalone: true, selector: "vsp-alert", inputs: { tone: "tone", title: "title" }, ngImport: i0, template: `<div [class]="cls">
423
+ <ng-content select="[slot=icon]" />
424
+ <div style="flex: 1">
425
+ @if (title) {
426
+ <div class="ui-alert-title">{{ title }}</div>
427
+ }
428
+ <div class="ui-alert-body"><ng-content /></div>
429
+ </div>
430
+ <ng-content select="[slot=action]" />
431
+ </div>`, isInline: true });
432
+ }
433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAlert, decorators: [{
434
+ type: Component,
435
+ args: [{
436
+ selector: 'vsp-alert',
437
+ template: `<div [class]="cls">
438
+ <ng-content select="[slot=icon]" />
439
+ <div style="flex: 1">
440
+ @if (title) {
441
+ <div class="ui-alert-title">{{ title }}</div>
442
+ }
443
+ <div class="ui-alert-body"><ng-content /></div>
444
+ </div>
445
+ <ng-content select="[slot=action]" />
446
+ </div>`,
447
+ }]
448
+ }], propDecorators: { tone: [{
449
+ type: Input
450
+ }], title: [{
451
+ type: Input
452
+ }] } });
453
+
454
+ class VspField {
455
+ label;
456
+ required = false;
457
+ hint;
458
+ error;
459
+ htmlFor;
460
+ get hintCls() {
461
+ return this.error ? 'ui-hint err' : 'ui-hint';
462
+ }
463
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspField, deps: [], target: i0.ɵɵFactoryTarget.Component });
464
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspField, isStandalone: true, selector: "vsp-field", inputs: { label: "label", required: "required", hint: "hint", error: "error", htmlFor: "htmlFor" }, ngImport: i0, template: `<div class="ui-field">
465
+ @if (label) {
466
+ <label class="ui-label" [attr.for]="htmlFor">
467
+ <span
468
+ >{{ label }}
469
+ @if (required) {
470
+ <span class="req"> *</span>
471
+ }
472
+ </span>
473
+ </label>
474
+ }
475
+ <ng-content />
476
+ @if (error || hint) {
477
+ <span [class]="hintCls">{{ error || hint }}</span>
478
+ }
479
+ </div>`, isInline: true });
480
+ }
481
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspField, decorators: [{
482
+ type: Component,
483
+ args: [{
484
+ selector: 'vsp-field',
485
+ template: `<div class="ui-field">
486
+ @if (label) {
487
+ <label class="ui-label" [attr.for]="htmlFor">
488
+ <span
489
+ >{{ label }}
490
+ @if (required) {
491
+ <span class="req"> *</span>
492
+ }
493
+ </span>
494
+ </label>
495
+ }
496
+ <ng-content />
497
+ @if (error || hint) {
498
+ <span [class]="hintCls">{{ error || hint }}</span>
499
+ }
500
+ </div>`,
501
+ }]
502
+ }], propDecorators: { label: [{
503
+ type: Input
504
+ }], required: [{
505
+ type: Input
506
+ }], hint: [{
507
+ type: Input
508
+ }], error: [{
509
+ type: Input
510
+ }], htmlFor: [{
511
+ type: Input
512
+ }] } });
513
+ class VspInput {
514
+ value = '';
515
+ valueChange = new EventEmitter();
516
+ invalid = false;
517
+ get cls() {
518
+ return this.invalid ? 'ui-input invalid' : 'ui-input';
519
+ }
520
+ onInput(e) {
521
+ this.value = e.target.value;
522
+ this.valueChange.emit(this.value);
523
+ }
524
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
525
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspInput, isStandalone: true, selector: "vsp-input", inputs: { value: "value", invalid: "invalid" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<input [class]="cls" [value]="value" (input)="onInput($event)" />`, isInline: true });
526
+ }
527
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspInput, decorators: [{
528
+ type: Component,
529
+ args: [{
530
+ selector: 'vsp-input',
531
+ template: `<input [class]="cls" [value]="value" (input)="onInput($event)" />`,
532
+ }]
533
+ }], propDecorators: { value: [{
534
+ type: Input
535
+ }], valueChange: [{
536
+ type: Output
537
+ }], invalid: [{
538
+ type: Input
539
+ }] } });
540
+ class VspTextarea {
541
+ value = '';
542
+ valueChange = new EventEmitter();
543
+ onInput(e) {
544
+ this.value = e.target.value;
545
+ this.valueChange.emit(this.value);
546
+ }
547
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
548
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspTextarea, isStandalone: true, selector: "vsp-textarea", inputs: { value: "value" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<textarea class="ui-textarea" [value]="value" (input)="onInput($event)"></textarea>`, isInline: true });
549
+ }
550
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTextarea, decorators: [{
551
+ type: Component,
552
+ args: [{
553
+ selector: 'vsp-textarea',
554
+ template: `<textarea class="ui-textarea" [value]="value" (input)="onInput($event)"></textarea>`,
555
+ }]
556
+ }], propDecorators: { value: [{
557
+ type: Input
558
+ }], valueChange: [{
559
+ type: Output
560
+ }] } });
561
+
562
+ class VspSwitch {
563
+ checked = false;
564
+ checkedChange = new EventEmitter();
565
+ size;
566
+ disabled = false;
567
+ get cls() {
568
+ return ['ui-switch', this.size === 'sm' && 'sm', this.checked && 'on']
569
+ .filter(Boolean)
570
+ .join(' ');
571
+ }
572
+ toggle() {
573
+ this.checked = !this.checked;
574
+ this.checkedChange.emit(this.checked);
575
+ }
576
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
577
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspSwitch, isStandalone: true, selector: "vsp-switch", inputs: { checked: "checked", size: "size", disabled: "disabled" }, outputs: { checkedChange: "checkedChange" }, ngImport: i0, template: `<button
578
+ type="button"
579
+ [disabled]="disabled"
580
+ [class]="cls"
581
+ [attr.aria-pressed]="checked"
582
+ aria-label="Toggle"
583
+ (click)="toggle()"
584
+ ></button>`, isInline: true });
585
+ }
586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSwitch, decorators: [{
587
+ type: Component,
588
+ args: [{
589
+ selector: 'vsp-switch',
590
+ template: `<button
591
+ type="button"
592
+ [disabled]="disabled"
593
+ [class]="cls"
594
+ [attr.aria-pressed]="checked"
595
+ aria-label="Toggle"
596
+ (click)="toggle()"
597
+ ></button>`,
598
+ }]
599
+ }], propDecorators: { checked: [{
600
+ type: Input
601
+ }], checkedChange: [{
602
+ type: Output
603
+ }], size: [{
604
+ type: Input
605
+ }], disabled: [{
606
+ type: Input
607
+ }] } });
608
+ class VspCheckbox {
609
+ checked = false;
610
+ checkedChange = new EventEmitter();
611
+ label;
612
+ sub;
613
+ disabled = false;
614
+ get checkCls() {
615
+ return this.checked ? 'ui-check on' : 'ui-check';
616
+ }
617
+ toggle() {
618
+ this.checked = !this.checked;
619
+ this.checkedChange.emit(this.checked);
620
+ }
621
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
622
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspCheckbox, isStandalone: true, selector: "vsp-checkbox", inputs: { checked: "checked", label: "label", sub: "sub", disabled: "disabled" }, outputs: { checkedChange: "checkedChange" }, ngImport: i0, template: `<label class="ui-opt" [style.opacity]="disabled ? 0.5 : 1">
623
+ <input
624
+ type="checkbox"
625
+ [checked]="checked"
626
+ [disabled]="disabled"
627
+ (change)="toggle()"
628
+ style="position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0"
629
+ />
630
+ <span [class]="checkCls"></span>
631
+ <span>
632
+ <span>{{ label }}</span>
633
+ @if (sub) {
634
+ <span class="ui-opt-sub">{{ sub }}</span>
635
+ }
636
+ </span>
637
+ </label>`, isInline: true });
638
+ }
639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCheckbox, decorators: [{
640
+ type: Component,
641
+ args: [{
642
+ selector: 'vsp-checkbox',
643
+ template: `<label class="ui-opt" [style.opacity]="disabled ? 0.5 : 1">
644
+ <input
645
+ type="checkbox"
646
+ [checked]="checked"
647
+ [disabled]="disabled"
648
+ (change)="toggle()"
649
+ style="position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0"
650
+ />
651
+ <span [class]="checkCls"></span>
652
+ <span>
653
+ <span>{{ label }}</span>
654
+ @if (sub) {
655
+ <span class="ui-opt-sub">{{ sub }}</span>
656
+ }
657
+ </span>
658
+ </label>`,
659
+ }]
660
+ }], propDecorators: { checked: [{
661
+ type: Input
662
+ }], checkedChange: [{
663
+ type: Output
664
+ }], label: [{
665
+ type: Input
666
+ }], sub: [{
667
+ type: Input
668
+ }], disabled: [{
669
+ type: Input
670
+ }] } });
671
+
672
+ const val = (o) => (typeof o === 'string' ? o : o.value);
673
+ const lbl = (o) => (typeof o === 'string' ? o : o.label);
674
+ const subOf = (o) => (typeof o === 'object' ? o.sub : undefined);
675
+ class VspRadio {
676
+ checked = false;
677
+ label;
678
+ sub;
679
+ name;
680
+ value;
681
+ select = new EventEmitter();
682
+ get dotCls() {
683
+ return this.checked ? 'ui-radio-dot on' : 'ui-radio-dot';
684
+ }
685
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspRadio, deps: [], target: i0.ɵɵFactoryTarget.Component });
686
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspRadio, isStandalone: true, selector: "vsp-radio", inputs: { checked: "checked", label: "label", sub: "sub", name: "name", value: "value" }, outputs: { select: "select" }, ngImport: i0, template: `<label class="ui-opt">
687
+ <input
688
+ type="radio"
689
+ [name]="name"
690
+ [value]="value"
691
+ [checked]="checked"
692
+ (change)="select.emit()"
693
+ style="position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0"
694
+ />
695
+ <span [class]="dotCls"></span>
696
+ <span>
697
+ <span>{{ label }}</span>
698
+ @if (sub) {
699
+ <span class="ui-opt-sub">{{ sub }}</span>
700
+ }
701
+ </span>
702
+ </label>`, isInline: true });
703
+ }
704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspRadio, decorators: [{
705
+ type: Component,
706
+ args: [{
707
+ selector: 'vsp-radio',
708
+ template: `<label class="ui-opt">
709
+ <input
710
+ type="radio"
711
+ [name]="name"
712
+ [value]="value"
713
+ [checked]="checked"
714
+ (change)="select.emit()"
715
+ style="position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0"
716
+ />
717
+ <span [class]="dotCls"></span>
718
+ <span>
719
+ <span>{{ label }}</span>
720
+ @if (sub) {
721
+ <span class="ui-opt-sub">{{ sub }}</span>
722
+ }
723
+ </span>
724
+ </label>`,
725
+ }]
726
+ }], propDecorators: { checked: [{
727
+ type: Input
728
+ }], label: [{
729
+ type: Input
730
+ }], sub: [{
731
+ type: Input
732
+ }], name: [{
733
+ type: Input
734
+ }], value: [{
735
+ type: Input
736
+ }], select: [{
737
+ type: Output
738
+ }] } });
739
+ class VspRadioGroup {
740
+ value;
741
+ valueChange = new EventEmitter();
742
+ options = [];
743
+ name = 'vsp-radio';
744
+ val = val;
745
+ lbl = lbl;
746
+ subOf = subOf;
747
+ pick(v) {
748
+ this.value = v;
749
+ this.valueChange.emit(v);
750
+ }
751
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspRadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
752
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspRadioGroup, isStandalone: true, selector: "vsp-radio-group", inputs: { value: "value", options: "options", name: "name" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<div style="display: flex; flex-direction: column; gap: 12px">
753
+ @for (o of options; track val(o)) {
754
+ <vsp-radio
755
+ [name]="name"
756
+ [label]="lbl(o)"
757
+ [sub]="subOf(o)"
758
+ [value]="val(o)"
759
+ [checked]="value === val(o)"
760
+ (select)="pick(val(o))"
761
+ />
762
+ }
763
+ </div>`, isInline: true, dependencies: [{ kind: "component", type: VspRadio, selector: "vsp-radio", inputs: ["checked", "label", "sub", "name", "value"], outputs: ["select"] }] });
764
+ }
765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspRadioGroup, decorators: [{
766
+ type: Component,
767
+ args: [{
768
+ selector: 'vsp-radio-group',
769
+ imports: [VspRadio],
770
+ template: `<div style="display: flex; flex-direction: column; gap: 12px">
771
+ @for (o of options; track val(o)) {
772
+ <vsp-radio
773
+ [name]="name"
774
+ [label]="lbl(o)"
775
+ [sub]="subOf(o)"
776
+ [value]="val(o)"
777
+ [checked]="value === val(o)"
778
+ (select)="pick(val(o))"
779
+ />
780
+ }
781
+ </div>`,
782
+ }]
783
+ }], propDecorators: { value: [{
784
+ type: Input
785
+ }], valueChange: [{
786
+ type: Output
787
+ }], options: [{
788
+ type: Input
789
+ }], name: [{
790
+ type: Input
791
+ }] } });
792
+ class VspSlider {
793
+ value = 0;
794
+ valueChange = new EventEmitter();
795
+ min = 0;
796
+ max = 100;
797
+ step = 1;
798
+ onInput(e) {
799
+ this.value = Number(e.target.value);
800
+ this.valueChange.emit(this.value);
801
+ }
802
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSlider, deps: [], target: i0.ɵɵFactoryTarget.Component });
803
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspSlider, isStandalone: true, selector: "vsp-slider", inputs: { value: "value", min: "min", max: "max", step: "step" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<input
804
+ type="range"
805
+ class="ui-slider"
806
+ [value]="value"
807
+ [min]="min"
808
+ [max]="max"
809
+ [step]="step"
810
+ (input)="onInput($event)"
811
+ />`, isInline: true });
812
+ }
813
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspSlider, decorators: [{
814
+ type: Component,
815
+ args: [{
816
+ selector: 'vsp-slider',
817
+ template: `<input
818
+ type="range"
819
+ class="ui-slider"
820
+ [value]="value"
821
+ [min]="min"
822
+ [max]="max"
823
+ [step]="step"
824
+ (input)="onInput($event)"
825
+ />`,
826
+ }]
827
+ }], propDecorators: { value: [{
828
+ type: Input
829
+ }], valueChange: [{
830
+ type: Output
831
+ }], min: [{
832
+ type: Input
833
+ }], max: [{
834
+ type: Input
835
+ }], step: [{
836
+ type: Input
837
+ }] } });
838
+ class VspNativeSelect {
839
+ value;
840
+ valueChange = new EventEmitter();
841
+ options = [];
842
+ val = val;
843
+ lbl = lbl;
844
+ onChange(e) {
845
+ this.value = e.target.value;
846
+ this.valueChange.emit(this.value);
847
+ }
848
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspNativeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
849
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspNativeSelect, isStandalone: true, selector: "vsp-native-select", inputs: { value: "value", options: "options" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<select class="ui-select" [value]="value" (change)="onChange($event)">
850
+ @for (o of options; track val(o)) {
851
+ <option [value]="val(o)">{{ lbl(o) }}</option>
852
+ }
853
+ </select>`, isInline: true });
854
+ }
855
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspNativeSelect, decorators: [{
856
+ type: Component,
857
+ args: [{
858
+ selector: 'vsp-native-select',
859
+ template: `<select class="ui-select" [value]="value" (change)="onChange($event)">
860
+ @for (o of options; track val(o)) {
861
+ <option [value]="val(o)">{{ lbl(o) }}</option>
862
+ }
863
+ </select>`,
864
+ }]
865
+ }], propDecorators: { value: [{
866
+ type: Input
867
+ }], valueChange: [{
868
+ type: Output
869
+ }], options: [{
870
+ type: Input
871
+ }] } });
872
+
873
+ class VspTabs {
874
+ tabs = [];
875
+ value;
876
+ valueChange = new EventEmitter();
877
+ id(t) {
878
+ return typeof t === 'string' ? t : t.value;
879
+ }
880
+ lbl(t) {
881
+ return typeof t === 'string' ? t : t.label;
882
+ }
883
+ cnt(t) {
884
+ return typeof t === 'object' ? t.count : undefined;
885
+ }
886
+ cls(t) {
887
+ return 'ui-tab' + (this.value === this.id(t) ? ' on' : '');
888
+ }
889
+ pick(v) {
890
+ this.value = v;
891
+ this.valueChange.emit(v);
892
+ }
893
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
894
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspTabs, isStandalone: true, selector: "vsp-tabs", inputs: { tabs: "tabs", value: "value" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<div class="ui-tabs" style="align-items: center">
895
+ @for (t of tabs; track id(t)) {
896
+ <button type="button" [class]="cls(t)" (click)="pick(id(t))">
897
+ {{ lbl(t) }}
898
+ @if (cnt(t) != null) {
899
+ <span class="badge badge-muted" style="margin-left: 7px">{{ cnt(t) }}</span>
900
+ }
901
+ </button>
902
+ }
903
+ <div style="flex: 1"></div>
904
+ <ng-content select="[slot=right]" />
905
+ </div>`, isInline: true });
906
+ }
907
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTabs, decorators: [{
908
+ type: Component,
909
+ args: [{
910
+ selector: 'vsp-tabs',
911
+ template: `<div class="ui-tabs" style="align-items: center">
912
+ @for (t of tabs; track id(t)) {
913
+ <button type="button" [class]="cls(t)" (click)="pick(id(t))">
914
+ {{ lbl(t) }}
915
+ @if (cnt(t) != null) {
916
+ <span class="badge badge-muted" style="margin-left: 7px">{{ cnt(t) }}</span>
917
+ }
918
+ </button>
919
+ }
920
+ <div style="flex: 1"></div>
921
+ <ng-content select="[slot=right]" />
922
+ </div>`,
923
+ }]
924
+ }], propDecorators: { tabs: [{
925
+ type: Input
926
+ }], value: [{
927
+ type: Input
928
+ }], valueChange: [{
929
+ type: Output
930
+ }] } });
931
+ class VspBreadcrumb {
932
+ items = [];
933
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBreadcrumb, deps: [], target: i0.ɵɵFactoryTarget.Component });
934
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspBreadcrumb, isStandalone: true, selector: "vsp-breadcrumb", inputs: { items: "items" }, ngImport: i0, template: `<nav style="display: flex; align-items: center; gap: 7px; font-size: 12.5px">
935
+ @for (it of items; track $index; let i = $index, last = $last) {
936
+ @if (i > 0) {
937
+ <svg
938
+ viewBox="0 0 24 24"
939
+ width="13"
940
+ height="13"
941
+ fill="none"
942
+ stroke="currentColor"
943
+ stroke-width="2"
944
+ stroke-linecap="round"
945
+ stroke-linejoin="round"
946
+ style="color: var(--text-faint)"
947
+ >
948
+ <path d="M9 18l6-6-6-6" />
949
+ </svg>
950
+ }
951
+ <span
952
+ [style.color]="last ? 'var(--text)' : 'var(--text-dim)'"
953
+ [style.fontWeight]="last ? 600 : 500"
954
+ >{{ it }}</span
955
+ >
956
+ }
957
+ </nav>`, isInline: true });
958
+ }
959
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBreadcrumb, decorators: [{
960
+ type: Component,
961
+ args: [{
962
+ selector: 'vsp-breadcrumb',
963
+ template: `<nav style="display: flex; align-items: center; gap: 7px; font-size: 12.5px">
964
+ @for (it of items; track $index; let i = $index, last = $last) {
965
+ @if (i > 0) {
966
+ <svg
967
+ viewBox="0 0 24 24"
968
+ width="13"
969
+ height="13"
970
+ fill="none"
971
+ stroke="currentColor"
972
+ stroke-width="2"
973
+ stroke-linecap="round"
974
+ stroke-linejoin="round"
975
+ style="color: var(--text-faint)"
976
+ >
977
+ <path d="M9 18l6-6-6-6" />
978
+ </svg>
979
+ }
980
+ <span
981
+ [style.color]="last ? 'var(--text)' : 'var(--text-dim)'"
982
+ [style.fontWeight]="last ? 600 : 500"
983
+ >{{ it }}</span
984
+ >
985
+ }
986
+ </nav>`,
987
+ }]
988
+ }], propDecorators: { items: [{
989
+ type: Input
990
+ }] } });
991
+ class VspPagination {
992
+ page = 0;
993
+ pageChange = new EventEmitter();
994
+ pages = 1;
995
+ get nums() {
996
+ const r = [];
997
+ for (let i = 0; i < this.pages; i++) {
998
+ if (i === 0 || i === this.pages - 1 || Math.abs(i - this.page) <= 1)
999
+ r.push({ gap: false, n: i });
1000
+ else if (!r[r.length - 1]?.gap)
1001
+ r.push({ gap: true, n: -1 });
1002
+ }
1003
+ return r;
1004
+ }
1005
+ numCls(n) {
1006
+ return 'btn btn-sm ' + (n === this.page ? 'btn-primary' : 'btn-subtle');
1007
+ }
1008
+ go(p) {
1009
+ this.page = p;
1010
+ this.pageChange.emit(p);
1011
+ }
1012
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspPagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
1013
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspPagination, isStandalone: true, selector: "vsp-pagination", inputs: { page: "page", pages: "pages" }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: `<div style="display: flex; gap: 4px; align-items: center">
1014
+ <button
1015
+ type="button"
1016
+ class="btn btn-ghost btn-sm"
1017
+ [disabled]="page === 0"
1018
+ aria-label="Previous page"
1019
+ (click)="go(page - 1)"
1020
+ >
1021
+ <svg
1022
+ viewBox="0 0 24 24"
1023
+ width="14"
1024
+ height="14"
1025
+ fill="none"
1026
+ stroke="currentColor"
1027
+ stroke-width="2"
1028
+ stroke-linecap="round"
1029
+ stroke-linejoin="round"
1030
+ >
1031
+ <path d="M15 18l-6-6 6-6" />
1032
+ </svg>
1033
+ </button>
1034
+ @for (item of nums; track $index) {
1035
+ @if (item.gap) {
1036
+ <span class="mono" style="padding: 0 6px; color: var(--text-faint)">…</span>
1037
+ } @else {
1038
+ <button
1039
+ type="button"
1040
+ [class]="numCls(item.n)"
1041
+ style="min-width: 32px; padding: 0"
1042
+ (click)="go(item.n)"
1043
+ >
1044
+ {{ item.n + 1 }}
1045
+ </button>
1046
+ }
1047
+ }
1048
+ <button
1049
+ type="button"
1050
+ class="btn btn-ghost btn-sm"
1051
+ [disabled]="page >= pages - 1"
1052
+ aria-label="Next page"
1053
+ (click)="go(page + 1)"
1054
+ >
1055
+ <svg
1056
+ viewBox="0 0 24 24"
1057
+ width="14"
1058
+ height="14"
1059
+ fill="none"
1060
+ stroke="currentColor"
1061
+ stroke-width="2"
1062
+ stroke-linecap="round"
1063
+ stroke-linejoin="round"
1064
+ >
1065
+ <path d="M9 18l6-6-6-6" />
1066
+ </svg>
1067
+ </button>
1068
+ </div>`, isInline: true });
1069
+ }
1070
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspPagination, decorators: [{
1071
+ type: Component,
1072
+ args: [{
1073
+ selector: 'vsp-pagination',
1074
+ template: `<div style="display: flex; gap: 4px; align-items: center">
1075
+ <button
1076
+ type="button"
1077
+ class="btn btn-ghost btn-sm"
1078
+ [disabled]="page === 0"
1079
+ aria-label="Previous page"
1080
+ (click)="go(page - 1)"
1081
+ >
1082
+ <svg
1083
+ viewBox="0 0 24 24"
1084
+ width="14"
1085
+ height="14"
1086
+ fill="none"
1087
+ stroke="currentColor"
1088
+ stroke-width="2"
1089
+ stroke-linecap="round"
1090
+ stroke-linejoin="round"
1091
+ >
1092
+ <path d="M15 18l-6-6 6-6" />
1093
+ </svg>
1094
+ </button>
1095
+ @for (item of nums; track $index) {
1096
+ @if (item.gap) {
1097
+ <span class="mono" style="padding: 0 6px; color: var(--text-faint)">…</span>
1098
+ } @else {
1099
+ <button
1100
+ type="button"
1101
+ [class]="numCls(item.n)"
1102
+ style="min-width: 32px; padding: 0"
1103
+ (click)="go(item.n)"
1104
+ >
1105
+ {{ item.n + 1 }}
1106
+ </button>
1107
+ }
1108
+ }
1109
+ <button
1110
+ type="button"
1111
+ class="btn btn-ghost btn-sm"
1112
+ [disabled]="page >= pages - 1"
1113
+ aria-label="Next page"
1114
+ (click)="go(page + 1)"
1115
+ >
1116
+ <svg
1117
+ viewBox="0 0 24 24"
1118
+ width="14"
1119
+ height="14"
1120
+ fill="none"
1121
+ stroke="currentColor"
1122
+ stroke-width="2"
1123
+ stroke-linecap="round"
1124
+ stroke-linejoin="round"
1125
+ >
1126
+ <path d="M9 18l6-6-6-6" />
1127
+ </svg>
1128
+ </button>
1129
+ </div>`,
1130
+ }]
1131
+ }], propDecorators: { page: [{
1132
+ type: Input
1133
+ }], pageChange: [{
1134
+ type: Output
1135
+ }], pages: [{
1136
+ type: Input
1137
+ }] } });
1138
+ class VspStepper {
1139
+ steps = [];
1140
+ current = 0;
1141
+ barCls(i) {
1142
+ return 'ui-step-bar' + (i <= this.current ? ' done' : '');
1143
+ }
1144
+ stepCls(i) {
1145
+ return 'ui-step ' + (i < this.current ? 'done' : i === this.current ? 'active' : 'pending');
1146
+ }
1147
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
1148
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspStepper, isStandalone: true, selector: "vsp-stepper", inputs: { steps: "steps", current: "current" }, ngImport: i0, template: `<div class="ui-steps">
1149
+ @for (s of steps; track $index; let i = $index) {
1150
+ @if (i > 0) {
1151
+ <div [class]="barCls(i)"></div>
1152
+ }
1153
+ <div [class]="stepCls(i)">
1154
+ <span class="ui-step-dot">
1155
+ @if (i < current) {
1156
+ <svg
1157
+ viewBox="0 0 24 24"
1158
+ width="14"
1159
+ height="14"
1160
+ fill="none"
1161
+ stroke="currentColor"
1162
+ stroke-width="2"
1163
+ stroke-linecap="round"
1164
+ stroke-linejoin="round"
1165
+ >
1166
+ <path d="M20 6L9 17l-5-5" />
1167
+ </svg>
1168
+ } @else {
1169
+ {{ i + 1 }}
1170
+ }
1171
+ </span>
1172
+ <span class="ui-step-label">{{ s }}</span>
1173
+ </div>
1174
+ }
1175
+ </div>`, isInline: true });
1176
+ }
1177
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspStepper, decorators: [{
1178
+ type: Component,
1179
+ args: [{
1180
+ selector: 'vsp-stepper',
1181
+ template: `<div class="ui-steps">
1182
+ @for (s of steps; track $index; let i = $index) {
1183
+ @if (i > 0) {
1184
+ <div [class]="barCls(i)"></div>
1185
+ }
1186
+ <div [class]="stepCls(i)">
1187
+ <span class="ui-step-dot">
1188
+ @if (i < current) {
1189
+ <svg
1190
+ viewBox="0 0 24 24"
1191
+ width="14"
1192
+ height="14"
1193
+ fill="none"
1194
+ stroke="currentColor"
1195
+ stroke-width="2"
1196
+ stroke-linecap="round"
1197
+ stroke-linejoin="round"
1198
+ >
1199
+ <path d="M20 6L9 17l-5-5" />
1200
+ </svg>
1201
+ } @else {
1202
+ {{ i + 1 }}
1203
+ }
1204
+ </span>
1205
+ <span class="ui-step-label">{{ s }}</span>
1206
+ </div>
1207
+ }
1208
+ </div>`,
1209
+ }]
1210
+ }], propDecorators: { steps: [{
1211
+ type: Input
1212
+ }], current: [{
1213
+ type: Input
1214
+ }] } });
1215
+
1216
+ class VspCircularProgress {
1217
+ value = 0;
1218
+ size = 76;
1219
+ thickness = 7;
1220
+ color = 'var(--accent)';
1221
+ label;
1222
+ get r() {
1223
+ return (this.size - this.thickness) / 2;
1224
+ }
1225
+ get circ() {
1226
+ return 2 * Math.PI * this.r;
1227
+ }
1228
+ get offset() {
1229
+ return this.circ * (1 - Math.min(100, this.value) / 100);
1230
+ }
1231
+ get display() {
1232
+ return this.label ?? `${Math.round(this.value)}%`;
1233
+ }
1234
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCircularProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
1235
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: VspCircularProgress, isStandalone: true, selector: "vsp-circular-progress", inputs: { value: "value", size: "size", thickness: "thickness", color: "color", label: "label" }, ngImport: i0, template: `<div style="position: relative" [style.width.px]="size" [style.height.px]="size">
1236
+ <svg [attr.width]="size" [attr.height]="size" style="transform: rotate(-90deg)">
1237
+ <circle
1238
+ [attr.cx]="size / 2"
1239
+ [attr.cy]="size / 2"
1240
+ [attr.r]="r"
1241
+ fill="none"
1242
+ stroke="var(--surface-3)"
1243
+ [attr.stroke-width]="thickness"
1244
+ />
1245
+ <circle
1246
+ [attr.cx]="size / 2"
1247
+ [attr.cy]="size / 2"
1248
+ [attr.r]="r"
1249
+ fill="none"
1250
+ [attr.stroke]="color"
1251
+ [attr.stroke-width]="thickness"
1252
+ stroke-linecap="round"
1253
+ [attr.stroke-dasharray]="circ"
1254
+ [attr.stroke-dashoffset]="offset"
1255
+ style="transition: stroke-dashoffset 0.5s cubic-bezier(0.3, 0.7, 0.3, 1)"
1256
+ />
1257
+ </svg>
1258
+ <div
1259
+ class="tnum"
1260
+ [style.fontSize.px]="size * 0.24"
1261
+ style="position: absolute; inset: 0; display: grid; place-items: center; font-weight: 800"
1262
+ >
1263
+ {{ display }}
1264
+ </div>
1265
+ </div>`, isInline: true });
1266
+ }
1267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCircularProgress, decorators: [{
1268
+ type: Component,
1269
+ args: [{
1270
+ selector: 'vsp-circular-progress',
1271
+ template: `<div style="position: relative" [style.width.px]="size" [style.height.px]="size">
1272
+ <svg [attr.width]="size" [attr.height]="size" style="transform: rotate(-90deg)">
1273
+ <circle
1274
+ [attr.cx]="size / 2"
1275
+ [attr.cy]="size / 2"
1276
+ [attr.r]="r"
1277
+ fill="none"
1278
+ stroke="var(--surface-3)"
1279
+ [attr.stroke-width]="thickness"
1280
+ />
1281
+ <circle
1282
+ [attr.cx]="size / 2"
1283
+ [attr.cy]="size / 2"
1284
+ [attr.r]="r"
1285
+ fill="none"
1286
+ [attr.stroke]="color"
1287
+ [attr.stroke-width]="thickness"
1288
+ stroke-linecap="round"
1289
+ [attr.stroke-dasharray]="circ"
1290
+ [attr.stroke-dashoffset]="offset"
1291
+ style="transition: stroke-dashoffset 0.5s cubic-bezier(0.3, 0.7, 0.3, 1)"
1292
+ />
1293
+ </svg>
1294
+ <div
1295
+ class="tnum"
1296
+ [style.fontSize.px]="size * 0.24"
1297
+ style="position: absolute; inset: 0; display: grid; place-items: center; font-weight: 800"
1298
+ >
1299
+ {{ display }}
1300
+ </div>
1301
+ </div>`,
1302
+ }]
1303
+ }], propDecorators: { value: [{
1304
+ type: Input
1305
+ }], size: [{
1306
+ type: Input
1307
+ }], thickness: [{
1308
+ type: Input
1309
+ }], color: [{
1310
+ type: Input
1311
+ }], label: [{
1312
+ type: Input
1313
+ }] } });
1314
+ class VspStat {
1315
+ label;
1316
+ value;
1317
+ delta;
1318
+ deltaDir = 'up';
1319
+ tone = 'var(--accent)';
1320
+ get deltaCls() {
1321
+ return 'badge ' + (this.deltaDir === 'up' ? 'badge-pos' : 'badge-neg');
1322
+ }
1323
+ get arrow() {
1324
+ return this.deltaDir === 'up' ? 'M12 19V5M5 12l7-7 7 7' : 'M12 5v14M5 12l7 7 7-7';
1325
+ }
1326
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspStat, deps: [], target: i0.ɵɵFactoryTarget.Component });
1327
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspStat, isStandalone: true, selector: "vsp-stat", inputs: { label: "label", value: "value", delta: "delta", deltaDir: "deltaDir", tone: "tone" }, ngImport: i0, template: `<div class="card card-pad" style="display: flex; align-items: center; gap: 13px">
1328
+ <span
1329
+ #ic
1330
+ [style.display]="ic.childElementCount ? '' : 'none'"
1331
+ [style.background]="'color-mix(in oklab, ' + tone + ' 14%, transparent)'"
1332
+ [style.color]="tone"
1333
+ style="width: 38px; height: 38px; border-radius: var(--r-sm); flex-shrink: 0; display: grid; place-items: center"
1334
+ >
1335
+ <ng-content select="[slot=icon]" />
1336
+ </span>
1337
+ <div style="min-width: 0">
1338
+ <div class="eyebrow">{{ label }}</div>
1339
+ <div style="display: flex; align-items: baseline; gap: 8px; margin-top: 3px">
1340
+ <span class="tnum" style="font-size: 22px; font-weight: 800; letter-spacing: -0.02em">{{
1341
+ value
1342
+ }}</span>
1343
+ @if (delta != null) {
1344
+ <span [class]="deltaCls" style="padding: 1px 6px">
1345
+ <svg
1346
+ viewBox="0 0 24 24"
1347
+ width="10"
1348
+ height="10"
1349
+ fill="none"
1350
+ stroke="currentColor"
1351
+ stroke-width="2"
1352
+ stroke-linecap="round"
1353
+ stroke-linejoin="round"
1354
+ >
1355
+ <path [attr.d]="arrow" />
1356
+ </svg>
1357
+ {{ delta }}
1358
+ </span>
1359
+ }
1360
+ </div>
1361
+ </div>
1362
+ </div>`, isInline: true });
1363
+ }
1364
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspStat, decorators: [{
1365
+ type: Component,
1366
+ args: [{
1367
+ selector: 'vsp-stat',
1368
+ template: `<div class="card card-pad" style="display: flex; align-items: center; gap: 13px">
1369
+ <span
1370
+ #ic
1371
+ [style.display]="ic.childElementCount ? '' : 'none'"
1372
+ [style.background]="'color-mix(in oklab, ' + tone + ' 14%, transparent)'"
1373
+ [style.color]="tone"
1374
+ style="width: 38px; height: 38px; border-radius: var(--r-sm); flex-shrink: 0; display: grid; place-items: center"
1375
+ >
1376
+ <ng-content select="[slot=icon]" />
1377
+ </span>
1378
+ <div style="min-width: 0">
1379
+ <div class="eyebrow">{{ label }}</div>
1380
+ <div style="display: flex; align-items: baseline; gap: 8px; margin-top: 3px">
1381
+ <span class="tnum" style="font-size: 22px; font-weight: 800; letter-spacing: -0.02em">{{
1382
+ value
1383
+ }}</span>
1384
+ @if (delta != null) {
1385
+ <span [class]="deltaCls" style="padding: 1px 6px">
1386
+ <svg
1387
+ viewBox="0 0 24 24"
1388
+ width="10"
1389
+ height="10"
1390
+ fill="none"
1391
+ stroke="currentColor"
1392
+ stroke-width="2"
1393
+ stroke-linecap="round"
1394
+ stroke-linejoin="round"
1395
+ >
1396
+ <path [attr.d]="arrow" />
1397
+ </svg>
1398
+ {{ delta }}
1399
+ </span>
1400
+ }
1401
+ </div>
1402
+ </div>
1403
+ </div>`,
1404
+ }]
1405
+ }], propDecorators: { label: [{
1406
+ type: Input
1407
+ }], value: [{
1408
+ type: Input
1409
+ }], delta: [{
1410
+ type: Input
1411
+ }], deltaDir: [{
1412
+ type: Input
1413
+ }], tone: [{
1414
+ type: Input
1415
+ }] } });
1416
+ const TL_TONE = {
1417
+ pos: 'var(--success)',
1418
+ neg: 'var(--danger)',
1419
+ warn: 'var(--warning)',
1420
+ info: 'var(--accent)',
1421
+ };
1422
+ class VspTimeline {
1423
+ items = [];
1424
+ dotStyle(tone) {
1425
+ if (!tone)
1426
+ return '';
1427
+ const c = TL_TONE[tone];
1428
+ return `background:color-mix(in oklab, ${c} 14%, transparent);color:${c};border-color:color-mix(in oklab, ${c} 30%, transparent)`;
1429
+ }
1430
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTimeline, deps: [], target: i0.ɵɵFactoryTarget.Component });
1431
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspTimeline, isStandalone: true, selector: "vsp-timeline", inputs: { items: "items" }, ngImport: i0, template: `<div class="ui-tl">
1432
+ @for (it of items; track $index) {
1433
+ <div class="ui-tl-item">
1434
+ <span class="ui-tl-dot" [style]="dotStyle(it.tone)">
1435
+ <svg
1436
+ viewBox="0 0 24 24"
1437
+ width="14"
1438
+ height="14"
1439
+ fill="none"
1440
+ stroke="currentColor"
1441
+ stroke-width="2"
1442
+ stroke-linecap="round"
1443
+ stroke-linejoin="round"
1444
+ >
1445
+ <circle cx="12" cy="12" r="9" />
1446
+ <path d="M12 7v5l3 2" />
1447
+ </svg>
1448
+ </span>
1449
+ <div class="ui-tl-body">
1450
+ <div style="display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap">
1451
+ <span style="font-weight: 600; font-size: 13.5px">{{ it.title }}</span>
1452
+ @if (it.time) {
1453
+ <span class="eyebrow" style="margin-left: auto">{{ it.time }}</span>
1454
+ }
1455
+ </div>
1456
+ @if (it.body) {
1457
+ <div style="font-size: 12.5px; color: var(--text-dim); margin-top: 3px">
1458
+ {{ it.body }}
1459
+ </div>
1460
+ }
1461
+ </div>
1462
+ </div>
1463
+ }
1464
+ </div>`, isInline: true });
1465
+ }
1466
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTimeline, decorators: [{
1467
+ type: Component,
1468
+ args: [{
1469
+ selector: 'vsp-timeline',
1470
+ template: `<div class="ui-tl">
1471
+ @for (it of items; track $index) {
1472
+ <div class="ui-tl-item">
1473
+ <span class="ui-tl-dot" [style]="dotStyle(it.tone)">
1474
+ <svg
1475
+ viewBox="0 0 24 24"
1476
+ width="14"
1477
+ height="14"
1478
+ fill="none"
1479
+ stroke="currentColor"
1480
+ stroke-width="2"
1481
+ stroke-linecap="round"
1482
+ stroke-linejoin="round"
1483
+ >
1484
+ <circle cx="12" cy="12" r="9" />
1485
+ <path d="M12 7v5l3 2" />
1486
+ </svg>
1487
+ </span>
1488
+ <div class="ui-tl-body">
1489
+ <div style="display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap">
1490
+ <span style="font-weight: 600; font-size: 13.5px">{{ it.title }}</span>
1491
+ @if (it.time) {
1492
+ <span class="eyebrow" style="margin-left: auto">{{ it.time }}</span>
1493
+ }
1494
+ </div>
1495
+ @if (it.body) {
1496
+ <div style="font-size: 12.5px; color: var(--text-dim); margin-top: 3px">
1497
+ {{ it.body }}
1498
+ </div>
1499
+ }
1500
+ </div>
1501
+ </div>
1502
+ }
1503
+ </div>`,
1504
+ }]
1505
+ }], propDecorators: { items: [{
1506
+ type: Input
1507
+ }] } });
1508
+ class VspDescriptionList {
1509
+ items = [];
1510
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspDescriptionList, deps: [], target: i0.ɵɵFactoryTarget.Component });
1511
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspDescriptionList, isStandalone: true, selector: "vsp-description-list", inputs: { items: "items" }, ngImport: i0, template: `<dl class="ui-dl">
1512
+ @for (item of items; track $index; let last = $last) {
1513
+ <dt [class.last]="last">{{ item[0] }}</dt>
1514
+ <dd [class.last]="last">{{ item[1] }}</dd>
1515
+ }
1516
+ </dl>`, isInline: true });
1517
+ }
1518
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspDescriptionList, decorators: [{
1519
+ type: Component,
1520
+ args: [{
1521
+ selector: 'vsp-description-list',
1522
+ template: `<dl class="ui-dl">
1523
+ @for (item of items; track $index; let last = $last) {
1524
+ <dt [class.last]="last">{{ item[0] }}</dt>
1525
+ <dd [class.last]="last">{{ item[1] }}</dd>
1526
+ }
1527
+ </dl>`,
1528
+ }]
1529
+ }], propDecorators: { items: [{
1530
+ type: Input
1531
+ }] } });
1532
+
1533
+ const BANNER_ICON = {
1534
+ info: 'M12 3l1.6 5L19 9.6l-5 1.6L12 16l-1.6-4.8L5 9.6l5.4-1.6z',
1535
+ warn: 'M18 8a6 6 0 00-12 0c0 7-3 9-3 9h18s-3-2-3-9',
1536
+ accent: 'M13 2L3 14h9l-1 8 10-12h-9l1-8z',
1537
+ };
1538
+ class VspBanner {
1539
+ tone = 'info';
1540
+ dismissible = false;
1541
+ dismiss = new EventEmitter();
1542
+ get cls() {
1543
+ return 'ui-banner ' + this.tone;
1544
+ }
1545
+ get iconPath() {
1546
+ return BANNER_ICON[this.tone];
1547
+ }
1548
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBanner, deps: [], target: i0.ɵɵFactoryTarget.Component });
1549
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspBanner, isStandalone: true, selector: "vsp-banner", inputs: { tone: "tone", dismissible: "dismissible" }, outputs: { dismiss: "dismiss" }, ngImport: i0, template: `<div [class]="cls">
1550
+ <span #ic style="display: contents"><ng-content select="[slot=icon]" /></span>
1551
+ @if (!ic.childElementCount) {
1552
+ <svg
1553
+ viewBox="0 0 24 24"
1554
+ width="18"
1555
+ height="18"
1556
+ fill="none"
1557
+ stroke="currentColor"
1558
+ stroke-width="2"
1559
+ stroke-linecap="round"
1560
+ stroke-linejoin="round"
1561
+ >
1562
+ <path [attr.d]="iconPath" />
1563
+ </svg>
1564
+ }
1565
+ <div style="flex: 1; font-size: 13px; font-weight: 500"><ng-content /></div>
1566
+ <ng-content select="[slot=action]" />
1567
+ @if (dismissible) {
1568
+ <button type="button" class="ui-banner-x" aria-label="Dismiss" (click)="dismiss.emit()">
1569
+ <svg
1570
+ viewBox="0 0 24 24"
1571
+ width="15"
1572
+ height="15"
1573
+ fill="none"
1574
+ stroke="currentColor"
1575
+ stroke-width="2"
1576
+ stroke-linecap="round"
1577
+ stroke-linejoin="round"
1578
+ >
1579
+ <path d="M18 6L6 18M6 6l12 12" />
1580
+ </svg>
1581
+ </button>
1582
+ }
1583
+ </div>`, isInline: true });
1584
+ }
1585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBanner, decorators: [{
1586
+ type: Component,
1587
+ args: [{
1588
+ selector: 'vsp-banner',
1589
+ template: `<div [class]="cls">
1590
+ <span #ic style="display: contents"><ng-content select="[slot=icon]" /></span>
1591
+ @if (!ic.childElementCount) {
1592
+ <svg
1593
+ viewBox="0 0 24 24"
1594
+ width="18"
1595
+ height="18"
1596
+ fill="none"
1597
+ stroke="currentColor"
1598
+ stroke-width="2"
1599
+ stroke-linecap="round"
1600
+ stroke-linejoin="round"
1601
+ >
1602
+ <path [attr.d]="iconPath" />
1603
+ </svg>
1604
+ }
1605
+ <div style="flex: 1; font-size: 13px; font-weight: 500"><ng-content /></div>
1606
+ <ng-content select="[slot=action]" />
1607
+ @if (dismissible) {
1608
+ <button type="button" class="ui-banner-x" aria-label="Dismiss" (click)="dismiss.emit()">
1609
+ <svg
1610
+ viewBox="0 0 24 24"
1611
+ width="15"
1612
+ height="15"
1613
+ fill="none"
1614
+ stroke="currentColor"
1615
+ stroke-width="2"
1616
+ stroke-linecap="round"
1617
+ stroke-linejoin="round"
1618
+ >
1619
+ <path d="M18 6L6 18M6 6l12 12" />
1620
+ </svg>
1621
+ </button>
1622
+ }
1623
+ </div>`,
1624
+ }]
1625
+ }], propDecorators: { tone: [{
1626
+ type: Input
1627
+ }], dismissible: [{
1628
+ type: Input
1629
+ }], dismiss: [{
1630
+ type: Output
1631
+ }] } });
1632
+ class VspEmptyState {
1633
+ title;
1634
+ desc;
1635
+ compact = false;
1636
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspEmptyState, deps: [], target: i0.ɵɵFactoryTarget.Component });
1637
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspEmptyState, isStandalone: true, selector: "vsp-empty-state", inputs: { title: "title", desc: "desc", compact: "compact" }, ngImport: i0, template: `<div
1638
+ style="display: grid; place-items: center; text-align: center"
1639
+ [style.padding]="compact ? '32px 20px' : '56px 24px'"
1640
+ >
1641
+ <div style="max-width: 340px">
1642
+ <span
1643
+ style="width: 56px; height: 56px; border-radius: 16px; display: grid; place-items: center; margin: 0 auto 18px; background: color-mix(in oklab, var(--accent) 12%, transparent); color: var(--accent); border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent)"
1644
+ >
1645
+ <span #ic style="display: contents"><ng-content select="[slot=icon]" /></span>
1646
+ @if (!ic.childElementCount) {
1647
+ <svg
1648
+ viewBox="0 0 24 24"
1649
+ width="26"
1650
+ height="26"
1651
+ fill="none"
1652
+ stroke="currentColor"
1653
+ stroke-width="2"
1654
+ stroke-linecap="round"
1655
+ stroke-linejoin="round"
1656
+ >
1657
+ <path
1658
+ d="M22 12h-6l-2 3h-4l-2-3H2M5.45 5.11L2 12v6a2 2 0 002 2h16a2 2 0 002-2v-6l-3.45-6.89A2 2 0 0016.76 4H7.24a2 2 0 00-1.79 1.11z"
1659
+ />
1660
+ </svg>
1661
+ }
1662
+ </span>
1663
+ <div style="font-size: 17px; font-weight: 700">{{ title }}</div>
1664
+ @if (desc) {
1665
+ <p style="margin: 7px 0 0; color: var(--text-dim); font-size: 13.5px; line-height: 1.6">
1666
+ {{ desc }}
1667
+ </p>
1668
+ }
1669
+ <div
1670
+ #ac
1671
+ [style.display]="ac.childElementCount ? 'flex' : 'none'"
1672
+ style="margin-top: 20px; gap: 8px; justify-content: center"
1673
+ >
1674
+ <ng-content select="[slot=action]" />
1675
+ </div>
1676
+ </div>
1677
+ </div>`, isInline: true });
1678
+ }
1679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspEmptyState, decorators: [{
1680
+ type: Component,
1681
+ args: [{
1682
+ selector: 'vsp-empty-state',
1683
+ template: `<div
1684
+ style="display: grid; place-items: center; text-align: center"
1685
+ [style.padding]="compact ? '32px 20px' : '56px 24px'"
1686
+ >
1687
+ <div style="max-width: 340px">
1688
+ <span
1689
+ style="width: 56px; height: 56px; border-radius: 16px; display: grid; place-items: center; margin: 0 auto 18px; background: color-mix(in oklab, var(--accent) 12%, transparent); color: var(--accent); border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent)"
1690
+ >
1691
+ <span #ic style="display: contents"><ng-content select="[slot=icon]" /></span>
1692
+ @if (!ic.childElementCount) {
1693
+ <svg
1694
+ viewBox="0 0 24 24"
1695
+ width="26"
1696
+ height="26"
1697
+ fill="none"
1698
+ stroke="currentColor"
1699
+ stroke-width="2"
1700
+ stroke-linecap="round"
1701
+ stroke-linejoin="round"
1702
+ >
1703
+ <path
1704
+ d="M22 12h-6l-2 3h-4l-2-3H2M5.45 5.11L2 12v6a2 2 0 002 2h16a2 2 0 002-2v-6l-3.45-6.89A2 2 0 0016.76 4H7.24a2 2 0 00-1.79 1.11z"
1705
+ />
1706
+ </svg>
1707
+ }
1708
+ </span>
1709
+ <div style="font-size: 17px; font-weight: 700">{{ title }}</div>
1710
+ @if (desc) {
1711
+ <p style="margin: 7px 0 0; color: var(--text-dim); font-size: 13.5px; line-height: 1.6">
1712
+ {{ desc }}
1713
+ </p>
1714
+ }
1715
+ <div
1716
+ #ac
1717
+ [style.display]="ac.childElementCount ? 'flex' : 'none'"
1718
+ style="margin-top: 20px; gap: 8px; justify-content: center"
1719
+ >
1720
+ <ng-content select="[slot=action]" />
1721
+ </div>
1722
+ </div>
1723
+ </div>`,
1724
+ }]
1725
+ }], propDecorators: { title: [{
1726
+ type: Input
1727
+ }], desc: [{
1728
+ type: Input
1729
+ }], compact: [{
1730
+ type: Input
1731
+ }] } });
1732
+ class VspAccordion {
1733
+ items = [];
1734
+ multiple = false;
1735
+ defaultOpen = [];
1736
+ open = new Set();
1737
+ ngOnInit() {
1738
+ this.open = new Set(this.defaultOpen);
1739
+ }
1740
+ toggle(i) {
1741
+ const n = new Set(this.multiple ? this.open : []);
1742
+ if (this.open.has(i))
1743
+ n.delete(i);
1744
+ else
1745
+ n.add(i);
1746
+ this.open = n;
1747
+ }
1748
+ itemCls(i) {
1749
+ return 'ui-acc-item' + (this.open.has(i) ? ' open' : '');
1750
+ }
1751
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component });
1752
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspAccordion, isStandalone: true, selector: "vsp-accordion", inputs: { items: "items", multiple: "multiple", defaultOpen: "defaultOpen" }, ngImport: i0, template: `<div class="ui-acc">
1753
+ @for (it of items; track $index; let i = $index) {
1754
+ <div [class]="itemCls(i)">
1755
+ <button type="button" class="ui-acc-head" (click)="toggle(i)">
1756
+ {{ it.title }}
1757
+ <svg
1758
+ class="chev"
1759
+ viewBox="0 0 24 24"
1760
+ width="17"
1761
+ height="17"
1762
+ fill="none"
1763
+ stroke="currentColor"
1764
+ stroke-width="2"
1765
+ stroke-linecap="round"
1766
+ stroke-linejoin="round"
1767
+ >
1768
+ <path d="M9 18l6-6-6-6" />
1769
+ </svg>
1770
+ </button>
1771
+ <div class="ui-acc-bodywrap">
1772
+ <div>
1773
+ <div class="ui-acc-body">{{ it.body }}</div>
1774
+ </div>
1775
+ </div>
1776
+ </div>
1777
+ }
1778
+ </div>`, isInline: true });
1779
+ }
1780
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAccordion, decorators: [{
1781
+ type: Component,
1782
+ args: [{
1783
+ selector: 'vsp-accordion',
1784
+ template: `<div class="ui-acc">
1785
+ @for (it of items; track $index; let i = $index) {
1786
+ <div [class]="itemCls(i)">
1787
+ <button type="button" class="ui-acc-head" (click)="toggle(i)">
1788
+ {{ it.title }}
1789
+ <svg
1790
+ class="chev"
1791
+ viewBox="0 0 24 24"
1792
+ width="17"
1793
+ height="17"
1794
+ fill="none"
1795
+ stroke="currentColor"
1796
+ stroke-width="2"
1797
+ stroke-linecap="round"
1798
+ stroke-linejoin="round"
1799
+ >
1800
+ <path d="M9 18l6-6-6-6" />
1801
+ </svg>
1802
+ </button>
1803
+ <div class="ui-acc-bodywrap">
1804
+ <div>
1805
+ <div class="ui-acc-body">{{ it.body }}</div>
1806
+ </div>
1807
+ </div>
1808
+ </div>
1809
+ }
1810
+ </div>`,
1811
+ }]
1812
+ }], propDecorators: { items: [{
1813
+ type: Input
1814
+ }], multiple: [{
1815
+ type: Input
1816
+ }], defaultOpen: [{
1817
+ type: Input
1818
+ }] } });
1819
+
1820
+ /**
1821
+ * Generated bundle index. Do not edit.
1822
+ */
1823
+
1824
+ export { VspAccordion, VspAlert, VspAvatar, VspAvatarGroup, VspBadge, VspBanner, VspBreadcrumb, VspButton, VspCard, VspCardHead, VspCheckbox, VspCircularProgress, VspDescriptionList, VspDivider, VspEmptyState, VspField, VspIconButton, VspInput, VspKbd, VspNativeSelect, VspPagination, VspProgress, VspRadio, VspRadioGroup, VspSegmented, VspSkeleton, VspSlider, VspSpinner, VspStat, VspStepper, VspSwitch, VspTabs, VspTag, VspTextarea, VspTimeline };
1825
+ //# sourceMappingURL=vespera-ui-angular.mjs.map