@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,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
import { DestroyRef, Directive, ElementRef, afterNextRender, booleanAttribute, inject, input, numberAttribute } from "@angular/core";
|
|
3
|
-
import { HyMotion,
|
|
3
|
+
import { HyMotion, HySceneLight, MOTION } from "@hyalo/angular/motion";
|
|
4
4
|
var HyReveal = class HyReveal {
|
|
5
5
|
el = inject(ElementRef).nativeElement;
|
|
6
6
|
motion = inject(HyMotion);
|
|
@@ -122,54 +122,37 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
122
122
|
});
|
|
123
123
|
function bindPointer(handlers) {
|
|
124
124
|
const host = inject(ElementRef).nativeElement;
|
|
125
|
-
const
|
|
126
|
-
const destroyRef = inject(DestroyRef);
|
|
125
|
+
const scene = inject(HySceneLight), destroy = inject(DestroyRef);
|
|
127
126
|
afterNextRender(() => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
let rect = null;
|
|
131
|
-
let active = false;
|
|
132
|
-
const enter = (event) => {
|
|
133
|
-
if (!motion.enabled() || event.pointerType === "touch") return;
|
|
134
|
-
active = true;
|
|
135
|
-
rect = host.getBoundingClientRect();
|
|
136
|
-
h.enter?.(event, rect);
|
|
137
|
-
};
|
|
138
|
-
const move = (event) => {
|
|
139
|
-
if (!active) return enter(event);
|
|
140
|
-
if (!rect) return;
|
|
141
|
-
h.move(event, rect);
|
|
142
|
-
};
|
|
143
|
-
const leave = () => {
|
|
144
|
-
if (!active) return;
|
|
145
|
-
active = false;
|
|
146
|
-
rect = null;
|
|
147
|
-
h.leave?.();
|
|
148
|
-
};
|
|
149
|
-
host.addEventListener("pointerenter", enter, { passive: true });
|
|
150
|
-
host.addEventListener("pointermove", move, { passive: true });
|
|
151
|
-
host.addEventListener("pointerleave", leave, { passive: true });
|
|
152
|
-
destroyRef.onDestroy(() => {
|
|
153
|
-
host.removeEventListener("pointerenter", enter);
|
|
154
|
-
host.removeEventListener("pointermove", move);
|
|
155
|
-
host.removeEventListener("pointerleave", leave);
|
|
156
|
-
});
|
|
127
|
+
const unregister = scene.register(host, handlers());
|
|
128
|
+
destroy.onDestroy(unregister);
|
|
157
129
|
});
|
|
158
130
|
}
|
|
159
131
|
function cssVarSetter(el, name, unit, motion, vars) {
|
|
160
|
-
let quick
|
|
132
|
+
let quick;
|
|
133
|
+
let engine;
|
|
134
|
+
let disposed = false;
|
|
161
135
|
motion.gsap().then((gsap) => {
|
|
162
|
-
if (!gsap) return;
|
|
136
|
+
if (!gsap || disposed) return;
|
|
137
|
+
engine = gsap;
|
|
163
138
|
el.classList.add("hy-gsap");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
139
|
+
if (!el.style.getPropertyValue(name)) el.style.setProperty(name, `0${unit}`);
|
|
140
|
+
quick = gsap.quickTo(el, name, vars);
|
|
141
|
+
});
|
|
142
|
+
const set = ((value) => {
|
|
143
|
+
if (disposed) return;
|
|
144
|
+
if (quick && motion.enabled()) quick(value);
|
|
145
|
+
else {
|
|
146
|
+
engine?.killTweensOf(el);
|
|
147
|
+
el.style.setProperty(name, `${value}${unit}`);
|
|
148
|
+
}
|
|
168
149
|
});
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
150
|
+
set.destroy = () => {
|
|
151
|
+
disposed = true;
|
|
152
|
+
engine?.killTweensOf(el);
|
|
153
|
+
quick = void 0;
|
|
172
154
|
};
|
|
155
|
+
return set;
|
|
173
156
|
}
|
|
174
157
|
var HyTilt = class HyTilt {
|
|
175
158
|
el = inject(ElementRef).nativeElement;
|
|
@@ -191,6 +174,10 @@ var HyTilt = class HyTilt {
|
|
|
191
174
|
const rx = cssVarSetter(this.el, "--hy-rx", "deg", this.motion, vars);
|
|
192
175
|
const ry = cssVarSetter(this.el, "--hy-ry", "deg", this.motion, vars);
|
|
193
176
|
return {
|
|
177
|
+
destroy: () => {
|
|
178
|
+
rx.destroy();
|
|
179
|
+
ry.destroy();
|
|
180
|
+
},
|
|
194
181
|
enter: () => {
|
|
195
182
|
if (this.tiltGlow()) this.el.style.setProperty("--hy-glow", "0.32");
|
|
196
183
|
},
|
|
@@ -298,6 +285,10 @@ var HyMagnetic = class HyMagnetic {
|
|
|
298
285
|
const my = cssVarSetter(this.el, "--hy-my", "px", this.motion, vars);
|
|
299
286
|
const clamp = (v) => Math.max(-this.magneticMax(), Math.min(this.magneticMax(), v));
|
|
300
287
|
return {
|
|
288
|
+
destroy: () => {
|
|
289
|
+
mx.destroy();
|
|
290
|
+
my.destroy();
|
|
291
|
+
},
|
|
301
292
|
move: (event, rect) => {
|
|
302
293
|
const strength = this.magneticStrength();
|
|
303
294
|
mx(clamp((event.clientX - rect.left - rect.width / 2) * strength));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hyalo-angular-interaction.mjs","names":["matchesMedia"],"sources":["../../../projects/hyalo/interaction/reveal.ts","../../../projects/hyalo/interaction/pointer.ts","../../../projects/hyalo/interaction/tilt.ts","../../../projects/hyalo/interaction/magnetic.ts","../../../projects/hyalo/interaction/ripple.ts"],"sourcesContent":["import {\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n afterNextRender,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n numberAttribute,\r\n} from '@angular/core';\r\nimport { HyMotion } from '@hyalo/angular';\r\n\r\n/** Where a revealed element comes from. */\r\nexport type HyRevealFrom = 'up' | 'fade' | 'scale';\r\n\r\n/**\r\n * Fades and lifts an element in when it scrolls into view.\r\n *\r\n * ```html\r\n * @for (item of items; track item.id; let i = $index) {\r\n * <article hyReveal [revealDelay]=\"i * 60\">...</article>\r\n * }\r\n * ```\r\n *\r\n * Content is never hidden by default. The directive only hides an element\r\n * after hydration, only when it is below the fold, and only when motion is\r\n * enabled. Elements already on screen are left alone, so server-rendered\r\n * content does not flash. CSS transitions do the work, so it also runs on the\r\n * low tier when reduced motion is off.\r\n *\r\n * Put it on the glass element itself (`<hy-card hyReveal>`), not on a\r\n * wrapper around glass. While a wrapper fades, its glass children cannot\r\n * blur what is behind it, and the blur snaps in when the fade ends.\r\n */\r\n@Directive({\r\n selector: '[hyReveal]',\r\n host: { '[style.--hy-reveal-delay.ms]': 'revealDelay()' },\r\n})\r\nexport class HyReveal {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** Delay in milliseconds, for staggering. */\r\n readonly revealDelay = input(0, { transform: numberAttribute });\r\n /** The starting pose. */\r\n readonly revealFrom = input<HyRevealFrom>('up');\r\n /** Reveal again each time the element re-enters the viewport. */\r\n readonly revealRepeat = input(false, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n const destroyRef = inject(DestroyRef);\r\n afterNextRender(() => {\r\n if (this.motion.reduced() || typeof IntersectionObserver !== 'function') return;\r\n let first = true;\r\n const observer = new IntersectionObserver(\r\n ([entry]) => {\r\n if (!entry) return;\r\n if (first) {\r\n first = false;\r\n if (entry.isIntersecting) {\r\n if (!this.revealRepeat()) observer.disconnect();\r\n return;\r\n }\r\n this.el.setAttribute('data-hy-reveal-from', this.revealFrom());\r\n this.el.setAttribute('data-hy-reveal', 'hidden');\r\n return;\r\n }\r\n if (entry.isIntersecting) {\r\n this.el.setAttribute('data-hy-reveal', 'shown');\r\n if (!this.revealRepeat()) observer.disconnect();\r\n } else if (this.revealRepeat()) {\r\n this.el.setAttribute('data-hy-reveal', 'hidden');\r\n }\r\n },\r\n { rootMargin: '0px 0px -8% 0px' },\r\n );\r\n observer.observe(this.el);\r\n destroyRef.onDestroy(() => observer.disconnect());\r\n });\r\n }\r\n}\r\n","import { DestroyRef, ElementRef, afterNextRender, inject } from '@angular/core';\r\nimport { HyMotion, ɵmatchesMedia as matchesMedia } from '@hyalo/angular';\r\n\r\n/** Handlers that run outside change detection. */\r\nexport interface PointerHandlers {\r\n enter?(event: PointerEvent, rect: DOMRect): void;\r\n move(event: PointerEvent, rect: DOMRect): void;\r\n leave?(): void;\r\n}\r\n\r\n/**\r\n * Wires pointer listeners straight to the DOM, so high-frequency\r\n * `pointermove` events never schedule change detection. Listeners are only\r\n * attached on devices with a fine pointer, and they do nothing while motion\r\n * is disabled.\r\n */\r\nexport function bindPointer(handlers: () => PointerHandlers): void {\r\n const host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n const motion = inject(HyMotion);\r\n const destroyRef = inject(DestroyRef);\r\n\r\n afterNextRender(() => {\r\n if (!matchesMedia('(hover: hover) and (pointer: fine)')) return;\r\n const h = handlers();\r\n let rect: DOMRect | null = null;\r\n let active = false;\r\n\r\n const enter = (event: PointerEvent): void => {\r\n if (!motion.enabled() || event.pointerType === 'touch') return;\r\n active = true;\r\n rect = host.getBoundingClientRect();\r\n h.enter?.(event, rect);\r\n };\r\n const move = (event: PointerEvent): void => {\r\n if (!active) return enter(event);\r\n if (!rect) return;\r\n h.move(event, rect);\r\n };\r\n const leave = (): void => {\r\n if (!active) return;\r\n active = false;\r\n rect = null;\r\n h.leave?.();\r\n };\r\n\r\n host.addEventListener('pointerenter', enter, { passive: true });\r\n host.addEventListener('pointermove', move, { passive: true });\r\n host.addEventListener('pointerleave', leave, { passive: true });\r\n destroyRef.onDestroy(() => {\r\n host.removeEventListener('pointerenter', enter);\r\n host.removeEventListener('pointermove', move);\r\n host.removeEventListener('pointerleave', leave);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Returns a setter for one CSS custom property. Uses GSAP `quickTo` when GSAP\r\n * is available, so values glide, and a plain `style.setProperty` otherwise,\r\n * where a CSS transition does the smoothing.\r\n */\r\nexport function cssVarSetter(\r\n el: HTMLElement,\r\n name: string,\r\n unit: string,\r\n motion: HyMotion,\r\n vars: Record<string, unknown>,\r\n): (value: number) => void {\r\n let quick: ((value: number) => unknown) | null = null;\r\n void motion.gsap().then((gsap) => {\r\n if (!gsap) return;\r\n el.classList.add('hy-gsap');\r\n quick = gsap.quickTo(el, name, { ...vars, unit });\r\n });\r\n return (value) => {\r\n if (quick) quick(value);\r\n else el.style.setProperty(name, `${value}${unit}`);\r\n };\r\n}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n numberAttribute,\r\n} from '@angular/core';\r\nimport { HyMotion, MOTION } from '@hyalo/angular';\r\n\r\nimport { bindPointer, cssVarSetter } from './pointer';\r\n\r\n/**\r\n * Tilts the element toward the cursor and moves a soft glow under it.\r\n *\r\n * ```html\r\n * <hy-card hyTilt [tiltMax]=\"8\">...</hy-card>\r\n * ```\r\n *\r\n * Runs only with a fine pointer, with motion enabled and above the low\r\n * fidelity tier. The glow uses `--hy-px`, `--hy-py` and `--hy-glow`, which the\r\n * glass material already reads.\r\n */\r\n@Directive({\r\n selector: '[hyTilt]',\r\n host: { class: 'hy-tilt' },\r\n})\r\nexport class HyTilt {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** Maximum rotation in degrees. */\r\n readonly tiltMax = input(6, { transform: numberAttribute });\r\n /** Whether to show the pointer glow. */\r\n readonly tiltGlow = input(true, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n bindPointer(() => {\r\n const vars = { duration: MOTION.settle.duration, ease: MOTION.settle.ease };\r\n const rx = cssVarSetter(this.el, '--hy-rx', 'deg', this.motion, vars);\r\n const ry = cssVarSetter(this.el, '--hy-ry', 'deg', this.motion, vars);\r\n return {\r\n enter: () => {\r\n if (this.tiltGlow()) this.el.style.setProperty('--hy-glow', '0.32');\r\n },\r\n move: (event, rect) => {\r\n const x = (event.clientX - rect.left) / rect.width;\r\n const y = (event.clientY - rect.top) / rect.height;\r\n const max = this.tiltMax();\r\n ry((x - 0.5) * 2 * max);\r\n rx((0.5 - y) * 2 * max);\r\n this.el.style.setProperty('--hy-px', `${(x * 100).toFixed(1)}%`);\r\n this.el.style.setProperty('--hy-py', `${(y * 100).toFixed(1)}%`);\r\n },\r\n leave: () => {\r\n rx(0);\r\n ry(0);\r\n this.el.style.setProperty('--hy-glow', '0');\r\n },\r\n };\r\n });\r\n }\r\n}\r\n","import { Directive, ElementRef, inject, input, numberAttribute } from '@angular/core';\r\nimport { HyMotion, MOTION } from '@hyalo/angular';\r\n\r\nimport { bindPointer, cssVarSetter } from './pointer';\r\n\r\n/**\r\n * Pulls the element a little toward the cursor while it hovers.\r\n *\r\n * Uses the `translate` property, so it never fights with a `transform` the\r\n * element already has.\r\n */\r\n@Directive({\r\n selector: '[hyMagnetic]',\r\n host: { class: 'hy-magnetic' },\r\n})\r\nexport class HyMagnetic {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** How far the element follows the cursor, as a share of the distance. */\r\n readonly magneticStrength = input(0.3, { transform: numberAttribute });\r\n /** Upper limit for the offset in pixels. */\r\n readonly magneticMax = input(10, { transform: numberAttribute });\r\n\r\n constructor() {\r\n bindPointer(() => {\r\n const vars = { duration: MOTION.settle.duration, ease: MOTION.settle.ease };\r\n const mx = cssVarSetter(this.el, '--hy-mx', 'px', this.motion, vars);\r\n const my = cssVarSetter(this.el, '--hy-my', 'px', this.motion, vars);\r\n const clamp = (v: number): number =>\r\n Math.max(-this.magneticMax(), Math.min(this.magneticMax(), v));\r\n return {\r\n move: (event, rect) => {\r\n const strength = this.magneticStrength();\r\n mx(clamp((event.clientX - rect.left - rect.width / 2) * strength));\r\n my(clamp((event.clientY - rect.top - rect.height / 2) * strength));\r\n },\r\n leave: () => {\r\n mx(0);\r\n my(0);\r\n },\r\n };\r\n });\r\n }\r\n}\r\n","import {\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n afterNextRender,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\nimport { HyMotion } from '@hyalo/angular';\r\n\r\n/**\r\n * A soft light ripple from the press point. Purely decorative: it is\r\n * skipped with reduced motion and never affects layout.\r\n */\r\n@Directive({\r\n selector: '[hyRipple]',\r\n host: { class: 'hy-ripple-host' },\r\n})\r\nexport class HyRipple {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** Turns the ripple off without removing the directive. */\r\n readonly rippleDisabled = input(false, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n const destroyRef = inject(DestroyRef);\r\n afterNextRender(() => {\r\n const down = (event: PointerEvent): void => {\r\n if (this.rippleDisabled() || this.motion.reduced() || event.button !== 0) return;\r\n const rect = this.el.getBoundingClientRect();\r\n const size = Math.hypot(rect.width, rect.height) * 2;\r\n const wave = this.el.ownerDocument.createElement('span');\r\n wave.className = 'hy-ripple';\r\n wave.setAttribute('aria-hidden', 'true');\r\n wave.style.setProperty('--hy-ripple-size', `${size}px`);\r\n wave.style.setProperty('--hy-ripple-x', `${event.clientX - rect.left}px`);\r\n wave.style.setProperty('--hy-ripple-y', `${event.clientY - rect.top}px`);\r\n wave.addEventListener('animationend', () => wave.remove(), { once: true });\r\n this.el.appendChild(wave);\r\n };\r\n this.el.addEventListener('pointerdown', down, { passive: true });\r\n destroyRef.onDestroy(() => this.el.removeEventListener('pointerdown', down));\r\n });\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hyalo-angular-interaction.mjs","names":[],"sources":["../../../projects/hyalo/interaction/reveal.ts","../../../projects/hyalo/interaction/pointer.ts","../../../projects/hyalo/interaction/tilt.ts","../../../projects/hyalo/interaction/magnetic.ts","../../../projects/hyalo/interaction/ripple.ts"],"sourcesContent":["import {\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n afterNextRender,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n numberAttribute,\r\n} from '@angular/core';\r\nimport { HyMotion } from '@hyalo/angular/motion';\r\n\r\n/** Where a revealed element comes from. */\r\nexport type HyRevealFrom = 'up' | 'fade' | 'scale';\r\n\r\n/**\r\n * Fades and lifts an element in when it scrolls into view.\r\n *\r\n * ```html\r\n * @for (item of items; track item.id; let i = $index) {\r\n * <article hyReveal [revealDelay]=\"i * 60\">...</article>\r\n * }\r\n * ```\r\n *\r\n * Content is never hidden by default. The directive only hides an element\r\n * after hydration, only when it is below the fold, and only when motion is\r\n * enabled. Elements already on screen are left alone, so server-rendered\r\n * content does not flash. CSS transitions do the work, so it also runs on the\r\n * low tier when reduced motion is off.\r\n *\r\n * Put it on the glass element itself (`<hy-card hyReveal>`), not on a\r\n * wrapper around glass. While a wrapper fades, its glass children cannot\r\n * blur what is behind it, and the blur snaps in when the fade ends.\r\n */\r\n@Directive({\r\n selector: '[hyReveal]',\r\n host: { '[style.--hy-reveal-delay.ms]': 'revealDelay()' },\r\n})\r\nexport class HyReveal {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** Delay in milliseconds, for staggering. */\r\n readonly revealDelay = input(0, { transform: numberAttribute });\r\n /** The starting pose. */\r\n readonly revealFrom = input<HyRevealFrom>('up');\r\n /** Reveal again each time the element re-enters the viewport. */\r\n readonly revealRepeat = input(false, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n const destroyRef = inject(DestroyRef);\r\n afterNextRender(() => {\r\n if (this.motion.reduced() || typeof IntersectionObserver !== 'function') return;\r\n let first = true;\r\n const observer = new IntersectionObserver(\r\n ([entry]) => {\r\n if (!entry) return;\r\n if (first) {\r\n first = false;\r\n if (entry.isIntersecting) {\r\n if (!this.revealRepeat()) observer.disconnect();\r\n return;\r\n }\r\n this.el.setAttribute('data-hy-reveal-from', this.revealFrom());\r\n this.el.setAttribute('data-hy-reveal', 'hidden');\r\n return;\r\n }\r\n if (entry.isIntersecting) {\r\n this.el.setAttribute('data-hy-reveal', 'shown');\r\n if (!this.revealRepeat()) observer.disconnect();\r\n } else if (this.revealRepeat()) {\r\n this.el.setAttribute('data-hy-reveal', 'hidden');\r\n }\r\n },\r\n { rootMargin: '0px 0px -8% 0px' },\r\n );\r\n observer.observe(this.el);\r\n destroyRef.onDestroy(() => observer.disconnect());\r\n });\r\n }\r\n}\r\n","import { DestroyRef, ElementRef, afterNextRender, inject } from '@angular/core';\r\nimport { HyMotion, HySceneLight, type HyPointerHandlers } from '@hyalo/angular/motion';\r\nexport type PointerHandlers = HyPointerHandlers;\r\n\r\nexport function bindPointer(handlers: () => PointerHandlers): void {\r\n const host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n const scene = inject(HySceneLight),\r\n destroy = inject(DestroyRef);\r\n afterNextRender(() => {\r\n const unregister = scene.register(host, handlers());\r\n destroy.onDestroy(unregister);\r\n });\r\n}\r\n\r\nexport interface HyCssSetter {\r\n (value: number): void;\r\n destroy(): void;\r\n}\r\nexport function cssVarSetter(\r\n el: HTMLElement,\r\n name: string,\r\n unit: string,\r\n motion: HyMotion,\r\n vars: Record<string, unknown>,\r\n): HyCssSetter {\r\n let quick: ((value: number) => unknown) | undefined;\r\n let engine: Awaited<ReturnType<HyMotion['gsap']>>;\r\n let disposed = false;\r\n void motion.gsap().then((gsap) => {\r\n if (!gsap || disposed) return;\r\n engine = gsap;\r\n el.classList.add('hy-gsap');\r\n // quickTo preserves a custom property's existing unit instead of appending one.\r\n if (!el.style.getPropertyValue(name)) el.style.setProperty(name, `0${unit}`);\r\n quick = gsap.quickTo(el, name, vars);\r\n });\r\n const set = ((value: number): void => {\r\n if (disposed) return;\r\n if (quick && motion.enabled()) quick(value);\r\n else {\r\n engine?.killTweensOf(el);\r\n el.style.setProperty(name, `${value}${unit}`);\r\n }\r\n }) as HyCssSetter;\r\n set.destroy = () => {\r\n disposed = true;\r\n engine?.killTweensOf(el);\r\n quick = undefined;\r\n };\r\n return set;\r\n}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n numberAttribute,\r\n} from '@angular/core';\r\nimport { HyMotion, MOTION } from '@hyalo/angular/motion';\r\n\r\nimport { bindPointer, cssVarSetter } from './pointer';\r\n\r\n/**\r\n * Tilts the element toward the cursor and moves a soft glow under it.\r\n *\r\n * ```html\r\n * <hy-card hyTilt [tiltMax]=\"8\">...</hy-card>\r\n * ```\r\n *\r\n * Runs only with a fine pointer, with motion enabled and above the low\r\n * fidelity tier. The glow uses `--hy-px`, `--hy-py` and `--hy-glow`, which the\r\n * glass material already reads.\r\n */\r\n@Directive({\r\n selector: '[hyTilt]',\r\n host: { class: 'hy-tilt' },\r\n})\r\nexport class HyTilt {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** Maximum rotation in degrees. */\r\n readonly tiltMax = input(6, { transform: numberAttribute });\r\n /** Whether to show the pointer glow. */\r\n readonly tiltGlow = input(true, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n bindPointer(() => {\r\n const vars = { duration: MOTION.settle.duration, ease: MOTION.settle.ease };\r\n const rx = cssVarSetter(this.el, '--hy-rx', 'deg', this.motion, vars);\r\n const ry = cssVarSetter(this.el, '--hy-ry', 'deg', this.motion, vars);\r\n return {\r\n destroy: () => {\r\n rx.destroy();\r\n ry.destroy();\r\n },\r\n enter: () => {\r\n if (this.tiltGlow()) this.el.style.setProperty('--hy-glow', '0.32');\r\n },\r\n move: (event, rect) => {\r\n const x = (event.clientX - rect.left) / rect.width;\r\n const y = (event.clientY - rect.top) / rect.height;\r\n const max = this.tiltMax();\r\n ry((x - 0.5) * 2 * max);\r\n rx((0.5 - y) * 2 * max);\r\n this.el.style.setProperty('--hy-px', `${(x * 100).toFixed(1)}%`);\r\n this.el.style.setProperty('--hy-py', `${(y * 100).toFixed(1)}%`);\r\n },\r\n leave: () => {\r\n rx(0);\r\n ry(0);\r\n this.el.style.setProperty('--hy-glow', '0');\r\n },\r\n };\r\n });\r\n }\r\n}\r\n","import { Directive, ElementRef, inject, input, numberAttribute } from '@angular/core';\r\nimport { HyMotion, MOTION } from '@hyalo/angular/motion';\r\n\r\nimport { bindPointer, cssVarSetter } from './pointer';\r\n\r\n/**\r\n * Pulls the element a little toward the cursor while it hovers.\r\n *\r\n * Uses the `translate` property, so it never fights with a `transform` the\r\n * element already has.\r\n */\r\n@Directive({\r\n selector: '[hyMagnetic]',\r\n host: { class: 'hy-magnetic' },\r\n})\r\nexport class HyMagnetic {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** How far the element follows the cursor, as a share of the distance. */\r\n readonly magneticStrength = input(0.3, { transform: numberAttribute });\r\n /** Upper limit for the offset in pixels. */\r\n readonly magneticMax = input(10, { transform: numberAttribute });\r\n\r\n constructor() {\r\n bindPointer(() => {\r\n const vars = { duration: MOTION.settle.duration, ease: MOTION.settle.ease };\r\n const mx = cssVarSetter(this.el, '--hy-mx', 'px', this.motion, vars);\r\n const my = cssVarSetter(this.el, '--hy-my', 'px', this.motion, vars);\r\n const clamp = (v: number): number =>\r\n Math.max(-this.magneticMax(), Math.min(this.magneticMax(), v));\r\n return {\r\n destroy: () => {\r\n mx.destroy();\r\n my.destroy();\r\n },\r\n move: (event, rect) => {\r\n const strength = this.magneticStrength();\r\n mx(clamp((event.clientX - rect.left - rect.width / 2) * strength));\r\n my(clamp((event.clientY - rect.top - rect.height / 2) * strength));\r\n },\r\n leave: () => {\r\n mx(0);\r\n my(0);\r\n },\r\n };\r\n });\r\n }\r\n}\r\n","import {\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n afterNextRender,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\nimport { HyMotion } from '@hyalo/angular/motion';\r\n\r\n/**\r\n * A soft light ripple from the press point. Purely decorative: it is\r\n * skipped with reduced motion and never affects layout.\r\n */\r\n@Directive({\r\n selector: '[hyRipple]',\r\n host: { class: 'hy-ripple-host' },\r\n})\r\nexport class HyRipple {\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n private readonly motion = inject(HyMotion);\r\n\r\n /** Turns the ripple off without removing the directive. */\r\n readonly rippleDisabled = input(false, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n const destroyRef = inject(DestroyRef);\r\n afterNextRender(() => {\r\n const down = (event: PointerEvent): void => {\r\n if (this.rippleDisabled() || this.motion.reduced() || event.button !== 0) return;\r\n const rect = this.el.getBoundingClientRect();\r\n const size = Math.hypot(rect.width, rect.height) * 2;\r\n const wave = this.el.ownerDocument.createElement('span');\r\n wave.className = 'hy-ripple';\r\n wave.setAttribute('aria-hidden', 'true');\r\n wave.style.setProperty('--hy-ripple-size', `${size}px`);\r\n wave.style.setProperty('--hy-ripple-x', `${event.clientX - rect.left}px`);\r\n wave.style.setProperty('--hy-ripple-y', `${event.clientY - rect.top}px`);\r\n wave.addEventListener('animationend', () => wave.remove(), { once: true });\r\n this.el.appendChild(wave);\r\n };\r\n this.el.addEventListener('pointerdown', down, { passive: true });\r\n destroyRef.onDestroy(() => this.el.removeEventListener('pointerdown', down));\r\n });\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
|
3
|
+
var HyKbd = class HyKbd {
|
|
4
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
5
|
+
minVersion: "12.0.0",
|
|
6
|
+
version: "22.2.3",
|
|
7
|
+
ngImport: i0,
|
|
8
|
+
type: HyKbd,
|
|
9
|
+
deps: [],
|
|
10
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
11
|
+
});
|
|
12
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
13
|
+
minVersion: "14.0.0",
|
|
14
|
+
version: "22.2.3",
|
|
15
|
+
type: HyKbd,
|
|
16
|
+
isStandalone: true,
|
|
17
|
+
selector: "kbd[hyKbd]",
|
|
18
|
+
ngImport: i0,
|
|
19
|
+
template: "<ng-content />\r\n",
|
|
20
|
+
styles: [":host{display:inline-flex;align-items:center;justify-content:center;min-inline-size:1.5rem;min-block-size:1.5rem;padding:.125rem .375rem;border:1px solid var(--hy-line-strong);border-block-end-width:2px;border-radius:.375rem;background:var(--hy-surface-2);color:var(--hy-ink-2);font:500 .75rem/1.4 var(--hy-font-mono);white-space:nowrap}\n"],
|
|
21
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
25
|
+
minVersion: "12.0.0",
|
|
26
|
+
version: "22.2.3",
|
|
27
|
+
ngImport: i0,
|
|
28
|
+
type: HyKbd,
|
|
29
|
+
decorators: [{
|
|
30
|
+
type: Component,
|
|
31
|
+
args: [{
|
|
32
|
+
selector: "kbd[hyKbd]",
|
|
33
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
34
|
+
template: "<ng-content />\r\n",
|
|
35
|
+
styles: [":host{display:inline-flex;align-items:center;justify-content:center;min-inline-size:1.5rem;min-block-size:1.5rem;padding:.125rem .375rem;border:1px solid var(--hy-line-strong);border-block-end-width:2px;border-radius:.375rem;background:var(--hy-surface-2);color:var(--hy-ink-2);font:500 .75rem/1.4 var(--hy-font-mono);white-space:nowrap}\n"]
|
|
36
|
+
}]
|
|
37
|
+
}]
|
|
38
|
+
});
|
|
39
|
+
export { HyKbd };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=hyalo-angular-kbd.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyalo-angular-kbd.mjs","names":[],"sources":["../../../projects/hyalo/kbd/kbd.ts","../../../projects/hyalo/kbd/kbd.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component } from '@angular/core';\r\n@Component({\r\n // Native elements preserve link, list, key, and button semantics.\r\n // eslint-disable-next-line @angular-eslint/component-selector\r\n selector: 'kbd[hyKbd]',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './kbd.html',\r\n styleUrl: './kbd.css',\r\n})\r\nexport class HyKbd {}\r\n","<ng-content />\r\n"],"mappings":";;AASA,IAAa,QAAb,MAAa,MAAK;CAAL,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAK,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAL,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAK,cAAA;EAAA,UAAA;EAAA,UAAA;EAAA,UCTlB;EACA,QAAA,CAAA,qVAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;ADQa,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAK,YAAA,CAAA;EARjB,MAAA;EAGW,MAAA,CAAA;GAAA,UAAA;GAAY,iBACL,wBAAwB;GAAM,UAAA;GAAA,QAAA,CAAA,qVAAA;EAAA,CAAA"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, Injectable, computed, inject, input, signal } from "@angular/core";
|
|
3
|
+
import { HY_DIALOG_DATA, HyDialog, HyDialogRef } from "@hyalo/angular/dialog";
|
|
4
|
+
import { HyButton } from "@hyalo/angular/button";
|
|
5
|
+
var HyLightboxView = class HyLightboxView {
|
|
6
|
+
data = inject(HY_DIALOG_DATA);
|
|
7
|
+
ref = inject(HyDialogRef);
|
|
8
|
+
index = signal(Math.max(0, Math.min(this.data.images.length - 1, Math.trunc(this.data.index ?? 0) || 0)), ...ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []);
|
|
9
|
+
image = computed(() => this.data.images[this.index()], ...ngDevMode ? [{ debugName: "image" }] : /* istanbul ignore next */ []);
|
|
10
|
+
move(delta) {
|
|
11
|
+
this.index.update((i) => Math.max(0, Math.min(this.data.images.length - 1, i + delta)));
|
|
12
|
+
}
|
|
13
|
+
onKey(event) {
|
|
14
|
+
if (event.target.matches("input, textarea, select")) return;
|
|
15
|
+
const rtl = event.currentTarget.ownerDocument.defaultView?.getComputedStyle(event.currentTarget).direction === "rtl";
|
|
16
|
+
if (event.key === "ArrowRight") {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
this.move(rtl ? -1 : 1);
|
|
19
|
+
} else if (event.key === "ArrowLeft") {
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
this.move(rtl ? 1 : -1);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
25
|
+
minVersion: "12.0.0",
|
|
26
|
+
version: "22.2.3",
|
|
27
|
+
ngImport: i0,
|
|
28
|
+
type: HyLightboxView,
|
|
29
|
+
deps: [],
|
|
30
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
31
|
+
});
|
|
32
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
33
|
+
minVersion: "17.0.0",
|
|
34
|
+
version: "22.2.3",
|
|
35
|
+
type: HyLightboxView,
|
|
36
|
+
isStandalone: true,
|
|
37
|
+
selector: "hy-lightbox-view",
|
|
38
|
+
host: { listeners: { "keydown": "onKey($event)" } },
|
|
39
|
+
ngImport: i0,
|
|
40
|
+
template: "<div class=\"controls\">\r\n <button hyButton type=\"button\" variant=\"ghost\" (click)=\"ref.close()\">\r\n {{ data.closeLabel ?? 'Close gallery' }}\r\n </button>\r\n</div>\r\n@if (image(); as image) {\r\n <figure>\r\n <img [src]=\"image.src\" [alt]=\"image.alt\" />\r\n @if (image.caption) {\r\n <figcaption>{{ image.caption }}</figcaption>\r\n }\r\n </figure>\r\n}\r\n<div class=\"controls\">\r\n <button hyButton type=\"button\" variant=\"glass\" [disabled]=\"index() === 0\" (click)=\"move(-1)\">\r\n {{ data.previousLabel ?? 'Previous image' }}\r\n </button>\r\n <span aria-live=\"polite\" aria-atomic=\"true\">{{ index() + 1 }} / {{ data.images.length }}</span>\r\n <button\r\n hyButton\r\n type=\"button\"\r\n variant=\"glass\"\r\n [disabled]=\"index() === data.images.length - 1\"\r\n (click)=\"move(1)\"\r\n >\r\n {{ data.nextLabel ?? 'Next image' }}\r\n </button>\r\n</div>\r\n",
|
|
41
|
+
styles: [":host{display:block;color:var(--hy-ink)}figure{margin:var(--hy-space-4) 0;text-align:center}img{display:block;max-inline-size:100%;max-block-size:65dvh;margin-inline:auto;object-fit:contain}figcaption{padding-block:var(--hy-space-3);color:var(--hy-ink-2)}.controls{display:flex;align-items:center;justify-content:space-between;gap:var(--hy-space-3)}\n"],
|
|
42
|
+
dependencies: [{
|
|
43
|
+
kind: "component",
|
|
44
|
+
type: HyButton,
|
|
45
|
+
selector: "button[hyButton], a[hyButton]",
|
|
46
|
+
inputs: [
|
|
47
|
+
"variant",
|
|
48
|
+
"size",
|
|
49
|
+
"tone",
|
|
50
|
+
"iconOnly",
|
|
51
|
+
"loading",
|
|
52
|
+
"disabled"
|
|
53
|
+
]
|
|
54
|
+
}],
|
|
55
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
59
|
+
minVersion: "12.0.0",
|
|
60
|
+
version: "22.2.3",
|
|
61
|
+
ngImport: i0,
|
|
62
|
+
type: HyLightboxView,
|
|
63
|
+
decorators: [{
|
|
64
|
+
type: Component,
|
|
65
|
+
args: [{
|
|
66
|
+
selector: "hy-lightbox-view",
|
|
67
|
+
imports: [HyButton],
|
|
68
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
69
|
+
host: { "(keydown)": "onKey($event)" },
|
|
70
|
+
template: "<div class=\"controls\">\r\n <button hyButton type=\"button\" variant=\"ghost\" (click)=\"ref.close()\">\r\n {{ data.closeLabel ?? 'Close gallery' }}\r\n </button>\r\n</div>\r\n@if (image(); as image) {\r\n <figure>\r\n <img [src]=\"image.src\" [alt]=\"image.alt\" />\r\n @if (image.caption) {\r\n <figcaption>{{ image.caption }}</figcaption>\r\n }\r\n </figure>\r\n}\r\n<div class=\"controls\">\r\n <button hyButton type=\"button\" variant=\"glass\" [disabled]=\"index() === 0\" (click)=\"move(-1)\">\r\n {{ data.previousLabel ?? 'Previous image' }}\r\n </button>\r\n <span aria-live=\"polite\" aria-atomic=\"true\">{{ index() + 1 }} / {{ data.images.length }}</span>\r\n <button\r\n hyButton\r\n type=\"button\"\r\n variant=\"glass\"\r\n [disabled]=\"index() === data.images.length - 1\"\r\n (click)=\"move(1)\"\r\n >\r\n {{ data.nextLabel ?? 'Next image' }}\r\n </button>\r\n</div>\r\n",
|
|
71
|
+
styles: [":host{display:block;color:var(--hy-ink)}figure{margin:var(--hy-space-4) 0;text-align:center}img{display:block;max-inline-size:100%;max-block-size:65dvh;margin-inline:auto;object-fit:contain}figcaption{padding-block:var(--hy-space-3);color:var(--hy-ink-2)}.controls{display:flex;align-items:center;justify-content:space-between;gap:var(--hy-space-3)}\n"]
|
|
72
|
+
}]
|
|
73
|
+
}]
|
|
74
|
+
});
|
|
75
|
+
var HyLightbox = class HyLightbox {
|
|
76
|
+
dialog = inject(HyDialog);
|
|
77
|
+
open(images, options = {}) {
|
|
78
|
+
if (!images.length) return null;
|
|
79
|
+
return this.dialog.open(HyLightboxView, {
|
|
80
|
+
size: "full",
|
|
81
|
+
label: options.label ?? "Image gallery",
|
|
82
|
+
data: {
|
|
83
|
+
...options,
|
|
84
|
+
images
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
89
|
+
minVersion: "12.0.0",
|
|
90
|
+
version: "22.2.3",
|
|
91
|
+
ngImport: i0,
|
|
92
|
+
type: HyLightbox,
|
|
93
|
+
deps: [],
|
|
94
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
95
|
+
});
|
|
96
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
97
|
+
minVersion: "12.0.0",
|
|
98
|
+
version: "22.2.3",
|
|
99
|
+
ngImport: i0,
|
|
100
|
+
type: HyLightbox,
|
|
101
|
+
providedIn: "root"
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
105
|
+
minVersion: "12.0.0",
|
|
106
|
+
version: "22.2.3",
|
|
107
|
+
ngImport: i0,
|
|
108
|
+
type: HyLightbox,
|
|
109
|
+
decorators: [{
|
|
110
|
+
type: Injectable,
|
|
111
|
+
args: [{ providedIn: "root" }]
|
|
112
|
+
}]
|
|
113
|
+
});
|
|
114
|
+
var HyGallery = class HyGallery {
|
|
115
|
+
lightbox = inject(HyLightbox);
|
|
116
|
+
images = input.required(...ngDevMode ? [{ debugName: "images" }] : /* istanbul ignore next */ []);
|
|
117
|
+
label = input("Image gallery", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
118
|
+
openLabel = input("Open image", ...ngDevMode ? [{ debugName: "openLabel" }] : /* istanbul ignore next */ []);
|
|
119
|
+
options = input({}, ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
|
|
120
|
+
open(index) {
|
|
121
|
+
this.lightbox.open(this.images(), {
|
|
122
|
+
...this.options(),
|
|
123
|
+
label: this.label(),
|
|
124
|
+
index
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
128
|
+
minVersion: "12.0.0",
|
|
129
|
+
version: "22.2.3",
|
|
130
|
+
ngImport: i0,
|
|
131
|
+
type: HyGallery,
|
|
132
|
+
deps: [],
|
|
133
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
134
|
+
});
|
|
135
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
136
|
+
minVersion: "17.0.0",
|
|
137
|
+
version: "22.2.3",
|
|
138
|
+
type: HyGallery,
|
|
139
|
+
isStandalone: true,
|
|
140
|
+
selector: "hy-gallery",
|
|
141
|
+
inputs: {
|
|
142
|
+
images: {
|
|
143
|
+
classPropertyName: "images",
|
|
144
|
+
publicName: "images",
|
|
145
|
+
isSignal: true,
|
|
146
|
+
isRequired: true,
|
|
147
|
+
transformFunction: null
|
|
148
|
+
},
|
|
149
|
+
label: {
|
|
150
|
+
classPropertyName: "label",
|
|
151
|
+
publicName: "label",
|
|
152
|
+
isSignal: true,
|
|
153
|
+
isRequired: false,
|
|
154
|
+
transformFunction: null
|
|
155
|
+
},
|
|
156
|
+
openLabel: {
|
|
157
|
+
classPropertyName: "openLabel",
|
|
158
|
+
publicName: "openLabel",
|
|
159
|
+
isSignal: true,
|
|
160
|
+
isRequired: false,
|
|
161
|
+
transformFunction: null
|
|
162
|
+
},
|
|
163
|
+
options: {
|
|
164
|
+
classPropertyName: "options",
|
|
165
|
+
publicName: "options",
|
|
166
|
+
isSignal: true,
|
|
167
|
+
isRequired: false,
|
|
168
|
+
transformFunction: null
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
ngImport: i0,
|
|
172
|
+
template: "<div role=\"group\" [attr.aria-label]=\"label()\">\r\n @for (image of images(); track $index; let i = $index) {\r\n <button type=\"button\" [attr.aria-label]=\"openLabel() + ': ' + image.alt\" (click)=\"open(i)\">\r\n <img [src]=\"image.thumbnail ?? image.src\" [alt]=\"image.alt\" loading=\"lazy\" />\r\n </button>\r\n }\r\n</div>\r\n",
|
|
173
|
+
styles: [":host{display:block}div{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,10rem),1fr));gap:var(--hy-space-3)}button{padding:0;overflow:clip;border:1px solid var(--hy-line);border-radius:var(--hy-radius-m);background:var(--hy-surface-2);cursor:zoom-in}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:3px}img{display:block;inline-size:100%;aspect-ratio:4/3;object-fit:cover}\n"],
|
|
174
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
178
|
+
minVersion: "12.0.0",
|
|
179
|
+
version: "22.2.3",
|
|
180
|
+
ngImport: i0,
|
|
181
|
+
type: HyGallery,
|
|
182
|
+
decorators: [{
|
|
183
|
+
type: Component,
|
|
184
|
+
args: [{
|
|
185
|
+
selector: "hy-gallery",
|
|
186
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
187
|
+
template: "<div role=\"group\" [attr.aria-label]=\"label()\">\r\n @for (image of images(); track $index; let i = $index) {\r\n <button type=\"button\" [attr.aria-label]=\"openLabel() + ': ' + image.alt\" (click)=\"open(i)\">\r\n <img [src]=\"image.thumbnail ?? image.src\" [alt]=\"image.alt\" loading=\"lazy\" />\r\n </button>\r\n }\r\n</div>\r\n",
|
|
188
|
+
styles: [":host{display:block}div{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,10rem),1fr));gap:var(--hy-space-3)}button{padding:0;overflow:clip;border:1px solid var(--hy-line);border-radius:var(--hy-radius-m);background:var(--hy-surface-2);cursor:zoom-in}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:3px}img{display:block;inline-size:100%;aspect-ratio:4/3;object-fit:cover}\n"]
|
|
189
|
+
}]
|
|
190
|
+
}],
|
|
191
|
+
propDecorators: {
|
|
192
|
+
images: [{
|
|
193
|
+
type: i0.Input,
|
|
194
|
+
args: [{
|
|
195
|
+
isSignal: true,
|
|
196
|
+
alias: "images",
|
|
197
|
+
required: true
|
|
198
|
+
}]
|
|
199
|
+
}],
|
|
200
|
+
label: [{
|
|
201
|
+
type: i0.Input,
|
|
202
|
+
args: [{
|
|
203
|
+
isSignal: true,
|
|
204
|
+
alias: "label",
|
|
205
|
+
required: false
|
|
206
|
+
}]
|
|
207
|
+
}],
|
|
208
|
+
openLabel: [{
|
|
209
|
+
type: i0.Input,
|
|
210
|
+
args: [{
|
|
211
|
+
isSignal: true,
|
|
212
|
+
alias: "openLabel",
|
|
213
|
+
required: false
|
|
214
|
+
}]
|
|
215
|
+
}],
|
|
216
|
+
options: [{
|
|
217
|
+
type: i0.Input,
|
|
218
|
+
args: [{
|
|
219
|
+
isSignal: true,
|
|
220
|
+
alias: "options",
|
|
221
|
+
required: false
|
|
222
|
+
}]
|
|
223
|
+
}]
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
export { HyGallery, HyLightbox, HyLightboxView };
|
|
227
|
+
|
|
228
|
+
//# sourceMappingURL=hyalo-angular-lightbox.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyalo-angular-lightbox.mjs","names":[],"sources":["../../../projects/hyalo/lightbox/lightbox.ts","../../../projects/hyalo/lightbox/lightbox.html","../../../projects/hyalo/lightbox/gallery.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n Injectable,\r\n computed,\r\n inject,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\nimport { HY_DIALOG_DATA, HyDialog, HyDialogRef } from '@hyalo/angular/dialog';\r\nimport { HyButton } from '@hyalo/angular/button';\r\n\r\nexport interface HyGalleryImage {\r\n readonly src: string;\r\n readonly alt: string;\r\n readonly thumbnail?: string;\r\n readonly caption?: string;\r\n}\r\nexport interface HyLightboxOptions {\r\n readonly index?: number;\r\n readonly label?: string;\r\n readonly closeLabel?: string;\r\n readonly previousLabel?: string;\r\n readonly nextLabel?: string;\r\n}\r\ninterface GalleryData extends HyLightboxOptions {\r\n readonly images: readonly HyGalleryImage[];\r\n}\r\n\r\n@Component({\r\n selector: 'hy-lightbox-view',\r\n imports: [HyButton],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { '(keydown)': 'onKey($event)' },\r\n templateUrl: './lightbox.html',\r\n styleUrl: './lightbox.css',\r\n})\r\nexport class HyLightboxView {\r\n protected readonly data = inject(HY_DIALOG_DATA) as GalleryData;\r\n protected readonly ref = inject(HyDialogRef);\r\n protected readonly index = signal(\r\n Math.max(0, Math.min(this.data.images.length - 1, Math.trunc(this.data.index ?? 0) || 0)),\r\n );\r\n protected readonly image = computed(() => this.data.images[this.index()]);\r\n protected move(delta: number): void {\r\n this.index.update((i) => Math.max(0, Math.min(this.data.images.length - 1, i + delta)));\r\n }\r\n protected onKey(event: KeyboardEvent): void {\r\n if ((event.target as HTMLElement).matches('input, textarea, select')) return;\r\n const rtl =\r\n (event.currentTarget as HTMLElement).ownerDocument.defaultView?.getComputedStyle(\r\n event.currentTarget as HTMLElement,\r\n ).direction === 'rtl';\r\n if (event.key === 'ArrowRight') {\r\n event.preventDefault();\r\n this.move(rtl ? -1 : 1);\r\n } else if (event.key === 'ArrowLeft') {\r\n event.preventDefault();\r\n this.move(rtl ? 1 : -1);\r\n }\r\n }\r\n}\r\n/** Opens a gallery using the kit dialog's focus trap, Escape handling and focus restore. */\r\n@Injectable({ providedIn: 'root' })\r\nexport class HyLightbox {\r\n private readonly dialog = inject(HyDialog);\r\n open(images: readonly HyGalleryImage[], options: HyLightboxOptions = {}): HyDialogRef | null {\r\n if (!images.length) return null;\r\n return this.dialog.open(HyLightboxView, {\r\n size: 'full',\r\n label: options.label ?? 'Image gallery',\r\n data: { ...options, images },\r\n });\r\n }\r\n}\r\n@Component({\r\n selector: 'hy-gallery',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './gallery.html',\r\n styleUrl: './gallery.css',\r\n})\r\nexport class HyGallery {\r\n private readonly lightbox = inject(HyLightbox);\r\n readonly images = input.required<readonly HyGalleryImage[]>();\r\n readonly label = input('Image gallery');\r\n readonly openLabel = input('Open image');\r\n readonly options = input<HyLightboxOptions>({});\r\n open(index: number): void {\r\n this.lightbox.open(this.images(), { ...this.options(), label: this.label(), index });\r\n }\r\n}\r\n","<div class=\"controls\">\r\n <button hyButton type=\"button\" variant=\"ghost\" (click)=\"ref.close()\">\r\n {{ data.closeLabel ?? 'Close gallery' }}\r\n </button>\r\n</div>\r\n@if (image(); as image) {\r\n <figure>\r\n <img [src]=\"image.src\" [alt]=\"image.alt\" />\r\n @if (image.caption) {\r\n <figcaption>{{ image.caption }}</figcaption>\r\n }\r\n </figure>\r\n}\r\n<div class=\"controls\">\r\n <button hyButton type=\"button\" variant=\"glass\" [disabled]=\"index() === 0\" (click)=\"move(-1)\">\r\n {{ data.previousLabel ?? 'Previous image' }}\r\n </button>\r\n <span aria-live=\"polite\" aria-atomic=\"true\">{{ index() + 1 }} / {{ data.images.length }}</span>\r\n <button\r\n hyButton\r\n type=\"button\"\r\n variant=\"glass\"\r\n [disabled]=\"index() === data.images.length - 1\"\r\n (click)=\"move(1)\"\r\n >\r\n {{ data.nextLabel ?? 'Next image' }}\r\n </button>\r\n</div>\r\n","<div role=\"group\" [attr.aria-label]=\"label()\">\r\n @for (image of images(); track $index; let i = $index) {\r\n <button type=\"button\" [attr.aria-label]=\"openLabel() + ': ' + image.alt\" (click)=\"open(i)\">\r\n <img [src]=\"image.thumbnail ?? image.src\" [alt]=\"image.alt\" loading=\"lazy\" />\r\n </button>\r\n }\r\n</div>\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
|
3
|
+
var HyLink = class HyLink {
|
|
4
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
5
|
+
minVersion: "12.0.0",
|
|
6
|
+
version: "22.2.3",
|
|
7
|
+
ngImport: i0,
|
|
8
|
+
type: HyLink,
|
|
9
|
+
deps: [],
|
|
10
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
11
|
+
});
|
|
12
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
13
|
+
minVersion: "14.0.0",
|
|
14
|
+
version: "22.2.3",
|
|
15
|
+
type: HyLink,
|
|
16
|
+
isStandalone: true,
|
|
17
|
+
selector: "a[hyLink]",
|
|
18
|
+
ngImport: i0,
|
|
19
|
+
template: "<ng-content />",
|
|
20
|
+
isInline: true,
|
|
21
|
+
styles: [":host{color:var(--hy-primary);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.2em;transition:text-underline-offset var(--hy-dur-quick) var(--hy-ease-out)}:host(:focus-visible){outline:2px solid var(--hy-primary);outline-offset:4px;border-radius:2px}@media(hover:hover)and (pointer:fine){:host(:hover){text-underline-offset:.35em}}\n"],
|
|
22
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
26
|
+
minVersion: "12.0.0",
|
|
27
|
+
version: "22.2.3",
|
|
28
|
+
ngImport: i0,
|
|
29
|
+
type: HyLink,
|
|
30
|
+
decorators: [{
|
|
31
|
+
type: Component,
|
|
32
|
+
args: [{
|
|
33
|
+
selector: "a[hyLink]",
|
|
34
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
35
|
+
template: "<ng-content />",
|
|
36
|
+
styles: [":host{color:var(--hy-primary);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.2em;transition:text-underline-offset var(--hy-dur-quick) var(--hy-ease-out)}:host(:focus-visible){outline:2px solid var(--hy-primary);outline-offset:4px;border-radius:2px}@media(hover:hover)and (pointer:fine){:host(:hover){text-underline-offset:.35em}}\n"]
|
|
37
|
+
}]
|
|
38
|
+
}]
|
|
39
|
+
});
|
|
40
|
+
export { HyLink };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=hyalo-angular-link.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyalo-angular-link.mjs","names":[],"sources":["../../../projects/hyalo/link/link.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component } from '@angular/core';\r\n@Component({\r\n // eslint-disable-next-line @angular-eslint/component-selector\r\n selector: 'a[hyLink]',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n template: '<ng-content />',\r\n styleUrl: './link.css',\r\n})\r\nexport class HyLink {}\r\n"],"mappings":";;AAQA,IAAa,SAAb,MAAa,OAAM;CAAN,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAM,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAN,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAM,cAAA;EAAA,UAAA;EAAA,UAAA;EAAA,UAHP;EAAgB,UAAA;EAAA,QAAA,CAAA,6WAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAGf,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAM,YAAA,CAAA;EAPlB,MAAA;EAEW,MAAA,CAAA;GAAA,UAAA;GAAW,iBACJ,wBAAwB;GAAM,UACrC;GAAgB,QAAA,CAAA,6WAAA;EAAA,CAAA"}
|