bits-ui 2.16.4 → 2.17.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.
Files changed (42) hide show
  1. package/dist/bits/accordion/accordion.svelte.d.ts +4 -2
  2. package/dist/bits/accordion/accordion.svelte.js +2 -1
  3. package/dist/bits/collapsible/collapsible.svelte.d.ts +3 -1
  4. package/dist/bits/collapsible/collapsible.svelte.js +2 -1
  5. package/dist/bits/context-menu/components/context-menu.svelte +3 -1
  6. package/dist/bits/date-field/date-field.svelte.d.ts +5 -0
  7. package/dist/bits/date-field/date-field.svelte.js +5 -0
  8. package/dist/bits/dialog/dialog.svelte.d.ts +4 -0
  9. package/dist/bits/dialog/dialog.svelte.js +3 -1
  10. package/dist/bits/link-preview/link-preview.svelte.d.ts +5 -3
  11. package/dist/bits/link-preview/link-preview.svelte.js +2 -1
  12. package/dist/bits/menu/components/menu-sub-content-static.svelte +12 -3
  13. package/dist/bits/menu/components/menu-sub-content.svelte +12 -3
  14. package/dist/bits/menu/components/menu-sub-trigger.svelte +1 -1
  15. package/dist/bits/menu/components/menu.svelte +5 -0
  16. package/dist/bits/menu/components/menu.svelte.d.ts +1 -0
  17. package/dist/bits/menu/menu.svelte.d.ts +8 -4
  18. package/dist/bits/menu/menu.svelte.js +636 -12
  19. package/dist/bits/menubar/components/menubar-menu.svelte +3 -0
  20. package/dist/bits/menubar/menubar.svelte.d.ts +2 -0
  21. package/dist/bits/menubar/menubar.svelte.js +22 -2
  22. package/dist/bits/navigation-menu/components/navigation-menu-content.svelte +7 -2
  23. package/dist/bits/navigation-menu/components/navigation-menu-indicator.svelte +9 -2
  24. package/dist/bits/navigation-menu/components/navigation-menu-viewport.svelte +5 -3
  25. package/dist/bits/navigation-menu/navigation-menu.svelte.js +1 -1
  26. package/dist/bits/popover/popover.svelte.d.ts +7 -3
  27. package/dist/bits/popover/popover.svelte.js +3 -1
  28. package/dist/bits/select/select.svelte.d.ts +8 -4
  29. package/dist/bits/select/select.svelte.js +20 -3
  30. package/dist/bits/tooltip/tooltip.svelte.d.ts +5 -3
  31. package/dist/bits/tooltip/tooltip.svelte.js +3 -2
  32. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.d.ts +5 -5
  33. package/dist/bits/utilities/presence-layer/presence-layer.svelte +5 -1
  34. package/dist/bits/utilities/presence-layer/presence.svelte.d.ts +3 -38
  35. package/dist/bits/utilities/presence-layer/presence.svelte.js +49 -146
  36. package/dist/bits/utilities/presence-layer/types.d.ts +7 -3
  37. package/dist/internal/animations-complete.js +64 -9
  38. package/dist/internal/attrs.d.ts +5 -0
  39. package/dist/internal/attrs.js +8 -2
  40. package/dist/internal/presence-manager.svelte.d.ts +4 -1
  41. package/dist/internal/presence-manager.svelte.js +42 -1
  42. package/package.json +1 -1
@@ -24,4 +24,7 @@
24
24
  dir={menuState.root.opts.dir.current}
25
25
  _internal_variant="menubar"
26
26
  {...restProps}
27
+ _internal_should_skip_exit_animation={() =>
28
+ menuState.root.skipExitAnimationForMenuValue === menuState.opts.value.current
29
+ }
27
30
  />
@@ -18,6 +18,8 @@ export declare class MenubarRootState {
18
18
  readonly attachment: RefAttachment;
19
19
  wasOpenedByKeyboard: boolean;
20
20
  triggerIds: string[];
21
+ /** Outgoing menu id when swapping to another top-level menu... skip exit animation wait only then */
22
+ skipExitAnimationForMenuValue: string | null;
21
23
  valueToChangeHandler: Map<string, ReadableBox<OnChangeFn<boolean>>>;
22
24
  constructor(opts: MenubarRootStateOpts);
23
25
  /**
@@ -21,6 +21,8 @@ export class MenubarRootState {
21
21
  attachment;
22
22
  wasOpenedByKeyboard = $state(false);
23
23
  triggerIds = $state([]);
24
+ /** Outgoing menu id when swapping to another top-level menu... skip exit animation wait only then */
25
+ skipExitAnimationForMenuValue = $state(null);
24
26
  valueToChangeHandler = new Map();
25
27
  constructor(opts) {
26
28
  this.opts = opts;
@@ -55,6 +57,10 @@ export class MenubarRootState {
55
57
  };
56
58
  updateValue = (value) => {
57
59
  const currValue = this.opts.value.current;
60
+ const switchingMenus = Boolean(currValue && value && currValue !== value);
61
+ if (switchingMenus) {
62
+ this.skipExitAnimationForMenuValue = currValue;
63
+ }
58
64
  const currHandler = this.valueToChangeHandler.get(currValue)?.current;
59
65
  const nextHandler = this.valueToChangeHandler.get(value)?.current;
60
66
  this.opts.value.current = value;
@@ -64,6 +70,11 @@ export class MenubarRootState {
64
70
  if (nextHandler) {
65
71
  nextHandler(true);
66
72
  }
73
+ if (switchingMenus) {
74
+ afterTick(() => {
75
+ this.skipExitAnimationForMenuValue = null;
76
+ });
77
+ }
67
78
  };
68
79
  getTriggers = () => {
69
80
  const node = this.opts.ref.current;
@@ -271,13 +282,22 @@ export class MenubarContentState {
271
282
  if (isPrevKey)
272
283
  candidates.reverse();
273
284
  const candidateValues = candidates.map(({ value }) => value);
274
- const currentIndex = candidateValues.indexOf(this.menu.opts.value.current);
285
+ // use the root's open menu id — during rapid switching, stale content can still be
286
+ // focused while another menu is already open; per-menu value would navigate from the wrong index
287
+ const openMenuValue = this.root.opts.value.current;
288
+ if (!openMenuValue)
289
+ return;
290
+ const currentIndex = candidateValues.indexOf(openMenuValue);
291
+ if (currentIndex === -1)
292
+ return;
275
293
  candidates = this.root.opts.loop.current
276
294
  ? wrapArray(candidates, currentIndex + 1)
277
295
  : candidates.slice(currentIndex + 1);
278
296
  const [nextValue] = candidates;
279
- if (nextValue)
297
+ if (nextValue) {
280
298
  this.menu.root.onMenuOpen(nextValue.value, nextValue.triggerId);
299
+ e.preventDefault();
300
+ }
281
301
  };
282
302
  props = $derived.by(() => ({
283
303
  id: this.opts.id.current,
@@ -3,6 +3,7 @@
3
3
  import { NavigationMenuContentState } from "../navigation-menu.svelte.js";
4
4
  import NavigationMenuContentImpl from "./navigation-menu-content-impl.svelte";
5
5
  import { createId } from "../../../internal/create-id.js";
6
+ import { getDataTransitionAttrs } from "../../../internal/attrs.js";
6
7
  import type { NavigationMenuContentProps } from "../../../types.js";
7
8
  import Portal from "../../utilities/portal/portal.svelte";
8
9
  import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
@@ -38,8 +39,12 @@
38
39
  open={forceMount || contentState.open || contentState.isLastActiveValue}
39
40
  ref={contentState.opts.ref}
40
41
  >
41
- {#snippet presence()}
42
- <NavigationMenuContentImpl {...mergedProps} {children} {child} />
42
+ {#snippet presence({ transitionStatus })}
43
+ <NavigationMenuContentImpl
44
+ {...mergeProps(mergedProps, getDataTransitionAttrs(transitionStatus))}
45
+ {children}
46
+ {child}
47
+ />
43
48
  <Mounted bind:mounted={contentState.mounted} />
44
49
  {/snippet}
45
50
  </PresenceLayer>
@@ -4,6 +4,7 @@
4
4
  import { NavigationMenuIndicatorState } from "../navigation-menu.svelte.js";
5
5
  import NavigationMenuIndicatorImpl from "./navigation-menu-indicator-impl.svelte";
6
6
  import { createId } from "../../../internal/create-id.js";
7
+ import { getDataTransitionAttrs } from "../../../internal/attrs.js";
7
8
  import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
8
9
  import Portal from "../../utilities/portal/portal.svelte";
9
10
 
@@ -25,8 +26,14 @@
25
26
  {#if indicatorState.context.indicatorTrackRef.current}
26
27
  <Portal to={indicatorState.context.indicatorTrackRef.current}>
27
28
  <PresenceLayer open={forceMount || indicatorState.isVisible} ref={boxWith(() => ref)}>
28
- {#snippet presence()}
29
- <NavigationMenuIndicatorImpl {...mergedProps} {children} {child} {id} bind:ref />
29
+ {#snippet presence({ transitionStatus })}
30
+ <NavigationMenuIndicatorImpl
31
+ {...mergeProps(mergedProps, getDataTransitionAttrs(transitionStatus))}
32
+ {children}
33
+ {child}
34
+ {id}
35
+ bind:ref
36
+ />
30
37
  {/snippet}
31
38
  </PresenceLayer>
32
39
  </Portal>
@@ -2,6 +2,7 @@
2
2
  import type { NavigationMenuViewportProps } from "../types.js";
3
3
  import { NavigationMenuViewportState } from "../navigation-menu.svelte.js";
4
4
  import { createId } from "../../../internal/create-id.js";
5
+ import { getDataTransitionAttrs } from "../../../internal/attrs.js";
5
6
  import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
6
7
  import { boxWith, mergeProps } from "svelte-toolbelt";
7
8
  import { Mounted } from "../../utilities/index.js";
@@ -29,11 +30,12 @@
29
30
  </script>
30
31
 
31
32
  <PresenceLayer open={forceMount || viewportState.open} ref={viewportState.opts.ref}>
32
- {#snippet presence()}
33
+ {#snippet presence({ transitionStatus })}
34
+ {@const presenceProps = getDataTransitionAttrs(transitionStatus)}
33
35
  {#if child}
34
- {@render child({ props: mergedProps })}
36
+ {@render child({ props: mergeProps(mergedProps, presenceProps) })}
35
37
  {:else}
36
- <div {...mergedProps}>
38
+ <div {...mergeProps(mergedProps, presenceProps)}>
37
39
  {@render children?.()}
38
40
  </div>
39
41
  {/if}
@@ -80,7 +80,7 @@ export class NavigationMenuRootState {
80
80
  const isOpen = this.opts?.value?.current !== "";
81
81
  if (isOpen || this.isDelaySkipped.current) {
82
82
  // 150 for user to switch trigger or move into content view
83
- return 100;
83
+ return 150;
84
84
  }
85
85
  else {
86
86
  return this.opts.delayDuration.current;
@@ -87,9 +87,6 @@ export declare class PopoverContentState {
87
87
  open: boolean;
88
88
  };
89
89
  readonly props: {
90
- readonly id: string;
91
- readonly tabindex: -1;
92
- readonly "data-state": "open" | "closed";
93
90
  readonly style: {
94
91
  readonly pointerEvents: "auto";
95
92
  readonly contain: "layout style";
@@ -98,6 +95,11 @@ export declare class PopoverContentState {
98
95
  readonly onfocusin: (e: BitsFocusEvent) => void;
99
96
  readonly onpointerenter: (e: BitsPointerEvent) => void;
100
97
  readonly onpointerleave: (e: BitsPointerEvent) => void;
98
+ readonly "data-starting-style"?: "";
99
+ readonly "data-ending-style"?: "";
100
+ readonly id: string;
101
+ readonly tabindex: -1;
102
+ readonly "data-state": "open" | "closed";
101
103
  };
102
104
  readonly popperProps: {
103
105
  onInteractOutside: (e: PointerEvent) => void;
@@ -134,6 +136,8 @@ export declare class PopoverOverlayState {
134
136
  open: boolean;
135
137
  };
136
138
  readonly props: {
139
+ readonly "data-starting-style"?: "";
140
+ readonly "data-ending-style"?: "";
137
141
  readonly id: string;
138
142
  readonly style: {
139
143
  readonly pointerEvents: "auto";
@@ -1,7 +1,7 @@
1
1
  import { attachRef, boxWith, DOMContext, } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
3
  import { kbd } from "../../internal/kbd.js";
4
- import { createBitsAttrs, boolToStr, getDataOpenClosed } from "../../internal/attrs.js";
4
+ import { createBitsAttrs, boolToStr, getDataOpenClosed, getDataTransitionAttrs, } from "../../internal/attrs.js";
5
5
  import { isElement, isTouch } from "../../internal/is.js";
6
6
  import { PresenceManager } from "../../internal/presence-manager.svelte.js";
7
7
  import { SafePolygon } from "../../internal/safe-polygon.svelte.js";
@@ -325,6 +325,7 @@ export class PopoverContentState {
325
325
  id: this.opts.id.current,
326
326
  tabindex: -1,
327
327
  "data-state": getDataOpenClosed(this.root.opts.open.current),
328
+ ...getDataTransitionAttrs(this.root.contentPresence.transitionStatus),
328
329
  [popoverAttrs.content]: "",
329
330
  style: {
330
331
  pointerEvents: "auto",
@@ -397,6 +398,7 @@ export class PopoverOverlayState {
397
398
  pointerEvents: "auto",
398
399
  },
399
400
  "data-state": getDataOpenClosed(this.root.opts.open.current),
401
+ ...getDataTransitionAttrs(this.root.overlayPresence.transitionStatus),
400
402
  ...this.attachment,
401
403
  }));
402
404
  }
@@ -41,11 +41,13 @@ declare abstract class SelectBaseRootState {
41
41
  readonly highlightedValue: string | null;
42
42
  readonly highlightedId: string | undefined;
43
43
  readonly highlightedLabel: string | null;
44
+ contentIsPositioned: boolean;
44
45
  isUsingKeyboard: boolean;
45
46
  isCombobox: boolean;
46
47
  domContext: DOMContext;
47
48
  constructor(opts: SelectBaseRootStateOpts);
48
49
  setHighlightedNode(node: HTMLElement | null, initial?: boolean): void;
50
+ scrollHighlightedNodeIntoView(node: HTMLElement): void;
49
51
  getCandidateNodes(): HTMLElement[];
50
52
  setHighlightedToFirstCandidate(initial?: boolean): void;
51
53
  getNodeByValue(value: string): HTMLElement | null;
@@ -211,10 +213,6 @@ export declare class SelectContentState {
211
213
  open: boolean;
212
214
  };
213
215
  readonly props: {
214
- readonly id: string;
215
- readonly role: "listbox";
216
- readonly "aria-multiselectable": "true" | undefined;
217
- readonly "data-state": "open" | "closed";
218
216
  readonly style: {
219
217
  readonly display: "flex";
220
218
  readonly flexDirection: "column";
@@ -223,6 +221,12 @@ export declare class SelectContentState {
223
221
  readonly pointerEvents: "auto";
224
222
  };
225
223
  readonly onpointermove: (_: BitsPointerEvent) => void;
224
+ readonly "data-starting-style"?: "";
225
+ readonly "data-ending-style"?: "";
226
+ readonly id: string;
227
+ readonly role: "listbox";
228
+ readonly "aria-multiselectable": "true" | undefined;
229
+ readonly "data-state": "open" | "closed";
226
230
  };
227
231
  readonly popperProps: {
228
232
  onInteractOutside: (e: PointerEvent) => void;
@@ -2,7 +2,7 @@ import { Context, Previous, watch } from "runed";
2
2
  import { afterSleep, afterTick, onDestroyEffect, attachRef, DOMContext, boxWith, } from "svelte-toolbelt";
3
3
  import { on } from "svelte/events";
4
4
  import { backward, forward, next, prev } from "../../internal/arrays.js";
5
- import { boolToStr, boolToStrTrueOrUndef, boolToEmptyStrOrUndef, getDataOpenClosed, boolToTrueOrUndef, } from "../../internal/attrs.js";
5
+ import { boolToStr, boolToStrTrueOrUndef, boolToEmptyStrOrUndef, getDataOpenClosed, boolToTrueOrUndef, getDataTransitionAttrs, } from "../../internal/attrs.js";
6
6
  import { kbd } from "../../internal/kbd.js";
7
7
  import { noop } from "../../internal/noop.js";
8
8
  import { isIOS } from "../../internal/is.js";
@@ -65,6 +65,7 @@ class SelectBaseRootState {
65
65
  return null;
66
66
  return this.highlightedNode.getAttribute("data-label");
67
67
  });
68
+ contentIsPositioned = $state(false);
68
69
  isUsingKeyboard = false;
69
70
  isCombobox = false;
70
71
  domContext = new DOMContext(() => null);
@@ -87,9 +88,14 @@ class SelectBaseRootState {
87
88
  setHighlightedNode(node, initial = false) {
88
89
  this.highlightedNode = node;
89
90
  if (node && (this.isUsingKeyboard || initial)) {
90
- node.scrollIntoView({ block: this.opts.scrollAlignment.current });
91
+ this.scrollHighlightedNodeIntoView(node);
91
92
  }
92
93
  }
94
+ scrollHighlightedNodeIntoView(node) {
95
+ if (!this.viewportNode || !this.contentIsPositioned)
96
+ return;
97
+ node.scrollIntoView({ block: this.opts.scrollAlignment.current });
98
+ }
93
99
  getCandidateNodes() {
94
100
  const node = this.contentNode;
95
101
  if (!node)
@@ -713,13 +719,20 @@ export class SelectContentState {
713
719
  }
714
720
  onDestroyEffect(() => {
715
721
  this.root.contentNode = null;
722
+ this.root.contentIsPositioned = false;
716
723
  this.isPositioned = false;
717
724
  });
718
725
  watch(() => this.root.opts.open.current, () => {
719
726
  if (this.root.opts.open.current)
720
727
  return;
728
+ this.root.contentIsPositioned = false;
721
729
  this.isPositioned = false;
722
730
  });
731
+ watch([() => this.isPositioned, () => this.root.highlightedNode], () => {
732
+ if (!this.isPositioned || !this.root.highlightedNode)
733
+ return;
734
+ this.root.scrollHighlightedNodeIntoView(this.root.highlightedNode);
735
+ });
723
736
  this.onpointermove = this.onpointermove.bind(this);
724
737
  }
725
738
  onpointermove(_) {
@@ -759,6 +772,7 @@ export class SelectContentState {
759
772
  role: "listbox",
760
773
  "aria-multiselectable": this.root.isMulti ? "true" : undefined,
761
774
  "data-state": getDataOpenClosed(this.root.opts.open.current),
775
+ ...getDataTransitionAttrs(this.root.contentPresence.transitionStatus),
762
776
  [this.root.getBitsAttr("content")]: "",
763
777
  style: {
764
778
  display: "flex",
@@ -782,6 +796,7 @@ export class SelectContentState {
782
796
  // onPlaced is also called when the menu is closed, so we need to check if the menu
783
797
  // is actually open to avoid setting positioning to true when the menu is closed
784
798
  if (this.root.opts.open.current) {
799
+ this.root.contentIsPositioned = true;
785
800
  this.isPositioned = true;
786
801
  }
787
802
  },
@@ -1120,7 +1135,9 @@ export class SelectScrollDownButtonState {
1120
1135
  }
1121
1136
  this.scrollIntoViewTimer = afterSleep(5, () => {
1122
1137
  const activeItem = this.root.highlightedNode;
1123
- activeItem?.scrollIntoView({ block: this.root.opts.scrollAlignment.current });
1138
+ if (!activeItem)
1139
+ return;
1140
+ this.root.scrollHighlightedNodeIntoView(activeItem);
1124
1141
  });
1125
1142
  });
1126
1143
  }
@@ -153,12 +153,14 @@ export declare class TooltipContentState {
153
153
  open: boolean;
154
154
  };
155
155
  readonly props: {
156
- readonly id: string;
157
- readonly "data-state": "closed" | "delayed-open" | "instant-open";
158
- readonly "data-disabled": "" | undefined;
159
156
  readonly style: {
160
157
  readonly outline: "none";
161
158
  };
159
+ readonly "data-starting-style"?: "";
160
+ readonly "data-ending-style"?: "";
161
+ readonly id: string;
162
+ readonly "data-state": "closed" | "delayed-open" | "instant-open";
163
+ readonly "data-disabled": "" | undefined;
162
164
  };
163
165
  readonly popperProps: {
164
166
  onInteractOutside: (e: PointerEvent) => void;
@@ -2,7 +2,7 @@ import { onMountEffect, attachRef, DOMContext, simpleBox, boxWith, } from "svelt
2
2
  import { on } from "svelte/events";
3
3
  import { Context, watch } from "runed";
4
4
  import { isElement, isFocusVisible } from "../../internal/is.js";
5
- import { createBitsAttrs, boolToEmptyStrOrUndef } from "../../internal/attrs.js";
5
+ import { createBitsAttrs, boolToEmptyStrOrUndef, getDataTransitionAttrs, } from "../../internal/attrs.js";
6
6
  import { TimeoutFn } from "../../internal/timeout-fn.js";
7
7
  import { SafePolygon } from "../../internal/safe-polygon.svelte.js";
8
8
  import { PresenceManager } from "../../internal/presence-manager.svelte.js";
@@ -163,8 +163,8 @@ export class TooltipProviderState {
163
163
  onClose = (tooltip) => {
164
164
  if (this.#openTooltip === tooltip) {
165
165
  this.#openTooltip = null;
166
+ this.#startTimer();
166
167
  }
167
- this.#startTimer();
168
168
  };
169
169
  isTooltipOpen = (tooltip) => {
170
170
  return this.#openTooltip === tooltip;
@@ -665,6 +665,7 @@ export class TooltipContentState {
665
665
  id: this.opts.id.current,
666
666
  "data-state": this.root.stateAttr,
667
667
  "data-disabled": boolToEmptyStrOrUndef(this.root.disabled),
668
+ ...getDataTransitionAttrs(this.root.contentPresence.transitionStatus),
668
669
  style: {
669
670
  outline: "none",
670
671
  },
@@ -348,7 +348,7 @@ export declare class FloatingContentState {
348
348
  readonly perspective?: import("csstype").Property.Perspective<0 | (string & {})> | undefined;
349
349
  readonly perspectiveOrigin?: import("csstype").Property.PerspectiveOrigin<0 | (string & {})> | undefined;
350
350
  readonly pointerEvents?: import("csstype").Property.PointerEvents | undefined;
351
- position: "relative" | "absolute" | "fixed" | "sticky" | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "-webkit-sticky" | "static";
351
+ position: "relative" | "absolute" | "inherit" | "fixed" | "sticky" | "-moz-initial" | "initial" | "revert" | "revert-layer" | "unset" | "-webkit-sticky" | "static";
352
352
  readonly printColorAdjust?: import("csstype").Property.PrintColorAdjust | undefined;
353
353
  readonly quotes?: import("csstype").Property.Quotes | undefined;
354
354
  readonly resize?: import("csstype").Property.Resize | undefined;
@@ -901,10 +901,10 @@ export declare class FloatingContentState {
901
901
  readonly vectorEffect?: import("csstype").Property.VectorEffect | undefined;
902
902
  readonly "pointer-events"?: string | undefined;
903
903
  readonly "--bits-floating-transform-origin": `${any} ${any}`;
904
- readonly "--bits-floating-available-width": "undefinedpx" | `${number}px`;
905
- readonly "--bits-floating-available-height": "undefinedpx" | `${number}px`;
906
- readonly "--bits-floating-anchor-width": "undefinedpx" | `${number}px`;
907
- readonly "--bits-floating-anchor-height": "undefinedpx" | `${number}px`;
904
+ readonly "--bits-floating-available-width": `${number}px` | "undefinedpx";
905
+ readonly "--bits-floating-available-height": `${number}px` | "undefinedpx";
906
+ readonly "--bits-floating-anchor-width": `${number}px` | "undefinedpx";
907
+ readonly "--bits-floating-anchor-height": `${number}px` | "undefinedpx";
908
908
  };
909
909
  readonly dir: Direction;
910
910
  };
@@ -12,5 +12,9 @@
12
12
  </script>
13
13
 
14
14
  {#if forceMount || open || presenceState.isPresent}
15
- {@render presence?.({ present: presenceState.isPresent })}
15
+ {@render
16
+ presence?.({
17
+ present: presenceState.isPresent,
18
+ transitionStatus: presenceState.transitionStatus,
19
+ })}
16
20
  {/if}
@@ -1,50 +1,15 @@
1
1
  import { type ReadableBox, type ReadableBoxedValues } from "svelte-toolbelt";
2
- import { Previous } from "runed";
3
- import { StateMachine } from "../../../internal/state-machine.js";
2
+ import type { TransitionState } from "../../../internal/attrs.js";
4
3
  export interface PresenceOptions extends ReadableBoxedValues<{
5
4
  open: boolean;
6
5
  ref: HTMLElement | null;
7
6
  }> {
8
7
  }
9
- type PresenceStatus = "unmounted" | "mounted" | "unmountSuspended";
10
- /**
11
- * Cached style properties to avoid storing live CSSStyleDeclaration
12
- * which triggers style recalculations when accessed.
13
- */
14
- interface CachedStyles {
15
- display: string;
16
- animationName: string;
17
- }
18
- declare const presenceMachine: {
19
- readonly mounted: {
20
- readonly UNMOUNT: "unmounted";
21
- readonly ANIMATION_OUT: "unmountSuspended";
22
- };
23
- readonly unmountSuspended: {
24
- readonly MOUNT: "mounted";
25
- readonly ANIMATION_END: "unmounted";
26
- };
27
- readonly unmounted: {
28
- readonly MOUNT: "mounted";
29
- };
30
- };
31
- type PresenceMachine = StateMachine<typeof presenceMachine>;
32
8
  export declare class Presence {
9
+ #private;
33
10
  readonly opts: PresenceOptions;
34
- prevAnimationNameState: string;
35
- styles: CachedStyles;
36
- initialStatus: PresenceStatus;
37
- previousPresent: Previous<boolean>;
38
- machine: PresenceMachine;
39
11
  present: ReadableBox<boolean>;
40
12
  constructor(opts: PresenceOptions);
41
- /**
42
- * Triggering an ANIMATION_OUT during an ANIMATION_IN will fire an `animationcancel`
43
- * event for ANIMATION_IN after we have entered `unmountSuspended` state. So, we
44
- * make sure we only trigger ANIMATION_END for the currently active animation.
45
- */
46
- handleAnimationEnd(event: AnimationEvent): void;
47
- handleAnimationStart(event: AnimationEvent): void;
48
13
  isPresent: boolean;
14
+ get transitionStatus(): TransitionState;
49
15
  }
50
- export {};