bits-ui 2.14.0 → 2.14.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.
Files changed (53) hide show
  1. package/dist/bits/accordion/accordion.svelte.d.ts +5 -1
  2. package/dist/bits/accordion/accordion.svelte.js +21 -2
  3. package/dist/bits/accordion/components/accordion-content.svelte +12 -24
  4. package/dist/bits/alert-dialog/components/alert-dialog-content.svelte +50 -62
  5. package/dist/bits/collapsible/collapsible.svelte.d.ts +4 -1
  6. package/dist/bits/collapsible/collapsible.svelte.js +15 -2
  7. package/dist/bits/collapsible/components/collapsible-content.svelte +12 -24
  8. package/dist/bits/context-menu/components/context-menu-content-static.svelte +2 -0
  9. package/dist/bits/context-menu/components/context-menu-content.svelte +2 -0
  10. package/dist/bits/date-field/date-field.svelte.js +5 -3
  11. package/dist/bits/dialog/components/dialog-content.svelte +44 -57
  12. package/dist/bits/dialog/components/dialog-overlay.svelte +9 -12
  13. package/dist/bits/dialog/dialog.svelte.d.ts +6 -0
  14. package/dist/bits/dialog/dialog.svelte.js +17 -3
  15. package/dist/bits/dropdown-menu/components/dropdown-menu-content-static.svelte +2 -0
  16. package/dist/bits/dropdown-menu/components/dropdown-menu-content.svelte +2 -0
  17. package/dist/bits/link-preview/components/link-preview-content-static.svelte +2 -0
  18. package/dist/bits/link-preview/components/link-preview-content.svelte +2 -0
  19. package/dist/bits/link-preview/link-preview.svelte.d.ts +3 -0
  20. package/dist/bits/link-preview/link-preview.svelte.js +6 -2
  21. package/dist/bits/menu/components/menu-content-static.svelte +2 -0
  22. package/dist/bits/menu/components/menu-content.svelte +2 -0
  23. package/dist/bits/menu/components/menu-sub-content-static.svelte +2 -0
  24. package/dist/bits/menu/components/menu-sub-content.svelte +2 -0
  25. package/dist/bits/menu/menu.svelte.d.ts +3 -0
  26. package/dist/bits/menu/menu.svelte.js +6 -2
  27. package/dist/bits/popover/components/popover-content-static.svelte +2 -0
  28. package/dist/bits/popover/components/popover-content.svelte +2 -0
  29. package/dist/bits/popover/components/popover-overlay.svelte +9 -12
  30. package/dist/bits/popover/popover.svelte.d.ts +6 -0
  31. package/dist/bits/popover/popover.svelte.js +16 -3
  32. package/dist/bits/select/components/select-content-static.svelte +2 -0
  33. package/dist/bits/select/components/select-content.svelte +2 -0
  34. package/dist/bits/select/select.svelte.d.ts +3 -0
  35. package/dist/bits/select/select.svelte.js +6 -2
  36. package/dist/bits/tooltip/components/tooltip-content-static.svelte +2 -0
  37. package/dist/bits/tooltip/components/tooltip-content.svelte +2 -0
  38. package/dist/bits/tooltip/tooltip.svelte.d.ts +3 -0
  39. package/dist/bits/tooltip/tooltip.svelte.js +6 -2
  40. package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte +1 -1
  41. package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte.d.ts +1 -1
  42. package/dist/bits/utilities/popper-layer/popper-layer.svelte +43 -45
  43. package/dist/bits/utilities/popper-layer/types.d.ts +4 -0
  44. package/dist/internal/animations-complete.js +7 -15
  45. package/dist/internal/date-time/field/helpers.js +3 -1
  46. package/dist/internal/date-time/field/time-helpers.js +4 -1
  47. package/dist/internal/presence-manager.svelte.d.ts +14 -0
  48. package/dist/internal/presence-manager.svelte.js +34 -0
  49. package/dist/internal/should-enable-focus-trap.d.ts +1 -2
  50. package/dist/internal/should-enable-focus-trap.js +2 -2
  51. package/package.json +2 -2
  52. package/dist/internal/open-change-complete.d.ts +0 -13
  53. package/dist/internal/open-change-complete.js +0 -24
@@ -2,6 +2,7 @@ import { type Box, type ReadableBoxedValues, type WritableBoxedValues } from "sv
2
2
  import type { BitsKeyboardEvent, BitsMouseEvent, RefAttachment, WithRefOpts } from "../../internal/types.js";
3
3
  import type { Orientation } from "../../shared/index.js";
4
4
  import { RovingFocusGroup } from "../../internal/roving-focus-group.js";
5
+ import { PresenceManager } from "../../internal/presence-manager.svelte.js";
5
6
  interface AccordionBaseStateOpts extends WithRefOpts, ReadableBoxedValues<{
6
7
  disabled: boolean;
7
8
  orientation: Orientation;
@@ -82,6 +83,8 @@ export declare class AccordionItemState {
82
83
  readonly isActive: boolean;
83
84
  readonly isDisabled: boolean;
84
85
  readonly attachment: RefAttachment;
86
+ contentNode: HTMLElement | null;
87
+ contentPresence: PresenceManager;
85
88
  constructor(opts: AccordionItemStateOpts);
86
89
  updateValue(): void;
87
90
  readonly props: {
@@ -121,10 +124,12 @@ export declare class AccordionContentState {
121
124
  readonly open: boolean;
122
125
  constructor(opts: AccordionContentStateOpts, item: AccordionItemState);
123
126
  static create(props: AccordionContentStateOpts): AccordionContentState;
127
+ get shouldRender(): boolean;
124
128
  readonly snippetProps: {
125
129
  open: boolean;
126
130
  };
127
131
  readonly props: {
132
+ readonly hidden: boolean | "until-found" | undefined;
128
133
  readonly id: string;
129
134
  readonly "data-state": "open" | "closed";
130
135
  readonly "data-disabled": "" | undefined;
@@ -133,7 +138,6 @@ export declare class AccordionContentState {
133
138
  readonly "--bits-accordion-content-height": `${number}px`;
134
139
  readonly "--bits-accordion-content-width": `${number}px`;
135
140
  };
136
- readonly hidden: "until-found" | undefined;
137
141
  };
138
142
  }
139
143
  export declare class AccordionHeaderState {
@@ -1,10 +1,11 @@
1
- import { afterTick, attachRef, } from "svelte-toolbelt";
1
+ import { afterTick, attachRef, boxWith, } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
3
  import { boolToStr, boolToEmptyStrOrUndef, getDataOpenClosed } from "../../internal/attrs.js";
4
4
  import { kbd } from "../../internal/kbd.js";
5
5
  import { createBitsAttrs } from "../../internal/attrs.js";
6
6
  import { RovingFocusGroup } from "../../internal/roving-focus-group.js";
7
7
  import { on } from "svelte/events";
8
+ import { PresenceManager } from "../../internal/presence-manager.svelte.js";
8
9
  const accordionAttrs = createBitsAttrs({
9
10
  component: "accordion",
10
11
  parts: ["root", "trigger", "content", "item", "header"],
@@ -85,11 +86,17 @@ export class AccordionItemState {
85
86
  isActive = $derived.by(() => this.root.includesItem(this.opts.value.current));
86
87
  isDisabled = $derived.by(() => this.opts.disabled.current || this.root.opts.disabled.current);
87
88
  attachment;
89
+ contentNode = $state(null);
90
+ contentPresence;
88
91
  constructor(opts) {
89
92
  this.opts = opts;
90
93
  this.root = opts.rootState;
91
94
  this.updateValue = this.updateValue.bind(this);
92
95
  this.attachment = attachRef(this.opts.ref);
96
+ this.contentPresence = new PresenceManager({
97
+ ref: boxWith(() => this.contentNode),
98
+ open: boxWith(() => this.isActive),
99
+ });
93
100
  }
94
101
  updateValue() {
95
102
  this.root.toggleItem(this.opts.value.current);
@@ -170,7 +177,7 @@ export class AccordionContentState {
170
177
  this.opts = opts;
171
178
  this.item = item;
172
179
  this.#isMountAnimationPrevented = this.item.isActive;
173
- this.attachment = attachRef(this.opts.ref);
180
+ this.attachment = attachRef(this.opts.ref, (v) => (this.item.contentNode = v));
174
181
  // Prevent mount animations on initial render
175
182
  $effect(() => {
176
183
  const rAF = requestAnimationFrame(() => {
@@ -223,6 +230,9 @@ export class AccordionContentState {
223
230
  }
224
231
  });
225
232
  };
233
+ get shouldRender() {
234
+ return this.item.contentPresence.shouldRender;
235
+ }
226
236
  snippetProps = $derived.by(() => ({ open: this.item.isActive }));
227
237
  props = $derived.by(() => ({
228
238
  id: this.opts.id.current,
@@ -237,6 +247,15 @@ export class AccordionContentState {
237
247
  hidden: this.opts.hiddenUntilFound.current && !this.item.isActive
238
248
  ? "until-found"
239
249
  : undefined,
250
+ ...(this.opts.hiddenUntilFound.current && !this.shouldRender
251
+ ? {}
252
+ : {
253
+ hidden: this.opts.hiddenUntilFound.current
254
+ ? !this.shouldRender
255
+ : this.opts.forceMount.current
256
+ ? undefined
257
+ : !this.shouldRender,
258
+ }),
240
259
  ...this.attachment,
241
260
  }));
242
261
  }
@@ -2,7 +2,6 @@
2
2
  import { mergeProps, boxWith } from "svelte-toolbelt";
3
3
  import { AccordionContentState } from "../accordion.svelte.js";
4
4
  import type { AccordionContentProps } from "../types.js";
5
- import { PresenceLayer } from "../../utilities/presence-layer/index.js";
6
5
  import { createId } from "../../../internal/create-id.js";
7
6
 
8
7
  const uid = $props.id();
@@ -26,28 +25,17 @@
26
25
  ),
27
26
  hiddenUntilFound: boxWith(() => hiddenUntilFound),
28
27
  });
28
+
29
+ const mergedProps = $derived(mergeProps(restProps, contentState.props));
29
30
  </script>
30
31
 
31
- <PresenceLayer forceMount={true} open={contentState.open} ref={contentState.opts.ref}>
32
- {#snippet presence({ present })}
33
- {@const mergedProps = mergeProps(
34
- restProps,
35
- contentState.props,
36
- hiddenUntilFound && !present
37
- ? {}
38
- : {
39
- hidden: hiddenUntilFound ? !present : forceMount ? undefined : !present,
40
- }
41
- )}
42
- {#if child}
43
- {@render child({
44
- props: mergedProps,
45
- ...contentState.snippetProps,
46
- })}
47
- {:else}
48
- <div {...mergedProps}>
49
- {@render children?.()}
50
- </div>
51
- {/if}
52
- {/snippet}
53
- </PresenceLayer>
32
+ {#if child}
33
+ {@render child({
34
+ props: mergedProps,
35
+ ...contentState.snippetProps,
36
+ })}
37
+ {:else}
38
+ <div {...mergedProps}>
39
+ {@render children?.()}
40
+ </div>
41
+ {/if}
@@ -4,13 +4,11 @@
4
4
  import DismissibleLayer from "../../utilities/dismissible-layer/dismissible-layer.svelte";
5
5
  import EscapeLayer from "../../utilities/escape-layer/escape-layer.svelte";
6
6
  import FocusScope from "../../utilities/focus-scope/focus-scope.svelte";
7
- import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
8
7
  import TextSelectionLayer from "../../utilities/text-selection-layer/text-selection-layer.svelte";
9
8
  import { createId } from "../../../internal/create-id.js";
10
9
  import { noop } from "../../../internal/noop.js";
11
10
  import ScrollLock from "../../utilities/scroll-lock/scroll-lock.svelte";
12
11
  import { DialogContentState } from "../../dialog/dialog.svelte.js";
13
- import { shouldEnableFocusTrap } from "../../../internal/should-enable-focus-trap.js";
14
12
 
15
13
  const uid = $props.id();
16
14
 
@@ -42,74 +40,64 @@
42
40
  const mergedProps = $derived(mergeProps(restProps, contentState.props));
43
41
  </script>
44
42
 
45
- <PresenceLayer
46
- {forceMount}
47
- open={contentState.root.opts.open.current || forceMount}
48
- ref={contentState.opts.ref}
49
- >
50
- {#snippet presence()}
51
- <FocusScope
52
- ref={contentState.opts.ref}
53
- loop
54
- {trapFocus}
55
- enabled={shouldEnableFocusTrap({
56
- forceMount,
57
- present: contentState.root.opts.open.current,
58
- open: contentState.root.opts.open.current,
59
- })}
60
- {onCloseAutoFocus}
61
- onOpenAutoFocus={(e) => {
62
- onOpenAutoFocus(e);
63
- if (e.defaultPrevented) return;
64
- e.preventDefault();
65
- afterSleep(0, () => contentState.opts.ref.current?.focus());
66
- }}
67
- >
68
- {#snippet focusScope({ props: focusScopeProps })}
69
- <EscapeLayer
43
+ {#if contentState.shouldRender || forceMount}
44
+ <FocusScope
45
+ ref={contentState.opts.ref}
46
+ loop
47
+ {trapFocus}
48
+ enabled={contentState.root.opts.open.current}
49
+ {onCloseAutoFocus}
50
+ onOpenAutoFocus={(e) => {
51
+ onOpenAutoFocus(e);
52
+ if (e.defaultPrevented) return;
53
+ e.preventDefault();
54
+ afterSleep(0, () => contentState.opts.ref.current?.focus());
55
+ }}
56
+ >
57
+ {#snippet focusScope({ props: focusScopeProps })}
58
+ <EscapeLayer
59
+ {...mergedProps}
60
+ enabled={contentState.root.opts.open.current}
61
+ ref={contentState.opts.ref}
62
+ onEscapeKeydown={(e) => {
63
+ onEscapeKeydown(e);
64
+ if (e.defaultPrevented) return;
65
+ contentState.root.handleClose();
66
+ }}
67
+ >
68
+ <DismissibleLayer
70
69
  {...mergedProps}
71
- enabled={contentState.root.opts.open.current}
72
70
  ref={contentState.opts.ref}
73
- onEscapeKeydown={(e) => {
74
- onEscapeKeydown(e);
71
+ enabled={contentState.root.opts.open.current}
72
+ {interactOutsideBehavior}
73
+ onInteractOutside={(e) => {
74
+ onInteractOutside(e);
75
75
  if (e.defaultPrevented) return;
76
76
  contentState.root.handleClose();
77
77
  }}
78
78
  >
79
- <DismissibleLayer
79
+ <TextSelectionLayer
80
80
  {...mergedProps}
81
81
  ref={contentState.opts.ref}
82
82
  enabled={contentState.root.opts.open.current}
83
- {interactOutsideBehavior}
84
- onInteractOutside={(e) => {
85
- onInteractOutside(e);
86
- if (e.defaultPrevented) return;
87
- contentState.root.handleClose();
88
- }}
89
83
  >
90
- <TextSelectionLayer
91
- {...mergedProps}
92
- ref={contentState.opts.ref}
93
- enabled={contentState.root.opts.open.current}
94
- >
95
- {#if child}
96
- {#if contentState.root.opts.open.current}
97
- <ScrollLock {preventScroll} {restoreScrollDelay} />
98
- {/if}
99
- {@render child({
100
- props: mergeProps(mergedProps, focusScopeProps),
101
- ...contentState.snippetProps,
102
- })}
103
- {:else}
104
- <ScrollLock {preventScroll} />
105
- <div {...mergeProps(mergedProps, focusScopeProps)}>
106
- {@render children?.()}
107
- </div>
84
+ {#if child}
85
+ {#if contentState.root.opts.open.current}
86
+ <ScrollLock {preventScroll} {restoreScrollDelay} />
108
87
  {/if}
109
- </TextSelectionLayer>
110
- </DismissibleLayer>
111
- </EscapeLayer>
112
- {/snippet}
113
- </FocusScope>
114
- {/snippet}
115
- </PresenceLayer>
88
+ {@render child({
89
+ props: mergeProps(mergedProps, focusScopeProps),
90
+ ...contentState.snippetProps,
91
+ })}
92
+ {:else}
93
+ <ScrollLock {preventScroll} />
94
+ <div {...mergeProps(mergedProps, focusScopeProps)}>
95
+ {@render children?.()}
96
+ </div>
97
+ {/if}
98
+ </TextSelectionLayer>
99
+ </DismissibleLayer>
100
+ </EscapeLayer>
101
+ {/snippet}
102
+ </FocusScope>
103
+ {/if}
@@ -1,5 +1,6 @@
1
1
  import { type ReadableBoxedValues, type WritableBoxedValues } from "svelte-toolbelt";
2
2
  import type { BitsKeyboardEvent, BitsMouseEvent, OnChangeFn, RefAttachment, WithRefOpts } from "../../internal/types.js";
3
+ import { PresenceManager } from "../../internal/presence-manager.svelte.js";
3
4
  interface CollapsibleRootStateOpts extends WithRefOpts, WritableBoxedValues<{
4
5
  open: boolean;
5
6
  }>, ReadableBoxedValues<{
@@ -12,6 +13,7 @@ export declare class CollapsibleRootState {
12
13
  readonly opts: CollapsibleRootStateOpts;
13
14
  readonly attachment: RefAttachment;
14
15
  contentNode: HTMLElement | null;
16
+ contentPresence: PresenceManager;
15
17
  contentId: string | undefined;
16
18
  constructor(opts: CollapsibleRootStateOpts);
17
19
  toggleOpen(): void;
@@ -34,16 +36,17 @@ export declare class CollapsibleContentState {
34
36
  readonly attachment: RefAttachment;
35
37
  readonly present: boolean;
36
38
  constructor(opts: CollapsibleContentStateOpts, root: CollapsibleRootState);
39
+ get shouldRender(): boolean;
37
40
  readonly snippetProps: {
38
41
  open: boolean;
39
42
  };
40
43
  readonly props: {
44
+ readonly hidden: boolean | "until-found" | undefined;
41
45
  readonly id: string;
42
46
  readonly style: {
43
47
  readonly "--bits-collapsible-content-height": string | undefined;
44
48
  readonly "--bits-collapsible-content-width": string | undefined;
45
49
  };
46
- readonly hidden: "until-found" | undefined;
47
50
  readonly "data-state": "open" | "closed";
48
51
  readonly "data-disabled": "" | undefined;
49
52
  };
@@ -2,8 +2,8 @@ import { afterTick, attachRef, boxWith, } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
3
  import { createBitsAttrs, boolToStr, boolToEmptyStrOrUndef, getDataOpenClosed, } from "../../internal/attrs.js";
4
4
  import { kbd } from "../../internal/kbd.js";
5
- import { OpenChangeComplete } from "../../internal/open-change-complete.js";
6
5
  import { on } from "svelte/events";
6
+ import { PresenceManager } from "../../internal/presence-manager.svelte.js";
7
7
  const collapsibleAttrs = createBitsAttrs({
8
8
  component: "collapsible",
9
9
  parts: ["root", "content", "trigger"],
@@ -16,12 +16,13 @@ export class CollapsibleRootState {
16
16
  opts;
17
17
  attachment;
18
18
  contentNode = $state(null);
19
+ contentPresence;
19
20
  contentId = $state(undefined);
20
21
  constructor(opts) {
21
22
  this.opts = opts;
22
23
  this.toggleOpen = this.toggleOpen.bind(this);
23
24
  this.attachment = attachRef(this.opts.ref);
24
- new OpenChangeComplete({
25
+ this.contentPresence = new PresenceManager({
25
26
  ref: boxWith(() => this.contentNode),
26
27
  open: this.opts.open,
27
28
  onComplete: () => {
@@ -114,6 +115,9 @@ export class CollapsibleContentState {
114
115
  });
115
116
  });
116
117
  }
118
+ get shouldRender() {
119
+ return this.root.contentPresence.shouldRender;
120
+ }
117
121
  snippetProps = $derived.by(() => ({
118
122
  open: this.root.opts.open.current,
119
123
  }));
@@ -133,6 +137,15 @@ export class CollapsibleContentState {
133
137
  "data-state": getDataOpenClosed(this.root.opts.open.current),
134
138
  "data-disabled": boolToEmptyStrOrUndef(this.root.opts.disabled.current),
135
139
  [collapsibleAttrs.content]: "",
140
+ ...(this.opts.hiddenUntilFound.current && !this.shouldRender
141
+ ? {}
142
+ : {
143
+ hidden: this.opts.hiddenUntilFound.current
144
+ ? !this.shouldRender
145
+ : this.opts.forceMount.current
146
+ ? undefined
147
+ : !this.shouldRender,
148
+ }),
136
149
  ...this.attachment,
137
150
  }));
138
151
  }
@@ -2,7 +2,6 @@
2
2
  import { boxWith, mergeProps } from "svelte-toolbelt";
3
3
  import { CollapsibleContentState } from "../collapsible.svelte.js";
4
4
  import type { CollapsibleContentProps } from "../types.js";
5
- import { PresenceLayer } from "../../utilities/presence-layer/index.js";
6
5
  import { createId } from "../../../internal/create-id.js";
7
6
 
8
7
  const uid = $props.id();
@@ -26,28 +25,17 @@
26
25
  (v) => (ref = v)
27
26
  ),
28
27
  });
28
+
29
+ const mergedProps = $derived(mergeProps(restProps, contentState.props));
29
30
  </script>
30
31
 
31
- <PresenceLayer forceMount={true} open={contentState.present} ref={contentState.opts.ref}>
32
- {#snippet presence({ present })}
33
- {@const mergedProps = mergeProps(
34
- restProps,
35
- contentState.props,
36
- hiddenUntilFound && !present
37
- ? {}
38
- : {
39
- hidden: hiddenUntilFound ? !present : forceMount ? undefined : !present,
40
- }
41
- )}
42
- {#if child}
43
- {@render child({
44
- ...contentState.snippetProps,
45
- props: mergedProps,
46
- })}
47
- {:else}
48
- <div {...mergedProps}>
49
- {@render children?.()}
50
- </div>
51
- {/if}
52
- {/snippet}
53
- </PresenceLayer>
32
+ {#if child}
33
+ {@render child({
34
+ ...contentState.snippetProps,
35
+ props: mergedProps,
36
+ })}
37
+ {:else}
38
+ <div {...mergedProps}>
39
+ {@render children?.()}
40
+ </div>
41
+ {/if}
@@ -79,6 +79,7 @@
79
79
  {loop}
80
80
  {forceMount}
81
81
  {id}
82
+ shouldRender={contentState.shouldRender}
82
83
  >
83
84
  {#snippet popper({ props })}
84
85
  {@const finalProps = mergeProps(props, {
@@ -111,6 +112,7 @@
111
112
  {loop}
112
113
  forceMount={false}
113
114
  {id}
115
+ shouldRender={contentState.shouldRender}
114
116
  >
115
117
  {#snippet popper({ props })}
116
118
  {@const finalProps = mergeProps(props, {
@@ -86,6 +86,7 @@
86
86
  {trapFocus}
87
87
  {loop}
88
88
  {id}
89
+ shouldRender={contentState.shouldRender}
89
90
  >
90
91
  {#snippet popper({ props, wrapperProps })}
91
92
  {@const finalProps = mergeProps(props, {
@@ -119,6 +120,7 @@
119
120
  {trapFocus}
120
121
  {loop}
121
122
  {id}
123
+ shouldRender={contentState.shouldRender}
122
124
  >
123
125
  {#snippet popper({ props, wrapperProps })}
124
126
  {@const finalProps = mergeProps(props, {
@@ -7,7 +7,7 @@ import { kbd } from "../../internal/kbd.js";
7
7
  import { useId } from "../../internal/use-id.js";
8
8
  import { createFormatter } from "../../internal/date-time/formatter.js";
9
9
  import { getAnnouncer } from "../../internal/date-time/announcer.js";
10
- import { areAllSegmentsFilled, createContent, getValueFromSegments, inferGranularity, initSegmentStates, initializeSegmentValues, isAcceptableSegmentKey, isDateAndTimeSegmentObj, isDateSegmentPart, isFirstSegment, removeDescriptionElement, setDescription, } from "../../internal/date-time/field/helpers.js";
10
+ import { areAllSegmentsFilled, createContent, getDefaultHourCycle, getValueFromSegments, inferGranularity, initSegmentStates, initializeSegmentValues, isAcceptableSegmentKey, isDateAndTimeSegmentObj, isDateSegmentPart, isFirstSegment, removeDescriptionElement, setDescription, } from "../../internal/date-time/field/helpers.js";
11
11
  import { DATE_SEGMENT_PARTS, EDITABLE_TIME_SEGMENT_PARTS, } from "../../internal/date-time/field/parts.js";
12
12
  import { getDaysInMonth, isBefore, toDate } from "../../internal/date-time/utils.js";
13
13
  import { getFirstSegment, handleSegmentNavigation, isSegmentNavigationKey, moveToNextSegment, moveToPrevSegment, } from "../../internal/date-time/field/segments.js";
@@ -50,9 +50,11 @@ const SEGMENT_CONFIGS = {
50
50
  max: (root) => {
51
51
  if (root.hourCycle.current === 24)
52
52
  return 23;
53
- if ("dayPeriod" in root.segmentValues && root.segmentValues.dayPeriod !== null)
53
+ if (root.hourCycle.current === 12)
54
54
  return 12;
55
- return 23;
55
+ // if hourCycle is undefined, infer from locale
56
+ const inferredHourCycle = getDefaultHourCycle(root.locale.current);
57
+ return inferredHourCycle === 12 ? 12 : 23;
56
58
  },
57
59
  cycle: 1,
58
60
  canBeZero: true,
@@ -5,12 +5,10 @@
5
5
  import DismissibleLayer from "../../utilities/dismissible-layer/dismissible-layer.svelte";
6
6
  import EscapeLayer from "../../utilities/escape-layer/escape-layer.svelte";
7
7
  import FocusScope from "../../utilities/focus-scope/focus-scope.svelte";
8
- import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
9
8
  import TextSelectionLayer from "../../utilities/text-selection-layer/text-selection-layer.svelte";
10
9
  import { createId } from "../../../internal/create-id.js";
11
10
  import { noop } from "../../../internal/noop.js";
12
11
  import ScrollLock from "../../utilities/scroll-lock/scroll-lock.svelte";
13
- import { shouldEnableFocusTrap } from "../../../internal/should-enable-focus-trap.js";
14
12
  const uid = $props.id();
15
13
 
16
14
  let {
@@ -40,69 +38,58 @@
40
38
  const mergedProps = $derived(mergeProps(restProps, contentState.props));
41
39
  </script>
42
40
 
43
- <PresenceLayer
44
- {...mergedProps}
45
- {forceMount}
46
- open={contentState.root.opts.open.current || forceMount}
47
- ref={contentState.opts.ref}
48
- >
49
- {#snippet presence()}
50
- <FocusScope
51
- ref={contentState.opts.ref}
52
- loop
53
- {trapFocus}
54
- enabled={shouldEnableFocusTrap({
55
- forceMount,
56
- present: contentState.root.opts.open.current,
57
- open: contentState.root.opts.open.current,
58
- })}
59
- {onOpenAutoFocus}
60
- {onCloseAutoFocus}
61
- >
62
- {#snippet focusScope({ props: focusScopeProps })}
63
- <EscapeLayer
41
+ {#if contentState.shouldRender || forceMount}
42
+ <FocusScope
43
+ ref={contentState.opts.ref}
44
+ loop
45
+ {trapFocus}
46
+ enabled={contentState.root.opts.open.current}
47
+ {onOpenAutoFocus}
48
+ {onCloseAutoFocus}
49
+ >
50
+ {#snippet focusScope({ props: focusScopeProps })}
51
+ <EscapeLayer
52
+ {...mergedProps}
53
+ enabled={contentState.root.opts.open.current}
54
+ ref={contentState.opts.ref}
55
+ onEscapeKeydown={(e) => {
56
+ onEscapeKeydown(e);
57
+ if (e.defaultPrevented) return;
58
+ contentState.root.handleClose();
59
+ }}
60
+ >
61
+ <DismissibleLayer
64
62
  {...mergedProps}
65
- enabled={contentState.root.opts.open.current}
66
63
  ref={contentState.opts.ref}
67
- onEscapeKeydown={(e) => {
68
- onEscapeKeydown(e);
64
+ enabled={contentState.root.opts.open.current}
65
+ onInteractOutside={(e) => {
66
+ onInteractOutside(e);
69
67
  if (e.defaultPrevented) return;
70
68
  contentState.root.handleClose();
71
69
  }}
72
70
  >
73
- <DismissibleLayer
71
+ <TextSelectionLayer
74
72
  {...mergedProps}
75
73
  ref={contentState.opts.ref}
76
74
  enabled={contentState.root.opts.open.current}
77
- onInteractOutside={(e) => {
78
- onInteractOutside(e);
79
- if (e.defaultPrevented) return;
80
- contentState.root.handleClose();
81
- }}
82
75
  >
83
- <TextSelectionLayer
84
- {...mergedProps}
85
- ref={contentState.opts.ref}
86
- enabled={contentState.root.opts.open.current}
87
- >
88
- {#if child}
89
- {#if contentState.root.opts.open.current}
90
- <ScrollLock {preventScroll} {restoreScrollDelay} />
91
- {/if}
92
- {@render child({
93
- props: mergeProps(mergedProps, focusScopeProps),
94
- ...contentState.snippetProps,
95
- })}
96
- {:else}
97
- <ScrollLock {preventScroll} />
98
- <div {...mergeProps(mergedProps, focusScopeProps)}>
99
- {@render children?.()}
100
- </div>
76
+ {#if child}
77
+ {#if contentState.root.opts.open.current}
78
+ <ScrollLock {preventScroll} {restoreScrollDelay} />
101
79
  {/if}
102
- </TextSelectionLayer>
103
- </DismissibleLayer>
104
- </EscapeLayer>
105
- {/snippet}
106
- </FocusScope>
107
- {/snippet}
108
- </PresenceLayer>
80
+ {@render child({
81
+ props: mergeProps(mergedProps, focusScopeProps),
82
+ ...contentState.snippetProps,
83
+ })}
84
+ {:else}
85
+ <ScrollLock {preventScroll} />
86
+ <div {...mergeProps(mergedProps, focusScopeProps)}>
87
+ {@render children?.()}
88
+ </div>
89
+ {/if}
90
+ </TextSelectionLayer>
91
+ </DismissibleLayer>
92
+ </EscapeLayer>
93
+ {/snippet}
94
+ </FocusScope>
95
+ {/if}
@@ -3,7 +3,6 @@
3
3
  import { DialogOverlayState } from "../dialog.svelte.js";
4
4
  import type { DialogOverlayProps } from "../types.js";
5
5
  import { createId } from "../../../internal/create-id.js";
6
- import PresenceLayer from "../../utilities/presence-layer/presence-layer.svelte";
7
6
 
8
7
  const uid = $props.id();
9
8
 
@@ -27,14 +26,12 @@
27
26
  const mergedProps = $derived(mergeProps(restProps, overlayState.props));
28
27
  </script>
29
28
 
30
- <PresenceLayer open={overlayState.root.opts.open.current || forceMount} ref={overlayState.opts.ref}>
31
- {#snippet presence()}
32
- {#if child}
33
- {@render child({ props: mergeProps(mergedProps), ...overlayState.snippetProps })}
34
- {:else}
35
- <div {...mergeProps(mergedProps)}>
36
- {@render children?.(overlayState.snippetProps)}
37
- </div>
38
- {/if}
39
- {/snippet}
40
- </PresenceLayer>
29
+ {#if overlayState.shouldRender || forceMount}
30
+ {#if child}
31
+ {@render child({ props: mergeProps(mergedProps), ...overlayState.snippetProps })}
32
+ {:else}
33
+ <div {...mergeProps(mergedProps)}>
34
+ {@render children?.(overlayState.snippetProps)}
35
+ </div>
36
+ {/if}
37
+ {/if}