@pzerelles/headlessui-svelte 2.1.2-next.31 → 2.1.2-next.33
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 +84 -55
- package/dist/button/Button.svelte.d.ts +4 -32
- package/dist/checkbox/Checkbox.svelte +177 -121
- package/dist/checkbox/Checkbox.svelte.d.ts +14 -32
- package/dist/close-button/CloseButton.svelte +10 -7
- package/dist/close-button/CloseButton.svelte.d.ts +2 -44
- package/dist/data-interactive/DataInteractive.svelte +49 -37
- package/dist/data-interactive/DataInteractive.svelte.d.ts +7 -30
- package/dist/description/Description.svelte +35 -22
- package/dist/description/Description.svelte.d.ts +7 -28
- package/dist/dialog/Dialog.svelte +326 -232
- package/dist/dialog/Dialog.svelte.d.ts +4 -42
- package/dist/dialog/DialogBackdrop.svelte +33 -16
- package/dist/dialog/DialogBackdrop.svelte.d.ts +4 -29
- package/dist/dialog/DialogPanel.svelte +60 -29
- package/dist/dialog/DialogPanel.svelte.d.ts +4 -30
- package/dist/dialog/DialogTitle.svelte +51 -24
- package/dist/dialog/DialogTitle.svelte.d.ts +6 -27
- package/dist/field/Field.svelte +44 -28
- package/dist/field/Field.svelte.d.ts +4 -30
- package/dist/fieldset/Fieldset.svelte +48 -30
- package/dist/fieldset/Fieldset.svelte.d.ts +5 -31
- package/dist/focus-trap/FocusTrap.svelte +430 -298
- package/dist/focus-trap/FocusTrap.svelte.d.ts +5 -34
- package/dist/hooks/use-inert-others.svelte.js +10 -10
- package/dist/hooks/use-resolve-button-type.svelte.js +0 -1
- package/dist/input/Input.svelte +95 -54
- package/dist/input/Input.svelte.d.ts +13 -27
- package/dist/internal/FloatingProvider.svelte +14 -9
- package/dist/internal/FocusSentinel.svelte +49 -40
- package/dist/internal/ForcePortalRoot.svelte +7 -3
- package/dist/internal/FormFields.svelte +47 -34
- package/dist/internal/FormFieldsProvider.svelte +9 -5
- package/dist/internal/FormResolver.svelte +25 -16
- package/dist/internal/Hidden.svelte +45 -38
- package/dist/internal/Hidden.svelte.d.ts +4 -30
- package/dist/internal/MainTreeProvider.svelte +90 -37
- package/dist/internal/Portal.svelte +18 -14
- package/dist/label/Label.svelte +100 -59
- package/dist/label/Label.svelte.d.ts +7 -32
- package/dist/legend/Legend.svelte +27 -4
- package/dist/legend/Legend.svelte.d.ts +4 -3
- package/dist/listbox/Listbox.svelte +518 -391
- package/dist/listbox/Listbox.svelte.d.ts +11 -35
- package/dist/listbox/ListboxButton.svelte +175 -128
- package/dist/listbox/ListboxButton.svelte.d.ts +5 -32
- package/dist/listbox/ListboxOption.svelte +171 -130
- package/dist/listbox/ListboxOption.svelte.d.ts +12 -26
- package/dist/listbox/ListboxOptions.svelte +403 -305
- package/dist/listbox/ListboxOptions.svelte.d.ts +4 -38
- package/dist/listbox/ListboxSelectedOption.svelte +40 -19
- package/dist/listbox/ListboxSelectedOption.svelte.d.ts +8 -33
- package/dist/menu/Menu.svelte +76 -52
- package/dist/menu/Menu.svelte.d.ts +3 -31
- package/dist/menu/MenuButton.svelte +158 -118
- package/dist/menu/MenuButton.svelte.d.ts +4 -34
- package/dist/menu/MenuHeading.svelte +34 -15
- package/dist/menu/MenuHeading.svelte.d.ts +4 -31
- package/dist/menu/MenuItem.svelte +143 -108
- package/dist/menu/MenuItem.svelte.d.ts +5 -32
- package/dist/menu/MenuItems.svelte +301 -230
- package/dist/menu/MenuItems.svelte.d.ts +4 -38
- package/dist/menu/MenuSection.svelte +26 -10
- package/dist/menu/MenuSection.svelte.d.ts +5 -29
- package/dist/menu/MenuSeparator.svelte +20 -5
- package/dist/menu/MenuSeparator.svelte.d.ts +5 -28
- package/dist/popover/Popover.svelte +217 -151
- package/dist/popover/Popover.svelte.d.ts +4 -30
- package/dist/popover/PopoverBackdrop.svelte +71 -42
- package/dist/popover/PopoverBackdrop.svelte.d.ts +6 -34
- package/dist/popover/PopoverButton.svelte +302 -222
- package/dist/popover/PopoverButton.svelte.d.ts +6 -29
- package/dist/popover/PopoverGroup.svelte +64 -36
- package/dist/popover/PopoverGroup.svelte.d.ts +5 -28
- package/dist/popover/PopoverPanel.svelte +335 -248
- package/dist/popover/PopoverPanel.svelte.d.ts +5 -36
- package/dist/popover/index.d.ts +1 -1
- package/dist/portal/InternalPortal.svelte +143 -86
- package/dist/portal/InternalPortal.svelte.d.ts +4 -30
- package/dist/portal/Portal.svelte +8 -4
- package/dist/portal/Portal.svelte.d.ts +2 -18
- package/dist/portal/PortalGroup.svelte +23 -10
- package/dist/portal/PortalGroup.svelte.d.ts +3 -31
- package/dist/select/Select.svelte +100 -69
- package/dist/select/Select.svelte.d.ts +5 -32
- package/dist/switch/Switch.svelte +181 -133
- package/dist/switch/Switch.svelte.d.ts +5 -38
- package/dist/switch/SwitchGroup.svelte +45 -32
- package/dist/switch/SwitchGroup.svelte.d.ts +7 -28
- package/dist/tabs/Tab.svelte +195 -143
- package/dist/tabs/Tab.svelte.d.ts +4 -32
- package/dist/tabs/TabGroup.svelte +87 -57
- package/dist/tabs/TabGroup.svelte.d.ts +4 -34
- package/dist/tabs/TabList.svelte +31 -12
- package/dist/tabs/TabList.svelte.d.ts +5 -28
- package/dist/tabs/TabPanel.svelte +69 -44
- package/dist/tabs/TabPanel.svelte.d.ts +4 -34
- package/dist/tabs/TabPanels.svelte +19 -8
- package/dist/tabs/TabPanels.svelte.d.ts +5 -27
- package/dist/textarea/Textarea.svelte +87 -54
- package/dist/textarea/Textarea.svelte.d.ts +13 -27
- package/dist/transition/InternalTransitionChild.svelte +267 -171
- package/dist/transition/InternalTransitionChild.svelte.d.ts +3 -33
- package/dist/transition/Transition.svelte +88 -67
- package/dist/transition/Transition.svelte.d.ts +3 -36
- package/dist/transition/TransitionChild.svelte +31 -12
- package/dist/transition/TransitionChild.svelte.d.ts +8 -35
- package/dist/transition/context.svelte.js +7 -7
- package/dist/utils/DisabledProvider.svelte +7 -3
- package/dist/utils/ElementOrComponent.svelte +88 -24
- package/dist/utils/ElementOrComponent.svelte.d.ts +32 -27
- package/dist/utils/StableCollection.svelte +54 -36
- package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +27 -12
- package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +88 -44
- package/dist/utils/state.js +4 -4
- package/dist/utils/types.d.ts +14 -12
- package/package.json +12 -12
- package/dist/combobox/Combobox.svelte +0 -6
- package/dist/combobox/Combobox.svelte.d.ts +0 -50
- package/dist/utils/Generic.svelte +0 -46
- package/dist/utils/Generic.svelte.d.ts +0 -32
- package/dist/utils/alternative-types.d.ts +0 -20
- package/dist/utils/alternative-types.js +0 -1
package/dist/tabs/Tab.svelte
CHANGED
|
@@ -1,155 +1,207 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Props } from "../utils/types.js"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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);
|
|
42
|
-
}
|
|
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));
|
|
4
|
+
const DEFAULT_TAB_TAG = "button" as const
|
|
5
|
+
type TabRenderPropArg = {
|
|
6
|
+
hover: boolean
|
|
7
|
+
focus: boolean
|
|
8
|
+
active: boolean
|
|
9
|
+
autofocus: boolean
|
|
10
|
+
selected: boolean
|
|
11
|
+
disabled: boolean
|
|
64
12
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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;
|
|
13
|
+
type TabPropsWeControl = "aria-controls" | "aria-selected" | "role" | "tabIndex"
|
|
14
|
+
|
|
15
|
+
export type TabProps = Props<
|
|
16
|
+
typeof DEFAULT_TAB_TAG,
|
|
17
|
+
TabRenderPropArg,
|
|
18
|
+
{
|
|
19
|
+
element?: HTMLElement
|
|
20
|
+
id?: string
|
|
21
|
+
autofocus?: boolean
|
|
22
|
+
disabled?: boolean
|
|
100
23
|
}
|
|
24
|
+
>
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<script lang="ts">
|
|
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
|
+
element = $bindable(),
|
|
47
|
+
id = `headlessui-tabs-tab-${internalId}`,
|
|
48
|
+
disabled = false,
|
|
49
|
+
autofocus = false,
|
|
50
|
+
...theirProps
|
|
51
|
+
}: TabProps = $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: element })
|
|
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
|
|
101
65
|
})
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
66
|
+
const selected = $derived(myIndex === selectedIndex)
|
|
67
|
+
|
|
68
|
+
const activateUsing = $derived((cb: () => FocusResult) => {
|
|
69
|
+
let result = cb()
|
|
70
|
+
if (result === FocusResult.Success && activation === "auto") {
|
|
71
|
+
let newTab = getOwnerDocument(element)?.activeElement
|
|
72
|
+
let idx = context.tabs.findIndex((tab) => tab.current === newTab)
|
|
73
|
+
if (idx !== -1) change(idx)
|
|
107
74
|
}
|
|
75
|
+
return result
|
|
108
76
|
})
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
77
|
+
|
|
78
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
79
|
+
let list = tabs.map((tab) => tab.current).filter(Boolean) as HTMLElement[]
|
|
80
|
+
|
|
81
|
+
if (event.key === " " || event.key === "Enter") {
|
|
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))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let result = activateUsing(() => {
|
|
106
|
+
return match(orientation, {
|
|
107
|
+
vertical() {
|
|
108
|
+
if (event.key === "ArrowUp") return focusIn(list, Focus.Previous | Focus.WrapAround)
|
|
109
|
+
if (event.key === "ArrowDown") return focusIn(list, Focus.Next | Focus.WrapAround)
|
|
110
|
+
return FocusResult.Error
|
|
111
|
+
},
|
|
112
|
+
horizontal() {
|
|
113
|
+
if (event.key === "ArrowLeft") return focusIn(list, Focus.Previous | Focus.WrapAround)
|
|
114
|
+
if (event.key === "ArrowRight") return focusIn(list, Focus.Next | Focus.WrapAround)
|
|
115
|
+
return FocusResult.Error
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
if (result === FocusResult.Success) {
|
|
121
|
+
return event.preventDefault()
|
|
114
122
|
}
|
|
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;
|
|
131
123
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
124
|
+
|
|
125
|
+
let ready = $state(false)
|
|
126
|
+
const handleSelection = () => {
|
|
127
|
+
if (ready) return
|
|
128
|
+
ready = true
|
|
129
|
+
|
|
130
|
+
element?.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()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const { isHovered: hover, hoverProps } = $derived(
|
|
146
|
+
useHover({
|
|
147
|
+
get disabled() {
|
|
148
|
+
return disabled
|
|
149
|
+
},
|
|
150
|
+
})
|
|
151
|
+
)
|
|
152
|
+
const { pressed: active, pressProps } = $derived(
|
|
153
|
+
useActivePress({
|
|
154
|
+
get disabled() {
|
|
155
|
+
return disabled
|
|
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 ?? undefined, as: element ? element.tagName.toLowerCase() : DEFAULT_TAB_TAG }
|
|
179
|
+
},
|
|
180
|
+
get ref() {
|
|
181
|
+
return tabRef
|
|
147
182
|
},
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
const ourProps = $derived(
|
|
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
|
+
)
|
|
151
204
|
)
|
|
152
|
-
);
|
|
153
205
|
</script>
|
|
154
206
|
|
|
155
|
-
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_TAB_TAG} name="Tab" bind:
|
|
207
|
+
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_TAB_TAG} name="Tab" bind:element />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Props } from "../utils/types.js";
|
|
2
2
|
declare const DEFAULT_TAB_TAG: "button";
|
|
3
3
|
type TabRenderPropArg = {
|
|
4
4
|
hover: boolean;
|
|
@@ -8,39 +8,11 @@ type TabRenderPropArg = {
|
|
|
8
8
|
selected: boolean;
|
|
9
9
|
disabled: boolean;
|
|
10
10
|
};
|
|
11
|
-
type
|
|
12
|
-
|
|
11
|
+
export type TabProps = Props<typeof DEFAULT_TAB_TAG, TabRenderPropArg, {
|
|
12
|
+
element?: HTMLElement;
|
|
13
13
|
id?: string;
|
|
14
14
|
autofocus?: boolean;
|
|
15
15
|
disabled?: boolean;
|
|
16
16
|
}>;
|
|
17
|
-
declare
|
|
18
|
-
props(): {
|
|
19
|
-
as?: TTag | undefined;
|
|
20
|
-
} & (Exclude<keyof import("../utils/types.js").PropsOf<TTag>, ("slot" | "as" | "children" | "class" | "ref") | "disabled" | "autofocus" | "id" | TabPropsWeControl> extends infer T extends keyof import("../utils/types.js").PropsOf<TTag> ? { [P in T]: import("../utils/types.js").PropsOf<TTag>[P]; } : never) & {
|
|
21
|
-
children?: import("svelte").Snippet<[{
|
|
22
|
-
slot: TabRenderPropArg;
|
|
23
|
-
props: Record<string, any>;
|
|
24
|
-
}]> | undefined;
|
|
25
|
-
class?: string | ((bag: TabRenderPropArg) => string) | null | undefined;
|
|
26
|
-
ref?: HTMLElement;
|
|
27
|
-
} & {
|
|
28
|
-
id?: string;
|
|
29
|
-
autofocus?: boolean;
|
|
30
|
-
disabled?: boolean;
|
|
31
|
-
};
|
|
32
|
-
events(): {};
|
|
33
|
-
slots(): {};
|
|
34
|
-
bindings(): "ref";
|
|
35
|
-
exports(): {};
|
|
36
|
-
}
|
|
37
|
-
interface $$IsomorphicComponent {
|
|
38
|
-
new <TTag extends ElementType = typeof DEFAULT_TAB_TAG>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
|
|
39
|
-
$$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
|
|
40
|
-
} & ReturnType<__sveltets_Render<TTag>['exports']>;
|
|
41
|
-
<TTag extends ElementType = typeof DEFAULT_TAB_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {}): ReturnType<__sveltets_Render<TTag>['exports']>;
|
|
42
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
43
|
-
}
|
|
44
|
-
declare const Tab: $$IsomorphicComponent;
|
|
45
|
-
type Tab<TTag extends ElementType = typeof DEFAULT_TAB_TAG> = InstanceType<typeof Tab<TTag>>;
|
|
17
|
+
declare const Tab: import("svelte").Component<TabProps, {}, "element">;
|
|
46
18
|
export default Tab;
|
|
@@ -1,62 +1,92 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Props } from "../utils/types.js"
|
|
3
|
+
import { sortByDomNode } from "../utils/focus-management.js"
|
|
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
|
|
5
11
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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);
|
|
12
|
+
export type TabGroupProps = Props<
|
|
13
|
+
typeof DEFAULT_TABS_TAG,
|
|
14
|
+
TabsRenderPropArg,
|
|
15
|
+
{
|
|
16
|
+
element?: HTMLElement
|
|
17
|
+
defaultIndex?: number
|
|
18
|
+
onchange?: (index: number) => void
|
|
19
|
+
selectedIndex?: number
|
|
20
|
+
vertical?: boolean
|
|
21
|
+
manual?: boolean
|
|
35
22
|
}
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
>
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script lang="ts">
|
|
27
|
+
import StableCollection from "../utils/StableCollection.svelte"
|
|
28
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte"
|
|
29
|
+
import { createTabContext } from "./context.svelte.js"
|
|
30
|
+
import { untrack } from "svelte"
|
|
31
|
+
|
|
32
|
+
let {
|
|
33
|
+
element = $bindable(),
|
|
34
|
+
defaultIndex = 0,
|
|
35
|
+
vertical = false,
|
|
36
|
+
manual = false,
|
|
37
|
+
onchange,
|
|
38
|
+
selectedIndex = undefined,
|
|
39
|
+
...theirProps
|
|
40
|
+
}: TabGroupProps = $props()
|
|
41
|
+
const _state = createTabContext({
|
|
42
|
+
get vertical() {
|
|
43
|
+
return vertical
|
|
44
|
+
},
|
|
45
|
+
get manual() {
|
|
46
|
+
return manual
|
|
47
|
+
},
|
|
48
|
+
get selectedIndex() {
|
|
49
|
+
return selectedIndex
|
|
50
|
+
},
|
|
51
|
+
get defaultIndex() {
|
|
52
|
+
return defaultIndex
|
|
53
|
+
},
|
|
54
|
+
change: (index: number) => {
|
|
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]))
|
|
38
88
|
}
|
|
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
|
-
});
|
|
89
|
+
})
|
|
60
90
|
</script>
|
|
61
91
|
|
|
62
92
|
<StableCollection>
|
|
@@ -74,5 +104,5 @@ $effect(() => {
|
|
|
74
104
|
}}
|
|
75
105
|
/>
|
|
76
106
|
{/if}
|
|
77
|
-
<ElementOrComponent {theirProps} slots={slot} defaultTag={DEFAULT_TABS_TAG} name="TabGroup" bind:
|
|
107
|
+
<ElementOrComponent {theirProps} slots={slot} defaultTag={DEFAULT_TABS_TAG} name="TabGroup" bind:element />
|
|
78
108
|
</StableCollection>
|
|
@@ -1,45 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Props } from "../utils/types.js";
|
|
2
2
|
declare const DEFAULT_TABS_TAG: "div";
|
|
3
3
|
type TabsRenderPropArg = {
|
|
4
4
|
selectedIndex: number;
|
|
5
5
|
};
|
|
6
|
-
type
|
|
7
|
-
|
|
6
|
+
export type TabGroupProps = Props<typeof DEFAULT_TABS_TAG, TabsRenderPropArg, {
|
|
7
|
+
element?: HTMLElement;
|
|
8
8
|
defaultIndex?: number;
|
|
9
9
|
onchange?: (index: number) => void;
|
|
10
10
|
selectedIndex?: number;
|
|
11
11
|
vertical?: boolean;
|
|
12
12
|
manual?: boolean;
|
|
13
13
|
}>;
|
|
14
|
-
declare
|
|
15
|
-
props(): {
|
|
16
|
-
as?: TTag | undefined;
|
|
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
|
-
children?: import("svelte").Snippet<[{
|
|
19
|
-
slot: TabsRenderPropArg;
|
|
20
|
-
props: Record<string, any>;
|
|
21
|
-
}]> | undefined;
|
|
22
|
-
class?: string | ((bag: TabsRenderPropArg) => string) | null | undefined;
|
|
23
|
-
ref?: HTMLElement;
|
|
24
|
-
} & {
|
|
25
|
-
defaultIndex?: number;
|
|
26
|
-
onchange?: (index: number) => void;
|
|
27
|
-
selectedIndex?: number;
|
|
28
|
-
vertical?: boolean;
|
|
29
|
-
manual?: boolean;
|
|
30
|
-
};
|
|
31
|
-
events(): {};
|
|
32
|
-
slots(): {};
|
|
33
|
-
bindings(): "ref";
|
|
34
|
-
exports(): {};
|
|
35
|
-
}
|
|
36
|
-
interface $$IsomorphicComponent {
|
|
37
|
-
new <TTag extends ElementType = typeof DEFAULT_TABS_TAG>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TTag>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TTag>['props']>, ReturnType<__sveltets_Render<TTag>['events']>, ReturnType<__sveltets_Render<TTag>['slots']>> & {
|
|
38
|
-
$$bindings?: ReturnType<__sveltets_Render<TTag>['bindings']>;
|
|
39
|
-
} & ReturnType<__sveltets_Render<TTag>['exports']>;
|
|
40
|
-
<TTag extends ElementType = typeof DEFAULT_TABS_TAG>(internal: unknown, props: ReturnType<__sveltets_Render<TTag>['props']> & {}): ReturnType<__sveltets_Render<TTag>['exports']>;
|
|
41
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
42
|
-
}
|
|
43
|
-
declare const TabGroup: $$IsomorphicComponent;
|
|
44
|
-
type TabGroup<TTag extends ElementType = typeof DEFAULT_TABS_TAG> = InstanceType<typeof TabGroup<TTag>>;
|
|
14
|
+
declare const TabGroup: import("svelte").Component<TabGroupProps, {}, "element">;
|
|
45
15
|
export default TabGroup;
|
package/dist/tabs/TabList.svelte
CHANGED
|
@@ -1,16 +1,35 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { 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 = Props<
|
|
11
|
+
typeof DEFAULT_LIST_TAG,
|
|
12
|
+
ListRenderPropArg,
|
|
13
|
+
{
|
|
14
|
+
element?: HTMLElement
|
|
15
|
+
}
|
|
16
|
+
>
|
|
2
17
|
</script>
|
|
3
18
|
|
|
4
|
-
<script lang="ts"
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
})
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte"
|
|
21
|
+
import { useTabs } from "./context.svelte.js"
|
|
22
|
+
|
|
23
|
+
const context = useTabs("TabList")
|
|
24
|
+
const { orientation, selectedIndex } = $derived(context)
|
|
25
|
+
|
|
26
|
+
const slot = $derived({ selectedIndex } satisfies ListRenderPropArg)
|
|
27
|
+
|
|
28
|
+
let { element = $bindable(), ...theirProps }: TabListProps = $props()
|
|
29
|
+
const ourProps = $derived({
|
|
30
|
+
role: "tablist",
|
|
31
|
+
"aria-orientation": orientation,
|
|
32
|
+
})
|
|
14
33
|
</script>
|
|
15
34
|
|
|
16
|
-
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_LIST_TAG} name="TabList" bind:
|
|
35
|
+
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_LIST_TAG} name="TabList" bind:element />
|