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.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/src/lib/components/avatar/avatar.svelte.ts +34 -37
  3. package/src/lib/components/avatar/components/avatar-fallback.svelte +9 -6
  4. package/src/lib/components/avatar/components/avatar-image.svelte +18 -9
  5. package/src/lib/components/avatar/components/avatar.svelte +20 -16
  6. package/src/lib/components/checkbox/checkbox.svelte.ts +45 -55
  7. package/src/lib/components/checkbox/components/checkbox-group-label.svelte +9 -6
  8. package/src/lib/components/checkbox/components/checkbox-group.svelte +25 -16
  9. package/src/lib/components/checkbox/components/checkbox.svelte +39 -25
  10. package/src/lib/components/dialog/components/dialog-close.svelte +13 -8
  11. package/src/lib/components/dialog/components/dialog-content-headless.svelte +14 -11
  12. package/src/lib/components/dialog/components/dialog-description.svelte +9 -6
  13. package/src/lib/components/dialog/components/dialog-overlay.svelte +10 -7
  14. package/src/lib/components/dialog/components/dialog-title.svelte +12 -7
  15. package/src/lib/components/dialog/components/dialog-trigger.svelte +12 -7
  16. package/src/lib/components/dialog/components/dialog.svelte +10 -4
  17. package/src/lib/components/dialog/components/modal-surface.svelte +11 -8
  18. package/src/lib/components/dialog/dialog.svelte.ts +73 -61
  19. package/src/lib/components/drawer/drawer.svelte +8 -3
  20. package/src/lib/components/link-preview/components/link-preview-content.svelte +15 -8
  21. package/src/lib/components/link-preview/components/link-preview-trigger.svelte +9 -6
  22. package/src/lib/components/link-preview/components/link-preview.svelte +19 -11
  23. package/src/lib/components/link-preview/link-preview.svelte.ts +42 -43
  24. package/src/lib/components/menu/menu.svelte.ts +20 -1
  25. package/src/lib/components/meter/components/meter.svelte +18 -9
  26. package/src/lib/components/meter/meter.svelte.ts +15 -18
  27. package/src/lib/components/popover/components/popover-close.svelte +9 -6
  28. package/src/lib/components/popover/components/popover-content.svelte +12 -7
  29. package/src/lib/components/popover/components/popover-trigger.svelte +21 -10
  30. package/src/lib/components/popover/components/popover.svelte +9 -8
  31. package/src/lib/components/popover/popover.svelte.ts +68 -74
  32. package/src/lib/components/progress/components/progress.svelte +18 -9
  33. package/src/lib/components/progress/progress.svelte.ts +14 -17
  34. package/src/lib/components/separator/components/separator.svelte +15 -8
  35. package/src/lib/components/separator/separator.svelte.ts +12 -15
  36. package/src/lib/components/sidebar/sidebar-mobile-surface.svelte +8 -4
  37. package/src/lib/components/toggle/components/toggle.svelte +19 -14
  38. package/src/lib/components/toggle/toggle.svelte.ts +15 -20
  39. package/src/lib/components/tooltip/components/tooltip-content.svelte +15 -8
  40. package/src/lib/components/tooltip/components/tooltip-provider.svelte +18 -7
  41. package/src/lib/components/tooltip/components/tooltip-trigger.svelte +21 -10
  42. package/src/lib/components/tooltip/components/tooltip.svelte +34 -21
  43. package/src/lib/components/tooltip/tooltip.svelte.ts +96 -99
  44. package/src/lib/internal/escape-layer/use-escape-layer.svelte.ts +13 -29
  45. package/src/lib/internal/group-value.svelte.ts +11 -10
  46. package/src/lib/internal/native-popover.svelte.ts +6 -6
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { mergeProps } from '../../../internal/merge-props.js';
4
3
  import type { LinkPreviewContentProps } from '../types.js';
5
4
  import { LinkPreviewContentState } from '../link-preview.svelte.js';
@@ -25,13 +24,21 @@
25
24
  }: LinkPreviewContentProps = $props();
26
25
 
27
26
  const contentState = LinkPreviewContentState.create({
28
- id: boxWith(() => id),
29
- ref: boxWith(
30
- () => ref,
31
- (v) => (ref = v),
32
- ),
33
- onInteractOutside: boxWith(() => onInteractOutside),
34
- onEscapeKeydown: boxWith(() => onEscapeKeydown),
27
+ get id() {
28
+ return id;
29
+ },
30
+ get onInteractOutside() {
31
+ return onInteractOutside;
32
+ },
33
+ get onEscapeKeydown() {
34
+ return onEscapeKeydown;
35
+ },
36
+ get ref() {
37
+ return ref;
38
+ },
39
+ set ref(v) {
40
+ ref = v;
41
+ },
35
42
  });
36
43
 
37
44
  const lifecycleProps = useNativePopoverLifecycle(contentState);
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { mergeProps } from '../../../internal/merge-props.js';
4
3
  import type { LinkPreviewTriggerProps } from '../types.js';
5
4
  import { LinkPreviewTriggerState } from '../link-preview.svelte.js';
@@ -10,11 +9,15 @@
10
9
  let { ref = $bindable(null), id = createId(uid), child, children, ...restProps }: LinkPreviewTriggerProps = $props();
11
10
 
12
11
  const triggerState = LinkPreviewTriggerState.create({
13
- id: boxWith(() => id),
14
- ref: boxWith(
15
- () => ref,
16
- (v) => (ref = v),
17
- ),
12
+ get id() {
13
+ return id;
14
+ },
15
+ get ref() {
16
+ return ref;
17
+ },
18
+ set ref(v) {
19
+ ref = v;
20
+ },
18
21
  });
19
22
 
20
23
  const mergedProps = $derived(mergeProps({ 'data-slot': 'hover-card-trigger' }, restProps, triggerState.props));
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { OpenCell } from '../../../internal/open-cell.svelte.js';
4
3
  import type { LinkPreviewRootProps } from '../types.js';
5
4
  import { LinkPreviewRootState } from '../link-preview.svelte.js';
@@ -14,20 +13,29 @@
14
13
  children,
15
14
  }: LinkPreviewRootProps = $props();
16
15
 
17
- // Cell over the source prop; the engine keeps its boxed-open interface (vendored,
18
- // ADR 0006) — the box is a bridge over the cell, so the cell owns `open`.
16
+ // Cell over the source prop; the cell owns `open`, the engine reads and writes it through it.
19
17
  // svelte-ignore state_referenced_locally
20
18
  const cell = givenCell ?? new OpenCell(() => open);
21
19
 
22
20
  LinkPreviewRootState.create({
23
- disabled: boxWith(() => disabled),
24
- open: boxWith(
25
- () => cell.open,
26
- (v) => (cell.open = v),
27
- ),
28
- openDelay: boxWith(() => openDelay),
29
- closeDelay: boxWith(() => closeDelay),
30
- onOpenChangeComplete: boxWith(() => onOpenChangeComplete),
21
+ get open() {
22
+ return cell.open;
23
+ },
24
+ set open(v) {
25
+ cell.open = v;
26
+ },
27
+ get disabled() {
28
+ return disabled;
29
+ },
30
+ get openDelay() {
31
+ return openDelay;
32
+ },
33
+ get closeDelay() {
34
+ return closeDelay;
35
+ },
36
+ get onOpenChangeComplete() {
37
+ return onOpenChangeComplete;
38
+ },
31
39
  });
32
40
  </script>
33
41
 
@@ -1,9 +1,9 @@
1
- import { attachRef, DOMContext, type ReadableBoxedValues, type WritableBoxedValues } from '../../internal/tools/index.js';
1
+ import { attachRef, DOMContext } from '../../internal/tools/index.js';
2
2
  import { on } from 'svelte/events';
3
3
  import { createContext, onDestroy, untrack } from 'svelte';
4
4
  import { createBitsAttrs, boolToStr, getDataOpenClosed } from '../../internal/attrs.js';
5
5
  import { isElement } from '../../internal/tools/utils/dom.js';
6
- import type { BitsFocusEvent, BitsPointerEvent, OnChangeFn, RefAttachment, WithRefOpts } from '../../internal/types.js';
6
+ import type { BitsFocusEvent, BitsPointerEvent, OnChangeFn, RefAttachment, RefOpts } from '../../internal/types.js';
7
7
  import { getTabbableCandidates } from '../../internal/tabbable.js';
8
8
  import { SafePolygon } from '../../internal/safe-polygon.svelte.js';
9
9
  import { createEffectTimeout } from '../../internal/timeout-fn.svelte.js';
@@ -15,17 +15,13 @@ const linkPreviewAttrs = createBitsAttrs({
15
15
 
16
16
  const [getLinkPreviewRoot, setLinkPreviewRoot] = createContext<LinkPreviewRootState>();
17
17
 
18
- interface LinkPreviewRootStateOpts
19
- extends
20
- WritableBoxedValues<{
21
- open: boolean;
22
- }>,
23
- ReadableBoxedValues<{
24
- disabled: boolean;
25
- openDelay: number;
26
- closeDelay: number;
27
- onOpenChangeComplete: OnChangeFn<boolean>;
28
- }> {}
18
+ interface LinkPreviewRootStateOpts {
19
+ open: boolean;
20
+ readonly disabled: boolean;
21
+ readonly openDelay: number;
22
+ readonly closeDelay: number;
23
+ readonly onOpenChangeComplete: OnChangeFn<boolean>;
24
+ }
29
25
 
30
26
  export class LinkPreviewRootState {
31
27
  static create(opts: LinkPreviewRootStateOpts) {
@@ -41,17 +37,17 @@ export class LinkPreviewRootState {
41
37
  triggerNode = $state<HTMLElement | null>(null);
42
38
  domContext: DOMContext = new DOMContext(() => null);
43
39
  #openTimer = createEffectTimeout(() => {
44
- this.opts.open.current = true;
45
- }, () => this.opts.openDelay.current);
40
+ this.opts.open = true;
41
+ }, () => this.opts.openDelay);
46
42
  #closeTimer = createEffectTimeout(() => {
47
- this.opts.open.current = false;
48
- }, () => this.opts.closeDelay.current);
43
+ this.opts.open = false;
44
+ }, () => this.opts.closeDelay);
49
45
 
50
46
  constructor(opts: LinkPreviewRootStateOpts) {
51
47
  this.opts = opts;
52
48
 
53
49
  $effect(() => {
54
- const isOpen = this.opts.open.current;
50
+ const isOpen = this.opts.open;
55
51
  return untrack(() => {
56
52
  if (!isOpen) {
57
53
  this.hasSelection = false;
@@ -99,13 +95,13 @@ export class LinkPreviewRootState {
99
95
 
100
96
  handleOpen() {
101
97
  this.clearTimeout();
102
- if (this.opts.open.current || this.opts.disabled.current) return;
98
+ if (this.opts.open || this.opts.disabled) return;
103
99
  this.#openTimer.start();
104
100
  }
105
101
 
106
102
  immediateClose() {
107
103
  this.clearTimeout();
108
- this.opts.open.current = false;
104
+ this.opts.open = false;
109
105
  }
110
106
 
111
107
  handleClose() {
@@ -117,7 +113,7 @@ export class LinkPreviewRootState {
117
113
  }
118
114
  }
119
115
 
120
- interface LinkPreviewTriggerStateOpts extends WithRefOpts {}
116
+ interface LinkPreviewTriggerStateOpts extends RefOpts {}
121
117
 
122
118
  export class LinkPreviewTriggerState {
123
119
  static create(opts: LinkPreviewTriggerStateOpts) {
@@ -131,8 +127,11 @@ export class LinkPreviewTriggerState {
131
127
  constructor(opts: LinkPreviewTriggerStateOpts, root: LinkPreviewRootState) {
132
128
  this.opts = opts;
133
129
  this.root = root;
134
- this.attachment = attachRef(this.opts.ref, (v) => (this.root.triggerNode = v));
135
- this.root.domContext = new DOMContext(opts.ref);
130
+ this.attachment = attachRef<HTMLElement>(
131
+ (v) => (opts.ref = v),
132
+ (v) => (this.root.triggerNode = v),
133
+ );
134
+ this.root.domContext = new DOMContext(() => opts.ref);
136
135
  this.onpointerenter = this.onpointerenter.bind(this);
137
136
  this.onpointerleave = this.onpointerleave.bind(this);
138
137
  this.onfocus = this.onfocus.bind(this);
@@ -147,7 +146,7 @@ export class LinkPreviewTriggerState {
147
146
  onpointerleave(e: BitsPointerEvent) {
148
147
  if (e.pointerType === 'touch') return;
149
148
  // The content is always mounted (native popover, display toggled), so open is the only gate.
150
- if (!this.root.opts.open.current) {
149
+ if (!this.root.opts.open) {
151
150
  this.root.immediateClose();
152
151
  }
153
152
  }
@@ -164,10 +163,10 @@ export class LinkPreviewTriggerState {
164
163
  readonly props = $derived.by(
165
164
  () =>
166
165
  ({
167
- id: this.opts.id.current,
166
+ id: this.opts.id,
168
167
  'aria-haspopup': 'dialog',
169
- 'aria-expanded': boolToStr(this.root.opts.open.current),
170
- 'data-state': getDataOpenClosed(this.root.opts.open.current),
168
+ 'aria-expanded': boolToStr(this.root.opts.open),
169
+ 'data-state': getDataOpenClosed(this.root.opts.open),
171
170
  'aria-controls': this.root.contentNode?.id,
172
171
  role: 'button',
173
172
  [linkPreviewAttrs.trigger]: '',
@@ -180,13 +179,10 @@ export class LinkPreviewTriggerState {
180
179
  );
181
180
  }
182
181
 
183
- interface LinkPreviewContentStateOpts
184
- extends
185
- WithRefOpts,
186
- ReadableBoxedValues<{
187
- onInteractOutside: (e: PointerEvent) => void;
188
- onEscapeKeydown: (e: KeyboardEvent) => void;
189
- }> {}
182
+ interface LinkPreviewContentStateOpts extends RefOpts {
183
+ readonly onInteractOutside: (e: PointerEvent) => void;
184
+ readonly onEscapeKeydown: (e: KeyboardEvent) => void;
185
+ }
190
186
 
191
187
  export class LinkPreviewContentState {
192
188
  static create(opts: LinkPreviewContentStateOpts) {
@@ -200,16 +196,19 @@ export class LinkPreviewContentState {
200
196
  constructor(opts: LinkPreviewContentStateOpts, root: LinkPreviewRootState) {
201
197
  this.opts = opts;
202
198
  this.root = root;
203
- this.attachment = attachRef(this.opts.ref, (v) => (this.root.contentNode = v));
204
- this.root.domContext = new DOMContext(opts.ref);
199
+ this.attachment = attachRef<HTMLElement>(
200
+ (v) => (opts.ref = v),
201
+ (v) => (this.root.contentNode = v),
202
+ );
203
+ this.root.domContext = new DOMContext(() => opts.ref);
205
204
  this.onpointerdown = this.onpointerdown.bind(this);
206
205
  this.onpointerenter = this.onpointerenter.bind(this);
207
206
  this.onfocusout = this.onfocusout.bind(this);
208
207
 
209
208
  new SafePolygon({
210
209
  triggerNode: () => this.root.triggerNode,
211
- contentNode: () => this.opts.ref.current,
212
- enabled: () => this.root.opts.open.current,
210
+ contentNode: () => this.opts.ref,
211
+ enabled: () => this.root.opts.open,
213
212
  onPointerExit: () => {
214
213
  this.root.handleClose();
215
214
  },
@@ -241,25 +240,25 @@ export class LinkPreviewContentState {
241
240
  }
242
241
 
243
242
  onInteractOutside = (e: PointerEvent) => {
244
- this.opts.onInteractOutside.current(e);
243
+ this.opts.onInteractOutside(e);
245
244
  if (e.defaultPrevented) return;
246
245
  this.root.handleClose();
247
246
  };
248
247
 
249
248
  onEscapeKeydown = (e: KeyboardEvent) => {
250
- this.opts.onEscapeKeydown.current?.(e);
249
+ this.opts.onEscapeKeydown?.(e);
251
250
  if (e.defaultPrevented) return;
252
251
  this.root.handleClose();
253
252
  };
254
253
 
255
- readonly snippetProps = $derived.by(() => ({ open: this.root.opts.open.current }));
254
+ readonly snippetProps = $derived.by(() => ({ open: this.root.opts.open }));
256
255
 
257
256
  readonly props = $derived.by(
258
257
  () =>
259
258
  ({
260
- id: this.opts.id.current,
259
+ id: this.opts.id,
261
260
  tabindex: -1,
262
- 'data-state': getDataOpenClosed(this.root.opts.open.current),
261
+ 'data-state': getDataOpenClosed(this.root.opts.open),
263
262
  [linkPreviewAttrs.content]: '',
264
263
  onpointerdown: this.onpointerdown,
265
264
  onpointerenter: this.onpointerenter,
@@ -1139,7 +1139,26 @@ export class MenuCheckboxItemState {
1139
1139
  constructor(opts: MenuItemCombinedProps & MenuCheckboxItemStateOpts, shared: MenuItemSharedState) {
1140
1140
  this.opts = opts;
1141
1141
  this.item = new MenuItemState(opts, shared, { closes: false, act: () => this.#toggle() });
1142
- this.groupChecked = joinGroup(hasMenuCheckboxGroup() ? getMenuCheckboxGroup() : null, opts);
1142
+ // Accessor views over the boxed options until the menu engine converts.
1143
+ const group = hasMenuCheckboxGroup() ? getMenuCheckboxGroup() : null;
1144
+ this.groupChecked = joinGroup(
1145
+ group && {
1146
+ get value() {
1147
+ return group.opts.value.current;
1148
+ },
1149
+ set value(v) {
1150
+ group.opts.value.current = v;
1151
+ },
1152
+ },
1153
+ {
1154
+ get value() {
1155
+ return opts.value.current;
1156
+ },
1157
+ get checked() {
1158
+ return opts.checked.current;
1159
+ },
1160
+ },
1161
+ );
1143
1162
  }
1144
1163
 
1145
1164
  #toggle() {
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { mergeProps } from '../../../internal/merge-props.js';
4
3
  import type { MeterRootProps } from '../types.js';
5
4
  import { MeterRootState } from '../meter.svelte.js';
@@ -19,14 +18,24 @@
19
18
  }: MeterRootProps = $props();
20
19
 
21
20
  const rootState = MeterRootState.create({
22
- value: boxWith(() => value),
23
- max: boxWith(() => max),
24
- min: boxWith(() => min),
25
- id: boxWith(() => id),
26
- ref: boxWith(
27
- () => ref,
28
- (v) => (ref = v),
29
- ),
21
+ get value() {
22
+ return value;
23
+ },
24
+ get max() {
25
+ return max;
26
+ },
27
+ get min() {
28
+ return min;
29
+ },
30
+ get id() {
31
+ return id;
32
+ },
33
+ get ref() {
34
+ return ref;
35
+ },
36
+ set ref(v) {
37
+ ref = v;
38
+ },
30
39
  });
31
40
 
32
41
  const mergedProps = $derived(mergeProps(restProps, rootState.props));
@@ -1,5 +1,5 @@
1
- import { attachRef, type ReadableBoxedValues } from '../../internal/tools/index.js';
2
- import type { RefAttachment, WithRefOpts } from '../../internal/types.js';
1
+ import { attachRef } from '../../internal/tools/index.js';
2
+ import type { RefAttachment, RefOpts } from '../../internal/types.js';
3
3
  import { createBitsAttrs } from '../../internal/attrs.js';
4
4
 
5
5
  const meterAttrs = createBitsAttrs({
@@ -7,14 +7,11 @@ const meterAttrs = createBitsAttrs({
7
7
  parts: ['root'],
8
8
  });
9
9
 
10
- interface MeterRootStateOpts
11
- extends
12
- WithRefOpts,
13
- ReadableBoxedValues<{
14
- value: number;
15
- max: number;
16
- min: number;
17
- }> {}
10
+ interface MeterRootStateOpts extends RefOpts {
11
+ readonly value: number;
12
+ readonly max: number;
13
+ readonly min: number;
14
+ }
18
15
 
19
16
  export class MeterRootState {
20
17
  static create(opts: MeterRootStateOpts) {
@@ -26,20 +23,20 @@ export class MeterRootState {
26
23
 
27
24
  constructor(opts: MeterRootStateOpts) {
28
25
  this.opts = opts;
29
- this.attachment = attachRef(this.opts.ref);
26
+ this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
30
27
  }
31
28
 
32
29
  readonly props = $derived.by(
33
30
  () =>
34
31
  ({
35
32
  role: 'meter',
36
- value: this.opts.value.current,
37
- 'aria-valuemin': this.opts.min.current,
38
- 'aria-valuemax': this.opts.max.current,
39
- 'aria-valuenow': this.opts.value.current,
40
- 'data-value': this.opts.value.current,
41
- 'data-max': this.opts.max.current,
42
- 'data-min': this.opts.min.current,
33
+ value: this.opts.value,
34
+ 'aria-valuemin': this.opts.min,
35
+ 'aria-valuemax': this.opts.max,
36
+ 'aria-valuenow': this.opts.value,
37
+ 'data-value': this.opts.value,
38
+ 'data-max': this.opts.max,
39
+ 'data-min': this.opts.min,
43
40
  [meterAttrs.root]: '',
44
41
  ...this.attachment,
45
42
  }) as const,
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { mergeProps } from '../../../internal/merge-props.js';
4
3
  import type { PopoverCloseProps } from '../types.js';
5
4
  import { PopoverCloseState } from '../popover.svelte.js';
@@ -11,11 +10,15 @@
11
10
  let { child, children, id = createId(uid), ref = $bindable(null), ...restProps }: PopoverCloseProps = $props();
12
11
 
13
12
  const closeState = PopoverCloseState.create({
14
- id: boxWith(() => id),
15
- ref: boxWith(
16
- () => ref,
17
- (value) => (ref = value),
18
- ),
13
+ get id() {
14
+ return id;
15
+ },
16
+ get ref() {
17
+ return ref;
18
+ },
19
+ set ref(v) {
20
+ ref = v;
21
+ },
19
22
  });
20
23
 
21
24
  const mergedProps = $derived(
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { mergeProps } from '../../../internal/merge-props.js';
4
3
  import type { PopoverContentProps } from '../types.js';
5
4
  import { PopoverContentState } from '../popover.svelte.js';
@@ -36,12 +35,18 @@
36
35
  }: PopoverContentProps = $props();
37
36
 
38
37
  const contentState = PopoverContentState.create({
39
- id: boxWith(() => id),
40
- ref: boxWith(
41
- () => ref,
42
- (v) => (ref = v),
43
- ),
44
- customAnchor: boxWith(() => customAnchor),
38
+ get id() {
39
+ return id;
40
+ },
41
+ get customAnchor() {
42
+ return customAnchor;
43
+ },
44
+ get ref() {
45
+ return ref;
46
+ },
47
+ set ref(v) {
48
+ ref = v;
49
+ },
45
50
  });
46
51
 
47
52
  const lifecycleProps = useNativePopoverLifecycle(contentState, { anchor: () => customAnchor, mode: 'auto' });
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { boxWith } from '../../../internal/tools/index.js';
3
2
  import { mergeProps } from '../../../internal/merge-props.js';
4
3
  import type { PopoverTriggerProps } from '../types.js';
5
4
  import { PopoverTriggerState } from '../popover.svelte.js';
@@ -21,15 +20,27 @@
21
20
  }: PopoverTriggerProps = $props();
22
21
 
23
22
  const triggerState = PopoverTriggerState.create({
24
- id: boxWith(() => id),
25
- ref: boxWith(
26
- () => ref,
27
- (v) => (ref = v),
28
- ),
29
- disabled: boxWith(() => Boolean(disabled)),
30
- openOnHover: boxWith(() => openOnHover),
31
- openDelay: boxWith(() => openDelay),
32
- closeDelay: boxWith(() => closeDelay),
23
+ get id() {
24
+ return id;
25
+ },
26
+ get disabled() {
27
+ return Boolean(disabled);
28
+ },
29
+ get openOnHover() {
30
+ return openOnHover;
31
+ },
32
+ get openDelay() {
33
+ return openDelay;
34
+ },
35
+ get closeDelay() {
36
+ return closeDelay;
37
+ },
38
+ get ref() {
39
+ return ref;
40
+ },
41
+ set ref(v) {
42
+ ref = v;
43
+ },
33
44
  });
34
45
 
35
46
  const mergedProps = $derived(mergeProps({ 'data-slot': 'popover-trigger' }, restProps, triggerState.props, { type }));
@@ -2,7 +2,6 @@
2
2
  import type { PopoverRootProps } from '../types.js';
3
3
  import { PopoverRootState } from '../popover.svelte.js';
4
4
  import { OpenCell } from '../../../internal/open-cell.svelte.js';
5
- import { boxWith } from '../../../internal/tools/index.js';
6
5
 
7
6
  let { open = false, onOpenChangeComplete = () => {}, state, children }: PopoverRootProps = $props();
8
7
 
@@ -10,16 +9,18 @@
10
9
  // derivation source, and the children snippet is the only way the cell leaves.
11
10
  // A caller-built `state` cell (with its own source/writer) takes over both roles.
12
11
  // The cell's identity is fixed at mount — swapping `state` later is not supported.
13
- // The engine keeps its boxed-open interface (vendored, ADR 0006); the box is a
14
- // bridge over the cell, so the cell stays the one owner of `open`.
15
12
  // svelte-ignore state_referenced_locally
16
13
  const popover = state ?? new OpenCell(() => open);
17
14
  PopoverRootState.create({
18
- open: boxWith(
19
- () => popover.open,
20
- (value) => (popover.open = value),
21
- ),
22
- onOpenChangeComplete: boxWith(() => onOpenChangeComplete),
15
+ get open() {
16
+ return popover.open;
17
+ },
18
+ set open(value) {
19
+ popover.open = value;
20
+ },
21
+ get onOpenChangeComplete() {
22
+ return onOpenChangeComplete;
23
+ },
23
24
  });
24
25
  </script>
25
26