@pzerelles/headlessui-svelte 2.1.2-next.29 → 2.1.2-next.30
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/button/Button.svelte +54 -84
- package/dist/checkbox/Checkbox.svelte +120 -173
- package/dist/checkbox/Checkbox.svelte.d.ts +1 -1
- package/dist/close-button/CloseButton.svelte +6 -12
- package/dist/combobox/Combobox.svelte +3 -50
- package/dist/data-interactive/DataInteractive.svelte +29 -55
- package/dist/description/Description.svelte +21 -31
- package/dist/dialog/Dialog.svelte +228 -320
- package/dist/dialog/DialogBackdrop.svelte +12 -29
- package/dist/dialog/DialogPanel.svelte +25 -48
- package/dist/dialog/DialogTitle.svelte +23 -38
- package/dist/field/Field.svelte +25 -47
- package/dist/fieldset/Fieldset.svelte +29 -50
- package/dist/focus-trap/FocusTrap.svelte +283 -419
- package/dist/input/Input.svelte +53 -84
- package/dist/internal/FloatingProvider.svelte +9 -14
- package/dist/internal/FocusSentinel.svelte +8 -16
- package/dist/internal/ForcePortalRoot.svelte +3 -7
- package/dist/internal/FormFields.svelte +34 -47
- package/dist/internal/FormFieldsProvider.svelte +5 -9
- package/dist/internal/FormResolver.svelte +15 -20
- package/dist/internal/Hidden.svelte +29 -50
- package/dist/internal/MainTreeProvider.svelte +36 -89
- package/dist/internal/Portal.svelte +14 -18
- package/dist/label/Label.svelte +58 -93
- package/dist/legend/Legend.svelte +3 -12
- package/dist/listbox/Listbox.svelte +387 -525
- package/dist/listbox/Listbox.svelte.d.ts +1 -1
- package/dist/listbox/ListboxButton.svelte +127 -173
- package/dist/listbox/ListboxOption.svelte +129 -170
- package/dist/listbox/ListboxOptions.svelte +304 -400
- package/dist/listbox/ListboxSelectedOption.svelte +15 -38
- package/dist/menu/Menu.svelte +51 -78
- package/dist/menu/MenuButton.svelte +117 -157
- package/dist/menu/MenuHeading.svelte +14 -32
- package/dist/menu/MenuItem.svelte +107 -142
- package/dist/menu/MenuItems.svelte +229 -301
- package/dist/menu/MenuSection.svelte +9 -24
- package/dist/menu/MenuSeparator.svelte +4 -17
- package/dist/popover/Popover.svelte +150 -216
- package/dist/popover/PopoverBackdrop.svelte +41 -67
- package/dist/popover/PopoverButton.svelte +212 -292
- package/dist/popover/PopoverGroup.svelte +35 -62
- package/dist/popover/PopoverPanel.svelte +229 -311
- package/dist/portal/InternalPortal.svelte +85 -141
- package/dist/portal/Portal.svelte +2 -5
- package/dist/portal/PortalGroup.svelte +9 -30
- package/dist/select/Select.svelte +68 -98
- package/dist/switch/Switch.svelte +132 -179
- package/dist/switch/SwitchGroup.svelte +31 -44
- package/dist/tabs/Tab.svelte +142 -194
- package/dist/tabs/TabGroup.svelte +56 -86
- package/dist/tabs/TabGroup.svelte.d.ts +1 -1
- package/dist/tabs/TabList.svelte +11 -31
- package/dist/tabs/TabPanel.svelte +42 -67
- package/dist/tabs/TabPanels.svelte +7 -18
- package/dist/textarea/Textarea.svelte +53 -84
- package/dist/transition/InternalTransitionChild.svelte +170 -259
- package/dist/transition/Transition.svelte +66 -96
- package/dist/transition/TransitionChild.svelte +11 -31
- package/dist/utils/DisabledProvider.svelte +3 -7
- package/dist/utils/ElementOrComponent.svelte +23 -43
- package/dist/utils/Generic.svelte +16 -27
- package/dist/utils/StableCollection.svelte +36 -54
- package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +12 -27
- package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +44 -88
- package/package.json +4 -4
package/dist/tabs/Tab.svelte
CHANGED
|
@@ -1,207 +1,155 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
1
|
+
<script lang="ts" module>const DEFAULT_TAB_TAG = "button";
|
|
2
|
+
</script>
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TAB_TAG">import { useId } from "../hooks/use-id.js";
|
|
5
|
+
import { useStableCollectionIndex } from "../utils/StableCollection.svelte";
|
|
6
|
+
import { Focus, focusIn, FocusResult } from "../utils/focus-management.js";
|
|
7
|
+
import { getOwnerDocument } from "../utils/owner.js";
|
|
8
|
+
import { match } from "../utils/match.js";
|
|
9
|
+
import { microTask } from "../utils/microTask.js";
|
|
10
|
+
import { useActivePress } from "../hooks/use-active-press.svelte.js";
|
|
11
|
+
import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
|
|
12
|
+
import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js";
|
|
13
|
+
import { onMount } from "svelte";
|
|
14
|
+
import { useHover } from "../hooks/use-hover.svelte.js";
|
|
15
|
+
import { mergeProps } from "../utils/render.js";
|
|
16
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
17
|
+
import { useTabs } from "./context.svelte.js";
|
|
18
|
+
const internalId = useId();
|
|
19
|
+
let {
|
|
20
|
+
ref = $bindable(),
|
|
21
|
+
id = `headlessui-tabs-tab-${internalId}`,
|
|
22
|
+
disabled = false,
|
|
23
|
+
autofocus = false,
|
|
24
|
+
...theirProps
|
|
25
|
+
} = $props();
|
|
26
|
+
const context = useTabs("Tab");
|
|
27
|
+
const { orientation, activation, selectedIndex, tabs, panels, registerTab, change } = $derived(context);
|
|
28
|
+
const tabRef = $derived({ current: ref });
|
|
29
|
+
onMount(() => registerTab(tabRef));
|
|
30
|
+
const mySSRIndex = useStableCollectionIndex("tabs");
|
|
31
|
+
const myIndex = $derived.by(() => {
|
|
32
|
+
const index = tabs.findIndex((tab) => tab === tabRef);
|
|
33
|
+
return index === -1 ? mySSRIndex : index;
|
|
34
|
+
});
|
|
35
|
+
const selected = $derived(myIndex === selectedIndex);
|
|
36
|
+
const activateUsing = $derived((cb) => {
|
|
37
|
+
let result = cb();
|
|
38
|
+
if (result === FocusResult.Success && activation === "auto") {
|
|
39
|
+
let newTab = getOwnerDocument(ref)?.activeElement;
|
|
40
|
+
let idx = context.tabs.findIndex((tab) => tab.current === newTab);
|
|
41
|
+
if (idx !== -1) change(idx);
|
|
12
42
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
43
|
+
return result;
|
|
44
|
+
});
|
|
45
|
+
const handleKeyDown = (event) => {
|
|
46
|
+
let list = tabs.map((tab) => tab.current).filter(Boolean);
|
|
47
|
+
if (event.key === " " || event.key === "Enter") {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
event.stopPropagation();
|
|
50
|
+
change(myIndex);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
switch (event.key) {
|
|
54
|
+
case "Home":
|
|
55
|
+
case "PageUp":
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
event.stopPropagation();
|
|
58
|
+
return activateUsing(() => focusIn(list, Focus.First));
|
|
59
|
+
case "End":
|
|
60
|
+
case "PageDown":
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
event.stopPropagation();
|
|
63
|
+
return activateUsing(() => focusIn(list, Focus.Last));
|
|
64
|
+
}
|
|
65
|
+
let result = activateUsing(() => {
|
|
66
|
+
return match(orientation, {
|
|
67
|
+
vertical() {
|
|
68
|
+
if (event.key === "ArrowUp") return focusIn(list, Focus.Previous | Focus.WrapAround);
|
|
69
|
+
if (event.key === "ArrowDown") return focusIn(list, Focus.Next | Focus.WrapAround);
|
|
70
|
+
return FocusResult.Error;
|
|
71
|
+
},
|
|
72
|
+
horizontal() {
|
|
73
|
+
if (event.key === "ArrowLeft") return focusIn(list, Focus.Previous | Focus.WrapAround);
|
|
74
|
+
if (event.key === "ArrowRight") return focusIn(list, Focus.Next | Focus.WrapAround);
|
|
75
|
+
return FocusResult.Error;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
if (result === FocusResult.Success) {
|
|
80
|
+
return event.preventDefault();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
let ready = $state(false);
|
|
84
|
+
const handleSelection = () => {
|
|
85
|
+
if (ready) return;
|
|
86
|
+
ready = true;
|
|
87
|
+
ref?.focus({ preventScroll: true });
|
|
88
|
+
change(myIndex);
|
|
89
|
+
microTask(() => {
|
|
90
|
+
ready = false;
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
const handleMouseDown = (event) => {
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
};
|
|
96
|
+
const { isHovered: hover, hoverProps } = $derived(
|
|
97
|
+
useHover({
|
|
98
|
+
get disabled() {
|
|
99
|
+
return disabled;
|
|
23
100
|
}
|
|
24
|
-
>
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TAB_TAG">
|
|
28
|
-
import { useId } from "../hooks/use-id.js"
|
|
29
|
-
import { useStableCollectionIndex } from "../utils/StableCollection.svelte"
|
|
30
|
-
import { Focus, focusIn, FocusResult } from "../utils/focus-management.js"
|
|
31
|
-
import { getOwnerDocument } from "../utils/owner.js"
|
|
32
|
-
import { match } from "../utils/match.js"
|
|
33
|
-
import { microTask } from "../utils/microTask.js"
|
|
34
|
-
import { useActivePress } from "../hooks/use-active-press.svelte.js"
|
|
35
|
-
import { useFocusRing } from "../hooks/use-focus-ring.svelte.js"
|
|
36
|
-
import { useResolveButtonType } from "../hooks/use-resolve-button-type.svelte.js"
|
|
37
|
-
import type { MutableRefObject } from "../utils/ref.svelte.js"
|
|
38
|
-
import { onMount } from "svelte"
|
|
39
|
-
import { useHover } from "../hooks/use-hover.svelte.js"
|
|
40
|
-
import { mergeProps } from "../utils/render.js"
|
|
41
|
-
import ElementOrComponent from "../utils/ElementOrComponent.svelte"
|
|
42
|
-
import { useTabs } from "./context.svelte.js"
|
|
43
|
-
|
|
44
|
-
const internalId = useId()
|
|
45
|
-
let {
|
|
46
|
-
ref = $bindable(),
|
|
47
|
-
id = `headlessui-tabs-tab-${internalId}`,
|
|
48
|
-
disabled = false,
|
|
49
|
-
autofocus = false,
|
|
50
|
-
...theirProps
|
|
51
|
-
}: { as?: TTag } & TabProps<TTag> = $props()
|
|
52
|
-
|
|
53
|
-
const context = useTabs("Tab")
|
|
54
|
-
const { orientation, activation, selectedIndex, tabs, panels, registerTab, change } = $derived(context)
|
|
55
|
-
|
|
56
|
-
const tabRef = $derived<MutableRefObject<HTMLElement | undefined>>({ current: ref })
|
|
57
|
-
|
|
58
|
-
onMount(() => registerTab(tabRef))
|
|
59
|
-
|
|
60
|
-
const mySSRIndex = useStableCollectionIndex("tabs")
|
|
61
|
-
|
|
62
|
-
const myIndex = $derived.by(() => {
|
|
63
|
-
const index = tabs.findIndex((tab) => tab === tabRef)
|
|
64
|
-
return index === -1 ? mySSRIndex : index
|
|
65
101
|
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
let newTab = getOwnerDocument(ref)?.activeElement
|
|
72
|
-
let idx = context.tabs.findIndex((tab) => tab.current === newTab)
|
|
73
|
-
if (idx !== -1) change(idx)
|
|
102
|
+
);
|
|
103
|
+
const { pressed: active, pressProps } = $derived(
|
|
104
|
+
useActivePress({
|
|
105
|
+
get disabled() {
|
|
106
|
+
return disabled;
|
|
74
107
|
}
|
|
75
|
-
return result
|
|
76
108
|
})
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
event.preventDefault()
|
|
83
|
-
event.stopPropagation()
|
|
84
|
-
|
|
85
|
-
change(myIndex)
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
switch (event.key) {
|
|
90
|
-
case "Home":
|
|
91
|
-
case "PageUp":
|
|
92
|
-
event.preventDefault()
|
|
93
|
-
event.stopPropagation()
|
|
94
|
-
|
|
95
|
-
return activateUsing(() => focusIn(list, Focus.First))
|
|
96
|
-
|
|
97
|
-
case "End":
|
|
98
|
-
case "PageDown":
|
|
99
|
-
event.preventDefault()
|
|
100
|
-
event.stopPropagation()
|
|
101
|
-
|
|
102
|
-
return activateUsing(() => focusIn(list, Focus.Last))
|
|
109
|
+
);
|
|
110
|
+
const { isFocusVisible: focus, focusProps } = $derived(
|
|
111
|
+
useFocusRing({
|
|
112
|
+
get autofocus() {
|
|
113
|
+
return autofocus;
|
|
103
114
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (result === FocusResult.Success) {
|
|
121
|
-
return event.preventDefault()
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
let ready = $state(false)
|
|
126
|
-
const handleSelection = () => {
|
|
127
|
-
if (ready) return
|
|
128
|
-
ready = true
|
|
129
|
-
|
|
130
|
-
ref?.focus({ preventScroll: true })
|
|
131
|
-
change(myIndex)
|
|
132
|
-
|
|
133
|
-
microTask(() => {
|
|
134
|
-
ready = false
|
|
135
|
-
})
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// This is important because we want to only focus the tab when it gets focus
|
|
139
|
-
// OR it finished the click event (mouseup). However, if you perform a `click`,
|
|
140
|
-
// then you will first get the `focus` and then get the `click` event.
|
|
141
|
-
const handleMouseDown = (event: MouseEvent) => {
|
|
142
|
-
event.preventDefault()
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
const slot = $derived({
|
|
118
|
+
selected,
|
|
119
|
+
hover,
|
|
120
|
+
active,
|
|
121
|
+
focus,
|
|
122
|
+
autofocus,
|
|
123
|
+
disabled
|
|
124
|
+
});
|
|
125
|
+
const resolvedType = useResolveButtonType({
|
|
126
|
+
get props() {
|
|
127
|
+
return { type: theirProps.type, as: theirProps.as };
|
|
128
|
+
},
|
|
129
|
+
get ref() {
|
|
130
|
+
return tabRef;
|
|
143
131
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const { isFocusVisible: focus, focusProps } = $derived(
|
|
160
|
-
useFocusRing({
|
|
161
|
-
get autofocus() {
|
|
162
|
-
return autofocus
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
const slot = $derived({
|
|
168
|
-
selected,
|
|
169
|
-
hover,
|
|
170
|
-
active,
|
|
171
|
-
focus,
|
|
172
|
-
autofocus,
|
|
173
|
-
disabled,
|
|
174
|
-
} satisfies TabRenderPropArg)
|
|
175
|
-
|
|
176
|
-
const resolvedType = useResolveButtonType({
|
|
177
|
-
get props() {
|
|
178
|
-
return { type: theirProps.type, as: theirProps.as }
|
|
179
|
-
},
|
|
180
|
-
get ref() {
|
|
181
|
-
return tabRef
|
|
132
|
+
});
|
|
133
|
+
const ourProps = $derived(
|
|
134
|
+
mergeProps(
|
|
135
|
+
{
|
|
136
|
+
onkeydown: handleKeyDown,
|
|
137
|
+
onmousedown: handleMouseDown,
|
|
138
|
+
onclick: handleSelection,
|
|
139
|
+
id,
|
|
140
|
+
role: "tab",
|
|
141
|
+
type: resolvedType.type,
|
|
142
|
+
"aria-controls": panels[myIndex]?.current?.id,
|
|
143
|
+
"aria-selected": selected,
|
|
144
|
+
tabIndex: selected ? 0 : -1,
|
|
145
|
+
disabled: disabled || void 0,
|
|
146
|
+
autofocus
|
|
182
147
|
},
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
mergeProps(
|
|
187
|
-
{
|
|
188
|
-
onkeydown: handleKeyDown,
|
|
189
|
-
onmousedown: handleMouseDown,
|
|
190
|
-
onclick: handleSelection,
|
|
191
|
-
id,
|
|
192
|
-
role: "tab",
|
|
193
|
-
type: resolvedType.type,
|
|
194
|
-
"aria-controls": panels[myIndex]?.current?.id,
|
|
195
|
-
"aria-selected": selected,
|
|
196
|
-
tabIndex: selected ? 0 : -1,
|
|
197
|
-
disabled: disabled || undefined,
|
|
198
|
-
autofocus,
|
|
199
|
-
},
|
|
200
|
-
focusProps,
|
|
201
|
-
hoverProps,
|
|
202
|
-
pressProps
|
|
203
|
-
)
|
|
148
|
+
focusProps,
|
|
149
|
+
hoverProps,
|
|
150
|
+
pressProps
|
|
204
151
|
)
|
|
152
|
+
);
|
|
205
153
|
</script>
|
|
206
154
|
|
|
207
155
|
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_TAB_TAG} name="Tab" bind:ref />
|
|
@@ -1,92 +1,62 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import FocusSentinel from "../internal/FocusSentinel.svelte"
|
|
5
|
-
|
|
6
|
-
const DEFAULT_TABS_TAG = "div" as const
|
|
7
|
-
type TabsRenderPropArg = {
|
|
8
|
-
selectedIndex: number
|
|
9
|
-
}
|
|
10
|
-
type TabsPropsWeControl = never
|
|
11
|
-
|
|
12
|
-
export type TabGroupProps<TTag extends ElementType = typeof DEFAULT_TABS_TAG> = Props<
|
|
13
|
-
TTag,
|
|
14
|
-
TabsRenderPropArg,
|
|
15
|
-
TabsPropsWeControl,
|
|
16
|
-
{
|
|
17
|
-
defaultIndex?: number
|
|
18
|
-
onchange?: (index: number) => void
|
|
19
|
-
selectedIndex?: number
|
|
20
|
-
vertical?: boolean
|
|
21
|
-
manual?: boolean
|
|
22
|
-
}
|
|
23
|
-
>
|
|
1
|
+
<script lang="ts" module>import { sortByDomNode } from "../utils/focus-management.js";
|
|
2
|
+
import FocusSentinel from "../internal/FocusSentinel.svelte";
|
|
3
|
+
const DEFAULT_TABS_TAG = "div";
|
|
24
4
|
</script>
|
|
25
5
|
|
|
26
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TABS_TAG">
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (realSelectedIndex !== index) {
|
|
56
|
-
onchange?.(index)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!isControlled) {
|
|
60
|
-
_state.selectedIndex = index
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
})
|
|
64
|
-
const isControlled = $derived(_state.info.isControlled)
|
|
65
|
-
const realSelectedIndex = $derived(isControlled ? selectedIndex! : _state.selectedIndex)
|
|
66
|
-
|
|
67
|
-
const slot = $derived({
|
|
68
|
-
selectedIndex: _state.selectedIndex,
|
|
69
|
-
} satisfies TabsRenderPropArg)
|
|
70
|
-
const stableTabs = $derived(_state.tabs)
|
|
71
|
-
|
|
72
|
-
$effect(() => {
|
|
73
|
-
const newSelectedIndex = selectedIndex ?? defaultIndex
|
|
74
|
-
untrack(() => (_state.selectedIndex = newSelectedIndex))
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
$effect(() => {
|
|
78
|
-
if (realSelectedIndex === undefined) return
|
|
79
|
-
if (_state.tabs.length <= 0) return
|
|
80
|
-
|
|
81
|
-
// TODO: Figure out a way to detect this without the slow sort on every render. Might be fine
|
|
82
|
-
// unless you have a lot of tabs.
|
|
83
|
-
let sorted = sortByDomNode(_state.tabs, (tab) => tab.current ?? null)
|
|
84
|
-
let didOrderChange = sorted.some((tab, i) => _state.tabs[i] !== tab)
|
|
85
|
-
|
|
86
|
-
if (didOrderChange) {
|
|
87
|
-
_state.change(sorted.findIndex((tab) => tab === _state.tabs[realSelectedIndex]))
|
|
6
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TABS_TAG">import StableCollection from "../utils/StableCollection.svelte";
|
|
7
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
8
|
+
import { createTabContext } from "./context.svelte.js";
|
|
9
|
+
import { untrack } from "svelte";
|
|
10
|
+
let {
|
|
11
|
+
ref = $bindable(),
|
|
12
|
+
defaultIndex = 0,
|
|
13
|
+
vertical = false,
|
|
14
|
+
manual = false,
|
|
15
|
+
onchange,
|
|
16
|
+
selectedIndex = void 0,
|
|
17
|
+
...theirProps
|
|
18
|
+
} = $props();
|
|
19
|
+
const _state = createTabContext({
|
|
20
|
+
get vertical() {
|
|
21
|
+
return vertical;
|
|
22
|
+
},
|
|
23
|
+
get manual() {
|
|
24
|
+
return manual;
|
|
25
|
+
},
|
|
26
|
+
get selectedIndex() {
|
|
27
|
+
return selectedIndex;
|
|
28
|
+
},
|
|
29
|
+
get defaultIndex() {
|
|
30
|
+
return defaultIndex;
|
|
31
|
+
},
|
|
32
|
+
change: (index) => {
|
|
33
|
+
if (realSelectedIndex !== index) {
|
|
34
|
+
onchange?.(index);
|
|
88
35
|
}
|
|
89
|
-
|
|
36
|
+
if (!isControlled) {
|
|
37
|
+
_state.selectedIndex = index;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const isControlled = $derived(_state.info.isControlled);
|
|
42
|
+
const realSelectedIndex = $derived(isControlled ? selectedIndex : _state.selectedIndex);
|
|
43
|
+
const slot = $derived({
|
|
44
|
+
selectedIndex: _state.selectedIndex
|
|
45
|
+
});
|
|
46
|
+
const stableTabs = $derived(_state.tabs);
|
|
47
|
+
$effect(() => {
|
|
48
|
+
const newSelectedIndex = selectedIndex ?? defaultIndex;
|
|
49
|
+
untrack(() => _state.selectedIndex = newSelectedIndex);
|
|
50
|
+
});
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (realSelectedIndex === void 0) return;
|
|
53
|
+
if (_state.tabs.length <= 0) return;
|
|
54
|
+
let sorted = sortByDomNode(_state.tabs, (tab) => tab.current ?? null);
|
|
55
|
+
let didOrderChange = sorted.some((tab, i) => _state.tabs[i] !== tab);
|
|
56
|
+
if (didOrderChange) {
|
|
57
|
+
_state.change(sorted.findIndex((tab) => tab === _state.tabs[realSelectedIndex]));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
90
60
|
</script>
|
|
91
61
|
|
|
92
62
|
<StableCollection>
|
|
@@ -14,7 +14,7 @@ export type TabGroupProps<TTag extends ElementType = typeof DEFAULT_TABS_TAG> =
|
|
|
14
14
|
declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_TABS_TAG> {
|
|
15
15
|
props(): {
|
|
16
16
|
as?: TTag | undefined;
|
|
17
|
-
} & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("slot" | "as" | "children" | "class" | "ref") | "onchange" | "
|
|
17
|
+
} & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("slot" | "as" | "children" | "class" | "ref") | "onchange" | "manual" | "vertical" | "selectedIndex" | "defaultIndex"> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
|
|
18
18
|
children?: import("svelte").Snippet<[{
|
|
19
19
|
slot: TabsRenderPropArg;
|
|
20
20
|
props: Record<string, any>;
|
package/dist/tabs/TabList.svelte
CHANGED
|
@@ -1,36 +1,16 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { ElementType, Props } from "../utils/types.js"
|
|
3
|
-
|
|
4
|
-
const DEFAULT_LIST_TAG = "div" as const
|
|
5
|
-
type ListRenderPropArg = {
|
|
6
|
-
selectedIndex: number
|
|
7
|
-
}
|
|
8
|
-
type ListPropsWeControl = "aria-orientation" | "role"
|
|
9
|
-
|
|
10
|
-
export type TabListProps<TTag extends ElementType = typeof DEFAULT_LIST_TAG> = Props<
|
|
11
|
-
TTag,
|
|
12
|
-
ListRenderPropArg,
|
|
13
|
-
ListPropsWeControl,
|
|
14
|
-
{
|
|
15
|
-
//
|
|
16
|
-
}
|
|
17
|
-
>
|
|
1
|
+
<script lang="ts" module>const DEFAULT_LIST_TAG = "div";
|
|
18
2
|
</script>
|
|
19
3
|
|
|
20
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_LIST_TAG">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const ourProps = $derived({
|
|
31
|
-
role: "tablist",
|
|
32
|
-
"aria-orientation": orientation,
|
|
33
|
-
})
|
|
4
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_LIST_TAG">import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
5
|
+
import { useTabs } from "./context.svelte.js";
|
|
6
|
+
const context = useTabs("TabList");
|
|
7
|
+
const { orientation, selectedIndex } = $derived(context);
|
|
8
|
+
const slot = $derived({ selectedIndex });
|
|
9
|
+
let { ref = $bindable(), ...theirProps } = $props();
|
|
10
|
+
const ourProps = $derived({
|
|
11
|
+
role: "tablist",
|
|
12
|
+
"aria-orientation": orientation
|
|
13
|
+
});
|
|
34
14
|
</script>
|
|
35
15
|
|
|
36
16
|
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_LIST_TAG} name="TabList" bind:ref />
|
|
@@ -1,73 +1,48 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const DEFAULT_PANEL_TAG = "div" as const
|
|
5
|
-
type PanelRenderPropArg = {
|
|
6
|
-
selected: boolean
|
|
7
|
-
focus: boolean
|
|
8
|
-
}
|
|
9
|
-
type PanelPropsWeControl = "role" | "aria-labelledby"
|
|
10
|
-
const PanelRenderFeatures = RenderFeatures.RenderStrategy | RenderFeatures.Static
|
|
11
|
-
|
|
12
|
-
export type TabPanelProps<TTag extends ElementType = typeof DEFAULT_PANEL_TAG> = Props<
|
|
13
|
-
TTag,
|
|
14
|
-
PanelRenderPropArg,
|
|
15
|
-
PanelPropsWeControl,
|
|
16
|
-
PropsForFeatures<typeof PanelRenderFeatures> & { id?: string; tabIndex?: number }
|
|
17
|
-
>
|
|
1
|
+
<script lang="ts" module>const DEFAULT_PANEL_TAG = "div";
|
|
2
|
+
const PanelRenderFeatures = RenderFeatures.RenderStrategy | RenderFeatures.Static;
|
|
18
3
|
</script>
|
|
19
4
|
|
|
20
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_PANEL_TAG">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const ourProps = $derived(
|
|
61
|
-
mergeProps(
|
|
62
|
-
{
|
|
63
|
-
id,
|
|
64
|
-
role: "tabpanel",
|
|
65
|
-
"aria-labelledby": tabs[myIndex]?.current?.id,
|
|
66
|
-
tabIndex: selected ? 0 : -1,
|
|
67
|
-
},
|
|
68
|
-
focusProps
|
|
69
|
-
)
|
|
5
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_PANEL_TAG">import { useId } from "../hooks/use-id.js";
|
|
6
|
+
import { mergeProps, RenderFeatures } from "../utils/render.js";
|
|
7
|
+
import { useStableCollectionIndex } from "../utils/StableCollection.svelte";
|
|
8
|
+
import { useFocusRing } from "../hooks/use-focus-ring.svelte.js";
|
|
9
|
+
import Hidden from "../internal/Hidden.svelte";
|
|
10
|
+
import { onMount } from "svelte";
|
|
11
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
12
|
+
import { useTabs } from "./context.svelte.js";
|
|
13
|
+
const internalId = useId();
|
|
14
|
+
let {
|
|
15
|
+
ref = $bindable(),
|
|
16
|
+
id = `headlessui-tabs-panel-${internalId}`,
|
|
17
|
+
tabIndex = 0,
|
|
18
|
+
...theirProps
|
|
19
|
+
} = $props();
|
|
20
|
+
const context = useTabs("TabPanel");
|
|
21
|
+
const { selectedIndex, tabs, panels, registerPanel } = $derived(context);
|
|
22
|
+
const panelRef = $derived({ current: ref });
|
|
23
|
+
onMount(() => registerPanel(panelRef));
|
|
24
|
+
const mySSRIndex = useStableCollectionIndex("panels");
|
|
25
|
+
const myIndex = $derived.by(() => {
|
|
26
|
+
const index = tabs.findIndex((panel) => panel === panelRef);
|
|
27
|
+
return index === -1 ? mySSRIndex : index;
|
|
28
|
+
});
|
|
29
|
+
const selected = $derived(myIndex === selectedIndex);
|
|
30
|
+
const { isFocusVisible: focus, focusProps } = $derived(useFocusRing());
|
|
31
|
+
const slot = $derived({
|
|
32
|
+
selected,
|
|
33
|
+
focus
|
|
34
|
+
});
|
|
35
|
+
const ourProps = $derived(
|
|
36
|
+
mergeProps(
|
|
37
|
+
{
|
|
38
|
+
id,
|
|
39
|
+
role: "tabpanel",
|
|
40
|
+
"aria-labelledby": tabs[myIndex]?.current?.id,
|
|
41
|
+
tabIndex: selected ? 0 : -1
|
|
42
|
+
},
|
|
43
|
+
focusProps
|
|
70
44
|
)
|
|
45
|
+
);
|
|
71
46
|
</script>
|
|
72
47
|
|
|
73
48
|
{#if !selected && (theirProps.unmount ?? true) && !(theirProps.static ?? false)}
|