@pzerelles/headlessui-svelte 2.1.2-next.3 → 2.1.2-next.5

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 (65) hide show
  1. package/dist/button/Button.svelte +84 -54
  2. package/dist/checkbox/Checkbox.svelte +174 -120
  3. package/dist/close-button/CloseButton.svelte +12 -6
  4. package/dist/combobox/Combobox.svelte +50 -3
  5. package/dist/data-interactive/DataInteractive.svelte +57 -29
  6. package/dist/description/Description.svelte +32 -21
  7. package/dist/dialog/Dialog.svelte +69 -34
  8. package/dist/dialog/DialogBackdrop.svelte +29 -12
  9. package/dist/dialog/DialogPanel.svelte +49 -26
  10. package/dist/dialog/DialogTitle.svelte +38 -23
  11. package/dist/dialog/InternalDialog.svelte +263 -202
  12. package/dist/field/Field.svelte +49 -26
  13. package/dist/fieldset/Fieldset.svelte +50 -29
  14. package/dist/focus-trap/FocusTrap.svelte +419 -290
  15. package/dist/focus-trap/FocusTrap.svelte.d.ts +2 -14
  16. package/dist/focus-trap/FocusTrapFeatures.d.ts +14 -0
  17. package/dist/focus-trap/FocusTrapFeatures.js +15 -0
  18. package/dist/input/Input.svelte +85 -53
  19. package/dist/internal/FocusSentinel.svelte +16 -8
  20. package/dist/internal/ForcePortalRoot.svelte +7 -3
  21. package/dist/internal/FormFields.svelte +31 -20
  22. package/dist/internal/FormResolver.svelte +20 -15
  23. package/dist/internal/Hidden.svelte +44 -27
  24. package/dist/internal/Hidden.svelte.d.ts +2 -5
  25. package/dist/internal/HiddenFeatures.d.ts +5 -0
  26. package/dist/internal/HiddenFeatures.js +9 -0
  27. package/dist/internal/HoistFormFields.svelte +7 -4
  28. package/dist/internal/MainTreeProvider.svelte +89 -36
  29. package/dist/internal/Portal.svelte +18 -14
  30. package/dist/label/Label.svelte +91 -57
  31. package/dist/legend/Legend.svelte +18 -3
  32. package/dist/listbox/Listbox.svelte +588 -409
  33. package/dist/listbox/Listbox.svelte.d.ts +2 -12
  34. package/dist/listbox/ListboxButton.svelte +176 -127
  35. package/dist/listbox/ListboxOption.svelte +166 -125
  36. package/dist/listbox/ListboxOptions.svelte +340 -244
  37. package/dist/listbox/ListboxSelectedOption.svelte +38 -15
  38. package/dist/listbox/ListboxStates.d.ts +12 -0
  39. package/dist/listbox/ListboxStates.js +15 -0
  40. package/dist/menu/Menu.svelte +307 -218
  41. package/dist/menu/MenuButton.svelte +157 -115
  42. package/dist/menu/MenuHeading.svelte +34 -14
  43. package/dist/menu/MenuItem.svelte +145 -107
  44. package/dist/menu/MenuItems.svelte +298 -224
  45. package/dist/menu/MenuSection.svelte +26 -9
  46. package/dist/menu/MenuSeparator.svelte +20 -4
  47. package/dist/portal/InternalPortal.svelte +141 -85
  48. package/dist/portal/Portal.svelte +5 -2
  49. package/dist/portal/PortalGroup.svelte +30 -9
  50. package/dist/switch/Switch.svelte +179 -122
  51. package/dist/switch/Switch.svelte.d.ts +4 -4
  52. package/dist/switch/SwitchGroup.svelte +44 -31
  53. package/dist/tabs/Tab.svelte +195 -143
  54. package/dist/tabs/TabGroup.svelte +292 -205
  55. package/dist/tabs/TabList.svelte +31 -11
  56. package/dist/tabs/TabPanel.svelte +68 -43
  57. package/dist/tabs/TabPanels.svelte +18 -7
  58. package/dist/textarea/Textarea.svelte +83 -53
  59. package/dist/transition/InternalTransitionChild.svelte +259 -170
  60. package/dist/transition/Transition.svelte +96 -66
  61. package/dist/transition/TransitionChild.svelte +31 -11
  62. package/dist/utils/ElementOrComponent.svelte +44 -23
  63. package/dist/utils/Generic.svelte +29 -17
  64. package/dist/utils/StableCollection.svelte +54 -36
  65. package/package.json +10 -10
@@ -1,225 +1,312 @@
1
- <script lang="ts" module>import { sortByDomNode } from "../utils/focus-management.js";
2
- import { match } from "../utils/match.js";
3
- import FocusSentinel from "../internal/FocusSentinel.svelte";
4
- import { setContext, getContext, untrack } from "svelte";
5
- const DEFAULT_TABS_TAG = "div";
6
- export function useData(component) {
7
- const context = getContext("TabsData");
8
- if (!context) {
9
- let err = new Error(`<${component} /> is missing a parent <Tab.Group /> component.`);
10
- if (Error.captureStackTrace) Error.captureStackTrace(err, useData);
11
- throw err;
1
+ <script lang="ts" module>
2
+ import type { ElementType, Props } from "../utils/types.js"
3
+ import { sortByDomNode } from "../utils/focus-management.js"
4
+ import { match } from "../utils/match.js"
5
+ import FocusSentinel from "../internal/FocusSentinel.svelte"
6
+ import { setContext, getContext, untrack } from "svelte"
7
+
8
+ const DEFAULT_TABS_TAG = "div" as const
9
+ type TabsRenderPropArg = {
10
+ selectedIndex: number
11
+ }
12
+ type TabsPropsWeControl = never
13
+
14
+ export type TabGroupProps<TTag extends ElementType = typeof DEFAULT_TABS_TAG> = Props<
15
+ TTag,
16
+ TabsRenderPropArg,
17
+ TabsPropsWeControl,
18
+ {
19
+ defaultIndex?: number
20
+ onchange?: (index: number) => void
21
+ selectedIndex?: number
22
+ vertical?: boolean
23
+ manual?: boolean
24
+ }
25
+ >
26
+
27
+ interface StateDefinition {
28
+ info: { isControlled: boolean }
29
+ selectedIndex: number
30
+
31
+ tabs: MutableRefObject<HTMLElement | undefined>[]
32
+ panels: MutableRefObject<HTMLElement | undefined>[]
33
+ }
34
+
35
+ type TabsDataContext = StateDefinition & {
36
+ orientation: "horizontal" | "vertical"
37
+ activation: "manual" | "auto"
12
38
  }
13
- return context;
14
- }
15
- export function useActions(component) {
16
- const context = getContext("TabsActions");
17
- if (!context) {
18
- const err = new Error(`<${component} /> is missing a parent <Tab.Group /> component.`);
19
- if (Error.captureStackTrace) Error.captureStackTrace(err, useActions);
20
- throw err;
39
+
40
+ export function useData(component: string) {
41
+ const context = getContext<TabsDataContext>("TabsData")
42
+ if (!context) {
43
+ let err = new Error(`<${component} /> is missing a parent <Tab.Group /> component.`)
44
+ if (Error.captureStackTrace) Error.captureStackTrace(err, useData)
45
+ throw err
46
+ }
47
+ return context
48
+ }
49
+
50
+ type TabsActionsContext = {
51
+ registerTab: (tab: MutableRefObject<HTMLElement | undefined>) => () => void
52
+ registerPanel: (panel: MutableRefObject<HTMLElement | undefined>) => () => void
53
+ change: (index: number) => void
54
+ }
55
+
56
+ export function useActions(component: string) {
57
+ const context = getContext<TabsActionsContext>("TabsActions")
58
+ if (!context) {
59
+ const err = new Error(`<${component} /> is missing a parent <Tab.Group /> component.`)
60
+ if (Error.captureStackTrace) Error.captureStackTrace(err, useActions)
61
+ throw err
62
+ }
63
+ return context
21
64
  }
22
- return context;
23
- }
24
65
  </script>
25
66
 
26
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TABS_TAG">import StableCollection from "../utils/StableCollection.svelte";
27
- import ElementOrComponent from "../utils/ElementOrComponent.svelte";
28
- var Direction = /* @__PURE__ */ ((Direction2) => {
29
- Direction2[Direction2["Forwards"] = 0] = "Forwards";
30
- Direction2[Direction2["Backwards"] = 1] = "Backwards";
31
- return Direction2;
32
- })(Direction || {});
33
- var Ordering = /* @__PURE__ */ ((Ordering2) => {
34
- Ordering2[Ordering2["Less"] = -1] = "Less";
35
- Ordering2[Ordering2["Equal"] = 0] = "Equal";
36
- Ordering2[Ordering2["Greater"] = 1] = "Greater";
37
- return Ordering2;
38
- })(Ordering || {});
39
- const stateReducer = (initialState) => {
40
- let _state2 = $state(initialState);
41
- return {
67
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_TABS_TAG">
68
+ import StableCollection from "../utils/StableCollection.svelte"
69
+ import type { MutableRefObject } from "../utils/ref.svelte.js"
70
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte"
71
+
72
+ enum Direction {
73
+ Forwards,
74
+ Backwards,
75
+ }
76
+
77
+ enum Ordering {
78
+ Less = -1,
79
+ Equal = 0,
80
+ Greater = 1,
81
+ }
82
+
83
+ const stateReducer = (initialState: StateDefinition) => {
84
+ let _state = $state(initialState)
85
+ return {
86
+ get info() {
87
+ return _state.info
88
+ },
89
+ get selectedIndex() {
90
+ return _state.selectedIndex
91
+ },
92
+ get tabs() {
93
+ return _state.tabs
94
+ },
95
+ get panels() {
96
+ return _state.panels
97
+ },
98
+ setSelectedIndex(index: number) {
99
+ if (index === _state.selectedIndex) return _state
100
+ let tabs = sortByDomNode(_state.tabs, (tab) => tab.current ?? null)
101
+ let panels = sortByDomNode(_state.panels, (panel) => panel.current ?? null)
102
+
103
+ let focusableTabs = tabs.filter((tab) => !tab?.current?.hasAttribute("disabled"))
104
+
105
+ let nextState = { ..._state, tabs, panels }
106
+
107
+ if (
108
+ // Underflow
109
+ index < 0 ||
110
+ // Overflow
111
+ index > tabs.length - 1
112
+ ) {
113
+ let direction = match(Math.sign(index - _state.selectedIndex), {
114
+ [Ordering.Less]: () => Direction.Backwards,
115
+ [Ordering.Equal]: () => {
116
+ return match(Math.sign(index), {
117
+ [Ordering.Less]: () => Direction.Forwards,
118
+ [Ordering.Equal]: () => Direction.Forwards,
119
+ [Ordering.Greater]: () => Direction.Backwards,
120
+ })
121
+ },
122
+ [Ordering.Greater]: () => Direction.Forwards,
123
+ })
124
+
125
+ // If there are no focusable tabs then.
126
+ // We won't change the selected index
127
+ // because it's likely the user is
128
+ // lazy loading tabs and there's
129
+ // nothing to focus on yet
130
+ if (focusableTabs.length === 0) {
131
+ _state = nextState
132
+ return _state
133
+ }
134
+
135
+ let nextSelectedIndex = match(direction, {
136
+ [Direction.Forwards]: () => tabs.findIndex((tab) => tab === focusableTabs[0]),
137
+ [Direction.Backwards]: () => tabs.findIndex((tab) => tab === focusableTabs[focusableTabs.length - 1]),
138
+ })
139
+
140
+ _state = {
141
+ ...nextState,
142
+ selectedIndex: nextSelectedIndex === -1 ? _state.selectedIndex : nextSelectedIndex,
143
+ }
144
+ return _state
145
+ }
146
+
147
+ // Middle
148
+ let before = tabs.slice(0, index)
149
+ let after = tabs.slice(index)
150
+
151
+ let next = [...after, ...before].find((tab) => focusableTabs.some((_tab) => _tab === tab))
152
+ if (!next) {
153
+ _state = nextState
154
+ return _state
155
+ }
156
+
157
+ let selectedIndex = tabs.findIndex((tab) => tab === next) ?? _state.selectedIndex
158
+ if (selectedIndex === -1) selectedIndex = _state.selectedIndex
159
+
160
+ _state = { ...nextState, selectedIndex }
161
+ return _state
162
+ },
163
+ registerTab(tab: MutableRefObject<HTMLElement | undefined>) {
164
+ if (_state.tabs.some((_tab) => _tab === tab)) return _state
165
+
166
+ _state.tabs = sortByDomNode([..._state.tabs, tab], (tab) => tab.current ?? null)
167
+ let activeTab = _state.tabs[_state.selectedIndex]
168
+
169
+ // When the component is uncontrolled, then we want to maintain the actively
170
+ // selected tab even if new tabs are inserted or removed before the active
171
+ // tab.
172
+ //
173
+ // When the component is controlled, then we don't want to do this and
174
+ // instead we want to select the tab based on the `selectedIndex` prop.
175
+ if (!_state.info.isControlled) {
176
+ const selectedIndex = _state.tabs.findIndex((tab) => tab === activeTab)
177
+ if (selectedIndex !== _state.selectedIndex) _state.selectedIndex = selectedIndex
178
+ }
179
+
180
+ return _state
181
+ },
182
+ unregisterTab(tab: MutableRefObject<HTMLElement | undefined>) {
183
+ _state.tabs = _state.tabs.filter((_tab) => _tab !== tab)
184
+ return _state
185
+ },
186
+ registerPanel(panel: MutableRefObject<HTMLElement | undefined>) {
187
+ if (_state.panels.some((_panel) => _panel === panel)) return _state
188
+ _state.panels = sortByDomNode([..._state.panels, panel], (panel) => panel.current ?? null)
189
+ return _state
190
+ },
191
+ unregisterPanel(panel: MutableRefObject<HTMLElement | undefined>) {
192
+ _state.panels = _state.panels.filter((_panel) => _panel !== panel)
193
+ return _state
194
+ },
195
+ }
196
+ }
197
+
198
+ let {
199
+ ref = $bindable(),
200
+ defaultIndex = 0,
201
+ vertical = false,
202
+ manual = false,
203
+ onchange,
204
+ selectedIndex = undefined,
205
+ ...theirProps
206
+ }: { as?: TTag } & TabGroupProps<TTag> = $props()
207
+ const orientation = $derived(vertical ? "vertical" : "horizontal")
208
+ const activation = $derived(manual ? "manual" : "auto")
209
+
210
+ const isControlled = $derived(selectedIndex !== undefined)
211
+
212
+ const _state = stateReducer({
213
+ info: { isControlled: selectedIndex !== undefined },
214
+ selectedIndex: selectedIndex ?? defaultIndex,
215
+ tabs: [],
216
+ panels: [],
217
+ })
218
+ $effect(() => {
219
+ untrack(() => _state.info).isControlled = isControlled
220
+ })
221
+
222
+ const slot = $derived({
223
+ selectedIndex: _state.selectedIndex,
224
+ } satisfies TabsRenderPropArg)
225
+ const stableTabs = $derived(_state.tabs)
226
+
227
+ const tabsData = {
228
+ get orientation() {
229
+ return orientation
230
+ },
231
+ get activation() {
232
+ return activation
233
+ },
42
234
  get info() {
43
- return _state2.info;
235
+ return _state.info
44
236
  },
45
237
  get selectedIndex() {
46
- return _state2.selectedIndex;
238
+ return _state.selectedIndex
47
239
  },
48
240
  get tabs() {
49
- return _state2.tabs;
241
+ return _state.tabs
50
242
  },
51
243
  get panels() {
52
- return _state2.panels;
244
+ return _state.panels
53
245
  },
54
- setSelectedIndex(index) {
55
- if (index === _state2.selectedIndex) return _state2;
56
- let tabs = sortByDomNode(_state2.tabs, (tab) => tab.current ?? null);
57
- let panels = sortByDomNode(_state2.panels, (panel) => panel.current ?? null);
58
- let focusableTabs = tabs.filter((tab) => !tab?.current?.hasAttribute("disabled"));
59
- let nextState = { ..._state2, tabs, panels };
60
- if (
61
- // Underflow
62
- index < 0 || // Overflow
63
- index > tabs.length - 1
64
- ) {
65
- let direction = match(Math.sign(index - _state2.selectedIndex), {
66
- [-1 /* Less */]: () => 1 /* Backwards */,
67
- [0 /* Equal */]: () => {
68
- return match(Math.sign(index), {
69
- [-1 /* Less */]: () => 0 /* Forwards */,
70
- [0 /* Equal */]: () => 0 /* Forwards */,
71
- [1 /* Greater */]: () => 1 /* Backwards */
72
- });
73
- },
74
- [1 /* Greater */]: () => 0 /* Forwards */
75
- });
76
- if (focusableTabs.length === 0) {
77
- _state2 = nextState;
78
- return _state2;
79
- }
80
- let nextSelectedIndex = match(direction, {
81
- [0 /* Forwards */]: () => tabs.findIndex((tab) => tab === focusableTabs[0]),
82
- [1 /* Backwards */]: () => tabs.findIndex((tab) => tab === focusableTabs[focusableTabs.length - 1])
83
- });
84
- _state2 = {
85
- ...nextState,
86
- selectedIndex: nextSelectedIndex === -1 ? _state2.selectedIndex : nextSelectedIndex
87
- };
88
- return _state2;
89
- }
90
- let before = tabs.slice(0, index);
91
- let after = tabs.slice(index);
92
- let next = [...after, ...before].find((tab) => focusableTabs.some((_tab) => _tab === tab));
93
- if (!next) {
94
- _state2 = nextState;
95
- return _state2;
96
- }
97
- let selectedIndex2 = tabs.findIndex((tab) => tab === next) ?? _state2.selectedIndex;
98
- if (selectedIndex2 === -1) selectedIndex2 = _state2.selectedIndex;
99
- _state2 = { ...nextState, selectedIndex: selectedIndex2 };
100
- return _state2;
246
+ }
247
+
248
+ const realSelectedIndex = $derived(isControlled ? selectedIndex! : _state.selectedIndex)
249
+
250
+ const registerTab = (tab: MutableRefObject<HTMLElement | undefined>) => {
251
+ _state.registerTab(tab)
252
+ return () => _state.unregisterTab(tab)
253
+ }
254
+
255
+ const registerPanel = (panel: MutableRefObject<HTMLElement | undefined>) => {
256
+ _state.registerPanel(panel)
257
+ return () => _state.unregisterPanel(panel)
258
+ }
259
+
260
+ const change = (index: number) => {
261
+ if (realSelectedIndex !== index) {
262
+ onchange?.(index)
263
+ }
264
+
265
+ if (!isControlled) {
266
+ _state.setSelectedIndex(index)
267
+ }
268
+ }
269
+
270
+ setContext<TabsActionsContext>("TabsActions", { registerTab, registerPanel, change })
271
+ setContext<TabsDataContext>("TabsData", {
272
+ get orientation() {
273
+ return orientation
101
274
  },
102
- registerTab(tab) {
103
- if (_state2.tabs.some((_tab) => _tab === tab)) return _state2;
104
- _state2.tabs = sortByDomNode([..._state2.tabs, tab], (tab2) => tab2.current ?? null);
105
- let activeTab = _state2.tabs[_state2.selectedIndex];
106
- if (!_state2.info.isControlled) {
107
- const selectedIndex2 = _state2.tabs.findIndex((tab2) => tab2 === activeTab);
108
- if (selectedIndex2 !== _state2.selectedIndex) _state2.selectedIndex = selectedIndex2;
109
- }
110
- return _state2;
275
+ get activation() {
276
+ return activation
111
277
  },
112
- unregisterTab(tab) {
113
- _state2.tabs = _state2.tabs.filter((_tab) => _tab !== tab);
114
- return _state2;
278
+ get info() {
279
+ return _state.info
115
280
  },
116
- registerPanel(panel) {
117
- if (_state2.panels.some((_panel) => _panel === panel)) return _state2;
118
- _state2.panels = sortByDomNode([..._state2.panels, panel], (panel2) => panel2.current ?? null);
119
- return _state2;
281
+ get selectedIndex() {
282
+ return _state.selectedIndex
283
+ },
284
+ get tabs() {
285
+ return _state.tabs
286
+ },
287
+ get panels() {
288
+ return _state.panels
120
289
  },
121
- unregisterPanel(panel) {
122
- _state2.panels = _state2.panels.filter((_panel) => _panel !== panel);
123
- return _state2;
290
+ })
291
+
292
+ $effect(() => {
293
+ const newSelectedIndex = selectedIndex ?? defaultIndex
294
+ untrack(() => _state.setSelectedIndex(newSelectedIndex))
295
+ })
296
+
297
+ $effect(() => {
298
+ if (realSelectedIndex === undefined) return
299
+ if (_state.tabs.length <= 0) return
300
+
301
+ // TODO: Figure out a way to detect this without the slow sort on every render. Might be fine
302
+ // unless you have a lot of tabs.
303
+ let sorted = sortByDomNode(_state.tabs, (tab) => tab.current ?? null)
304
+ let didOrderChange = sorted.some((tab, i) => _state.tabs[i] !== tab)
305
+
306
+ if (didOrderChange) {
307
+ change(sorted.findIndex((tab) => tab === _state.tabs[realSelectedIndex]))
124
308
  }
125
- };
126
- };
127
- let {
128
- ref = $bindable(),
129
- defaultIndex = 0,
130
- vertical = false,
131
- manual = false,
132
- onchange,
133
- selectedIndex = void 0,
134
- ...theirProps
135
- } = $props();
136
- const orientation = $derived(vertical ? "vertical" : "horizontal");
137
- const activation = $derived(manual ? "manual" : "auto");
138
- const isControlled = $derived(selectedIndex !== void 0);
139
- const _state = stateReducer({
140
- info: { isControlled: selectedIndex !== void 0 },
141
- selectedIndex: selectedIndex ?? defaultIndex,
142
- tabs: [],
143
- panels: []
144
- });
145
- $effect(() => {
146
- untrack(() => _state.info).isControlled = isControlled;
147
- });
148
- const slot = $derived({
149
- selectedIndex: _state.selectedIndex
150
- });
151
- const stableTabs = $derived(_state.tabs);
152
- const tabsData = {
153
- get orientation() {
154
- return orientation;
155
- },
156
- get activation() {
157
- return activation;
158
- },
159
- get info() {
160
- return _state.info;
161
- },
162
- get selectedIndex() {
163
- return _state.selectedIndex;
164
- },
165
- get tabs() {
166
- return _state.tabs;
167
- },
168
- get panels() {
169
- return _state.panels;
170
- }
171
- };
172
- const realSelectedIndex = $derived(isControlled ? selectedIndex : _state.selectedIndex);
173
- const registerTab = (tab) => {
174
- _state.registerTab(tab);
175
- return () => _state.unregisterTab(tab);
176
- };
177
- const registerPanel = (panel) => {
178
- _state.registerPanel(panel);
179
- return () => _state.unregisterPanel(panel);
180
- };
181
- const change = (index) => {
182
- if (realSelectedIndex !== index) {
183
- onchange?.(index);
184
- }
185
- if (!isControlled) {
186
- _state.setSelectedIndex(index);
187
- }
188
- };
189
- setContext("TabsActions", { registerTab, registerPanel, change });
190
- setContext("TabsData", {
191
- get orientation() {
192
- return orientation;
193
- },
194
- get activation() {
195
- return activation;
196
- },
197
- get info() {
198
- return _state.info;
199
- },
200
- get selectedIndex() {
201
- return _state.selectedIndex;
202
- },
203
- get tabs() {
204
- return _state.tabs;
205
- },
206
- get panels() {
207
- return _state.panels;
208
- }
209
- });
210
- $effect(() => {
211
- const newSelectedIndex = selectedIndex ?? defaultIndex;
212
- untrack(() => _state.setSelectedIndex(newSelectedIndex));
213
- });
214
- $effect(() => {
215
- if (realSelectedIndex === void 0) return;
216
- if (_state.tabs.length <= 0) return;
217
- let sorted = sortByDomNode(_state.tabs, (tab) => tab.current ?? null);
218
- let didOrderChange = sorted.some((tab, i) => _state.tabs[i] !== tab);
219
- if (didOrderChange) {
220
- change(sorted.findIndex((tab) => tab === _state.tabs[realSelectedIndex]));
221
- }
222
- });
309
+ })
223
310
  </script>
224
311
 
225
312
  <StableCollection>
@@ -1,16 +1,36 @@
1
- <script lang="ts" module>const DEFAULT_LIST_TAG = "div";
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
+ >
2
18
  </script>
3
19
 
4
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_LIST_TAG">import { useData } from "./TabGroup.svelte";
5
- import ElementOrComponent from "../utils/ElementOrComponent.svelte";
6
- const data = useData("Tab.List");
7
- const { orientation, selectedIndex } = $derived(data);
8
- const slot = $derived({ selectedIndex });
9
- let { ref = $bindable(), ...theirProps } = $props();
10
- const ourProps = $derived({
11
- role: "tablist",
12
- "aria-orientation": orientation
13
- });
20
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_LIST_TAG">
21
+ import { useData } from "./TabGroup.svelte"
22
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte"
23
+
24
+ const data = useData("Tab.List")
25
+ const { orientation, selectedIndex } = $derived(data)
26
+
27
+ const slot = $derived({ selectedIndex } satisfies ListRenderPropArg)
28
+
29
+ let { ref = $bindable(), ...theirProps }: { as?: TTag } & TabListProps<TTag> = $props()
30
+ const ourProps = $derived({
31
+ role: "tablist",
32
+ "aria-orientation": orientation,
33
+ })
14
34
  </script>
15
35
 
16
36
  <ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_LIST_TAG} name="TabList" bind:ref />