bits-ui 2.9.3 → 2.9.5

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/dist/app.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-var */
2
1
  import type { ReadableBox } from "svelte-toolbelt";
3
2
  import type { DismissibleLayerState } from "./bits/utilities/dismissible-layer/use-dismissable-layer.svelte.ts";
4
3
  import type { InteractOutsideBehaviorType } from "./bits/utilities/dismissible-layer/types.ts";
@@ -6,6 +6,7 @@
6
6
  import { FloatingLayer } from "../../utilities/floating-layer/index.js";
7
7
 
8
8
  let {
9
+ disabled = false,
9
10
  open = $bindable(false),
10
11
  onOpenChange = noop,
11
12
  onOpenChangeComplete = noop,
@@ -15,6 +16,7 @@
15
16
  }: LinkPreviewRootProps = $props();
16
17
 
17
18
  LinkPreviewRootState.create({
19
+ disabled: box.with(() => disabled),
18
20
  open: box.with(
19
21
  () => open,
20
22
  (v) => {
@@ -3,6 +3,7 @@ import type { BitsFocusEvent, BitsPointerEvent, OnChangeFn, RefAttachment, WithR
3
3
  interface LinkPreviewRootStateOpts extends WritableBoxedValues<{
4
4
  open: boolean;
5
5
  }>, ReadableBoxedValues<{
6
+ disabled: boolean;
6
7
  openDelay: number;
7
8
  closeDelay: number;
8
9
  onOpenChangeComplete: OnChangeFn<boolean>;
@@ -76,7 +76,7 @@ export class LinkPreviewRootState {
76
76
  }
77
77
  handleOpen() {
78
78
  this.clearTimeout();
79
- if (this.opts.open.current)
79
+ if (this.opts.open.current || this.opts.disabled.current)
80
80
  return;
81
81
  this.isOpening = true;
82
82
  this.timeout = this.domContext.setTimeout(() => {
@@ -52,8 +52,10 @@
52
52
  checked: box.with(
53
53
  () => checked,
54
54
  (v) => {
55
- checked = v;
56
- onCheckedChange(v);
55
+ if (v !== checked) {
56
+ checked = v;
57
+ onCheckedChange(v);
58
+ }
57
59
  }
58
60
  ),
59
61
  id: box.with(() => id),
@@ -67,8 +69,10 @@
67
69
  indeterminate: box.with(
68
70
  () => indeterminate,
69
71
  (v) => {
70
- indeterminate = v;
71
- onIndeterminateChange(v);
72
+ if (v !== indeterminate) {
73
+ indeterminate = v;
74
+ onIndeterminateChange(v);
75
+ }
72
76
  }
73
77
  ),
74
78
  value: box.with(() => value),
@@ -11,6 +11,7 @@ const lockMap = new SvelteMap();
11
11
  let initialBodyStyle = $state(null);
12
12
  let stopTouchMoveListener = null;
13
13
  let cleanupTimeoutId = null;
14
+ let isInCleanupTransition = false;
14
15
  const anyLocked = box.with(() => {
15
16
  for (const value of lockMap.values()) {
16
17
  if (value)
@@ -35,7 +36,6 @@ const bodyLockStackCount = new SharedState(() => {
35
36
  isIOS && stopTouchMoveListener?.();
36
37
  // reset initialBodyStyle so next locker captures the correct styles
37
38
  initialBodyStyle = null;
38
- hasEverBeenLocked = false;
39
39
  }
40
40
  function cancelPendingCleanup() {
41
41
  if (cleanupTimeoutId === null)
@@ -45,6 +45,7 @@ const bodyLockStackCount = new SharedState(() => {
45
45
  }
46
46
  function scheduleCleanupIfNoNewLocks(delay, callback) {
47
47
  cancelPendingCleanup();
48
+ isInCleanupTransition = true;
48
49
  cleanupScheduledAt = Date.now();
49
50
  const currentCleanupId = cleanupScheduledAt;
50
51
  /**
@@ -64,24 +65,20 @@ const bodyLockStackCount = new SharedState(() => {
64
65
  return;
65
66
  // ensure no new locks were added during the delay
66
67
  if (!isAnyLocked(lockMap)) {
68
+ isInCleanupTransition = false;
67
69
  callback();
68
70
  }
71
+ else {
72
+ isInCleanupTransition = false;
73
+ }
69
74
  };
70
- if (delay === null) {
71
- // use a small delay even when no restoreScrollDelay is set
72
- // to handle same-tick destroy/create scenarios (~1 frame)
73
- cleanupTimeoutId = window.setTimeout(cleanupFn, 16);
74
- }
75
- else {
76
- cleanupTimeoutId = window.setTimeout(cleanupFn, delay);
77
- }
75
+ const actualDelay = delay === null ? 24 : delay;
76
+ cleanupTimeoutId = window.setTimeout(cleanupFn, actualDelay);
78
77
  }
79
- // track if we've ever applied lock styles in this session
80
- let hasEverBeenLocked = false;
81
78
  function ensureInitialStyleCaptured() {
82
- if (!hasEverBeenLocked && initialBodyStyle === null) {
79
+ // only capture initial style once, when no locks exist and no cleanup is in progress
80
+ if (initialBodyStyle === null && lockMap.size === 0 && !isInCleanupTransition) {
83
81
  initialBodyStyle = document.body.getAttribute("style");
84
- hasEverBeenLocked = true;
85
82
  }
86
83
  }
87
84
  watch(() => anyLocked.current, () => {
@@ -89,6 +86,8 @@ const bodyLockStackCount = new SharedState(() => {
89
86
  return;
90
87
  // ensure we've captured the initial style before applying any lock styles
91
88
  ensureInitialStyleCaptured();
89
+ // if we're applying lock styles, we're no longer in a cleanup transition
90
+ isInCleanupTransition = false;
92
91
  const bodyStyle = getComputedStyle(document.body);
93
92
  // TODO: account for RTL direction, etc.
94
93
  const verticalScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "2.9.3",
3
+ "version": "2.9.5",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",
@@ -20,19 +20,19 @@
20
20
  ],
21
21
  "devDependencies": {
22
22
  "@internationalized/date": "^3.8.2",
23
- "@sveltejs/kit": "^2.21.5",
24
- "@sveltejs/package": "^2.3.11",
25
- "@sveltejs/vite-plugin-svelte": "^5.1.0",
26
- "@types/node": "^20.17.6",
23
+ "@sveltejs/kit": "^2.31.0",
24
+ "@sveltejs/package": "^2.4.1",
25
+ "@sveltejs/vite-plugin-svelte": "^6.1.2",
26
+ "@types/node": "^20.19.0",
27
27
  "@types/resize-observer-browser": "^0.1.11",
28
28
  "csstype": "^3.1.3",
29
29
  "jsdom": "^24.1.3",
30
30
  "publint": "^0.2.12",
31
- "svelte": "5.33.2",
32
- "svelte-check": "^4.2.2",
31
+ "svelte": "^5.38.1",
32
+ "svelte-check": "^4.3.1",
33
33
  "typescript": "^5.8.3",
34
- "vite": "^6.3.5",
35
- "vitest": "3.2.3"
34
+ "vite": "^7.0.4",
35
+ "vitest": "^3.2.3"
36
36
  },
37
37
  "svelte": "./dist/index.js",
38
38
  "types": "./dist/index.d.ts",