@hyalo/angular 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +95 -41
- package/README.md +46 -32
- package/fesm2022/hyalo-angular-accordion.mjs +6 -6
- package/fesm2022/hyalo-angular-accordion.mjs.map +1 -1
- package/fesm2022/hyalo-angular-alert.mjs +171 -0
- package/fesm2022/hyalo-angular-alert.mjs.map +1 -0
- package/fesm2022/hyalo-angular-aspect-ratio.mjs +64 -0
- package/fesm2022/hyalo-angular-aspect-ratio.mjs.map +1 -0
- package/fesm2022/hyalo-angular-avatar.mjs +169 -0
- package/fesm2022/hyalo-angular-avatar.mjs.map +1 -0
- package/fesm2022/hyalo-angular-badge.mjs +268 -0
- package/fesm2022/hyalo-angular-badge.mjs.map +1 -0
- package/fesm2022/hyalo-angular-bento.mjs +132 -0
- package/fesm2022/hyalo-angular-bento.mjs.map +1 -0
- package/fesm2022/hyalo-angular-blocks.mjs +985 -0
- package/fesm2022/hyalo-angular-blocks.mjs.map +1 -0
- package/fesm2022/hyalo-angular-border-beam.mjs +73 -0
- package/fesm2022/hyalo-angular-border-beam.mjs.map +1 -0
- package/fesm2022/hyalo-angular-breadcrumb.mjs +77 -0
- package/fesm2022/hyalo-angular-breadcrumb.mjs.map +1 -0
- package/fesm2022/hyalo-angular-button-group.mjs +90 -0
- package/fesm2022/hyalo-angular-button-group.mjs.map +1 -0
- package/fesm2022/hyalo-angular-button.mjs +4 -3
- package/fesm2022/hyalo-angular-button.mjs.map +1 -1
- package/fesm2022/hyalo-angular-card.mjs +2 -2
- package/fesm2022/hyalo-angular-card.mjs.map +1 -1
- package/fesm2022/hyalo-angular-carousel.mjs +709 -0
- package/fesm2022/hyalo-angular-carousel.mjs.map +1 -0
- package/fesm2022/hyalo-angular-chapter-nav.mjs +336 -0
- package/fesm2022/hyalo-angular-chapter-nav.mjs.map +1 -0
- package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs +5 -0
- package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs.map +1 -0
- package/fesm2022/hyalo-angular-chart.mjs +391 -0
- package/fesm2022/hyalo-angular-chart.mjs.map +1 -0
- package/fesm2022/hyalo-angular-choice.mjs +2 -1
- package/fesm2022/hyalo-angular-choice.mjs.map +1 -1
- package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs +40 -0
- package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs.map +1 -0
- package/fesm2022/hyalo-angular-code-block.mjs +161 -0
- package/fesm2022/hyalo-angular-code-block.mjs.map +1 -0
- package/fesm2022/hyalo-angular-command.mjs +193 -0
- package/fesm2022/hyalo-angular-command.mjs.map +1 -0
- package/fesm2022/hyalo-angular-copy.mjs +138 -0
- package/fesm2022/hyalo-angular-copy.mjs.map +1 -0
- package/fesm2022/hyalo-angular-core.mjs +424 -0
- package/fesm2022/hyalo-angular-core.mjs.map +1 -0
- package/fesm2022/hyalo-angular-description-list.mjs +57 -0
- package/fesm2022/hyalo-angular-description-list.mjs.map +1 -0
- package/fesm2022/hyalo-angular-dialog.mjs +51 -22
- package/fesm2022/hyalo-angular-dialog.mjs.map +1 -1
- package/fesm2022/hyalo-angular-divider.mjs +66 -0
- package/fesm2022/hyalo-angular-divider.mjs.map +1 -0
- package/fesm2022/hyalo-angular-empty-state.mjs +123 -0
- package/fesm2022/hyalo-angular-empty-state.mjs.map +1 -0
- package/fesm2022/hyalo-angular-field.mjs +41 -9
- package/fesm2022/hyalo-angular-field.mjs.map +1 -1
- package/fesm2022/hyalo-angular-filter.mjs +309 -0
- package/fesm2022/hyalo-angular-filter.mjs.map +1 -0
- package/fesm2022/hyalo-angular-hotspot.mjs +225 -0
- package/fesm2022/hyalo-angular-hotspot.mjs.map +1 -0
- package/fesm2022/hyalo-angular-hover-card.mjs +233 -0
- package/fesm2022/hyalo-angular-hover-card.mjs.map +1 -0
- package/fesm2022/hyalo-angular-icon.mjs +42 -0
- package/fesm2022/hyalo-angular-icon.mjs.map +1 -1
- package/fesm2022/hyalo-angular-image-compare.mjs +168 -0
- package/fesm2022/hyalo-angular-image-compare.mjs.map +1 -0
- package/fesm2022/hyalo-angular-interaction.mjs +32 -41
- package/fesm2022/hyalo-angular-interaction.mjs.map +1 -1
- package/fesm2022/hyalo-angular-kbd.mjs +41 -0
- package/fesm2022/hyalo-angular-kbd.mjs.map +1 -0
- package/fesm2022/hyalo-angular-lightbox.mjs +228 -0
- package/fesm2022/hyalo-angular-lightbox.mjs.map +1 -0
- package/fesm2022/hyalo-angular-link.mjs +42 -0
- package/fesm2022/hyalo-angular-link.mjs.map +1 -0
- package/fesm2022/hyalo-angular-list.mjs +131 -0
- package/fesm2022/hyalo-angular-list.mjs.map +1 -0
- package/fesm2022/hyalo-angular-marquee.mjs +197 -0
- package/fesm2022/hyalo-angular-marquee.mjs.map +1 -0
- package/fesm2022/hyalo-angular-menu.mjs +423 -0
- package/fesm2022/hyalo-angular-menu.mjs.map +1 -0
- package/fesm2022/hyalo-angular-mesh.mjs +126 -0
- package/fesm2022/hyalo-angular-mesh.mjs.map +1 -0
- package/fesm2022/hyalo-angular-motion.mjs +620 -0
- package/fesm2022/hyalo-angular-motion.mjs.map +1 -0
- package/fesm2022/hyalo-angular-navbar.mjs +1 -1
- package/fesm2022/hyalo-angular-navbar.mjs.map +1 -1
- package/fesm2022/hyalo-angular-navigation-menu.mjs +222 -0
- package/fesm2022/hyalo-angular-navigation-menu.mjs.map +1 -0
- package/fesm2022/hyalo-angular-number-ticker.mjs +174 -0
- package/fesm2022/hyalo-angular-number-ticker.mjs.map +1 -0
- package/fesm2022/hyalo-angular-overlay.mjs +71 -2
- package/fesm2022/hyalo-angular-overlay.mjs.map +1 -1
- package/fesm2022/hyalo-angular-pagination.mjs +187 -0
- package/fesm2022/hyalo-angular-pagination.mjs.map +1 -0
- package/fesm2022/hyalo-angular-popover.mjs +34 -5
- package/fesm2022/hyalo-angular-popover.mjs.map +1 -1
- package/fesm2022/hyalo-angular-progress.mjs +209 -0
- package/fesm2022/hyalo-angular-progress.mjs.map +1 -0
- package/fesm2022/hyalo-angular-progressive-blur.mjs +73 -0
- package/fesm2022/hyalo-angular-progressive-blur.mjs.map +1 -0
- package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs +186 -0
- package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs.map +1 -0
- package/fesm2022/hyalo-angular-refraction.mjs +178 -0
- package/fesm2022/hyalo-angular-refraction.mjs.map +1 -0
- package/fesm2022/hyalo-angular-scroll-area.mjs +93 -0
- package/fesm2022/hyalo-angular-scroll-area.mjs.map +1 -0
- package/fesm2022/hyalo-angular-scroll-to-top.mjs +127 -0
- package/fesm2022/hyalo-angular-scroll-to-top.mjs.map +1 -0
- package/fesm2022/hyalo-angular-segmented.mjs +1 -1
- package/fesm2022/hyalo-angular-segmented.mjs.map +1 -1
- package/fesm2022/hyalo-angular-select.mjs +112 -15
- package/fesm2022/hyalo-angular-select.mjs.map +1 -1
- package/fesm2022/hyalo-angular-sidebar.mjs +241 -0
- package/fesm2022/hyalo-angular-sidebar.mjs.map +1 -0
- package/fesm2022/hyalo-angular-skeleton.mjs +131 -0
- package/fesm2022/hyalo-angular-skeleton.mjs.map +1 -0
- package/fesm2022/hyalo-angular-sparkline.mjs +110 -0
- package/fesm2022/hyalo-angular-sparkline.mjs.map +1 -0
- package/fesm2022/hyalo-angular-split-text.mjs +126 -0
- package/fesm2022/hyalo-angular-split-text.mjs.map +1 -0
- package/fesm2022/hyalo-angular-stat.mjs +193 -0
- package/fesm2022/hyalo-angular-stat.mjs.map +1 -0
- package/fesm2022/hyalo-angular-stepper.mjs +254 -0
- package/fesm2022/hyalo-angular-stepper.mjs.map +1 -0
- package/fesm2022/hyalo-angular-table.mjs +335 -0
- package/fesm2022/hyalo-angular-table.mjs.map +1 -0
- package/fesm2022/hyalo-angular-tabs.mjs +1 -1
- package/fesm2022/hyalo-angular-tabs.mjs.map +1 -1
- package/fesm2022/hyalo-angular-theme.mjs +1 -1
- package/fesm2022/hyalo-angular-theme.mjs.map +1 -1
- package/fesm2022/hyalo-angular-timeline.mjs +157 -0
- package/fesm2022/hyalo-angular-timeline.mjs.map +1 -0
- package/fesm2022/hyalo-angular-toast.mjs +2 -1
- package/fesm2022/hyalo-angular-toast.mjs.map +1 -1
- package/fesm2022/hyalo-angular.mjs +2 -473
- package/package.json +198 -2
- package/styles/parts/field.css +44 -36
- package/styles/parts/glass.css +2 -0
- package/styles/parts/motion.css +19 -0
- package/styles/parts/typography.css +17 -0
- package/types/hyalo-angular-accordion.d.ts +1 -1
- package/types/hyalo-angular-alert.d.ts +47 -0
- package/types/hyalo-angular-aspect-ratio.d.ts +13 -0
- package/types/hyalo-angular-avatar.d.ts +39 -0
- package/types/hyalo-angular-badge.d.ts +82 -0
- package/types/hyalo-angular-bento.d.ts +25 -0
- package/types/hyalo-angular-blocks.d.ts +272 -0
- package/types/hyalo-angular-border-beam.d.ts +15 -0
- package/types/hyalo-angular-breadcrumb.d.ts +22 -0
- package/types/hyalo-angular-button-group.d.ts +19 -0
- package/types/hyalo-angular-button.d.ts +4 -3
- package/types/hyalo-angular-card.d.ts +1 -1
- package/types/hyalo-angular-carousel.d.ts +147 -0
- package/types/hyalo-angular-chapter-nav.d.ts +79 -0
- package/types/hyalo-angular-chart.d.ts +90 -0
- package/types/hyalo-angular-code-block.d.ts +46 -0
- package/types/hyalo-angular-command.d.ts +41 -0
- package/types/hyalo-angular-copy.d.ts +39 -0
- package/types/hyalo-angular-core.d.ts +210 -0
- package/types/hyalo-angular-description-list.d.ts +16 -0
- package/types/hyalo-angular-dialog.d.ts +2 -1
- package/types/hyalo-angular-divider.d.ts +12 -0
- package/types/hyalo-angular-empty-state.d.ts +30 -0
- package/types/hyalo-angular-field.d.ts +10 -4
- package/types/hyalo-angular-filter.d.ts +122 -0
- package/types/hyalo-angular-hotspot.d.ts +70 -0
- package/types/hyalo-angular-hover-card.d.ts +47 -0
- package/types/hyalo-angular-image-compare.d.ts +55 -0
- package/types/hyalo-angular-kbd.d.ts +5 -0
- package/types/hyalo-angular-lightbox.d.ts +67 -0
- package/types/hyalo-angular-link.d.ts +5 -0
- package/types/hyalo-angular-list.d.ts +30 -0
- package/types/hyalo-angular-marquee.d.ts +48 -0
- package/types/hyalo-angular-menu.d.ts +105 -0
- package/types/hyalo-angular-mesh.d.ts +36 -0
- package/types/hyalo-angular-motion.d.ts +218 -0
- package/types/hyalo-angular-navigation-menu.d.ts +47 -0
- package/types/hyalo-angular-number-ticker.d.ts +52 -0
- package/types/hyalo-angular-overlay.d.ts +9 -0
- package/types/hyalo-angular-pagination.d.ts +59 -0
- package/types/hyalo-angular-popover.d.ts +10 -0
- package/types/hyalo-angular-progress.d.ts +46 -0
- package/types/hyalo-angular-progressive-blur.d.ts +14 -0
- package/types/hyalo-angular-refraction.d.ts +46 -0
- package/types/hyalo-angular-scroll-area.d.ts +18 -0
- package/types/hyalo-angular-scroll-to-top.d.ts +31 -0
- package/types/hyalo-angular-segmented.d.ts +1 -1
- package/types/hyalo-angular-select.d.ts +49 -3
- package/types/hyalo-angular-sidebar.d.ts +57 -0
- package/types/hyalo-angular-skeleton.d.ts +34 -0
- package/types/hyalo-angular-sparkline.d.ts +19 -0
- package/types/hyalo-angular-split-text.d.ts +24 -0
- package/types/hyalo-angular-stat.d.ts +56 -0
- package/types/hyalo-angular-stepper.d.ts +63 -0
- package/types/hyalo-angular-table.d.ts +125 -0
- package/types/hyalo-angular-timeline.d.ts +36 -0
- package/types/hyalo-angular.d.ts +2 -345
- package/fesm2022/hyalo-angular.mjs.map +0 -1
|
@@ -1,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
|
-
|
|
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 {
|
|
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.
|
|
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" :
|
|
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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"}
|