actual-css 0.3.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/src/js/tooltip.js CHANGED
@@ -14,9 +14,9 @@
14
14
  * treated as a tooltip trigger.
15
15
  *
16
16
  * Sharing: an explicit tooltip may be referenced by several triggers. The
17
- * tooltip element is wired once (floating listeners + tracking);
18
- * each trigger only registers itself and the wiring is torn down
19
- * when the last trigger leaves the DOM.
17
+ * tooltip element is wired once; each trigger only registers
18
+ * itself. Positional tracking runs only while the tip is visible,
19
+ * and all wiring is torn down when the last trigger leaves the DOM.
20
20
  *
21
21
  * Lazy: tooltip elements are created (shorthand) or wired (explicit) on
22
22
  * first mouseover / focusin. No page-load scan, no DOM overhead
@@ -39,7 +39,7 @@ const HIDE_DELAY_MS = 100;
39
39
  * @property {Set<Element>} refs Triggers that currently reference this tip.
40
40
  * @property {Element | null} activeRef Trigger that last showed this tip.
41
41
  * @property {AbortController} controller Tip-level event listener cleanup.
42
- * @property {() => void} stopTracking Floating-position cleanup.
42
+ * @property {(() => void) | null} stopTracking Floating-position cleanup while visible.
43
43
  * @property {boolean} generated True when the tip was created from data-tooltip text.
44
44
  * @property {{ parent: Node, next: ChildNode | null } | null} mount Original DOM position for explicit tips moved into a dialog/body root.
45
45
  * @property {ReturnType<typeof setTimeout> | null} timer Pending delayed show.
@@ -52,7 +52,7 @@ const HIDE_DELAY_MS = 100;
52
52
  let uid = 0;
53
53
  const triggerStates = new WeakMap(); // trigger -> { tip, cleanup }
54
54
  /** @type {WeakMap<Element, TooltipState>} */
55
- const tipStates = new WeakMap(); // tip -> { refs, activeRef, controller, untrack, generated, mount, timer }
55
+ const tipStates = new WeakMap(); // tip -> { refs, activeRef, controller, stopTracking, generated, mount, timer }
56
56
 
57
57
  function mountTip(tip, trigger) {
58
58
  const root = trigger.closest("dialog") || trigger.ownerDocument.body;
@@ -140,6 +140,22 @@ function repositionTip(ref, tip) {
140
140
  });
141
141
  }
142
142
 
143
+ function startTracking(tip, state) {
144
+ if (state.stopTracking) return;
145
+
146
+ state.stopTracking = autoUpdate(tip, () => {
147
+ if (isAlwaysVisible(state.activeRef)) tip.hidden = false;
148
+ if (state.activeRef && !tip.hidden && !repositionTip(state.activeRef, tip)) {
149
+ hideTip(tip, true);
150
+ }
151
+ });
152
+ }
153
+
154
+ function stopTracking(state) {
155
+ state?.stopTracking?.();
156
+ if (state) state.stopTracking = null;
157
+ }
158
+
143
159
  function hideTip(tip, force = false) {
144
160
  const state = tipStates.get(tip);
145
161
  if (!force && isAlwaysVisible(state?.activeRef)) return;
@@ -152,6 +168,7 @@ function hideTip(tip, force = false) {
152
168
  state.hideTimer = null;
153
169
  }
154
170
  tip.hidden = true;
171
+ stopTracking(state);
155
172
  }
156
173
 
157
174
  function clearHide(tip) {
@@ -185,12 +202,7 @@ function wireTip(tip, options = {}) {
185
202
  refs: new Set(),
186
203
  activeRef: null,
187
204
  controller,
188
- stopTracking: autoUpdate(tip, () => {
189
- if (isAlwaysVisible(state.activeRef)) tip.hidden = false;
190
- if (!tip.hidden && state.activeRef) {
191
- if (!repositionTip(state.activeRef, tip)) hideTip(tip, true);
192
- }
193
- }),
205
+ stopTracking: null,
194
206
  generated: options.generated === true,
195
207
  mount: options.mount || null,
196
208
  timer: null,
@@ -308,7 +320,7 @@ function ensureTip(trigger) {
308
320
 
309
321
  hideTip(tip, true);
310
322
  state.controller.abort();
311
- state.stopTracking();
323
+ stopTracking(state);
312
324
  tipStates.delete(tip);
313
325
  if (state.generated) tip.remove();
314
326
  else restoreTip(tip, state);
@@ -334,6 +346,7 @@ function show(tip, ref, immediate = false) {
334
346
  state.timer = null;
335
347
  tip.hidden = false;
336
348
  repositionTip(ref, tip);
349
+ startTracking(tip, state);
337
350
  };
338
351
 
339
352
  if (immediate) reveal();