@uni-design-system/uni-angular 10.0.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, inject, DestroyRef, computed, linkedSignal, resource, Injectable, InjectionToken, input, ChangeDetectionStrategy, Component, ElementRef, Directive, model, afterRenderEffect, Renderer2, output, viewChild, ViewChild, viewChildren, effect, untracked, isDevMode, contentChildren, afterNextRender, booleanAttribute } from '@angular/core';
|
|
2
|
+
import { signal, inject, DestroyRef, computed, linkedSignal, resource, Injectable, InjectionToken, input, ChangeDetectionStrategy, Component, ElementRef, Directive, model, afterRenderEffect, Renderer2, output, viewChild, ViewChild, viewChildren, effect, untracked, isDevMode, contentChildren, afterNextRender, forwardRef, booleanAttribute } from '@angular/core';
|
|
3
3
|
import { injectGlobal, css, keyframes } from '@emotion/css';
|
|
4
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 { NgTemplateOutlet, NgClass, CommonModule } from '@angular/common';
|
|
@@ -30,9 +30,23 @@ function resolveFocusTarget(element) {
|
|
|
30
30
|
/**
|
|
31
31
|
* Visually hides content while keeping it available to screen readers.
|
|
32
32
|
* Use for text alternatives (e.g. badge counts, icon-only affordances).
|
|
33
|
+
*
|
|
34
|
+
* `fixed`, not `absolute`, and that is load-bearing. An absolutely positioned
|
|
35
|
+
* box resolves its containing block to the nearest *positioned* ancestor —
|
|
36
|
+
* which, since the controls emitting these spans are `position: static`, is
|
|
37
|
+
* whatever positioned box happens to be above them in the consumer's layout,
|
|
38
|
+
* often several scroll containers up. The span then skips every intervening
|
|
39
|
+
* `overflow: auto` and lands in that distant ancestor's scrollable overflow,
|
|
40
|
+
* turning 1x1 of invisible text into real scrollable distance in a box that
|
|
41
|
+
* never opted into scrolling. A fixed box's containing block is the viewport,
|
|
42
|
+
* so it joins no ancestor's scrollable overflow at all.
|
|
43
|
+
*
|
|
44
|
+
* Caveat: inside a `transform`ed (or `filter`ed/`contain`ed) ancestor a fixed
|
|
45
|
+
* box re-anchors to that ancestor. Harmless here — the element is 1x1 and
|
|
46
|
+
* clipped to nothing, so where it lands never matters, only what it overflows.
|
|
33
47
|
*/
|
|
34
48
|
const visuallyHidden = {
|
|
35
|
-
position: '
|
|
49
|
+
position: 'fixed',
|
|
36
50
|
width: 1,
|
|
37
51
|
height: 1,
|
|
38
52
|
padding: 0,
|
|
@@ -1017,8 +1031,17 @@ function createPressRepeat(config) {
|
|
|
1017
1031
|
if (event) {
|
|
1018
1032
|
// Keeps the pointer stream on the button even when the finger slides
|
|
1019
1033
|
// off it, so `pointerup` still arrives and the run still ends.
|
|
1034
|
+
//
|
|
1035
|
+
// This also suppresses the browser's default focus handling, which is
|
|
1036
|
+
// why `focus` exists: a spinner button that leaves focus nowhere means
|
|
1037
|
+
// the arrow keys stop working the moment you click `+`, exactly when a
|
|
1038
|
+
// user is most likely to reach for them.
|
|
1020
1039
|
event.preventDefault();
|
|
1021
1040
|
const target = event.currentTarget;
|
|
1041
|
+
// The button is handed over as a fallback, for controls that have no
|
|
1042
|
+
// text field to focus (a read-only quantity stepper, where the buttons
|
|
1043
|
+
// are themselves the tab stops).
|
|
1044
|
+
config.focus?.(target instanceof HTMLElement ? target : null);
|
|
1022
1045
|
// jsdom and older engines lack the method entirely.
|
|
1023
1046
|
if (target instanceof Element && typeof target.setPointerCapture === 'function') {
|
|
1024
1047
|
try {
|
|
@@ -2533,7 +2556,7 @@ class UniCheckboxComponent extends BaseComponent {
|
|
|
2533
2556
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
2534
2557
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
2535
2558
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
2536
|
-
/** Synced from required() validators by the Signal Forms [
|
|
2559
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
2537
2560
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
2538
2561
|
/**
|
|
2539
2562
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -5311,7 +5334,7 @@ class UniInputComponent {
|
|
|
5311
5334
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
5312
5335
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
5313
5336
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
5314
|
-
/** Synced from required() validators by the Signal Forms [
|
|
5337
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
5315
5338
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
5316
5339
|
/**
|
|
5317
5340
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -5327,7 +5350,7 @@ class UniInputComponent {
|
|
|
5327
5350
|
*/
|
|
5328
5351
|
type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
5329
5352
|
// --- CONSTRAINTS ---
|
|
5330
|
-
// These are Signal Forms' own optional control inputs, so the `[
|
|
5353
|
+
// These are Signal Forms' own optional control inputs, so the `[formField]`
|
|
5331
5354
|
// directive syncs them from the field's validators the same way it syncs
|
|
5332
5355
|
// `required` — and they are reflected onto the native element so the browser
|
|
5333
5356
|
// can do its part (number steppers, length limits, on-screen keyboards).
|
|
@@ -5548,7 +5571,7 @@ class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
|
5548
5571
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
5549
5572
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
5550
5573
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
5551
|
-
/** Synced from required() validators by the Signal Forms [
|
|
5574
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
5552
5575
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
5553
5576
|
/**
|
|
5554
5577
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -5779,7 +5802,7 @@ class UniRadioComponent extends BaseComponent {
|
|
|
5779
5802
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
5780
5803
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
5781
5804
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
5782
|
-
/** Synced from required() validators by the Signal Forms [
|
|
5805
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
5783
5806
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
5784
5807
|
/**
|
|
5785
5808
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -6090,7 +6113,7 @@ class UniSelectComponent {
|
|
|
6090
6113
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
6091
6114
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
6092
6115
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
6093
|
-
/** Synced from required() validators by the Signal Forms [
|
|
6116
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
6094
6117
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
6095
6118
|
/**
|
|
6096
6119
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -6537,6 +6560,9 @@ class UniNumberInputComponent extends BaseComponent {
|
|
|
6537
6560
|
onRelease: () => this.announceValue(),
|
|
6538
6561
|
disabled: () => this.disabled() || this.readOnly() || this.atMax(),
|
|
6539
6562
|
repeat: () => this.repeat(),
|
|
6563
|
+
// A native spinner leaves focus in its field; without this the arrow keys
|
|
6564
|
+
// go dead the moment you click a stepper.
|
|
6565
|
+
focus: () => this.inputRef().nativeElement.focus(),
|
|
6540
6566
|
timing: this.repeatTiming,
|
|
6541
6567
|
});
|
|
6542
6568
|
decrement = createPressRepeat({
|
|
@@ -6544,6 +6570,9 @@ class UniNumberInputComponent extends BaseComponent {
|
|
|
6544
6570
|
onRelease: () => this.announceValue(),
|
|
6545
6571
|
disabled: () => this.disabled() || this.readOnly() || this.atMin(),
|
|
6546
6572
|
repeat: () => this.repeat(),
|
|
6573
|
+
// A native spinner leaves focus in its field; without this the arrow keys
|
|
6574
|
+
// go dead the moment you click a stepper.
|
|
6575
|
+
focus: () => this.inputRef().nativeElement.focus(),
|
|
6547
6576
|
timing: this.repeatTiming,
|
|
6548
6577
|
});
|
|
6549
6578
|
// --- Input events ---------------------------------------------------------
|
|
@@ -7947,11 +7976,13 @@ class UniQuantityStepperComponent extends BaseComponent {
|
|
|
7947
7976
|
increment = createPressRepeat({
|
|
7948
7977
|
onStep: () => this.applyStep(1, false),
|
|
7949
7978
|
onRelease: () => this.announceValue(),
|
|
7979
|
+
focus: (button) => this.focusField(button),
|
|
7950
7980
|
disabled: () => this.disabled() || this.atMax(),
|
|
7951
7981
|
});
|
|
7952
7982
|
decrement = createPressRepeat({
|
|
7953
7983
|
onStep: () => this.applyStep(-1, false),
|
|
7954
7984
|
onRelease: () => this.announceValue(),
|
|
7985
|
+
focus: (button) => this.focusField(button),
|
|
7955
7986
|
disabled: () => this.disabled() || this.atMin(),
|
|
7956
7987
|
});
|
|
7957
7988
|
// --- Keyboard -------------------------------------------------------------
|
|
@@ -7985,8 +8016,17 @@ class UniQuantityStepperComponent extends BaseComponent {
|
|
|
7985
8016
|
this.increment.cancel();
|
|
7986
8017
|
this.decrement.cancel();
|
|
7987
8018
|
}
|
|
7988
|
-
|
|
7989
|
-
|
|
8019
|
+
/**
|
|
8020
|
+
* Focus the field a stepper press should land in. With `editable=false` there
|
|
8021
|
+
* is no field and the buttons are the tab stops, so the pressed button takes
|
|
8022
|
+
* it instead.
|
|
8023
|
+
*/
|
|
8024
|
+
focusField(fallback) {
|
|
8025
|
+
const input = this.inputRef()?.nativeElement;
|
|
8026
|
+
if (input)
|
|
8027
|
+
input.focus();
|
|
8028
|
+
else
|
|
8029
|
+
fallback?.focus();
|
|
7990
8030
|
}
|
|
7991
8031
|
// --- Styling --------------------------------------------------------------
|
|
7992
8032
|
className = computed(() => css({ display: 'inline-block' }), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
@@ -8000,7 +8040,6 @@ class UniQuantityStepperComponent extends BaseComponent {
|
|
|
8000
8040
|
*/
|
|
8001
8041
|
fieldChrome = this.theme.getComponentOptions('input');
|
|
8002
8042
|
rootClass = computed(() => {
|
|
8003
|
-
const options = this.componentOptions();
|
|
8004
8043
|
const colors = this.theme.colors();
|
|
8005
8044
|
const chrome = this.fieldChrome();
|
|
8006
8045
|
return css({
|
|
@@ -8011,9 +8050,9 @@ class UniQuantityStepperComponent extends BaseComponent {
|
|
|
8011
8050
|
// field beside it rather than 32 plus its border.
|
|
8012
8051
|
boxSizing: 'border-box',
|
|
8013
8052
|
overflow: 'hidden',
|
|
8014
|
-
...this.theme.backgroundColor(this.disabled() ?
|
|
8015
|
-
...this.theme.border(
|
|
8016
|
-
...this.theme.radius(
|
|
8053
|
+
...this.theme.backgroundColor(this.disabled() ? chrome.disabledColor : this.containerColor()),
|
|
8054
|
+
...this.theme.border(this.containerBorder()),
|
|
8055
|
+
...this.theme.radius(this.containerRadius()),
|
|
8017
8056
|
...(this.showError() ? { borderColor: colors['warn'] } : {}),
|
|
8018
8057
|
...(this.disabled() ? { cursor: 'not-allowed' } : {}),
|
|
8019
8058
|
// The middle input clears its own outline (removeInputPlatformStyling),
|
|
@@ -8061,8 +8100,30 @@ class UniQuantityStepperComponent extends BaseComponent {
|
|
|
8061
8100
|
...this.theme.focusRing(),
|
|
8062
8101
|
});
|
|
8063
8102
|
}, ...(ngDevMode ? [{ debugName: "buttonClass" }] : /* istanbul ignore next */ []));
|
|
8103
|
+
/**
|
|
8104
|
+
* Container chrome, defaulting to the shared `input` entry rather than to
|
|
8105
|
+
* hardcoded tokens. It is not a field, but it sits beside them in carts and
|
|
8106
|
+
* table rows, so a theme that restyles `input` must carry it along — the
|
|
8107
|
+
* options below stay as per-component overrides for a deliberately different
|
|
8108
|
+
* look.
|
|
8109
|
+
*/
|
|
8110
|
+
containerColor = computed(() => this.componentOptions().color ?? this.fieldChrome().color, ...(ngDevMode ? [{ debugName: "containerColor" }] : /* istanbul ignore next */ []));
|
|
8111
|
+
containerBorder = computed(() => this.componentOptions().border ?? this.fieldChrome().border, ...(ngDevMode ? [{ debugName: "containerBorder" }] : /* istanbul ignore next */ []));
|
|
8112
|
+
containerRadius = computed(() => this.componentOptions().borderRadius ?? this.fieldChrome().borderRadius, ...(ngDevMode ? [{ debugName: "containerRadius" }] : /* istanbul ignore next */ []));
|
|
8064
8113
|
/** The rules either side of the value, matching the frame around it. */
|
|
8065
|
-
dividerBorder = computed(() => this.
|
|
8114
|
+
dividerBorder = computed(() => this.containerBorder(), ...(ngDevMode ? [{ debugName: "dividerBorder" }] : /* istanbul ignore next */ []));
|
|
8115
|
+
/**
|
|
8116
|
+
* Characters the value cell asks the browser to size itself for.
|
|
8117
|
+
*
|
|
8118
|
+
* Load-bearing: a bare `<input>` defaults to `size="20"`, and `flex-basis:
|
|
8119
|
+
* auto` resolves to that intrinsic width — so the control claimed ~230px
|
|
8120
|
+
* instead of the ~100px its buttons and `valueWidth` need, and stole track
|
|
8121
|
+
* width from anything beside it in a grid (`1fr` is `minmax(auto, 1fr)`, and
|
|
8122
|
+
* the `auto` floor includes this). Tracking the content keeps the cell honest
|
|
8123
|
+
* while still letting it grow with the digits, which a fixed `width` would
|
|
8124
|
+
* not. `valueWidth` remains the floor, via `min-width`.
|
|
8125
|
+
*/
|
|
8126
|
+
valueSize = computed(() => Math.max(this.displayText().length, 1), ...(ngDevMode ? [{ debugName: "valueSize" }] : /* istanbul ignore next */ []));
|
|
8066
8127
|
valueBase() {
|
|
8067
8128
|
const options = this.componentOptions();
|
|
8068
8129
|
const colors = this.theme.colors();
|
|
@@ -8095,11 +8156,11 @@ class UniQuantityStepperComponent extends BaseComponent {
|
|
|
8095
8156
|
readoutClass = computed(() => css([this.valueBase(), { display: 'grid', placeItems: 'center' }]), ...(ngDevMode ? [{ debugName: "readoutClass" }] : /* istanbul ignore next */ []));
|
|
8096
8157
|
glyphSize = computed(() => Math.max(12, Math.round(this.height() / 2)), ...(ngDevMode ? [{ debugName: "glyphSize" }] : /* istanbul ignore next */ []));
|
|
8097
8158
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniQuantityStepperComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
8098
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniQuantityStepperComponent, isStandalone: true, selector: "uni-quantity-stepper, QuantityStepper", 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 }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, deleteAtMin: { classPropertyName: "deleteAtMin", publicName: "deleteAtMin", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", removed: "removed" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'quantityStepper' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- With an editable middle the input is the tab stop and the buttons are\n pointer affordances (tabindex=\"-1\"), exactly as in uni-number-input. With a\n read-only middle there is nothing else to focus, so the buttons become the\n tab stops and the group carries the name. -->\n<div\n [class]=\"rootClass()\"\n [attr.role]=\"editable() ? null : 'group'\"\n [attr.aria-label]=\"editable() ? null : label()\"\n>\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || (atMin() && !showDelete())\"\n [attr.aria-label]=\"decrementLabel()\"\n (pointerdown)=\"onDecrementPress($event)\"\n (pointerup)=\"decrement.release()\"\n (pointercancel)=\"decrement.cancel()\"\n (lostpointercapture)=\"decrement.release()\"\n (click)=\"onDecrementClick()\"\n >\n <uni-icon [name]=\"decrementIcon()\" [size]=\"glyphSize()\" />\n </button>\n\n @if (editable()) {\n <input\n #field\n type=\"text\"\n role=\"spinbutton\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [class]=\"inputClass()\"\n [value]=\"displayText()\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-valuenow]=\"value() ?? null\"\n [attr.aria-valuemin]=\"resolvedMin()\"\n [attr.aria-valuemax]=\"max() ?? null\"\n [attr.aria-valuetext]=\"displayText() || 'Empty'\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (input)=\"onInput($any($event.target).value)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n } @else {\n <!-- Text, not a control: no role and no tab stop, so a reader reads it as\n the group's content. -->\n <span [class]=\"readoutClass()\">{{ displayText() }}</span>\n }\n\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || atMax()\"\n [attr.aria-label]=\"'Increase ' + label()\"\n (pointerdown)=\"increment.press($event)\"\n (pointerup)=\"increment.release()\"\n (pointercancel)=\"increment.cancel()\"\n (lostpointercapture)=\"increment.release()\"\n >\n <uni-icon [name]=\"componentOptions().incrementIcon ?? 'plus'\" [size]=\"glyphSize()\" />\n </button>\n</div>\n\n@if (editable()) {\n <span [id]=\"hintId\" [class]=\"srOnly\">\n Use the up and down arrow keys to change the quantity.\n </span>\n}\n\n<!-- Fences, clamps and removals are otherwise silent. Held stepping announces\n once, on release. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n", dependencies: [{ kind: "component", type: UniIconComponent, selector: "uni-icon", inputs: ["color", "name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8159
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniQuantityStepperComponent, isStandalone: true, selector: "uni-quantity-stepper, QuantityStepper", 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 }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, deleteAtMin: { classPropertyName: "deleteAtMin", publicName: "deleteAtMin", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", removed: "removed" }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'quantityStepper' }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["field"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- With an editable middle the input is the tab stop and the buttons are\n pointer affordances (tabindex=\"-1\"), exactly as in uni-number-input. With a\n read-only middle there is nothing else to focus, so the buttons become the\n tab stops and the group carries the name. -->\n<div\n [class]=\"rootClass()\"\n [attr.role]=\"editable() ? null : 'group'\"\n [attr.aria-label]=\"editable() ? null : label()\"\n>\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || (atMin() && !showDelete())\"\n [attr.aria-label]=\"decrementLabel()\"\n (pointerdown)=\"onDecrementPress($event)\"\n (pointerup)=\"decrement.release()\"\n (pointercancel)=\"decrement.cancel()\"\n (lostpointercapture)=\"decrement.release()\"\n (click)=\"onDecrementClick()\"\n >\n <uni-icon [name]=\"decrementIcon()\" [size]=\"glyphSize()\" />\n </button>\n\n @if (editable()) {\n <input\n #field\n type=\"text\"\n role=\"spinbutton\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [class]=\"inputClass()\"\n [attr.size]=\"valueSize()\"\n [value]=\"displayText()\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-valuenow]=\"value() ?? null\"\n [attr.aria-valuemin]=\"resolvedMin()\"\n [attr.aria-valuemax]=\"max() ?? null\"\n [attr.aria-valuetext]=\"displayText() || 'Empty'\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (input)=\"onInput($any($event.target).value)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n } @else {\n <!-- Text, not a control: no role and no tab stop, so a reader reads it as\n the group's content. -->\n <span [class]=\"readoutClass()\">{{ displayText() }}</span>\n }\n\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || atMax()\"\n [attr.aria-label]=\"'Increase ' + label()\"\n (pointerdown)=\"increment.press($event)\"\n (pointerup)=\"increment.release()\"\n (pointercancel)=\"increment.cancel()\"\n (lostpointercapture)=\"increment.release()\"\n >\n <uni-icon [name]=\"componentOptions().incrementIcon ?? 'plus'\" [size]=\"glyphSize()\" />\n </button>\n</div>\n\n@if (editable()) {\n <span [id]=\"hintId\" [class]=\"srOnly\">\n Use the up and down arrow keys to change the quantity.\n </span>\n}\n\n<!-- Fences, clamps and removals are otherwise silent. Held stepping announces\n once, on release. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n", dependencies: [{ kind: "component", type: UniIconComponent, selector: "uni-icon", inputs: ["color", "name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8099
8160
|
}
|
|
8100
8161
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniQuantityStepperComponent, decorators: [{
|
|
8101
8162
|
type: Component,
|
|
8102
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-quantity-stepper, QuantityStepper', imports: [UniIconComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'quantityStepper' }], host: { '[class]': 'className()' }, template: "<!-- With an editable middle the input is the tab stop and the buttons are\n pointer affordances (tabindex=\"-1\"), exactly as in uni-number-input. With a\n read-only middle there is nothing else to focus, so the buttons become the\n tab stops and the group carries the name. -->\n<div\n [class]=\"rootClass()\"\n [attr.role]=\"editable() ? null : 'group'\"\n [attr.aria-label]=\"editable() ? null : label()\"\n>\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || (atMin() && !showDelete())\"\n [attr.aria-label]=\"decrementLabel()\"\n (pointerdown)=\"onDecrementPress($event)\"\n (pointerup)=\"decrement.release()\"\n (pointercancel)=\"decrement.cancel()\"\n (lostpointercapture)=\"decrement.release()\"\n (click)=\"onDecrementClick()\"\n >\n <uni-icon [name]=\"decrementIcon()\" [size]=\"glyphSize()\" />\n </button>\n\n @if (editable()) {\n <input\n #field\n type=\"text\"\n role=\"spinbutton\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [class]=\"inputClass()\"\n [value]=\"displayText()\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-valuenow]=\"value() ?? null\"\n [attr.aria-valuemin]=\"resolvedMin()\"\n [attr.aria-valuemax]=\"max() ?? null\"\n [attr.aria-valuetext]=\"displayText() || 'Empty'\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (input)=\"onInput($any($event.target).value)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n } @else {\n <!-- Text, not a control: no role and no tab stop, so a reader reads it as\n the group's content. -->\n <span [class]=\"readoutClass()\">{{ displayText() }}</span>\n }\n\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || atMax()\"\n [attr.aria-label]=\"'Increase ' + label()\"\n (pointerdown)=\"increment.press($event)\"\n (pointerup)=\"increment.release()\"\n (pointercancel)=\"increment.cancel()\"\n (lostpointercapture)=\"increment.release()\"\n >\n <uni-icon [name]=\"componentOptions().incrementIcon ?? 'plus'\" [size]=\"glyphSize()\" />\n </button>\n</div>\n\n@if (editable()) {\n <span [id]=\"hintId\" [class]=\"srOnly\">\n Use the up and down arrow keys to change the quantity.\n </span>\n}\n\n<!-- Fences, clamps and removals are otherwise silent. Held stepping announces\n once, on release. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n" }]
|
|
8163
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-quantity-stepper, QuantityStepper', imports: [UniIconComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'quantityStepper' }], host: { '[class]': 'className()' }, template: "<!-- With an editable middle the input is the tab stop and the buttons are\n pointer affordances (tabindex=\"-1\"), exactly as in uni-number-input. With a\n read-only middle there is nothing else to focus, so the buttons become the\n tab stops and the group carries the name. -->\n<div\n [class]=\"rootClass()\"\n [attr.role]=\"editable() ? null : 'group'\"\n [attr.aria-label]=\"editable() ? null : label()\"\n>\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || (atMin() && !showDelete())\"\n [attr.aria-label]=\"decrementLabel()\"\n (pointerdown)=\"onDecrementPress($event)\"\n (pointerup)=\"decrement.release()\"\n (pointercancel)=\"decrement.cancel()\"\n (lostpointercapture)=\"decrement.release()\"\n (click)=\"onDecrementClick()\"\n >\n <uni-icon [name]=\"decrementIcon()\" [size]=\"glyphSize()\" />\n </button>\n\n @if (editable()) {\n <input\n #field\n type=\"text\"\n role=\"spinbutton\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [class]=\"inputClass()\"\n [attr.size]=\"valueSize()\"\n [value]=\"displayText()\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-valuenow]=\"value() ?? null\"\n [attr.aria-valuemin]=\"resolvedMin()\"\n [attr.aria-valuemax]=\"max() ?? null\"\n [attr.aria-valuetext]=\"displayText() || 'Empty'\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n (input)=\"onInput($any($event.target).value)\"\n (keydown)=\"onKeydown($event)\"\n (blur)=\"onBlur()\"\n />\n } @else {\n <!-- Text, not a control: no role and no tab stop, so a reader reads it as\n the group's content. -->\n <span [class]=\"readoutClass()\">{{ displayText() }}</span>\n }\n\n <button\n type=\"button\"\n [class]=\"buttonClass()\"\n [attr.tabindex]=\"editable() ? -1 : null\"\n [disabled]=\"disabled() || atMax()\"\n [attr.aria-label]=\"'Increase ' + label()\"\n (pointerdown)=\"increment.press($event)\"\n (pointerup)=\"increment.release()\"\n (pointercancel)=\"increment.cancel()\"\n (lostpointercapture)=\"increment.release()\"\n >\n <uni-icon [name]=\"componentOptions().incrementIcon ?? 'plus'\" [size]=\"glyphSize()\" />\n </button>\n</div>\n\n@if (editable()) {\n <span [id]=\"hintId\" [class]=\"srOnly\">\n Use the up and down arrow keys to change the quantity.\n </span>\n}\n\n<!-- Fences, clamps and removals are otherwise silent. Held stepping announces\n once, on release. -->\n<span role=\"status\" aria-live=\"polite\" [class]=\"srOnly\">{{ announcer.message() }}</span>\n" }]
|
|
8103
8164
|
}], 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 }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], deleteAtMin: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteAtMin", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], inputRef: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }] } });
|
|
8104
8165
|
|
|
8105
8166
|
/**
|
|
@@ -8667,7 +8728,7 @@ class UniTextareaComponent {
|
|
|
8667
8728
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
8668
8729
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
8669
8730
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
8670
|
-
/** Synced from required() validators by the Signal Forms [
|
|
8731
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
8671
8732
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
8672
8733
|
/**
|
|
8673
8734
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -8679,7 +8740,7 @@ class UniTextareaComponent {
|
|
|
8679
8740
|
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
8680
8741
|
/** Visible text rows. Defaults to the theme's `textarea` options. */
|
|
8681
8742
|
rows = input(undefined, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
8682
|
-
// Signal Forms' own optional control inputs: the `[
|
|
8743
|
+
// Signal Forms' own optional control inputs: the `[formField]` directive syncs
|
|
8683
8744
|
// them from the field's validators, as it does `required`.
|
|
8684
8745
|
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
8685
8746
|
name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
@@ -8714,6 +8775,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
8714
8775
|
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-textarea', imports: [UniInputBoxComponent], template: "<uni-input-box [error]=\"showError()\" height=\"auto\" [width]=\"width()\" [fullWidth]=\"fullWidth()\" [grow]=\"grow()\">\n <textarea\n [value]=\"value()\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (blur)=\"markAsTouched()\"\n [rows]=\"resolvedRows()\"\n [class]=\"textareaClass()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete() || null\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [attr.spellcheck]=\"spellcheck() ?? null\"\n [attr.aria-label]=\"label()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n ></textarea>\n</uni-input-box>\n" }]
|
|
8715
8776
|
}], 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 }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], spellcheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellcheck", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], grow: [{ type: i0.Input, args: [{ isSignal: true, alias: "grow", required: false }] }] } });
|
|
8716
8777
|
|
|
8778
|
+
/**
|
|
8779
|
+
* Everything a switch needs, from the three numbers a theme actually states.
|
|
8780
|
+
*
|
|
8781
|
+
* `travel` is why this is derived rather than written down: the knob starts at
|
|
8782
|
+
* `inset` and must end the same distance from the far edge, so it moves
|
|
8783
|
+
* `width - inset - knob - inset`, which reduces to `width - height`. The old
|
|
8784
|
+
* code hardcoded a translate of one track height, which was correct only while
|
|
8785
|
+
* the width was locked at 2x and the knob at 0.8x.
|
|
8786
|
+
*/
|
|
8787
|
+
function geometry(width, height, inset) {
|
|
8788
|
+
return { width, height, inset, knob: height - inset * 2, travel: width - height, radius: height / 2 };
|
|
8789
|
+
}
|
|
8717
8790
|
class UniToggleComponent extends BaseComponent {
|
|
8718
8791
|
// --- REQUIRED SIGNALS (populated by FormCheckboxControl) ---
|
|
8719
8792
|
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
@@ -8721,7 +8794,7 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8721
8794
|
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
8722
8795
|
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
8723
8796
|
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
8724
|
-
/** Synced from required() validators by the Signal Forms [
|
|
8797
|
+
/** Synced from required() validators by the Signal Forms [formField] directive. */
|
|
8725
8798
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
8726
8799
|
/**
|
|
8727
8800
|
* Id(s) of external element(s) describing this control — typically your
|
|
@@ -8730,6 +8803,16 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8730
8803
|
ariaDescribedBy = input(...(ngDevMode ? [undefined, { debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
|
|
8731
8804
|
// --- CONFIGURATION ---
|
|
8732
8805
|
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
8806
|
+
/**
|
|
8807
|
+
* Checked-state track color token, overriding the theme's
|
|
8808
|
+
* `toggle.behavior.checkedColor`.
|
|
8809
|
+
*
|
|
8810
|
+
* This exists alongside the theme option because `variant` — where this color
|
|
8811
|
+
* used to live exclusively — defaults to `'primary'`, so the component cannot
|
|
8812
|
+
* tell "set to primary" from "not set". Without an input, a theme-level
|
|
8813
|
+
* `checkedColor` would silently make per-instance `variant` inert.
|
|
8814
|
+
*/
|
|
8815
|
+
checkedColor = input(...(ngDevMode ? [undefined, { debugName: "checkedColor" }] : /* istanbul ignore next */ []));
|
|
8733
8816
|
// Only show errors if the user has actually interacted with the field
|
|
8734
8817
|
showError = computed(() => this.invalid() && (this.touched() || this.dirty()), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
|
|
8735
8818
|
markAsTouched() {
|
|
@@ -8739,18 +8822,44 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8739
8822
|
this.checked.set(event.target.checked);
|
|
8740
8823
|
this.markAsTouched();
|
|
8741
8824
|
}
|
|
8825
|
+
/**
|
|
8826
|
+
* Track and knob geometry for the active `size`, read out of the theme's
|
|
8827
|
+
* `sizes` block as data — `width`, `height` and the knob's inset `padding`.
|
|
8828
|
+
*
|
|
8829
|
+
* Read rather than spread: `padding` must not reach the track as real CSS or
|
|
8830
|
+
* it would double up with the knob's own `top`/`left` offsets. `uni-calendar`
|
|
8831
|
+
* treats its size block the same way.
|
|
8832
|
+
*/
|
|
8742
8833
|
metrics = computed(() => {
|
|
8743
|
-
|
|
8744
|
-
|
|
8834
|
+
// The legacy single-number token wins when a theme still sets it: that
|
|
8835
|
+
// theme opted into the old derived-ratio geometry before `sizes` existed,
|
|
8836
|
+
// and it applies to every instance regardless of the `size` input.
|
|
8837
|
+
const legacy = this.componentOptions().size;
|
|
8838
|
+
if (legacy != null) {
|
|
8839
|
+
const height = Number(legacy);
|
|
8840
|
+
return geometry(height * 2, height, (height - height * 0.8) / 2);
|
|
8841
|
+
}
|
|
8842
|
+
const size = this.style();
|
|
8843
|
+
const height = Number(size['height'] ?? 20);
|
|
8844
|
+
const width = Number(size['width'] ?? height * 2);
|
|
8845
|
+
const inset = Number(size['padding'] ?? (height - height * 0.8) / 2);
|
|
8846
|
+
return geometry(width, height, inset);
|
|
8847
|
+
}, ...(ngDevMode ? [{ debugName: "metrics" }] : /* istanbul ignore next */ []));
|
|
8848
|
+
/** The resolved checked/accent color: input, then theme option, then variant. */
|
|
8849
|
+
accent = computed(() => this.checkedColor() ?? this.componentOptions().checkedColor ?? this.variant(), ...(ngDevMode ? [{ debugName: "accent" }] : /* istanbul ignore next */ []));
|
|
8850
|
+
/** Knob slide and track color change, as a motion token — never `all`. */
|
|
8851
|
+
transitions = computed(() => {
|
|
8852
|
+
const motion = this.theme.motion(this.componentOptions().motion ?? 'control');
|
|
8853
|
+
const speed = motion.duration / 1000;
|
|
8745
8854
|
return {
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8855
|
+
// Scoped, never `all`: the focus ring must apply instantly rather than
|
|
8856
|
+
// interpolating its outline color from a stale value.
|
|
8857
|
+
track: `background-color ${speed}s ${motion.easing}, border-color ${speed}s ${motion.easing}`,
|
|
8858
|
+
knob: `transform ${speed}s ${motion.easing}, background-color ${speed}s ${motion.easing}`,
|
|
8750
8859
|
};
|
|
8751
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
8860
|
+
}, ...(ngDevMode ? [{ debugName: "transitions" }] : /* istanbul ignore next */ []));
|
|
8752
8861
|
toggleLabel = computed(() => {
|
|
8753
|
-
const {
|
|
8862
|
+
const { height, width, knob, inset, radius } = this.metrics();
|
|
8754
8863
|
return css({
|
|
8755
8864
|
userSelect: 'none',
|
|
8756
8865
|
cursor: this.disabled() ? 'not-allowed' : 'pointer',
|
|
@@ -8760,26 +8869,24 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8760
8869
|
gap: 8,
|
|
8761
8870
|
opacity: this.disabled() ? 0.6 : 1,
|
|
8762
8871
|
'& .toggle-switch': {
|
|
8763
|
-
width
|
|
8764
|
-
height
|
|
8872
|
+
width,
|
|
8873
|
+
height,
|
|
8765
8874
|
backgroundColor: this.disabled()
|
|
8766
8875
|
? this.getThemeColor('disabled')
|
|
8767
8876
|
: this.getThemeColor(this.componentOptions().trackColor ?? 'surface-variant'),
|
|
8768
|
-
borderRadius:
|
|
8877
|
+
borderRadius: radius,
|
|
8769
8878
|
position: 'relative',
|
|
8770
|
-
|
|
8771
|
-
// than interpolating its outline color from a stale value.
|
|
8772
|
-
transition: 'background-color 0.3s ease, border-color 0.3s ease',
|
|
8879
|
+
transition: this.transitions().track,
|
|
8773
8880
|
},
|
|
8774
8881
|
'& .toggle-slider': {
|
|
8775
|
-
width:
|
|
8776
|
-
height:
|
|
8882
|
+
width: knob,
|
|
8883
|
+
height: knob,
|
|
8777
8884
|
backgroundColor: this.getThemeColor(this.componentOptions().knobColor ?? 'surface'),
|
|
8778
8885
|
borderRadius: '50%',
|
|
8779
8886
|
position: 'absolute',
|
|
8780
|
-
top:
|
|
8781
|
-
left:
|
|
8782
|
-
transition:
|
|
8887
|
+
top: inset,
|
|
8888
|
+
left: inset,
|
|
8889
|
+
transition: this.transitions().knob,
|
|
8783
8890
|
...this.theme.boxShadow('raised'),
|
|
8784
8891
|
},
|
|
8785
8892
|
// Hover darkens whatever the token resolves to — the button convention.
|
|
@@ -8791,7 +8898,8 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8791
8898
|
});
|
|
8792
8899
|
}, ...(ngDevMode ? [{ debugName: "toggleLabel" }] : /* istanbul ignore next */ []));
|
|
8793
8900
|
toggleInput = computed(() => {
|
|
8794
|
-
const {
|
|
8901
|
+
const { travel } = this.metrics();
|
|
8902
|
+
const accent = this.getThemeColor(this.accent());
|
|
8795
8903
|
return css({
|
|
8796
8904
|
position: 'absolute',
|
|
8797
8905
|
zIndex: -1,
|
|
@@ -8799,18 +8907,20 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8799
8907
|
height: 0,
|
|
8800
8908
|
opacity: 0,
|
|
8801
8909
|
'&:checked + .toggle-switch': {
|
|
8802
|
-
backgroundColor:
|
|
8803
|
-
borderColor:
|
|
8910
|
+
backgroundColor: accent,
|
|
8911
|
+
borderColor: accent,
|
|
8804
8912
|
},
|
|
8805
8913
|
'&:checked + .toggle-switch .toggle-slider': {
|
|
8806
|
-
transform: `translateX(${
|
|
8914
|
+
transform: `translateX(${travel}px)`,
|
|
8807
8915
|
},
|
|
8808
8916
|
'&:disabled + .toggle-switch': {
|
|
8809
8917
|
cursor: 'not-allowed',
|
|
8810
8918
|
},
|
|
8811
|
-
// The shared, themable focus indicator, keyed off the hidden input.
|
|
8919
|
+
// The shared, themable focus indicator, keyed off the hidden input. It
|
|
8920
|
+
// wears the checked color rather than the variant, so a themed on-state
|
|
8921
|
+
// is not paired with a ring in some other role's color.
|
|
8812
8922
|
'&:focus + .toggle-switch': {
|
|
8813
|
-
...this.theme.focusRingStyle(
|
|
8923
|
+
...this.theme.focusRingStyle(accent),
|
|
8814
8924
|
},
|
|
8815
8925
|
});
|
|
8816
8926
|
}, ...(ngDevMode ? [{ debugName: "toggleInput" }] : /* istanbul ignore next */ []));
|
|
@@ -8819,12 +8929,12 @@ class UniToggleComponent extends BaseComponent {
|
|
|
8819
8929
|
return colors[token] ? colors[token] : colors['primary'];
|
|
8820
8930
|
}
|
|
8821
8931
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniToggleComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
8822
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniToggleComponent, isStandalone: true, selector: "uni-toggle", inputs: { checked: { classPropertyName: "checked", publicName: "checked", 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: false, transformFunction: null } }, outputs: { checked: "checkedChange", touched: "touchedChange" }, providers: [{ provide: COMPONENT_NAME, useValue: 'toggle' }], usesInheritance: true, ngImport: i0, template: "<label [class]=\"toggleLabel()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n [class]=\"toggleInput()\"\n [checked]=\"checked()\"\n (change)=\"handleChange($event)\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n />\n <div class=\"toggle-switch\">\n <div class=\"toggle-slider\"></div>\n </div>\n @if (label()) {\n <span uni-text=\"label\">{{ label() }}</span>\n }\n</label>\n", dependencies: [{ kind: "directive", type: UniTextDirective, selector: "[uni-text]", inputs: ["uni-text", "typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8932
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniToggleComponent, isStandalone: true, selector: "uni-toggle", inputs: { checked: { classPropertyName: "checked", publicName: "checked", 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: false, transformFunction: null }, checkedColor: { classPropertyName: "checkedColor", publicName: "checkedColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touched: "touchedChange" }, providers: [{ provide: COMPONENT_NAME, useValue: 'toggle' }], usesInheritance: true, ngImport: i0, template: "<label [class]=\"toggleLabel()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n [class]=\"toggleInput()\"\n [checked]=\"checked()\"\n (change)=\"handleChange($event)\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n />\n <div class=\"toggle-switch\">\n <div class=\"toggle-slider\"></div>\n </div>\n @if (label()) {\n <span uni-text=\"label\">{{ label() }}</span>\n }\n</label>\n", dependencies: [{ kind: "directive", type: UniTextDirective, selector: "[uni-text]", inputs: ["uni-text", "typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8823
8933
|
}
|
|
8824
8934
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniToggleComponent, decorators: [{
|
|
8825
8935
|
type: Component,
|
|
8826
8936
|
args: [{ selector: 'uni-toggle', imports: [UniTextDirective], providers: [{ provide: COMPONENT_NAME, useValue: 'toggle' }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<label [class]=\"toggleLabel()\">\n <input\n type=\"checkbox\"\n role=\"switch\"\n [class]=\"toggleInput()\"\n [checked]=\"checked()\"\n (change)=\"handleChange($event)\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n />\n <div class=\"toggle-switch\">\n <div class=\"toggle-slider\"></div>\n </div>\n @if (label()) {\n <span uni-text=\"label\">{{ label() }}</span>\n }\n</label>\n" }]
|
|
8827
|
-
}], 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 }] }] } });
|
|
8937
|
+
}], 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 }] }], checkedColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkedColor", required: false }] }] } });
|
|
8828
8938
|
|
|
8829
8939
|
/**
|
|
8830
8940
|
* Every layout and typography attribute directive, for
|
|
@@ -10461,8 +10571,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
10461
10571
|
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[uni-dialog-header]', imports: [UniBoxDirective, UniIconButtonComponent, UniTextDirective, UniRowDirective], providers: [{ provide: COMPONENT_NAME, useValue: 'dialogHeader' }], template: "<div\n row-layout\n [containerColor]=\"componentOptions().color\"\n [borderRadius]=\"componentOptions().borderRadius\"\n [height]=\"componentOptions().height\"\n alignItems=\"center\"\n [paddingHorizontal]=\"componentOptions().paddingHorizontal ?? 'sm'\"\n>\n <!-- Balance spacer: only centered titles need to offset the close button. -->\n @if ((componentOptions().textAlign || 'center') === 'center') {\n <div box-layout [width]=\"26\"></div>\n }\n <div box-layout [grow]=\"1\" [attr.id]=\"titleId\">\n <span uni-text\n [typeface]=\"componentOptions().textRole\"\n [color]=\"componentOptions().textColor\"\n display=\"block\"\n [align]=\"componentOptions().textAlign || 'center'\"\n ><ng-content></ng-content\n ></span>\n </div>\n <button\n icon-button\n [iconName]=\"componentOptions().closeButtonIcon\"\n [symbolName]=\"componentOptions().closeButtonSymbol\"\n variant=\"ghost\"\n (click)=\"closeDialog()\"\n [size]=\"componentOptions().closeButtonSize || 'md'\"\n >\n Close\n </button>\n</div>\n" }]
|
|
10462
10572
|
}], ctorParameters: () => [] });
|
|
10463
10573
|
|
|
10574
|
+
const DRAWER_PANEL = new InjectionToken('uni-drawer-panel');
|
|
10575
|
+
|
|
10576
|
+
/**
|
|
10577
|
+
* The drawer's pinned footer action row — the save bar of an editor panel.
|
|
10578
|
+
*
|
|
10579
|
+
* Sits outside the scrolling body, so the actions stay reachable however long
|
|
10580
|
+
* the form is. Mirrors `[dialog-buttons]`; the difference is posture, which
|
|
10581
|
+
* lives in the `drawerButtons` theme options rather than here.
|
|
10582
|
+
*/
|
|
10583
|
+
class UniDrawerButtonsComponent extends BaseComponent {
|
|
10584
|
+
drawer = inject(DRAWER_PANEL, { optional: true });
|
|
10585
|
+
confirmButtonText = input(...(ngDevMode ? [undefined, { debugName: "confirmButtonText" }] : /* istanbul ignore next */ []));
|
|
10586
|
+
confirmButtonVariant = input(...(ngDevMode ? [undefined, { debugName: "confirmButtonVariant" }] : /* istanbul ignore next */ []));
|
|
10587
|
+
cancelButtonText = input(...(ngDevMode ? [undefined, { debugName: "cancelButtonText" }] : /* istanbul ignore next */ []));
|
|
10588
|
+
cancelButtonVariant = input(...(ngDevMode ? [undefined, { debugName: "cancelButtonVariant" }] : /* istanbul ignore next */ []));
|
|
10589
|
+
disableConfirm = input(...(ngDevMode ? [undefined, { debugName: "disableConfirm" }] : /* istanbul ignore next */ []));
|
|
10590
|
+
padding = input(...(ngDevMode ? [undefined, { debugName: "padding" }] : /* istanbul ignore next */ []));
|
|
10591
|
+
justifyContent = input(...(ngDevMode ? [undefined, { debugName: "justifyContent" }] : /* istanbul ignore next */ []));
|
|
10592
|
+
confirmed = output();
|
|
10593
|
+
// Inputs win over theme options; the trailing literal is the fallback.
|
|
10594
|
+
confirmVariant = computed(() => this.confirmButtonVariant() ?? this.componentOptions().confirmButtonVariant ?? 'primary', ...(ngDevMode ? [{ debugName: "confirmVariant" }] : /* istanbul ignore next */ []));
|
|
10595
|
+
cancelVariant = computed(() => this.cancelButtonVariant() ?? this.componentOptions().cancelButtonVariant ?? 'quaternary', ...(ngDevMode ? [{ debugName: "cancelVariant" }] : /* istanbul ignore next */ []));
|
|
10596
|
+
paddingValue = computed(() => this.padding() ?? this.componentOptions().padding ?? 'md', ...(ngDevMode ? [{ debugName: "paddingValue" }] : /* istanbul ignore next */ []));
|
|
10597
|
+
justifyContentValue = computed(() => this.justifyContent() ?? this.componentOptions().justifyContent ?? 'flex-end', ...(ngDevMode ? [{ debugName: "justifyContentValue" }] : /* istanbul ignore next */ []));
|
|
10598
|
+
gapValue = computed(() => this.componentOptions().gap ?? 'sm', ...(ngDevMode ? [{ debugName: "gapValue" }] : /* istanbul ignore next */ []));
|
|
10599
|
+
buttonSize = computed(() => this.componentOptions().buttonSize ?? 'md', ...(ngDevMode ? [{ debugName: "buttonSize" }] : /* istanbul ignore next */ []));
|
|
10600
|
+
/** A pinned row, sized by its content rather than by the body beside it. */
|
|
10601
|
+
hostClass = computed(() => css({
|
|
10602
|
+
flex: 'none',
|
|
10603
|
+
...this.theme.borderTop(this.componentOptions().divider),
|
|
10604
|
+
}), ...(ngDevMode ? [{ debugName: "hostClass" }] : /* istanbul ignore next */ []));
|
|
10605
|
+
className = computed(() => css([
|
|
10606
|
+
this.componentTheme().fixed,
|
|
10607
|
+
this.componentOptions().stretch && {
|
|
10608
|
+
width: '100%',
|
|
10609
|
+
minWidth: '100%',
|
|
10610
|
+
'& > button': { flex: '1 1 50%', maxWidth: '50%' },
|
|
10611
|
+
},
|
|
10612
|
+
]), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
10613
|
+
/**
|
|
10614
|
+
* Cancel routes through the drawer's own close decision, so a panel with
|
|
10615
|
+
* unsaved changes can veto it exactly as it vetoes Escape.
|
|
10616
|
+
*/
|
|
10617
|
+
closeDrawer() {
|
|
10618
|
+
this.drawer?.requestClose('close-button');
|
|
10619
|
+
}
|
|
10620
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerButtonsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
10621
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniDrawerButtonsComponent, isStandalone: true, selector: "[uni-drawer-buttons], [drawer-buttons]", inputs: { confirmButtonText: { classPropertyName: "confirmButtonText", publicName: "confirmButtonText", isSignal: true, isRequired: false, transformFunction: null }, confirmButtonVariant: { classPropertyName: "confirmButtonVariant", publicName: "confirmButtonVariant", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonText: { classPropertyName: "cancelButtonText", publicName: "cancelButtonText", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonVariant: { classPropertyName: "cancelButtonVariant", publicName: "cancelButtonVariant", isSignal: true, isRequired: false, transformFunction: null }, disableConfirm: { classPropertyName: "disableConfirm", publicName: "disableConfirm", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, justifyContent: { classPropertyName: "justifyContent", publicName: "justifyContent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed" }, host: { properties: { "class": "hostClass()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'drawerButtons' }], usesInheritance: true, ngImport: i0, template: "<div\n row-layout\n [gap]=\"gapValue()\"\n [padding]=\"paddingValue()\"\n [justifyContent]=\"justifyContentValue()\"\n [flexDirection]=\"componentOptions().reverseOrder ? 'row-reverse' : 'row'\"\n [class]=\"className()\"\n>\n <button text-button [variant]=\"cancelVariant()\" [size]=\"buttonSize()\" (click)=\"closeDrawer()\">\n {{ cancelButtonText() || 'Cancel' }}\n </button>\n <button\n text-button\n [variant]=\"confirmVariant()\"\n [size]=\"buttonSize()\"\n (click)=\"confirmed.emit()\"\n [disable]=\"disableConfirm()\"\n >\n {{ confirmButtonText() || 'Save' }}\n </button>\n</div>\n", dependencies: [{ kind: "directive", type: UniRowDirective, selector: "[uni-row-layout], [row-layout]", inputs: ["display", "flexDirection", "minWidth"] }, { kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10622
|
+
}
|
|
10623
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerButtonsComponent, decorators: [{
|
|
10624
|
+
type: Component,
|
|
10625
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[uni-drawer-buttons], [drawer-buttons]', imports: [UniRowDirective, UniButtonComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'drawerButtons' }], host: { '[class]': 'hostClass()' }, template: "<div\n row-layout\n [gap]=\"gapValue()\"\n [padding]=\"paddingValue()\"\n [justifyContent]=\"justifyContentValue()\"\n [flexDirection]=\"componentOptions().reverseOrder ? 'row-reverse' : 'row'\"\n [class]=\"className()\"\n>\n <button text-button [variant]=\"cancelVariant()\" [size]=\"buttonSize()\" (click)=\"closeDrawer()\">\n {{ cancelButtonText() || 'Cancel' }}\n </button>\n <button\n text-button\n [variant]=\"confirmVariant()\"\n [size]=\"buttonSize()\"\n (click)=\"confirmed.emit()\"\n [disable]=\"disableConfirm()\"\n >\n {{ confirmButtonText() || 'Save' }}\n </button>\n</div>\n" }]
|
|
10626
|
+
}], propDecorators: { confirmButtonText: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmButtonText", required: false }] }], confirmButtonVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmButtonVariant", required: false }] }], cancelButtonText: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonText", required: false }] }], cancelButtonVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonVariant", required: false }] }], disableConfirm: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableConfirm", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], justifyContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "justifyContent", required: false }] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }] } });
|
|
10627
|
+
|
|
10628
|
+
/**
|
|
10629
|
+
* The drawer's pinned header row: a title, and optionally a close button.
|
|
10630
|
+
*
|
|
10631
|
+
* Sits outside the scrolling body, so it stays put while the form beneath it
|
|
10632
|
+
* moves. Reached either by projecting it — `<div uni-drawer-header>` — or
|
|
10633
|
+
* implicitly, by giving `uni-drawer` a `headline`, in which case the drawer
|
|
10634
|
+
* renders one of these itself.
|
|
10635
|
+
*/
|
|
10636
|
+
class UniDrawerHeaderComponent extends BaseComponent {
|
|
10637
|
+
drawer = inject(DRAWER_PANEL, { optional: true });
|
|
10638
|
+
/** Title text. Falls back to the drawer's `headline`; projected content wins over both. */
|
|
10639
|
+
headline = input(...(ngDevMode ? [undefined, { debugName: "headline" }] : /* istanbul ignore next */ []));
|
|
10640
|
+
/** Attached to the title so the drawer is labelled by it. */
|
|
10641
|
+
titleId = this.drawer?.titleId ?? null;
|
|
10642
|
+
title = computed(() => this.headline() ?? this.drawer?.headline() ?? '', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
10643
|
+
showClose = computed(() => this.drawer?.defaultCloseButton() ?? true, ...(ngDevMode ? [{ debugName: "showClose" }] : /* istanbul ignore next */ []));
|
|
10644
|
+
constructor() {
|
|
10645
|
+
super();
|
|
10646
|
+
// Tells the drawer it is labelled by this row rather than by `ariaLabel`.
|
|
10647
|
+
this.drawer?.hasHeader.set(true);
|
|
10648
|
+
}
|
|
10649
|
+
/** Never a bare close: the drawer decides, so a veto is honoured here too. */
|
|
10650
|
+
closeDrawer() {
|
|
10651
|
+
this.drawer?.requestClose('close-button');
|
|
10652
|
+
}
|
|
10653
|
+
className = computed(() => css({
|
|
10654
|
+
// A pinned row: it is a flex child of the panel and must not be sized
|
|
10655
|
+
// by the scrolling body beside it.
|
|
10656
|
+
flex: 'none',
|
|
10657
|
+
...this.theme.borderBottom(this.componentOptions().divider),
|
|
10658
|
+
}), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
10659
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10660
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniDrawerHeaderComponent, isStandalone: true, selector: "[uni-drawer-header]", inputs: { headline: { classPropertyName: "headline", publicName: "headline", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'drawerHeader' }], usesInheritance: true, ngImport: i0, template: "<div\n row-layout\n [containerColor]=\"componentOptions().color\"\n [height]=\"componentOptions().height\"\n alignItems=\"center\"\n gap=\"sm\"\n [padding]=\"componentOptions().padding ?? 'md'\"\n>\n <div box-layout [grow]=\"1\" [minWidth]=\"0\" [attr.id]=\"titleId\">\n <span\n uni-text\n [typeface]=\"componentOptions().textRole\"\n [color]=\"componentOptions().textColor\"\n display=\"block\"\n [align]=\"componentOptions().textAlign || 'left'\"\n ><ng-content>{{ title() }}</ng-content></span\n >\n </div>\n @if (showClose()) {\n <button\n icon-button\n [iconName]=\"componentOptions().closeButtonIcon\"\n [symbolName]=\"componentOptions().closeButtonSymbol\"\n variant=\"ghost\"\n (click)=\"closeDrawer()\"\n [size]=\"componentOptions().closeButtonSize || 'md'\"\n >\n Close\n </button>\n }\n</div>\n", dependencies: [{ kind: "directive", type: UniBoxDirective, selector: "[uni-box-layout], [box-layout]", inputs: ["containerColor", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "flex", "shrink", "basis", "marginInline", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }, { kind: "component", type: UniIconButtonComponent, selector: "button[uni-icon-button], button[icon-button]", inputs: ["ariaLabel", "iconName", "symbolName", "variant", "size", "disable", "loading", "opticalSize"] }, { kind: "directive", type: UniTextDirective, selector: "[uni-text]", inputs: ["uni-text", "typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }, { kind: "directive", type: UniRowDirective, selector: "[uni-row-layout], [row-layout]", inputs: ["display", "flexDirection", "minWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10661
|
+
}
|
|
10662
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerHeaderComponent, decorators: [{
|
|
10663
|
+
type: Component,
|
|
10664
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: '[uni-drawer-header]', imports: [UniBoxDirective, UniIconButtonComponent, UniTextDirective, UniRowDirective], providers: [{ provide: COMPONENT_NAME, useValue: 'drawerHeader' }], host: { '[class]': 'className()' }, template: "<div\n row-layout\n [containerColor]=\"componentOptions().color\"\n [height]=\"componentOptions().height\"\n alignItems=\"center\"\n gap=\"sm\"\n [padding]=\"componentOptions().padding ?? 'md'\"\n>\n <div box-layout [grow]=\"1\" [minWidth]=\"0\" [attr.id]=\"titleId\">\n <span\n uni-text\n [typeface]=\"componentOptions().textRole\"\n [color]=\"componentOptions().textColor\"\n display=\"block\"\n [align]=\"componentOptions().textAlign || 'left'\"\n ><ng-content>{{ title() }}</ng-content></span\n >\n </div>\n @if (showClose()) {\n <button\n icon-button\n [iconName]=\"componentOptions().closeButtonIcon\"\n [symbolName]=\"componentOptions().closeButtonSymbol\"\n variant=\"ghost\"\n (click)=\"closeDrawer()\"\n [size]=\"componentOptions().closeButtonSize || 'md'\"\n >\n Close\n </button>\n }\n</div>\n" }]
|
|
10665
|
+
}], ctorParameters: () => [], propDecorators: { headline: [{ type: i0.Input, args: [{ isSignal: true, alias: "headline", required: false }] }] } });
|
|
10666
|
+
|
|
10464
10667
|
/**
|
|
10465
|
-
*
|
|
10668
|
+
* Drawer with two modes sharing one three-row layout:
|
|
10466
10669
|
*
|
|
10467
10670
|
* - `side` — an in-flow `<aside>` that pushes content (dashboard sidenav);
|
|
10468
10671
|
* opening/closing animates its width, and the divider border primitive
|
|
@@ -10471,17 +10674,78 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
10471
10674
|
* scrim backdrop come from the platform (same machinery as `uni-dialog`),
|
|
10472
10675
|
* sliding in from its edge.
|
|
10473
10676
|
*
|
|
10474
|
-
*
|
|
10475
|
-
* `drawer
|
|
10677
|
+
* **The panel is never the scroll container.** It is a flex column of three
|
|
10678
|
+
* rows — an optional `[uni-drawer-header]`, the projected body, an optional
|
|
10679
|
+
* `[uni-drawer-buttons]` — and only the body scrolls. The panel itself is
|
|
10680
|
+
* `overflow: clip` on both axes. That is what lets a header and a save bar pin
|
|
10681
|
+
* while a long form scrolls between them, and it is why the theme's `padding`
|
|
10682
|
+
* option lands on the body row rather than the panel: padding on a scrolling
|
|
10683
|
+
* box scrolls away with its content.
|
|
10684
|
+
*
|
|
10685
|
+
* Surface, width, divider, elevation, padding, backdrop, scrim and background
|
|
10686
|
+
* all resolve from `drawer` theme tokens.
|
|
10476
10687
|
*/
|
|
10477
10688
|
class UniDrawerComponent extends BaseComponent {
|
|
10478
10689
|
/** Two-way bindable open state: [(open)]. */
|
|
10479
10690
|
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
10480
10691
|
mode = input('side', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
10481
10692
|
position = input('start', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
10482
|
-
/**
|
|
10483
|
-
|
|
10484
|
-
|
|
10693
|
+
/**
|
|
10694
|
+
* Accessible name for the overlay mode. Only consulted when the drawer has
|
|
10695
|
+
* no header to be labelled by.
|
|
10696
|
+
*
|
|
10697
|
+
* There is deliberately no default. A drawer used as an editor panel that
|
|
10698
|
+
* inherited the literal "Navigation" would announce itself as something it
|
|
10699
|
+
* is not, and a wrong accessible name is worse than a missing one — the
|
|
10700
|
+
* missing one is at least caught by any audit.
|
|
10701
|
+
*/
|
|
10702
|
+
ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
10703
|
+
/**
|
|
10704
|
+
* Title for the drawer's header row. Shorthand for projecting a
|
|
10705
|
+
* `[uni-drawer-header]`; project one instead when the header needs more
|
|
10706
|
+
* than a title (a record counter, prev/next navigation).
|
|
10707
|
+
*/
|
|
10708
|
+
headline = input(...(ngDevMode ? [undefined, { debugName: "headline" }] : /* istanbul ignore next */ []));
|
|
10709
|
+
/** Whether the header row renders a close button. */
|
|
10710
|
+
defaultCloseButton = input(true, ...(ngDevMode ? [{ debugName: "defaultCloseButton" }] : /* istanbul ignore next */ []));
|
|
10711
|
+
/** Panel width in px, overriding the theme's `drawer.behavior.width`. */
|
|
10712
|
+
width = input(...(ngDevMode ? [undefined, { debugName: "width" }] : /* istanbul ignore next */ []));
|
|
10713
|
+
/**
|
|
10714
|
+
* Whether the overlay dims the page behind it, overriding the theme's
|
|
10715
|
+
* `drawer.behavior.scrim`. False leaves the backdrop transparent so the page
|
|
10716
|
+
* stays legible while the panel is open — an editor panel beside a board the
|
|
10717
|
+
* user is still reading.
|
|
10718
|
+
*
|
|
10719
|
+
* This does not make the drawer non-modal: focus is still trapped and the
|
|
10720
|
+
* page behind is still inert. It is a visibility choice, not a modality one.
|
|
10721
|
+
*/
|
|
10722
|
+
scrim = input(...(ngDevMode ? [undefined, { debugName: "scrim" }] : /* istanbul ignore next */ []));
|
|
10723
|
+
/**
|
|
10724
|
+
* CSS selector for the element to focus when the overlay opens. The native
|
|
10725
|
+
* default is the first focusable element, which in an editor panel is
|
|
10726
|
+
* usually the close button rather than the first field.
|
|
10727
|
+
*/
|
|
10728
|
+
initialFocus = input(...(ngDevMode ? [undefined, { debugName: "initialFocus" }] : /* istanbul ignore next */ []));
|
|
10729
|
+
/**
|
|
10730
|
+
* The drawer is *asking* to close — Escape, the backdrop, or a close/cancel
|
|
10731
|
+
* button. Pair with `disableAutoClose` to hold the panel open while an async
|
|
10732
|
+
* confirmation runs.
|
|
10733
|
+
*/
|
|
10734
|
+
closeRequest = output();
|
|
10735
|
+
/**
|
|
10736
|
+
* When true the drawer never closes itself; it only emits `closeRequest` and
|
|
10737
|
+
* waits for the consumer to set `open`. Off by default, so a drawer that
|
|
10738
|
+
* ignores `closeRequest` behaves exactly as it always has.
|
|
10739
|
+
*/
|
|
10740
|
+
disableAutoClose = input(false, ...(ngDevMode ? [{ debugName: "disableAutoClose" }] : /* istanbul ignore next */ []));
|
|
10741
|
+
/** Set by a projected `[uni-drawer-header]` so it can pin flush to the top. */
|
|
10742
|
+
hasHeader = signal(false, ...(ngDevMode ? [{ debugName: "hasHeader" }] : /* istanbul ignore next */ []));
|
|
10743
|
+
/** Id referenced by aria-labelledby; the header row attaches it to its title. */
|
|
10744
|
+
titleId = uniqueId('uni-drawer-title');
|
|
10745
|
+
labelledBy = computed(() => (this.hasHeader() ? this.titleId : null), ...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
|
|
10746
|
+
headerTemplate = viewChild.required('header');
|
|
10747
|
+
bodyTemplate = viewChild.required('body');
|
|
10748
|
+
footerTemplate = viewChild.required('footer');
|
|
10485
10749
|
overlay = viewChild('overlay', ...(ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []));
|
|
10486
10750
|
constructor() {
|
|
10487
10751
|
super();
|
|
@@ -10493,6 +10757,9 @@ class UniDrawerComponent extends BaseComponent {
|
|
|
10493
10757
|
if (!dialog.open) {
|
|
10494
10758
|
dialog.removeAttribute('closing');
|
|
10495
10759
|
dialog.showModal();
|
|
10760
|
+
const selector = this.initialFocus();
|
|
10761
|
+
if (selector)
|
|
10762
|
+
dialog.querySelector(selector)?.focus();
|
|
10496
10763
|
}
|
|
10497
10764
|
}
|
|
10498
10765
|
else if (dialog.open) {
|
|
@@ -10501,14 +10768,24 @@ class UniDrawerComponent extends BaseComponent {
|
|
|
10501
10768
|
}
|
|
10502
10769
|
});
|
|
10503
10770
|
}
|
|
10771
|
+
/**
|
|
10772
|
+
* The one place a close is decided, so every route in — Escape, the
|
|
10773
|
+
* backdrop, the header's close button, the footer's cancel — behaves
|
|
10774
|
+
* identically and is equally vetoable.
|
|
10775
|
+
*/
|
|
10776
|
+
requestClose(reason) {
|
|
10777
|
+
this.closeRequest.emit({ reason });
|
|
10778
|
+
if (!this.disableAutoClose())
|
|
10779
|
+
this.open.set(false);
|
|
10780
|
+
}
|
|
10504
10781
|
onBackdropClick(event) {
|
|
10505
10782
|
if (event.target.nodeName === 'DIALOG')
|
|
10506
|
-
this.
|
|
10783
|
+
this.requestClose('backdrop');
|
|
10507
10784
|
}
|
|
10508
10785
|
/** Route Escape through the animated close, keeping `open` in sync. */
|
|
10509
10786
|
onCancel(event) {
|
|
10510
10787
|
event.preventDefault();
|
|
10511
|
-
this.
|
|
10788
|
+
this.requestClose('escape');
|
|
10512
10789
|
}
|
|
10513
10790
|
onAnimationEnd(event) {
|
|
10514
10791
|
const dialog = this.overlay()?.nativeElement;
|
|
@@ -10522,53 +10799,129 @@ class UniDrawerComponent extends BaseComponent {
|
|
|
10522
10799
|
edge = computed(() => (this.position() === 'start' ? '-100%' : '100%'), ...(ngDevMode ? [{ debugName: "edge" }] : /* istanbul ignore next */ []));
|
|
10523
10800
|
slideIn = computed(() => keyframes({ from: { transform: `translateX(${this.edge()})` }, to: { transform: 'translateX(0)' } }), ...(ngDevMode ? [{ debugName: "slideIn" }] : /* istanbul ignore next */ []));
|
|
10524
10801
|
slideOut = computed(() => keyframes({ from: { transform: 'translateX(0)' }, to: { transform: `translateX(${this.edge()})` } }), ...(ngDevMode ? [{ debugName: "slideOut" }] : /* istanbul ignore next */ []));
|
|
10802
|
+
/** Input wins over the theme option; the literal is the last-resort default. */
|
|
10803
|
+
panelWidth = computed(() => this.width() ?? this.componentOptions().width ?? 280, ...(ngDevMode ? [{ debugName: "panelWidth" }] : /* istanbul ignore next */ []));
|
|
10804
|
+
showScrim = computed(() => this.scrim() ?? this.componentOptions().scrim ?? true, ...(ngDevMode ? [{ debugName: "showScrim" }] : /* istanbul ignore next */ []));
|
|
10805
|
+
/**
|
|
10806
|
+
* The panel's surface. `solid` is the plain color pair; `glass` and
|
|
10807
|
+
* `gradient` derive from it, so a theme swaps treatment without restating
|
|
10808
|
+
* the color.
|
|
10809
|
+
*/
|
|
10810
|
+
surface = computed(() => {
|
|
10811
|
+
const options = this.componentOptions();
|
|
10812
|
+
const pair = this.theme.colorPair(options.color);
|
|
10813
|
+
const base = pair?.backgroundColor;
|
|
10814
|
+
const treatment = options.background ?? 'solid';
|
|
10815
|
+
if (!base || treatment === 'solid')
|
|
10816
|
+
return pair;
|
|
10817
|
+
if (treatment === 'glass') {
|
|
10818
|
+
return {
|
|
10819
|
+
...pair,
|
|
10820
|
+
backgroundColor: `color-mix(in srgb, ${base} 72%, transparent)`,
|
|
10821
|
+
backdropFilter: 'blur(12px) saturate(1.4)',
|
|
10822
|
+
};
|
|
10823
|
+
}
|
|
10824
|
+
// A vertical tint toward the content color: always visible, and it never
|
|
10825
|
+
// lets the page show through the way a fade to transparent would.
|
|
10826
|
+
return {
|
|
10827
|
+
...pair,
|
|
10828
|
+
backgroundImage: `linear-gradient(to bottom, ${base} 0%, color-mix(in srgb, ${base} 92%, ${pair?.color ?? 'transparent'} 8%) 100%)`,
|
|
10829
|
+
};
|
|
10830
|
+
}, ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
|
|
10831
|
+
/** The shared flex column: three rows, and never a scroll container itself. */
|
|
10832
|
+
shell = {
|
|
10833
|
+
boxSizing: 'border-box',
|
|
10834
|
+
display: 'flex',
|
|
10835
|
+
flexDirection: 'column',
|
|
10836
|
+
// Both axes, explicitly, and never the shorthand. Setting one axis alone
|
|
10837
|
+
// computes the other to `auto` — which is precisely how a panel becomes
|
|
10838
|
+
// an accidental scroll container.
|
|
10839
|
+
overflowX: 'clip',
|
|
10840
|
+
overflowY: 'clip',
|
|
10841
|
+
};
|
|
10525
10842
|
sideClass = computed(() => {
|
|
10526
10843
|
const options = this.componentOptions();
|
|
10527
|
-
const width =
|
|
10844
|
+
const width = this.panelWidth();
|
|
10528
10845
|
const start = this.position() === 'start';
|
|
10529
10846
|
return css({
|
|
10530
|
-
|
|
10531
|
-
boxSizing: 'border-box',
|
|
10847
|
+
...this.shell,
|
|
10532
10848
|
height: '100%',
|
|
10533
10849
|
flex: 'none',
|
|
10534
|
-
overflowX: 'hidden',
|
|
10535
|
-
overflowY: 'auto',
|
|
10536
10850
|
transition: 'width 0.25s ease, visibility 0.25s',
|
|
10537
|
-
...this.
|
|
10851
|
+
...this.surface(),
|
|
10538
10852
|
...(start
|
|
10539
10853
|
? this.theme.borderRight(options.divider)
|
|
10540
10854
|
: this.theme.borderLeft(options.divider)),
|
|
10541
10855
|
...(this.open()
|
|
10542
|
-
? { width, visibility: 'visible'
|
|
10543
|
-
: { width: 0, visibility: 'hidden',
|
|
10856
|
+
? { width, visibility: 'visible' }
|
|
10857
|
+
: { width: 0, visibility: 'hidden', border: 'none' }),
|
|
10544
10858
|
});
|
|
10545
10859
|
}, ...(ngDevMode ? [{ debugName: "sideClass" }] : /* istanbul ignore next */ []));
|
|
10546
10860
|
overClass = computed(() => {
|
|
10547
10861
|
const options = this.componentOptions();
|
|
10548
10862
|
const start = this.position() === 'start';
|
|
10549
10863
|
return css({
|
|
10550
|
-
|
|
10551
|
-
width:
|
|
10864
|
+
...this.shell,
|
|
10865
|
+
width: this.panelWidth(),
|
|
10552
10866
|
maxWidth: '90vw',
|
|
10553
10867
|
height: '100dvh',
|
|
10554
10868
|
maxHeight: '100dvh',
|
|
10555
10869
|
border: 'none',
|
|
10870
|
+
padding: 0,
|
|
10556
10871
|
margin: start ? '0 auto 0 0' : '0 0 0 auto',
|
|
10557
|
-
|
|
10558
|
-
...this.theme.colorPair(options.color),
|
|
10559
|
-
...this.theme.padding(options.padding),
|
|
10872
|
+
...this.surface(),
|
|
10560
10873
|
...this.theme.boxShadow(options.elevation),
|
|
10561
|
-
|
|
10874
|
+
// The UA stylesheet hides a closed dialog with `display: none`, which the
|
|
10875
|
+
// shell's `display: flex` would otherwise beat on specificity — leaving
|
|
10876
|
+
// the panel sitting in normal flow behind the page whenever it is shut.
|
|
10877
|
+
// The closing animation still runs: `open` is only removed after it ends.
|
|
10878
|
+
'&:not([open])': { display: 'none' },
|
|
10879
|
+
// `scrim: false` keeps the modality — focus trap, inert page — but stops
|
|
10880
|
+
// the drawer dimming what it covers.
|
|
10881
|
+
'&::backdrop': this.showScrim() ? { ...options.backdrop } : { background: 'transparent' },
|
|
10562
10882
|
'&[open]': { animation: `${this.slideIn()} 250ms ease-out` },
|
|
10563
10883
|
'&[closing]': { animation: `${this.slideOut()} 250ms ease-in` },
|
|
10564
10884
|
});
|
|
10565
10885
|
}, ...(ngDevMode ? [{ debugName: "overClass" }] : /* istanbul ignore next */ []));
|
|
10886
|
+
/** The only scrolling row, and the only padded one. */
|
|
10887
|
+
bodyClass = computed(() => css({
|
|
10888
|
+
flex: '1 1 auto',
|
|
10889
|
+
minHeight: 0,
|
|
10890
|
+
// Defence in depth: a positioned body is the containing block for any
|
|
10891
|
+
// stray absolute descendant, so nothing can re-home into an ancestor
|
|
10892
|
+
// and inflate its scrollHeight. Only safe because the shell above is
|
|
10893
|
+
// `overflow: clip` — on its own this would move the phantom overflow
|
|
10894
|
+
// into this scroller instead of out of the panel.
|
|
10895
|
+
position: 'relative',
|
|
10896
|
+
overflowX: 'hidden',
|
|
10897
|
+
overflowY: 'auto',
|
|
10898
|
+
overscrollBehavior: 'contain',
|
|
10899
|
+
...this.theme.padding(this.componentOptions().padding),
|
|
10900
|
+
}), ...(ngDevMode ? [{ debugName: "bodyClass" }] : /* istanbul ignore next */ []));
|
|
10566
10901
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10567
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniDrawerComponent, isStandalone: true, selector: "uni-drawer", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }
|
|
10568
|
-
|
|
10902
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniDrawerComponent, isStandalone: true, selector: "uni-drawer", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, headline: { classPropertyName: "headline", publicName: "headline", isSignal: true, isRequired: false, transformFunction: null }, defaultCloseButton: { classPropertyName: "defaultCloseButton", publicName: "defaultCloseButton", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, scrim: { classPropertyName: "scrim", publicName: "scrim", isSignal: true, isRequired: false, transformFunction: null }, initialFocus: { classPropertyName: "initialFocus", publicName: "initialFocus", isSignal: true, isRequired: false, transformFunction: null }, disableAutoClose: { classPropertyName: "disableAutoClose", publicName: "disableAutoClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closeRequest: "closeRequest" }, providers: [
|
|
10903
|
+
{ provide: COMPONENT_NAME, useValue: 'drawer' },
|
|
10904
|
+
{ provide: DRAWER_PANEL, useExisting: forwardRef(() => UniDrawerComponent) },
|
|
10905
|
+
], viewQueries: [{ propertyName: "headerTemplate", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "bodyTemplate", first: true, predicate: ["body"], descendants: true, isSignal: true }, { propertyName: "footerTemplate", first: true, predicate: ["footer"], descendants: true, isSignal: true }, { propertyName: "overlay", first: true, predicate: ["overlay"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
10906
|
+
<!-- One <ng-content> per slot, each parked in a template so both modes can
|
|
10907
|
+
render the same projected nodes. The catch-all is declared last so the
|
|
10908
|
+
two selective slots claim their content first. -->
|
|
10909
|
+
<ng-template #header>
|
|
10910
|
+
@if (headline()) {
|
|
10911
|
+
<div uni-drawer-header></div>
|
|
10912
|
+
}
|
|
10913
|
+
<ng-content select="[uni-drawer-header]" />
|
|
10914
|
+
</ng-template>
|
|
10915
|
+
<ng-template #footer>
|
|
10916
|
+
<ng-content select="[uni-drawer-buttons], [drawer-buttons]" />
|
|
10917
|
+
</ng-template>
|
|
10918
|
+
<ng-template #body><ng-content /></ng-template>
|
|
10919
|
+
|
|
10569
10920
|
@if (mode() === 'side') {
|
|
10570
10921
|
<aside [class]="sideClass()" [attr.aria-hidden]="open() ? null : 'true'">
|
|
10571
|
-
<ng-container [ngTemplateOutlet]="
|
|
10922
|
+
<ng-container [ngTemplateOutlet]="headerTemplate()" />
|
|
10923
|
+
<div [class]="bodyClass()"><ng-container [ngTemplateOutlet]="bodyTemplate()" /></div>
|
|
10924
|
+
<ng-container [ngTemplateOutlet]="footerTemplate()" />
|
|
10572
10925
|
</aside>
|
|
10573
10926
|
} @else {
|
|
10574
10927
|
<!-- Click handles the ::backdrop only (target check); keyboard closing
|
|
@@ -10578,28 +10931,49 @@ class UniDrawerComponent extends BaseComponent {
|
|
|
10578
10931
|
<dialog
|
|
10579
10932
|
#overlay
|
|
10580
10933
|
[class]="overClass()"
|
|
10581
|
-
[attr.aria-
|
|
10934
|
+
[attr.aria-labelledby]="labelledBy()"
|
|
10935
|
+
[attr.aria-label]="labelledBy() ? null : ariaLabel()"
|
|
10582
10936
|
(click)="onBackdropClick($event)"
|
|
10583
10937
|
(cancel)="onCancel($event)"
|
|
10584
10938
|
(animationend)="onAnimationEnd($event)"
|
|
10585
10939
|
>
|
|
10586
|
-
<ng-container [ngTemplateOutlet]="
|
|
10940
|
+
<ng-container [ngTemplateOutlet]="headerTemplate()" />
|
|
10941
|
+
<div [class]="bodyClass()"><ng-container [ngTemplateOutlet]="bodyTemplate()" /></div>
|
|
10942
|
+
<ng-container [ngTemplateOutlet]="footerTemplate()" />
|
|
10587
10943
|
</dialog>
|
|
10588
10944
|
}
|
|
10589
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10945
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: UniDrawerHeaderComponent, selector: "[uni-drawer-header]", inputs: ["headline"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10590
10946
|
}
|
|
10591
10947
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerComponent, decorators: [{
|
|
10592
10948
|
type: Component,
|
|
10593
10949
|
args: [{
|
|
10594
10950
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
10595
10951
|
selector: 'uni-drawer',
|
|
10596
|
-
imports: [NgTemplateOutlet],
|
|
10597
|
-
providers: [
|
|
10952
|
+
imports: [NgTemplateOutlet, UniDrawerHeaderComponent],
|
|
10953
|
+
providers: [
|
|
10954
|
+
{ provide: COMPONENT_NAME, useValue: 'drawer' },
|
|
10955
|
+
{ provide: DRAWER_PANEL, useExisting: forwardRef(() => UniDrawerComponent) },
|
|
10956
|
+
],
|
|
10598
10957
|
template: `
|
|
10599
|
-
<ng-template
|
|
10958
|
+
<!-- One <ng-content> per slot, each parked in a template so both modes can
|
|
10959
|
+
render the same projected nodes. The catch-all is declared last so the
|
|
10960
|
+
two selective slots claim their content first. -->
|
|
10961
|
+
<ng-template #header>
|
|
10962
|
+
@if (headline()) {
|
|
10963
|
+
<div uni-drawer-header></div>
|
|
10964
|
+
}
|
|
10965
|
+
<ng-content select="[uni-drawer-header]" />
|
|
10966
|
+
</ng-template>
|
|
10967
|
+
<ng-template #footer>
|
|
10968
|
+
<ng-content select="[uni-drawer-buttons], [drawer-buttons]" />
|
|
10969
|
+
</ng-template>
|
|
10970
|
+
<ng-template #body><ng-content /></ng-template>
|
|
10971
|
+
|
|
10600
10972
|
@if (mode() === 'side') {
|
|
10601
10973
|
<aside [class]="sideClass()" [attr.aria-hidden]="open() ? null : 'true'">
|
|
10602
|
-
<ng-container [ngTemplateOutlet]="
|
|
10974
|
+
<ng-container [ngTemplateOutlet]="headerTemplate()" />
|
|
10975
|
+
<div [class]="bodyClass()"><ng-container [ngTemplateOutlet]="bodyTemplate()" /></div>
|
|
10976
|
+
<ng-container [ngTemplateOutlet]="footerTemplate()" />
|
|
10603
10977
|
</aside>
|
|
10604
10978
|
} @else {
|
|
10605
10979
|
<!-- Click handles the ::backdrop only (target check); keyboard closing
|
|
@@ -10609,17 +10983,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
10609
10983
|
<dialog
|
|
10610
10984
|
#overlay
|
|
10611
10985
|
[class]="overClass()"
|
|
10612
|
-
[attr.aria-
|
|
10986
|
+
[attr.aria-labelledby]="labelledBy()"
|
|
10987
|
+
[attr.aria-label]="labelledBy() ? null : ariaLabel()"
|
|
10613
10988
|
(click)="onBackdropClick($event)"
|
|
10614
10989
|
(cancel)="onCancel($event)"
|
|
10615
10990
|
(animationend)="onAnimationEnd($event)"
|
|
10616
10991
|
>
|
|
10617
|
-
<ng-container [ngTemplateOutlet]="
|
|
10992
|
+
<ng-container [ngTemplateOutlet]="headerTemplate()" />
|
|
10993
|
+
<div [class]="bodyClass()"><ng-container [ngTemplateOutlet]="bodyTemplate()" /></div>
|
|
10994
|
+
<ng-container [ngTemplateOutlet]="footerTemplate()" />
|
|
10618
10995
|
</dialog>
|
|
10619
10996
|
}
|
|
10620
10997
|
`,
|
|
10621
10998
|
}]
|
|
10622
|
-
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }],
|
|
10999
|
+
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], headline: [{ type: i0.Input, args: [{ isSignal: true, alias: "headline", required: false }] }], defaultCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultCloseButton", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], scrim: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrim", required: false }] }], initialFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialFocus", required: false }] }], closeRequest: [{ type: i0.Output, args: ["closeRequest"] }], disableAutoClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableAutoClose", required: false }] }], headerTemplate: [{ type: i0.ViewChild, args: ['header', { isSignal: true }] }], bodyTemplate: [{ type: i0.ViewChild, args: ['body', { isSignal: true }] }], footerTemplate: [{ type: i0.ViewChild, args: ['footer', { isSignal: true }] }], overlay: [{ type: i0.ViewChild, args: ['overlay', { isSignal: true }] }] } });
|
|
10623
11000
|
|
|
10624
11001
|
class UniExpandComponent extends BaseComponent {
|
|
10625
11002
|
collapsed = model(true, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
@@ -14263,5 +14640,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
14263
14640
|
* Generated bundle index. Do not edit.
|
|
14264
14641
|
*/
|
|
14265
14642
|
|
|
14266
|
-
export { BodyRenderDirective, ConfirmationDialogComponent, DragAndDropDirective, FOCUSABLE_SELECTOR, ListboxNavigation, LocalStorageService, NotificationService, NotificationsComponent, RippleDirective, TRANSFORM_ORIGINS, ThemeService, UNI_FORMS, UNI_LAYOUT, UNI_THEMES, UniAlertComponent, UniAppBarComponent, UniAvatarComponent, UniAvatarGroupComponent, UniBackgroundComponent, UniBadgeComponent, UniBaseDatasource, UniBoxDirective, UniBreadcrumbComponent, UniButtonComponent, UniButtonGroupComponent, UniCalendarComponent, UniCalloutComponent, UniCardComponent, UniCardContentComponent, UniCardHeaderComponent, UniCenterDirective, UniCheckboxComponent, UniComboboxComponent, UniDataSearchComponent, UniDataTableComponent, UniDateInputComponent, UniDateTimeInputComponent, UniDebounceInputComponent, UniDialogButtonsComponent, UniDialogComponent, UniDialogHeaderComponent, UniDividerComponent, UniDrawerComponent, UniDropdownComponent, UniExpandAreaComponent, UniExpandComponent, UniExpandToggleComponent, UniFileDropZoneComponent, UniGridAreaDirective, UniGridDirective, UniIconButtonComponent, UniIconComponent, UniInputBoxComponent, UniInputComponent, UniJsonViewComponent, UniMenuComponent, UniMultiSelectComponent, UniMultiSelectDropdownComponent, UniNotificationBadgeComponent, UniNumberInputComponent, UniNumberRangeInputComponent, UniPaginatorComponent, UniPopoverComponent, UniProgressBarComponent, UniProgressGaugeComponent, UniQuantityStepperComponent, UniRadioComponent, UniRecordDatasource, UniRowDirective, UniScrollAreaComponent, UniSearchInputComponent, UniSelectComponent, UniServerSideDatasource, UniSkeletonComponent, UniSliderComponent, UniSnackbarComponent, UniSortHeaderComponent, UniStackDirective, UniStatComponent, UniSymbolComponent, UniTabComponent, UniTabsComponent, UniTagComponent, UniTagInputComponent, UniTextDirective, UniTextareaComponent, UniThemeBuilderComponent, UniThemeSwitchComponent, UniTimeInputComponent, UniToggleComponent, UniTooltipComponent, UniTourComponent, UniWrapDirective, acceptableFile, addDays, addMonths, anchorArrowStyles, anchorStyles, buildMonthGrid, clampDecimal, clearAnchorName, compareDecimal, createAnnouncer, createListboxNavigation, createPressRepeat, dayOfWeek, daysInMonth, decimalScale, discreteOverlayTransition, evaluateExpression, focusableElements, formatDate, formatMonthHeading, formatNumber, formatTime, fromScaled, getFileExtension, inclusiveDayCount, isCanonicalDecimal, isDivider, isToggleOpen, isValidDate, isoDate, joinDateTime, listboxPopupAttr, listboxPopupStyles, localeDatePlaceholder, localeDefaultHour12, localeFieldOrder, localeMonthNames, localeNumberParts, localeWeekStart, losesPrecision, monthOf, motionSafe, newAnchorName, newListboxAnchor, normalizeDecimal, parseDateText, parseNumber, parseTimeText, promoteListboxPopup, rawNumberText, resolveElement, resolveFocusTarget, resolveNumberFormat, restoreOverlayFocus, roundDecimal, setAnchorName, settleNumber, shiftDecimal, speakNumber, splitDateTime, spotlightStyles, stepDecimal, supportsAnchoredPopup, timeSlots, toAsciiDigits, toDecimal, toNumber, toScaled, todayIso, transformOriginFor, uniqueId, useTimer, visuallyHidden, weekdayNames };
|
|
14643
|
+
export { BodyRenderDirective, ConfirmationDialogComponent, DRAWER_PANEL, DragAndDropDirective, FOCUSABLE_SELECTOR, ListboxNavigation, LocalStorageService, NotificationService, NotificationsComponent, RippleDirective, TRANSFORM_ORIGINS, ThemeService, UNI_FORMS, UNI_LAYOUT, UNI_THEMES, UniAlertComponent, UniAppBarComponent, UniAvatarComponent, UniAvatarGroupComponent, UniBackgroundComponent, UniBadgeComponent, UniBaseDatasource, UniBoxDirective, UniBreadcrumbComponent, UniButtonComponent, UniButtonGroupComponent, UniCalendarComponent, UniCalloutComponent, UniCardComponent, UniCardContentComponent, UniCardHeaderComponent, UniCenterDirective, UniCheckboxComponent, UniComboboxComponent, UniDataSearchComponent, UniDataTableComponent, UniDateInputComponent, UniDateTimeInputComponent, UniDebounceInputComponent, UniDialogButtonsComponent, UniDialogComponent, UniDialogHeaderComponent, UniDividerComponent, UniDrawerButtonsComponent, UniDrawerComponent, UniDrawerHeaderComponent, UniDropdownComponent, UniExpandAreaComponent, UniExpandComponent, UniExpandToggleComponent, UniFileDropZoneComponent, UniGridAreaDirective, UniGridDirective, UniIconButtonComponent, UniIconComponent, UniInputBoxComponent, UniInputComponent, UniJsonViewComponent, UniMenuComponent, UniMultiSelectComponent, UniMultiSelectDropdownComponent, UniNotificationBadgeComponent, UniNumberInputComponent, UniNumberRangeInputComponent, UniPaginatorComponent, UniPopoverComponent, UniProgressBarComponent, UniProgressGaugeComponent, UniQuantityStepperComponent, UniRadioComponent, UniRecordDatasource, UniRowDirective, UniScrollAreaComponent, UniSearchInputComponent, UniSelectComponent, UniServerSideDatasource, UniSkeletonComponent, UniSliderComponent, UniSnackbarComponent, UniSortHeaderComponent, UniStackDirective, UniStatComponent, UniSymbolComponent, UniTabComponent, UniTabsComponent, UniTagComponent, UniTagInputComponent, UniTextDirective, UniTextareaComponent, UniThemeBuilderComponent, UniThemeSwitchComponent, UniTimeInputComponent, UniToggleComponent, UniTooltipComponent, UniTourComponent, UniWrapDirective, acceptableFile, addDays, addMonths, anchorArrowStyles, anchorStyles, buildMonthGrid, clampDecimal, clearAnchorName, compareDecimal, createAnnouncer, createListboxNavigation, createPressRepeat, dayOfWeek, daysInMonth, decimalScale, discreteOverlayTransition, evaluateExpression, focusableElements, formatDate, formatMonthHeading, formatNumber, formatTime, fromScaled, getFileExtension, inclusiveDayCount, isCanonicalDecimal, isDivider, isToggleOpen, isValidDate, isoDate, joinDateTime, listboxPopupAttr, listboxPopupStyles, localeDatePlaceholder, localeDefaultHour12, localeFieldOrder, localeMonthNames, localeNumberParts, localeWeekStart, losesPrecision, monthOf, motionSafe, newAnchorName, newListboxAnchor, normalizeDecimal, parseDateText, parseNumber, parseTimeText, promoteListboxPopup, rawNumberText, resolveElement, resolveFocusTarget, resolveNumberFormat, restoreOverlayFocus, roundDecimal, setAnchorName, settleNumber, shiftDecimal, speakNumber, splitDateTime, spotlightStyles, stepDecimal, supportsAnchoredPopup, timeSlots, toAsciiDigits, toDecimal, toNumber, toScaled, todayIso, transformOriginFor, uniqueId, useTimer, visuallyHidden, weekdayNames };
|
|
14267
14644
|
//# sourceMappingURL=uni-design-system-uni-angular.mjs.map
|