@uni-design-system/uni-angular 8.3.1 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed, linkedSignal, resource, Injectable, inject, DestroyRef, InjectionToken, input, ChangeDetectionStrategy, Component, contentChildren, output, Renderer2, ElementRef, Directive, model, viewChild, effect, untracked, afterNextRender, ViewChild,
|
|
2
|
+
import { signal, computed, linkedSignal, resource, Injectable, inject, DestroyRef, InjectionToken, input, ChangeDetectionStrategy, Component, contentChildren, output, Renderer2, ElementRef, Directive, model, viewChild, effect, untracked, afterRenderEffect, afterNextRender, ViewChild, booleanAttribute, viewChildren } from '@angular/core';
|
|
3
3
|
import { injectGlobal, css, keyframes } from '@emotion/css';
|
|
4
|
-
import { UniThemes, LightTheme, toTypefaces, parseTheme, formatThemeIssues, hydrateTheme, createThemeFromPalette, Z_INDEX, removeInputPlatformStyling, fadeIn, fadeOut,
|
|
4
|
+
import { UniThemes, LightTheme, toTypefaces, parseTheme, formatThemeIssues, hydrateTheme, createThemeFromPalette, Z_INDEX, removeInputPlatformStyling, fadeIn, fadeOut, expandDuration, expandFadeIn, collapseFadeOut, HOVER_OR_KEYBOARD_FOCUS, ShapeRadii, generatePalette, emitThemeFile, emitDtcgTokens } from '@uni-design-system/uni-core';
|
|
5
5
|
import { NgClass, NgTemplateOutlet, CommonModule } from '@angular/common';
|
|
6
6
|
|
|
7
7
|
let nextUniqueId = 0;
|
|
@@ -49,6 +49,35 @@ const visuallyHidden = {
|
|
|
49
49
|
function motionSafe(styles) {
|
|
50
50
|
return { '@media (prefers-reduced-motion: no-preference)': styles };
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* A polite live region's text, for the running commentary a form control owes
|
|
54
|
+
* a screen reader: commits, clears, refused entries, result counts — changes
|
|
55
|
+
* a sighted user sees but that are otherwise silent.
|
|
56
|
+
*
|
|
57
|
+
* Extracted because five controls (`uni-combobox`, `uni-tag-input`,
|
|
58
|
+
* `uni-time-input`, `uni-date-input`, `uni-calendar`) carried byte-identical
|
|
59
|
+
* copies, including the repeat trick below — the kind of subtlety that is
|
|
60
|
+
* quietly dropped when the sixth control hand-rolls its own.
|
|
61
|
+
*
|
|
62
|
+
* Announcing the same text twice must still be heard: assistive tech reads a
|
|
63
|
+
* live region when its content *changes*, so setting an identical string is a
|
|
64
|
+
* no-op and the second "No match." would be silent. A trailing space breaks
|
|
65
|
+
* the equality without changing a word of what is read. Successive repeats
|
|
66
|
+
* alternate between the padded and unpadded form, so nothing accumulates.
|
|
67
|
+
*
|
|
68
|
+
* Deliberately holds no DOM and no styling: the region belongs to the
|
|
69
|
+
* component's own template, where its placement and visually-hidden class are
|
|
70
|
+
* already the component's business.
|
|
71
|
+
*/
|
|
72
|
+
function createAnnouncer() {
|
|
73
|
+
const message = signal('', ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
|
|
74
|
+
return {
|
|
75
|
+
message: message.asReadonly(),
|
|
76
|
+
announce(text) {
|
|
77
|
+
message.set(message() === text ? `${text} ` : text);
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
52
81
|
|
|
53
82
|
/**
|
|
54
83
|
* Canonical date/time value shapes shared by `uni-calendar`,
|
|
@@ -347,8 +376,9 @@ const joinDateTime = (date, time) => date && time ? `${date}T${time}` : undefine
|
|
|
347
376
|
* Extracted because three controls need the identical contract
|
|
348
377
|
* (`uni-search-input`, `uni-tag-input`, and the multi-select upgrade), and the
|
|
349
378
|
* parts that silently drift between hand-rolled copies all live here: the
|
|
350
|
-
* wrap-around arithmetic
|
|
351
|
-
*
|
|
379
|
+
* wrap-around arithmetic and keeping the active id in sync with the option
|
|
380
|
+
* list. Home/End are opt-in (`homeEndNavigates`) because a text field's caret
|
|
381
|
+
* has the better claim on them.
|
|
352
382
|
*
|
|
353
383
|
* `Enter` and `Escape` are deliberately *not* handled: what they mean depends
|
|
354
384
|
* on the control (submit a search, commit a typed token, clear the field), and
|
|
@@ -362,6 +392,7 @@ class ListboxNavigation {
|
|
|
362
392
|
_activeIndex = signal(-1, ...(ngDevMode ? [{ debugName: "_activeIndex" }] : /* istanbul ignore next */ []));
|
|
363
393
|
wrap;
|
|
364
394
|
isDisabled;
|
|
395
|
+
homeEndNavigates;
|
|
365
396
|
/** Whether the popup is showing. Also false when there is nothing to show. */
|
|
366
397
|
open = computed(() => this._open() && this.config.count() > 0, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
367
398
|
/** Index of the highlighted option, or -1 when none is active. */
|
|
@@ -380,6 +411,7 @@ class ListboxNavigation {
|
|
|
380
411
|
this.listboxId = uniqueId(config.idPrefix ?? 'uni-listbox');
|
|
381
412
|
this.wrap = config.wrap ?? true;
|
|
382
413
|
this.isDisabled = config.disabled ?? (() => false);
|
|
414
|
+
this.homeEndNavigates = config.homeEndNavigates ?? false;
|
|
383
415
|
}
|
|
384
416
|
/** Stable per-option id, for `role="option"` elements. */
|
|
385
417
|
optionId(index) {
|
|
@@ -397,9 +429,9 @@ class ListboxNavigation {
|
|
|
397
429
|
this._activeIndex.set(index);
|
|
398
430
|
}
|
|
399
431
|
/**
|
|
400
|
-
* Handle ArrowDown / ArrowUp
|
|
401
|
-
* Returns true when the key was consumed, so
|
|
402
|
-
* its own handling for everything else.
|
|
432
|
+
* Handle ArrowDown / ArrowUp — and Home / End where `homeEndNavigates` is
|
|
433
|
+
* on. Opens the popup if needed. Returns true when the key was consumed, so
|
|
434
|
+
* a caller can fall through to its own handling for everything else.
|
|
403
435
|
*/
|
|
404
436
|
navigate(event) {
|
|
405
437
|
const count = this.config.count();
|
|
@@ -421,10 +453,11 @@ class ListboxNavigation {
|
|
|
421
453
|
case 'ArrowUp':
|
|
422
454
|
// Opening with ArrowUp lands on the last option, matching menus.
|
|
423
455
|
return current < 0 ? this.seek(count - 1, -1, count) : this.step(current, -1, count);
|
|
456
|
+
// Left to the caret unless a consumer opts in — see `homeEndNavigates`.
|
|
424
457
|
case 'Home':
|
|
425
|
-
return this.seek(0, 1, count);
|
|
458
|
+
return this.homeEndNavigates ? this.seek(0, 1, count) : null;
|
|
426
459
|
case 'End':
|
|
427
|
-
return this.seek(count - 1, -1, count);
|
|
460
|
+
return this.homeEndNavigates ? this.seek(count - 1, -1, count) : null;
|
|
428
461
|
default:
|
|
429
462
|
return null;
|
|
430
463
|
}
|
|
@@ -674,10 +707,31 @@ function transformOriginFor(panel, trigger) {
|
|
|
674
707
|
|
|
675
708
|
/**
|
|
676
709
|
* Shared plumbing for top-layer overlays built on the native `popover`
|
|
677
|
-
* attribute (dropdown, popover, callout
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
* sourced.
|
|
710
|
+
* attribute (dropdown, popover, callout, tooltip, the listbox popups,
|
|
711
|
+
* snackbar). Pure functions and data — no DOM ownership — so each component
|
|
712
|
+
* keeps its own template while the anchor bookkeeping, discrete-transition
|
|
713
|
+
* block, and focus-restore rule stay single-sourced.
|
|
714
|
+
*
|
|
715
|
+
* These are deliberately à-la-carte rather than one factory: the overlays
|
|
716
|
+
* share *mechanics* but not *lifecycles*. A dropdown toggles from a trigger
|
|
717
|
+
* click and restores focus; a tooltip follows hover and never takes focus; a
|
|
718
|
+
* callout traps focus behind a scrim; a listbox popup is rendered by `@if`
|
|
719
|
+
* with focus staying in the field; a snackbar has no anchor at all and closes
|
|
720
|
+
* on a timer. Take what a component needs and leave the rest.
|
|
721
|
+
*
|
|
722
|
+
* **Choosing `popover="auto"` vs `"manual"`** — the one decision worth making
|
|
723
|
+
* deliberately. `auto` brings native light-dismiss: an outside pointerdown or
|
|
724
|
+
* Escape closes it. That is right for a panel the user opened and can dismiss
|
|
725
|
+
* by looking away — dropdown, popover, callout, tooltip.
|
|
726
|
+
*
|
|
727
|
+
* `manual` is right when the control already owns dismissal, and light-dismiss
|
|
728
|
+
* would fight it. Two cases in this library:
|
|
729
|
+
* - the listbox popups, whose own field is *outside* the popup, so `auto`
|
|
730
|
+
* would close the list on every click into the input;
|
|
731
|
+
* - the snackbar, which would be torn away from someone still reading it by
|
|
732
|
+
* a click anywhere on the page.
|
|
733
|
+
*
|
|
734
|
+
* `manual` means the component must close it — nothing else will.
|
|
681
735
|
*/
|
|
682
736
|
/** Placement → `transform-origin`, so scale animations grow from the anchor. */
|
|
683
737
|
const TRANSFORM_ORIGINS = {
|
|
@@ -721,13 +775,20 @@ function isToggleOpen(event) {
|
|
|
721
775
|
* top layer: `transition-behavior: allow-discrete` over the `hidden` keys plus
|
|
722
776
|
* `display`/`overlay`, the shown state under `:popover-open`, and
|
|
723
777
|
* `@starting-style` so entry transitions run from the hidden state.
|
|
778
|
+
*
|
|
779
|
+
* `display` and `overlay` must ride along or the element cannot animate into
|
|
780
|
+
* and out of the top layer at all — it would simply appear and vanish.
|
|
781
|
+
*
|
|
782
|
+
* `timingFunction` is omitted from the output when not given, leaving the CSS
|
|
783
|
+
* initial value (`ease`), so callers that never asked for one are unaffected.
|
|
724
784
|
*/
|
|
725
|
-
function discreteOverlayTransition(durationMs, hidden, shown) {
|
|
785
|
+
function discreteOverlayTransition(durationMs, hidden, shown, timingFunction) {
|
|
726
786
|
return {
|
|
727
787
|
transitionProperty: [...Object.keys(hidden), 'display', 'overlay']
|
|
728
788
|
.map((key) => key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`))
|
|
729
789
|
.join(', '),
|
|
730
790
|
transitionDuration: `${durationMs}ms`,
|
|
791
|
+
...(timingFunction ? { transitionTimingFunction: timingFunction } : {}),
|
|
731
792
|
transitionBehavior: 'allow-discrete',
|
|
732
793
|
...hidden,
|
|
733
794
|
'&:popover-open': shown,
|
|
@@ -1276,6 +1337,9 @@ class ThemeService {
|
|
|
1276
1337
|
borders = computed(() => this.theme().borders, ...(ngDevMode ? [{ debugName: "borders" }] : /* istanbul ignore next */ []));
|
|
1277
1338
|
shadows = computed(() => this.theme().shadows, ...(ngDevMode ? [{ debugName: "shadows" }] : /* istanbul ignore next */ []));
|
|
1278
1339
|
icons = computed(() => this.theme().icons, ...(ngDevMode ? [{ debugName: "icons" }] : /* istanbul ignore next */ []));
|
|
1340
|
+
// `?? {}` for themes registered as JSON that predate the motion scale —
|
|
1341
|
+
// the validator does not require it, so they must not crash on read.
|
|
1342
|
+
motions = computed(() => this.theme().motion ?? {}, ...(ngDevMode ? [{ debugName: "motions" }] : /* istanbul ignore next */ []));
|
|
1279
1343
|
constructor() {
|
|
1280
1344
|
// Honor the user's reduced-motion preference across every component
|
|
1281
1345
|
// (WCAG 2.3.3): collapse all animations/transitions to a single frame.
|
|
@@ -1513,6 +1577,16 @@ class ThemeService {
|
|
|
1513
1577
|
borderRadius,
|
|
1514
1578
|
};
|
|
1515
1579
|
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Resolves a named motion primitive. Falls back to `popup` and then to a
|
|
1582
|
+
* hard default, so a theme that predates the motion scale — or names a
|
|
1583
|
+
* token that isn't there — still animates rather than snapping.
|
|
1584
|
+
*/
|
|
1585
|
+
motion(token) {
|
|
1586
|
+
const motions = this.motions();
|
|
1587
|
+
return ((token ? motions[token] : undefined) ??
|
|
1588
|
+
motions['popup'] ?? { duration: 100, easing: 'linear', scale: 0.8 });
|
|
1589
|
+
}
|
|
1516
1590
|
radius(size) {
|
|
1517
1591
|
return !size ? undefined : { borderRadius: this.radii()[size] };
|
|
1518
1592
|
}
|
|
@@ -2904,7 +2978,8 @@ class UniCalendarComponent extends BaseComponent {
|
|
|
2904
2978
|
/** Hover/focus candidate painting the preview band while a range is pending. */
|
|
2905
2979
|
previewDate = signal(null, ...(ngDevMode ? [{ debugName: "previewDate" }] : /* istanbul ignore next */ []));
|
|
2906
2980
|
/** Live-region text; selections are otherwise silent for a screen reader. */
|
|
2907
|
-
|
|
2981
|
+
/** Commits, clears and refusals are otherwise silent to a screen reader. */
|
|
2982
|
+
announcer = createAnnouncer();
|
|
2908
2983
|
resolvedLocale = computed(() => this.locale() ?? (document.documentElement.lang || navigator.language || 'en-US'), ...(ngDevMode ? [{ debugName: "resolvedLocale" }] : /* istanbul ignore next */ []));
|
|
2909
2984
|
resolvedWeekStart = computed(() => this.weekStart() ?? localeWeekStart(this.resolvedLocale()), ...(ngDevMode ? [{ debugName: "resolvedWeekStart" }] : /* istanbul ignore next */ []));
|
|
2910
2985
|
/**
|
|
@@ -3036,12 +3111,12 @@ class UniCalendarComponent extends BaseComponent {
|
|
|
3036
3111
|
const full = (d) => formatDate(d, locale, { dateStyle: 'full' });
|
|
3037
3112
|
if (this.mode() === 'single') {
|
|
3038
3113
|
this.value.set(date);
|
|
3039
|
-
this.announce(`${full(date)} selected.`);
|
|
3114
|
+
this.announcer.announce(`${full(date)} selected.`);
|
|
3040
3115
|
}
|
|
3041
3116
|
else if (!this.pendingStart()) {
|
|
3042
3117
|
this.pendingStart.set(date);
|
|
3043
3118
|
this.previewDate.set(date);
|
|
3044
|
-
this.announce(`Start date ${full(date)}. Choose an end date.`);
|
|
3119
|
+
this.announcer.announce(`Start date ${full(date)}. Choose an end date.`);
|
|
3045
3120
|
}
|
|
3046
3121
|
else {
|
|
3047
3122
|
let [start, end] = [this.pendingStart(), date];
|
|
@@ -3051,14 +3126,14 @@ class UniCalendarComponent extends BaseComponent {
|
|
|
3051
3126
|
this.previewDate.set(null);
|
|
3052
3127
|
this.value.set({ start, end });
|
|
3053
3128
|
const days = inclusiveDayCount(start, end);
|
|
3054
|
-
this.announce(`Range selected, ${full(start)} to ${full(end)}. ${days} ${days === 1 ? 'day' : 'days'}.`);
|
|
3129
|
+
this.announcer.announce(`Range selected, ${full(start)} to ${full(end)}. ${days} ${days === 1 ? 'day' : 'days'}.`);
|
|
3055
3130
|
}
|
|
3056
3131
|
this.selected.emit(date);
|
|
3057
3132
|
}
|
|
3058
3133
|
cancelPending() {
|
|
3059
3134
|
this.pendingStart.set(null);
|
|
3060
3135
|
this.previewDate.set(null);
|
|
3061
|
-
this.announce('Range selection cancelled.');
|
|
3136
|
+
this.announcer.announce('Range selection cancelled.');
|
|
3062
3137
|
}
|
|
3063
3138
|
// --- Navigation ------------------------------------------------------------
|
|
3064
3139
|
onNav(direction) {
|
|
@@ -3158,10 +3233,6 @@ class UniCalendarComponent extends BaseComponent {
|
|
|
3158
3233
|
}
|
|
3159
3234
|
return first;
|
|
3160
3235
|
}
|
|
3161
|
-
announce(message) {
|
|
3162
|
-
// Re-announce identical text by breaking the string equality.
|
|
3163
|
-
this.announcement.set(this.announcement() === message ? `${message} ` : message);
|
|
3164
|
-
}
|
|
3165
3236
|
// --- Styling ---------------------------------------------------------------
|
|
3166
3237
|
daySize = computed(() => (this.componentTheme().sizes?.[this.size()] ?? {}), ...(ngDevMode ? [{ debugName: "daySize" }] : /* istanbul ignore next */ []));
|
|
3167
3238
|
className = computed(() => css([(this.componentTheme().fixed ?? { display: 'inline-block' })]), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
@@ -3294,11 +3365,11 @@ class UniCalendarComponent extends BaseComponent {
|
|
|
3294
3365
|
}
|
|
3295
3366
|
showOutside = computed(() => this.componentOptions().showOutsideDays ?? false, ...(ngDevMode ? [{ debugName: "showOutside" }] : /* istanbul ignore next */ []));
|
|
3296
3367
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniCalendarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3297
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniCalendarComponent, isStandalone: true, selector: "uni-calendar, Calendar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, month: { classPropertyName: "month", publicName: "month", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, markers: { classPropertyName: "markers", publicName: "markers", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, weekStart: { classPropertyName: "weekStart", publicName: "weekStart", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", month: "monthChange", selected: "selected" }, host: { listeners: { "focusout": "onHostFocusOut($event)" }, properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'calendar' }], usesInheritance: true, ngImport: i0, template: "<div [class]=\"navClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navPrevSymbol ?? 'chevron_left'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(-1)\"\n >\n Previous month\n </button>\n <!-- aria-live so PageUp/Down narrates the new month without refocusing. -->\n <div [class]=\"headingClass()\" [id]=\"headingId\" aria-live=\"polite\">{{ heading() }}</div>\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navNextSymbol ?? 'chevron_right'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(1)\"\n >\n Next month\n </button>\n</div>\n\n<!-- One tab stop: the roving tabindex lives on the day buttons, and the grid\n itself only relays their bubbling keys (same delegation as tag-input). -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n role=\"grid\"\n [class]=\"gridClass()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : headingId\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onGridKeydown($event)\"\n>\n <div role=\"row\" [class]=\"rowClass()\">\n @for (weekday of weekdays(); track weekday.full) {\n <div role=\"columnheader\" [class]=\"weekdayClass()\">\n <abbr [attr.title]=\"weekday.full\">{{ weekday.label }}</abbr>\n </div>\n }\n </div>\n\n @for (week of gridWeeks(); track week[0].date) {\n <div role=\"row\" [class]=\"rowClass()\">\n @for (cell of week; track cell.date) {\n @if (cell.outside) {\n <!-- Outside days: hidden placeholders by default (geometry kept),\n muted and non-interactive under the showOutsideDays option. -->\n <div role=\"gridcell\" aria-hidden=\"true\" [class]=\"cell.cellClass\">\n @if (showOutside()) {\n <span [class]=\"outsideDayClass()\">{{ cell.day }}</span>\n }\n </div>\n } @else {\n <div\n role=\"gridcell\"\n [class]=\"cell.cellClass\"\n [attr.aria-selected]=\"cell.selected || cell.inBand ? true : null\"\n >\n <button\n type=\"button\"\n [class]=\"cell.dayClass\"\n [attr.data-date]=\"cell.date\"\n [tabindex]=\"cell.tabIndex\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-current]=\"cell.today ? 'date' : null\"\n [disabled]=\"cell.disabled || disabled()\"\n (click)=\"select(cell.date)\"\n (mouseenter)=\"onDayHover(cell.date)\"\n >\n {{ cell.day }}\n @if (cell.markers.length) {\n <span [class]=\"dotsClass()\">\n @for (marker of cell.markers; track $index) {\n <span data-dot [class]=\"dotClassFor(marker.variant)\"></span>\n }\n </span>\n }\n </button>\n </div>\n }\n }\n </div>\n }\n</div>\n\n<!-- Selections and range progress are otherwise silent for a screen reader. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{
|
|
3368
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniCalendarComponent, isStandalone: true, selector: "uni-calendar, Calendar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, month: { classPropertyName: "month", publicName: "month", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, markers: { classPropertyName: "markers", publicName: "markers", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, weekStart: { classPropertyName: "weekStart", publicName: "weekStart", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", month: "monthChange", selected: "selected" }, host: { listeners: { "focusout": "onHostFocusOut($event)" }, properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'calendar' }], usesInheritance: true, ngImport: i0, template: "<div [class]=\"navClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navPrevSymbol ?? 'chevron_left'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(-1)\"\n >\n Previous month\n </button>\n <!-- aria-live so PageUp/Down narrates the new month without refocusing. -->\n <div [class]=\"headingClass()\" [id]=\"headingId\" aria-live=\"polite\">{{ heading() }}</div>\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navNextSymbol ?? 'chevron_right'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(1)\"\n >\n Next month\n </button>\n</div>\n\n<!-- One tab stop: the roving tabindex lives on the day buttons, and the grid\n itself only relays their bubbling keys (same delegation as tag-input). -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n role=\"grid\"\n [class]=\"gridClass()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : headingId\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onGridKeydown($event)\"\n>\n <div role=\"row\" [class]=\"rowClass()\">\n @for (weekday of weekdays(); track weekday.full) {\n <div role=\"columnheader\" [class]=\"weekdayClass()\">\n <abbr [attr.title]=\"weekday.full\">{{ weekday.label }}</abbr>\n </div>\n }\n </div>\n\n @for (week of gridWeeks(); track week[0].date) {\n <div role=\"row\" [class]=\"rowClass()\">\n @for (cell of week; track cell.date) {\n @if (cell.outside) {\n <!-- Outside days: hidden placeholders by default (geometry kept),\n muted and non-interactive under the showOutsideDays option. -->\n <div role=\"gridcell\" aria-hidden=\"true\" [class]=\"cell.cellClass\">\n @if (showOutside()) {\n <span [class]=\"outsideDayClass()\">{{ cell.day }}</span>\n }\n </div>\n } @else {\n <div\n role=\"gridcell\"\n [class]=\"cell.cellClass\"\n [attr.aria-selected]=\"cell.selected || cell.inBand ? true : null\"\n >\n <button\n type=\"button\"\n [class]=\"cell.dayClass\"\n [attr.data-date]=\"cell.date\"\n [tabindex]=\"cell.tabIndex\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-current]=\"cell.today ? 'date' : null\"\n [disabled]=\"cell.disabled || disabled()\"\n (click)=\"select(cell.date)\"\n (mouseenter)=\"onDayHover(cell.date)\"\n >\n {{ cell.day }}\n @if (cell.markers.length) {\n <span [class]=\"dotsClass()\">\n @for (marker of cell.markers; track $index) {\n <span data-dot [class]=\"dotClassFor(marker.variant)\"></span>\n }\n </span>\n }\n </button>\n </div>\n }\n }\n </div>\n }\n</div>\n\n<!-- Selections and range progress are otherwise silent for a screen reader. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n", dependencies: [{ kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3298
3369
|
}
|
|
3299
3370
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniCalendarComponent, decorators: [{
|
|
3300
3371
|
type: Component,
|
|
3301
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-calendar, Calendar', imports: [UniIconButtonComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'calendar' }], host: { '[class]': 'className()', '(focusout)': 'onHostFocusOut($event)' }, template: "<div [class]=\"navClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navPrevSymbol ?? 'chevron_left'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(-1)\"\n >\n Previous month\n </button>\n <!-- aria-live so PageUp/Down narrates the new month without refocusing. -->\n <div [class]=\"headingClass()\" [id]=\"headingId\" aria-live=\"polite\">{{ heading() }}</div>\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navNextSymbol ?? 'chevron_right'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(1)\"\n >\n Next month\n </button>\n</div>\n\n<!-- One tab stop: the roving tabindex lives on the day buttons, and the grid\n itself only relays their bubbling keys (same delegation as tag-input). -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n role=\"grid\"\n [class]=\"gridClass()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : headingId\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onGridKeydown($event)\"\n>\n <div role=\"row\" [class]=\"rowClass()\">\n @for (weekday of weekdays(); track weekday.full) {\n <div role=\"columnheader\" [class]=\"weekdayClass()\">\n <abbr [attr.title]=\"weekday.full\">{{ weekday.label }}</abbr>\n </div>\n }\n </div>\n\n @for (week of gridWeeks(); track week[0].date) {\n <div role=\"row\" [class]=\"rowClass()\">\n @for (cell of week; track cell.date) {\n @if (cell.outside) {\n <!-- Outside days: hidden placeholders by default (geometry kept),\n muted and non-interactive under the showOutsideDays option. -->\n <div role=\"gridcell\" aria-hidden=\"true\" [class]=\"cell.cellClass\">\n @if (showOutside()) {\n <span [class]=\"outsideDayClass()\">{{ cell.day }}</span>\n }\n </div>\n } @else {\n <div\n role=\"gridcell\"\n [class]=\"cell.cellClass\"\n [attr.aria-selected]=\"cell.selected || cell.inBand ? true : null\"\n >\n <button\n type=\"button\"\n [class]=\"cell.dayClass\"\n [attr.data-date]=\"cell.date\"\n [tabindex]=\"cell.tabIndex\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-current]=\"cell.today ? 'date' : null\"\n [disabled]=\"cell.disabled || disabled()\"\n (click)=\"select(cell.date)\"\n (mouseenter)=\"onDayHover(cell.date)\"\n >\n {{ cell.day }}\n @if (cell.markers.length) {\n <span [class]=\"dotsClass()\">\n @for (marker of cell.markers; track $index) {\n <span data-dot [class]=\"dotClassFor(marker.variant)\"></span>\n }\n </span>\n }\n </button>\n </div>\n }\n }\n </div>\n }\n</div>\n\n<!-- Selections and range progress are otherwise silent for a screen reader. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{
|
|
3372
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-calendar, Calendar', imports: [UniIconButtonComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'calendar' }], host: { '[class]': 'className()', '(focusout)': 'onHostFocusOut($event)' }, template: "<div [class]=\"navClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navPrevSymbol ?? 'chevron_left'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(-1)\"\n >\n Previous month\n </button>\n <!-- aria-live so PageUp/Down narrates the new month without refocusing. -->\n <div [class]=\"headingClass()\" [id]=\"headingId\" aria-live=\"polite\">{{ heading() }}</div>\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().navNextSymbol ?? 'chevron_right'\"\n [disable]=\"disabled()\"\n (click)=\"onNav(1)\"\n >\n Next month\n </button>\n</div>\n\n<!-- One tab stop: the roving tabindex lives on the day buttons, and the grid\n itself only relays their bubbling keys (same delegation as tag-input). -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n role=\"grid\"\n [class]=\"gridClass()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : headingId\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onGridKeydown($event)\"\n>\n <div role=\"row\" [class]=\"rowClass()\">\n @for (weekday of weekdays(); track weekday.full) {\n <div role=\"columnheader\" [class]=\"weekdayClass()\">\n <abbr [attr.title]=\"weekday.full\">{{ weekday.label }}</abbr>\n </div>\n }\n </div>\n\n @for (week of gridWeeks(); track week[0].date) {\n <div role=\"row\" [class]=\"rowClass()\">\n @for (cell of week; track cell.date) {\n @if (cell.outside) {\n <!-- Outside days: hidden placeholders by default (geometry kept),\n muted and non-interactive under the showOutsideDays option. -->\n <div role=\"gridcell\" aria-hidden=\"true\" [class]=\"cell.cellClass\">\n @if (showOutside()) {\n <span [class]=\"outsideDayClass()\">{{ cell.day }}</span>\n }\n </div>\n } @else {\n <div\n role=\"gridcell\"\n [class]=\"cell.cellClass\"\n [attr.aria-selected]=\"cell.selected || cell.inBand ? true : null\"\n >\n <button\n type=\"button\"\n [class]=\"cell.dayClass\"\n [attr.data-date]=\"cell.date\"\n [tabindex]=\"cell.tabIndex\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-current]=\"cell.today ? 'date' : null\"\n [disabled]=\"cell.disabled || disabled()\"\n (click)=\"select(cell.date)\"\n (mouseenter)=\"onDayHover(cell.date)\"\n >\n {{ cell.day }}\n @if (cell.markers.length) {\n <span [class]=\"dotsClass()\">\n @for (marker of cell.markers; track $index) {\n <span data-dot [class]=\"dotClassFor(marker.variant)\"></span>\n }\n </span>\n }\n </button>\n </div>\n }\n }\n </div>\n }\n</div>\n\n<!-- Selections and range progress are otherwise silent for a screen reader. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n" }]
|
|
3302
3373
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], month: [{ type: i0.Input, args: [{ isSignal: true, alias: "month", required: false }] }, { type: i0.Output, args: ["monthChange"] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], markers: [{ type: i0.Input, args: [{ isSignal: true, alias: "markers", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], weekStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStart", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }] } });
|
|
3303
3374
|
|
|
3304
3375
|
/**
|
|
@@ -3466,7 +3537,7 @@ class UniCalloutComponent extends BaseComponent {
|
|
|
3466
3537
|
clearAnchorName(target);
|
|
3467
3538
|
this.activeTarget.set(null);
|
|
3468
3539
|
this.scrimContent.set(false);
|
|
3469
|
-
}, this.
|
|
3540
|
+
}, this.motion().duration);
|
|
3470
3541
|
// The duet loop may have sent the user into the target on purpose — don't
|
|
3471
3542
|
// yank them back out of it.
|
|
3472
3543
|
if (!focusInTarget && this.prevFocus && document.contains(this.prevFocus)) {
|
|
@@ -3579,8 +3650,20 @@ class UniCalloutComponent extends BaseComponent {
|
|
|
3579
3650
|
scrimColor: options.scrimColor,
|
|
3580
3651
|
});
|
|
3581
3652
|
}, ...(ngDevMode ? [{ debugName: "spotlight" }] : /* istanbul ignore next */ []));
|
|
3582
|
-
|
|
3653
|
+
/**
|
|
3654
|
+
* Timing for the open/close fade and the teardown that follows it. The
|
|
3655
|
+
* deprecated `transitionMs` wins when a theme still sets it, so existing
|
|
3656
|
+
* themes keep their timing; otherwise the `motion` token decides.
|
|
3657
|
+
*/
|
|
3658
|
+
motion = computed(() => {
|
|
3583
3659
|
const options = this.componentOptions();
|
|
3660
|
+
const token = this.theme.motion(options.motion ?? 'panel');
|
|
3661
|
+
return options.transitionMs === undefined
|
|
3662
|
+
? token
|
|
3663
|
+
: { ...token, duration: options.transitionMs };
|
|
3664
|
+
}, ...(ngDevMode ? [{ debugName: "motion" }] : /* istanbul ignore next */ []));
|
|
3665
|
+
scrimClassName = computed(() => {
|
|
3666
|
+
const motion = this.motion();
|
|
3584
3667
|
return css({
|
|
3585
3668
|
position: 'fixed',
|
|
3586
3669
|
inset: 0,
|
|
@@ -3593,7 +3676,7 @@ class UniCalloutComponent extends BaseComponent {
|
|
|
3593
3676
|
overflow: 'visible',
|
|
3594
3677
|
pointerEvents: 'none',
|
|
3595
3678
|
'& > *': { position: 'fixed' },
|
|
3596
|
-
...discreteOverlayTransition(
|
|
3679
|
+
...discreteOverlayTransition(motion.duration, { opacity: 0 }, { opacity: 1 }, motion.easing),
|
|
3597
3680
|
});
|
|
3598
3681
|
}, ...(ngDevMode ? [{ debugName: "scrimClassName" }] : /* istanbul ignore next */ []));
|
|
3599
3682
|
windowClassName = computed(() => {
|
|
@@ -3615,6 +3698,7 @@ class UniCalloutComponent extends BaseComponent {
|
|
|
3615
3698
|
}), ...(ngDevMode ? [{ debugName: "fullCoverClassName" }] : /* istanbul ignore next */ []));
|
|
3616
3699
|
panelClassName = computed(() => {
|
|
3617
3700
|
const options = this.componentOptions();
|
|
3701
|
+
const motion = this.motion();
|
|
3618
3702
|
const anchored = this.activeTarget() !== null;
|
|
3619
3703
|
return css({
|
|
3620
3704
|
...this.theme.colorPair(options.color),
|
|
@@ -3633,7 +3717,7 @@ class UniCalloutComponent extends BaseComponent {
|
|
|
3633
3717
|
mainAxis: options.offset + options.spotlightPadding,
|
|
3634
3718
|
})
|
|
3635
3719
|
: {}),
|
|
3636
|
-
...discreteOverlayTransition(
|
|
3720
|
+
...discreteOverlayTransition(motion.duration, { opacity: 0, translate: '0 6px' }, { opacity: 1, translate: '0 0' }, motion.easing),
|
|
3637
3721
|
});
|
|
3638
3722
|
}, ...(ngDevMode ? [{ debugName: "panelClassName" }] : /* istanbul ignore next */ []));
|
|
3639
3723
|
headRowClassName = computed(() => {
|
|
@@ -3948,9 +4032,105 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
3948
4032
|
}], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }, { type: i0.Output, args: ["indeterminateChange"] }] } });
|
|
3949
4033
|
|
|
3950
4034
|
/**
|
|
3951
|
-
*
|
|
3952
|
-
*
|
|
3953
|
-
*
|
|
4035
|
+
* Whether the browser can keep a top-layer popup attached to its field.
|
|
4036
|
+
*
|
|
4037
|
+
* The top layer and anchor positioning must be adopted together, and support
|
|
4038
|
+
* for them does not arrive together: Safari shipped `popover` in 17 but
|
|
4039
|
+
* `position-anchor` only in 26. Promoting the popup without anchor support
|
|
4040
|
+
* would strand it — a top-layer element has no positioned ancestor, so the
|
|
4041
|
+
* fallback's `position: absolute; top: 100%` would resolve against the
|
|
4042
|
+
* viewport and drop the list a full screen height down the page. So the
|
|
4043
|
+
* `popover` attribute is gated on this too, not just the anchored CSS.
|
|
4044
|
+
*
|
|
4045
|
+
* Undefined `CSS` (jsdom) reads as unsupported, which is also what keeps the
|
|
4046
|
+
* popup in the normal flow — and the component specs unchanged — under test.
|
|
4047
|
+
*/
|
|
4048
|
+
const supportsAnchoredPopup = () => typeof CSS !== 'undefined' && CSS.supports?.('position-anchor: --a') === true;
|
|
4049
|
+
/** `popover` attribute value for a listbox popup, or null where unsupported.
|
|
4050
|
+
Always `manual`: these controls already own dismissal (focusout, Escape,
|
|
4051
|
+
commit), and `auto`'s light-dismiss fires on pointerdown outside the
|
|
4052
|
+
popup — which includes their own field, closing the list behind the
|
|
4053
|
+
component's back on every click into the input. */
|
|
4054
|
+
const listboxPopupAttr = () => supportsAnchoredPopup() ? 'manual' : null;
|
|
4055
|
+
/**
|
|
4056
|
+
* A document-unique `anchor-name`, plus the style fragment that puts it on the
|
|
4057
|
+
* field wrapper. Spread `style` into the wrapper's `css()` and pass `name` to
|
|
4058
|
+
* {@link listboxPopupStyles}.
|
|
4059
|
+
*/
|
|
4060
|
+
function newListboxAnchor() {
|
|
4061
|
+
const name = newAnchorName();
|
|
4062
|
+
return { name, style: { anchorName: name } };
|
|
4063
|
+
}
|
|
4064
|
+
/**
|
|
4065
|
+
* Shows the popup in the top layer as soon as it renders, and scales its
|
|
4066
|
+
* entry animation out of the edge it actually opened from.
|
|
4067
|
+
*
|
|
4068
|
+
* The popups are `@if`-rendered, and a `popover` element is `display: none`
|
|
4069
|
+
* until `showPopover()` runs — so appearing in the DOM is not enough. Runs on
|
|
4070
|
+
* every render pass; `showPopover()` on an already-open popup throws, which is
|
|
4071
|
+
* the cheapest way to ask "is it open?".
|
|
4072
|
+
*
|
|
4073
|
+
* The origin is measured rather than assumed: `position-try-fallbacks` may
|
|
4074
|
+
* have flipped the popup above its field near the bottom of the viewport, and
|
|
4075
|
+
* the static `top center` would then grow it from the wrong edge. Measuring
|
|
4076
|
+
* forces layout, so it lands before the first frame of the transition.
|
|
4077
|
+
*
|
|
4078
|
+
* Call from an injection context (a field initializer or the constructor);
|
|
4079
|
+
* the component's host element is the anchor.
|
|
4080
|
+
*/
|
|
4081
|
+
function promoteListboxPopup(ref) {
|
|
4082
|
+
const anchor = inject(ElementRef).nativeElement;
|
|
4083
|
+
afterRenderEffect(() => {
|
|
4084
|
+
const element = ref()?.nativeElement;
|
|
4085
|
+
// The attribute, not the `popover` IDL property: the property is what the
|
|
4086
|
+
// gate already decided, and jsdom does not reflect it.
|
|
4087
|
+
if (!element?.isConnected || !element.hasAttribute('popover'))
|
|
4088
|
+
return;
|
|
4089
|
+
try {
|
|
4090
|
+
element.showPopover();
|
|
4091
|
+
}
|
|
4092
|
+
catch {
|
|
4093
|
+
return; // Already open — its origin was set when it opened.
|
|
4094
|
+
}
|
|
4095
|
+
const origin = transformOriginFor(element.getBoundingClientRect(), anchor.getBoundingClientRect());
|
|
4096
|
+
if (origin)
|
|
4097
|
+
element.style.transformOrigin = origin;
|
|
4098
|
+
});
|
|
4099
|
+
}
|
|
4100
|
+
/**
|
|
4101
|
+
* The anchored half: the popup in the top layer, tracked to its field by the
|
|
4102
|
+
* browser with no scroll or resize listeners. This is what lets the list
|
|
4103
|
+
* escape an `overflow: hidden` ancestor, which the in-flow fallback below
|
|
4104
|
+
* cannot do.
|
|
4105
|
+
*
|
|
4106
|
+
* `anchor-size(width)` matches the field's width the way `left: 0; right: 0`
|
|
4107
|
+
* did in flow. Only the block flip is offered: the popup is as wide as its
|
|
4108
|
+
* own field, so flipping it inline would only slide it off that field.
|
|
4109
|
+
*
|
|
4110
|
+
* `border: none` drops the UA's `[popover]` border. Its `background-color:
|
|
4111
|
+
* Canvas` needs no reset — the base rules' `colorPair` beats it on origin
|
|
4112
|
+
* alone — and must not get one: `background` is a shorthand, so resetting it
|
|
4113
|
+
* here would erase that painted surface and leave the list transparent.
|
|
4114
|
+
*
|
|
4115
|
+
* `border-box` keeps the popup exactly as wide as its field: `anchor-size`
|
|
4116
|
+
* yields the anchor's border-box width, which the base rules' padding would
|
|
4117
|
+
* otherwise widen by 8px.
|
|
4118
|
+
*/
|
|
4119
|
+
const anchoredPopupStyles = (anchor, motion) => ({
|
|
4120
|
+
...anchorStyles(anchor, 'bottom-start', { mainAxis: 4 }),
|
|
4121
|
+
positionTryFallbacks: 'flip-block',
|
|
4122
|
+
width: 'anchor-size(width)',
|
|
4123
|
+
boxSizing: 'border-box',
|
|
4124
|
+
border: 'none',
|
|
4125
|
+
// Grows out of the field's bottom edge; corrected after measuring when the
|
|
4126
|
+
// browser flips the popup above instead (see promoteListboxPopup).
|
|
4127
|
+
transformOrigin: 'top center',
|
|
4128
|
+
...motionSafe(discreteOverlayTransition(motion.duration, { opacity: 0, transform: `scale(${motion.scale ?? 1})` }, { opacity: 1, transform: 'scale(1)' }, motion.easing)),
|
|
4129
|
+
});
|
|
4130
|
+
/**
|
|
4131
|
+
* Style block for the popup behind every `ListboxNavigation` consumer: a
|
|
4132
|
+
* `ul[role="listbox"]` under its field wrapper, with the shared option chrome
|
|
4133
|
+
* and active/hover highlight.
|
|
3954
4134
|
*
|
|
3955
4135
|
* Extracted because four components (`uni-search-input`, `uni-tag-input`,
|
|
3956
4136
|
* `uni-time-input`, `uni-combobox`) carried hand-rolled copies, and the parts
|
|
@@ -3958,11 +4138,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
3958
4138
|
* trio, and the `activeColor` pair that themes re-point when their container
|
|
3959
4139
|
* tokens don't contrast (see the Wellsourced overrides).
|
|
3960
4140
|
*
|
|
4141
|
+
* Pass `anchor` (from {@link newListboxAnchor}) to get the top-layer
|
|
4142
|
+
* positioning where the browser supports it. Without it — or on a browser that
|
|
4143
|
+
* lacks anchor positioning — the popup stays absolutely positioned under a
|
|
4144
|
+
* `position: relative` wrapper, which clips inside `overflow: hidden`
|
|
4145
|
+
* ancestors but at least stays on its field.
|
|
4146
|
+
*
|
|
3961
4147
|
* Compose extras with the array form — `css([listboxPopupStyles(…), {…}])` —
|
|
3962
4148
|
* so a component's own `& [role="option"]` block cascades after this one
|
|
3963
4149
|
* instead of replacing it (an object spread would overwrite the key).
|
|
3964
4150
|
*/
|
|
3965
|
-
const listboxPopupStyles = (theme, options, { maxHeight = 280 } = {}) => ({
|
|
4151
|
+
const listboxPopupStyles = (theme, options, { maxHeight = 280, anchor } = {}) => ({
|
|
3966
4152
|
position: 'absolute',
|
|
3967
4153
|
top: '100%',
|
|
3968
4154
|
left: 0,
|
|
@@ -3985,6 +4171,10 @@ const listboxPopupStyles = (theme, options, { maxHeight = 280 } = {}) => ({
|
|
|
3985
4171
|
...theme.colorPair((options.activeColor ?? 'primary-container')),
|
|
3986
4172
|
},
|
|
3987
4173
|
},
|
|
4174
|
+
// Last, so the anchored rules win over the in-flow ones they replace.
|
|
4175
|
+
...(anchor
|
|
4176
|
+
? { '@supports (position-anchor: --a)': anchoredPopupStyles(anchor, theme.motion(options.motion)) }
|
|
4177
|
+
: {}),
|
|
3988
4178
|
});
|
|
3989
4179
|
|
|
3990
4180
|
class UniInputBoxComponent extends BaseComponent {
|
|
@@ -4107,12 +4297,18 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4107
4297
|
listRef = viewChild('listbox', ...(ngDevMode ? [{ debugName: "listRef" }] : /* istanbul ignore next */ []));
|
|
4108
4298
|
/** Cancelled on destroy — a late tick would emit on a destroyed OutputRef. */
|
|
4109
4299
|
queryTimer;
|
|
4300
|
+
/** Ties the popup to the field so the browser tracks it in the top layer. */
|
|
4301
|
+
anchor = newListboxAnchor();
|
|
4302
|
+
/** `manual` where the top layer is usable, else null — see the popup helper. */
|
|
4303
|
+
popupAttr = listboxPopupAttr();
|
|
4110
4304
|
constructor() {
|
|
4111
4305
|
super();
|
|
4112
4306
|
inject(DestroyRef).onDestroy(() => clearTimeout(this.queryTimer));
|
|
4307
|
+
promoteListboxPopup(this.listRef);
|
|
4113
4308
|
}
|
|
4114
4309
|
srOnly = css(visuallyHidden);
|
|
4115
|
-
|
|
4310
|
+
/** Commits, clears and refusals are otherwise silent to a screen reader. */
|
|
4311
|
+
announcer = createAnnouncer();
|
|
4116
4312
|
/** null → the field shows the committed label; a string is an uncommitted draft. */
|
|
4117
4313
|
draft = signal(null, ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
4118
4314
|
/**
|
|
@@ -4163,7 +4359,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4163
4359
|
this.draft.set(null);
|
|
4164
4360
|
this.closeList();
|
|
4165
4361
|
this.setFieldText(this.displayValue());
|
|
4166
|
-
this.announce(`${option.label} selected.`);
|
|
4362
|
+
this.announcer.announce(`${option.label} selected.`);
|
|
4167
4363
|
this.selected.emit(option);
|
|
4168
4364
|
return true;
|
|
4169
4365
|
}
|
|
@@ -4172,7 +4368,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4172
4368
|
this.draft.set(null);
|
|
4173
4369
|
this.closeList();
|
|
4174
4370
|
this.setFieldText('');
|
|
4175
|
-
this.announce('Selection cleared.');
|
|
4371
|
+
this.announcer.announce('Selection cleared.');
|
|
4176
4372
|
this.cleared.emit();
|
|
4177
4373
|
this.inputRef().nativeElement.focus();
|
|
4178
4374
|
}
|
|
@@ -4200,7 +4396,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4200
4396
|
// clearable fields may null the model this way.
|
|
4201
4397
|
if (this.clearable() && this.value() !== null && !enterOnly) {
|
|
4202
4398
|
this.value.set(null);
|
|
4203
|
-
this.announce('Selection cleared.');
|
|
4399
|
+
this.announcer.announce('Selection cleared.');
|
|
4204
4400
|
this.cleared.emit();
|
|
4205
4401
|
}
|
|
4206
4402
|
this.draft.set(null);
|
|
@@ -4231,7 +4427,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4231
4427
|
reject() {
|
|
4232
4428
|
const query = this.revertDraft();
|
|
4233
4429
|
if (query) {
|
|
4234
|
-
this.announce(`No match for “${query}”.`);
|
|
4430
|
+
this.announcer.announce(`No match for “${query}”.`);
|
|
4235
4431
|
this.rejected.emit({ query });
|
|
4236
4432
|
}
|
|
4237
4433
|
}
|
|
@@ -4267,12 +4463,9 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4267
4463
|
this.scrollToActive();
|
|
4268
4464
|
return;
|
|
4269
4465
|
}
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
this.scrollToActive();
|
|
4274
|
-
return;
|
|
4275
|
-
}
|
|
4466
|
+
// Home/End are deliberately absent: they belong to the caret, even with
|
|
4467
|
+
// the list open (APG's editable-combobox pattern). ArrowUp on a closed
|
|
4468
|
+
// list already lands on the last option, so nothing is lost.
|
|
4276
4469
|
switch (event.key) {
|
|
4277
4470
|
case 'Enter':
|
|
4278
4471
|
// Never submits a form while the list is open.
|
|
@@ -4280,7 +4473,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4280
4473
|
event.preventDefault();
|
|
4281
4474
|
if (!this.resolveDraft(true)) {
|
|
4282
4475
|
const count = this.filteredIndices().length;
|
|
4283
|
-
this.announce(count === 0 ? `${this.emptyText()}.` : `${count} results. Use the arrow keys.`);
|
|
4476
|
+
this.announcer.announce(count === 0 ? `${this.emptyText()}.` : `${count} results. Use the arrow keys.`);
|
|
4284
4477
|
}
|
|
4285
4478
|
return;
|
|
4286
4479
|
case 'Escape':
|
|
@@ -4312,7 +4505,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4312
4505
|
// Filtering is otherwise silent to a screen reader.
|
|
4313
4506
|
if (this.filterLocally() && text !== '') {
|
|
4314
4507
|
const count = this.filteredIndices().length;
|
|
4315
|
-
this.announce(count === 0 ? `${this.emptyText()}.` : `${count} result${count === 1 ? '' : 's'}.`);
|
|
4508
|
+
this.announcer.announce(count === 0 ? `${this.emptyText()}.` : `${count} result${count === 1 ? '' : 's'}.`);
|
|
4316
4509
|
}
|
|
4317
4510
|
}, this.debounceTime());
|
|
4318
4511
|
}
|
|
@@ -4380,12 +4573,8 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4380
4573
|
if (element)
|
|
4381
4574
|
element.value = text;
|
|
4382
4575
|
}
|
|
4383
|
-
announce(message) {
|
|
4384
|
-
// Re-announce identical text by breaking the string equality.
|
|
4385
|
-
this.announcement.set(this.announcement() === message ? `${message} ` : message);
|
|
4386
|
-
}
|
|
4387
4576
|
// --- Styling ----------------------------------------------------------------
|
|
4388
|
-
className = computed(() => css({ display: 'block', position: 'relative', width: this.width() }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
4577
|
+
className = computed(() => css({ display: 'block', position: 'relative', width: this.width(), ...this.anchor.style }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
4389
4578
|
rowClass = computed(() => css({ display: 'flex', alignItems: 'center', flex: 1, width: '100%', minWidth: 0 }), ...(ngDevMode ? [{ debugName: "rowClass" }] : /* istanbul ignore next */ []));
|
|
4390
4579
|
inputClass = computed(() => css({
|
|
4391
4580
|
flex: 1,
|
|
@@ -4421,6 +4610,7 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4421
4610
|
// A scroll height, never a cap: a closed-set control must not render a
|
|
4422
4611
|
// reachable-by-keyboard-only subset (contrast searchInput.maxSuggestions).
|
|
4423
4612
|
maxHeight: (options.maxVisibleOptions ?? 8) * 36 + 8,
|
|
4613
|
+
anchor: this.anchor.name,
|
|
4424
4614
|
}),
|
|
4425
4615
|
{
|
|
4426
4616
|
'& [role="option"]': {
|
|
@@ -4459,11 +4649,11 @@ class UniComboboxComponent extends BaseComponent {
|
|
|
4459
4649
|
]);
|
|
4460
4650
|
}, ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
|
|
4461
4651
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniComboboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4462
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniComboboxComponent, isStandalone: true, selector: "uni-combobox, Combobox", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, filterLocally: { classPropertyName: "filterLocally", publicName: "filterLocally", isSignal: true, isRequired: false, transformFunction: null }, filterWith: { classPropertyName: "filterWith", publicName: "filterWith", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", query: "query", selected: "selected", cleared: "cleared", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'combobox' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "listRef", first: true, predicate: ["listbox"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n resolves only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\">\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"placeholder() ?? ''\"\n [value]=\"displayValue()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"popupOpen()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput()\"\n (click)=\"onFieldClick()\"\n />\n @if (clearable() && value() !== null && !disabled()) {\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [iconName]=\"componentOptions().clearIcon ?? 'close'\"\n (click)=\"clear()\"\n >\n Clear {{ label() }}\n </button>\n }\n <!-- Pointer-only: keyboard has ArrowDown, the input announces expanded. -->\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"toggleClass()\"\n [disabled]=\"disabled()\"\n (mousedown)=\"onToggleMousedown($event)\"\n >\n <uni-icon [name]=\"componentOptions().toggleIcon ?? 'chevronDown'\" size=\"20\" />\n </button>\n </div>\n </uni-input-box>\n\n @if (popupOpen()) {\n <ul
|
|
4652
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniComboboxComponent, isStandalone: true, selector: "uni-combobox, Combobox", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, filterLocally: { classPropertyName: "filterLocally", publicName: "filterLocally", isSignal: true, isRequired: false, transformFunction: null }, filterWith: { classPropertyName: "filterWith", publicName: "filterWith", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", query: "query", selected: "selected", cleared: "cleared", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'combobox' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "listRef", first: true, predicate: ["listbox"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n resolves only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\">\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"placeholder() ?? ''\"\n [value]=\"displayValue()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"popupOpen()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput()\"\n (click)=\"onFieldClick()\"\n />\n @if (clearable() && value() !== null && !disabled()) {\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [iconName]=\"componentOptions().clearIcon ?? 'close'\"\n (click)=\"clear()\"\n >\n Clear {{ label() }}\n </button>\n }\n <!-- Pointer-only: keyboard has ArrowDown, the input announces expanded. -->\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"toggleClass()\"\n [disabled]=\"disabled()\"\n (mousedown)=\"onToggleMousedown($event)\"\n >\n <uni-icon [name]=\"componentOptions().toggleIcon ?? 'chevronDown'\" size=\"20\" />\n </button>\n </div>\n </uni-input-box>\n\n @if (popupOpen()) {\n <ul\n #listbox\n [id]=\"list.listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @if (filteredIndices().length === 0) {\n <!-- Non-interactive: not an option, not navigable, no id. -->\n <li class=\"empty\">{{ emptyText() }}</li>\n } @else {\n @for (optIndex of filteredIndices(); track optIndex; let i = $index) {\n <!-- aria-selected marks the *committed* option; the active one is\n carried by aria-activedescendant \u2014 they are different facts. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"optIndex === committedIndex()\"\n [attr.aria-disabled]=\"options()[optIndex].disabled ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onOptionClick(optIndex)\"\n >\n <span class=\"check\" aria-hidden=\"true\">\n @if (optIndex === committedIndex()) {\n <uni-icon [name]=\"componentOptions().selectedIcon ?? 'check'\" size=\"18\" />\n }\n </span>\n <span class=\"text\">\n <span class=\"option-label\">{{ options()[optIndex].label }}</span>\n @if (options()[optIndex].description) {\n <span class=\"desc\">{{ options()[optIndex].description }}</span>\n }\n </span>\n </li>\n }\n }\n </ul>\n }\n\n <!-- Commits, clears, refusals and result counts are otherwise silent. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n", dependencies: [{ kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }, { kind: "component", type: UniIconComponent, selector: "uni-icon", inputs: ["color", "name", "size"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4463
4653
|
}
|
|
4464
4654
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniComboboxComponent, decorators: [{
|
|
4465
4655
|
type: Component,
|
|
4466
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-combobox, Combobox', imports: [UniIconButtonComponent, UniIconComponent, UniInputBoxComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'combobox' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n resolves only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\">\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"placeholder() ?? ''\"\n [value]=\"displayValue()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"popupOpen()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput()\"\n (click)=\"onFieldClick()\"\n />\n @if (clearable() && value() !== null && !disabled()) {\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [iconName]=\"componentOptions().clearIcon ?? 'close'\"\n (click)=\"clear()\"\n >\n Clear {{ label() }}\n </button>\n }\n <!-- Pointer-only: keyboard has ArrowDown, the input announces expanded. -->\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"toggleClass()\"\n [disabled]=\"disabled()\"\n (mousedown)=\"onToggleMousedown($event)\"\n >\n <uni-icon [name]=\"componentOptions().toggleIcon ?? 'chevronDown'\" size=\"20\" />\n </button>\n </div>\n </uni-input-box>\n\n @if (popupOpen()) {\n <ul
|
|
4656
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-combobox, Combobox', imports: [UniIconButtonComponent, UniIconComponent, UniInputBoxComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'combobox' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n resolves only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\">\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"placeholder() ?? ''\"\n [value]=\"displayValue()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"popupOpen()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onKeydown($event)\"\n (input)=\"onInput()\"\n (click)=\"onFieldClick()\"\n />\n @if (clearable() && value() !== null && !disabled()) {\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n [iconName]=\"componentOptions().clearIcon ?? 'close'\"\n (click)=\"clear()\"\n >\n Clear {{ label() }}\n </button>\n }\n <!-- Pointer-only: keyboard has ArrowDown, the input announces expanded. -->\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"toggleClass()\"\n [disabled]=\"disabled()\"\n (mousedown)=\"onToggleMousedown($event)\"\n >\n <uni-icon [name]=\"componentOptions().toggleIcon ?? 'chevronDown'\" size=\"20\" />\n </button>\n </div>\n </uni-input-box>\n\n @if (popupOpen()) {\n <ul\n #listbox\n [id]=\"list.listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @if (filteredIndices().length === 0) {\n <!-- Non-interactive: not an option, not navigable, no id. -->\n <li class=\"empty\">{{ emptyText() }}</li>\n } @else {\n @for (optIndex of filteredIndices(); track optIndex; let i = $index) {\n <!-- aria-selected marks the *committed* option; the active one is\n carried by aria-activedescendant \u2014 they are different facts. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"optIndex === committedIndex()\"\n [attr.aria-disabled]=\"options()[optIndex].disabled ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onOptionClick(optIndex)\"\n >\n <span class=\"check\" aria-hidden=\"true\">\n @if (optIndex === committedIndex()) {\n <uni-icon [name]=\"componentOptions().selectedIcon ?? 'check'\" size=\"18\" />\n }\n </span>\n <span class=\"text\">\n <span class=\"option-label\">{{ options()[optIndex].label }}</span>\n @if (options()[optIndex].description) {\n <span class=\"desc\">{{ options()[optIndex].description }}</span>\n }\n </span>\n </li>\n }\n }\n </ul>\n }\n\n <!-- Commits, clears, refusals and result counts are otherwise silent. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n" }]
|
|
4467
4657
|
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], filterLocally: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLocally", required: false }] }], filterWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterWith", required: false }] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], query: [{ type: i0.Output, args: ["query"] }], selected: [{ type: i0.Output, args: ["selected"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], rejected: [{ type: i0.Output, args: ["rejected"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], listRef: [{ type: i0.ViewChild, args: ['listbox', { isSignal: true }] }] } });
|
|
4468
4658
|
|
|
4469
4659
|
class UniDataSearchComponent extends BaseComponent {
|
|
@@ -4947,7 +5137,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
4947
5137
|
|
|
4948
5138
|
class UniDropdownComponent extends BaseComponent {
|
|
4949
5139
|
renderer = inject(Renderer2);
|
|
4950
|
-
delay = 100;
|
|
4951
5140
|
// Reactively track visibility status using Signals
|
|
4952
5141
|
showing = signal(false, ...(ngDevMode ? [{ debugName: "showing" }] : /* istanbul ignore next */ []));
|
|
4953
5142
|
trigger = input.required(...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
|
|
@@ -4981,25 +5170,9 @@ class UniDropdownComponent extends BaseComponent {
|
|
|
4981
5170
|
get _dropdown() {
|
|
4982
5171
|
return this.dropdownRef.nativeElement;
|
|
4983
5172
|
}
|
|
4984
|
-
// Pre-measure default only: the requested placement's corner. The real
|
|
4985
|
-
// origin is measured per toggle (syncTransformOrigin), because
|
|
4986
|
-
// position-try fallbacks may have flipped the panel.
|
|
4987
|
-
transformOriginMap = {
|
|
4988
|
-
top: 'bottom center',
|
|
4989
|
-
right: 'center left',
|
|
4990
|
-
bottom: 'top center',
|
|
4991
|
-
left: 'center right',
|
|
4992
|
-
'top-start': 'bottom left',
|
|
4993
|
-
'top-end': 'bottom right',
|
|
4994
|
-
'right-start': 'top left',
|
|
4995
|
-
'right-end': 'bottom left',
|
|
4996
|
-
'bottom-start': 'top left',
|
|
4997
|
-
'bottom-end': 'top right',
|
|
4998
|
-
'left-start': 'top right',
|
|
4999
|
-
'left-end': 'bottom right',
|
|
5000
|
-
};
|
|
5001
5173
|
dropdownClass = computed(() => {
|
|
5002
5174
|
const currentPlacement = this.placement();
|
|
5175
|
+
const motion = this.theme.motion(this.componentOptions().motion);
|
|
5003
5176
|
return css([
|
|
5004
5177
|
{
|
|
5005
5178
|
// Reset browser agent default popover styles
|
|
@@ -5011,27 +5184,14 @@ class UniDropdownComponent extends BaseComponent {
|
|
|
5011
5184
|
// Native anchor positioning: the browser keeps the panel attached to
|
|
5012
5185
|
// the trigger (no scroll/resize listeners needed)
|
|
5013
5186
|
...anchorStyles(this.anchorName, currentPlacement, this.offset()),
|
|
5014
|
-
//
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
//
|
|
5020
|
-
|
|
5021
|
-
transform:
|
|
5022
|
-
transformOrigin: this.transformOriginMap[currentPlacement],
|
|
5023
|
-
// 3. Active state styling controlled via the native browser pseudo-class
|
|
5024
|
-
['&:popover-open']: {
|
|
5025
|
-
opacity: 1,
|
|
5026
|
-
transform: 'scale(1)',
|
|
5027
|
-
},
|
|
5028
|
-
// 4. Starting-style rules what properties animate *from* when transitioning in
|
|
5029
|
-
['@starting-style']: {
|
|
5030
|
-
['&:popover-open']: {
|
|
5031
|
-
opacity: 0,
|
|
5032
|
-
transform: 'scale(0.8)',
|
|
5033
|
-
},
|
|
5034
|
-
},
|
|
5187
|
+
// Grows out of the corner touching the trigger. A pre-measure default
|
|
5188
|
+
// only: the real origin is measured per toggle (syncTransformOrigin),
|
|
5189
|
+
// because position-try fallbacks may have flipped the panel.
|
|
5190
|
+
transformOrigin: TRANSFORM_ORIGINS[currentPlacement],
|
|
5191
|
+
// Scale-and-fade into and out of the top layer, including the
|
|
5192
|
+
// `@starting-style` the entry transition runs from. Timing comes from
|
|
5193
|
+
// the theme's motion scale, so retiming every overlay is one edit.
|
|
5194
|
+
...discreteOverlayTransition(motion.duration, { opacity: 0, transform: `scale(${motion.scale ?? 1})` }, { opacity: 1, transform: 'scale(1)' }, motion.easing),
|
|
5035
5195
|
},
|
|
5036
5196
|
]);
|
|
5037
5197
|
}, ...(ngDevMode ? [{ debugName: "dropdownClass" }] : /* istanbul ignore next */ []));
|
|
@@ -5046,7 +5206,7 @@ class UniDropdownComponent extends BaseComponent {
|
|
|
5046
5206
|
this.toggleDropdown();
|
|
5047
5207
|
});
|
|
5048
5208
|
// Anchor the popover panel to the trigger element
|
|
5049
|
-
|
|
5209
|
+
setAnchorName(this._trigger, this.anchorName);
|
|
5050
5210
|
// Wire the ARIA popup contract onto the focusable trigger element
|
|
5051
5211
|
const focusTarget = this._focusTarget;
|
|
5052
5212
|
this.renderer.setAttribute(focusTarget, 'aria-expanded', 'false');
|
|
@@ -5056,7 +5216,7 @@ class UniDropdownComponent extends BaseComponent {
|
|
|
5056
5216
|
}
|
|
5057
5217
|
// Sync state if user invokes light-dismiss via outside click or Escape key
|
|
5058
5218
|
this.renderer.listen(this._dropdown, 'toggle', (event) => {
|
|
5059
|
-
const isOpened = event
|
|
5219
|
+
const isOpened = isToggleOpen(event);
|
|
5060
5220
|
// Both edges: on open so the entry scale grows out of the trigger, and
|
|
5061
5221
|
// on close-start so a panel the browser flipped while open (scroll near
|
|
5062
5222
|
// a viewport edge) still collapses back toward the trigger.
|
|
@@ -5068,14 +5228,15 @@ class UniDropdownComponent extends BaseComponent {
|
|
|
5068
5228
|
}
|
|
5069
5229
|
else {
|
|
5070
5230
|
this.dropdownHiding.emit(true);
|
|
5071
|
-
|
|
5231
|
+
// Keyboard users are never stranded when the top layer closes (WCAG 2.4.3).
|
|
5232
|
+
restoreOverlayFocus(this._dropdown, this._focusTarget);
|
|
5072
5233
|
}
|
|
5073
5234
|
});
|
|
5074
5235
|
}
|
|
5075
5236
|
/**
|
|
5076
5237
|
* Scale the open/close animation from the corner touching the trigger,
|
|
5077
5238
|
* wherever the browser actually placed the panel. The static
|
|
5078
|
-
* `
|
|
5239
|
+
* `TRANSFORM_ORIGINS` entry covers only the *requested* placement; with
|
|
5079
5240
|
* `position-try-fallbacks` the panel may have flipped at a viewport edge,
|
|
5080
5241
|
* and a `bottom-end` picker rendered above its field would otherwise still
|
|
5081
5242
|
* animate from the top-right corner.
|
|
@@ -5085,17 +5246,6 @@ class UniDropdownComponent extends BaseComponent {
|
|
|
5085
5246
|
if (origin)
|
|
5086
5247
|
this.renderer.setStyle(this._dropdown, 'transform-origin', origin);
|
|
5087
5248
|
}
|
|
5088
|
-
/**
|
|
5089
|
-
* Returns focus to the trigger when the popover closes while focus was
|
|
5090
|
-
* inside it (or was dropped on <body> by the top layer closing), so
|
|
5091
|
-
* keyboard users are never stranded (WCAG 2.4.3).
|
|
5092
|
-
*/
|
|
5093
|
-
restoreFocus() {
|
|
5094
|
-
const active = document.activeElement;
|
|
5095
|
-
if (active === document.body || (active && this._dropdown.contains(active))) {
|
|
5096
|
-
this._focusTarget.focus();
|
|
5097
|
-
}
|
|
5098
|
-
}
|
|
5099
5249
|
toggleDropdown() {
|
|
5100
5250
|
if (this.showing()) {
|
|
5101
5251
|
this._dropdown.hidePopover();
|
|
@@ -5216,7 +5366,8 @@ class UniDateInputComponent extends BaseComponent {
|
|
|
5216
5366
|
srOnly = css(visuallyHidden);
|
|
5217
5367
|
/** A refused commit — styles the field and sets aria-invalid until edited. */
|
|
5218
5368
|
draftInvalid = signal(false, ...(ngDevMode ? [{ debugName: "draftInvalid" }] : /* istanbul ignore next */ []));
|
|
5219
|
-
|
|
5369
|
+
/** Commits, clears and refusals are otherwise silent to a screen reader. */
|
|
5370
|
+
announcer = createAnnouncer();
|
|
5220
5371
|
toggleElement = computed(() => this.toggleRef()?.nativeElement, ...(ngDevMode ? [{ debugName: "toggleElement" }] : /* istanbul ignore next */ []));
|
|
5221
5372
|
popupOpen = computed(() => this.dropdown()?.showing() ?? false, ...(ngDevMode ? [{ debugName: "popupOpen" }] : /* istanbul ignore next */ []));
|
|
5222
5373
|
resolvedLocale = computed(() => this.locale() ?? (document.documentElement.lang || navigator.language || 'en-US'), ...(ngDevMode ? [{ debugName: "resolvedLocale" }] : /* istanbul ignore next */ []));
|
|
@@ -5247,7 +5398,7 @@ class UniDateInputComponent extends BaseComponent {
|
|
|
5247
5398
|
this.draftInvalid.set(false);
|
|
5248
5399
|
this.setFieldText(this.displayText());
|
|
5249
5400
|
if (!silent)
|
|
5250
|
-
this.announce(date ? `${this.fullDate(date)}.` : 'Date cleared.');
|
|
5401
|
+
this.announcer.announce(date ? `${this.fullDate(date)}.` : 'Date cleared.');
|
|
5251
5402
|
}
|
|
5252
5403
|
refuse(raw, reason) {
|
|
5253
5404
|
this.draftInvalid.set(true);
|
|
@@ -5256,7 +5407,7 @@ class UniDateInputComponent extends BaseComponent {
|
|
|
5256
5407
|
'out-of-range': `${raw} is outside the allowed dates.`,
|
|
5257
5408
|
disabled: `${raw} isn't available.`,
|
|
5258
5409
|
}[reason];
|
|
5259
|
-
this.announce(message);
|
|
5410
|
+
this.announcer.announce(message);
|
|
5260
5411
|
this.rejected.emit({ raw, reason });
|
|
5261
5412
|
}
|
|
5262
5413
|
commit(raw) {
|
|
@@ -5404,9 +5555,6 @@ class UniDateInputComponent extends BaseComponent {
|
|
|
5404
5555
|
if (element)
|
|
5405
5556
|
element.value = text;
|
|
5406
5557
|
}
|
|
5407
|
-
announce(message) {
|
|
5408
|
-
this.announcement.set(this.announcement() === message ? `${message} ` : message);
|
|
5409
|
-
}
|
|
5410
5558
|
// --- Styling -----------------------------------------------------------------------
|
|
5411
5559
|
className = computed(() => css({ display: 'block', position: 'relative' }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
5412
5560
|
rowClass = computed(() => css({ display: 'flex', alignItems: 'center', flex: 1, width: '100%', minWidth: 0 }), ...(ngDevMode ? [{ debugName: "rowClass" }] : /* istanbul ignore next */ []));
|
|
@@ -5440,7 +5588,7 @@ class UniDateInputComponent extends BaseComponent {
|
|
|
5440
5588
|
]);
|
|
5441
5589
|
}, ...(ngDevMode ? [{ debugName: "embeddedClass" }] : /* istanbul ignore next */ []));
|
|
5442
5590
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDateInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5443
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniDateInputComponent, isStandalone: true, selector: "uni-date-input, DateInput", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, displayFormat: { classPropertyName: "displayFormat", publicName: "displayFormat", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, parse: { classPropertyName: "parse", publicName: "parse", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, markers: { classPropertyName: "markers", publicName: "markers", isSignal: true, isRequired: false, transformFunction: null }, weekStart: { classPropertyName: "weekStart", publicName: "weekStart", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", opened: "opened", closed: "closed", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'dateInput' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "toggleRef", first: true, predicate: ["toggle"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "popupRef", first: true, predicate: ["popupDialog"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: UniDropdownComponent, descendants: true, isSignal: true }, { propertyName: "calendar", first: true, predicate: UniCalendarComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so commits happen only when focus\n leaves the whole field, not while moving into the popup. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <!-- The dropdown wires aria-haspopup/aria-expanded/aria-controls onto\n this button; its name tracks the value (\"Change date, \u2026\"). -->\n <button\n #toggle\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'calendar_month'\"\n [disable]=\"disabled()\"\n >\n {{ toggleLabel() }}\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (toggleElement()) {\n <uni-dropdown\n [trigger]=\"toggleElement()!\"\n ariaHasPopup=\"dialog\"\n placement=\"bottom-end\"\n [color]=\"componentOptions().popupColor ?? 'primary-surface'\"\n [shadow]=\"componentOptions().popupShadow ?? 'menu'\"\n [borderRadius]=\"componentOptions().popupBorderRadius ?? 'xs'\"\n paddingVertical=\"xs\"\n paddingHorizontal=\"xs\"\n (dropdownShowing)=\"onPopupShowing()\"\n (dropdownHiding)=\"onPopupHiding()\"\n >\n <!-- A focus-holding dialog per the APG date-picker pattern: Tab cycles\n inside, Escape closes and returns focus to the field. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div #popupDialog role=\"dialog\" aria-label=\"Choose date\" (keydown)=\"onPopupKeydown($event)\">\n <uni-calendar\n mode=\"single\"\n [value]=\"value()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [markers]=\"markers()\"\n [weekStart]=\"weekStart()\"\n [locale]=\"locale()\"\n (selected)=\"onCalendarPick($event)\"\n />\n </div>\n </uni-dropdown>\n }\n\n <!-- Commits, steps and rejections are otherwise a silent reformat. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{
|
|
5591
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniDateInputComponent, isStandalone: true, selector: "uni-date-input, DateInput", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, displayFormat: { classPropertyName: "displayFormat", publicName: "displayFormat", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, parse: { classPropertyName: "parse", publicName: "parse", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, markers: { classPropertyName: "markers", publicName: "markers", isSignal: true, isRequired: false, transformFunction: null }, weekStart: { classPropertyName: "weekStart", publicName: "weekStart", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", opened: "opened", closed: "closed", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'dateInput' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "toggleRef", first: true, predicate: ["toggle"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "popupRef", first: true, predicate: ["popupDialog"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: UniDropdownComponent, descendants: true, isSignal: true }, { propertyName: "calendar", first: true, predicate: UniCalendarComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so commits happen only when focus\n leaves the whole field, not while moving into the popup. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <!-- The dropdown wires aria-haspopup/aria-expanded/aria-controls onto\n this button; its name tracks the value (\"Change date, \u2026\"). -->\n <button\n #toggle\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'calendar_month'\"\n [disable]=\"disabled()\"\n >\n {{ toggleLabel() }}\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (toggleElement()) {\n <uni-dropdown\n [trigger]=\"toggleElement()!\"\n ariaHasPopup=\"dialog\"\n placement=\"bottom-end\"\n [color]=\"componentOptions().popupColor ?? 'primary-surface'\"\n [shadow]=\"componentOptions().popupShadow ?? 'menu'\"\n [borderRadius]=\"componentOptions().popupBorderRadius ?? 'xs'\"\n paddingVertical=\"xs\"\n paddingHorizontal=\"xs\"\n (dropdownShowing)=\"onPopupShowing()\"\n (dropdownHiding)=\"onPopupHiding()\"\n >\n <!-- A focus-holding dialog per the APG date-picker pattern: Tab cycles\n inside, Escape closes and returns focus to the field. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div #popupDialog role=\"dialog\" aria-label=\"Choose date\" (keydown)=\"onPopupKeydown($event)\">\n <uni-calendar\n mode=\"single\"\n [value]=\"value()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [markers]=\"markers()\"\n [weekStart]=\"weekStart()\"\n [locale]=\"locale()\"\n (selected)=\"onCalendarPick($event)\"\n />\n </div>\n </uni-dropdown>\n }\n\n <!-- Commits, steps and rejections are otherwise a silent reformat. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: UniCalendarComponent, selector: "uni-calendar, Calendar", inputs: ["value", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "mode", "month", "minDate", "maxDate", "disabledDates", "markers", "locale", "weekStart", "ariaLabel", "size"], outputs: ["valueChange", "touchedChange", "monthChange", "selected"] }, { kind: "component", type: UniDropdownComponent, selector: "uni-dropdown", inputs: ["trigger", "placement", "offset", "ariaHasPopup", "paddingVertical", "paddingHorizontal", "border", "borderRadius", "shadow", "color"], outputs: ["dropdownShowing", "dropdownHiding"] }, { kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5444
5592
|
}
|
|
5445
5593
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDateInputComponent, decorators: [{
|
|
5446
5594
|
type: Component,
|
|
@@ -5450,7 +5598,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5450
5598
|
UniDropdownComponent,
|
|
5451
5599
|
UniIconButtonComponent,
|
|
5452
5600
|
UniInputBoxComponent,
|
|
5453
|
-
], providers: [{ provide: COMPONENT_NAME, useValue: 'dateInput' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so commits happen only when focus\n leaves the whole field, not while moving into the popup. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <!-- The dropdown wires aria-haspopup/aria-expanded/aria-controls onto\n this button; its name tracks the value (\"Change date, \u2026\"). -->\n <button\n #toggle\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'calendar_month'\"\n [disable]=\"disabled()\"\n >\n {{ toggleLabel() }}\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (toggleElement()) {\n <uni-dropdown\n [trigger]=\"toggleElement()!\"\n ariaHasPopup=\"dialog\"\n placement=\"bottom-end\"\n [color]=\"componentOptions().popupColor ?? 'primary-surface'\"\n [shadow]=\"componentOptions().popupShadow ?? 'menu'\"\n [borderRadius]=\"componentOptions().popupBorderRadius ?? 'xs'\"\n paddingVertical=\"xs\"\n paddingHorizontal=\"xs\"\n (dropdownShowing)=\"onPopupShowing()\"\n (dropdownHiding)=\"onPopupHiding()\"\n >\n <!-- A focus-holding dialog per the APG date-picker pattern: Tab cycles\n inside, Escape closes and returns focus to the field. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div #popupDialog role=\"dialog\" aria-label=\"Choose date\" (keydown)=\"onPopupKeydown($event)\">\n <uni-calendar\n mode=\"single\"\n [value]=\"value()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [markers]=\"markers()\"\n [weekStart]=\"weekStart()\"\n [locale]=\"locale()\"\n (selected)=\"onCalendarPick($event)\"\n />\n </div>\n </uni-dropdown>\n }\n\n <!-- Commits, steps and rejections are otherwise a silent reformat. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{
|
|
5601
|
+
], providers: [{ provide: COMPONENT_NAME, useValue: 'dateInput' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so commits happen only when focus\n leaves the whole field, not while moving into the popup. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <!-- The dropdown wires aria-haspopup/aria-expanded/aria-controls onto\n this button; its name tracks the value (\"Change date, \u2026\"). -->\n <button\n #toggle\n icon-button\n type=\"button\"\n size=\"sm\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'calendar_month'\"\n [disable]=\"disabled()\"\n >\n {{ toggleLabel() }}\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (toggleElement()) {\n <uni-dropdown\n [trigger]=\"toggleElement()!\"\n ariaHasPopup=\"dialog\"\n placement=\"bottom-end\"\n [color]=\"componentOptions().popupColor ?? 'primary-surface'\"\n [shadow]=\"componentOptions().popupShadow ?? 'menu'\"\n [borderRadius]=\"componentOptions().popupBorderRadius ?? 'xs'\"\n paddingVertical=\"xs\"\n paddingHorizontal=\"xs\"\n (dropdownShowing)=\"onPopupShowing()\"\n (dropdownHiding)=\"onPopupHiding()\"\n >\n <!-- A focus-holding dialog per the APG date-picker pattern: Tab cycles\n inside, Escape closes and returns focus to the field. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div #popupDialog role=\"dialog\" aria-label=\"Choose date\" (keydown)=\"onPopupKeydown($event)\">\n <uni-calendar\n mode=\"single\"\n [value]=\"value()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [markers]=\"markers()\"\n [weekStart]=\"weekStart()\"\n [locale]=\"locale()\"\n (selected)=\"onCalendarPick($event)\"\n />\n </div>\n </uni-dropdown>\n }\n\n <!-- Commits, steps and rejections are otherwise a silent reformat. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n" }]
|
|
5454
5602
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], displayFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayFormat", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], parse: [{ type: i0.Input, args: [{ isSignal: true, alias: "parse", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], markers: [{ type: i0.Input, args: [{ isSignal: true, alias: "markers", required: false }] }], weekStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStart", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], rejected: [{ type: i0.Output, args: ["rejected"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], toggleRef: [{ type: i0.ViewChild, args: ['toggle', { ...{ read: ElementRef }, isSignal: true }] }], popupRef: [{ type: i0.ViewChild, args: ['popupDialog', { isSignal: true }] }], dropdown: [{ type: i0.ViewChild, args: [i0.forwardRef(() => UniDropdownComponent), { isSignal: true }] }], calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => UniCalendarComponent), { isSignal: true }] }] } });
|
|
5455
5603
|
|
|
5456
5604
|
const toMinutes = (time) => {
|
|
@@ -5501,10 +5649,19 @@ class UniTimeInputComponent extends BaseComponent {
|
|
|
5501
5649
|
host = inject(ElementRef);
|
|
5502
5650
|
inputRef = viewChild('field', ...(ngDevMode ? [{ debugName: "inputRef" }] : /* istanbul ignore next */ []));
|
|
5503
5651
|
listRef = viewChild('listbox', ...(ngDevMode ? [{ debugName: "listRef" }] : /* istanbul ignore next */ []));
|
|
5652
|
+
/** Ties the popup to the field so the browser tracks it in the top layer. */
|
|
5653
|
+
anchor = newListboxAnchor();
|
|
5654
|
+
/** `manual` where the top layer is usable, else null — see the popup helper. */
|
|
5655
|
+
popupAttr = listboxPopupAttr();
|
|
5656
|
+
constructor() {
|
|
5657
|
+
super();
|
|
5658
|
+
promoteListboxPopup(this.listRef);
|
|
5659
|
+
}
|
|
5504
5660
|
srOnly = css(visuallyHidden);
|
|
5505
5661
|
/** A refused commit — styles the field and sets aria-invalid until edited. */
|
|
5506
5662
|
draftInvalid = signal(false, ...(ngDevMode ? [{ debugName: "draftInvalid" }] : /* istanbul ignore next */ []));
|
|
5507
|
-
|
|
5663
|
+
/** Commits, clears and refusals are otherwise silent to a screen reader. */
|
|
5664
|
+
announcer = createAnnouncer();
|
|
5508
5665
|
resolvedLocale = computed(() => this.locale() ?? (document.documentElement.lang || navigator.language || 'en-US'), ...(ngDevMode ? [{ debugName: "resolvedLocale" }] : /* istanbul ignore next */ []));
|
|
5509
5666
|
resolvedHour12 = computed(() => this.hour12() ?? localeDefaultHour12(this.resolvedLocale()), ...(ngDevMode ? [{ debugName: "resolvedHour12" }] : /* istanbul ignore next */ []));
|
|
5510
5667
|
/** The listed times: pinned `slots` verbatim, else the generated step grid. */
|
|
@@ -5530,7 +5687,7 @@ class UniTimeInputComponent extends BaseComponent {
|
|
|
5530
5687
|
this.draftInvalid.set(false);
|
|
5531
5688
|
this.setFieldText(this.displayText());
|
|
5532
5689
|
if (!silent)
|
|
5533
|
-
this.announce(time ? `${this.formatValue(time)}.` : 'Time cleared.');
|
|
5690
|
+
this.announcer.announce(time ? `${this.formatValue(time)}.` : 'Time cleared.');
|
|
5534
5691
|
}
|
|
5535
5692
|
refuse(raw, reason, shown = raw) {
|
|
5536
5693
|
this.draftInvalid.set(true);
|
|
@@ -5539,7 +5696,7 @@ class UniTimeInputComponent extends BaseComponent {
|
|
|
5539
5696
|
'out-of-range': `${shown} is outside the allowed times.`,
|
|
5540
5697
|
unavailable: `${shown} isn't available.`,
|
|
5541
5698
|
}[reason];
|
|
5542
|
-
this.announce(message);
|
|
5699
|
+
this.announcer.announce(message);
|
|
5543
5700
|
this.rejected.emit({ raw, reason });
|
|
5544
5701
|
}
|
|
5545
5702
|
commit(raw) {
|
|
@@ -5721,11 +5878,8 @@ class UniTimeInputComponent extends BaseComponent {
|
|
|
5721
5878
|
if (element)
|
|
5722
5879
|
element.value = text;
|
|
5723
5880
|
}
|
|
5724
|
-
announce(message) {
|
|
5725
|
-
this.announcement.set(this.announcement() === message ? `${message} ` : message);
|
|
5726
|
-
}
|
|
5727
5881
|
// --- Styling -----------------------------------------------------------------------
|
|
5728
|
-
className = computed(() => css({ display: 'block', position: 'relative' }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
5882
|
+
className = computed(() => css({ display: 'block', position: 'relative', ...this.anchor.style }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
5729
5883
|
rowClass = computed(() => css({ display: 'flex', alignItems: 'center', flex: 1, width: '100%', minWidth: 0 }), ...(ngDevMode ? [{ debugName: "rowClass" }] : /* istanbul ignore next */ []));
|
|
5730
5884
|
inputClass = computed(() => {
|
|
5731
5885
|
const colors = this.theme.colorPalette();
|
|
@@ -5754,15 +5908,16 @@ class UniTimeInputComponent extends BaseComponent {
|
|
|
5754
5908
|
const options = this.componentOptions();
|
|
5755
5909
|
return css(listboxPopupStyles(this.theme, options, {
|
|
5756
5910
|
maxHeight: (options.maxVisibleOptions ?? 7) * 36,
|
|
5911
|
+
anchor: this.anchor.name,
|
|
5757
5912
|
}));
|
|
5758
5913
|
}, ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
|
|
5759
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTimeInputComponent, deps:
|
|
5760
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTimeInputComponent, isStandalone: true, selector: "uni-time-input, TimeInput", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, slots: { classPropertyName: "slots", publicName: "slots", isSignal: true, isRequired: false, transformFunction: null }, hour12: { classPropertyName: "hour12", publicName: "hour12", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'timeInput' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "listRef", first: true, predicate: ["listbox"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n commits only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"list.open()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n aria-haspopup=\"listbox\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'schedule'\"\n [attr.aria-expanded]=\"list.open()\"\n [disable]=\"disabled()\"\n (click)=\"onToggle()\"\n >\n Choose time\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (list.open()) {\n <ul
|
|
5914
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTimeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5915
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTimeInputComponent, isStandalone: true, selector: "uni-time-input, TimeInput", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, slots: { classPropertyName: "slots", publicName: "slots", isSignal: true, isRequired: false, transformFunction: null }, hour12: { classPropertyName: "hour12", publicName: "hour12", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'timeInput' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "listRef", first: true, predicate: ["listbox"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n commits only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"list.open()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n aria-haspopup=\"listbox\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'schedule'\"\n [attr.aria-expanded]=\"list.open()\"\n [disable]=\"disabled()\"\n (click)=\"onToggle()\"\n >\n Choose time\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (list.open()) {\n <ul\n #listbox\n [id]=\"list.listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @for (time of options(); track time; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"time === value()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"selectOption(time)\"\n >\n {{ optionLabels()[i] }}\n </li>\n }\n </ul>\n }\n\n <!-- Commits and rejections are otherwise a silent reformat. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5761
5916
|
}
|
|
5762
5917
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTimeInputComponent, decorators: [{
|
|
5763
5918
|
type: Component,
|
|
5764
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-time-input, TimeInput', imports: [NgTemplateOutlet, UniIconButtonComponent, UniInputBoxComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'timeInput' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n commits only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"list.open()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n aria-haspopup=\"listbox\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'schedule'\"\n [attr.aria-expanded]=\"list.open()\"\n [disable]=\"disabled()\"\n (click)=\"onToggle()\"\n >\n Choose time\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (list.open()) {\n <ul
|
|
5765
|
-
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], slots: [{ type: i0.Input, args: [{ isSignal: true, alias: "slots", required: false }] }], hour12: [{ type: i0.Input, args: [{ isSignal: true, alias: "hour12", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }], rejected: [{ type: i0.Output, args: ["rejected"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], listRef: [{ type: i0.ViewChild, args: ['listbox', { isSignal: true }] }] } });
|
|
5919
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-time-input, TimeInput', imports: [NgTemplateOutlet, UniIconButtonComponent, UniInputBoxComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'timeInput' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so the list closes and the draft\n commits only when focus leaves the whole field. -->\n<div (focusout)=\"onFocusOut($event)\">\n <ng-template #parts>\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"displayText()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"list.open()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"ariaDescribedBy() ?? null\"\n [attr.aria-invalid]=\"showError() || draftInvalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput()\"\n />\n <span [class]=\"toggleWrapClass()\">\n <button\n icon-button\n type=\"button\"\n size=\"sm\"\n aria-haspopup=\"listbox\"\n [symbolName]=\"componentOptions().toggleSymbol ?? 'schedule'\"\n [attr.aria-expanded]=\"list.open()\"\n [disable]=\"disabled()\"\n (click)=\"onToggle()\"\n >\n Choose time\n </button>\n </span>\n </ng-template>\n\n @if (embedded()) {\n <!-- A composer (uni-date-time-input) owns the field chrome. -->\n <div [class]=\"embeddedClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n } @else {\n <uni-input-box [error]=\"showError() || draftInvalid()\" [disabled]=\"disabled()\">\n <div [class]=\"rowClass()\"><ng-container [ngTemplateOutlet]=\"parts\" /></div>\n </uni-input-box>\n }\n\n @if (list.open()) {\n <ul\n #listbox\n [id]=\"list.listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @for (time of options(); track time; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"time === value()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"selectOption(time)\"\n >\n {{ optionLabels()[i] }}\n </li>\n }\n </ul>\n }\n\n <!-- Commits and rejections are otherwise a silent reformat. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n" }]
|
|
5920
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], slots: [{ type: i0.Input, args: [{ isSignal: true, alias: "slots", required: false }] }], hour12: [{ type: i0.Input, args: [{ isSignal: true, alias: "hour12", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], embedded: [{ type: i0.Input, args: [{ isSignal: true, alias: "embedded", required: false }] }], rejected: [{ type: i0.Output, args: ["rejected"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], listRef: [{ type: i0.ViewChild, args: ['listbox', { isSignal: true }] }] } });
|
|
5766
5921
|
|
|
5767
5922
|
/**
|
|
5768
5923
|
* One field for a date and a time: a thin composer seating a uni-date-input
|
|
@@ -6357,10 +6512,23 @@ class UniExpandComponent extends BaseComponent {
|
|
|
6357
6512
|
const override = this.transitionSpeed();
|
|
6358
6513
|
if (override !== undefined)
|
|
6359
6514
|
return override;
|
|
6360
|
-
const speed = this.componentOptions().transitionSpeed ?? EXPAND_DEFAULT_SPEED;
|
|
6361
6515
|
const height = this.contentHeight();
|
|
6516
|
+
const speed = this.baseSpeed();
|
|
6362
6517
|
return height === undefined ? speed : expandDuration(height, speed);
|
|
6363
6518
|
}, ...(ngDevMode ? [{ debugName: "duration" }] : /* istanbul ignore next */ []));
|
|
6519
|
+
/**
|
|
6520
|
+
* Base speed in seconds, before the size-aware scaling above. The
|
|
6521
|
+
* deprecated `transitionSpeed` option wins when a theme still sets it;
|
|
6522
|
+
* otherwise the `motion` token's duration (ms) converts to seconds.
|
|
6523
|
+
*/
|
|
6524
|
+
baseSpeed = computed(() => {
|
|
6525
|
+
const options = this.componentOptions();
|
|
6526
|
+
if (options.transitionSpeed !== undefined)
|
|
6527
|
+
return options.transitionSpeed;
|
|
6528
|
+
return this.theme.motion(options.motion ?? 'reveal').duration / 1000;
|
|
6529
|
+
}, ...(ngDevMode ? [{ debugName: "baseSpeed" }] : /* istanbul ignore next */ []));
|
|
6530
|
+
/** Curve for the reveal, from the same token as the speed. */
|
|
6531
|
+
easing = computed(() => this.theme.motion(this.componentOptions().motion ?? 'reveal').easing, ...(ngDevMode ? [{ debugName: "easing" }] : /* istanbul ignore next */ []));
|
|
6364
6532
|
cssDuration = computed(() => `${this.duration()}s`, ...(ngDevMode ? [{ debugName: "cssDuration" }] : /* istanbul ignore next */ []));
|
|
6365
6533
|
/**
|
|
6366
6534
|
* A custom element is `display: inline` by default, which would lay the
|
|
@@ -6393,19 +6561,19 @@ class UniExpandComponent extends BaseComponent {
|
|
|
6393
6561
|
* `duration`, so the classes stay static while timing tracks the theme and
|
|
6394
6562
|
* the content's size through signals alone.
|
|
6395
6563
|
*/
|
|
6396
|
-
expandAnimation = css(motionSafe({
|
|
6564
|
+
expandAnimation = computed(() => css(motionSafe({
|
|
6397
6565
|
overflow: 'hidden',
|
|
6398
|
-
animation: `${this.expand}
|
|
6399
|
-
}));
|
|
6400
|
-
collapseAnimation = css(motionSafe({
|
|
6566
|
+
animation: `${this.expand} ${this.easing()} ${this.baseSpeed()}s`,
|
|
6567
|
+
})), ...(ngDevMode ? [{ debugName: "expandAnimation" }] : /* istanbul ignore next */ []));
|
|
6568
|
+
collapseAnimation = computed(() => css(motionSafe({
|
|
6401
6569
|
overflow: 'hidden',
|
|
6402
|
-
animation: `${this.collapse}
|
|
6403
|
-
}));
|
|
6570
|
+
animation: `${this.collapse} ${this.easing()} ${this.baseSpeed()}s`,
|
|
6571
|
+
})), ...(ngDevMode ? [{ debugName: "collapseAnimation" }] : /* istanbul ignore next */ []));
|
|
6404
6572
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniExpandComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6405
6573
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniExpandComponent, isStandalone: true, selector: "uni-expand", inputs: { collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, transitionSpeed: { classPropertyName: "transitionSpeed", publicName: "transitionSpeed", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsed: "collapsedChange" }, host: { properties: { "attr.id": "regionId", "class": "hostClassName" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'expand' }], viewQueries: [{ propertyName: "contentRef", first: true, predicate: ["content"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `@if (!collapsed()) {
|
|
6406
6574
|
<div
|
|
6407
|
-
[animate.enter]="ready() ? expandAnimation : ''"
|
|
6408
|
-
[animate.leave]="collapseAnimation"
|
|
6575
|
+
[animate.enter]="ready() ? expandAnimation() : ''"
|
|
6576
|
+
[animate.leave]="collapseAnimation()"
|
|
6409
6577
|
[class]="expandClassName"
|
|
6410
6578
|
[style.animation-duration]="cssDuration()"
|
|
6411
6579
|
>
|
|
@@ -6424,8 +6592,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
6424
6592
|
providers: [{ provide: COMPONENT_NAME, useValue: 'expand' }],
|
|
6425
6593
|
template: `@if (!collapsed()) {
|
|
6426
6594
|
<div
|
|
6427
|
-
[animate.enter]="ready() ? expandAnimation : ''"
|
|
6428
|
-
[animate.leave]="collapseAnimation"
|
|
6595
|
+
[animate.enter]="ready() ? expandAnimation() : ''"
|
|
6596
|
+
[animate.leave]="collapseAnimation()"
|
|
6429
6597
|
[class]="expandClassName"
|
|
6430
6598
|
[style.animation-duration]="cssDuration()"
|
|
6431
6599
|
>
|
|
@@ -6471,9 +6639,20 @@ class UniExpandToggleComponent {
|
|
|
6471
6639
|
* region is size-scaled or overridden per instance.
|
|
6472
6640
|
*/
|
|
6473
6641
|
transitionSpeed = input(...(ngDevMode ? [undefined, { debugName: "transitionSpeed" }] : /* istanbul ignore next */ []));
|
|
6474
|
-
/** Fallback clock when no `transitionSpeed` is bound: the `expand`
|
|
6475
|
-
|
|
6476
|
-
|
|
6642
|
+
/** Fallback clock when no `transitionSpeed` is bound: the `expand` entry's
|
|
6643
|
+
motion token — the same one the region itself reads. */
|
|
6644
|
+
themeService = inject(ThemeService);
|
|
6645
|
+
expandOptions = this.themeService.getComponentOptions('expand');
|
|
6646
|
+
speed = computed(() => {
|
|
6647
|
+
const override = this.transitionSpeed();
|
|
6648
|
+
if (override !== undefined)
|
|
6649
|
+
return override;
|
|
6650
|
+
const options = this.expandOptions();
|
|
6651
|
+
// Same order uni-expand uses, so the chevron and the region never drift.
|
|
6652
|
+
if (options.transitionSpeed !== undefined)
|
|
6653
|
+
return options.transitionSpeed;
|
|
6654
|
+
return this.themeService.motion(options.motion ?? 'reveal').duration / 1000;
|
|
6655
|
+
}, ...(ngDevMode ? [{ debugName: "speed" }] : /* istanbul ignore next */ []));
|
|
6477
6656
|
/**
|
|
6478
6657
|
* The glyph rotates, never the host.
|
|
6479
6658
|
*
|
|
@@ -6954,7 +7133,10 @@ class UniMenuItemComponent {
|
|
|
6954
7133
|
const variantStyle = variant
|
|
6955
7134
|
? this.theme.component('menuItem')().variants?.[variant]
|
|
6956
7135
|
: undefined;
|
|
6957
|
-
|
|
7136
|
+
// Neither set means no transition at all — the escape hatch predates the
|
|
7137
|
+
// motion scale and still works. The deprecated option wins over the token.
|
|
7138
|
+
const motion = options.motion ? this.theme.motion(options.motion) : undefined;
|
|
7139
|
+
const transitionSpeed = options.transitionSpeed ?? (motion ? motion.duration / 1000 : 0);
|
|
6958
7140
|
return css([
|
|
6959
7141
|
{
|
|
6960
7142
|
display: 'flex',
|
|
@@ -6983,7 +7165,7 @@ class UniMenuItemComponent {
|
|
|
6983
7165
|
pointerEvents: 'none',
|
|
6984
7166
|
},
|
|
6985
7167
|
},
|
|
6986
|
-
transitionSpeed > 0 && { transition: `all ${transitionSpeed}s ease` },
|
|
7168
|
+
transitionSpeed > 0 && { transition: `all ${transitionSpeed}s ${motion?.easing ?? 'ease'}` },
|
|
6987
7169
|
// Variant tones override the base look. A variant that restyles the
|
|
6988
7170
|
// highlight must key it with HOVER_OR_KEYBOARD_FOCUS — Emotion merges by
|
|
6989
7171
|
// exact selector text, so a variant spelling it `&:hover, &:focus`
|
|
@@ -7263,6 +7445,9 @@ class UniMultiSelectComponent {
|
|
|
7263
7445
|
})), ...(ngDevMode ? [{ debugName: "optionsWithSelections" }] : /* istanbul ignore next */ []));
|
|
7264
7446
|
className = css({ display: 'contents' });
|
|
7265
7447
|
handleCheck(checked, value) {
|
|
7448
|
+
// The rendered checkbox is disabled, so this only guards a direct call.
|
|
7449
|
+
if (this.options().find((option) => option.value === value)?.disabled)
|
|
7450
|
+
return;
|
|
7266
7451
|
const selections = this.selections();
|
|
7267
7452
|
if (!selections && !checked)
|
|
7268
7453
|
return;
|
|
@@ -7277,8 +7462,11 @@ class UniMultiSelectComponent {
|
|
|
7277
7462
|
return;
|
|
7278
7463
|
}
|
|
7279
7464
|
}
|
|
7465
|
+
/** Selects every *enabled* option — a disabled option is not committable. */
|
|
7280
7466
|
selectAll() {
|
|
7281
|
-
const allValues = this.options()
|
|
7467
|
+
const allValues = this.options()
|
|
7468
|
+
.filter((option) => !option.disabled)
|
|
7469
|
+
.map((option) => option.value);
|
|
7282
7470
|
this.updates.emit(allValues);
|
|
7283
7471
|
}
|
|
7284
7472
|
deselectAll() {
|
|
@@ -7290,11 +7478,11 @@ class UniMultiSelectComponent {
|
|
|
7290
7478
|
width: '100%',
|
|
7291
7479
|
});
|
|
7292
7480
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7293
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniMultiSelectComponent, isStandalone: true, selector: "uni-multi-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, selections: { classPropertyName: "selections", publicName: "selections", isSignal: true, isRequired: false, transformFunction: null }, flexDirection: { classPropertyName: "flexDirection", publicName: "flexDirection", isSignal: true, isRequired: false, transformFunction: null }, checkboxGap: { classPropertyName: "checkboxGap", publicName: "checkboxGap", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { updates: "updates" }, host: { properties: { "class": "className" } }, ngImport: i0, template: "<div box-layout display=\"flex\" [flexDirection]=\"flexDirection()\" [gap]=\"checkboxGap()\">\n <!-- track $index: option values may be objects and consumers rebuild the\n array, so identity tracking recreated every node (NG0956). -->\n @for (option of options(); track $index) {\n <div [class]=\"optionWrapper\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"values().indexOf(option.value) > -1\"\n (checkedChange)=\"handleCheck($event, option.value)\"\n variant=\"primary\"\n >\n </uni-checkbox>\n </div>\n }\n</div>\n", dependencies: [{ kind: "component", type: UniCheckboxComponent, selector: "uni-checkbox", inputs: ["checked", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "label", "indeterminate"], outputs: ["checkedChange", "touchedChange", "indeterminateChange"] }, { kind: "component", type: UniBoxComponent, selector: "[uni-box-layout], [box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7481
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniMultiSelectComponent, isStandalone: true, selector: "uni-multi-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, selections: { classPropertyName: "selections", publicName: "selections", isSignal: true, isRequired: false, transformFunction: null }, flexDirection: { classPropertyName: "flexDirection", publicName: "flexDirection", isSignal: true, isRequired: false, transformFunction: null }, checkboxGap: { classPropertyName: "checkboxGap", publicName: "checkboxGap", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { updates: "updates" }, host: { properties: { "class": "className" } }, ngImport: i0, template: "<div box-layout display=\"flex\" [flexDirection]=\"flexDirection()\" [gap]=\"checkboxGap()\">\n <!-- track $index: option values may be objects and consumers rebuild the\n array, so identity tracking recreated every node (NG0956). -->\n @for (option of options(); track $index) {\n <div [class]=\"optionWrapper\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"values().indexOf(option.value) > -1\"\n (checkedChange)=\"handleCheck($event, option.value)\"\n variant=\"primary\"\n [disabled]=\"!!option.disabled\"\n >\n </uni-checkbox>\n </div>\n }\n</div>\n", dependencies: [{ kind: "component", type: UniCheckboxComponent, selector: "uni-checkbox", inputs: ["checked", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "label", "indeterminate"], outputs: ["checkedChange", "touchedChange", "indeterminateChange"] }, { kind: "component", type: UniBoxComponent, selector: "[uni-box-layout], [box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7294
7482
|
}
|
|
7295
7483
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniMultiSelectComponent, decorators: [{
|
|
7296
7484
|
type: Component,
|
|
7297
|
-
args: [{ selector: 'uni-multi-select', imports: [UniCheckboxComponent, UniBoxComponent], host: { '[class]': 'className' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div box-layout display=\"flex\" [flexDirection]=\"flexDirection()\" [gap]=\"checkboxGap()\">\n <!-- track $index: option values may be objects and consumers rebuild the\n array, so identity tracking recreated every node (NG0956). -->\n @for (option of options(); track $index) {\n <div [class]=\"optionWrapper\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"values().indexOf(option.value) > -1\"\n (checkedChange)=\"handleCheck($event, option.value)\"\n variant=\"primary\"\n >\n </uni-checkbox>\n </div>\n }\n</div>\n" }]
|
|
7485
|
+
args: [{ selector: 'uni-multi-select', imports: [UniCheckboxComponent, UniBoxComponent], host: { '[class]': 'className' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div box-layout display=\"flex\" [flexDirection]=\"flexDirection()\" [gap]=\"checkboxGap()\">\n <!-- track $index: option values may be objects and consumers rebuild the\n array, so identity tracking recreated every node (NG0956). -->\n @for (option of options(); track $index) {\n <div [class]=\"optionWrapper\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"values().indexOf(option.value) > -1\"\n (checkedChange)=\"handleCheck($event, option.value)\"\n variant=\"primary\"\n [disabled]=\"!!option.disabled\"\n >\n </uni-checkbox>\n </div>\n }\n</div>\n" }]
|
|
7298
7486
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], selections: [{ type: i0.Input, args: [{ isSignal: true, alias: "selections", required: false }] }], updates: [{ type: i0.Output, args: ["updates"] }], flexDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "flexDirection", required: false }] }], checkboxGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxGap", required: false }] }] } });
|
|
7299
7487
|
|
|
7300
7488
|
class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
@@ -7337,10 +7525,18 @@ class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
|
7337
7525
|
* arithmetic — wrapping, Home/End, and never pointing past a list the
|
|
7338
7526
|
* filter has narrowed — the same contract `uni-search-input` and
|
|
7339
7527
|
* `uni-tag-input` use, so the keys behave identically across all three.
|
|
7528
|
+
*
|
|
7529
|
+
* `disabled` indexes into `filteredOptions`, matching `count`: arrows step
|
|
7530
|
+
* over disabled rows and Home/End land on the nearest enabled one, so the
|
|
7531
|
+
* focus target is always a checkbox that can actually take focus.
|
|
7340
7532
|
*/
|
|
7341
7533
|
list = createListboxNavigation({
|
|
7342
7534
|
count: () => this.filteredOptions().length,
|
|
7343
7535
|
idPrefix: 'uni-multi-select',
|
|
7536
|
+
disabled: (index) => !!this.filteredOptions()[index]?.disabled,
|
|
7537
|
+
// Focus rides the option checkboxes here, not a text field, so Home/End
|
|
7538
|
+
// have no caret to defer to — unlike the combobox-style consumers.
|
|
7539
|
+
homeEndNavigates: true,
|
|
7344
7540
|
});
|
|
7345
7541
|
/** Announced with the selection so the count is not left to guesswork. */
|
|
7346
7542
|
selectionSummary = computed(() => {
|
|
@@ -7407,11 +7603,18 @@ class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
|
7407
7603
|
this.list.show();
|
|
7408
7604
|
this.list.setActive(index);
|
|
7409
7605
|
}
|
|
7606
|
+
/**
|
|
7607
|
+
* Selects every *enabled* option. A disabled option is not committable, so
|
|
7608
|
+
* "select all" must not commit one on the user's behalf — the same rule
|
|
7609
|
+
* `toggleOption` and the keyboard path follow.
|
|
7610
|
+
*/
|
|
7410
7611
|
selectAll() {
|
|
7411
7612
|
if (this.disabled())
|
|
7412
7613
|
return;
|
|
7413
7614
|
this.touched.set(true);
|
|
7414
|
-
const allValues = this.options()
|
|
7615
|
+
const allValues = this.options()
|
|
7616
|
+
.filter((option) => !option.disabled)
|
|
7617
|
+
.map((option) => option.value);
|
|
7415
7618
|
this.value.set(allValues);
|
|
7416
7619
|
}
|
|
7417
7620
|
deselectAll() {
|
|
@@ -7424,7 +7627,8 @@ class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
|
7424
7627
|
return computed(() => this.value().includes(option.value));
|
|
7425
7628
|
}
|
|
7426
7629
|
toggleOption(option, checked) {
|
|
7427
|
-
|
|
7630
|
+
// The nav hook keeps the keyboard off disabled rows; this stops a pointer.
|
|
7631
|
+
if (this.disabled() || option.disabled)
|
|
7428
7632
|
return;
|
|
7429
7633
|
this.touched.set(true);
|
|
7430
7634
|
const { value } = option;
|
|
@@ -7440,7 +7644,7 @@ class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
|
7440
7644
|
});
|
|
7441
7645
|
}
|
|
7442
7646
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniMultiSelectDropdownComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
7443
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniMultiSelectDropdownComponent, isStandalone: true, selector: "uni-multi-select-dropdown", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "className" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'multiSelectDropdown' }], viewQueries: [{ propertyName: "optionRefs", predicate: ["optionRow"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<button\n [class]=\"triggerClass\"\n #trigger\n [style.cursor]=\"disabled() ? 'default' : 'pointer'\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n (click)=\"!disabled() && touched.set(true)\"\n>\n @if (label(); as fieldLabel) {\n <span [class]=\"srOnly\">{{ fieldLabel }},</span>\n }\n <span [class]=\"srOnly\">{{ selectionSummary() }}</span>\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div\n row-layout\n alignItems=\"center\"\n justifyContent=\"space-between\"\n [fullWidth]=\"true\"\n [minWidth]=\"0\"\n paddingLeft=\"sm\"\n >\n <span uni-text\n display=\"block\"\n [typeface]=\"componentOptions().textRole\"\n [color]=\"textColor()\"\n [ellipsis]=\"true\"\n [style.flex-grow]=\"1\"\n >{{ selectedLabelsText() }}</span>\n <uni-symbol name=\"keyboard_arrow_down\" [style.flex-shrink]=\"0\"></uni-symbol>\n </div>\n </uni-input-box>\n</button>\n<uni-dropdown\n #dropdown\n [trigger]=\"trigger\"\n ariaHasPopup=\"dialog\"\n (dropdownShowing)=\"$event && searchInput.focus()\"\n (dropdownHiding)=\"$event && trigger.focus()\"\n>\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div (keydown)=\"onPanelKeydown($event)\">\n <div box-layout gap=\"xs\" padding=\"xs\">\n <input\n #searchInput\n type=\"text\"\n [class]=\"searchInputClass()\"\n [value]=\"query()\"\n (input)=\"handleQueryInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Filter options\"\n (click)=\"$event.stopPropagation()\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div\n stack-layout\n gap=\"xs\"\n padding=\"xs\"\n role=\"group\"\n [attr.aria-label]=\"label() ? label() + ' options' : 'Options'\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <div #optionRow (focusin)=\"onOptionFocus(i)\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"isOptionSelected(option)()\"\n (checkedChange)=\"toggleOption(option, $event)\"\n variant=\"primary\"\n [disabled]=\"disabled()\"\n >\n </uni-checkbox>\n </div>\n }\n @if (filteredOptions().length === 0) {\n <span uni-text=\"label\" role=\"status\">No options match.</span>\n }\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div row-layout gap=\"xs\" justifyContent=\"space-around\" padding=\"xs\">\n <button text-button (click)=\"dropdown.hideDropdown()\" size=\"sm\" variant=\"ghost\">Done</button>\n </div>\n </div>\n</uni-dropdown>\n", dependencies: [{ kind: "component", type: UniCheckboxComponent, selector: "uni-checkbox", inputs: ["checked", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "label", "indeterminate"], outputs: ["checkedChange", "touchedChange", "indeterminateChange"] }, { kind: "component", type: UniBoxComponent, selector: "[uni-box-layout], [box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }, { kind: "component", type: UniDropdownComponent, selector: "uni-dropdown", inputs: ["trigger", "placement", "offset", "ariaHasPopup", "paddingVertical", "paddingHorizontal", "border", "borderRadius", "shadow", "color"], outputs: ["dropdownShowing", "dropdownHiding"] }, { kind: "component", type: UniStackComponent, selector: "[uni-stack-layout], [stack-layout]", inputs: ["display", "flexDirection", "minHeight"] }, { kind: "component", type: UniDividerComponent, selector: "uni-divider", inputs: ["orientation", "border"] }, { kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }, { kind: "component", type: UniTextComponent, selector: "[uni-text]", inputs: ["uni-text", "typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }, { kind: "component", type: UniRowComponent, selector: "[uni-row-layout], [row-layout]", inputs: ["display", "flexDirection", "minWidth"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7647
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniMultiSelectDropdownComponent, isStandalone: true, selector: "uni-multi-select-dropdown", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "className" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'multiSelectDropdown' }], viewQueries: [{ propertyName: "optionRefs", predicate: ["optionRow"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<button\n [class]=\"triggerClass\"\n #trigger\n [style.cursor]=\"disabled() ? 'default' : 'pointer'\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n (click)=\"!disabled() && touched.set(true)\"\n>\n @if (label(); as fieldLabel) {\n <span [class]=\"srOnly\">{{ fieldLabel }},</span>\n }\n <span [class]=\"srOnly\">{{ selectionSummary() }}</span>\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div\n row-layout\n alignItems=\"center\"\n justifyContent=\"space-between\"\n [fullWidth]=\"true\"\n [minWidth]=\"0\"\n paddingLeft=\"sm\"\n >\n <span uni-text\n display=\"block\"\n [typeface]=\"componentOptions().textRole\"\n [color]=\"textColor()\"\n [ellipsis]=\"true\"\n [style.flex-grow]=\"1\"\n >{{ selectedLabelsText() }}</span>\n <uni-symbol name=\"keyboard_arrow_down\" [style.flex-shrink]=\"0\"></uni-symbol>\n </div>\n </uni-input-box>\n</button>\n<uni-dropdown\n #dropdown\n [trigger]=\"trigger\"\n ariaHasPopup=\"dialog\"\n (dropdownShowing)=\"$event && searchInput.focus()\"\n (dropdownHiding)=\"$event && trigger.focus()\"\n>\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div (keydown)=\"onPanelKeydown($event)\">\n <div box-layout gap=\"xs\" padding=\"xs\">\n <input\n #searchInput\n type=\"text\"\n [class]=\"searchInputClass()\"\n [value]=\"query()\"\n (input)=\"handleQueryInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Filter options\"\n (click)=\"$event.stopPropagation()\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div\n stack-layout\n gap=\"xs\"\n padding=\"xs\"\n role=\"group\"\n [attr.aria-label]=\"label() ? label() + ' options' : 'Options'\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <div #optionRow (focusin)=\"onOptionFocus(i)\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"isOptionSelected(option)()\"\n (checkedChange)=\"toggleOption(option, $event)\"\n variant=\"primary\"\n [disabled]=\"disabled() || !!option.disabled\"\n >\n </uni-checkbox>\n </div>\n }\n @if (filteredOptions().length === 0) {\n <span uni-text=\"label\" role=\"status\">No options match.</span>\n }\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div row-layout gap=\"xs\" justifyContent=\"space-around\" padding=\"xs\">\n <button text-button (click)=\"dropdown.hideDropdown()\" size=\"sm\" variant=\"ghost\">Done</button>\n </div>\n </div>\n</uni-dropdown>\n", dependencies: [{ kind: "component", type: UniCheckboxComponent, selector: "uni-checkbox", inputs: ["checked", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "label", "indeterminate"], outputs: ["checkedChange", "touchedChange", "indeterminateChange"] }, { kind: "component", type: UniBoxComponent, selector: "[uni-box-layout], [box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }, { kind: "component", type: UniDropdownComponent, selector: "uni-dropdown", inputs: ["trigger", "placement", "offset", "ariaHasPopup", "paddingVertical", "paddingHorizontal", "border", "borderRadius", "shadow", "color"], outputs: ["dropdownShowing", "dropdownHiding"] }, { kind: "component", type: UniStackComponent, selector: "[uni-stack-layout], [stack-layout]", inputs: ["display", "flexDirection", "minHeight"] }, { kind: "component", type: UniDividerComponent, selector: "uni-divider", inputs: ["orientation", "border"] }, { kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }, { kind: "component", type: UniTextComponent, selector: "[uni-text]", inputs: ["uni-text", "typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }, { kind: "component", type: UniRowComponent, selector: "[uni-row-layout], [row-layout]", inputs: ["display", "flexDirection", "minWidth"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7444
7648
|
}
|
|
7445
7649
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniMultiSelectDropdownComponent, decorators: [{
|
|
7446
7650
|
type: Component,
|
|
@@ -7455,7 +7659,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
7455
7659
|
UniSymbolComponent,
|
|
7456
7660
|
UniRowComponent,
|
|
7457
7661
|
UniInputBoxComponent,
|
|
7458
|
-
], providers: [{ provide: COMPONENT_NAME, useValue: 'multiSelectDropdown' }], host: { '[class]': 'className' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [class]=\"triggerClass\"\n #trigger\n [style.cursor]=\"disabled() ? 'default' : 'pointer'\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n (click)=\"!disabled() && touched.set(true)\"\n>\n @if (label(); as fieldLabel) {\n <span [class]=\"srOnly\">{{ fieldLabel }},</span>\n }\n <span [class]=\"srOnly\">{{ selectionSummary() }}</span>\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div\n row-layout\n alignItems=\"center\"\n justifyContent=\"space-between\"\n [fullWidth]=\"true\"\n [minWidth]=\"0\"\n paddingLeft=\"sm\"\n >\n <span uni-text\n display=\"block\"\n [typeface]=\"componentOptions().textRole\"\n [color]=\"textColor()\"\n [ellipsis]=\"true\"\n [style.flex-grow]=\"1\"\n >{{ selectedLabelsText() }}</span>\n <uni-symbol name=\"keyboard_arrow_down\" [style.flex-shrink]=\"0\"></uni-symbol>\n </div>\n </uni-input-box>\n</button>\n<uni-dropdown\n #dropdown\n [trigger]=\"trigger\"\n ariaHasPopup=\"dialog\"\n (dropdownShowing)=\"$event && searchInput.focus()\"\n (dropdownHiding)=\"$event && trigger.focus()\"\n>\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div (keydown)=\"onPanelKeydown($event)\">\n <div box-layout gap=\"xs\" padding=\"xs\">\n <input\n #searchInput\n type=\"text\"\n [class]=\"searchInputClass()\"\n [value]=\"query()\"\n (input)=\"handleQueryInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Filter options\"\n (click)=\"$event.stopPropagation()\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div\n stack-layout\n gap=\"xs\"\n padding=\"xs\"\n role=\"group\"\n [attr.aria-label]=\"label() ? label() + ' options' : 'Options'\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <div #optionRow (focusin)=\"onOptionFocus(i)\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"isOptionSelected(option)()\"\n (checkedChange)=\"toggleOption(option, $event)\"\n variant=\"primary\"\n [disabled]=\"disabled()\"\n >\n </uni-checkbox>\n </div>\n }\n @if (filteredOptions().length === 0) {\n <span uni-text=\"label\" role=\"status\">No options match.</span>\n }\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div row-layout gap=\"xs\" justifyContent=\"space-around\" padding=\"xs\">\n <button text-button (click)=\"dropdown.hideDropdown()\" size=\"sm\" variant=\"ghost\">Done</button>\n </div>\n </div>\n</uni-dropdown>\n" }]
|
|
7662
|
+
], providers: [{ provide: COMPONENT_NAME, useValue: 'multiSelectDropdown' }], host: { '[class]': 'className' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [class]=\"triggerClass\"\n #trigger\n [style.cursor]=\"disabled() ? 'default' : 'pointer'\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n (click)=\"!disabled() && touched.set(true)\"\n>\n @if (label(); as fieldLabel) {\n <span [class]=\"srOnly\">{{ fieldLabel }},</span>\n }\n <span [class]=\"srOnly\">{{ selectionSummary() }}</span>\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div\n row-layout\n alignItems=\"center\"\n justifyContent=\"space-between\"\n [fullWidth]=\"true\"\n [minWidth]=\"0\"\n paddingLeft=\"sm\"\n >\n <span uni-text\n display=\"block\"\n [typeface]=\"componentOptions().textRole\"\n [color]=\"textColor()\"\n [ellipsis]=\"true\"\n [style.flex-grow]=\"1\"\n >{{ selectedLabelsText() }}</span>\n <uni-symbol name=\"keyboard_arrow_down\" [style.flex-shrink]=\"0\"></uni-symbol>\n </div>\n </uni-input-box>\n</button>\n<uni-dropdown\n #dropdown\n [trigger]=\"trigger\"\n ariaHasPopup=\"dialog\"\n (dropdownShowing)=\"$event && searchInput.focus()\"\n (dropdownHiding)=\"$event && trigger.focus()\"\n>\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div (keydown)=\"onPanelKeydown($event)\">\n <div box-layout gap=\"xs\" padding=\"xs\">\n <input\n #searchInput\n type=\"text\"\n [class]=\"searchInputClass()\"\n [value]=\"query()\"\n (input)=\"handleQueryInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Filter options\"\n (click)=\"$event.stopPropagation()\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div\n stack-layout\n gap=\"xs\"\n padding=\"xs\"\n role=\"group\"\n [attr.aria-label]=\"label() ? label() + ' options' : 'Options'\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <div #optionRow (focusin)=\"onOptionFocus(i)\">\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"isOptionSelected(option)()\"\n (checkedChange)=\"toggleOption(option, $event)\"\n variant=\"primary\"\n [disabled]=\"disabled() || !!option.disabled\"\n >\n </uni-checkbox>\n </div>\n }\n @if (filteredOptions().length === 0) {\n <span uni-text=\"label\" role=\"status\">No options match.</span>\n }\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div row-layout gap=\"xs\" justifyContent=\"space-around\" padding=\"xs\">\n <button text-button (click)=\"dropdown.hideDropdown()\" size=\"sm\" variant=\"ghost\">Done</button>\n </div>\n </div>\n</uni-dropdown>\n" }]
|
|
7459
7663
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], optionRefs: [{ type: i0.ViewChildren, args: ['optionRow', { isSignal: true }] }] } });
|
|
7460
7664
|
|
|
7461
7665
|
class UniNotificationBadgeComponent extends BaseComponent {
|
|
@@ -7568,12 +7772,23 @@ class UniAlertComponent extends BaseComponent {
|
|
|
7568
7772
|
alertRef;
|
|
7569
7773
|
alertState = signal('closed', ...(ngDevMode ? [{ debugName: "alertState" }] : /* istanbul ignore next */ []));
|
|
7570
7774
|
effectiveVariant = computed(() => this.variant() || this.componentOptions().defaultVariant, ...(ngDevMode ? [{ debugName: "effectiveVariant" }] : /* istanbul ignore next */ []));
|
|
7775
|
+
/**
|
|
7776
|
+
* Timing for the enter/leave transition. The deprecated `transitionSpeed`
|
|
7777
|
+
* (seconds) wins when a theme still sets it.
|
|
7778
|
+
*/
|
|
7779
|
+
motion = computed(() => {
|
|
7780
|
+
const options = this.componentOptions();
|
|
7781
|
+
const token = this.theme.motion(options.motion ?? 'notification');
|
|
7782
|
+
return options.transitionSpeed === undefined
|
|
7783
|
+
? token
|
|
7784
|
+
: { ...token, duration: options.transitionSpeed * 1000 };
|
|
7785
|
+
}, ...(ngDevMode ? [{ debugName: "motion" }] : /* istanbul ignore next */ []));
|
|
7571
7786
|
alertClass = computed(() => css({
|
|
7572
7787
|
...this.theme.getContainerColors(this.effectiveVariant(), this.useVariant()),
|
|
7573
7788
|
...this.theme.radius(this.componentOptions().borderRadius),
|
|
7574
7789
|
...this.theme.border(this.effectiveVariant()),
|
|
7575
7790
|
...this.theme.boxShadow(this.componentOptions().elevation),
|
|
7576
|
-
transition: `all ${this.
|
|
7791
|
+
transition: `all ${this.motion().duration / 1000}s ${this.motion().easing}`,
|
|
7577
7792
|
transitionBehavior: 'allow-discrete',
|
|
7578
7793
|
opacity: 1,
|
|
7579
7794
|
top: this.componentOptions().topPosition,
|
|
@@ -7679,19 +7894,48 @@ class UniSnackbarComponent extends BaseComponent {
|
|
|
7679
7894
|
super();
|
|
7680
7895
|
effect(() => (this.show() ? this.open() : this.close()));
|
|
7681
7896
|
}
|
|
7897
|
+
/**
|
|
7898
|
+
* Timing for the enter/leave transition. The deprecated `transitionDelay`
|
|
7899
|
+
* wins when a theme still sets it — it is a CSS time string, so `0.35s` and
|
|
7900
|
+
* `350ms` both parse back to milliseconds.
|
|
7901
|
+
*/
|
|
7902
|
+
motion = computed(() => {
|
|
7903
|
+
const options = this.componentOptions();
|
|
7904
|
+
const token = this.theme.motion(options.motion ?? 'notification');
|
|
7905
|
+
const legacy = options.transitionDelay;
|
|
7906
|
+
if (!legacy)
|
|
7907
|
+
return token;
|
|
7908
|
+
const ms = legacy.trim().endsWith('ms') ? parseFloat(legacy) : parseFloat(legacy) * 1000;
|
|
7909
|
+
return Number.isFinite(ms) ? { ...token, duration: ms } : token;
|
|
7910
|
+
}, ...(ngDevMode ? [{ debugName: "motion" }] : /* istanbul ignore next */ []));
|
|
7682
7911
|
snackbarClass = computed(() => css({
|
|
7912
|
+
// The UA's `[popover]` border, before the theme's own so a themed border
|
|
7913
|
+
// still wins. Its `background-color: Canvas` needs no reset — the
|
|
7914
|
+
// container colors below beat it on origin, and resetting `background`
|
|
7915
|
+
// here would erase them, since it is a shorthand.
|
|
7916
|
+
border: 'none',
|
|
7683
7917
|
...this.theme.getContainerColors(this.variant() || 'primary', this.useVariant()),
|
|
7684
7918
|
...this.theme.radius('sm'),
|
|
7685
7919
|
...this.theme.border(this.variant() || 'primary'),
|
|
7686
7920
|
...this.theme.boxShadow('dialog'),
|
|
7687
7921
|
padding: 0,
|
|
7688
|
-
transition: `all ${this.
|
|
7922
|
+
transition: `all ${this.motion().duration}ms ${this.motion().easing}`,
|
|
7689
7923
|
transitionBehavior: 'allow-discrete',
|
|
7690
7924
|
opacity: 1,
|
|
7691
|
-
|
|
7692
|
-
|
|
7925
|
+
// `[popover]` arrives centred by `inset: 0; margin: auto`. Undo that,
|
|
7926
|
+
// then rebuild the bottom-centred placement `<dialog>` used to get from
|
|
7927
|
+
// its own UA rules: shrink to the content, pin to the bottom, and let
|
|
7928
|
+
// auto inline margins centre it between the viewport edges.
|
|
7693
7929
|
position: 'fixed',
|
|
7694
|
-
'
|
|
7930
|
+
inset: 'auto',
|
|
7931
|
+
left: 0,
|
|
7932
|
+
right: 0,
|
|
7933
|
+
bottom: this.componentOptions().bottomPosition,
|
|
7934
|
+
width: 'fit-content',
|
|
7935
|
+
maxWidth: '100%',
|
|
7936
|
+
marginInline: 'auto',
|
|
7937
|
+
marginBlock: 0,
|
|
7938
|
+
'&:popover-open': {
|
|
7695
7939
|
'@starting-style': {
|
|
7696
7940
|
bottom: 0,
|
|
7697
7941
|
opacity: 0,
|
|
@@ -7712,7 +7956,9 @@ class UniSnackbarComponent extends BaseComponent {
|
|
|
7712
7956
|
ngAfterViewInit() {
|
|
7713
7957
|
this._snackbar?.addEventListener('animationend', (e) => {
|
|
7714
7958
|
if (e.animationName == this.fadeOut) {
|
|
7715
|
-
|
|
7959
|
+
// Leaves the top layer only once the fade has finished — hiding first
|
|
7960
|
+
// would remove the bar mid-animation.
|
|
7961
|
+
this.hide();
|
|
7716
7962
|
this.showing.emit(false);
|
|
7717
7963
|
}
|
|
7718
7964
|
});
|
|
@@ -7727,7 +7973,12 @@ class UniSnackbarComponent extends BaseComponent {
|
|
|
7727
7973
|
}
|
|
7728
7974
|
open() {
|
|
7729
7975
|
this._snackbar?.removeAttribute('closing');
|
|
7730
|
-
|
|
7976
|
+
try {
|
|
7977
|
+
this._snackbar?.showPopover();
|
|
7978
|
+
}
|
|
7979
|
+
catch {
|
|
7980
|
+
// Already showing — reopening is a no-op, the timer below still restarts.
|
|
7981
|
+
}
|
|
7731
7982
|
this.show.set(true);
|
|
7732
7983
|
this.showing.emit(true);
|
|
7733
7984
|
if (this._timeout)
|
|
@@ -7737,6 +7988,15 @@ class UniSnackbarComponent extends BaseComponent {
|
|
|
7737
7988
|
this._snackbar?.setAttribute('closing', 'true');
|
|
7738
7989
|
this.show.set(false);
|
|
7739
7990
|
}
|
|
7991
|
+
/** Drops out of the top layer. Called once the closing fade has run. */
|
|
7992
|
+
hide() {
|
|
7993
|
+
try {
|
|
7994
|
+
this._snackbar?.hidePopover();
|
|
7995
|
+
}
|
|
7996
|
+
catch {
|
|
7997
|
+
// Already hidden.
|
|
7998
|
+
}
|
|
7999
|
+
}
|
|
7740
8000
|
pauseTimer() {
|
|
7741
8001
|
this.timer.pause();
|
|
7742
8002
|
}
|
|
@@ -7744,7 +8004,7 @@ class UniSnackbarComponent extends BaseComponent {
|
|
|
7744
8004
|
this.timer.resume();
|
|
7745
8005
|
}
|
|
7746
8006
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSnackbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7747
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSnackbarComponent, isStandalone: true, selector: "uni-snackbar", inputs: { show: { classPropertyName: "show", publicName: "show", isSignal: true, isRequired: false, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, symbolName: { classPropertyName: "symbolName", publicName: "symbolName", isSignal: true, isRequired: false, transformFunction: null }, timeout: { classPropertyName: "timeout", publicName: "timeout", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, useVariant: { classPropertyName: "useVariant", publicName: "useVariant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { show: "showChange", action: "action", showing: "showing" }, providers: [{ provide: COMPONENT_NAME, useValue: 'snackbar' }], viewQueries: [{ propertyName: "snackbarRef", first: true, predicate: ["snackbar"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@let icon = iconName();\n@let symbol = symbolName();\n<!-- role=\"status\" announces the message politely without stealing focus
|
|
8007
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSnackbarComponent, isStandalone: true, selector: "uni-snackbar", inputs: { show: { classPropertyName: "show", publicName: "show", isSignal: true, isRequired: false, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, symbolName: { classPropertyName: "symbolName", publicName: "symbolName", isSignal: true, isRequired: false, transformFunction: null }, timeout: { classPropertyName: "timeout", publicName: "timeout", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, useVariant: { classPropertyName: "useVariant", publicName: "useVariant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { show: "showChange", action: "action", showing: "showing" }, providers: [{ provide: COMPONENT_NAME, useValue: 'snackbar' }], viewQueries: [{ propertyName: "snackbarRef", first: true, predicate: ["snackbar"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@let icon = iconName();\n@let symbol = symbolName();\n<!-- role=\"status\" announces the message politely without stealing focus.\n popover=\"manual\" puts the bar in the top layer so no stacking context or\n `overflow: hidden` ancestor can cover or clip it; \"manual\" because a\n snackbar is dismissed by its own button or its timer, never by a click\n elsewhere on the page. Not a <dialog>: it is never modal, and dialog's\n `open` attribute would be a second, competing notion of \"shown\". -->\n<div\n #snackbar\n popover=\"manual\"\n [class]=\"snackbarClass()\"\n role=\"status\"\n (mouseenter)=\"pauseTimer()\"\n (mouseleave)=\"resumeTimer()\"\n (focusin)=\"pauseTimer()\"\n (focusout)=\"resumeTimer()\"\n>\n <div row-layout alignItems=\"center\">\n @if (icon || symbol) {\n <div box-layout [height]=\"26\" [width]=\"26\" paddingLeft=\"sm\">\n @if (icon) {\n <uni-icon [name]=\"icon\"></uni-icon>\n } @else if (symbol) {\n <uni-symbol [name]=\"symbol\" [opticalSize]=\"26\"></uni-symbol>\n }\n </div>\n }\n <div box-layout padding=\"sm\">\n <span uni-text>\n <ng-content></ng-content>\n </span>\n </div>\n <div box-layout paddingRight=\"sm\">\n @if (!actionLabel()) {\n <button icon-button (click)=\"close()\" iconName=\"close\" size=\"md\">Close</button>\n } @else {\n <button text-button variant=\"ghost\" (click)=\"this.action.emit(); close()\">\n {{ actionLabel() }}\n </button>\n }\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: UniRowComponent, selector: "[uni-row-layout], [row-layout]", inputs: ["display", "flexDirection", "minWidth"] }, { kind: "component", type: UniBoxComponent, selector: "[uni-box-layout], [box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }, { kind: "component", type: UniTextComponent, selector: "[uni-text]", inputs: ["uni-text", "typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }, { kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }, { kind: "component", type: UniIconComponent, selector: "uni-icon", inputs: ["color", "name", "size"] }, { kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7748
8008
|
}
|
|
7749
8009
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSnackbarComponent, decorators: [{
|
|
7750
8010
|
type: Component,
|
|
@@ -7756,7 +8016,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
7756
8016
|
UniSymbolComponent,
|
|
7757
8017
|
UniIconComponent,
|
|
7758
8018
|
UniButtonComponent,
|
|
7759
|
-
], providers: [{ provide: COMPONENT_NAME, useValue: 'snackbar' }], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let icon = iconName();\n@let symbol = symbolName();\n<!-- role=\"status\" announces the message politely without stealing focus
|
|
8019
|
+
], providers: [{ provide: COMPONENT_NAME, useValue: 'snackbar' }], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let icon = iconName();\n@let symbol = symbolName();\n<!-- role=\"status\" announces the message politely without stealing focus.\n popover=\"manual\" puts the bar in the top layer so no stacking context or\n `overflow: hidden` ancestor can cover or clip it; \"manual\" because a\n snackbar is dismissed by its own button or its timer, never by a click\n elsewhere on the page. Not a <dialog>: it is never modal, and dialog's\n `open` attribute would be a second, competing notion of \"shown\". -->\n<div\n #snackbar\n popover=\"manual\"\n [class]=\"snackbarClass()\"\n role=\"status\"\n (mouseenter)=\"pauseTimer()\"\n (mouseleave)=\"resumeTimer()\"\n (focusin)=\"pauseTimer()\"\n (focusout)=\"resumeTimer()\"\n>\n <div row-layout alignItems=\"center\">\n @if (icon || symbol) {\n <div box-layout [height]=\"26\" [width]=\"26\" paddingLeft=\"sm\">\n @if (icon) {\n <uni-icon [name]=\"icon\"></uni-icon>\n } @else if (symbol) {\n <uni-symbol [name]=\"symbol\" [opticalSize]=\"26\"></uni-symbol>\n }\n </div>\n }\n <div box-layout padding=\"sm\">\n <span uni-text>\n <ng-content></ng-content>\n </span>\n </div>\n <div box-layout paddingRight=\"sm\">\n @if (!actionLabel()) {\n <button icon-button (click)=\"close()\" iconName=\"close\" size=\"md\">Close</button>\n } @else {\n <button text-button variant=\"ghost\" (click)=\"this.action.emit(); close()\">\n {{ actionLabel() }}\n </button>\n }\n </div>\n </div>\n</div>\n" }]
|
|
7760
8020
|
}], ctorParameters: () => [], propDecorators: { show: [{ type: i0.Input, args: [{ isSignal: true, alias: "show", required: false }] }, { type: i0.Output, args: ["showChange"] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], symbolName: [{ type: i0.Input, args: [{ isSignal: true, alias: "symbolName", required: false }] }], timeout: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeout", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], useVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "useVariant", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], showing: [{ type: i0.Output, args: ["showing"] }], snackbarRef: [{ type: i0.ViewChild, args: ['snackbar', { isSignal: true }] }] } });
|
|
7761
8021
|
|
|
7762
8022
|
class NotificationsComponent {
|
|
@@ -8134,6 +8394,7 @@ class UniPopoverComponent extends BaseComponent {
|
|
|
8134
8394
|
}, ...(ngDevMode ? [{ debugName: "resolvedMaxWidth" }] : /* istanbul ignore next */ []));
|
|
8135
8395
|
popoverClassName = computed(() => {
|
|
8136
8396
|
const options = this.componentOptions();
|
|
8397
|
+
const motion = this.theme.motion(options.motion);
|
|
8137
8398
|
return css({
|
|
8138
8399
|
...this.theme.colorPair(options.color),
|
|
8139
8400
|
...this.theme.radius(options.borderRadius),
|
|
@@ -8145,7 +8406,7 @@ class UniPopoverComponent extends BaseComponent {
|
|
|
8145
8406
|
maxWidth: this.resolvedMaxWidth(),
|
|
8146
8407
|
overflow: 'visible',
|
|
8147
8408
|
...anchorStyles(this.anchorName, this.placement(), { mainAxis: options.offset }),
|
|
8148
|
-
...discreteOverlayTransition(
|
|
8409
|
+
...discreteOverlayTransition(motion.duration, { opacity: 0 }, { opacity: 1 }, motion.easing),
|
|
8149
8410
|
});
|
|
8150
8411
|
}, ...(ngDevMode ? [{ debugName: "popoverClassName" }] : /* istanbul ignore next */ []));
|
|
8151
8412
|
/** Empty regions collapse, so bare content renders v1's single-region look. */
|
|
@@ -8344,9 +8605,12 @@ class UniRadioComponent extends BaseComponent {
|
|
|
8344
8605
|
// transitions are scoped — never `all` — so the focus ring's outline and
|
|
8345
8606
|
// shadow apply instantly instead of interpolating from a stale outline
|
|
8346
8607
|
// color, which flashed a dark ring before the themed ring color landed.
|
|
8347
|
-
const
|
|
8348
|
-
|
|
8349
|
-
const
|
|
8608
|
+
const options = this.componentOptions();
|
|
8609
|
+
// The deprecated option wins so a theme that set it keeps its timing.
|
|
8610
|
+
const motion = this.theme.motion(options.motion ?? 'control');
|
|
8611
|
+
const speed = options.transitionSpeed ?? motion.duration / 1000;
|
|
8612
|
+
const ringTransition = `border-color ${speed}s ${motion.easing}, background-color ${speed}s ${motion.easing}`;
|
|
8613
|
+
const dotTransition = `transform ${speed}s ${motion.easing}`;
|
|
8350
8614
|
return css({
|
|
8351
8615
|
userSelect: 'none',
|
|
8352
8616
|
cursor: this.disabled() ? 'not-allowed' : 'pointer',
|
|
@@ -8455,6 +8719,15 @@ class UniSearchInputComponent extends BaseComponent {
|
|
|
8455
8719
|
search = output();
|
|
8456
8720
|
suggestionSelected = output();
|
|
8457
8721
|
field = viewChild.required(UniDebounceInputComponent);
|
|
8722
|
+
listRef = viewChild('listbox', ...(ngDevMode ? [{ debugName: "listRef" }] : /* istanbul ignore next */ []));
|
|
8723
|
+
/** Ties the popup to the field so the browser tracks it in the top layer. */
|
|
8724
|
+
anchor = newListboxAnchor();
|
|
8725
|
+
/** `manual` where the top layer is usable, else null — see the popup helper. */
|
|
8726
|
+
popupAttr = listboxPopupAttr();
|
|
8727
|
+
constructor() {
|
|
8728
|
+
super();
|
|
8729
|
+
promoteListboxPopup(this.listRef);
|
|
8730
|
+
}
|
|
8458
8731
|
visibleSuggestions = computed(() => this.suggestions().slice(0, this.componentOptions().maxSuggestions ?? 8), ...(ngDevMode ? [{ debugName: "visibleSuggestions" }] : /* istanbul ignore next */ []));
|
|
8459
8732
|
/** Shared combobox bookkeeping: open state, active option, ARIA ids. */
|
|
8460
8733
|
list = createListboxNavigation({
|
|
@@ -8513,20 +8786,21 @@ class UniSearchInputComponent extends BaseComponent {
|
|
|
8513
8786
|
display: 'block',
|
|
8514
8787
|
position: 'relative',
|
|
8515
8788
|
width: this.width(),
|
|
8789
|
+
...this.anchor.style,
|
|
8516
8790
|
'& .uni-search-lead': {
|
|
8517
8791
|
fontSize: 20,
|
|
8518
8792
|
...this.theme.color('on-background-variant'),
|
|
8519
8793
|
...this.theme.paddingLeft('sm'),
|
|
8520
8794
|
},
|
|
8521
8795
|
}), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
8522
|
-
listClass = computed(() => css(listboxPopupStyles(this.theme, this.componentOptions())), ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
|
|
8523
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSearchInputComponent, deps:
|
|
8524
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSearchInputComponent, isStandalone: true, selector: "uni-search-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change", search: "search", suggestionSelected: "suggestionSelected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'searchInput' }], viewQueries: [{ propertyName: "field", first: true, predicate: UniDebounceInputComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Keydown/focusout ride the bubbling events from the inner input; the\n wrapper itself stays out of the tab order. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div (keydown)=\"onKeydown($event)\" (focusout)=\"onFocusOut($event)\">\n <uni-debounce-input\n #searchField\n [label]=\"label()\"\n [placeholder]=\"placeholder() ?? label()\"\n [debounceTime]=\"debounceTime()\"\n role=\"combobox\"\n [ariaExpanded]=\"list.open()\"\n [ariaControls]=\"listboxId\"\n [ariaActivedescendant]=\"list.activeDescendantId() ?? undefined\"\n (change)=\"handleChange($event)\"\n >\n <uni-symbol pre-input class=\"uni-search-lead\" name=\"{{ componentOptions().searchSymbol ?? 'search' }}\" aria-hidden=\"true\" />\n @if (hasQuery()) {\n <button\n post-input\n icon-button\n [iconName]=\"componentOptions().clearSymbol ?? 'close'\"\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"clear()\"\n >\n Clear search\n </button>\n }\n </uni-debounce-input>\n\n @if (list.open()) {\n <ul
|
|
8796
|
+
listClass = computed(() => css(listboxPopupStyles(this.theme, this.componentOptions(), { anchor: this.anchor.name })), ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
|
|
8797
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8798
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSearchInputComponent, isStandalone: true, selector: "uni-search-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change", search: "search", suggestionSelected: "suggestionSelected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'searchInput' }], viewQueries: [{ propertyName: "field", first: true, predicate: UniDebounceInputComponent, descendants: true, isSignal: true }, { propertyName: "listRef", first: true, predicate: ["listbox"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Keydown/focusout ride the bubbling events from the inner input; the\n wrapper itself stays out of the tab order. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div (keydown)=\"onKeydown($event)\" (focusout)=\"onFocusOut($event)\">\n <uni-debounce-input\n #searchField\n [label]=\"label()\"\n [placeholder]=\"placeholder() ?? label()\"\n [debounceTime]=\"debounceTime()\"\n role=\"combobox\"\n [ariaExpanded]=\"list.open()\"\n [ariaControls]=\"listboxId\"\n [ariaActivedescendant]=\"list.activeDescendantId() ?? undefined\"\n (change)=\"handleChange($event)\"\n >\n <uni-symbol pre-input class=\"uni-search-lead\" name=\"{{ componentOptions().searchSymbol ?? 'search' }}\" aria-hidden=\"true\" />\n @if (hasQuery()) {\n <button\n post-input\n icon-button\n [iconName]=\"componentOptions().clearSymbol ?? 'close'\"\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"clear()\"\n >\n Clear search\n </button>\n }\n </uni-debounce-input>\n\n @if (list.open()) {\n <ul\n #listbox\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @for (suggestion of visibleSuggestions(); track suggestion; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"i === list.activeIndex()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"select(suggestion)\"\n >\n {{ suggestion }}\n </li>\n }\n </ul>\n }\n</div>\n", dependencies: [{ kind: "component", type: UniDebounceInputComponent, selector: "uni-debounce-input", inputs: ["inputName", "inputId", "debounceTime", "label", "placeholder", "disabled", "role", "ariaExpanded", "ariaControls", "ariaActivedescendant"], outputs: ["change"] }, { kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8525
8799
|
}
|
|
8526
8800
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSearchInputComponent, decorators: [{
|
|
8527
8801
|
type: Component,
|
|
8528
|
-
args: [{ selector: 'uni-search-input', imports: [UniDebounceInputComponent, UniIconButtonComponent, UniSymbolComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'searchInput' }], host: { '[class]': 'className()' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Keydown/focusout ride the bubbling events from the inner input; the\n wrapper itself stays out of the tab order. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div (keydown)=\"onKeydown($event)\" (focusout)=\"onFocusOut($event)\">\n <uni-debounce-input\n #searchField\n [label]=\"label()\"\n [placeholder]=\"placeholder() ?? label()\"\n [debounceTime]=\"debounceTime()\"\n role=\"combobox\"\n [ariaExpanded]=\"list.open()\"\n [ariaControls]=\"listboxId\"\n [ariaActivedescendant]=\"list.activeDescendantId() ?? undefined\"\n (change)=\"handleChange($event)\"\n >\n <uni-symbol pre-input class=\"uni-search-lead\" name=\"{{ componentOptions().searchSymbol ?? 'search' }}\" aria-hidden=\"true\" />\n @if (hasQuery()) {\n <button\n post-input\n icon-button\n [iconName]=\"componentOptions().clearSymbol ?? 'close'\"\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"clear()\"\n >\n Clear search\n </button>\n }\n </uni-debounce-input>\n\n @if (list.open()) {\n <ul
|
|
8529
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], change: [{ type: i0.Output, args: ["change"] }], search: [{ type: i0.Output, args: ["search"] }], suggestionSelected: [{ type: i0.Output, args: ["suggestionSelected"] }], field: [{ type: i0.ViewChild, args: [i0.forwardRef(() => UniDebounceInputComponent), { isSignal: true }] }] } });
|
|
8802
|
+
args: [{ selector: 'uni-search-input', imports: [UniDebounceInputComponent, UniIconButtonComponent, UniSymbolComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'searchInput' }], host: { '[class]': 'className()' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Keydown/focusout ride the bubbling events from the inner input; the\n wrapper itself stays out of the tab order. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div (keydown)=\"onKeydown($event)\" (focusout)=\"onFocusOut($event)\">\n <uni-debounce-input\n #searchField\n [label]=\"label()\"\n [placeholder]=\"placeholder() ?? label()\"\n [debounceTime]=\"debounceTime()\"\n role=\"combobox\"\n [ariaExpanded]=\"list.open()\"\n [ariaControls]=\"listboxId\"\n [ariaActivedescendant]=\"list.activeDescendantId() ?? undefined\"\n (change)=\"handleChange($event)\"\n >\n <uni-symbol pre-input class=\"uni-search-lead\" name=\"{{ componentOptions().searchSymbol ?? 'search' }}\" aria-hidden=\"true\" />\n @if (hasQuery()) {\n <button\n post-input\n icon-button\n [iconName]=\"componentOptions().clearSymbol ?? 'close'\"\n variant=\"ghost\"\n size=\"sm\"\n (click)=\"clear()\"\n >\n Clear search\n </button>\n }\n </uni-debounce-input>\n\n @if (list.open()) {\n <ul\n #listbox\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @for (suggestion of visibleSuggestions(); track suggestion; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"i === list.activeIndex()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"select(suggestion)\"\n >\n {{ suggestion }}\n </li>\n }\n </ul>\n }\n</div>\n" }]
|
|
8803
|
+
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], change: [{ type: i0.Output, args: ["change"] }], search: [{ type: i0.Output, args: ["search"] }], suggestionSelected: [{ type: i0.Output, args: ["suggestionSelected"] }], field: [{ type: i0.ViewChild, args: [i0.forwardRef(() => UniDebounceInputComponent), { isSignal: true }] }], listRef: [{ type: i0.ViewChild, args: ['listbox', { isSignal: true }] }] } });
|
|
8530
8804
|
|
|
8531
8805
|
/**
|
|
8532
8806
|
* UniSearchInputComponent Barrel File
|
|
@@ -8603,11 +8877,11 @@ class UniSelectComponent {
|
|
|
8603
8877
|
pointerEvents: 'none' /* Crucial for clicking through */,
|
|
8604
8878
|
});
|
|
8605
8879
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8606
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSelectComponent, isStandalone: true, selector: "uni-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <!-- [selected] evaluates during the option's own render, so a selection\n pointing at an option added in the same change-detection pass still\n applies (the select-level [value] write lands before new options\n exist and is ignored by the browser). -->\n <option
|
|
8880
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSelectComponent, isStandalone: true, selector: "uni-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <!-- [selected] evaluates during the option's own render, so a selection\n pointing at an option added in the same change-detection pass still\n applies (the select-level [value] write lands before new options\n exist and is ignored by the browser). -->\n <option\n [value]=\"i\"\n [selected]=\"currentSelectedIndex() === i.toString()\"\n [disabled]=\"opt.disabled ?? false\"\n >\n {{ opt.label }}\n </option>\n }\n </select>\n <uni-symbol name=\"keyboard_arrow_down\" [class]=\"arrowClass\" />\n</uni-input-box>\n", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8607
8881
|
}
|
|
8608
8882
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSelectComponent, decorators: [{
|
|
8609
8883
|
type: Component,
|
|
8610
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-select', imports: [UniInputBoxComponent, UniSymbolComponent], template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <!-- [selected] evaluates during the option's own render, so a selection\n pointing at an option added in the same change-detection pass still\n applies (the select-level [value] write lands before new options\n exist and is ignored by the browser). -->\n <option
|
|
8884
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-select', imports: [UniInputBoxComponent, UniSymbolComponent], template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <!-- [selected] evaluates during the option's own render, so a selection\n pointing at an option added in the same change-detection pass still\n applies (the select-level [value] write lands before new options\n exist and is ignored by the browser). -->\n <option\n [value]=\"i\"\n [selected]=\"currentSelectedIndex() === i.toString()\"\n [disabled]=\"opt.disabled ?? false\"\n >\n {{ opt.label }}\n </option>\n }\n </select>\n <uni-symbol name=\"keyboard_arrow_down\" [class]=\"arrowClass\" />\n</uni-input-box>\n" }]
|
|
8611
8885
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
8612
8886
|
|
|
8613
8887
|
/**
|
|
@@ -8615,6 +8889,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
8615
8889
|
* lines (the last line shortened, as real text would be), `rect` and `circle`
|
|
8616
8890
|
* render fixed shapes. The shimmer only animates when the user allows motion;
|
|
8617
8891
|
* it degrades to static blocks under `prefers-reduced-motion`.
|
|
8892
|
+
*
|
|
8893
|
+
* Color and radius are theme options with per-instance overrides, because one
|
|
8894
|
+
* app routinely needs several: skeletons on a card and on the page background
|
|
8895
|
+
* want different tints, and a pill placeholder wants a different corner than
|
|
8896
|
+
* the text bars beside it.
|
|
8618
8897
|
*/
|
|
8619
8898
|
class UniSkeletonComponent extends BaseComponent {
|
|
8620
8899
|
shape = input('text', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
@@ -8624,6 +8903,19 @@ class UniSkeletonComponent extends BaseComponent {
|
|
|
8624
8903
|
height = input(undefined, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
|
|
8625
8904
|
/** Number of text lines (text shape only). */
|
|
8626
8905
|
lines = input(1, ...(ngDevMode ? [{ debugName: "lines" }] : /* istanbul ignore next */ []));
|
|
8906
|
+
/** Base color token; overrides the theme option for this skeleton. */
|
|
8907
|
+
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
8908
|
+
/** Shimmer highlight token; overrides the theme option for this skeleton. */
|
|
8909
|
+
highlightColor = input(undefined, ...(ngDevMode ? [{ debugName: "highlightColor" }] : /* istanbul ignore next */ []));
|
|
8910
|
+
/** Radius token; overrides the theme option. Circles are always round. */
|
|
8911
|
+
borderRadius = input(undefined, ...(ngDevMode ? [{ debugName: "borderRadius" }] : /* istanbul ignore next */ []));
|
|
8912
|
+
/**
|
|
8913
|
+
* Announces the skeleton to assistive tech as a polite status. Leave unset
|
|
8914
|
+
* when a container already carries `aria-busy` — the skeleton then stays
|
|
8915
|
+
* `aria-hidden`, as a decorative placeholder should.
|
|
8916
|
+
*/
|
|
8917
|
+
label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
8918
|
+
srOnly = css(visuallyHidden);
|
|
8627
8919
|
cssSize = (value) => typeof value === 'number' ? `${value}px` : value;
|
|
8628
8920
|
resolvedHeight = computed(() => {
|
|
8629
8921
|
const height = this.height();
|
|
@@ -8641,36 +8933,61 @@ class UniSkeletonComponent extends BaseComponent {
|
|
|
8641
8933
|
// Multi-line text blocks end on a short line, like real paragraphs do.
|
|
8642
8934
|
return Array.from({ length: lines }, (_, i) => lines > 1 && i === lines - 1 ? (width ?? '60%') : (width ?? '100%'));
|
|
8643
8935
|
}, ...(ngDevMode ? [{ debugName: "lineWidths" }] : /* istanbul ignore next */ []));
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8936
|
+
/**
|
|
8937
|
+
* The band is `bandWidth`% of the block, so it clears the block after
|
|
8938
|
+
* travelling `100 / bandWidth` of its own width — the offsets below are
|
|
8939
|
+
* percentages of the band, not of the block.
|
|
8940
|
+
*/
|
|
8941
|
+
sweep = (bandWidth, direction) => {
|
|
8942
|
+
const travel = `${Number(((100 / bandWidth) * 100).toFixed(2))}%`;
|
|
8943
|
+
const [from, to] = direction === 'rtl' ? [travel, '-100%'] : ['-100%', travel];
|
|
8944
|
+
return keyframes({
|
|
8945
|
+
from: { transform: `translateX(${from})` },
|
|
8946
|
+
to: { transform: `translateX(${to})` },
|
|
8947
|
+
});
|
|
8948
|
+
};
|
|
8648
8949
|
className = computed(() => {
|
|
8649
8950
|
const options = this.componentOptions();
|
|
8650
|
-
const base = this.theme.colors()[options.color ?? 'surface-variant'];
|
|
8651
|
-
const highlight = this.theme.colors()[options.highlightColor ?? 'surface'];
|
|
8951
|
+
const base = this.theme.colors()[this.color() ?? options.color ?? 'surface-variant'];
|
|
8952
|
+
const highlight = this.theme.colors()[this.highlightColor() ?? options.highlightColor ?? 'surface'];
|
|
8652
8953
|
const animated = (options.animation ?? 'shimmer') === 'shimmer';
|
|
8954
|
+
const bandWidth = Math.max(1, options.highlightWidth ?? 40);
|
|
8653
8955
|
return css({
|
|
8654
8956
|
display: 'flex',
|
|
8655
8957
|
flexDirection: 'column',
|
|
8656
8958
|
...this.theme.gap(options.gap),
|
|
8657
8959
|
'& .uni-skeleton-block': {
|
|
8960
|
+
position: 'relative',
|
|
8961
|
+
overflow: 'hidden',
|
|
8658
8962
|
height: this.resolvedHeight(),
|
|
8659
8963
|
backgroundColor: base,
|
|
8660
8964
|
...(this.shape() === 'circle'
|
|
8661
8965
|
? { borderRadius: '50%', flex: 'none' }
|
|
8662
|
-
: this.theme.radius(options.borderRadius)),
|
|
8966
|
+
: this.theme.radius(this.borderRadius() ?? options.borderRadius)),
|
|
8663
8967
|
...(animated &&
|
|
8664
8968
|
motionSafe({
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8969
|
+
// A translated band composites; animating background-position
|
|
8970
|
+
// repaints the block every frame. Both gradient ends are the base
|
|
8971
|
+
// color, so the band dissolves into the block with no alpha and
|
|
8972
|
+
// no fringing where it meets the edges.
|
|
8973
|
+
'&::after': {
|
|
8974
|
+
content: '""',
|
|
8975
|
+
position: 'absolute',
|
|
8976
|
+
insetBlock: 0,
|
|
8977
|
+
left: 0,
|
|
8978
|
+
width: `${bandWidth}%`,
|
|
8979
|
+
backgroundImage: `linear-gradient(90deg, ${base} 0%, ${highlight} 50%, ${base} 100%)`,
|
|
8980
|
+
animation: `${this.sweep(bandWidth, options.direction ?? 'ltr')} ${options.duration ?? 1.4}s ease-in-out infinite`,
|
|
8981
|
+
},
|
|
8668
8982
|
})),
|
|
8669
8983
|
},
|
|
8670
8984
|
});
|
|
8671
8985
|
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
8672
8986
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSkeletonComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
8673
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSkeletonComponent, isStandalone: true, selector: "uni-skeleton", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null } },
|
|
8987
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSkeletonComponent, isStandalone: true, selector: "uni-skeleton", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, highlightColor: { classPropertyName: "highlightColor", publicName: "highlightColor", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "attr.aria-hidden": "label() ? null : true", "attr.role": "label() ? 'status' : null" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'skeleton' }], usesInheritance: true, ngImport: i0, template: `
|
|
8988
|
+
@if (label(); as text) {
|
|
8989
|
+
<span [class]="srOnly">{{ text }}</span>
|
|
8990
|
+
}
|
|
8674
8991
|
@for (line of lineWidths(); track $index) {
|
|
8675
8992
|
<div class="uni-skeleton-block" [style.width]="line"></div>
|
|
8676
8993
|
}
|
|
@@ -8682,14 +8999,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
8682
8999
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
8683
9000
|
selector: 'uni-skeleton',
|
|
8684
9001
|
providers: [{ provide: COMPONENT_NAME, useValue: 'skeleton' }],
|
|
8685
|
-
host: {
|
|
9002
|
+
host: {
|
|
9003
|
+
'[class]': 'className()',
|
|
9004
|
+
'[attr.aria-hidden]': 'label() ? null : true',
|
|
9005
|
+
'[attr.role]': "label() ? 'status' : null",
|
|
9006
|
+
},
|
|
8686
9007
|
template: `
|
|
9008
|
+
@if (label(); as text) {
|
|
9009
|
+
<span [class]="srOnly">{{ text }}</span>
|
|
9010
|
+
}
|
|
8687
9011
|
@for (line of lineWidths(); track $index) {
|
|
8688
9012
|
<div class="uni-skeleton-block" [style.width]="line"></div>
|
|
8689
9013
|
}
|
|
8690
9014
|
`,
|
|
8691
9015
|
}]
|
|
8692
|
-
}], propDecorators: { shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }] } });
|
|
9016
|
+
}], propDecorators: { shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], highlightColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightColor", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
8693
9017
|
|
|
8694
9018
|
/**
|
|
8695
9019
|
* Range slider on a native `<input type="range">` — keyboard interaction and
|
|
@@ -9492,12 +9816,21 @@ class UniTagInputComponent extends BaseComponent {
|
|
|
9492
9816
|
rejected = output();
|
|
9493
9817
|
inputRef = viewChild.required('field');
|
|
9494
9818
|
chipRefs = viewChildren('chip', ...(ngDevMode ? [{ debugName: "chipRefs" }] : /* istanbul ignore next */ []));
|
|
9819
|
+
listRef = viewChild('listbox', ...(ngDevMode ? [{ debugName: "listRef" }] : /* istanbul ignore next */ []));
|
|
9820
|
+
/** Ties the popup to the field so the browser tracks it in the top layer. */
|
|
9821
|
+
anchor = newListboxAnchor();
|
|
9822
|
+
/** `manual` where the top layer is usable, else null — see the popup helper. */
|
|
9823
|
+
popupAttr = listboxPopupAttr();
|
|
9824
|
+
constructor() {
|
|
9825
|
+
super();
|
|
9826
|
+
promoteListboxPopup(this.listRef);
|
|
9827
|
+
}
|
|
9495
9828
|
/** Uncommitted text in the field. */
|
|
9496
9829
|
draft = signal('', ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
9497
9830
|
/** Index of the focused chip, or -1 when focus is in the text input. */
|
|
9498
9831
|
focusedChip = signal(-1, ...(ngDevMode ? [{ debugName: "focusedChip" }] : /* istanbul ignore next */ []));
|
|
9499
|
-
/**
|
|
9500
|
-
|
|
9832
|
+
/** Adds, removes and refusals are otherwise silent to a screen reader. */
|
|
9833
|
+
announcer = createAnnouncer();
|
|
9501
9834
|
hintId = uniqueId('uni-tag-input-hint');
|
|
9502
9835
|
srOnly = css(visuallyHidden);
|
|
9503
9836
|
queryTimer;
|
|
@@ -9563,13 +9896,13 @@ class UniTagInputComponent extends BaseComponent {
|
|
|
9563
9896
|
};
|
|
9564
9897
|
this.value.update((items) => [...items, item]);
|
|
9565
9898
|
this.added.emit(item);
|
|
9566
|
-
this.announce(`${this.labelOf(item)} added. ${this.value().length} ${this.countNoun()}.`);
|
|
9899
|
+
this.announcer.announce(`${this.labelOf(item)} added. ${this.value().length} ${this.countNoun()}.`);
|
|
9567
9900
|
return true;
|
|
9568
9901
|
}
|
|
9569
9902
|
reject(raw, reason) {
|
|
9570
9903
|
this.rejected.emit({ raw, reason });
|
|
9571
9904
|
// The visual cue is a brief pulse a screen reader cannot see.
|
|
9572
|
-
this.announce(reason === 'duplicate' ? `${raw} is already added.` : `${raw} was not added: limit reached.`);
|
|
9905
|
+
this.announcer.announce(reason === 'duplicate' ? `${raw} is already added.` : `${raw} was not added: limit reached.`);
|
|
9573
9906
|
}
|
|
9574
9907
|
removeAt(index, focus = 'input') {
|
|
9575
9908
|
const item = this.value()[index];
|
|
@@ -9577,7 +9910,7 @@ class UniTagInputComponent extends BaseComponent {
|
|
|
9577
9910
|
return;
|
|
9578
9911
|
this.value.update((items) => items.filter((_, i) => i !== index));
|
|
9579
9912
|
this.removed.emit(item);
|
|
9580
|
-
this.announce(`${this.labelOf(item)} removed. ${this.value().length} ${this.countNoun()}.`);
|
|
9913
|
+
this.announcer.announce(`${this.labelOf(item)} removed. ${this.value().length} ${this.countNoun()}.`);
|
|
9581
9914
|
const remaining = this.value().length;
|
|
9582
9915
|
if (focus === 'left' && index > 0)
|
|
9583
9916
|
this.focusChip(index - 1);
|
|
@@ -9589,10 +9922,6 @@ class UniTagInputComponent extends BaseComponent {
|
|
|
9589
9922
|
countNoun() {
|
|
9590
9923
|
return this.value().length === 1 ? 'item' : 'items';
|
|
9591
9924
|
}
|
|
9592
|
-
announce(message) {
|
|
9593
|
-
// Re-announce identical text by breaking the string equality.
|
|
9594
|
-
this.announcement.set(this.announcement() === message ? `${message} ` : message);
|
|
9595
|
-
}
|
|
9596
9925
|
// --- Focus ---------------------------------------------------------------
|
|
9597
9926
|
focusInput() {
|
|
9598
9927
|
this.focusedChip.set(-1);
|
|
@@ -9765,7 +10094,11 @@ class UniTagInputComponent extends BaseComponent {
|
|
|
9765
10094
|
input.value = text;
|
|
9766
10095
|
}
|
|
9767
10096
|
// --- Styling -------------------------------------------------------------
|
|
9768
|
-
|
|
10097
|
+
/** The host is the popup's anchor — the box the list mirrors the width of,
|
|
10098
|
+
and the one its entry animation is measured against. The wrapper below
|
|
10099
|
+
has the same geometry but is only the fallback's positioning context. */
|
|
10100
|
+
className = computed(() => css({ display: 'block', ...this.anchor.style }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
10101
|
+
wrapperClass = computed(() => css({ position: 'relative' }), ...(ngDevMode ? [{ debugName: "wrapperClass" }] : /* istanbul ignore next */ []));
|
|
9769
10102
|
fieldClass = computed(() => {
|
|
9770
10103
|
const options = this.componentOptions();
|
|
9771
10104
|
return css({
|
|
@@ -9789,14 +10122,14 @@ class UniTagInputComponent extends BaseComponent {
|
|
|
9789
10122
|
font: 'inherit',
|
|
9790
10123
|
padding: 0,
|
|
9791
10124
|
}), ...(ngDevMode ? [{ debugName: "inputClass" }] : /* istanbul ignore next */ []));
|
|
9792
|
-
listClass = computed(() => css(listboxPopupStyles(this.theme, this.componentOptions())), ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
|
|
9793
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTagInputComponent, deps:
|
|
9794
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTagInputComponent, isStandalone: true, selector: "uni-tag-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, preset: { classPropertyName: "preset", publicName: "preset", isSignal: true, isRequired: false, transformFunction: null }, separators: { classPropertyName: "separators", publicName: "separators", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, validate: { classPropertyName: "validate", publicName: "validate", isSignal: true, isRequired: false, transformFunction: null }, parse: { classPropertyName: "parse", publicName: "parse", isSignal: true, isRequired: false, transformFunction: null }, tagVariant: { classPropertyName: "tagVariant", publicName: "tagVariant", isSignal: true, isRequired: false, transformFunction: null }, tagTone: { classPropertyName: "tagTone", publicName: "tagTone", isSignal: true, isRequired: false, transformFunction: null }, tagSize: { classPropertyName: "tagSize", publicName: "tagSize", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", query: "query", added: "added", removed: "removed", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'tagInput' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "chipRefs", predicate: ["chip"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so the list closes only when focus\n leaves the whole field, not while moving between chips and the input. -->\n<div
|
|
10125
|
+
listClass = computed(() => css(listboxPopupStyles(this.theme, this.componentOptions(), { anchor: this.anchor.name })), ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
|
|
10126
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTagInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10127
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTagInputComponent, isStandalone: true, selector: "uni-tag-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, preset: { classPropertyName: "preset", publicName: "preset", isSignal: true, isRequired: false, transformFunction: null }, separators: { classPropertyName: "separators", publicName: "separators", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, allowDuplicates: { classPropertyName: "allowDuplicates", publicName: "allowDuplicates", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, validate: { classPropertyName: "validate", publicName: "validate", isSignal: true, isRequired: false, transformFunction: null }, parse: { classPropertyName: "parse", publicName: "parse", isSignal: true, isRequired: false, transformFunction: null }, tagVariant: { classPropertyName: "tagVariant", publicName: "tagVariant", isSignal: true, isRequired: false, transformFunction: null }, tagTone: { classPropertyName: "tagTone", publicName: "tagTone", isSignal: true, isRequired: false, transformFunction: null }, tagSize: { classPropertyName: "tagSize", publicName: "tagSize", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", query: "query", added: "added", removed: "removed", rejected: "rejected" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'tagInput' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "chipRefs", predicate: ["chip"], descendants: true, isSignal: true }, { propertyName: "listRef", first: true, predicate: ["listbox"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Focusout rides the bubbling event so the list closes only when focus\n leaves the whole field, not while moving between chips and the input. -->\n<div [class]=\"wrapperClass()\" (focusout)=\"onFocusOut($event)\">\n <uni-input-box [error]=\"showError()\" height=\"auto\">\n <ul [class]=\"fieldClass()\">\n @for (item of value(); track item.value; let i = $index) {\n <!-- The focusable element is the chip's own button; this <li> only\n receives keys bubbling up from it, so it must stay out of the tab\n order (same delegation the menu uses for its roving focus). -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <li #chip (keydown)=\"onChipKeydown($event, i)\" (dblclick)=\"editChip(i)\">\n <uni-tag\n [label]=\"labelOf(item)\"\n [value]=\"item.value\"\n [avatarSrc]=\"item.avatarSrc\"\n [variant]=\"item.invalid ? 'warn' : tagVariant()\"\n [tone]=\"tagTone()\"\n [size]=\"tagSize() ?? componentOptions().chipSize ?? 'md'\"\n [invalid]=\"!!item.invalid\"\n [disabled]=\"!!item.disabled || disabled()\"\n [interactive]=\"true\"\n [removable]=\"!item.disabled && !disabled()\"\n [controlTabIndex]=\"-1\"\n (removed)=\"removeAt(i)\"\n />\n </li>\n }\n\n <li [class]=\"inputClass()\">\n <!-- The field is one tab stop: chips carry tabindex=\"-1\" and are\n entered with Backspace/ArrowLeft, so Tab never walks through\n eight recipients to reach the next control. -->\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"placeholder() ?? ''\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"list.open()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput($any($event.target).value)\"\n (paste)=\"onPaste($event)\"\n (blur)=\"onBlur()\"\n />\n </li>\n </ul>\n </uni-input-box>\n\n @if (list.open()) {\n <ul\n #listbox\n [id]=\"list.listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @for (suggestion of visibleSuggestions(); track suggestion.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"i === list.activeIndex()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"selectSuggestion(suggestion)\"\n >\n {{ labelOf(suggestion) }}\n @if (suggestion.description) {\n <span [class]=\"srOnly\">{{ suggestion.description }}</span>\n }\n </li>\n }\n </ul>\n }\n\n <!-- Said once for the whole field, rather than every chip advertising it. -->\n <span [id]=\"hintId\" [class]=\"srOnly\">\n Press Backspace to reach the last entry, then Backspace again to remove it.\n </span>\n\n <!-- Adds and removes are otherwise silent for a screen reader. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }, { kind: "component", type: UniTagComponent, selector: "uni-tag", inputs: ["size", "tone", "label", "value", "maxWidth", "avatarSrc", "avatarName", "iconName", "symbolName", "dot", "removable", "interactive", "selected", "invalid", "disabled", "removeLabel", "controlTabIndex"], outputs: ["removed", "activated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9795
10128
|
}
|
|
9796
10129
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTagInputComponent, decorators: [{
|
|
9797
10130
|
type: Component,
|
|
9798
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-tag-input', imports: [UniInputBoxComponent, UniTagComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'tagInput' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so the list closes only when focus\n leaves the whole field, not while moving between chips and the input. -->\n<div
|
|
9799
|
-
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], preset: [{ type: i0.Input, args: [{ isSignal: true, alias: "preset", required: false }] }], separators: [{ type: i0.Input, args: [{ isSignal: true, alias: "separators", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], parse: [{ type: i0.Input, args: [{ isSignal: true, alias: "parse", required: false }] }], tagVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagVariant", required: false }] }], tagTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagTone", required: false }] }], tagSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagSize", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], query: [{ type: i0.Output, args: ["query"] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], added: [{ type: i0.Output, args: ["added"] }], removed: [{ type: i0.Output, args: ["removed"] }], rejected: [{ type: i0.Output, args: ["rejected"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], chipRefs: [{ type: i0.ViewChildren, args: ['chip', { isSignal: true }] }] } });
|
|
10131
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-tag-input', imports: [UniInputBoxComponent, UniTagComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'tagInput' }], host: { '[class]': 'className()' }, template: "<!-- Focusout rides the bubbling event so the list closes only when focus\n leaves the whole field, not while moving between chips and the input. -->\n<div [class]=\"wrapperClass()\" (focusout)=\"onFocusOut($event)\">\n <uni-input-box [error]=\"showError()\" height=\"auto\">\n <ul [class]=\"fieldClass()\">\n @for (item of value(); track item.value; let i = $index) {\n <!-- The focusable element is the chip's own button; this <li> only\n receives keys bubbling up from it, so it must stay out of the tab\n order (same delegation the menu uses for its roving focus). -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <li #chip (keydown)=\"onChipKeydown($event, i)\" (dblclick)=\"editChip(i)\">\n <uni-tag\n [label]=\"labelOf(item)\"\n [value]=\"item.value\"\n [avatarSrc]=\"item.avatarSrc\"\n [variant]=\"item.invalid ? 'warn' : tagVariant()\"\n [tone]=\"tagTone()\"\n [size]=\"tagSize() ?? componentOptions().chipSize ?? 'md'\"\n [invalid]=\"!!item.invalid\"\n [disabled]=\"!!item.disabled || disabled()\"\n [interactive]=\"true\"\n [removable]=\"!item.disabled && !disabled()\"\n [controlTabIndex]=\"-1\"\n (removed)=\"removeAt(i)\"\n />\n </li>\n }\n\n <li [class]=\"inputClass()\">\n <!-- The field is one tab stop: chips carry tabindex=\"-1\" and are\n entered with Backspace/ArrowLeft, so Tab never walks through\n eight recipients to reach the next control. -->\n <input\n #field\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n [class]=\"inputClass()\"\n [disabled]=\"disabled()\"\n [placeholder]=\"placeholder() ?? ''\"\n [attr.aria-label]=\"label()\"\n [attr.aria-expanded]=\"list.open()\"\n [attr.aria-controls]=\"list.listboxId\"\n [attr.aria-activedescendant]=\"list.activeDescendantId()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (keydown)=\"onInputKeydown($event)\"\n (input)=\"onInput($any($event.target).value)\"\n (paste)=\"onPaste($event)\"\n (blur)=\"onBlur()\"\n />\n </li>\n </ul>\n </uni-input-box>\n\n @if (list.open()) {\n <ul\n #listbox\n [id]=\"list.listboxId\"\n role=\"listbox\"\n [attr.popover]=\"popupAttr\"\n [attr.aria-label]=\"label()\"\n [class]=\"listClass()\"\n >\n @for (suggestion of visibleSuggestions(); track suggestion.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"list.optionId(i)\"\n [class.active]=\"i === list.activeIndex()\"\n [attr.aria-selected]=\"i === list.activeIndex()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"selectSuggestion(suggestion)\"\n >\n {{ labelOf(suggestion) }}\n @if (suggestion.description) {\n <span [class]=\"srOnly\">{{ suggestion.description }}</span>\n }\n </li>\n }\n </ul>\n }\n\n <!-- Said once for the whole field, rather than every chip advertising it. -->\n <span [id]=\"hintId\" [class]=\"srOnly\">\n Press Backspace to reach the last entry, then Backspace again to remove it.\n </span>\n\n <!-- Adds and removes are otherwise silent for a screen reader. -->\n <span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n</div>\n" }]
|
|
10132
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], preset: [{ type: i0.Input, args: [{ isSignal: true, alias: "preset", required: false }] }], separators: [{ type: i0.Input, args: [{ isSignal: true, alias: "separators", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], parse: [{ type: i0.Input, args: [{ isSignal: true, alias: "parse", required: false }] }], tagVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagVariant", required: false }] }], tagTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagTone", required: false }] }], tagSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagSize", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], query: [{ type: i0.Output, args: ["query"] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], added: [{ type: i0.Output, args: ["added"] }], removed: [{ type: i0.Output, args: ["removed"] }], rejected: [{ type: i0.Output, args: ["rejected"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], chipRefs: [{ type: i0.ViewChildren, args: ['chip', { isSignal: true }] }], listRef: [{ type: i0.ViewChild, args: ['listbox', { isSignal: true }] }] } });
|
|
9800
10133
|
|
|
9801
10134
|
/**
|
|
9802
10135
|
* UniTagInputComponent Barrel File
|
|
@@ -11090,7 +11423,9 @@ class UniTourComponent extends BaseComponent {
|
|
|
11090
11423
|
skipped = output();
|
|
11091
11424
|
calloutOpen = signal(false, ...(ngDevMode ? [{ debugName: "calloutOpen" }] : /* istanbul ignore next */ []));
|
|
11092
11425
|
satisfied = signal(true, ...(ngDevMode ? [{ debugName: "satisfied" }] : /* istanbul ignore next */ []));
|
|
11093
|
-
|
|
11426
|
+
/** Repeats must still be heard: the same gate message can come round
|
|
11427
|
+
again on a later step. */
|
|
11428
|
+
announcer = createAnnouncer();
|
|
11094
11429
|
resolvedTarget = signal(undefined, ...(ngDevMode ? [{ debugName: "resolvedTarget" }] : /* istanbul ignore next */ []));
|
|
11095
11430
|
presentedIndex = signal(null, ...(ngDevMode ? [{ debugName: "presentedIndex" }] : /* istanbul ignore next */ []));
|
|
11096
11431
|
gateCleanup = null;
|
|
@@ -11194,7 +11529,7 @@ class UniTourComponent extends BaseComponent {
|
|
|
11194
11529
|
this.advance();
|
|
11195
11530
|
}
|
|
11196
11531
|
else {
|
|
11197
|
-
this.
|
|
11532
|
+
this.announcer.announce('Next available');
|
|
11198
11533
|
}
|
|
11199
11534
|
});
|
|
11200
11535
|
this.gateCleanup = () => {
|
|
@@ -11262,11 +11597,11 @@ class UniTourComponent extends BaseComponent {
|
|
|
11262
11597
|
}, ...(ngDevMode ? [{ debugName: "dotsClassName" }] : /* istanbul ignore next */ []));
|
|
11263
11598
|
fractionClassName = css({ margin: '0 auto' });
|
|
11264
11599
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTourComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11265
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTourComponent, isStandalone: true, selector: "uni-tour", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, skipLabel: { classPropertyName: "skipLabel", publicName: "skipLabel", isSignal: true, isRequired: false, transformFunction: null }, doneLabel: { classPropertyName: "doneLabel", publicName: "doneLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange", started: "started", stepChanged: "stepChanged", finished: "finished", skipped: "skipped" }, providers: [{ provide: COMPONENT_NAME, useValue: 'tour' }], usesInheritance: true, ngImport: i0, template: "<uni-callout\n [(open)]=\"calloutOpen\"\n [key]=\"currentStep()?.key ?? ''\"\n [target]=\"resolvedTarget()\"\n [placement]=\"currentStep()?.placement ?? 'bottom'\"\n [backdrop]=\"currentStep()?.backdrop\"\n [targetInteractive]=\"targetInteractive()\"\n [header]=\"currentStep()?.title ?? ''\"\n [ariaLabel]=\"stepAriaLabel()\"\n [closeLabel]=\"skipLabel()\"\n (dismissed)=\"onDismissed($event)\"\n (panelKeydown)=\"onPanelKeydown($event)\"\n>\n <p>{{ currentStep()?.body }}</p>\n <div callout-actions [class]=\"footerClassName()\">\n @if (index() > 0) {\n <button text-button variant=\"ghost\" (click)=\"back()\">{{ backLabel() }}</button>\n }\n @if (componentOptions().progressStyle === 'fraction') {\n <span aria-hidden=\"true\" [class]=\"fractionClassName\">{{ index() + 1 }} of {{ steps().length }}</span>\n } @else {\n <span aria-hidden=\"true\" [class]=\"dotsClassName()\">\n @for (step of steps(); track $index) {\n <i [class.on]=\"$index === index()\"></i>\n }\n </span>\n }\n <!-- A click-gate advances by using the target itself \u2014 a Next button\n would be a lie, so none renders. -->\n @if (!clickGate()) {\n <button text-button [disable]=\"!satisfied()\" (click)=\"advance()\">\n {{ isLast() ? doneLabel() : nextLabel() }}\n </button>\n }\n </div>\n</uni-callout>\n<!-- One live region per tour: gate unlocks are announced here. -->\n<span role=\"status\" [class]=\"statusClassName\">{{
|
|
11600
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTourComponent, isStandalone: true, selector: "uni-tour", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, skipLabel: { classPropertyName: "skipLabel", publicName: "skipLabel", isSignal: true, isRequired: false, transformFunction: null }, doneLabel: { classPropertyName: "doneLabel", publicName: "doneLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange", started: "started", stepChanged: "stepChanged", finished: "finished", skipped: "skipped" }, providers: [{ provide: COMPONENT_NAME, useValue: 'tour' }], usesInheritance: true, ngImport: i0, template: "<uni-callout\n [(open)]=\"calloutOpen\"\n [key]=\"currentStep()?.key ?? ''\"\n [target]=\"resolvedTarget()\"\n [placement]=\"currentStep()?.placement ?? 'bottom'\"\n [backdrop]=\"currentStep()?.backdrop\"\n [targetInteractive]=\"targetInteractive()\"\n [header]=\"currentStep()?.title ?? ''\"\n [ariaLabel]=\"stepAriaLabel()\"\n [closeLabel]=\"skipLabel()\"\n (dismissed)=\"onDismissed($event)\"\n (panelKeydown)=\"onPanelKeydown($event)\"\n>\n <p>{{ currentStep()?.body }}</p>\n <div callout-actions [class]=\"footerClassName()\">\n @if (index() > 0) {\n <button text-button variant=\"ghost\" (click)=\"back()\">{{ backLabel() }}</button>\n }\n @if (componentOptions().progressStyle === 'fraction') {\n <span aria-hidden=\"true\" [class]=\"fractionClassName\">{{ index() + 1 }} of {{ steps().length }}</span>\n } @else {\n <span aria-hidden=\"true\" [class]=\"dotsClassName()\">\n @for (step of steps(); track $index) {\n <i [class.on]=\"$index === index()\"></i>\n }\n </span>\n }\n <!-- A click-gate advances by using the target itself \u2014 a Next button\n would be a lie, so none renders. -->\n @if (!clickGate()) {\n <button text-button [disable]=\"!satisfied()\" (click)=\"advance()\">\n {{ isLast() ? doneLabel() : nextLabel() }}\n </button>\n }\n </div>\n</uni-callout>\n<!-- One live region per tour: gate unlocks are announced here. -->\n<span role=\"status\" [class]=\"statusClassName\">{{ announcer.message() }}</span>\n", dependencies: [{ kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }, { kind: "component", type: UniCalloutComponent, selector: "uni-callout", inputs: ["open", "key", "target", "placement", "backdrop", "targetInteractive", "dismissible", "dismissOnBackdrop", "header", "arrow", "ariaLabel", "closeLabel"], outputs: ["openChange", "opened", "closed", "dismissed", "panelKeydown"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11266
11601
|
}
|
|
11267
11602
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTourComponent, decorators: [{
|
|
11268
11603
|
type: Component,
|
|
11269
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-tour', imports: [UniButtonComponent, UniCalloutComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'tour' }], template: "<uni-callout\n [(open)]=\"calloutOpen\"\n [key]=\"currentStep()?.key ?? ''\"\n [target]=\"resolvedTarget()\"\n [placement]=\"currentStep()?.placement ?? 'bottom'\"\n [backdrop]=\"currentStep()?.backdrop\"\n [targetInteractive]=\"targetInteractive()\"\n [header]=\"currentStep()?.title ?? ''\"\n [ariaLabel]=\"stepAriaLabel()\"\n [closeLabel]=\"skipLabel()\"\n (dismissed)=\"onDismissed($event)\"\n (panelKeydown)=\"onPanelKeydown($event)\"\n>\n <p>{{ currentStep()?.body }}</p>\n <div callout-actions [class]=\"footerClassName()\">\n @if (index() > 0) {\n <button text-button variant=\"ghost\" (click)=\"back()\">{{ backLabel() }}</button>\n }\n @if (componentOptions().progressStyle === 'fraction') {\n <span aria-hidden=\"true\" [class]=\"fractionClassName\">{{ index() + 1 }} of {{ steps().length }}</span>\n } @else {\n <span aria-hidden=\"true\" [class]=\"dotsClassName()\">\n @for (step of steps(); track $index) {\n <i [class.on]=\"$index === index()\"></i>\n }\n </span>\n }\n <!-- A click-gate advances by using the target itself \u2014 a Next button\n would be a lie, so none renders. -->\n @if (!clickGate()) {\n <button text-button [disable]=\"!satisfied()\" (click)=\"advance()\">\n {{ isLast() ? doneLabel() : nextLabel() }}\n </button>\n }\n </div>\n</uni-callout>\n<!-- One live region per tour: gate unlocks are announced here. -->\n<span role=\"status\" [class]=\"statusClassName\">{{
|
|
11604
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-tour', imports: [UniButtonComponent, UniCalloutComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'tour' }], template: "<uni-callout\n [(open)]=\"calloutOpen\"\n [key]=\"currentStep()?.key ?? ''\"\n [target]=\"resolvedTarget()\"\n [placement]=\"currentStep()?.placement ?? 'bottom'\"\n [backdrop]=\"currentStep()?.backdrop\"\n [targetInteractive]=\"targetInteractive()\"\n [header]=\"currentStep()?.title ?? ''\"\n [ariaLabel]=\"stepAriaLabel()\"\n [closeLabel]=\"skipLabel()\"\n (dismissed)=\"onDismissed($event)\"\n (panelKeydown)=\"onPanelKeydown($event)\"\n>\n <p>{{ currentStep()?.body }}</p>\n <div callout-actions [class]=\"footerClassName()\">\n @if (index() > 0) {\n <button text-button variant=\"ghost\" (click)=\"back()\">{{ backLabel() }}</button>\n }\n @if (componentOptions().progressStyle === 'fraction') {\n <span aria-hidden=\"true\" [class]=\"fractionClassName\">{{ index() + 1 }} of {{ steps().length }}</span>\n } @else {\n <span aria-hidden=\"true\" [class]=\"dotsClassName()\">\n @for (step of steps(); track $index) {\n <i [class.on]=\"$index === index()\"></i>\n }\n </span>\n }\n <!-- A click-gate advances by using the target itself \u2014 a Next button\n would be a lie, so none renders. -->\n @if (!clickGate()) {\n <button text-button [disable]=\"!satisfied()\" (click)=\"advance()\">\n {{ isLast() ? doneLabel() : nextLabel() }}\n </button>\n }\n </div>\n</uni-callout>\n<!-- One live region per tour: gate unlocks are announced here. -->\n<span role=\"status\" [class]=\"statusClassName\">{{ announcer.message() }}</span>\n" }]
|
|
11270
11605
|
}], ctorParameters: () => [], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }, { type: i0.Output, args: ["activeChange"] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], backLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "backLabel", required: false }] }], skipLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLabel", required: false }] }], doneLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "doneLabel", required: false }] }], started: [{ type: i0.Output, args: ["started"] }], stepChanged: [{ type: i0.Output, args: ["stepChanged"] }], finished: [{ type: i0.Output, args: ["finished"] }], skipped: [{ type: i0.Output, args: ["skipped"] }] } });
|
|
11271
11606
|
|
|
11272
11607
|
/**
|
|
@@ -11279,5 +11614,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
11279
11614
|
* Generated bundle index. Do not edit.
|
|
11280
11615
|
*/
|
|
11281
11616
|
|
|
11282
|
-
export { BodyRenderDirective, ConfirmationDialogComponent, DragAndDropDirective, FOCUSABLE_SELECTOR, ListboxNavigation, LocalStorageService, NotificationService, NotificationsComponent, RippleDirective, TRANSFORM_ORIGINS, ThemeService, UNI_THEMES, UniAlertComponent, UniAppBarComponent, UniAvatarComponent, UniAvatarGroupComponent, UniBackgroundComponent, UniBadgeComponent, UniBaseDatasource, UniBoxComponent, UniBreadcrumbComponent, UniButtonComponent, UniButtonGroupComponent, UniCalendarComponent, UniCalloutComponent, UniCardComponent, UniCardContentComponent, UniCardHeaderComponent, UniCenterComponent, UniCheckboxComponent, UniComboboxComponent, UniDataSearchComponent, UniDataTableComponent, UniDateInputComponent, UniDateTimeInputComponent, UniDebounceInputComponent, UniDialogButtonsComponent, UniDialogComponent, UniDialogHeaderComponent, UniDividerComponent, UniDrawerComponent, UniDropdownComponent, UniExpandAreaComponent, UniExpandComponent, UniExpandToggleComponent, UniFileDropZoneComponent, UniGridAreaComponent, UniGridComponent, UniIconButtonComponent, UniIconComponent, UniInputBoxComponent, UniInputComponent, UniJsonViewComponent, UniMenuComponent, UniMultiSelectComponent, UniMultiSelectDropdownComponent, UniNotificationBadgeComponent, UniPaginatorComponent, UniPopoverComponent, UniProgressBarComponent, UniProgressGaugeComponent, UniRadioComponent, UniRecordDatasource, UniRowComponent, UniScrollAreaComponent, UniSearchInputComponent, UniSelectComponent, UniServerSideDatasource, UniSkeletonComponent, UniSliderComponent, UniSnackbarComponent, UniSortHeaderComponent, UniStackComponent, UniStatComponent, UniSymbolComponent, UniTabComponent, UniTabsComponent, UniTagComponent, UniTagInputComponent, UniTextComponent, UniTextareaComponent, UniThemeBuilderComponent, UniThemeSwitchComponent, UniTimeInputComponent, UniToggleComponent, UniTooltipComponent, UniTourComponent, UniWrapComponent, acceptableFile, addDays, addMonths, anchorArrowStyles, anchorStyles, buildMonthGrid, clearAnchorName, createListboxNavigation, dayOfWeek, daysInMonth, discreteOverlayTransition, focusableElements, formatDate, formatMonthHeading, formatTime, getFileExtension, inclusiveDayCount, isDivider, isToggleOpen, isValidDate, isoDate, joinDateTime, listboxPopupStyles, localeDatePlaceholder, localeDefaultHour12, localeFieldOrder, localeMonthNames, localeWeekStart, monthOf, motionSafe, newAnchorName, parseDateText, parseTimeText, resolveElement, resolveFocusTarget, restoreOverlayFocus, setAnchorName, splitDateTime, spotlightStyles, timeSlots, todayIso, transformOriginFor, uniqueId, useTimer, visuallyHidden, weekdayNames };
|
|
11617
|
+
export { BodyRenderDirective, ConfirmationDialogComponent, DragAndDropDirective, FOCUSABLE_SELECTOR, ListboxNavigation, LocalStorageService, NotificationService, NotificationsComponent, RippleDirective, TRANSFORM_ORIGINS, ThemeService, UNI_THEMES, UniAlertComponent, UniAppBarComponent, UniAvatarComponent, UniAvatarGroupComponent, UniBackgroundComponent, UniBadgeComponent, UniBaseDatasource, UniBoxComponent, UniBreadcrumbComponent, UniButtonComponent, UniButtonGroupComponent, UniCalendarComponent, UniCalloutComponent, UniCardComponent, UniCardContentComponent, UniCardHeaderComponent, UniCenterComponent, UniCheckboxComponent, UniComboboxComponent, UniDataSearchComponent, UniDataTableComponent, UniDateInputComponent, UniDateTimeInputComponent, UniDebounceInputComponent, UniDialogButtonsComponent, UniDialogComponent, UniDialogHeaderComponent, UniDividerComponent, UniDrawerComponent, UniDropdownComponent, UniExpandAreaComponent, UniExpandComponent, UniExpandToggleComponent, UniFileDropZoneComponent, UniGridAreaComponent, UniGridComponent, UniIconButtonComponent, UniIconComponent, UniInputBoxComponent, UniInputComponent, UniJsonViewComponent, UniMenuComponent, UniMultiSelectComponent, UniMultiSelectDropdownComponent, UniNotificationBadgeComponent, UniPaginatorComponent, UniPopoverComponent, UniProgressBarComponent, UniProgressGaugeComponent, UniRadioComponent, UniRecordDatasource, UniRowComponent, UniScrollAreaComponent, UniSearchInputComponent, UniSelectComponent, UniServerSideDatasource, UniSkeletonComponent, UniSliderComponent, UniSnackbarComponent, UniSortHeaderComponent, UniStackComponent, UniStatComponent, UniSymbolComponent, UniTabComponent, UniTabsComponent, UniTagComponent, UniTagInputComponent, UniTextComponent, UniTextareaComponent, UniThemeBuilderComponent, UniThemeSwitchComponent, UniTimeInputComponent, UniToggleComponent, UniTooltipComponent, UniTourComponent, UniWrapComponent, acceptableFile, addDays, addMonths, anchorArrowStyles, anchorStyles, buildMonthGrid, clearAnchorName, createAnnouncer, createListboxNavigation, dayOfWeek, daysInMonth, discreteOverlayTransition, focusableElements, formatDate, formatMonthHeading, formatTime, getFileExtension, inclusiveDayCount, isDivider, isToggleOpen, isValidDate, isoDate, joinDateTime, listboxPopupAttr, listboxPopupStyles, localeDatePlaceholder, localeDefaultHour12, localeFieldOrder, localeMonthNames, localeWeekStart, monthOf, motionSafe, newAnchorName, newListboxAnchor, parseDateText, parseTimeText, promoteListboxPopup, resolveElement, resolveFocusTarget, restoreOverlayFocus, setAnchorName, splitDateTime, spotlightStyles, supportsAnchoredPopup, timeSlots, todayIso, transformOriginFor, uniqueId, useTimer, visuallyHidden, weekdayNames };
|
|
11283
11618
|
//# sourceMappingURL=uni-design-system-uni-angular.mjs.map
|