bits-ui 1.0.0-next.90 → 1.0.0-next.92

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 (50) hide show
  1. package/dist/bits/alert-dialog/components/alert-dialog-content.svelte +8 -5
  2. package/dist/bits/command/command.svelte.d.ts +0 -1
  3. package/dist/bits/command/command.svelte.js +50 -61
  4. package/dist/bits/command/components/command.svelte +3 -2
  5. package/dist/bits/command/compute-command-score.d.ts +26 -0
  6. package/dist/bits/command/{command-score.js → compute-command-score.js} +47 -15
  7. package/dist/bits/command/index.d.ts +1 -0
  8. package/dist/bits/command/index.js +1 -0
  9. package/dist/bits/command/types.d.ts +2 -1
  10. package/dist/bits/dialog/components/dialog-content.svelte +8 -5
  11. package/dist/bits/index.d.ts +1 -1
  12. package/dist/bits/index.js +1 -1
  13. package/dist/bits/menubar/components/menubar-content-static.svelte +9 -0
  14. package/dist/bits/menubar/components/menubar-content.svelte +9 -0
  15. package/dist/bits/menubar/menubar.svelte.d.ts +7 -3
  16. package/dist/bits/menubar/menubar.svelte.js +10 -2
  17. package/dist/bits/navigation-menu/components/navigation-menu-content-impl.svelte +90 -0
  18. package/dist/bits/navigation-menu/components/navigation-menu-content-impl.svelte.d.ts +13 -0
  19. package/dist/bits/navigation-menu/components/navigation-menu-content.svelte +18 -57
  20. package/dist/bits/navigation-menu/components/navigation-menu-content.svelte.d.ts +1 -1
  21. package/dist/bits/navigation-menu/components/navigation-menu-indicator-impl.svelte +32 -0
  22. package/dist/bits/navigation-menu/components/navigation-menu-indicator-impl.svelte.d.ts +4 -0
  23. package/dist/bits/navigation-menu/components/navigation-menu-indicator.svelte +7 -19
  24. package/dist/bits/navigation-menu/components/navigation-menu-list.svelte +10 -8
  25. package/dist/bits/navigation-menu/components/navigation-menu-sub.svelte +44 -0
  26. package/dist/bits/navigation-menu/components/navigation-menu-sub.svelte.d.ts +4 -0
  27. package/dist/bits/navigation-menu/components/navigation-menu-trigger.svelte +3 -3
  28. package/dist/bits/navigation-menu/components/navigation-menu-viewport.svelte +3 -3
  29. package/dist/bits/navigation-menu/exports.d.ts +2 -1
  30. package/dist/bits/navigation-menu/exports.js +1 -0
  31. package/dist/bits/navigation-menu/navigation-menu.svelte.d.ts +209 -201
  32. package/dist/bits/navigation-menu/navigation-menu.svelte.js +572 -621
  33. package/dist/bits/navigation-menu/types.d.ts +18 -2
  34. package/dist/bits/select/select.svelte.d.ts +2 -2
  35. package/dist/bits/select/select.svelte.js +27 -8
  36. package/dist/bits/utilities/dismissible-layer/use-dismissable-layer.svelte.js +1 -1
  37. package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.js +2 -2
  38. package/dist/bits/utilities/popper-layer/popper-layer.svelte +2 -2
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +1 -1
  41. package/dist/internal/events.d.ts +1 -1
  42. package/dist/internal/events.js +2 -2
  43. package/dist/internal/previous-with-init.svelte.d.ts +11 -0
  44. package/dist/internal/previous-with-init.svelte.js +21 -0
  45. package/dist/internal/tabbable.d.ts +1 -0
  46. package/dist/internal/tabbable.js +1 -1
  47. package/dist/internal/use-arrow-navigation.d.ts +0 -1
  48. package/dist/internal/use-arrow-navigation.js +2 -2
  49. package/package.json +1 -1
  50. package/dist/bits/command/command-score.d.ts +0 -1
@@ -1,4 +1,6 @@
1
- import type { OnChangeFn, WithChild, Without } from "../../internal/types.js";
1
+ import type { EscapeBehaviorType } from "../utilities/escape-layer/types.js";
2
+ import type { InteractOutsideBehaviorType } from "../utilities/dismissible-layer/types.js";
3
+ import type { OnChangeFn, WithChild, WithChildNoChildrenSnippetProps, Without } from "../../internal/types.js";
2
4
  import type { BitsPrimitiveAnchorAttributes, BitsPrimitiveButtonAttributes, BitsPrimitiveDivAttributes, BitsPrimitiveElementAttributes, BitsPrimitiveLiAttributes, BitsPrimitiveUListAttributes } from "../../shared/attributes.js";
3
5
  import type { Direction, Orientation } from "../../shared/index.js";
4
6
  export type NavigationMenuRootPropsWithoutHTML = WithChild<{
@@ -53,7 +55,13 @@ export type NavigationMenuSubPropsWithoutHTML = WithChild<{
53
55
  orientation?: Orientation;
54
56
  }>;
55
57
  export type NavigationMenuSubProps = NavigationMenuSubPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, NavigationMenuSubPropsWithoutHTML>;
56
- export type NavigationMenuListPropsWithoutHTML = WithChild;
58
+ export type NavigationMenuListPropsWithoutHTML = WithChildNoChildrenSnippetProps<{}, {
59
+ /**
60
+ * Attributes to spread onto a wrapper element around the content.
61
+ * Do not style the wrapper element, its styles are computed by Floating UI.
62
+ */
63
+ wrapperProps: Record<string, unknown>;
64
+ }>;
57
65
  export type NavigationMenuListProps = NavigationMenuListPropsWithoutHTML & Without<BitsPrimitiveUListAttributes, NavigationMenuListPropsWithoutHTML>;
58
66
  export type NavigationMenuItemPropsWithoutHTML = WithChild<{
59
67
  /**
@@ -87,6 +95,14 @@ export type NavigationMenuContentPropsWithoutHTML = WithChild<{
87
95
  * Default behavior can be prevented with `event.preventDefault()`
88
96
  */
89
97
  onEscapeKeydown?: (event: KeyboardEvent) => void;
98
+ /**
99
+ * Behavior when the escape key is pressed while the menu content is open.
100
+ */
101
+ escapeKeydownBehavior?: EscapeBehaviorType;
102
+ /**
103
+ * Behavior when an interaction occurs outside the content.
104
+ */
105
+ interactOutsideBehavior?: InteractOutsideBehaviorType;
90
106
  /**
91
107
  * Whether to forcefully mount the content, regardless of the open state.
92
108
  * This is useful when wanting to use more custom transition and animation
@@ -212,7 +212,7 @@ declare class SelectItemState {
212
212
  * multiple clicks.
213
213
  */
214
214
  onpointerup(e: BitsPointerEvent): void;
215
- onpointermove(_: BitsPointerEvent): void;
215
+ onpointermove(e: BitsPointerEvent): void;
216
216
  props: {
217
217
  readonly [x: string]: string | ((e: BitsPointerEvent) => void) | undefined;
218
218
  readonly id: string;
@@ -223,7 +223,7 @@ declare class SelectItemState {
223
223
  readonly "data-highlighted": "" | undefined;
224
224
  readonly "data-selected": "" | undefined;
225
225
  readonly "data-label": string;
226
- readonly onpointermove: (_: BitsPointerEvent) => void;
226
+ readonly onpointermove: (e: BitsPointerEvent) => void;
227
227
  readonly onpointerdown: (e: BitsPointerEvent) => void;
228
228
  readonly onpointerup: (e: BitsPointerEvent) => void;
229
229
  };
@@ -7,6 +7,7 @@ import { kbd } from "../../internal/kbd.js";
7
7
  import { noop } from "../../internal/noop.js";
8
8
  import { useDOMTypeahead } from "../../internal/use-dom-typeahead.svelte.js";
9
9
  import { useDataTypeahead } from "../../internal/use-data-typeahead.svelte.js";
10
+ import { isIOS } from "../../internal/is.js";
10
11
  // prettier-ignore
11
12
  export const INTERACTION_KEYS = [kbd.ARROW_LEFT, kbd.ESCAPE, kbd.ARROW_RIGHT, kbd.SHIFT, kbd.CAPS_LOCK, kbd.CONTROL, kbd.ALT, kbd.META, kbd.ENTER, kbd.F1, kbd.F2, kbd.F3, kbd.F4, kbd.F5, kbd.F6, kbd.F7, kbd.F8, kbd.F9, kbd.F10, kbd.F11, kbd.F12];
12
13
  export const FIRST_KEYS = [kbd.ARROW_DOWN, kbd.PAGE_UP, kbd.HOME];
@@ -706,7 +707,7 @@ class SelectItemState {
706
707
  highlighted: this.isHighlighted,
707
708
  }));
708
709
  onpointerdown(e) {
709
- // prevent focus from leaving the combobox
710
+ // prevent focus from leaving the input/select trigger
710
711
  e.preventDefault();
711
712
  }
712
713
  /**
@@ -718,19 +719,37 @@ class SelectItemState {
718
719
  if (e.defaultPrevented || !this.opts.ref.current)
719
720
  return;
720
721
  // prevent any default behavior
721
- e.preventDefault();
722
722
  /**
723
- * For one reason or another, when it's a touch pointer and _only_ in combobox mode,
724
- * we need to listen for the immediate click event to handle the selection, otherwise
725
- * a click event will be fired on the element behind the item after the content closes.
723
+ * For one reason or another, when it's a touch pointer and _not_ on IOS,
724
+ * we need to listen for the immediate click event to handle the selection,
725
+ * otherwise a click event will fire on the element _behind_ the item.
726
726
  */
727
- if (e.pointerType === "touch") {
728
- on(this.opts.ref.current, "click", () => this.handleSelect(), { once: true });
727
+ if (e.pointerType === "touch" && !isIOS) {
728
+ on(this.opts.ref.current, "click", () => {
729
+ this.handleSelect();
730
+ // set highlighted node since we don't do it on `pointermove` events
731
+ // for touch devices
732
+ this.root.setHighlightedNode(this.opts.ref.current);
733
+ }, { once: true });
729
734
  return;
730
735
  }
736
+ e.preventDefault();
731
737
  this.handleSelect();
738
+ if (e.pointerType === "touch") {
739
+ // set highlighted node since we don't do it on `pointermove` events
740
+ // for touch devices
741
+ this.root.setHighlightedNode(this.opts.ref.current);
742
+ }
732
743
  }
733
- onpointermove(_) {
744
+ onpointermove(e) {
745
+ /**
746
+ * We don't want to highlight items on touch devices when scrolling,
747
+ * as this is confusing behavior, so we return here and instead handle
748
+ * the highlighting on the `pointerup` (or following `click`) event for
749
+ * touch devices only.
750
+ */
751
+ if (e.pointerType === "touch")
752
+ return;
734
753
  if (this.root.highlightedNode !== this.opts.ref.current) {
735
754
  this.root.setHighlightedNode(this.opts.ref.current);
736
755
  }
@@ -16,9 +16,9 @@ export class DismissibleLayerState {
16
16
  pointerdown: false,
17
17
  };
18
18
  #isResponsibleLayer = false;
19
+ #isFocusInsideDOMTree = false;
19
20
  node = box(null);
20
21
  #documentObj = undefined;
21
- #isFocusInsideDOMTree = $state(false);
22
22
  #onFocusOutside;
23
23
  currNode = $state(null);
24
24
  #unsubClickListener = noop;
@@ -26,7 +26,7 @@ export function useFocusScope({ id, loop, enabled, onOpenAutoFocus, onCloseAutoF
26
26
  ref,
27
27
  deps: () => enabled.current,
28
28
  });
29
- let lastFocusedElement = $state(null);
29
+ let lastFocusedElement = null;
30
30
  watch([() => ref.current, () => enabled.current], ([container, enabled]) => {
31
31
  if (!container || !enabled)
32
32
  return;
@@ -116,7 +116,7 @@ export function useFocusScope({ id, loop, enabled, onOpenAutoFocus, onCloseAutoF
116
116
  function handleOpen(container, prevFocusedElement) {
117
117
  if (!container)
118
118
  container = document.getElementById(id.current);
119
- if (!container)
119
+ if (!container || !enabled.current)
120
120
  return;
121
121
  focusScopeStack.add(focusScope);
122
122
  const hasFocusedCandidate = container.contains(prevFocusedElement);
@@ -44,7 +44,7 @@
44
44
  </script>
45
45
 
46
46
  <PresenceLayer {id} {present} {...restProps}>
47
- {#snippet presence({ present })}
47
+ {#snippet presence()}
48
48
  <PopperLayerInner
49
49
  {popper}
50
50
  {onEscapeKeydown}
@@ -72,7 +72,7 @@
72
72
  {onPlaced}
73
73
  {customAnchor}
74
74
  {isStatic}
75
- enabled={present.current}
75
+ enabled={present}
76
76
  {onInteractOutside}
77
77
  {onCloseAutoFocus}
78
78
  {onOpenAutoFocus}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, } from "./bits/index.js";
1
+ export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, computeCommandScore, } from "./bits/index.js";
2
2
  export * from "./shared/index.js";
3
3
  export type * from "./shared/index.js";
4
4
  export * from "./types.js";
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, } from "./bits/index.js";
1
+ export { Accordion, AlertDialog, AspectRatio, Avatar, Button, Calendar, Checkbox, Collapsible, Combobox, Command, ContextMenu, DateField, DatePicker, DateRangeField, DateRangePicker, Dialog, DropdownMenu, Label, LinkPreview, Menubar, NavigationMenu, Pagination, PinInput, Popover, Progress, RadioGroup, RangeCalendar, ScrollArea, Select, Separator, Slider, Switch, Tabs, Toggle, ToggleGroup, Toolbar, Tooltip, Portal, IsUsingKeyboard, computeCommandScore, } from "./bits/index.js";
2
2
  export * from "./shared/index.js";
3
3
  export * from "./types.js";
@@ -16,6 +16,6 @@ export declare class CustomEventDispatcher<T = unknown> {
16
16
  constructor(eventName: string, options?: Omit<CustomEventInit<T>, "detail">);
17
17
  createEvent(detail?: T): CustomEvent<T>;
18
18
  dispatch(element: EventTarget, detail?: T): CustomEvent<T>;
19
- listen(element: EventTarget, callback: (event: CustomEvent<T>) => void): () => void;
19
+ listen(element: EventTarget, callback: (event: CustomEvent<T>) => void, options?: AddEventListenerOptions): () => void;
20
20
  }
21
21
  export {};
@@ -40,10 +40,10 @@ export class CustomEventDispatcher {
40
40
  element.dispatchEvent(event);
41
41
  return event;
42
42
  }
43
- listen(element, callback) {
43
+ listen(element, callback, options) {
44
44
  const handler = (event) => {
45
45
  callback(event);
46
46
  };
47
- return on(element, this.eventName, handler);
47
+ return on(element, this.eventName, handler, options);
48
48
  }
49
49
  }
@@ -0,0 +1,11 @@
1
+ import type { Getter } from "svelte-toolbelt";
2
+ /**
3
+ * Holds the previous value of a getter, with the initial value being
4
+ * the value of the getter when the instance is created, rather than
5
+ * `undefined`.
6
+ */
7
+ export declare class PreviousWithInit<T> {
8
+ #private;
9
+ constructor(getter: Getter<T>);
10
+ get current(): T;
11
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Holds the previous value of a getter, with the initial value being
3
+ * the value of the getter when the instance is created, rather than
4
+ * `undefined`.
5
+ */
6
+ export class PreviousWithInit {
7
+ #previous = $state(null);
8
+ #curr;
9
+ constructor(getter) {
10
+ const init = getter();
11
+ this.#previous = init;
12
+ this.#curr = init;
13
+ $effect(() => {
14
+ this.#previous = this.#curr;
15
+ this.#curr = getter();
16
+ });
17
+ }
18
+ get current() {
19
+ return this.#previous;
20
+ }
21
+ }
@@ -1,3 +1,4 @@
1
+ export declare function getTabbableIn(container: HTMLElement, direction: "next" | "prev"): import("tabbable").FocusableElement | undefined;
1
2
  /**
2
3
  * Gets all tabbable elements in the body and finds the next/previous tabbable element
3
4
  * from the `currentNode` based on the `direction` provided.
@@ -13,7 +13,7 @@ function getTabbableOptions() {
13
13
  : "none",
14
14
  };
15
15
  }
16
- function getTabbableIn(container, direction) {
16
+ export function getTabbableIn(container, direction) {
17
17
  const allTabbable = tabbable(container, getTabbableOptions());
18
18
  if (direction === "prev") {
19
19
  allTabbable.reverse();
@@ -51,7 +51,6 @@ interface ArrowNavigationOptions {
51
51
  focus?: boolean;
52
52
  }
53
53
  /**
54
- * Allow arrow navigation for every html element with data-radix-vue-collection-item tag
55
54
  *
56
55
  * @param e Keyboard event
57
56
  * @param currentElement Event initiator element or any element that wants to handle the navigation
@@ -1,6 +1,5 @@
1
1
  const ignoredElement = ["INPUT", "TEXTAREA"];
2
2
  /**
3
- * Allow arrow navigation for every html element with data-radix-vue-collection-item tag
4
3
  *
5
4
  * @param e Keyboard event
6
5
  * @param currentElement Event initiator element or any element that wants to handle the navigation
@@ -10,8 +9,9 @@ const ignoredElement = ["INPUT", "TEXTAREA"];
10
9
  */
11
10
  export function useArrowNavigation(e, currentElement, parentElement, options) {
12
11
  if (!currentElement ||
13
- (options.enableIgnoredElement && ignoredElement.includes(currentElement.nodeName)))
12
+ (options.enableIgnoredElement && ignoredElement.includes(currentElement.nodeName))) {
14
13
  return null;
14
+ }
15
15
  const { arrowKeyOptions = "both", attributeName, itemsArray = [], loop = true, dir = "ltr", preventScroll = true, focus = false, } = options;
16
16
  const [right, left, up, down, home, end] = [
17
17
  e.key === "ArrowRight",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "1.0.0-next.90",
3
+ "version": "1.0.0-next.92",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",
@@ -1 +0,0 @@
1
- export declare function commandScore(string: string, abbreviation: string, aliases?: string[]): number;