@pzerelles/headlessui-svelte 2.1.2-next.7 → 2.1.2-next.8
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 -174
- package/dist/close-button/CloseButton.svelte +6 -12
- package/dist/combobox/Combobox.svelte +3 -50
- package/dist/data-interactive/DataInteractive.svelte +29 -57
- package/dist/description/Description.svelte +21 -32
- package/dist/dialog/Dialog.svelte +34 -69
- package/dist/dialog/DialogBackdrop.svelte +12 -29
- package/dist/dialog/DialogPanel.svelte +26 -49
- package/dist/dialog/DialogTitle.svelte +23 -38
- package/dist/dialog/InternalDialog.svelte +202 -263
- package/dist/field/Field.svelte +26 -49
- 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/FocusSentinel.svelte +8 -16
- package/dist/internal/ForcePortalRoot.svelte +3 -7
- package/dist/internal/FormFields.svelte +20 -31
- package/dist/internal/FormResolver.svelte +15 -20
- package/dist/internal/Hidden.svelte +23 -44
- package/dist/internal/HoistFormFields.svelte +4 -7
- package/dist/internal/MainTreeProvider.svelte +36 -89
- package/dist/internal/Portal.svelte +14 -18
- package/dist/label/Label.svelte +57 -91
- package/dist/legend/Legend.svelte +3 -18
- package/dist/listbox/Listbox.svelte +396 -588
- package/dist/listbox/ListboxButton.svelte +127 -176
- package/dist/listbox/ListboxOption.svelte +125 -166
- package/dist/listbox/ListboxOptions.svelte +244 -340
- package/dist/listbox/ListboxSelectedOption.svelte +15 -38
- package/dist/menu/Menu.svelte +218 -307
- package/dist/menu/MenuButton.svelte +115 -157
- package/dist/menu/MenuHeading.svelte +14 -34
- package/dist/menu/MenuItem.svelte +107 -145
- package/dist/menu/MenuItems.svelte +224 -298
- package/dist/menu/MenuSection.svelte +9 -26
- package/dist/menu/MenuSeparator.svelte +4 -20
- package/dist/portal/InternalPortal.svelte +85 -141
- package/dist/portal/Portal.svelte +2 -5
- package/dist/portal/PortalGroup.svelte +9 -30
- package/dist/switch/Switch.svelte +132 -179
- package/dist/switch/SwitchGroup.svelte +31 -44
- package/dist/tabs/Tab.svelte +143 -195
- package/dist/tabs/TabGroup.svelte +205 -292
- package/dist/tabs/TabList.svelte +11 -31
- package/dist/tabs/TabPanel.svelte +43 -68
- 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/ElementOrComponent.svelte +23 -44
- package/dist/utils/Generic.svelte +17 -29
- package/dist/utils/StableCollection.svelte +36 -54
- package/package.json +1 -1
|
@@ -1,270 +1,209 @@
|
|
|
1
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_DIALOG_TAG">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_DIALOG_TAG">import { useId } from "../hooks/use-id.js";
|
|
2
|
+
import { useMainTreeNode, useRootContainers } from "../hooks/use-root-containers.svelte.js";
|
|
3
|
+
import { clearOpenClosedContext, State, useOpenClosed } from "../internal/open-closed.js";
|
|
4
|
+
import { useNestedPortals } from "../portal/InternalPortal.svelte";
|
|
5
|
+
import { getOwnerDocument } from "../utils/owner.js";
|
|
6
|
+
import { DEFAULT_DIALOG_TAG, DialogRenderFeatures } from "./Dialog.svelte";
|
|
7
|
+
import { useInertOthers } from "../hooks/use-inert-others.svelte.js";
|
|
8
|
+
import { useOutsideClick } from "../hooks/use-outside-click.svelte.js";
|
|
9
|
+
import { useEscape } from "../hooks/use-escape.svelte.js";
|
|
10
|
+
import { useScrollLock } from "../hooks/use-scroll-lock.svelte.js";
|
|
11
|
+
import { useOnDisappear } from "../hooks/use-on-disappear.svelte.js";
|
|
12
|
+
import { setContext } from "svelte";
|
|
13
|
+
import { useIsTouchDevice } from "../hooks/use-is-touch-device.svelte.js";
|
|
14
|
+
import FocusTrap, { FocusTrapFeatures } from "../focus-trap/FocusTrap.svelte";
|
|
15
|
+
import Portal from "../portal/Portal.svelte";
|
|
16
|
+
import PortalGroup from "../portal/PortalGroup.svelte";
|
|
17
|
+
import ForcePortalRoot from "../internal/ForcePortalRoot.svelte";
|
|
18
|
+
import { createCloseContext } from "../internal/close-provider.js";
|
|
19
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
20
|
+
import { DialogStates } from "./context.svelte.js";
|
|
21
|
+
import { useDescriptions } from "../description/context.svelte.js";
|
|
22
|
+
const internalId = useId();
|
|
23
|
+
let {
|
|
24
|
+
ref = $bindable(),
|
|
25
|
+
id = `headlessui-dialog-${internalId}`,
|
|
26
|
+
open: theirOpen,
|
|
27
|
+
onclose,
|
|
28
|
+
initialFocus,
|
|
29
|
+
role: theirRole = "dialog",
|
|
30
|
+
autofocus = true,
|
|
31
|
+
__demoMode = false,
|
|
32
|
+
unmount = false,
|
|
33
|
+
...theirProps
|
|
34
|
+
} = $props();
|
|
35
|
+
let didWarnOnRole = $state(false);
|
|
36
|
+
const role = $derived.by(() => {
|
|
37
|
+
if (theirRole === "dialog" || theirRole === "alertdialog") {
|
|
38
|
+
return theirRole;
|
|
39
|
+
}
|
|
40
|
+
if (!didWarnOnRole) {
|
|
41
|
+
didWarnOnRole = true;
|
|
42
|
+
console.warn(
|
|
43
|
+
`Invalid role [${theirRole}] passed to <Dialog />. Only \`dialog\` and and \`alertdialog\` are supported. Using \`dialog\` instead.`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return "dialog";
|
|
47
|
+
});
|
|
48
|
+
const usesOpenClosedState = useOpenClosed();
|
|
49
|
+
const open = $derived(
|
|
50
|
+
theirOpen === void 0 && usesOpenClosedState !== null ? (usesOpenClosedState.value & State.Open) === State.Open : theirOpen
|
|
51
|
+
);
|
|
52
|
+
const ownerDocument = $derived(getOwnerDocument(ref));
|
|
53
|
+
const dialogState = $derived(open ? DialogStates.Open : DialogStates.Closed);
|
|
54
|
+
let _state = $state({
|
|
55
|
+
titleId: null,
|
|
56
|
+
panelRef: null
|
|
57
|
+
});
|
|
58
|
+
const close = $derived(() => onclose(false));
|
|
59
|
+
const setTitleId = (id2) => _state.titleId = id2;
|
|
60
|
+
const enabled = $derived(dialogState === DialogStates.Open);
|
|
61
|
+
const nestedPortals = useNestedPortals();
|
|
62
|
+
const { portals } = $derived(nestedPortals);
|
|
63
|
+
const defaultContainer = {
|
|
64
|
+
get current() {
|
|
65
|
+
return _state.panelRef ?? ref;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const mainTreeNode = useMainTreeNode();
|
|
69
|
+
let { resolvedContainers: resolvedRootContainers } = $derived(
|
|
70
|
+
useRootContainers({
|
|
71
|
+
get mainTreeNode() {
|
|
72
|
+
return mainTreeNode.node;
|
|
73
|
+
},
|
|
74
|
+
get portals() {
|
|
75
|
+
return portals;
|
|
76
|
+
},
|
|
77
|
+
get defaultContainers() {
|
|
78
|
+
return defaultContainer.current ? [defaultContainer.current] : [];
|
|
51
79
|
}
|
|
52
|
-
|
|
53
|
-
return "dialog"
|
|
54
80
|
})
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const nestedPortals = useNestedPortals()
|
|
79
|
-
const { portals } = $derived(nestedPortals)
|
|
80
|
-
|
|
81
|
-
// We use this because reading these values during initial render(s)
|
|
82
|
-
// can result in `null` rather then the actual elements
|
|
83
|
-
// This doesn't happen when using certain components like a
|
|
84
|
-
// `<Dialog.Title>` because they cause the parent to re-render
|
|
85
|
-
const defaultContainer: { readonly current: HTMLElement | undefined } = {
|
|
86
|
-
get current() {
|
|
87
|
-
return _state.panelRef ?? ref
|
|
88
|
-
},
|
|
81
|
+
);
|
|
82
|
+
const isClosing = $derived(
|
|
83
|
+
usesOpenClosedState !== null ? (usesOpenClosedState.value & State.Closing) === State.Closing : false
|
|
84
|
+
);
|
|
85
|
+
const inertOthersEnabled = $derived(__demoMode ? false : isClosing ? false : enabled);
|
|
86
|
+
useInertOthers({
|
|
87
|
+
get enabled() {
|
|
88
|
+
return inertOthersEnabled;
|
|
89
|
+
},
|
|
90
|
+
elements: {
|
|
91
|
+
get allowed() {
|
|
92
|
+
return [
|
|
93
|
+
// Allow the headlessui-portal of the Dialog to be interactive. This
|
|
94
|
+
// contains the current dialog and the necessary focus guard elements.
|
|
95
|
+
ref?.closest("[data-headlessui-portal]") ?? null
|
|
96
|
+
];
|
|
97
|
+
},
|
|
98
|
+
get disallowed() {
|
|
99
|
+
return [
|
|
100
|
+
// Disallow the "main" tree root node
|
|
101
|
+
mainTreeNode.node?.closest("body > *:not(#headlessui-portal-root)") ?? null
|
|
102
|
+
];
|
|
103
|
+
}
|
|
89
104
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// Ensure other elements can't be interacted with
|
|
116
|
-
const inertOthersEnabled = $derived(__demoMode ? false : isClosing ? false : enabled)
|
|
117
|
-
useInertOthers({
|
|
118
|
-
get enabled() {
|
|
119
|
-
return inertOthersEnabled
|
|
120
|
-
},
|
|
121
|
-
elements: {
|
|
122
|
-
get allowed() {
|
|
123
|
-
return [
|
|
124
|
-
// Allow the headlessui-portal of the Dialog to be interactive. This
|
|
125
|
-
// contains the current dialog and the necessary focus guard elements.
|
|
126
|
-
ref?.closest<HTMLElement>("[data-headlessui-portal]") ?? null,
|
|
127
|
-
]
|
|
128
|
-
},
|
|
129
|
-
get disallowed() {
|
|
130
|
-
return [
|
|
131
|
-
// Disallow the "main" tree root node
|
|
132
|
-
mainTreeNode.node?.closest<HTMLElement>("body > *:not(#headlessui-portal-root)") ?? null,
|
|
133
|
-
]
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
// Close Dialog on outside click
|
|
139
|
-
useOutsideClick({
|
|
140
|
-
get enabled() {
|
|
141
|
-
return enabled
|
|
142
|
-
},
|
|
143
|
-
get containers() {
|
|
144
|
-
return resolvedRootContainers
|
|
145
|
-
},
|
|
146
|
-
cb(event) {
|
|
147
|
-
event.preventDefault()
|
|
148
|
-
close()
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
// Handle `Escape` to close
|
|
153
|
-
useEscape({
|
|
154
|
-
get enabled() {
|
|
155
|
-
return enabled
|
|
156
|
-
},
|
|
157
|
-
get view() {
|
|
158
|
-
return ownerDocument?.defaultView ?? null
|
|
159
|
-
},
|
|
160
|
-
cb(event) {
|
|
161
|
-
event.preventDefault()
|
|
162
|
-
event.stopPropagation()
|
|
163
|
-
|
|
164
|
-
// Ensure that we blur the current activeElement to prevent maintaining
|
|
165
|
-
// focus and potentially scrolling the page to the end (because the Dialog
|
|
166
|
-
// is rendered in a Portal at the end of the document.body and the browser
|
|
167
|
-
// tries to keep the focused element in view)
|
|
168
|
-
//
|
|
169
|
-
// Typically only happens in Safari.
|
|
170
|
-
if (
|
|
171
|
-
document.activeElement &&
|
|
172
|
-
"blur" in document.activeElement &&
|
|
173
|
-
typeof document.activeElement.blur === "function"
|
|
174
|
-
) {
|
|
175
|
-
document.activeElement.blur()
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
close()
|
|
179
|
-
},
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
// Scroll lock
|
|
183
|
-
const scrollLockEnabled = $derived(__demoMode ? false : isClosing ? false : enabled)
|
|
184
|
-
useScrollLock({
|
|
185
|
-
get enabled() {
|
|
186
|
-
return scrollLockEnabled
|
|
187
|
-
},
|
|
188
|
-
get ownerDocument() {
|
|
189
|
-
return ownerDocument
|
|
190
|
-
},
|
|
191
|
-
resolveAllowedContainers() {
|
|
192
|
-
return resolvedRootContainers
|
|
193
|
-
},
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
// Ensure we close the dialog as soon as the dialog itself becomes hidden
|
|
197
|
-
useOnDisappear({
|
|
198
|
-
get enabled() {
|
|
199
|
-
return enabled
|
|
200
|
-
},
|
|
201
|
-
get ref() {
|
|
202
|
-
return ref
|
|
203
|
-
},
|
|
204
|
-
get ondisappear() {
|
|
205
|
-
return close
|
|
206
|
-
},
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
const describedby = useDescriptions()
|
|
210
|
-
|
|
211
|
-
setContext<DialogContext>("DialogContext", {
|
|
212
|
-
get titleId() {
|
|
213
|
-
return _state.titleId
|
|
214
|
-
},
|
|
215
|
-
get panelRef() {
|
|
216
|
-
return _state.panelRef
|
|
217
|
-
},
|
|
218
|
-
get dialogState() {
|
|
219
|
-
return dialogState
|
|
220
|
-
},
|
|
221
|
-
get close() {
|
|
222
|
-
return close
|
|
223
|
-
},
|
|
224
|
-
get unmount() {
|
|
225
|
-
return unmount
|
|
226
|
-
},
|
|
227
|
-
setTitleId,
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
const slot = $derived({ open: dialogState === DialogStates.Open } satisfies DialogRenderPropArg)
|
|
231
|
-
|
|
232
|
-
const ourProps = $derived({
|
|
233
|
-
id,
|
|
234
|
-
role,
|
|
235
|
-
tabIndex: -1,
|
|
236
|
-
"aria-modal": __demoMode ? undefined : dialogState === DialogStates.Open ? true : undefined,
|
|
237
|
-
"aria-labelledby": _state.titleId,
|
|
238
|
-
"aria-describedby": describedby.value,
|
|
239
|
-
unmount,
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
const shouldMoveFocusInside = !useIsTouchDevice().value
|
|
243
|
-
const focusTrapFeatures = $derived.by(() => {
|
|
244
|
-
let focusTrapFeatures = FocusTrapFeatures.None
|
|
245
|
-
|
|
246
|
-
if (enabled && !__demoMode) {
|
|
247
|
-
focusTrapFeatures |= FocusTrapFeatures.RestoreFocus
|
|
248
|
-
focusTrapFeatures |= FocusTrapFeatures.TabLock
|
|
249
|
-
|
|
250
|
-
if (autofocus) {
|
|
251
|
-
focusTrapFeatures |= FocusTrapFeatures.AutoFocus
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (shouldMoveFocusInside) {
|
|
255
|
-
focusTrapFeatures |= FocusTrapFeatures.InitialFocus
|
|
256
|
-
}
|
|
105
|
+
});
|
|
106
|
+
useOutsideClick({
|
|
107
|
+
get enabled() {
|
|
108
|
+
return enabled;
|
|
109
|
+
},
|
|
110
|
+
get containers() {
|
|
111
|
+
return resolvedRootContainers;
|
|
112
|
+
},
|
|
113
|
+
cb(event) {
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
close();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
useEscape({
|
|
119
|
+
get enabled() {
|
|
120
|
+
return enabled;
|
|
121
|
+
},
|
|
122
|
+
get view() {
|
|
123
|
+
return ownerDocument?.defaultView ?? null;
|
|
124
|
+
},
|
|
125
|
+
cb(event) {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
event.stopPropagation();
|
|
128
|
+
if (document.activeElement && "blur" in document.activeElement && typeof document.activeElement.blur === "function") {
|
|
129
|
+
document.activeElement.blur();
|
|
257
130
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
131
|
+
close();
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
const scrollLockEnabled = $derived(__demoMode ? false : isClosing ? false : enabled);
|
|
135
|
+
useScrollLock({
|
|
136
|
+
get enabled() {
|
|
137
|
+
return scrollLockEnabled;
|
|
138
|
+
},
|
|
139
|
+
get ownerDocument() {
|
|
140
|
+
return ownerDocument;
|
|
141
|
+
},
|
|
142
|
+
resolveAllowedContainers() {
|
|
143
|
+
return resolvedRootContainers;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
useOnDisappear({
|
|
147
|
+
get enabled() {
|
|
148
|
+
return enabled;
|
|
149
|
+
},
|
|
150
|
+
get ref() {
|
|
151
|
+
return ref;
|
|
152
|
+
},
|
|
153
|
+
get ondisappear() {
|
|
154
|
+
return close;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
const describedby = useDescriptions();
|
|
158
|
+
setContext("DialogContext", {
|
|
159
|
+
get titleId() {
|
|
160
|
+
return _state.titleId;
|
|
161
|
+
},
|
|
162
|
+
get panelRef() {
|
|
163
|
+
return _state.panelRef;
|
|
164
|
+
},
|
|
165
|
+
get dialogState() {
|
|
166
|
+
return dialogState;
|
|
167
|
+
},
|
|
168
|
+
get close() {
|
|
169
|
+
return close;
|
|
170
|
+
},
|
|
171
|
+
get unmount() {
|
|
172
|
+
return unmount;
|
|
173
|
+
},
|
|
174
|
+
setTitleId
|
|
175
|
+
});
|
|
176
|
+
const slot = $derived({ open: dialogState === DialogStates.Open });
|
|
177
|
+
const ourProps = $derived({
|
|
178
|
+
id,
|
|
179
|
+
role,
|
|
180
|
+
tabIndex: -1,
|
|
181
|
+
"aria-modal": __demoMode ? void 0 : dialogState === DialogStates.Open ? true : void 0,
|
|
182
|
+
"aria-labelledby": _state.titleId,
|
|
183
|
+
"aria-describedby": describedby.value,
|
|
184
|
+
unmount
|
|
185
|
+
});
|
|
186
|
+
const shouldMoveFocusInside = !useIsTouchDevice().value;
|
|
187
|
+
const focusTrapFeatures = $derived.by(() => {
|
|
188
|
+
let focusTrapFeatures2 = FocusTrapFeatures.None;
|
|
189
|
+
if (enabled && !__demoMode) {
|
|
190
|
+
focusTrapFeatures2 |= FocusTrapFeatures.RestoreFocus;
|
|
191
|
+
focusTrapFeatures2 |= FocusTrapFeatures.TabLock;
|
|
192
|
+
if (autofocus) {
|
|
193
|
+
focusTrapFeatures2 |= FocusTrapFeatures.AutoFocus;
|
|
194
|
+
}
|
|
195
|
+
if (shouldMoveFocusInside) {
|
|
196
|
+
focusTrapFeatures2 |= FocusTrapFeatures.InitialFocus;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return focusTrapFeatures2;
|
|
200
|
+
});
|
|
201
|
+
clearOpenClosedContext();
|
|
202
|
+
createCloseContext({
|
|
203
|
+
get close() {
|
|
204
|
+
return close;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
268
207
|
</script>
|
|
269
208
|
|
|
270
209
|
<ForcePortalRoot force={true}>
|
package/dist/field/Field.svelte
CHANGED
|
@@ -1,54 +1,31 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { ElementType, Props } from "../utils/types.js"
|
|
3
|
-
|
|
4
|
-
let DEFAULT_FIELD_TAG = "div" as const
|
|
5
|
-
|
|
6
|
-
type FieldRenderPropArg = {}
|
|
7
|
-
type FieldPropsWeControl = never
|
|
8
|
-
|
|
9
|
-
export type FieldProps<TTag extends ElementType = typeof DEFAULT_FIELD_TAG> = Props<
|
|
10
|
-
TTag,
|
|
11
|
-
FieldRenderPropArg,
|
|
12
|
-
FieldPropsWeControl,
|
|
13
|
-
{
|
|
14
|
-
disabled?: boolean
|
|
15
|
-
}
|
|
16
|
-
>
|
|
1
|
+
<script lang="ts" module>let DEFAULT_FIELD_TAG = "div";
|
|
17
2
|
</script>
|
|
18
3
|
|
|
19
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FIELD_TAG">
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const slot = $derived({ disabled })
|
|
47
|
-
|
|
48
|
-
const ourProps = $derived({
|
|
49
|
-
disabled: disabled || undefined,
|
|
50
|
-
"aria-disabled": disabled || undefined,
|
|
51
|
-
})
|
|
4
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FIELD_TAG">import { useDisabled } from "../hooks/use-disabled.js";
|
|
5
|
+
import { createIdContext } from "../utils/id.js";
|
|
6
|
+
import { stateFromSlot } from "../utils/state.js";
|
|
7
|
+
import { nanoid } from "nanoid";
|
|
8
|
+
import { setContext } from "svelte";
|
|
9
|
+
import { useLabels } from "../label/context.svelte.js";
|
|
10
|
+
import { useDescriptions } from "../description/context.svelte.js";
|
|
11
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
12
|
+
let { ref = $bindable(), disabled: ownDisabled = false, ...theirProps } = $props();
|
|
13
|
+
const inputId = `headlessui-control-${nanoid(8)}`;
|
|
14
|
+
createIdContext(inputId);
|
|
15
|
+
useLabels();
|
|
16
|
+
useDescriptions();
|
|
17
|
+
const providedDisabled = useDisabled();
|
|
18
|
+
const disabled = $derived(providedDisabled.value || ownDisabled);
|
|
19
|
+
setContext("DisabledContext", {
|
|
20
|
+
get value() {
|
|
21
|
+
return disabled;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
const slot = $derived({ disabled });
|
|
25
|
+
const ourProps = $derived({
|
|
26
|
+
disabled: disabled || void 0,
|
|
27
|
+
"aria-disabled": disabled || void 0
|
|
28
|
+
});
|
|
52
29
|
</script>
|
|
53
30
|
|
|
54
31
|
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_FIELD_TAG} name="Field" bind:ref />
|
|
@@ -1,55 +1,34 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { ElementType, Props } from "../utils/types.js"
|
|
3
|
-
let DEFAULT_FIELDSET_TAG = "fieldset" as const
|
|
4
|
-
|
|
5
|
-
type FieldsetRenderPropArg = {}
|
|
6
|
-
type FieldsetPropsWeControl = "aria-labelledby" | "aria-disabled" | "role"
|
|
7
|
-
|
|
8
|
-
export type FieldsetProps<TTag extends ElementType = typeof DEFAULT_FIELDSET_TAG> = Props<
|
|
9
|
-
TTag,
|
|
10
|
-
FieldsetRenderPropArg,
|
|
11
|
-
FieldsetPropsWeControl,
|
|
12
|
-
{
|
|
13
|
-
disabled?: boolean
|
|
14
|
-
}
|
|
15
|
-
>
|
|
1
|
+
<script lang="ts" module>let DEFAULT_FIELDSET_TAG = "fieldset";
|
|
16
2
|
</script>
|
|
17
3
|
|
|
18
|
-
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FIELDSET_TAG">
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
: {
|
|
48
|
-
role: "group",
|
|
49
|
-
"aria-labelledby": labelledBy.value,
|
|
50
|
-
"aria-disabled": disabled || undefined,
|
|
51
|
-
}
|
|
52
|
-
)
|
|
4
|
+
<script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FIELDSET_TAG">import { setContext } from "svelte";
|
|
5
|
+
import { useDisabled } from "../hooks/use-disabled.js";
|
|
6
|
+
import { useLabels } from "../label/context.svelte.js";
|
|
7
|
+
import ElementOrComponent from "../utils/ElementOrComponent.svelte";
|
|
8
|
+
let {
|
|
9
|
+
ref = $bindable(),
|
|
10
|
+
disabled: ownDisabled = false,
|
|
11
|
+
...theirProps
|
|
12
|
+
} = $props();
|
|
13
|
+
const providedDisabled = useDisabled();
|
|
14
|
+
const disabled = $derived(providedDisabled.value || ownDisabled);
|
|
15
|
+
setContext("DisabledContext", {
|
|
16
|
+
get value() {
|
|
17
|
+
return disabled;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const labelledBy = useLabels();
|
|
21
|
+
const slot = $derived({ disabled });
|
|
22
|
+
const ourProps = $derived(
|
|
23
|
+
(theirProps.as ?? DEFAULT_FIELDSET_TAG) === "fieldset" ? {
|
|
24
|
+
"aria-labelledby": labelledBy.value,
|
|
25
|
+
disabled: disabled || void 0
|
|
26
|
+
} : {
|
|
27
|
+
role: "group",
|
|
28
|
+
"aria-labelledby": labelledBy.value,
|
|
29
|
+
"aria-disabled": disabled || void 0
|
|
30
|
+
}
|
|
31
|
+
);
|
|
53
32
|
</script>
|
|
54
33
|
|
|
55
34
|
<ElementOrComponent {ourProps} {theirProps} {slot} defaultTag={DEFAULT_FIELDSET_TAG} name="Fieldset" bind:ref />
|