sheer-ui 0.4.2 → 0.4.3
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/package.json +1 -1
- package/src/lib/components/avatar/avatar.svelte.ts +34 -37
- package/src/lib/components/avatar/components/avatar-fallback.svelte +9 -6
- package/src/lib/components/avatar/components/avatar-image.svelte +18 -9
- package/src/lib/components/avatar/components/avatar.svelte +20 -16
- package/src/lib/components/checkbox/checkbox.svelte.ts +45 -55
- package/src/lib/components/checkbox/components/checkbox-group-label.svelte +9 -6
- package/src/lib/components/checkbox/components/checkbox-group.svelte +25 -16
- package/src/lib/components/checkbox/components/checkbox.svelte +39 -25
- package/src/lib/components/dialog/components/dialog-close.svelte +13 -8
- package/src/lib/components/dialog/components/dialog-content-headless.svelte +14 -11
- package/src/lib/components/dialog/components/dialog-description.svelte +9 -6
- package/src/lib/components/dialog/components/dialog-overlay.svelte +10 -7
- package/src/lib/components/dialog/components/dialog-title.svelte +12 -7
- package/src/lib/components/dialog/components/dialog-trigger.svelte +12 -7
- package/src/lib/components/dialog/components/dialog.svelte +10 -4
- package/src/lib/components/dialog/components/modal-surface.svelte +11 -8
- package/src/lib/components/dialog/dialog.svelte.ts +73 -61
- package/src/lib/components/drawer/drawer.svelte +8 -3
- package/src/lib/components/link-preview/components/link-preview-content.svelte +15 -8
- package/src/lib/components/link-preview/components/link-preview-trigger.svelte +9 -6
- package/src/lib/components/link-preview/components/link-preview.svelte +19 -11
- package/src/lib/components/link-preview/link-preview.svelte.ts +42 -43
- package/src/lib/components/menu/menu.svelte.ts +20 -1
- package/src/lib/components/meter/components/meter.svelte +18 -9
- package/src/lib/components/meter/meter.svelte.ts +15 -18
- package/src/lib/components/popover/components/popover-close.svelte +9 -6
- package/src/lib/components/popover/components/popover-content.svelte +12 -7
- package/src/lib/components/popover/components/popover-trigger.svelte +21 -10
- package/src/lib/components/popover/components/popover.svelte +9 -8
- package/src/lib/components/popover/popover.svelte.ts +68 -74
- package/src/lib/components/progress/components/progress.svelte +18 -9
- package/src/lib/components/progress/progress.svelte.ts +14 -17
- package/src/lib/components/separator/components/separator.svelte +15 -8
- package/src/lib/components/separator/separator.svelte.ts +12 -15
- package/src/lib/components/sidebar/sidebar-mobile-surface.svelte +8 -4
- package/src/lib/components/toggle/components/toggle.svelte +19 -14
- package/src/lib/components/toggle/toggle.svelte.ts +15 -20
- package/src/lib/components/tooltip/components/tooltip-content.svelte +15 -8
- package/src/lib/components/tooltip/components/tooltip-provider.svelte +18 -7
- package/src/lib/components/tooltip/components/tooltip-trigger.svelte +21 -10
- package/src/lib/components/tooltip/components/tooltip.svelte +34 -21
- package/src/lib/components/tooltip/tooltip.svelte.ts +96 -99
- package/src/lib/internal/escape-layer/use-escape-layer.svelte.ts +13 -29
- package/src/lib/internal/group-value.svelte.ts +11 -10
- package/src/lib/internal/native-popover.svelte.ts +6 -6
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { join } from 'overrule';
|
|
3
3
|
import type { ClassValue } from 'svelte/elements';
|
|
4
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
5
4
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
6
5
|
import type { TooltipContentProps } from '../types.js';
|
|
7
6
|
import { TooltipContentState } from '../tooltip.svelte.js';
|
|
@@ -28,13 +27,21 @@
|
|
|
28
27
|
}: TooltipContentProps & { arrowClasses?: ClassValue; portalProps?: unknown } = $props();
|
|
29
28
|
|
|
30
29
|
const contentState = TooltipContentState.create({
|
|
31
|
-
id
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
get id() {
|
|
31
|
+
return id;
|
|
32
|
+
},
|
|
33
|
+
get ref() {
|
|
34
|
+
return ref;
|
|
35
|
+
},
|
|
36
|
+
set ref(v) {
|
|
37
|
+
ref = v;
|
|
38
|
+
},
|
|
39
|
+
get onInteractOutside() {
|
|
40
|
+
return onInteractOutside;
|
|
41
|
+
},
|
|
42
|
+
get onEscapeKeydown() {
|
|
43
|
+
return onEscapeKeydown;
|
|
44
|
+
},
|
|
38
45
|
});
|
|
39
46
|
|
|
40
47
|
const lifecycleProps = useNativePopoverLifecycle(contentState);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
3
2
|
import type { TooltipProviderProps } from '../types.js';
|
|
4
3
|
import { TooltipProviderState } from '../tooltip.svelte.js';
|
|
5
4
|
|
|
@@ -14,12 +13,24 @@
|
|
|
14
13
|
}: TooltipProviderProps = $props();
|
|
15
14
|
|
|
16
15
|
TooltipProviderState.create({
|
|
17
|
-
delayDuration
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
get delayDuration() {
|
|
17
|
+
return delayDuration;
|
|
18
|
+
},
|
|
19
|
+
get disableCloseOnTriggerClick() {
|
|
20
|
+
return disableCloseOnTriggerClick;
|
|
21
|
+
},
|
|
22
|
+
get disableHoverableContent() {
|
|
23
|
+
return disableHoverableContent;
|
|
24
|
+
},
|
|
25
|
+
get disabled() {
|
|
26
|
+
return disabled;
|
|
27
|
+
},
|
|
28
|
+
get ignoreNonKeyboardFocus() {
|
|
29
|
+
return ignoreNonKeyboardFocus;
|
|
30
|
+
},
|
|
31
|
+
get skipDelayDuration() {
|
|
32
|
+
return skipDelayDuration;
|
|
33
|
+
},
|
|
23
34
|
});
|
|
24
35
|
</script>
|
|
25
36
|
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script lang="ts" generics="T = never">
|
|
6
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
7
6
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
8
7
|
import type { TooltipTriggerProps } from '../types.js';
|
|
9
8
|
import { TooltipTriggerState } from '../tooltip.svelte.js';
|
|
@@ -25,15 +24,27 @@
|
|
|
25
24
|
}: TooltipTriggerProps<T> = $props();
|
|
26
25
|
|
|
27
26
|
const triggerState = TooltipTriggerState.create({
|
|
28
|
-
id
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
get id() {
|
|
28
|
+
return id;
|
|
29
|
+
},
|
|
30
|
+
get disabled() {
|
|
31
|
+
return disabled ?? false;
|
|
32
|
+
},
|
|
33
|
+
get tabindex() {
|
|
34
|
+
return tabindex ?? 0;
|
|
35
|
+
},
|
|
36
|
+
get payload() {
|
|
37
|
+
return payload;
|
|
38
|
+
},
|
|
39
|
+
get tether() {
|
|
40
|
+
return tether;
|
|
41
|
+
},
|
|
42
|
+
get ref() {
|
|
43
|
+
return ref;
|
|
44
|
+
},
|
|
45
|
+
set ref(v) {
|
|
46
|
+
ref = v;
|
|
47
|
+
},
|
|
37
48
|
});
|
|
38
49
|
|
|
39
50
|
const mergedProps = $derived(mergeProps({ 'data-slot': 'tooltip-trigger' }, restProps, triggerState.props, { type }));
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script lang="ts" generics="T = never">
|
|
6
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
7
6
|
import { OpenCell } from '../../../internal/open-cell.svelte.js';
|
|
8
7
|
import type { TooltipRootProps } from '../types.js';
|
|
9
8
|
import { TooltipRootState } from '../tooltip.svelte.js';
|
|
@@ -22,34 +21,48 @@
|
|
|
22
21
|
children,
|
|
23
22
|
}: TooltipRootProps<T> = $props();
|
|
24
23
|
|
|
25
|
-
// Cell over the source prop; the engine keeps its boxed-open interface (vendored,
|
|
26
|
-
// ADR 0006) — the box is a bridge over the cell, so the cell owns `open`.
|
|
27
24
|
// svelte-ignore state_referenced_locally
|
|
28
25
|
const cell = givenCell ?? new OpenCell(() => open);
|
|
29
26
|
|
|
30
27
|
const rootState = TooltipRootState.create({
|
|
31
|
-
open
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
28
|
+
get open() {
|
|
29
|
+
return cell.open;
|
|
30
|
+
},
|
|
31
|
+
set open(v) {
|
|
32
|
+
cell.open = v;
|
|
33
|
+
},
|
|
34
|
+
get triggerId() {
|
|
35
|
+
return triggerId;
|
|
36
|
+
},
|
|
37
|
+
set triggerId(v) {
|
|
38
|
+
triggerId = v;
|
|
39
|
+
},
|
|
40
|
+
get delayDuration() {
|
|
41
|
+
return delayDuration;
|
|
42
|
+
},
|
|
43
|
+
get disableCloseOnTriggerClick() {
|
|
44
|
+
return disableCloseOnTriggerClick;
|
|
45
|
+
},
|
|
46
|
+
get disableHoverableContent() {
|
|
47
|
+
return disableHoverableContent;
|
|
48
|
+
},
|
|
49
|
+
get ignoreNonKeyboardFocus() {
|
|
50
|
+
return ignoreNonKeyboardFocus;
|
|
51
|
+
},
|
|
52
|
+
get disabled() {
|
|
53
|
+
return disabled;
|
|
54
|
+
},
|
|
55
|
+
get onOpenChangeComplete() {
|
|
56
|
+
return onOpenChangeComplete;
|
|
57
|
+
},
|
|
58
|
+
get tether() {
|
|
59
|
+
return tether;
|
|
60
|
+
},
|
|
48
61
|
});
|
|
49
62
|
</script>
|
|
50
63
|
|
|
51
64
|
{@render children?.({
|
|
52
|
-
open: rootState.opts.open
|
|
65
|
+
open: rootState.opts.open,
|
|
53
66
|
triggerId: rootState.activeTriggerId,
|
|
54
67
|
payload: rootState.activePayload as [T] extends [never] ? null : T | null,
|
|
55
68
|
})}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { attachRef, DOMContext
|
|
1
|
+
import { attachRef, DOMContext } from '../../internal/tools/index.js';
|
|
2
2
|
import { on } from 'svelte/events';
|
|
3
3
|
import { createContext, onMount, untrack } from 'svelte';
|
|
4
4
|
import { isElement } from '../../internal/tools/utils/dom.js';
|
|
5
5
|
import { createBitsAttrs, boolToEmptyStrOrUndef } from '../../internal/attrs.js';
|
|
6
|
-
import type { OnChangeFn, RefAttachment,
|
|
6
|
+
import type { OnChangeFn, RefAttachment, RefOpts } from '../../internal/types.js';
|
|
7
7
|
import type { FocusEventHandler, MouseEventHandler, PointerEventHandler } from 'svelte/elements';
|
|
8
8
|
import { createEffectTimeout } from '../../internal/timeout-fn.svelte.js';
|
|
9
9
|
import { SafePolygon } from '../../internal/safe-polygon.svelte.js';
|
|
@@ -122,7 +122,7 @@ export class TooltipTether<Payload = never> {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
get isOpen() {
|
|
125
|
-
return this.#state.root?.opts.open
|
|
125
|
+
return this.#state.root?.opts.open ?? false;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -130,14 +130,14 @@ export function createTooltipTether<Payload = never>() {
|
|
|
130
130
|
return new TooltipTether<Payload>();
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
interface TooltipProviderStateOpts
|
|
134
|
-
delayDuration: number;
|
|
135
|
-
disableHoverableContent: boolean;
|
|
136
|
-
disableCloseOnTriggerClick: boolean;
|
|
137
|
-
disabled: boolean;
|
|
138
|
-
ignoreNonKeyboardFocus: boolean;
|
|
139
|
-
skipDelayDuration: number;
|
|
140
|
-
}
|
|
133
|
+
interface TooltipProviderStateOpts {
|
|
134
|
+
readonly delayDuration: number;
|
|
135
|
+
readonly disableHoverableContent: boolean;
|
|
136
|
+
readonly disableCloseOnTriggerClick: boolean;
|
|
137
|
+
readonly disabled: boolean;
|
|
138
|
+
readonly ignoreNonKeyboardFocus: boolean;
|
|
139
|
+
readonly skipDelayDuration: number;
|
|
140
|
+
}
|
|
141
141
|
|
|
142
142
|
export class TooltipProviderState {
|
|
143
143
|
static create(opts: TooltipProviderStateOpts) {
|
|
@@ -154,7 +154,7 @@ export class TooltipProviderState {
|
|
|
154
154
|
() => {
|
|
155
155
|
this.isOpenDelayed = true;
|
|
156
156
|
},
|
|
157
|
-
() => this.opts.skipDelayDuration
|
|
157
|
+
() => this.opts.skipDelayDuration,
|
|
158
158
|
);
|
|
159
159
|
|
|
160
160
|
onMount(() =>
|
|
@@ -175,7 +175,7 @@ export class TooltipProviderState {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
#startTimer = () => {
|
|
178
|
-
const skipDuration = this.opts.skipDelayDuration
|
|
178
|
+
const skipDuration = this.opts.skipDelayDuration;
|
|
179
179
|
|
|
180
180
|
if (skipDuration === 0) {
|
|
181
181
|
// no grace period — reset immediately so next trigger waits the full delay
|
|
@@ -212,21 +212,17 @@ export class TooltipProviderState {
|
|
|
212
212
|
};
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
interface TooltipRootStateOpts
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
WritableBoxedValues<{
|
|
227
|
-
open: boolean;
|
|
228
|
-
triggerId: string | null;
|
|
229
|
-
}> {}
|
|
215
|
+
interface TooltipRootStateOpts {
|
|
216
|
+
readonly delayDuration: number | undefined;
|
|
217
|
+
readonly disableHoverableContent: boolean | undefined;
|
|
218
|
+
readonly disableCloseOnTriggerClick: boolean | undefined;
|
|
219
|
+
readonly disabled: boolean | undefined;
|
|
220
|
+
readonly ignoreNonKeyboardFocus: boolean | undefined;
|
|
221
|
+
readonly onOpenChangeComplete: OnChangeFn<boolean>;
|
|
222
|
+
readonly tether: TooltipTether<unknown> | undefined;
|
|
223
|
+
open: boolean;
|
|
224
|
+
triggerId: string | null;
|
|
225
|
+
}
|
|
230
226
|
|
|
231
227
|
export class TooltipRootState {
|
|
232
228
|
static create(opts: TooltipRootStateOpts) {
|
|
@@ -234,16 +230,16 @@ export class TooltipRootState {
|
|
|
234
230
|
}
|
|
235
231
|
readonly opts: TooltipRootStateOpts;
|
|
236
232
|
readonly provider: TooltipProviderState;
|
|
237
|
-
readonly delayDuration = $derived.by(() => this.opts.delayDuration
|
|
233
|
+
readonly delayDuration = $derived.by(() => this.opts.delayDuration ?? this.provider.opts.delayDuration);
|
|
238
234
|
readonly disableHoverableContent = $derived.by(
|
|
239
|
-
() => this.opts.disableHoverableContent
|
|
235
|
+
() => this.opts.disableHoverableContent ?? this.provider.opts.disableHoverableContent,
|
|
240
236
|
);
|
|
241
237
|
readonly disableCloseOnTriggerClick = $derived.by(
|
|
242
|
-
() => this.opts.disableCloseOnTriggerClick
|
|
238
|
+
() => this.opts.disableCloseOnTriggerClick ?? this.provider.opts.disableCloseOnTriggerClick,
|
|
243
239
|
);
|
|
244
|
-
readonly disabled = $derived.by(() => this.opts.disabled
|
|
240
|
+
readonly disabled = $derived.by(() => this.opts.disabled ?? this.provider.opts.disabled);
|
|
245
241
|
readonly ignoreNonKeyboardFocus = $derived.by(
|
|
246
|
-
() => this.opts.ignoreNonKeyboardFocus
|
|
242
|
+
() => this.opts.ignoreNonKeyboardFocus ?? this.provider.opts.ignoreNonKeyboardFocus,
|
|
247
243
|
);
|
|
248
244
|
readonly registry: TooltipTriggerRegistryState;
|
|
249
245
|
readonly tether: TooltipTetherState | null;
|
|
@@ -251,19 +247,19 @@ export class TooltipRootState {
|
|
|
251
247
|
#wasOpenDelayed = $state(false);
|
|
252
248
|
readonly #timerFn: ReturnType<typeof createEffectTimeout<() => void>>;
|
|
253
249
|
readonly stateAttr = $derived.by(() => {
|
|
254
|
-
if (!this.opts.open
|
|
250
|
+
if (!this.opts.open) return 'closed';
|
|
255
251
|
return this.#wasOpenDelayed ? 'delayed-open' : 'instant-open';
|
|
256
252
|
});
|
|
257
253
|
|
|
258
254
|
constructor(opts: TooltipRootStateOpts, provider: TooltipProviderState) {
|
|
259
255
|
this.opts = opts;
|
|
260
256
|
this.provider = provider;
|
|
261
|
-
this.tether = opts.tether
|
|
257
|
+
this.tether = opts.tether?.state ?? null;
|
|
262
258
|
this.registry = this.tether?.registry ?? new TooltipTriggerRegistryState();
|
|
263
259
|
this.#timerFn = createEffectTimeout(
|
|
264
260
|
() => {
|
|
265
261
|
this.#wasOpenDelayed = true;
|
|
266
|
-
this.opts.open
|
|
262
|
+
this.opts.open = true;
|
|
267
263
|
},
|
|
268
264
|
() => this.delayDuration ?? 0,
|
|
269
265
|
);
|
|
@@ -281,7 +277,7 @@ export class TooltipRootState {
|
|
|
281
277
|
|
|
282
278
|
let openStarted = false;
|
|
283
279
|
$effect(() => {
|
|
284
|
-
const isOpen = this.opts.open
|
|
280
|
+
const isOpen = this.opts.open;
|
|
285
281
|
if (!openStarted) {
|
|
286
282
|
openStarted = true;
|
|
287
283
|
return;
|
|
@@ -297,7 +293,7 @@ export class TooltipRootState {
|
|
|
297
293
|
});
|
|
298
294
|
|
|
299
295
|
$effect(() => {
|
|
300
|
-
const triggerId = this.opts.triggerId
|
|
296
|
+
const triggerId = this.opts.triggerId;
|
|
301
297
|
untrack(() => {
|
|
302
298
|
if (triggerId === this.registry.activeTriggerId) return;
|
|
303
299
|
this.registry.setActiveTrigger(triggerId);
|
|
@@ -307,8 +303,8 @@ export class TooltipRootState {
|
|
|
307
303
|
$effect(() => {
|
|
308
304
|
const activeTriggerId = this.registry.activeTriggerId;
|
|
309
305
|
untrack(() => {
|
|
310
|
-
if (this.opts.triggerId
|
|
311
|
-
this.opts.triggerId
|
|
306
|
+
if (this.opts.triggerId === activeTriggerId) return;
|
|
307
|
+
this.opts.triggerId = activeTriggerId;
|
|
312
308
|
});
|
|
313
309
|
});
|
|
314
310
|
}
|
|
@@ -317,12 +313,12 @@ export class TooltipRootState {
|
|
|
317
313
|
this.#timerFn.stop();
|
|
318
314
|
this.#wasOpenDelayed = false;
|
|
319
315
|
this.ensureActiveTrigger();
|
|
320
|
-
this.opts.open
|
|
316
|
+
this.opts.open = true;
|
|
321
317
|
};
|
|
322
318
|
|
|
323
319
|
handleClose = () => {
|
|
324
320
|
this.#timerFn.stop();
|
|
325
|
-
this.opts.open
|
|
321
|
+
this.opts.open = false;
|
|
326
322
|
};
|
|
327
323
|
|
|
328
324
|
#handleDelayedOpen = () => {
|
|
@@ -334,7 +330,7 @@ export class TooltipRootState {
|
|
|
334
330
|
// if no delay needed (either skip delay active or delay is 0), open immediately
|
|
335
331
|
if (shouldSkipDelay || delayDuration === 0) {
|
|
336
332
|
this.#wasOpenDelayed = false;
|
|
337
|
-
this.opts.open
|
|
333
|
+
this.opts.open = true;
|
|
338
334
|
} else {
|
|
339
335
|
// use timer for actual delays
|
|
340
336
|
this.#timerFn.start();
|
|
@@ -359,8 +355,8 @@ export class TooltipRootState {
|
|
|
359
355
|
return;
|
|
360
356
|
}
|
|
361
357
|
|
|
362
|
-
if (this.opts.triggerId
|
|
363
|
-
this.registry.setActiveTrigger(this.opts.triggerId
|
|
358
|
+
if (this.opts.triggerId !== null && this.registry.has(this.opts.triggerId)) {
|
|
359
|
+
this.registry.setActiveTrigger(this.opts.triggerId);
|
|
364
360
|
return;
|
|
365
361
|
}
|
|
366
362
|
|
|
@@ -375,7 +371,7 @@ export class TooltipRootState {
|
|
|
375
371
|
registerTrigger = (trigger: TooltipTriggerRecord) => {
|
|
376
372
|
this.registry.register(trigger);
|
|
377
373
|
|
|
378
|
-
if (trigger.disabled && this.registry.activeTriggerId === trigger.id && this.opts.open
|
|
374
|
+
if (trigger.disabled && this.registry.activeTriggerId === trigger.id && this.opts.open) {
|
|
379
375
|
this.handleClose();
|
|
380
376
|
}
|
|
381
377
|
};
|
|
@@ -383,7 +379,7 @@ export class TooltipRootState {
|
|
|
383
379
|
updateTrigger = (trigger: TooltipTriggerRecord) => {
|
|
384
380
|
this.registry.update(trigger);
|
|
385
381
|
|
|
386
|
-
if (trigger.disabled && this.registry.activeTriggerId === trigger.id && this.opts.open
|
|
382
|
+
if (trigger.disabled && this.registry.activeTriggerId === trigger.id && this.opts.open) {
|
|
387
383
|
this.handleClose();
|
|
388
384
|
}
|
|
389
385
|
};
|
|
@@ -392,7 +388,7 @@ export class TooltipRootState {
|
|
|
392
388
|
const isActive = this.registry.activeTriggerId === id;
|
|
393
389
|
this.registry.unregister(id);
|
|
394
390
|
|
|
395
|
-
if (isActive && this.opts.open
|
|
391
|
+
if (isActive && this.opts.open) {
|
|
396
392
|
this.handleClose();
|
|
397
393
|
}
|
|
398
394
|
};
|
|
@@ -414,20 +410,18 @@ export class TooltipRootState {
|
|
|
414
410
|
}
|
|
415
411
|
}
|
|
416
412
|
|
|
417
|
-
interface TooltipTriggerStateOpts
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
payload: unknown;
|
|
424
|
-
tether: TooltipTether<unknown> | undefined;
|
|
425
|
-
}> {}
|
|
413
|
+
interface TooltipTriggerStateOpts extends RefOpts {
|
|
414
|
+
readonly disabled: boolean;
|
|
415
|
+
readonly tabindex: number;
|
|
416
|
+
readonly payload: unknown;
|
|
417
|
+
readonly tether: TooltipTether<unknown> | undefined;
|
|
418
|
+
}
|
|
426
419
|
|
|
427
420
|
export class TooltipTriggerState {
|
|
428
421
|
static create(opts: TooltipTriggerStateOpts) {
|
|
429
|
-
|
|
430
|
-
|
|
422
|
+
const tether = opts.tether;
|
|
423
|
+
if (tether) {
|
|
424
|
+
return new TooltipTriggerState(opts, null, tether.state);
|
|
431
425
|
}
|
|
432
426
|
return new TooltipTriggerState(opts, getTooltipRoot(), null);
|
|
433
427
|
}
|
|
@@ -445,31 +439,34 @@ export class TooltipTriggerState {
|
|
|
445
439
|
this.opts = opts;
|
|
446
440
|
this.root = root;
|
|
447
441
|
this.tether = tether;
|
|
448
|
-
this.domContext = new DOMContext(opts.ref);
|
|
449
|
-
this.attachment = attachRef(
|
|
442
|
+
this.domContext = new DOMContext(() => opts.ref);
|
|
443
|
+
this.attachment = attachRef<HTMLElement>(
|
|
444
|
+
(v) => (opts.ref = v),
|
|
445
|
+
(v) => this.#register(v),
|
|
446
|
+
);
|
|
450
447
|
|
|
451
448
|
$effect(() => {
|
|
452
|
-
const _id = this.opts.id
|
|
449
|
+
const _id = this.opts.id;
|
|
453
450
|
untrack(() => {
|
|
454
|
-
this.#register(this.opts.ref
|
|
451
|
+
this.#register(this.opts.ref);
|
|
455
452
|
});
|
|
456
453
|
});
|
|
457
454
|
$effect(() => {
|
|
458
|
-
const _payload = this.opts.payload
|
|
455
|
+
const _payload = this.opts.payload;
|
|
459
456
|
untrack(() => {
|
|
460
|
-
this.#register(this.opts.ref
|
|
457
|
+
this.#register(this.opts.ref);
|
|
461
458
|
});
|
|
462
459
|
});
|
|
463
460
|
$effect(() => {
|
|
464
|
-
const _disabled = this.opts.disabled
|
|
461
|
+
const _disabled = this.opts.disabled;
|
|
465
462
|
untrack(() => {
|
|
466
|
-
this.#register(this.opts.ref
|
|
463
|
+
this.#register(this.opts.ref);
|
|
467
464
|
});
|
|
468
465
|
});
|
|
469
466
|
|
|
470
467
|
onMount(() => {
|
|
471
468
|
this.#mounted = true;
|
|
472
|
-
this.#register(this.opts.ref
|
|
469
|
+
this.#register(this.opts.ref);
|
|
473
470
|
|
|
474
471
|
return () => {
|
|
475
472
|
const root = this.#getRoot();
|
|
@@ -493,14 +490,14 @@ export class TooltipTriggerState {
|
|
|
493
490
|
|
|
494
491
|
#isDisabled = () => {
|
|
495
492
|
const root = this.#getRoot();
|
|
496
|
-
return this.opts.disabled
|
|
493
|
+
return this.opts.disabled || Boolean(root?.disabled);
|
|
497
494
|
};
|
|
498
495
|
|
|
499
496
|
#register = (node: HTMLElement | null) => {
|
|
500
497
|
if (!this.#mounted) return;
|
|
501
|
-
const id = this.opts.id
|
|
502
|
-
const payload = this.opts.payload
|
|
503
|
-
const disabled = this.opts.disabled
|
|
498
|
+
const id = this.opts.id;
|
|
499
|
+
const payload = this.opts.payload;
|
|
500
|
+
const disabled = this.opts.disabled;
|
|
504
501
|
|
|
505
502
|
if (this.#lastRegisteredId && this.#lastRegisteredId !== id) {
|
|
506
503
|
const root = this.#getRoot();
|
|
@@ -526,7 +523,7 @@ export class TooltipTriggerState {
|
|
|
526
523
|
this.tether.registry.register(triggerRecord);
|
|
527
524
|
}
|
|
528
525
|
|
|
529
|
-
if (disabled && this.tether.registry.activeTriggerId === id && root?.opts.open
|
|
526
|
+
if (disabled && this.tether.registry.activeTriggerId === id && root?.opts.open) {
|
|
530
527
|
root.handleClose();
|
|
531
528
|
}
|
|
532
529
|
} else {
|
|
@@ -567,14 +564,14 @@ export class TooltipTriggerState {
|
|
|
567
564
|
const root = this.#getRoot();
|
|
568
565
|
if (!root) return;
|
|
569
566
|
if (this.#isDisabled()) {
|
|
570
|
-
if (root.opts.open
|
|
567
|
+
if (root.opts.open) {
|
|
571
568
|
root.handleClose();
|
|
572
569
|
}
|
|
573
570
|
return;
|
|
574
571
|
}
|
|
575
572
|
if (e.pointerType === 'touch') return;
|
|
576
573
|
|
|
577
|
-
root.onTriggerEnter(this.opts.id
|
|
574
|
+
root.onTriggerEnter(this.opts.id);
|
|
578
575
|
this.#hasPointerMoveOpened = true;
|
|
579
576
|
};
|
|
580
577
|
|
|
@@ -582,7 +579,7 @@ export class TooltipTriggerState {
|
|
|
582
579
|
const root = this.#getRoot();
|
|
583
580
|
if (!root) return;
|
|
584
581
|
if (this.#isDisabled()) {
|
|
585
|
-
if (root.opts.open
|
|
582
|
+
if (root.opts.open) {
|
|
586
583
|
root.handleClose();
|
|
587
584
|
}
|
|
588
585
|
return;
|
|
@@ -590,7 +587,7 @@ export class TooltipTriggerState {
|
|
|
590
587
|
if (e.pointerType === 'touch') return;
|
|
591
588
|
if (this.#hasPointerMoveOpened) return;
|
|
592
589
|
|
|
593
|
-
root.onTriggerEnter(this.opts.id
|
|
590
|
+
root.onTriggerEnter(this.opts.id);
|
|
594
591
|
this.#hasPointerMoveOpened = true;
|
|
595
592
|
};
|
|
596
593
|
|
|
@@ -598,7 +595,7 @@ export class TooltipTriggerState {
|
|
|
598
595
|
const root = this.#getRoot();
|
|
599
596
|
if (!root) return;
|
|
600
597
|
if (this.#isDisabled()) return;
|
|
601
|
-
if (!root.isActiveTrigger(this.opts.id
|
|
598
|
+
if (!root.isActiveTrigger(this.opts.id)) {
|
|
602
599
|
this.#hasPointerMoveOpened = false;
|
|
603
600
|
return;
|
|
604
601
|
}
|
|
@@ -611,7 +608,7 @@ export class TooltipTriggerState {
|
|
|
611
608
|
if (isElement(relatedTarget)) {
|
|
612
609
|
for (const record of root.registry.triggers.values()) {
|
|
613
610
|
if (record.node !== relatedTarget) continue;
|
|
614
|
-
if (root.provider.opts.skipDelayDuration
|
|
611
|
+
if (root.provider.opts.skipDelayDuration > 0) {
|
|
615
612
|
this.#hasPointerMoveOpened = false;
|
|
616
613
|
return;
|
|
617
614
|
}
|
|
@@ -630,14 +627,14 @@ export class TooltipTriggerState {
|
|
|
630
627
|
if (!root) return;
|
|
631
628
|
if (this.#isPointerDown) return;
|
|
632
629
|
if (this.#isDisabled()) {
|
|
633
|
-
if (root.opts.open
|
|
630
|
+
if (root.opts.open) {
|
|
634
631
|
root.handleClose();
|
|
635
632
|
}
|
|
636
633
|
return;
|
|
637
634
|
}
|
|
638
635
|
|
|
639
636
|
if (root.ignoreNonKeyboardFocus && !e.currentTarget.matches(':focus-visible')) return;
|
|
640
|
-
root.setActiveTrigger(this.opts.id
|
|
637
|
+
root.setActiveTrigger(this.opts.id);
|
|
641
638
|
root.handleOpen();
|
|
642
639
|
};
|
|
643
640
|
|
|
@@ -655,18 +652,18 @@ export class TooltipTriggerState {
|
|
|
655
652
|
|
|
656
653
|
readonly props = $derived.by(() => {
|
|
657
654
|
const root = this.#getRoot();
|
|
658
|
-
const isOpenForTrigger = Boolean(root?.opts.open
|
|
655
|
+
const isOpenForTrigger = Boolean(root?.opts.open && root.isActiveTrigger(this.opts.id));
|
|
659
656
|
const isDisabled = this.#isDisabled();
|
|
660
657
|
|
|
661
658
|
return {
|
|
662
|
-
id: this.opts.id
|
|
659
|
+
id: this.opts.id,
|
|
663
660
|
'aria-describedby': isOpenForTrigger ? root?.contentNode?.id : undefined,
|
|
664
661
|
'data-state': isOpenForTrigger ? root?.stateAttr : 'closed',
|
|
665
662
|
'data-disabled': boolToEmptyStrOrUndef(isDisabled),
|
|
666
663
|
'data-delay-duration': `${root?.delayDuration ?? 0}`,
|
|
667
664
|
[tooltipAttrs.trigger]: '',
|
|
668
|
-
tabindex: isDisabled ? undefined : this.opts.tabindex
|
|
669
|
-
disabled: this.opts.disabled
|
|
665
|
+
tabindex: isDisabled ? undefined : this.opts.tabindex,
|
|
666
|
+
disabled: this.opts.disabled,
|
|
670
667
|
onpointerup: this.#onpointerup,
|
|
671
668
|
onpointerdown: this.#onpointerdown,
|
|
672
669
|
onpointerenter: this.#onpointerenter,
|
|
@@ -680,13 +677,10 @@ export class TooltipTriggerState {
|
|
|
680
677
|
});
|
|
681
678
|
}
|
|
682
679
|
|
|
683
|
-
interface TooltipContentStateOpts
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
onInteractOutside: (e: PointerEvent) => void;
|
|
688
|
-
onEscapeKeydown: (e: KeyboardEvent) => void;
|
|
689
|
-
}> {}
|
|
680
|
+
interface TooltipContentStateOpts extends RefOpts {
|
|
681
|
+
readonly onInteractOutside: (e: PointerEvent) => void;
|
|
682
|
+
readonly onEscapeKeydown: (e: KeyboardEvent) => void;
|
|
683
|
+
}
|
|
690
684
|
|
|
691
685
|
export class TooltipContentState {
|
|
692
686
|
static create(opts: TooltipContentStateOpts) {
|
|
@@ -698,17 +692,20 @@ export class TooltipContentState {
|
|
|
698
692
|
constructor(opts: TooltipContentStateOpts, root: TooltipRootState) {
|
|
699
693
|
this.opts = opts;
|
|
700
694
|
this.root = root;
|
|
701
|
-
this.attachment = attachRef(
|
|
695
|
+
this.attachment = attachRef<HTMLElement>(
|
|
696
|
+
(v) => (opts.ref = v),
|
|
697
|
+
(v) => (this.root.contentNode = v),
|
|
698
|
+
);
|
|
702
699
|
|
|
703
700
|
new SafePolygon({
|
|
704
701
|
triggerNode: () => this.root.triggerNode,
|
|
705
702
|
contentNode: () => this.root.contentNode,
|
|
706
|
-
enabled: () => this.root.opts.open
|
|
703
|
+
enabled: () => this.root.opts.open && !this.root.disableHoverableContent,
|
|
707
704
|
transitIntentTimeout: 180,
|
|
708
705
|
ignoredTargets: () => {
|
|
709
706
|
// only skip closing for sibling triggers when there's a skip-delay grace period;
|
|
710
707
|
// with skipDelayDuration=0 the close+reopen is intentional (full delay + re-animation)
|
|
711
|
-
if (this.root.provider.opts.skipDelayDuration
|
|
708
|
+
if (this.root.provider.opts.skipDelayDuration === 0) return [];
|
|
712
709
|
const nodes: HTMLElement[] = [];
|
|
713
710
|
const activeTriggerNode = this.root.triggerNode;
|
|
714
711
|
for (const record of this.root.registry.triggers.values()) {
|
|
@@ -731,13 +728,13 @@ export class TooltipContentState {
|
|
|
731
728
|
e.preventDefault();
|
|
732
729
|
return;
|
|
733
730
|
}
|
|
734
|
-
this.opts.onInteractOutside
|
|
731
|
+
this.opts.onInteractOutside(e);
|
|
735
732
|
if (e.defaultPrevented) return;
|
|
736
733
|
this.root.handleClose();
|
|
737
734
|
};
|
|
738
735
|
|
|
739
736
|
onEscapeKeydown = (e: KeyboardEvent) => {
|
|
740
|
-
this.opts.onEscapeKeydown
|
|
737
|
+
this.opts.onEscapeKeydown?.(e);
|
|
741
738
|
if (e.defaultPrevented) return;
|
|
742
739
|
this.root.handleClose();
|
|
743
740
|
};
|
|
@@ -750,12 +747,12 @@ export class TooltipContentState {
|
|
|
750
747
|
e.preventDefault();
|
|
751
748
|
};
|
|
752
749
|
|
|
753
|
-
readonly snippetProps = $derived.by(() => ({ open: this.root.opts.open
|
|
750
|
+
readonly snippetProps = $derived.by(() => ({ open: this.root.opts.open }));
|
|
754
751
|
|
|
755
752
|
readonly props = $derived.by(
|
|
756
753
|
() =>
|
|
757
754
|
({
|
|
758
|
-
id: this.opts.id
|
|
755
|
+
id: this.opts.id,
|
|
759
756
|
'data-state': this.root.stateAttr,
|
|
760
757
|
'data-disabled': boolToEmptyStrOrUndef(this.root.disabled),
|
|
761
758
|
style: {
|