@wildmason/aegis 1.18.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -2
- package/dist/fesm2022/wildmason-aegis-license.mjs +153 -0
- package/dist/fesm2022/wildmason-aegis-license.mjs.map +1 -0
- package/dist/fesm2022/wildmason-aegis.mjs +510 -319
- package/dist/fesm2022/wildmason-aegis.mjs.map +1 -1
- package/dist/types/wildmason-aegis-license.d.ts +73 -0
- package/dist/types/wildmason-aegis.d.ts +174 -71
- package/inputs.css +4 -8
- package/package.json +27 -13
|
@@ -8,7 +8,6 @@ import { Subject, debounceTime, switchMap, of, catchError, finalize } from 'rxjs
|
|
|
8
8
|
import * as i1 from '@angular/cdk/scrolling';
|
|
9
9
|
import { ScrollingModule, CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
|
10
10
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
11
|
-
import { invoke } from '@tauri-apps/api/core';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* WmModal — Lightweight modal backdrop with Escape key and click-outside dismissal.
|
|
@@ -47,7 +46,7 @@ import { invoke } from '@tauri-apps/api/core';
|
|
|
47
46
|
*/
|
|
48
47
|
class WmModal {
|
|
49
48
|
/** Whether the modal is currently open. */
|
|
50
|
-
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
49
|
+
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
51
50
|
/** Emitted when the user requests the modal to close (Escape or backdrop click). */
|
|
52
51
|
dismiss = output();
|
|
53
52
|
/**
|
|
@@ -55,15 +54,15 @@ class WmModal {
|
|
|
55
54
|
* - 'center' (default): panel is vertically centered (items-center)
|
|
56
55
|
* - 'top': panel appears near the top (items-start pt-20), for search/command overlays
|
|
57
56
|
*/
|
|
58
|
-
align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : []));
|
|
57
|
+
align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
|
|
59
58
|
onEscape() {
|
|
60
59
|
if (this.visible())
|
|
61
60
|
this.dismiss.emit();
|
|
62
61
|
}
|
|
63
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
64
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
62
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
63
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmModal, isStandalone: true, selector: "wm-modal", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: true, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismiss: "dismiss" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@if (visible()) {\n <div [class]=\"align() === 'top'\n ? 'fixed inset-0 flex items-start justify-center pt-20 z-50'\n : 'fixed inset-0 flex items-center justify-center z-50'\"\n style=\"background: var(--wm-modal-backdrop)\"\n (click)=\"dismiss.emit()\">\n <!-- The trap must sit on an element this template owns, inside this `@if`, so it\n has a parentNode by the time CdkTrapFocus runs ngAfterContentInit. A consumer\n cannot achieve that on projected content \u2014 see the class doc. -->\n <div (click)=\"$event.stopPropagation()\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <ng-content />\n </div>\n </div>\n}\n", dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
65
64
|
}
|
|
66
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
65
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmModal, decorators: [{
|
|
67
66
|
type: Component,
|
|
68
67
|
args: [{ selector: 'wm-modal', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CdkTrapFocus], template: "@if (visible()) {\n <div [class]=\"align() === 'top'\n ? 'fixed inset-0 flex items-start justify-center pt-20 z-50'\n : 'fixed inset-0 flex items-center justify-center z-50'\"\n style=\"background: var(--wm-modal-backdrop)\"\n (click)=\"dismiss.emit()\">\n <!-- The trap must sit on an element this template owns, inside this `@if`, so it\n has a parentNode by the time CdkTrapFocus runs ngAfterContentInit. A consumer\n cannot achieve that on projected content \u2014 see the class doc. -->\n <div (click)=\"$event.stopPropagation()\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <ng-content />\n </div>\n </div>\n}\n" }]
|
|
69
68
|
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], onEscape: [{
|
|
@@ -100,20 +99,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
100
99
|
*/
|
|
101
100
|
class WmDialog {
|
|
102
101
|
/** Two-way binding for open/closed state. */
|
|
103
|
-
isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
102
|
+
isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
104
103
|
/** Dialog heading text. When set, aria-labelledby is applied automatically. */
|
|
105
|
-
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
104
|
+
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
106
105
|
/** Panel width preset. sm = 360px, md = 480px (default), lg = 640px. */
|
|
107
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
106
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
108
107
|
close() { this.isOpen.set(false); }
|
|
109
108
|
onEscape() {
|
|
110
109
|
if (this.isOpen())
|
|
111
110
|
this.close();
|
|
112
111
|
}
|
|
113
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
114
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
112
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
113
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmDialog, isStandalone: true, selector: "wm-dialog", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@if (isOpen()) {\n <!-- Backdrop \u2014 click to close -->\n <div class=\"wm-dialog-backdrop\" (click)=\"close()\" aria-hidden=\"true\"></div>\n\n <!-- Panel -->\n <div\n class=\"wm-dialog\"\n [class]=\"'wm-dialog--' + size()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title() ? 'wm-dialog-title' : null\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n >\n <div class=\"wm-dialog-header\">\n <h2 class=\"wm-dialog-title\" id=\"wm-dialog-title\">{{ title() }}</h2>\n <button\n class=\"wm-dialog-close\"\n type=\"button\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"wm-dialog-body\">\n <ng-content select=\"[body]\" />\n </div>\n </div>\n}\n", styles: [":host{display:contents}.wm-dialog-backdrop{position:fixed;inset:0;background:rgba(0,0,0,var(--wm-backdrop-opacity));z-index:100}.wm-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:101;background:var(--wm-bg-float);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:var(--wm-shadow-lg);width:var(--wm-dialog-width, 480px);max-width:calc(100vw - 2rem);max-height:calc(100dvh - 4rem);display:flex;flex-direction:column;overflow:hidden;outline:none}.wm-dialog--sm{width:var(--wm-dialog-width, 360px)}.wm-dialog--lg{width:var(--wm-dialog-width, 640px)}.wm-dialog-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:1.125rem 1.25rem;flex-shrink:0;background:var(--wm-bg-raised)}.wm-dialog-title{font-size:1rem;font-weight:600;color:var(--wm-text-primary);margin:0;line-height:1.3}.wm-dialog-close{display:flex;align-items:center;justify-content:center;width:28px;height:28px;flex-shrink:0;border-radius:var(--wm-radius-sm);border:none;background:transparent;color:var(--wm-text-muted);cursor:pointer;transition:background var(--wm-transition-fast),color var(--wm-transition-fast)}.wm-dialog-close:hover{background:var(--wm-bg-hover);color:var(--wm-text-primary)}.wm-dialog-close:focus-visible{outline:2px solid var(--wm-color-accent);outline-offset:1px}.wm-dialog-body{flex:1;overflow-y:auto;padding:1rem 1.25rem 1.25rem;font-size:.875rem;color:var(--wm-text-secondary);line-height:1.6}@media(prefers-reduced-motion:reduce){.wm-dialog-close{transition:none}}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }] });
|
|
115
114
|
}
|
|
116
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmDialog, decorators: [{
|
|
117
116
|
type: Component,
|
|
118
117
|
args: [{ selector: 'wm-dialog', imports: [CdkTrapFocus], template: "@if (isOpen()) {\n <!-- Backdrop \u2014 click to close -->\n <div class=\"wm-dialog-backdrop\" (click)=\"close()\" aria-hidden=\"true\"></div>\n\n <!-- Panel -->\n <div\n class=\"wm-dialog\"\n [class]=\"'wm-dialog--' + size()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title() ? 'wm-dialog-title' : null\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n >\n <div class=\"wm-dialog-header\">\n <h2 class=\"wm-dialog-title\" id=\"wm-dialog-title\">{{ title() }}</h2>\n <button\n class=\"wm-dialog-close\"\n type=\"button\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"wm-dialog-body\">\n <ng-content select=\"[body]\" />\n </div>\n </div>\n}\n", styles: [":host{display:contents}.wm-dialog-backdrop{position:fixed;inset:0;background:rgba(0,0,0,var(--wm-backdrop-opacity));z-index:100}.wm-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:101;background:var(--wm-bg-float);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:var(--wm-shadow-lg);width:var(--wm-dialog-width, 480px);max-width:calc(100vw - 2rem);max-height:calc(100dvh - 4rem);display:flex;flex-direction:column;overflow:hidden;outline:none}.wm-dialog--sm{width:var(--wm-dialog-width, 360px)}.wm-dialog--lg{width:var(--wm-dialog-width, 640px)}.wm-dialog-header{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:1.125rem 1.25rem;flex-shrink:0;background:var(--wm-bg-raised)}.wm-dialog-title{font-size:1rem;font-weight:600;color:var(--wm-text-primary);margin:0;line-height:1.3}.wm-dialog-close{display:flex;align-items:center;justify-content:center;width:28px;height:28px;flex-shrink:0;border-radius:var(--wm-radius-sm);border:none;background:transparent;color:var(--wm-text-muted);cursor:pointer;transition:background var(--wm-transition-fast),color var(--wm-transition-fast)}.wm-dialog-close:hover{background:var(--wm-bg-hover);color:var(--wm-text-primary)}.wm-dialog-close:focus-visible{outline:2px solid var(--wm-color-accent);outline-offset:1px}.wm-dialog-body{flex:1;overflow-y:auto;padding:1rem 1.25rem 1.25rem;font-size:.875rem;color:var(--wm-text-secondary);line-height:1.6}@media(prefers-reduced-motion:reduce){.wm-dialog-close{transition:none}}\n"] }]
|
|
119
118
|
}], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], onEscape: [{
|
|
@@ -259,15 +258,15 @@ class WmSelect {
|
|
|
259
258
|
*/
|
|
260
259
|
scrollStrategy = new WmAnchoredScrollStrategy();
|
|
261
260
|
/** Array of options to display. */
|
|
262
|
-
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
261
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
263
262
|
/** The currently selected value. Two-way bindable. */
|
|
264
|
-
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
263
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
265
264
|
/** Placeholder text shown when no option is selected. */
|
|
266
|
-
placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
265
|
+
placeholder = input('Select…', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
267
266
|
/** Disables the trigger and prevents the panel from opening. */
|
|
268
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
269
|
-
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
270
|
-
selectedOption = computed(() => this.options().find((o) => o.value === this.value()) ?? null, ...(ngDevMode ? [{ debugName: "selectedOption" }] : []));
|
|
267
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
268
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
269
|
+
selectedOption = computed(() => this.options().find((o) => o.value === this.value()) ?? null, ...(ngDevMode ? [{ debugName: "selectedOption" }] : /* istanbul ignore next */ []));
|
|
271
270
|
hostEl = inject((ElementRef));
|
|
272
271
|
get overlayWidth() {
|
|
273
272
|
return this.hostEl.nativeElement.offsetWidth || 200;
|
|
@@ -287,10 +286,10 @@ class WmSelect {
|
|
|
287
286
|
this.isOpen.set(false);
|
|
288
287
|
}
|
|
289
288
|
}
|
|
290
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
291
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
289
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
290
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmSelect, isStandalone: true, selector: "wm-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "<!-- Trigger button \u2014 anchors the CDK overlay -->\n<div\n class=\"wm-select-host\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n>\n <button\n type=\"button\"\n role=\"combobox\"\n class=\"wm-select-trigger\"\n [class.is-open]=\"isOpen()\"\n [class.is-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n aria-haspopup=\"listbox\"\n [attr.aria-disabled]=\"disabled() ? true : null\"\n [disabled]=\"disabled() || null\"\n (click)=\"toggleOpen()\"\n >\n <span class=\"wm-select-value\" [class.is-placeholder]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\n <!-- Chevron icon \u2014 rotates when open -->\n <svg\n class=\"wm-select-chevron\"\n [class.is-open]=\"isOpen()\"\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <path d=\"M6 9l6 6 6-6\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n</div>\n\n<!-- Dropdown panel \u2014 rendered in CDK overlay container -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"wm-select-backdrop\"\n (backdropClick)=\"isOpen.set(false)\"\n (detach)=\"isOpen.set(false)\"\n>\n <div\n class=\"wm-select-panel\"\n role=\"listbox\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n >\n @for (opt of options(); track opt.value) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"wm-select-option\"\n [class.is-selected]=\"opt.value === value()\"\n [class.is-disabled]=\"!!opt.disabled\"\n [attr.aria-selected]=\"opt.value === value()\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n [disabled]=\"opt.disabled || null\"\n (click)=\"selectOption(opt)\"\n >\n <span class=\"wm-select-option-label\">{{ opt.label }}</span>\n @if (opt.value === value()) {\n <!-- Checkmark for selected option -->\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n }\n </button>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block}.wm-select-host{display:block}.wm-select-trigger{display:flex;align-items:center;justify-content:space-between;gap:.5rem;width:100%;padding:0 .75rem;height:36px;background:var(--wm-bg-base);border:1px solid var(--wm-border-input);border-radius:var(--wm-radius-md);color:var(--wm-text-primary);font-size:.875rem;font-family:inherit;cursor:pointer;transition:border-color var(--wm-transition-fast),box-shadow var(--wm-transition-fast);outline:none;text-align:left}.wm-select-trigger:hover:not(.is-disabled){border-color:var(--wm-color-accent-readable)}.wm-select-trigger:focus-visible{border-color:var(--wm-color-accent-readable);box-shadow:0 0 0 3px color-mix(in srgb,var(--wm-color-accent) 25%,transparent)}.wm-select-trigger.is-open{border-color:var(--wm-color-accent-readable);box-shadow:0 0 0 3px color-mix(in srgb,var(--wm-color-accent) 20%,transparent)}.wm-select-trigger.is-disabled{opacity:.45;cursor:not-allowed}.wm-select-value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-select-value.is-placeholder{color:var(--wm-text-placeholder)}.wm-select-chevron{flex-shrink:0;color:var(--wm-text-muted);transition:transform var(--wm-transition-fast)}.wm-select-chevron.is-open{transform:rotate(180deg)}.wm-select-backdrop{position:fixed;inset:0}.wm-select-panel{width:100%;background:var(--wm-bg-float);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:0 4px 6px -1px #00000014,0 10px 20px -4px #0000001f;overflow:hidden;outline:none;padding:.25rem}.wm-select-option{display:flex;align-items:center;justify-content:space-between;gap:.5rem;width:100%;padding:.4375rem .625rem;border:none;border-radius:var(--wm-radius-sm);background:transparent;color:var(--wm-text-primary);font-size:.875rem;font-family:inherit;cursor:pointer;text-align:left;transition:background var(--wm-transition-fast)}.wm-select-option:hover:not(.is-disabled):not(.is-selected){background:var(--wm-bg-active)}.wm-select-option.is-selected{background:color-mix(in srgb,var(--wm-color-accent) 10%,transparent);color:var(--wm-color-accent-readable);font-weight:500}.wm-select-option.is-disabled{opacity:.4;cursor:not-allowed}.wm-select-option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-select-option svg{flex-shrink:0;color:var(--wm-color-accent-readable)}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }] });
|
|
292
291
|
}
|
|
293
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
292
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmSelect, decorators: [{
|
|
294
293
|
type: Component,
|
|
295
294
|
args: [{ selector: 'wm-select', imports: [CdkConnectedOverlay, CdkOverlayOrigin, CdkTrapFocus], template: "<!-- Trigger button \u2014 anchors the CDK overlay -->\n<div\n class=\"wm-select-host\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n>\n <button\n type=\"button\"\n role=\"combobox\"\n class=\"wm-select-trigger\"\n [class.is-open]=\"isOpen()\"\n [class.is-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n aria-haspopup=\"listbox\"\n [attr.aria-disabled]=\"disabled() ? true : null\"\n [disabled]=\"disabled() || null\"\n (click)=\"toggleOpen()\"\n >\n <span class=\"wm-select-value\" [class.is-placeholder]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\n <!-- Chevron icon \u2014 rotates when open -->\n <svg\n class=\"wm-select-chevron\"\n [class.is-open]=\"isOpen()\"\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <path d=\"M6 9l6 6 6-6\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n</div>\n\n<!-- Dropdown panel \u2014 rendered in CDK overlay container -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"wm-select-backdrop\"\n (backdropClick)=\"isOpen.set(false)\"\n (detach)=\"isOpen.set(false)\"\n>\n <div\n class=\"wm-select-panel\"\n role=\"listbox\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n >\n @for (opt of options(); track opt.value) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"wm-select-option\"\n [class.is-selected]=\"opt.value === value()\"\n [class.is-disabled]=\"!!opt.disabled\"\n [attr.aria-selected]=\"opt.value === value()\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n [disabled]=\"opt.disabled || null\"\n (click)=\"selectOption(opt)\"\n >\n <span class=\"wm-select-option-label\">{{ opt.label }}</span>\n @if (opt.value === value()) {\n <!-- Checkmark for selected option -->\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n }\n </button>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block}.wm-select-host{display:block}.wm-select-trigger{display:flex;align-items:center;justify-content:space-between;gap:.5rem;width:100%;padding:0 .75rem;height:36px;background:var(--wm-bg-base);border:1px solid var(--wm-border-input);border-radius:var(--wm-radius-md);color:var(--wm-text-primary);font-size:.875rem;font-family:inherit;cursor:pointer;transition:border-color var(--wm-transition-fast),box-shadow var(--wm-transition-fast);outline:none;text-align:left}.wm-select-trigger:hover:not(.is-disabled){border-color:var(--wm-color-accent-readable)}.wm-select-trigger:focus-visible{border-color:var(--wm-color-accent-readable);box-shadow:0 0 0 3px color-mix(in srgb,var(--wm-color-accent) 25%,transparent)}.wm-select-trigger.is-open{border-color:var(--wm-color-accent-readable);box-shadow:0 0 0 3px color-mix(in srgb,var(--wm-color-accent) 20%,transparent)}.wm-select-trigger.is-disabled{opacity:.45;cursor:not-allowed}.wm-select-value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-select-value.is-placeholder{color:var(--wm-text-placeholder)}.wm-select-chevron{flex-shrink:0;color:var(--wm-text-muted);transition:transform var(--wm-transition-fast)}.wm-select-chevron.is-open{transform:rotate(180deg)}.wm-select-backdrop{position:fixed;inset:0}.wm-select-panel{width:100%;background:var(--wm-bg-float);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:0 4px 6px -1px #00000014,0 10px 20px -4px #0000001f;overflow:hidden;outline:none;padding:.25rem}.wm-select-option{display:flex;align-items:center;justify-content:space-between;gap:.5rem;width:100%;padding:.4375rem .625rem;border:none;border-radius:var(--wm-radius-sm);background:transparent;color:var(--wm-text-primary);font-size:.875rem;font-family:inherit;cursor:pointer;text-align:left;transition:background var(--wm-transition-fast)}.wm-select-option:hover:not(.is-disabled):not(.is-selected){background:var(--wm-bg-active)}.wm-select-option.is-selected{background:color-mix(in srgb,var(--wm-color-accent) 10%,transparent);color:var(--wm-color-accent-readable);font-weight:500}.wm-select-option.is-disabled{opacity:.4;cursor:not-allowed}.wm-select-option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-select-option svg{flex-shrink:0;color:var(--wm-color-accent-readable)}\n"] }]
|
|
296
295
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
@@ -346,11 +345,11 @@ class WmPopover {
|
|
|
346
345
|
*/
|
|
347
346
|
scrollStrategy = new WmAnchoredScrollStrategy();
|
|
348
347
|
/** Whether the panel is currently open. */
|
|
349
|
-
isOpen = input(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
348
|
+
isOpen = input(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
350
349
|
/** Panel width in pixels, or 'auto' to match content. */
|
|
351
|
-
width = input('auto', ...(ngDevMode ? [{ debugName: "width" }] : []));
|
|
350
|
+
width = input('auto', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
|
|
352
351
|
/** ARIA role for the floating panel element. Use 'menu', 'listbox', 'dialog', etc. */
|
|
353
|
-
role = input('dialog', ...(ngDevMode ? [{ debugName: "role" }] : []));
|
|
352
|
+
role = input('dialog', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
354
353
|
/**
|
|
355
354
|
* Accessible name applied to the floating panel element.
|
|
356
355
|
*
|
|
@@ -358,11 +357,11 @@ class WmPopover {
|
|
|
358
357
|
* equivalent labelling relationship. Keeping the name on the panel shell
|
|
359
358
|
* ensures the trigger's aria-controls points to the named semantic surface.
|
|
360
359
|
*/
|
|
361
|
-
ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
360
|
+
ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
362
361
|
/** Value for aria-haspopup on the trigger element. */
|
|
363
|
-
hasPopup = input('dialog', ...(ngDevMode ? [{ debugName: "hasPopup" }] : []));
|
|
362
|
+
hasPopup = input('dialog', ...(ngDevMode ? [{ debugName: "hasPopup" }] : /* istanbul ignore next */ []));
|
|
364
363
|
/** Horizontal alignment: 'start' aligns left edges, 'end' aligns right edges. */
|
|
365
|
-
align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : []));
|
|
364
|
+
align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
|
|
366
365
|
/**
|
|
367
366
|
* Whether the focus trap auto-captures focus into the panel on attach
|
|
368
367
|
* and restores it on detach. Defaults to `true`, which is right for
|
|
@@ -378,14 +377,14 @@ class WmPopover {
|
|
|
378
377
|
* panel when it has focus; this only opts out of the auto-capture and
|
|
379
378
|
* auto-restore.
|
|
380
379
|
*/
|
|
381
|
-
trapFocusAutoCapture = input(true, ...(ngDevMode ? [{ debugName: "trapFocusAutoCapture" }] : []));
|
|
380
|
+
trapFocusAutoCapture = input(true, ...(ngDevMode ? [{ debugName: "trapFocusAutoCapture" }] : /* istanbul ignore next */ []));
|
|
382
381
|
/** Emitted when the panel should close (backdrop click, Escape key, CDK detach). */
|
|
383
382
|
closed = output();
|
|
384
383
|
renderer = inject(Renderer2);
|
|
385
384
|
hostEl = inject(ElementRef);
|
|
386
385
|
cdr = inject(ChangeDetectorRef);
|
|
387
386
|
panelId = 'wm-popover-' + Math.random().toString(36).substring(2, 9);
|
|
388
|
-
panel = viewChild('panel', ...(ngDevMode ? [{ debugName: "panel" }] : []));
|
|
387
|
+
panel = viewChild('panel', ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
|
|
389
388
|
constructor() {
|
|
390
389
|
effect(() => {
|
|
391
390
|
const open = this.isOpen();
|
|
@@ -432,10 +431,10 @@ class WmPopover {
|
|
|
432
431
|
onClose() {
|
|
433
432
|
this.closed.emit();
|
|
434
433
|
}
|
|
435
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
436
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.
|
|
434
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmPopover, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
435
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: WmPopover, isStandalone: true, selector: "wm-popover", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hasPopup: { classPropertyName: "hasPopup", publicName: "hasPopup", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, trapFocusAutoCapture: { classPropertyName: "trapFocusAutoCapture", publicName: "trapFocusAutoCapture", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Trigger anchor -->\n<div cdkOverlayOrigin #origin=\"cdkOverlayOrigin\" class=\"wm-popover-trigger\">\n <ng-content select=\"[trigger]\"></ng-content>\n</div>\n\n<!-- Floating panel -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"onClose()\"\n (detach)=\"onClose()\"\n (attach)=\"onAttach()\"\n>\n <div\n #panel\n [id]=\"panelId\"\n [attr.role]=\"role()\"\n [attr.aria-label]=\"ariaLabel()\"\n class=\"wm-popover-panel\"\n [style.width]=\"width() === 'auto' ? 'auto' : width() + 'px'\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"trapFocusAutoCapture()\"\n (keydown.escape)=\"onClose()\"\n >\n <ng-content select=\"[content]\"></ng-content>\n </div>\n</ng-template>\n", styles: ["wm-popover{display:inline-flex;align-items:center}.wm-popover-trigger{display:block;width:100%}.wm-popover-panel{background:var(--wm-bg-raised);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:0 4px 6px -1px #00000014,0 10px 20px -4px #00000024;overflow:hidden;outline:none}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
437
436
|
}
|
|
438
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
437
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmPopover, decorators: [{
|
|
439
438
|
type: Component,
|
|
440
439
|
args: [{ selector: 'wm-popover', imports: [CdkConnectedOverlay, CdkOverlayOrigin, CdkTrapFocus], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<!-- Trigger anchor -->\n<div cdkOverlayOrigin #origin=\"cdkOverlayOrigin\" class=\"wm-popover-trigger\">\n <ng-content select=\"[trigger]\"></ng-content>\n</div>\n\n<!-- Floating panel -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"onClose()\"\n (detach)=\"onClose()\"\n (attach)=\"onAttach()\"\n>\n <div\n #panel\n [id]=\"panelId\"\n [attr.role]=\"role()\"\n [attr.aria-label]=\"ariaLabel()\"\n class=\"wm-popover-panel\"\n [style.width]=\"width() === 'auto' ? 'auto' : width() + 'px'\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"trapFocusAutoCapture()\"\n (keydown.escape)=\"onClose()\"\n >\n <ng-content select=\"[content]\"></ng-content>\n </div>\n</ng-template>\n", styles: ["wm-popover{display:inline-flex;align-items:center}.wm-popover-trigger{display:block;width:100%}.wm-popover-panel{background:var(--wm-bg-raised);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:0 4px 6px -1px #00000014,0 10px 20px -4px #00000024;overflow:hidden;outline:none}\n"] }]
|
|
441
440
|
}], ctorParameters: () => [], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hasPopup: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasPopup", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], trapFocusAutoCapture: [{ type: i0.Input, args: [{ isSignal: true, alias: "trapFocusAutoCapture", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
|
|
@@ -474,10 +473,10 @@ class WmAutoFocus {
|
|
|
474
473
|
}
|
|
475
474
|
}, 50);
|
|
476
475
|
}
|
|
477
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
478
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.
|
|
476
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmAutoFocus, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
477
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.23", type: WmAutoFocus, isStandalone: true, selector: "[wmAutoFocus]", inputs: { enabled: ["wmAutoFocus", "enabled"] }, ngImport: i0 });
|
|
479
478
|
}
|
|
480
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmAutoFocus, decorators: [{
|
|
481
480
|
type: Directive,
|
|
482
481
|
args: [{
|
|
483
482
|
selector: '[wmAutoFocus]',
|
|
@@ -488,23 +487,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
488
487
|
}] } });
|
|
489
488
|
|
|
490
489
|
class WmTab {
|
|
491
|
-
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
490
|
+
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
492
491
|
/**
|
|
493
492
|
* Keeps a prerequisite-gated tab discoverable while preventing activation.
|
|
494
493
|
* Unlike a native disabled button, unavailable tabs remain in the roving
|
|
495
494
|
* focus order so keyboard and assistive-technology users can learn why the
|
|
496
495
|
* destination cannot be opened yet.
|
|
497
496
|
*/
|
|
498
|
-
unavailable = input(false, ...(ngDevMode ? [{ debugName: "unavailable" }] : []));
|
|
497
|
+
unavailable = input(false, ...(ngDevMode ? [{ debugName: "unavailable" }] : /* istanbul ignore next */ []));
|
|
499
498
|
/** Exact prerequisite guidance exposed to both pointer and AT users. */
|
|
500
|
-
unavailableReason = input('', ...(ngDevMode ? [{ debugName: "unavailableReason" }] : []));
|
|
499
|
+
unavailableReason = input('', ...(ngDevMode ? [{ debugName: "unavailableReason" }] : /* istanbul ignore next */ []));
|
|
501
500
|
/** Render a non-interactive group divider immediately before this tab. */
|
|
502
|
-
separatorBefore = input(false, ...(ngDevMode ? [{ debugName: "separatorBefore" }] : []));
|
|
501
|
+
separatorBefore = input(false, ...(ngDevMode ? [{ debugName: "separatorBefore" }] : /* istanbul ignore next */ []));
|
|
503
502
|
tmpl = viewChild.required('tmpl');
|
|
504
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
505
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.
|
|
503
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTab, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
504
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: WmTab, isStandalone: true, selector: "wm-tab", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, unavailable: { classPropertyName: "unavailable", publicName: "unavailable", isSignal: true, isRequired: false, transformFunction: null }, unavailableReason: { classPropertyName: "unavailableReason", publicName: "unavailableReason", isSignal: true, isRequired: false, transformFunction: null }, separatorBefore: { classPropertyName: "separatorBefore", publicName: "separatorBefore", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: none" }, viewQueries: [{ propertyName: "tmpl", first: true, predicate: ["tmpl"], descendants: true, isSignal: true }], ngImport: i0, template: `<ng-template #tmpl><ng-content /></ng-template>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
506
505
|
}
|
|
507
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
506
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTab, decorators: [{
|
|
508
507
|
type: Component,
|
|
509
508
|
args: [{
|
|
510
509
|
selector: 'wm-tab',
|
|
@@ -515,11 +514,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
515
514
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], unavailable: [{ type: i0.Input, args: [{ isSignal: true, alias: "unavailable", required: false }] }], unavailableReason: [{ type: i0.Input, args: [{ isSignal: true, alias: "unavailableReason", required: false }] }], separatorBefore: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorBefore", required: false }] }], tmpl: [{ type: i0.ViewChild, args: ['tmpl', { isSignal: true }] }] } });
|
|
516
515
|
|
|
517
516
|
class WmTabs {
|
|
518
|
-
activeValue = input.required(...(ngDevMode ? [{ debugName: "activeValue" }] : []));
|
|
519
|
-
variant = input('line', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
517
|
+
activeValue = input.required(...(ngDevMode ? [{ debugName: "activeValue" }] : /* istanbul ignore next */ []));
|
|
518
|
+
variant = input('line', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
520
519
|
select = output();
|
|
521
|
-
tabs = contentChildren(WmTab, ...(ngDevMode ? [{ debugName: "tabs" }] : []));
|
|
522
|
-
focusedIndex = signal(null, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : []));
|
|
520
|
+
tabs = contentChildren(WmTab, ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
521
|
+
focusedIndex = signal(null, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
|
|
523
522
|
selectTab(tab, index) {
|
|
524
523
|
this.focusedIndex.set(index);
|
|
525
524
|
if (!tab.unavailable())
|
|
@@ -562,33 +561,33 @@ class WmTabs {
|
|
|
562
561
|
btns[nextIndex]?.focus();
|
|
563
562
|
}
|
|
564
563
|
}
|
|
565
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
566
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
564
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
565
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmTabs, isStandalone: true, selector: "wm-tabs", inputs: { activeValue: { classPropertyName: "activeValue", publicName: "activeValue", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select" }, queries: [{ propertyName: "tabs", predicate: WmTab, isSignal: true }], ngImport: i0, template: "<div\n class=\"wm-tabs\"\n [class.wm-tabs--line]=\"variant() === 'line'\"\n [class.wm-tabs--pill]=\"variant() === 'pill'\"\n role=\"tablist\"\n #container\n (keydown)=\"onKeyDown($event, container)\"\n>\n @for (tab of tabs(); track tab.value(); let i = $index) {\n @if (tab.separatorBefore()) {\n <span\n class=\"wm-tab-separator\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n ></span>\n }\n <button\n type=\"button\"\n role=\"tab\"\n class=\"wm-tab\"\n [id]=\"'wm-tab-' + tab.value()\"\n [attr.aria-selected]=\"activeValue() === tab.value()\"\n [attr.aria-controls]=\"'wm-panel-' + tab.value()\"\n [attr.aria-disabled]=\"tab.unavailable() ? true : null\"\n [attr.aria-description]=\"tab.unavailable() ? tab.unavailableReason() : null\"\n [attr.title]=\"tab.unavailable() ? tab.unavailableReason() : null\"\n [tabIndex]=\"(focusedIndex() === null ? activeValue() === tab.value() : focusedIndex() === i) ? 0 : -1\"\n [class.is-active]=\"activeValue() === tab.value()\"\n [class.is-unavailable]=\"tab.unavailable()\"\n (click)=\"selectTab(tab, i)\"\n (focus)=\"focusedIndex.set(i)\"\n (blur)=\"onBlur()\"\n >\n <ng-container [ngTemplateOutlet]=\"tab.tmpl()\" />\n </button>\n }\n</div>\n", styles: [".wm-tab{display:inline-flex;align-items:center;gap:6px;font-size:.8125rem;font-weight:600;background:transparent;border:none;cursor:pointer;white-space:nowrap;transition:color var(--wm-duration-fast) var(--wm-ease-standard),background var(--wm-duration-fast) var(--wm-ease-standard),border-color var(--wm-duration-fast) var(--wm-ease-standard)}.wm-tab:focus-visible{outline:2px solid var(--wm-color-accent);outline-offset:-2px;border-radius:var(--wm-radius-sm)}.wm-tab.is-unavailable{cursor:not-allowed;color:color-mix(in srgb,var(--wm-text-muted) 52%,transparent);box-shadow:none}.wm-tab.is-unavailable:hover{background:transparent;color:color-mix(in srgb,var(--wm-text-muted) 52%,transparent)}.wm-tab-separator{flex:0 0 1px;align-self:center;width:1px;height:1.25rem;margin:0 .375rem;background:var(--wm-border-subtle)}.wm-tabs--line{display:flex;gap:1.5rem;border-bottom:1px solid var(--wm-border-subtle)}.wm-tabs--line .wm-tab{padding:.625rem .25rem;color:var(--wm-text-muted);border-radius:0;border-bottom:2px solid transparent;margin-bottom:-1px}.wm-tabs--line .wm-tab:hover{color:var(--wm-text-secondary)}.wm-tabs--line .wm-tab.is-active{color:var(--wm-color-accent-readable);border-bottom-color:var(--wm-color-accent-readable)}.wm-tabs--pill{display:inline-flex;background:var(--wm-bg-sunken);padding:.25rem;border-radius:var(--wm-radius-md);gap:.125rem;border:1px solid var(--wm-border-subtle)}.wm-tabs--pill .wm-tab{padding:.375rem .75rem;border-radius:var(--wm-radius-sm);color:var(--wm-text-muted)}.wm-tabs--pill .wm-tab:hover{background:color-mix(in srgb,var(--wm-color-accent) 5%,transparent);color:var(--wm-text-secondary)}.wm-tabs--pill .wm-tab.is-active{background:var(--wm-bg-float);color:var(--wm-text-primary);box-shadow:var(--wm-shadow-sm)}.wm-tabs--line .wm-tab.is-unavailable,.wm-tabs--line .wm-tab.is-unavailable:hover,.wm-tabs--pill .wm-tab.is-unavailable,.wm-tabs--pill .wm-tab.is-unavailable:hover{background:transparent;color:color-mix(in srgb,var(--wm-text-muted) 52%,transparent);box-shadow:none}@media(prefers-reduced-motion:reduce){.wm-tab{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
567
566
|
}
|
|
568
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
567
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTabs, decorators: [{
|
|
569
568
|
type: Component,
|
|
570
569
|
args: [{ selector: 'wm-tabs', imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"wm-tabs\"\n [class.wm-tabs--line]=\"variant() === 'line'\"\n [class.wm-tabs--pill]=\"variant() === 'pill'\"\n role=\"tablist\"\n #container\n (keydown)=\"onKeyDown($event, container)\"\n>\n @for (tab of tabs(); track tab.value(); let i = $index) {\n @if (tab.separatorBefore()) {\n <span\n class=\"wm-tab-separator\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n ></span>\n }\n <button\n type=\"button\"\n role=\"tab\"\n class=\"wm-tab\"\n [id]=\"'wm-tab-' + tab.value()\"\n [attr.aria-selected]=\"activeValue() === tab.value()\"\n [attr.aria-controls]=\"'wm-panel-' + tab.value()\"\n [attr.aria-disabled]=\"tab.unavailable() ? true : null\"\n [attr.aria-description]=\"tab.unavailable() ? tab.unavailableReason() : null\"\n [attr.title]=\"tab.unavailable() ? tab.unavailableReason() : null\"\n [tabIndex]=\"(focusedIndex() === null ? activeValue() === tab.value() : focusedIndex() === i) ? 0 : -1\"\n [class.is-active]=\"activeValue() === tab.value()\"\n [class.is-unavailable]=\"tab.unavailable()\"\n (click)=\"selectTab(tab, i)\"\n (focus)=\"focusedIndex.set(i)\"\n (blur)=\"onBlur()\"\n >\n <ng-container [ngTemplateOutlet]=\"tab.tmpl()\" />\n </button>\n }\n</div>\n", styles: [".wm-tab{display:inline-flex;align-items:center;gap:6px;font-size:.8125rem;font-weight:600;background:transparent;border:none;cursor:pointer;white-space:nowrap;transition:color var(--wm-duration-fast) var(--wm-ease-standard),background var(--wm-duration-fast) var(--wm-ease-standard),border-color var(--wm-duration-fast) var(--wm-ease-standard)}.wm-tab:focus-visible{outline:2px solid var(--wm-color-accent);outline-offset:-2px;border-radius:var(--wm-radius-sm)}.wm-tab.is-unavailable{cursor:not-allowed;color:color-mix(in srgb,var(--wm-text-muted) 52%,transparent);box-shadow:none}.wm-tab.is-unavailable:hover{background:transparent;color:color-mix(in srgb,var(--wm-text-muted) 52%,transparent)}.wm-tab-separator{flex:0 0 1px;align-self:center;width:1px;height:1.25rem;margin:0 .375rem;background:var(--wm-border-subtle)}.wm-tabs--line{display:flex;gap:1.5rem;border-bottom:1px solid var(--wm-border-subtle)}.wm-tabs--line .wm-tab{padding:.625rem .25rem;color:var(--wm-text-muted);border-radius:0;border-bottom:2px solid transparent;margin-bottom:-1px}.wm-tabs--line .wm-tab:hover{color:var(--wm-text-secondary)}.wm-tabs--line .wm-tab.is-active{color:var(--wm-color-accent-readable);border-bottom-color:var(--wm-color-accent-readable)}.wm-tabs--pill{display:inline-flex;background:var(--wm-bg-sunken);padding:.25rem;border-radius:var(--wm-radius-md);gap:.125rem;border:1px solid var(--wm-border-subtle)}.wm-tabs--pill .wm-tab{padding:.375rem .75rem;border-radius:var(--wm-radius-sm);color:var(--wm-text-muted)}.wm-tabs--pill .wm-tab:hover{background:color-mix(in srgb,var(--wm-color-accent) 5%,transparent);color:var(--wm-text-secondary)}.wm-tabs--pill .wm-tab.is-active{background:var(--wm-bg-float);color:var(--wm-text-primary);box-shadow:var(--wm-shadow-sm)}.wm-tabs--line .wm-tab.is-unavailable,.wm-tabs--line .wm-tab.is-unavailable:hover,.wm-tabs--pill .wm-tab.is-unavailable,.wm-tabs--pill .wm-tab.is-unavailable:hover{background:transparent;color:color-mix(in srgb,var(--wm-text-muted) 52%,transparent);box-shadow:none}@media(prefers-reduced-motion:reduce){.wm-tab{transition:none}}\n"] }]
|
|
571
570
|
}], propDecorators: { activeValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeValue", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => WmTab), { isSignal: true }] }] } });
|
|
572
571
|
|
|
573
572
|
class WmButton {
|
|
574
|
-
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
575
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
576
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
577
|
-
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : []));
|
|
573
|
+
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
574
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
575
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
576
|
+
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
578
577
|
/** Makes the button square (equal width/height). Use for icon-only buttons. */
|
|
579
|
-
iconOnly = input(false, ...(ngDevMode ? [{ debugName: "iconOnly" }] : []));
|
|
578
|
+
iconOnly = input(false, ...(ngDevMode ? [{ debugName: "iconOnly" }] : /* istanbul ignore next */ []));
|
|
580
579
|
/** Accessible label forwarded to the inner <button>. Required for icon-only buttons. */
|
|
581
|
-
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
580
|
+
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
582
581
|
/** Tooltip text forwarded to the inner <button>. Named btnTitle to avoid native attribute conflict. */
|
|
583
|
-
btnTitle = input('', ...(ngDevMode ? [{ debugName: "btnTitle" }] : []));
|
|
582
|
+
btnTitle = input('', ...(ngDevMode ? [{ debugName: "btnTitle" }] : /* istanbul ignore next */ []));
|
|
584
583
|
btnClass = computed(() => {
|
|
585
584
|
const base = `wm-btn wm-btn--${this.variant()} wm-btn--${this.size()}`;
|
|
586
585
|
return this.iconOnly() ? `${base} btn-icon-only` : base;
|
|
587
|
-
}, ...(ngDevMode ? [{ debugName: "btnClass" }] : []));
|
|
588
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
589
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.
|
|
586
|
+
}, ...(ngDevMode ? [{ debugName: "btnClass" }] : /* istanbul ignore next */ []));
|
|
587
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
588
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: WmButton, isStandalone: true, selector: "wm-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, btnTitle: { classPropertyName: "btnTitle", publicName: "btnTitle", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<button\n [class]=\"btnClass()\"\n [disabled]=\"disabled()\"\n [type]=\"type()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.title]=\"btnTitle() || null\"\n>\n <ng-content />\n</button>\n", styles: [":host{display:inline-flex}\n"] });
|
|
590
589
|
}
|
|
591
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
590
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmButton, decorators: [{
|
|
592
591
|
type: Component,
|
|
593
592
|
args: [{ selector: 'wm-button', template: "<button\n [class]=\"btnClass()\"\n [disabled]=\"disabled()\"\n [type]=\"type()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.title]=\"btnTitle() || null\"\n>\n <ng-content />\n</button>\n", styles: [":host{display:inline-flex}\n"] }]
|
|
594
593
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], btnTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "btnTitle", required: false }] }] } });
|
|
@@ -615,31 +614,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
615
614
|
*/
|
|
616
615
|
class Checkbox {
|
|
617
616
|
/** Two-way bindable checked state. */
|
|
618
|
-
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
617
|
+
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
619
618
|
/**
|
|
620
619
|
* Shows a dash icon instead of a checkmark. Typically used for a "select all"
|
|
621
620
|
* checkbox when only some child items are selected.
|
|
622
621
|
* Note: indeterminate is display-only — clicking always toggles to true/false.
|
|
623
622
|
*/
|
|
624
|
-
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : []));
|
|
623
|
+
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
|
|
625
624
|
/** Visible text label rendered next to the checkbox box. */
|
|
626
|
-
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
627
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
625
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
626
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
628
627
|
/** Maps to aria-checked: true, false, or "mixed" (for indeterminate). */
|
|
629
628
|
ariaChecked = computed(() => {
|
|
630
629
|
if (this.indeterminate() && !this.checked())
|
|
631
630
|
return 'mixed';
|
|
632
631
|
return this.checked();
|
|
633
|
-
}, ...(ngDevMode ? [{ debugName: "ariaChecked" }] : []));
|
|
632
|
+
}, ...(ngDevMode ? [{ debugName: "ariaChecked" }] : /* istanbul ignore next */ []));
|
|
634
633
|
toggle() {
|
|
635
634
|
if (!this.disabled()) {
|
|
636
635
|
this.checked.update(v => !v);
|
|
637
636
|
}
|
|
638
637
|
}
|
|
639
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
640
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
638
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: Checkbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
639
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: Checkbox, isStandalone: true, selector: "wm-checkbox", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, ngImport: i0, template: "<label class=\"wm-checkbox-wrap\" [class.is-disabled]=\"disabled()\">\n <button\n type=\"button\"\n role=\"checkbox\"\n class=\"wm-checkbox-box\"\n [class.is-checked]=\"checked()\"\n [class.is-indeterminate]=\"indeterminate() && !checked()\"\n [attr.aria-checked]=\"ariaChecked()\"\n [attr.aria-disabled]=\"disabled() ? true : null\"\n [disabled]=\"disabled() || null\"\n (click)=\"toggle()\"\n (keydown.space)=\"$event.preventDefault(); toggle()\"\n >\n @if (indeterminate() && !checked()) {\n <!-- Dash for indeterminate (\"some selected\") state -->\n <svg class=\"wm-checkbox-icon\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <line x1=\"2\" y1=\"6\" x2=\"10\" y2=\"6\"\n stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\"/>\n </svg>\n } @else if (checked()) {\n <!-- Animated checkmark for selected state -->\n <svg class=\"wm-checkbox-icon\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <polyline class=\"check-mark\" points=\"2,6.5 4.5,9 10,3\"\n fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n }\n </button>\n\n @if (label()) {\n <span class=\"wm-checkbox-label\">{{ label() }}</span>\n }\n</label>\n", styles: [":host{display:inline-flex}.wm-checkbox-wrap{display:inline-flex;align-items:center;gap:.5rem;cursor:pointer;-webkit-user-select:none;user-select:none}.wm-checkbox-wrap.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.wm-checkbox-box{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex-shrink:0;border:2px solid var(--wm-border-input);border-radius:4px;background:var(--wm-bg-base);color:#fff;cursor:pointer;padding:0;outline:none;transition:background var(--wm-transition-fast),border-color var(--wm-transition-fast),box-shadow var(--wm-transition-fast)}.wm-checkbox-box:focus-visible{box-shadow:0 0 0 2px var(--wm-bg-base),0 0 0 4px var(--wm-color-accent)}.wm-checkbox-box.is-checked,.wm-checkbox-box.is-indeterminate{background:var(--wm-color-accent);border-color:var(--wm-color-accent-readable)}.wm-checkbox-icon{width:12px;height:12px;display:block;flex-shrink:0}@keyframes check-draw{0%{stroke-dashoffset:16}to{stroke-dashoffset:0}}.check-mark{stroke-dasharray:16;stroke-dashoffset:0;animation:check-draw .18s ease-out forwards}.wm-checkbox-label{font-size:.875rem;color:var(--wm-text-primary);line-height:1.4}@media(prefers-reduced-motion:reduce){.wm-checkbox-box{transition:none}.check-mark{animation:none}}\n"] });
|
|
641
640
|
}
|
|
642
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
641
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: Checkbox, decorators: [{
|
|
643
642
|
type: Component,
|
|
644
643
|
args: [{ selector: 'wm-checkbox', template: "<label class=\"wm-checkbox-wrap\" [class.is-disabled]=\"disabled()\">\n <button\n type=\"button\"\n role=\"checkbox\"\n class=\"wm-checkbox-box\"\n [class.is-checked]=\"checked()\"\n [class.is-indeterminate]=\"indeterminate() && !checked()\"\n [attr.aria-checked]=\"ariaChecked()\"\n [attr.aria-disabled]=\"disabled() ? true : null\"\n [disabled]=\"disabled() || null\"\n (click)=\"toggle()\"\n (keydown.space)=\"$event.preventDefault(); toggle()\"\n >\n @if (indeterminate() && !checked()) {\n <!-- Dash for indeterminate (\"some selected\") state -->\n <svg class=\"wm-checkbox-icon\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <line x1=\"2\" y1=\"6\" x2=\"10\" y2=\"6\"\n stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\"/>\n </svg>\n } @else if (checked()) {\n <!-- Animated checkmark for selected state -->\n <svg class=\"wm-checkbox-icon\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <polyline class=\"check-mark\" points=\"2,6.5 4.5,9 10,3\"\n fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n }\n </button>\n\n @if (label()) {\n <span class=\"wm-checkbox-label\">{{ label() }}</span>\n }\n</label>\n", styles: [":host{display:inline-flex}.wm-checkbox-wrap{display:inline-flex;align-items:center;gap:.5rem;cursor:pointer;-webkit-user-select:none;user-select:none}.wm-checkbox-wrap.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.wm-checkbox-box{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex-shrink:0;border:2px solid var(--wm-border-input);border-radius:4px;background:var(--wm-bg-base);color:#fff;cursor:pointer;padding:0;outline:none;transition:background var(--wm-transition-fast),border-color var(--wm-transition-fast),box-shadow var(--wm-transition-fast)}.wm-checkbox-box:focus-visible{box-shadow:0 0 0 2px var(--wm-bg-base),0 0 0 4px var(--wm-color-accent)}.wm-checkbox-box.is-checked,.wm-checkbox-box.is-indeterminate{background:var(--wm-color-accent);border-color:var(--wm-color-accent-readable)}.wm-checkbox-icon{width:12px;height:12px;display:block;flex-shrink:0}@keyframes check-draw{0%{stroke-dashoffset:16}to{stroke-dashoffset:0}}.check-mark{stroke-dasharray:16;stroke-dashoffset:0;animation:check-draw .18s ease-out forwards}.wm-checkbox-label{font-size:.875rem;color:var(--wm-text-primary);line-height:1.4}@media(prefers-reduced-motion:reduce){.wm-checkbox-box{transition:none}.check-mark{animation:none}}\n"] }]
|
|
645
644
|
}], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
@@ -674,17 +673,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
674
673
|
*/
|
|
675
674
|
class NumberInput {
|
|
676
675
|
/** Minimum allowed value. */
|
|
677
|
-
min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : []));
|
|
676
|
+
min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
678
677
|
/** Maximum allowed value. */
|
|
679
|
-
max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : []));
|
|
678
|
+
max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
680
679
|
/** Amount to increment/decrement per step. Defaults to 1. */
|
|
681
|
-
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : []));
|
|
680
|
+
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
|
|
682
681
|
/** Placeholder text shown when the field is empty. */
|
|
683
|
-
placeholder = input('0', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
682
|
+
placeholder = input('0', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
684
683
|
/** Disables the control from the template. Also set automatically by reactive forms. */
|
|
685
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
686
|
-
inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
687
|
-
internalValue = signal(null, ...(ngDevMode ? [{ debugName: "internalValue" }] : []));
|
|
684
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
685
|
+
inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : /* istanbul ignore next */ []));
|
|
686
|
+
internalValue = signal(null, ...(ngDevMode ? [{ debugName: "internalValue" }] : /* istanbul ignore next */ []));
|
|
688
687
|
onChangeFn = () => { };
|
|
689
688
|
onTouchedFn = () => { };
|
|
690
689
|
/** CVA interface — called when the form model changes programmatically. */
|
|
@@ -731,8 +730,8 @@ class NumberInput {
|
|
|
731
730
|
if (el)
|
|
732
731
|
el.nativeElement.value = String(val);
|
|
733
732
|
}
|
|
734
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
735
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.
|
|
733
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: NumberInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
734
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: NumberInput, isStandalone: true, selector: "wm-number-input", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
736
735
|
{
|
|
737
736
|
provide: NG_VALUE_ACCESSOR,
|
|
738
737
|
useExisting: forwardRef(() => NumberInput),
|
|
@@ -740,7 +739,7 @@ class NumberInput {
|
|
|
740
739
|
},
|
|
741
740
|
], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Uses .wm-input-group and .wm-number-* classes from inputs.css.\n The input fills the group; the controls column sits at the trailing edge.\n-->\n<div\n class=\"wm-input-group wm-number-field\"\n [class.is-disabled]=\"disabled()\"\n>\n <input\n #inputEl\n type=\"number\"\n class=\"wm-input-bare wm-number-input\"\n [value]=\"internalValue() ?? ''\"\n [placeholder]=\"placeholder()\"\n [attr.min]=\"min() ?? null\"\n [attr.max]=\"max() ?? null\"\n [step]=\"step()\"\n [disabled]=\"disabled() || null\"\n (change)=\"onInputChange($event)\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onTouchedFn()\"\n />\n\n <div class=\"wm-number-controls\" aria-hidden=\"true\">\n <button\n type=\"button\"\n class=\"wm-number-btn\"\n tabindex=\"-1\"\n [disabled]=\"disabled() || null\"\n (mousedown)=\"preventFocusSteal($event)\"\n (click)=\"increment()\"\n aria-label=\"Increment\"\n >\n <!-- chevron-up (lucide) -->\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m18 15-6-6-6 6\"/>\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wm-number-btn\"\n tabindex=\"-1\"\n [disabled]=\"disabled() || null\"\n (mousedown)=\"preventFocusSteal($event)\"\n (click)=\"decrement()\"\n aria-label=\"Decrement\"\n >\n <!-- chevron-down (lucide) -->\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\"/>\n </svg>\n </button>\n </div>\n</div>\n", styles: [":host{display:block}.wm-number-field.is-disabled{opacity:.45;pointer-events:none}\n"] });
|
|
742
741
|
}
|
|
743
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
742
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: NumberInput, decorators: [{
|
|
744
743
|
type: Component,
|
|
745
744
|
args: [{ selector: 'wm-number-input', providers: [
|
|
746
745
|
{
|
|
@@ -766,24 +765,350 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
766
765
|
*/
|
|
767
766
|
class Toggle {
|
|
768
767
|
/** Two-way bindable state. Use [(checked)]="mySignal" or [checked]="val" (changeChecked)="val=$event". */
|
|
769
|
-
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
|
|
768
|
+
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
770
769
|
/** Visually and functionally disables the toggle. State is still readable by assistive tech. */
|
|
771
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
770
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
772
771
|
/** Accessible label. Required if no visible label text surrounds the toggle in the DOM. */
|
|
773
|
-
ariaLabel = input('Toggle', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
772
|
+
ariaLabel = input('Toggle', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
774
773
|
toggle() {
|
|
775
774
|
if (!this.disabled()) {
|
|
776
775
|
this.checked.update(v => !v);
|
|
777
776
|
}
|
|
778
777
|
}
|
|
779
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
780
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.
|
|
778
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: Toggle, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
779
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: Toggle, isStandalone: true, selector: "wm-toggle", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, ngImport: i0, template: "<button\n type=\"button\"\n role=\"switch\"\n class=\"wm-toggle\"\n [class.is-on]=\"checked()\"\n [class.is-disabled]=\"disabled()\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-disabled]=\"disabled() ? true : null\"\n [disabled]=\"disabled() || null\"\n (click)=\"toggle()\"\n>\n <span class=\"wm-toggle-track\" aria-hidden=\"true\">\n <span class=\"wm-toggle-thumb\"></span>\n </span>\n</button>\n", styles: [":host{display:inline-flex}.wm-toggle{display:inline-flex;align-items:center;background:none;border:none;padding:2px;margin:-2px;cursor:pointer;border-radius:var(--wm-radius-full);outline:none}.wm-toggle:focus-visible .wm-toggle-track{outline:2px solid var(--wm-color-accent);outline-offset:2px}.wm-toggle.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.wm-toggle-track{position:relative;width:40px;height:22px;background:var(--wm-border-input);border-radius:var(--wm-radius-full);transition:background var(--wm-transition-fast);flex-shrink:0}.wm-toggle.is-on .wm-toggle-track{background:var(--wm-color-accent)}.wm-toggle-thumb{position:absolute;top:3px;left:3px;width:16px;height:16px;background:#fff;border-radius:var(--wm-radius-full);box-shadow:0 1px 3px #00000040;transition:transform var(--wm-transition-fast)}.wm-toggle.is-on .wm-toggle-thumb{transform:translate(18px)}@media(prefers-reduced-motion:reduce){.wm-toggle-track,.wm-toggle-thumb{transition:none}}\n"] });
|
|
781
780
|
}
|
|
782
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
781
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: Toggle, decorators: [{
|
|
783
782
|
type: Component,
|
|
784
783
|
args: [{ selector: 'wm-toggle', template: "<button\n type=\"button\"\n role=\"switch\"\n class=\"wm-toggle\"\n [class.is-on]=\"checked()\"\n [class.is-disabled]=\"disabled()\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-disabled]=\"disabled() ? true : null\"\n [disabled]=\"disabled() || null\"\n (click)=\"toggle()\"\n>\n <span class=\"wm-toggle-track\" aria-hidden=\"true\">\n <span class=\"wm-toggle-thumb\"></span>\n </span>\n</button>\n", styles: [":host{display:inline-flex}.wm-toggle{display:inline-flex;align-items:center;background:none;border:none;padding:2px;margin:-2px;cursor:pointer;border-radius:var(--wm-radius-full);outline:none}.wm-toggle:focus-visible .wm-toggle-track{outline:2px solid var(--wm-color-accent);outline-offset:2px}.wm-toggle.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.wm-toggle-track{position:relative;width:40px;height:22px;background:var(--wm-border-input);border-radius:var(--wm-radius-full);transition:background var(--wm-transition-fast);flex-shrink:0}.wm-toggle.is-on .wm-toggle-track{background:var(--wm-color-accent)}.wm-toggle-thumb{position:absolute;top:3px;left:3px;width:16px;height:16px;background:#fff;border-radius:var(--wm-radius-full);box-shadow:0 1px 3px #00000040;transition:transform var(--wm-transition-fast)}.wm-toggle.is-on .wm-toggle-thumb{transform:translate(18px)}@media(prefers-reduced-motion:reduce){.wm-toggle-track,.wm-toggle-thumb{transition:none}}\n"] }]
|
|
785
784
|
}], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
786
785
|
|
|
786
|
+
/**
|
|
787
|
+
* Upper bound on generated marks. A numeric interval that would exceed it draws
|
|
788
|
+
* NOTHING rather than a truncated grid or a frozen tab: an empty rail is
|
|
789
|
+
* obviously wrong to whoever set it, where a silently shortened grid is not.
|
|
790
|
+
*/
|
|
791
|
+
const MAX_TICKS = 1000;
|
|
792
|
+
/**
|
|
793
|
+
* Upper bound on reserved readout strings. Only labelled stops reach this, so
|
|
794
|
+
* it is a guard against a pathological grid rather than a limit anyone meets.
|
|
795
|
+
*/
|
|
796
|
+
const MAX_VALUE_CANDIDATES = 64;
|
|
797
|
+
/**
|
|
798
|
+
* WmSlider — Continuous value selection along a bounded range.
|
|
799
|
+
*
|
|
800
|
+
* Built on a native `<input type="range">`. The native control is the whole
|
|
801
|
+
* interaction: pointer drag, touch, arrow keys, Home/End, Page Up/Page Down,
|
|
802
|
+
* RTL mirroring and the implicit `role="slider"` with `aria-valuenow` all come
|
|
803
|
+
* from the browser rather than from hand-written handlers. Aegis styles the
|
|
804
|
+
* track and thumb through the range pseudo-elements, so there is no invisible
|
|
805
|
+
* overlay input and no drag maths to get wrong.
|
|
806
|
+
*
|
|
807
|
+
* When to use:
|
|
808
|
+
* - A bounded value where the approximate position matters more than the exact
|
|
809
|
+
* number (volume, opacity, zoom, a brightness or threshold setting)
|
|
810
|
+
* - A value the user wants to sweep through and preview as it changes
|
|
811
|
+
*
|
|
812
|
+
* When NOT to use:
|
|
813
|
+
* - An exact number the user knows before they start typing it → <wm-number-input>
|
|
814
|
+
* - Fewer than about five discrete choices → <wm-select> or a pill tab group
|
|
815
|
+
* - An unbounded value — a slider has to have a min and a max
|
|
816
|
+
*
|
|
817
|
+
* Value pipeline: every value, whether it arrives from a two-way binding, a
|
|
818
|
+
* form, or a drag, is clamped into min..max and snapped onto the step grid
|
|
819
|
+
* measured FROM MIN. The snapped value is written back, so the binding, the
|
|
820
|
+
* form control and the thumb never disagree.
|
|
821
|
+
*
|
|
822
|
+
* Accessibility:
|
|
823
|
+
* - The native input is the focusable control and carries the slider role.
|
|
824
|
+
* - `ariaLabel` is required unless visible surrounding text names the control.
|
|
825
|
+
* - `formatValue` also drives `aria-valuetext`, so a screen reader announces
|
|
826
|
+
* "40 percent" rather than "40" when the raw number means nothing alone.
|
|
827
|
+
* - Ticks and the value readout are decoration; the native value is the truth.
|
|
828
|
+
*
|
|
829
|
+
* Form integration:
|
|
830
|
+
* <!-- Template-driven -->
|
|
831
|
+
* <wm-slider [(ngModel)]="volume" [min]="0" [max]="100" />
|
|
832
|
+
*
|
|
833
|
+
* <!-- Reactive -->
|
|
834
|
+
* <wm-slider formControlName="opacity" [min]="0" [max]="1" [step]="0.05" />
|
|
835
|
+
*
|
|
836
|
+
* <!-- Two-way signal binding, no forms -->
|
|
837
|
+
* <wm-slider [(value)]="volume" ariaLabel="Volume" />
|
|
838
|
+
*/
|
|
839
|
+
class WmSlider {
|
|
840
|
+
/** Two-way bindable value. Always reads back clamped and snapped to the step grid. */
|
|
841
|
+
value = model(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
842
|
+
/** Lower bound, inclusive. */
|
|
843
|
+
min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
844
|
+
/** Upper bound, inclusive. Values never exceed it, even when it is off the step grid. */
|
|
845
|
+
max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
846
|
+
/** Grid spacing, measured from `min`. Use 0 for a continuous slider. */
|
|
847
|
+
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
|
|
848
|
+
/** Disables the control from the template. Reactive forms set this independently. */
|
|
849
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
850
|
+
/** Accessible name. Required unless visible text already names the control. */
|
|
851
|
+
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
852
|
+
/** Shows a live readout beside the rail. */
|
|
853
|
+
showValue = input(false, ...(ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []));
|
|
854
|
+
/**
|
|
855
|
+
* Renders the value for humans. Also sets `aria-valuetext`, so pass one
|
|
856
|
+
* whenever the bare number would not be understood on its own.
|
|
857
|
+
*/
|
|
858
|
+
formatValue = input(null, ...(ngDevMode ? [{ debugName: "formatValue" }] : /* istanbul ignore next */ []));
|
|
859
|
+
/**
|
|
860
|
+
* How the track is drawn. `rail` is one continuous bar. `segmented` breaks it
|
|
861
|
+
* into blocks bounded by the grid stops, and the block holding the value fills
|
|
862
|
+
* partially — so a segmented track does not have to mean one block per step,
|
|
863
|
+
* and survives a dense range that one-block-per-step cannot.
|
|
864
|
+
*/
|
|
865
|
+
track = input('rail', ...(ngDevMode ? [{ debugName: "track" }] : /* istanbul ignore next */ []));
|
|
866
|
+
/**
|
|
867
|
+
* The grid, in one of three shapes:
|
|
868
|
+
* - a **number** — a stop every N, measured from `min`
|
|
869
|
+
* - an **array** of {@link WmSliderTick} — explicit stops, with labels and levels
|
|
870
|
+
* - a **{@link WmSliderTickFn}** — computed from the live range
|
|
871
|
+
*
|
|
872
|
+
* Whatever the shape, the result is clamped to the range, sorted, and
|
|
873
|
+
* de-duplicated. The same resolved grid draws the marks AND bounds the blocks
|
|
874
|
+
* of a segmented track, so the two renderings cannot disagree.
|
|
875
|
+
*
|
|
876
|
+
* The grid is deliberately independent of `step`: a 0–100 slider stepping by 1
|
|
877
|
+
* carries 101 reachable values and should still draw about 11 marks.
|
|
878
|
+
*/
|
|
879
|
+
ticks = input([], ...(ngDevMode ? [{ debugName: "ticks" }] : /* istanbul ignore next */ []));
|
|
880
|
+
/** Set by reactive forms through setDisabledState, independent of the input. */
|
|
881
|
+
formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
|
|
882
|
+
isDisabled = computed(() => this.disabled() || this.formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
883
|
+
/** Position of the thumb across the span, 0..1, as a CSS-ready string. */
|
|
884
|
+
fraction = computed(() => trim(this.fractionOf(this.value())), ...(ngDevMode ? [{ debugName: "fraction" }] : /* istanbul ignore next */ []));
|
|
885
|
+
displayValue = computed(() => {
|
|
886
|
+
const format = this.formatValue();
|
|
887
|
+
return format ? format(this.value()) : String(this.value());
|
|
888
|
+
}, ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
889
|
+
/**
|
|
890
|
+
* Every string the readout can show at a grid stop, de-duplicated.
|
|
891
|
+
*
|
|
892
|
+
* The shell is `1fr auto`, so a readout column sized by the CURRENT value
|
|
893
|
+
* takes its width from the rail and gives it back on the next value — the bar
|
|
894
|
+
* moves while you drag it. Rendering these hidden in the readout's own grid
|
|
895
|
+
* cell makes the browser reserve the widest of them once, with no measuring.
|
|
896
|
+
*
|
|
897
|
+
* Only LABELLED stops contribute. An unlabelled stop is a position rather
|
|
898
|
+
* than a word, and a numeric readout is already bounded by tabular numerals
|
|
899
|
+
* and the two endpoints — so a 101-mark grid reserves two slots, not 101.
|
|
900
|
+
*/
|
|
901
|
+
valueCandidates = computed(() => {
|
|
902
|
+
const format = this.formatValue();
|
|
903
|
+
const render = (value) => (format ? format(value) : String(value));
|
|
904
|
+
const values = [
|
|
905
|
+
this.min(),
|
|
906
|
+
this.max(),
|
|
907
|
+
...this.resolvedTicks()
|
|
908
|
+
.filter(tick => tick.label !== undefined)
|
|
909
|
+
.map(tick => tick.value),
|
|
910
|
+
];
|
|
911
|
+
const out = new Set();
|
|
912
|
+
for (const value of values) {
|
|
913
|
+
out.add(render(value));
|
|
914
|
+
if (out.size >= MAX_VALUE_CANDIDATES)
|
|
915
|
+
break;
|
|
916
|
+
}
|
|
917
|
+
return [...out];
|
|
918
|
+
}, ...(ngDevMode ? [{ debugName: "valueCandidates" }] : /* istanbul ignore next */ []));
|
|
919
|
+
/** Null unless a formatter is set — a valuetext echoing valuenow is noise. */
|
|
920
|
+
valueText = computed(() => {
|
|
921
|
+
const format = this.formatValue();
|
|
922
|
+
return format ? format(this.value()) : null;
|
|
923
|
+
}, ...(ngDevMode ? [{ debugName: "valueText" }] : /* istanbul ignore next */ []));
|
|
924
|
+
/** The declared grid, before it is measured against the range. */
|
|
925
|
+
declaredTicks = computed(() => {
|
|
926
|
+
const raw = this.ticks();
|
|
927
|
+
if (typeof raw === 'number') {
|
|
928
|
+
return gridEvery(this.min(), this.max(), raw);
|
|
929
|
+
}
|
|
930
|
+
if (typeof raw === 'function') {
|
|
931
|
+
return raw({ min: this.min(), max: this.max(), step: this.step() }) ?? [];
|
|
932
|
+
}
|
|
933
|
+
return raw ?? [];
|
|
934
|
+
}, ...(ngDevMode ? [{ debugName: "declaredTicks" }] : /* istanbul ignore next */ []));
|
|
935
|
+
resolvedTicks = computed(() => {
|
|
936
|
+
const min = this.min();
|
|
937
|
+
const max = this.max();
|
|
938
|
+
const current = this.value();
|
|
939
|
+
const seen = new Set();
|
|
940
|
+
return this.declaredTicks()
|
|
941
|
+
.filter(tick => tick.value >= min && tick.value <= max)
|
|
942
|
+
// A duplicate value is not cosmetic — two marks at one value collide on
|
|
943
|
+
// the @for track key and Angular throws. First declaration wins, so an
|
|
944
|
+
// explicit label is never dropped in favour of a bare repeat.
|
|
945
|
+
.filter(tick => {
|
|
946
|
+
if (seen.has(tick.value))
|
|
947
|
+
return false;
|
|
948
|
+
seen.add(tick.value);
|
|
949
|
+
return true;
|
|
950
|
+
})
|
|
951
|
+
.sort((a, b) => a.value - b.value)
|
|
952
|
+
.map(tick => {
|
|
953
|
+
const fraction = this.fractionOf(tick.value);
|
|
954
|
+
return {
|
|
955
|
+
...tick,
|
|
956
|
+
level: tick.level ?? 'major',
|
|
957
|
+
fraction,
|
|
958
|
+
left: `calc(var(--wm-slider-thumb) / 2 + ${trim(fraction)} * (100% - var(--wm-slider-thumb)))`,
|
|
959
|
+
passed: tick.value <= current,
|
|
960
|
+
};
|
|
961
|
+
});
|
|
962
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedTicks" }] : /* istanbul ignore next */ []));
|
|
963
|
+
/**
|
|
964
|
+
* Blocks of a segmented track. The boundaries are the grid stops plus the two
|
|
965
|
+
* ends of the range, so the blocks are the intervals BETWEEN stops — which is
|
|
966
|
+
* what a block can honestly represent. Each one is sized by its own span, so
|
|
967
|
+
* an uneven grid produces uneven blocks rather than lying about the scale.
|
|
968
|
+
*/
|
|
969
|
+
segments = computed(() => {
|
|
970
|
+
if (this.track() !== 'segmented')
|
|
971
|
+
return [];
|
|
972
|
+
const min = this.min();
|
|
973
|
+
const max = this.max();
|
|
974
|
+
if (max <= min)
|
|
975
|
+
return [];
|
|
976
|
+
const current = this.value();
|
|
977
|
+
const bounds = [...new Set([min, ...this.resolvedTicks().map(t => t.value), max])].sort((a, b) => a - b);
|
|
978
|
+
const out = [];
|
|
979
|
+
for (let i = 0; i < bounds.length - 1; i++) {
|
|
980
|
+
const from = bounds[i];
|
|
981
|
+
const to = bounds[i + 1];
|
|
982
|
+
const span = to - from;
|
|
983
|
+
if (span <= 0)
|
|
984
|
+
continue;
|
|
985
|
+
const fill = Math.min(Math.max((current - from) / span, 0), 1);
|
|
986
|
+
out.push({
|
|
987
|
+
from,
|
|
988
|
+
to,
|
|
989
|
+
span,
|
|
990
|
+
fill,
|
|
991
|
+
passed: fill >= 1,
|
|
992
|
+
current: fill > 0 && fill < 1,
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
return out;
|
|
996
|
+
}, ...(ngDevMode ? [{ debugName: "segments" }] : /* istanbul ignore next */ []));
|
|
997
|
+
hasTickLabels = computed(() => this.resolvedTicks().some(tick => tick.label !== undefined), ...(ngDevMode ? [{ debugName: "hasTickLabels" }] : /* istanbul ignore next */ []));
|
|
998
|
+
onChangeFn = () => { };
|
|
999
|
+
onTouchedFn = () => { };
|
|
1000
|
+
constructor() {
|
|
1001
|
+
// Normalisation runs on the value itself rather than on a derived signal,
|
|
1002
|
+
// so a caller that binds [(value)] or a form control gets the corrected
|
|
1003
|
+
// number back instead of holding one the thumb does not sit on.
|
|
1004
|
+
effect(() => {
|
|
1005
|
+
const resolved = this.resolve(this.value());
|
|
1006
|
+
if (resolved !== this.value()) {
|
|
1007
|
+
this.value.set(resolved);
|
|
1008
|
+
this.onChangeFn(resolved);
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
writeValue(value) {
|
|
1013
|
+
this.value.set(this.resolve(value ?? this.min()));
|
|
1014
|
+
}
|
|
1015
|
+
registerOnChange(fn) {
|
|
1016
|
+
this.onChangeFn = fn;
|
|
1017
|
+
}
|
|
1018
|
+
registerOnTouched(fn) {
|
|
1019
|
+
this.onTouchedFn = fn;
|
|
1020
|
+
}
|
|
1021
|
+
setDisabledState(isDisabled) {
|
|
1022
|
+
this.formDisabled.set(isDisabled);
|
|
1023
|
+
}
|
|
1024
|
+
onRangeInput(event) {
|
|
1025
|
+
const resolved = this.resolve(Number(event.target.value));
|
|
1026
|
+
this.value.set(resolved);
|
|
1027
|
+
this.onChangeFn(resolved);
|
|
1028
|
+
}
|
|
1029
|
+
/** Clamps into min..max, then snaps onto the step grid measured from min. */
|
|
1030
|
+
resolve(raw) {
|
|
1031
|
+
const min = this.min();
|
|
1032
|
+
const max = this.max();
|
|
1033
|
+
if (!Number.isFinite(raw))
|
|
1034
|
+
return min;
|
|
1035
|
+
if (max <= min)
|
|
1036
|
+
return min;
|
|
1037
|
+
const clamped = Math.min(Math.max(raw, min), max);
|
|
1038
|
+
const step = this.step();
|
|
1039
|
+
if (!Number.isFinite(step) || step <= 0)
|
|
1040
|
+
return clamped;
|
|
1041
|
+
// Rounding through a fixed number of decimals keeps a 0.1 grid on 0.3
|
|
1042
|
+
// rather than 0.30000000000000004, which would then render and compare
|
|
1043
|
+
// as a different number than the one the caller asked for.
|
|
1044
|
+
const decimals = decimalsOf(step) + decimalsOf(min);
|
|
1045
|
+
const snapped = round(min + Math.round((clamped - min) / step) * step, decimals);
|
|
1046
|
+
// Snapping up can overshoot a max that is not a whole number of steps
|
|
1047
|
+
// above min; the last reachable stop is one step back.
|
|
1048
|
+
return snapped > max ? round(snapped - step, decimals) : snapped;
|
|
1049
|
+
}
|
|
1050
|
+
fractionOf(value) {
|
|
1051
|
+
const span = this.max() - this.min();
|
|
1052
|
+
if (span <= 0)
|
|
1053
|
+
return 0;
|
|
1054
|
+
return (value - this.min()) / span;
|
|
1055
|
+
}
|
|
1056
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmSlider, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1057
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmSlider, isStandalone: true, selector: "wm-slider", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, formatValue: { classPropertyName: "formatValue", publicName: "formatValue", isSignal: true, isRequired: false, transformFunction: null }, track: { classPropertyName: "track", publicName: "track", isSignal: true, isRequired: false, transformFunction: null }, ticks: { classPropertyName: "ticks", publicName: "ticks", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
|
|
1058
|
+
{
|
|
1059
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1060
|
+
useExisting: forwardRef(() => WmSlider),
|
|
1061
|
+
multi: true,
|
|
1062
|
+
},
|
|
1063
|
+
], ngImport: i0, template: "<!--\n The native <input type=\"range\"> is the control, not a decoration over one:\n its track and thumb are the styled surfaces. --wm-slider-p carries the thumb\n position to the CSS so the filled part of the track, every tick and every\n block are placed from the same number the thumb is.\n-->\n<div\n class=\"wm-slider\"\n [attr.data-track]=\"track()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.has-ticks]=\"resolvedTicks().length > 0\"\n [style.--wm-slider-p]=\"fraction()\"\n>\n <div class=\"wm-slider-rail\">\n @if (segments().length > 0) {\n <!--\n Blocks sit under the transparent native track. They are bounded by the\n same resolved grid the marks come from, so a block and the mark on its\n edge can never disagree about where a value falls.\n -->\n <div class=\"wm-slider-segments\" aria-hidden=\"true\">\n @for (segment of segments(); track segment.from) {\n <span\n class=\"wm-slider-seg\"\n [class.is-passed]=\"segment.passed\"\n [class.is-current]=\"segment.current\"\n [style.flexGrow]=\"segment.span\"\n [style.--wm-slider-seg-p]=\"segment.fill\"\n ></span>\n }\n </div>\n }\n\n @if (resolvedTicks().length > 0) {\n <div class=\"wm-slider-ticks\" aria-hidden=\"true\">\n @for (tick of resolvedTicks(); track tick.value) {\n <span\n class=\"wm-slider-tick\"\n [class.wm-slider-tick--minor]=\"tick.level === 'minor'\"\n [class.is-passed]=\"tick.passed\"\n [style.left]=\"tick.left\"\n ></span>\n }\n </div>\n }\n\n <input\n class=\"wm-slider-input\"\n type=\"range\"\n [value]=\"value()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step() > 0 ? step() : 'any'\"\n [disabled]=\"isDisabled() || null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-valuetext]=\"valueText()\"\n (input)=\"onRangeInput($event)\"\n (blur)=\"onTouchedFn()\"\n />\n </div>\n\n @if (showValue()) {\n <!--\n The sizers stack on the output in one grid cell, so the column reserves\n the widest string the readout can hold and stops stealing width from the\n rail every time the value changes.\n -->\n <div class=\"wm-slider-value-cell\">\n <output class=\"wm-slider-value\">{{ displayValue() }}</output>\n @for (candidate of valueCandidates(); track candidate) {\n <span class=\"wm-slider-value-sizer\" aria-hidden=\"true\">{{ candidate }}</span>\n }\n </div>\n }\n\n @if (hasTickLabels()) {\n <div class=\"wm-slider-tick-labels\" aria-hidden=\"true\">\n @for (tick of resolvedTicks(); track tick.value) {\n @if (tick.label !== undefined) {\n <span class=\"wm-slider-tick-label\" [style.left]=\"tick.left\">{{ tick.label }}</span>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.wm-slider{--wm-slider-thumb: 16px;--wm-slider-track: 4px;--wm-slider-gap: 3px;--wm-slider-p: 0;--wm-slider-stop: calc( var(--wm-slider-thumb) / 2 + var(--wm-slider-p) * (100% - var(--wm-slider-thumb)) );--wm-slider-fill: linear-gradient( to right, var(--wm-color-accent) 0 var(--wm-slider-stop), var(--wm-border-input) var(--wm-slider-stop) 100% );display:grid;grid-template-columns:1fr auto;align-items:center;column-gap:.75rem;row-gap:.375rem}.wm-slider-rail{position:relative;min-width:0}.wm-slider.has-ticks .wm-slider-rail{margin-bottom:10px}.wm-slider-input{-webkit-appearance:none;appearance:none;display:block;width:100%;height:var(--wm-slider-thumb);margin:0;padding:0;background:transparent;cursor:pointer;position:relative;z-index:1}.wm-slider-input:focus{outline:none}.wm-slider-input::-webkit-slider-runnable-track{height:var(--wm-slider-track);border-radius:var(--wm-radius-full);background:var(--wm-slider-fill)}.wm-slider-input::-webkit-slider-thumb{-webkit-appearance:none;width:var(--wm-slider-thumb);height:var(--wm-slider-thumb);margin-top:calc((var(--wm-slider-track) - var(--wm-slider-thumb)) / 2);border-radius:var(--wm-radius-full);background:var(--wm-color-accent);border:2px solid var(--wm-bg-base);box-shadow:var(--wm-shadow-sm);transition:background var(--wm-transition-fast),transform var(--wm-transition-fast)}.wm-slider-input:hover::-webkit-slider-thumb{background:var(--wm-color-accent-hover);transform:scale(1.12)}.wm-slider-input:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--wm-bg-base),0 0 0 4px var(--wm-color-accent)}.wm-slider-input::-moz-range-track{height:var(--wm-slider-track);border-radius:var(--wm-radius-full);background:var(--wm-slider-fill)}.wm-slider-input::-moz-range-thumb{width:var(--wm-slider-thumb);height:var(--wm-slider-thumb);box-sizing:border-box;border-radius:var(--wm-radius-full);background:var(--wm-color-accent);border:2px solid var(--wm-bg-base);box-shadow:var(--wm-shadow-sm);transition:background var(--wm-transition-fast),transform var(--wm-transition-fast)}.wm-slider-input:hover::-moz-range-thumb{background:var(--wm-color-accent-hover);transform:scale(1.12)}.wm-slider-input:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px var(--wm-bg-base),0 0 0 4px var(--wm-color-accent)}.wm-slider-ticks{position:absolute;inset-inline:0;top:100%;margin-top:2px;height:6px;pointer-events:none}.wm-slider-tick{position:absolute;top:0;width:2px;height:6px;margin-left:-1px;border-radius:1px;background:var(--wm-border-input);transition:background var(--wm-transition-fast)}.wm-slider-tick.is-passed{background:var(--wm-color-accent)}.wm-slider-tick--minor{height:3px;background:var(--wm-border-subtle)}.wm-slider-tick--minor.is-passed{background:color-mix(in srgb,var(--wm-color-accent) 55%,transparent)}.wm-slider[data-track=segmented]{--wm-slider-fill: none}.wm-slider-segments{position:absolute;inset:0 calc(var(--wm-slider-thumb) / 2);display:flex;align-items:center;gap:var(--wm-slider-gap);pointer-events:none}.wm-slider-seg{flex-basis:0;min-width:0;height:var(--wm-slider-track);border-radius:1px;background:var(--wm-border-input);transition:background var(--wm-transition-fast)}.wm-slider-seg.is-passed{background:var(--wm-color-accent)}.wm-slider-seg.is-current{background-image:linear-gradient(var(--wm-color-accent) 0 0);background-repeat:no-repeat;background-size:calc(var(--wm-slider-seg-p, 0) * 100%) 100%}.wm-slider-tick-labels{position:relative;grid-column:1;height:1rem}.wm-slider-tick-label{position:absolute;top:0;transform:translate(-50%);font-size:.75rem;color:var(--wm-text-muted);white-space:nowrap}.wm-slider-value-cell{grid-area:1 / 2;display:grid;justify-items:end}.wm-slider-value,.wm-slider-value-sizer{grid-area:1 / 1;font-family:var(--wm-font-mono);font-size:.8125rem;font-variant-numeric:tabular-nums;white-space:nowrap}.wm-slider-value{color:var(--wm-text-secondary);min-width:4ch;text-align:right}.wm-slider-value-sizer{visibility:hidden;pointer-events:none}.wm-slider.is-disabled{opacity:.5}.wm-slider-input:disabled{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.wm-slider-input::-webkit-slider-thumb,.wm-slider-input::-moz-range-thumb,.wm-slider-tick{transition:none}.wm-slider-input:hover::-webkit-slider-thumb,.wm-slider-input:hover::-moz-range-thumb{transform:none}}\n"] });
|
|
1064
|
+
}
|
|
1065
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmSlider, decorators: [{
|
|
1066
|
+
type: Component,
|
|
1067
|
+
args: [{ selector: 'wm-slider', providers: [
|
|
1068
|
+
{
|
|
1069
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1070
|
+
useExisting: forwardRef(() => WmSlider),
|
|
1071
|
+
multi: true,
|
|
1072
|
+
},
|
|
1073
|
+
], template: "<!--\n The native <input type=\"range\"> is the control, not a decoration over one:\n its track and thumb are the styled surfaces. --wm-slider-p carries the thumb\n position to the CSS so the filled part of the track, every tick and every\n block are placed from the same number the thumb is.\n-->\n<div\n class=\"wm-slider\"\n [attr.data-track]=\"track()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.has-ticks]=\"resolvedTicks().length > 0\"\n [style.--wm-slider-p]=\"fraction()\"\n>\n <div class=\"wm-slider-rail\">\n @if (segments().length > 0) {\n <!--\n Blocks sit under the transparent native track. They are bounded by the\n same resolved grid the marks come from, so a block and the mark on its\n edge can never disagree about where a value falls.\n -->\n <div class=\"wm-slider-segments\" aria-hidden=\"true\">\n @for (segment of segments(); track segment.from) {\n <span\n class=\"wm-slider-seg\"\n [class.is-passed]=\"segment.passed\"\n [class.is-current]=\"segment.current\"\n [style.flexGrow]=\"segment.span\"\n [style.--wm-slider-seg-p]=\"segment.fill\"\n ></span>\n }\n </div>\n }\n\n @if (resolvedTicks().length > 0) {\n <div class=\"wm-slider-ticks\" aria-hidden=\"true\">\n @for (tick of resolvedTicks(); track tick.value) {\n <span\n class=\"wm-slider-tick\"\n [class.wm-slider-tick--minor]=\"tick.level === 'minor'\"\n [class.is-passed]=\"tick.passed\"\n [style.left]=\"tick.left\"\n ></span>\n }\n </div>\n }\n\n <input\n class=\"wm-slider-input\"\n type=\"range\"\n [value]=\"value()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [step]=\"step() > 0 ? step() : 'any'\"\n [disabled]=\"isDisabled() || null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-valuetext]=\"valueText()\"\n (input)=\"onRangeInput($event)\"\n (blur)=\"onTouchedFn()\"\n />\n </div>\n\n @if (showValue()) {\n <!--\n The sizers stack on the output in one grid cell, so the column reserves\n the widest string the readout can hold and stops stealing width from the\n rail every time the value changes.\n -->\n <div class=\"wm-slider-value-cell\">\n <output class=\"wm-slider-value\">{{ displayValue() }}</output>\n @for (candidate of valueCandidates(); track candidate) {\n <span class=\"wm-slider-value-sizer\" aria-hidden=\"true\">{{ candidate }}</span>\n }\n </div>\n }\n\n @if (hasTickLabels()) {\n <div class=\"wm-slider-tick-labels\" aria-hidden=\"true\">\n @for (tick of resolvedTicks(); track tick.value) {\n @if (tick.label !== undefined) {\n <span class=\"wm-slider-tick-label\" [style.left]=\"tick.left\">{{ tick.label }}</span>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.wm-slider{--wm-slider-thumb: 16px;--wm-slider-track: 4px;--wm-slider-gap: 3px;--wm-slider-p: 0;--wm-slider-stop: calc( var(--wm-slider-thumb) / 2 + var(--wm-slider-p) * (100% - var(--wm-slider-thumb)) );--wm-slider-fill: linear-gradient( to right, var(--wm-color-accent) 0 var(--wm-slider-stop), var(--wm-border-input) var(--wm-slider-stop) 100% );display:grid;grid-template-columns:1fr auto;align-items:center;column-gap:.75rem;row-gap:.375rem}.wm-slider-rail{position:relative;min-width:0}.wm-slider.has-ticks .wm-slider-rail{margin-bottom:10px}.wm-slider-input{-webkit-appearance:none;appearance:none;display:block;width:100%;height:var(--wm-slider-thumb);margin:0;padding:0;background:transparent;cursor:pointer;position:relative;z-index:1}.wm-slider-input:focus{outline:none}.wm-slider-input::-webkit-slider-runnable-track{height:var(--wm-slider-track);border-radius:var(--wm-radius-full);background:var(--wm-slider-fill)}.wm-slider-input::-webkit-slider-thumb{-webkit-appearance:none;width:var(--wm-slider-thumb);height:var(--wm-slider-thumb);margin-top:calc((var(--wm-slider-track) - var(--wm-slider-thumb)) / 2);border-radius:var(--wm-radius-full);background:var(--wm-color-accent);border:2px solid var(--wm-bg-base);box-shadow:var(--wm-shadow-sm);transition:background var(--wm-transition-fast),transform var(--wm-transition-fast)}.wm-slider-input:hover::-webkit-slider-thumb{background:var(--wm-color-accent-hover);transform:scale(1.12)}.wm-slider-input:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--wm-bg-base),0 0 0 4px var(--wm-color-accent)}.wm-slider-input::-moz-range-track{height:var(--wm-slider-track);border-radius:var(--wm-radius-full);background:var(--wm-slider-fill)}.wm-slider-input::-moz-range-thumb{width:var(--wm-slider-thumb);height:var(--wm-slider-thumb);box-sizing:border-box;border-radius:var(--wm-radius-full);background:var(--wm-color-accent);border:2px solid var(--wm-bg-base);box-shadow:var(--wm-shadow-sm);transition:background var(--wm-transition-fast),transform var(--wm-transition-fast)}.wm-slider-input:hover::-moz-range-thumb{background:var(--wm-color-accent-hover);transform:scale(1.12)}.wm-slider-input:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px var(--wm-bg-base),0 0 0 4px var(--wm-color-accent)}.wm-slider-ticks{position:absolute;inset-inline:0;top:100%;margin-top:2px;height:6px;pointer-events:none}.wm-slider-tick{position:absolute;top:0;width:2px;height:6px;margin-left:-1px;border-radius:1px;background:var(--wm-border-input);transition:background var(--wm-transition-fast)}.wm-slider-tick.is-passed{background:var(--wm-color-accent)}.wm-slider-tick--minor{height:3px;background:var(--wm-border-subtle)}.wm-slider-tick--minor.is-passed{background:color-mix(in srgb,var(--wm-color-accent) 55%,transparent)}.wm-slider[data-track=segmented]{--wm-slider-fill: none}.wm-slider-segments{position:absolute;inset:0 calc(var(--wm-slider-thumb) / 2);display:flex;align-items:center;gap:var(--wm-slider-gap);pointer-events:none}.wm-slider-seg{flex-basis:0;min-width:0;height:var(--wm-slider-track);border-radius:1px;background:var(--wm-border-input);transition:background var(--wm-transition-fast)}.wm-slider-seg.is-passed{background:var(--wm-color-accent)}.wm-slider-seg.is-current{background-image:linear-gradient(var(--wm-color-accent) 0 0);background-repeat:no-repeat;background-size:calc(var(--wm-slider-seg-p, 0) * 100%) 100%}.wm-slider-tick-labels{position:relative;grid-column:1;height:1rem}.wm-slider-tick-label{position:absolute;top:0;transform:translate(-50%);font-size:.75rem;color:var(--wm-text-muted);white-space:nowrap}.wm-slider-value-cell{grid-area:1 / 2;display:grid;justify-items:end}.wm-slider-value,.wm-slider-value-sizer{grid-area:1 / 1;font-family:var(--wm-font-mono);font-size:.8125rem;font-variant-numeric:tabular-nums;white-space:nowrap}.wm-slider-value{color:var(--wm-text-secondary);min-width:4ch;text-align:right}.wm-slider-value-sizer{visibility:hidden;pointer-events:none}.wm-slider.is-disabled{opacity:.5}.wm-slider-input:disabled{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.wm-slider-input::-webkit-slider-thumb,.wm-slider-input::-moz-range-thumb,.wm-slider-tick{transition:none}.wm-slider-input:hover::-webkit-slider-thumb,.wm-slider-input:hover::-moz-range-thumb{transform:none}}\n"] }]
|
|
1074
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], formatValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatValue", required: false }] }], track: [{ type: i0.Input, args: [{ isSignal: true, alias: "track", required: false }] }], ticks: [{ type: i0.Input, args: [{ isSignal: true, alias: "ticks", required: false }] }] } });
|
|
1075
|
+
/**
|
|
1076
|
+
* A stop every `interval`, starting at `min` and never passing `max`. Returns
|
|
1077
|
+
* nothing for an interval that is not positive, or one that would draw more
|
|
1078
|
+
* than {@link MAX_TICKS} marks.
|
|
1079
|
+
*/
|
|
1080
|
+
function gridEvery(min, max, interval) {
|
|
1081
|
+
if (!Number.isFinite(interval) || interval <= 0)
|
|
1082
|
+
return [];
|
|
1083
|
+
const span = max - min;
|
|
1084
|
+
if (!Number.isFinite(span) || span <= 0)
|
|
1085
|
+
return [];
|
|
1086
|
+
const count = Math.floor(span / interval + 1e-9);
|
|
1087
|
+
if (count + 1 > MAX_TICKS)
|
|
1088
|
+
return [];
|
|
1089
|
+
const decimals = decimalsOf(interval) + decimalsOf(min);
|
|
1090
|
+
const out = [];
|
|
1091
|
+
for (let i = 0; i <= count; i++) {
|
|
1092
|
+
out.push({ value: round(min + i * interval, decimals) });
|
|
1093
|
+
}
|
|
1094
|
+
return out;
|
|
1095
|
+
}
|
|
1096
|
+
/** Decimal places in a number's plain decimal form, capped to what f64 can hold. */
|
|
1097
|
+
function decimalsOf(value) {
|
|
1098
|
+
const text = String(value);
|
|
1099
|
+
if (text.includes('e') || text.includes('E'))
|
|
1100
|
+
return 10;
|
|
1101
|
+
const dot = text.indexOf('.');
|
|
1102
|
+
return dot === -1 ? 0 : Math.min(text.length - dot - 1, 10);
|
|
1103
|
+
}
|
|
1104
|
+
function round(value, decimals) {
|
|
1105
|
+
return Number(value.toFixed(Math.min(decimals, 10)));
|
|
1106
|
+
}
|
|
1107
|
+
/** A CSS-ready fraction: enough precision to be exact, no trailing noise. */
|
|
1108
|
+
function trim(fraction) {
|
|
1109
|
+
return String(round(fraction, 6));
|
|
1110
|
+
}
|
|
1111
|
+
|
|
787
1112
|
/**
|
|
788
1113
|
* GhostField — transparent-until-hover wrapper for inline-editable fields.
|
|
789
1114
|
*
|
|
@@ -797,10 +1122,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
797
1122
|
* </wm-ghost-field>
|
|
798
1123
|
*/
|
|
799
1124
|
class GhostField {
|
|
800
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
801
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.
|
|
1125
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: GhostField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1126
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.23", type: GhostField, isStandalone: true, selector: "wm-ghost-field", ngImport: i0, template: `<div class="wm-ghost-field"><ng-content /></div>`, isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
802
1127
|
}
|
|
803
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1128
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: GhostField, decorators: [{
|
|
804
1129
|
type: Component,
|
|
805
1130
|
args: [{
|
|
806
1131
|
selector: 'wm-ghost-field',
|
|
@@ -827,14 +1152,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
827
1152
|
* </wm-page-header>
|
|
828
1153
|
*/
|
|
829
1154
|
class PageHeader {
|
|
830
|
-
flavourText = input.required(...(ngDevMode ? [{ debugName: "flavourText" }] : []));
|
|
831
|
-
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
832
|
-
subtitle = input(...(ngDevMode ? [undefined, { debugName: "subtitle" }] : []));
|
|
833
|
-
badgeLabel = input(...(ngDevMode ? [undefined, { debugName: "badgeLabel" }] : []));
|
|
834
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
835
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1155
|
+
flavourText = input.required(...(ngDevMode ? [{ debugName: "flavourText" }] : /* istanbul ignore next */ []));
|
|
1156
|
+
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
1157
|
+
subtitle = input(...(ngDevMode ? [undefined, { debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
1158
|
+
badgeLabel = input(...(ngDevMode ? [undefined, { debugName: "badgeLabel" }] : /* istanbul ignore next */ []));
|
|
1159
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: PageHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1160
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: PageHeader, isStandalone: true, selector: "wm-page-header", inputs: { flavourText: { classPropertyName: "flavourText", publicName: "flavourText", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, badgeLabel: { classPropertyName: "badgeLabel", publicName: "badgeLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<header class=\"wm-page-header\">\n <div class=\"wm-page-header__left\">\n <div class=\"wm-page-header__eyebrow\">\n <ng-content select=\"[icon]\" />\n <span>{{ flavourText() }}</span>\n </div>\n <h2 class=\"wm-page-header__title\">{{ title() }}</h2>\n @if (subtitle()) {\n <p class=\"wm-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n\n <div class=\"wm-page-header__right\">\n <div class=\"wm-page-header__status\">\n @if (badgeLabel()) {\n <span class=\"wm-page-header__badge\">{{ badgeLabel() }}</span>\n }\n <ng-content select=\"[back]\" />\n </div>\n <div class=\"wm-page-header__actions\">\n <ng-content />\n </div>\n </div>\n</header>\n", styles: ["wm-page-header,.wm-page-header{display:flex;align-items:flex-end;justify-content:space-between;border-bottom:1px solid var(--wm-border-subtle);padding-bottom:1.5rem}.wm-page-header__left{display:flex;flex-direction:column;gap:4px}.wm-page-header__eyebrow{display:flex;align-items:center;gap:8px;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--wm-text-muted)}.wm-page-header__eyebrow svg,.wm-page-header__eyebrow img{width:12px;height:12px;flex-shrink:0}.wm-page-header__title{margin:0;font-size:1.5rem;font-weight:700;letter-spacing:-.025em;color:var(--wm-text-primary)}.wm-page-header__subtitle{margin:0;font-size:.875rem;color:var(--wm-text-muted)}.wm-page-header__right{display:flex;flex-direction:column;align-items:flex-end;gap:12px}.wm-page-header__status,.wm-page-header__actions{display:flex;align-items:center;gap:12px}.wm-page-header__actions:empty{display:none}.wm-page-header__badge{font-size:.6875rem;font-family:var(--wm-font-mono, monospace);font-weight:700;text-transform:uppercase;letter-spacing:-.05em;color:var(--wm-text-muted);background:var(--wm-bg-float);padding:4px 8px;border-radius:var(--wm-radius-sm);border:1px solid var(--wm-border-subtle);box-shadow:0 1px 2px #0000000d;white-space:nowrap}@media(max-width:767px){wm-page-header,.wm-page-header{flex-direction:column;align-items:stretch;gap:6px;padding-bottom:0;border-bottom:none}.wm-page-header__right{align-items:flex-start}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
836
1161
|
}
|
|
837
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1162
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: PageHeader, decorators: [{
|
|
838
1163
|
type: Component,
|
|
839
1164
|
args: [{ selector: 'wm-page-header', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"wm-page-header\">\n <div class=\"wm-page-header__left\">\n <div class=\"wm-page-header__eyebrow\">\n <ng-content select=\"[icon]\" />\n <span>{{ flavourText() }}</span>\n </div>\n <h2 class=\"wm-page-header__title\">{{ title() }}</h2>\n @if (subtitle()) {\n <p class=\"wm-page-header__subtitle\">{{ subtitle() }}</p>\n }\n </div>\n\n <div class=\"wm-page-header__right\">\n <div class=\"wm-page-header__status\">\n @if (badgeLabel()) {\n <span class=\"wm-page-header__badge\">{{ badgeLabel() }}</span>\n }\n <ng-content select=\"[back]\" />\n </div>\n <div class=\"wm-page-header__actions\">\n <ng-content />\n </div>\n </div>\n</header>\n", styles: ["wm-page-header,.wm-page-header{display:flex;align-items:flex-end;justify-content:space-between;border-bottom:1px solid var(--wm-border-subtle);padding-bottom:1.5rem}.wm-page-header__left{display:flex;flex-direction:column;gap:4px}.wm-page-header__eyebrow{display:flex;align-items:center;gap:8px;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--wm-text-muted)}.wm-page-header__eyebrow svg,.wm-page-header__eyebrow img{width:12px;height:12px;flex-shrink:0}.wm-page-header__title{margin:0;font-size:1.5rem;font-weight:700;letter-spacing:-.025em;color:var(--wm-text-primary)}.wm-page-header__subtitle{margin:0;font-size:.875rem;color:var(--wm-text-muted)}.wm-page-header__right{display:flex;flex-direction:column;align-items:flex-end;gap:12px}.wm-page-header__status,.wm-page-header__actions{display:flex;align-items:center;gap:12px}.wm-page-header__actions:empty{display:none}.wm-page-header__badge{font-size:.6875rem;font-family:var(--wm-font-mono, monospace);font-weight:700;text-transform:uppercase;letter-spacing:-.05em;color:var(--wm-text-muted);background:var(--wm-bg-float);padding:4px 8px;border-radius:var(--wm-radius-sm);border:1px solid var(--wm-border-subtle);box-shadow:0 1px 2px #0000000d;white-space:nowrap}@media(max-width:767px){wm-page-header,.wm-page-header{flex-direction:column;align-items:stretch;gap:6px;padding-bottom:0;border-bottom:none}.wm-page-header__right{align-items:flex-start}}\n"] }]
|
|
840
1165
|
}], propDecorators: { flavourText: [{ type: i0.Input, args: [{ isSignal: true, alias: "flavourText", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], badgeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeLabel", required: false }] }] } });
|
|
@@ -847,23 +1172,23 @@ let nextPanelId = 0;
|
|
|
847
1172
|
*/
|
|
848
1173
|
class ComboboxPanel {
|
|
849
1174
|
/** Filtered options to display. */
|
|
850
|
-
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
1175
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
851
1176
|
/** Index of the keyboard-highlighted option (-1 = none). */
|
|
852
|
-
highlightIndex = input(-1, ...(ngDevMode ? [{ debugName: "highlightIndex" }] : []));
|
|
1177
|
+
highlightIndex = input(-1, ...(ngDevMode ? [{ debugName: "highlightIndex" }] : /* istanbul ignore next */ []));
|
|
853
1178
|
/** Values currently selected (for checkmark display). */
|
|
854
|
-
selectedValues = input(new Set(), ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
|
|
1179
|
+
selectedValues = input(new Set(), ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
855
1180
|
/** Whether the parent is multi-select. */
|
|
856
|
-
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
1181
|
+
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
857
1182
|
/** Pixel height per row. */
|
|
858
|
-
itemHeight = input(36, ...(ngDevMode ? [{ debugName: "itemHeight" }] : []));
|
|
1183
|
+
itemHeight = input(36, ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
859
1184
|
/** Max panel height in pixels. */
|
|
860
|
-
maxHeight = input(256, ...(ngDevMode ? [{ debugName: "maxHeight" }] : []));
|
|
1185
|
+
maxHeight = input(256, ...(ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []));
|
|
861
1186
|
/** Current filter text — used for match highlighting in labels. */
|
|
862
|
-
filterQuery = input('', ...(ngDevMode ? [{ debugName: "filterQuery" }] : []));
|
|
1187
|
+
filterQuery = input('', ...(ngDevMode ? [{ debugName: "filterQuery" }] : /* istanbul ignore next */ []));
|
|
863
1188
|
/** Show spinner when async filter is pending. */
|
|
864
|
-
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1189
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
865
1190
|
/** Shown in empty state when freeform input is enabled. */
|
|
866
|
-
freeformHint = input('', ...(ngDevMode ? [{ debugName: "freeformHint" }] : []));
|
|
1191
|
+
freeformHint = input('', ...(ngDevMode ? [{ debugName: "freeformHint" }] : /* istanbul ignore next */ []));
|
|
867
1192
|
/** Emitted on mousedown (not click) to prevent focus steal. */
|
|
868
1193
|
optionClicked = output();
|
|
869
1194
|
viewport;
|
|
@@ -875,11 +1200,11 @@ class ComboboxPanel {
|
|
|
875
1200
|
viewportHeight = computed(() => {
|
|
876
1201
|
const count = this.options().length;
|
|
877
1202
|
return Math.min(count * this.itemHeight(), this.maxHeight());
|
|
878
|
-
}, ...(ngDevMode ? [{ debugName: "viewportHeight" }] : []));
|
|
1203
|
+
}, ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
|
|
879
1204
|
/** Whether to show the empty state. */
|
|
880
|
-
showEmpty = computed(() => this.options().length === 0 && !this.loading(), ...(ngDevMode ? [{ debugName: "showEmpty" }] : []));
|
|
1205
|
+
showEmpty = computed(() => this.options().length === 0 && !this.loading(), ...(ngDevMode ? [{ debugName: "showEmpty" }] : /* istanbul ignore next */ []));
|
|
881
1206
|
/** Text for the empty state. */
|
|
882
|
-
emptyText = computed(() => this.freeformHint() || 'No matches', ...(ngDevMode ? [{ debugName: "emptyText" }] : []));
|
|
1207
|
+
emptyText = computed(() => this.freeformHint() || 'No matches', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
|
|
883
1208
|
/**
|
|
884
1209
|
* Precomputed label segments for each option, split by the current filter query.
|
|
885
1210
|
* Recomputes whenever options or filterQuery changes.
|
|
@@ -887,7 +1212,7 @@ class ComboboxPanel {
|
|
|
887
1212
|
segmentedLabels = computed(() => {
|
|
888
1213
|
const query = this.filterQuery().trim();
|
|
889
1214
|
return this.options().map(opt => this.splitLabel(opt.label, query));
|
|
890
|
-
}, ...(ngDevMode ? [{ debugName: "segmentedLabels" }] : []));
|
|
1215
|
+
}, ...(ngDevMode ? [{ debugName: "segmentedLabels" }] : /* istanbul ignore next */ []));
|
|
891
1216
|
/** Map from option value to a stable key for DOM IDs. */
|
|
892
1217
|
optionKeyMap = new Map();
|
|
893
1218
|
nextObjectIndex = 0;
|
|
@@ -967,10 +1292,10 @@ class ComboboxPanel {
|
|
|
967
1292
|
}
|
|
968
1293
|
return segments;
|
|
969
1294
|
}
|
|
970
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
971
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1295
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: ComboboxPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1296
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: ComboboxPanel, isStandalone: true, selector: "wm-combobox-panel", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, highlightIndex: { classPropertyName: "highlightIndex", publicName: "highlightIndex", isSignal: true, isRequired: false, transformFunction: null }, selectedValues: { classPropertyName: "selectedValues", publicName: "selectedValues", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, filterQuery: { classPropertyName: "filterQuery", publicName: "filterQuery", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, freeformHint: { classPropertyName: "freeformHint", publicName: "freeformHint", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionClicked: "optionClicked" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true }], ngImport: i0, template: "@if (loading()) {\n <div class=\"wm-cb-loading\" aria-live=\"polite\">\n <svg\n class=\"wm-cb-spinner\"\n width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <circle\n cx=\"10\" cy=\"10\" r=\"8\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-dasharray=\"40 60\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"wm-cb-loading-text\">Loading\u2026</span>\n </div>\n} @else if (showEmpty()) {\n <div class=\"wm-cb-empty\" aria-live=\"polite\">{{ emptyText() }}</div>\n} @else {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"itemHeight()\"\n [style.height.px]=\"viewportHeight()\"\n class=\"wm-cb-viewport\"\n >\n <div\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n >\n <div\n *cdkVirtualFor=\"let opt of options(); let i = index\"\n role=\"option\"\n class=\"wm-cb-option\"\n [id]=\"optionIdAt(i)\"\n [class.is-highlighted]=\"i === highlightIndex()\"\n [class.is-selected]=\"isSelected(opt.value)\"\n [class.is-disabled]=\"!!opt.disabled\"\n [attr.aria-selected]=\"isSelected(opt.value)\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n (mousedown)=\"onOptionMousedown($event, opt, i)\"\n >\n <span class=\"wm-cb-option-label\">\n @for (seg of segmentsAt(i); track $index) {\n @if (seg.match) {\n <b class=\"wm-cb-match\">{{ seg.text }}</b>\n } @else {\n {{ seg.text }}\n }\n }\n </span>\n @if (isSelected(opt.value)) {\n <svg\n class=\"wm-cb-check\"\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <polyline\n points=\"20 6 9 17 4 12\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"\n />\n </svg>\n }\n </div>\n </div>\n </cdk-virtual-scroll-viewport>\n}\n", styles: [":host{display:block}.wm-cb-viewport{width:100%}.wm-cb-option{display:flex;align-items:center;justify-content:space-between;gap:.5rem;padding:.4375rem .625rem;border:none;border-radius:var(--wm-radius-sm);background:transparent;color:var(--wm-text-primary);font-size:.875rem;font-family:inherit;cursor:pointer;text-align:left;transition:background var(--wm-transition-fast);-webkit-user-select:none;user-select:none}.wm-cb-option:hover:not(.is-disabled):not(.is-highlighted){background:var(--wm-bg-active)}.wm-cb-option.is-highlighted{background:color-mix(in srgb,var(--wm-color-accent) 15%,transparent)}.wm-cb-option.is-selected{background:color-mix(in srgb,var(--wm-color-accent) 10%,transparent);color:var(--wm-color-accent-readable);font-weight:500}.wm-cb-option.is-disabled{opacity:.4;cursor:not-allowed}.wm-cb-option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-cb-match{font-weight:700;color:var(--wm-color-accent-readable)}.wm-cb-check{flex-shrink:0;color:var(--wm-color-accent-readable)}.wm-cb-empty{padding:.75rem .625rem;color:var(--wm-text-muted);font-size:.875rem;text-align:center}.wm-cb-loading{display:flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem .625rem;color:var(--wm-text-muted);font-size:.875rem}.wm-cb-spinner{animation:wm-cb-spin .8s linear infinite}@keyframes wm-cb-spin{to{transform:rotate(360deg)}}.wm-cb-loading-text{color:var(--wm-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
972
1297
|
}
|
|
973
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1298
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: ComboboxPanel, decorators: [{
|
|
974
1299
|
type: Component,
|
|
975
1300
|
args: [{ selector: 'wm-combobox-panel', imports: [ScrollingModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (loading()) {\n <div class=\"wm-cb-loading\" aria-live=\"polite\">\n <svg\n class=\"wm-cb-spinner\"\n width=\"20\" height=\"20\" viewBox=\"0 0 20 20\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <circle\n cx=\"10\" cy=\"10\" r=\"8\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-dasharray=\"40 60\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"wm-cb-loading-text\">Loading\u2026</span>\n </div>\n} @else if (showEmpty()) {\n <div class=\"wm-cb-empty\" aria-live=\"polite\">{{ emptyText() }}</div>\n} @else {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"itemHeight()\"\n [style.height.px]=\"viewportHeight()\"\n class=\"wm-cb-viewport\"\n >\n <div\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n >\n <div\n *cdkVirtualFor=\"let opt of options(); let i = index\"\n role=\"option\"\n class=\"wm-cb-option\"\n [id]=\"optionIdAt(i)\"\n [class.is-highlighted]=\"i === highlightIndex()\"\n [class.is-selected]=\"isSelected(opt.value)\"\n [class.is-disabled]=\"!!opt.disabled\"\n [attr.aria-selected]=\"isSelected(opt.value)\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n (mousedown)=\"onOptionMousedown($event, opt, i)\"\n >\n <span class=\"wm-cb-option-label\">\n @for (seg of segmentsAt(i); track $index) {\n @if (seg.match) {\n <b class=\"wm-cb-match\">{{ seg.text }}</b>\n } @else {\n {{ seg.text }}\n }\n }\n </span>\n @if (isSelected(opt.value)) {\n <svg\n class=\"wm-cb-check\"\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <polyline\n points=\"20 6 9 17 4 12\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"\n />\n </svg>\n }\n </div>\n </div>\n </cdk-virtual-scroll-viewport>\n}\n", styles: [":host{display:block}.wm-cb-viewport{width:100%}.wm-cb-option{display:flex;align-items:center;justify-content:space-between;gap:.5rem;padding:.4375rem .625rem;border:none;border-radius:var(--wm-radius-sm);background:transparent;color:var(--wm-text-primary);font-size:.875rem;font-family:inherit;cursor:pointer;text-align:left;transition:background var(--wm-transition-fast);-webkit-user-select:none;user-select:none}.wm-cb-option:hover:not(.is-disabled):not(.is-highlighted){background:var(--wm-bg-active)}.wm-cb-option.is-highlighted{background:color-mix(in srgb,var(--wm-color-accent) 15%,transparent)}.wm-cb-option.is-selected{background:color-mix(in srgb,var(--wm-color-accent) 10%,transparent);color:var(--wm-color-accent-readable);font-weight:500}.wm-cb-option.is-disabled{opacity:.4;cursor:not-allowed}.wm-cb-option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-cb-match{font-weight:700;color:var(--wm-color-accent-readable)}.wm-cb-check{flex-shrink:0;color:var(--wm-color-accent-readable)}.wm-cb-empty{padding:.75rem .625rem;color:var(--wm-text-muted);font-size:.875rem;text-align:center}.wm-cb-loading{display:flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem .625rem;color:var(--wm-text-muted);font-size:.875rem}.wm-cb-spinner{animation:wm-cb-spin .8s linear infinite}@keyframes wm-cb-spin{to{transform:rotate(360deg)}}.wm-cb-loading-text{color:var(--wm-text-muted)}\n"] }]
|
|
976
1301
|
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], highlightIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightIndex", required: false }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], filterQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterQuery", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], freeformHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "freeformHint", required: false }] }], optionClicked: [{ type: i0.Output, args: ["optionClicked"] }], viewport: [{
|
|
@@ -1014,17 +1339,17 @@ class WmCombobox {
|
|
|
1014
1339
|
scrollStrategy = new WmAnchoredScrollStrategy();
|
|
1015
1340
|
// ── Public inputs ──────────────────────────────────────────────────────
|
|
1016
1341
|
/** Full option list (before filtering). */
|
|
1017
|
-
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
1342
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
1018
1343
|
/** Selected value (single-select). Two-way bindable. */
|
|
1019
|
-
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
1344
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1020
1345
|
/** Selected values (multi-select). Two-way bindable. */
|
|
1021
|
-
values = model([], ...(ngDevMode ? [{ debugName: "values" }] : []));
|
|
1346
|
+
values = model([], ...(ngDevMode ? [{ debugName: "values" }] : /* istanbul ignore next */ []));
|
|
1022
1347
|
/** Enable multi-select mode with chips. */
|
|
1023
|
-
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
1348
|
+
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
1024
1349
|
/** Allow typed text to be accepted as a freeform value. */
|
|
1025
|
-
allowFreeform = input(false, ...(ngDevMode ? [{ debugName: "allowFreeform" }] : []));
|
|
1350
|
+
allowFreeform = input(false, ...(ngDevMode ? [{ debugName: "allowFreeform" }] : /* istanbul ignore next */ []));
|
|
1026
1351
|
/** Placeholder text for the input. */
|
|
1027
|
-
placeholder = input('Search\u2026', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
1352
|
+
placeholder = input('Search\u2026', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1028
1353
|
/**
|
|
1029
1354
|
* Accessible name for the combobox input.
|
|
1030
1355
|
*
|
|
@@ -1034,21 +1359,21 @@ class WmCombobox {
|
|
|
1034
1359
|
* so in multi-select mode there is otherwise no accessible name at all once
|
|
1035
1360
|
* the user picks anything.
|
|
1036
1361
|
*/
|
|
1037
|
-
ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
1362
|
+
ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
1038
1363
|
/**
|
|
1039
1364
|
* ID of a visible element that names this combobox. Prefer this over
|
|
1040
1365
|
* `ariaLabel` when a visible caption exists, so the accessible name matches
|
|
1041
1366
|
* the visible text (WCAG 2.5.3, Label in Name).
|
|
1042
1367
|
*/
|
|
1043
|
-
ariaLabelledby = input(null, ...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : []));
|
|
1368
|
+
ariaLabelledby = input(null, ...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []));
|
|
1044
1369
|
/** Disable the combobox. */
|
|
1045
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
1370
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
1046
1371
|
/** Custom async filter function. Overrides default substring matching. */
|
|
1047
|
-
filterFn = input(null, ...(ngDevMode ? [{ debugName: "filterFn" }] : []));
|
|
1372
|
+
filterFn = input(null, ...(ngDevMode ? [{ debugName: "filterFn" }] : /* istanbul ignore next */ []));
|
|
1048
1373
|
/** Pixel height of each option row. */
|
|
1049
|
-
itemHeight = input(36, ...(ngDevMode ? [{ debugName: "itemHeight" }] : []));
|
|
1374
|
+
itemHeight = input(36, ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
1050
1375
|
/** Max panel height in pixels. */
|
|
1051
|
-
maxPanelHeight = input(256, ...(ngDevMode ? [{ debugName: "maxPanelHeight" }] : []));
|
|
1376
|
+
maxPanelHeight = input(256, ...(ngDevMode ? [{ debugName: "maxPanelHeight" }] : /* istanbul ignore next */ []));
|
|
1052
1377
|
// ── Public outputs ─────────────────────────────────────────────────────
|
|
1053
1378
|
/** Emitted when the input text changes. */
|
|
1054
1379
|
query = output();
|
|
@@ -1057,14 +1382,14 @@ class WmCombobox {
|
|
|
1057
1382
|
/** Emitted when the panel closes. */
|
|
1058
1383
|
closed = output();
|
|
1059
1384
|
// ── View children ──────────────────────────────────────────────────────
|
|
1060
|
-
inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
|
|
1061
|
-
panel = viewChild(ComboboxPanel, ...(ngDevMode ? [{ debugName: "panel" }] : []));
|
|
1385
|
+
inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : /* istanbul ignore next */ []));
|
|
1386
|
+
panel = viewChild(ComboboxPanel, ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
|
|
1062
1387
|
// ── Internal state ─────────────────────────────────────────────────────
|
|
1063
|
-
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
1064
|
-
inputText = signal('', ...(ngDevMode ? [{ debugName: "inputText" }] : []));
|
|
1065
|
-
highlightIndex = signal(-1, ...(ngDevMode ? [{ debugName: "highlightIndex" }] : []));
|
|
1066
|
-
asyncLoading = signal(false, ...(ngDevMode ? [{ debugName: "asyncLoading" }] : []));
|
|
1067
|
-
asyncResults = signal(null, ...(ngDevMode ? [{ debugName: "asyncResults" }] : []));
|
|
1388
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
1389
|
+
inputText = signal('', ...(ngDevMode ? [{ debugName: "inputText" }] : /* istanbul ignore next */ []));
|
|
1390
|
+
highlightIndex = signal(-1, ...(ngDevMode ? [{ debugName: "highlightIndex" }] : /* istanbul ignore next */ []));
|
|
1391
|
+
asyncLoading = signal(false, ...(ngDevMode ? [{ debugName: "asyncLoading" }] : /* istanbul ignore next */ []));
|
|
1392
|
+
asyncResults = signal(null, ...(ngDevMode ? [{ debugName: "asyncResults" }] : /* istanbul ignore next */ []));
|
|
1068
1393
|
/** Text the input had when the panel opened — restored on Escape. */
|
|
1069
1394
|
savedText = '';
|
|
1070
1395
|
hostEl = inject((ElementRef));
|
|
@@ -1075,7 +1400,7 @@ class WmCombobox {
|
|
|
1075
1400
|
filterSubject = new Subject();
|
|
1076
1401
|
filterSub = null;
|
|
1077
1402
|
// ── Live region debounce ───────────────────────────────────────────────
|
|
1078
|
-
liveText = signal('', ...(ngDevMode ? [{ debugName: "liveText" }] : []));
|
|
1403
|
+
liveText = signal('', ...(ngDevMode ? [{ debugName: "liveText" }] : /* istanbul ignore next */ []));
|
|
1079
1404
|
liveTimer = null;
|
|
1080
1405
|
// ── Computed ───────────────────────────────────────────────────────────
|
|
1081
1406
|
/** Set of currently selected values for the panel. */
|
|
@@ -1085,7 +1410,7 @@ class WmCombobox {
|
|
|
1085
1410
|
}
|
|
1086
1411
|
const v = this.value();
|
|
1087
1412
|
return v != null ? new Set([v]) : new Set();
|
|
1088
|
-
}, ...(ngDevMode ? [{ debugName: "selectedValues" }] : []));
|
|
1413
|
+
}, ...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
1089
1414
|
/** Filtered options shown in the panel. */
|
|
1090
1415
|
filteredOptions = computed(() => {
|
|
1091
1416
|
// If async filterFn is set and we have results, use those.
|
|
@@ -1098,7 +1423,7 @@ class WmCombobox {
|
|
|
1098
1423
|
if (!query)
|
|
1099
1424
|
return opts;
|
|
1100
1425
|
return opts.filter(o => o.label.toLowerCase().includes(query));
|
|
1101
|
-
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : []));
|
|
1426
|
+
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
1102
1427
|
/** Chips for multi-select mode. */
|
|
1103
1428
|
chips = computed(() => {
|
|
1104
1429
|
if (!this.multiple())
|
|
@@ -1109,7 +1434,7 @@ class WmCombobox {
|
|
|
1109
1434
|
const opt = opts.find(o => o.value === v);
|
|
1110
1435
|
return { value: v, label: opt?.label ?? String(v) };
|
|
1111
1436
|
});
|
|
1112
|
-
}, ...(ngDevMode ? [{ debugName: "chips" }] : []));
|
|
1437
|
+
}, ...(ngDevMode ? [{ debugName: "chips" }] : /* istanbul ignore next */ []));
|
|
1113
1438
|
/** The aria-activedescendant value. */
|
|
1114
1439
|
activeDescendant = computed(() => {
|
|
1115
1440
|
const idx = this.highlightIndex();
|
|
@@ -1117,19 +1442,19 @@ class WmCombobox {
|
|
|
1117
1442
|
if (idx < 0 || !p)
|
|
1118
1443
|
return null;
|
|
1119
1444
|
return p.optionIdAt(idx) || null;
|
|
1120
|
-
}, ...(ngDevMode ? [{ debugName: "activeDescendant" }] : []));
|
|
1445
|
+
}, ...(ngDevMode ? [{ debugName: "activeDescendant" }] : /* istanbul ignore next */ []));
|
|
1121
1446
|
/** The listbox ID from the panel (for aria-controls). */
|
|
1122
1447
|
panelListboxId = computed(() => {
|
|
1123
1448
|
const p = this.panel();
|
|
1124
1449
|
return p ? p.listboxId : null;
|
|
1125
|
-
}, ...(ngDevMode ? [{ debugName: "panelListboxId" }] : []));
|
|
1450
|
+
}, ...(ngDevMode ? [{ debugName: "panelListboxId" }] : /* istanbul ignore next */ []));
|
|
1126
1451
|
/** Freeform hint for empty state. */
|
|
1127
1452
|
freeformHint = computed(() => {
|
|
1128
1453
|
if (!this.allowFreeform())
|
|
1129
1454
|
return '';
|
|
1130
1455
|
const text = this.inputText().trim();
|
|
1131
1456
|
return text ? `Press Enter to add "${text}"` : '';
|
|
1132
|
-
}, ...(ngDevMode ? [{ debugName: "freeformHint" }] : []));
|
|
1457
|
+
}, ...(ngDevMode ? [{ debugName: "freeformHint" }] : /* istanbul ignore next */ []));
|
|
1133
1458
|
/** Overlay width tracks host element width. */
|
|
1134
1459
|
get overlayWidth() {
|
|
1135
1460
|
return this.hostEl.nativeElement.offsetWidth || 200;
|
|
@@ -1520,8 +1845,8 @@ class WmCombobox {
|
|
|
1520
1845
|
const opt = this.options().find(o => o.value === v);
|
|
1521
1846
|
this.inputText.set(opt?.label ?? (typeof v === 'string' ? v : ''));
|
|
1522
1847
|
}
|
|
1523
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1524
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1848
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmCombobox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1849
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmCombobox, isStandalone: true, selector: "wm-combobox", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, allowFreeform: { classPropertyName: "allowFreeform", publicName: "allowFreeform", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "ariaLabelledby", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, filterFn: { classPropertyName: "filterFn", publicName: "filterFn", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, maxPanelHeight: { classPropertyName: "maxPanelHeight", publicName: "maxPanelHeight", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", values: "valuesChange", query: "query", opened: "opened", closed: "closed" }, providers: [
|
|
1525
1850
|
{
|
|
1526
1851
|
provide: NG_VALUE_ACCESSOR,
|
|
1527
1852
|
useExisting: forwardRef(() => WmCombobox),
|
|
@@ -1529,7 +1854,7 @@ class WmCombobox {
|
|
|
1529
1854
|
},
|
|
1530
1855
|
], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ComboboxPanel, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Trigger wrapper \u2014 anchors the CDK overlay -->\n<div\n class=\"wm-cb-trigger\"\n [class.is-open]=\"isOpen()\"\n [class.is-disabled]=\"disabled()\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n (click)=\"onTriggerClick()\"\n>\n <!-- Multi-select chips -->\n @if (multiple()) {\n @for (chip of chips(); track chip.value) {\n <span class=\"wm-cb-chip\">\n <span class=\"wm-cb-chip-label\">{{ chip.label }}</span>\n <button\n type=\"button\"\n class=\"wm-cb-chip-remove\"\n tabindex=\"-1\"\n [attr.aria-label]=\"'Remove ' + chip.label\"\n (mousedown)=\"$event.preventDefault(); $event.stopPropagation()\"\n (click)=\"$event.stopPropagation(); removeChip(chip.value)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M18 6L6 18M6 6l12 12\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </span>\n }\n }\n\n <!-- Text input -->\n <input\n #inputEl\n type=\"text\"\n class=\"wm-cb-input\"\n role=\"combobox\"\n autocomplete=\"off\"\n [attr.placeholder]=\"chips().length ? '' : placeholder()\"\n [attr.aria-label]=\"ariaLabelledby() ? null : ariaLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby()\"\n [attr.aria-expanded]=\"isOpen()\"\n aria-haspopup=\"listbox\"\n [attr.aria-autocomplete]=\"allowFreeform() ? 'both' : 'list'\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-controls]=\"isOpen() ? panelListboxId() : null\"\n [disabled]=\"disabled() || null\"\n [value]=\"inputText()\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n\n <!-- Chevron -->\n <svg\n class=\"wm-cb-chevron\"\n [class.is-open]=\"isOpen()\"\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\"\n fill=\"none\" aria-hidden=\"true\"\n >\n <path d=\"M6 9l6 6 6-6\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n</div>\n\n<!-- Live region for screen readers -->\n<span class=\"wm-cb-sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ liveText() }}\n</span>\n\n<!-- Dropdown panel in CDK overlay -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayWidth]=\"overlayWidth\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"wm-cb-backdrop\"\n (backdropClick)=\"close()\"\n (detach)=\"close()\"\n>\n <div class=\"wm-cb-panel\">\n <wm-combobox-panel\n [options]=\"filteredOptions()\"\n [highlightIndex]=\"highlightIndex()\"\n [selectedValues]=\"selectedValues()\"\n [multiple]=\"multiple()\"\n [itemHeight]=\"itemHeight()\"\n [maxHeight]=\"maxPanelHeight()\"\n [filterQuery]=\"inputText()\"\n [loading]=\"asyncLoading()\"\n [freeformHint]=\"freeformHint()\"\n (optionClicked)=\"onOptionClicked($event)\"\n />\n </div>\n</ng-template>\n", styles: [":host{display:block}.wm-cb-trigger{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;width:100%;min-height:36px;padding:.25rem .5rem;background:var(--wm-bg-base);border:1px solid var(--wm-border-input);border-radius:var(--wm-radius-sm);color:var(--wm-text-primary);font-size:.875rem;cursor:text;transition:border-color var(--wm-transition-fast),box-shadow var(--wm-transition-fast)}.wm-cb-trigger:hover:not(.is-disabled){border-color:var(--wm-color-accent-readable)}.wm-cb-trigger:focus-within:not(.is-disabled){border-color:var(--wm-color-accent-readable);box-shadow:0 0 0 3px color-mix(in srgb,var(--wm-color-accent) 25%,transparent)}.wm-cb-trigger.is-open{border-color:var(--wm-color-accent-readable);box-shadow:0 0 0 3px color-mix(in srgb,var(--wm-color-accent) 20%,transparent)}.wm-cb-trigger.is-disabled{opacity:.45;cursor:not-allowed}.wm-cb-input{flex:1 1 60px;min-width:60px;border:none;outline:none;background:transparent;color:inherit;font:inherit;padding:.125rem 0}.wm-cb-input::placeholder{color:var(--wm-text-placeholder)}.wm-cb-input:disabled{cursor:not-allowed}.wm-cb-chevron{flex-shrink:0;color:var(--wm-text-muted);transition:transform var(--wm-transition-fast);pointer-events:none}.wm-cb-chevron.is-open{transform:rotate(180deg)}.wm-cb-chip{display:inline-flex;align-items:center;gap:.25rem;max-width:100%;padding:.125rem .375rem;background:color-mix(in srgb,var(--wm-color-accent) 15%,transparent);border:1px solid color-mix(in srgb,var(--wm-color-accent) 30%,transparent);border-radius:var(--wm-radius-sm);font-size:.8125rem;line-height:1.4;color:var(--wm-text-primary);-webkit-user-select:none;user-select:none}.wm-cb-chip-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wm-cb-chip-remove{display:inline-flex;align-items:center;justify-content:center;padding:0;border:none;background:transparent;color:var(--wm-text-muted);cursor:pointer;border-radius:var(--wm-radius-sm);transition:color var(--wm-transition-fast)}.wm-cb-chip-remove:hover{color:var(--wm-text-primary)}.wm-cb-backdrop{position:fixed;inset:0}.wm-cb-panel{width:100%;background:var(--wm-bg-float);border:1px solid var(--wm-border);border-radius:var(--wm-radius-lg);box-shadow:0 4px 6px -1px #00000014,0 10px 20px -4px #0000001f;overflow:hidden;padding:.25rem}.wm-cb-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ComboboxPanel, selector: "wm-combobox-panel", inputs: ["options", "highlightIndex", "selectedValues", "multiple", "itemHeight", "maxHeight", "filterQuery", "loading", "freeformHint"], outputs: ["optionClicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1531
1856
|
}
|
|
1532
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmCombobox, decorators: [{
|
|
1533
1858
|
type: Component,
|
|
1534
1859
|
args: [{ selector: 'wm-combobox', imports: [CdkConnectedOverlay, CdkOverlayOrigin, ComboboxPanel], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1535
1860
|
{
|
|
@@ -1552,7 +1877,7 @@ let nextId$1 = 0;
|
|
|
1552
1877
|
* Custom duration via show(message, type, durationMs).
|
|
1553
1878
|
*/
|
|
1554
1879
|
class WmToastService {
|
|
1555
|
-
toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : []));
|
|
1880
|
+
toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
|
|
1556
1881
|
show(message, type = 'info', duration) {
|
|
1557
1882
|
const id = ++nextId$1;
|
|
1558
1883
|
this.toasts.update(list => [...list, { id, message, type }]);
|
|
@@ -1582,10 +1907,10 @@ class WmToastService {
|
|
|
1582
1907
|
dismiss(id) {
|
|
1583
1908
|
this.toasts.update(list => list.filter(t => t.id !== id));
|
|
1584
1909
|
}
|
|
1585
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1586
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
1910
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1911
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmToastService, providedIn: 'root' });
|
|
1587
1912
|
}
|
|
1588
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1913
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmToastService, decorators: [{
|
|
1589
1914
|
type: Injectable,
|
|
1590
1915
|
args: [{ providedIn: 'root' }]
|
|
1591
1916
|
}] });
|
|
@@ -1604,7 +1929,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1604
1929
|
class WmToastContainer {
|
|
1605
1930
|
toastService = inject(WmToastService);
|
|
1606
1931
|
/** Tick signal that updates every second — drives the elapsed time display. */
|
|
1607
|
-
tick = signal(Date.now(), ...(ngDevMode ? [{ debugName: "tick" }] : []));
|
|
1932
|
+
tick = signal(Date.now(), ...(ngDevMode ? [{ debugName: "tick" }] : /* istanbul ignore next */ []));
|
|
1608
1933
|
tickInterval = setInterval(() => {
|
|
1609
1934
|
// Only tick when there are progress toasts with createdAt
|
|
1610
1935
|
if (this.toastService.toasts().some(t => t.type === 'progress' && t.createdAt)) {
|
|
@@ -1633,10 +1958,10 @@ class WmToastContainer {
|
|
|
1633
1958
|
const secs = diff % 60;
|
|
1634
1959
|
return `${mins}m ${secs.toString().padStart(2, '0')}s`;
|
|
1635
1960
|
}
|
|
1636
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1637
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1961
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmToastContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1962
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmToastContainer, isStandalone: true, selector: "wm-toast-container", ngImport: i0, template: "<div class=\"wm-toast-container\" role=\"log\" aria-live=\"polite\" aria-label=\"Notifications\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div [class]=\"typeClass(toast)\" role=\"status\">\n <!-- Success icon (check-circle) -->\n @if (toast.type === 'success') {\n <svg class=\"wm-toast-icon\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/>\n <polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n }\n <!-- Error icon (x-circle) -->\n @if (toast.type === 'error') {\n <svg class=\"wm-toast-icon\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/>\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n }\n <!-- Info icon -->\n @if (toast.type === 'info') {\n <svg class=\"wm-toast-icon\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"/>\n </svg>\n }\n <!-- Progress spinner -->\n @if (toast.type === 'progress') {\n <span class=\"wm-toast-spinner\" aria-hidden=\"true\"></span>\n }\n\n <span class=\"wm-toast-message\">\n {{ toast.message }}\n @if (toast.type === 'progress' && toast.createdAt) {\n <span class=\"wm-toast-elapsed\"> ({{ elapsed(toast.createdAt) }})</span>\n }\n </span>\n\n <!-- Cancel button for progress toasts with an onCancel callback -->\n @if (toast.type === 'progress' && toast.onCancel) {\n <button class=\"wm-toast-cancel\" (click)=\"cancel(toast)\" aria-label=\"Cancel operation\">Cancel</button>\n }\n\n <!-- Dismiss button \u2014 always shown -->\n <button class=\"wm-toast-dismiss\" (click)=\"dismiss(toast.id)\" aria-label=\"Dismiss notification\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n }\n</div>\n", styles: [".wm-toast-container{position:fixed;bottom:1rem;right:1rem;display:flex;flex-direction:column;gap:.5rem;z-index:9999;pointer-events:none}.wm-toast{display:flex;align-items:flex-start;gap:.625rem;padding:.625rem .875rem;border-radius:var(--wm-radius-sm, 4px);box-shadow:var(--wm-shadow-md, 0 4px 12px rgba(0,0,0,.25));font-size:.8125rem;line-height:1.4;min-width:220px;max-width:360px;pointer-events:auto;animation:wm-toast-slide-in .15s ease-out both}.wm-toast--success{background:var(--wm-color-success-bg);color:var(--wm-color-success-readable);border:1px solid var(--wm-color-success-border)}.wm-toast--error{background:var(--wm-color-danger-bg);color:var(--wm-color-danger-readable);border:1px solid var(--wm-color-danger-border)}.wm-toast--info{background:var(--wm-bg-raised);color:var(--wm-text-primary);border:1px solid var(--wm-border)}.wm-toast--progress{background:var(--wm-bg-raised);color:var(--wm-text-primary);border:1px solid var(--wm-color-accent-border)}.wm-toast-icon{flex-shrink:0;margin-top:1px}.wm-toast-message{flex:1;line-height:1.4}.wm-toast-dismiss{flex-shrink:0;background:none;border:none;color:inherit;opacity:.6;cursor:pointer;padding:0;margin-left:.25rem;transition:opacity .15s ease}.wm-toast-dismiss:hover{opacity:1}.wm-toast-spinner{width:14px;height:14px;border:2px solid color-mix(in srgb,var(--wm-color-accent) 30%,transparent);border-top-color:var(--wm-color-accent-readable);border-radius:50%;flex-shrink:0;margin-top:1px;animation:wm-toast-spin .7s linear infinite}.wm-toast-elapsed{opacity:.6;font-size:.75rem;font-variant-numeric:tabular-nums}.wm-toast-cancel{flex-shrink:0;background:none;border:1px solid color-mix(in srgb,currentColor 30%,transparent);border-radius:var(--wm-radius-sm, 4px);color:inherit;opacity:.7;cursor:pointer;padding:.125rem .5rem;font-size:.75rem;transition:opacity .15s ease,border-color .15s ease}.wm-toast-cancel:hover{opacity:1;border-color:currentColor}@keyframes wm-toast-spin{to{transform:rotate(360deg)}}@keyframes wm-toast-slide-in{0%{opacity:0;transform:translate(1rem)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.wm-toast{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1638
1963
|
}
|
|
1639
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1964
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmToastContainer, decorators: [{
|
|
1640
1965
|
type: Component,
|
|
1641
1966
|
args: [{ selector: 'wm-toast-container', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"wm-toast-container\" role=\"log\" aria-live=\"polite\" aria-label=\"Notifications\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div [class]=\"typeClass(toast)\" role=\"status\">\n <!-- Success icon (check-circle) -->\n @if (toast.type === 'success') {\n <svg class=\"wm-toast-icon\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/>\n <polyline points=\"22 4 12 14.01 9 11.01\"/>\n </svg>\n }\n <!-- Error icon (x-circle) -->\n @if (toast.type === 'error') {\n <svg class=\"wm-toast-icon\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"/>\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"/>\n </svg>\n }\n <!-- Info icon -->\n @if (toast.type === 'info') {\n <svg class=\"wm-toast-icon\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\"/>\n </svg>\n }\n <!-- Progress spinner -->\n @if (toast.type === 'progress') {\n <span class=\"wm-toast-spinner\" aria-hidden=\"true\"></span>\n }\n\n <span class=\"wm-toast-message\">\n {{ toast.message }}\n @if (toast.type === 'progress' && toast.createdAt) {\n <span class=\"wm-toast-elapsed\"> ({{ elapsed(toast.createdAt) }})</span>\n }\n </span>\n\n <!-- Cancel button for progress toasts with an onCancel callback -->\n @if (toast.type === 'progress' && toast.onCancel) {\n <button class=\"wm-toast-cancel\" (click)=\"cancel(toast)\" aria-label=\"Cancel operation\">Cancel</button>\n }\n\n <!-- Dismiss button \u2014 always shown -->\n <button class=\"wm-toast-dismiss\" (click)=\"dismiss(toast.id)\" aria-label=\"Dismiss notification\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n }\n</div>\n", styles: [".wm-toast-container{position:fixed;bottom:1rem;right:1rem;display:flex;flex-direction:column;gap:.5rem;z-index:9999;pointer-events:none}.wm-toast{display:flex;align-items:flex-start;gap:.625rem;padding:.625rem .875rem;border-radius:var(--wm-radius-sm, 4px);box-shadow:var(--wm-shadow-md, 0 4px 12px rgba(0,0,0,.25));font-size:.8125rem;line-height:1.4;min-width:220px;max-width:360px;pointer-events:auto;animation:wm-toast-slide-in .15s ease-out both}.wm-toast--success{background:var(--wm-color-success-bg);color:var(--wm-color-success-readable);border:1px solid var(--wm-color-success-border)}.wm-toast--error{background:var(--wm-color-danger-bg);color:var(--wm-color-danger-readable);border:1px solid var(--wm-color-danger-border)}.wm-toast--info{background:var(--wm-bg-raised);color:var(--wm-text-primary);border:1px solid var(--wm-border)}.wm-toast--progress{background:var(--wm-bg-raised);color:var(--wm-text-primary);border:1px solid var(--wm-color-accent-border)}.wm-toast-icon{flex-shrink:0;margin-top:1px}.wm-toast-message{flex:1;line-height:1.4}.wm-toast-dismiss{flex-shrink:0;background:none;border:none;color:inherit;opacity:.6;cursor:pointer;padding:0;margin-left:.25rem;transition:opacity .15s ease}.wm-toast-dismiss:hover{opacity:1}.wm-toast-spinner{width:14px;height:14px;border:2px solid color-mix(in srgb,var(--wm-color-accent) 30%,transparent);border-top-color:var(--wm-color-accent-readable);border-radius:50%;flex-shrink:0;margin-top:1px;animation:wm-toast-spin .7s linear infinite}.wm-toast-elapsed{opacity:.6;font-size:.75rem;font-variant-numeric:tabular-nums}.wm-toast-cancel{flex-shrink:0;background:none;border:1px solid color-mix(in srgb,currentColor 30%,transparent);border-radius:var(--wm-radius-sm, 4px);color:inherit;opacity:.7;cursor:pointer;padding:.125rem .5rem;font-size:.75rem;transition:opacity .15s ease,border-color .15s ease}.wm-toast-cancel:hover{opacity:1;border-color:currentColor}@keyframes wm-toast-spin{to{transform:rotate(360deg)}}@keyframes wm-toast-slide-in{0%{opacity:0;transform:translate(1rem)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.wm-toast{animation:none}}\n"] }]
|
|
1642
1967
|
}] });
|
|
@@ -1656,9 +1981,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
1656
1981
|
*/
|
|
1657
1982
|
class WmTooltipPanel {
|
|
1658
1983
|
/** Tooltip body. Newlines are preserved — see `white-space` in tooltip.css. */
|
|
1659
|
-
text = input('', ...(ngDevMode ? [{ debugName: "text" }] : []));
|
|
1984
|
+
text = input('', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
1660
1985
|
/** Id the host points at with aria-describedby / aria-labelledby. */
|
|
1661
|
-
panelId = input('', ...(ngDevMode ? [{ debugName: "panelId" }] : []));
|
|
1986
|
+
panelId = input('', ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
|
|
1662
1987
|
/**
|
|
1663
1988
|
* Drives the enter transition.
|
|
1664
1989
|
*
|
|
@@ -1666,16 +1991,16 @@ class WmTooltipPanel {
|
|
|
1666
1991
|
* fade has two states to move between. Attaching straight to the visible
|
|
1667
1992
|
* state would give the browser nothing to interpolate from.
|
|
1668
1993
|
*/
|
|
1669
|
-
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
1670
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1671
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.
|
|
1994
|
+
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
1995
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTooltipPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1996
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: WmTooltipPanel, isStandalone: true, selector: "wm-tooltip-panel", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, panelId: { classPropertyName: "panelId", publicName: "panelId", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<div
|
|
1672
1997
|
class="wm-tooltip-panel"
|
|
1673
1998
|
[class.wm-tooltip-panel--visible]="visible()"
|
|
1674
1999
|
[id]="panelId()"
|
|
1675
2000
|
role="tooltip"
|
|
1676
2001
|
>{{ text() }}</div>`, isInline: true, styles: [".wm-tooltip-panel{max-width:var(--wm-tooltip-max-width, 260px);padding:6px 9px;background:var(--wm-text-primary);color:var(--wm-bg-base);border-radius:var(--wm-radius-md);box-shadow:var(--wm-shadow-md);font-family:var(--wm-font-sans);font-size:11.5px;font-weight:500;line-height:1.5;text-align:left;white-space:pre-line;overflow-wrap:break-word;opacity:0;transform:translateY(-2px);transition:opacity var(--wm-transition-fast),transform var(--wm-transition-fast)}.wm-tooltip-panel--visible{opacity:1;transform:translateY(0)}.wm-rich-tooltip-panel{max-width:var(--wm-rich-tooltip-max-width, 320px);white-space:normal}.wm-tooltip-above .wm-tooltip-panel{transform:translateY(2px)}.wm-tooltip-above .wm-tooltip-panel--visible{transform:translateY(0)}@media(prefers-reduced-motion:reduce){.wm-tooltip-panel,.wm-tooltip-above .wm-tooltip-panel{transition:none;transform:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1677
2002
|
}
|
|
1678
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2003
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTooltipPanel, decorators: [{
|
|
1679
2004
|
type: Component,
|
|
1680
2005
|
args: [{ selector: 'wm-tooltip-panel', template: `<div
|
|
1681
2006
|
class="wm-tooltip-panel"
|
|
@@ -1771,21 +2096,21 @@ let nextId = 0;
|
|
|
1771
2096
|
*/
|
|
1772
2097
|
class WmTooltip {
|
|
1773
2098
|
/** Tooltip body. Blank or absent means the tooltip never opens. */
|
|
1774
|
-
wmTooltip = input('', ...(ngDevMode ? [{ debugName: "wmTooltip" }] : []));
|
|
2099
|
+
wmTooltip = input('', ...(ngDevMode ? [{ debugName: "wmTooltip" }] : /* istanbul ignore next */ []));
|
|
1775
2100
|
/** Preferred side. Flips automatically when the viewport has no room. */
|
|
1776
|
-
wmTooltipPosition = input('bottom', ...(ngDevMode ? [{ debugName: "wmTooltipPosition" }] : []));
|
|
2101
|
+
wmTooltipPosition = input('bottom', ...(ngDevMode ? [{ debugName: "wmTooltipPosition" }] : /* istanbul ignore next */ []));
|
|
1777
2102
|
/** Milliseconds a pointer must rest on the host before the panel opens. */
|
|
1778
|
-
wmTooltipDelay = input(250, ...(ngDevMode ? [{ debugName: "wmTooltipDelay" }] : []));
|
|
2103
|
+
wmTooltipDelay = input(250, ...(ngDevMode ? [{ debugName: "wmTooltipDelay" }] : /* istanbul ignore next */ []));
|
|
1779
2104
|
/** Suppress the tooltip without unbinding it — for a control whose explanation only applies in some states. */
|
|
1780
|
-
wmTooltipDisabled = input(false, ...(ngDevMode ? [{ debugName: "wmTooltipDisabled" }] : []));
|
|
2105
|
+
wmTooltipDisabled = input(false, ...(ngDevMode ? [{ debugName: "wmTooltipDisabled" }] : /* istanbul ignore next */ []));
|
|
1781
2106
|
/** Whether the panel describes the host or names it. See WmTooltipRelation. */
|
|
1782
|
-
wmTooltipRelation = input('description', ...(ngDevMode ? [{ debugName: "wmTooltipRelation" }] : []));
|
|
2107
|
+
wmTooltipRelation = input('description', ...(ngDevMode ? [{ debugName: "wmTooltipRelation" }] : /* istanbul ignore next */ []));
|
|
1783
2108
|
/**
|
|
1784
2109
|
* Make a non-focusable host a tab stop so a keyboard user can reach the
|
|
1785
2110
|
* tooltip. Only applied when the host is not already focusable, and never
|
|
1786
2111
|
* safe inside a roving-tabindex container — see the class comment.
|
|
1787
2112
|
*/
|
|
1788
|
-
wmTooltipFocusable = input(false, ...(ngDevMode ? [{ debugName: "wmTooltipFocusable" }] : []));
|
|
2113
|
+
wmTooltipFocusable = input(false, ...(ngDevMode ? [{ debugName: "wmTooltipFocusable" }] : /* istanbul ignore next */ []));
|
|
1789
2114
|
host = inject(ElementRef).nativeElement;
|
|
1790
2115
|
injector = inject(Injector);
|
|
1791
2116
|
renderer = inject(Renderer2);
|
|
@@ -2120,10 +2445,10 @@ class WmTooltip {
|
|
|
2120
2445
|
this.overlayRef = null;
|
|
2121
2446
|
this.portal = null;
|
|
2122
2447
|
}
|
|
2123
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2124
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.
|
|
2448
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2449
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.23", type: WmTooltip, isStandalone: true, selector: "[wmTooltip]", inputs: { wmTooltip: { classPropertyName: "wmTooltip", publicName: "wmTooltip", isSignal: true, isRequired: false, transformFunction: null }, wmTooltipPosition: { classPropertyName: "wmTooltipPosition", publicName: "wmTooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, wmTooltipDelay: { classPropertyName: "wmTooltipDelay", publicName: "wmTooltipDelay", isSignal: true, isRequired: false, transformFunction: null }, wmTooltipDisabled: { classPropertyName: "wmTooltipDisabled", publicName: "wmTooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, wmTooltipRelation: { classPropertyName: "wmTooltipRelation", publicName: "wmTooltipRelation", isSignal: true, isRequired: false, transformFunction: null }, wmTooltipFocusable: { classPropertyName: "wmTooltipFocusable", publicName: "wmTooltipFocusable", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "onPointerEnterHost()", "mouseleave": "onPointerLeaveHost()", "focusin": "onFocusHost()", "focusout": "onBlurHost()", "click": "hideNow()" } }, exportAs: ["wmTooltip"], ngImport: i0 });
|
|
2125
2450
|
}
|
|
2126
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmTooltip, decorators: [{
|
|
2127
2452
|
type: Directive,
|
|
2128
2453
|
args: [{
|
|
2129
2454
|
selector: '[wmTooltip]',
|
|
@@ -2147,13 +2472,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
2147
2472
|
*/
|
|
2148
2473
|
class WmRichTooltipPanel {
|
|
2149
2474
|
/** The caller-owned Angular template rendered as the tooltip body. */
|
|
2150
|
-
content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : []));
|
|
2475
|
+
content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
2151
2476
|
/** Id the trigger points at with aria-describedby / aria-labelledby. */
|
|
2152
|
-
panelId = input('', ...(ngDevMode ? [{ debugName: "panelId" }] : []));
|
|
2477
|
+
panelId = input('', ...(ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []));
|
|
2153
2478
|
/** Drives the enter transition after the overlay has attached. */
|
|
2154
|
-
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
2155
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2156
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.
|
|
2479
|
+
visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
2480
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltipPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2481
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: WmRichTooltipPanel, isStandalone: true, selector: "wm-rich-tooltip-panel", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, panelId: { classPropertyName: "panelId", publicName: "panelId", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<div
|
|
2157
2482
|
class="wm-tooltip-panel wm-rich-tooltip-panel"
|
|
2158
2483
|
[class.wm-tooltip-panel--visible]="visible()"
|
|
2159
2484
|
[id]="panelId()"
|
|
@@ -2162,7 +2487,7 @@ class WmRichTooltipPanel {
|
|
|
2162
2487
|
<ng-container [ngTemplateOutlet]="content()"></ng-container>
|
|
2163
2488
|
</div>`, isInline: true, styles: [".wm-tooltip-panel{max-width:var(--wm-tooltip-max-width, 260px);padding:6px 9px;background:var(--wm-text-primary);color:var(--wm-bg-base);border-radius:var(--wm-radius-md);box-shadow:var(--wm-shadow-md);font-family:var(--wm-font-sans);font-size:11.5px;font-weight:500;line-height:1.5;text-align:left;white-space:pre-line;overflow-wrap:break-word;opacity:0;transform:translateY(-2px);transition:opacity var(--wm-transition-fast),transform var(--wm-transition-fast)}.wm-tooltip-panel--visible{opacity:1;transform:translateY(0)}.wm-rich-tooltip-panel{max-width:var(--wm-rich-tooltip-max-width, 320px);white-space:normal}.wm-tooltip-above .wm-tooltip-panel{transform:translateY(2px)}.wm-tooltip-above .wm-tooltip-panel--visible{transform:translateY(0)}@media(prefers-reduced-motion:reduce){.wm-tooltip-panel,.wm-tooltip-above .wm-tooltip-panel{transition:none;transform:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2164
2489
|
}
|
|
2165
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2490
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltipPanel, decorators: [{
|
|
2166
2491
|
type: Component,
|
|
2167
2492
|
args: [{ selector: 'wm-rich-tooltip-panel', imports: [NgTemplateOutlet], template: `<div
|
|
2168
2493
|
class="wm-tooltip-panel wm-rich-tooltip-panel"
|
|
@@ -2177,10 +2502,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
2177
2502
|
/** Marks the projected element that owns a rich tooltip. */
|
|
2178
2503
|
class WmRichTooltipTrigger {
|
|
2179
2504
|
elementRef = inject((ElementRef));
|
|
2180
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2181
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.
|
|
2505
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltipTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2506
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.23", type: WmRichTooltipTrigger, isStandalone: true, selector: "[wmRichTooltipTrigger]", ngImport: i0 });
|
|
2182
2507
|
}
|
|
2183
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2508
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltipTrigger, decorators: [{
|
|
2184
2509
|
type: Directive,
|
|
2185
2510
|
args: [{
|
|
2186
2511
|
selector: '[wmRichTooltipTrigger]',
|
|
@@ -2189,10 +2514,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
2189
2514
|
/** Marks the projected Angular template used as a rich tooltip's body. */
|
|
2190
2515
|
class WmRichTooltipContent {
|
|
2191
2516
|
templateRef = inject((TemplateRef));
|
|
2192
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2193
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.
|
|
2517
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltipContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2518
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.23", type: WmRichTooltipContent, isStandalone: true, selector: "ng-template[wmRichTooltipContent]", ngImport: i0 });
|
|
2194
2519
|
}
|
|
2195
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2520
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltipContent, decorators: [{
|
|
2196
2521
|
type: Directive,
|
|
2197
2522
|
args: [{
|
|
2198
2523
|
selector: 'ng-template[wmRichTooltipContent]',
|
|
@@ -2230,19 +2555,19 @@ const HIDE_DELAY_MS = 120;
|
|
|
2230
2555
|
*/
|
|
2231
2556
|
class WmRichTooltip {
|
|
2232
2557
|
/** Preferred side. Flips automatically when the viewport has no room. */
|
|
2233
|
-
position = input('bottom', ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
2558
|
+
position = input('bottom', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
2234
2559
|
/** Milliseconds a pointer must rest on the trigger before opening. */
|
|
2235
|
-
delay = input(250, ...(ngDevMode ? [{ debugName: "delay" }] : []));
|
|
2560
|
+
delay = input(250, ...(ngDevMode ? [{ debugName: "delay" }] : /* istanbul ignore next */ []));
|
|
2236
2561
|
/** Suppress the tooltip without removing its projected content. */
|
|
2237
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
2562
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
2238
2563
|
/** Whether the panel describes the trigger or names it. */
|
|
2239
|
-
relation = input('description', ...(ngDevMode ? [{ debugName: "relation" }] : []));
|
|
2564
|
+
relation = input('description', ...(ngDevMode ? [{ debugName: "relation" }] : /* istanbul ignore next */ []));
|
|
2240
2565
|
/** Make a non-focusable projected trigger reachable by keyboard when needed. */
|
|
2241
|
-
focusable = input(false, ...(ngDevMode ? [{ debugName: "focusable" }] : []));
|
|
2566
|
+
focusable = input(false, ...(ngDevMode ? [{ debugName: "focusable" }] : /* istanbul ignore next */ []));
|
|
2242
2567
|
injector = inject(Injector);
|
|
2243
2568
|
renderer = inject(Renderer2);
|
|
2244
|
-
triggerQuery = contentChild(WmRichTooltipTrigger, ...(ngDevMode ? [{ debugName: "triggerQuery" }] : []));
|
|
2245
|
-
contentQuery = contentChild(WmRichTooltipContent, ...(ngDevMode ? [{ debugName: "contentQuery" }] : []));
|
|
2569
|
+
triggerQuery = contentChild(WmRichTooltipTrigger, ...(ngDevMode ? [{ debugName: "triggerQuery" }] : /* istanbul ignore next */ []));
|
|
2570
|
+
contentQuery = contentChild(WmRichTooltipContent, ...(ngDevMode ? [{ debugName: "contentQuery" }] : /* istanbul ignore next */ []));
|
|
2246
2571
|
panelId = `wm-rich-tooltip-${nextRichTooltipId++}`;
|
|
2247
2572
|
triggerElement = null;
|
|
2248
2573
|
contentTemplate = null;
|
|
@@ -2585,13 +2910,13 @@ class WmRichTooltip {
|
|
|
2585
2910
|
this.overlayRef = null;
|
|
2586
2911
|
this.portal = null;
|
|
2587
2912
|
}
|
|
2588
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2589
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.
|
|
2913
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltip, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2914
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: WmRichTooltip, isStandalone: true, selector: "wm-rich-tooltip", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, relation: { classPropertyName: "relation", publicName: "relation", isSignal: true, isRequired: false, transformFunction: null }, focusable: { classPropertyName: "focusable", publicName: "focusable", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: contents" }, queries: [{ propertyName: "triggerQuery", first: true, predicate: WmRichTooltipTrigger, descendants: true, isSignal: true }, { propertyName: "contentQuery", first: true, predicate: WmRichTooltipContent, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
2590
2915
|
<ng-content select="[wmRichTooltipTrigger]"></ng-content>
|
|
2591
2916
|
<ng-content select="ng-template[wmRichTooltipContent]"></ng-content>
|
|
2592
2917
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2593
2918
|
}
|
|
2594
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmRichTooltip, decorators: [{
|
|
2595
2920
|
type: Component,
|
|
2596
2921
|
args: [{
|
|
2597
2922
|
selector: 'wm-rich-tooltip',
|
|
@@ -2605,145 +2930,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
|
|
|
2605
2930
|
}]
|
|
2606
2931
|
}], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], relation: [{ type: i0.Input, args: [{ isSignal: true, alias: "relation", required: false }] }], focusable: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusable", required: false }] }], triggerQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => WmRichTooltipTrigger), { isSignal: true }] }], contentQuery: [{ type: i0.ContentChild, args: [i0.forwardRef(() => WmRichTooltipContent), { isSignal: true }] }] } });
|
|
2607
2932
|
|
|
2608
|
-
class WmLicenseService {
|
|
2609
|
-
toast = inject(WmToastService);
|
|
2610
|
-
license = signal(null, ...(ngDevMode ? [{ debugName: "license" }] : []));
|
|
2611
|
-
isLicensed = computed(() => this.license()?.valid ?? false, ...(ngDevMode ? [{ debugName: "isLicensed" }] : []));
|
|
2612
|
-
orgName = computed(() => this.license()?.org ?? null, ...(ngDevMode ? [{ debugName: "orgName" }] : []));
|
|
2613
|
-
async checkLicense() {
|
|
2614
|
-
try {
|
|
2615
|
-
const status = await invoke('get_license_status');
|
|
2616
|
-
this.license.set(status);
|
|
2617
|
-
if (!status.valid && status.error) {
|
|
2618
|
-
const message = status.error === 'expired'
|
|
2619
|
-
? 'Your license key has expired.'
|
|
2620
|
-
: 'Your license key is not valid.';
|
|
2621
|
-
this.toast.error(message);
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
catch (e) {
|
|
2625
|
-
console.error('License check failed:', e);
|
|
2626
|
-
this.license.set(null);
|
|
2627
|
-
}
|
|
2628
|
-
}
|
|
2629
|
-
async installKey(jwt) {
|
|
2630
|
-
const status = await invoke('install_license', { key: jwt });
|
|
2631
|
-
this.license.set(status);
|
|
2632
|
-
return status;
|
|
2633
|
-
}
|
|
2634
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2635
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseService, providedIn: 'root' });
|
|
2636
|
-
}
|
|
2637
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseService, decorators: [{
|
|
2638
|
-
type: Injectable,
|
|
2639
|
-
args: [{ providedIn: 'root' }]
|
|
2640
|
-
}] });
|
|
2641
|
-
|
|
2642
|
-
class WmLicenseNudge {
|
|
2643
|
-
licenseService = inject(WmLicenseService);
|
|
2644
|
-
/**
|
|
2645
|
-
* Self-declared use type from the host app's first-run modal. When the
|
|
2646
|
-
* user has declared `personal` or `oss` the nudge stays hidden — they've
|
|
2647
|
-
* already told us a commercial key isn't relevant. `commercial` (without
|
|
2648
|
-
* a key) and `null` (no declaration yet) keep the nudge visible.
|
|
2649
|
-
*
|
|
2650
|
-
* Typed `string | null` rather than `WmDeclaredUseType | null` because
|
|
2651
|
-
* ng-packagr's partial-compilation d.ts emit drops the `null` from a
|
|
2652
|
-
* union with a string-literal type, which then forces every consumer to
|
|
2653
|
-
* `as` the binding. Runtime narrowing happens in `shouldShow`.
|
|
2654
|
-
*/
|
|
2655
|
-
declaredUseType = input(null, ...(ngDevMode ? [{ debugName: "declaredUseType" }] : []));
|
|
2656
|
-
dismissed = signal(false, ...(ngDevMode ? [{ debugName: "dismissed" }] : []));
|
|
2657
|
-
enterLicense = output();
|
|
2658
|
-
shouldShow = () => {
|
|
2659
|
-
if (this.licenseService.isLicensed())
|
|
2660
|
-
return false;
|
|
2661
|
-
if (this.dismissed())
|
|
2662
|
-
return false;
|
|
2663
|
-
const ut = this.declaredUseType();
|
|
2664
|
-
if (ut === 'personal' || ut === 'oss')
|
|
2665
|
-
return false;
|
|
2666
|
-
return true;
|
|
2667
|
-
};
|
|
2668
|
-
dismiss() {
|
|
2669
|
-
this.dismissed.set(true);
|
|
2670
|
-
}
|
|
2671
|
-
onEnterLicense() {
|
|
2672
|
-
this.enterLicense.emit();
|
|
2673
|
-
}
|
|
2674
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseNudge, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2675
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: WmLicenseNudge, isStandalone: true, selector: "wm-license-nudge", inputs: { declaredUseType: { classPropertyName: "declaredUseType", publicName: "declaredUseType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { enterLicense: "enterLicense" }, ngImport: i0, template: "@if (shouldShow()) {\n <div class=\"wm-license-nudge\">\n <span class=\"wm-license-nudge__text\">\n Using this at work? Organizations require a commercial license.\n </span>\n <div class=\"wm-license-nudge__actions\">\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"onEnterLicense()\">Enter License Key</wm-button>\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"dismiss()\">Dismiss</wm-button>\n </div>\n </div>\n}\n", styles: [".wm-license-nudge{display:flex;align-items:center;justify-content:space-between;gap:var(--wm-space-md, 12px);padding:var(--wm-space-sm, 8px) var(--wm-space-md, 12px);background:var(--wm-bg-subtle, #2a2a2a);border-bottom:1px solid var(--wm-border, #3a3a3a);font-size:var(--wm-font-sm, 13px);color:var(--wm-fg-secondary, #999)}.wm-license-nudge__text{flex:1}.wm-license-nudge__actions{display:flex;gap:var(--wm-space-xs, 4px);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: WmButton, selector: "wm-button", inputs: ["variant", "size", "disabled", "type", "iconOnly", "ariaLabel", "btnTitle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2676
|
-
}
|
|
2677
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseNudge, decorators: [{
|
|
2678
|
-
type: Component,
|
|
2679
|
-
args: [{ selector: 'wm-license-nudge', standalone: true, imports: [WmButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (shouldShow()) {\n <div class=\"wm-license-nudge\">\n <span class=\"wm-license-nudge__text\">\n Using this at work? Organizations require a commercial license.\n </span>\n <div class=\"wm-license-nudge__actions\">\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"onEnterLicense()\">Enter License Key</wm-button>\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"dismiss()\">Dismiss</wm-button>\n </div>\n </div>\n}\n", styles: [".wm-license-nudge{display:flex;align-items:center;justify-content:space-between;gap:var(--wm-space-md, 12px);padding:var(--wm-space-sm, 8px) var(--wm-space-md, 12px);background:var(--wm-bg-subtle, #2a2a2a);border-bottom:1px solid var(--wm-border, #3a3a3a);font-size:var(--wm-font-sm, 13px);color:var(--wm-fg-secondary, #999)}.wm-license-nudge__text{flex:1}.wm-license-nudge__actions{display:flex;gap:var(--wm-space-xs, 4px);flex-shrink:0}\n"] }]
|
|
2680
|
-
}], propDecorators: { declaredUseType: [{ type: i0.Input, args: [{ isSignal: true, alias: "declaredUseType", required: false }] }], enterLicense: [{ type: i0.Output, args: ["enterLicense"] }] } });
|
|
2681
|
-
|
|
2682
|
-
class WmLicenseDialog {
|
|
2683
|
-
licenseService = inject(WmLicenseService);
|
|
2684
|
-
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
2685
|
-
dismiss = output();
|
|
2686
|
-
keyInput = signal('', ...(ngDevMode ? [{ debugName: "keyInput" }] : []));
|
|
2687
|
-
validationResult = signal(null, ...(ngDevMode ? [{ debugName: "validationResult" }] : []));
|
|
2688
|
-
validating = signal(false, ...(ngDevMode ? [{ debugName: "validating" }] : []));
|
|
2689
|
-
installed = signal(false, ...(ngDevMode ? [{ debugName: "installed" }] : []));
|
|
2690
|
-
onDismiss() {
|
|
2691
|
-
this.reset();
|
|
2692
|
-
this.dismiss.emit();
|
|
2693
|
-
}
|
|
2694
|
-
onKeyInput(event) {
|
|
2695
|
-
const value = event.target.value;
|
|
2696
|
-
this.keyInput.set(value);
|
|
2697
|
-
this.validationResult.set(null);
|
|
2698
|
-
this.installed.set(false);
|
|
2699
|
-
}
|
|
2700
|
-
async validate() {
|
|
2701
|
-
const jwt = this.keyInput().trim();
|
|
2702
|
-
if (!jwt)
|
|
2703
|
-
return;
|
|
2704
|
-
this.validating.set(true);
|
|
2705
|
-
try {
|
|
2706
|
-
const status = await this.licenseService.installKey(jwt);
|
|
2707
|
-
this.validationResult.set(status);
|
|
2708
|
-
if (status.valid) {
|
|
2709
|
-
this.installed.set(true);
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
catch (e) {
|
|
2713
|
-
this.validationResult.set({
|
|
2714
|
-
valid: false,
|
|
2715
|
-
org: null,
|
|
2716
|
-
product: '',
|
|
2717
|
-
seats: null,
|
|
2718
|
-
tier: null,
|
|
2719
|
-
expires: null,
|
|
2720
|
-
key_id: null,
|
|
2721
|
-
error: String(e),
|
|
2722
|
-
});
|
|
2723
|
-
}
|
|
2724
|
-
finally {
|
|
2725
|
-
this.validating.set(false);
|
|
2726
|
-
}
|
|
2727
|
-
}
|
|
2728
|
-
reset() {
|
|
2729
|
-
this.keyInput.set('');
|
|
2730
|
-
this.validationResult.set(null);
|
|
2731
|
-
this.validating.set(false);
|
|
2732
|
-
this.installed.set(false);
|
|
2733
|
-
}
|
|
2734
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2735
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: WmLicenseDialog, isStandalone: true, selector: "wm-license-dialog", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { dismiss: "dismiss" }, ngImport: i0, template: "<wm-modal [visible]=\"visible()\" (dismiss)=\"onDismiss()\">\n <div class=\"wm-license-dialog\">\n <h2 class=\"wm-license-dialog__title\">Enter License Key</h2>\n\n @if (installed()) {\n <div class=\"wm-license-dialog__success\">\n <p class=\"wm-license-dialog__success-text\">License activated successfully.</p>\n <dl class=\"wm-license-dialog__details\">\n <dt>Organization</dt>\n <dd>{{ validationResult()?.org }}</dd>\n <dt>Seats</dt>\n <dd>{{ validationResult()?.seats }}</dd>\n <dt>Expires</dt>\n <dd>{{ validationResult()?.expires?.slice(0, 10) }}</dd>\n </dl>\n <wm-button variant=\"primary\" size=\"sm\" (click)=\"onDismiss()\">Done</wm-button>\n </div>\n } @else {\n <textarea\n class=\"wm-license-dialog__input\"\n placeholder=\"Paste your license key here...\"\n [value]=\"keyInput()\"\n (input)=\"onKeyInput($event)\"\n rows=\"4\"\n ></textarea>\n\n @if (validationResult(); as result) {\n @if (!result.valid) {\n <p class=\"wm-license-dialog__error\">\n @if (result.error === 'expired') {\n This license key has expired.\n } @else {\n This is not a valid license key for this product.\n }\n </p>\n }\n }\n\n <div class=\"wm-license-dialog__actions\">\n <wm-button\n variant=\"primary\"\n size=\"sm\"\n [disabled]=\"!keyInput().trim() || validating()\"\n (click)=\"validate()\"\n >\n @if (validating()) { Validating... } @else { Activate }\n </wm-button>\n </div>\n }\n </div>\n</wm-modal>\n", styles: [".wm-license-dialog{background:var(--wm-bg-raised, #1e1e1e);border-radius:var(--wm-radius-md, 8px);padding:var(--wm-space-lg, 20px);width:480px;max-width:90vw;display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__title{font-size:var(--wm-font-lg, 16px);font-weight:600;color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__input{width:100%;resize:vertical;font-family:var(--wm-font-mono, monospace);font-size:var(--wm-font-sm, 13px);padding:var(--wm-space-sm, 8px);border:1px solid var(--wm-border, #3a3a3a);border-radius:var(--wm-radius-sm, 4px);background:var(--wm-bg-input, #141414);color:var(--wm-fg-primary, #fff);box-sizing:border-box}.wm-license-dialog__input:focus{outline:none;border-color:var(--wm-accent, #4a9eff)}.wm-license-dialog__error{color:var(--wm-fg-error, #f44);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__success{display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__success-text{color:var(--wm-fg-success, #4caf50);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details{display:grid;grid-template-columns:auto 1fr;gap:var(--wm-space-xs, 4px) var(--wm-space-md, 12px);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details dt{color:var(--wm-fg-secondary, #999)}.wm-license-dialog__details dd{color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__actions{display:flex;justify-content:flex-end;gap:var(--wm-space-sm, 8px)}\n"], dependencies: [{ kind: "component", type: WmModal, selector: "wm-modal", inputs: ["visible", "align"], outputs: ["dismiss"] }, { kind: "component", type: WmButton, selector: "wm-button", inputs: ["variant", "size", "disabled", "type", "iconOnly", "ariaLabel", "btnTitle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2736
|
-
}
|
|
2737
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: WmLicenseDialog, decorators: [{
|
|
2738
|
-
type: Component,
|
|
2739
|
-
args: [{ selector: 'wm-license-dialog', standalone: true, imports: [WmModal, WmButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<wm-modal [visible]=\"visible()\" (dismiss)=\"onDismiss()\">\n <div class=\"wm-license-dialog\">\n <h2 class=\"wm-license-dialog__title\">Enter License Key</h2>\n\n @if (installed()) {\n <div class=\"wm-license-dialog__success\">\n <p class=\"wm-license-dialog__success-text\">License activated successfully.</p>\n <dl class=\"wm-license-dialog__details\">\n <dt>Organization</dt>\n <dd>{{ validationResult()?.org }}</dd>\n <dt>Seats</dt>\n <dd>{{ validationResult()?.seats }}</dd>\n <dt>Expires</dt>\n <dd>{{ validationResult()?.expires?.slice(0, 10) }}</dd>\n </dl>\n <wm-button variant=\"primary\" size=\"sm\" (click)=\"onDismiss()\">Done</wm-button>\n </div>\n } @else {\n <textarea\n class=\"wm-license-dialog__input\"\n placeholder=\"Paste your license key here...\"\n [value]=\"keyInput()\"\n (input)=\"onKeyInput($event)\"\n rows=\"4\"\n ></textarea>\n\n @if (validationResult(); as result) {\n @if (!result.valid) {\n <p class=\"wm-license-dialog__error\">\n @if (result.error === 'expired') {\n This license key has expired.\n } @else {\n This is not a valid license key for this product.\n }\n </p>\n }\n }\n\n <div class=\"wm-license-dialog__actions\">\n <wm-button\n variant=\"primary\"\n size=\"sm\"\n [disabled]=\"!keyInput().trim() || validating()\"\n (click)=\"validate()\"\n >\n @if (validating()) { Validating... } @else { Activate }\n </wm-button>\n </div>\n }\n </div>\n</wm-modal>\n", styles: [".wm-license-dialog{background:var(--wm-bg-raised, #1e1e1e);border-radius:var(--wm-radius-md, 8px);padding:var(--wm-space-lg, 20px);width:480px;max-width:90vw;display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__title{font-size:var(--wm-font-lg, 16px);font-weight:600;color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__input{width:100%;resize:vertical;font-family:var(--wm-font-mono, monospace);font-size:var(--wm-font-sm, 13px);padding:var(--wm-space-sm, 8px);border:1px solid var(--wm-border, #3a3a3a);border-radius:var(--wm-radius-sm, 4px);background:var(--wm-bg-input, #141414);color:var(--wm-fg-primary, #fff);box-sizing:border-box}.wm-license-dialog__input:focus{outline:none;border-color:var(--wm-accent, #4a9eff)}.wm-license-dialog__error{color:var(--wm-fg-error, #f44);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__success{display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__success-text{color:var(--wm-fg-success, #4caf50);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details{display:grid;grid-template-columns:auto 1fr;gap:var(--wm-space-xs, 4px) var(--wm-space-md, 12px);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details dt{color:var(--wm-fg-secondary, #999)}.wm-license-dialog__details dd{color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__actions{display:flex;justify-content:flex-end;gap:var(--wm-space-sm, 8px)}\n"] }]
|
|
2740
|
-
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }] } });
|
|
2741
|
-
|
|
2742
2933
|
// Components
|
|
2743
2934
|
|
|
2744
2935
|
/**
|
|
2745
2936
|
* Generated bundle index. Do not edit.
|
|
2746
2937
|
*/
|
|
2747
2938
|
|
|
2748
|
-
export { Checkbox, GhostField, NumberInput, PageHeader, Toggle, WmAnchoredScrollStrategy, WmAutoFocus, WmButton, WmCombobox, WmDialog,
|
|
2939
|
+
export { Checkbox, GhostField, NumberInput, PageHeader, Toggle, WmAnchoredScrollStrategy, WmAutoFocus, WmButton, WmCombobox, WmDialog, WmModal, WmPopover, WmRichTooltip, WmRichTooltipContent, WmRichTooltipTrigger, WmSelect, WmSlider, WmTab, WmTabs, WmToastContainer, WmToastService, WmTooltip, onViewportChange };
|
|
2749
2940
|
//# sourceMappingURL=wildmason-aegis.mjs.map
|