@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,4 +1,4 @@
1
- import { MOTION } from "@hyalo/angular";
1
+ import { MOTION } from "@hyalo/angular/motion";
2
2
  const OPPOSITE = {
3
3
  top: "bottom",
4
4
  bottom: "top",
@@ -89,6 +89,75 @@ var HyPresence = class {
89
89
  this.cancel = stop;
90
90
  }
91
91
  };
92
- export { hyConnectedPositions, hyDropdownPositions, HyPresence as ɵHyPresence };
92
+ function triangle(p, a, b, c) {
93
+ const side = (u, v, w) => (u.x - w.x) * (v.y - w.y) - (v.x - w.x) * (u.y - w.y);
94
+ const d = [
95
+ side(p, a, b),
96
+ side(p, b, c),
97
+ side(p, c, a)
98
+ ];
99
+ return !(d.some((v) => v < 0) && d.some((v) => v > 0));
100
+ }
101
+ var HyHoverIntent = class {
102
+ document;
103
+ timer;
104
+ abort;
105
+ constructor(document) {
106
+ this.document = document;
107
+ }
108
+ cancel() {
109
+ clearTimeout(this.timer);
110
+ this.abort?.abort();
111
+ this.abort = void 0;
112
+ }
113
+ leave(event, target, close) {
114
+ this.cancel();
115
+ const finish = () => {
116
+ this.cancel();
117
+ close();
118
+ };
119
+ this.timer = setTimeout(finish, 150);
120
+ if (!event || !target || event.pointerType === "touch") return;
121
+ const bounds = target.getBoundingClientRect(), start = {
122
+ x: event.clientX,
123
+ y: event.clientY
124
+ };
125
+ const dx = (bounds.left + bounds.right) / 2 - start.x, dy = (bounds.top + bounds.bottom) / 2 - start.y;
126
+ const horizontal = Math.abs(dx) / Math.max(1, bounds.width) > Math.abs(dy) / Math.max(1, bounds.height);
127
+ const edge = horizontal ? dx > 0 ? bounds.left : bounds.right : dy > 0 ? bounds.top : bounds.bottom;
128
+ const a = horizontal ? {
129
+ x: edge,
130
+ y: bounds.top - 8
131
+ } : {
132
+ x: bounds.left - 8,
133
+ y: edge
134
+ };
135
+ const b = horizontal ? {
136
+ x: edge,
137
+ y: bounds.bottom + 8
138
+ } : {
139
+ x: bounds.right + 8,
140
+ y: edge
141
+ };
142
+ const deadline = performance.now() + 500;
143
+ this.abort = new AbortController();
144
+ this.document.addEventListener("pointermove", (move) => {
145
+ if (performance.now() >= deadline) {
146
+ finish();
147
+ return;
148
+ }
149
+ if (!triangle({
150
+ x: move.clientX,
151
+ y: move.clientY
152
+ }, start, a, b)) return;
153
+ clearTimeout(this.timer);
154
+ this.timer = setTimeout(finish, Math.min(150, deadline - performance.now()));
155
+ }, {
156
+ passive: true,
157
+ signal: this.abort.signal
158
+ });
159
+ }
160
+ };
161
+ export { HyHoverIntent, hyConnectedPositions, hyDropdownPositions, HyPresence as ɵHyPresence };
93
162
 
94
163
  //# sourceMappingURL=hyalo-angular-overlay.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"hyalo-angular-overlay.mjs","names":[],"sources":["../../../projects/hyalo/overlay/positions.ts","../../../projects/hyalo/overlay/presence.ts"],"sourcesContent":["import type { ConnectedPosition } from '@angular/cdk/overlay';\r\n\r\n/**\r\n * Where a floating element sits relative to its trigger. `start` and `end`\r\n * follow the text direction, so `end` is on the right in LTR and on the left\r\n * in RTL.\r\n */\r\nexport type HyPlacement = 'top' | 'bottom' | 'start' | 'end';\r\n\r\nconst OPPOSITE: Record<HyPlacement, HyPlacement> = {\r\n top: 'bottom',\r\n bottom: 'top',\r\n start: 'end',\r\n end: 'start',\r\n};\r\n\r\nfunction position(placement: HyPlacement, offset: number): ConnectedPosition {\r\n switch (placement) {\r\n case 'top':\r\n return {\r\n originX: 'center',\r\n originY: 'top',\r\n overlayX: 'center',\r\n overlayY: 'bottom',\r\n offsetY: -offset,\r\n };\r\n case 'bottom':\r\n return {\r\n originX: 'center',\r\n originY: 'bottom',\r\n overlayX: 'center',\r\n overlayY: 'top',\r\n offsetY: offset,\r\n };\r\n case 'start':\r\n return {\r\n originX: 'start',\r\n originY: 'center',\r\n overlayX: 'end',\r\n overlayY: 'center',\r\n offsetX: -offset,\r\n };\r\n case 'end':\r\n return {\r\n originX: 'end',\r\n originY: 'center',\r\n overlayX: 'start',\r\n overlayY: 'center',\r\n offsetX: offset,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * CDK positions for a placement, with the opposite side as the first\r\n * fallback when there is no room.\r\n */\r\nexport function hyConnectedPositions(placement: HyPlacement, offset = 8): ConnectedPosition[] {\r\n return [position(placement, offset), position(OPPOSITE[placement], offset)];\r\n}\r\n\r\n/** Positions for a dropdown that lines up with the trigger's start edge. */\r\nexport function hyDropdownPositions(offset = 6): ConnectedPosition[] {\r\n return [\r\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset },\r\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset },\r\n ];\r\n}\r\n","import { MOTION } from '@hyalo/angular';\r\n\r\n/**\r\n * @internal Enter and exit for small overlays (tooltips, popovers, select\r\n * panels), driven by `data-state` and CSS transitions.\r\n *\r\n * Transitions start from the current value, so reopening a panel while it\r\n * is still fading out simply turns it around, with no jump.\r\n */\r\nexport class HyPresence {\r\n private cancel: (() => void) | null = null;\r\n\r\n /** True while an exit is playing. */\r\n get leaving(): boolean {\r\n return this.cancel !== null;\r\n }\r\n\r\n /** Shows a panel that was just attached, or turns a leaving one around. */\r\n enter(el: HTMLElement): void {\r\n if (this.cancel) {\r\n this.cancel();\r\n } else {\r\n el.dataset['state'] = 'closed';\r\n // Commit the closed pose so the change to open transitions.\r\n void el.offsetWidth;\r\n }\r\n el.dataset['state'] = 'open';\r\n }\r\n\r\n /** Plays the exit, then calls `done`, unless `enter` turns it around first. */\r\n leave(el: HTMLElement, done: () => void): void {\r\n if (this.cancel) return;\r\n el.dataset['state'] = 'closing';\r\n const stop = (): void => {\r\n el.removeEventListener('transitionend', onEnd);\r\n clearTimeout(timer);\r\n this.cancel = null;\r\n };\r\n const onEnd = (event: TransitionEvent): void => {\r\n if (event.target !== el || event.propertyName !== 'opacity') return;\r\n stop();\r\n done();\r\n };\r\n // A safety net for when transitionend never comes, as with no transition.\r\n const timer = setTimeout(\r\n () => {\r\n stop();\r\n done();\r\n },\r\n MOTION.quick.duration * 1000 + 80,\r\n );\r\n el.addEventListener('transitionend', onEnd);\r\n this.cancel = stop;\r\n }\r\n}\r\n"],"mappings":";AASA,MAAM,WAA6C;CACjD,KAAK;CACL,QAAQ;CACR,OAAO;CACP,KAAK;AACN;AAED,SAAS,SAAS,WAAwB,QAAc;CACtD,QAAQ,WAAR;EACE,KAAK,OACH,OAAO;GACL,SAAS;GACT,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS,CAAC;EACX;EACH,KAAK,UACH,OAAO;GACL,SAAS;GACT,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACV;EACH,KAAK,SACH,OAAO;GACL,SAAS;GACT,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS,CAAC;EACX;EACH,KAAK,OACH,OAAO;GACL,SAAS;GACT,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACV;CACL;AACF;AAMA,SAAgB,qBAAqB,WAAwB,SAAS,GAAC;CACrE,OAAO,CAAC,SAAS,WAAW,MAAM,GAAG,SAAS,SAAS,YAAY,MAAM,CAAC;AAC5E;AAGA,SAAgB,oBAAoB,SAAS,GAAC;CAC5C,OAAO,CACL;EAAE,SAAS;EAAS,SAAS;EAAU,UAAU;EAAS,UAAU;EAAO,SAAS;CAAM,GAC1F;EAAE,SAAS;EAAS,SAAS;EAAO,UAAU;EAAS,UAAU;EAAU,SAAS,CAAC;CAAM,CAC5F;AACH;AC1DA,IAAa,aAAb,MAAuB;CACb,SAA8B;CAGtC,IAAI,UAAO;EACT,OAAO,KAAK,WAAW;CACzB;CAGA,MAAM,IAAe;EACnB,IAAI,KAAK,QACP,KAAK,OAAM;OACN;GACL,GAAG,QAAQ,WAAW;GAEtB,AAAK,GAAG;EACV;EACA,GAAG,QAAQ,WAAW;CACxB;CAGA,MAAM,IAAiB,MAAgB;EACrC,IAAI,KAAK,QAAQ;EACjB,GAAG,QAAQ,WAAW;EACtB,MAAM,aAAkB;GACtB,GAAG,oBAAoB,iBAAiB,KAAK;GAC7C,aAAa,KAAK;GAClB,KAAK,SAAS;EAChB;EACA,MAAM,SAAS,UAAgC;GAC7C,IAAI,MAAM,WAAW,MAAM,MAAM,iBAAiB,WAAW;GAC7D,KAAI;GACJ,KAAI;EACN;EAEA,MAAM,QAAQ,iBACP;GACH,KAAI;GACJ,KAAI;EACN,GACA,OAAO,MAAM,WAAW,MAAO,EAAE;EAEnC,GAAG,iBAAiB,iBAAiB,KAAK;EAC1C,KAAK,SAAS;CAChB;AACD"}
1
+ {"version":3,"file":"hyalo-angular-overlay.mjs","names":[],"sources":["../../../projects/hyalo/overlay/positions.ts","../../../projects/hyalo/overlay/presence.ts","../../../projects/hyalo/overlay/hover-intent.ts"],"sourcesContent":["import type { ConnectedPosition } from '@angular/cdk/overlay';\r\n\r\n/**\r\n * Where a floating element sits relative to its trigger. `start` and `end`\r\n * follow the text direction, so `end` is on the right in LTR and on the left\r\n * in RTL.\r\n */\r\nexport type HyPlacement = 'top' | 'bottom' | 'start' | 'end';\r\n\r\nconst OPPOSITE: Record<HyPlacement, HyPlacement> = {\r\n top: 'bottom',\r\n bottom: 'top',\r\n start: 'end',\r\n end: 'start',\r\n};\r\n\r\nfunction position(placement: HyPlacement, offset: number): ConnectedPosition {\r\n switch (placement) {\r\n case 'top':\r\n return {\r\n originX: 'center',\r\n originY: 'top',\r\n overlayX: 'center',\r\n overlayY: 'bottom',\r\n offsetY: -offset,\r\n };\r\n case 'bottom':\r\n return {\r\n originX: 'center',\r\n originY: 'bottom',\r\n overlayX: 'center',\r\n overlayY: 'top',\r\n offsetY: offset,\r\n };\r\n case 'start':\r\n return {\r\n originX: 'start',\r\n originY: 'center',\r\n overlayX: 'end',\r\n overlayY: 'center',\r\n offsetX: -offset,\r\n };\r\n case 'end':\r\n return {\r\n originX: 'end',\r\n originY: 'center',\r\n overlayX: 'start',\r\n overlayY: 'center',\r\n offsetX: offset,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * CDK positions for a placement, with the opposite side as the first\r\n * fallback when there is no room.\r\n */\r\nexport function hyConnectedPositions(placement: HyPlacement, offset = 8): ConnectedPosition[] {\r\n return [position(placement, offset), position(OPPOSITE[placement], offset)];\r\n}\r\n\r\n/** Positions for a dropdown that lines up with the trigger's start edge. */\r\nexport function hyDropdownPositions(offset = 6): ConnectedPosition[] {\r\n return [\r\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset },\r\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset },\r\n ];\r\n}\r\n","import { MOTION } from '@hyalo/angular/motion';\r\n\r\n/**\r\n * @internal Enter and exit for small overlays (tooltips, popovers, select\r\n * panels), driven by `data-state` and CSS transitions.\r\n *\r\n * Transitions start from the current value, so reopening a panel while it\r\n * is still fading out simply turns it around, with no jump.\r\n */\r\nexport class HyPresence {\r\n private cancel: (() => void) | null = null;\r\n\r\n /** True while an exit is playing. */\r\n get leaving(): boolean {\r\n return this.cancel !== null;\r\n }\r\n\r\n /** Shows a panel that was just attached, or turns a leaving one around. */\r\n enter(el: HTMLElement): void {\r\n if (this.cancel) {\r\n this.cancel();\r\n } else {\r\n el.dataset['state'] = 'closed';\r\n // Commit the closed pose so the change to open transitions.\r\n void el.offsetWidth;\r\n }\r\n el.dataset['state'] = 'open';\r\n }\r\n\r\n /** Plays the exit, then calls `done`, unless `enter` turns it around first. */\r\n leave(el: HTMLElement, done: () => void): void {\r\n if (this.cancel) return;\r\n el.dataset['state'] = 'closing';\r\n const stop = (): void => {\r\n el.removeEventListener('transitionend', onEnd);\r\n clearTimeout(timer);\r\n this.cancel = null;\r\n };\r\n const onEnd = (event: TransitionEvent): void => {\r\n if (event.target !== el || event.propertyName !== 'opacity') return;\r\n stop();\r\n done();\r\n };\r\n // A safety net for when transitionend never comes, as with no transition.\r\n const timer = setTimeout(\r\n () => {\r\n stop();\r\n done();\r\n },\r\n MOTION.quick.duration * 1000 + 80,\r\n );\r\n el.addEventListener('transitionend', onEnd);\r\n this.cancel = stop;\r\n }\r\n}\r\n","interface Point {\r\n x: number;\r\n y: number;\r\n}\r\nfunction triangle(p: Point, a: Point, b: Point, c: Point): boolean {\r\n const side = (u: Point, v: Point, w: Point): number =>\r\n (u.x - w.x) * (v.y - w.y) - (v.x - w.x) * (u.y - w.y);\r\n const d = [side(p, a, b), side(p, b, c), side(p, c, a)];\r\n return !(d.some((v) => v < 0) && d.some((v) => v > 0));\r\n}\r\n/** Bounded pointer grace; keyboard dismissal never waits for the corridor. */\r\nexport class HyHoverIntent {\r\n private timer?: ReturnType<typeof setTimeout>;\r\n private abort?: AbortController;\r\n constructor(private readonly document: Document) {}\r\n cancel(): void {\r\n clearTimeout(this.timer);\r\n this.abort?.abort();\r\n this.abort = undefined;\r\n }\r\n leave(event: PointerEvent | undefined, target: HTMLElement | undefined, close: () => void): void {\r\n this.cancel();\r\n const finish = (): void => {\r\n this.cancel();\r\n close();\r\n };\r\n this.timer = setTimeout(finish, 150);\r\n if (!event || !target || event.pointerType === 'touch') return;\r\n const bounds = target.getBoundingClientRect(),\r\n start = { x: event.clientX, y: event.clientY };\r\n const dx = (bounds.left + bounds.right) / 2 - start.x,\r\n dy = (bounds.top + bounds.bottom) / 2 - start.y;\r\n const horizontal =\r\n Math.abs(dx) / Math.max(1, bounds.width) > Math.abs(dy) / Math.max(1, bounds.height);\r\n const edge = horizontal\r\n ? dx > 0\r\n ? bounds.left\r\n : bounds.right\r\n : dy > 0\r\n ? bounds.top\r\n : bounds.bottom;\r\n const a = horizontal ? { x: edge, y: bounds.top - 8 } : { x: bounds.left - 8, y: edge };\r\n const b = horizontal ? { x: edge, y: bounds.bottom + 8 } : { x: bounds.right + 8, y: edge };\r\n const deadline = performance.now() + 500;\r\n this.abort = new AbortController();\r\n this.document.addEventListener(\r\n 'pointermove',\r\n (move) => {\r\n if (performance.now() >= deadline) {\r\n finish();\r\n return;\r\n }\r\n if (!triangle({ x: move.clientX, y: move.clientY }, start, a, b)) return;\r\n clearTimeout(this.timer);\r\n this.timer = setTimeout(finish, Math.min(150, deadline - performance.now()));\r\n },\r\n { passive: true, signal: this.abort.signal },\r\n );\r\n }\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ import { HyLocale } from "@hyalo/angular/core";
2
+ import * as i0 from "@angular/core";
3
+ import { ChangeDetectionStrategy, Component, computed, inject, input, model } from "@angular/core";
4
+ const positive = (value) => Number.isFinite(value) ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(1, Math.floor(value))) : 1;
5
+ var HyPagination = class HyPagination {
6
+ page = model(1, ...ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []);
7
+ total = input.required(...ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []);
8
+ pageSize = input(10, ...ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []);
9
+ locale = input(...ngDevMode ? [void 0, { debugName: "locale" }] : /* istanbul ignore next */ []);
10
+ globalLocale = inject(HyLocale);
11
+ effectiveLocale = computed(() => this.locale() ?? this.globalLocale.locale(), ...ngDevMode ? [{ debugName: "effectiveLocale" }] : /* istanbul ignore next */ []);
12
+ label = input("Pagination", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
13
+ previousLabel = input("Previous page", ...ngDevMode ? [{ debugName: "previousLabel" }] : /* istanbul ignore next */ []);
14
+ nextLabel = input("Next page", ...ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []);
15
+ pageCount = computed(() => Math.max(1, Math.min(Number.MAX_SAFE_INTEGER, Math.ceil((Number.isFinite(this.total()) ? Math.max(0, this.total()) : 0) / positive(this.pageSize())))), ...ngDevMode ? [{ debugName: "pageCount" }] : /* istanbul ignore next */ []);
16
+ current = computed(() => Math.min(this.pageCount(), positive(this.page())), ...ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []);
17
+ pages = computed(() => {
18
+ const current = this.current(), last = this.pageCount(), set = /* @__PURE__ */ new Set([1, last]);
19
+ for (let n = Math.max(1, current - 1); n <= Math.min(last, current + 1); n++) set.add(n);
20
+ const nums = [...set].sort((a, b) => a - b), result = [];
21
+ const fmt = new Intl.NumberFormat(this.effectiveLocale());
22
+ let previous = 0;
23
+ for (const value of nums) {
24
+ if (previous && value - previous > 1) result.push(null);
25
+ result.push({
26
+ value,
27
+ label: fmt.format(value)
28
+ });
29
+ previous = value;
30
+ }
31
+ return result;
32
+ }, ...ngDevMode ? [{ debugName: "pages" }] : /* istanbul ignore next */ []);
33
+ go(page) {
34
+ const next = Math.min(this.pageCount(), positive(page));
35
+ if (next !== this.current()) this.page.set(next);
36
+ }
37
+ static ɵfac = i0.ɵɵngDeclareFactory({
38
+ minVersion: "12.0.0",
39
+ version: "22.2.3",
40
+ ngImport: i0,
41
+ type: HyPagination,
42
+ deps: [],
43
+ target: i0.ɵɵFactoryTarget.Component
44
+ });
45
+ static ɵcmp = i0.ɵɵngDeclareComponent({
46
+ minVersion: "17.0.0",
47
+ version: "22.2.3",
48
+ type: HyPagination,
49
+ isStandalone: true,
50
+ selector: "hy-pagination",
51
+ inputs: {
52
+ page: {
53
+ classPropertyName: "page",
54
+ publicName: "page",
55
+ isSignal: true,
56
+ isRequired: false,
57
+ transformFunction: null
58
+ },
59
+ total: {
60
+ classPropertyName: "total",
61
+ publicName: "total",
62
+ isSignal: true,
63
+ isRequired: true,
64
+ transformFunction: null
65
+ },
66
+ pageSize: {
67
+ classPropertyName: "pageSize",
68
+ publicName: "pageSize",
69
+ isSignal: true,
70
+ isRequired: false,
71
+ transformFunction: null
72
+ },
73
+ locale: {
74
+ classPropertyName: "locale",
75
+ publicName: "locale",
76
+ isSignal: true,
77
+ isRequired: false,
78
+ transformFunction: null
79
+ },
80
+ label: {
81
+ classPropertyName: "label",
82
+ publicName: "label",
83
+ isSignal: true,
84
+ isRequired: false,
85
+ transformFunction: null
86
+ },
87
+ previousLabel: {
88
+ classPropertyName: "previousLabel",
89
+ publicName: "previousLabel",
90
+ isSignal: true,
91
+ isRequired: false,
92
+ transformFunction: null
93
+ },
94
+ nextLabel: {
95
+ classPropertyName: "nextLabel",
96
+ publicName: "nextLabel",
97
+ isSignal: true,
98
+ isRequired: false,
99
+ transformFunction: null
100
+ }
101
+ },
102
+ outputs: { page: "pageChange" },
103
+ ngImport: i0,
104
+ template: "<nav [attr.aria-label]=\"label()\">\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"previousLabel()\"\r\n [disabled]=\"current() === 1\"\r\n (click)=\"go(current() - 1)\"\r\n >\r\n <span aria-hidden=\"true\" class=\"arrow\">‹</span>\r\n </button>\r\n @for (item of pages(); track $index) {\r\n @if (item) {\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"'Page ' + item.label\"\r\n [attr.aria-current]=\"item.value === current() ? 'page' : null\"\r\n (click)=\"go(item.value)\"\r\n >\r\n {{ item.label }}\r\n </button>\r\n } @else {\r\n <span aria-hidden=\"true\">…</span>\r\n }\r\n }\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"nextLabel()\"\r\n [disabled]=\"current() === pageCount()\"\r\n (click)=\"go(current() + 1)\"\r\n >\r\n <span aria-hidden=\"true\" class=\"arrow\">›</span>\r\n </button>\r\n</nav>\r\n",
105
+ styles: [":host{display:block}nav{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem}button{min-inline-size:44px;min-block-size:44px;padding:.5rem;border:1px solid transparent;border-radius:var(--hy-radius-s);background:transparent;color:var(--hy-ink);font:inherit;font-variant-numeric:tabular-nums;cursor:pointer}button:hover:enabled{background:var(--hy-surface-3)}button[aria-current]{background:var(--hy-primary);color:var(--hy-primary-ink)}button:disabled{opacity:.4;cursor:default}.arrow{display:block;font-size:1.5rem}:host-context([dir=\"rtl\"]) .arrow{transform:scaleX(-1)}:is(button,a,input):focus-visible{outline:2px solid var(--hy-primary);outline-offset:3px}\n"],
106
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
107
+ });
108
+ };
109
+ i0.ɵɵngDeclareClassMetadata({
110
+ minVersion: "12.0.0",
111
+ version: "22.2.3",
112
+ ngImport: i0,
113
+ type: HyPagination,
114
+ decorators: [{
115
+ type: Component,
116
+ args: [{
117
+ selector: "hy-pagination",
118
+ changeDetection: ChangeDetectionStrategy.OnPush,
119
+ template: "<nav [attr.aria-label]=\"label()\">\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"previousLabel()\"\r\n [disabled]=\"current() === 1\"\r\n (click)=\"go(current() - 1)\"\r\n >\r\n <span aria-hidden=\"true\" class=\"arrow\">‹</span>\r\n </button>\r\n @for (item of pages(); track $index) {\r\n @if (item) {\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"'Page ' + item.label\"\r\n [attr.aria-current]=\"item.value === current() ? 'page' : null\"\r\n (click)=\"go(item.value)\"\r\n >\r\n {{ item.label }}\r\n </button>\r\n } @else {\r\n <span aria-hidden=\"true\">…</span>\r\n }\r\n }\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"nextLabel()\"\r\n [disabled]=\"current() === pageCount()\"\r\n (click)=\"go(current() + 1)\"\r\n >\r\n <span aria-hidden=\"true\" class=\"arrow\">›</span>\r\n </button>\r\n</nav>\r\n",
120
+ styles: [":host{display:block}nav{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem}button{min-inline-size:44px;min-block-size:44px;padding:.5rem;border:1px solid transparent;border-radius:var(--hy-radius-s);background:transparent;color:var(--hy-ink);font:inherit;font-variant-numeric:tabular-nums;cursor:pointer}button:hover:enabled{background:var(--hy-surface-3)}button[aria-current]{background:var(--hy-primary);color:var(--hy-primary-ink)}button:disabled{opacity:.4;cursor:default}.arrow{display:block;font-size:1.5rem}:host-context([dir=\"rtl\"]) .arrow{transform:scaleX(-1)}:is(button,a,input):focus-visible{outline:2px solid var(--hy-primary);outline-offset:3px}\n"]
121
+ }]
122
+ }],
123
+ propDecorators: {
124
+ page: [{
125
+ type: i0.Input,
126
+ args: [{
127
+ isSignal: true,
128
+ alias: "page",
129
+ required: false
130
+ }]
131
+ }, {
132
+ type: i0.Output,
133
+ args: ["pageChange"]
134
+ }],
135
+ total: [{
136
+ type: i0.Input,
137
+ args: [{
138
+ isSignal: true,
139
+ alias: "total",
140
+ required: true
141
+ }]
142
+ }],
143
+ pageSize: [{
144
+ type: i0.Input,
145
+ args: [{
146
+ isSignal: true,
147
+ alias: "pageSize",
148
+ required: false
149
+ }]
150
+ }],
151
+ locale: [{
152
+ type: i0.Input,
153
+ args: [{
154
+ isSignal: true,
155
+ alias: "locale",
156
+ required: false
157
+ }]
158
+ }],
159
+ label: [{
160
+ type: i0.Input,
161
+ args: [{
162
+ isSignal: true,
163
+ alias: "label",
164
+ required: false
165
+ }]
166
+ }],
167
+ previousLabel: [{
168
+ type: i0.Input,
169
+ args: [{
170
+ isSignal: true,
171
+ alias: "previousLabel",
172
+ required: false
173
+ }]
174
+ }],
175
+ nextLabel: [{
176
+ type: i0.Input,
177
+ args: [{
178
+ isSignal: true,
179
+ alias: "nextLabel",
180
+ required: false
181
+ }]
182
+ }]
183
+ }
184
+ });
185
+ export { HyPagination };
186
+
187
+ //# sourceMappingURL=hyalo-angular-pagination.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-pagination.mjs","names":[],"sources":["../../../projects/hyalo/pagination/pagination.ts","../../../projects/hyalo/pagination/pagination.html"],"sourcesContent":["import { HyLocale } from '@hyalo/angular/core';\r\nimport { ChangeDetectionStrategy, Component, computed, input, model } from '@angular/core';\r\nimport { inject } from '@angular/core';\r\nconst positive = (value: number): number =>\r\n Number.isFinite(value) ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(1, Math.floor(value))) : 1;\r\n@Component({\r\n selector: 'hy-pagination',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './pagination.html',\r\n styleUrl: './pagination.css',\r\n})\r\nexport class HyPagination {\r\n readonly page = model(1);\r\n readonly total = input.required<number>();\r\n readonly pageSize = input(10);\r\n readonly locale = input<string>();\r\n private readonly globalLocale = inject(HyLocale);\r\n private readonly effectiveLocale = computed(() => this.locale() ?? this.globalLocale.locale());\r\n readonly label = input('Pagination');\r\n readonly previousLabel = input('Previous page');\r\n readonly nextLabel = input('Next page');\r\n readonly pageCount = computed(() =>\r\n Math.max(\r\n 1,\r\n Math.min(\r\n Number.MAX_SAFE_INTEGER,\r\n Math.ceil(\r\n (Number.isFinite(this.total()) ? Math.max(0, this.total()) : 0) /\r\n positive(this.pageSize()),\r\n ),\r\n ),\r\n ),\r\n );\r\n readonly current = computed(() => Math.min(this.pageCount(), positive(this.page())));\r\n readonly pages = computed(() => {\r\n const current = this.current(),\r\n last = this.pageCount(),\r\n set = new Set([1, last]);\r\n for (let n = Math.max(1, current - 1); n <= Math.min(last, current + 1); n++) set.add(n);\r\n const nums = [...set].sort((a, b) => a - b),\r\n result: ({ value: number; label: string } | null)[] = [];\r\n const fmt = new Intl.NumberFormat(this.effectiveLocale());\r\n let previous = 0;\r\n for (const value of nums) {\r\n if (previous && value - previous > 1) result.push(null);\r\n result.push({ value, label: fmt.format(value) });\r\n previous = value;\r\n }\r\n return result;\r\n });\r\n go(page: number): void {\r\n const next = Math.min(this.pageCount(), positive(page));\r\n if (next !== this.current()) this.page.set(next);\r\n }\r\n}\r\n","<nav [attr.aria-label]=\"label()\">\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"previousLabel()\"\r\n [disabled]=\"current() === 1\"\r\n (click)=\"go(current() - 1)\"\r\n >\r\n <span aria-hidden=\"true\" class=\"arrow\">‹</span>\r\n </button>\r\n @for (item of pages(); track $index) {\r\n @if (item) {\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"'Page ' + item.label\"\r\n [attr.aria-current]=\"item.value === current() ? 'page' : null\"\r\n (click)=\"go(item.value)\"\r\n >\r\n {{ item.label }}\r\n </button>\r\n } @else {\r\n <span aria-hidden=\"true\">…</span>\r\n }\r\n }\r\n <button\r\n type=\"button\"\r\n [attr.aria-label]=\"nextLabel()\"\r\n [disabled]=\"current() === pageCount()\"\r\n (click)=\"go(current() + 1)\"\r\n >\r\n <span aria-hidden=\"true\" class=\"arrow\">›</span>\r\n </button>\r\n</nav>\r\n"],"mappings":"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"}
@@ -2,7 +2,8 @@ import { AriaDescriber, FocusTrapFactory } from "@angular/cdk/a11y";
2
2
  import * as i0 from "@angular/core";
3
3
  import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injector, ViewContainerRef, booleanAttribute, effect, inject, input, model, numberAttribute, signal, untracked } from "@angular/core";
4
4
  import { hyConnectedPositions, ɵHyPresence } from "@hyalo/angular/overlay";
5
- import { HyFidelity, injectId } from "@hyalo/angular";
5
+ import { take } from "rxjs";
6
+ import { HyFidelity, injectId } from "@hyalo/angular/core";
6
7
  let kit;
7
8
  function loadOverlay() {
8
9
  kit ??= import("./hyalo-angular-popover-overlay-kit-6wPwnxln.mjs").catch((error) => {
@@ -270,11 +271,13 @@ var HyPopover = class HyPopover {
270
271
  position = null;
271
272
  presence = new ɵHyPresence();
272
273
  destroyed = false;
274
+ positioned = false;
273
275
  content = input.required({
274
276
  ...ngDevMode ? { debugName: "content" } : /* istanbul ignore next */ {},
275
277
  alias: "hyPopover"
276
278
  });
277
279
  popoverLabel = input(...ngDevMode ? [void 0, { debugName: "popoverLabel" }] : /* istanbul ignore next */ []);
280
+ popoverMaterial = input("frosted", ...ngDevMode ? [{ debugName: "popoverMaterial" }] : /* istanbul ignore next */ []);
278
281
  popoverPlacement = input("bottom", ...ngDevMode ? [{ debugName: "popoverPlacement" }] : /* istanbul ignore next */ []);
279
282
  open = model(false, {
280
283
  ...ngDevMode ? { debugName: "open" } : /* istanbul ignore next */ {},
@@ -328,11 +331,10 @@ var HyPopover = class HyPopover {
328
331
  });
329
332
  }
330
333
  if (this.overlayRef.hasAttached()) {
331
- if (this.presence.leaving) this.presence.enter(this.overlayRef.overlayElement);
334
+ if (this.presence.leaving && this.positioned) this.reveal(this.overlayRef.overlayElement);
332
335
  return;
333
336
  }
334
337
  this.position?.withPositions(hyConnectedPositions(this.popoverPlacement(), 10));
335
- this.overlayRef.attach(new TemplatePortal(this.content(), this.viewContainer));
336
338
  const pane = this.overlayRef.overlayElement;
337
339
  pane.id = this.panelId;
338
340
  pane.setAttribute("role", "dialog");
@@ -340,12 +342,24 @@ var HyPopover = class HyPopover {
340
342
  if (label) pane.setAttribute("aria-label", label);
341
343
  else pane.removeAttribute("aria-label");
342
344
  pane.classList.add("hy-glass", "hy-popover");
343
- pane.dataset["material"] = this.fidelity.tier() === "low" ? "solid" : "frosted";
345
+ pane.dataset["material"] = this.fidelity.tier() === "low" ? "solid" : this.popoverMaterial();
346
+ pane.dataset["state"] = "closed";
347
+ pane.style.visibility = "hidden";
348
+ this.positioned = false;
344
349
  pane.addEventListener("focusout", this.onFocusOut);
350
+ this.position?.positionChanges.pipe(take(1)).subscribe(() => {
351
+ this.positioned = true;
352
+ if (this.destroyed || !this.open() || !this.overlayRef?.hasAttached()) return;
353
+ this.reveal(pane);
354
+ });
355
+ this.overlayRef.attach(new TemplatePortal(this.content(), this.viewContainer));
356
+ }
357
+ reveal(pane) {
358
+ pane.style.removeProperty("visibility");
345
359
  this.presence.enter(pane);
346
360
  const trap = this.focusTraps.create(pane);
347
361
  trap.focusFirstTabbableElementWhenReady().then((found) => {
348
- if (!found) {
362
+ if (!found && this.open() && !this.destroyed) {
349
363
  pane.tabIndex = -1;
350
364
  pane.focus();
351
365
  }
@@ -391,6 +405,13 @@ var HyPopover = class HyPopover {
391
405
  isRequired: false,
392
406
  transformFunction: null
393
407
  },
408
+ popoverMaterial: {
409
+ classPropertyName: "popoverMaterial",
410
+ publicName: "popoverMaterial",
411
+ isSignal: true,
412
+ isRequired: false,
413
+ transformFunction: null
414
+ },
394
415
  popoverPlacement: {
395
416
  classPropertyName: "popoverPlacement",
396
417
  publicName: "popoverPlacement",
@@ -461,6 +482,14 @@ i0.ɵɵngDeclareClassMetadata({
461
482
  required: false
462
483
  }]
463
484
  }],
485
+ popoverMaterial: [{
486
+ type: i0.Input,
487
+ args: [{
488
+ isSignal: true,
489
+ alias: "popoverMaterial",
490
+ required: false
491
+ }]
492
+ }],
464
493
  popoverPlacement: [{
465
494
  type: i0.Input,
466
495
  args: [{
@@ -1 +1 @@
1
- {"version":3,"file":"hyalo-angular-popover.mjs","names":["HyPresence","HyPresence"],"sources":["../../../projects/hyalo/popover/load-overlay.ts","../../../projects/hyalo/popover/tooltip.ts","../../../projects/hyalo/popover/popover.ts"],"sourcesContent":["/**\r\n * @internal Loads the overlay code the first time a tooltip or popover is\r\n * about to open. A page full of triggers then costs nothing until someone\r\n * hovers or clicks one, and the import resolves to the same module when the\r\n * app already uses the overlay elsewhere.\r\n */\r\nexport type HyOverlayKit = typeof import('./overlay-kit');\r\n\r\nlet kit: Promise<HyOverlayKit> | undefined;\r\n\r\n/** @internal */\r\nexport function loadOverlay(): Promise<HyOverlayKit> {\r\n kit ??= import('./overlay-kit').catch((error: unknown) => {\r\n // A failed chunk load should not stick; the next open tries again.\r\n kit = undefined;\r\n throw error;\r\n });\r\n return kit;\r\n}\r\n","import { AriaDescriber } from '@angular/cdk/a11y';\r\nimport type { FlexibleConnectedPositionStrategy, OverlayRef } from '@angular/cdk/overlay';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n Injector,\r\n booleanAttribute,\r\n effect,\r\n inject,\r\n input,\r\n numberAttribute,\r\n signal,\r\n} from '@angular/core';\r\nimport {\r\n hyConnectedPositions,\r\n type HyPlacement,\r\n ɵHyPresence as HyPresence,\r\n} from '@hyalo/angular/overlay';\r\nimport { loadOverlay } from './load-overlay';\r\n\r\n@Component({\r\n selector: 'hy-tooltip-panel',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { class: 'hy-tooltip', 'aria-hidden': 'true' },\r\n template: `{{ message() }}`,\r\n})\r\nexport class HyTooltipPanel {\r\n readonly message = signal('');\r\n}\r\n\r\n/**\r\n * A short text hint on hover or keyboard focus.\r\n *\r\n * ```html\r\n * <button hyButton iconOnly aria-label=\"Copy link\" hyTooltip=\"Copy link\">...</button>\r\n * ```\r\n *\r\n * The text is also added to the trigger's `aria-describedby` through a\r\n * hidden element, so screen readers get it without the visual tooltip. The\r\n * tooltip stays open while the pointer is over it and closes on Escape, as\r\n * WCAG 1.4.13 asks. Keep it short and never put interactive content in it;\r\n * use `hyPopover` for that.\r\n */\r\n@Directive({\r\n selector: '[hyTooltip]',\r\n host: {\r\n '(pointerenter)': 'onPointerEnter($event)',\r\n '(pointerleave)': 'scheduleHide()',\r\n '(focusin)': 'show(0)',\r\n '(focusout)': 'hide()',\r\n '(keydown.escape)': 'hide()',\r\n },\r\n})\r\nexport class HyTooltip {\r\n private readonly injector = inject(Injector);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly describer = inject(AriaDescriber);\r\n private overlayRef: OverlayRef | null = null;\r\n private position: FlexibleConnectedPositionStrategy | null = null;\r\n private panel: HyTooltipPanel | null = null;\r\n private panelEl: HTMLElement | null = null;\r\n private readonly presence = new HyPresence();\r\n private showTimer: ReturnType<typeof setTimeout> | undefined;\r\n private hideTimer: ReturnType<typeof setTimeout> | undefined;\r\n /** True from show() until hide(), so a late overlay load knows to stop. */\r\n private wanted = false;\r\n private destroyed = false;\r\n\r\n /** The tooltip text. */\r\n readonly message = input('', { alias: 'hyTooltip' });\r\n /** Preferred side. Flips when there is no room. */\r\n readonly tooltipPlacement = input<HyPlacement>('top');\r\n /** Hover delay in milliseconds. Focus shows it right away. */\r\n readonly tooltipDelay = input(400, { transform: numberAttribute });\r\n readonly tooltipDisabled = input(false, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n let described = '';\r\n effect(() => {\r\n const message = this.message();\r\n if (described) this.describer.removeDescription(this.host.nativeElement, described);\r\n if (message) this.describer.describe(this.host.nativeElement, message);\r\n described = message;\r\n if (this.panel) this.panel.message.set(message);\r\n });\r\n inject(DestroyRef).onDestroy(() => {\r\n this.destroyed = true;\r\n clearTimeout(this.showTimer);\r\n clearTimeout(this.hideTimer);\r\n if (described) this.describer.removeDescription(this.host.nativeElement, described);\r\n this.overlayRef?.dispose();\r\n });\r\n }\r\n\r\n protected onPointerEnter(event: PointerEvent): void {\r\n if (event.pointerType !== 'touch') this.show(this.tooltipDelay());\r\n }\r\n\r\n /** Shows the tooltip after the given delay. */\r\n show(delay = this.tooltipDelay()): void {\r\n if (this.tooltipDisabled() || !this.message()) return;\r\n clearTimeout(this.hideTimer);\r\n clearTimeout(this.showTimer);\r\n this.wanted = true;\r\n // Load during the hover delay, so the tooltip is ready when it ends.\r\n loadOverlay().catch(() => undefined);\r\n this.showTimer = setTimeout(() => void this.attach(), delay);\r\n }\r\n\r\n /** Starts hiding the tooltip now. It fades out quickly. */\r\n hide(): void {\r\n this.wanted = false;\r\n clearTimeout(this.showTimer);\r\n clearTimeout(this.hideTimer);\r\n const ref = this.overlayRef;\r\n if (!ref?.hasAttached() || !this.panelEl) return;\r\n this.presence.leave(this.panelEl, () => ref.detach());\r\n }\r\n\r\n protected scheduleHide(): void {\r\n clearTimeout(this.showTimer);\r\n this.hideTimer = setTimeout(() => this.hide(), 120);\r\n }\r\n\r\n private async attach(): Promise<void> {\r\n const kit = await loadOverlay().catch(() => null);\r\n if (!kit || !this.wanted || this.destroyed) return;\r\n const {\r\n ComponentPortal,\r\n createFlexibleConnectedPositionStrategy,\r\n createOverlayRef,\r\n createRepositionScrollStrategy,\r\n } = kit;\r\n if (!this.overlayRef) {\r\n this.position = createFlexibleConnectedPositionStrategy(this.injector, this.host)\r\n .withFlexibleDimensions(false)\r\n .withViewportMargin(8)\r\n .withTransformOriginOn('.hy-tooltip');\r\n this.overlayRef = createOverlayRef(this.injector, {\r\n positionStrategy: this.position,\r\n scrollStrategy: createRepositionScrollStrategy(this.injector),\r\n panelClass: 'hy-tooltip-pane',\r\n });\r\n // Hovering the tooltip itself keeps it open.\r\n this.overlayRef.overlayElement.addEventListener('pointerenter', () =>\r\n clearTimeout(this.hideTimer),\r\n );\r\n this.overlayRef.overlayElement.addEventListener('pointerleave', () => this.scheduleHide());\r\n }\r\n if (this.overlayRef.hasAttached()) {\r\n if (this.presence.leaving && this.panelEl) this.presence.enter(this.panelEl);\r\n return;\r\n }\r\n // Read on every show, so a changed placement applies next time.\r\n this.position?.withPositions(hyConnectedPositions(this.tooltipPlacement()));\r\n const ref = this.overlayRef.attach(new ComponentPortal(HyTooltipPanel, null, this.injector));\r\n this.panel = ref.instance;\r\n this.panel.message.set(this.message());\r\n const el = ref.location.nativeElement as HTMLElement;\r\n this.panelEl = el;\r\n this.presence.enter(el);\r\n ref.onDestroy(() => {\r\n this.panel = null;\r\n this.panelEl = null;\r\n });\r\n }\r\n}\r\n","import { FocusTrapFactory } from '@angular/cdk/a11y';\r\nimport type { FlexibleConnectedPositionStrategy, OverlayRef } from '@angular/cdk/overlay';\r\nimport {\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n Injector,\r\n TemplateRef,\r\n ViewContainerRef,\r\n inject,\r\n input,\r\n model,\r\n effect,\r\n untracked,\r\n} from '@angular/core';\r\nimport { HyFidelity, injectId } from '@hyalo/angular';\r\nimport {\r\n hyConnectedPositions,\r\n type HyPlacement,\r\n ɵHyPresence as HyPresence,\r\n} from '@hyalo/angular/overlay';\r\nimport { loadOverlay } from './load-overlay';\r\n\r\n/**\r\n * A non-modal glass panel anchored to a trigger, for content that does not\r\n * fit in a tooltip: a short form, a menu of links, details.\r\n *\r\n * ```html\r\n * <button hyButton variant=\"glass\" [hyPopover]=\"share\" popoverLabel=\"Share\">Share</button>\r\n * <ng-template #share>\r\n * <a href=\"...\">Copy link</a>\r\n * </ng-template>\r\n * ```\r\n *\r\n * Click or Enter toggles it. On open, focus moves to the first focusable\r\n * element inside. Escape closes it and returns focus to the trigger, and so\r\n * does clicking outside or tabbing out of it.\r\n */\r\n@Directive({\r\n selector: '[hyPopover]',\r\n exportAs: 'hyPopover',\r\n host: {\r\n 'aria-haspopup': 'dialog',\r\n '[attr.aria-expanded]': 'open()',\r\n '[attr.aria-controls]': 'open() ? panelId : null',\r\n '(click)': 'toggle()',\r\n // Fetch the overlay code as soon as the user heads for the trigger.\r\n '(pointerenter)': 'preload()',\r\n '(focusin)': 'preload()',\r\n },\r\n})\r\nexport class HyPopover {\r\n private readonly injector = inject(Injector);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly viewContainer = inject(ViewContainerRef);\r\n private readonly focusTraps = inject(FocusTrapFactory);\r\n private readonly fidelity = inject(HyFidelity);\r\n protected readonly panelId = injectId('popover');\r\n private overlayRef: OverlayRef | null = null;\r\n private position: FlexibleConnectedPositionStrategy | null = null;\r\n private readonly presence = new HyPresence();\r\n private destroyed = false;\r\n\r\n /** The content. */\r\n readonly content = input.required<TemplateRef<unknown>>({ alias: 'hyPopover' });\r\n /** Accessible name of the panel. */\r\n readonly popoverLabel = input<string>();\r\n /** Preferred side. Flips when there is no room. */\r\n readonly popoverPlacement = input<HyPlacement>('bottom');\r\n /** Whether the panel is open. Two-way bindable as `[(popoverOpen)]`. */\r\n readonly open = model(false, { alias: 'popoverOpen' });\r\n\r\n constructor() {\r\n effect(() => {\r\n const open = this.open();\r\n untracked(() => (open ? void this.attach() : this.detach()));\r\n });\r\n inject(DestroyRef).onDestroy(() => {\r\n this.destroyed = true;\r\n this.overlayRef?.dispose();\r\n });\r\n }\r\n\r\n toggle(): void {\r\n this.open.update((v) => !v);\r\n }\r\n\r\n /** Closes the panel, optionally moving focus back to the trigger. */\r\n close(restoreFocus = true): void {\r\n if (!this.open()) return;\r\n this.open.set(false);\r\n if (restoreFocus) this.host.nativeElement.focus();\r\n }\r\n\r\n protected preload(): void {\r\n loadOverlay().catch(() => undefined);\r\n }\r\n\r\n private async attach(): Promise<void> {\r\n const kit = await loadOverlay().catch(() => null);\r\n if (this.destroyed) return;\r\n if (!kit) {\r\n // Without the overlay code there is no panel, so do not claim one.\r\n this.open.set(false);\r\n return;\r\n }\r\n // It may have been closed again while the code loaded.\r\n if (!this.open()) return;\r\n const {\r\n TemplatePortal,\r\n createFlexibleConnectedPositionStrategy,\r\n createOverlayRef,\r\n createRepositionScrollStrategy,\r\n } = kit;\r\n if (!this.overlayRef) {\r\n this.position = createFlexibleConnectedPositionStrategy(this.injector, this.host)\r\n .withViewportMargin(12)\r\n .withPush(true)\r\n // The panel grows out of its trigger, not out of its own centre.\r\n .withTransformOriginOn('.hy-popover');\r\n this.overlayRef = createOverlayRef(this.injector, {\r\n positionStrategy: this.position,\r\n scrollStrategy: createRepositionScrollStrategy(this.injector),\r\n panelClass: 'hy-popover-pane',\r\n });\r\n this.overlayRef.keydownEvents().subscribe((event) => {\r\n if (event.key === 'Escape') {\r\n event.preventDefault();\r\n this.close();\r\n }\r\n });\r\n this.overlayRef.outsidePointerEvents().subscribe((event) => {\r\n if (!this.host.nativeElement.contains(event.target as Node)) this.close(false);\r\n });\r\n }\r\n if (this.overlayRef.hasAttached()) {\r\n // Reopened while fading out: turn the exit around.\r\n if (this.presence.leaving) this.presence.enter(this.overlayRef.overlayElement);\r\n return;\r\n }\r\n // Read on every open, so a changed placement applies next time.\r\n this.position?.withPositions(hyConnectedPositions(this.popoverPlacement(), 10));\r\n this.overlayRef.attach(new TemplatePortal(this.content(), this.viewContainer));\r\n\r\n const pane = this.overlayRef.overlayElement;\r\n pane.id = this.panelId;\r\n pane.setAttribute('role', 'dialog');\r\n const label = this.popoverLabel();\r\n if (label) pane.setAttribute('aria-label', label);\r\n else pane.removeAttribute('aria-label');\r\n pane.classList.add('hy-glass', 'hy-popover');\r\n pane.dataset['material'] = this.fidelity.tier() === 'low' ? 'solid' : 'frosted';\r\n pane.addEventListener('focusout', this.onFocusOut);\r\n this.presence.enter(pane);\r\n\r\n const trap = this.focusTraps.create(pane);\r\n void trap.focusFirstTabbableElementWhenReady().then((found) => {\r\n if (!found) {\r\n pane.tabIndex = -1;\r\n pane.focus();\r\n }\r\n trap.destroy();\r\n });\r\n }\r\n\r\n private detach(): void {\r\n const ref = this.overlayRef;\r\n if (!ref?.hasAttached()) return;\r\n ref.overlayElement.removeEventListener('focusout', this.onFocusOut);\r\n this.presence.leave(ref.overlayElement, () => ref.detach());\r\n }\r\n\r\n private readonly onFocusOut = (event: FocusEvent): void => {\r\n const next = event.relatedTarget as Node | null;\r\n if (\r\n next &&\r\n !this.overlayRef?.overlayElement.contains(next) &&\r\n next !== this.host.nativeElement\r\n ) {\r\n this.close(false);\r\n }\r\n };\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"hyalo-angular-popover.mjs","names":["HyPresence","HyPresence"],"sources":["../../../projects/hyalo/popover/load-overlay.ts","../../../projects/hyalo/popover/tooltip.ts","../../../projects/hyalo/popover/popover.ts"],"sourcesContent":["/**\r\n * @internal Loads the overlay code the first time a tooltip or popover is\r\n * about to open. A page full of triggers then costs nothing until someone\r\n * hovers or clicks one, and the import resolves to the same module when the\r\n * app already uses the overlay elsewhere.\r\n */\r\nexport type HyOverlayKit = typeof import('./overlay-kit');\r\n\r\nlet kit: Promise<HyOverlayKit> | undefined;\r\n\r\n/** @internal */\r\nexport function loadOverlay(): Promise<HyOverlayKit> {\r\n kit ??= import('./overlay-kit').catch((error: unknown) => {\r\n // A failed chunk load should not stick; the next open tries again.\r\n kit = undefined;\r\n throw error;\r\n });\r\n return kit;\r\n}\r\n","import { AriaDescriber } from '@angular/cdk/a11y';\r\nimport type { FlexibleConnectedPositionStrategy, OverlayRef } from '@angular/cdk/overlay';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n Injector,\r\n booleanAttribute,\r\n effect,\r\n inject,\r\n input,\r\n numberAttribute,\r\n signal,\r\n} from '@angular/core';\r\nimport {\r\n hyConnectedPositions,\r\n type HyPlacement,\r\n ɵHyPresence as HyPresence,\r\n} from '@hyalo/angular/overlay';\r\nimport { loadOverlay } from './load-overlay';\r\n\r\n@Component({\r\n selector: 'hy-tooltip-panel',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { class: 'hy-tooltip', 'aria-hidden': 'true' },\r\n template: `{{ message() }}`,\r\n})\r\nexport class HyTooltipPanel {\r\n readonly message = signal('');\r\n}\r\n\r\n/**\r\n * A short text hint on hover or keyboard focus.\r\n *\r\n * ```html\r\n * <button hyButton iconOnly aria-label=\"Copy link\" hyTooltip=\"Copy link\">...</button>\r\n * ```\r\n *\r\n * The text is also added to the trigger's `aria-describedby` through a\r\n * hidden element, so screen readers get it without the visual tooltip. The\r\n * tooltip stays open while the pointer is over it and closes on Escape, as\r\n * WCAG 1.4.13 asks. Keep it short and never put interactive content in it;\r\n * use `hyPopover` for that.\r\n */\r\n@Directive({\r\n selector: '[hyTooltip]',\r\n host: {\r\n '(pointerenter)': 'onPointerEnter($event)',\r\n '(pointerleave)': 'scheduleHide()',\r\n '(focusin)': 'show(0)',\r\n '(focusout)': 'hide()',\r\n '(keydown.escape)': 'hide()',\r\n },\r\n})\r\nexport class HyTooltip {\r\n private readonly injector = inject(Injector);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly describer = inject(AriaDescriber);\r\n private overlayRef: OverlayRef | null = null;\r\n private position: FlexibleConnectedPositionStrategy | null = null;\r\n private panel: HyTooltipPanel | null = null;\r\n private panelEl: HTMLElement | null = null;\r\n private readonly presence = new HyPresence();\r\n private showTimer: ReturnType<typeof setTimeout> | undefined;\r\n private hideTimer: ReturnType<typeof setTimeout> | undefined;\r\n /** True from show() until hide(), so a late overlay load knows to stop. */\r\n private wanted = false;\r\n private destroyed = false;\r\n\r\n /** The tooltip text. */\r\n readonly message = input('', { alias: 'hyTooltip' });\r\n /** Preferred side. Flips when there is no room. */\r\n readonly tooltipPlacement = input<HyPlacement>('top');\r\n /** Hover delay in milliseconds. Focus shows it right away. */\r\n readonly tooltipDelay = input(400, { transform: numberAttribute });\r\n readonly tooltipDisabled = input(false, { transform: booleanAttribute });\r\n\r\n constructor() {\r\n let described = '';\r\n effect(() => {\r\n const message = this.message();\r\n if (described) this.describer.removeDescription(this.host.nativeElement, described);\r\n if (message) this.describer.describe(this.host.nativeElement, message);\r\n described = message;\r\n if (this.panel) this.panel.message.set(message);\r\n });\r\n inject(DestroyRef).onDestroy(() => {\r\n this.destroyed = true;\r\n clearTimeout(this.showTimer);\r\n clearTimeout(this.hideTimer);\r\n if (described) this.describer.removeDescription(this.host.nativeElement, described);\r\n this.overlayRef?.dispose();\r\n });\r\n }\r\n\r\n protected onPointerEnter(event: PointerEvent): void {\r\n if (event.pointerType !== 'touch') this.show(this.tooltipDelay());\r\n }\r\n\r\n /** Shows the tooltip after the given delay. */\r\n show(delay = this.tooltipDelay()): void {\r\n if (this.tooltipDisabled() || !this.message()) return;\r\n clearTimeout(this.hideTimer);\r\n clearTimeout(this.showTimer);\r\n this.wanted = true;\r\n // Load during the hover delay, so the tooltip is ready when it ends.\r\n loadOverlay().catch(() => undefined);\r\n this.showTimer = setTimeout(() => void this.attach(), delay);\r\n }\r\n\r\n /** Starts hiding the tooltip now. It fades out quickly. */\r\n hide(): void {\r\n this.wanted = false;\r\n clearTimeout(this.showTimer);\r\n clearTimeout(this.hideTimer);\r\n const ref = this.overlayRef;\r\n if (!ref?.hasAttached() || !this.panelEl) return;\r\n this.presence.leave(this.panelEl, () => ref.detach());\r\n }\r\n\r\n protected scheduleHide(): void {\r\n clearTimeout(this.showTimer);\r\n this.hideTimer = setTimeout(() => this.hide(), 120);\r\n }\r\n\r\n private async attach(): Promise<void> {\r\n const kit = await loadOverlay().catch(() => null);\r\n if (!kit || !this.wanted || this.destroyed) return;\r\n const {\r\n ComponentPortal,\r\n createFlexibleConnectedPositionStrategy,\r\n createOverlayRef,\r\n createRepositionScrollStrategy,\r\n } = kit;\r\n if (!this.overlayRef) {\r\n this.position = createFlexibleConnectedPositionStrategy(this.injector, this.host)\r\n .withFlexibleDimensions(false)\r\n .withViewportMargin(8)\r\n .withTransformOriginOn('.hy-tooltip');\r\n this.overlayRef = createOverlayRef(this.injector, {\r\n positionStrategy: this.position,\r\n scrollStrategy: createRepositionScrollStrategy(this.injector),\r\n panelClass: 'hy-tooltip-pane',\r\n });\r\n // Hovering the tooltip itself keeps it open.\r\n this.overlayRef.overlayElement.addEventListener('pointerenter', () =>\r\n clearTimeout(this.hideTimer),\r\n );\r\n this.overlayRef.overlayElement.addEventListener('pointerleave', () => this.scheduleHide());\r\n }\r\n if (this.overlayRef.hasAttached()) {\r\n if (this.presence.leaving && this.panelEl) this.presence.enter(this.panelEl);\r\n return;\r\n }\r\n // Read on every show, so a changed placement applies next time.\r\n this.position?.withPositions(hyConnectedPositions(this.tooltipPlacement()));\r\n const ref = this.overlayRef.attach(new ComponentPortal(HyTooltipPanel, null, this.injector));\r\n this.panel = ref.instance;\r\n this.panel.message.set(this.message());\r\n const el = ref.location.nativeElement as HTMLElement;\r\n this.panelEl = el;\r\n this.presence.enter(el);\r\n ref.onDestroy(() => {\r\n this.panel = null;\r\n this.panelEl = null;\r\n });\r\n }\r\n}\r\n","import { FocusTrapFactory } from '@angular/cdk/a11y';\r\nimport { take } from 'rxjs';\r\nimport type { FlexibleConnectedPositionStrategy, OverlayRef } from '@angular/cdk/overlay';\r\nimport {\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n Injector,\r\n TemplateRef,\r\n ViewContainerRef,\r\n inject,\r\n input,\r\n model,\r\n effect,\r\n untracked,\r\n} from '@angular/core';\r\nimport { HyFidelity, injectId, type HyMaterial } from '@hyalo/angular/core';\r\nimport {\r\n hyConnectedPositions,\r\n type HyPlacement,\r\n ɵHyPresence as HyPresence,\r\n} from '@hyalo/angular/overlay';\r\nimport { loadOverlay } from './load-overlay';\r\n\r\n/**\r\n * A non-modal glass panel anchored to a trigger, for content that does not\r\n * fit in a tooltip: a short form, a menu of links, details.\r\n *\r\n * ```html\r\n * <button hyButton variant=\"glass\" [hyPopover]=\"share\" popoverLabel=\"Share\">Share</button>\r\n * <ng-template #share>\r\n * <a href=\"...\">Copy link</a>\r\n * </ng-template>\r\n * ```\r\n *\r\n * Click or Enter toggles it. On open, focus moves to the first focusable\r\n * element inside. Escape closes it and returns focus to the trigger, and so\r\n * does clicking outside or tabbing out of it.\r\n */\r\n@Directive({\r\n selector: '[hyPopover]',\r\n exportAs: 'hyPopover',\r\n host: {\r\n 'aria-haspopup': 'dialog',\r\n '[attr.aria-expanded]': 'open()',\r\n '[attr.aria-controls]': 'open() ? panelId : null',\r\n '(click)': 'toggle()',\r\n // Fetch the overlay code as soon as the user heads for the trigger.\r\n '(pointerenter)': 'preload()',\r\n '(focusin)': 'preload()',\r\n },\r\n})\r\nexport class HyPopover {\r\n private readonly injector = inject(Injector);\r\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly viewContainer = inject(ViewContainerRef);\r\n private readonly focusTraps = inject(FocusTrapFactory);\r\n private readonly fidelity = inject(HyFidelity);\r\n protected readonly panelId = injectId('popover');\r\n private overlayRef: OverlayRef | null = null;\r\n private position: FlexibleConnectedPositionStrategy | null = null;\r\n private readonly presence = new HyPresence();\r\n private destroyed = false;\r\n private positioned = false;\r\n\r\n /** The content. */\r\n readonly content = input.required<TemplateRef<unknown>>({ alias: 'hyPopover' });\r\n /** Accessible name of the panel. */\r\n readonly popoverLabel = input<string>();\r\n /** Use solid over image content when the background would reduce text contrast. */\r\n readonly popoverMaterial = input<HyMaterial>('frosted');\r\n /** Preferred side. Flips when there is no room. */\r\n readonly popoverPlacement = input<HyPlacement>('bottom');\r\n /** Whether the panel is open. Two-way bindable as `[(popoverOpen)]`. */\r\n readonly open = model(false, { alias: 'popoverOpen' });\r\n\r\n constructor() {\r\n effect(() => {\r\n const open = this.open();\r\n untracked(() => (open ? void this.attach() : this.detach()));\r\n });\r\n inject(DestroyRef).onDestroy(() => {\r\n this.destroyed = true;\r\n this.overlayRef?.dispose();\r\n });\r\n }\r\n\r\n toggle(): void {\r\n this.open.update((v) => !v);\r\n }\r\n\r\n /** Closes the panel, optionally moving focus back to the trigger. */\r\n close(restoreFocus = true): void {\r\n if (!this.open()) return;\r\n this.open.set(false);\r\n if (restoreFocus) this.host.nativeElement.focus();\r\n }\r\n\r\n protected preload(): void {\r\n loadOverlay().catch(() => undefined);\r\n }\r\n\r\n private async attach(): Promise<void> {\r\n const kit = await loadOverlay().catch(() => null);\r\n if (this.destroyed) return;\r\n if (!kit) {\r\n // Without the overlay code there is no panel, so do not claim one.\r\n this.open.set(false);\r\n return;\r\n }\r\n // It may have been closed again while the code loaded.\r\n if (!this.open()) return;\r\n const {\r\n TemplatePortal,\r\n createFlexibleConnectedPositionStrategy,\r\n createOverlayRef,\r\n createRepositionScrollStrategy,\r\n } = kit;\r\n if (!this.overlayRef) {\r\n this.position = createFlexibleConnectedPositionStrategy(this.injector, this.host)\r\n .withViewportMargin(12)\r\n .withPush(true)\r\n // The panel grows out of its trigger, not out of its own centre.\r\n .withTransformOriginOn('.hy-popover');\r\n this.overlayRef = createOverlayRef(this.injector, {\r\n positionStrategy: this.position,\r\n scrollStrategy: createRepositionScrollStrategy(this.injector),\r\n panelClass: 'hy-popover-pane',\r\n });\r\n this.overlayRef.keydownEvents().subscribe((event) => {\r\n if (event.key === 'Escape') {\r\n event.preventDefault();\r\n this.close();\r\n }\r\n });\r\n this.overlayRef.outsidePointerEvents().subscribe((event) => {\r\n if (!this.host.nativeElement.contains(event.target as Node)) this.close(false);\r\n });\r\n }\r\n if (this.overlayRef.hasAttached()) {\r\n // Reopened while fading out: turn the exit around.\r\n if (this.presence.leaving && this.positioned) this.reveal(this.overlayRef.overlayElement);\r\n return;\r\n }\r\n // Read on every open, so a changed placement applies next time.\r\n this.position?.withPositions(hyConnectedPositions(this.popoverPlacement(), 10));\r\n const pane = this.overlayRef.overlayElement;\r\n pane.id = this.panelId;\r\n pane.setAttribute('role', 'dialog');\r\n const label = this.popoverLabel();\r\n if (label) pane.setAttribute('aria-label', label);\r\n else pane.removeAttribute('aria-label');\r\n pane.classList.add('hy-glass', 'hy-popover');\r\n pane.dataset['material'] = this.fidelity.tier() === 'low' ? 'solid' : this.popoverMaterial();\r\n pane.dataset['state'] = 'closed';\r\n pane.style.visibility = 'hidden';\r\n this.positioned = false;\r\n pane.addEventListener('focusout', this.onFocusOut);\r\n // CDK positions after rendering the portal. Do not expose its unpositioned first frame.\r\n this.position?.positionChanges.pipe(take(1)).subscribe(() => {\r\n this.positioned = true;\r\n if (this.destroyed || !this.open() || !this.overlayRef?.hasAttached()) return;\r\n this.reveal(pane);\r\n });\r\n this.overlayRef.attach(new TemplatePortal(this.content(), this.viewContainer));\r\n }\r\n\r\n private reveal(pane: HTMLElement): void {\r\n pane.style.removeProperty('visibility');\r\n this.presence.enter(pane);\r\n const trap = this.focusTraps.create(pane);\r\n void trap.focusFirstTabbableElementWhenReady().then((found) => {\r\n if (!found && this.open() && !this.destroyed) {\r\n pane.tabIndex = -1;\r\n pane.focus();\r\n }\r\n trap.destroy();\r\n });\r\n }\r\n\r\n private detach(): void {\r\n const ref = this.overlayRef;\r\n if (!ref?.hasAttached()) return;\r\n ref.overlayElement.removeEventListener('focusout', this.onFocusOut);\r\n this.presence.leave(ref.overlayElement, () => ref.detach());\r\n }\r\n\r\n private readonly onFocusOut = (event: FocusEvent): void => {\r\n const next = event.relatedTarget as Node | null;\r\n if (\r\n next &&\r\n !this.overlayRef?.overlayElement.contains(next) &&\r\n next !== this.host.nativeElement\r\n ) {\r\n this.close(false);\r\n }\r\n };\r\n}\r\n"],"mappings":"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"}