@celestia-island/hikari 0.45.8 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,61 @@
1
+ // Shared floating-tooltip geometry for HkTooltip (component) and the
2
+ // document-level tooltip bridge (runtime/tooltipBridge.ts). One placement
3
+ // switch, one zoom story: whatever hosts a popup against a trigger rect
4
+ // positions it through this helper so the two surfaces can never drift.
5
+ import type { CSSProperties } from "vue";
6
+ import { ancestorZoom } from "./cssZoom";
7
+
8
+ export type TooltipPlacement = "top" | "bottom" | "left" | "right";
9
+
10
+ /** Gap between the trigger rect and the popup, in root visual px. */
11
+ export const TOOLTIP_GAP_PX = 8;
12
+
13
+ /**
14
+ * Build the inline style that pins a `position: fixed` popup to one side
15
+ * of a trigger rect.
16
+ *
17
+ * The popup teleports to <body> — inside any root CSS zoom subtree —
18
+ * while `rect` is already in the root visual space (standardized zoom
19
+ * reports ancestor zoom applied). The browser scales the tooltip's local
20
+ * px back up at paint, so the visual rect values must be written divided
21
+ * by the cumulative zoom or the tooltip drifts zoom× off its trigger
22
+ * (chest's root-level manual DPI scale).
23
+ */
24
+ export function tooltipPositionStyle(
25
+ rect: DOMRect,
26
+ placement: TooltipPlacement,
27
+ maxWidth?: string,
28
+ ): CSSProperties {
29
+ const z = ancestorZoom(document.body);
30
+ const local = (v: number) => `${v / z}px`;
31
+ const style: CSSProperties = {};
32
+
33
+ if (maxWidth) {
34
+ style.maxWidth = maxWidth;
35
+ }
36
+
37
+ switch (placement) {
38
+ case "top":
39
+ style.top = local(rect.top - TOOLTIP_GAP_PX);
40
+ style.left = local(rect.left + rect.width / 2);
41
+ style.transform = "translate(-50%, -100%)";
42
+ break;
43
+ case "bottom":
44
+ style.top = local(rect.bottom + TOOLTIP_GAP_PX);
45
+ style.left = local(rect.left + rect.width / 2);
46
+ style.transform = "translate(-50%, 0)";
47
+ break;
48
+ case "left":
49
+ style.top = local(rect.top + rect.height / 2);
50
+ style.left = local(rect.left - TOOLTIP_GAP_PX);
51
+ style.transform = "translate(-100%, -50%)";
52
+ break;
53
+ case "right":
54
+ style.top = local(rect.top + rect.height / 2);
55
+ style.left = local(rect.right + TOOLTIP_GAP_PX);
56
+ style.transform = "translate(0, -50%)";
57
+ break;
58
+ }
59
+
60
+ return style;
61
+ }