actual-css 0.5.0 → 0.7.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.
- package/CHANGELOG.md +63 -0
- package/dist/actual.css +1 -0
- package/dist/actual.full.css +589 -131
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/browser-support.md +39 -14
- package/docs/design-notes/css-anchor.md +1 -1
- package/docs/design-notes/enhancement-contract.md +30 -13
- package/docs/design-notes/forced-colors.md +11 -7
- package/docs/design-notes/grid.md +4 -4
- package/docs/design-notes/naming.md +15 -9
- package/docs/design-notes/platform-alignment.md +60 -0
- package/docs/design-notes/popover-manual-poc.md +248 -0
- package/docs/design-notes/references.md +4 -0
- package/docs/design-notes/steps.md +748 -0
- package/docs/design-notes/surface-reparenting.md +122 -0
- package/docs/design-notes/widget-primitives.md +32 -15
- package/docs/navigation.json +1 -0
- package/docs/pages/components/alert.md +13 -8
- package/docs/pages/components/aura.md +102 -6
- package/docs/pages/components/avatar.md +9 -6
- package/docs/pages/components/badge.md +11 -7
- package/docs/pages/components/button.md +17 -17
- package/docs/pages/components/card.md +15 -8
- package/docs/pages/components/chat.md +1 -1
- package/docs/pages/components/dialog.md +10 -7
- package/docs/pages/components/drawer.md +1 -1
- package/docs/pages/components/fab.md +12 -10
- package/docs/pages/components/indicator.md +6 -6
- package/docs/pages/components/list.md +11 -2
- package/docs/pages/components/navbar.md +1 -1
- package/docs/pages/components/pagination.md +1 -1
- package/docs/pages/components/rating.md +4 -4
- package/docs/pages/components/skeleton.md +1 -1
- package/docs/pages/components/spinner.md +1 -1
- package/docs/pages/components/steps.md +376 -52
- package/docs/pages/components/table.md +5 -5
- package/docs/pages/enhancements/flyout.md +104 -12
- package/docs/pages/enhancements/overview.md +2 -2
- package/docs/pages/enhancements/scrollspy.md +1 -1
- package/docs/pages/enhancements/status-bar.md +20 -0
- package/docs/pages/enhancements/tabs.md +1 -1
- package/docs/pages/enhancements/tooltip.md +12 -0
- package/docs/pages/examples/overview.md +2 -0
- package/docs/pages/forms/choice-cards.md +4 -4
- package/docs/pages/forms/combobox.md +87 -0
- package/docs/pages/forms/floating-field.md +5 -3
- package/docs/pages/forms/joined-controls.md +4 -4
- package/docs/pages/forms/labels.md +8 -5
- package/docs/pages/forms/overview.md +25 -18
- package/docs/pages/forms/password.md +3 -2
- package/docs/pages/forms/range.md +13 -2
- package/docs/pages/forms/states-and-sizes.md +6 -4
- package/docs/pages/forms/validation.md +13 -9
- package/docs/pages/foundations/philosophy.md +15 -1
- package/docs/pages/foundations/theming.md +8 -0
- package/docs/pages/foundations/tokens.md +9 -6
- package/docs/pages/foundations/typography.md +1 -1
- package/docs/pages/guides/bootstrap.md +3 -3
- package/docs/pages/guides/introduction.md +1 -1
- package/docs/pages/guides/modular-import.md +21 -10
- package/docs/pages/guides/progressive-enhancement.md +96 -73
- package/docs/pages/guides/tailwind.md +2 -2
- package/docs/pages/layout/app-shell.md +4 -4
- package/docs/pages/layout/choosing.md +10 -6
- package/docs/pages/layout/grid.md +11 -10
- package/docs/pages/layout/stack.md +10 -6
- package/docs/pages/patterns/structured-lists.md +7 -7
- package/docs/pages/utilities/accessibility.md +1 -1
- package/docs/pages/utilities/flex.md +20 -13
- package/docs/pages/utilities/links.md +1 -1
- package/docs/pages/utilities/list.md +1 -1
- package/docs/pages/utilities/overflow.md +14 -7
- package/docs/pages/utilities/overview.md +22 -0
- package/docs/pages/utilities/shape.md +1 -1
- package/docs/pages/utilities/sizing-wrapping.md +10 -8
- package/docs/pages/utilities/spacing.md +26 -19
- package/docs/pages/utilities/text.md +1 -1
- package/llms.txt +27 -4
- package/package.json +7 -4
- package/scripts/reserved-classes.json +4 -1
- package/src/css/components/fab.css +44 -8
- package/src/css/components/flyout.css +49 -3
- package/src/css/components/join.css +7 -0
- package/src/css/components/list.css +3 -1
- package/src/css/components/menu.css +16 -10
- package/src/css/components/steps.css +277 -69
- package/src/css/components/tooltip.css +37 -1
- package/src/css/core/tokens.css +1 -0
- package/src/css/effects/aura.css +101 -11
- package/src/css/forms/custom-select.css +1 -1
- package/src/css/forms/floating-field.css +8 -6
- package/src/css/layout/container-query.css +37 -13
- package/src/css/layout/grid.css +7 -7
- package/src/css/layout/index.css +1 -1
- package/src/js/password.js +1 -1
- package/src/js/status.js +38 -2
- package/src/js/surface.js +28 -12
- package/src/js/tooltip.js +2 -2
- package/src/js/floating.js +0 -432
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* messages stay in the surrounding .field, not inside the cell, so the
|
|
8
8
|
* resting label can center on the control alone.
|
|
9
9
|
*
|
|
10
|
-
* The control must precede the label: the float is driven by the
|
|
11
|
-
* combinator and :placeholder-shown.
|
|
10
|
+
* The control must precede the label: the float is driven by the general
|
|
11
|
+
* sibling combinator and :placeholder-shown. Injected nodes may appear between
|
|
12
|
+
* the control and the label (password managers, extension wrappers); the cell
|
|
13
|
+
* contract stays a single control plus one label. Every .input/.textarea needs
|
|
12
14
|
* placeholder=" " to expose a reliable empty state — without it the label
|
|
13
15
|
* only reacts to focus.
|
|
14
16
|
*
|
|
@@ -56,14 +58,14 @@
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
/* Single-line controls rest in the middle until they receive a value. */
|
|
59
|
-
.floating-field > :is(.input, .select)
|
|
61
|
+
.floating-field > :is(.input, .select) ~ .field-label {
|
|
60
62
|
inset-block-start: 50%;
|
|
61
63
|
transform: translateY(-50%);
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
/* An empty textarea label follows the control's normal first-line position;
|
|
65
67
|
the control itself keeps the extra headroom reserved for its floated state. */
|
|
66
|
-
.floating-field > .textarea
|
|
68
|
+
.floating-field > .textarea ~ .field-label {
|
|
67
69
|
inset-block-start: calc(1em + var(--border-width));
|
|
68
70
|
transform: none;
|
|
69
71
|
}
|
|
@@ -72,7 +74,7 @@
|
|
|
72
74
|
not have propagated the value to the placeholder state yet. */
|
|
73
75
|
.floating-field
|
|
74
76
|
> :is(.input, .textarea):is(:focus, :autofill, :not(:placeholder-shown))
|
|
75
|
-
|
|
77
|
+
~ .field-label {
|
|
76
78
|
inset-block-start: var(--floating-label-top);
|
|
77
79
|
transform: none;
|
|
78
80
|
font-size: var(--font-size-xs);
|
|
@@ -91,7 +93,7 @@
|
|
|
91
93
|
.input[type="month"],
|
|
92
94
|
.input[type="week"]
|
|
93
95
|
)
|
|
94
|
-
|
|
96
|
+
~ .field-label {
|
|
95
97
|
inset-block-start: var(--floating-label-top);
|
|
96
98
|
transform: none;
|
|
97
99
|
font-size: var(--font-size-xs);
|
|
@@ -1,15 +1,39 @@
|
|
|
1
|
-
/* Convenience helper
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
/* Convenience helper for size-aware components: establishes an inline-size
|
|
2
|
+
query container named actual-container. The name is the contract, not this
|
|
3
|
+
class — an author can declare `container: actual-container / inline-size` on
|
|
4
|
+
their own region and get the same result.
|
|
5
|
+
|
|
6
|
+
actual-container is shared. Granting it to a region may enable size-aware
|
|
7
|
+
enhancements for any Actual component inside that region, not only the one
|
|
8
|
+
that motivated the container: .grid-N reads it for balanced subdivision,
|
|
9
|
+
.steps for its label collapse, and future components will read the same
|
|
10
|
+
context. That is the scope of the API, not a caveat.
|
|
11
|
+
|
|
12
|
+
An anonymous query container is not part of it. A region that declares
|
|
13
|
+
`container-type: inline-size` for the application's own purposes carries no
|
|
14
|
+
actual-container name, so no framework component changes behaviour there.
|
|
15
|
+
Opting into the protocol is always explicit. Nothing here is a prerequisite
|
|
16
|
+
either — every primitive is responsive without it; this adds precision.
|
|
17
|
+
|
|
18
|
+
Place it where the width you want measured lives: usually a wrapper for a
|
|
19
|
+
grid, whose queried children sit inside it, and the component itself for
|
|
20
|
+
.steps, whose own row is the width in question.
|
|
21
|
+
|
|
22
|
+
The rule for where it is safe is the containment rule, not a list of
|
|
23
|
+
primitives. Query containment removes the element's intrinsic inline-size
|
|
24
|
+
contribution, so:
|
|
25
|
+
|
|
26
|
+
safe the element's width is imposed by its context
|
|
27
|
+
(.steps sets inline-size: 100%, so it survives even as a
|
|
28
|
+
.cluster child — it wraps and fills)
|
|
29
|
+
|
|
30
|
+
unsafe the element's width depends on its contents' intrinsic
|
|
31
|
+
contribution (a bare .grid child of .cluster measures 0 once
|
|
32
|
+
contained, as does a float, inline-block, table, grid auto track,
|
|
33
|
+
max-content parent, or an abspos box sized by its contents)
|
|
34
|
+
|
|
35
|
+
So .cluster is neither safe nor unsafe; what matters is where the child's
|
|
36
|
+
width comes from. */
|
|
13
37
|
.container-query {
|
|
14
|
-
container: actual-
|
|
38
|
+
container: actual-container / inline-size;
|
|
15
39
|
}
|
package/src/css/layout/grid.css
CHANGED
|
@@ -86,13 +86,13 @@
|
|
|
86
86
|
min-inline-size: 0;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/* Balanced subdivision, activated by an ancestor container named actual-
|
|
89
|
+
/* Balanced subdivision, activated by an ancestor container named actual-container.
|
|
90
90
|
* A .grid-N inside such a container enters only divisor states of N. The name
|
|
91
91
|
* is deliberate: a grid must not key off the nearest anonymous query container,
|
|
92
92
|
* or a region that sets container-type: inline-size for an unrelated reason
|
|
93
93
|
* would silently change the grid. The author opts the grid in by naming the
|
|
94
94
|
* context — .container-query is the official helper, or declare
|
|
95
|
-
* container: actual-
|
|
95
|
+
* container: actual-container / inline-size on your own region.
|
|
96
96
|
*
|
|
97
97
|
* .grid-2 2 -> 1
|
|
98
98
|
* .grid-3 3 -> 1
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
* inline contribution and collapses it inside .cluster, .topbar, floats, and
|
|
110
110
|
* any shrink-to-fit box. See docs/design-notes/grid.md.
|
|
111
111
|
*
|
|
112
|
-
* Without an actual-
|
|
112
|
+
* Without an actual-container ancestor none of these @container rules resolve, so
|
|
113
113
|
* the auto-fill baseline above stays. The min-width: 0 rule is the lowest
|
|
114
114
|
* step: it pins the grid to one column inside a container before any larger
|
|
115
115
|
* threshold fires (a bare grid would otherwise show a 2 + 1 orphan at 28-48rem).
|
|
@@ -125,25 +125,25 @@
|
|
|
125
125
|
* Ascending min-width only: the last matching step wins by cascade order.
|
|
126
126
|
*/
|
|
127
127
|
@supports (container-type: inline-size) {
|
|
128
|
-
@container actual-
|
|
128
|
+
@container actual-container (min-width: 0px) {
|
|
129
129
|
:where(.grid-2, .grid-3, .grid-4, .grid-6) {
|
|
130
130
|
grid-template-columns: 1fr;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
@container actual-
|
|
134
|
+
@container actual-container (min-width: 28rem) {
|
|
135
135
|
:where(.grid-2, .grid-4, .grid-6) {
|
|
136
136
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
@container actual-
|
|
140
|
+
@container actual-container (min-width: 48rem) {
|
|
141
141
|
:where(.grid-3, .grid-6) {
|
|
142
142
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
@container actual-
|
|
146
|
+
@container actual-container (min-width: 64rem) {
|
|
147
147
|
:where(.grid-4) {
|
|
148
148
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
149
149
|
}
|
package/src/css/layout/index.css
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* .sidebar-layout main content + secondary aside
|
|
15
15
|
* .grid responsive collection; item width is the contract
|
|
16
16
|
* .grid-N structural density of N; balanced inside a container named
|
|
17
|
-
* actual-
|
|
17
|
+
* actual-container (in grid.css)
|
|
18
18
|
* .column-layout explicit 12-column region composition; the author owns
|
|
19
19
|
* narrow-container recomposition
|
|
20
20
|
* .scroller theme-aware scrollbar density and colour
|
package/src/js/password.js
CHANGED
|
@@ -92,7 +92,7 @@ if (typeof document !== "undefined") {
|
|
|
92
92
|
submitRoots.add(document);
|
|
93
93
|
document.addEventListener("submit", handleSubmit);
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
document.defaultView?.addEventListener("pagehide", () => {
|
|
96
96
|
for (const input of revealed) {
|
|
97
97
|
// Opportunistic housekeeping: an input removed from the DOM before
|
|
98
98
|
// navigation no longer needs reverting and can leave the set.
|
package/src/js/status.js
CHANGED
|
@@ -31,6 +31,12 @@
|
|
|
31
31
|
* - Any other code, without importing this module: dispatch `actual:status`
|
|
32
32
|
* directly — `detail: { message, intent, duration }`, or `{}` to clear.
|
|
33
33
|
*
|
|
34
|
+
* A message originating inside an open dialog temporarily mounts the singleton
|
|
35
|
+
* bar in that dialog. Content outside a modal dialog is inert and cannot sit
|
|
36
|
+
* above its top layer, so this keeps both the visual feedback and live region
|
|
37
|
+
* in the active subtree. Programmatic callers pass the originating element as
|
|
38
|
+
* `options.source`; event and command entry points propagate it automatically.
|
|
39
|
+
*
|
|
34
40
|
* The element contract is `[data-status][role="status"]`. Both are required:
|
|
35
41
|
* "status" is a generic domain word, so `role="status"` keeps the
|
|
36
42
|
* document-wide lookup from matching an unrelated app element that happens to
|
|
@@ -59,12 +65,39 @@ let statusTimer;
|
|
|
59
65
|
// never emptied by the previous message's cleanup.
|
|
60
66
|
let statusGeneration = 0;
|
|
61
67
|
let viewportTracker = null;
|
|
68
|
+
const statusHomes = new WeakMap();
|
|
62
69
|
|
|
63
70
|
function statusTarget() {
|
|
64
71
|
if (typeof document === "undefined") return null;
|
|
65
72
|
return document.querySelector(STATUS_SELECTOR);
|
|
66
73
|
}
|
|
67
74
|
|
|
75
|
+
function restoreStatusTarget(target) {
|
|
76
|
+
const home = statusHomes.get(target);
|
|
77
|
+
if (!home) return;
|
|
78
|
+
|
|
79
|
+
const parent = home.parent?.isConnected ? home.parent : target.ownerDocument?.body;
|
|
80
|
+
if (parent) {
|
|
81
|
+
const reference = home.nextSibling?.parentNode === parent ? home.nextSibling : null;
|
|
82
|
+
parent.insertBefore(target, reference);
|
|
83
|
+
}
|
|
84
|
+
statusHomes.delete(target);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function mountStatusTarget(target, source) {
|
|
88
|
+
const dialog = source?.closest?.("dialog[open]");
|
|
89
|
+
if (!dialog || dialog.ownerDocument !== target.ownerDocument) {
|
|
90
|
+
restoreStatusTarget(target);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (dialog.contains(target)) return;
|
|
94
|
+
|
|
95
|
+
if (!statusHomes.has(target)) {
|
|
96
|
+
statusHomes.set(target, { parent: target.parentNode, nextSibling: target.nextSibling });
|
|
97
|
+
}
|
|
98
|
+
dialog.append(target);
|
|
99
|
+
}
|
|
100
|
+
|
|
68
101
|
// The bar is fixed to the layout viewport, so the mobile software keyboard
|
|
69
102
|
// covers it. visualViewport reports the occluded band; the CSS adds it to the
|
|
70
103
|
// bottom inset. Tracking runs only while a message is on screen.
|
|
@@ -130,6 +163,8 @@ export function status(message, options = {}) {
|
|
|
130
163
|
clearTimeout(statusTimer);
|
|
131
164
|
statusGeneration++;
|
|
132
165
|
|
|
166
|
+
mountStatusTarget(target, options.source);
|
|
167
|
+
|
|
133
168
|
clearIntentClasses(target);
|
|
134
169
|
const intent = intentClasses(options.intent);
|
|
135
170
|
if (intent.length) {
|
|
@@ -168,6 +203,7 @@ status.clear = function clear() {
|
|
|
168
203
|
target.textContent = "";
|
|
169
204
|
clearIntentClasses(target);
|
|
170
205
|
releaseViewport();
|
|
206
|
+
restoreStatusTarget(target);
|
|
171
207
|
});
|
|
172
208
|
};
|
|
173
209
|
|
|
@@ -198,7 +234,7 @@ function connectStatusTrigger(trigger, target) {
|
|
|
198
234
|
if (typeof document !== "undefined") {
|
|
199
235
|
document.addEventListener(EVENTS.invalid, (event) => {
|
|
200
236
|
const message = event.detail?.message;
|
|
201
|
-
if (message) status(message, { intent: "danger" });
|
|
237
|
+
if (message) status(message, { intent: "danger", source: event.target });
|
|
202
238
|
});
|
|
203
239
|
|
|
204
240
|
// Public contract: any code can trigger the status bar this way, without
|
|
@@ -209,7 +245,7 @@ if (typeof document !== "undefined") {
|
|
|
209
245
|
// paths end in the same exit, so a detail that lost its message never
|
|
210
246
|
// strands a stale one on screen.
|
|
211
247
|
if (message != null) {
|
|
212
|
-
status(message, { intent, duration });
|
|
248
|
+
status(message, { intent, duration, source: event.target });
|
|
213
249
|
} else {
|
|
214
250
|
status.clear();
|
|
215
251
|
}
|
package/src/js/surface.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { autoUpdate, reposition, repositionAt } from "@lekoala/floating";
|
|
1
2
|
import enhance from "./enhance.js";
|
|
2
3
|
import { registerEscapeDismissal } from "./escape.js";
|
|
3
4
|
import { EVENTS } from "./events.js";
|
|
4
|
-
import { autoUpdate, reposition, repositionAt } from "./floating.js";
|
|
5
5
|
|
|
6
6
|
import { CLASSES } from "./selectors.js";
|
|
7
7
|
import { waitForTransitions } from "./transition.js";
|
|
@@ -210,6 +210,10 @@ function startSurfaceResources(menu, state) {
|
|
|
210
210
|
const armKey = (event) => {
|
|
211
211
|
if (!event.defaultPrevented && SCROLL_KEYS.has(event.key)) arm(event);
|
|
212
212
|
};
|
|
213
|
+
const dismissOnScroll = (event) => {
|
|
214
|
+
if (state.scrollIntentAt == null || menu.contains(event.target)) return;
|
|
215
|
+
closeSurface(menu);
|
|
216
|
+
};
|
|
213
217
|
const captureOptions = { signal: controller.signal, capture: true };
|
|
214
218
|
const passiveCaptureOptions = { ...captureOptions, passive: true };
|
|
215
219
|
const doc = menu.ownerDocument;
|
|
@@ -217,20 +221,13 @@ function startSurfaceResources(menu, state) {
|
|
|
217
221
|
doc.addEventListener("touchmove", arm, passiveCaptureOptions);
|
|
218
222
|
doc.addEventListener("wheel", arm, passiveCaptureOptions);
|
|
219
223
|
doc.addEventListener("keydown", armKey, { signal: controller.signal });
|
|
224
|
+
doc.addEventListener("scroll", dismissOnScroll, passiveCaptureOptions);
|
|
220
225
|
state.stopScrollIntent = () => controller.abort();
|
|
221
226
|
}
|
|
222
|
-
|
|
227
|
+
const anchor = state.point ? null : state.trigger || state.source;
|
|
228
|
+
state.stopTracking = autoUpdate(anchor, menu, ({ type }) => {
|
|
223
229
|
if (menu.hidden) return;
|
|
224
|
-
if (
|
|
225
|
-
type === "scroll" &&
|
|
226
|
-
state.dismissOnScroll &&
|
|
227
|
-
state.scrollIntentAt != null &&
|
|
228
|
-
timeStamp >= state.scrollIntentAt &&
|
|
229
|
-
[...targets].some((target) => target !== menu && !menu.contains(target))
|
|
230
|
-
) {
|
|
231
|
-
closeSurface(menu);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
230
|
+
if (type === "scroll" && state.dismissOnScroll) return;
|
|
234
231
|
applyPresentation(menu, state);
|
|
235
232
|
if (!positionSurface(menu)) closeSurface(menu);
|
|
236
233
|
});
|
|
@@ -249,11 +246,30 @@ export function prepareSurface(menu) {
|
|
|
249
246
|
reaperFor(menu)?.refresh(menu);
|
|
250
247
|
}
|
|
251
248
|
|
|
249
|
+
/*
|
|
250
|
+
* One lifecycle owner per surface. surface.js opens by clearing [hidden] and
|
|
251
|
+
* adding .is-open; it never calls showPopover(). So a [popover] panel handed to
|
|
252
|
+
* the runtime has two owners and stays shut: the platform keeps a popover it
|
|
253
|
+
* was never asked to show closed, whatever the runtime writes.
|
|
254
|
+
*
|
|
255
|
+
* This covers every popover value. "manual" is a candidate future transport for
|
|
256
|
+
* this module, which does not make it a legitimate mix today. Delete this guard
|
|
257
|
+
* in the commit that makes surface.js call showPopover().
|
|
258
|
+
*/
|
|
259
|
+
function warnPopoverConflict(panel) {
|
|
260
|
+
if (!panel.hasAttribute("popover")) return;
|
|
261
|
+
console.warn(
|
|
262
|
+
"Actual: the surface lifecycle cannot own a [popover] element — choose one lifecycle owner (remove the popover attribute, or drop the Actual enhancement).",
|
|
263
|
+
panel,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
252
267
|
export function retainSurface(panel) {
|
|
253
268
|
if (!panel) return () => {};
|
|
254
269
|
|
|
255
270
|
let entry = surfaceRetainers.get(panel);
|
|
256
271
|
if (!entry) {
|
|
272
|
+
warnPopoverConflict(panel);
|
|
257
273
|
prepareSurface(panel);
|
|
258
274
|
entry = { count: 0 };
|
|
259
275
|
surfaceRetainers.set(panel, entry);
|
package/src/js/tooltip.js
CHANGED
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
* Hide: blur, pointer leave, Escape
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
+
import { autoUpdate, reposition } from "@lekoala/floating";
|
|
30
31
|
import enhance from "./enhance.js";
|
|
31
32
|
import { registerEscapeDismissal } from "./escape.js";
|
|
32
|
-
import { autoUpdate, reposition } from "./floating.js";
|
|
33
33
|
import { CLASSES } from "./selectors.js";
|
|
34
34
|
|
|
35
35
|
const SHOW_DELAY_MS = 150;
|
|
@@ -163,7 +163,7 @@ function updateTrackedTip(tip, state) {
|
|
|
163
163
|
function startTracking(tip, state) {
|
|
164
164
|
if (state.stopTracking) return;
|
|
165
165
|
|
|
166
|
-
state.stopTracking = autoUpdate(tip, () => updateTrackedTip(tip, state));
|
|
166
|
+
state.stopTracking = autoUpdate(state.activeRef, tip, () => updateTrackedTip(tip, state));
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
function stopTracking(state) {
|