@uni-design-system/uni-angular 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed, linkedSignal, resource, Injectable, inject, DestroyRef, InjectionToken, input, ChangeDetectionStrategy, Component, Renderer2, ElementRef, Directive, model,
|
|
2
|
+
import { signal, computed, linkedSignal, resource, Injectable, inject, DestroyRef, InjectionToken, input, ChangeDetectionStrategy, Component, contentChildren, output, Renderer2, ElementRef, Directive, model, effect, viewChild, afterNextRender, ViewChild, viewChildren } from '@angular/core';
|
|
3
3
|
import { injectGlobal, css, keyframes } from '@emotion/css';
|
|
4
|
-
import { UniThemes, LightTheme, toTypefaces, createThemeFromPalette, Z_INDEX, fadeIn, fadeOut, expandFadeIn, collapseFadeOut, removeInputPlatformStyling } from '@uni-design-system/uni-core';
|
|
4
|
+
import { UniThemes, LightTheme, toTypefaces, createThemeFromPalette, Z_INDEX, fadeIn, fadeOut, expandFadeIn, collapseFadeOut, removeInputPlatformStyling, ShapeRadii, generatePalette, emitThemeFile, emitDtcgTokens } from '@uni-design-system/uni-core';
|
|
5
5
|
import { NgClass, NgTemplateOutlet, CommonModule } from '@angular/common';
|
|
6
6
|
|
|
7
7
|
let nextUniqueId = 0;
|
|
@@ -901,6 +901,283 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
901
901
|
}]
|
|
902
902
|
}], ctorParameters: () => [] });
|
|
903
903
|
|
|
904
|
+
const COMPONENT_NAME = new InjectionToken('');
|
|
905
|
+
class BaseComponent {
|
|
906
|
+
componentName = inject(COMPONENT_NAME);
|
|
907
|
+
theme = inject(ThemeService);
|
|
908
|
+
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ [])); // TODO: Make Variant support undefined
|
|
909
|
+
size = input('lg', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
910
|
+
componentTheme = computed(() => this.theme.getComponentTheme(this.componentName)(), ...(ngDevMode ? [{ debugName: "componentTheme" }] : /* istanbul ignore next */ []));
|
|
911
|
+
componentOptions = computed(() => this.theme.getComponentOptions(this.componentName)(), ...(ngDevMode ? [{ debugName: "componentOptions" }] : /* istanbul ignore next */ []));
|
|
912
|
+
style = computed(() => this.theme.componentStyle(this.componentName, this.variant(), this.size())(), ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
|
|
913
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
914
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: BaseComponent, isStandalone: true, selector: "ng-component", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
915
|
+
}
|
|
916
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BaseComponent, decorators: [{
|
|
917
|
+
type: Component,
|
|
918
|
+
args: [{
|
|
919
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
920
|
+
imports: [],
|
|
921
|
+
template: ``,
|
|
922
|
+
}]
|
|
923
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Horizontal application bar: project leading controls (menu button, logo)
|
|
927
|
+
* with the `leading` attribute, actions with `trailing` (pushed to the far
|
|
928
|
+
* edge), and either pass `title` or project custom center content. Surface,
|
|
929
|
+
* divider, height, typography and spacing all resolve from `appBar` tokens.
|
|
930
|
+
* Place it inside your page's `<header>` landmark.
|
|
931
|
+
*/
|
|
932
|
+
class UniAppBarComponent extends BaseComponent {
|
|
933
|
+
/** Bar title; alternatively project your own center content. */
|
|
934
|
+
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
|
|
935
|
+
/** Stick the bar to the top of its scroll container. */
|
|
936
|
+
sticky = input(false, ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
|
|
937
|
+
className = computed(() => {
|
|
938
|
+
const options = this.componentOptions();
|
|
939
|
+
return css({
|
|
940
|
+
display: 'flex',
|
|
941
|
+
alignItems: 'center',
|
|
942
|
+
boxSizing: 'border-box',
|
|
943
|
+
width: '100%',
|
|
944
|
+
height: options.height ?? 56,
|
|
945
|
+
flex: 'none',
|
|
946
|
+
...this.theme.colorPair(options.color),
|
|
947
|
+
...this.theme.gap(options.gap),
|
|
948
|
+
...this.theme.paddingLeft(options.padding),
|
|
949
|
+
...this.theme.paddingRight(options.padding),
|
|
950
|
+
...this.theme.borderBottom(options.divider),
|
|
951
|
+
...this.theme.boxShadow(options.elevation),
|
|
952
|
+
'& .uni-app-bar-title': {
|
|
953
|
+
...this.theme.typeface(options.typeface),
|
|
954
|
+
whiteSpace: 'nowrap',
|
|
955
|
+
},
|
|
956
|
+
'& .uni-app-bar-spacer': { flexGrow: 1 },
|
|
957
|
+
...(this.sticky() && { position: 'sticky', top: 0, zIndex: 10 }),
|
|
958
|
+
});
|
|
959
|
+
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
960
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniAppBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
961
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniAppBarComponent, isStandalone: true, selector: "uni-app-bar, AppBar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'appBar' }], usesInheritance: true, ngImport: i0, template: `
|
|
962
|
+
<ng-content select="[leading]" />
|
|
963
|
+
@if (title()) {
|
|
964
|
+
<span class="uni-app-bar-title">{{ title() }}</span>
|
|
965
|
+
}
|
|
966
|
+
<ng-content />
|
|
967
|
+
<span class="uni-app-bar-spacer"></span>
|
|
968
|
+
<ng-content select="[trailing]" />
|
|
969
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
970
|
+
}
|
|
971
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniAppBarComponent, decorators: [{
|
|
972
|
+
type: Component,
|
|
973
|
+
args: [{
|
|
974
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
975
|
+
selector: 'uni-app-bar, AppBar',
|
|
976
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'appBar' }],
|
|
977
|
+
host: { '[class]': 'className()' },
|
|
978
|
+
template: `
|
|
979
|
+
<ng-content select="[leading]" />
|
|
980
|
+
@if (title()) {
|
|
981
|
+
<span class="uni-app-bar-title">{{ title() }}</span>
|
|
982
|
+
}
|
|
983
|
+
<ng-content />
|
|
984
|
+
<span class="uni-app-bar-spacer"></span>
|
|
985
|
+
<ng-content select="[trailing]" />
|
|
986
|
+
`,
|
|
987
|
+
}]
|
|
988
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }] } });
|
|
989
|
+
|
|
990
|
+
class UniSymbolComponent extends BaseComponent {
|
|
991
|
+
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
992
|
+
fill = input(...(ngDevMode ? [undefined, { debugName: "fill" }] : /* istanbul ignore next */ []));
|
|
993
|
+
weight = input(...(ngDevMode ? [undefined, { debugName: "weight" }] : /* istanbul ignore next */ []));
|
|
994
|
+
grade = input(...(ngDevMode ? [undefined, { debugName: "grade" }] : /* istanbul ignore next */ []));
|
|
995
|
+
opticalSize = input(...(ngDevMode ? [undefined, { debugName: "opticalSize" }] : /* istanbul ignore next */ []));
|
|
996
|
+
className = computed(() => {
|
|
997
|
+
const settings = `'FILL' ${this.fill() || this.componentOptions().fill || 0}, ` +
|
|
998
|
+
`'wght' ${this.weight() || this.componentOptions().weight || 400}, ` +
|
|
999
|
+
`'GRAD' ${this.grade() || this.componentOptions().grade || 0}, ` +
|
|
1000
|
+
`'opsz' ${this.opticalSize() || this.componentOptions().opticalSize || 24}`;
|
|
1001
|
+
return ('material-symbols-rounded ' +
|
|
1002
|
+
css({
|
|
1003
|
+
fontVariationSettings: settings,
|
|
1004
|
+
fontSize: `${this.opticalSize() || this.componentOptions().opticalSize || 24}px`,
|
|
1005
|
+
}));
|
|
1006
|
+
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1007
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSymbolComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1008
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniSymbolComponent, isStandalone: true, selector: "uni-symbol, Symbol", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: false, transformFunction: null }, grade: { classPropertyName: "grade", publicName: "grade", isSignal: true, isRequired: false, transformFunction: null }, opticalSize: { classPropertyName: "opticalSize", publicName: "opticalSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'symbol' }], usesInheritance: true, ngImport: i0, template: `{{ name() }}`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1009
|
+
}
|
|
1010
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSymbolComponent, decorators: [{
|
|
1011
|
+
type: Component,
|
|
1012
|
+
args: [{
|
|
1013
|
+
selector: 'uni-symbol, Symbol',
|
|
1014
|
+
imports: [],
|
|
1015
|
+
template: `{{ name() }}`,
|
|
1016
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'symbol' }],
|
|
1017
|
+
// Icons are decorative: hide the ligature text (e.g. "chevron_left") from
|
|
1018
|
+
// screen readers. Meaningful icons get their name from the parent control.
|
|
1019
|
+
host: {
|
|
1020
|
+
'[class]': 'className()',
|
|
1021
|
+
'aria-hidden': 'true',
|
|
1022
|
+
},
|
|
1023
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1024
|
+
}]
|
|
1025
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], fill: [{ type: i0.Input, args: [{ isSignal: true, alias: "fill", required: false }] }], weight: [{ type: i0.Input, args: [{ isSignal: true, alias: "weight", required: false }] }], grade: [{ type: i0.Input, args: [{ isSignal: true, alias: "grade", required: false }] }], opticalSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "opticalSize", required: false }] }] } });
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* Identity avatar with a graceful fallback chain: image → initials from
|
|
1029
|
+
* `name` → themed symbol. Coloring, radius, typeface and sizes all resolve
|
|
1030
|
+
* from `avatar` theme tokens; `variant` picks the container palette.
|
|
1031
|
+
*/
|
|
1032
|
+
class UniAvatarComponent extends BaseComponent {
|
|
1033
|
+
/** Image URL; on load error the avatar falls back to initials/symbol. */
|
|
1034
|
+
src = input(...(ngDevMode ? [undefined, { debugName: "src" }] : /* istanbul ignore next */ []));
|
|
1035
|
+
/** Person's name: drives the initials and the accessible label. */
|
|
1036
|
+
name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : /* istanbul ignore next */ []));
|
|
1037
|
+
/** Verbatim text instead of derived initials (e.g. a group's “+3”). */
|
|
1038
|
+
text = input(...(ngDevMode ? [undefined, { debugName: "text" }] : /* istanbul ignore next */ []));
|
|
1039
|
+
imageFailed = signal(false, ...(ngDevMode ? [{ debugName: "imageFailed" }] : /* istanbul ignore next */ []));
|
|
1040
|
+
showImage = computed(() => !!this.src() && !this.imageFailed(), ...(ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []));
|
|
1041
|
+
initials = computed(() => {
|
|
1042
|
+
const name = this.name()?.trim();
|
|
1043
|
+
if (!name)
|
|
1044
|
+
return '';
|
|
1045
|
+
const words = name.split(/\s+/);
|
|
1046
|
+
const first = words[0]?.[0] ?? '';
|
|
1047
|
+
const last = words.length > 1 ? (words[words.length - 1][0] ?? '') : '';
|
|
1048
|
+
return (first + last).toUpperCase();
|
|
1049
|
+
}, ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
1050
|
+
label = computed(() => this.name() ?? this.text(), ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
1051
|
+
className = computed(() => css([
|
|
1052
|
+
// Typeface (family/weight) before the merged theme style, so the size
|
|
1053
|
+
// record's fontSize wins over the typeface's.
|
|
1054
|
+
{
|
|
1055
|
+
...this.theme.typeface(this.componentOptions().typeface),
|
|
1056
|
+
...this.theme.radius(this.componentOptions().borderRadius),
|
|
1057
|
+
},
|
|
1058
|
+
this.style(),
|
|
1059
|
+
{
|
|
1060
|
+
display: 'inline-flex',
|
|
1061
|
+
alignItems: 'center',
|
|
1062
|
+
justifyContent: 'center',
|
|
1063
|
+
flex: 'none',
|
|
1064
|
+
overflow: 'hidden',
|
|
1065
|
+
userSelect: 'none',
|
|
1066
|
+
lineHeight: 1,
|
|
1067
|
+
'& img': { width: '100%', height: '100%', objectFit: 'cover' },
|
|
1068
|
+
'& symbol': { fontSize: '1.4em' },
|
|
1069
|
+
},
|
|
1070
|
+
]), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1071
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniAvatarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1072
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniAvatarComponent, isStandalone: true, selector: "uni-avatar, Avatar", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className()", "attr.role": "label() ? 'img' : null", "attr.aria-label": "label() || null", "attr.aria-hidden": "label() ? null : 'true'" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'avatar' }], usesInheritance: true, ngImport: i0, template: `
|
|
1073
|
+
@if (showImage()) {
|
|
1074
|
+
<img [src]="src()" alt="" (error)="imageFailed.set(true)" />
|
|
1075
|
+
} @else if (text()) {
|
|
1076
|
+
<span>{{ text() }}</span>
|
|
1077
|
+
} @else if (initials()) {
|
|
1078
|
+
<span>{{ initials() }}</span>
|
|
1079
|
+
} @else {
|
|
1080
|
+
<Symbol [name]="componentOptions().fallbackSymbol ?? 'person'" />
|
|
1081
|
+
}
|
|
1082
|
+
`, isInline: true, dependencies: [{ kind: "component", type: UniSymbolComponent, selector: "uni-symbol, Symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1083
|
+
}
|
|
1084
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniAvatarComponent, decorators: [{
|
|
1085
|
+
type: Component,
|
|
1086
|
+
args: [{
|
|
1087
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1088
|
+
selector: 'uni-avatar, Avatar',
|
|
1089
|
+
imports: [UniSymbolComponent],
|
|
1090
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'avatar' }],
|
|
1091
|
+
host: {
|
|
1092
|
+
'[class]': 'className()',
|
|
1093
|
+
'[attr.role]': "label() ? 'img' : null",
|
|
1094
|
+
'[attr.aria-label]': 'label() || null',
|
|
1095
|
+
'[attr.aria-hidden]': "label() ? null : 'true'",
|
|
1096
|
+
},
|
|
1097
|
+
template: `
|
|
1098
|
+
@if (showImage()) {
|
|
1099
|
+
<img [src]="src()" alt="" (error)="imageFailed.set(true)" />
|
|
1100
|
+
} @else if (text()) {
|
|
1101
|
+
<span>{{ text() }}</span>
|
|
1102
|
+
} @else if (initials()) {
|
|
1103
|
+
<span>{{ initials() }}</span>
|
|
1104
|
+
} @else {
|
|
1105
|
+
<Symbol [name]="componentOptions().fallbackSymbol ?? 'person'" />
|
|
1106
|
+
}
|
|
1107
|
+
`,
|
|
1108
|
+
}]
|
|
1109
|
+
}], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }] } });
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* Overlapping stack of avatars. `max` collapses the overflow into a themed
|
|
1113
|
+
* “+N” chip (itself a `uni-avatar`). Overlap and separator ring resolve from
|
|
1114
|
+
* `avatarGroup` theme tokens.
|
|
1115
|
+
*/
|
|
1116
|
+
class UniAvatarGroupComponent extends BaseComponent {
|
|
1117
|
+
/** Show at most this many avatars; the rest collapse into a “+N” chip. */
|
|
1118
|
+
max = input(undefined, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
1119
|
+
avatars = contentChildren(UniAvatarComponent, ...(ngDevMode ? [{ debugName: "avatars" }] : /* istanbul ignore next */ []));
|
|
1120
|
+
surplus = computed(() => {
|
|
1121
|
+
const max = this.max();
|
|
1122
|
+
if (max === undefined)
|
|
1123
|
+
return 0;
|
|
1124
|
+
return Math.max(0, this.avatars().length - max);
|
|
1125
|
+
}, ...(ngDevMode ? [{ debugName: "surplus" }] : /* istanbul ignore next */ []));
|
|
1126
|
+
className = computed(() => {
|
|
1127
|
+
const options = this.componentOptions();
|
|
1128
|
+
const overlap = this.theme.spacing()[options.overlap ?? 'sm'] ?? '8px';
|
|
1129
|
+
const ring = `${options.ringWidth ?? 2}px solid ${this.theme.colors()[options.ringColor ?? 'surface'] ?? 'transparent'}`;
|
|
1130
|
+
const max = this.max();
|
|
1131
|
+
return css({
|
|
1132
|
+
display: 'inline-flex',
|
|
1133
|
+
alignItems: 'center',
|
|
1134
|
+
'& uni-avatar': {
|
|
1135
|
+
border: ring,
|
|
1136
|
+
marginLeft: `calc(-1 * ${overlap})`,
|
|
1137
|
+
'&:first-child': { marginLeft: 0 },
|
|
1138
|
+
},
|
|
1139
|
+
// Collapse the overflow: hide projected avatars past `max`, but never
|
|
1140
|
+
// the surplus chip this component renders itself.
|
|
1141
|
+
...(max !== undefined && {
|
|
1142
|
+
[`& uni-avatar:nth-of-type(n + ${max + 1}):not(.uni-surplus)`]: { display: 'none' },
|
|
1143
|
+
}),
|
|
1144
|
+
});
|
|
1145
|
+
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1146
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniAvatarGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1147
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniAvatarGroupComponent, isStandalone: true, selector: "uni-avatar-group, AvatarGroup", inputs: { max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'avatarGroup' }], queries: [{ propertyName: "avatars", predicate: UniAvatarComponent, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
1148
|
+
<ng-content />
|
|
1149
|
+
@if (surplus() > 0) {
|
|
1150
|
+
<uni-avatar
|
|
1151
|
+
class="uni-surplus"
|
|
1152
|
+
[text]="'+' + surplus()"
|
|
1153
|
+
variant="quaternary"
|
|
1154
|
+
[size]="size()"
|
|
1155
|
+
/>
|
|
1156
|
+
}
|
|
1157
|
+
`, isInline: true, dependencies: [{ kind: "component", type: UniAvatarComponent, selector: "uni-avatar, Avatar", inputs: ["src", "name", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1158
|
+
}
|
|
1159
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniAvatarGroupComponent, decorators: [{
|
|
1160
|
+
type: Component,
|
|
1161
|
+
args: [{
|
|
1162
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1163
|
+
selector: 'uni-avatar-group, AvatarGroup',
|
|
1164
|
+
imports: [UniAvatarComponent],
|
|
1165
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'avatarGroup' }],
|
|
1166
|
+
host: { '[class]': 'className()', role: 'group' },
|
|
1167
|
+
template: `
|
|
1168
|
+
<ng-content />
|
|
1169
|
+
@if (surplus() > 0) {
|
|
1170
|
+
<uni-avatar
|
|
1171
|
+
class="uni-surplus"
|
|
1172
|
+
[text]="'+' + surplus()"
|
|
1173
|
+
variant="quaternary"
|
|
1174
|
+
[size]="size()"
|
|
1175
|
+
/>
|
|
1176
|
+
}
|
|
1177
|
+
`,
|
|
1178
|
+
}]
|
|
1179
|
+
}], propDecorators: { max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], avatars: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => UniAvatarComponent), { isSignal: true }] }] } });
|
|
1180
|
+
|
|
904
1181
|
class UniBackgroundComponent {
|
|
905
1182
|
theme = inject(ThemeService);
|
|
906
1183
|
image = input(...(ngDevMode ? [undefined, { debugName: "image" }] : /* istanbul ignore next */ []));
|
|
@@ -941,27 +1218,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
941
1218
|
* This file exports all public-facing elements of the background component.
|
|
942
1219
|
*/
|
|
943
1220
|
|
|
944
|
-
const COMPONENT_NAME = new InjectionToken('');
|
|
945
|
-
class BaseComponent {
|
|
946
|
-
componentName = inject(COMPONENT_NAME);
|
|
947
|
-
theme = inject(ThemeService);
|
|
948
|
-
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ [])); // TODO: Make Variant support undefined
|
|
949
|
-
size = input('lg', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
950
|
-
componentTheme = computed(() => this.theme.getComponentTheme(this.componentName)(), ...(ngDevMode ? [{ debugName: "componentTheme" }] : /* istanbul ignore next */ []));
|
|
951
|
-
componentOptions = computed(() => this.theme.getComponentOptions(this.componentName)(), ...(ngDevMode ? [{ debugName: "componentOptions" }] : /* istanbul ignore next */ []));
|
|
952
|
-
style = computed(() => this.theme.componentStyle(this.componentName, this.variant(), this.size())(), ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
|
|
953
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
954
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: BaseComponent, isStandalone: true, selector: "ng-component", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
955
|
-
}
|
|
956
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BaseComponent, decorators: [{
|
|
957
|
-
type: Component,
|
|
958
|
-
args: [{
|
|
959
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
960
|
-
imports: [],
|
|
961
|
-
template: ``,
|
|
962
|
-
}]
|
|
963
|
-
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
964
|
-
|
|
965
1221
|
class UniBadgeComponent extends BaseComponent {
|
|
966
1222
|
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
967
1223
|
useVariant = input(false, ...(ngDevMode ? [{ debugName: "useVariant" }] : /* istanbul ignore next */ []));
|
|
@@ -998,6 +1254,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
998
1254
|
}]
|
|
999
1255
|
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], useVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "useVariant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }] } });
|
|
1000
1256
|
|
|
1257
|
+
/**
|
|
1258
|
+
* WAI-ARIA breadcrumb: a `nav` landmark wrapping an ordered list; the last
|
|
1259
|
+
* item is the current page (`aria-current="page"`), separators are decorative.
|
|
1260
|
+
* Items with `href` render as real links; without one they render as
|
|
1261
|
+
* link-styled buttons emitting `itemClicked` — wire that to your router.
|
|
1262
|
+
*/
|
|
1263
|
+
class UniBreadcrumbComponent extends BaseComponent {
|
|
1264
|
+
/** The trail, root first; the last item is the current page. */
|
|
1265
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
1266
|
+
/** Landmark label distinguishing this nav from others on the page. */
|
|
1267
|
+
ariaLabel = input('Breadcrumb', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
1268
|
+
/** Emits the clicked ancestor item (also fires for `href` links). */
|
|
1269
|
+
itemClicked = output();
|
|
1270
|
+
className = computed(() => {
|
|
1271
|
+
const options = this.componentOptions();
|
|
1272
|
+
const linkColor = this.theme.colors()[options.color ?? 'on-background-variant'];
|
|
1273
|
+
return css({
|
|
1274
|
+
'& ol': {
|
|
1275
|
+
display: 'flex',
|
|
1276
|
+
alignItems: 'center',
|
|
1277
|
+
flexWrap: 'wrap',
|
|
1278
|
+
listStyle: 'none',
|
|
1279
|
+
margin: 0,
|
|
1280
|
+
padding: 0,
|
|
1281
|
+
...this.theme.typeface(options.typeface),
|
|
1282
|
+
},
|
|
1283
|
+
'& li': {
|
|
1284
|
+
display: 'inline-flex',
|
|
1285
|
+
alignItems: 'center',
|
|
1286
|
+
...this.theme.gap(options.gap),
|
|
1287
|
+
},
|
|
1288
|
+
'& a, & button': {
|
|
1289
|
+
background: 'none',
|
|
1290
|
+
border: 0,
|
|
1291
|
+
padding: 0,
|
|
1292
|
+
font: 'inherit',
|
|
1293
|
+
cursor: 'pointer',
|
|
1294
|
+
textDecoration: 'none',
|
|
1295
|
+
color: linkColor,
|
|
1296
|
+
'&:hover': { textDecoration: 'underline' },
|
|
1297
|
+
'&:focus-visible': {
|
|
1298
|
+
outline: `2px solid ${this.theme.colors()['primary']}`,
|
|
1299
|
+
outlineOffset: 2,
|
|
1300
|
+
},
|
|
1301
|
+
},
|
|
1302
|
+
'& [aria-current]': {
|
|
1303
|
+
...this.theme.color(options.currentColor),
|
|
1304
|
+
},
|
|
1305
|
+
'& symbol': { fontSize: '1.1em', ...this.theme.color(options.color) },
|
|
1306
|
+
...this.theme.gap(options.gap),
|
|
1307
|
+
});
|
|
1308
|
+
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1309
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniBreadcrumbComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1310
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniBreadcrumbComponent, isStandalone: true, selector: "uni-breadcrumb, Breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, providers: [{ provide: COMPONENT_NAME, useValue: 'breadcrumb' }], usesInheritance: true, ngImport: i0, template: `
|
|
1311
|
+
<nav [attr.aria-label]="ariaLabel()" [class]="className()">
|
|
1312
|
+
<ol>
|
|
1313
|
+
@for (item of items(); track item.label; let last = $last; let i = $index) {
|
|
1314
|
+
<li>
|
|
1315
|
+
@if (last) {
|
|
1316
|
+
<span aria-current="page">{{ item.label }}</span>
|
|
1317
|
+
} @else if (item.href) {
|
|
1318
|
+
<a [href]="item.href" (click)="itemClicked.emit(item)">{{ item.label }}</a>
|
|
1319
|
+
} @else {
|
|
1320
|
+
<button type="button" (click)="itemClicked.emit(item)">{{ item.label }}</button>
|
|
1321
|
+
}
|
|
1322
|
+
@if (!last) {
|
|
1323
|
+
<Symbol
|
|
1324
|
+
aria-hidden="true"
|
|
1325
|
+
[name]="componentOptions().separatorSymbol ?? 'chevron_right'"
|
|
1326
|
+
/>
|
|
1327
|
+
}
|
|
1328
|
+
</li>
|
|
1329
|
+
}
|
|
1330
|
+
</ol>
|
|
1331
|
+
</nav>
|
|
1332
|
+
`, isInline: true, dependencies: [{ kind: "component", type: UniSymbolComponent, selector: "uni-symbol, Symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1333
|
+
}
|
|
1334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniBreadcrumbComponent, decorators: [{
|
|
1335
|
+
type: Component,
|
|
1336
|
+
args: [{
|
|
1337
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1338
|
+
selector: 'uni-breadcrumb, Breadcrumb',
|
|
1339
|
+
imports: [UniSymbolComponent],
|
|
1340
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'breadcrumb' }],
|
|
1341
|
+
template: `
|
|
1342
|
+
<nav [attr.aria-label]="ariaLabel()" [class]="className()">
|
|
1343
|
+
<ol>
|
|
1344
|
+
@for (item of items(); track item.label; let last = $last; let i = $index) {
|
|
1345
|
+
<li>
|
|
1346
|
+
@if (last) {
|
|
1347
|
+
<span aria-current="page">{{ item.label }}</span>
|
|
1348
|
+
} @else if (item.href) {
|
|
1349
|
+
<a [href]="item.href" (click)="itemClicked.emit(item)">{{ item.label }}</a>
|
|
1350
|
+
} @else {
|
|
1351
|
+
<button type="button" (click)="itemClicked.emit(item)">{{ item.label }}</button>
|
|
1352
|
+
}
|
|
1353
|
+
@if (!last) {
|
|
1354
|
+
<Symbol
|
|
1355
|
+
aria-hidden="true"
|
|
1356
|
+
[name]="componentOptions().separatorSymbol ?? 'chevron_right'"
|
|
1357
|
+
/>
|
|
1358
|
+
}
|
|
1359
|
+
</li>
|
|
1360
|
+
}
|
|
1361
|
+
</ol>
|
|
1362
|
+
</nav>
|
|
1363
|
+
`,
|
|
1364
|
+
}]
|
|
1365
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
1366
|
+
|
|
1001
1367
|
class UniIconComponent {
|
|
1002
1368
|
themeService = inject(ThemeService);
|
|
1003
1369
|
color = input(...(ngDevMode ? [undefined, { debugName: "color" }] : /* istanbul ignore next */ []));
|
|
@@ -1289,43 +1655,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1289
1655
|
}]
|
|
1290
1656
|
}], ctorParameters: () => [], propDecorators: { display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], wrapItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrapItems", required: false }] }] } });
|
|
1291
1657
|
|
|
1292
|
-
class UniSymbolComponent extends BaseComponent {
|
|
1293
|
-
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
1294
|
-
fill = input(...(ngDevMode ? [undefined, { debugName: "fill" }] : /* istanbul ignore next */ []));
|
|
1295
|
-
weight = input(...(ngDevMode ? [undefined, { debugName: "weight" }] : /* istanbul ignore next */ []));
|
|
1296
|
-
grade = input(...(ngDevMode ? [undefined, { debugName: "grade" }] : /* istanbul ignore next */ []));
|
|
1297
|
-
opticalSize = input(...(ngDevMode ? [undefined, { debugName: "opticalSize" }] : /* istanbul ignore next */ []));
|
|
1298
|
-
className = computed(() => {
|
|
1299
|
-
const settings = `'FILL' ${this.fill() || this.componentOptions().fill || 0}, ` +
|
|
1300
|
-
`'wght' ${this.weight() || this.componentOptions().weight || 400}, ` +
|
|
1301
|
-
`'GRAD' ${this.grade() || this.componentOptions().grade || 0}, ` +
|
|
1302
|
-
`'opsz' ${this.opticalSize() || this.componentOptions().opticalSize || 24}`;
|
|
1303
|
-
return ('material-symbols-rounded ' +
|
|
1304
|
-
css({
|
|
1305
|
-
fontVariationSettings: settings,
|
|
1306
|
-
fontSize: `${this.opticalSize() || this.componentOptions().opticalSize || 24}px`,
|
|
1307
|
-
}));
|
|
1308
|
-
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
1309
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSymbolComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1310
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniSymbolComponent, isStandalone: true, selector: "uni-symbol, Symbol", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, weight: { classPropertyName: "weight", publicName: "weight", isSignal: true, isRequired: false, transformFunction: null }, grade: { classPropertyName: "grade", publicName: "grade", isSignal: true, isRequired: false, transformFunction: null }, opticalSize: { classPropertyName: "opticalSize", publicName: "opticalSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'symbol' }], usesInheritance: true, ngImport: i0, template: `{{ name() }}`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1311
|
-
}
|
|
1312
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSymbolComponent, decorators: [{
|
|
1313
|
-
type: Component,
|
|
1314
|
-
args: [{
|
|
1315
|
-
selector: 'uni-symbol, Symbol',
|
|
1316
|
-
imports: [],
|
|
1317
|
-
template: `{{ name() }}`,
|
|
1318
|
-
providers: [{ provide: COMPONENT_NAME, useValue: 'symbol' }],
|
|
1319
|
-
// Icons are decorative: hide the ligature text (e.g. "chevron_left") from
|
|
1320
|
-
// screen readers. Meaningful icons get their name from the parent control.
|
|
1321
|
-
host: {
|
|
1322
|
-
'[class]': 'className()',
|
|
1323
|
-
'aria-hidden': 'true',
|
|
1324
|
-
},
|
|
1325
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1326
|
-
}]
|
|
1327
|
-
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], fill: [{ type: i0.Input, args: [{ isSignal: true, alias: "fill", required: false }] }], weight: [{ type: i0.Input, args: [{ isSignal: true, alias: "weight", required: false }] }], grade: [{ type: i0.Input, args: [{ isSignal: true, alias: "grade", required: false }] }], opticalSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "opticalSize", required: false }] }] } });
|
|
1328
|
-
|
|
1329
1658
|
// https://css-tricks.com/how-to-recreate-the-ripple-effect-of-material-design-buttons/
|
|
1330
1659
|
class RippleDirective {
|
|
1331
1660
|
renderer = inject(Renderer2);
|
|
@@ -1401,6 +1730,11 @@ class UniButtonComponent extends BaseComponent {
|
|
|
1401
1730
|
paddingBottom: '6%',
|
|
1402
1731
|
});
|
|
1403
1732
|
className = computed(() => css([
|
|
1733
|
+
// Token-driven radius + typeface from component options. Applied before
|
|
1734
|
+
// `style()` so theme `sizes`/`fixed` (per-size fontSize, or hand-set
|
|
1735
|
+
// radii/families in older themes) keep winning.
|
|
1736
|
+
this.theme.radius(this.componentOptions().borderRadius),
|
|
1737
|
+
{ ...this.theme.typeface(this.componentOptions().typeface) },
|
|
1404
1738
|
this.style() && {
|
|
1405
1739
|
...this.style(), // TODO: Set priority on theme-defined styles
|
|
1406
1740
|
},
|
|
@@ -1618,12 +1952,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1618
1952
|
}], propDecorators: { typeface: [{ type: i0.Input, args: [{ isSignal: true, alias: "typeface", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], nowrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "nowrap", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], ellipsis: [{ type: i0.Input, args: [{ isSignal: true, alias: "ellipsis", required: false }] }] } });
|
|
1619
1953
|
|
|
1620
1954
|
class UniCardComponent extends BaseComponent {
|
|
1955
|
+
/**
|
|
1956
|
+
* Token-resolved frame (variant-named border primitive, radii, elevation)
|
|
1957
|
+
* under the merged theme style, so hand-authored fixed/variant styles from
|
|
1958
|
+
* older themes keep winning.
|
|
1959
|
+
*/
|
|
1960
|
+
cardStyle = computed(() => ({
|
|
1961
|
+
...this.theme.border(this.componentOptions().border ?? this.variant()),
|
|
1962
|
+
...this.theme.radius(this.componentOptions().borderRadius),
|
|
1963
|
+
...this.theme.boxShadow(this.componentOptions().elevation),
|
|
1964
|
+
...this.style(),
|
|
1965
|
+
}), ...(ngDevMode ? [{ debugName: "cardStyle" }] : /* istanbul ignore next */ []));
|
|
1621
1966
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniCardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1622
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: UniCardComponent, isStandalone: true, selector: "uni-card, Card", providers: [{ provide: COMPONENT_NAME, useValue: 'card' }], usesInheritance: true, ngImport: i0, template: "<div [style]=\"
|
|
1967
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: UniCardComponent, isStandalone: true, selector: "uni-card, Card", providers: [{ provide: COMPONENT_NAME, useValue: 'card' }], usesInheritance: true, ngImport: i0, template: "<div [style]=\"cardStyle()\">\n <ng-content></ng-content>\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1623
1968
|
}
|
|
1624
1969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniCardComponent, decorators: [{
|
|
1625
1970
|
type: Component,
|
|
1626
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-card, Card', imports: [], providers: [{ provide: COMPONENT_NAME, useValue: 'card' }], template: "<div [style]=\"
|
|
1971
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-card, Card', imports: [], providers: [{ provide: COMPONENT_NAME, useValue: 'card' }], template: "<div [style]=\"cardStyle()\">\n <ng-content></ng-content>\n</div>\n" }]
|
|
1627
1972
|
}] });
|
|
1628
1973
|
|
|
1629
1974
|
class UniCardHeaderComponent extends BaseComponent {
|
|
@@ -1868,7 +2213,9 @@ class UniIconButtonComponent {
|
|
|
1868
2213
|
border: 0,
|
|
1869
2214
|
cursor: 'pointer',
|
|
1870
2215
|
transition: 'all 0.28s ease',
|
|
1871
|
-
|
|
2216
|
+
// Token-driven radius (`max` = circle) with the legacy 999 fallback
|
|
2217
|
+
// for hand-authored themes that predate iconButton options.
|
|
2218
|
+
...(this.theme.radius(this.config().options?.borderRadius) ?? { borderRadius: 999 }),
|
|
1872
2219
|
display: 'block',
|
|
1873
2220
|
'&:disabled': {
|
|
1874
2221
|
cursor: 'not-allowed !important',
|
|
@@ -2652,6 +2999,158 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
2652
2999
|
}]
|
|
2653
3000
|
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], border: [{ type: i0.Input, args: [{ isSignal: true, alias: "border", required: false }] }] } });
|
|
2654
3001
|
|
|
3002
|
+
/**
|
|
3003
|
+
* Navigation drawer with two modes sharing one content slot:
|
|
3004
|
+
*
|
|
3005
|
+
* - `side` — an in-flow `<aside>` that pushes content (dashboard sidenav);
|
|
3006
|
+
* opening/closing animates its width, and the divider border primitive
|
|
3007
|
+
* separates it from the page.
|
|
3008
|
+
* - `over` — a native `<dialog>` in the top layer: focus trap, Escape and
|
|
3009
|
+
* scrim backdrop come from the platform (same machinery as `uni-dialog`),
|
|
3010
|
+
* sliding in from its edge.
|
|
3011
|
+
*
|
|
3012
|
+
* Surface, width, divider, elevation, padding and backdrop all resolve from
|
|
3013
|
+
* `drawer` theme tokens.
|
|
3014
|
+
*/
|
|
3015
|
+
class UniDrawerComponent extends BaseComponent {
|
|
3016
|
+
/** Two-way bindable open state: [(open)]. */
|
|
3017
|
+
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
3018
|
+
mode = input('side', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
3019
|
+
position = input('start', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
3020
|
+
/** Accessible name for the overlay mode's dialog. */
|
|
3021
|
+
ariaLabel = input('Navigation', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
3022
|
+
contentTemplate = viewChild.required('content');
|
|
3023
|
+
overlay = viewChild('overlay', ...(ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []));
|
|
3024
|
+
constructor() {
|
|
3025
|
+
super();
|
|
3026
|
+
effect(() => {
|
|
3027
|
+
const dialog = this.overlay()?.nativeElement;
|
|
3028
|
+
if (!dialog)
|
|
3029
|
+
return;
|
|
3030
|
+
if (this.open()) {
|
|
3031
|
+
if (!dialog.open) {
|
|
3032
|
+
dialog.removeAttribute('closing');
|
|
3033
|
+
dialog.showModal();
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
else if (dialog.open) {
|
|
3037
|
+
// Slide out first; the dialog closes when the animation reports done.
|
|
3038
|
+
dialog.setAttribute('closing', 'true');
|
|
3039
|
+
}
|
|
3040
|
+
});
|
|
3041
|
+
}
|
|
3042
|
+
onBackdropClick(event) {
|
|
3043
|
+
if (event.target.nodeName === 'DIALOG')
|
|
3044
|
+
this.open.set(false);
|
|
3045
|
+
}
|
|
3046
|
+
/** Route Escape through the animated close, keeping `open` in sync. */
|
|
3047
|
+
onCancel(event) {
|
|
3048
|
+
event.preventDefault();
|
|
3049
|
+
this.open.set(false);
|
|
3050
|
+
}
|
|
3051
|
+
onAnimationEnd(event) {
|
|
3052
|
+
const dialog = this.overlay()?.nativeElement;
|
|
3053
|
+
if (!dialog || !dialog.hasAttribute('closing'))
|
|
3054
|
+
return;
|
|
3055
|
+
if (event.animationName.includes(this.slideOut())) {
|
|
3056
|
+
dialog.close();
|
|
3057
|
+
dialog.removeAttribute('closing');
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
edge = computed(() => (this.position() === 'start' ? '-100%' : '100%'), ...(ngDevMode ? [{ debugName: "edge" }] : /* istanbul ignore next */ []));
|
|
3061
|
+
slideIn = computed(() => keyframes({ from: { transform: `translateX(${this.edge()})` }, to: { transform: 'translateX(0)' } }), ...(ngDevMode ? [{ debugName: "slideIn" }] : /* istanbul ignore next */ []));
|
|
3062
|
+
slideOut = computed(() => keyframes({ from: { transform: 'translateX(0)' }, to: { transform: `translateX(${this.edge()})` } }), ...(ngDevMode ? [{ debugName: "slideOut" }] : /* istanbul ignore next */ []));
|
|
3063
|
+
sideClass = computed(() => {
|
|
3064
|
+
const options = this.componentOptions();
|
|
3065
|
+
const width = options.width ?? 280;
|
|
3066
|
+
const start = this.position() === 'start';
|
|
3067
|
+
return css({
|
|
3068
|
+
display: 'block',
|
|
3069
|
+
boxSizing: 'border-box',
|
|
3070
|
+
height: '100%',
|
|
3071
|
+
flex: 'none',
|
|
3072
|
+
overflowX: 'hidden',
|
|
3073
|
+
overflowY: 'auto',
|
|
3074
|
+
transition: 'width 0.25s ease, visibility 0.25s',
|
|
3075
|
+
...this.theme.colorPair(options.color),
|
|
3076
|
+
...(start
|
|
3077
|
+
? this.theme.borderRight(options.divider)
|
|
3078
|
+
: this.theme.borderLeft(options.divider)),
|
|
3079
|
+
...(this.open()
|
|
3080
|
+
? { width, visibility: 'visible', ...this.theme.padding(options.padding) }
|
|
3081
|
+
: { width: 0, visibility: 'hidden', padding: 0, border: 'none' }),
|
|
3082
|
+
});
|
|
3083
|
+
}, ...(ngDevMode ? [{ debugName: "sideClass" }] : /* istanbul ignore next */ []));
|
|
3084
|
+
overClass = computed(() => {
|
|
3085
|
+
const options = this.componentOptions();
|
|
3086
|
+
const start = this.position() === 'start';
|
|
3087
|
+
return css({
|
|
3088
|
+
boxSizing: 'border-box',
|
|
3089
|
+
width: options.width ?? 280,
|
|
3090
|
+
maxWidth: '90vw',
|
|
3091
|
+
height: '100dvh',
|
|
3092
|
+
maxHeight: '100dvh',
|
|
3093
|
+
border: 'none',
|
|
3094
|
+
margin: start ? '0 auto 0 0' : '0 0 0 auto',
|
|
3095
|
+
overflowY: 'auto',
|
|
3096
|
+
...this.theme.colorPair(options.color),
|
|
3097
|
+
...this.theme.padding(options.padding),
|
|
3098
|
+
...this.theme.boxShadow(options.elevation),
|
|
3099
|
+
'&::backdrop': { ...options.backdrop },
|
|
3100
|
+
'&[open]': { animation: `${this.slideIn()} 250ms ease-out` },
|
|
3101
|
+
'&[closing]': { animation: `${this.slideOut()} 250ms ease-in` },
|
|
3102
|
+
});
|
|
3103
|
+
}, ...(ngDevMode ? [{ debugName: "overClass" }] : /* istanbul ignore next */ []));
|
|
3104
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3105
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniDrawerComponent, isStandalone: true, selector: "uni-drawer, 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 } }, outputs: { open: "openChange" }, providers: [{ provide: COMPONENT_NAME, useValue: 'drawer' }], viewQueries: [{ propertyName: "contentTemplate", first: true, predicate: ["content"], descendants: true, isSignal: true }, { propertyName: "overlay", first: true, predicate: ["overlay"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
3106
|
+
<ng-template #content><ng-content /></ng-template>
|
|
3107
|
+
@if (mode() === 'side') {
|
|
3108
|
+
<aside [class]="sideClass()" [attr.aria-hidden]="open() ? null : 'true'">
|
|
3109
|
+
<ng-container [ngTemplateOutlet]="contentTemplate()" />
|
|
3110
|
+
</aside>
|
|
3111
|
+
} @else {
|
|
3112
|
+
<dialog
|
|
3113
|
+
#overlay
|
|
3114
|
+
[class]="overClass()"
|
|
3115
|
+
[attr.aria-label]="ariaLabel()"
|
|
3116
|
+
(click)="onBackdropClick($event)"
|
|
3117
|
+
(cancel)="onCancel($event)"
|
|
3118
|
+
(animationend)="onAnimationEnd($event)"
|
|
3119
|
+
>
|
|
3120
|
+
<ng-container [ngTemplateOutlet]="contentTemplate()" />
|
|
3121
|
+
</dialog>
|
|
3122
|
+
}
|
|
3123
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3124
|
+
}
|
|
3125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniDrawerComponent, decorators: [{
|
|
3126
|
+
type: Component,
|
|
3127
|
+
args: [{
|
|
3128
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3129
|
+
selector: 'uni-drawer, Drawer',
|
|
3130
|
+
imports: [NgTemplateOutlet],
|
|
3131
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'drawer' }],
|
|
3132
|
+
template: `
|
|
3133
|
+
<ng-template #content><ng-content /></ng-template>
|
|
3134
|
+
@if (mode() === 'side') {
|
|
3135
|
+
<aside [class]="sideClass()" [attr.aria-hidden]="open() ? null : 'true'">
|
|
3136
|
+
<ng-container [ngTemplateOutlet]="contentTemplate()" />
|
|
3137
|
+
</aside>
|
|
3138
|
+
} @else {
|
|
3139
|
+
<dialog
|
|
3140
|
+
#overlay
|
|
3141
|
+
[class]="overClass()"
|
|
3142
|
+
[attr.aria-label]="ariaLabel()"
|
|
3143
|
+
(click)="onBackdropClick($event)"
|
|
3144
|
+
(cancel)="onCancel($event)"
|
|
3145
|
+
(animationend)="onAnimationEnd($event)"
|
|
3146
|
+
>
|
|
3147
|
+
<ng-container [ngTemplateOutlet]="contentTemplate()" />
|
|
3148
|
+
</dialog>
|
|
3149
|
+
}
|
|
3150
|
+
`,
|
|
3151
|
+
}]
|
|
3152
|
+
}], 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 }] }], contentTemplate: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }], overlay: [{ type: i0.ViewChild, args: ['overlay', { isSignal: true }] }] } });
|
|
3153
|
+
|
|
2655
3154
|
class UniDropdownComponent extends BaseComponent {
|
|
2656
3155
|
renderer = inject(Renderer2);
|
|
2657
3156
|
delay = 100;
|
|
@@ -3387,6 +3886,8 @@ class UniInputBoxComponent extends BaseComponent {
|
|
|
3387
3886
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3388
3887
|
error = input(false, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
3389
3888
|
minWidth = input('0', ...(ngDevMode ? [{ debugName: "minWidth" }] : /* istanbul ignore next */ []));
|
|
3889
|
+
/** Override the themed field height, e.g. `'auto'` for multi-line fields. */
|
|
3890
|
+
height = input(undefined, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
|
|
3390
3891
|
color = computed(() => this.error() ? this.componentOptions().errorColor : this.componentOptions().color, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
3391
3892
|
border = computed(() => this.error() ? this.componentOptions().errorBorder : this.componentOptions().border, ...(ngDevMode ? [{ debugName: "border" }] : /* istanbul ignore next */ []));
|
|
3392
3893
|
shadow = computed(() => this.error() ? this.componentOptions().errorShadow : this.componentOptions().shadow, ...(ngDevMode ? [{ debugName: "shadow" }] : /* istanbul ignore next */ []));
|
|
@@ -3397,33 +3898,39 @@ class UniInputBoxComponent extends BaseComponent {
|
|
|
3397
3898
|
cursor: 'not-allowed !important',
|
|
3398
3899
|
},
|
|
3399
3900
|
{
|
|
3400
|
-
'& input, select': {
|
|
3901
|
+
'& input, select, textarea': {
|
|
3401
3902
|
...removeInputPlatformStyling,
|
|
3402
3903
|
height: '100%',
|
|
3403
3904
|
...this.theme.paddingLeft(this.componentOptions().paddingLeft),
|
|
3404
3905
|
...this.theme.color(this.componentOptions().textColor),
|
|
3405
3906
|
...this.theme.typeface(this.componentOptions().typeFace),
|
|
3406
3907
|
},
|
|
3407
|
-
|
|
3908
|
+
// Multi-line fields size themselves (rows/resize), not from the box.
|
|
3909
|
+
'& textarea': {
|
|
3910
|
+
height: 'auto',
|
|
3911
|
+
...this.theme.paddingTop('xs'),
|
|
3912
|
+
...this.theme.paddingBottom('xs'),
|
|
3913
|
+
},
|
|
3914
|
+
'&:has(input:disabled, select:disabled, textarea:disabled)': {
|
|
3408
3915
|
...this.theme.color(this.componentOptions().disabledTextColor),
|
|
3409
3916
|
...this.theme.backgroundColor(this.componentOptions().disabledColor),
|
|
3410
3917
|
},
|
|
3411
|
-
'& input:disabled, select:disabled': {
|
|
3918
|
+
'& input:disabled, select:disabled, textarea:disabled': {
|
|
3412
3919
|
cursor: 'not-allowed !important',
|
|
3413
3920
|
},
|
|
3414
|
-
'&:has(input:focus, select:focus)': {
|
|
3921
|
+
'&:has(input:focus, select:focus, textarea:focus)': {
|
|
3415
3922
|
outline: this.componentOptions().focusOutline,
|
|
3416
3923
|
outlineOffset: this.componentOptions().focusOutlineOffset,
|
|
3417
3924
|
},
|
|
3418
3925
|
},
|
|
3419
3926
|
]), ...(ngDevMode ? [{ debugName: "inputBoxClass" }] : /* istanbul ignore next */ []));
|
|
3420
3927
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniInputBoxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3421
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniInputBoxComponent, isStandalone: true, selector: "uni-input-box", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'input' }], usesInheritance: true, ngImport: i0, template: "<div\n row-layout\n alignItems=\"center\"\n [height]=\"componentOptions().height\"\n [color]=\"color()\"\n [border]=\"border()\"\n [borderRadius]=\"componentOptions().borderRadius\"\n [shadow]=\"shadow()\"\n [minWidth]=\"minWidth()\"\n [class]=\"inputBoxClass()\"\n position=\"relative\"\n>\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "component", type: UniRowComponent, selector: "div[uni-row-layout], Row, div[row-layout]", inputs: ["display", "flexDirection", "minWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3928
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniInputBoxComponent, isStandalone: true, selector: "uni-input-box", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "className" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'input' }], usesInheritance: true, ngImport: i0, template: "<div\n row-layout\n alignItems=\"center\"\n [height]=\"height() ?? componentOptions().height\"\n [color]=\"color()\"\n [border]=\"border()\"\n [borderRadius]=\"componentOptions().borderRadius\"\n [shadow]=\"shadow()\"\n [minWidth]=\"minWidth()\"\n [class]=\"inputBoxClass()\"\n position=\"relative\"\n>\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "component", type: UniRowComponent, selector: "div[uni-row-layout], Row, div[row-layout]", inputs: ["display", "flexDirection", "minWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3422
3929
|
}
|
|
3423
3930
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniInputBoxComponent, decorators: [{
|
|
3424
3931
|
type: Component,
|
|
3425
|
-
args: [{ selector: 'uni-input-box', imports: [UniRowComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'input' }], host: { '[class]': 'className' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n row-layout\n alignItems=\"center\"\n [height]=\"componentOptions().height\"\n [color]=\"color()\"\n [border]=\"border()\"\n [borderRadius]=\"componentOptions().borderRadius\"\n [shadow]=\"shadow()\"\n [minWidth]=\"minWidth()\"\n [class]=\"inputBoxClass()\"\n position=\"relative\"\n>\n <ng-content></ng-content>\n</div>\n" }]
|
|
3426
|
-
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }] } });
|
|
3932
|
+
args: [{ selector: 'uni-input-box', imports: [UniRowComponent], providers: [{ provide: COMPONENT_NAME, useValue: 'input' }], host: { '[class]': 'className' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n row-layout\n alignItems=\"center\"\n [height]=\"height() ?? componentOptions().height\"\n [color]=\"color()\"\n [border]=\"border()\"\n [borderRadius]=\"componentOptions().borderRadius\"\n [shadow]=\"shadow()\"\n [minWidth]=\"minWidth()\"\n [class]=\"inputBoxClass()\"\n position=\"relative\"\n>\n <ng-content></ng-content>\n</div>\n" }]
|
|
3933
|
+
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
|
|
3427
3934
|
|
|
3428
3935
|
class UniInputComponent {
|
|
3429
3936
|
// --- REQUIRED SIGNALS (populated by FormValueControl) ---
|
|
@@ -3452,7 +3959,7 @@ class UniInputComponent {
|
|
|
3452
3959
|
}
|
|
3453
3960
|
inputClass = css({});
|
|
3454
3961
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3455
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniInputComponent, isStandalone: true, selector: "uni-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\">\n <ng-content select=\"pre-input\" />\n <input\n [value]=\"value()\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n (blur)=\"markAsTouched()\"\n [class]=\"inputClass\"\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 />\n <ng-content select=\"post-input\" />\n</uni-input-box>\n", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3962
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniInputComponent, isStandalone: true, selector: "uni-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\">\n <ng-content select=\"pre-input\" />\n <input\n [value]=\"value()\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n (blur)=\"markAsTouched()\"\n [class]=\"inputClass\"\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 />\n <ng-content select=\"post-input\" />\n</uni-input-box>\n", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3456
3963
|
}
|
|
3457
3964
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniInputComponent, decorators: [{
|
|
3458
3965
|
type: Component,
|
|
@@ -3872,7 +4379,7 @@ class UniMultiSelectDropdownComponent extends BaseComponent {
|
|
|
3872
4379
|
});
|
|
3873
4380
|
}
|
|
3874
4381
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniMultiSelectDropdownComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3875
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniMultiSelectDropdownComponent, isStandalone: true, selector: "uni-multi-select-dropdown, MultiSelectDropdown", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "className" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'multiSelectDropdown' }], usesInheritance: true, ngImport: i0, template: "<button\n [class]=\"triggerClass\"\n #trigger\n [style.cursor]=\"disabled() ? 'default' : 'pointer'\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n (click)=\"!disabled() && touched.set(true)\"\n>\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div\n row-layout\n alignItems=\"center\"\n justifyContent=\"space-between\"\n [fullWidth]=\"true\"\n [minWidth]=\"0\"\n paddingLeft=\"sm\"\n >\n <Text\n display=\"block\"\n [typeface]=\"componentOptions().textRole\"\n [color]=\"textColor()\"\n [ellipsis]=\"true\"\n [style.flex-grow]=\"1\"\n >{{ selectedLabelsText() }}</Text\n >\n <Symbol name=\"keyboard_arrow_down\" [style.flex-shrink]=\"0\"></Symbol>\n </div>\n </uni-input-box>\n</button>\n<uni-dropdown\n #dropdown\n [trigger]=\"trigger\"\n ariaHasPopup=\"dialog\"\n (dropdownShowing)=\"$event && searchInput.focus()\"\n (dropdownHiding)=\"$event && trigger.focus()\"\n>\n <div box-layout gap=\"xs\" padding=\"xs\">\n <input\n #searchInput\n type=\"text\"\n [class]=\"searchInputClass()\"\n [value]=\"query()\"\n (input)=\"handleQueryInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Filter options\"\n (click)=\"$event.stopPropagation()\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div stack-layout gap=\"xs\" padding=\"xs\">\n @for (option of filteredOptions(); track option.value) {\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"isOptionSelected(option)()\"\n (checkedChange)=\"toggleOption(option, $event)\"\n variant=\"primary\"\n [disabled]=\"disabled()\"\n >\n </uni-checkbox>\n }\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div row-layout gap=\"xs\" justifyContent=\"space-around\" padding=\"xs\">\n <button text-button (click)=\"dropdown.hideDropdown()\" size=\"sm\" variant=\"ghost\">Done</button>\n </div>\n</uni-dropdown>\n", dependencies: [{ kind: "component", type: UniCheckboxComponent, selector: "uni-checkbox, Checkbox", inputs: ["checked", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "label", "indeterminate"], outputs: ["checkedChange", "touchedChange", "indeterminateChange"] }, { kind: "component", type: UniBoxComponent, selector: "div[uni-box-layout], Box, div[box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }, { kind: "component", type: UniDropdownComponent, selector: "uni-dropdown, Dropdown", inputs: ["trigger", "placement", "offset", "ariaHasPopup", "paddingVertical", "paddingHorizontal"], outputs: ["dropdownShowing", "dropdownHiding"] }, { kind: "component", type: UniStackComponent, selector: "div[uni-stack-layout], Stack, div[stack-layout]", inputs: ["display", "flexDirection", "minHeight"] }, { kind: "component", type: UniDividerComponent, selector: "uni-divider, Divider", inputs: ["orientation", "border"] }, { kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], Button, button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }, { kind: "component", type: UniTextComponent, selector: "uni-text, Text", inputs: ["typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol, Symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }, { kind: "component", type: UniRowComponent, selector: "div[uni-row-layout], Row, div[row-layout]", inputs: ["display", "flexDirection", "minWidth"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4382
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniMultiSelectDropdownComponent, isStandalone: true, selector: "uni-multi-select-dropdown, MultiSelectDropdown", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "className" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'multiSelectDropdown' }], usesInheritance: true, ngImport: i0, template: "<button\n [class]=\"triggerClass\"\n #trigger\n [style.cursor]=\"disabled() ? 'default' : 'pointer'\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n (click)=\"!disabled() && touched.set(true)\"\n>\n <uni-input-box [error]=\"showError()\" [disabled]=\"disabled()\">\n <div\n row-layout\n alignItems=\"center\"\n justifyContent=\"space-between\"\n [fullWidth]=\"true\"\n [minWidth]=\"0\"\n paddingLeft=\"sm\"\n >\n <Text\n display=\"block\"\n [typeface]=\"componentOptions().textRole\"\n [color]=\"textColor()\"\n [ellipsis]=\"true\"\n [style.flex-grow]=\"1\"\n >{{ selectedLabelsText() }}</Text\n >\n <Symbol name=\"keyboard_arrow_down\" [style.flex-shrink]=\"0\"></Symbol>\n </div>\n </uni-input-box>\n</button>\n<uni-dropdown\n #dropdown\n [trigger]=\"trigger\"\n ariaHasPopup=\"dialog\"\n (dropdownShowing)=\"$event && searchInput.focus()\"\n (dropdownHiding)=\"$event && trigger.focus()\"\n>\n <div box-layout gap=\"xs\" padding=\"xs\">\n <input\n #searchInput\n type=\"text\"\n [class]=\"searchInputClass()\"\n [value]=\"query()\"\n (input)=\"handleQueryInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Filter options\"\n (click)=\"$event.stopPropagation()\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div stack-layout gap=\"xs\" padding=\"xs\">\n @for (option of filteredOptions(); track option.value) {\n <uni-checkbox\n [label]=\"option.label\"\n [checked]=\"isOptionSelected(option)()\"\n (checkedChange)=\"toggleOption(option, $event)\"\n variant=\"primary\"\n [disabled]=\"disabled()\"\n >\n </uni-checkbox>\n }\n </div>\n\n <uni-divider [border]=\"componentOptions().dividerBorder\" />\n\n <div row-layout gap=\"xs\" justifyContent=\"space-around\" padding=\"xs\">\n <button text-button (click)=\"dropdown.hideDropdown()\" size=\"sm\" variant=\"ghost\">Done</button>\n </div>\n</uni-dropdown>\n", dependencies: [{ kind: "component", type: UniCheckboxComponent, selector: "uni-checkbox, Checkbox", inputs: ["checked", "disabled", "touched", "invalid", "dirty", "required", "ariaDescribedBy", "label", "indeterminate"], outputs: ["checkedChange", "touchedChange", "indeterminateChange"] }, { kind: "component", type: UniBoxComponent, selector: "div[uni-box-layout], Box, div[box-layout]", inputs: ["color", "backgroundColor", "borderRadius", "borderRadiusLeft", "borderRadiusRight", "borderRadiusTop", "borderRadiusBottom", "padding", "paddingHorizontal", "paddingVertical", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "dashBorder", "alignSelf", "alignItems", "alignContent", "justifyContent", "grow", "display", "position", "inset", "height", "minHeight", "maxHeight", "width", "minWidth", "maxWidth", "ignoreDir", "gridArea", "gridColumn", "gridRow", "overflow", "elevation", "shadow", "gap", "fullWidth", "fullHeight", "flexDirection", "textAlign", "wrapItems", "zIndex"] }, { kind: "component", type: UniDropdownComponent, selector: "uni-dropdown, Dropdown", inputs: ["trigger", "placement", "offset", "ariaHasPopup", "paddingVertical", "paddingHorizontal"], outputs: ["dropdownShowing", "dropdownHiding"] }, { kind: "component", type: UniStackComponent, selector: "div[uni-stack-layout], Stack, div[stack-layout]", inputs: ["display", "flexDirection", "minHeight"] }, { kind: "component", type: UniDividerComponent, selector: "uni-divider, Divider", inputs: ["orientation", "border"] }, { kind: "component", type: UniButtonComponent, selector: "button[uni-text-button], Button, button[text-button]", inputs: ["disable", "loading", "fullWidth", "symbolLeft", "symbolRight"] }, { kind: "component", type: UniTextComponent, selector: "uni-text, Text", inputs: ["typeface", "color", "display", "align", "nowrap", "maxWidth", "ellipsis"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol, Symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }, { kind: "component", type: UniRowComponent, selector: "div[uni-row-layout], Row, div[row-layout]", inputs: ["display", "flexDirection", "minWidth"] }, { kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3876
4383
|
}
|
|
3877
4384
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniMultiSelectDropdownComponent, decorators: [{
|
|
3878
4385
|
type: Component,
|
|
@@ -4723,13 +5230,475 @@ class UniSelectComponent {
|
|
|
4723
5230
|
pointerEvents: 'none' /* Crucial for clicking through */,
|
|
4724
5231
|
});
|
|
4725
5232
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4726
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSelectComponent, isStandalone: true, selector: "uni-select, SelectInput", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <option [value]=\"i\">\n {{ opt.label }}\n </option>\n }\n </select>\n <uni-symbol name=\"keyboard_arrow_down\" [class]=\"arrowClass\" />\n</uni-input-box>\n", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol, Symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5233
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSelectComponent, isStandalone: true, selector: "uni-select, SelectInput", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <option [value]=\"i\">\n {{ opt.label }}\n </option>\n }\n </select>\n <uni-symbol name=\"keyboard_arrow_down\" [class]=\"arrowClass\" />\n</uni-input-box>\n", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }, { kind: "component", type: UniSymbolComponent, selector: "uni-symbol, Symbol", inputs: ["name", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4727
5234
|
}
|
|
4728
5235
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSelectComponent, decorators: [{
|
|
4729
5236
|
type: Component,
|
|
4730
5237
|
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-select, SelectInput', imports: [UniInputBoxComponent, UniSymbolComponent], template: "<uni-input-box [error]=\"showError()\" [class]=\"selectClass\">\n <select\n [disabled]=\"disabled()\"\n [value]=\"currentSelectedIndex()\"\n (change)=\"handleSelectChange($event)\"\n (blur)=\"touched.set(true)\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-invalid]=\"showError() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [attr.aria-describedby]=\"ariaDescribedBy() || null\"\n >\n @if (placeholder()) {\n <option [value]=\"UNSELECTED\" disabled selected>\n {{ placeholder() }}\n </option>\n }\n\n @for (opt of options(); track opt.label; let i = $index) {\n <option [value]=\"i\">\n {{ opt.label }}\n </option>\n }\n </select>\n <uni-symbol name=\"keyboard_arrow_down\" [class]=\"arrowClass\" />\n</uni-input-box>\n" }]
|
|
4731
5238
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
4732
5239
|
|
|
5240
|
+
/**
|
|
5241
|
+
* Loading placeholder painted with surface tokens. `text` renders one or more
|
|
5242
|
+
* lines (the last line shortened, as real text would be), `rect` and `circle`
|
|
5243
|
+
* render fixed shapes. The shimmer only animates when the user allows motion;
|
|
5244
|
+
* it degrades to static blocks under `prefers-reduced-motion`.
|
|
5245
|
+
*/
|
|
5246
|
+
class UniSkeletonComponent extends BaseComponent {
|
|
5247
|
+
shape = input('text', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
5248
|
+
/** CSS width; defaults to 100% for text/rect and `height` for circles. */
|
|
5249
|
+
width = input(undefined, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
|
|
5250
|
+
/** CSS height per block; defaults to 1em (text), 96px (rect), 40px (circle). */
|
|
5251
|
+
height = input(undefined, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
|
|
5252
|
+
/** Number of text lines (text shape only). */
|
|
5253
|
+
lines = input(1, ...(ngDevMode ? [{ debugName: "lines" }] : /* istanbul ignore next */ []));
|
|
5254
|
+
cssSize = (value) => typeof value === 'number' ? `${value}px` : value;
|
|
5255
|
+
resolvedHeight = computed(() => {
|
|
5256
|
+
const height = this.height();
|
|
5257
|
+
if (height !== undefined)
|
|
5258
|
+
return this.cssSize(height);
|
|
5259
|
+
return { text: '1em', rect: '96px', circle: '40px' }[this.shape()];
|
|
5260
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : /* istanbul ignore next */ []));
|
|
5261
|
+
lineWidths = computed(() => {
|
|
5262
|
+
const width = this.width() !== undefined ? this.cssSize(this.width()) : undefined;
|
|
5263
|
+
if (this.shape() === 'circle')
|
|
5264
|
+
return [width ?? this.resolvedHeight()];
|
|
5265
|
+
if (this.shape() === 'rect')
|
|
5266
|
+
return [width ?? '100%'];
|
|
5267
|
+
const lines = Math.max(1, this.lines());
|
|
5268
|
+
// Multi-line text blocks end on a short line, like real paragraphs do.
|
|
5269
|
+
return Array.from({ length: lines }, (_, i) => lines > 1 && i === lines - 1 ? (width ?? '60%') : (width ?? '100%'));
|
|
5270
|
+
}, ...(ngDevMode ? [{ debugName: "lineWidths" }] : /* istanbul ignore next */ []));
|
|
5271
|
+
sweep = keyframes({
|
|
5272
|
+
from: { backgroundPosition: '200% 0' },
|
|
5273
|
+
to: { backgroundPosition: '-200% 0' },
|
|
5274
|
+
});
|
|
5275
|
+
className = computed(() => {
|
|
5276
|
+
const options = this.componentOptions();
|
|
5277
|
+
const base = this.theme.colors()[options.color ?? 'surface-variant'];
|
|
5278
|
+
const highlight = this.theme.colors()[options.highlightColor ?? 'surface'];
|
|
5279
|
+
const animated = (options.animation ?? 'shimmer') === 'shimmer';
|
|
5280
|
+
return css({
|
|
5281
|
+
display: 'flex',
|
|
5282
|
+
flexDirection: 'column',
|
|
5283
|
+
...this.theme.gap(options.gap),
|
|
5284
|
+
'& .uni-skeleton-block': {
|
|
5285
|
+
height: this.resolvedHeight(),
|
|
5286
|
+
backgroundColor: base,
|
|
5287
|
+
...(this.shape() === 'circle'
|
|
5288
|
+
? { borderRadius: '50%', flex: 'none' }
|
|
5289
|
+
: this.theme.radius(options.borderRadius)),
|
|
5290
|
+
...(animated &&
|
|
5291
|
+
motionSafe({
|
|
5292
|
+
backgroundImage: `linear-gradient(90deg, ${base} 40%, ${highlight} 50%, ${base} 60%)`,
|
|
5293
|
+
backgroundSize: '200% 100%',
|
|
5294
|
+
animation: `${this.sweep} ${options.duration ?? 1.4}s ease-in-out infinite`,
|
|
5295
|
+
})),
|
|
5296
|
+
},
|
|
5297
|
+
});
|
|
5298
|
+
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
5299
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSkeletonComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5300
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniSkeletonComponent, isStandalone: true, selector: "uni-skeleton, Skeleton", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, lines: { classPropertyName: "lines", publicName: "lines", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "class": "className()" } }, providers: [{ provide: COMPONENT_NAME, useValue: 'skeleton' }], usesInheritance: true, ngImport: i0, template: `
|
|
5301
|
+
@for (line of lineWidths(); track $index) {
|
|
5302
|
+
<div class="uni-skeleton-block" [style.width]="line"></div>
|
|
5303
|
+
}
|
|
5304
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5305
|
+
}
|
|
5306
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSkeletonComponent, decorators: [{
|
|
5307
|
+
type: Component,
|
|
5308
|
+
args: [{
|
|
5309
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5310
|
+
selector: 'uni-skeleton, Skeleton',
|
|
5311
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'skeleton' }],
|
|
5312
|
+
host: { '[class]': 'className()', 'aria-hidden': 'true' },
|
|
5313
|
+
template: `
|
|
5314
|
+
@for (line of lineWidths(); track $index) {
|
|
5315
|
+
<div class="uni-skeleton-block" [style.width]="line"></div>
|
|
5316
|
+
}
|
|
5317
|
+
`,
|
|
5318
|
+
}]
|
|
5319
|
+
}], propDecorators: { shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }] } });
|
|
5320
|
+
|
|
5321
|
+
/**
|
|
5322
|
+
* Range slider on a native `<input type="range">` — keyboard interaction and
|
|
5323
|
+
* the ARIA slider contract come from the platform. Fill, track, thumb and
|
|
5324
|
+
* radii resolve from `slider` theme tokens; the fill percentage rides a CSS
|
|
5325
|
+
* custom property so dragging never regenerates styles.
|
|
5326
|
+
*/
|
|
5327
|
+
class UniSliderComponent extends BaseComponent {
|
|
5328
|
+
// --- REQUIRED SIGNALS (populated by FormValueControl) ---
|
|
5329
|
+
value = model(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
5330
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
5331
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
5332
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
5333
|
+
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
5334
|
+
/** Synced from required() validators by the Signal Forms [field] directive. */
|
|
5335
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
5336
|
+
/**
|
|
5337
|
+
* Id(s) of external element(s) describing this control — typically your
|
|
5338
|
+
* app-rendered value or error text — exposed as aria-describedby.
|
|
5339
|
+
*/
|
|
5340
|
+
ariaDescribedBy = input(...(ngDevMode ? [undefined, { debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
|
|
5341
|
+
// --- CONFIGURATION ---
|
|
5342
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
5343
|
+
// `min`/`max` are part of the FormValueControl contract (synced from
|
|
5344
|
+
// min()/max() validators), so their type must admit undefined.
|
|
5345
|
+
min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
5346
|
+
max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
5347
|
+
step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
|
|
5348
|
+
resolvedMin = computed(() => this.min() ?? 0, ...(ngDevMode ? [{ debugName: "resolvedMin" }] : /* istanbul ignore next */ []));
|
|
5349
|
+
resolvedMax = computed(() => this.max() ?? 100, ...(ngDevMode ? [{ debugName: "resolvedMax" }] : /* istanbul ignore next */ []));
|
|
5350
|
+
markAsTouched() {
|
|
5351
|
+
this.touched.set(true);
|
|
5352
|
+
}
|
|
5353
|
+
handleInput(event) {
|
|
5354
|
+
this.value.set(Number(event.target.value));
|
|
5355
|
+
}
|
|
5356
|
+
fillPercent = computed(() => {
|
|
5357
|
+
const min = this.resolvedMin();
|
|
5358
|
+
const range = this.resolvedMax() - min;
|
|
5359
|
+
if (range <= 0)
|
|
5360
|
+
return '0%';
|
|
5361
|
+
const ratio = (this.value() - min) / range;
|
|
5362
|
+
return `${Math.min(100, Math.max(0, ratio * 100))}%`;
|
|
5363
|
+
}, ...(ngDevMode ? [{ debugName: "fillPercent" }] : /* istanbul ignore next */ []));
|
|
5364
|
+
inputClass = computed(() => {
|
|
5365
|
+
const options = this.componentOptions();
|
|
5366
|
+
const fill = this.theme.colors()[options.color ?? 'primary'];
|
|
5367
|
+
const track = this.theme.colors()[options.trackColor ?? 'surface-variant'];
|
|
5368
|
+
const radius = this.theme.radii()[options.borderRadius ?? 'max'];
|
|
5369
|
+
const trackHeight = options.trackHeight ?? 4;
|
|
5370
|
+
const thumbSize = options.thumbSize ?? 16;
|
|
5371
|
+
// Webkit paints the fill via a gradient stopped at the custom property;
|
|
5372
|
+
// Firefox has a real ::-moz-range-progress.
|
|
5373
|
+
const trackFill = `linear-gradient(to right, ${fill} var(--uni-slider-fill), ${track} var(--uni-slider-fill))`;
|
|
5374
|
+
const thumb = {
|
|
5375
|
+
appearance: 'none',
|
|
5376
|
+
width: thumbSize,
|
|
5377
|
+
height: thumbSize,
|
|
5378
|
+
borderRadius: radius,
|
|
5379
|
+
border: 'none',
|
|
5380
|
+
background: fill,
|
|
5381
|
+
cursor: 'pointer',
|
|
5382
|
+
};
|
|
5383
|
+
return css({
|
|
5384
|
+
appearance: 'none',
|
|
5385
|
+
width: '100%',
|
|
5386
|
+
height: thumbSize,
|
|
5387
|
+
margin: 0,
|
|
5388
|
+
background: 'transparent',
|
|
5389
|
+
cursor: 'pointer',
|
|
5390
|
+
'&::-webkit-slider-runnable-track': {
|
|
5391
|
+
height: trackHeight,
|
|
5392
|
+
borderRadius: radius,
|
|
5393
|
+
background: trackFill,
|
|
5394
|
+
},
|
|
5395
|
+
'&::-webkit-slider-thumb': {
|
|
5396
|
+
...thumb,
|
|
5397
|
+
marginTop: (trackHeight - thumbSize) / 2,
|
|
5398
|
+
},
|
|
5399
|
+
'&::-moz-range-track': { height: trackHeight, borderRadius: radius, background: track },
|
|
5400
|
+
'&::-moz-range-progress': { height: trackHeight, borderRadius: radius, background: fill },
|
|
5401
|
+
'&::-moz-range-thumb': thumb,
|
|
5402
|
+
'&:focus-visible': { outline: `2px solid ${fill}`, outlineOffset: 2 },
|
|
5403
|
+
'&:disabled': {
|
|
5404
|
+
cursor: 'not-allowed',
|
|
5405
|
+
opacity: 0.5,
|
|
5406
|
+
'&::-webkit-slider-thumb': { cursor: 'not-allowed' },
|
|
5407
|
+
'&::-moz-range-thumb': { cursor: 'not-allowed' },
|
|
5408
|
+
},
|
|
5409
|
+
});
|
|
5410
|
+
}, ...(ngDevMode ? [{ debugName: "inputClass" }] : /* istanbul ignore next */ []));
|
|
5411
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSliderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5412
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniSliderComponent, isStandalone: true, selector: "uni-slider, Slider", 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 } }, outputs: { value: "valueChange", touched: "touchedChange" }, providers: [{ provide: COMPONENT_NAME, useValue: 'slider' }], usesInheritance: true, ngImport: i0, template: `
|
|
5413
|
+
<input
|
|
5414
|
+
type="range"
|
|
5415
|
+
[class]="inputClass()"
|
|
5416
|
+
[style.--uni-slider-fill]="fillPercent()"
|
|
5417
|
+
[min]="resolvedMin()"
|
|
5418
|
+
[max]="resolvedMax()"
|
|
5419
|
+
[step]="step()"
|
|
5420
|
+
[value]="value()"
|
|
5421
|
+
[disabled]="disabled()"
|
|
5422
|
+
(input)="handleInput($event)"
|
|
5423
|
+
(blur)="markAsTouched()"
|
|
5424
|
+
[attr.aria-label]="label()"
|
|
5425
|
+
[attr.aria-describedby]="ariaDescribedBy() || null"
|
|
5426
|
+
/>
|
|
5427
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5428
|
+
}
|
|
5429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniSliderComponent, decorators: [{
|
|
5430
|
+
type: Component,
|
|
5431
|
+
args: [{
|
|
5432
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5433
|
+
selector: 'uni-slider, Slider',
|
|
5434
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'slider' }],
|
|
5435
|
+
template: `
|
|
5436
|
+
<input
|
|
5437
|
+
type="range"
|
|
5438
|
+
[class]="inputClass()"
|
|
5439
|
+
[style.--uni-slider-fill]="fillPercent()"
|
|
5440
|
+
[min]="resolvedMin()"
|
|
5441
|
+
[max]="resolvedMax()"
|
|
5442
|
+
[step]="step()"
|
|
5443
|
+
[value]="value()"
|
|
5444
|
+
[disabled]="disabled()"
|
|
5445
|
+
(input)="handleInput($event)"
|
|
5446
|
+
(blur)="markAsTouched()"
|
|
5447
|
+
[attr.aria-label]="label()"
|
|
5448
|
+
[attr.aria-describedby]="ariaDescribedBy() || null"
|
|
5449
|
+
/>
|
|
5450
|
+
`,
|
|
5451
|
+
}]
|
|
5452
|
+
}], 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 }] }] } });
|
|
5453
|
+
|
|
5454
|
+
/**
|
|
5455
|
+
* One tab inside `uni-tabs`: a label for the tablist plus projected panel
|
|
5456
|
+
* content. Content is captured in a template and only instantiated while the
|
|
5457
|
+
* tab is selected, so inactive panels cost nothing.
|
|
5458
|
+
*/
|
|
5459
|
+
class UniTabComponent {
|
|
5460
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
5461
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
5462
|
+
/** Stable ids wiring tab ↔ panel ARIA relationships. */
|
|
5463
|
+
id = uniqueId('uni-tab');
|
|
5464
|
+
panelId = `${this.id}-panel`;
|
|
5465
|
+
content = viewChild.required('content');
|
|
5466
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5467
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.12", type: UniTabComponent, isStandalone: true, selector: "uni-tab, Tab", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, isSignal: true }], ngImport: i0, template: `<ng-template #content><ng-content /></ng-template>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5468
|
+
}
|
|
5469
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTabComponent, decorators: [{
|
|
5470
|
+
type: Component,
|
|
5471
|
+
args: [{
|
|
5472
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5473
|
+
selector: 'uni-tab, Tab',
|
|
5474
|
+
template: `<ng-template #content><ng-content /></ng-template>`,
|
|
5475
|
+
}]
|
|
5476
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], content: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }] } });
|
|
5477
|
+
|
|
5478
|
+
/**
|
|
5479
|
+
* WAI-ARIA tabs: roving tabindex, automatic activation (arrow keys move focus
|
|
5480
|
+
* and select), Home/End, disabled tabs skipped. Only the selected panel is
|
|
5481
|
+
* instantiated. All styling resolves from `tabs` theme option tokens.
|
|
5482
|
+
*/
|
|
5483
|
+
class UniTabsComponent extends BaseComponent {
|
|
5484
|
+
/** Index of the selected tab; two-way bindable. */
|
|
5485
|
+
selectedIndex = model(0, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : /* istanbul ignore next */ []));
|
|
5486
|
+
tabs = contentChildren(UniTabComponent, ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
5487
|
+
tabButtons = viewChildren('tabButton', ...(ngDevMode ? [{ debugName: "tabButtons" }] : /* istanbul ignore next */ []));
|
|
5488
|
+
/** The selection, snapped to the nearest enabled tab. */
|
|
5489
|
+
activeIndex = computed(() => {
|
|
5490
|
+
const tabs = this.tabs();
|
|
5491
|
+
const wanted = this.selectedIndex();
|
|
5492
|
+
if (tabs[wanted] && !tabs[wanted].disabled())
|
|
5493
|
+
return wanted;
|
|
5494
|
+
const firstEnabled = tabs.findIndex((tab) => !tab.disabled());
|
|
5495
|
+
return firstEnabled === -1 ? 0 : firstEnabled;
|
|
5496
|
+
}, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
5497
|
+
activeTab = computed(() => this.tabs()[this.activeIndex()], ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
5498
|
+
select(index) {
|
|
5499
|
+
if (this.tabs()[index]?.disabled())
|
|
5500
|
+
return;
|
|
5501
|
+
this.selectedIndex.set(index);
|
|
5502
|
+
}
|
|
5503
|
+
onKeydown(event) {
|
|
5504
|
+
const enabled = this.tabs()
|
|
5505
|
+
.map((tab, index) => ({ tab, index }))
|
|
5506
|
+
.filter(({ tab }) => !tab.disabled())
|
|
5507
|
+
.map(({ index }) => index);
|
|
5508
|
+
if (enabled.length === 0)
|
|
5509
|
+
return;
|
|
5510
|
+
const position = enabled.indexOf(this.activeIndex());
|
|
5511
|
+
let next;
|
|
5512
|
+
switch (event.key) {
|
|
5513
|
+
case 'ArrowRight':
|
|
5514
|
+
next = enabled[(position + 1) % enabled.length];
|
|
5515
|
+
break;
|
|
5516
|
+
case 'ArrowLeft':
|
|
5517
|
+
next = enabled[(position - 1 + enabled.length) % enabled.length];
|
|
5518
|
+
break;
|
|
5519
|
+
case 'Home':
|
|
5520
|
+
next = enabled[0];
|
|
5521
|
+
break;
|
|
5522
|
+
case 'End':
|
|
5523
|
+
next = enabled[enabled.length - 1];
|
|
5524
|
+
break;
|
|
5525
|
+
default:
|
|
5526
|
+
return;
|
|
5527
|
+
}
|
|
5528
|
+
event.preventDefault();
|
|
5529
|
+
this.select(next);
|
|
5530
|
+
this.tabButtons()[next]?.nativeElement.focus();
|
|
5531
|
+
}
|
|
5532
|
+
tablistClass = computed(() => {
|
|
5533
|
+
const options = this.componentOptions();
|
|
5534
|
+
return css({
|
|
5535
|
+
display: 'flex',
|
|
5536
|
+
alignItems: 'stretch',
|
|
5537
|
+
...this.theme.gap(options.gap),
|
|
5538
|
+
...this.theme.borderBottom(options.divider),
|
|
5539
|
+
});
|
|
5540
|
+
}, ...(ngDevMode ? [{ debugName: "tablistClass" }] : /* istanbul ignore next */ []));
|
|
5541
|
+
tabClass = computed(() => {
|
|
5542
|
+
const options = this.componentOptions();
|
|
5543
|
+
const thickness = options.indicatorThickness
|
|
5544
|
+
? this.theme.getThickness(options.indicatorThickness)
|
|
5545
|
+
: 2;
|
|
5546
|
+
return css({
|
|
5547
|
+
border: 0,
|
|
5548
|
+
background: 'transparent',
|
|
5549
|
+
cursor: 'pointer',
|
|
5550
|
+
// The indicator overlays the divider: reserve its thickness on every
|
|
5551
|
+
// tab so labels don't shift when selection moves.
|
|
5552
|
+
borderBottom: `${thickness}px solid transparent`,
|
|
5553
|
+
marginBottom: -1,
|
|
5554
|
+
...this.theme.typeface(options.typeface),
|
|
5555
|
+
...this.theme.color(options.textColor),
|
|
5556
|
+
...this.theme.paddingLeft(options.padding),
|
|
5557
|
+
...this.theme.paddingRight(options.padding),
|
|
5558
|
+
...this.theme.paddingTop('sm'),
|
|
5559
|
+
...this.theme.paddingBottom('sm'),
|
|
5560
|
+
...this.theme.radius(options.borderRadius),
|
|
5561
|
+
...motionSafe({ transition: 'color 0.15s ease, border-color 0.15s ease' }),
|
|
5562
|
+
'&.active': {
|
|
5563
|
+
...this.theme.color(options.activeTextColor),
|
|
5564
|
+
...this.theme.backgroundColor(options.activeColor),
|
|
5565
|
+
borderBottomColor: this.theme.colors()[options.indicatorColor ?? 'primary'],
|
|
5566
|
+
},
|
|
5567
|
+
'&:disabled': {
|
|
5568
|
+
...this.theme.color('on-disabled'),
|
|
5569
|
+
cursor: 'not-allowed',
|
|
5570
|
+
},
|
|
5571
|
+
'&:focus-visible': {
|
|
5572
|
+
outline: `2px solid ${this.theme.colors()[options.indicatorColor ?? 'primary']}`,
|
|
5573
|
+
outlineOffset: -2,
|
|
5574
|
+
},
|
|
5575
|
+
});
|
|
5576
|
+
}, ...(ngDevMode ? [{ debugName: "tabClass" }] : /* istanbul ignore next */ []));
|
|
5577
|
+
panelClass = computed(() => css({
|
|
5578
|
+
...this.theme.paddingTop('md'),
|
|
5579
|
+
'&:focus-visible': {
|
|
5580
|
+
outline: `2px solid ${this.theme.colors()[this.componentOptions().indicatorColor ?? 'primary']}`,
|
|
5581
|
+
outlineOffset: 2,
|
|
5582
|
+
},
|
|
5583
|
+
}), ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
|
|
5584
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTabsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
5585
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniTabsComponent, isStandalone: true, selector: "uni-tabs, Tabs", inputs: { selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange" }, providers: [{ provide: COMPONENT_NAME, useValue: 'tabs' }], queries: [{ propertyName: "tabs", predicate: UniTabComponent, isSignal: true }], viewQueries: [{ propertyName: "tabButtons", predicate: ["tabButton"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
5586
|
+
<div role="tablist" [class]="tablistClass()" (keydown)="onKeydown($event)">
|
|
5587
|
+
@for (tab of tabs(); track tab.id; let i = $index) {
|
|
5588
|
+
<button
|
|
5589
|
+
#tabButton
|
|
5590
|
+
type="button"
|
|
5591
|
+
role="tab"
|
|
5592
|
+
[id]="tab.id"
|
|
5593
|
+
[class]="tabClass()"
|
|
5594
|
+
[attr.aria-selected]="i === activeIndex()"
|
|
5595
|
+
[attr.aria-controls]="tab.panelId"
|
|
5596
|
+
[attr.tabindex]="i === activeIndex() ? 0 : -1"
|
|
5597
|
+
[disabled]="tab.disabled()"
|
|
5598
|
+
[class.active]="i === activeIndex()"
|
|
5599
|
+
(click)="select(i)"
|
|
5600
|
+
>
|
|
5601
|
+
{{ tab.label() }}
|
|
5602
|
+
</button>
|
|
5603
|
+
}
|
|
5604
|
+
</div>
|
|
5605
|
+
@if (activeTab(); as tab) {
|
|
5606
|
+
<div
|
|
5607
|
+
role="tabpanel"
|
|
5608
|
+
[id]="tab.panelId"
|
|
5609
|
+
[attr.aria-labelledby]="tab.id"
|
|
5610
|
+
tabindex="0"
|
|
5611
|
+
[class]="panelClass()"
|
|
5612
|
+
>
|
|
5613
|
+
<ng-container [ngTemplateOutlet]="tab.content()" />
|
|
5614
|
+
</div>
|
|
5615
|
+
}
|
|
5616
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5617
|
+
}
|
|
5618
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTabsComponent, decorators: [{
|
|
5619
|
+
type: Component,
|
|
5620
|
+
args: [{
|
|
5621
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5622
|
+
selector: 'uni-tabs, Tabs',
|
|
5623
|
+
imports: [NgTemplateOutlet],
|
|
5624
|
+
providers: [{ provide: COMPONENT_NAME, useValue: 'tabs' }],
|
|
5625
|
+
template: `
|
|
5626
|
+
<div role="tablist" [class]="tablistClass()" (keydown)="onKeydown($event)">
|
|
5627
|
+
@for (tab of tabs(); track tab.id; let i = $index) {
|
|
5628
|
+
<button
|
|
5629
|
+
#tabButton
|
|
5630
|
+
type="button"
|
|
5631
|
+
role="tab"
|
|
5632
|
+
[id]="tab.id"
|
|
5633
|
+
[class]="tabClass()"
|
|
5634
|
+
[attr.aria-selected]="i === activeIndex()"
|
|
5635
|
+
[attr.aria-controls]="tab.panelId"
|
|
5636
|
+
[attr.tabindex]="i === activeIndex() ? 0 : -1"
|
|
5637
|
+
[disabled]="tab.disabled()"
|
|
5638
|
+
[class.active]="i === activeIndex()"
|
|
5639
|
+
(click)="select(i)"
|
|
5640
|
+
>
|
|
5641
|
+
{{ tab.label() }}
|
|
5642
|
+
</button>
|
|
5643
|
+
}
|
|
5644
|
+
</div>
|
|
5645
|
+
@if (activeTab(); as tab) {
|
|
5646
|
+
<div
|
|
5647
|
+
role="tabpanel"
|
|
5648
|
+
[id]="tab.panelId"
|
|
5649
|
+
[attr.aria-labelledby]="tab.id"
|
|
5650
|
+
tabindex="0"
|
|
5651
|
+
[class]="panelClass()"
|
|
5652
|
+
>
|
|
5653
|
+
<ng-container [ngTemplateOutlet]="tab.content()" />
|
|
5654
|
+
</div>
|
|
5655
|
+
}
|
|
5656
|
+
`,
|
|
5657
|
+
}]
|
|
5658
|
+
}], propDecorators: { selectedIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIndex", required: false }] }, { type: i0.Output, args: ["selectedIndexChange"] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => UniTabComponent), { isSignal: true }] }], tabButtons: [{ type: i0.ViewChildren, args: ['tabButton', { isSignal: true }] }] } });
|
|
5659
|
+
|
|
5660
|
+
class UniTextareaComponent {
|
|
5661
|
+
theme = inject(ThemeService);
|
|
5662
|
+
// --- REQUIRED SIGNALS (populated by FormValueControl) ---
|
|
5663
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
5664
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
5665
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
5666
|
+
invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
5667
|
+
dirty = input(false, ...(ngDevMode ? [{ debugName: "dirty" }] : /* istanbul ignore next */ []));
|
|
5668
|
+
/** Synced from required() validators by the Signal Forms [field] directive. */
|
|
5669
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
5670
|
+
/**
|
|
5671
|
+
* Id(s) of external element(s) describing this control — typically your
|
|
5672
|
+
* app-rendered error message — exposed as aria-describedby.
|
|
5673
|
+
*/
|
|
5674
|
+
ariaDescribedBy = input(...(ngDevMode ? [undefined, { debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
|
|
5675
|
+
// --- CONFIGURATION ---
|
|
5676
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
5677
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
5678
|
+
/** Visible text rows. Defaults to the theme's `textarea` options. */
|
|
5679
|
+
rows = input(undefined, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
5680
|
+
options = this.theme.getComponentOptions('textarea');
|
|
5681
|
+
resolvedRows = computed(() => this.rows() ?? this.options().rows ?? 3, ...(ngDevMode ? [{ debugName: "resolvedRows" }] : /* istanbul ignore next */ []));
|
|
5682
|
+
// Only show errors if the user has actually interacted with the field
|
|
5683
|
+
showError = computed(() => this.invalid() && (this.touched() || this.dirty()), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
|
|
5684
|
+
textareaClass = computed(() => css({
|
|
5685
|
+
width: '100%',
|
|
5686
|
+
resize: this.options().resize ?? 'vertical',
|
|
5687
|
+
}), ...(ngDevMode ? [{ debugName: "textareaClass" }] : /* istanbul ignore next */ []));
|
|
5688
|
+
markAsTouched() {
|
|
5689
|
+
this.touched.set(true);
|
|
5690
|
+
}
|
|
5691
|
+
handleInput(event) {
|
|
5692
|
+
this.value.set(event.target.value);
|
|
5693
|
+
}
|
|
5694
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5695
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: UniTextareaComponent, isStandalone: true, selector: "uni-textarea", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: "<uni-input-box [error]=\"showError()\" height=\"auto\">\n <textarea\n [value]=\"value()\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n (blur)=\"markAsTouched()\"\n [rows]=\"resolvedRows()\"\n [class]=\"textareaClass()\"\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", dependencies: [{ kind: "component", type: UniInputBoxComponent, selector: "uni-input-box", inputs: ["disabled", "error", "minWidth", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5696
|
+
}
|
|
5697
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniTextareaComponent, decorators: [{
|
|
5698
|
+
type: Component,
|
|
5699
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'uni-textarea', imports: [UniInputBoxComponent], template: "<uni-input-box [error]=\"showError()\" height=\"auto\">\n <textarea\n [value]=\"value()\"\n (input)=\"handleInput($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n (blur)=\"markAsTouched()\"\n [rows]=\"resolvedRows()\"\n [class]=\"textareaClass()\"\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" }]
|
|
5700
|
+
}], 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 }] }] } });
|
|
5701
|
+
|
|
4733
5702
|
/**
|
|
4734
5703
|
* UniSortHeaderComponent Barrel File
|
|
4735
5704
|
*
|
|
@@ -4769,13 +5738,14 @@ const SCHEMES = [
|
|
|
4769
5738
|
'triadic',
|
|
4770
5739
|
];
|
|
4771
5740
|
const CATEGORIES = ['jewel', 'pastel', 'earth', 'neutral', 'florescent', 'shades'];
|
|
5741
|
+
const SHAPES = ['sharp', 'modern', 'playful'];
|
|
4772
5742
|
const VARIANTS = ['primary', 'secondary', 'tertiary', 'warn', 'ghost'];
|
|
4773
|
-
// Representative tokens
|
|
5743
|
+
// Representative tokens shown as swatches in each mode panel.
|
|
4774
5744
|
const SWATCHES = [
|
|
4775
5745
|
{ label: 'primary', token: 'primary', on: 'on-primary' },
|
|
4776
5746
|
{ label: 'secondary', token: 'secondary', on: 'on-secondary' },
|
|
4777
5747
|
{ label: 'tertiary', token: 'tertiary', on: 'on-tertiary' },
|
|
4778
|
-
{ label: '
|
|
5748
|
+
{ label: 'container', token: 'primary-container', on: 'on-primary-container' },
|
|
4779
5749
|
{ label: 'error', token: 'error', on: 'on-error' },
|
|
4780
5750
|
{ label: 'warn', token: 'warn', on: 'on-warn' },
|
|
4781
5751
|
{ label: 'success', token: 'success', on: 'on-success' },
|
|
@@ -4842,6 +5812,7 @@ class UniThemeBuilderComponent {
|
|
|
4842
5812
|
theme = inject(ThemeService);
|
|
4843
5813
|
schemes = SCHEMES;
|
|
4844
5814
|
categories = CATEGORIES;
|
|
5815
|
+
shapes = SHAPES;
|
|
4845
5816
|
variants = VARIANTS;
|
|
4846
5817
|
sizes = ['sm', 'md', 'lg', 'xl'];
|
|
4847
5818
|
swatches = SWATCHES;
|
|
@@ -4849,6 +5820,7 @@ class UniThemeBuilderComponent {
|
|
|
4849
5820
|
seed = signal('#4F46E5', ...(ngDevMode ? [{ debugName: "seed" }] : /* istanbul ignore next */ []));
|
|
4850
5821
|
scheme = signal('triadic', ...(ngDevMode ? [{ debugName: "scheme" }] : /* istanbul ignore next */ []));
|
|
4851
5822
|
category = signal('neutral', ...(ngDevMode ? [{ debugName: "category" }] : /* istanbul ignore next */ []));
|
|
5823
|
+
shape = signal('modern', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
4852
5824
|
floor = signal(18, ...(ngDevMode ? [{ debugName: "floor" }] : /* istanbul ignore next */ []));
|
|
4853
5825
|
mode = signal('light', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
4854
5826
|
pinPrimary = signal(false, ...(ngDevMode ? [{ debugName: "pinPrimary" }] : /* istanbul ignore next */ []));
|
|
@@ -4857,6 +5829,8 @@ class UniThemeBuilderComponent {
|
|
|
4857
5829
|
secondaryHex = signal('#D4A373', ...(ngDevMode ? [{ debugName: "secondaryHex" }] : /* istanbul ignore next */ []));
|
|
4858
5830
|
/** Soft brand targets carried by the active preset (cleared on seed edits). */
|
|
4859
5831
|
targets = signal(undefined, ...(ngDevMode ? [{ debugName: "targets" }] : /* istanbul ignore next */ []));
|
|
5832
|
+
copied = signal(null, ...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
|
|
5833
|
+
showAllPairs = signal(false, ...(ngDevMode ? [{ debugName: "showAllPairs" }] : /* istanbul ignore next */ []));
|
|
4860
5834
|
constructor() {
|
|
4861
5835
|
// Seed the controls from an already-active custom palette, if any.
|
|
4862
5836
|
const existing = this.theme.customPalette();
|
|
@@ -4883,19 +5857,88 @@ class UniThemeBuilderComponent {
|
|
|
4883
5857
|
category: this.category(),
|
|
4884
5858
|
mode: this.mode(),
|
|
4885
5859
|
accentSaturationFloor: this.floor(),
|
|
5860
|
+
radii: ShapeRadii[this.shape()],
|
|
4886
5861
|
...(this.targets() ? { targets: this.targets() } : {}),
|
|
4887
5862
|
brand: {
|
|
4888
5863
|
...(this.pinPrimary() ? { primary: this.primaryHex() } : {}),
|
|
4889
5864
|
...(this.pinSecondary() ? { secondary: this.secondaryHex() } : {}),
|
|
4890
5865
|
},
|
|
4891
5866
|
}), ...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
4892
|
-
|
|
5867
|
+
/**
|
|
5868
|
+
* Both modes generated on every input change (< 15 ms each), independent of
|
|
5869
|
+
* the storybook-wide theme — the side-by-side preview and the contrast
|
|
5870
|
+
* report always show the full light+dark picture.
|
|
5871
|
+
*/
|
|
5872
|
+
palettes = computed(() => {
|
|
5873
|
+
const base = { ...this.config() };
|
|
5874
|
+
const checks = [];
|
|
5875
|
+
const light = generatePalette({ ...base, mode: 'light', checks });
|
|
5876
|
+
const dark = generatePalette({ ...base, mode: 'dark', checks });
|
|
5877
|
+
return { light, dark, checks };
|
|
5878
|
+
}, ...(ngDevMode ? [{ debugName: "palettes" }] : /* istanbul ignore next */ []));
|
|
5879
|
+
modePanels = computed(() => [
|
|
5880
|
+
{ label: 'light', colors: this.palettes().light },
|
|
5881
|
+
{ label: 'dark', colors: this.palettes().dark },
|
|
5882
|
+
], ...(ngDevMode ? [{ debugName: "modePanels" }] : /* istanbul ignore next */ []));
|
|
5883
|
+
report = computed(() => {
|
|
5884
|
+
const { checks } = this.palettes();
|
|
5885
|
+
return {
|
|
5886
|
+
checks,
|
|
5887
|
+
failing: checks.filter((c) => !c.pass),
|
|
5888
|
+
worst: checks.reduce((worst, c) => Math.min(worst, c.ratio), 21),
|
|
5889
|
+
};
|
|
5890
|
+
}, ...(ngDevMode ? [{ debugName: "report" }] : /* istanbul ignore next */ []));
|
|
5891
|
+
visibleChecks = computed(() => this.showAllPairs() ? this.report().checks : this.report().failing, ...(ngDevMode ? [{ debugName: "visibleChecks" }] : /* istanbul ignore next */ []));
|
|
5892
|
+
snippet = computed(() => {
|
|
5893
|
+
const { radii: _radii, ...rest } = this.config();
|
|
5894
|
+
return JSON.stringify(rest);
|
|
5895
|
+
}, ...(ngDevMode ? [{ debugName: "snippet" }] : /* istanbul ignore next */ []));
|
|
5896
|
+
/** The builder state expressed as engine input — drives all three exports. */
|
|
5897
|
+
generationInput = computed(() => {
|
|
5898
|
+
const targets = this.targets();
|
|
5899
|
+
const seeds = [this.pinPrimary() ? this.primaryHex() : (targets?.primary ?? this.seed())];
|
|
5900
|
+
const secondary = this.pinSecondary() ? this.secondaryHex() : targets?.secondary;
|
|
5901
|
+
if (secondary)
|
|
5902
|
+
seeds.push(secondary);
|
|
5903
|
+
if (targets?.tertiary)
|
|
5904
|
+
seeds.push(targets.tertiary);
|
|
5905
|
+
return {
|
|
5906
|
+
seed: seeds.length === 1 ? seeds[0] : seeds,
|
|
5907
|
+
scheme: this.scheme(),
|
|
5908
|
+
vibe: this.category(),
|
|
5909
|
+
shape: this.shape(),
|
|
5910
|
+
name: 'Brand',
|
|
5911
|
+
};
|
|
5912
|
+
}, ...(ngDevMode ? [{ debugName: "generationInput" }] : /* istanbul ignore next */ []));
|
|
4893
5913
|
color(token) {
|
|
4894
5914
|
return this.theme.colors()[token] ?? 'transparent';
|
|
4895
5915
|
}
|
|
4896
5916
|
apply() {
|
|
4897
5917
|
this.theme.applyPalette(this.config());
|
|
4898
5918
|
}
|
|
5919
|
+
copyToClipboard(kind, text) {
|
|
5920
|
+
void navigator.clipboard?.writeText(text).then(() => {
|
|
5921
|
+
this.copied.set(kind);
|
|
5922
|
+
setTimeout(() => this.copied.set(null), 1600);
|
|
5923
|
+
});
|
|
5924
|
+
}
|
|
5925
|
+
copyThemeFile() {
|
|
5926
|
+
this.copyToClipboard('file', emitThemeFile(this.generationInput()).content);
|
|
5927
|
+
}
|
|
5928
|
+
copyNgAdd() {
|
|
5929
|
+
const input = this.generationInput();
|
|
5930
|
+
const seeds = Array.isArray(input.seed) ? input.seed.join(',') : input.seed;
|
|
5931
|
+
this.copyToClipboard('ngadd', `ng add @uni-design-system/uni-angular --brand=${seeds} --shape=${input.shape}`);
|
|
5932
|
+
}
|
|
5933
|
+
copyDtcg() {
|
|
5934
|
+
const { light, dark } = this.palettes();
|
|
5935
|
+
const radii = ShapeRadii[this.shape()];
|
|
5936
|
+
const spacing = this.theme.spacing();
|
|
5937
|
+
this.copyToClipboard('dtcg', JSON.stringify({
|
|
5938
|
+
light: emitDtcgTokens({ colors: light, radii, spacing }),
|
|
5939
|
+
dark: emitDtcgTokens({ colors: dark, radii, spacing }),
|
|
5940
|
+
}, null, 2));
|
|
5941
|
+
}
|
|
4899
5942
|
setSeed(v) {
|
|
4900
5943
|
if (/^#?[0-9a-fA-F]{6}$/.test(v.replace('#', ''))) {
|
|
4901
5944
|
this.seed.set(v.startsWith('#') ? v : `#${v}`);
|
|
@@ -4912,6 +5955,10 @@ class UniThemeBuilderComponent {
|
|
|
4912
5955
|
this.category.set(v);
|
|
4913
5956
|
this.apply();
|
|
4914
5957
|
}
|
|
5958
|
+
setShape(v) {
|
|
5959
|
+
this.shape.set(v);
|
|
5960
|
+
this.apply();
|
|
5961
|
+
}
|
|
4915
5962
|
setFloor(v) {
|
|
4916
5963
|
this.floor.set(Number(v));
|
|
4917
5964
|
this.apply();
|
|
@@ -4957,6 +6004,7 @@ class UniThemeBuilderComponent {
|
|
|
4957
6004
|
this.seed.set('#4F46E5');
|
|
4958
6005
|
this.scheme.set('triadic');
|
|
4959
6006
|
this.category.set('neutral');
|
|
6007
|
+
this.shape.set('modern');
|
|
4960
6008
|
this.floor.set(18);
|
|
4961
6009
|
this.mode.set('light');
|
|
4962
6010
|
this.targets.set(undefined);
|
|
@@ -5055,6 +6103,16 @@ class UniThemeBuilderComponent {
|
|
|
5055
6103
|
color: this.c('on-primary'),
|
|
5056
6104
|
borderColor: this.c('primary'),
|
|
5057
6105
|
},
|
|
6106
|
+
'& .tb-exports': { display: 'flex', flexDirection: 'column', gap: 6 },
|
|
6107
|
+
'& .tb-exports button': {
|
|
6108
|
+
height: 32,
|
|
6109
|
+
borderRadius: 8,
|
|
6110
|
+
cursor: 'pointer',
|
|
6111
|
+
fontSize: 12.5,
|
|
6112
|
+
border: `1px solid ${this.c('primary')}`,
|
|
6113
|
+
background: this.c('primary-surface'),
|
|
6114
|
+
color: this.c('on-primary-surface'),
|
|
6115
|
+
},
|
|
5058
6116
|
'& .tb-pin.dim input[type=color], & .tb-pin.dim input[type=text]': { opacity: 0.45 },
|
|
5059
6117
|
'& .tb-pin em': {
|
|
5060
6118
|
fontStyle: 'normal',
|
|
@@ -5087,34 +6145,86 @@ class UniThemeBuilderComponent {
|
|
|
5087
6145
|
display: 'flex',
|
|
5088
6146
|
flexDirection: 'column',
|
|
5089
6147
|
gap: 10,
|
|
5090
|
-
'& .tb-
|
|
6148
|
+
'& .tb-modes': {
|
|
5091
6149
|
display: 'grid',
|
|
5092
|
-
gridTemplateColumns: 'repeat(auto-
|
|
5093
|
-
gap:
|
|
6150
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
|
6151
|
+
gap: 14,
|
|
5094
6152
|
marginBottom: 20,
|
|
5095
6153
|
},
|
|
6154
|
+
'& .tb-panel': {
|
|
6155
|
+
border: '1px solid',
|
|
6156
|
+
borderRadius: 14,
|
|
6157
|
+
padding: 14,
|
|
6158
|
+
display: 'flex',
|
|
6159
|
+
flexDirection: 'column',
|
|
6160
|
+
gap: 12,
|
|
6161
|
+
},
|
|
6162
|
+
'& .tb-panel-tag': {
|
|
6163
|
+
fontSize: 10.5,
|
|
6164
|
+
letterSpacing: '0.12em',
|
|
6165
|
+
textTransform: 'uppercase',
|
|
6166
|
+
},
|
|
6167
|
+
'& .tb-mode-swatches': {
|
|
6168
|
+
display: 'grid',
|
|
6169
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(110px, 1fr))',
|
|
6170
|
+
gap: 8,
|
|
6171
|
+
},
|
|
5096
6172
|
'& .tb-swatch': {
|
|
5097
|
-
borderRadius:
|
|
5098
|
-
padding: '
|
|
5099
|
-
minHeight:
|
|
6173
|
+
borderRadius: 10,
|
|
6174
|
+
padding: '12px 12px',
|
|
6175
|
+
minHeight: 60,
|
|
5100
6176
|
display: 'flex',
|
|
5101
6177
|
flexDirection: 'column',
|
|
5102
6178
|
justifyContent: 'space-between',
|
|
5103
6179
|
},
|
|
5104
|
-
'& .tb-swatch span': { fontSize:
|
|
5105
|
-
'& .tb-swatch code': { fontFamily: 'monospace', fontSize:
|
|
6180
|
+
'& .tb-swatch span': { fontSize: 12.5, fontWeight: 600 },
|
|
6181
|
+
'& .tb-swatch code': { fontFamily: 'monospace', fontSize: 10.5, opacity: 0.85 },
|
|
6182
|
+
'& .tb-mini-card': { borderRadius: 10, overflow: 'hidden', border: '1px solid' },
|
|
6183
|
+
'& .tb-mini-head': { padding: '8px 14px', fontWeight: 600, fontSize: 13 },
|
|
6184
|
+
'& .tb-mini-body': { padding: '10px 14px', fontSize: 12.5, lineHeight: 1.5 },
|
|
5106
6185
|
'& .tb-buttons': { display: 'flex', flexWrap: 'wrap', gap: 12, alignItems: 'center', marginBottom: 14 },
|
|
5107
|
-
'& .tb-
|
|
5108
|
-
'& .tb-
|
|
5109
|
-
'& .tb-
|
|
5110
|
-
|
|
6186
|
+
'& .tb-pass': { color: this.c('success'), fontWeight: 700 },
|
|
6187
|
+
'& .tb-fail': { color: this.c('error'), fontWeight: 700 },
|
|
6188
|
+
'& .tb-link': {
|
|
6189
|
+
marginLeft: 10,
|
|
6190
|
+
background: 'none',
|
|
6191
|
+
border: 'none',
|
|
6192
|
+
cursor: 'pointer',
|
|
6193
|
+
color: this.c('primary'),
|
|
6194
|
+
fontSize: 11,
|
|
6195
|
+
textTransform: 'none',
|
|
6196
|
+
letterSpacing: 'normal',
|
|
6197
|
+
textDecoration: 'underline',
|
|
6198
|
+
},
|
|
6199
|
+
'& .tb-matrix': {
|
|
6200
|
+
maxHeight: 320,
|
|
6201
|
+
overflow: 'auto',
|
|
6202
|
+
border: `1px solid ${this.c('outline')}`,
|
|
6203
|
+
borderRadius: 10,
|
|
6204
|
+
marginBottom: 12,
|
|
6205
|
+
'& table': { width: '100%', borderCollapse: 'collapse', fontSize: 12 },
|
|
6206
|
+
'& th': {
|
|
6207
|
+
position: 'sticky',
|
|
6208
|
+
top: 0,
|
|
6209
|
+
textAlign: 'left',
|
|
6210
|
+
padding: '8px 10px',
|
|
6211
|
+
background: this.c('surface-variant'),
|
|
6212
|
+
color: this.c('on-surface-variant'),
|
|
6213
|
+
fontSize: 10.5,
|
|
6214
|
+
textTransform: 'uppercase',
|
|
6215
|
+
letterSpacing: '0.08em',
|
|
6216
|
+
},
|
|
6217
|
+
'& td': { padding: '6px 10px', borderTop: `1px solid ${this.c('outline')}` },
|
|
6218
|
+
'& td code': { fontFamily: 'monospace', fontSize: 11.5 },
|
|
6219
|
+
'& tr.bad td': { background: this.c('error-container'), color: this.c('on-error-container') },
|
|
6220
|
+
},
|
|
5111
6221
|
'& .tb-hint': { fontSize: 12.5, opacity: 0.6, marginTop: 8 },
|
|
5112
6222
|
}), ...(ngDevMode ? [{ debugName: "preview" }] : /* istanbul ignore next */ []));
|
|
5113
6223
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniThemeBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5114
6224
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniThemeBuilderComponent, isStandalone: true, selector: "uni-theme-builder", host: { properties: { "class": "shell()" } }, ngImport: i0, template: `
|
|
5115
6225
|
<aside [class]="controls()">
|
|
5116
6226
|
<header class="tb-head">
|
|
5117
|
-
<span class="tb-eyebrow">Theme builder ·
|
|
6227
|
+
<span class="tb-eyebrow">Theme builder · Playground</span>
|
|
5118
6228
|
<h2 class="tb-title">Make Uni your brand</h2>
|
|
5119
6229
|
<p class="tb-lede">
|
|
5120
6230
|
Every token is derived in OKLCH from a seed color, a scheme and a category — or bring
|
|
@@ -5161,13 +6271,22 @@ class UniThemeBuilderComponent {
|
|
|
5161
6271
|
</select>
|
|
5162
6272
|
</label>
|
|
5163
6273
|
|
|
6274
|
+
<label class="tb-field">
|
|
6275
|
+
<span>Shape</span>
|
|
6276
|
+
<select (change)="setShape($any($event.target).value)">
|
|
6277
|
+
@for (s of shapes; track s) {
|
|
6278
|
+
<option [value]="s" [selected]="s === shape()">{{ s }}</option>
|
|
6279
|
+
}
|
|
6280
|
+
</select>
|
|
6281
|
+
</label>
|
|
6282
|
+
|
|
5164
6283
|
<label class="tb-field">
|
|
5165
6284
|
<span>Accent saturation floor · {{ floor() }}</span>
|
|
5166
6285
|
<input type="range" min="0" max="45" [value]="floor()" (input)="setFloor($any($event.target).value)" />
|
|
5167
6286
|
</label>
|
|
5168
6287
|
|
|
5169
6288
|
<div class="tb-field">
|
|
5170
|
-
<span>
|
|
6289
|
+
<span>Storybook mode</span>
|
|
5171
6290
|
<div class="tb-toggle">
|
|
5172
6291
|
<button type="button" [class.on]="mode() === 'light'" (click)="setMode('light')">Light</button>
|
|
5173
6292
|
<button type="button" [class.on]="mode() === 'dark'" (click)="setMode('dark')">Dark</button>
|
|
@@ -5196,6 +6315,21 @@ class UniThemeBuilderComponent {
|
|
|
5196
6315
|
</div>
|
|
5197
6316
|
</label>
|
|
5198
6317
|
|
|
6318
|
+
<div class="tb-field">
|
|
6319
|
+
<span>Export</span>
|
|
6320
|
+
<div class="tb-exports">
|
|
6321
|
+
<button type="button" (click)="copyThemeFile()">
|
|
6322
|
+
{{ copied() === 'file' ? 'Copied ✓' : 'Copy uni-theme.ts' }}
|
|
6323
|
+
</button>
|
|
6324
|
+
<button type="button" (click)="copyNgAdd()">
|
|
6325
|
+
{{ copied() === 'ngadd' ? 'Copied ✓' : 'Copy ng add command' }}
|
|
6326
|
+
</button>
|
|
6327
|
+
<button type="button" (click)="copyDtcg()">
|
|
6328
|
+
{{ copied() === 'dtcg' ? 'Copied ✓' : 'Copy DTCG JSON' }}
|
|
6329
|
+
</button>
|
|
6330
|
+
</div>
|
|
6331
|
+
</div>
|
|
6332
|
+
|
|
5199
6333
|
<div class="tb-actions">
|
|
5200
6334
|
<button type="button" class="tb-reset" (click)="reset()">Reset to default</button>
|
|
5201
6335
|
</div>
|
|
@@ -5203,17 +6337,35 @@ class UniThemeBuilderComponent {
|
|
|
5203
6337
|
</aside>
|
|
5204
6338
|
|
|
5205
6339
|
<section [class]="preview()">
|
|
5206
|
-
<p class="tb-group">
|
|
5207
|
-
<div class="tb-
|
|
5208
|
-
@for (
|
|
5209
|
-
<div class="tb-
|
|
5210
|
-
<span>{{
|
|
5211
|
-
<
|
|
6340
|
+
<p class="tb-group">Light & dark — generated together, side by side</p>
|
|
6341
|
+
<div class="tb-modes">
|
|
6342
|
+
@for (m of modePanels(); track m.label) {
|
|
6343
|
+
<div class="tb-panel" [style.background]="m.colors['background']" [style.borderColor]="m.colors['outline']">
|
|
6344
|
+
<span class="tb-panel-tag" [style.color]="m.colors['on-background-variant']">{{ m.label }}</span>
|
|
6345
|
+
<div class="tb-mode-swatches">
|
|
6346
|
+
@for (s of swatches; track s.label) {
|
|
6347
|
+
<div class="tb-swatch" [style.background]="m.colors[s.token]" [style.color]="m.colors[s.on]">
|
|
6348
|
+
<span>{{ s.label }}</span>
|
|
6349
|
+
<code>{{ m.colors[s.token] }}</code>
|
|
6350
|
+
</div>
|
|
6351
|
+
}
|
|
6352
|
+
</div>
|
|
6353
|
+
<div class="tb-mini-card" [style.background]="m.colors['surface']" [style.borderColor]="m.colors['outline']">
|
|
6354
|
+
<div class="tb-mini-head" [style.background]="m.colors['primary']" [style.color]="m.colors['on-primary']">
|
|
6355
|
+
Card header
|
|
6356
|
+
</div>
|
|
6357
|
+
<div class="tb-mini-body" [style.color]="m.colors['on-surface']">
|
|
6358
|
+
Semantic inks stay legible:
|
|
6359
|
+
<b [style.color]="m.colors['error']">error</b> ·
|
|
6360
|
+
<b [style.color]="m.colors['warn']">warn</b> ·
|
|
6361
|
+
<b [style.color]="m.colors['success']">success</b>.
|
|
6362
|
+
</div>
|
|
6363
|
+
</div>
|
|
5212
6364
|
</div>
|
|
5213
6365
|
}
|
|
5214
6366
|
</div>
|
|
5215
6367
|
|
|
5216
|
-
<p class="tb-group">
|
|
6368
|
+
<p class="tb-group">Real components — your brand, live ({{ mode() }})</p>
|
|
5217
6369
|
<div class="tb-buttons">
|
|
5218
6370
|
@for (v of variants; track v) {
|
|
5219
6371
|
<button text-button [variant]="v" size="lg">{{ v }}</button>
|
|
@@ -5225,26 +6377,45 @@ class UniThemeBuilderComponent {
|
|
|
5225
6377
|
}
|
|
5226
6378
|
</div>
|
|
5227
6379
|
|
|
5228
|
-
<p class="tb-group">
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
<
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
<div class="tb-
|
|
5242
|
-
<
|
|
5243
|
-
<
|
|
5244
|
-
|
|
5245
|
-
|
|
6380
|
+
<p class="tb-group">
|
|
6381
|
+
Contrast report — {{ report().checks.length }} pairs ·
|
|
6382
|
+
worst {{ report().worst }}:1 ·
|
|
6383
|
+
@if (report().failing.length === 0) {
|
|
6384
|
+
<span class="tb-pass">all AA</span>
|
|
6385
|
+
} @else {
|
|
6386
|
+
<span class="tb-fail">{{ report().failing.length }} failing</span>
|
|
6387
|
+
}
|
|
6388
|
+
<button type="button" class="tb-link" (click)="showAllPairs.set(!showAllPairs())">
|
|
6389
|
+
{{ showAllPairs() ? 'hide detail' : 'show all pairs' }}
|
|
6390
|
+
</button>
|
|
6391
|
+
</p>
|
|
6392
|
+
@if (report().failing.length > 0 || showAllPairs()) {
|
|
6393
|
+
<div class="tb-matrix">
|
|
6394
|
+
<table>
|
|
6395
|
+
<thead>
|
|
6396
|
+
<tr><th>mode</th><th>foreground</th><th>on</th><th>ratio</th><th>needs</th><th>level</th></tr>
|
|
6397
|
+
</thead>
|
|
6398
|
+
<tbody>
|
|
6399
|
+
@for (c of visibleChecks(); track $index) {
|
|
6400
|
+
<tr [class.bad]="!c.pass">
|
|
6401
|
+
<td>{{ c.mode }}</td>
|
|
6402
|
+
<td><code>{{ c.foreground }}</code></td>
|
|
6403
|
+
<td><code>{{ c.background }}</code></td>
|
|
6404
|
+
<td>{{ c.ratio }}</td>
|
|
6405
|
+
<td>{{ c.required }}</td>
|
|
6406
|
+
<td>{{ c.level }}</td>
|
|
6407
|
+
</tr>
|
|
6408
|
+
}
|
|
6409
|
+
</tbody>
|
|
6410
|
+
</table>
|
|
5246
6411
|
</div>
|
|
5247
|
-
|
|
6412
|
+
}
|
|
6413
|
+
@if (report().failing.length > 0) {
|
|
6414
|
+
<p class="tb-hint">
|
|
6415
|
+
Failing pairs come from hard-pinned brand colors (pins are emitted verbatim). Un-pin, or
|
|
6416
|
+
use a preset — soft targets keep brand hue while the guard-rail restores AA.
|
|
6417
|
+
</p>
|
|
6418
|
+
}
|
|
5248
6419
|
|
|
5249
6420
|
<p class="tb-hint">Tip: browse to any component story in the sidebar — it's wearing your brand now.</p>
|
|
5250
6421
|
</section>
|
|
@@ -5260,7 +6431,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5260
6431
|
template: `
|
|
5261
6432
|
<aside [class]="controls()">
|
|
5262
6433
|
<header class="tb-head">
|
|
5263
|
-
<span class="tb-eyebrow">Theme builder ·
|
|
6434
|
+
<span class="tb-eyebrow">Theme builder · Playground</span>
|
|
5264
6435
|
<h2 class="tb-title">Make Uni your brand</h2>
|
|
5265
6436
|
<p class="tb-lede">
|
|
5266
6437
|
Every token is derived in OKLCH from a seed color, a scheme and a category — or bring
|
|
@@ -5307,13 +6478,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5307
6478
|
</select>
|
|
5308
6479
|
</label>
|
|
5309
6480
|
|
|
6481
|
+
<label class="tb-field">
|
|
6482
|
+
<span>Shape</span>
|
|
6483
|
+
<select (change)="setShape($any($event.target).value)">
|
|
6484
|
+
@for (s of shapes; track s) {
|
|
6485
|
+
<option [value]="s" [selected]="s === shape()">{{ s }}</option>
|
|
6486
|
+
}
|
|
6487
|
+
</select>
|
|
6488
|
+
</label>
|
|
6489
|
+
|
|
5310
6490
|
<label class="tb-field">
|
|
5311
6491
|
<span>Accent saturation floor · {{ floor() }}</span>
|
|
5312
6492
|
<input type="range" min="0" max="45" [value]="floor()" (input)="setFloor($any($event.target).value)" />
|
|
5313
6493
|
</label>
|
|
5314
6494
|
|
|
5315
6495
|
<div class="tb-field">
|
|
5316
|
-
<span>
|
|
6496
|
+
<span>Storybook mode</span>
|
|
5317
6497
|
<div class="tb-toggle">
|
|
5318
6498
|
<button type="button" [class.on]="mode() === 'light'" (click)="setMode('light')">Light</button>
|
|
5319
6499
|
<button type="button" [class.on]="mode() === 'dark'" (click)="setMode('dark')">Dark</button>
|
|
@@ -5342,6 +6522,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5342
6522
|
</div>
|
|
5343
6523
|
</label>
|
|
5344
6524
|
|
|
6525
|
+
<div class="tb-field">
|
|
6526
|
+
<span>Export</span>
|
|
6527
|
+
<div class="tb-exports">
|
|
6528
|
+
<button type="button" (click)="copyThemeFile()">
|
|
6529
|
+
{{ copied() === 'file' ? 'Copied ✓' : 'Copy uni-theme.ts' }}
|
|
6530
|
+
</button>
|
|
6531
|
+
<button type="button" (click)="copyNgAdd()">
|
|
6532
|
+
{{ copied() === 'ngadd' ? 'Copied ✓' : 'Copy ng add command' }}
|
|
6533
|
+
</button>
|
|
6534
|
+
<button type="button" (click)="copyDtcg()">
|
|
6535
|
+
{{ copied() === 'dtcg' ? 'Copied ✓' : 'Copy DTCG JSON' }}
|
|
6536
|
+
</button>
|
|
6537
|
+
</div>
|
|
6538
|
+
</div>
|
|
6539
|
+
|
|
5345
6540
|
<div class="tb-actions">
|
|
5346
6541
|
<button type="button" class="tb-reset" (click)="reset()">Reset to default</button>
|
|
5347
6542
|
</div>
|
|
@@ -5349,17 +6544,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5349
6544
|
</aside>
|
|
5350
6545
|
|
|
5351
6546
|
<section [class]="preview()">
|
|
5352
|
-
<p class="tb-group">
|
|
5353
|
-
<div class="tb-
|
|
5354
|
-
@for (
|
|
5355
|
-
<div class="tb-
|
|
5356
|
-
<span>{{
|
|
5357
|
-
<
|
|
6547
|
+
<p class="tb-group">Light & dark — generated together, side by side</p>
|
|
6548
|
+
<div class="tb-modes">
|
|
6549
|
+
@for (m of modePanels(); track m.label) {
|
|
6550
|
+
<div class="tb-panel" [style.background]="m.colors['background']" [style.borderColor]="m.colors['outline']">
|
|
6551
|
+
<span class="tb-panel-tag" [style.color]="m.colors['on-background-variant']">{{ m.label }}</span>
|
|
6552
|
+
<div class="tb-mode-swatches">
|
|
6553
|
+
@for (s of swatches; track s.label) {
|
|
6554
|
+
<div class="tb-swatch" [style.background]="m.colors[s.token]" [style.color]="m.colors[s.on]">
|
|
6555
|
+
<span>{{ s.label }}</span>
|
|
6556
|
+
<code>{{ m.colors[s.token] }}</code>
|
|
6557
|
+
</div>
|
|
6558
|
+
}
|
|
6559
|
+
</div>
|
|
6560
|
+
<div class="tb-mini-card" [style.background]="m.colors['surface']" [style.borderColor]="m.colors['outline']">
|
|
6561
|
+
<div class="tb-mini-head" [style.background]="m.colors['primary']" [style.color]="m.colors['on-primary']">
|
|
6562
|
+
Card header
|
|
6563
|
+
</div>
|
|
6564
|
+
<div class="tb-mini-body" [style.color]="m.colors['on-surface']">
|
|
6565
|
+
Semantic inks stay legible:
|
|
6566
|
+
<b [style.color]="m.colors['error']">error</b> ·
|
|
6567
|
+
<b [style.color]="m.colors['warn']">warn</b> ·
|
|
6568
|
+
<b [style.color]="m.colors['success']">success</b>.
|
|
6569
|
+
</div>
|
|
6570
|
+
</div>
|
|
5358
6571
|
</div>
|
|
5359
6572
|
}
|
|
5360
6573
|
</div>
|
|
5361
6574
|
|
|
5362
|
-
<p class="tb-group">
|
|
6575
|
+
<p class="tb-group">Real components — your brand, live ({{ mode() }})</p>
|
|
5363
6576
|
<div class="tb-buttons">
|
|
5364
6577
|
@for (v of variants; track v) {
|
|
5365
6578
|
<button text-button [variant]="v" size="lg">{{ v }}</button>
|
|
@@ -5371,26 +6584,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5371
6584
|
}
|
|
5372
6585
|
</div>
|
|
5373
6586
|
|
|
5374
|
-
<p class="tb-group">
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
<
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
<div class="tb-
|
|
5388
|
-
<
|
|
5389
|
-
<
|
|
5390
|
-
|
|
5391
|
-
|
|
6587
|
+
<p class="tb-group">
|
|
6588
|
+
Contrast report — {{ report().checks.length }} pairs ·
|
|
6589
|
+
worst {{ report().worst }}:1 ·
|
|
6590
|
+
@if (report().failing.length === 0) {
|
|
6591
|
+
<span class="tb-pass">all AA</span>
|
|
6592
|
+
} @else {
|
|
6593
|
+
<span class="tb-fail">{{ report().failing.length }} failing</span>
|
|
6594
|
+
}
|
|
6595
|
+
<button type="button" class="tb-link" (click)="showAllPairs.set(!showAllPairs())">
|
|
6596
|
+
{{ showAllPairs() ? 'hide detail' : 'show all pairs' }}
|
|
6597
|
+
</button>
|
|
6598
|
+
</p>
|
|
6599
|
+
@if (report().failing.length > 0 || showAllPairs()) {
|
|
6600
|
+
<div class="tb-matrix">
|
|
6601
|
+
<table>
|
|
6602
|
+
<thead>
|
|
6603
|
+
<tr><th>mode</th><th>foreground</th><th>on</th><th>ratio</th><th>needs</th><th>level</th></tr>
|
|
6604
|
+
</thead>
|
|
6605
|
+
<tbody>
|
|
6606
|
+
@for (c of visibleChecks(); track $index) {
|
|
6607
|
+
<tr [class.bad]="!c.pass">
|
|
6608
|
+
<td>{{ c.mode }}</td>
|
|
6609
|
+
<td><code>{{ c.foreground }}</code></td>
|
|
6610
|
+
<td><code>{{ c.background }}</code></td>
|
|
6611
|
+
<td>{{ c.ratio }}</td>
|
|
6612
|
+
<td>{{ c.required }}</td>
|
|
6613
|
+
<td>{{ c.level }}</td>
|
|
6614
|
+
</tr>
|
|
6615
|
+
}
|
|
6616
|
+
</tbody>
|
|
6617
|
+
</table>
|
|
5392
6618
|
</div>
|
|
5393
|
-
|
|
6619
|
+
}
|
|
6620
|
+
@if (report().failing.length > 0) {
|
|
6621
|
+
<p class="tb-hint">
|
|
6622
|
+
Failing pairs come from hard-pinned brand colors (pins are emitted verbatim). Un-pin, or
|
|
6623
|
+
use a preset — soft targets keep brand hue while the guard-rail restores AA.
|
|
6624
|
+
</p>
|
|
6625
|
+
}
|
|
5394
6626
|
|
|
5395
6627
|
<p class="tb-hint">Tip: browse to any component story in the sidebar — it's wearing your brand now.</p>
|
|
5396
6628
|
</section>
|
|
@@ -5509,5 +6741,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5509
6741
|
* Generated bundle index. Do not edit.
|
|
5510
6742
|
*/
|
|
5511
6743
|
|
|
5512
|
-
export { BodyRenderDirective, ConfirmationDialogComponent, DragAndDropDirective, FOCUSABLE_SELECTOR, LocalStorageService, NotificationService, NotificationsComponent, RippleDirective, ThemeService, UNI_THEMES, UniAlertComponent, UniBackgroundComponent, UniBadgeComponent, UniBaseDatasource, UniBoxComponent, UniButtonComponent, UniButtonGroupComponent, UniCardComponent, UniCardContentComponent, UniCardHeaderComponent, UniCenterComponent, UniCheckboxComponent, UniDataSearchComponent, UniDataTableComponent, UniDebounceInputComponent, UniDialogButtonsComponent, UniDialogComponent, UniDialogHeaderComponent, UniDividerComponent, UniDropdownComponent, UniExpandAreaComponent, UniExpandComponent, UniExpandToggleComponent, UniFileDropZoneComponent, UniGridAreaComponent, UniGridComponent, UniIconButtonComponent, UniIconComponent, UniInputBoxComponent, UniInputComponent, UniJsonViewComponent, UniMenuComponent, UniMultiSelectComponent, UniMultiSelectDropdownComponent, UniNotificationBadgeComponent, UniPaginatorComponent, UniPopoverComponent, UniProgressBarComponent, UniProgressGaugeComponent, UniRadioComponent, UniRecordDatasource, UniRowComponent, UniScrollAreaComponent, UniSearchInputComponent, UniSelectComponent, UniServerSideDatasource, UniSnackbarComponent, UniSortHeaderComponent, UniStackComponent, UniSymbolComponent, UniTagComponent, UniTextComponent, UniThemeBuilderComponent, UniToggleComponent, UniTooltipComponent, UniWrapComponent, acceptableFile, anchorArrowStyles, anchorStyles, getFileExtension, motionSafe, newAnchorName, resolveFocusTarget, uniqueId, useTimer, visuallyHidden };
|
|
6744
|
+
export { BodyRenderDirective, ConfirmationDialogComponent, DragAndDropDirective, FOCUSABLE_SELECTOR, LocalStorageService, NotificationService, NotificationsComponent, RippleDirective, ThemeService, UNI_THEMES, UniAlertComponent, UniAppBarComponent, UniAvatarComponent, UniAvatarGroupComponent, UniBackgroundComponent, UniBadgeComponent, UniBaseDatasource, UniBoxComponent, UniBreadcrumbComponent, UniButtonComponent, UniButtonGroupComponent, UniCardComponent, UniCardContentComponent, UniCardHeaderComponent, UniCenterComponent, UniCheckboxComponent, UniDataSearchComponent, UniDataTableComponent, UniDebounceInputComponent, UniDialogButtonsComponent, UniDialogComponent, UniDialogHeaderComponent, UniDividerComponent, UniDrawerComponent, UniDropdownComponent, UniExpandAreaComponent, UniExpandComponent, UniExpandToggleComponent, UniFileDropZoneComponent, UniGridAreaComponent, UniGridComponent, UniIconButtonComponent, UniIconComponent, UniInputBoxComponent, UniInputComponent, UniJsonViewComponent, UniMenuComponent, UniMultiSelectComponent, UniMultiSelectDropdownComponent, UniNotificationBadgeComponent, UniPaginatorComponent, UniPopoverComponent, UniProgressBarComponent, UniProgressGaugeComponent, UniRadioComponent, UniRecordDatasource, UniRowComponent, UniScrollAreaComponent, UniSearchInputComponent, UniSelectComponent, UniServerSideDatasource, UniSkeletonComponent, UniSliderComponent, UniSnackbarComponent, UniSortHeaderComponent, UniStackComponent, UniSymbolComponent, UniTabComponent, UniTabsComponent, UniTagComponent, UniTextComponent, UniTextareaComponent, UniThemeBuilderComponent, UniToggleComponent, UniTooltipComponent, UniWrapComponent, acceptableFile, anchorArrowStyles, anchorStyles, getFileExtension, motionSafe, newAnchorName, resolveFocusTarget, uniqueId, useTimer, visuallyHidden };
|
|
5513
6745
|
//# sourceMappingURL=uni-design-system-uni-angular.mjs.map
|