@arun-dev/headless 4.0.0 → 4.2.0
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/checkbox/index.cjs +302 -0
- package/dist/checkbox/index.d.cts +123 -0
- package/dist/checkbox/index.d.ts +123 -0
- package/dist/checkbox/index.js +138 -0
- package/dist/chunk-IWUVUY76.js +29 -0
- package/dist/radio-group/index.cjs +298 -0
- package/dist/radio-group/index.d.cts +128 -0
- package/dist/radio-group/index.d.ts +128 -0
- package/dist/radio-group/index.js +157 -0
- package/dist/switch/index.cjs +45 -35
- package/dist/switch/index.js +11 -24
- package/package.json +21 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useControlled
|
|
3
|
+
} from "../chunk-UEIB3I3T.js";
|
|
4
|
+
import {
|
|
5
|
+
__export,
|
|
6
|
+
useRender
|
|
7
|
+
} from "../chunk-OQTWWZ4B.js";
|
|
8
|
+
|
|
9
|
+
// src/radio-group/index.parts.ts
|
|
10
|
+
var index_parts_exports = {};
|
|
11
|
+
__export(index_parts_exports, {
|
|
12
|
+
Item: () => RadioGroupItem,
|
|
13
|
+
Root: () => RadioGroupRoot
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// src/radio-group/RadioGroupRoot.tsx
|
|
17
|
+
import { useCallback, useEffect, useId, useMemo, useRef } from "react";
|
|
18
|
+
|
|
19
|
+
// src/radio-group/RadioGroupRootContext.ts
|
|
20
|
+
import { createContext, useContext } from "react";
|
|
21
|
+
var RadioGroupRootContext = createContext(null);
|
|
22
|
+
function useRadioGroupRootContext() {
|
|
23
|
+
const context = useContext(RadioGroupRootContext);
|
|
24
|
+
if (context === null) {
|
|
25
|
+
throw new Error("<RadioGroup.Item> must be rendered inside <RadioGroup.Root>.");
|
|
26
|
+
}
|
|
27
|
+
return context;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/radio-group/radioGroupDataAttributes.ts
|
|
31
|
+
function radioGroupItemDataAttributes({ checked, disabled }) {
|
|
32
|
+
return {
|
|
33
|
+
"data-checked": checked ? "" : void 0,
|
|
34
|
+
"data-unchecked": checked ? void 0 : "",
|
|
35
|
+
"data-disabled": disabled ? "" : void 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function radioGroupDataAttributes({ disabled }) {
|
|
39
|
+
return {
|
|
40
|
+
"data-disabled": disabled ? "" : void 0
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/radio-group/RadioGroupRoot.tsx
|
|
45
|
+
import { jsx } from "react/jsx-runtime";
|
|
46
|
+
function radiosIn(root, name) {
|
|
47
|
+
if (!root) return [];
|
|
48
|
+
return [...root.querySelectorAll('input[type="radio"]')].filter(
|
|
49
|
+
(input) => input.name === name
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function RadioGroupRoot({
|
|
53
|
+
value: valueProp,
|
|
54
|
+
defaultValue,
|
|
55
|
+
onValueChange,
|
|
56
|
+
name: nameProp,
|
|
57
|
+
disabled = false,
|
|
58
|
+
required = false,
|
|
59
|
+
form,
|
|
60
|
+
className,
|
|
61
|
+
children,
|
|
62
|
+
render,
|
|
63
|
+
...rest
|
|
64
|
+
}) {
|
|
65
|
+
const [value, setValue] = useControlled({
|
|
66
|
+
controlled: valueProp,
|
|
67
|
+
default: defaultValue ?? null,
|
|
68
|
+
name: "RadioGroup.Root",
|
|
69
|
+
state: "value"
|
|
70
|
+
});
|
|
71
|
+
const generatedName = useId();
|
|
72
|
+
const name = nameProp ?? generatedName;
|
|
73
|
+
const commitValue = useCallback(
|
|
74
|
+
(next) => {
|
|
75
|
+
setValue(next);
|
|
76
|
+
onValueChange?.(next);
|
|
77
|
+
},
|
|
78
|
+
[setValue, onValueChange]
|
|
79
|
+
);
|
|
80
|
+
const elementRef = useRef(null);
|
|
81
|
+
const { current: initialValue } = useRef(value);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
const owner = radiosIn(elementRef.current, name)[0]?.form;
|
|
84
|
+
if (!owner) return;
|
|
85
|
+
function onReset(event) {
|
|
86
|
+
queueMicrotask(() => {
|
|
87
|
+
if (event.defaultPrevented) return;
|
|
88
|
+
for (const input of radiosIn(elementRef.current, name)) {
|
|
89
|
+
input.checked = input.value === value;
|
|
90
|
+
}
|
|
91
|
+
if (value === initialValue) return;
|
|
92
|
+
commitValue(initialValue);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
owner.addEventListener("reset", onReset);
|
|
96
|
+
return () => owner.removeEventListener("reset", onReset);
|
|
97
|
+
}, [name, value, commitValue, initialValue]);
|
|
98
|
+
const state = useMemo(
|
|
99
|
+
() => ({ value, disabled, required, name, form, select: commitValue }),
|
|
100
|
+
[value, disabled, required, name, form, commitValue]
|
|
101
|
+
);
|
|
102
|
+
const element = useRender({
|
|
103
|
+
render,
|
|
104
|
+
defaultTagName: "div",
|
|
105
|
+
props: {
|
|
106
|
+
role: "radiogroup",
|
|
107
|
+
"aria-disabled": disabled || void 0,
|
|
108
|
+
"aria-required": required || void 0,
|
|
109
|
+
...radioGroupDataAttributes(state),
|
|
110
|
+
className,
|
|
111
|
+
children,
|
|
112
|
+
ref: elementRef
|
|
113
|
+
},
|
|
114
|
+
consumerProps: rest
|
|
115
|
+
});
|
|
116
|
+
return /* @__PURE__ */ jsx(RadioGroupRootContext.Provider, { value: state, children: element });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/radio-group/RadioGroupItem.tsx
|
|
120
|
+
import { useMemo as useMemo2 } from "react";
|
|
121
|
+
function RadioGroupItem({
|
|
122
|
+
value,
|
|
123
|
+
disabled: disabledProp = false,
|
|
124
|
+
className,
|
|
125
|
+
render,
|
|
126
|
+
...rest
|
|
127
|
+
}) {
|
|
128
|
+
const group = useRadioGroupRootContext();
|
|
129
|
+
const disabled = group.disabled || disabledProp;
|
|
130
|
+
const checked = group.value === value;
|
|
131
|
+
const state = useMemo2(() => ({ checked, disabled }), [checked, disabled]);
|
|
132
|
+
return useRender({
|
|
133
|
+
render,
|
|
134
|
+
defaultTagName: "input",
|
|
135
|
+
props: {
|
|
136
|
+
type: "radio",
|
|
137
|
+
name: group.name,
|
|
138
|
+
value,
|
|
139
|
+
// Controlled from the group's value, so React restores it after any change the
|
|
140
|
+
// group declines — the platform never gets the last word on what is checked.
|
|
141
|
+
checked,
|
|
142
|
+
form: group.form,
|
|
143
|
+
required: group.required || void 0,
|
|
144
|
+
disabled: disabled || void 0,
|
|
145
|
+
...radioGroupItemDataAttributes(state),
|
|
146
|
+
className,
|
|
147
|
+
onChange() {
|
|
148
|
+
if (disabled) return;
|
|
149
|
+
group.select(value);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
consumerProps: rest
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
export {
|
|
156
|
+
index_parts_exports as RadioGroup
|
|
157
|
+
};
|
package/dist/switch/index.cjs
CHANGED
|
@@ -32,7 +32,7 @@ __export(index_parts_exports, {
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
// src/switch/SwitchRoot.tsx
|
|
35
|
-
var
|
|
35
|
+
var import_react5 = require("react");
|
|
36
36
|
|
|
37
37
|
// src/core/useControlled.ts
|
|
38
38
|
var import_react = require("react");
|
|
@@ -67,8 +67,34 @@ function useControlled({
|
|
|
67
67
|
return [value, setValue];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// src/core/
|
|
70
|
+
// src/core/useFormReset.ts
|
|
71
71
|
var import_react2 = require("react");
|
|
72
|
+
function useFormReset({
|
|
73
|
+
elementRef,
|
|
74
|
+
inputRef,
|
|
75
|
+
value,
|
|
76
|
+
inputChecked,
|
|
77
|
+
commit
|
|
78
|
+
}) {
|
|
79
|
+
const { current: initialValue } = (0, import_react2.useRef)(value);
|
|
80
|
+
(0, import_react2.useEffect)(() => {
|
|
81
|
+
const form = elementRef.current?.form;
|
|
82
|
+
if (!form) return;
|
|
83
|
+
function onReset(event) {
|
|
84
|
+
queueMicrotask(() => {
|
|
85
|
+
if (event.defaultPrevented) return;
|
|
86
|
+
if (inputRef.current) inputRef.current.checked = inputChecked;
|
|
87
|
+
if (value === initialValue) return;
|
|
88
|
+
commit(initialValue);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
form.addEventListener("reset", onReset);
|
|
92
|
+
return () => form.removeEventListener("reset", onReset);
|
|
93
|
+
}, [elementRef, inputRef, value, inputChecked, commit, initialValue]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/core/useRender.ts
|
|
97
|
+
var import_react3 = require("react");
|
|
72
98
|
|
|
73
99
|
// src/core/mergeProps.ts
|
|
74
100
|
function isEventHandler(key) {
|
|
@@ -150,17 +176,17 @@ function useRender({
|
|
|
150
176
|
consumerProps
|
|
151
177
|
}) {
|
|
152
178
|
const merged = mergeProps(props, consumerProps);
|
|
153
|
-
if ((0,
|
|
154
|
-
return (0,
|
|
179
|
+
if ((0, import_react3.isValidElement)(render)) {
|
|
180
|
+
return (0, import_react3.cloneElement)(render, mergeProps(merged, render.props));
|
|
155
181
|
}
|
|
156
|
-
return (0,
|
|
182
|
+
return (0, import_react3.createElement)(defaultTagName, merged);
|
|
157
183
|
}
|
|
158
184
|
|
|
159
185
|
// src/switch/SwitchRootContext.ts
|
|
160
|
-
var
|
|
161
|
-
var SwitchRootContext = (0,
|
|
186
|
+
var import_react4 = require("react");
|
|
187
|
+
var SwitchRootContext = (0, import_react4.createContext)(null);
|
|
162
188
|
function useSwitchRootContext() {
|
|
163
|
-
const context = (0,
|
|
189
|
+
const context = (0, import_react4.useContext)(SwitchRootContext);
|
|
164
190
|
if (context === null) {
|
|
165
191
|
throw new Error("<Switch.Thumb> must be rendered inside <Switch.Root>.");
|
|
166
192
|
}
|
|
@@ -196,17 +222,23 @@ function SwitchRoot({
|
|
|
196
222
|
name: "Switch.Root",
|
|
197
223
|
state: "checked"
|
|
198
224
|
});
|
|
199
|
-
const commitChecked = (0,
|
|
225
|
+
const commitChecked = (0, import_react5.useCallback)(
|
|
200
226
|
(next) => {
|
|
201
227
|
setChecked(next);
|
|
202
228
|
onCheckedChange?.(next);
|
|
203
229
|
},
|
|
204
230
|
[setChecked, onCheckedChange]
|
|
205
231
|
);
|
|
206
|
-
const state = (0,
|
|
207
|
-
const elementRef = (0,
|
|
208
|
-
const inputRef = (0,
|
|
209
|
-
useFormReset({
|
|
232
|
+
const state = (0, import_react5.useMemo)(() => ({ checked, disabled }), [checked, disabled]);
|
|
233
|
+
const elementRef = (0, import_react5.useRef)(null);
|
|
234
|
+
const inputRef = (0, import_react5.useRef)(null);
|
|
235
|
+
useFormReset({
|
|
236
|
+
elementRef,
|
|
237
|
+
inputRef,
|
|
238
|
+
value: checked,
|
|
239
|
+
inputChecked: checked,
|
|
240
|
+
commit: commitChecked
|
|
241
|
+
});
|
|
210
242
|
const element = useRender({
|
|
211
243
|
render,
|
|
212
244
|
defaultTagName: "button",
|
|
@@ -245,28 +277,6 @@ function SwitchRoot({
|
|
|
245
277
|
) : null
|
|
246
278
|
] });
|
|
247
279
|
}
|
|
248
|
-
function useFormReset({
|
|
249
|
-
elementRef,
|
|
250
|
-
inputRef,
|
|
251
|
-
checked,
|
|
252
|
-
commitChecked
|
|
253
|
-
}) {
|
|
254
|
-
const { current: initialChecked } = (0, import_react4.useRef)(checked);
|
|
255
|
-
(0, import_react4.useEffect)(() => {
|
|
256
|
-
const form = elementRef.current?.form;
|
|
257
|
-
if (!form) return;
|
|
258
|
-
function onReset(event) {
|
|
259
|
-
queueMicrotask(() => {
|
|
260
|
-
if (event.defaultPrevented) return;
|
|
261
|
-
if (inputRef.current) inputRef.current.checked = checked;
|
|
262
|
-
if (checked === initialChecked) return;
|
|
263
|
-
commitChecked(initialChecked);
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
form.addEventListener("reset", onReset);
|
|
267
|
-
return () => form.removeEventListener("reset", onReset);
|
|
268
|
-
}, [elementRef, inputRef, checked, commitChecked, initialChecked]);
|
|
269
|
-
}
|
|
270
280
|
|
|
271
281
|
// src/switch/SwitchThumb.tsx
|
|
272
282
|
function SwitchThumb({ className, children, render, ...rest }) {
|
package/dist/switch/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useFormReset
|
|
3
|
+
} from "../chunk-IWUVUY76.js";
|
|
1
4
|
import {
|
|
2
5
|
useControlled
|
|
3
6
|
} from "../chunk-UEIB3I3T.js";
|
|
@@ -14,7 +17,7 @@ __export(index_parts_exports, {
|
|
|
14
17
|
});
|
|
15
18
|
|
|
16
19
|
// src/switch/SwitchRoot.tsx
|
|
17
|
-
import { useCallback,
|
|
20
|
+
import { useCallback, useMemo, useRef } from "react";
|
|
18
21
|
|
|
19
22
|
// src/switch/SwitchRootContext.ts
|
|
20
23
|
import { createContext, useContext } from "react";
|
|
@@ -66,7 +69,13 @@ function SwitchRoot({
|
|
|
66
69
|
const state = useMemo(() => ({ checked, disabled }), [checked, disabled]);
|
|
67
70
|
const elementRef = useRef(null);
|
|
68
71
|
const inputRef = useRef(null);
|
|
69
|
-
useFormReset({
|
|
72
|
+
useFormReset({
|
|
73
|
+
elementRef,
|
|
74
|
+
inputRef,
|
|
75
|
+
value: checked,
|
|
76
|
+
inputChecked: checked,
|
|
77
|
+
commit: commitChecked
|
|
78
|
+
});
|
|
70
79
|
const element = useRender({
|
|
71
80
|
render,
|
|
72
81
|
defaultTagName: "button",
|
|
@@ -105,28 +114,6 @@ function SwitchRoot({
|
|
|
105
114
|
) : null
|
|
106
115
|
] });
|
|
107
116
|
}
|
|
108
|
-
function useFormReset({
|
|
109
|
-
elementRef,
|
|
110
|
-
inputRef,
|
|
111
|
-
checked,
|
|
112
|
-
commitChecked
|
|
113
|
-
}) {
|
|
114
|
-
const { current: initialChecked } = useRef(checked);
|
|
115
|
-
useEffect(() => {
|
|
116
|
-
const form = elementRef.current?.form;
|
|
117
|
-
if (!form) return;
|
|
118
|
-
function onReset(event) {
|
|
119
|
-
queueMicrotask(() => {
|
|
120
|
-
if (event.defaultPrevented) return;
|
|
121
|
-
if (inputRef.current) inputRef.current.checked = checked;
|
|
122
|
-
if (checked === initialChecked) return;
|
|
123
|
-
commitChecked(initialChecked);
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
form.addEventListener("reset", onReset);
|
|
127
|
-
return () => form.removeEventListener("reset", onReset);
|
|
128
|
-
}, [elementRef, inputRef, checked, commitChecked, initialChecked]);
|
|
129
|
-
}
|
|
130
117
|
|
|
131
118
|
// src/switch/SwitchThumb.tsx
|
|
132
119
|
function SwitchThumb({ className, children, render, ...rest }) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arun-dev/headless",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Unstyled React behaviour primitives — render engine, controlled/uncontrolled state, and data-* state projection. Ships no CSS and no class names.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,6 +44,26 @@
|
|
|
44
44
|
"default": "./dist/button/index.cjs"
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
|
+
"./checkbox": {
|
|
48
|
+
"import": {
|
|
49
|
+
"types": "./dist/checkbox/index.d.ts",
|
|
50
|
+
"default": "./dist/checkbox/index.js"
|
|
51
|
+
},
|
|
52
|
+
"require": {
|
|
53
|
+
"types": "./dist/checkbox/index.d.cts",
|
|
54
|
+
"default": "./dist/checkbox/index.cjs"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"./radio-group": {
|
|
58
|
+
"import": {
|
|
59
|
+
"types": "./dist/radio-group/index.d.ts",
|
|
60
|
+
"default": "./dist/radio-group/index.js"
|
|
61
|
+
},
|
|
62
|
+
"require": {
|
|
63
|
+
"types": "./dist/radio-group/index.d.cts",
|
|
64
|
+
"default": "./dist/radio-group/index.cjs"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
47
67
|
"./switch": {
|
|
48
68
|
"import": {
|
|
49
69
|
"types": "./dist/switch/index.d.ts",
|