bits-ui 2.8.0 → 2.8.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.
Files changed (99) hide show
  1. package/dist/bits/accordion/accordion.svelte.d.ts +6 -1
  2. package/dist/bits/accordion/accordion.svelte.js +15 -5
  3. package/dist/bits/alert-dialog/components/alert-dialog-content.svelte +6 -9
  4. package/dist/bits/aspect-ratio/aspect-ratio.svelte.d.ts +2 -1
  5. package/dist/bits/aspect-ratio/aspect-ratio.svelte.js +3 -1
  6. package/dist/bits/avatar/avatar.svelte.d.ts +4 -1
  7. package/dist/bits/avatar/avatar.svelte.js +9 -3
  8. package/dist/bits/calendar/calendar.svelte.d.ts +15 -1
  9. package/dist/bits/calendar/calendar.svelte.js +42 -14
  10. package/dist/bits/calendar/components/calendar-next-button.svelte +3 -1
  11. package/dist/bits/calendar/components/calendar-prev-button.svelte +3 -1
  12. package/dist/bits/checkbox/checkbox.svelte.d.ts +4 -1
  13. package/dist/bits/checkbox/checkbox.svelte.js +9 -3
  14. package/dist/bits/collapsible/collapsible.svelte.d.ts +4 -1
  15. package/dist/bits/collapsible/collapsible.svelte.js +9 -3
  16. package/dist/bits/command/command.svelte.d.ts +13 -1
  17. package/dist/bits/command/command.svelte.js +36 -12
  18. package/dist/bits/context-menu/components/context-menu-content.svelte +1 -1
  19. package/dist/bits/date-field/date-field.svelte.d.ts +8 -2
  20. package/dist/bits/date-field/date-field.svelte.js +18 -6
  21. package/dist/bits/date-range-field/date-range-field.svelte.d.ts +3 -1
  22. package/dist/bits/date-range-field/date-range-field.svelte.js +6 -2
  23. package/dist/bits/dialog/components/dialog-content.svelte +5 -7
  24. package/dist/bits/dialog/dialog.svelte.d.ts +9 -1
  25. package/dist/bits/dialog/dialog.svelte.js +33 -18
  26. package/dist/bits/dropdown-menu/components/dropdown-menu-content.svelte +3 -2
  27. package/dist/bits/label/label.svelte.d.ts +2 -1
  28. package/dist/bits/label/label.svelte.js +3 -1
  29. package/dist/bits/link-preview/link-preview.svelte.d.ts +3 -1
  30. package/dist/bits/link-preview/link-preview.svelte.js +6 -2
  31. package/dist/bits/menu/menu.svelte.d.ts +12 -1
  32. package/dist/bits/menu/menu.svelte.js +38 -26
  33. package/dist/bits/menubar/components/menubar-trigger.svelte +4 -3
  34. package/dist/bits/menubar/menubar.svelte.d.ts +4 -3
  35. package/dist/bits/menubar/menubar.svelte.js +9 -6
  36. package/dist/bits/meter/meter.svelte.d.ts +2 -1
  37. package/dist/bits/meter/meter.svelte.js +3 -1
  38. package/dist/bits/navigation-menu/components/navigation-menu-link.svelte +2 -1
  39. package/dist/bits/navigation-menu/components/navigation-menu-trigger.svelte +2 -1
  40. package/dist/bits/navigation-menu/navigation-menu.svelte.d.ts +14 -3
  41. package/dist/bits/navigation-menu/navigation-menu.svelte.js +33 -13
  42. package/dist/bits/pagination/pagination.svelte.d.ts +4 -1
  43. package/dist/bits/pagination/pagination.svelte.js +9 -3
  44. package/dist/bits/pin-input/pin-input.svelte.d.ts +4 -1
  45. package/dist/bits/pin-input/pin-input.svelte.js +8 -3
  46. package/dist/bits/popover/popover.svelte.d.ts +4 -1
  47. package/dist/bits/popover/popover.svelte.js +9 -3
  48. package/dist/bits/progress/progress.svelte.d.ts +2 -1
  49. package/dist/bits/progress/progress.svelte.js +3 -1
  50. package/dist/bits/radio-group/radio-group.svelte.d.ts +3 -1
  51. package/dist/bits/radio-group/radio-group.svelte.js +6 -2
  52. package/dist/bits/range-calendar/range-calendar.svelte.d.ts +4 -1
  53. package/dist/bits/range-calendar/range-calendar.svelte.js +9 -3
  54. package/dist/bits/rating-group/rating-group.svelte.d.ts +3 -1
  55. package/dist/bits/rating-group/rating-group.svelte.js +6 -2
  56. package/dist/bits/scroll-area/scroll-area.svelte.d.ts +8 -1
  57. package/dist/bits/scroll-area/scroll-area.svelte.js +20 -7
  58. package/dist/bits/select/select.svelte.d.ts +10 -1
  59. package/dist/bits/select/select.svelte.js +27 -9
  60. package/dist/bits/separator/separator.svelte.d.ts +2 -1
  61. package/dist/bits/separator/separator.svelte.js +3 -1
  62. package/dist/bits/slider/slider.svelte.d.ts +7 -1
  63. package/dist/bits/slider/slider.svelte.js +18 -6
  64. package/dist/bits/switch/switch.svelte.d.ts +3 -1
  65. package/dist/bits/switch/switch.svelte.js +6 -2
  66. package/dist/bits/tabs/tabs.svelte.d.ts +5 -1
  67. package/dist/bits/tabs/tabs.svelte.js +12 -4
  68. package/dist/bits/time-field/time-field.svelte.d.ts +7 -1
  69. package/dist/bits/time-field/time-field.svelte.js +18 -6
  70. package/dist/bits/time-range-field/time-range-field.svelte.d.ts +3 -1
  71. package/dist/bits/time-range-field/time-range-field.svelte.js +6 -2
  72. package/dist/bits/toggle/toggle.svelte.d.ts +2 -1
  73. package/dist/bits/toggle/toggle.svelte.js +3 -1
  74. package/dist/bits/toggle-group/toggle-group.svelte.d.ts +3 -1
  75. package/dist/bits/toggle-group/toggle-group.svelte.js +6 -2
  76. package/dist/bits/toolbar/toolbar.svelte.d.ts +6 -1
  77. package/dist/bits/toolbar/toolbar.svelte.js +15 -5
  78. package/dist/bits/tooltip/tooltip.svelte.d.ts +3 -1
  79. package/dist/bits/tooltip/tooltip.svelte.js +6 -2
  80. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.d.ts +9 -0
  81. package/dist/bits/utilities/floating-layer/use-floating-layer.svelte.js +6 -3
  82. package/dist/bits/utilities/focus-scope/focus-scope-manager.d.ts +12 -0
  83. package/dist/bits/utilities/focus-scope/focus-scope-manager.js +40 -0
  84. package/dist/bits/utilities/focus-scope/focus-scope.svelte +6 -8
  85. package/dist/bits/utilities/focus-scope/focus-scope.svelte.d.ts +1 -0
  86. package/dist/bits/utilities/focus-scope/focus-scope.svelte.js +204 -0
  87. package/dist/bits/utilities/focus-scope/types.d.ts +2 -6
  88. package/dist/bits/utilities/popper-layer/popper-layer-inner.svelte +2 -2
  89. package/dist/internal/focus.js +1 -1
  90. package/dist/internal/should-enable-focus-trap.d.ts +5 -0
  91. package/dist/internal/should-enable-focus-trap.js +5 -0
  92. package/dist/internal/types.d.ts +2 -1
  93. package/package.json +2 -2
  94. package/dist/bits/utilities/focus-scope/focus-scope-stack.svelte.d.ts +0 -14
  95. package/dist/bits/utilities/focus-scope/focus-scope-stack.svelte.js +0 -50
  96. package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.d.ts +0 -49
  97. package/dist/bits/utilities/focus-scope/use-focus-scope.svelte.js +0 -218
  98. package/dist/internal/should-trap-focus.d.ts +0 -6
  99. package/dist/internal/should-trap-focus.js +0 -5
@@ -1,218 +0,0 @@
1
- import { afterSleep, afterTick, DOMContext, executeCallbacks, } from "svelte-toolbelt";
2
- import { Context, watch } from "runed";
3
- import { on } from "svelte/events";
4
- import { createFocusScopeAPI, createFocusScopeStack, removeLinks, } from "./focus-scope-stack.svelte.js";
5
- import { focus, focusFirst, getTabbableCandidates, getTabbableEdges } from "../../../internal/focus.js";
6
- import { CustomEventDispatcher } from "../../../internal/events.js";
7
- import { isHTMLElement } from "../../../internal/is.js";
8
- import { kbd } from "../../../internal/kbd.js";
9
- import { isTabbable } from "tabbable";
10
- const AutoFocusOnMountEvent = new CustomEventDispatcher("focusScope.autoFocusOnMount", {
11
- bubbles: false,
12
- cancelable: true,
13
- });
14
- const AutoFocusOnDestroyEvent = new CustomEventDispatcher("focusScope.autoFocusOnDestroy", {
15
- bubbles: false,
16
- cancelable: true,
17
- });
18
- export const FocusScopeContext = new Context("FocusScope");
19
- export function useFocusScope({ id, loop, enabled, onOpenAutoFocus, onCloseAutoFocus, forceMount, ref, }) {
20
- const focusScopeStack = createFocusScopeStack();
21
- const focusScope = createFocusScopeAPI();
22
- const ctx = FocusScopeContext.getOr({ ignoreCloseAutoFocus: false });
23
- let lastFocusedElement = null;
24
- const domContext = new DOMContext(ref);
25
- function manageFocus(event) {
26
- if (focusScope.paused || !ref.current || focusScope.isHandlingFocus)
27
- return;
28
- focusScope.isHandlingFocus = true;
29
- try {
30
- const target = event.target;
31
- if (!isHTMLElement(target))
32
- return;
33
- const isWithinActiveScope = ref.current.contains(target);
34
- if (event.type === "focusin") {
35
- if (isWithinActiveScope) {
36
- lastFocusedElement = target;
37
- }
38
- else {
39
- if (ctx.ignoreCloseAutoFocus)
40
- return;
41
- focus(lastFocusedElement, { select: true });
42
- }
43
- }
44
- else if (event.type === "focusout") {
45
- if (!isWithinActiveScope && !ctx.ignoreCloseAutoFocus) {
46
- focus(lastFocusedElement, { select: true });
47
- }
48
- }
49
- }
50
- finally {
51
- focusScope.isHandlingFocus = false;
52
- }
53
- }
54
- /**
55
- * Handles DOM mutations within the container. Specifically checks if the
56
- * last known focused element inside the container has been removed. If so,
57
- * and focus has escaped the container (likely moved to document.body),
58
- * it refocuses the container itself to maintain the trap.
59
- */
60
- function handleMutations(mutations) {
61
- // if there's no record of a last focused el, or container isn't mounted, bail
62
- if (!lastFocusedElement || !ref.current)
63
- return;
64
- // track if the last focused element was removed
65
- let elementWasRemoved = false;
66
- for (const mutation of mutations) {
67
- // we only care about mutations where nodes were removed
68
- if (mutation.type === "childList" && mutation.removedNodes.length > 0) {
69
- // check if any removed nodes are the last focused element or contain it
70
- for (const removedNode of mutation.removedNodes) {
71
- if (removedNode === lastFocusedElement) {
72
- elementWasRemoved = true;
73
- // found it directly
74
- break;
75
- }
76
- // contains() only works on elements, so we need to check nodeType
77
- if (removedNode.nodeType === Node.ELEMENT_NODE &&
78
- removedNode.contains(lastFocusedElement)) {
79
- elementWasRemoved = true;
80
- // descendant found,
81
- break;
82
- }
83
- }
84
- }
85
- // if we've confirmed removal in any mutation, bail
86
- if (elementWasRemoved)
87
- break;
88
- }
89
- /**
90
- * If the element was removed and focus is now outside the container,
91
- * (e.g., browser moved it to body), refocus the container.
92
- */
93
- if (elementWasRemoved &&
94
- ref.current &&
95
- !ref.current.contains(domContext.getActiveElement())) {
96
- focus(ref.current);
97
- }
98
- }
99
- watch([() => ref.current, () => enabled.current], ([container, enabled]) => {
100
- if (!container || !enabled)
101
- return;
102
- const removeEvents = executeCallbacks(on(domContext.getDocument(), "focusin", manageFocus), on(domContext.getDocument(), "focusout", manageFocus));
103
- const mutationObserver = new MutationObserver(handleMutations);
104
- mutationObserver.observe(container, {
105
- childList: true,
106
- subtree: true,
107
- attributes: false,
108
- });
109
- return () => {
110
- removeEvents();
111
- mutationObserver.disconnect();
112
- };
113
- });
114
- watch([() => forceMount.current, () => ref.current], ([forceMount, container]) => {
115
- if (forceMount)
116
- return;
117
- const prevFocusedElement = domContext.getActiveElement();
118
- handleOpen(container, prevFocusedElement);
119
- return () => {
120
- if (!container)
121
- return;
122
- handleClose(prevFocusedElement);
123
- };
124
- });
125
- watch([() => forceMount.current, () => ref.current, () => enabled.current], ([forceMount, container]) => {
126
- if (!forceMount)
127
- return;
128
- const prevFocusedElement = domContext.getActiveElement();
129
- handleOpen(container, prevFocusedElement);
130
- return () => {
131
- if (!container)
132
- return;
133
- handleClose(prevFocusedElement);
134
- };
135
- });
136
- function handleOpen(container, prevFocusedElement) {
137
- if (!container)
138
- container = domContext.getElementById(id.current);
139
- if (!container || !enabled.current)
140
- return;
141
- focusScopeStack.add(focusScope);
142
- const hasFocusedCandidate = container.contains(prevFocusedElement);
143
- if (!hasFocusedCandidate) {
144
- const mountEvent = AutoFocusOnMountEvent.createEvent();
145
- onOpenAutoFocus.current(mountEvent);
146
- if (!mountEvent.defaultPrevented) {
147
- afterTick(() => {
148
- if (!container)
149
- return;
150
- const result = focusFirst(removeLinks(getTabbableCandidates(container)), {
151
- select: true,
152
- }, () => domContext.getActiveElement());
153
- if (!result)
154
- focus(container);
155
- });
156
- }
157
- }
158
- }
159
- function handleClose(prevFocusedElement) {
160
- const destroyEvent = AutoFocusOnDestroyEvent.createEvent();
161
- onCloseAutoFocus.current?.(destroyEvent);
162
- const shouldIgnore = ctx.ignoreCloseAutoFocus;
163
- afterSleep(0, () => {
164
- if (!destroyEvent.defaultPrevented && prevFocusedElement && !shouldIgnore) {
165
- focus(isTabbable(prevFocusedElement)
166
- ? prevFocusedElement
167
- : domContext.getDocument().body, {
168
- select: true,
169
- });
170
- }
171
- focusScopeStack.remove(focusScope);
172
- });
173
- }
174
- function handleKeydown(e) {
175
- if (!enabled.current)
176
- return;
177
- if (!loop.current && !enabled.current)
178
- return;
179
- if (focusScope.paused)
180
- return;
181
- const isTabKey = e.key === kbd.TAB && !e.ctrlKey && !e.altKey && !e.metaKey;
182
- const focusedElement = domContext.getActiveElement();
183
- if (!(isTabKey && focusedElement))
184
- return;
185
- const container = ref.current;
186
- if (!container)
187
- return;
188
- const [first, last] = getTabbableEdges(container);
189
- const hasTabbableElementsInside = first && last;
190
- if (!hasTabbableElementsInside) {
191
- if (focusedElement === container) {
192
- e.preventDefault();
193
- }
194
- }
195
- else {
196
- if (!e.shiftKey && focusedElement === last) {
197
- e.preventDefault();
198
- if (loop.current)
199
- focus(first, { select: true });
200
- }
201
- else if (e.shiftKey && focusedElement === first) {
202
- e.preventDefault();
203
- if (loop.current)
204
- focus(last, { select: true });
205
- }
206
- }
207
- }
208
- const props = $derived.by(() => ({
209
- id: id.current,
210
- tabindex: -1,
211
- onkeydown: handleKeydown,
212
- }));
213
- return {
214
- get props() {
215
- return props;
216
- },
217
- };
218
- }
@@ -1,6 +0,0 @@
1
- export declare function shouldTrapFocus({ forceMount, present, trapFocus, open, }: {
2
- forceMount: boolean;
3
- present: boolean;
4
- trapFocus: boolean;
5
- open: boolean;
6
- }): boolean;
@@ -1,5 +0,0 @@
1
- export function shouldTrapFocus({ forceMount, present, trapFocus, open, }) {
2
- if (forceMount)
3
- return open && trapFocus;
4
- return present && trapFocus && open;
5
- }