@hyalo/angular 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +21 -0
  3. package/README.md +32 -3
  4. package/fesm2022/hyalo-angular-accordion.mjs +230 -0
  5. package/fesm2022/hyalo-angular-accordion.mjs.map +1 -0
  6. package/fesm2022/hyalo-angular-button.mjs +203 -0
  7. package/fesm2022/hyalo-angular-button.mjs.map +1 -0
  8. package/fesm2022/hyalo-angular-card.mjs +221 -0
  9. package/fesm2022/hyalo-angular-card.mjs.map +1 -0
  10. package/fesm2022/hyalo-angular-choice.mjs +788 -0
  11. package/fesm2022/hyalo-angular-choice.mjs.map +1 -0
  12. package/fesm2022/hyalo-angular-dialog.mjs +571 -0
  13. package/fesm2022/hyalo-angular-dialog.mjs.map +1 -0
  14. package/fesm2022/hyalo-angular-field.mjs +312 -0
  15. package/fesm2022/hyalo-angular-field.mjs.map +1 -0
  16. package/fesm2022/hyalo-angular-icon.mjs +343 -0
  17. package/fesm2022/hyalo-angular-icon.mjs.map +1 -0
  18. package/fesm2022/hyalo-angular-interaction.mjs +455 -0
  19. package/fesm2022/hyalo-angular-interaction.mjs.map +1 -0
  20. package/fesm2022/hyalo-angular-navbar.mjs +343 -0
  21. package/fesm2022/hyalo-angular-navbar.mjs.map +1 -0
  22. package/fesm2022/hyalo-angular-overlay.mjs +94 -0
  23. package/fesm2022/hyalo-angular-overlay.mjs.map +1 -0
  24. package/fesm2022/hyalo-angular-popover-overlay-kit-6wPwnxln.mjs +3 -0
  25. package/fesm2022/hyalo-angular-popover.mjs +487 -0
  26. package/fesm2022/hyalo-angular-popover.mjs.map +1 -0
  27. package/fesm2022/hyalo-angular-segmented.mjs +223 -0
  28. package/fesm2022/hyalo-angular-segmented.mjs.map +1 -0
  29. package/fesm2022/hyalo-angular-select.mjs +464 -0
  30. package/fesm2022/hyalo-angular-select.mjs.map +1 -0
  31. package/fesm2022/hyalo-angular-tabs.mjs +324 -0
  32. package/fesm2022/hyalo-angular-tabs.mjs.map +1 -0
  33. package/fesm2022/hyalo-angular-theme.mjs +94 -0
  34. package/fesm2022/hyalo-angular-theme.mjs.map +1 -0
  35. package/fesm2022/hyalo-angular-toast.mjs +322 -0
  36. package/fesm2022/hyalo-angular-toast.mjs.map +1 -0
  37. package/fesm2022/hyalo-angular.mjs +473 -0
  38. package/fesm2022/hyalo-angular.mjs.map +1 -0
  39. package/package.json +133 -3
  40. package/styles/hyalo-core.css +25 -0
  41. package/styles/hyalo.css +17 -0
  42. package/styles/overlays/dialog.css +9 -0
  43. package/styles/overlays/popover.css +9 -0
  44. package/styles/overlays/select.css +9 -0
  45. package/styles/overlays/toast.css +8 -0
  46. package/styles/palettes/aurora.css +47 -0
  47. package/styles/palettes/ember.css +47 -0
  48. package/styles/palettes/graphite.css +47 -0
  49. package/styles/palettes/ocean.css +47 -0
  50. package/styles/palettes/orchid.css +47 -0
  51. package/styles/palettes/rose.css +47 -0
  52. package/styles/parts/card.css +49 -0
  53. package/styles/parts/dialog.css +116 -0
  54. package/styles/parts/drawer.css +124 -0
  55. package/styles/parts/field.css +36 -0
  56. package/styles/parts/glass.css +137 -0
  57. package/styles/parts/motion.css +82 -0
  58. package/styles/parts/navbar.css +55 -0
  59. package/styles/parts/popover.css +27 -0
  60. package/styles/parts/presence.css +55 -0
  61. package/styles/parts/reset.css +42 -0
  62. package/styles/parts/select.css +46 -0
  63. package/styles/parts/themes.css +105 -0
  64. package/styles/parts/toast.css +128 -0
  65. package/styles/parts/tokens.css +151 -0
  66. package/styles/parts/typography.css +64 -0
  67. package/types/hyalo-angular-accordion.d.ts +74 -0
  68. package/types/hyalo-angular-button.d.ts +88 -0
  69. package/types/hyalo-angular-card.d.ts +61 -0
  70. package/types/hyalo-angular-choice.d.ts +259 -0
  71. package/types/hyalo-angular-dialog.d.ts +170 -0
  72. package/types/hyalo-angular-field.d.ts +135 -0
  73. package/types/hyalo-angular-icon.d.ts +122 -0
  74. package/types/hyalo-angular-interaction.d.ts +131 -0
  75. package/types/hyalo-angular-navbar.d.ts +110 -0
  76. package/types/hyalo-angular-overlay.d.ts +31 -0
  77. package/types/hyalo-angular-popover.d.ts +142 -0
  78. package/types/hyalo-angular-segmented.d.ts +79 -0
  79. package/types/hyalo-angular-select.d.ts +130 -0
  80. package/types/hyalo-angular-tabs.d.ts +102 -0
  81. package/types/hyalo-angular-theme.d.ts +46 -0
  82. package/types/hyalo-angular-toast.d.ts +79 -0
  83. package/types/hyalo-angular.d.ts +345 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@hyalo/angular` are listed here. The format follows [Keep a Changelog](https://keepachangelog.com), and versions follow [Semantic Versioning](https://semver.org). Until 1.0, a minor version can include breaking changes.
4
+
5
+ ## 0.1.0 (unreleased)
6
+
7
+ The first release.
8
+
9
+ ### Foundations (`@hyalo/angular`)
10
+
11
+ - `provideHyalo()` for global config, with the material, size and tone axes.
12
+ - `HyFidelity`, which steps the glass down on devices or settings where blur would hurt.
13
+ - `HyMotion` with motion presets, a spring helper and an optional, lazily loaded GSAP.
14
+ - The glass material directive and interaction state.
15
+
16
+ ### Components
17
+
18
+ Each one is standalone and has its own entry point.
19
+
20
+ - `@hyalo/angular/accordion`: `hy-accordion` and `hy-accordion-item` on Angular Aria.
21
+ - `@hyalo/angular/button`: `hyButton` for buttons and link buttons, with an inline loading spinner.
22
+ - `@hyalo/angular/card`: `hy-card` with media, header, body and footer slots.
23
+ - `@hyalo/angular/choice`: `hy-checkbox`, `hy-radio-group` with `hy-radio`, and `hy-switch`.
24
+ - `@hyalo/angular/dialog`: the `HyDialog` and `HyDrawer` services, content parts, a confirm helper, side drawers and bottom sheets.
25
+ - `@hyalo/angular/field`: `hy-field` and `hyInput` for text fields, with Signal Forms support.
26
+ - `@hyalo/angular/icon`: `hy-icon` with a name registry and Lucide-compatible data.
27
+ - `@hyalo/angular/interaction`: reveal, tilt, magnetic and ripple directives.
28
+ - `@hyalo/angular/navbar`: `hy-navbar` with a collapsible menu and scroll behaviour.
29
+ - `@hyalo/angular/overlay`: logical placement helpers for CDK overlays.
30
+ - `@hyalo/angular/popover`: `hyTooltip` and `hyPopover`, loading the CDK overlay on first open.
31
+ - `@hyalo/angular/segmented`: `hy-segmented`.
32
+ - `@hyalo/angular/select`: `hy-select` on the Angular Aria combobox and listbox.
33
+ - `@hyalo/angular/tabs`: `hy-tabs` on Angular Aria.
34
+ - `@hyalo/angular/theme`: `HyPalette` for switching palettes at runtime.
35
+ - `@hyalo/angular/toast`: the `HyToaster` service with swipe to dismiss.
36
+
37
+ ### Styles
38
+
39
+ - `styles/hyalo.css` with everything, or `styles/hyalo-core.css` plus one file per overlay from `styles/overlays/`.
40
+ - Design tokens, light and dark themes, and component tokens, all in cascade layers.
41
+ - Six on-demand palettes in `styles/palettes/`: aurora, ember, orchid, ocean, rose and graphite.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HamedRsl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,32 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/HamedRsl/Hyalo/main/.github/assets/hyalo-logo.jpg" alt="Hyalo, Angular UI kit" width="240" />
3
+ </p>
4
+
5
+ # @hyalo/angular
6
+
7
+ Liquid glass components for Angular, built on Angular Aria and the CDK. Signal based, zoneless, server-render safe, accessible, and ready for RTL.
8
+
9
+ ```sh
10
+ npm install @hyalo/angular @angular/cdk @angular/aria
11
+ ```
12
+
13
+ Add the stylesheet before your own styles in `angular.json`:
14
+
15
+ ```json
16
+ "styles": ["node_modules/@hyalo/angular/styles/hyalo.css", "src/styles.css"]
17
+ ```
18
+
19
+ `hyalo.css` includes every overlay's styles. To leave out the ones you don't use, list `hyalo-core.css` plus the files you need from `styles/overlays/` (`select.css`, `popover.css`, `dialog.css`, `toast.css`) instead.
20
+
21
+ Then import the standalone components you need. Each one has its own entry point, so a lazy route only loads what it uses:
22
+
23
+ ```ts
24
+ import { HyButton } from '@hyalo/angular/button';
25
+ import { HY_CARD } from '@hyalo/angular/card';
26
+ ```
27
+
28
+ `@hyalo/angular` itself holds the shared foundations, such as `provideHyalo()`, `HyFidelity` and `HyMotion`.
29
+
30
+ Configuration, theming, RTL, motion and the full component list are in the [repository README](https://github.com/HamedRsl/Hyalo#readme).
31
+
32
+ MIT licensed.
@@ -0,0 +1,230 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, booleanAttribute, input, model, numberAttribute } from "@angular/core";
3
+ import * as i1 from "@angular/aria/accordion";
4
+ import { AccordionGroup, AccordionPanel, AccordionTrigger } from "@angular/aria/accordion";
5
+ import { HyIcon } from "@hyalo/angular/icon";
6
+ import * as i2 from "@hyalo/angular";
7
+ import { HyMaterialDirective } from "@hyalo/angular";
8
+ var HyAccordionItem = class HyAccordionItem {
9
+ heading = input("", ...ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []);
10
+ headingLevel = input(3, {
11
+ ...ngDevMode ? { debugName: "headingLevel" } : /* istanbul ignore next */ {},
12
+ transform: numberAttribute
13
+ });
14
+ expanded = model(false, ...ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []);
15
+ disabled = input(false, {
16
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
17
+ transform: booleanAttribute
18
+ });
19
+ static ɵfac = i0.ɵɵngDeclareFactory({
20
+ minVersion: "12.0.0",
21
+ version: "22.2.3",
22
+ ngImport: i0,
23
+ type: HyAccordionItem,
24
+ deps: [],
25
+ target: i0.ɵɵFactoryTarget.Component
26
+ });
27
+ static ɵcmp = i0.ɵɵngDeclareComponent({
28
+ minVersion: "17.1.0",
29
+ version: "22.2.3",
30
+ type: HyAccordionItem,
31
+ isStandalone: true,
32
+ selector: "hy-accordion-item",
33
+ inputs: {
34
+ heading: {
35
+ classPropertyName: "heading",
36
+ publicName: "heading",
37
+ isSignal: true,
38
+ isRequired: false,
39
+ transformFunction: null
40
+ },
41
+ headingLevel: {
42
+ classPropertyName: "headingLevel",
43
+ publicName: "headingLevel",
44
+ isSignal: true,
45
+ isRequired: false,
46
+ transformFunction: null
47
+ },
48
+ expanded: {
49
+ classPropertyName: "expanded",
50
+ publicName: "expanded",
51
+ isSignal: true,
52
+ isRequired: false,
53
+ transformFunction: null
54
+ },
55
+ disabled: {
56
+ classPropertyName: "disabled",
57
+ publicName: "disabled",
58
+ isSignal: true,
59
+ isRequired: false,
60
+ transformFunction: null
61
+ }
62
+ },
63
+ outputs: { expanded: "expandedChange" },
64
+ host: {
65
+ properties: { "attr.data-open": "expanded() || null" },
66
+ classAttribute: "hy-accordion-item"
67
+ },
68
+ ngImport: i0,
69
+ template: "<div class=\"hy-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\r\n <button\r\n type=\"button\"\r\n class=\"hy-accordion__trigger\"\r\n ngAccordionTrigger\r\n [panel]=\"panel\"\r\n [(expanded)]=\"expanded\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"hy-accordion__label\">\r\n {{ heading() }}\r\n <ng-content select=\"[hyAccordionHeading]\" />\r\n </span>\r\n <hy-icon class=\"hy-accordion__chevron\" name=\"chevron-down\" />\r\n </button>\r\n</div>\r\n<div ngAccordionPanel #panel=\"ngAccordionPanel\" class=\"hy-accordion__panel\">\r\n <div class=\"hy-accordion__body\">\r\n <div class=\"hy-accordion__content\"><ng-content /></div>\r\n </div>\r\n</div>\r\n",
70
+ styles: [":host{display:block}:host+:host{border-block-start:1px solid var(--hy-accordion-divider, var(--hy-line))}.hy-accordion__heading{margin:0}.hy-accordion__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--hy-space-4);inline-size:100%;min-block-size:var(--hy-accordion-trigger-height, 3.5rem);padding:var(--hy-space-3) 0;border:0;background:transparent;color:var(--hy-ink);font:inherit;font-size:var(--hy-step-1);font-weight:580;text-align:start;cursor:pointer}.hy-accordion__trigger:focus-visible{outline:none;border-radius:var(--hy-radius-s);box-shadow:var(--hy-focus-ring)}.hy-accordion__trigger[aria-disabled=true]{opacity:.45;cursor:not-allowed}.hy-accordion__chevron{flex:none;color:var(--hy-ink-3);transition:rotate var(--hy-dur-settle) var(--hy-ease-out)}:host([data-open]) .hy-accordion__chevron{rotate:180deg}.hy-accordion__body{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--hy-dur-settle) var(--hy-ease-out)}:host([data-open]) .hy-accordion__body{grid-template-rows:1fr}.hy-accordion__content{min-block-size:0;overflow:hidden;color:var(--hy-ink-2)}:host([data-open]) .hy-accordion__content{padding-block-end:var(--hy-space-5)}.hy-accordion__panel[inert] .hy-accordion__content{visibility:hidden;transition:visibility 0s linear var(--hy-dur-settle)}@media print{.hy-accordion__body{grid-template-rows:1fr}.hy-accordion__panel[inert] .hy-accordion__content{visibility:visible}}\n"],
71
+ dependencies: [
72
+ {
73
+ kind: "directive",
74
+ type: AccordionTrigger,
75
+ selector: "[ngAccordionTrigger]",
76
+ inputs: [
77
+ "panel",
78
+ "id",
79
+ "disabled",
80
+ "expanded"
81
+ ],
82
+ outputs: ["expandedChange"],
83
+ exportAs: ["ngAccordionTrigger"]
84
+ },
85
+ {
86
+ kind: "directive",
87
+ type: AccordionPanel,
88
+ selector: "[ngAccordionPanel]",
89
+ inputs: ["id"],
90
+ exportAs: ["ngAccordionPanel"]
91
+ },
92
+ {
93
+ kind: "component",
94
+ type: HyIcon,
95
+ selector: "hy-icon",
96
+ inputs: [
97
+ "name",
98
+ "icon",
99
+ "label",
100
+ "size",
101
+ "strokeWidth"
102
+ ]
103
+ }
104
+ ],
105
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
106
+ });
107
+ };
108
+ i0.ɵɵngDeclareClassMetadata({
109
+ minVersion: "12.0.0",
110
+ version: "22.2.3",
111
+ ngImport: i0,
112
+ type: HyAccordionItem,
113
+ decorators: [{
114
+ type: Component,
115
+ args: [{
116
+ selector: "hy-accordion-item",
117
+ imports: [
118
+ AccordionTrigger,
119
+ AccordionPanel,
120
+ HyIcon
121
+ ],
122
+ changeDetection: ChangeDetectionStrategy.OnPush,
123
+ host: {
124
+ class: "hy-accordion-item",
125
+ "[attr.data-open]": "expanded() || null"
126
+ },
127
+ template: "<div class=\"hy-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\r\n <button\r\n type=\"button\"\r\n class=\"hy-accordion__trigger\"\r\n ngAccordionTrigger\r\n [panel]=\"panel\"\r\n [(expanded)]=\"expanded\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"hy-accordion__label\">\r\n {{ heading() }}\r\n <ng-content select=\"[hyAccordionHeading]\" />\r\n </span>\r\n <hy-icon class=\"hy-accordion__chevron\" name=\"chevron-down\" />\r\n </button>\r\n</div>\r\n<div ngAccordionPanel #panel=\"ngAccordionPanel\" class=\"hy-accordion__panel\">\r\n <div class=\"hy-accordion__body\">\r\n <div class=\"hy-accordion__content\"><ng-content /></div>\r\n </div>\r\n</div>\r\n",
128
+ styles: [":host{display:block}:host+:host{border-block-start:1px solid var(--hy-accordion-divider, var(--hy-line))}.hy-accordion__heading{margin:0}.hy-accordion__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--hy-space-4);inline-size:100%;min-block-size:var(--hy-accordion-trigger-height, 3.5rem);padding:var(--hy-space-3) 0;border:0;background:transparent;color:var(--hy-ink);font:inherit;font-size:var(--hy-step-1);font-weight:580;text-align:start;cursor:pointer}.hy-accordion__trigger:focus-visible{outline:none;border-radius:var(--hy-radius-s);box-shadow:var(--hy-focus-ring)}.hy-accordion__trigger[aria-disabled=true]{opacity:.45;cursor:not-allowed}.hy-accordion__chevron{flex:none;color:var(--hy-ink-3);transition:rotate var(--hy-dur-settle) var(--hy-ease-out)}:host([data-open]) .hy-accordion__chevron{rotate:180deg}.hy-accordion__body{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--hy-dur-settle) var(--hy-ease-out)}:host([data-open]) .hy-accordion__body{grid-template-rows:1fr}.hy-accordion__content{min-block-size:0;overflow:hidden;color:var(--hy-ink-2)}:host([data-open]) .hy-accordion__content{padding-block-end:var(--hy-space-5)}.hy-accordion__panel[inert] .hy-accordion__content{visibility:hidden;transition:visibility 0s linear var(--hy-dur-settle)}@media print{.hy-accordion__body{grid-template-rows:1fr}.hy-accordion__panel[inert] .hy-accordion__content{visibility:visible}}\n"]
129
+ }]
130
+ }],
131
+ propDecorators: {
132
+ heading: [{
133
+ type: i0.Input,
134
+ args: [{
135
+ isSignal: true,
136
+ alias: "heading",
137
+ required: false
138
+ }]
139
+ }],
140
+ headingLevel: [{
141
+ type: i0.Input,
142
+ args: [{
143
+ isSignal: true,
144
+ alias: "headingLevel",
145
+ required: false
146
+ }]
147
+ }],
148
+ expanded: [{
149
+ type: i0.Input,
150
+ args: [{
151
+ isSignal: true,
152
+ alias: "expanded",
153
+ required: false
154
+ }]
155
+ }, {
156
+ type: i0.Output,
157
+ args: ["expandedChange"]
158
+ }],
159
+ disabled: [{
160
+ type: i0.Input,
161
+ args: [{
162
+ isSignal: true,
163
+ alias: "disabled",
164
+ required: false
165
+ }]
166
+ }]
167
+ }
168
+ });
169
+ var HyAccordion = class HyAccordion {
170
+ static ɵfac = i0.ɵɵngDeclareFactory({
171
+ minVersion: "12.0.0",
172
+ version: "22.2.3",
173
+ ngImport: i0,
174
+ type: HyAccordion,
175
+ deps: [],
176
+ target: i0.ɵɵFactoryTarget.Component
177
+ });
178
+ static ɵcmp = i0.ɵɵngDeclareComponent({
179
+ minVersion: "14.0.0",
180
+ version: "22.2.3",
181
+ type: HyAccordion,
182
+ isStandalone: true,
183
+ selector: "hy-accordion",
184
+ host: { classAttribute: "hy-accordion" },
185
+ hostDirectives: [{
186
+ directive: i1.AccordionGroup,
187
+ inputs: [
188
+ "multiExpandable",
189
+ "multiple",
190
+ "disabled",
191
+ "disabled"
192
+ ]
193
+ }, {
194
+ directive: i2.HyMaterialDirective,
195
+ inputs: ["hyMaterial", "material"]
196
+ }],
197
+ ngImport: i0,
198
+ template: `<ng-content />`,
199
+ isInline: true,
200
+ styles: [":host{display:block;border-radius:var(--hy-radius-l);padding-inline:var(--hy-space-5)}\n"],
201
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
202
+ });
203
+ };
204
+ i0.ɵɵngDeclareClassMetadata({
205
+ minVersion: "12.0.0",
206
+ version: "22.2.3",
207
+ ngImport: i0,
208
+ type: HyAccordion,
209
+ decorators: [{
210
+ type: Component,
211
+ args: [{
212
+ selector: "hy-accordion",
213
+ changeDetection: ChangeDetectionStrategy.OnPush,
214
+ hostDirectives: [{
215
+ directive: AccordionGroup,
216
+ inputs: ["multiExpandable: multiple", "disabled"]
217
+ }, {
218
+ directive: HyMaterialDirective,
219
+ inputs: ["hyMaterial: material"]
220
+ }],
221
+ host: { class: "hy-accordion" },
222
+ template: `<ng-content />`,
223
+ styles: [":host{display:block;border-radius:var(--hy-radius-l);padding-inline:var(--hy-space-5)}\n"]
224
+ }]
225
+ }]
226
+ });
227
+ const HY_ACCORDION = [HyAccordion, HyAccordionItem];
228
+ export { HY_ACCORDION, HyAccordion, HyAccordionItem };
229
+
230
+ //# sourceMappingURL=hyalo-angular-accordion.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-accordion.mjs","names":[],"sources":["../../../projects/hyalo/accordion/accordion.ts","../../../projects/hyalo/accordion/accordion-item.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n booleanAttribute,\r\n input,\r\n model,\r\n numberAttribute,\r\n} from '@angular/core';\r\nimport { AccordionGroup, AccordionPanel, AccordionTrigger } from '@angular/aria/accordion';\r\nimport { HyIcon } from '@hyalo/angular/icon';\r\n\r\nimport { HyMaterialDirective } from '@hyalo/angular';\r\n\r\n/**\r\n * One collapsible section. The panel content stays in the DOM while closed\r\n * (marked `inert`), so in-page search and FAQ structured data still see it.\r\n */\r\n@Component({\r\n selector: 'hy-accordion-item',\r\n imports: [AccordionTrigger, AccordionPanel, HyIcon],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'hy-accordion-item',\r\n '[attr.data-open]': 'expanded() || null',\r\n },\r\n templateUrl: './accordion-item.html',\r\n styleUrl: './accordion.css',\r\n})\r\nexport class HyAccordionItem {\r\n /** Text of the header button. */\r\n readonly heading = input('');\r\n /** Heading level of the header, 2 to 6. Pick the one that fits the page outline. */\r\n readonly headingLevel = input(3, { transform: numberAttribute });\r\n /** Whether the section is open. Two-way bindable. */\r\n readonly expanded = model(false);\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n}\r\n\r\n/**\r\n * A stack of collapsible sections on Angular Aria. Arrow keys move between\r\n * headers, Home and End jump to the ends, Enter or Space toggles.\r\n *\r\n * ```html\r\n * <hy-accordion>\r\n * <hy-accordion-item heading=\"How long does delivery take?\">Three to five working days.</hy-accordion-item>\r\n * <hy-accordion-item heading=\"Can I return it?\">Within 30 days, free of charge.</hy-accordion-item>\r\n * </hy-accordion>\r\n * ```\r\n *\r\n * Only one section is open at a time unless `multiple` is set. Opening and\r\n * closing animate the height with CSS grid, which costs no layout script.\r\n */\r\n@Component({\r\n selector: 'hy-accordion',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n hostDirectives: [\r\n { directive: AccordionGroup, inputs: ['multiExpandable: multiple', 'disabled'] },\r\n { directive: HyMaterialDirective, inputs: ['hyMaterial: material'] },\r\n ],\r\n host: { class: 'hy-accordion' },\r\n template: `<ng-content />`,\r\n styles: `\r\n :host {\r\n display: block;\r\n border-radius: var(--hy-radius-l);\r\n padding-inline: var(--hy-space-5);\r\n }\r\n `,\r\n})\r\nexport class HyAccordion {}\r\n\r\n/** Everything needed to build an accordion. */\r\nexport const HY_ACCORDION = [HyAccordion, HyAccordionItem] as const;\r\n","<div class=\"hy-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\r\n <button\r\n type=\"button\"\r\n class=\"hy-accordion__trigger\"\r\n ngAccordionTrigger\r\n [panel]=\"panel\"\r\n [(expanded)]=\"expanded\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"hy-accordion__label\">\r\n {{ heading() }}\r\n <ng-content select=\"[hyAccordionHeading]\" />\r\n </span>\r\n <hy-icon class=\"hy-accordion__chevron\" name=\"chevron-down\" />\r\n </button>\r\n</div>\r\n<div ngAccordionPanel #panel=\"ngAccordionPanel\" class=\"hy-accordion__panel\">\r\n <div class=\"hy-accordion__body\">\r\n <div class=\"hy-accordion__content\"><ng-content /></div>\r\n </div>\r\n</div>\r\n"],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, ElementRef, booleanAttribute, computed, inject, input } from "@angular/core";
3
+ import * as i1 from "@hyalo/angular";
4
+ import { HY_CONFIG, HyFidelity, HyInteractive } from "@hyalo/angular";
5
+ var HyButton = class HyButton {
6
+ config = inject(HY_CONFIG);
7
+ fidelity = inject(HyFidelity);
8
+ el = inject(ElementRef).nativeElement;
9
+ isButton = this.el.tagName === "BUTTON";
10
+ variant = input("solid", ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
11
+ size = input(this.config.size, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
12
+ tone = input(this.config.tone, ...ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []);
13
+ iconOnly = input(false, {
14
+ ...ngDevMode ? { debugName: "iconOnly" } : /* istanbul ignore next */ {},
15
+ transform: booleanAttribute
16
+ });
17
+ loading = input(false, {
18
+ ...ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {},
19
+ transform: booleanAttribute
20
+ });
21
+ disabled = input(false, {
22
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
23
+ transform: booleanAttribute
24
+ });
25
+ material = computed(() => {
26
+ if (this.variant() !== "glass") return null;
27
+ return this.fidelity.tier() === "low" ? "solid" : this.config.material;
28
+ }, ...ngDevMode ? [{ debugName: "material" }] : /* istanbul ignore next */ []);
29
+ blocked = computed(() => this.loading() || !this.isButton && this.disabled(), ...ngDevMode ? [{ debugName: "blocked" }] : /* istanbul ignore next */ []);
30
+ constructor() {
31
+ this.el.addEventListener("click", (event) => {
32
+ if (!this.blocked()) return;
33
+ event.preventDefault();
34
+ event.stopImmediatePropagation();
35
+ }, { capture: true });
36
+ }
37
+ static ɵfac = i0.ɵɵngDeclareFactory({
38
+ minVersion: "12.0.0",
39
+ version: "22.2.3",
40
+ ngImport: i0,
41
+ type: HyButton,
42
+ deps: [],
43
+ target: i0.ɵɵFactoryTarget.Component
44
+ });
45
+ static ɵcmp = i0.ɵɵngDeclareComponent({
46
+ minVersion: "17.0.0",
47
+ version: "22.2.3",
48
+ type: HyButton,
49
+ isStandalone: true,
50
+ selector: "button[hyButton], a[hyButton]",
51
+ inputs: {
52
+ variant: {
53
+ classPropertyName: "variant",
54
+ publicName: "variant",
55
+ isSignal: true,
56
+ isRequired: false,
57
+ transformFunction: null
58
+ },
59
+ size: {
60
+ classPropertyName: "size",
61
+ publicName: "size",
62
+ isSignal: true,
63
+ isRequired: false,
64
+ transformFunction: null
65
+ },
66
+ tone: {
67
+ classPropertyName: "tone",
68
+ publicName: "tone",
69
+ isSignal: true,
70
+ isRequired: false,
71
+ transformFunction: null
72
+ },
73
+ iconOnly: {
74
+ classPropertyName: "iconOnly",
75
+ publicName: "iconOnly",
76
+ isSignal: true,
77
+ isRequired: false,
78
+ transformFunction: null
79
+ },
80
+ loading: {
81
+ classPropertyName: "loading",
82
+ publicName: "loading",
83
+ isSignal: true,
84
+ isRequired: false,
85
+ transformFunction: null
86
+ },
87
+ disabled: {
88
+ classPropertyName: "disabled",
89
+ publicName: "disabled",
90
+ isSignal: true,
91
+ isRequired: false,
92
+ transformFunction: null
93
+ }
94
+ },
95
+ host: {
96
+ properties: {
97
+ "class.hy-glass": "variant() === \"glass\"",
98
+ "attr.data-material": "material()",
99
+ "attr.data-thickness": "variant() === \"glass\" ? \"thin\" : null",
100
+ "attr.data-variant": "variant()",
101
+ "attr.data-size": "size()",
102
+ "attr.data-tone": "tone()",
103
+ "attr.data-icon-only": "iconOnly() || null",
104
+ "attr.data-loading": "loading() || null",
105
+ "attr.aria-busy": "loading() || null",
106
+ "attr.aria-disabled": "blocked() || null",
107
+ "attr.disabled": "isButton && disabled() ? \"\" : null",
108
+ "attr.tabindex": "!isButton && disabled() ? -1 : null"
109
+ },
110
+ classAttribute: "hy-button"
111
+ },
112
+ hostDirectives: [{ directive: i1.HyInteractive }],
113
+ ngImport: i0,
114
+ template: "<span class=\"hy-button__label\"><ng-content /></span>\r\n@if (loading()) {\r\n <!-- Inline, so a button does not pull in the icon registry. -->\r\n <span class=\"hy-button__spinner\" aria-hidden=\"true\">\r\n <svg viewBox=\"0 0 24 24\"><path d=\"M21 12a9 9 0 1 1-6.219-8.56\" /></svg>\r\n </span>\r\n}\r\n",
115
+ styles: [":host{--_c: var(--hy-primary);--_on: var(--hy-primary-ink);--_h: var(--hy-control-md);--_px: var(--hy-space-4);position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--hy-space-2);block-size:var(--_h);min-inline-size:var(--_h);padding-inline:var(--_px);border:1px solid transparent;border-radius:var(--hy-button-radius, var(--hy-radius-pill));font:inherit;font-size:var(--hy-step-0);font-weight:var(--hy-button-font-weight, 560);line-height:1;white-space:nowrap;text-decoration:none;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;transition:background-color var(--hy-dur-quick) var(--hy-ease-out),color var(--hy-dur-quick) var(--hy-ease-out),box-shadow var(--hy-dur-quick) var(--hy-ease-out),scale var(--hy-dur-quick) var(--hy-ease-out),translate var(--hy-dur-settle) var(--hy-ease-out),--hy-glow var(--hy-dur-settle) var(--hy-ease-out)}:host([data-size=\"sm\"]){--_h: var(--hy-control-sm);--_px: var(--hy-space-3);font-size:var(--hy-step--1);letter-spacing:var(--hy-tracking-small)}:host([data-size=\"lg\"]){--_h: var(--hy-control-lg);--_px: var(--hy-space-6);font-size:var(--hy-step-1)}:host([data-icon-only]){padding-inline:0;inline-size:var(--_h)}:host([data-tone=\"secondary\"]){--_c: var(--hy-secondary, var(--hy-primary));--_on: var(--hy-secondary-ink, var(--hy-primary-ink))}:host([data-tone=\"neutral\"]){--_c: var(--hy-ink);--_on: var(--hy-bg)}:host([data-tone=\"danger\"]){--_c: var(--hy-danger);--_on: var(--hy-danger-ink)}:host([data-tone=\"success\"]){--_c: var(--hy-success);--_on: var(--hy-bg)}:host([data-tone=\"warning\"]){--_c: var(--hy-warning);--_on: var(--hy-bg)}:host([data-variant=\"solid\"]){background-color:var(--_c);color:var(--_on);box-shadow:inset 0 1px #ffffff38,0 6px 16px -8px color-mix(in srgb,var(--_c) 70%,transparent)}:host([data-variant=\"solid\"][data-hover]){background-color:color-mix(in srgb,var(--_c) 88%,var(--hy-ink))}:host([data-variant=\"glass\"]){color:var(--hy-ink)}:host([data-variant=\"glass\"][data-hover]){--hy-glow: .25}:host([data-variant=\"soft\"]){background-color:color-mix(in srgb,var(--_c) 13%,transparent);color:var(--_c)}:host([data-variant=\"soft\"][data-hover]){background-color:color-mix(in srgb,var(--_c) 20%,transparent)}:host([data-variant=\"ghost\"]){background-color:transparent;color:var(--_c)}:host([data-variant=\"ghost\"][data-hover]){background-color:color-mix(in srgb,var(--_c) 10%,transparent)}:host([data-press]){scale:.97;transition-duration:min(.1s,var(--hy-dur-quick))}:host([data-variant=\"solid\"][data-press]){background-color:color-mix(in srgb,var(--_c) 78%,var(--hy-ink))}:host([data-variant=\"soft\"][data-press]){background-color:color-mix(in srgb,var(--_c) 26%,transparent)}:host([data-variant=\"ghost\"][data-press]){background-color:color-mix(in srgb,var(--_c) 16%,transparent)}:host([data-variant=\"glass\"][data-press]){--hy-glow: .45}:host(:focus-visible){outline:none;box-shadow:var(--hy-focus-ring)}:host(:disabled),:host([aria-disabled=\"true\"]:not([data-loading])){opacity:.45;cursor:not-allowed;pointer-events:none}:host([data-loading]){cursor:progress}.hy-button__label{display:inline-flex;align-items:center;gap:inherit}:host([data-loading]) .hy-button__label{visibility:hidden}.hy-button__spinner{position:absolute;inset:0;display:grid;place-items:center}.hy-button__spinner svg{inline-size:1.25em;block-size:1.25em;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;animation:hy-spin .8s linear infinite}@keyframes hy-spin{to{rotate:1turn}}@media(prefers-reduced-motion:reduce){.hy-button__spinner svg{animation-duration:2.4s}}@media(forced-colors:active){:host{border-color:ButtonText}}\n"],
116
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
117
+ });
118
+ };
119
+ i0.ɵɵngDeclareClassMetadata({
120
+ minVersion: "12.0.0",
121
+ version: "22.2.3",
122
+ ngImport: i0,
123
+ type: HyButton,
124
+ decorators: [{
125
+ type: Component,
126
+ args: [{
127
+ selector: "button[hyButton], a[hyButton]",
128
+ changeDetection: ChangeDetectionStrategy.OnPush,
129
+ hostDirectives: [HyInteractive],
130
+ host: {
131
+ class: "hy-button",
132
+ "[class.hy-glass]": "variant() === \"glass\"",
133
+ "[attr.data-material]": "material()",
134
+ "[attr.data-thickness]": "variant() === \"glass\" ? \"thin\" : null",
135
+ "[attr.data-variant]": "variant()",
136
+ "[attr.data-size]": "size()",
137
+ "[attr.data-tone]": "tone()",
138
+ "[attr.data-icon-only]": "iconOnly() || null",
139
+ "[attr.data-loading]": "loading() || null",
140
+ "[attr.aria-busy]": "loading() || null",
141
+ "[attr.aria-disabled]": "blocked() || null",
142
+ "[attr.disabled]": "isButton && disabled() ? \"\" : null",
143
+ "[attr.tabindex]": "!isButton && disabled() ? -1 : null"
144
+ },
145
+ template: "<span class=\"hy-button__label\"><ng-content /></span>\r\n@if (loading()) {\r\n <!-- Inline, so a button does not pull in the icon registry. -->\r\n <span class=\"hy-button__spinner\" aria-hidden=\"true\">\r\n <svg viewBox=\"0 0 24 24\"><path d=\"M21 12a9 9 0 1 1-6.219-8.56\" /></svg>\r\n </span>\r\n}\r\n",
146
+ styles: [":host{--_c: var(--hy-primary);--_on: var(--hy-primary-ink);--_h: var(--hy-control-md);--_px: var(--hy-space-4);position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--hy-space-2);block-size:var(--_h);min-inline-size:var(--_h);padding-inline:var(--_px);border:1px solid transparent;border-radius:var(--hy-button-radius, var(--hy-radius-pill));font:inherit;font-size:var(--hy-step-0);font-weight:var(--hy-button-font-weight, 560);line-height:1;white-space:nowrap;text-decoration:none;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;transition:background-color var(--hy-dur-quick) var(--hy-ease-out),color var(--hy-dur-quick) var(--hy-ease-out),box-shadow var(--hy-dur-quick) var(--hy-ease-out),scale var(--hy-dur-quick) var(--hy-ease-out),translate var(--hy-dur-settle) var(--hy-ease-out),--hy-glow var(--hy-dur-settle) var(--hy-ease-out)}:host([data-size=\"sm\"]){--_h: var(--hy-control-sm);--_px: var(--hy-space-3);font-size:var(--hy-step--1);letter-spacing:var(--hy-tracking-small)}:host([data-size=\"lg\"]){--_h: var(--hy-control-lg);--_px: var(--hy-space-6);font-size:var(--hy-step-1)}:host([data-icon-only]){padding-inline:0;inline-size:var(--_h)}:host([data-tone=\"secondary\"]){--_c: var(--hy-secondary, var(--hy-primary));--_on: var(--hy-secondary-ink, var(--hy-primary-ink))}:host([data-tone=\"neutral\"]){--_c: var(--hy-ink);--_on: var(--hy-bg)}:host([data-tone=\"danger\"]){--_c: var(--hy-danger);--_on: var(--hy-danger-ink)}:host([data-tone=\"success\"]){--_c: var(--hy-success);--_on: var(--hy-bg)}:host([data-tone=\"warning\"]){--_c: var(--hy-warning);--_on: var(--hy-bg)}:host([data-variant=\"solid\"]){background-color:var(--_c);color:var(--_on);box-shadow:inset 0 1px #ffffff38,0 6px 16px -8px color-mix(in srgb,var(--_c) 70%,transparent)}:host([data-variant=\"solid\"][data-hover]){background-color:color-mix(in srgb,var(--_c) 88%,var(--hy-ink))}:host([data-variant=\"glass\"]){color:var(--hy-ink)}:host([data-variant=\"glass\"][data-hover]){--hy-glow: .25}:host([data-variant=\"soft\"]){background-color:color-mix(in srgb,var(--_c) 13%,transparent);color:var(--_c)}:host([data-variant=\"soft\"][data-hover]){background-color:color-mix(in srgb,var(--_c) 20%,transparent)}:host([data-variant=\"ghost\"]){background-color:transparent;color:var(--_c)}:host([data-variant=\"ghost\"][data-hover]){background-color:color-mix(in srgb,var(--_c) 10%,transparent)}:host([data-press]){scale:.97;transition-duration:min(.1s,var(--hy-dur-quick))}:host([data-variant=\"solid\"][data-press]){background-color:color-mix(in srgb,var(--_c) 78%,var(--hy-ink))}:host([data-variant=\"soft\"][data-press]){background-color:color-mix(in srgb,var(--_c) 26%,transparent)}:host([data-variant=\"ghost\"][data-press]){background-color:color-mix(in srgb,var(--_c) 16%,transparent)}:host([data-variant=\"glass\"][data-press]){--hy-glow: .45}:host(:focus-visible){outline:none;box-shadow:var(--hy-focus-ring)}:host(:disabled),:host([aria-disabled=\"true\"]:not([data-loading])){opacity:.45;cursor:not-allowed;pointer-events:none}:host([data-loading]){cursor:progress}.hy-button__label{display:inline-flex;align-items:center;gap:inherit}:host([data-loading]) .hy-button__label{visibility:hidden}.hy-button__spinner{position:absolute;inset:0;display:grid;place-items:center}.hy-button__spinner svg{inline-size:1.25em;block-size:1.25em;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;animation:hy-spin .8s linear infinite}@keyframes hy-spin{to{rotate:1turn}}@media(prefers-reduced-motion:reduce){.hy-button__spinner svg{animation-duration:2.4s}}@media(forced-colors:active){:host{border-color:ButtonText}}\n"]
147
+ }]
148
+ }],
149
+ ctorParameters: () => [],
150
+ propDecorators: {
151
+ variant: [{
152
+ type: i0.Input,
153
+ args: [{
154
+ isSignal: true,
155
+ alias: "variant",
156
+ required: false
157
+ }]
158
+ }],
159
+ size: [{
160
+ type: i0.Input,
161
+ args: [{
162
+ isSignal: true,
163
+ alias: "size",
164
+ required: false
165
+ }]
166
+ }],
167
+ tone: [{
168
+ type: i0.Input,
169
+ args: [{
170
+ isSignal: true,
171
+ alias: "tone",
172
+ required: false
173
+ }]
174
+ }],
175
+ iconOnly: [{
176
+ type: i0.Input,
177
+ args: [{
178
+ isSignal: true,
179
+ alias: "iconOnly",
180
+ required: false
181
+ }]
182
+ }],
183
+ loading: [{
184
+ type: i0.Input,
185
+ args: [{
186
+ isSignal: true,
187
+ alias: "loading",
188
+ required: false
189
+ }]
190
+ }],
191
+ disabled: [{
192
+ type: i0.Input,
193
+ args: [{
194
+ isSignal: true,
195
+ alias: "disabled",
196
+ required: false
197
+ }]
198
+ }]
199
+ }
200
+ });
201
+ export { HyButton };
202
+
203
+ //# sourceMappingURL=hyalo-angular-button.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-button.mjs","names":[],"sources":["../../../projects/hyalo/button/button.ts","../../../projects/hyalo/button/button.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n booleanAttribute,\r\n computed,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\nimport { HY_CONFIG, HyFidelity, HyInteractive, type HySize, type HyTone } from '@hyalo/angular';\r\n\r\n/**\r\n * - `solid`: filled with the tone colour. The main action on a view.\r\n * - `glass`: a glass surface with tone-coloured text.\r\n * - `soft`: a light wash of the tone colour.\r\n * - `ghost`: text only, a surface appears on hover.\r\n */\r\nexport type HyButtonVariant = 'solid' | 'glass' | 'soft' | 'ghost';\r\n\r\n/**\r\n * Button and link button.\r\n *\r\n * ```html\r\n * <button hyButton (click)=\"save()\">Save</button>\r\n * <a hyButton variant=\"glass\" routerLink=\"/pricing\">Pricing</a>\r\n * <button hyButton iconOnly aria-label=\"Close\"><hy-icon name=\"x\" /></button>\r\n * ```\r\n *\r\n * It stays a native `<button>` or `<a>`, so forms, routing and keyboard\r\n * behaviour work as usual. A press dims and shrinks it the moment the\r\n * pointer goes down. Add `hyMagnetic` for the magnetic hover effect, or\r\n * `hyRipple` for a press ripple.\r\n *\r\n * While `loading`, the button keeps its focus and width, sets `aria-busy`\r\n * and ignores clicks. A disabled link gets `aria-disabled` and leaves the\r\n * tab order, since links have no native disabled state.\r\n */\r\n@Component({\r\n // Attribute selector so the host stays a native <button> or <a>.\r\n // eslint-disable-next-line @angular-eslint/component-selector\r\n selector: 'button[hyButton], a[hyButton]',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n hostDirectives: [HyInteractive],\r\n host: {\r\n class: 'hy-button',\r\n '[class.hy-glass]': 'variant() === \"glass\"',\r\n '[attr.data-material]': 'material()',\r\n // Buttons are small chips of glass, so they get the thinnest material.\r\n '[attr.data-thickness]': 'variant() === \"glass\" ? \"thin\" : null',\r\n '[attr.data-variant]': 'variant()',\r\n '[attr.data-size]': 'size()',\r\n '[attr.data-tone]': 'tone()',\r\n '[attr.data-icon-only]': 'iconOnly() || null',\r\n '[attr.data-loading]': 'loading() || null',\r\n '[attr.aria-busy]': 'loading() || null',\r\n '[attr.aria-disabled]': 'blocked() || null',\r\n '[attr.disabled]': 'isButton && disabled() ? \"\" : null',\r\n '[attr.tabindex]': '!isButton && disabled() ? -1 : null',\r\n },\r\n templateUrl: './button.html',\r\n styleUrl: './button.css',\r\n})\r\nexport class HyButton {\r\n private readonly config = inject(HY_CONFIG);\r\n private readonly fidelity = inject(HyFidelity);\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n protected readonly isButton = this.el.tagName === 'BUTTON';\r\n\r\n /** Visual style. */\r\n readonly variant = input<HyButtonVariant>('solid');\r\n /** Height and padding. Defaults to the configured size. */\r\n readonly size = input<HySize>(this.config.size);\r\n /** Colour role. Defaults to the configured tone. */\r\n readonly tone = input<HyTone>(this.config.tone);\r\n /** Square button for a single icon. Give it an `aria-label`. */\r\n readonly iconOnly = input(false, { transform: booleanAttribute });\r\n /** Shows a spinner and blocks clicks without dropping focus. */\r\n readonly loading = input(false, { transform: booleanAttribute });\r\n /** Disables the button. On links this sets `aria-disabled`. */\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n\r\n /** Glass follows the configured material and goes solid on the low tier. */\r\n protected readonly material = computed(() => {\r\n if (this.variant() !== 'glass') return null;\r\n return this.fidelity.tier() === 'low' ? 'solid' : this.config.material;\r\n });\r\n\r\n /** True when clicks should be ignored. */\r\n protected readonly blocked = computed(\r\n () => this.loading() || (!this.isButton && this.disabled()),\r\n );\r\n\r\n constructor() {\r\n // A capture listener on the element runs before the app's own (click)\r\n // handlers, so a blocked click never reaches them.\r\n this.el.addEventListener(\r\n 'click',\r\n (event) => {\r\n if (!this.blocked()) return;\r\n event.preventDefault();\r\n event.stopImmediatePropagation();\r\n },\r\n { capture: true },\r\n );\r\n }\r\n}\r\n","<span class=\"hy-button__label\"><ng-content /></span>\r\n@if (loading()) {\r\n <!-- Inline, so a button does not pull in the icon registry. -->\r\n <span class=\"hy-button__spinner\" aria-hidden=\"true\">\r\n <svg viewBox=\"0 0 24 24\"><path d=\"M21 12a9 9 0 1 1-6.219-8.56\" /></svg>\r\n </span>\r\n}\r\n"],"mappings":"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"}