bits-ui 1.3.0 → 1.3.2

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.
@@ -13,6 +13,7 @@
13
13
 
14
14
  <svelte:element
15
15
  this={href ? "a" : "button"}
16
+ data-button-root
16
17
  type={href ? undefined : type}
17
18
  href={href && !disabled ? href : undefined}
18
19
  disabled={href ? undefined : disabled}
@@ -21,7 +21,6 @@ declare class PopoverTriggerState {
21
21
  readonly root: PopoverRootState;
22
22
  constructor(opts: PopoverTriggerStateProps, root: PopoverRootState);
23
23
  onclick(e: BitsMouseEvent): void;
24
- onpointerdown(e: BitsPointerEvent): void;
25
24
  onkeydown(e: BitsKeyboardEvent): void;
26
25
  props: {
27
26
  readonly id: string;
@@ -31,7 +30,6 @@ declare class PopoverTriggerState {
31
30
  readonly "aria-controls": string | undefined;
32
31
  readonly "data-popover-trigger": "";
33
32
  readonly disabled: boolean;
34
- readonly onpointerdown: (e: BitsPointerEvent) => void;
35
33
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
36
34
  readonly onclick: (e: BitsMouseEvent) => void;
37
35
  };
@@ -32,7 +32,6 @@ class PopoverTriggerState {
32
32
  },
33
33
  });
34
34
  this.onclick = this.onclick.bind(this);
35
- this.onpointerdown = this.onpointerdown.bind(this);
36
35
  this.onkeydown = this.onkeydown.bind(this);
37
36
  }
38
37
  onclick(e) {
@@ -42,15 +41,6 @@ class PopoverTriggerState {
42
41
  return;
43
42
  this.root.toggleOpen();
44
43
  }
45
- onpointerdown(e) {
46
- if (this.opts.disabled.current)
47
- return;
48
- if (e.button !== 0)
49
- return;
50
- // We prevent default to prevent focus from moving to the trigger
51
- // since this action will open the popover and focus will move to the content
52
- e.preventDefault();
53
- }
54
44
  onkeydown(e) {
55
45
  if (this.opts.disabled.current)
56
46
  return;
@@ -74,7 +64,6 @@ class PopoverTriggerState {
74
64
  "data-popover-trigger": "",
75
65
  disabled: this.opts.disabled.current,
76
66
  //
77
- onpointerdown: this.onpointerdown,
78
67
  onkeydown: this.onkeydown,
79
68
  onclick: this.onclick,
80
69
  }));
@@ -41,7 +41,6 @@
41
41
  enabled={contentState.root.opts.open.current}
42
42
  {id}
43
43
  {preventScroll}
44
- onPlaced={() => (contentState.isPositioned = true)}
45
44
  forceMount={true}
46
45
  >
47
46
  {#snippet popper({ props, wrapperProps })}
@@ -131,10 +131,6 @@ declare class SelectTriggerState {
131
131
  constructor(opts: SelectTriggerStateProps, root: SelectRootState);
132
132
  onkeydown(e: BitsKeyboardEvent): void;
133
133
  onclick(e: BitsMouseEvent): void;
134
- /**
135
- * `pointerdown` fires before the `focus` event, so we can prevent the default
136
- * behavior of focusing the button and keep focus on the input.
137
- */
138
134
  onpointerdown(e: BitsPointerEvent): void;
139
135
  onpointerup(e: BitsPointerEvent): void;
140
136
  props: {
@@ -339,6 +335,7 @@ declare class SelectScrollDownButtonState {
339
335
  content: SelectContentState;
340
336
  root: SelectBaseRootState;
341
337
  canScrollDown: boolean;
338
+ scrollIntoViewTimer: ReturnType<typeof globalThis.setTimeout> | null;
342
339
  constructor(state: SelectScrollButtonImplState);
343
340
  /**
344
341
  * @param manual - if true, it means the function was invoked manually outside of an event
@@ -1,5 +1,5 @@
1
1
  import { Context, Previous, watch } from "runed";
2
- import { afterTick, onDestroyEffect, srOnlyStyles, styleToString, useRefById, } from "svelte-toolbelt";
2
+ import { afterSleep, afterTick, onDestroyEffect, srOnlyStyles, styleToString, useRefById, } from "svelte-toolbelt";
3
3
  import { on } from "svelte/events";
4
4
  import { backward, forward, next, prev } from "../../internal/arrays.js";
5
5
  import { getAriaExpanded, getAriaHidden, getDataDisabled, getDataOpenClosed, getDisabled, getRequired, } from "../../internal/attrs.js";
@@ -163,6 +163,11 @@ class SelectMultipleRootState extends SelectBaseRootState {
163
163
  constructor(opts) {
164
164
  super(opts);
165
165
  this.opts = opts;
166
+ $effect(() => {
167
+ if (!this.opts.open.current && this.highlightedNode) {
168
+ this.setHighlightedNode(null);
169
+ }
170
+ });
166
171
  watch(() => this.opts.open.current, () => {
167
172
  if (!this.opts.open.current)
168
173
  return;
@@ -484,6 +489,7 @@ class SelectTriggerState {
484
489
  }
485
490
  if (!this.root.isMulti && !isCurrentSelectedValue) {
486
491
  this.root.handleClose();
492
+ return;
487
493
  }
488
494
  }
489
495
  if (e.key === kbd.ARROW_UP && e.altKey) {
@@ -546,10 +552,6 @@ class SelectTriggerState {
546
552
  const currTarget = e.currentTarget;
547
553
  currTarget.focus();
548
554
  }
549
- /**
550
- * `pointerdown` fires before the `focus` event, so we can prevent the default
551
- * behavior of focusing the button and keep focus on the input.
552
- */
553
555
  onpointerdown(e) {
554
556
  if (this.root.opts.disabled.current)
555
557
  return;
@@ -566,7 +568,6 @@ class SelectTriggerState {
566
568
  if (e.button === 0 && e.ctrlKey === false) {
567
569
  if (this.root.opts.open.current === false) {
568
570
  this.#handlePointerOpen(e);
569
- e.preventDefault();
570
571
  }
571
572
  else {
572
573
  this.root.handleClose();
@@ -576,7 +577,12 @@ class SelectTriggerState {
576
577
  onpointerup(e) {
577
578
  e.preventDefault();
578
579
  if (e.pointerType === "touch") {
579
- this.#handlePointerOpen(e);
580
+ if (this.root.opts.open.current === false) {
581
+ this.#handlePointerOpen(e);
582
+ }
583
+ else {
584
+ this.root.handleClose();
585
+ }
580
586
  }
581
587
  }
582
588
  props = $derived.by(() => ({
@@ -908,15 +914,13 @@ class SelectScrollButtonImplState {
908
914
  ...opts,
909
915
  deps: () => this.mounted,
910
916
  });
911
- watch(() => this.mounted, () => {
917
+ watch([() => this.mounted], () => {
912
918
  if (!this.mounted) {
913
919
  this.isUserScrolling = false;
914
920
  return;
915
921
  }
916
922
  if (this.isUserScrolling)
917
923
  return;
918
- const activeItem = this.root.highlightedNode;
919
- activeItem?.scrollIntoView({ block: "nearest" });
920
924
  });
921
925
  $effect(() => {
922
926
  if (this.mounted)
@@ -973,24 +977,30 @@ class SelectScrollDownButtonState {
973
977
  content;
974
978
  root;
975
979
  canScrollDown = $state(false);
980
+ scrollIntoViewTimer = null;
976
981
  constructor(state) {
977
982
  this.state = state;
978
983
  this.content = state.content;
979
984
  this.root = state.root;
980
985
  this.state.onAutoScroll = this.handleAutoScroll;
981
- watch([
982
- () => this.content.viewportNode,
983
- () => this.content.isPositioned,
984
- () => this.root.opts.open.current,
985
- ], () => {
986
- if (!this.content.viewportNode ||
987
- !this.content.isPositioned ||
988
- !this.root.opts.open.current) {
986
+ watch([() => this.content.viewportNode, () => this.content.isPositioned], () => {
987
+ if (!this.content.viewportNode || !this.content.isPositioned) {
989
988
  return;
990
989
  }
991
990
  this.handleScroll(true);
992
991
  return on(this.content.viewportNode, "scroll", () => this.handleScroll());
993
992
  });
993
+ watch(() => this.state.mounted, () => {
994
+ if (!this.state.mounted)
995
+ return;
996
+ if (this.scrollIntoViewTimer) {
997
+ clearTimeout(this.scrollIntoViewTimer);
998
+ }
999
+ this.scrollIntoViewTimer = afterSleep(5, () => {
1000
+ const activeItem = this.root.highlightedNode;
1001
+ activeItem?.scrollIntoView({ block: "nearest" });
1002
+ });
1003
+ });
994
1004
  }
995
1005
  /**
996
1006
  * @param manual - if true, it means the function was invoked manually outside of an event
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",