@mk-kit/ui 0.36.0 → 0.37.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/README.md +6 -6
- package/fesm2022/mk-kit-ui-chat.mjs +490 -0
- package/fesm2022/mk-kit-ui-chat.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-core.mjs +308 -1
- package/fesm2022/mk-kit-ui-core.mjs.map +1 -1
- package/fesm2022/mk-kit-ui-feedback.mjs +400 -8
- package/fesm2022/mk-kit-ui-feedback.mjs.map +1 -1
- package/fesm2022/mk-kit-ui-forms.mjs +816 -6
- package/fesm2022/mk-kit-ui-forms.mjs.map +1 -1
- package/fesm2022/mk-kit-ui-query-builder.mjs +276 -0
- package/fesm2022/mk-kit-ui-query-builder.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-table.mjs +20 -1
- package/fesm2022/mk-kit-ui-table.mjs.map +1 -1
- package/fesm2022/mk-kit-ui.mjs +2 -0
- package/fesm2022/mk-kit-ui.mjs.map +1 -1
- package/package.json +9 -1
- package/types/mk-kit-ui-chat.d.ts +288 -0
- package/types/mk-kit-ui-core.d.ts +163 -2
- package/types/mk-kit-ui-feedback.d.ts +111 -2
- package/types/mk-kit-ui-forms.d.ts +264 -3
- package/types/mk-kit-ui-query-builder.d.ts +98 -0
- package/types/mk-kit-ui-table.d.ts +12 -0
- package/types/mk-kit-ui.d.ts +2 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, input, booleanAttribute, contentChild, signal, effect, DestroyRef,
|
|
2
|
+
import { inject, input, booleanAttribute, ElementRef, contentChild, signal, computed, afterNextRender, effect, DestroyRef, forwardRef, ChangeDetectionStrategy, Component, DOCUMENT, Injector, viewChild, model, output, contentChildren, numberAttribute, afterRenderEffect, untracked, ViewContainerRef, Directive, viewChildren, TemplateRef, PLATFORM_ID } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { NgForm, FormGroupDirective, NgControl, Validators, FormGroup, FormArray, NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS } from '@angular/forms';
|
|
5
5
|
import { MK_I18N, mkUniqueId, mkFirstErrorMessage, MkFieldContext, MkAnchoredPanel, MkLiveAnnouncer, mkValidatorChange, mkHighlight } from '@mk-kit/ui/core';
|
|
@@ -95,8 +95,42 @@ class MkFormField {
|
|
|
95
95
|
/** Control size; nested controls inherit it. */
|
|
96
96
|
size = input('md', /* @ts-ignore */
|
|
97
97
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
98
|
+
/**
|
|
99
|
+
* Where the label sits: above the control (default), or `float` — inside
|
|
100
|
+
* the control, sliding up once it is focused or has a value. Floating works
|
|
101
|
+
* with `mkInput` / textarea and any control bound with `ngModel` or a
|
|
102
|
+
* `formControl`; the placeholder stays hidden until the label has moved.
|
|
103
|
+
*/
|
|
104
|
+
labelPosition = input('top', /* @ts-ignore */
|
|
105
|
+
...(ngDevMode ? [{ debugName: "labelPosition" }] : /* istanbul ignore next */ []));
|
|
106
|
+
host = inject(ElementRef);
|
|
98
107
|
/** The projected control's form binding, when it has one. */
|
|
99
108
|
ngControl = contentChild(NgControl, { ...(ngDevMode ? { debugName: "ngControl" } : /* istanbul ignore next */ {}), descendants: true });
|
|
109
|
+
/** A control inside the field has focus. */
|
|
110
|
+
focused = signal(false, /* @ts-ignore */
|
|
111
|
+
...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
|
|
112
|
+
/** Last value read straight from a native control (fallback when no NgControl). */
|
|
113
|
+
domValue = signal(null, /* @ts-ignore */
|
|
114
|
+
...(ngDevMode ? [{ debugName: "domValue" }] : /* istanbul ignore next */ []));
|
|
115
|
+
/** The field holds a non-empty value (drives the floating label). */
|
|
116
|
+
hasValue = computed(() => {
|
|
117
|
+
this.controlTick();
|
|
118
|
+
const control = this.ngControl();
|
|
119
|
+
const v = control ? control.value : this.domValue();
|
|
120
|
+
if (v == null || v === '')
|
|
121
|
+
return false;
|
|
122
|
+
if (Array.isArray(v))
|
|
123
|
+
return v.length > 0;
|
|
124
|
+
return true;
|
|
125
|
+
}, /* @ts-ignore */
|
|
126
|
+
...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
|
|
127
|
+
/** Track a native control's value for the floating label when nothing else reports it. */
|
|
128
|
+
readDomValue(target) {
|
|
129
|
+
const el = target;
|
|
130
|
+
if (!el || typeof el.value !== 'string')
|
|
131
|
+
return;
|
|
132
|
+
this.domValue.set(el.value);
|
|
133
|
+
}
|
|
100
134
|
/**
|
|
101
135
|
* Bumped on every change of the bound control so the computed state below
|
|
102
136
|
* re-reads it. `AbstractControl` is not signal-based, so this bridges its
|
|
@@ -113,6 +147,11 @@ class MkFormField {
|
|
|
113
147
|
/** Id of the error element. */
|
|
114
148
|
errorId = `${this.controlId}-error`;
|
|
115
149
|
constructor() {
|
|
150
|
+
afterNextRender(() => {
|
|
151
|
+
const el = this.host.nativeElement.querySelector('input, textarea, select');
|
|
152
|
+
if (el)
|
|
153
|
+
this.readDomValue(el);
|
|
154
|
+
});
|
|
116
155
|
const bump = () => this.controlTick.update((n) => n + 1);
|
|
117
156
|
let sub = null;
|
|
118
157
|
// `AbstractControl.events` emits on value, status, pristine and touched
|
|
@@ -190,12 +229,12 @@ class MkFormField {
|
|
|
190
229
|
}, /* @ts-ignore */
|
|
191
230
|
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
192
231
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkFormField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
193
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkFormField, isStandalone: true, selector: "mk-form-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, errorMessages: { classPropertyName: "errorMessages", publicName: "errorMessages", isSignal: true, isRequired: false, transformFunction: null }, errorOn: { classPropertyName: "errorOn", publicName: "errorOn", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.mk-form-field--sm": "size() === 'sm'", "class.mk-form-field--md": "size() === 'md'", "class.mk-form-field--lg": "size() === 'lg'", "class.mk-form-field--invalid": "hasError()", "class.mk-form-field--required": "isRequired()", "class.mk-form-field--disabled": "isDisabled()" }, classAttribute: "mk-form-field" }, providers: [
|
|
232
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkFormField, isStandalone: true, selector: "mk-form-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, errorMessages: { classPropertyName: "errorMessages", publicName: "errorMessages", isSignal: true, isRequired: false, transformFunction: null }, errorOn: { classPropertyName: "errorOn", publicName: "errorOn", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focusin": "focused.set(true)", "focusout": "focused.set(false)", "input": "readDomValue($event.target)", "change": "readDomValue($event.target)" }, properties: { "class.mk-form-field--sm": "size() === 'sm'", "class.mk-form-field--md": "size() === 'md'", "class.mk-form-field--lg": "size() === 'lg'", "class.mk-form-field--invalid": "hasError()", "class.mk-form-field--required": "isRequired()", "class.mk-form-field--disabled": "isDisabled()", "class.mk-form-field--float": "labelPosition() === 'float'", "class.mk-form-field--focused": "focused()", "class.mk-form-field--filled": "hasValue()" }, classAttribute: "mk-form-field" }, providers: [
|
|
194
233
|
{
|
|
195
234
|
provide: MkFieldContext,
|
|
196
235
|
useExisting: forwardRef(() => MkFormField),
|
|
197
236
|
},
|
|
198
|
-
], queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <label class=\"mk-form-field__label\" [id]=\"labelId\" [attr.for]=\"controlId\">\n <span class=\"mk-form-field__label-text\">{{ label() }}</span>\n @if (isRequired()) {\n <span class=\"mk-form-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n}\n\n<div class=\"mk-form-field__control\">\n <ng-content />\n</div>\n\n@if (hintVisible()) {\n <p class=\"mk-form-field__hint\" [id]=\"hintId\">{{ hint() }}</p>\n}\n\n@if (hasError()) {\n <p class=\"mk-form-field__error\" [id]=\"errorId\" role=\"alert\">{{ errorText() }}</p>\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--mk-space-2);font-family:var(--mk-font-sans);color:var(--mk-text)}.mk-form-field__label{display:inline-flex;align-items:center;gap:var(--mk-space-1);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-medium);line-height:var(--mk-line-height-snug);color:var(--mk-text);width:fit-content}:host(.mk-form-field--lg) .mk-form-field__label{font-size:var(--mk-font-size-md)}:host(.mk-form-field--sm) .mk-form-field__label{font-size:var(--mk-font-size-xs)}.mk-form-field__required{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-bold);line-height:1}.mk-form-field__control{display:block;min-width:0}.mk-form-field__hint,.mk-form-field__error{margin:0;font-size:var(--mk-font-size-xs);line-height:var(--mk-line-height-snug)}.mk-form-field__hint{color:var(--mk-text-muted)}.mk-form-field__error{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-medium)}:host(.mk-form-field--disabled){opacity:.6}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
237
|
+
], queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true, isSignal: true }], ngImport: i0, template: "@if (label() && labelPosition() !== 'float') {\n <label class=\"mk-form-field__label\" [id]=\"labelId\" [attr.for]=\"controlId\">\n <span class=\"mk-form-field__label-text\">{{ label() }}</span>\n @if (isRequired()) {\n <span class=\"mk-form-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n}\n\n<div class=\"mk-form-field__control\">\n <ng-content />\n @if (label() && labelPosition() === 'float') {\n <label class=\"mk-form-field__label mk-form-field__label--float\" [id]=\"labelId\" [attr.for]=\"controlId\">\n <span class=\"mk-form-field__label-text\">{{ label() }}</span>\n @if (isRequired()) {\n <span class=\"mk-form-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n</div>\n\n@if (hintVisible()) {\n <p class=\"mk-form-field__hint\" [id]=\"hintId\">{{ hint() }}</p>\n}\n\n@if (hasError()) {\n <p class=\"mk-form-field__error\" [id]=\"errorId\" role=\"alert\">{{ errorText() }}</p>\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--mk-space-2);font-family:var(--mk-font-sans);color:var(--mk-text)}.mk-form-field__label{display:inline-flex;align-items:center;gap:var(--mk-space-1);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-medium);line-height:var(--mk-line-height-snug);color:var(--mk-text);width:fit-content}:host(.mk-form-field--lg) .mk-form-field__label{font-size:var(--mk-font-size-md)}:host(.mk-form-field--sm) .mk-form-field__label{font-size:var(--mk-font-size-xs)}.mk-form-field__required{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-bold);line-height:1}.mk-form-field__control{display:block;min-width:0}.mk-form-field__hint,.mk-form-field__error{margin:0;font-size:var(--mk-font-size-xs);line-height:var(--mk-line-height-snug)}.mk-form-field__hint{color:var(--mk-text-muted)}.mk-form-field__error{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-medium)}:host(.mk-form-field--disabled){opacity:.6}:host(.mk-form-field--float) .mk-form-field__control{position:relative}.mk-form-field__label--float{position:absolute;inset-inline-start:var(--mk-space-3);top:50%;translate:0 -50%;max-width:calc(100% - 2 * var(--mk-space-3));overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:var(--mk-font-size-md);font-weight:var(--mk-font-weight-normal);color:var(--mk-text-muted);pointer-events:none;transition:top var(--mk-duration-fast) var(--mk-ease-standard),translate var(--mk-duration-fast) var(--mk-ease-standard),font-size var(--mk-duration-fast) var(--mk-ease-standard),color var(--mk-duration-fast) var(--mk-ease-standard)}:host(.mk-form-field--focused) .mk-form-field__label--float,:host(.mk-form-field--filled) .mk-form-field__label--float{top:.35rem;translate:0 0;font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-medium)}:host(.mk-form-field--focused) .mk-form-field__label--float{color:var(--mk-primary)}:host(.mk-form-field--invalid) .mk-form-field__label--float{color:var(--mk-danger-text)}:host(.mk-form-field--float) ::ng-deep .mk-input:not(textarea){height:calc(var(--mk-control-height-md) + .75rem);padding-top:1.05rem}:host(.mk-form-field--float) ::ng-deep textarea.mk-input{padding-top:1.5rem}:host(.mk-form-field--float:not(.mk-form-field--focused):not(.mk-form-field--filled)) ::ng-deep .mk-input::placeholder{color:transparent}@media(prefers-reduced-motion:reduce){.mk-form-field__label--float{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
199
238
|
}
|
|
200
239
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkFormField, decorators: [{
|
|
201
240
|
type: Component,
|
|
@@ -207,13 +246,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
207
246
|
'[class.mk-form-field--invalid]': 'hasError()',
|
|
208
247
|
'[class.mk-form-field--required]': 'isRequired()',
|
|
209
248
|
'[class.mk-form-field--disabled]': 'isDisabled()',
|
|
249
|
+
'[class.mk-form-field--float]': "labelPosition() === 'float'",
|
|
250
|
+
'[class.mk-form-field--focused]': 'focused()',
|
|
251
|
+
'[class.mk-form-field--filled]': 'hasValue()',
|
|
252
|
+
'(focusin)': 'focused.set(true)',
|
|
253
|
+
'(focusout)': 'focused.set(false)',
|
|
254
|
+
'(input)': 'readDomValue($event.target)',
|
|
255
|
+
'(change)': 'readDomValue($event.target)',
|
|
210
256
|
}, providers: [
|
|
211
257
|
{
|
|
212
258
|
provide: MkFieldContext,
|
|
213
259
|
useExisting: forwardRef(() => MkFormField),
|
|
214
260
|
},
|
|
215
|
-
], template: "@if (label()) {\n <label class=\"mk-form-field__label\" [id]=\"labelId\" [attr.for]=\"controlId\">\n <span class=\"mk-form-field__label-text\">{{ label() }}</span>\n @if (isRequired()) {\n <span class=\"mk-form-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n}\n\n<div class=\"mk-form-field__control\">\n <ng-content />\n</div>\n\n@if (hintVisible()) {\n <p class=\"mk-form-field__hint\" [id]=\"hintId\">{{ hint() }}</p>\n}\n\n@if (hasError()) {\n <p class=\"mk-form-field__error\" [id]=\"errorId\" role=\"alert\">{{ errorText() }}</p>\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--mk-space-2);font-family:var(--mk-font-sans);color:var(--mk-text)}.mk-form-field__label{display:inline-flex;align-items:center;gap:var(--mk-space-1);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-medium);line-height:var(--mk-line-height-snug);color:var(--mk-text);width:fit-content}:host(.mk-form-field--lg) .mk-form-field__label{font-size:var(--mk-font-size-md)}:host(.mk-form-field--sm) .mk-form-field__label{font-size:var(--mk-font-size-xs)}.mk-form-field__required{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-bold);line-height:1}.mk-form-field__control{display:block;min-width:0}.mk-form-field__hint,.mk-form-field__error{margin:0;font-size:var(--mk-font-size-xs);line-height:var(--mk-line-height-snug)}.mk-form-field__hint{color:var(--mk-text-muted)}.mk-form-field__error{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-medium)}:host(.mk-form-field--disabled){opacity:.6}\n"] }]
|
|
216
|
-
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessages", required: false }] }], errorOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorOn", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ngControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
261
|
+
], template: "@if (label() && labelPosition() !== 'float') {\n <label class=\"mk-form-field__label\" [id]=\"labelId\" [attr.for]=\"controlId\">\n <span class=\"mk-form-field__label-text\">{{ label() }}</span>\n @if (isRequired()) {\n <span class=\"mk-form-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n}\n\n<div class=\"mk-form-field__control\">\n <ng-content />\n @if (label() && labelPosition() === 'float') {\n <label class=\"mk-form-field__label mk-form-field__label--float\" [id]=\"labelId\" [attr.for]=\"controlId\">\n <span class=\"mk-form-field__label-text\">{{ label() }}</span>\n @if (isRequired()) {\n <span class=\"mk-form-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n</div>\n\n@if (hintVisible()) {\n <p class=\"mk-form-field__hint\" [id]=\"hintId\">{{ hint() }}</p>\n}\n\n@if (hasError()) {\n <p class=\"mk-form-field__error\" [id]=\"errorId\" role=\"alert\">{{ errorText() }}</p>\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--mk-space-2);font-family:var(--mk-font-sans);color:var(--mk-text)}.mk-form-field__label{display:inline-flex;align-items:center;gap:var(--mk-space-1);font-size:var(--mk-font-size-sm);font-weight:var(--mk-font-weight-medium);line-height:var(--mk-line-height-snug);color:var(--mk-text);width:fit-content}:host(.mk-form-field--lg) .mk-form-field__label{font-size:var(--mk-font-size-md)}:host(.mk-form-field--sm) .mk-form-field__label{font-size:var(--mk-font-size-xs)}.mk-form-field__required{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-bold);line-height:1}.mk-form-field__control{display:block;min-width:0}.mk-form-field__hint,.mk-form-field__error{margin:0;font-size:var(--mk-font-size-xs);line-height:var(--mk-line-height-snug)}.mk-form-field__hint{color:var(--mk-text-muted)}.mk-form-field__error{color:var(--mk-danger-text);font-weight:var(--mk-font-weight-medium)}:host(.mk-form-field--disabled){opacity:.6}:host(.mk-form-field--float) .mk-form-field__control{position:relative}.mk-form-field__label--float{position:absolute;inset-inline-start:var(--mk-space-3);top:50%;translate:0 -50%;max-width:calc(100% - 2 * var(--mk-space-3));overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:var(--mk-font-size-md);font-weight:var(--mk-font-weight-normal);color:var(--mk-text-muted);pointer-events:none;transition:top var(--mk-duration-fast) var(--mk-ease-standard),translate var(--mk-duration-fast) var(--mk-ease-standard),font-size var(--mk-duration-fast) var(--mk-ease-standard),color var(--mk-duration-fast) var(--mk-ease-standard)}:host(.mk-form-field--focused) .mk-form-field__label--float,:host(.mk-form-field--filled) .mk-form-field__label--float{top:.35rem;translate:0 0;font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-medium)}:host(.mk-form-field--focused) .mk-form-field__label--float{color:var(--mk-primary)}:host(.mk-form-field--invalid) .mk-form-field__label--float{color:var(--mk-danger-text)}:host(.mk-form-field--float) ::ng-deep .mk-input:not(textarea){height:calc(var(--mk-control-height-md) + .75rem);padding-top:1.05rem}:host(.mk-form-field--float) ::ng-deep textarea.mk-input{padding-top:1.5rem}:host(.mk-form-field--float:not(.mk-form-field--focused):not(.mk-form-field--filled)) ::ng-deep .mk-input::placeholder{color:transparent}@media(prefers-reduced-motion:reduce){.mk-form-field__label--float{transition:none}}\n"] }]
|
|
262
|
+
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessages", required: false }] }], errorOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorOn", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], labelPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPosition", required: false }] }], ngControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
217
263
|
|
|
218
264
|
/**
|
|
219
265
|
* FormErrorSummary — an accessible summary of a form's validation errors,
|
|
@@ -1436,6 +1482,770 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
1436
1482
|
], template: "<button\n #trigger\n type=\"button\"\n class=\"mk-select__trigger\"\n [id]=\"triggerId\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"\n open() && activeIndex() >= 0 ? optionId(activeIndex()) : null\n \"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-required]=\"isRequired() || null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n>\n @if (displayLabel()) {\n <span class=\"mk-select__value\">{{ displayLabel() }}</span>\n } @else {\n <span class=\"mk-select__value mk-select__value--placeholder\">{{\n placeholder()\n }}</span>\n }\n <span class=\"mk-select__arrow\" aria-hidden=\"true\"></span>\n</button>\n\n@if (open()) {\n <ul\n class=\"mk-select__list\"\n mkAnchoredPanel\n [mkAnchoredPanelFor]=\"trigger\"\n [matchWidth]=\"true\"\n (dismiss)=\"close()\"\n [id]=\"listId\"\n role=\"listbox\"\n [attr.aria-labelledby]=\"labelledBy()\"\n >\n @for (opt of options(); track $index; let i = $index) {\n <li\n class=\"mk-select__option\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"i === selectedIndex()\"\n [attr.aria-disabled]=\"opt.disabled || null\"\n [class.mk-select__option--active]=\"i === activeIndex()\"\n [class.mk-select__option--selected]=\"i === selectedIndex()\"\n [class.mk-select__option--disabled]=\"opt.disabled\"\n (mousedown)=\"$event.preventDefault()\"\n (mousemove)=\"!opt.disabled && activeIndex.set(i)\"\n (click)=\"selectOption(i)\"\n >\n <span class=\"mk-select__option-label\">{{ opt.label }}</span>\n @if (i === selectedIndex()) {\n <span class=\"mk-select__check\" aria-hidden=\"true\"></span>\n }\n </li>\n } @empty {\n <li class=\"mk-select__empty\" role=\"presentation\">{{ i18n.noOptions }}</li>\n }\n </ul>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;font-family:var(--mk-font-sans)}.mk-select__trigger{display:flex;align-items:center;gap:var(--mk-space-2);width:100%;height:var(--mk-control-height-md);padding:0 var(--mk-space-3);font-family:inherit;font-size:var(--mk-font-size-md);color:var(--mk-text);text-align:start;background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);cursor:pointer;transition:border-color var(--mk-duration-fast) var(--mk-ease-standard),box-shadow var(--mk-duration-fast) var(--mk-ease-standard)}:host(.mk-select--sm) .mk-select__trigger{height:var(--mk-control-height-sm);padding:0 var(--mk-space-2);font-size:var(--mk-font-size-sm);border-radius:var(--mk-radius-sm)}:host(.mk-select--lg) .mk-select__trigger{height:var(--mk-control-height-lg);padding:0 var(--mk-space-4);font-size:var(--mk-font-size-lg)}.mk-select__trigger:hover:not(:disabled){border-color:var(--mk-border-strong)}.mk-select__trigger:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset);border-color:var(--mk-primary)}:host(.mk-select--invalid) .mk-select__trigger{border-color:var(--mk-danger)}:host(.mk-select--invalid) .mk-select__trigger:focus-visible{outline-color:var(--mk-danger)}.mk-select__trigger:disabled{background-color:var(--mk-surface-2);color:var(--mk-text-disabled);border-color:var(--mk-border-subtle);cursor:not-allowed;opacity:.7}.mk-select__value{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-select__value--placeholder{color:var(--mk-text-subtle)}.mk-select__arrow{flex:none;width:.5rem;height:.5rem;border-right:2px solid var(--mk-text-muted);border-bottom:2px solid var(--mk-text-muted);transform:rotate(45deg) translateY(-2px);transition:transform var(--mk-duration-fast) var(--mk-ease-standard)}:host(.mk-select--open) .mk-select__arrow{transform:rotate(-135deg) translateY(-2px)}.mk-select__list{padding:var(--mk-space-1);list-style:none;max-height:16rem;overflow-y:auto;background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);box-shadow:var(--mk-shadow-lg)}.mk-select__option{display:flex;align-items:center;gap:var(--mk-space-2);padding:var(--mk-space-2) var(--mk-space-3);font-size:var(--mk-font-size-md);color:var(--mk-text);border-radius:var(--mk-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none}.mk-select__option-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-select__option--active{background-color:var(--mk-selected-bg)}.mk-select__option--selected{color:var(--mk-selected-text);font-weight:var(--mk-font-weight-medium)}.mk-select__option--disabled{color:var(--mk-text-disabled);cursor:not-allowed}.mk-select__check{flex:none;width:.4rem;height:.7rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg)}.mk-select__empty{padding:var(--mk-space-2) var(--mk-space-3);color:var(--mk-text-subtle);font-size:var(--mk-font-size-sm)}@media(prefers-reduced-motion:reduce){.mk-select__arrow,.mk-select__trigger{transition:none}}@media(pointer:coarse){.mk-select__trigger{font-size:max(var(--mk-font-size-md),16px)}:host(.mk-select--sm) .mk-select__trigger{font-size:max(var(--mk-font-size-sm),16px)}}\n"] }]
|
|
1437
1483
|
}], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
1438
1484
|
|
|
1485
|
+
/**
|
|
1486
|
+
* Listbox — a standalone, always-visible selection list (the ARIA `listbox`
|
|
1487
|
+
* pattern) for one or many values: settings panes, "choose a template"
|
|
1488
|
+
* pickers, side-by-side assignments, any place a dropdown would hide choices
|
|
1489
|
+
* the user should see at once.
|
|
1490
|
+
*
|
|
1491
|
+
* Keyboard: Up / Down move, Home / End jump, PageUp / PageDown skip ten,
|
|
1492
|
+
* type to jump to a label, Enter / Space select (toggle when `multiple`),
|
|
1493
|
+
* Shift+Arrow / Shift+click extend a range, Ctrl/Cmd+A selects all. Focus
|
|
1494
|
+
* stays on the list (`aria-activedescendant`). With `filterable`, a search
|
|
1495
|
+
* box above the list narrows it by label or description.
|
|
1496
|
+
*
|
|
1497
|
+
* Implements `ControlValueAccessor` and a two-way `value` model — a single
|
|
1498
|
+
* value, or an array when `multiple`.
|
|
1499
|
+
*
|
|
1500
|
+
* ```html
|
|
1501
|
+
* <mk-listbox [options]="plans" [(value)]="plan" ariaLabel="Plan" />
|
|
1502
|
+
* <mk-listbox multiple filterable [options]="people" [(ngModel)]="reviewers" />
|
|
1503
|
+
* ```
|
|
1504
|
+
*/
|
|
1505
|
+
class MkListbox {
|
|
1506
|
+
field = inject(MkFormField, { optional: true });
|
|
1507
|
+
i18n = inject(MK_I18N);
|
|
1508
|
+
listRef = viewChild.required('list', /* @ts-ignore */
|
|
1509
|
+
...(ngDevMode ? [{ debugName: "listRef" }] : /* istanbul ignore next */ []));
|
|
1510
|
+
/** The rows to choose from. */
|
|
1511
|
+
options = input([], /* @ts-ignore */
|
|
1512
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
1513
|
+
/** Allow several values; the model becomes an array. */
|
|
1514
|
+
multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1515
|
+
/** Show a search box that narrows the list by label / description. */
|
|
1516
|
+
filterable = input(false, { ...(ngDevMode ? { debugName: "filterable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1517
|
+
filterPlaceholder = input(undefined, /* @ts-ignore */
|
|
1518
|
+
...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : /* istanbul ignore next */ []));
|
|
1519
|
+
/**
|
|
1520
|
+
* Single-select only: moving with the arrow keys selects immediately
|
|
1521
|
+
* (default `true`); `false` requires Enter / Space to commit.
|
|
1522
|
+
*/
|
|
1523
|
+
selectionFollowsFocus = input(true, { ...(ngDevMode ? { debugName: "selectionFollowsFocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1524
|
+
/** Control size. Ignored when nested in an `mk-form-field`. */
|
|
1525
|
+
size = input('md', /* @ts-ignore */
|
|
1526
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
1527
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1528
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1529
|
+
/** Accessible name when there is no visible label / form field. */
|
|
1530
|
+
ariaLabel = input(undefined, /* @ts-ignore */
|
|
1531
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
1532
|
+
ariaLabelledby = input(undefined, /* @ts-ignore */
|
|
1533
|
+
...(ngDevMode ? [{ debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []));
|
|
1534
|
+
/** Text shown when no option matches the filter. */
|
|
1535
|
+
emptyText = input(undefined, /* @ts-ignore */
|
|
1536
|
+
...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
|
|
1537
|
+
/** Two-way value: one value, or an array when `multiple`. */
|
|
1538
|
+
value = model(null, /* @ts-ignore */
|
|
1539
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1540
|
+
/** Emitted after the user changes the selection (not on programmatic writes). */
|
|
1541
|
+
change = output();
|
|
1542
|
+
listId = this.field?.controlId ?? mkUniqueId('mk-listbox');
|
|
1543
|
+
filterId = mkUniqueId('mk-listbox-filter');
|
|
1544
|
+
query = signal('', /* @ts-ignore */
|
|
1545
|
+
...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
1546
|
+
activeIndex = signal(-1, /* @ts-ignore */
|
|
1547
|
+
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
1548
|
+
cvaDisabled = signal(false, /* @ts-ignore */
|
|
1549
|
+
...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
|
|
1550
|
+
onChange = () => { };
|
|
1551
|
+
onTouched = () => { };
|
|
1552
|
+
typeahead = '';
|
|
1553
|
+
typeaheadTimer;
|
|
1554
|
+
/** Range anchor for Shift selection (index in the visible list). */
|
|
1555
|
+
anchor = -1;
|
|
1556
|
+
effectiveSize = computed(() => (this.field ? this.field.size() : this.size()), /* @ts-ignore */
|
|
1557
|
+
...(ngDevMode ? [{ debugName: "effectiveSize" }] : /* istanbul ignore next */ []));
|
|
1558
|
+
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), /* @ts-ignore */
|
|
1559
|
+
...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
1560
|
+
isInvalid = computed(() => this.invalid() || (this.field?.hasError() ?? false), /* @ts-ignore */
|
|
1561
|
+
...(ngDevMode ? [{ debugName: "isInvalid" }] : /* istanbul ignore next */ []));
|
|
1562
|
+
labelledBy = computed(() => this.ariaLabelledby() ?? this.field?.labelId ?? null, /* @ts-ignore */
|
|
1563
|
+
...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
|
|
1564
|
+
describedBy = computed(() => this.field?.describedBy() ?? null, /* @ts-ignore */
|
|
1565
|
+
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
1566
|
+
/** Options that match the filter, in source order. */
|
|
1567
|
+
visible = computed(() => {
|
|
1568
|
+
const q = this.query().trim().toLocaleLowerCase();
|
|
1569
|
+
const all = this.options();
|
|
1570
|
+
if (!q)
|
|
1571
|
+
return [...all];
|
|
1572
|
+
return all.filter((o) => o.label.toLocaleLowerCase().includes(q) || (o.description?.toLocaleLowerCase().includes(q) ?? false));
|
|
1573
|
+
}, /* @ts-ignore */
|
|
1574
|
+
...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
1575
|
+
/** Visible options with group headings interleaved. */
|
|
1576
|
+
rows = computed(() => {
|
|
1577
|
+
const out = [];
|
|
1578
|
+
let lastGroup;
|
|
1579
|
+
this.visible().forEach((option, index) => {
|
|
1580
|
+
if (option.group && option.group !== lastGroup) {
|
|
1581
|
+
out.push({ kind: 'group', label: option.group, id: `${this.listId}-grp-${out.length}` });
|
|
1582
|
+
}
|
|
1583
|
+
lastGroup = option.group;
|
|
1584
|
+
out.push({ kind: 'option', option, index });
|
|
1585
|
+
});
|
|
1586
|
+
return out;
|
|
1587
|
+
}, /* @ts-ignore */
|
|
1588
|
+
...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
1589
|
+
selectedValues = computed(() => {
|
|
1590
|
+
const v = this.value();
|
|
1591
|
+
if (this.multiple())
|
|
1592
|
+
return Array.isArray(v) ? v : v == null ? [] : [v];
|
|
1593
|
+
return v == null ? [] : [v];
|
|
1594
|
+
}, /* @ts-ignore */
|
|
1595
|
+
...(ngDevMode ? [{ debugName: "selectedValues" }] : /* istanbul ignore next */ []));
|
|
1596
|
+
activeId = computed(() => (this.activeIndex() >= 0 ? this.optionId(this.activeIndex()) : null), /* @ts-ignore */
|
|
1597
|
+
...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
|
|
1598
|
+
constructor() {
|
|
1599
|
+
// Keep the active row in view as it changes.
|
|
1600
|
+
afterRenderEffect(() => {
|
|
1601
|
+
const i = this.activeIndex();
|
|
1602
|
+
if (i < 0)
|
|
1603
|
+
return;
|
|
1604
|
+
const el = this.listRef().nativeElement.ownerDocument.getElementById(this.optionId(i));
|
|
1605
|
+
el?.scrollIntoView?.({ block: 'nearest' });
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
optionId(index) {
|
|
1609
|
+
return `${this.listId}-opt-${index}`;
|
|
1610
|
+
}
|
|
1611
|
+
isSelected(option) {
|
|
1612
|
+
return this.selectedValues().includes(option.value);
|
|
1613
|
+
}
|
|
1614
|
+
/** Focus the list. */
|
|
1615
|
+
focus() {
|
|
1616
|
+
this.listRef().nativeElement.focus();
|
|
1617
|
+
}
|
|
1618
|
+
// --- Pointer -----------------------------------------------------------------
|
|
1619
|
+
onOptionClick(index, event) {
|
|
1620
|
+
if (this.isDisabled())
|
|
1621
|
+
return;
|
|
1622
|
+
const option = this.visible()[index];
|
|
1623
|
+
if (!option || option.disabled)
|
|
1624
|
+
return;
|
|
1625
|
+
this.activeIndex.set(index);
|
|
1626
|
+
if (this.multiple() && event.shiftKey && this.anchor >= 0) {
|
|
1627
|
+
this.selectRange(this.anchor, index, !(event.ctrlKey || event.metaKey));
|
|
1628
|
+
}
|
|
1629
|
+
else {
|
|
1630
|
+
this.commit(index, this.multiple() ? 'toggle' : 'select');
|
|
1631
|
+
this.anchor = index;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
onFilterInput(event) {
|
|
1635
|
+
this.query.set(event.target.value);
|
|
1636
|
+
this.activeIndex.set(-1);
|
|
1637
|
+
this.anchor = -1;
|
|
1638
|
+
}
|
|
1639
|
+
onFilterKeydown(event) {
|
|
1640
|
+
// Arrow keys from the search box hand over to the list.
|
|
1641
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
1642
|
+
event.preventDefault();
|
|
1643
|
+
this.focus();
|
|
1644
|
+
this.jump(event.key === 'ArrowDown' ? this.firstEnabled() : this.lastEnabled(), false);
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
// --- Keyboard ----------------------------------------------------------------
|
|
1648
|
+
onKeydown(event) {
|
|
1649
|
+
if (this.isDisabled())
|
|
1650
|
+
return;
|
|
1651
|
+
const key = event.key;
|
|
1652
|
+
const multi = this.multiple();
|
|
1653
|
+
switch (key) {
|
|
1654
|
+
case 'ArrowDown':
|
|
1655
|
+
case 'ArrowUp':
|
|
1656
|
+
event.preventDefault();
|
|
1657
|
+
this.step(key === 'ArrowDown' ? 1 : -1, event.shiftKey);
|
|
1658
|
+
break;
|
|
1659
|
+
case 'Home':
|
|
1660
|
+
case 'End':
|
|
1661
|
+
event.preventDefault();
|
|
1662
|
+
this.jump(key === 'Home' ? this.firstEnabled() : this.lastEnabled(), event.shiftKey);
|
|
1663
|
+
break;
|
|
1664
|
+
case 'PageDown':
|
|
1665
|
+
case 'PageUp':
|
|
1666
|
+
event.preventDefault();
|
|
1667
|
+
this.step(key === 'PageDown' ? 10 : -10, event.shiftKey, false);
|
|
1668
|
+
break;
|
|
1669
|
+
case 'Enter':
|
|
1670
|
+
case ' ':
|
|
1671
|
+
event.preventDefault();
|
|
1672
|
+
if (this.activeIndex() >= 0) {
|
|
1673
|
+
this.commit(this.activeIndex(), multi ? 'toggle' : 'select');
|
|
1674
|
+
this.anchor = this.activeIndex();
|
|
1675
|
+
}
|
|
1676
|
+
break;
|
|
1677
|
+
case 'a':
|
|
1678
|
+
case 'A':
|
|
1679
|
+
if (multi && (event.ctrlKey || event.metaKey)) {
|
|
1680
|
+
event.preventDefault();
|
|
1681
|
+
this.selectAll();
|
|
1682
|
+
}
|
|
1683
|
+
else if (key.length === 1)
|
|
1684
|
+
this.typeaheadSearch(key);
|
|
1685
|
+
break;
|
|
1686
|
+
default:
|
|
1687
|
+
if (key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey)
|
|
1688
|
+
this.typeaheadSearch(key);
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
onBlur() {
|
|
1692
|
+
this.onTouched();
|
|
1693
|
+
}
|
|
1694
|
+
/** Move the active row by `delta` (wrapping for ±1), extending the selection with Shift. */
|
|
1695
|
+
step(delta, extend, wrap = true) {
|
|
1696
|
+
const opts = this.visible();
|
|
1697
|
+
if (!opts.length)
|
|
1698
|
+
return;
|
|
1699
|
+
let i = this.activeIndex();
|
|
1700
|
+
if (i < 0) {
|
|
1701
|
+
this.jump(delta > 0 ? this.firstEnabled() : this.lastEnabled(), extend);
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
if (Math.abs(delta) === 1) {
|
|
1705
|
+
for (let s = 0; s < opts.length; s++) {
|
|
1706
|
+
i = wrap ? (i + delta + opts.length) % opts.length : Math.min(Math.max(i + delta, 0), opts.length - 1);
|
|
1707
|
+
if (!opts[i].disabled)
|
|
1708
|
+
break;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
else {
|
|
1712
|
+
i = Math.min(Math.max(i + delta, 0), opts.length - 1);
|
|
1713
|
+
// Land on an enabled row, searching in the direction of travel then back.
|
|
1714
|
+
let j = i;
|
|
1715
|
+
while (j >= 0 && j < opts.length && opts[j].disabled)
|
|
1716
|
+
j += Math.sign(delta);
|
|
1717
|
+
if (j < 0 || j >= opts.length) {
|
|
1718
|
+
j = i;
|
|
1719
|
+
while (j >= 0 && j < opts.length && opts[j].disabled)
|
|
1720
|
+
j -= Math.sign(delta);
|
|
1721
|
+
}
|
|
1722
|
+
i = j;
|
|
1723
|
+
}
|
|
1724
|
+
this.jump(i, extend);
|
|
1725
|
+
}
|
|
1726
|
+
jump(index, extend) {
|
|
1727
|
+
if (index < 0)
|
|
1728
|
+
return;
|
|
1729
|
+
this.activeIndex.set(index);
|
|
1730
|
+
if (this.multiple()) {
|
|
1731
|
+
if (extend) {
|
|
1732
|
+
if (this.anchor < 0)
|
|
1733
|
+
this.anchor = index;
|
|
1734
|
+
this.selectRange(this.anchor, index, true);
|
|
1735
|
+
}
|
|
1736
|
+
else {
|
|
1737
|
+
// Plain navigation moves the range anchor along with the cursor.
|
|
1738
|
+
this.anchor = index;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
else if (this.selectionFollowsFocus()) {
|
|
1742
|
+
this.commit(index, 'select');
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
firstEnabled() {
|
|
1746
|
+
return this.visible().findIndex((o) => !o.disabled);
|
|
1747
|
+
}
|
|
1748
|
+
lastEnabled() {
|
|
1749
|
+
const opts = this.visible();
|
|
1750
|
+
for (let i = opts.length - 1; i >= 0; i--)
|
|
1751
|
+
if (!opts[i].disabled)
|
|
1752
|
+
return i;
|
|
1753
|
+
return -1;
|
|
1754
|
+
}
|
|
1755
|
+
typeaheadSearch(char) {
|
|
1756
|
+
this.typeahead += char.toLocaleLowerCase();
|
|
1757
|
+
if (this.typeaheadTimer)
|
|
1758
|
+
clearTimeout(this.typeaheadTimer);
|
|
1759
|
+
this.typeaheadTimer = setTimeout(() => (this.typeahead = ''), 500);
|
|
1760
|
+
const opts = this.visible();
|
|
1761
|
+
const start = this.activeIndex() + 1;
|
|
1762
|
+
for (let s = 0; s < opts.length; s++) {
|
|
1763
|
+
const i = (start + s) % opts.length;
|
|
1764
|
+
if (!opts[i].disabled && opts[i].label.toLocaleLowerCase().startsWith(this.typeahead)) {
|
|
1765
|
+
this.jump(i, false);
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
// --- Selection ---------------------------------------------------------------
|
|
1771
|
+
commit(index, mode) {
|
|
1772
|
+
const option = this.visible()[index];
|
|
1773
|
+
if (!option || option.disabled)
|
|
1774
|
+
return;
|
|
1775
|
+
if (!this.multiple()) {
|
|
1776
|
+
if (this.value() === option.value)
|
|
1777
|
+
return;
|
|
1778
|
+
this.emit(option.value);
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
const current = this.selectedValues();
|
|
1782
|
+
const next = mode === 'toggle' && current.includes(option.value)
|
|
1783
|
+
? current.filter((v) => v !== option.value)
|
|
1784
|
+
: current.includes(option.value)
|
|
1785
|
+
? current
|
|
1786
|
+
: [...current, option.value];
|
|
1787
|
+
this.emit(next);
|
|
1788
|
+
}
|
|
1789
|
+
/** Select every enabled option between two visible indexes (replacing, or adding to, the selection). */
|
|
1790
|
+
selectRange(from, to, replace) {
|
|
1791
|
+
const opts = this.visible();
|
|
1792
|
+
const [lo, hi] = from < to ? [from, to] : [to, from];
|
|
1793
|
+
const range = opts.slice(lo, hi + 1).filter((o) => !o.disabled).map((o) => o.value);
|
|
1794
|
+
const base = replace ? [] : this.selectedValues();
|
|
1795
|
+
this.emit([...base, ...range.filter((v) => !base.includes(v))]);
|
|
1796
|
+
}
|
|
1797
|
+
selectAll() {
|
|
1798
|
+
const all = this.visible().filter((o) => !o.disabled).map((o) => o.value);
|
|
1799
|
+
const current = this.selectedValues();
|
|
1800
|
+
// Ctrl+A toggles: everything selected → clear, else select all.
|
|
1801
|
+
this.emit(all.every((v) => current.includes(v)) ? [] : all);
|
|
1802
|
+
}
|
|
1803
|
+
emit(value) {
|
|
1804
|
+
this.value.set(value);
|
|
1805
|
+
this.onChange(value);
|
|
1806
|
+
this.change.emit(value);
|
|
1807
|
+
}
|
|
1808
|
+
ngOnDestroy() {
|
|
1809
|
+
if (this.typeaheadTimer)
|
|
1810
|
+
clearTimeout(this.typeaheadTimer);
|
|
1811
|
+
}
|
|
1812
|
+
// --- ControlValueAccessor ----------------------------------------------------
|
|
1813
|
+
writeValue(value) {
|
|
1814
|
+
this.value.set(value);
|
|
1815
|
+
}
|
|
1816
|
+
registerOnChange(fn) {
|
|
1817
|
+
this.onChange = fn;
|
|
1818
|
+
}
|
|
1819
|
+
registerOnTouched(fn) {
|
|
1820
|
+
this.onTouched = fn;
|
|
1821
|
+
}
|
|
1822
|
+
setDisabledState(isDisabled) {
|
|
1823
|
+
this.cvaDisabled.set(isDisabled);
|
|
1824
|
+
}
|
|
1825
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkListbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1826
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkListbox, isStandalone: true, selector: "mk-listbox", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectionFollowsFocus: { classPropertyName: "selectionFollowsFocus", publicName: "selectionFollowsFocus", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", 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 }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "ariaLabelledby", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", change: "change" }, host: { properties: { "class.mk-listbox--sm": "effectiveSize() === 'sm'", "class.mk-listbox--md": "effectiveSize() === 'md'", "class.mk-listbox--lg": "effectiveSize() === 'lg'", "class.mk-listbox--multiple": "multiple()", "class.mk-listbox--invalid": "isInvalid()", "class.mk-listbox--disabled": "isDisabled()" }, classAttribute: "mk-listbox" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MkListbox), multi: true }], viewQueries: [{ propertyName: "listRef", first: true, predicate: ["list"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (filterable()) {\n <div class=\"mk-listbox__filter\">\n <input\n class=\"mk-listbox__filter-input\"\n type=\"search\"\n [id]=\"filterId\"\n [value]=\"query()\"\n [placeholder]=\"filterPlaceholder() ?? i18n.listboxFilter\"\n [disabled]=\"isDisabled()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-label]=\"i18n.listboxFilter\"\n autocomplete=\"off\"\n (input)=\"onFilterInput($event)\"\n (keydown)=\"onFilterKeydown($event)\"\n />\n </div>\n}\n\n<ul\n #list\n class=\"mk-listbox__list\"\n role=\"listbox\"\n [id]=\"listId\"\n [tabindex]=\"isDisabled() ? -1 : 0\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n [attr.aria-activedescendant]=\"activeId()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n>\n @for (row of rows(); track row.kind === 'group' ? row.id : row.option.value) {\n @if (row.kind === 'group') {\n <li class=\"mk-listbox__group\" role=\"presentation\" [id]=\"row.id\">{{ row.label }}</li>\n } @else {\n @let selected = isSelected(row.option);\n <li\n class=\"mk-listbox__option\"\n role=\"option\"\n [id]=\"optionId(row.index)\"\n [attr.aria-selected]=\"selected\"\n [attr.aria-disabled]=\"row.option.disabled || null\"\n [class.mk-listbox__option--active]=\"row.index === activeIndex()\"\n [class.mk-listbox__option--selected]=\"selected\"\n [class.mk-listbox__option--disabled]=\"row.option.disabled\"\n (click)=\"onOptionClick(row.index, $event)\"\n >\n @if (multiple()) {\n <span class=\"mk-listbox__box\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 12 12\" width=\"12\" height=\"12\" focusable=\"false\"><path d=\"M2.5 6.5l2.5 2.5 4.5-5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" /></svg>\n </span>\n }\n <span class=\"mk-listbox__text\">\n <span class=\"mk-listbox__label\">{{ row.option.label }}</span>\n @if (row.option.description) {\n <span class=\"mk-listbox__description\">{{ row.option.description }}</span>\n }\n </span>\n @if (!multiple() && selected) {\n <span class=\"mk-listbox__check\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n }\n @if (!rows().length) {\n <li class=\"mk-listbox__empty\" role=\"presentation\">{{ emptyText() ?? i18n.listboxEmpty }}</li>\n }\n</ul>\n", styles: [":host{--_pad-y: var(--mk-space-2);--_pad-x: var(--mk-space-3);--_font: var(--mk-font-size-md);display:flex;flex-direction:column;min-width:0;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);background:var(--mk-surface);color:var(--mk-text);font-family:var(--mk-font-sans);overflow:hidden}:host(.mk-listbox--sm){--_pad-y: var(--mk-space-1);--_pad-x: var(--mk-space-2);--_font: var(--mk-font-size-sm)}:host(.mk-listbox--lg){--_pad-y: var(--mk-space-3);--_pad-x: var(--mk-space-4);--_font: var(--mk-font-size-lg)}:host(:focus-within){border-color:var(--mk-primary);box-shadow:0 0 0 var(--mk-focus-ring-width) var(--mk-focus-ring, var(--mk-primary-subtle))}:host(.mk-listbox--invalid){border-color:var(--mk-danger)}:host(.mk-listbox--disabled){opacity:.6;cursor:not-allowed}.mk-listbox__filter{flex:none;padding:var(--mk-space-2);border-bottom:var(--mk-border-width) solid var(--mk-border)}.mk-listbox__filter-input{width:100%;padding:var(--_pad-y) var(--_pad-x);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-sm);background:var(--mk-surface);color:inherit;font:inherit;font-size:var(--_font)}.mk-listbox__filter-input:focus-visible{outline:none;border-color:var(--mk-primary)}.mk-listbox__filter-input::placeholder{color:var(--mk-text-muted)}.mk-listbox__list{flex:1 1 auto;min-height:0;max-height:var(--mk-listbox-max-height, 16rem);margin:0;padding:var(--mk-space-1);list-style:none;overflow-y:auto;overscroll-behavior:contain;outline:none}.mk-listbox__group{padding:var(--mk-space-2) var(--_pad-x) var(--mk-space-1);color:var(--mk-text-muted);font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.mk-listbox__option{display:flex;align-items:center;gap:var(--mk-space-2);padding:var(--_pad-y) var(--_pad-x);border-radius:var(--mk-radius-sm);font-size:var(--_font);cursor:pointer;-webkit-user-select:none;user-select:none}.mk-listbox__option:hover:not(.mk-listbox__option--disabled){background-color:var(--mk-hover-bg, var(--mk-surface-2))}.mk-listbox__option--active{background-color:var(--mk-selected-bg)}.mk-listbox__list:focus-visible .mk-listbox__option--active{box-shadow:inset 0 0 0 2px var(--mk-primary)}.mk-listbox__option--selected{color:var(--mk-selected-text);font-weight:var(--mk-font-weight-medium)}.mk-listbox__option--disabled{color:var(--mk-text-disabled);cursor:not-allowed}.mk-listbox__text{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}.mk-listbox__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-listbox__description{color:var(--mk-text-muted);font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-normal)}.mk-listbox__box{flex:none;display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;border:var(--mk-border-width) solid var(--mk-border-strong, var(--mk-border));border-radius:var(--mk-radius-sm);background:var(--mk-surface);color:transparent}.mk-listbox__option--selected .mk-listbox__box{border-color:var(--mk-primary);background:var(--mk-primary);color:var(--mk-primary-contrast, #fff)}.mk-listbox__check{flex:none;width:.4rem;height:.7rem;margin-inline-end:var(--mk-space-1);border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg)}.mk-listbox__empty{padding:var(--mk-space-3) var(--_pad-x);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}@media(forced-colors:active){.mk-listbox__option--active{outline:2px solid Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1827
|
+
}
|
|
1828
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkListbox, decorators: [{
|
|
1829
|
+
type: Component,
|
|
1830
|
+
args: [{ selector: 'mk-listbox', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1831
|
+
class: 'mk-listbox',
|
|
1832
|
+
'[class.mk-listbox--sm]': "effectiveSize() === 'sm'",
|
|
1833
|
+
'[class.mk-listbox--md]': "effectiveSize() === 'md'",
|
|
1834
|
+
'[class.mk-listbox--lg]': "effectiveSize() === 'lg'",
|
|
1835
|
+
'[class.mk-listbox--multiple]': 'multiple()',
|
|
1836
|
+
'[class.mk-listbox--invalid]': 'isInvalid()',
|
|
1837
|
+
'[class.mk-listbox--disabled]': 'isDisabled()',
|
|
1838
|
+
}, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MkListbox), multi: true }], template: "@if (filterable()) {\n <div class=\"mk-listbox__filter\">\n <input\n class=\"mk-listbox__filter-input\"\n type=\"search\"\n [id]=\"filterId\"\n [value]=\"query()\"\n [placeholder]=\"filterPlaceholder() ?? i18n.listboxFilter\"\n [disabled]=\"isDisabled()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-label]=\"i18n.listboxFilter\"\n autocomplete=\"off\"\n (input)=\"onFilterInput($event)\"\n (keydown)=\"onFilterKeydown($event)\"\n />\n </div>\n}\n\n<ul\n #list\n class=\"mk-listbox__list\"\n role=\"listbox\"\n [id]=\"listId\"\n [tabindex]=\"isDisabled() ? -1 : 0\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n [attr.aria-activedescendant]=\"activeId()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n>\n @for (row of rows(); track row.kind === 'group' ? row.id : row.option.value) {\n @if (row.kind === 'group') {\n <li class=\"mk-listbox__group\" role=\"presentation\" [id]=\"row.id\">{{ row.label }}</li>\n } @else {\n @let selected = isSelected(row.option);\n <li\n class=\"mk-listbox__option\"\n role=\"option\"\n [id]=\"optionId(row.index)\"\n [attr.aria-selected]=\"selected\"\n [attr.aria-disabled]=\"row.option.disabled || null\"\n [class.mk-listbox__option--active]=\"row.index === activeIndex()\"\n [class.mk-listbox__option--selected]=\"selected\"\n [class.mk-listbox__option--disabled]=\"row.option.disabled\"\n (click)=\"onOptionClick(row.index, $event)\"\n >\n @if (multiple()) {\n <span class=\"mk-listbox__box\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 12 12\" width=\"12\" height=\"12\" focusable=\"false\"><path d=\"M2.5 6.5l2.5 2.5 4.5-5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" /></svg>\n </span>\n }\n <span class=\"mk-listbox__text\">\n <span class=\"mk-listbox__label\">{{ row.option.label }}</span>\n @if (row.option.description) {\n <span class=\"mk-listbox__description\">{{ row.option.description }}</span>\n }\n </span>\n @if (!multiple() && selected) {\n <span class=\"mk-listbox__check\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n }\n @if (!rows().length) {\n <li class=\"mk-listbox__empty\" role=\"presentation\">{{ emptyText() ?? i18n.listboxEmpty }}</li>\n }\n</ul>\n", styles: [":host{--_pad-y: var(--mk-space-2);--_pad-x: var(--mk-space-3);--_font: var(--mk-font-size-md);display:flex;flex-direction:column;min-width:0;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);background:var(--mk-surface);color:var(--mk-text);font-family:var(--mk-font-sans);overflow:hidden}:host(.mk-listbox--sm){--_pad-y: var(--mk-space-1);--_pad-x: var(--mk-space-2);--_font: var(--mk-font-size-sm)}:host(.mk-listbox--lg){--_pad-y: var(--mk-space-3);--_pad-x: var(--mk-space-4);--_font: var(--mk-font-size-lg)}:host(:focus-within){border-color:var(--mk-primary);box-shadow:0 0 0 var(--mk-focus-ring-width) var(--mk-focus-ring, var(--mk-primary-subtle))}:host(.mk-listbox--invalid){border-color:var(--mk-danger)}:host(.mk-listbox--disabled){opacity:.6;cursor:not-allowed}.mk-listbox__filter{flex:none;padding:var(--mk-space-2);border-bottom:var(--mk-border-width) solid var(--mk-border)}.mk-listbox__filter-input{width:100%;padding:var(--_pad-y) var(--_pad-x);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-sm);background:var(--mk-surface);color:inherit;font:inherit;font-size:var(--_font)}.mk-listbox__filter-input:focus-visible{outline:none;border-color:var(--mk-primary)}.mk-listbox__filter-input::placeholder{color:var(--mk-text-muted)}.mk-listbox__list{flex:1 1 auto;min-height:0;max-height:var(--mk-listbox-max-height, 16rem);margin:0;padding:var(--mk-space-1);list-style:none;overflow-y:auto;overscroll-behavior:contain;outline:none}.mk-listbox__group{padding:var(--mk-space-2) var(--_pad-x) var(--mk-space-1);color:var(--mk-text-muted);font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-semibold);letter-spacing:.04em;text-transform:uppercase}.mk-listbox__option{display:flex;align-items:center;gap:var(--mk-space-2);padding:var(--_pad-y) var(--_pad-x);border-radius:var(--mk-radius-sm);font-size:var(--_font);cursor:pointer;-webkit-user-select:none;user-select:none}.mk-listbox__option:hover:not(.mk-listbox__option--disabled){background-color:var(--mk-hover-bg, var(--mk-surface-2))}.mk-listbox__option--active{background-color:var(--mk-selected-bg)}.mk-listbox__list:focus-visible .mk-listbox__option--active{box-shadow:inset 0 0 0 2px var(--mk-primary)}.mk-listbox__option--selected{color:var(--mk-selected-text);font-weight:var(--mk-font-weight-medium)}.mk-listbox__option--disabled{color:var(--mk-text-disabled);cursor:not-allowed}.mk-listbox__text{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}.mk-listbox__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-listbox__description{color:var(--mk-text-muted);font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-normal)}.mk-listbox__box{flex:none;display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;border:var(--mk-border-width) solid var(--mk-border-strong, var(--mk-border));border-radius:var(--mk-radius-sm);background:var(--mk-surface);color:transparent}.mk-listbox__option--selected .mk-listbox__box{border-color:var(--mk-primary);background:var(--mk-primary);color:var(--mk-primary-contrast, #fff)}.mk-listbox__check{flex:none;width:.4rem;height:.7rem;margin-inline-end:var(--mk-space-1);border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg)}.mk-listbox__empty{padding:var(--mk-space-3) var(--_pad-x);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}@media(forced-colors:active){.mk-listbox__option--active{outline:2px solid Highlight}}\n"] }]
|
|
1839
|
+
}], ctorParameters: () => [], propDecorators: { listRef: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], filterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterable", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], selectionFollowsFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionFollowsFocus", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], change: [{ type: i0.Output, args: ["change"] }] } });
|
|
1840
|
+
|
|
1841
|
+
/**
|
|
1842
|
+
* Cascader — a select whose choices are a hierarchy shown as side-by-side
|
|
1843
|
+
* columns (region → country → city, category → subcategory, org unit → team).
|
|
1844
|
+
* Each pick opens the next column; picking a leaf commits the whole path.
|
|
1845
|
+
*
|
|
1846
|
+
* The value is the **path** of option values (`['eu', 'pl', 'krk']`) by
|
|
1847
|
+
* default, or just the leaf's value with `valueMode="leaf"`. Parents are only
|
|
1848
|
+
* selectable with `selectParents` (a click on one then commits, and its
|
|
1849
|
+
* children stay reachable).
|
|
1850
|
+
*
|
|
1851
|
+
* Keyboard: Up / Down move within a column, Right opens the children, Left
|
|
1852
|
+
* goes back, Enter / Space selects, typing jumps to a label, Escape closes.
|
|
1853
|
+
* `expandTrigger="hover"` opens columns on pointer hover as well as click.
|
|
1854
|
+
*
|
|
1855
|
+
* Implements `ControlValueAccessor` and a two-way `value` model.
|
|
1856
|
+
*
|
|
1857
|
+
* ```html
|
|
1858
|
+
* <mk-cascader [options]="regions" [(value)]="location" placeholder="Where?" clearable />
|
|
1859
|
+
* ```
|
|
1860
|
+
*/
|
|
1861
|
+
class MkCascader {
|
|
1862
|
+
field = inject(MkFormField, { optional: true });
|
|
1863
|
+
i18n = inject(MK_I18N);
|
|
1864
|
+
host = inject(ElementRef);
|
|
1865
|
+
injector = inject(Injector);
|
|
1866
|
+
triggerRef = viewChild('trigger', /* @ts-ignore */
|
|
1867
|
+
...(ngDevMode ? [{ debugName: "triggerRef" }] : /* istanbul ignore next */ []));
|
|
1868
|
+
panelRef = viewChild('panel', /* @ts-ignore */
|
|
1869
|
+
...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
|
|
1870
|
+
/** The hierarchy to choose from. */
|
|
1871
|
+
options = input([], /* @ts-ignore */
|
|
1872
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
1873
|
+
/** Two-way value: the path of values (default) or the leaf value (`valueMode="leaf"`). */
|
|
1874
|
+
value = model(null, /* @ts-ignore */
|
|
1875
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1876
|
+
/** Bind the full path of values (default) or only the chosen option's value. */
|
|
1877
|
+
valueMode = input('path', /* @ts-ignore */
|
|
1878
|
+
...(ngDevMode ? [{ debugName: "valueMode" }] : /* istanbul ignore next */ []));
|
|
1879
|
+
/** Allow committing a parent option (click / Enter on it) instead of leaves only. */
|
|
1880
|
+
selectParents = input(false, { ...(ngDevMode ? { debugName: "selectParents" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1881
|
+
/** Open the next column on click (default) or also on pointer hover. */
|
|
1882
|
+
expandTrigger = input('click', /* @ts-ignore */
|
|
1883
|
+
...(ngDevMode ? [{ debugName: "expandTrigger" }] : /* istanbul ignore next */ []));
|
|
1884
|
+
placeholder = input(this.i18n.selectPlaceholder, /* @ts-ignore */
|
|
1885
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1886
|
+
/** Text between the labels of the chosen path. */
|
|
1887
|
+
separator = input(' / ', /* @ts-ignore */
|
|
1888
|
+
...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
|
|
1889
|
+
clearable = input(false, { ...(ngDevMode ? { debugName: "clearable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1890
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1891
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1892
|
+
/** Control size. Ignored when nested in an `mk-form-field`. */
|
|
1893
|
+
size = input('md', /* @ts-ignore */
|
|
1894
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
1895
|
+
/** Emitted after the user commits or clears a value. */
|
|
1896
|
+
change = output();
|
|
1897
|
+
triggerId = this.field?.controlId ?? mkUniqueId('mk-cascader');
|
|
1898
|
+
panelId = mkUniqueId('mk-cascader-panel');
|
|
1899
|
+
valueId = mkUniqueId('mk-cascader-value');
|
|
1900
|
+
open = signal(false, /* @ts-ignore */
|
|
1901
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1902
|
+
/** Row index highlighted in each open column, left to right. */
|
|
1903
|
+
activePath = signal([], /* @ts-ignore */
|
|
1904
|
+
...(ngDevMode ? [{ debugName: "activePath" }] : /* istanbul ignore next */ []));
|
|
1905
|
+
cvaDisabled = signal(false, /* @ts-ignore */
|
|
1906
|
+
...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
|
|
1907
|
+
onChange = () => { };
|
|
1908
|
+
onTouched = () => { };
|
|
1909
|
+
typeahead = '';
|
|
1910
|
+
typeaheadTimer;
|
|
1911
|
+
effectiveSize = computed(() => (this.field ? this.field.size() : this.size()), /* @ts-ignore */
|
|
1912
|
+
...(ngDevMode ? [{ debugName: "effectiveSize" }] : /* istanbul ignore next */ []));
|
|
1913
|
+
isDisabled = computed(() => this.disabled() || this.cvaDisabled(), /* @ts-ignore */
|
|
1914
|
+
...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
1915
|
+
isInvalid = computed(() => this.invalid() || (this.field?.hasError() ?? false), /* @ts-ignore */
|
|
1916
|
+
...(ngDevMode ? [{ debugName: "isInvalid" }] : /* istanbul ignore next */ []));
|
|
1917
|
+
isRequired = computed(() => this.field?.isRequired() ?? false, /* @ts-ignore */
|
|
1918
|
+
...(ngDevMode ? [{ debugName: "isRequired" }] : /* istanbul ignore next */ []));
|
|
1919
|
+
labelledBy = computed(() => this.field?.labelId ?? null, /* @ts-ignore */
|
|
1920
|
+
...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
|
|
1921
|
+
describedBy = computed(() => this.field?.describedBy() ?? null, /* @ts-ignore */
|
|
1922
|
+
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
1923
|
+
/** The options along the committed value, or `[]`. */
|
|
1924
|
+
selectedPath = computed(() => {
|
|
1925
|
+
const v = this.value();
|
|
1926
|
+
if (v == null)
|
|
1927
|
+
return [];
|
|
1928
|
+
if (this.valueMode() === 'path') {
|
|
1929
|
+
if (!Array.isArray(v))
|
|
1930
|
+
return [];
|
|
1931
|
+
const out = [];
|
|
1932
|
+
let list = this.options();
|
|
1933
|
+
for (const step of v) {
|
|
1934
|
+
const hit = list.find((o) => o.value === step);
|
|
1935
|
+
if (!hit)
|
|
1936
|
+
return [];
|
|
1937
|
+
out.push(hit);
|
|
1938
|
+
list = hit.children ?? [];
|
|
1939
|
+
}
|
|
1940
|
+
return out;
|
|
1941
|
+
}
|
|
1942
|
+
return this.findPath(this.options(), v) ?? [];
|
|
1943
|
+
}, /* @ts-ignore */
|
|
1944
|
+
...(ngDevMode ? [{ debugName: "selectedPath" }] : /* istanbul ignore next */ []));
|
|
1945
|
+
displayLabel = computed(() => this.selectedPath().map((o) => o.label).join(this.separator()), /* @ts-ignore */
|
|
1946
|
+
...(ngDevMode ? [{ debugName: "displayLabel" }] : /* istanbul ignore next */ []));
|
|
1947
|
+
/**
|
|
1948
|
+
* Columns rendered in the panel: the root list, then the children of every
|
|
1949
|
+
* opened parent along the active path. The last entry of the path is the
|
|
1950
|
+
* cursor — resting on a parent does not open it (click, hover or → does).
|
|
1951
|
+
*/
|
|
1952
|
+
columns = computed(() => {
|
|
1953
|
+
const cols = [[...this.options()]];
|
|
1954
|
+
const path = this.activePath();
|
|
1955
|
+
for (let depth = 0; depth < path.length - 1; depth++) {
|
|
1956
|
+
const opt = cols[depth]?.[path[depth]];
|
|
1957
|
+
if (!opt?.children?.length)
|
|
1958
|
+
break;
|
|
1959
|
+
cols.push([...opt.children]);
|
|
1960
|
+
}
|
|
1961
|
+
return cols;
|
|
1962
|
+
}, /* @ts-ignore */
|
|
1963
|
+
...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
1964
|
+
/** The column the keyboard cursor is in. */
|
|
1965
|
+
cursorColumn = computed(() => Math.max(0, Math.min(this.activePath().length - 1, this.columns().length - 1)), /* @ts-ignore */
|
|
1966
|
+
...(ngDevMode ? [{ debugName: "cursorColumn" }] : /* istanbul ignore next */ []));
|
|
1967
|
+
activeId = computed(() => {
|
|
1968
|
+
const path = this.activePath();
|
|
1969
|
+
const col = this.cursorColumn();
|
|
1970
|
+
return path.length ? this.optionId(col, path[col]) : null;
|
|
1971
|
+
}, /* @ts-ignore */
|
|
1972
|
+
...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
|
|
1973
|
+
constructor() {
|
|
1974
|
+
afterRenderEffect(() => {
|
|
1975
|
+
const id = this.activeId();
|
|
1976
|
+
if (!id || !this.open())
|
|
1977
|
+
return;
|
|
1978
|
+
this.panelRef()?.nativeElement.ownerDocument.getElementById(id)?.scrollIntoView?.({ block: 'nearest' });
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
optionId(column, row) {
|
|
1982
|
+
return `${this.panelId}-c${column}-r${row}`;
|
|
1983
|
+
}
|
|
1984
|
+
isOnPath(column, row) {
|
|
1985
|
+
return this.activePath()[column] === row;
|
|
1986
|
+
}
|
|
1987
|
+
isSelected(column, option) {
|
|
1988
|
+
return this.selectedPath()[column] === option;
|
|
1989
|
+
}
|
|
1990
|
+
isCursor(column, row) {
|
|
1991
|
+
return this.cursorColumn() === column && this.activePath()[column] === row;
|
|
1992
|
+
}
|
|
1993
|
+
// --- Open / close ------------------------------------------------------------
|
|
1994
|
+
toggle() {
|
|
1995
|
+
if (this.isDisabled())
|
|
1996
|
+
return;
|
|
1997
|
+
this.open() ? this.close() : this.openPanel();
|
|
1998
|
+
}
|
|
1999
|
+
openPanel() {
|
|
2000
|
+
if (this.isDisabled() || this.open())
|
|
2001
|
+
return;
|
|
2002
|
+
// Start on the committed path (its columns open), else on the first row.
|
|
2003
|
+
const sel = this.selectedPath();
|
|
2004
|
+
const path = sel.length ? this.indexPath(sel) : [this.firstEnabled(this.options())].filter((i) => i >= 0);
|
|
2005
|
+
this.activePath.set(path);
|
|
2006
|
+
this.open.set(true);
|
|
2007
|
+
afterNextRender(() => this.panelRef()?.nativeElement.focus(), { injector: this.injector });
|
|
2008
|
+
}
|
|
2009
|
+
close(restoreFocus = false) {
|
|
2010
|
+
if (!this.open())
|
|
2011
|
+
return;
|
|
2012
|
+
this.open.set(false);
|
|
2013
|
+
if (restoreFocus)
|
|
2014
|
+
this.triggerRef()?.nativeElement.focus();
|
|
2015
|
+
}
|
|
2016
|
+
onTriggerKeydown(event) {
|
|
2017
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
2018
|
+
event.preventDefault();
|
|
2019
|
+
this.openPanel();
|
|
2020
|
+
}
|
|
2021
|
+
else if (event.key === 'Escape') {
|
|
2022
|
+
event.preventDefault();
|
|
2023
|
+
this.close();
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
onFocusOut(event) {
|
|
2027
|
+
const related = event.relatedTarget;
|
|
2028
|
+
if (related && (this.host.nativeElement.contains(related) || this.panelRef()?.nativeElement.contains(related)))
|
|
2029
|
+
return;
|
|
2030
|
+
this.close();
|
|
2031
|
+
this.onTouched();
|
|
2032
|
+
}
|
|
2033
|
+
onPanelFocusout(event) {
|
|
2034
|
+
const related = event.relatedTarget;
|
|
2035
|
+
if (!related)
|
|
2036
|
+
return;
|
|
2037
|
+
if (this.host.nativeElement.contains(related) || this.panelRef()?.nativeElement.contains(related))
|
|
2038
|
+
return;
|
|
2039
|
+
this.close();
|
|
2040
|
+
this.onTouched();
|
|
2041
|
+
}
|
|
2042
|
+
// --- Pointer -----------------------------------------------------------------
|
|
2043
|
+
onOptionClick(column, row) {
|
|
2044
|
+
const option = this.columns()[column]?.[row];
|
|
2045
|
+
if (!option || option.disabled)
|
|
2046
|
+
return;
|
|
2047
|
+
if (option.children?.length) {
|
|
2048
|
+
this.expand(column, row);
|
|
2049
|
+
if (this.selectParents())
|
|
2050
|
+
this.commit(column, row);
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
this.setCursor(column, row);
|
|
2054
|
+
this.commit(column, row);
|
|
2055
|
+
}
|
|
2056
|
+
onOptionHover(column, row) {
|
|
2057
|
+
if (this.expandTrigger() !== 'hover')
|
|
2058
|
+
return;
|
|
2059
|
+
const option = this.columns()[column]?.[row];
|
|
2060
|
+
if (!option || option.disabled)
|
|
2061
|
+
return;
|
|
2062
|
+
this.expand(column, row);
|
|
2063
|
+
}
|
|
2064
|
+
clear(event) {
|
|
2065
|
+
event.stopPropagation();
|
|
2066
|
+
this.emit(null);
|
|
2067
|
+
this.triggerRef()?.nativeElement.focus();
|
|
2068
|
+
}
|
|
2069
|
+
// --- Keyboard ----------------------------------------------------------------
|
|
2070
|
+
onPanelKeydown(event) {
|
|
2071
|
+
const col = this.cursorColumn();
|
|
2072
|
+
const column = this.columns()[col] ?? [];
|
|
2073
|
+
const row = this.activePath()[col] ?? -1;
|
|
2074
|
+
switch (event.key) {
|
|
2075
|
+
case 'ArrowDown':
|
|
2076
|
+
case 'ArrowUp': {
|
|
2077
|
+
event.preventDefault();
|
|
2078
|
+
const next = this.stepRow(column, row, event.key === 'ArrowDown' ? 1 : -1);
|
|
2079
|
+
if (next >= 0)
|
|
2080
|
+
this.setCursor(col, next);
|
|
2081
|
+
break;
|
|
2082
|
+
}
|
|
2083
|
+
case 'Home':
|
|
2084
|
+
case 'End': {
|
|
2085
|
+
event.preventDefault();
|
|
2086
|
+
const next = event.key === 'Home' ? this.firstEnabled(column) : this.lastEnabled(column);
|
|
2087
|
+
if (next >= 0)
|
|
2088
|
+
this.setCursor(col, next);
|
|
2089
|
+
break;
|
|
2090
|
+
}
|
|
2091
|
+
case 'ArrowRight':
|
|
2092
|
+
event.preventDefault();
|
|
2093
|
+
if (row >= 0)
|
|
2094
|
+
this.expand(col, row);
|
|
2095
|
+
break;
|
|
2096
|
+
case 'ArrowLeft':
|
|
2097
|
+
event.preventDefault();
|
|
2098
|
+
if (col > 0)
|
|
2099
|
+
this.activePath.set(this.activePath().slice(0, col));
|
|
2100
|
+
break;
|
|
2101
|
+
case 'Enter':
|
|
2102
|
+
case ' ': {
|
|
2103
|
+
event.preventDefault();
|
|
2104
|
+
const option = column[row];
|
|
2105
|
+
if (!option || option.disabled)
|
|
2106
|
+
break;
|
|
2107
|
+
if (option.children?.length && !this.selectParents()) {
|
|
2108
|
+
this.expand(col, row);
|
|
2109
|
+
}
|
|
2110
|
+
else {
|
|
2111
|
+
this.commit(col, row);
|
|
2112
|
+
}
|
|
2113
|
+
break;
|
|
2114
|
+
}
|
|
2115
|
+
case 'Escape':
|
|
2116
|
+
event.preventDefault();
|
|
2117
|
+
event.stopPropagation();
|
|
2118
|
+
this.close(true);
|
|
2119
|
+
break;
|
|
2120
|
+
case 'Tab':
|
|
2121
|
+
this.close();
|
|
2122
|
+
break;
|
|
2123
|
+
default:
|
|
2124
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
2125
|
+
this.typeaheadSearch(event.key, col, column, row);
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
/** Point the cursor at `(column, row)`, trimming any deeper columns. */
|
|
2130
|
+
setCursor(column, row) {
|
|
2131
|
+
this.activePath.set([...this.activePath().slice(0, column), row]);
|
|
2132
|
+
}
|
|
2133
|
+
/** Open the children of `(column, row)` and move the cursor onto the first enabled one. */
|
|
2134
|
+
expand(column, row) {
|
|
2135
|
+
const option = this.columns()[column]?.[row];
|
|
2136
|
+
const children = option?.children;
|
|
2137
|
+
const first = children?.length ? this.firstEnabled(children) : -1;
|
|
2138
|
+
this.activePath.set(first >= 0 ? [...this.activePath().slice(0, column), row, first] : [...this.activePath().slice(0, column), row]);
|
|
2139
|
+
}
|
|
2140
|
+
stepRow(column, from, delta) {
|
|
2141
|
+
if (!column.length)
|
|
2142
|
+
return -1;
|
|
2143
|
+
let i = from;
|
|
2144
|
+
for (let s = 0; s < column.length; s++) {
|
|
2145
|
+
i = (i + delta + column.length) % column.length;
|
|
2146
|
+
if (!column[i].disabled)
|
|
2147
|
+
return i;
|
|
2148
|
+
}
|
|
2149
|
+
return -1;
|
|
2150
|
+
}
|
|
2151
|
+
firstEnabled(list) {
|
|
2152
|
+
return list.findIndex((o) => !o.disabled);
|
|
2153
|
+
}
|
|
2154
|
+
lastEnabled(list) {
|
|
2155
|
+
for (let i = list.length - 1; i >= 0; i--)
|
|
2156
|
+
if (!list[i].disabled)
|
|
2157
|
+
return i;
|
|
2158
|
+
return -1;
|
|
2159
|
+
}
|
|
2160
|
+
typeaheadSearch(char, col, column, from) {
|
|
2161
|
+
this.typeahead += char.toLocaleLowerCase();
|
|
2162
|
+
if (this.typeaheadTimer)
|
|
2163
|
+
clearTimeout(this.typeaheadTimer);
|
|
2164
|
+
this.typeaheadTimer = setTimeout(() => (this.typeahead = ''), 500);
|
|
2165
|
+
for (let s = 1; s <= column.length; s++) {
|
|
2166
|
+
const i = (from + s) % column.length;
|
|
2167
|
+
if (!column[i].disabled && column[i].label.toLocaleLowerCase().startsWith(this.typeahead)) {
|
|
2168
|
+
this.setCursor(col, i);
|
|
2169
|
+
return;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
// --- Value -------------------------------------------------------------------
|
|
2174
|
+
commit(column, row) {
|
|
2175
|
+
const cols = this.columns();
|
|
2176
|
+
const path = [];
|
|
2177
|
+
for (let c = 0; c < column; c++)
|
|
2178
|
+
path.push(cols[c][this.activePath()[c]]);
|
|
2179
|
+
path.push(cols[column][row]);
|
|
2180
|
+
const value = this.valueMode() === 'path' ? path.map((o) => o.value) : path[path.length - 1].value;
|
|
2181
|
+
this.emit(value);
|
|
2182
|
+
this.close(true);
|
|
2183
|
+
}
|
|
2184
|
+
emit(value) {
|
|
2185
|
+
this.value.set(value);
|
|
2186
|
+
this.onChange(value);
|
|
2187
|
+
this.change.emit(value);
|
|
2188
|
+
}
|
|
2189
|
+
/** Row indexes of a path of options. */
|
|
2190
|
+
indexPath(path) {
|
|
2191
|
+
const out = [];
|
|
2192
|
+
let list = this.options();
|
|
2193
|
+
for (const opt of path) {
|
|
2194
|
+
const i = list.indexOf(opt);
|
|
2195
|
+
if (i < 0)
|
|
2196
|
+
break;
|
|
2197
|
+
out.push(i);
|
|
2198
|
+
list = opt.children ?? [];
|
|
2199
|
+
}
|
|
2200
|
+
return out;
|
|
2201
|
+
}
|
|
2202
|
+
/** Depth-first search for the option whose value is `value` (leaf mode). */
|
|
2203
|
+
findPath(list, value, trail = []) {
|
|
2204
|
+
for (const opt of list) {
|
|
2205
|
+
const next = [...trail, opt];
|
|
2206
|
+
if (opt.value === value)
|
|
2207
|
+
return next;
|
|
2208
|
+
if (opt.children?.length) {
|
|
2209
|
+
const hit = this.findPath(opt.children, value, next);
|
|
2210
|
+
if (hit)
|
|
2211
|
+
return hit;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
return null;
|
|
2215
|
+
}
|
|
2216
|
+
ngOnDestroy() {
|
|
2217
|
+
if (this.typeaheadTimer)
|
|
2218
|
+
clearTimeout(this.typeaheadTimer);
|
|
2219
|
+
}
|
|
2220
|
+
// --- ControlValueAccessor ----------------------------------------------------
|
|
2221
|
+
writeValue(value) {
|
|
2222
|
+
this.value.set(value ?? null);
|
|
2223
|
+
}
|
|
2224
|
+
registerOnChange(fn) {
|
|
2225
|
+
this.onChange = fn;
|
|
2226
|
+
}
|
|
2227
|
+
registerOnTouched(fn) {
|
|
2228
|
+
this.onTouched = fn;
|
|
2229
|
+
}
|
|
2230
|
+
setDisabledState(isDisabled) {
|
|
2231
|
+
this.cvaDisabled.set(isDisabled);
|
|
2232
|
+
}
|
|
2233
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkCascader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2234
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkCascader, isStandalone: true, selector: "mk-cascader", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, valueMode: { classPropertyName: "valueMode", publicName: "valueMode", isSignal: true, isRequired: false, transformFunction: null }, selectParents: { classPropertyName: "selectParents", publicName: "selectParents", isSignal: true, isRequired: false, transformFunction: null }, expandTrigger: { classPropertyName: "expandTrigger", publicName: "expandTrigger", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", change: "change" }, host: { listeners: { "focusout": "onFocusOut($event)" }, properties: { "class.mk-cascader--sm": "effectiveSize() === 'sm'", "class.mk-cascader--lg": "effectiveSize() === 'lg'", "class.mk-cascader--open": "open()", "class.mk-cascader--invalid": "isInvalid()", "class.mk-cascader--disabled": "isDisabled()" }, classAttribute: "mk-cascader" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MkCascader), multi: true }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #field class=\"mk-cascader__field\">\n <button\n #trigger\n type=\"button\"\n class=\"mk-cascader__trigger\"\n [id]=\"triggerId\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-labelledby]=\"labelledBy() ? labelledBy() + ' ' + valueId : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-required]=\"isRequired() || null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n @if (displayLabel()) {\n <span class=\"mk-cascader__value\" [id]=\"valueId\">{{ displayLabel() }}</span>\n } @else {\n <span class=\"mk-cascader__value mk-cascader__value--placeholder\" [id]=\"valueId\">{{ placeholder() }}</span>\n }\n <span class=\"mk-cascader__icon\" aria-hidden=\"true\"></span>\n </button>\n\n @if (clearable() && selectedPath().length && !isDisabled()) {\n <button type=\"button\" class=\"mk-cascader__clear\" [attr.aria-label]=\"i18n.clear\" (click)=\"clear($event)\">\n <span class=\"mk-cascader__clear-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n</div>\n\n@if (open()) {\n <div\n #panel\n class=\"mk-cascader__panel\"\n role=\"listbox\"\n tabindex=\"-1\"\n [id]=\"panelId\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-activedescendant]=\"activeId()\"\n mkAnchoredPanel\n [mkAnchoredPanelFor]=\"field\"\n (dismiss)=\"close()\"\n (keydown)=\"onPanelKeydown($event)\"\n (focusout)=\"onPanelFocusout($event)\"\n >\n @for (column of columns(); track $index; let c = $index) {\n <ul class=\"mk-cascader__column\" role=\"group\">\n @for (opt of column; track $index; let r = $index) {\n <li\n class=\"mk-cascader__option\"\n role=\"option\"\n [id]=\"optionId(c, r)\"\n [attr.aria-selected]=\"isSelected(c, opt)\"\n [attr.aria-disabled]=\"opt.disabled || null\"\n [class.mk-cascader__option--path]=\"isOnPath(c, r)\"\n [class.mk-cascader__option--cursor]=\"isCursor(c, r)\"\n [class.mk-cascader__option--selected]=\"isSelected(c, opt)\"\n [class.mk-cascader__option--disabled]=\"opt.disabled\"\n (mousedown)=\"$event.preventDefault()\"\n (mouseenter)=\"onOptionHover(c, r)\"\n (click)=\"onOptionClick(c, r)\"\n >\n <span class=\"mk-cascader__option-label\">{{ opt.label }}</span>\n @if (opt.children?.length) {\n <span class=\"mk-cascader__chevron\" aria-hidden=\"true\"></span>\n }\n </li>\n } @empty {\n <li class=\"mk-cascader__empty\" role=\"presentation\">{{ i18n.noOptions }}</li>\n }\n </ul>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;font-family:var(--mk-font-sans)}.mk-cascader__field{display:flex;align-items:center;position:relative}.mk-cascader__trigger{flex:1 1 auto;display:flex;align-items:center;gap:var(--mk-space-2);width:100%;height:var(--mk-control-height-md);padding:0 var(--mk-space-3);text-align:start;font:inherit;font-size:var(--mk-font-size-md);color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);cursor:pointer}:host(.mk-cascader--sm) .mk-cascader__trigger{height:var(--mk-control-height-sm);padding:0 var(--mk-space-2);font-size:var(--mk-font-size-sm);border-radius:var(--mk-radius-sm)}:host(.mk-cascader--lg) .mk-cascader__trigger{height:var(--mk-control-height-lg);padding:0 var(--mk-space-4);font-size:var(--mk-font-size-lg)}.mk-cascader__trigger:hover:not(:disabled){border-color:var(--mk-border-strong)}.mk-cascader__trigger:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset);border-color:var(--mk-primary)}:host(.mk-cascader--invalid) .mk-cascader__trigger{border-color:var(--mk-danger)}:host(.mk-cascader--disabled) .mk-cascader__trigger{background-color:var(--mk-surface-2);color:var(--mk-text-disabled);cursor:not-allowed;opacity:.7}.mk-cascader__value{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-cascader__value--placeholder{color:var(--mk-text-subtle)}.mk-cascader__icon{flex:none;width:.6rem;height:.6rem;border-right:2px solid var(--mk-text-muted);border-bottom:2px solid var(--mk-text-muted);transform:rotate(45deg);transform-origin:center;margin-bottom:.15rem}:host(.mk-cascader--open) .mk-cascader__icon{transform:rotate(-135deg);margin-bottom:-.15rem}.mk-cascader__clear{position:absolute;inset-inline-end:var(--mk-space-8);display:grid;place-items:center;width:1.25rem;height:1.25rem;color:var(--mk-text-muted);background:transparent;border:none;border-radius:var(--mk-radius-circle);cursor:pointer}.mk-cascader__clear:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-cascader__clear-icon:before,.mk-cascader__clear-icon:after{content:\"\";position:absolute;width:.7rem;height:2px;background-color:currentColor}.mk-cascader__clear-icon:before{transform:rotate(45deg)}.mk-cascader__clear-icon:after{transform:rotate(-45deg)}.mk-cascader__panel{display:flex;align-items:stretch;background:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);box-shadow:var(--mk-shadow-lg);outline:none}.mk-cascader__column{min-width:10rem;max-height:16rem;margin:0;padding:var(--mk-space-1);list-style:none;overflow-y:auto;overscroll-behavior:contain}.mk-cascader__column+.mk-cascader__column{border-inline-start:var(--mk-border-width) solid var(--mk-border)}.mk-cascader__option{display:flex;align-items:center;gap:var(--mk-space-2);padding:var(--mk-space-2) var(--mk-space-3);font-size:var(--mk-font-size-md);color:var(--mk-text);border-radius:var(--mk-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none}.mk-cascader__option:hover:not(.mk-cascader__option--disabled){background-color:var(--mk-hover-bg, var(--mk-surface-2))}.mk-cascader__option--path{background-color:var(--mk-selected-bg)}.mk-cascader__option--cursor{box-shadow:inset 0 0 0 2px var(--mk-primary)}.mk-cascader__option--selected{color:var(--mk-selected-text);font-weight:var(--mk-font-weight-medium)}.mk-cascader__option--disabled{color:var(--mk-text-disabled);cursor:not-allowed}.mk-cascader__option-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-cascader__chevron{flex:none;width:.45rem;height:.45rem;border-right:2px solid var(--mk-text-muted);border-bottom:2px solid var(--mk-text-muted);transform:rotate(-45deg)}[dir=rtl] .mk-cascader__chevron{transform:rotate(135deg)}.mk-cascader__empty{padding:var(--mk-space-2) var(--mk-space-3);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}@media(max-width:640px){.mk-cascader__panel{flex-direction:column-reverse;max-height:60vh;overflow-y:auto}.mk-cascader__column{max-height:none}.mk-cascader__column+.mk-cascader__column{border-inline-start:0;border-bottom:var(--mk-border-width) solid var(--mk-border)}}\n"], dependencies: [{ kind: "directive", type: MkAnchoredPanel, selector: "[mkAnchoredPanel]", inputs: ["mkAnchoredPanelFor", "anchorRect", "placement", "gap", "matchWidth", "flip", "clamp", "keepOpenWhen"], outputs: ["dismiss"], exportAs: ["mkAnchoredPanel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2235
|
+
}
|
|
2236
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkCascader, decorators: [{
|
|
2237
|
+
type: Component,
|
|
2238
|
+
args: [{ selector: 'mk-cascader', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MkAnchoredPanel], host: {
|
|
2239
|
+
class: 'mk-cascader',
|
|
2240
|
+
'[class.mk-cascader--sm]': "effectiveSize() === 'sm'",
|
|
2241
|
+
'[class.mk-cascader--lg]': "effectiveSize() === 'lg'",
|
|
2242
|
+
'[class.mk-cascader--open]': 'open()',
|
|
2243
|
+
'[class.mk-cascader--invalid]': 'isInvalid()',
|
|
2244
|
+
'[class.mk-cascader--disabled]': 'isDisabled()',
|
|
2245
|
+
'(focusout)': 'onFocusOut($event)',
|
|
2246
|
+
}, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MkCascader), multi: true }], template: "<div #field class=\"mk-cascader__field\">\n <button\n #trigger\n type=\"button\"\n class=\"mk-cascader__trigger\"\n [id]=\"triggerId\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-labelledby]=\"labelledBy() ? labelledBy() + ' ' + valueId : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-required]=\"isRequired() || null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n @if (displayLabel()) {\n <span class=\"mk-cascader__value\" [id]=\"valueId\">{{ displayLabel() }}</span>\n } @else {\n <span class=\"mk-cascader__value mk-cascader__value--placeholder\" [id]=\"valueId\">{{ placeholder() }}</span>\n }\n <span class=\"mk-cascader__icon\" aria-hidden=\"true\"></span>\n </button>\n\n @if (clearable() && selectedPath().length && !isDisabled()) {\n <button type=\"button\" class=\"mk-cascader__clear\" [attr.aria-label]=\"i18n.clear\" (click)=\"clear($event)\">\n <span class=\"mk-cascader__clear-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n</div>\n\n@if (open()) {\n <div\n #panel\n class=\"mk-cascader__panel\"\n role=\"listbox\"\n tabindex=\"-1\"\n [id]=\"panelId\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-activedescendant]=\"activeId()\"\n mkAnchoredPanel\n [mkAnchoredPanelFor]=\"field\"\n (dismiss)=\"close()\"\n (keydown)=\"onPanelKeydown($event)\"\n (focusout)=\"onPanelFocusout($event)\"\n >\n @for (column of columns(); track $index; let c = $index) {\n <ul class=\"mk-cascader__column\" role=\"group\">\n @for (opt of column; track $index; let r = $index) {\n <li\n class=\"mk-cascader__option\"\n role=\"option\"\n [id]=\"optionId(c, r)\"\n [attr.aria-selected]=\"isSelected(c, opt)\"\n [attr.aria-disabled]=\"opt.disabled || null\"\n [class.mk-cascader__option--path]=\"isOnPath(c, r)\"\n [class.mk-cascader__option--cursor]=\"isCursor(c, r)\"\n [class.mk-cascader__option--selected]=\"isSelected(c, opt)\"\n [class.mk-cascader__option--disabled]=\"opt.disabled\"\n (mousedown)=\"$event.preventDefault()\"\n (mouseenter)=\"onOptionHover(c, r)\"\n (click)=\"onOptionClick(c, r)\"\n >\n <span class=\"mk-cascader__option-label\">{{ opt.label }}</span>\n @if (opt.children?.length) {\n <span class=\"mk-cascader__chevron\" aria-hidden=\"true\"></span>\n }\n </li>\n } @empty {\n <li class=\"mk-cascader__empty\" role=\"presentation\">{{ i18n.noOptions }}</li>\n }\n </ul>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;font-family:var(--mk-font-sans)}.mk-cascader__field{display:flex;align-items:center;position:relative}.mk-cascader__trigger{flex:1 1 auto;display:flex;align-items:center;gap:var(--mk-space-2);width:100%;height:var(--mk-control-height-md);padding:0 var(--mk-space-3);text-align:start;font:inherit;font-size:var(--mk-font-size-md);color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);cursor:pointer}:host(.mk-cascader--sm) .mk-cascader__trigger{height:var(--mk-control-height-sm);padding:0 var(--mk-space-2);font-size:var(--mk-font-size-sm);border-radius:var(--mk-radius-sm)}:host(.mk-cascader--lg) .mk-cascader__trigger{height:var(--mk-control-height-lg);padding:0 var(--mk-space-4);font-size:var(--mk-font-size-lg)}.mk-cascader__trigger:hover:not(:disabled){border-color:var(--mk-border-strong)}.mk-cascader__trigger:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset);border-color:var(--mk-primary)}:host(.mk-cascader--invalid) .mk-cascader__trigger{border-color:var(--mk-danger)}:host(.mk-cascader--disabled) .mk-cascader__trigger{background-color:var(--mk-surface-2);color:var(--mk-text-disabled);cursor:not-allowed;opacity:.7}.mk-cascader__value{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-cascader__value--placeholder{color:var(--mk-text-subtle)}.mk-cascader__icon{flex:none;width:.6rem;height:.6rem;border-right:2px solid var(--mk-text-muted);border-bottom:2px solid var(--mk-text-muted);transform:rotate(45deg);transform-origin:center;margin-bottom:.15rem}:host(.mk-cascader--open) .mk-cascader__icon{transform:rotate(-135deg);margin-bottom:-.15rem}.mk-cascader__clear{position:absolute;inset-inline-end:var(--mk-space-8);display:grid;place-items:center;width:1.25rem;height:1.25rem;color:var(--mk-text-muted);background:transparent;border:none;border-radius:var(--mk-radius-circle);cursor:pointer}.mk-cascader__clear:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-cascader__clear-icon:before,.mk-cascader__clear-icon:after{content:\"\";position:absolute;width:.7rem;height:2px;background-color:currentColor}.mk-cascader__clear-icon:before{transform:rotate(45deg)}.mk-cascader__clear-icon:after{transform:rotate(-45deg)}.mk-cascader__panel{display:flex;align-items:stretch;background:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);box-shadow:var(--mk-shadow-lg);outline:none}.mk-cascader__column{min-width:10rem;max-height:16rem;margin:0;padding:var(--mk-space-1);list-style:none;overflow-y:auto;overscroll-behavior:contain}.mk-cascader__column+.mk-cascader__column{border-inline-start:var(--mk-border-width) solid var(--mk-border)}.mk-cascader__option{display:flex;align-items:center;gap:var(--mk-space-2);padding:var(--mk-space-2) var(--mk-space-3);font-size:var(--mk-font-size-md);color:var(--mk-text);border-radius:var(--mk-radius-sm);cursor:pointer;-webkit-user-select:none;user-select:none}.mk-cascader__option:hover:not(.mk-cascader__option--disabled){background-color:var(--mk-hover-bg, var(--mk-surface-2))}.mk-cascader__option--path{background-color:var(--mk-selected-bg)}.mk-cascader__option--cursor{box-shadow:inset 0 0 0 2px var(--mk-primary)}.mk-cascader__option--selected{color:var(--mk-selected-text);font-weight:var(--mk-font-weight-medium)}.mk-cascader__option--disabled{color:var(--mk-text-disabled);cursor:not-allowed}.mk-cascader__option-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-cascader__chevron{flex:none;width:.45rem;height:.45rem;border-right:2px solid var(--mk-text-muted);border-bottom:2px solid var(--mk-text-muted);transform:rotate(-45deg)}[dir=rtl] .mk-cascader__chevron{transform:rotate(135deg)}.mk-cascader__empty{padding:var(--mk-space-2) var(--mk-space-3);color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}@media(max-width:640px){.mk-cascader__panel{flex-direction:column-reverse;max-height:60vh;overflow-y:auto}.mk-cascader__column{max-height:none}.mk-cascader__column+.mk-cascader__column{border-inline-start:0;border-bottom:var(--mk-border-width) solid var(--mk-border)}}\n"] }]
|
|
2247
|
+
}], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], 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"] }], valueMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueMode", required: false }] }], selectParents: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectParents", required: false }] }], expandTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandTrigger", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], change: [{ type: i0.Output, args: ["change"] }] } });
|
|
2248
|
+
|
|
1439
2249
|
/**
|
|
1440
2250
|
* Autocomplete — an accessible text input that suggests options as the user
|
|
1441
2251
|
* types, implementing the ARIA combobox (`aria-autocomplete="list"`) pattern
|
|
@@ -9204,5 +10014,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
9204
10014
|
* Generated bundle index. Do not edit.
|
|
9205
10015
|
*/
|
|
9206
10016
|
|
|
9207
|
-
export { MK_CARD_BRAND_NAMES, MK_IBAN_LENGTHS, MK_KEYBOARD_LAYOUT_QWERTY_PL, MK_PHONE_COUNTRIES, MK_POSTAL_FORMATS, MK_TAX_ID_FORMATS, MkAutocomplete, MkButtonToggle, MkButtonToggleGroup, MkCardNumberInput, MkCodeEditor, MkColorPicker, MkCurrencyInput, MkFileUpload, MkFormErrorSummary, MkFormField, MkI18nInput, MkIbanInput, MkInput, MkInputGroup, MkMention, MkMentionPanel, MkMultiSelect, MkNumberInput, MkNumericKeypad, MkOnScreenKeyboard, MkOnScreenKeyboardTrigger, MkOtp, MkPasswordInput, MkPhoneInput, MkPostalCodeInput, MkRadio, MkRadioGroup, MkRangeSlider, MkRating, MkRepeater, MkRepeaterEmpty, MkRepeaterRow, MkSelect, MkSignaturePad, MkSlider, MkSubmitInput, MkSwitch, MkTagInput, MkTaxIdInput, MkTransferList, MkTreeSelect, mkCountryFlag, mkDetectCardBrand, mkIbanChecksum, mkIbanIsValid, mkIbanValidator, mkLuhnCheck, mkNipChecksum, mkPostalCodeValidator, mkPostalFormat, mkTaxIdFormat, mkTaxIdIsValid, mkTaxIdValidator };
|
|
10017
|
+
export { MK_CARD_BRAND_NAMES, MK_IBAN_LENGTHS, MK_KEYBOARD_LAYOUT_QWERTY_PL, MK_PHONE_COUNTRIES, MK_POSTAL_FORMATS, MK_TAX_ID_FORMATS, MkAutocomplete, MkButtonToggle, MkButtonToggleGroup, MkCardNumberInput, MkCascader, MkCodeEditor, MkColorPicker, MkCurrencyInput, MkFileUpload, MkFormErrorSummary, MkFormField, MkI18nInput, MkIbanInput, MkInput, MkInputGroup, MkListbox, MkMention, MkMentionPanel, MkMultiSelect, MkNumberInput, MkNumericKeypad, MkOnScreenKeyboard, MkOnScreenKeyboardTrigger, MkOtp, MkPasswordInput, MkPhoneInput, MkPostalCodeInput, MkRadio, MkRadioGroup, MkRangeSlider, MkRating, MkRepeater, MkRepeaterEmpty, MkRepeaterRow, MkSelect, MkSignaturePad, MkSlider, MkSubmitInput, MkSwitch, MkTagInput, MkTaxIdInput, MkTransferList, MkTreeSelect, mkCountryFlag, mkDetectCardBrand, mkIbanChecksum, mkIbanIsValid, mkIbanValidator, mkLuhnCheck, mkNipChecksum, mkPostalCodeValidator, mkPostalFormat, mkTaxIdFormat, mkTaxIdIsValid, mkTaxIdValidator };
|
|
9208
10018
|
//# sourceMappingURL=mk-kit-ui-forms.mjs.map
|