@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.
Files changed (198) hide show
  1. package/CHANGELOG.md +95 -41
  2. package/README.md +46 -32
  3. package/fesm2022/hyalo-angular-accordion.mjs +6 -6
  4. package/fesm2022/hyalo-angular-accordion.mjs.map +1 -1
  5. package/fesm2022/hyalo-angular-alert.mjs +171 -0
  6. package/fesm2022/hyalo-angular-alert.mjs.map +1 -0
  7. package/fesm2022/hyalo-angular-aspect-ratio.mjs +64 -0
  8. package/fesm2022/hyalo-angular-aspect-ratio.mjs.map +1 -0
  9. package/fesm2022/hyalo-angular-avatar.mjs +169 -0
  10. package/fesm2022/hyalo-angular-avatar.mjs.map +1 -0
  11. package/fesm2022/hyalo-angular-badge.mjs +268 -0
  12. package/fesm2022/hyalo-angular-badge.mjs.map +1 -0
  13. package/fesm2022/hyalo-angular-bento.mjs +132 -0
  14. package/fesm2022/hyalo-angular-bento.mjs.map +1 -0
  15. package/fesm2022/hyalo-angular-blocks.mjs +985 -0
  16. package/fesm2022/hyalo-angular-blocks.mjs.map +1 -0
  17. package/fesm2022/hyalo-angular-border-beam.mjs +73 -0
  18. package/fesm2022/hyalo-angular-border-beam.mjs.map +1 -0
  19. package/fesm2022/hyalo-angular-breadcrumb.mjs +77 -0
  20. package/fesm2022/hyalo-angular-breadcrumb.mjs.map +1 -0
  21. package/fesm2022/hyalo-angular-button-group.mjs +90 -0
  22. package/fesm2022/hyalo-angular-button-group.mjs.map +1 -0
  23. package/fesm2022/hyalo-angular-button.mjs +4 -3
  24. package/fesm2022/hyalo-angular-button.mjs.map +1 -1
  25. package/fesm2022/hyalo-angular-card.mjs +2 -2
  26. package/fesm2022/hyalo-angular-card.mjs.map +1 -1
  27. package/fesm2022/hyalo-angular-carousel.mjs +709 -0
  28. package/fesm2022/hyalo-angular-carousel.mjs.map +1 -0
  29. package/fesm2022/hyalo-angular-chapter-nav.mjs +336 -0
  30. package/fesm2022/hyalo-angular-chapter-nav.mjs.map +1 -0
  31. package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs +5 -0
  32. package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs.map +1 -0
  33. package/fesm2022/hyalo-angular-chart.mjs +391 -0
  34. package/fesm2022/hyalo-angular-chart.mjs.map +1 -0
  35. package/fesm2022/hyalo-angular-choice.mjs +2 -1
  36. package/fesm2022/hyalo-angular-choice.mjs.map +1 -1
  37. package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs +40 -0
  38. package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs.map +1 -0
  39. package/fesm2022/hyalo-angular-code-block.mjs +161 -0
  40. package/fesm2022/hyalo-angular-code-block.mjs.map +1 -0
  41. package/fesm2022/hyalo-angular-command.mjs +193 -0
  42. package/fesm2022/hyalo-angular-command.mjs.map +1 -0
  43. package/fesm2022/hyalo-angular-copy.mjs +138 -0
  44. package/fesm2022/hyalo-angular-copy.mjs.map +1 -0
  45. package/fesm2022/hyalo-angular-core.mjs +424 -0
  46. package/fesm2022/hyalo-angular-core.mjs.map +1 -0
  47. package/fesm2022/hyalo-angular-description-list.mjs +57 -0
  48. package/fesm2022/hyalo-angular-description-list.mjs.map +1 -0
  49. package/fesm2022/hyalo-angular-dialog.mjs +51 -22
  50. package/fesm2022/hyalo-angular-dialog.mjs.map +1 -1
  51. package/fesm2022/hyalo-angular-divider.mjs +66 -0
  52. package/fesm2022/hyalo-angular-divider.mjs.map +1 -0
  53. package/fesm2022/hyalo-angular-empty-state.mjs +123 -0
  54. package/fesm2022/hyalo-angular-empty-state.mjs.map +1 -0
  55. package/fesm2022/hyalo-angular-field.mjs +41 -9
  56. package/fesm2022/hyalo-angular-field.mjs.map +1 -1
  57. package/fesm2022/hyalo-angular-filter.mjs +309 -0
  58. package/fesm2022/hyalo-angular-filter.mjs.map +1 -0
  59. package/fesm2022/hyalo-angular-hotspot.mjs +225 -0
  60. package/fesm2022/hyalo-angular-hotspot.mjs.map +1 -0
  61. package/fesm2022/hyalo-angular-hover-card.mjs +233 -0
  62. package/fesm2022/hyalo-angular-hover-card.mjs.map +1 -0
  63. package/fesm2022/hyalo-angular-icon.mjs +42 -0
  64. package/fesm2022/hyalo-angular-icon.mjs.map +1 -1
  65. package/fesm2022/hyalo-angular-image-compare.mjs +168 -0
  66. package/fesm2022/hyalo-angular-image-compare.mjs.map +1 -0
  67. package/fesm2022/hyalo-angular-interaction.mjs +32 -41
  68. package/fesm2022/hyalo-angular-interaction.mjs.map +1 -1
  69. package/fesm2022/hyalo-angular-kbd.mjs +41 -0
  70. package/fesm2022/hyalo-angular-kbd.mjs.map +1 -0
  71. package/fesm2022/hyalo-angular-lightbox.mjs +228 -0
  72. package/fesm2022/hyalo-angular-lightbox.mjs.map +1 -0
  73. package/fesm2022/hyalo-angular-link.mjs +42 -0
  74. package/fesm2022/hyalo-angular-link.mjs.map +1 -0
  75. package/fesm2022/hyalo-angular-list.mjs +131 -0
  76. package/fesm2022/hyalo-angular-list.mjs.map +1 -0
  77. package/fesm2022/hyalo-angular-marquee.mjs +197 -0
  78. package/fesm2022/hyalo-angular-marquee.mjs.map +1 -0
  79. package/fesm2022/hyalo-angular-menu.mjs +423 -0
  80. package/fesm2022/hyalo-angular-menu.mjs.map +1 -0
  81. package/fesm2022/hyalo-angular-mesh.mjs +126 -0
  82. package/fesm2022/hyalo-angular-mesh.mjs.map +1 -0
  83. package/fesm2022/hyalo-angular-motion.mjs +620 -0
  84. package/fesm2022/hyalo-angular-motion.mjs.map +1 -0
  85. package/fesm2022/hyalo-angular-navbar.mjs +1 -1
  86. package/fesm2022/hyalo-angular-navbar.mjs.map +1 -1
  87. package/fesm2022/hyalo-angular-navigation-menu.mjs +222 -0
  88. package/fesm2022/hyalo-angular-navigation-menu.mjs.map +1 -0
  89. package/fesm2022/hyalo-angular-number-ticker.mjs +174 -0
  90. package/fesm2022/hyalo-angular-number-ticker.mjs.map +1 -0
  91. package/fesm2022/hyalo-angular-overlay.mjs +71 -2
  92. package/fesm2022/hyalo-angular-overlay.mjs.map +1 -1
  93. package/fesm2022/hyalo-angular-pagination.mjs +187 -0
  94. package/fesm2022/hyalo-angular-pagination.mjs.map +1 -0
  95. package/fesm2022/hyalo-angular-popover.mjs +34 -5
  96. package/fesm2022/hyalo-angular-popover.mjs.map +1 -1
  97. package/fesm2022/hyalo-angular-progress.mjs +209 -0
  98. package/fesm2022/hyalo-angular-progress.mjs.map +1 -0
  99. package/fesm2022/hyalo-angular-progressive-blur.mjs +73 -0
  100. package/fesm2022/hyalo-angular-progressive-blur.mjs.map +1 -0
  101. package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs +186 -0
  102. package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs.map +1 -0
  103. package/fesm2022/hyalo-angular-refraction.mjs +178 -0
  104. package/fesm2022/hyalo-angular-refraction.mjs.map +1 -0
  105. package/fesm2022/hyalo-angular-scroll-area.mjs +93 -0
  106. package/fesm2022/hyalo-angular-scroll-area.mjs.map +1 -0
  107. package/fesm2022/hyalo-angular-scroll-to-top.mjs +127 -0
  108. package/fesm2022/hyalo-angular-scroll-to-top.mjs.map +1 -0
  109. package/fesm2022/hyalo-angular-segmented.mjs +1 -1
  110. package/fesm2022/hyalo-angular-segmented.mjs.map +1 -1
  111. package/fesm2022/hyalo-angular-select.mjs +112 -15
  112. package/fesm2022/hyalo-angular-select.mjs.map +1 -1
  113. package/fesm2022/hyalo-angular-sidebar.mjs +241 -0
  114. package/fesm2022/hyalo-angular-sidebar.mjs.map +1 -0
  115. package/fesm2022/hyalo-angular-skeleton.mjs +131 -0
  116. package/fesm2022/hyalo-angular-skeleton.mjs.map +1 -0
  117. package/fesm2022/hyalo-angular-sparkline.mjs +110 -0
  118. package/fesm2022/hyalo-angular-sparkline.mjs.map +1 -0
  119. package/fesm2022/hyalo-angular-split-text.mjs +126 -0
  120. package/fesm2022/hyalo-angular-split-text.mjs.map +1 -0
  121. package/fesm2022/hyalo-angular-stat.mjs +193 -0
  122. package/fesm2022/hyalo-angular-stat.mjs.map +1 -0
  123. package/fesm2022/hyalo-angular-stepper.mjs +254 -0
  124. package/fesm2022/hyalo-angular-stepper.mjs.map +1 -0
  125. package/fesm2022/hyalo-angular-table.mjs +335 -0
  126. package/fesm2022/hyalo-angular-table.mjs.map +1 -0
  127. package/fesm2022/hyalo-angular-tabs.mjs +1 -1
  128. package/fesm2022/hyalo-angular-tabs.mjs.map +1 -1
  129. package/fesm2022/hyalo-angular-theme.mjs +1 -1
  130. package/fesm2022/hyalo-angular-theme.mjs.map +1 -1
  131. package/fesm2022/hyalo-angular-timeline.mjs +157 -0
  132. package/fesm2022/hyalo-angular-timeline.mjs.map +1 -0
  133. package/fesm2022/hyalo-angular-toast.mjs +2 -1
  134. package/fesm2022/hyalo-angular-toast.mjs.map +1 -1
  135. package/fesm2022/hyalo-angular.mjs +2 -473
  136. package/package.json +198 -2
  137. package/styles/parts/field.css +44 -36
  138. package/styles/parts/glass.css +2 -0
  139. package/styles/parts/motion.css +19 -0
  140. package/styles/parts/typography.css +17 -0
  141. package/types/hyalo-angular-accordion.d.ts +1 -1
  142. package/types/hyalo-angular-alert.d.ts +47 -0
  143. package/types/hyalo-angular-aspect-ratio.d.ts +13 -0
  144. package/types/hyalo-angular-avatar.d.ts +39 -0
  145. package/types/hyalo-angular-badge.d.ts +82 -0
  146. package/types/hyalo-angular-bento.d.ts +25 -0
  147. package/types/hyalo-angular-blocks.d.ts +272 -0
  148. package/types/hyalo-angular-border-beam.d.ts +15 -0
  149. package/types/hyalo-angular-breadcrumb.d.ts +22 -0
  150. package/types/hyalo-angular-button-group.d.ts +19 -0
  151. package/types/hyalo-angular-button.d.ts +4 -3
  152. package/types/hyalo-angular-card.d.ts +1 -1
  153. package/types/hyalo-angular-carousel.d.ts +147 -0
  154. package/types/hyalo-angular-chapter-nav.d.ts +79 -0
  155. package/types/hyalo-angular-chart.d.ts +90 -0
  156. package/types/hyalo-angular-code-block.d.ts +46 -0
  157. package/types/hyalo-angular-command.d.ts +41 -0
  158. package/types/hyalo-angular-copy.d.ts +39 -0
  159. package/types/hyalo-angular-core.d.ts +210 -0
  160. package/types/hyalo-angular-description-list.d.ts +16 -0
  161. package/types/hyalo-angular-dialog.d.ts +2 -1
  162. package/types/hyalo-angular-divider.d.ts +12 -0
  163. package/types/hyalo-angular-empty-state.d.ts +30 -0
  164. package/types/hyalo-angular-field.d.ts +10 -4
  165. package/types/hyalo-angular-filter.d.ts +122 -0
  166. package/types/hyalo-angular-hotspot.d.ts +70 -0
  167. package/types/hyalo-angular-hover-card.d.ts +47 -0
  168. package/types/hyalo-angular-image-compare.d.ts +55 -0
  169. package/types/hyalo-angular-kbd.d.ts +5 -0
  170. package/types/hyalo-angular-lightbox.d.ts +67 -0
  171. package/types/hyalo-angular-link.d.ts +5 -0
  172. package/types/hyalo-angular-list.d.ts +30 -0
  173. package/types/hyalo-angular-marquee.d.ts +48 -0
  174. package/types/hyalo-angular-menu.d.ts +105 -0
  175. package/types/hyalo-angular-mesh.d.ts +36 -0
  176. package/types/hyalo-angular-motion.d.ts +218 -0
  177. package/types/hyalo-angular-navigation-menu.d.ts +47 -0
  178. package/types/hyalo-angular-number-ticker.d.ts +52 -0
  179. package/types/hyalo-angular-overlay.d.ts +9 -0
  180. package/types/hyalo-angular-pagination.d.ts +59 -0
  181. package/types/hyalo-angular-popover.d.ts +10 -0
  182. package/types/hyalo-angular-progress.d.ts +46 -0
  183. package/types/hyalo-angular-progressive-blur.d.ts +14 -0
  184. package/types/hyalo-angular-refraction.d.ts +46 -0
  185. package/types/hyalo-angular-scroll-area.d.ts +18 -0
  186. package/types/hyalo-angular-scroll-to-top.d.ts +31 -0
  187. package/types/hyalo-angular-segmented.d.ts +1 -1
  188. package/types/hyalo-angular-select.d.ts +49 -3
  189. package/types/hyalo-angular-sidebar.d.ts +57 -0
  190. package/types/hyalo-angular-skeleton.d.ts +34 -0
  191. package/types/hyalo-angular-sparkline.d.ts +19 -0
  192. package/types/hyalo-angular-split-text.d.ts +24 -0
  193. package/types/hyalo-angular-stat.d.ts +56 -0
  194. package/types/hyalo-angular-stepper.d.ts +63 -0
  195. package/types/hyalo-angular-table.d.ts +125 -0
  196. package/types/hyalo-angular-timeline.d.ts +36 -0
  197. package/types/hyalo-angular.d.ts +2 -345
  198. 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, MOTION, ɵmatchesMedia } from "@hyalo/angular";
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 motion = inject(HyMotion);
126
- const destroyRef = inject(DestroyRef);
125
+ const scene = inject(HySceneLight), destroy = inject(DestroyRef);
127
126
  afterNextRender(() => {
128
- if (!ɵmatchesMedia("(hover: hover) and (pointer: fine)")) return;
129
- const h = handlers();
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 = null;
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
- quick = gsap.quickTo(el, name, {
165
- ...vars,
166
- unit
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
- return (value) => {
170
- if (quick) quick(value);
171
- else el.style.setProperty(name, `${value}${unit}`);
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":";;;;AAqCA,IAAa,iBAAb,MAAa,eAAc;CACN,OAAO,OAAO,cAAc;CAC5B,MAAM,OAAO,WAAW;CACxB,QAAQ,OACzB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO,SAAS,GAAG,KAAK,MAAM,KAAK,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC,GACzF,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACkB,QAAQ,eAAe,KAAK,KAAK,OAAO,KAAK,MAAK,IAAI,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC/D,KAAK,OAAa;EAC1B,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO,SAAS,GAAG,IAAI,KAAK,CAAC,CAAC;CACxF;CACU,MAAM,OAAoB;EAClC,IAAK,MAAM,OAAuB,QAAQ,yBAAyB,GAAG;EACtE,MAAM,MACH,MAAM,cAA8B,cAAc,aAAa,iBAC9D,MAAM,aAA4B,CACnC,CAAC,cAAc;EAClB,IAAI,MAAM,QAAQ,cAAc;GAC9B,MAAM,eAAc;GACpB,KAAK,KAAK,MAAM,KAAK,CAAC;EACxB,OAAO,IAAI,MAAM,QAAQ,aAAa;GACpC,MAAM,eAAc;GACpB,KAAK,KAAK,MAAM,IAAI,EAAE;EACxB;CACF;CAvBW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAc,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAd,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAc,cAAA;EAAA,UAAA;EAAA,MAAA,EAAA,WAAA,EAAA,WAAA,gBAAA,EAAA;EAAA,UAAA;EAAA,UCrC3B;EA4BA,QAAA,CAAA,iWAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MDGY;GAAQ,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAMP,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAc,YAAA,CAAA;EAR1B,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAkB,SACnB,CAAC,QAAQ;GAAC,iBACF,wBAAwB;GAAM,MACzC,EAAE,aAAa,gBAAe;GAAE,UAAA;GAAA,QAAA,CAAA,iWAAA;EAAA,CAAA;;;AA+BxC,IAAa,aAAb,MAAa,WAAU;CACJ,SAAS,OAAO,QAAQ;CACzC,KAAK,QAAmC,UAA6B,CAAA,GAAE;EACrE,IAAI,CAAC,OAAO,QAAQ,OAAO;EAC3B,OAAO,KAAK,OAAO,KAAK,gBAAgB;GACtC,MAAM;GACN,OAAO,QAAQ,SAAS;GACxB,MAAM;IAAE,GAAG;IAAS;GAAM;EAC3B,CAAA;CACH;CATW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAV,OAAA,QAAA,GAAA,sBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,YADG;CAAM,CAAA;;AACnB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAU,YAAA,CAAA;EADtB,MAAA;EAAW,MAAA,CAAA,EAAE,YAAY,OAAM,CAAE;;;AAkBlC,IAAa,YAAb,MAAa,UAAS;CACH,WAAW,OAAO,UAAU;CACpC,SAAS,MAAM,SAAqC,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACpD,QAAQ,MAAM,iBAAgB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,YAAY,MAAM,cAAa,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC/B,UAAU,MAAyB,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC/C,KAAK,OAAa;EAChB,KAAK,SAAS,KAAK,KAAK,OAAM,GAAI;GAAE,GAAG,KAAK,QAAO;GAAI,OAAO,KAAK,MAAK;GAAI;EAAK,CAAE;CACrF;CARW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAS,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAT,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAS,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UEjFtB;EAOA,QAAA,CAAA,iaAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AF0Ea,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAS,YAAA,CAAA;EANrB,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAY,iBACL,wBAAwB;GAAM,UAAA;GAAA,QAAA,CAAA,iaAAA;EAAA,CAAA"}
@@ -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"}