@vespera-ui/angular 0.3.0 → 0.7.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.
@@ -1,5 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Input, Component, EventEmitter, Output } from '@angular/core';
2
+ import { Input, Component, EventEmitter, Output, ViewChildren } from '@angular/core';
3
+ import { NgTemplateOutlet } from '@angular/common';
3
4
 
4
5
  class VspButton {
5
6
  variant = 'ghost';
@@ -1817,7 +1818,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1817
1818
  type: Input
1818
1819
  }] } });
1819
1820
 
1820
- function smoothPath(pts) {
1821
+ function smoothPath$1(pts) {
1821
1822
  if (pts.length < 2)
1822
1823
  return '';
1823
1824
  let d = `M ${pts[0][0]} ${pts[0][1]}`;
@@ -1847,7 +1848,7 @@ class VspSparkline {
1847
1848
  ]);
1848
1849
  }
1849
1850
  get d() {
1850
- return smoothPath(this.pts);
1851
+ return smoothPath$1(this.pts);
1851
1852
  }
1852
1853
  get areaD() {
1853
1854
  return `${this.d} L ${this.w} ${this.h} L 0 ${this.h} Z`;
@@ -2146,9 +2147,908 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2146
2147
  type: Input
2147
2148
  }] } });
2148
2149
 
2150
+ class VspNumberStepper {
2151
+ value = 0;
2152
+ valueChange = new EventEmitter();
2153
+ min;
2154
+ max;
2155
+ step = 1;
2156
+ unit;
2157
+ set(v) {
2158
+ let n = v;
2159
+ if (this.min != null && n < this.min)
2160
+ n = this.min;
2161
+ if (this.max != null && n > this.max)
2162
+ n = this.max;
2163
+ this.value = n;
2164
+ this.valueChange.emit(n);
2165
+ }
2166
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspNumberStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
2167
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspNumberStepper, isStandalone: true, selector: "vsp-number-stepper", inputs: { value: "value", min: "min", max: "max", step: "step", unit: "unit" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `<div class="ui-stepper">
2168
+ <button
2169
+ type="button"
2170
+ aria-label="Decrease"
2171
+ [disabled]="min != null && value <= min"
2172
+ (click)="set(value - step)"
2173
+ >
2174
+
2175
+ </button>
2176
+ <span class="val"
2177
+ >{{ value }}
2178
+ @if (unit) {
2179
+ <i>{{ unit }}</i>
2180
+ }
2181
+ </span>
2182
+ <button
2183
+ type="button"
2184
+ aria-label="Increase"
2185
+ [disabled]="max != null && value >= max"
2186
+ (click)="set(value + step)"
2187
+ >
2188
+ +
2189
+ </button>
2190
+ </div>`, isInline: true });
2191
+ }
2192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspNumberStepper, decorators: [{
2193
+ type: Component,
2194
+ args: [{
2195
+ selector: 'vsp-number-stepper',
2196
+ template: `<div class="ui-stepper">
2197
+ <button
2198
+ type="button"
2199
+ aria-label="Decrease"
2200
+ [disabled]="min != null && value <= min"
2201
+ (click)="set(value - step)"
2202
+ >
2203
+
2204
+ </button>
2205
+ <span class="val"
2206
+ >{{ value }}
2207
+ @if (unit) {
2208
+ <i>{{ unit }}</i>
2209
+ }
2210
+ </span>
2211
+ <button
2212
+ type="button"
2213
+ aria-label="Increase"
2214
+ [disabled]="max != null && value >= max"
2215
+ (click)="set(value + step)"
2216
+ >
2217
+ +
2218
+ </button>
2219
+ </div>`,
2220
+ }]
2221
+ }], propDecorators: { value: [{
2222
+ type: Input
2223
+ }], valueChange: [{
2224
+ type: Output
2225
+ }], min: [{
2226
+ type: Input
2227
+ }], max: [{
2228
+ type: Input
2229
+ }], step: [{
2230
+ type: Input
2231
+ }], unit: [{
2232
+ type: Input
2233
+ }] } });
2234
+ class VspCopyButton {
2235
+ text = '';
2236
+ label = 'Copy';
2237
+ size = 'sm';
2238
+ done = false;
2239
+ get cls() {
2240
+ return 'btn btn-ghost' + (this.size === 'sm' ? ' btn-sm' : '');
2241
+ }
2242
+ async copy() {
2243
+ try {
2244
+ await navigator.clipboard?.writeText(this.text);
2245
+ }
2246
+ catch {
2247
+ /* clipboard unavailable */
2248
+ }
2249
+ this.done = true;
2250
+ setTimeout(() => (this.done = false), 1400);
2251
+ }
2252
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCopyButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
2253
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspCopyButton, isStandalone: true, selector: "vsp-copy-button", inputs: { text: "text", label: "label", size: "size" }, ngImport: i0, template: `<button type="button" [class]="cls" (click)="copy()">
2254
+ @if (done) {
2255
+ <span style="color: var(--success); display: inline-flex">
2256
+ <svg
2257
+ viewBox="0 0 24 24"
2258
+ width="15"
2259
+ height="15"
2260
+ fill="none"
2261
+ stroke="currentColor"
2262
+ stroke-width="2"
2263
+ stroke-linecap="round"
2264
+ stroke-linejoin="round"
2265
+ >
2266
+ <path d="M20 6L9 17l-5-5" />
2267
+ </svg> </span
2268
+ >Copied
2269
+ } @else {
2270
+ <svg
2271
+ viewBox="0 0 24 24"
2272
+ width="15"
2273
+ height="15"
2274
+ fill="none"
2275
+ stroke="currentColor"
2276
+ stroke-width="2"
2277
+ stroke-linecap="round"
2278
+ stroke-linejoin="round"
2279
+ >
2280
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8zM14 2v6h6" />
2281
+ </svg>
2282
+ {{ label }}
2283
+ }
2284
+ </button>`, isInline: true });
2285
+ }
2286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspCopyButton, decorators: [{
2287
+ type: Component,
2288
+ args: [{
2289
+ selector: 'vsp-copy-button',
2290
+ template: `<button type="button" [class]="cls" (click)="copy()">
2291
+ @if (done) {
2292
+ <span style="color: var(--success); display: inline-flex">
2293
+ <svg
2294
+ viewBox="0 0 24 24"
2295
+ width="15"
2296
+ height="15"
2297
+ fill="none"
2298
+ stroke="currentColor"
2299
+ stroke-width="2"
2300
+ stroke-linecap="round"
2301
+ stroke-linejoin="round"
2302
+ >
2303
+ <path d="M20 6L9 17l-5-5" />
2304
+ </svg> </span
2305
+ >Copied
2306
+ } @else {
2307
+ <svg
2308
+ viewBox="0 0 24 24"
2309
+ width="15"
2310
+ height="15"
2311
+ fill="none"
2312
+ stroke="currentColor"
2313
+ stroke-width="2"
2314
+ stroke-linecap="round"
2315
+ stroke-linejoin="round"
2316
+ >
2317
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8zM14 2v6h6" />
2318
+ </svg>
2319
+ {{ label }}
2320
+ }
2321
+ </button>`,
2322
+ }]
2323
+ }], propDecorators: { text: [{
2324
+ type: Input
2325
+ }], label: [{
2326
+ type: Input
2327
+ }], size: [{
2328
+ type: Input
2329
+ }] } });
2330
+ class VspInlineEdit {
2331
+ value = '';
2332
+ placeholder = 'Empty';
2333
+ save = new EventEmitter();
2334
+ editing = false;
2335
+ draft = '';
2336
+ start() {
2337
+ this.draft = this.value;
2338
+ this.editing = true;
2339
+ }
2340
+ commit() {
2341
+ this.editing = false;
2342
+ if (this.draft !== this.value)
2343
+ this.save.emit(this.draft);
2344
+ }
2345
+ cancel() {
2346
+ this.draft = this.value;
2347
+ this.editing = false;
2348
+ }
2349
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspInlineEdit, deps: [], target: i0.ɵɵFactoryTarget.Component });
2350
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspInlineEdit, isStandalone: true, selector: "vsp-inline-edit", inputs: { value: "value", placeholder: "placeholder" }, outputs: { save: "save" }, ngImport: i0, template: `@if (editing) {
2351
+ <input
2352
+ #inp
2353
+ autofocus
2354
+ class="ui-input"
2355
+ [value]="draft"
2356
+ style="height: 32px; max-width: 240px"
2357
+ (input)="draft = inp.value"
2358
+ (blur)="commit()"
2359
+ (keydown.enter)="commit()"
2360
+ (keydown.escape)="cancel()"
2361
+ />
2362
+ } @else {
2363
+ <span
2364
+ class="ui-inline"
2365
+ role="button"
2366
+ tabindex="0"
2367
+ (click)="start()"
2368
+ (keydown.enter)="start()"
2369
+ >
2370
+ <span [style.color]="value ? 'var(--text)' : 'var(--text-faint)'">{{
2371
+ value || placeholder
2372
+ }}</span>
2373
+ <span class="pen" style="display: inline-flex">
2374
+ <svg
2375
+ viewBox="0 0 24 24"
2376
+ width="14"
2377
+ height="14"
2378
+ fill="none"
2379
+ stroke="currentColor"
2380
+ stroke-width="2"
2381
+ stroke-linecap="round"
2382
+ stroke-linejoin="round"
2383
+ >
2384
+ <path d="M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4z" />
2385
+ </svg>
2386
+ </span>
2387
+ </span>
2388
+ }`, isInline: true });
2389
+ }
2390
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspInlineEdit, decorators: [{
2391
+ type: Component,
2392
+ args: [{
2393
+ selector: 'vsp-inline-edit',
2394
+ template: `@if (editing) {
2395
+ <input
2396
+ #inp
2397
+ autofocus
2398
+ class="ui-input"
2399
+ [value]="draft"
2400
+ style="height: 32px; max-width: 240px"
2401
+ (input)="draft = inp.value"
2402
+ (blur)="commit()"
2403
+ (keydown.enter)="commit()"
2404
+ (keydown.escape)="cancel()"
2405
+ />
2406
+ } @else {
2407
+ <span
2408
+ class="ui-inline"
2409
+ role="button"
2410
+ tabindex="0"
2411
+ (click)="start()"
2412
+ (keydown.enter)="start()"
2413
+ >
2414
+ <span [style.color]="value ? 'var(--text)' : 'var(--text-faint)'">{{
2415
+ value || placeholder
2416
+ }}</span>
2417
+ <span class="pen" style="display: inline-flex">
2418
+ <svg
2419
+ viewBox="0 0 24 24"
2420
+ width="14"
2421
+ height="14"
2422
+ fill="none"
2423
+ stroke="currentColor"
2424
+ stroke-width="2"
2425
+ stroke-linecap="round"
2426
+ stroke-linejoin="round"
2427
+ >
2428
+ <path d="M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4z" />
2429
+ </svg>
2430
+ </span>
2431
+ </span>
2432
+ }`,
2433
+ }]
2434
+ }], propDecorators: { value: [{
2435
+ type: Input
2436
+ }], placeholder: [{
2437
+ type: Input
2438
+ }], save: [{
2439
+ type: Output
2440
+ }] } });
2441
+
2442
+ class VspTree {
2443
+ data = [];
2444
+ defaultExpanded = [];
2445
+ expanded = new Set();
2446
+ selected = null;
2447
+ ngOnInit() {
2448
+ this.expanded = new Set(this.defaultExpanded);
2449
+ }
2450
+ id(n) {
2451
+ return n.id ?? n.label;
2452
+ }
2453
+ hasKids(n) {
2454
+ return (n.children ?? []).length > 0;
2455
+ }
2456
+ rowCls(n) {
2457
+ const i = this.id(n);
2458
+ return ('ui-tree-row' + (this.expanded.has(i) ? ' open' : '') + (this.selected === i ? ' sel' : ''));
2459
+ }
2460
+ activate(n) {
2461
+ const i = this.id(n);
2462
+ if (this.hasKids(n)) {
2463
+ const next = new Set(this.expanded);
2464
+ if (next.has(i))
2465
+ next.delete(i);
2466
+ else
2467
+ next.add(i);
2468
+ this.expanded = next;
2469
+ }
2470
+ this.selected = i;
2471
+ }
2472
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTree, deps: [], target: i0.ɵɵFactoryTarget.Component });
2473
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspTree, isStandalone: true, selector: "vsp-tree", inputs: { data: "data", defaultExpanded: "defaultExpanded" }, ngImport: i0, template: `<div class="ui-tree">
2474
+ @for (n of data; track $index) {
2475
+ <ng-container *ngTemplateOutlet="nodeTpl; context: { $implicit: n }" />
2476
+ }
2477
+ </div>
2478
+
2479
+ <ng-template #nodeTpl let-n>
2480
+ <div>
2481
+ <div
2482
+ [class]="rowCls(n)"
2483
+ role="button"
2484
+ tabindex="0"
2485
+ (click)="activate(n)"
2486
+ (keydown.enter)="activate(n)"
2487
+ >
2488
+ @if (hasKids(n)) {
2489
+ <svg
2490
+ class="tw-chev"
2491
+ viewBox="0 0 24 24"
2492
+ width="16"
2493
+ height="16"
2494
+ fill="none"
2495
+ stroke="currentColor"
2496
+ stroke-width="2"
2497
+ stroke-linecap="round"
2498
+ stroke-linejoin="round"
2499
+ >
2500
+ <path d="M9 18l6-6-6-6" />
2501
+ </svg>
2502
+ } @else {
2503
+ <span style="width: 16px; flex-shrink: 0"></span>
2504
+ }
2505
+ <svg
2506
+ class="tw-icon"
2507
+ viewBox="0 0 24 24"
2508
+ width="16"
2509
+ height="16"
2510
+ fill="none"
2511
+ stroke="currentColor"
2512
+ stroke-width="2"
2513
+ stroke-linecap="round"
2514
+ stroke-linejoin="round"
2515
+ >
2516
+ @if (hasKids(n)) {
2517
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
2518
+ } @else {
2519
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8zM14 2v6h6" />
2520
+ }
2521
+ </svg>
2522
+ <span
2523
+ style="flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
2524
+ >{{ n.label }}</span
2525
+ >
2526
+ @if (n.badge != null) {
2527
+ <span class="mono" style="font-size: 11px; color: var(--text-faint)">{{
2528
+ n.badge
2529
+ }}</span>
2530
+ }
2531
+ </div>
2532
+ @if (hasKids(n) && expanded.has(id(n))) {
2533
+ <div class="ui-tree-children">
2534
+ @for (c of n.children; track $index) {
2535
+ <ng-container *ngTemplateOutlet="nodeTpl; context: { $implicit: c }" />
2536
+ }
2537
+ </div>
2538
+ }
2539
+ </div>
2540
+ </ng-template>`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
2541
+ }
2542
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspTree, decorators: [{
2543
+ type: Component,
2544
+ args: [{
2545
+ selector: 'vsp-tree',
2546
+ imports: [NgTemplateOutlet],
2547
+ template: `<div class="ui-tree">
2548
+ @for (n of data; track $index) {
2549
+ <ng-container *ngTemplateOutlet="nodeTpl; context: { $implicit: n }" />
2550
+ }
2551
+ </div>
2552
+
2553
+ <ng-template #nodeTpl let-n>
2554
+ <div>
2555
+ <div
2556
+ [class]="rowCls(n)"
2557
+ role="button"
2558
+ tabindex="0"
2559
+ (click)="activate(n)"
2560
+ (keydown.enter)="activate(n)"
2561
+ >
2562
+ @if (hasKids(n)) {
2563
+ <svg
2564
+ class="tw-chev"
2565
+ viewBox="0 0 24 24"
2566
+ width="16"
2567
+ height="16"
2568
+ fill="none"
2569
+ stroke="currentColor"
2570
+ stroke-width="2"
2571
+ stroke-linecap="round"
2572
+ stroke-linejoin="round"
2573
+ >
2574
+ <path d="M9 18l6-6-6-6" />
2575
+ </svg>
2576
+ } @else {
2577
+ <span style="width: 16px; flex-shrink: 0"></span>
2578
+ }
2579
+ <svg
2580
+ class="tw-icon"
2581
+ viewBox="0 0 24 24"
2582
+ width="16"
2583
+ height="16"
2584
+ fill="none"
2585
+ stroke="currentColor"
2586
+ stroke-width="2"
2587
+ stroke-linecap="round"
2588
+ stroke-linejoin="round"
2589
+ >
2590
+ @if (hasKids(n)) {
2591
+ <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
2592
+ } @else {
2593
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8zM14 2v6h6" />
2594
+ }
2595
+ </svg>
2596
+ <span
2597
+ style="flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap"
2598
+ >{{ n.label }}</span
2599
+ >
2600
+ @if (n.badge != null) {
2601
+ <span class="mono" style="font-size: 11px; color: var(--text-faint)">{{
2602
+ n.badge
2603
+ }}</span>
2604
+ }
2605
+ </div>
2606
+ @if (hasKids(n) && expanded.has(id(n))) {
2607
+ <div class="ui-tree-children">
2608
+ @for (c of n.children; track $index) {
2609
+ <ng-container *ngTemplateOutlet="nodeTpl; context: { $implicit: c }" />
2610
+ }
2611
+ </div>
2612
+ }
2613
+ </div>
2614
+ </ng-template>`,
2615
+ }]
2616
+ }], propDecorators: { data: [{
2617
+ type: Input
2618
+ }], defaultExpanded: [{
2619
+ type: Input
2620
+ }] } });
2621
+
2622
+ class VspOTPInput {
2623
+ length = 6;
2624
+ value = '';
2625
+ valueChange = new EventEmitter();
2626
+ inputs;
2627
+ get indices() {
2628
+ return Array.from({ length: this.length }, (_, i) => i);
2629
+ }
2630
+ set(i, raw) {
2631
+ const clean = raw.replace(/\D/g, '');
2632
+ const chars = Array.from({ length: this.length }, (_, k) => this.value[k] ?? '');
2633
+ chars[i] = clean.slice(-1);
2634
+ this.value = chars.join('');
2635
+ this.valueChange.emit(this.value);
2636
+ if (clean && i < this.length - 1)
2637
+ this.inputs.get(i + 1)?.nativeElement.focus();
2638
+ }
2639
+ onKey(i, e) {
2640
+ if (e.key === 'Backspace' && !this.value[i] && i > 0)
2641
+ this.inputs.get(i - 1)?.nativeElement.focus();
2642
+ }
2643
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspOTPInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
2644
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspOTPInput, isStandalone: true, selector: "vsp-otp-input", inputs: { length: "length", value: "value" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "inputs", predicate: ["otp"], descendants: true }], ngImport: i0, template: `<div class="ui-otp">
2645
+ @for (i of indices; track i) {
2646
+ <input
2647
+ #otp
2648
+ inputmode="numeric"
2649
+ maxlength="1"
2650
+ [value]="value[i] ?? ''"
2651
+ (input)="set(i, otp.value)"
2652
+ (keydown)="onKey(i, $event)"
2653
+ />
2654
+ }
2655
+ </div>`, isInline: true });
2656
+ }
2657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspOTPInput, decorators: [{
2658
+ type: Component,
2659
+ args: [{
2660
+ selector: 'vsp-otp-input',
2661
+ template: `<div class="ui-otp">
2662
+ @for (i of indices; track i) {
2663
+ <input
2664
+ #otp
2665
+ inputmode="numeric"
2666
+ maxlength="1"
2667
+ [value]="value[i] ?? ''"
2668
+ (input)="set(i, otp.value)"
2669
+ (keydown)="onKey(i, $event)"
2670
+ />
2671
+ }
2672
+ </div>`,
2673
+ }]
2674
+ }], propDecorators: { length: [{
2675
+ type: Input
2676
+ }], value: [{
2677
+ type: Input
2678
+ }], valueChange: [{
2679
+ type: Output
2680
+ }], inputs: [{
2681
+ type: ViewChildren,
2682
+ args: ['otp']
2683
+ }] } });
2684
+
2685
+ function smoothPath(pts) {
2686
+ if (pts.length < 2)
2687
+ return '';
2688
+ let d = `M ${pts[0][0]} ${pts[0][1]}`;
2689
+ for (let i = 0; i < pts.length - 1; i++) {
2690
+ const [x0, y0] = pts[i];
2691
+ const [x1, y1] = pts[i + 1];
2692
+ const cx = (x0 + x1) / 2;
2693
+ d += ` C ${cx} ${y0} ${cx} ${y1} ${x1} ${y1}`;
2694
+ }
2695
+ return d;
2696
+ }
2697
+ function niceNum(n) {
2698
+ if (Math.abs(n) >= 1e6)
2699
+ return (n / 1e6).toFixed(n % 1e6 === 0 ? 0 : 1) + 'M';
2700
+ if (Math.abs(n) >= 1e3)
2701
+ return (n / 1e3).toFixed(n % 1e3 === 0 ? 0 : 1) + 'k';
2702
+ return String(n);
2703
+ }
2704
+ let acUid = 0;
2705
+ class VspAreaChart {
2706
+ series = [];
2707
+ labels;
2708
+ width = 760;
2709
+ height = 260;
2710
+ color = 'var(--accent)';
2711
+ color2 = 'var(--accent-2)';
2712
+ dual = false;
2713
+ gid = 'ac' + ++acUid;
2714
+ padL = 38;
2715
+ padB = 26;
2716
+ padT = 12;
2717
+ padR = 8;
2718
+ get innerW() {
2719
+ return Math.max(10, this.width - this.padL - this.padR);
2720
+ }
2721
+ get innerH() {
2722
+ return this.height - this.padB - this.padT;
2723
+ }
2724
+ get s0() {
2725
+ return this.series[0] ?? [];
2726
+ }
2727
+ get s1() {
2728
+ return this.series[1];
2729
+ }
2730
+ get max() {
2731
+ return Math.max(...(this.dual && this.s1 ? [...this.s0, ...this.s1] : this.s0), 0) * 1.12;
2732
+ }
2733
+ get rng() {
2734
+ return this.max || 1;
2735
+ }
2736
+ sx(i, len) {
2737
+ return this.padL + (i / Math.max(1, len - 1)) * this.innerW;
2738
+ }
2739
+ sy(v) {
2740
+ return this.padT + this.innerH - (v / this.rng) * this.innerH;
2741
+ }
2742
+ showLabel(i) {
2743
+ return !!this.labels && i % Math.ceil(this.labels.length / 7) === 0;
2744
+ }
2745
+ get ticks() {
2746
+ return Array.from({ length: 5 }, (_, i) => ({
2747
+ y: this.sy((this.max / 4) * i),
2748
+ label: niceNum(Math.round((this.max / 4) * i)),
2749
+ }));
2750
+ }
2751
+ get lineEls() {
2752
+ const sets = this.dual && this.s1 ? [this.s0, this.s1] : [this.s0];
2753
+ return sets.map((arr, li) => {
2754
+ const pts = arr.map((v, i) => [this.sx(i, arr.length), this.sy(v)]);
2755
+ const last = pts[pts.length - 1];
2756
+ const first = pts[0];
2757
+ return {
2758
+ d: smoothPath(pts),
2759
+ area: li === 0 && first && last
2760
+ ? `${smoothPath(pts)} L ${last[0]} ${this.padT + this.innerH} L ${first[0]} ${this.padT + this.innerH} Z`
2761
+ : null,
2762
+ stroke: li === 0 ? this.color : this.color2,
2763
+ dash: li === 1 ? '5 5' : null,
2764
+ opacity: li === 1 ? 0.7 : 1,
2765
+ };
2766
+ });
2767
+ }
2768
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAreaChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
2769
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspAreaChart, isStandalone: true, selector: "vsp-area-chart", inputs: { series: "series", labels: "labels", width: "width", height: "height", color: "color", color2: "color2", dual: "dual" }, ngImport: i0, template: `<svg [attr.width]="width" [attr.height]="height" style="display: block">
2770
+ <defs>
2771
+ <linearGradient [id]="gid" x1="0" x2="0" y1="0" y2="1">
2772
+ <stop offset="0" [attr.stop-color]="color" stop-opacity="0.22" />
2773
+ <stop offset="1" [attr.stop-color]="color" stop-opacity="0" />
2774
+ </linearGradient>
2775
+ </defs>
2776
+ @for (t of ticks; track $index) {
2777
+ <line
2778
+ [attr.x1]="padL"
2779
+ [attr.x2]="width - padR"
2780
+ [attr.y1]="t.y"
2781
+ [attr.y2]="t.y"
2782
+ stroke="var(--grid-line)"
2783
+ stroke-width="1"
2784
+ />
2785
+ <text
2786
+ [attr.x]="padL - 8"
2787
+ [attr.y]="t.y + 3.5"
2788
+ text-anchor="end"
2789
+ font-size="10"
2790
+ fill="var(--text-faint)"
2791
+ font-family="var(--font-mono)"
2792
+ >
2793
+ {{ t.label }}
2794
+ </text>
2795
+ }
2796
+ @if (labels) {
2797
+ @for (lb of labels; track $index; let i = $index) {
2798
+ @if (showLabel(i)) {
2799
+ <text
2800
+ [attr.x]="sx(i, labels.length)"
2801
+ [attr.y]="height - 8"
2802
+ text-anchor="middle"
2803
+ font-size="10"
2804
+ fill="var(--text-faint)"
2805
+ font-family="var(--font-mono)"
2806
+ >
2807
+ {{ lb }}
2808
+ </text>
2809
+ }
2810
+ }
2811
+ }
2812
+ @for (ln of lineEls; track $index) {
2813
+ @if (ln.area) {
2814
+ <path [attr.d]="ln.area" [attr.fill]="'url(#' + gid + ')'" />
2815
+ }
2816
+ <path
2817
+ [attr.d]="ln.d"
2818
+ fill="none"
2819
+ [attr.stroke]="ln.stroke"
2820
+ stroke-width="2.4"
2821
+ stroke-linecap="round"
2822
+ [attr.stroke-dasharray]="ln.dash"
2823
+ [style.opacity]="ln.opacity"
2824
+ />
2825
+ }
2826
+ </svg>`, isInline: true });
2827
+ }
2828
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspAreaChart, decorators: [{
2829
+ type: Component,
2830
+ args: [{
2831
+ selector: 'vsp-area-chart',
2832
+ template: `<svg [attr.width]="width" [attr.height]="height" style="display: block">
2833
+ <defs>
2834
+ <linearGradient [id]="gid" x1="0" x2="0" y1="0" y2="1">
2835
+ <stop offset="0" [attr.stop-color]="color" stop-opacity="0.22" />
2836
+ <stop offset="1" [attr.stop-color]="color" stop-opacity="0" />
2837
+ </linearGradient>
2838
+ </defs>
2839
+ @for (t of ticks; track $index) {
2840
+ <line
2841
+ [attr.x1]="padL"
2842
+ [attr.x2]="width - padR"
2843
+ [attr.y1]="t.y"
2844
+ [attr.y2]="t.y"
2845
+ stroke="var(--grid-line)"
2846
+ stroke-width="1"
2847
+ />
2848
+ <text
2849
+ [attr.x]="padL - 8"
2850
+ [attr.y]="t.y + 3.5"
2851
+ text-anchor="end"
2852
+ font-size="10"
2853
+ fill="var(--text-faint)"
2854
+ font-family="var(--font-mono)"
2855
+ >
2856
+ {{ t.label }}
2857
+ </text>
2858
+ }
2859
+ @if (labels) {
2860
+ @for (lb of labels; track $index; let i = $index) {
2861
+ @if (showLabel(i)) {
2862
+ <text
2863
+ [attr.x]="sx(i, labels.length)"
2864
+ [attr.y]="height - 8"
2865
+ text-anchor="middle"
2866
+ font-size="10"
2867
+ fill="var(--text-faint)"
2868
+ font-family="var(--font-mono)"
2869
+ >
2870
+ {{ lb }}
2871
+ </text>
2872
+ }
2873
+ }
2874
+ }
2875
+ @for (ln of lineEls; track $index) {
2876
+ @if (ln.area) {
2877
+ <path [attr.d]="ln.area" [attr.fill]="'url(#' + gid + ')'" />
2878
+ }
2879
+ <path
2880
+ [attr.d]="ln.d"
2881
+ fill="none"
2882
+ [attr.stroke]="ln.stroke"
2883
+ stroke-width="2.4"
2884
+ stroke-linecap="round"
2885
+ [attr.stroke-dasharray]="ln.dash"
2886
+ [style.opacity]="ln.opacity"
2887
+ />
2888
+ }
2889
+ </svg>`,
2890
+ }]
2891
+ }], propDecorators: { series: [{
2892
+ type: Input
2893
+ }], labels: [{
2894
+ type: Input
2895
+ }], width: [{
2896
+ type: Input
2897
+ }], height: [{
2898
+ type: Input
2899
+ }], color: [{
2900
+ type: Input
2901
+ }], color2: [{
2902
+ type: Input
2903
+ }], dual: [{
2904
+ type: Input
2905
+ }] } });
2906
+ class VspBarChart {
2907
+ data = [];
2908
+ labels;
2909
+ width = 620;
2910
+ height = 240;
2911
+ color = 'var(--accent)';
2912
+ padL = 34;
2913
+ padB = 26;
2914
+ padT = 10;
2915
+ get innerW() {
2916
+ return Math.max(10, this.width - this.padL - 8);
2917
+ }
2918
+ get innerH() {
2919
+ return this.height - this.padB - this.padT;
2920
+ }
2921
+ get max() {
2922
+ return Math.max(...this.data, 0) * 1.15 || 1;
2923
+ }
2924
+ get bw() {
2925
+ return this.innerW / (this.data.length || 1);
2926
+ }
2927
+ get barFill() {
2928
+ return `color-mix(in oklab, ${this.color} 78%, transparent)`;
2929
+ }
2930
+ get grid() {
2931
+ return [0, 0.5, 1].map((f) => ({
2932
+ y: this.padT + this.innerH - f * this.innerH,
2933
+ label: niceNum(Math.round(this.max * f)),
2934
+ }));
2935
+ }
2936
+ get bars() {
2937
+ return this.data.map((v, i) => {
2938
+ const bh = (v / this.max) * this.innerH;
2939
+ const x = this.padL + i * this.bw + this.bw * 0.18;
2940
+ const bwi = this.bw * 0.64;
2941
+ return { x, y: this.padT + this.innerH - bh, w: bwi, h: bh, label: this.labels?.[i] };
2942
+ });
2943
+ }
2944
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBarChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
2945
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: VspBarChart, isStandalone: true, selector: "vsp-bar-chart", inputs: { data: "data", labels: "labels", width: "width", height: "height", color: "color" }, ngImport: i0, template: `<svg [attr.width]="width" [attr.height]="height" style="display: block">
2946
+ @for (g of grid; track $index) {
2947
+ <line
2948
+ [attr.x1]="padL"
2949
+ [attr.x2]="width - 8"
2950
+ [attr.y1]="g.y"
2951
+ [attr.y2]="g.y"
2952
+ stroke="var(--grid-line)"
2953
+ />
2954
+ <text
2955
+ [attr.x]="padL - 8"
2956
+ [attr.y]="g.y + 3.5"
2957
+ text-anchor="end"
2958
+ font-size="10"
2959
+ fill="var(--text-faint)"
2960
+ font-family="var(--font-mono)"
2961
+ >
2962
+ {{ g.label }}
2963
+ </text>
2964
+ }
2965
+ @for (b of bars; track $index) {
2966
+ <rect
2967
+ [attr.x]="b.x"
2968
+ [attr.y]="b.y"
2969
+ [attr.width]="b.w"
2970
+ [attr.height]="b.h"
2971
+ rx="4"
2972
+ [attr.fill]="barFill"
2973
+ />
2974
+ @if (b.label != null) {
2975
+ <text
2976
+ [attr.x]="b.x + b.w / 2"
2977
+ [attr.y]="height - 8"
2978
+ text-anchor="middle"
2979
+ font-size="10"
2980
+ fill="var(--text-faint)"
2981
+ font-family="var(--font-mono)"
2982
+ >
2983
+ {{ b.label }}
2984
+ </text>
2985
+ }
2986
+ }
2987
+ </svg>`, isInline: true });
2988
+ }
2989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: VspBarChart, decorators: [{
2990
+ type: Component,
2991
+ args: [{
2992
+ selector: 'vsp-bar-chart',
2993
+ template: `<svg [attr.width]="width" [attr.height]="height" style="display: block">
2994
+ @for (g of grid; track $index) {
2995
+ <line
2996
+ [attr.x1]="padL"
2997
+ [attr.x2]="width - 8"
2998
+ [attr.y1]="g.y"
2999
+ [attr.y2]="g.y"
3000
+ stroke="var(--grid-line)"
3001
+ />
3002
+ <text
3003
+ [attr.x]="padL - 8"
3004
+ [attr.y]="g.y + 3.5"
3005
+ text-anchor="end"
3006
+ font-size="10"
3007
+ fill="var(--text-faint)"
3008
+ font-family="var(--font-mono)"
3009
+ >
3010
+ {{ g.label }}
3011
+ </text>
3012
+ }
3013
+ @for (b of bars; track $index) {
3014
+ <rect
3015
+ [attr.x]="b.x"
3016
+ [attr.y]="b.y"
3017
+ [attr.width]="b.w"
3018
+ [attr.height]="b.h"
3019
+ rx="4"
3020
+ [attr.fill]="barFill"
3021
+ />
3022
+ @if (b.label != null) {
3023
+ <text
3024
+ [attr.x]="b.x + b.w / 2"
3025
+ [attr.y]="height - 8"
3026
+ text-anchor="middle"
3027
+ font-size="10"
3028
+ fill="var(--text-faint)"
3029
+ font-family="var(--font-mono)"
3030
+ >
3031
+ {{ b.label }}
3032
+ </text>
3033
+ }
3034
+ }
3035
+ </svg>`,
3036
+ }]
3037
+ }], propDecorators: { data: [{
3038
+ type: Input
3039
+ }], labels: [{
3040
+ type: Input
3041
+ }], width: [{
3042
+ type: Input
3043
+ }], height: [{
3044
+ type: Input
3045
+ }], color: [{
3046
+ type: Input
3047
+ }] } });
3048
+
2149
3049
  /**
2150
3050
  * Generated bundle index. Do not edit.
2151
3051
  */
2152
3052
 
2153
- export { VspAccordion, VspAlert, VspAvatar, VspAvatarGroup, VspBadge, VspBanner, VspBreadcrumb, VspButton, VspCard, VspCardHead, VspCheckbox, VspCircularProgress, VspDescriptionList, VspDivider, VspDonut, VspEmptyState, VspField, VspIconButton, VspInput, VspKbd, VspNativeSelect, VspPagination, VspProgress, VspRadio, VspRadioGroup, VspSegmented, VspSkeleton, VspSlider, VspSparkline, VspSpinner, VspStat, VspStatCard, VspStepper, VspSwitch, VspTabs, VspTag, VspTextarea, VspTimeline };
3053
+ export { VspAccordion, VspAlert, VspAreaChart, VspAvatar, VspAvatarGroup, VspBadge, VspBanner, VspBarChart, VspBreadcrumb, VspButton, VspCard, VspCardHead, VspCheckbox, VspCircularProgress, VspCopyButton, VspDescriptionList, VspDivider, VspDonut, VspEmptyState, VspField, VspIconButton, VspInlineEdit, VspInput, VspKbd, VspNativeSelect, VspNumberStepper, VspOTPInput, VspPagination, VspProgress, VspRadio, VspRadioGroup, VspSegmented, VspSkeleton, VspSlider, VspSparkline, VspSpinner, VspStat, VspStatCard, VspStepper, VspSwitch, VspTabs, VspTag, VspTextarea, VspTimeline, VspTree };
2154
3054
  //# sourceMappingURL=vespera-ui-angular.mjs.map