@hyalo/angular 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +95 -41
- package/README.md +46 -32
- package/fesm2022/hyalo-angular-accordion.mjs +6 -6
- package/fesm2022/hyalo-angular-accordion.mjs.map +1 -1
- package/fesm2022/hyalo-angular-alert.mjs +171 -0
- package/fesm2022/hyalo-angular-alert.mjs.map +1 -0
- package/fesm2022/hyalo-angular-aspect-ratio.mjs +64 -0
- package/fesm2022/hyalo-angular-aspect-ratio.mjs.map +1 -0
- package/fesm2022/hyalo-angular-avatar.mjs +169 -0
- package/fesm2022/hyalo-angular-avatar.mjs.map +1 -0
- package/fesm2022/hyalo-angular-badge.mjs +268 -0
- package/fesm2022/hyalo-angular-badge.mjs.map +1 -0
- package/fesm2022/hyalo-angular-bento.mjs +132 -0
- package/fesm2022/hyalo-angular-bento.mjs.map +1 -0
- package/fesm2022/hyalo-angular-blocks.mjs +985 -0
- package/fesm2022/hyalo-angular-blocks.mjs.map +1 -0
- package/fesm2022/hyalo-angular-border-beam.mjs +73 -0
- package/fesm2022/hyalo-angular-border-beam.mjs.map +1 -0
- package/fesm2022/hyalo-angular-breadcrumb.mjs +77 -0
- package/fesm2022/hyalo-angular-breadcrumb.mjs.map +1 -0
- package/fesm2022/hyalo-angular-button-group.mjs +90 -0
- package/fesm2022/hyalo-angular-button-group.mjs.map +1 -0
- package/fesm2022/hyalo-angular-button.mjs +4 -3
- package/fesm2022/hyalo-angular-button.mjs.map +1 -1
- package/fesm2022/hyalo-angular-card.mjs +2 -2
- package/fesm2022/hyalo-angular-card.mjs.map +1 -1
- package/fesm2022/hyalo-angular-carousel.mjs +709 -0
- package/fesm2022/hyalo-angular-carousel.mjs.map +1 -0
- package/fesm2022/hyalo-angular-chapter-nav.mjs +336 -0
- package/fesm2022/hyalo-angular-chapter-nav.mjs.map +1 -0
- package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs +5 -0
- package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs.map +1 -0
- package/fesm2022/hyalo-angular-chart.mjs +391 -0
- package/fesm2022/hyalo-angular-chart.mjs.map +1 -0
- package/fesm2022/hyalo-angular-choice.mjs +2 -1
- package/fesm2022/hyalo-angular-choice.mjs.map +1 -1
- package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs +40 -0
- package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs.map +1 -0
- package/fesm2022/hyalo-angular-code-block.mjs +161 -0
- package/fesm2022/hyalo-angular-code-block.mjs.map +1 -0
- package/fesm2022/hyalo-angular-command.mjs +193 -0
- package/fesm2022/hyalo-angular-command.mjs.map +1 -0
- package/fesm2022/hyalo-angular-copy.mjs +138 -0
- package/fesm2022/hyalo-angular-copy.mjs.map +1 -0
- package/fesm2022/hyalo-angular-core.mjs +424 -0
- package/fesm2022/hyalo-angular-core.mjs.map +1 -0
- package/fesm2022/hyalo-angular-description-list.mjs +57 -0
- package/fesm2022/hyalo-angular-description-list.mjs.map +1 -0
- package/fesm2022/hyalo-angular-dialog.mjs +51 -22
- package/fesm2022/hyalo-angular-dialog.mjs.map +1 -1
- package/fesm2022/hyalo-angular-divider.mjs +66 -0
- package/fesm2022/hyalo-angular-divider.mjs.map +1 -0
- package/fesm2022/hyalo-angular-empty-state.mjs +123 -0
- package/fesm2022/hyalo-angular-empty-state.mjs.map +1 -0
- package/fesm2022/hyalo-angular-field.mjs +41 -9
- package/fesm2022/hyalo-angular-field.mjs.map +1 -1
- package/fesm2022/hyalo-angular-filter.mjs +309 -0
- package/fesm2022/hyalo-angular-filter.mjs.map +1 -0
- package/fesm2022/hyalo-angular-hotspot.mjs +225 -0
- package/fesm2022/hyalo-angular-hotspot.mjs.map +1 -0
- package/fesm2022/hyalo-angular-hover-card.mjs +233 -0
- package/fesm2022/hyalo-angular-hover-card.mjs.map +1 -0
- package/fesm2022/hyalo-angular-icon.mjs +42 -0
- package/fesm2022/hyalo-angular-icon.mjs.map +1 -1
- package/fesm2022/hyalo-angular-image-compare.mjs +168 -0
- package/fesm2022/hyalo-angular-image-compare.mjs.map +1 -0
- package/fesm2022/hyalo-angular-interaction.mjs +32 -41
- package/fesm2022/hyalo-angular-interaction.mjs.map +1 -1
- package/fesm2022/hyalo-angular-kbd.mjs +41 -0
- package/fesm2022/hyalo-angular-kbd.mjs.map +1 -0
- package/fesm2022/hyalo-angular-lightbox.mjs +228 -0
- package/fesm2022/hyalo-angular-lightbox.mjs.map +1 -0
- package/fesm2022/hyalo-angular-link.mjs +42 -0
- package/fesm2022/hyalo-angular-link.mjs.map +1 -0
- package/fesm2022/hyalo-angular-list.mjs +131 -0
- package/fesm2022/hyalo-angular-list.mjs.map +1 -0
- package/fesm2022/hyalo-angular-marquee.mjs +197 -0
- package/fesm2022/hyalo-angular-marquee.mjs.map +1 -0
- package/fesm2022/hyalo-angular-menu.mjs +423 -0
- package/fesm2022/hyalo-angular-menu.mjs.map +1 -0
- package/fesm2022/hyalo-angular-mesh.mjs +126 -0
- package/fesm2022/hyalo-angular-mesh.mjs.map +1 -0
- package/fesm2022/hyalo-angular-motion.mjs +620 -0
- package/fesm2022/hyalo-angular-motion.mjs.map +1 -0
- package/fesm2022/hyalo-angular-navbar.mjs +1 -1
- package/fesm2022/hyalo-angular-navbar.mjs.map +1 -1
- package/fesm2022/hyalo-angular-navigation-menu.mjs +222 -0
- package/fesm2022/hyalo-angular-navigation-menu.mjs.map +1 -0
- package/fesm2022/hyalo-angular-number-ticker.mjs +174 -0
- package/fesm2022/hyalo-angular-number-ticker.mjs.map +1 -0
- package/fesm2022/hyalo-angular-overlay.mjs +71 -2
- package/fesm2022/hyalo-angular-overlay.mjs.map +1 -1
- package/fesm2022/hyalo-angular-pagination.mjs +187 -0
- package/fesm2022/hyalo-angular-pagination.mjs.map +1 -0
- package/fesm2022/hyalo-angular-popover.mjs +34 -5
- package/fesm2022/hyalo-angular-popover.mjs.map +1 -1
- package/fesm2022/hyalo-angular-progress.mjs +209 -0
- package/fesm2022/hyalo-angular-progress.mjs.map +1 -0
- package/fesm2022/hyalo-angular-progressive-blur.mjs +73 -0
- package/fesm2022/hyalo-angular-progressive-blur.mjs.map +1 -0
- package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs +186 -0
- package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs.map +1 -0
- package/fesm2022/hyalo-angular-refraction.mjs +178 -0
- package/fesm2022/hyalo-angular-refraction.mjs.map +1 -0
- package/fesm2022/hyalo-angular-scroll-area.mjs +93 -0
- package/fesm2022/hyalo-angular-scroll-area.mjs.map +1 -0
- package/fesm2022/hyalo-angular-scroll-to-top.mjs +127 -0
- package/fesm2022/hyalo-angular-scroll-to-top.mjs.map +1 -0
- package/fesm2022/hyalo-angular-segmented.mjs +1 -1
- package/fesm2022/hyalo-angular-segmented.mjs.map +1 -1
- package/fesm2022/hyalo-angular-select.mjs +112 -15
- package/fesm2022/hyalo-angular-select.mjs.map +1 -1
- package/fesm2022/hyalo-angular-sidebar.mjs +241 -0
- package/fesm2022/hyalo-angular-sidebar.mjs.map +1 -0
- package/fesm2022/hyalo-angular-skeleton.mjs +131 -0
- package/fesm2022/hyalo-angular-skeleton.mjs.map +1 -0
- package/fesm2022/hyalo-angular-sparkline.mjs +110 -0
- package/fesm2022/hyalo-angular-sparkline.mjs.map +1 -0
- package/fesm2022/hyalo-angular-split-text.mjs +126 -0
- package/fesm2022/hyalo-angular-split-text.mjs.map +1 -0
- package/fesm2022/hyalo-angular-stat.mjs +193 -0
- package/fesm2022/hyalo-angular-stat.mjs.map +1 -0
- package/fesm2022/hyalo-angular-stepper.mjs +254 -0
- package/fesm2022/hyalo-angular-stepper.mjs.map +1 -0
- package/fesm2022/hyalo-angular-table.mjs +335 -0
- package/fesm2022/hyalo-angular-table.mjs.map +1 -0
- package/fesm2022/hyalo-angular-tabs.mjs +1 -1
- package/fesm2022/hyalo-angular-tabs.mjs.map +1 -1
- package/fesm2022/hyalo-angular-theme.mjs +1 -1
- package/fesm2022/hyalo-angular-theme.mjs.map +1 -1
- package/fesm2022/hyalo-angular-timeline.mjs +157 -0
- package/fesm2022/hyalo-angular-timeline.mjs.map +1 -0
- package/fesm2022/hyalo-angular-toast.mjs +2 -1
- package/fesm2022/hyalo-angular-toast.mjs.map +1 -1
- package/fesm2022/hyalo-angular.mjs +2 -473
- package/package.json +198 -2
- package/styles/parts/field.css +44 -36
- package/styles/parts/glass.css +2 -0
- package/styles/parts/motion.css +19 -0
- package/styles/parts/typography.css +17 -0
- package/types/hyalo-angular-accordion.d.ts +1 -1
- package/types/hyalo-angular-alert.d.ts +47 -0
- package/types/hyalo-angular-aspect-ratio.d.ts +13 -0
- package/types/hyalo-angular-avatar.d.ts +39 -0
- package/types/hyalo-angular-badge.d.ts +82 -0
- package/types/hyalo-angular-bento.d.ts +25 -0
- package/types/hyalo-angular-blocks.d.ts +272 -0
- package/types/hyalo-angular-border-beam.d.ts +15 -0
- package/types/hyalo-angular-breadcrumb.d.ts +22 -0
- package/types/hyalo-angular-button-group.d.ts +19 -0
- package/types/hyalo-angular-button.d.ts +4 -3
- package/types/hyalo-angular-card.d.ts +1 -1
- package/types/hyalo-angular-carousel.d.ts +147 -0
- package/types/hyalo-angular-chapter-nav.d.ts +79 -0
- package/types/hyalo-angular-chart.d.ts +90 -0
- package/types/hyalo-angular-code-block.d.ts +46 -0
- package/types/hyalo-angular-command.d.ts +41 -0
- package/types/hyalo-angular-copy.d.ts +39 -0
- package/types/hyalo-angular-core.d.ts +210 -0
- package/types/hyalo-angular-description-list.d.ts +16 -0
- package/types/hyalo-angular-dialog.d.ts +2 -1
- package/types/hyalo-angular-divider.d.ts +12 -0
- package/types/hyalo-angular-empty-state.d.ts +30 -0
- package/types/hyalo-angular-field.d.ts +10 -4
- package/types/hyalo-angular-filter.d.ts +122 -0
- package/types/hyalo-angular-hotspot.d.ts +70 -0
- package/types/hyalo-angular-hover-card.d.ts +47 -0
- package/types/hyalo-angular-image-compare.d.ts +55 -0
- package/types/hyalo-angular-kbd.d.ts +5 -0
- package/types/hyalo-angular-lightbox.d.ts +67 -0
- package/types/hyalo-angular-link.d.ts +5 -0
- package/types/hyalo-angular-list.d.ts +30 -0
- package/types/hyalo-angular-marquee.d.ts +48 -0
- package/types/hyalo-angular-menu.d.ts +105 -0
- package/types/hyalo-angular-mesh.d.ts +36 -0
- package/types/hyalo-angular-motion.d.ts +218 -0
- package/types/hyalo-angular-navigation-menu.d.ts +47 -0
- package/types/hyalo-angular-number-ticker.d.ts +52 -0
- package/types/hyalo-angular-overlay.d.ts +9 -0
- package/types/hyalo-angular-pagination.d.ts +59 -0
- package/types/hyalo-angular-popover.d.ts +10 -0
- package/types/hyalo-angular-progress.d.ts +46 -0
- package/types/hyalo-angular-progressive-blur.d.ts +14 -0
- package/types/hyalo-angular-refraction.d.ts +46 -0
- package/types/hyalo-angular-scroll-area.d.ts +18 -0
- package/types/hyalo-angular-scroll-to-top.d.ts +31 -0
- package/types/hyalo-angular-segmented.d.ts +1 -1
- package/types/hyalo-angular-select.d.ts +49 -3
- package/types/hyalo-angular-sidebar.d.ts +57 -0
- package/types/hyalo-angular-skeleton.d.ts +34 -0
- package/types/hyalo-angular-sparkline.d.ts +19 -0
- package/types/hyalo-angular-split-text.d.ts +24 -0
- package/types/hyalo-angular-stat.d.ts +56 -0
- package/types/hyalo-angular-stepper.d.ts +63 -0
- package/types/hyalo-angular-table.d.ts +125 -0
- package/types/hyalo-angular-timeline.d.ts +36 -0
- package/types/hyalo-angular.d.ts +2 -345
- package/fesm2022/hyalo-angular.mjs.map +0 -1
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from "@angular/common";
|
|
1
2
|
import * as i0 from "@angular/core";
|
|
2
|
-
import { ChangeDetectionStrategy, Component, booleanAttribute, computed, effect, inject, input, model, output, signal, untracked, viewChild } from "@angular/core";
|
|
3
|
+
import { ChangeDetectionStrategy, Component, DOCUMENT, DestroyRef, ElementRef, afterNextRender, booleanAttribute, computed, effect, inject, input, model, output, signal, untracked, viewChild } from "@angular/core";
|
|
3
4
|
import { Combobox, ComboboxPopup, ComboboxWidget } from "@angular/aria/combobox";
|
|
4
5
|
import { Listbox, Option } from "@angular/aria/listbox";
|
|
5
6
|
import { CdkConnectedOverlay, CdkOverlayOrigin } from "@angular/cdk/overlay";
|
|
6
|
-
import { HyFidelity, injectId } from "@hyalo/angular";
|
|
7
|
+
import { HyFidelity, injectId } from "@hyalo/angular/core";
|
|
7
8
|
import { HyIcon } from "@hyalo/angular/icon";
|
|
8
9
|
import { HY_FIELD } from "@hyalo/angular/field";
|
|
9
10
|
import { hyDropdownPositions, ɵHyPresence } from "@hyalo/angular/overlay";
|
|
10
11
|
var HySelect = class HySelect {
|
|
11
12
|
fidelity = inject(HyFidelity);
|
|
13
|
+
host = inject(ElementRef).nativeElement;
|
|
14
|
+
document = inject(DOCUMENT);
|
|
15
|
+
destroy = inject(DestroyRef);
|
|
16
|
+
ready = signal(false, ...ngDevMode ? [{ debugName: "ready" }] : /* istanbul ignore next */ []);
|
|
12
17
|
field = inject(HY_FIELD, { optional: true });
|
|
13
18
|
trigger = viewChild("trigger", ...ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []);
|
|
14
19
|
overlay = viewChild(CdkConnectedOverlay, ...ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []);
|
|
@@ -16,6 +21,8 @@ var HySelect = class HySelect {
|
|
|
16
21
|
options = input.required(...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
|
|
17
22
|
value = model(void 0, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
|
|
18
23
|
placeholder = input("Select", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
|
|
24
|
+
name = input("", ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
|
|
25
|
+
optionTemplate = input(...ngDevMode ? [void 0, { debugName: "optionTemplate" }] : /* istanbul ignore next */ []);
|
|
19
26
|
disabled = input(false, {
|
|
20
27
|
...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
|
|
21
28
|
transform: booleanAttribute
|
|
@@ -39,7 +46,9 @@ var HySelect = class HySelect {
|
|
|
39
46
|
});
|
|
40
47
|
touch = output();
|
|
41
48
|
labelable = true;
|
|
42
|
-
|
|
49
|
+
nativeId = injectId("select");
|
|
50
|
+
triggerId = this.nativeId + "-trigger";
|
|
51
|
+
id = computed(() => this.useNative() ? this.nativeId : this.triggerId, ...ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []);
|
|
43
52
|
errorMessage = computed(() => {
|
|
44
53
|
const first = this.errors()[0];
|
|
45
54
|
return first ? first.message ?? first.kind : void 0;
|
|
@@ -48,7 +57,37 @@ var HySelect = class HySelect {
|
|
|
48
57
|
rendered = signal(false, ...ngDevMode ? [{ debugName: "rendered" }] : /* istanbul ignore next */ []);
|
|
49
58
|
positions = hyDropdownPositions();
|
|
50
59
|
panelWidth = signal(0, ...ngDevMode ? [{ debugName: "panelWidth" }] : /* istanbul ignore next */ []);
|
|
51
|
-
useNative =
|
|
60
|
+
useNative = signal(true, ...ngDevMode ? [{ debugName: "useNative" }] : /* istanbul ignore next */ []);
|
|
61
|
+
keyedOptions = computed(() => {
|
|
62
|
+
const keys = /* @__PURE__ */ new Set();
|
|
63
|
+
return this.options().map((option) => {
|
|
64
|
+
const value = option.value;
|
|
65
|
+
if (option.key === void 0 && (typeof value === "object" || typeof value === "function")) throw new Error("HySelect: object values require a stable option key");
|
|
66
|
+
const key = option.key === void 0 ? `${typeof value}:${String(value)}` : `${typeof option.key}:${option.key}`;
|
|
67
|
+
if (keys.has(key)) throw new Error("HySelect: duplicate option key " + key);
|
|
68
|
+
keys.add(key);
|
|
69
|
+
return {
|
|
70
|
+
option,
|
|
71
|
+
key,
|
|
72
|
+
disabled: !!(option.disabled || option.group?.disabled),
|
|
73
|
+
context: { $implicit: option }
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}, ...ngDevMode ? [{ debugName: "keyedOptions" }] : /* istanbul ignore next */ []);
|
|
77
|
+
groups = computed(() => {
|
|
78
|
+
const groups = /* @__PURE__ */ new Map();
|
|
79
|
+
for (const option of this.keyedOptions()) {
|
|
80
|
+
const key = option.option.group?.key ?? "";
|
|
81
|
+
const group = groups.get(key) ?? {
|
|
82
|
+
key,
|
|
83
|
+
label: option.option.group?.label ?? "",
|
|
84
|
+
options: []
|
|
85
|
+
};
|
|
86
|
+
group.options.push(option);
|
|
87
|
+
groups.set(key, group);
|
|
88
|
+
}
|
|
89
|
+
return [...groups.values()];
|
|
90
|
+
}, ...ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []);
|
|
52
91
|
selectedOption = computed(() => this.options().find((o) => o.value === this.value()), ...ngDevMode ? [{ debugName: "selectedOption" }] : /* istanbul ignore next */ []);
|
|
53
92
|
listValue = computed(() => {
|
|
54
93
|
const v = this.value();
|
|
@@ -56,6 +95,13 @@ var HySelect = class HySelect {
|
|
|
56
95
|
}, ...ngDevMode ? [{ debugName: "listValue" }] : /* istanbul ignore next */ []);
|
|
57
96
|
showsError = computed(() => this.field ? this.field.errorShown() : this.invalid() && this.touched(), ...ngDevMode ? [{ debugName: "showsError" }] : /* istanbul ignore next */ []);
|
|
58
97
|
constructor() {
|
|
98
|
+
afterNextRender(() => this.ready.set(true));
|
|
99
|
+
effect(() => {
|
|
100
|
+
this.ready();
|
|
101
|
+
this.native();
|
|
102
|
+
this.fidelity.tier();
|
|
103
|
+
this.scheduleMode();
|
|
104
|
+
});
|
|
59
105
|
effect(() => {
|
|
60
106
|
const open = this.expanded();
|
|
61
107
|
untracked(() => {
|
|
@@ -101,13 +147,21 @@ var HySelect = class HySelect {
|
|
|
101
147
|
this.expanded.set(false);
|
|
102
148
|
this.trigger()?.nativeElement.focus();
|
|
103
149
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
150
|
+
scheduleMode() {
|
|
151
|
+
queueMicrotask(() => {
|
|
152
|
+
if (this.destroy.destroyed || !this.ready()) return;
|
|
153
|
+
if (this.expanded() || this.host.contains(this.document.activeElement)) return;
|
|
154
|
+
this.useNative.set(this.native() || this.fidelity.tier() === "low");
|
|
155
|
+
});
|
|
108
156
|
}
|
|
109
|
-
|
|
110
|
-
|
|
157
|
+
pickNative(event) {
|
|
158
|
+
const key = event.target.value;
|
|
159
|
+
if (!key && !this.required()) {
|
|
160
|
+
this.value.set(void 0);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const choice = this.keyedOptions().find((item) => item.key === key);
|
|
164
|
+
if (choice && !choice.disabled) this.value.set(choice.option.value);
|
|
111
165
|
}
|
|
112
166
|
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
113
167
|
minVersion: "12.0.0",
|
|
@@ -145,6 +199,20 @@ var HySelect = class HySelect {
|
|
|
145
199
|
isRequired: false,
|
|
146
200
|
transformFunction: null
|
|
147
201
|
},
|
|
202
|
+
name: {
|
|
203
|
+
classPropertyName: "name",
|
|
204
|
+
publicName: "name",
|
|
205
|
+
isSignal: true,
|
|
206
|
+
isRequired: false,
|
|
207
|
+
transformFunction: null
|
|
208
|
+
},
|
|
209
|
+
optionTemplate: {
|
|
210
|
+
classPropertyName: "optionTemplate",
|
|
211
|
+
publicName: "optionTemplate",
|
|
212
|
+
isSignal: true,
|
|
213
|
+
isRequired: false,
|
|
214
|
+
transformFunction: null
|
|
215
|
+
},
|
|
148
216
|
disabled: {
|
|
149
217
|
classPropertyName: "disabled",
|
|
150
218
|
publicName: "disabled",
|
|
@@ -193,6 +261,7 @@ var HySelect = class HySelect {
|
|
|
193
261
|
touch: "touch"
|
|
194
262
|
},
|
|
195
263
|
host: {
|
|
264
|
+
listeners: { "focusout": "scheduleMode()" },
|
|
196
265
|
properties: { "attr.data-native": "useNative() || null" },
|
|
197
266
|
classAttribute: "hy-select"
|
|
198
267
|
},
|
|
@@ -210,9 +279,19 @@ var HySelect = class HySelect {
|
|
|
210
279
|
isSignal: true
|
|
211
280
|
}],
|
|
212
281
|
ngImport: i0,
|
|
213
|
-
template: "
|
|
214
|
-
styles: [":host{position:relative;display:flex;align-items:center;flex:1;min-inline-size:0;align-self:stretch}.hy-select__trigger,.hy-select__native{flex:1;min-inline-size:0;align-self:stretch;display:flex;align-items:center;gap:var(--hy-space-2);padding:0;padding-inline-end:1.75rem;border:0;background:transparent;color:var(--hy-ink);font:inherit;text-align:start;cursor:pointer;appearance:none}.hy-select__trigger:focus-visible,.hy-select__native:focus-visible{outline:none}.hy-select__trigger:disabled,.hy-select__native:disabled{cursor:not-allowed}.hy-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hy-select__placeholder{color:var(--hy-ink-3)}.hy-select__chevron{position:absolute;inset-inline-end:0;color:var(--hy-ink-3);pointer-events:none;transition:rotate var(--hy-dur-
|
|
282
|
+
template: "<select\r\n class=\"hy-select__native\"\r\n [hidden]=\"!useNative()\"\r\n [id]=\"nativeId\"\r\n [disabled]=\"disabled() || !useNative()\"\r\n [required]=\"required()\"\r\n [name]=\"useNative() ? name() : undefined\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n (change)=\"pickNative($event)\"\r\n (blur)=\"touch.emit()\"\r\n>\r\n <option value=\"\" [disabled]=\"required()\" [selected]=\"!selectedOption()\">\r\n {{ placeholder() }}\r\n </option>\r\n @for (group of groups(); track group.key) {\r\n @if (group.key) {\r\n <optgroup [label]=\"group.label\">\r\n @for (item of group.options; track item.key) {\r\n <option\r\n [value]=\"item.key\"\r\n [selected]=\"item.option.value === value()\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n {{ item.option.label }}\r\n </option>\r\n }\r\n </optgroup>\r\n } @else {\r\n @for (item of group.options; track item.key) {\r\n <option\r\n [value]=\"item.key\"\r\n [selected]=\"item.option.value === value()\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n {{ item.option.label }}\r\n </option>\r\n }\r\n }\r\n }\r\n</select>\r\n<hy-icon [hidden]=\"!useNative()\" class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n<button\r\n #trigger\r\n type=\"button\"\r\n ngCombobox\r\n #combobox=\"ngCombobox\"\r\n cdkOverlayOrigin\r\n #origin=\"cdkOverlayOrigin\"\r\n class=\"hy-select__trigger\"\r\n [hidden]=\"useNative()\"\r\n [id]=\"triggerId\"\r\n [disabled]=\"disabled() || useNative()\"\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"setExpanded($event)\"\r\n [attr.aria-labelledby]=\"field ? field.labelId + ' ' + triggerId : null\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n [attr.aria-required]=\"required() || null\"\r\n (blur)=\"touch.emit()\"\r\n>\r\n <span class=\"hy-select__value\" [class.hy-select__placeholder]=\"!selectedOption()\">{{\r\n selectedOption()?.label ?? placeholder()\r\n }}</span>\r\n <hy-icon class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n</button>\r\n<ng-template ngComboboxPopup [combobox]=\"combobox\">\r\n <ng-template\r\n cdkConnectedOverlay\r\n [cdkConnectedOverlayOrigin]=\"origin\"\r\n [cdkConnectedOverlayOpen]=\"rendered() && !useNative()\"\r\n [cdkConnectedOverlayPositions]=\"positions\"\r\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\r\n cdkConnectedOverlayPanelClass=\"hy-select-overlay\"\r\n cdkConnectedOverlayTransformOriginOn=\".hy-select__panel\"\r\n (attach)=\"onAttach()\"\r\n (overlayOutsideClick)=\"expanded.set(false)\"\r\n >\r\n <!-- Focus remains on the combobox trigger while Aria manages the active option. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n ngComboboxWidget\r\n ngListbox\r\n #listbox=\"ngListbox\"\r\n class=\"hy-select__panel hy-glass\"\r\n data-material=\"frosted\"\r\n focusMode=\"activedescendant\"\r\n selectionMode=\"explicit\"\r\n [activeDescendant]=\"listbox.activeDescendant()\"\r\n [value]=\"listValue()\"\r\n (valueChange)=\"pick($event)\"\r\n (click)=\"onPanelClick($event)\"\r\n (keydown.enter)=\"close()\"\r\n (keydown.space)=\"close()\"\r\n >\r\n @for (group of groups(); track group.key) {\r\n <div role=\"group\" [attr.aria-label]=\"group.label || null\">\r\n @if (group.label) {\r\n <div class=\"hy-select__group-label\">{{ group.label }}</div>\r\n }\r\n @for (item of group.options; track item.key) {\r\n <div\r\n ngOption\r\n class=\"hy-select__option\"\r\n [value]=\"item.option.value\"\r\n [label]=\"item.option.label\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n @if (optionTemplate(); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"item.context\"\r\n />\r\n } @else {\r\n <span>{{ item.option.label }}</span>\r\n }\r\n <hy-icon class=\"hy-select__check\" name=\"check\" />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-template>\r\n",
|
|
283
|
+
styles: [":host{position:relative;display:flex;align-items:center;flex:1;min-inline-size:0;align-self:stretch}.hy-select__trigger,.hy-select__native{flex:1;min-inline-size:0;align-self:stretch;display:flex;align-items:center;gap:var(--hy-space-2);padding:0;padding-inline-end:1.75rem;border:0;background:transparent;color:var(--hy-ink);font:inherit;text-align:start;cursor:pointer;appearance:none}.hy-select__trigger:focus-visible,.hy-select__native:focus-visible{outline:none}.hy-select__trigger:disabled,.hy-select__native:disabled{cursor:not-allowed}.hy-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hy-select__placeholder{color:var(--hy-ink-3)}.hy-select__chevron{--hy-icon-size: 1rem;transform-origin:center;position:absolute;inset-inline-end:0;color:var(--hy-ink-3);pointer-events:none;transition:rotate var(--hy-dur-quick) var(--hy-ease-out)}.hy-select__trigger[aria-expanded=true] .hy-select__chevron{rotate:180deg}[hidden]{display:none!important}.hy-select__group-label{padding:var(--hy-space-2);color:var(--hy-ink-2);font-size:.75rem}@media(prefers-reduced-motion:reduce){.hy-select__chevron{transition:none}}\n"],
|
|
215
284
|
dependencies: [
|
|
285
|
+
{
|
|
286
|
+
kind: "directive",
|
|
287
|
+
type: NgTemplateOutlet,
|
|
288
|
+
selector: "[ngTemplateOutlet]",
|
|
289
|
+
inputs: [
|
|
290
|
+
"ngTemplateOutletContext",
|
|
291
|
+
"ngTemplateOutlet",
|
|
292
|
+
"ngTemplateOutletInjector"
|
|
293
|
+
]
|
|
294
|
+
},
|
|
216
295
|
{
|
|
217
296
|
kind: "directive",
|
|
218
297
|
type: Combobox,
|
|
@@ -350,6 +429,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
350
429
|
args: [{
|
|
351
430
|
selector: "hy-select",
|
|
352
431
|
imports: [
|
|
432
|
+
NgTemplateOutlet,
|
|
353
433
|
Combobox,
|
|
354
434
|
ComboboxPopup,
|
|
355
435
|
ComboboxWidget,
|
|
@@ -362,10 +442,11 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
362
442
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
363
443
|
host: {
|
|
364
444
|
class: "hy-select",
|
|
365
|
-
"[attr.data-native]": "useNative() || null"
|
|
445
|
+
"[attr.data-native]": "useNative() || null",
|
|
446
|
+
"(focusout)": "scheduleMode()"
|
|
366
447
|
},
|
|
367
|
-
template: "
|
|
368
|
-
styles: [":host{position:relative;display:flex;align-items:center;flex:1;min-inline-size:0;align-self:stretch}.hy-select__trigger,.hy-select__native{flex:1;min-inline-size:0;align-self:stretch;display:flex;align-items:center;gap:var(--hy-space-2);padding:0;padding-inline-end:1.75rem;border:0;background:transparent;color:var(--hy-ink);font:inherit;text-align:start;cursor:pointer;appearance:none}.hy-select__trigger:focus-visible,.hy-select__native:focus-visible{outline:none}.hy-select__trigger:disabled,.hy-select__native:disabled{cursor:not-allowed}.hy-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hy-select__placeholder{color:var(--hy-ink-3)}.hy-select__chevron{position:absolute;inset-inline-end:0;color:var(--hy-ink-3);pointer-events:none;transition:rotate var(--hy-dur-
|
|
448
|
+
template: "<select\r\n class=\"hy-select__native\"\r\n [hidden]=\"!useNative()\"\r\n [id]=\"nativeId\"\r\n [disabled]=\"disabled() || !useNative()\"\r\n [required]=\"required()\"\r\n [name]=\"useNative() ? name() : undefined\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n (change)=\"pickNative($event)\"\r\n (blur)=\"touch.emit()\"\r\n>\r\n <option value=\"\" [disabled]=\"required()\" [selected]=\"!selectedOption()\">\r\n {{ placeholder() }}\r\n </option>\r\n @for (group of groups(); track group.key) {\r\n @if (group.key) {\r\n <optgroup [label]=\"group.label\">\r\n @for (item of group.options; track item.key) {\r\n <option\r\n [value]=\"item.key\"\r\n [selected]=\"item.option.value === value()\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n {{ item.option.label }}\r\n </option>\r\n }\r\n </optgroup>\r\n } @else {\r\n @for (item of group.options; track item.key) {\r\n <option\r\n [value]=\"item.key\"\r\n [selected]=\"item.option.value === value()\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n {{ item.option.label }}\r\n </option>\r\n }\r\n }\r\n }\r\n</select>\r\n<hy-icon [hidden]=\"!useNative()\" class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n<button\r\n #trigger\r\n type=\"button\"\r\n ngCombobox\r\n #combobox=\"ngCombobox\"\r\n cdkOverlayOrigin\r\n #origin=\"cdkOverlayOrigin\"\r\n class=\"hy-select__trigger\"\r\n [hidden]=\"useNative()\"\r\n [id]=\"triggerId\"\r\n [disabled]=\"disabled() || useNative()\"\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"setExpanded($event)\"\r\n [attr.aria-labelledby]=\"field ? field.labelId + ' ' + triggerId : null\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n [attr.aria-required]=\"required() || null\"\r\n (blur)=\"touch.emit()\"\r\n>\r\n <span class=\"hy-select__value\" [class.hy-select__placeholder]=\"!selectedOption()\">{{\r\n selectedOption()?.label ?? placeholder()\r\n }}</span>\r\n <hy-icon class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n</button>\r\n<ng-template ngComboboxPopup [combobox]=\"combobox\">\r\n <ng-template\r\n cdkConnectedOverlay\r\n [cdkConnectedOverlayOrigin]=\"origin\"\r\n [cdkConnectedOverlayOpen]=\"rendered() && !useNative()\"\r\n [cdkConnectedOverlayPositions]=\"positions\"\r\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\r\n cdkConnectedOverlayPanelClass=\"hy-select-overlay\"\r\n cdkConnectedOverlayTransformOriginOn=\".hy-select__panel\"\r\n (attach)=\"onAttach()\"\r\n (overlayOutsideClick)=\"expanded.set(false)\"\r\n >\r\n <!-- Focus remains on the combobox trigger while Aria manages the active option. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n ngComboboxWidget\r\n ngListbox\r\n #listbox=\"ngListbox\"\r\n class=\"hy-select__panel hy-glass\"\r\n data-material=\"frosted\"\r\n focusMode=\"activedescendant\"\r\n selectionMode=\"explicit\"\r\n [activeDescendant]=\"listbox.activeDescendant()\"\r\n [value]=\"listValue()\"\r\n (valueChange)=\"pick($event)\"\r\n (click)=\"onPanelClick($event)\"\r\n (keydown.enter)=\"close()\"\r\n (keydown.space)=\"close()\"\r\n >\r\n @for (group of groups(); track group.key) {\r\n <div role=\"group\" [attr.aria-label]=\"group.label || null\">\r\n @if (group.label) {\r\n <div class=\"hy-select__group-label\">{{ group.label }}</div>\r\n }\r\n @for (item of group.options; track item.key) {\r\n <div\r\n ngOption\r\n class=\"hy-select__option\"\r\n [value]=\"item.option.value\"\r\n [label]=\"item.option.label\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n @if (optionTemplate(); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"item.context\"\r\n />\r\n } @else {\r\n <span>{{ item.option.label }}</span>\r\n }\r\n <hy-icon class=\"hy-select__check\" name=\"check\" />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-template>\r\n",
|
|
449
|
+
styles: [":host{position:relative;display:flex;align-items:center;flex:1;min-inline-size:0;align-self:stretch}.hy-select__trigger,.hy-select__native{flex:1;min-inline-size:0;align-self:stretch;display:flex;align-items:center;gap:var(--hy-space-2);padding:0;padding-inline-end:1.75rem;border:0;background:transparent;color:var(--hy-ink);font:inherit;text-align:start;cursor:pointer;appearance:none}.hy-select__trigger:focus-visible,.hy-select__native:focus-visible{outline:none}.hy-select__trigger:disabled,.hy-select__native:disabled{cursor:not-allowed}.hy-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hy-select__placeholder{color:var(--hy-ink-3)}.hy-select__chevron{--hy-icon-size: 1rem;transform-origin:center;position:absolute;inset-inline-end:0;color:var(--hy-ink-3);pointer-events:none;transition:rotate var(--hy-dur-quick) var(--hy-ease-out)}.hy-select__trigger[aria-expanded=true] .hy-select__chevron{rotate:180deg}[hidden]{display:none!important}.hy-select__group-label{padding:var(--hy-space-2);color:var(--hy-ink-2);font-size:.75rem}@media(prefers-reduced-motion:reduce){.hy-select__chevron{transition:none}}\n"]
|
|
369
450
|
}]
|
|
370
451
|
}],
|
|
371
452
|
ctorParameters: () => [],
|
|
@@ -405,6 +486,22 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
405
486
|
required: false
|
|
406
487
|
}]
|
|
407
488
|
}],
|
|
489
|
+
name: [{
|
|
490
|
+
type: i0.Input,
|
|
491
|
+
args: [{
|
|
492
|
+
isSignal: true,
|
|
493
|
+
alias: "name",
|
|
494
|
+
required: false
|
|
495
|
+
}]
|
|
496
|
+
}],
|
|
497
|
+
optionTemplate: [{
|
|
498
|
+
type: i0.Input,
|
|
499
|
+
args: [{
|
|
500
|
+
isSignal: true,
|
|
501
|
+
alias: "optionTemplate",
|
|
502
|
+
required: false
|
|
503
|
+
}]
|
|
504
|
+
}],
|
|
408
505
|
disabled: [{
|
|
409
506
|
type: i0.Input,
|
|
410
507
|
args: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hyalo-angular-select.mjs","names":["HyPresence"],"sources":["../../../projects/hyalo/select/select.ts","../../../projects/hyalo/select/select.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n booleanAttribute,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n model,\r\n output,\r\n signal,\r\n untracked,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { Combobox, ComboboxPopup, ComboboxWidget } from '@angular/aria/combobox';\r\nimport { Listbox, Option } from '@angular/aria/listbox';\r\nimport { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';\r\nimport type { FormValueControl } from '@angular/forms/signals';\r\nimport { HyFidelity, injectId } from '@hyalo/angular';\r\nimport { HyIcon } from '@hyalo/angular/icon';\r\nimport { HY_FIELD, type HyFieldControl } from '@hyalo/angular/field';\r\nimport { hyDropdownPositions, ɵHyPresence as HyPresence } from '@hyalo/angular/overlay';\r\n\r\n/** One choice in a select. */\r\nexport interface HySelectOption<T> {\r\n readonly value: T;\r\n readonly label: string;\r\n readonly disabled?: boolean;\r\n}\r\n\r\n/**\r\n * A single-choice select with a glass dropdown, built on Angular Aria's\r\n * combobox and listbox patterns.\r\n *\r\n * ```html\r\n * <hy-field label=\"Strap\">\r\n * <hy-select [options]=\"straps\" [formField]=\"form.strap\" placeholder=\"Choose a strap\" />\r\n * </hy-field>\r\n * ```\r\n *\r\n * Focus stays on the trigger while the list is open, and options are\r\n * announced through `aria-activedescendant`. Arrow keys move, Enter or\r\n * Space picks, Escape closes, and typing jumps to a matching option.\r\n *\r\n * On the low fidelity tier, or with `native`, it renders a real `<select>`\r\n * instead. That gives the platform picker on phones and costs nothing.\r\n */\r\n@Component({\r\n selector: 'hy-select',\r\n imports: [\r\n Combobox,\r\n ComboboxPopup,\r\n ComboboxWidget,\r\n Listbox,\r\n Option,\r\n CdkConnectedOverlay,\r\n CdkOverlayOrigin,\r\n HyIcon,\r\n ],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'hy-select',\r\n '[attr.data-native]': 'useNative() || null',\r\n },\r\n templateUrl: './select.html',\r\n styleUrl: './select.css',\r\n})\r\nexport class HySelect<T> implements FormValueControl<T | undefined>, HyFieldControl {\r\n private readonly fidelity = inject(HyFidelity);\r\n protected readonly field = inject(HY_FIELD, { optional: true });\r\n private readonly trigger = viewChild<ElementRef<HTMLElement>>('trigger');\r\n private readonly overlay = viewChild(CdkConnectedOverlay);\r\n private readonly presence = new HyPresence();\r\n\r\n /** The choices. */\r\n readonly options = input.required<readonly HySelectOption<T>[]>();\r\n /** Selected value. Two-way bindable and works with `[formField]`. */\r\n readonly value = model<T | undefined>(undefined);\r\n /** Text shown while nothing is selected. */\r\n readonly placeholder = input('Select');\r\n /** Disables the select. Set automatically by Signal Forms. */\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n /** Marks the field as required. Set automatically by Signal Forms. */\r\n readonly required = input(false, { transform: booleanAttribute });\r\n /** Set by Signal Forms. */\r\n readonly invalid = input(false, { transform: booleanAttribute });\r\n /** Set by Signal Forms. Only the first message is shown. */\r\n readonly errors = input<readonly { readonly kind: string; readonly message?: string }[]>([]);\r\n /** Set by Signal Forms. Errors show only after the field is touched. */\r\n readonly touched = input(false, { transform: booleanAttribute });\r\n /** Always render a native `<select>`. */\r\n readonly native = input(false, { transform: booleanAttribute });\r\n /** Emits when the control loses focus, so forms can mark it touched. */\r\n readonly touch = output<void>();\r\n\r\n readonly labelable = true;\r\n readonly id = signal(injectId('select')).asReadonly();\r\n readonly errorMessage = computed(() => {\r\n const first = this.errors()[0];\r\n return first ? (first.message ?? first.kind) : undefined;\r\n });\r\n\r\n protected readonly expanded = signal(false);\r\n /** Stays true while the panel fades out after `expanded` turns false. */\r\n protected readonly rendered = signal(false);\r\n protected readonly positions = hyDropdownPositions();\r\n protected readonly panelWidth = signal(0);\r\n protected readonly useNative = computed(() => this.native() || this.fidelity.tier() === 'low');\r\n protected readonly selectedOption = computed(() =>\r\n this.options().find((o) => o.value === this.value()),\r\n );\r\n protected readonly listValue = computed(() => {\r\n const v = this.value();\r\n return v === undefined ? [] : [v];\r\n });\r\n protected readonly showsError = computed(() =>\r\n this.field ? this.field.errorShown() : this.invalid() && this.touched(),\r\n );\r\n\r\n constructor() {\r\n effect(() => {\r\n const open = this.expanded();\r\n untracked(() => {\r\n const panel = this.panelElement();\r\n if (open) {\r\n // Reopened while fading out: turn the exit around.\r\n if (panel && this.presence.leaving) this.presence.enter(panel);\r\n this.rendered.set(true);\r\n } else if (panel) {\r\n this.presence.leave(panel, () => this.rendered.set(false));\r\n } else {\r\n this.rendered.set(false);\r\n }\r\n });\r\n });\r\n this.field?.register({\r\n id: this.id,\r\n invalid: computed(() => this.invalid() && this.touched()),\r\n errorMessage: this.errorMessage,\r\n required: this.required,\r\n disabled: this.disabled,\r\n labelable: true,\r\n });\r\n }\r\n\r\n protected setExpanded(open: boolean): void {\r\n if (open) this.panelWidth.set(this.trigger()?.nativeElement.offsetWidth ?? 0);\r\n this.expanded.set(open);\r\n }\r\n\r\n /** Runs when the overlay attaches a fresh panel. */\r\n protected onAttach(): void {\r\n const panel = this.panelElement();\r\n if (panel) this.presence.enter(panel);\r\n }\r\n\r\n private panelElement(): HTMLElement | null {\r\n return (\r\n this.overlay()?.overlayRef?.overlayElement.querySelector<HTMLElement>('.hy-select__panel') ??\r\n null\r\n );\r\n }\r\n\r\n protected pick(values: readonly T[]): void {\r\n const next = values[values.length - 1];\r\n if (next === undefined || next === this.value()) return;\r\n this.value.set(next);\r\n this.close();\r\n }\r\n\r\n /** Closes after a click on an option, including the one already selected. */\r\n protected onPanelClick(event: MouseEvent): void {\r\n const option = (event.target as Element | null)?.closest('[role=\"option\"]');\r\n if (option && option.getAttribute('aria-disabled') !== 'true') this.close();\r\n }\r\n\r\n protected close(): void {\r\n this.expanded.set(false);\r\n this.trigger()?.nativeElement.focus();\r\n }\r\n\r\n protected pickNative(event: Event): void {\r\n const index = Number((event.target as HTMLSelectElement).value);\r\n const option = this.options()[index];\r\n if (option) this.value.set(option.value);\r\n }\r\n\r\n protected indexOf(value: T | undefined): number {\r\n return this.options().findIndex((o) => o.value === value);\r\n }\r\n}\r\n","@if (useNative()) {\r\n <select\r\n class=\"hy-select__native\"\r\n [id]=\"id()\"\r\n [disabled]=\"disabled()\"\r\n [required]=\"required()\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n (change)=\"pickNative($event)\"\r\n (blur)=\"touch.emit()\"\r\n >\r\n @if (!selectedOption()) {\r\n <option value=\"\" disabled selected>{{ placeholder() }}</option>\r\n }\r\n @for (option of options(); track $index) {\r\n <option [value]=\"$index\" [selected]=\"option.value === value()\" [disabled]=\"!!option.disabled\">\r\n {{ option.label }}\r\n </option>\r\n }\r\n </select>\r\n <hy-icon class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n} @else {\r\n <button\r\n #trigger\r\n type=\"button\"\r\n ngCombobox\r\n #combobox=\"ngCombobox\"\r\n cdkOverlayOrigin\r\n #origin=\"cdkOverlayOrigin\"\r\n class=\"hy-select__trigger\"\r\n [id]=\"id()\"\r\n [disabled]=\"disabled()\"\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"setExpanded($event)\"\r\n [attr.aria-labelledby]=\"field ? field.labelId + ' ' + id() : null\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n [attr.aria-required]=\"required() || null\"\r\n (blur)=\"touch.emit()\"\r\n >\r\n <span class=\"hy-select__value\" [class.hy-select__placeholder]=\"!selectedOption()\">\r\n {{ selectedOption()?.label ?? placeholder() }}\r\n </span>\r\n <hy-icon class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n </button>\r\n\r\n <ng-template ngComboboxPopup [combobox]=\"combobox\">\r\n <ng-template\r\n cdkConnectedOverlay\r\n [cdkConnectedOverlayOrigin]=\"origin\"\r\n [cdkConnectedOverlayOpen]=\"rendered()\"\r\n [cdkConnectedOverlayPositions]=\"positions\"\r\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\r\n cdkConnectedOverlayPanelClass=\"hy-select-overlay\"\r\n cdkConnectedOverlayTransformOriginOn=\".hy-select__panel\"\r\n (attach)=\"onAttach()\"\r\n (overlayOutsideClick)=\"expanded.set(false)\"\r\n >\r\n <!-- Focus stays on the trigger; Aria relays keys here and manages tabindex. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n ngComboboxWidget\r\n ngListbox\r\n #listbox=\"ngListbox\"\r\n class=\"hy-select__panel hy-glass\"\r\n data-material=\"frosted\"\r\n focusMode=\"activedescendant\"\r\n selectionMode=\"explicit\"\r\n [activeDescendant]=\"listbox.activeDescendant()\"\r\n [value]=\"listValue()\"\r\n (valueChange)=\"pick($event)\"\r\n (click)=\"onPanelClick($event)\"\r\n (keydown.enter)=\"close()\"\r\n (keydown.space)=\"close()\"\r\n >\r\n @for (option of options(); track $index) {\r\n <div\r\n ngOption\r\n class=\"hy-select__option\"\r\n [value]=\"option.value\"\r\n [label]=\"option.label\"\r\n [disabled]=\"!!option.disabled\"\r\n >\r\n <span>{{ option.label }}</span>\r\n <hy-icon class=\"hy-select__check\" name=\"check\" />\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n </ng-template>\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hyalo-angular-select.mjs","names":["HyPresence"],"sources":["../../../projects/hyalo/select/select.ts","../../../projects/hyalo/select/select.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DOCUMENT,\r\n DestroyRef,\r\n TemplateRef,\r\n afterNextRender,\r\n ElementRef,\r\n booleanAttribute,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n model,\r\n output,\r\n signal,\r\n untracked,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { Combobox, ComboboxPopup, ComboboxWidget } from '@angular/aria/combobox';\r\nimport { Listbox, Option } from '@angular/aria/listbox';\r\nimport { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';\r\nimport type { FormValueControl } from '@angular/forms/signals';\r\nimport { HyFidelity, injectId } from '@hyalo/angular/core';\r\nimport { HyIcon } from '@hyalo/angular/icon';\r\nimport { HY_FIELD, type HyFieldControl } from '@hyalo/angular/field';\r\nimport { hyDropdownPositions, ɵHyPresence as HyPresence } from '@hyalo/angular/overlay';\r\n\r\n/** One choice in a select. */\r\nexport interface HySelectOption<T> {\r\n readonly key?: string | number;\r\n readonly group?: { readonly key: string; readonly label: string; readonly disabled?: boolean };\r\n readonly value: T;\r\n readonly label: string;\r\n readonly disabled?: boolean;\r\n}\r\n\r\nexport interface HySelectOptionContext<T> {\r\n readonly $implicit: HySelectOption<T>;\r\n}\r\n\r\n/**\r\n * A single-choice select with a glass dropdown, built on Angular Aria's\r\n * combobox and listbox patterns.\r\n *\r\n * ```html\r\n * <hy-field label=\"Strap\">\r\n * <hy-select [options]=\"straps\" [formField]=\"form.strap\" placeholder=\"Choose a strap\" />\r\n * </hy-field>\r\n * ```\r\n *\r\n * Focus stays on the trigger while the list is open, and options are\r\n * announced through `aria-activedescendant`. Arrow keys move, Enter or\r\n * Space picks, Escape closes, and typing jumps to a matching option.\r\n *\r\n * On the low fidelity tier, or with `native`, it renders a real `<select>`\r\n * instead. That gives the platform picker on phones and costs nothing.\r\n */\r\n@Component({\r\n selector: 'hy-select',\r\n imports: [\r\n NgTemplateOutlet,\r\n Combobox,\r\n ComboboxPopup,\r\n ComboboxWidget,\r\n Listbox,\r\n Option,\r\n CdkConnectedOverlay,\r\n CdkOverlayOrigin,\r\n HyIcon,\r\n ],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'hy-select',\r\n '[attr.data-native]': 'useNative() || null',\r\n '(focusout)': 'scheduleMode()',\r\n },\r\n templateUrl: './select.html',\r\n styleUrl: './select.css',\r\n})\r\nexport class HySelect<T> implements FormValueControl<T | undefined>, HyFieldControl {\r\n private readonly fidelity = inject(HyFidelity);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly document = inject(DOCUMENT);\r\n private readonly destroy = inject(DestroyRef);\r\n private readonly ready = signal(false);\r\n protected readonly field = inject(HY_FIELD, { optional: true });\r\n private readonly trigger = viewChild<ElementRef<HTMLElement>>('trigger');\r\n private readonly overlay = viewChild(CdkConnectedOverlay);\r\n private readonly presence = new HyPresence();\r\n\r\n /** The choices. */\r\n readonly options = input.required<readonly HySelectOption<T>[]>();\r\n /** Selected value. Two-way bindable and works with `[formField]`. */\r\n readonly value = model<T | undefined>(undefined);\r\n /** Text shown while nothing is selected. */\r\n readonly placeholder = input('Select');\r\n readonly name = input('');\r\n readonly optionTemplate = input<TemplateRef<HySelectOptionContext<T>>>();\r\n /** Disables the select. Set automatically by Signal Forms. */\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n /** Marks the field as required. Set automatically by Signal Forms. */\r\n readonly required = input(false, { transform: booleanAttribute });\r\n /** Set by Signal Forms. */\r\n readonly invalid = input(false, { transform: booleanAttribute });\r\n /** Set by Signal Forms. Only the first message is shown. */\r\n readonly errors = input<readonly { readonly kind: string; readonly message?: string }[]>([]);\r\n /** Set by Signal Forms. Errors show only after the field is touched. */\r\n readonly touched = input(false, { transform: booleanAttribute });\r\n /** Always render a native `<select>`. */\r\n readonly native = input(false, { transform: booleanAttribute });\r\n /** Emits when the control loses focus, so forms can mark it touched. */\r\n readonly touch = output<void>();\r\n\r\n readonly labelable = true;\r\n protected readonly nativeId = injectId('select');\r\n protected readonly triggerId = this.nativeId + '-trigger';\r\n readonly id = computed(() => (this.useNative() ? this.nativeId : this.triggerId));\r\n readonly errorMessage = computed(() => {\r\n const first = this.errors()[0];\r\n return first ? (first.message ?? first.kind) : undefined;\r\n });\r\n\r\n protected readonly expanded = signal(false);\r\n /** Stays true while the panel fades out after `expanded` turns false. */\r\n protected readonly rendered = signal(false);\r\n protected readonly positions = hyDropdownPositions();\r\n protected readonly panelWidth = signal(0);\r\n protected readonly useNative = signal(true);\r\n protected readonly keyedOptions = computed(() => {\r\n const keys = new Set<string>();\r\n return this.options().map((option) => {\r\n const value = option.value;\r\n if (option.key === undefined && (typeof value === 'object' || typeof value === 'function'))\r\n throw new Error('HySelect: object values require a stable option key');\r\n const key =\r\n option.key === undefined\r\n ? `${typeof value}:${String(value)}`\r\n : `${typeof option.key}:${option.key}`;\r\n if (keys.has(key)) throw new Error('HySelect: duplicate option key ' + key);\r\n keys.add(key);\r\n return {\r\n option,\r\n key,\r\n disabled: !!(option.disabled || option.group?.disabled),\r\n context: { $implicit: option },\r\n };\r\n });\r\n });\r\n protected readonly groups = computed(() => {\r\n const groups = new Map<\r\n string,\r\n {\r\n key: string;\r\n label: string;\r\n options: {\r\n option: HySelectOption<T>;\r\n key: string;\r\n disabled: boolean;\r\n context: HySelectOptionContext<T>;\r\n }[];\r\n }\r\n >();\r\n for (const option of this.keyedOptions()) {\r\n const key = option.option.group?.key ?? '';\r\n const group = groups.get(key) ?? {\r\n key,\r\n label: option.option.group?.label ?? '',\r\n options: [],\r\n };\r\n group.options.push(option);\r\n groups.set(key, group);\r\n }\r\n return [...groups.values()];\r\n });\r\n protected readonly selectedOption = computed(() =>\r\n this.options().find((o) => o.value === this.value()),\r\n );\r\n protected readonly listValue = computed(() => {\r\n const v = this.value();\r\n return v === undefined ? [] : [v];\r\n });\r\n protected readonly showsError = computed(() =>\r\n this.field ? this.field.errorShown() : this.invalid() && this.touched(),\r\n );\r\n\r\n constructor() {\r\n afterNextRender(() => this.ready.set(true));\r\n effect(() => {\r\n this.ready();\r\n this.native();\r\n this.fidelity.tier();\r\n this.scheduleMode();\r\n });\r\n effect(() => {\r\n const open = this.expanded();\r\n untracked(() => {\r\n const panel = this.panelElement();\r\n if (open) {\r\n // Reopened while fading out: turn the exit around.\r\n if (panel && this.presence.leaving) this.presence.enter(panel);\r\n this.rendered.set(true);\r\n } else if (panel) {\r\n this.presence.leave(panel, () => this.rendered.set(false));\r\n } else {\r\n this.rendered.set(false);\r\n }\r\n });\r\n });\r\n this.field?.register({\r\n id: this.id,\r\n invalid: computed(() => this.invalid() && this.touched()),\r\n errorMessage: this.errorMessage,\r\n required: this.required,\r\n disabled: this.disabled,\r\n labelable: true,\r\n });\r\n }\r\n\r\n protected setExpanded(open: boolean): void {\r\n if (open) this.panelWidth.set(this.trigger()?.nativeElement.offsetWidth ?? 0);\r\n this.expanded.set(open);\r\n }\r\n\r\n /** Runs when the overlay attaches a fresh panel. */\r\n protected onAttach(): void {\r\n const panel = this.panelElement();\r\n if (panel) this.presence.enter(panel);\r\n }\r\n\r\n private panelElement(): HTMLElement | null {\r\n return (\r\n this.overlay()?.overlayRef?.overlayElement.querySelector<HTMLElement>('.hy-select__panel') ??\r\n null\r\n );\r\n }\r\n\r\n protected pick(values: readonly T[]): void {\r\n const next = values[values.length - 1];\r\n if (next === undefined || next === this.value()) return;\r\n this.value.set(next);\r\n this.close();\r\n }\r\n\r\n /** Closes after a click on an option, including the one already selected. */\r\n protected onPanelClick(event: MouseEvent): void {\r\n const option = (event.target as Element | null)?.closest('[role=\"option\"]');\r\n if (option && option.getAttribute('aria-disabled') !== 'true') this.close();\r\n }\r\n\r\n protected close(): void {\r\n this.expanded.set(false);\r\n this.trigger()?.nativeElement.focus();\r\n }\r\n\r\n protected scheduleMode(): void {\r\n queueMicrotask(() => {\r\n if (this.destroy.destroyed || !this.ready()) return;\r\n if (this.expanded() || this.host.contains(this.document.activeElement)) return;\r\n this.useNative.set(this.native() || this.fidelity.tier() === 'low');\r\n });\r\n }\r\n\r\n protected pickNative(event: Event): void {\r\n const key = (event.target as HTMLSelectElement).value;\r\n if (!key && !this.required()) {\r\n this.value.set(undefined);\r\n return;\r\n }\r\n const choice = this.keyedOptions().find((item) => item.key === key);\r\n if (choice && !choice.disabled) this.value.set(choice.option.value);\r\n }\r\n}\r\n","<select\r\n class=\"hy-select__native\"\r\n [hidden]=\"!useNative()\"\r\n [id]=\"nativeId\"\r\n [disabled]=\"disabled() || !useNative()\"\r\n [required]=\"required()\"\r\n [name]=\"useNative() ? name() : undefined\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n (change)=\"pickNative($event)\"\r\n (blur)=\"touch.emit()\"\r\n>\r\n <option value=\"\" [disabled]=\"required()\" [selected]=\"!selectedOption()\">\r\n {{ placeholder() }}\r\n </option>\r\n @for (group of groups(); track group.key) {\r\n @if (group.key) {\r\n <optgroup [label]=\"group.label\">\r\n @for (item of group.options; track item.key) {\r\n <option\r\n [value]=\"item.key\"\r\n [selected]=\"item.option.value === value()\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n {{ item.option.label }}\r\n </option>\r\n }\r\n </optgroup>\r\n } @else {\r\n @for (item of group.options; track item.key) {\r\n <option\r\n [value]=\"item.key\"\r\n [selected]=\"item.option.value === value()\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n {{ item.option.label }}\r\n </option>\r\n }\r\n }\r\n }\r\n</select>\r\n<hy-icon [hidden]=\"!useNative()\" class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n<button\r\n #trigger\r\n type=\"button\"\r\n ngCombobox\r\n #combobox=\"ngCombobox\"\r\n cdkOverlayOrigin\r\n #origin=\"cdkOverlayOrigin\"\r\n class=\"hy-select__trigger\"\r\n [hidden]=\"useNative()\"\r\n [id]=\"triggerId\"\r\n [disabled]=\"disabled() || useNative()\"\r\n [expanded]=\"expanded()\"\r\n (expandedChange)=\"setExpanded($event)\"\r\n [attr.aria-labelledby]=\"field ? field.labelId + ' ' + triggerId : null\"\r\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\r\n [attr.aria-invalid]=\"showsError() || null\"\r\n [attr.aria-required]=\"required() || null\"\r\n (blur)=\"touch.emit()\"\r\n>\r\n <span class=\"hy-select__value\" [class.hy-select__placeholder]=\"!selectedOption()\">{{\r\n selectedOption()?.label ?? placeholder()\r\n }}</span>\r\n <hy-icon class=\"hy-select__chevron\" name=\"chevron-down\" />\r\n</button>\r\n<ng-template ngComboboxPopup [combobox]=\"combobox\">\r\n <ng-template\r\n cdkConnectedOverlay\r\n [cdkConnectedOverlayOrigin]=\"origin\"\r\n [cdkConnectedOverlayOpen]=\"rendered() && !useNative()\"\r\n [cdkConnectedOverlayPositions]=\"positions\"\r\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\r\n cdkConnectedOverlayPanelClass=\"hy-select-overlay\"\r\n cdkConnectedOverlayTransformOriginOn=\".hy-select__panel\"\r\n (attach)=\"onAttach()\"\r\n (overlayOutsideClick)=\"expanded.set(false)\"\r\n >\r\n <!-- Focus remains on the combobox trigger while Aria manages the active option. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n ngComboboxWidget\r\n ngListbox\r\n #listbox=\"ngListbox\"\r\n class=\"hy-select__panel hy-glass\"\r\n data-material=\"frosted\"\r\n focusMode=\"activedescendant\"\r\n selectionMode=\"explicit\"\r\n [activeDescendant]=\"listbox.activeDescendant()\"\r\n [value]=\"listValue()\"\r\n (valueChange)=\"pick($event)\"\r\n (click)=\"onPanelClick($event)\"\r\n (keydown.enter)=\"close()\"\r\n (keydown.space)=\"close()\"\r\n >\r\n @for (group of groups(); track group.key) {\r\n <div role=\"group\" [attr.aria-label]=\"group.label || null\">\r\n @if (group.label) {\r\n <div class=\"hy-select__group-label\">{{ group.label }}</div>\r\n }\r\n @for (item of group.options; track item.key) {\r\n <div\r\n ngOption\r\n class=\"hy-select__option\"\r\n [value]=\"item.option.value\"\r\n [label]=\"item.option.label\"\r\n [disabled]=\"item.disabled\"\r\n >\r\n @if (optionTemplate(); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"item.context\"\r\n />\r\n } @else {\r\n <span>{{ item.option.label }}</span>\r\n }\r\n <hy-icon class=\"hy-select__check\" name=\"check\" />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-template>\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, booleanAttribute, input, model } from "@angular/core";
|
|
3
|
+
import { HyIcon } from "@hyalo/angular/icon";
|
|
4
|
+
var HySidebar = class HySidebar {
|
|
5
|
+
collapsed = model(false, ...ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []);
|
|
6
|
+
toggle = (value) => !value;
|
|
7
|
+
label = input("Main navigation", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
8
|
+
collapseLabel = input("Collapse navigation", ...ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []);
|
|
9
|
+
expandLabel = input("Expand navigation", ...ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []);
|
|
10
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
11
|
+
minVersion: "12.0.0",
|
|
12
|
+
version: "22.2.3",
|
|
13
|
+
ngImport: i0,
|
|
14
|
+
type: HySidebar,
|
|
15
|
+
deps: [],
|
|
16
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
17
|
+
});
|
|
18
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
19
|
+
minVersion: "17.1.0",
|
|
20
|
+
version: "22.2.3",
|
|
21
|
+
type: HySidebar,
|
|
22
|
+
isStandalone: true,
|
|
23
|
+
selector: "hy-sidebar",
|
|
24
|
+
inputs: {
|
|
25
|
+
collapsed: {
|
|
26
|
+
classPropertyName: "collapsed",
|
|
27
|
+
publicName: "collapsed",
|
|
28
|
+
isSignal: true,
|
|
29
|
+
isRequired: false,
|
|
30
|
+
transformFunction: null
|
|
31
|
+
},
|
|
32
|
+
label: {
|
|
33
|
+
classPropertyName: "label",
|
|
34
|
+
publicName: "label",
|
|
35
|
+
isSignal: true,
|
|
36
|
+
isRequired: false,
|
|
37
|
+
transformFunction: null
|
|
38
|
+
},
|
|
39
|
+
collapseLabel: {
|
|
40
|
+
classPropertyName: "collapseLabel",
|
|
41
|
+
publicName: "collapseLabel",
|
|
42
|
+
isSignal: true,
|
|
43
|
+
isRequired: false,
|
|
44
|
+
transformFunction: null
|
|
45
|
+
},
|
|
46
|
+
expandLabel: {
|
|
47
|
+
classPropertyName: "expandLabel",
|
|
48
|
+
publicName: "expandLabel",
|
|
49
|
+
isSignal: true,
|
|
50
|
+
isRequired: false,
|
|
51
|
+
transformFunction: null
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
outputs: { collapsed: "collapsedChange" },
|
|
55
|
+
host: { properties: {
|
|
56
|
+
"attr.data-collapsed": "collapsed()",
|
|
57
|
+
"style.--hy-sidebar-label-display": "collapsed()?\"none\":null",
|
|
58
|
+
"style.--hy-sidebar-item-justify": "collapsed()?\"center\":null"
|
|
59
|
+
} },
|
|
60
|
+
ngImport: i0,
|
|
61
|
+
template: "<header>\n <div class=\"brand\"><ng-content select=\"[hySidebarBrand]\" /></div>\n <button\n type=\"button\"\n [attr.aria-label]=\"collapsed() ? expandLabel() : collapseLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"collapsed.update(toggle)\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3\" />\n <path d=\"M9 4v16\" />\n </svg>\n </button>\n</header>\n<nav [attr.aria-label]=\"label()\"><ng-content /></nav>\n<footer><ng-content select=\"[hySidebarFooter]\" /></footer>\n",
|
|
62
|
+
styles: [":host{display:flex;flex-direction:column;flex:none;gap:1.5rem;inline-size:var(--hy-sidebar-width, 16rem);max-inline-size:100%;min-inline-size:0;padding:.75rem;border:1px solid var(--hy-line);border-radius:var(--hy-radius-m);background:var(--hy-surface-2);box-sizing:border-box}:host([data-collapsed=\"true\"]){inline-size:4.5rem}header{display:flex;align-items:center;justify-content:space-between;gap:.5rem;min-block-size:44px}.brand{display:var(--hy-sidebar-label-display, block);min-inline-size:0;padding-inline-start:.375rem}button{display:grid;place-items:center;flex:none;inline-size:44px;block-size:44px;padding:0;background:transparent;color:var(--hy-ink-2);border:1px solid transparent;border-radius:var(--hy-radius-s);cursor:pointer;transition:background-color .12s ease,color .12s ease}button svg{transition:transform var(--hy-dur-quick) var(--hy-ease-out)}:host([data-collapsed=\"true\"]) button svg{transform:rotateY(180deg)}:host-context([dir=\"rtl\"]) button svg{scale:-1 1}@media(hover:hover)and (pointer:fine){button:hover{background:var(--hy-surface-3);color:var(--hy-ink)}}button:active{background:var(--hy-surface-4)}nav{display:grid;align-content:start;gap:.375rem}footer{margin-block-start:auto;display:var(--hy-sidebar-label-display, block);padding-block-start:1rem;border-block-start:1px solid var(--hy-line)}footer:empty{display:none}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:2px}@media(prefers-reduced-motion:reduce){button svg{transition:none}}:host-context([data-hy-motion=\"reduced\"]) button svg{transition:none}\n"],
|
|
63
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
67
|
+
minVersion: "12.0.0",
|
|
68
|
+
version: "22.2.3",
|
|
69
|
+
ngImport: i0,
|
|
70
|
+
type: HySidebar,
|
|
71
|
+
decorators: [{
|
|
72
|
+
type: Component,
|
|
73
|
+
args: [{
|
|
74
|
+
selector: "hy-sidebar",
|
|
75
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
76
|
+
host: {
|
|
77
|
+
"[attr.data-collapsed]": "collapsed()",
|
|
78
|
+
"[style.--hy-sidebar-label-display]": "collapsed()?\"none\":null",
|
|
79
|
+
"[style.--hy-sidebar-item-justify]": "collapsed()?\"center\":null"
|
|
80
|
+
},
|
|
81
|
+
template: "<header>\n <div class=\"brand\"><ng-content select=\"[hySidebarBrand]\" /></div>\n <button\n type=\"button\"\n [attr.aria-label]=\"collapsed() ? expandLabel() : collapseLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"collapsed.update(toggle)\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3\" />\n <path d=\"M9 4v16\" />\n </svg>\n </button>\n</header>\n<nav [attr.aria-label]=\"label()\"><ng-content /></nav>\n<footer><ng-content select=\"[hySidebarFooter]\" /></footer>\n",
|
|
82
|
+
styles: [":host{display:flex;flex-direction:column;flex:none;gap:1.5rem;inline-size:var(--hy-sidebar-width, 16rem);max-inline-size:100%;min-inline-size:0;padding:.75rem;border:1px solid var(--hy-line);border-radius:var(--hy-radius-m);background:var(--hy-surface-2);box-sizing:border-box}:host([data-collapsed=\"true\"]){inline-size:4.5rem}header{display:flex;align-items:center;justify-content:space-between;gap:.5rem;min-block-size:44px}.brand{display:var(--hy-sidebar-label-display, block);min-inline-size:0;padding-inline-start:.375rem}button{display:grid;place-items:center;flex:none;inline-size:44px;block-size:44px;padding:0;background:transparent;color:var(--hy-ink-2);border:1px solid transparent;border-radius:var(--hy-radius-s);cursor:pointer;transition:background-color .12s ease,color .12s ease}button svg{transition:transform var(--hy-dur-quick) var(--hy-ease-out)}:host([data-collapsed=\"true\"]) button svg{transform:rotateY(180deg)}:host-context([dir=\"rtl\"]) button svg{scale:-1 1}@media(hover:hover)and (pointer:fine){button:hover{background:var(--hy-surface-3);color:var(--hy-ink)}}button:active{background:var(--hy-surface-4)}nav{display:grid;align-content:start;gap:.375rem}footer{margin-block-start:auto;display:var(--hy-sidebar-label-display, block);padding-block-start:1rem;border-block-start:1px solid var(--hy-line)}footer:empty{display:none}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:2px}@media(prefers-reduced-motion:reduce){button svg{transition:none}}:host-context([data-hy-motion=\"reduced\"]) button svg{transition:none}\n"]
|
|
83
|
+
}]
|
|
84
|
+
}],
|
|
85
|
+
propDecorators: {
|
|
86
|
+
collapsed: [{
|
|
87
|
+
type: i0.Input,
|
|
88
|
+
args: [{
|
|
89
|
+
isSignal: true,
|
|
90
|
+
alias: "collapsed",
|
|
91
|
+
required: false
|
|
92
|
+
}]
|
|
93
|
+
}, {
|
|
94
|
+
type: i0.Output,
|
|
95
|
+
args: ["collapsedChange"]
|
|
96
|
+
}],
|
|
97
|
+
label: [{
|
|
98
|
+
type: i0.Input,
|
|
99
|
+
args: [{
|
|
100
|
+
isSignal: true,
|
|
101
|
+
alias: "label",
|
|
102
|
+
required: false
|
|
103
|
+
}]
|
|
104
|
+
}],
|
|
105
|
+
collapseLabel: [{
|
|
106
|
+
type: i0.Input,
|
|
107
|
+
args: [{
|
|
108
|
+
isSignal: true,
|
|
109
|
+
alias: "collapseLabel",
|
|
110
|
+
required: false
|
|
111
|
+
}]
|
|
112
|
+
}],
|
|
113
|
+
expandLabel: [{
|
|
114
|
+
type: i0.Input,
|
|
115
|
+
args: [{
|
|
116
|
+
isSignal: true,
|
|
117
|
+
alias: "expandLabel",
|
|
118
|
+
required: false
|
|
119
|
+
}]
|
|
120
|
+
}]
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
var HySidebarItem = class HySidebarItem {
|
|
124
|
+
label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
125
|
+
icon = input.required(...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
|
|
126
|
+
active = input(false, {
|
|
127
|
+
...ngDevMode ? { debugName: "active" } : /* istanbul ignore next */ {},
|
|
128
|
+
transform: booleanAttribute
|
|
129
|
+
});
|
|
130
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
131
|
+
minVersion: "12.0.0",
|
|
132
|
+
version: "22.2.3",
|
|
133
|
+
ngImport: i0,
|
|
134
|
+
type: HySidebarItem,
|
|
135
|
+
deps: [],
|
|
136
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
137
|
+
});
|
|
138
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
139
|
+
minVersion: "17.1.0",
|
|
140
|
+
version: "22.2.3",
|
|
141
|
+
type: HySidebarItem,
|
|
142
|
+
isStandalone: true,
|
|
143
|
+
selector: "a[hySidebarItem]",
|
|
144
|
+
inputs: {
|
|
145
|
+
label: {
|
|
146
|
+
classPropertyName: "label",
|
|
147
|
+
publicName: "label",
|
|
148
|
+
isSignal: true,
|
|
149
|
+
isRequired: true,
|
|
150
|
+
transformFunction: null
|
|
151
|
+
},
|
|
152
|
+
icon: {
|
|
153
|
+
classPropertyName: "icon",
|
|
154
|
+
publicName: "icon",
|
|
155
|
+
isSignal: true,
|
|
156
|
+
isRequired: true,
|
|
157
|
+
transformFunction: null
|
|
158
|
+
},
|
|
159
|
+
active: {
|
|
160
|
+
classPropertyName: "active",
|
|
161
|
+
publicName: "active",
|
|
162
|
+
isSignal: true,
|
|
163
|
+
isRequired: false,
|
|
164
|
+
transformFunction: null
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
host: { properties: {
|
|
168
|
+
"attr.aria-label": "label()",
|
|
169
|
+
"attr.title": "label()",
|
|
170
|
+
"attr.aria-current": "active()?\"page\":null"
|
|
171
|
+
} },
|
|
172
|
+
ngImport: i0,
|
|
173
|
+
template: "<hy-icon [name]=\"icon()\" /><span class=\"label\">{{label()}}</span><ng-content />",
|
|
174
|
+
isInline: true,
|
|
175
|
+
styles: [":host{display:flex;align-items:center;justify-content:var(--hy-sidebar-item-justify, start);gap:.75rem;min-block-size:44px;min-inline-size:0;padding:.625rem .75rem;border:1px solid transparent;border-radius:var(--hy-radius-s);color:var(--hy-ink-2);text-decoration:none;font-size:.875rem;font-weight:500;line-height:1.4;box-sizing:border-box;transition:background-color .12s ease,color .12s ease}.label{display:var(--hy-sidebar-label-display, inline);min-inline-size:0;overflow-wrap:anywhere}@media(hover:hover)and (pointer:fine){:host(:hover){background:var(--hy-surface-3);color:var(--hy-ink)}}:host(:active){background:var(--hy-surface-4)}:host([aria-current=\"page\"]){background:var(--hy-primary-wash);color:var(--hy-primary);font-weight:600}:host(:focus-visible){outline:2px solid var(--hy-primary);outline-offset:2px}hy-icon{flex:none;inline-size:1.125rem;block-size:1.125rem}\n"],
|
|
176
|
+
dependencies: [{
|
|
177
|
+
kind: "component",
|
|
178
|
+
type: HyIcon,
|
|
179
|
+
selector: "hy-icon",
|
|
180
|
+
inputs: [
|
|
181
|
+
"name",
|
|
182
|
+
"icon",
|
|
183
|
+
"label",
|
|
184
|
+
"size",
|
|
185
|
+
"strokeWidth"
|
|
186
|
+
]
|
|
187
|
+
}],
|
|
188
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
192
|
+
minVersion: "12.0.0",
|
|
193
|
+
version: "22.2.3",
|
|
194
|
+
ngImport: i0,
|
|
195
|
+
type: HySidebarItem,
|
|
196
|
+
decorators: [{
|
|
197
|
+
type: Component,
|
|
198
|
+
args: [{
|
|
199
|
+
selector: "a[hySidebarItem]",
|
|
200
|
+
imports: [HyIcon],
|
|
201
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
202
|
+
template: "<hy-icon [name]=\"icon()\" /><span class=\"label\">{{label()}}</span><ng-content />",
|
|
203
|
+
host: {
|
|
204
|
+
"[attr.aria-label]": "label()",
|
|
205
|
+
"[attr.title]": "label()",
|
|
206
|
+
"[attr.aria-current]": "active()?\"page\":null"
|
|
207
|
+
},
|
|
208
|
+
styles: [":host{display:flex;align-items:center;justify-content:var(--hy-sidebar-item-justify, start);gap:.75rem;min-block-size:44px;min-inline-size:0;padding:.625rem .75rem;border:1px solid transparent;border-radius:var(--hy-radius-s);color:var(--hy-ink-2);text-decoration:none;font-size:.875rem;font-weight:500;line-height:1.4;box-sizing:border-box;transition:background-color .12s ease,color .12s ease}.label{display:var(--hy-sidebar-label-display, inline);min-inline-size:0;overflow-wrap:anywhere}@media(hover:hover)and (pointer:fine){:host(:hover){background:var(--hy-surface-3);color:var(--hy-ink)}}:host(:active){background:var(--hy-surface-4)}:host([aria-current=\"page\"]){background:var(--hy-primary-wash);color:var(--hy-primary);font-weight:600}:host(:focus-visible){outline:2px solid var(--hy-primary);outline-offset:2px}hy-icon{flex:none;inline-size:1.125rem;block-size:1.125rem}\n"]
|
|
209
|
+
}]
|
|
210
|
+
}],
|
|
211
|
+
propDecorators: {
|
|
212
|
+
label: [{
|
|
213
|
+
type: i0.Input,
|
|
214
|
+
args: [{
|
|
215
|
+
isSignal: true,
|
|
216
|
+
alias: "label",
|
|
217
|
+
required: true
|
|
218
|
+
}]
|
|
219
|
+
}],
|
|
220
|
+
icon: [{
|
|
221
|
+
type: i0.Input,
|
|
222
|
+
args: [{
|
|
223
|
+
isSignal: true,
|
|
224
|
+
alias: "icon",
|
|
225
|
+
required: true
|
|
226
|
+
}]
|
|
227
|
+
}],
|
|
228
|
+
active: [{
|
|
229
|
+
type: i0.Input,
|
|
230
|
+
args: [{
|
|
231
|
+
isSignal: true,
|
|
232
|
+
alias: "active",
|
|
233
|
+
required: false
|
|
234
|
+
}]
|
|
235
|
+
}]
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
const HY_SIDEBAR = [HySidebar, HySidebarItem];
|
|
239
|
+
export { HY_SIDEBAR, HySidebar, HySidebarItem };
|
|
240
|
+
|
|
241
|
+
//# sourceMappingURL=hyalo-angular-sidebar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyalo-angular-sidebar.mjs","names":[],"sources":["../../../projects/hyalo/sidebar/sidebar.ts","../../../projects/hyalo/sidebar/sidebar.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, booleanAttribute, input, model } from '@angular/core';\nimport { HyIcon } from '@hyalo/angular/icon';\n@Component({\n selector: 'hy-sidebar',\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './sidebar.html',\n styleUrl: './sidebar.css',\n host: {\n '[attr.data-collapsed]': 'collapsed()',\n '[style.--hy-sidebar-label-display]': 'collapsed()?\"none\":null',\n '[style.--hy-sidebar-item-justify]': 'collapsed()?\"center\":null',\n },\n})\nexport class HySidebar {\n readonly collapsed = model(false);\n protected readonly toggle = (value: boolean): boolean => !value;\n readonly label = input('Main navigation');\n readonly collapseLabel = input('Collapse navigation');\n readonly expandLabel = input('Expand navigation');\n}\n@Component({\n // Native elements preserve link, list, key, and button semantics.\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'a[hySidebarItem]',\n imports: [HyIcon],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: '<hy-icon [name]=\"icon()\" /><span class=\"label\">{{label()}}</span><ng-content />',\n host: {\n '[attr.aria-label]': 'label()',\n '[attr.title]': 'label()',\n '[attr.aria-current]': 'active()?\"page\":null',\n },\n styleUrl: './sidebar-item.css',\n})\nexport class HySidebarItem {\n readonly label = input.required<string>();\n readonly icon = input.required<string>();\n readonly active = input(false, { transform: booleanAttribute });\n}\nexport const HY_SIDEBAR = [HySidebar, HySidebarItem] as const;\n","<header>\n <div class=\"brand\"><ng-content select=\"[hySidebarBrand]\" /></div>\n <button\n type=\"button\"\n [attr.aria-label]=\"collapsed() ? expandLabel() : collapseLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"collapsed.update(toggle)\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n aria-hidden=\"true\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"3\" />\n <path d=\"M9 4v16\" />\n </svg>\n </button>\n</header>\n<nav [attr.aria-label]=\"label()\"><ng-content /></nav>\n<footer><ng-content select=\"[hySidebarFooter]\" /></footer>\n"],"mappings":"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"}
|