@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.
Files changed (123) hide show
  1. package/dist/button/Button.svelte +84 -55
  2. package/dist/button/Button.svelte.d.ts +4 -32
  3. package/dist/checkbox/Checkbox.svelte +177 -121
  4. package/dist/checkbox/Checkbox.svelte.d.ts +14 -32
  5. package/dist/close-button/CloseButton.svelte +10 -7
  6. package/dist/close-button/CloseButton.svelte.d.ts +2 -44
  7. package/dist/data-interactive/DataInteractive.svelte +49 -37
  8. package/dist/data-interactive/DataInteractive.svelte.d.ts +7 -30
  9. package/dist/description/Description.svelte +35 -22
  10. package/dist/description/Description.svelte.d.ts +7 -28
  11. package/dist/dialog/Dialog.svelte +326 -232
  12. package/dist/dialog/Dialog.svelte.d.ts +4 -42
  13. package/dist/dialog/DialogBackdrop.svelte +33 -16
  14. package/dist/dialog/DialogBackdrop.svelte.d.ts +4 -29
  15. package/dist/dialog/DialogPanel.svelte +60 -29
  16. package/dist/dialog/DialogPanel.svelte.d.ts +4 -30
  17. package/dist/dialog/DialogTitle.svelte +51 -24
  18. package/dist/dialog/DialogTitle.svelte.d.ts +6 -27
  19. package/dist/field/Field.svelte +44 -28
  20. package/dist/field/Field.svelte.d.ts +4 -30
  21. package/dist/fieldset/Fieldset.svelte +48 -30
  22. package/dist/fieldset/Fieldset.svelte.d.ts +5 -31
  23. package/dist/focus-trap/FocusTrap.svelte +430 -298
  24. package/dist/focus-trap/FocusTrap.svelte.d.ts +5 -34
  25. package/dist/hooks/use-inert-others.svelte.js +10 -10
  26. package/dist/hooks/use-resolve-button-type.svelte.js +0 -1
  27. package/dist/input/Input.svelte +95 -54
  28. package/dist/input/Input.svelte.d.ts +13 -27
  29. package/dist/internal/FloatingProvider.svelte +14 -9
  30. package/dist/internal/FocusSentinel.svelte +49 -40
  31. package/dist/internal/ForcePortalRoot.svelte +7 -3
  32. package/dist/internal/FormFields.svelte +47 -34
  33. package/dist/internal/FormFieldsProvider.svelte +9 -5
  34. package/dist/internal/FormResolver.svelte +25 -16
  35. package/dist/internal/Hidden.svelte +45 -38
  36. package/dist/internal/Hidden.svelte.d.ts +4 -30
  37. package/dist/internal/MainTreeProvider.svelte +90 -37
  38. package/dist/internal/Portal.svelte +18 -14
  39. package/dist/label/Label.svelte +100 -59
  40. package/dist/label/Label.svelte.d.ts +7 -32
  41. package/dist/legend/Legend.svelte +27 -4
  42. package/dist/legend/Legend.svelte.d.ts +4 -3
  43. package/dist/listbox/Listbox.svelte +518 -391
  44. package/dist/listbox/Listbox.svelte.d.ts +11 -35
  45. package/dist/listbox/ListboxButton.svelte +175 -128
  46. package/dist/listbox/ListboxButton.svelte.d.ts +5 -32
  47. package/dist/listbox/ListboxOption.svelte +171 -130
  48. package/dist/listbox/ListboxOption.svelte.d.ts +12 -26
  49. package/dist/listbox/ListboxOptions.svelte +403 -305
  50. package/dist/listbox/ListboxOptions.svelte.d.ts +4 -38
  51. package/dist/listbox/ListboxSelectedOption.svelte +40 -19
  52. package/dist/listbox/ListboxSelectedOption.svelte.d.ts +8 -33
  53. package/dist/menu/Menu.svelte +76 -52
  54. package/dist/menu/Menu.svelte.d.ts +3 -31
  55. package/dist/menu/MenuButton.svelte +158 -118
  56. package/dist/menu/MenuButton.svelte.d.ts +4 -34
  57. package/dist/menu/MenuHeading.svelte +34 -15
  58. package/dist/menu/MenuHeading.svelte.d.ts +4 -31
  59. package/dist/menu/MenuItem.svelte +143 -108
  60. package/dist/menu/MenuItem.svelte.d.ts +5 -32
  61. package/dist/menu/MenuItems.svelte +301 -230
  62. package/dist/menu/MenuItems.svelte.d.ts +4 -38
  63. package/dist/menu/MenuSection.svelte +26 -10
  64. package/dist/menu/MenuSection.svelte.d.ts +5 -29
  65. package/dist/menu/MenuSeparator.svelte +20 -5
  66. package/dist/menu/MenuSeparator.svelte.d.ts +5 -28
  67. package/dist/popover/Popover.svelte +217 -151
  68. package/dist/popover/Popover.svelte.d.ts +4 -30
  69. package/dist/popover/PopoverBackdrop.svelte +71 -42
  70. package/dist/popover/PopoverBackdrop.svelte.d.ts +6 -34
  71. package/dist/popover/PopoverButton.svelte +302 -222
  72. package/dist/popover/PopoverButton.svelte.d.ts +6 -29
  73. package/dist/popover/PopoverGroup.svelte +64 -36
  74. package/dist/popover/PopoverGroup.svelte.d.ts +5 -28
  75. package/dist/popover/PopoverPanel.svelte +335 -248
  76. package/dist/popover/PopoverPanel.svelte.d.ts +5 -36
  77. package/dist/popover/index.d.ts +1 -1
  78. package/dist/portal/InternalPortal.svelte +143 -86
  79. package/dist/portal/InternalPortal.svelte.d.ts +4 -30
  80. package/dist/portal/Portal.svelte +8 -4
  81. package/dist/portal/Portal.svelte.d.ts +2 -18
  82. package/dist/portal/PortalGroup.svelte +23 -10
  83. package/dist/portal/PortalGroup.svelte.d.ts +3 -31
  84. package/dist/select/Select.svelte +100 -69
  85. package/dist/select/Select.svelte.d.ts +5 -32
  86. package/dist/switch/Switch.svelte +181 -133
  87. package/dist/switch/Switch.svelte.d.ts +5 -38
  88. package/dist/switch/SwitchGroup.svelte +45 -32
  89. package/dist/switch/SwitchGroup.svelte.d.ts +7 -28
  90. package/dist/tabs/Tab.svelte +195 -143
  91. package/dist/tabs/Tab.svelte.d.ts +4 -32
  92. package/dist/tabs/TabGroup.svelte +87 -57
  93. package/dist/tabs/TabGroup.svelte.d.ts +4 -34
  94. package/dist/tabs/TabList.svelte +31 -12
  95. package/dist/tabs/TabList.svelte.d.ts +5 -28
  96. package/dist/tabs/TabPanel.svelte +69 -44
  97. package/dist/tabs/TabPanel.svelte.d.ts +4 -34
  98. package/dist/tabs/TabPanels.svelte +19 -8
  99. package/dist/tabs/TabPanels.svelte.d.ts +5 -27
  100. package/dist/textarea/Textarea.svelte +87 -54
  101. package/dist/textarea/Textarea.svelte.d.ts +13 -27
  102. package/dist/transition/InternalTransitionChild.svelte +267 -171
  103. package/dist/transition/InternalTransitionChild.svelte.d.ts +3 -33
  104. package/dist/transition/Transition.svelte +88 -67
  105. package/dist/transition/Transition.svelte.d.ts +3 -36
  106. package/dist/transition/TransitionChild.svelte +31 -12
  107. package/dist/transition/TransitionChild.svelte.d.ts +8 -35
  108. package/dist/transition/context.svelte.js +7 -7
  109. package/dist/utils/DisabledProvider.svelte +7 -3
  110. package/dist/utils/ElementOrComponent.svelte +88 -24
  111. package/dist/utils/ElementOrComponent.svelte.d.ts +32 -27
  112. package/dist/utils/StableCollection.svelte +54 -36
  113. package/dist/utils/floating-ui/svelte/components/FloatingNode.svelte +27 -12
  114. package/dist/utils/floating-ui/svelte/components/FloatingTree.svelte +88 -44
  115. package/dist/utils/state.js +4 -4
  116. package/dist/utils/types.d.ts +14 -12
  117. package/package.json +12 -12
  118. package/dist/combobox/Combobox.svelte +0 -6
  119. package/dist/combobox/Combobox.svelte.d.ts +0 -50
  120. package/dist/utils/Generic.svelte +0 -46
  121. package/dist/utils/Generic.svelte.d.ts +0 -32
  122. package/dist/utils/alternative-types.d.ts +0 -20
  123. package/dist/utils/alternative-types.js +0 -1
@@ -1,155 +1,207 @@
1
- <script lang="ts" module>const DEFAULT_TAB_TAG = "button";
2
- </script>
1
+ <script lang="ts" module>
2
+ import type { Props } from "../utils/types.js"
3
3
 
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);
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
- 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;
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
- const { pressed: active, pressProps } = $derived(
104
- useActivePress({
105
- get disabled() {
106
- return disabled;
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 { isFocusVisible: focus, focusProps } = $derived(
111
- useFocusRing({
112
- get autofocus() {
113
- return autofocus;
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
- 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
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
- focusProps,
149
- hoverProps,
150
- pressProps
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:ref />
207
+ <ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_TAB_TAG} name="Tab" bind:element />
@@ -1,4 +1,4 @@
1
- import type { ElementType, Props } from "../utils/types.js";
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 TabPropsWeControl = "aria-controls" | "aria-selected" | "role" | "tabIndex";
12
- export type TabProps<TTag extends ElementType = typeof DEFAULT_TAB_TAG> = Props<TTag, TabRenderPropArg, TabPropsWeControl, {
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 class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_TAB_TAG> {
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>import { sortByDomNode } from "../utils/focus-management.js";
2
- import FocusSentinel from "../internal/FocusSentinel.svelte";
3
- const DEFAULT_TABS_TAG = "div";
4
- </script>
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
- <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);
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
- if (!isControlled) {
37
- _state.selectedIndex = index;
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:ref />
107
+ <ElementOrComponent {theirProps} slots={slot} defaultTag={DEFAULT_TABS_TAG} name="TabGroup" bind:element />
78
108
  </StableCollection>
@@ -1,45 +1,15 @@
1
- import type { ElementType, Props } from "../utils/types.js";
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 TabsPropsWeControl = never;
7
- export type TabGroupProps<TTag extends ElementType = typeof DEFAULT_TABS_TAG> = Props<TTag, TabsRenderPropArg, TabsPropsWeControl, {
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 class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_TABS_TAG> {
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;
@@ -1,16 +1,35 @@
1
- <script lang="ts" module>const DEFAULT_LIST_TAG = "div";
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" 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
- });
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:ref />
35
+ <ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_LIST_TAG} name="TabList" bind:element />