@arun-dev/headless 1.0.0 → 2.1.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/button/index.cjs +25 -10
- package/dist/button/index.js +4 -3
- package/dist/{chunk-HWG3GMTO.js → chunk-PYLPZVWQ.js} +23 -9
- package/dist/{chunk-2XSRAJHB.js → chunk-TNMGZWHA.js} +1 -1
- package/dist/index.cjs +23 -9
- package/dist/index.d.cts +23 -10
- package/dist/index.d.ts +23 -10
- package/dist/index.js +1 -1
- package/dist/switch/index.cjs +41 -27
- package/dist/switch/index.d.cts +22 -3
- package/dist/switch/index.d.ts +22 -3
- package/dist/switch/index.js +20 -20
- package/package.json +1 -1
package/dist/button/index.cjs
CHANGED
|
@@ -60,14 +60,33 @@ function isSyntheticEvent(event) {
|
|
|
60
60
|
return typeof event === "object" && event !== null && "nativeEvent" in event;
|
|
61
61
|
}
|
|
62
62
|
function makeEventPreventable(event) {
|
|
63
|
+
if (Object.prototype.hasOwnProperty.call(event, "preventComponentHandler")) return;
|
|
63
64
|
const target = event;
|
|
64
|
-
|
|
65
|
+
const prevent = () => {
|
|
65
66
|
target.componentHandlerPrevented = true;
|
|
66
67
|
};
|
|
68
|
+
target.preventComponentHandler = prevent;
|
|
69
|
+
const native = event.nativeEvent;
|
|
70
|
+
const stopImmediate = native?.stopImmediatePropagation?.bind(native);
|
|
71
|
+
if (native && stopImmediate) {
|
|
72
|
+
native.stopImmediatePropagation = () => {
|
|
73
|
+
stopImmediate();
|
|
74
|
+
prevent();
|
|
75
|
+
};
|
|
76
|
+
}
|
|
67
77
|
}
|
|
68
78
|
function isComponentHandlerPrevented(event) {
|
|
69
79
|
return typeof event === "object" && event !== null && event.componentHandlerPrevented === true;
|
|
70
80
|
}
|
|
81
|
+
function chainHandlers(earlier, value) {
|
|
82
|
+
return (...args) => {
|
|
83
|
+
const event = args[0];
|
|
84
|
+
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
85
|
+
value(...args);
|
|
86
|
+
if (isComponentHandlerPrevented(event)) return;
|
|
87
|
+
earlier(...args);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
71
90
|
function mergeProps(...objects) {
|
|
72
91
|
const merged = {};
|
|
73
92
|
for (const props of objects) {
|
|
@@ -77,13 +96,7 @@ function mergeProps(...objects) {
|
|
|
77
96
|
if (value === void 0) continue;
|
|
78
97
|
if (isEventHandler(key) && typeof value === "function") {
|
|
79
98
|
const earlier = merged[key];
|
|
80
|
-
merged[key] = typeof earlier === "function" ? (
|
|
81
|
-
const event = args[0];
|
|
82
|
-
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
83
|
-
value(...args);
|
|
84
|
-
if (isComponentHandlerPrevented(event)) return;
|
|
85
|
-
earlier(...args);
|
|
86
|
-
} : value;
|
|
99
|
+
merged[key] = typeof earlier === "function" ? chainHandlers(earlier, value) : value;
|
|
87
100
|
} else if (key === "className") {
|
|
88
101
|
merged.className = merged.className ? `${String(merged.className)} ${String(value)}` : value;
|
|
89
102
|
} else if (key === "style") {
|
|
@@ -123,11 +136,12 @@ function useRender({
|
|
|
123
136
|
render,
|
|
124
137
|
defaultTagName,
|
|
125
138
|
props,
|
|
139
|
+
consumerProps,
|
|
126
140
|
state,
|
|
127
141
|
stateAttributes
|
|
128
142
|
}) {
|
|
129
143
|
const attributes = state ? getStateAttributes(state, stateAttributes) : {};
|
|
130
|
-
const merged = mergeProps(attributes,
|
|
144
|
+
const merged = mergeProps(attributes, props, consumerProps);
|
|
131
145
|
if ((0, import_react.isValidElement)(render)) {
|
|
132
146
|
return (0, import_react.cloneElement)(render, mergeProps(merged, render.props));
|
|
133
147
|
}
|
|
@@ -239,7 +253,8 @@ function Button({
|
|
|
239
253
|
return useRender({
|
|
240
254
|
render: safeRender,
|
|
241
255
|
defaultTagName: "button",
|
|
242
|
-
props:
|
|
256
|
+
props: { role, className, children, ref: buttonRef },
|
|
257
|
+
consumerProps: elementProps
|
|
243
258
|
});
|
|
244
259
|
}
|
|
245
260
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/button/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
retractActivationProps,
|
|
3
3
|
useButton
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-TNMGZWHA.js";
|
|
5
5
|
import {
|
|
6
6
|
useRender
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-PYLPZVWQ.js";
|
|
8
8
|
|
|
9
9
|
// src/button/Button.tsx
|
|
10
10
|
import { cloneElement } from "react";
|
|
@@ -24,7 +24,8 @@ function Button({
|
|
|
24
24
|
return useRender({
|
|
25
25
|
render: safeRender,
|
|
26
26
|
defaultTagName: "button",
|
|
27
|
-
props:
|
|
27
|
+
props: { role, className, children, ref: buttonRef },
|
|
28
|
+
consumerProps: elementProps
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
export {
|
|
@@ -34,14 +34,33 @@ function isSyntheticEvent(event) {
|
|
|
34
34
|
return typeof event === "object" && event !== null && "nativeEvent" in event;
|
|
35
35
|
}
|
|
36
36
|
function makeEventPreventable(event) {
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(event, "preventComponentHandler")) return;
|
|
37
38
|
const target = event;
|
|
38
|
-
|
|
39
|
+
const prevent = () => {
|
|
39
40
|
target.componentHandlerPrevented = true;
|
|
40
41
|
};
|
|
42
|
+
target.preventComponentHandler = prevent;
|
|
43
|
+
const native = event.nativeEvent;
|
|
44
|
+
const stopImmediate = native?.stopImmediatePropagation?.bind(native);
|
|
45
|
+
if (native && stopImmediate) {
|
|
46
|
+
native.stopImmediatePropagation = () => {
|
|
47
|
+
stopImmediate();
|
|
48
|
+
prevent();
|
|
49
|
+
};
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
function isComponentHandlerPrevented(event) {
|
|
43
53
|
return typeof event === "object" && event !== null && event.componentHandlerPrevented === true;
|
|
44
54
|
}
|
|
55
|
+
function chainHandlers(earlier, value) {
|
|
56
|
+
return (...args) => {
|
|
57
|
+
const event = args[0];
|
|
58
|
+
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
59
|
+
value(...args);
|
|
60
|
+
if (isComponentHandlerPrevented(event)) return;
|
|
61
|
+
earlier(...args);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
45
64
|
function mergeProps(...objects) {
|
|
46
65
|
const merged = {};
|
|
47
66
|
for (const props of objects) {
|
|
@@ -51,13 +70,7 @@ function mergeProps(...objects) {
|
|
|
51
70
|
if (value === void 0) continue;
|
|
52
71
|
if (isEventHandler(key) && typeof value === "function") {
|
|
53
72
|
const earlier = merged[key];
|
|
54
|
-
merged[key] = typeof earlier === "function" ? (
|
|
55
|
-
const event = args[0];
|
|
56
|
-
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
57
|
-
value(...args);
|
|
58
|
-
if (isComponentHandlerPrevented(event)) return;
|
|
59
|
-
earlier(...args);
|
|
60
|
-
} : value;
|
|
73
|
+
merged[key] = typeof earlier === "function" ? chainHandlers(earlier, value) : value;
|
|
61
74
|
} else if (key === "className") {
|
|
62
75
|
merged.className = merged.className ? `${String(merged.className)} ${String(value)}` : value;
|
|
63
76
|
} else if (key === "style") {
|
|
@@ -98,11 +111,12 @@ function useRender({
|
|
|
98
111
|
render,
|
|
99
112
|
defaultTagName,
|
|
100
113
|
props,
|
|
114
|
+
consumerProps,
|
|
101
115
|
state,
|
|
102
116
|
stateAttributes
|
|
103
117
|
}) {
|
|
104
118
|
const attributes = state ? getStateAttributes(state, stateAttributes) : {};
|
|
105
|
-
const merged = mergeProps(attributes,
|
|
119
|
+
const merged = mergeProps(attributes, props, consumerProps);
|
|
106
120
|
if (isValidElement(render)) {
|
|
107
121
|
return cloneElement(render, mergeProps(merged, render.props));
|
|
108
122
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -59,14 +59,33 @@ function isSyntheticEvent(event) {
|
|
|
59
59
|
return typeof event === "object" && event !== null && "nativeEvent" in event;
|
|
60
60
|
}
|
|
61
61
|
function makeEventPreventable(event) {
|
|
62
|
+
if (Object.prototype.hasOwnProperty.call(event, "preventComponentHandler")) return;
|
|
62
63
|
const target = event;
|
|
63
|
-
|
|
64
|
+
const prevent = () => {
|
|
64
65
|
target.componentHandlerPrevented = true;
|
|
65
66
|
};
|
|
67
|
+
target.preventComponentHandler = prevent;
|
|
68
|
+
const native = event.nativeEvent;
|
|
69
|
+
const stopImmediate = native?.stopImmediatePropagation?.bind(native);
|
|
70
|
+
if (native && stopImmediate) {
|
|
71
|
+
native.stopImmediatePropagation = () => {
|
|
72
|
+
stopImmediate();
|
|
73
|
+
prevent();
|
|
74
|
+
};
|
|
75
|
+
}
|
|
66
76
|
}
|
|
67
77
|
function isComponentHandlerPrevented(event) {
|
|
68
78
|
return typeof event === "object" && event !== null && event.componentHandlerPrevented === true;
|
|
69
79
|
}
|
|
80
|
+
function chainHandlers(earlier, value) {
|
|
81
|
+
return (...args) => {
|
|
82
|
+
const event = args[0];
|
|
83
|
+
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
84
|
+
value(...args);
|
|
85
|
+
if (isComponentHandlerPrevented(event)) return;
|
|
86
|
+
earlier(...args);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
70
89
|
function mergeProps(...objects) {
|
|
71
90
|
const merged = {};
|
|
72
91
|
for (const props of objects) {
|
|
@@ -76,13 +95,7 @@ function mergeProps(...objects) {
|
|
|
76
95
|
if (value === void 0) continue;
|
|
77
96
|
if (isEventHandler(key) && typeof value === "function") {
|
|
78
97
|
const earlier = merged[key];
|
|
79
|
-
merged[key] = typeof earlier === "function" ? (
|
|
80
|
-
const event = args[0];
|
|
81
|
-
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
82
|
-
value(...args);
|
|
83
|
-
if (isComponentHandlerPrevented(event)) return;
|
|
84
|
-
earlier(...args);
|
|
85
|
-
} : value;
|
|
98
|
+
merged[key] = typeof earlier === "function" ? chainHandlers(earlier, value) : value;
|
|
86
99
|
} else if (key === "className") {
|
|
87
100
|
merged.className = merged.className ? `${String(merged.className)} ${String(value)}` : value;
|
|
88
101
|
} else if (key === "style") {
|
|
@@ -125,11 +138,12 @@ function useRender({
|
|
|
125
138
|
render,
|
|
126
139
|
defaultTagName,
|
|
127
140
|
props,
|
|
141
|
+
consumerProps,
|
|
128
142
|
state,
|
|
129
143
|
stateAttributes
|
|
130
144
|
}) {
|
|
131
145
|
const attributes = state ? getStateAttributes(state, stateAttributes) : {};
|
|
132
|
-
const merged = mergeProps(attributes,
|
|
146
|
+
const merged = mergeProps(attributes, props, consumerProps);
|
|
133
147
|
if ((0, import_react.isValidElement)(render)) {
|
|
134
148
|
return (0, import_react.cloneElement)(render, mergeProps(merged, render.props));
|
|
135
149
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Prop merging for headless components.
|
|
5
|
-
*
|
|
6
|
-
* A component and its consumer both want to put things on the same element. Naive
|
|
7
|
-
* spreading lets whichever runs last silently destroy the other's behaviour, so each
|
|
8
|
-
* kind of prop is combined rather than replaced.
|
|
9
|
-
*/
|
|
3
|
+
/** The shape prop objects are handled as here: unknown keys, unknown values. */
|
|
10
4
|
type UnknownProps = Record<string, unknown>;
|
|
11
5
|
/**
|
|
12
6
|
* An event a consumer's handler can use to stop the component's own handler running.
|
|
@@ -66,6 +60,17 @@ declare function mergeProps(...objects: (UnknownProps | undefined)[]): UnknownPr
|
|
|
66
60
|
type StateAttributeMapping<State> = {
|
|
67
61
|
[Key in keyof State]?: (value: State[Key]) => Record<string, string> | null;
|
|
68
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* Turns a state object into the `data-*` attributes a mapping declares for it.
|
|
65
|
+
*
|
|
66
|
+
* Walks the state's own keys, so a field the mapping does not cover contributes
|
|
67
|
+
* nothing, and a mapping entry that returns `null` is skipped. Entries may each
|
|
68
|
+
* emit several attributes; later keys win if two entries name the same attribute.
|
|
69
|
+
*
|
|
70
|
+
* @param state - The component's current state.
|
|
71
|
+
* @param mapping - Which fields become attributes. `undefined` yields `{}`.
|
|
72
|
+
* @returns The attributes to spread onto the element.
|
|
73
|
+
*/
|
|
69
74
|
declare function getStateAttributes<State extends Record<string, unknown>>(state: State, mapping: StateAttributeMapping<State> | undefined): UnknownProps;
|
|
70
75
|
/**
|
|
71
76
|
* The common case: a boolean that emits one attribute when true and another when
|
|
@@ -98,14 +103,22 @@ interface UseRenderParams<State extends Record<string, unknown>> {
|
|
|
98
103
|
render?: ReactElement | undefined;
|
|
99
104
|
/** Tag rendered when `render` is not supplied. */
|
|
100
105
|
defaultTagName: string;
|
|
101
|
-
/**
|
|
102
|
-
props
|
|
106
|
+
/** The component's own props. */
|
|
107
|
+
props?: UnknownProps;
|
|
108
|
+
/**
|
|
109
|
+
* The consumer's props, spread from `...rest`.
|
|
110
|
+
*
|
|
111
|
+
* A separate slot rather than a position in a list: precedence is then a property of
|
|
112
|
+
* this signature rather than a rule each component has to remember. A component
|
|
113
|
+
* cannot put a consumer's props before its own, because there is nowhere to put them.
|
|
114
|
+
*/
|
|
115
|
+
consumerProps?: UnknownProps;
|
|
103
116
|
/** The part's state, projected onto the DOM through `stateAttributes`. */
|
|
104
117
|
state?: State;
|
|
105
118
|
/** How each state field becomes `data-*` attributes. */
|
|
106
119
|
stateAttributes?: StateAttributeMapping<State>;
|
|
107
120
|
}
|
|
108
|
-
declare function useRender<State extends Record<string, unknown> = Record<string, never>>({ render, defaultTagName, props, state, stateAttributes, }: UseRenderParams<State>): ReactElement;
|
|
121
|
+
declare function useRender<State extends Record<string, unknown> = Record<string, never>>({ render, defaultTagName, props, consumerProps, state, stateAttributes, }: UseRenderParams<State>): ReactElement;
|
|
109
122
|
|
|
110
123
|
/**
|
|
111
124
|
* Supports both controlled and uncontrolled use of a single value.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Prop merging for headless components.
|
|
5
|
-
*
|
|
6
|
-
* A component and its consumer both want to put things on the same element. Naive
|
|
7
|
-
* spreading lets whichever runs last silently destroy the other's behaviour, so each
|
|
8
|
-
* kind of prop is combined rather than replaced.
|
|
9
|
-
*/
|
|
3
|
+
/** The shape prop objects are handled as here: unknown keys, unknown values. */
|
|
10
4
|
type UnknownProps = Record<string, unknown>;
|
|
11
5
|
/**
|
|
12
6
|
* An event a consumer's handler can use to stop the component's own handler running.
|
|
@@ -66,6 +60,17 @@ declare function mergeProps(...objects: (UnknownProps | undefined)[]): UnknownPr
|
|
|
66
60
|
type StateAttributeMapping<State> = {
|
|
67
61
|
[Key in keyof State]?: (value: State[Key]) => Record<string, string> | null;
|
|
68
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* Turns a state object into the `data-*` attributes a mapping declares for it.
|
|
65
|
+
*
|
|
66
|
+
* Walks the state's own keys, so a field the mapping does not cover contributes
|
|
67
|
+
* nothing, and a mapping entry that returns `null` is skipped. Entries may each
|
|
68
|
+
* emit several attributes; later keys win if two entries name the same attribute.
|
|
69
|
+
*
|
|
70
|
+
* @param state - The component's current state.
|
|
71
|
+
* @param mapping - Which fields become attributes. `undefined` yields `{}`.
|
|
72
|
+
* @returns The attributes to spread onto the element.
|
|
73
|
+
*/
|
|
69
74
|
declare function getStateAttributes<State extends Record<string, unknown>>(state: State, mapping: StateAttributeMapping<State> | undefined): UnknownProps;
|
|
70
75
|
/**
|
|
71
76
|
* The common case: a boolean that emits one attribute when true and another when
|
|
@@ -98,14 +103,22 @@ interface UseRenderParams<State extends Record<string, unknown>> {
|
|
|
98
103
|
render?: ReactElement | undefined;
|
|
99
104
|
/** Tag rendered when `render` is not supplied. */
|
|
100
105
|
defaultTagName: string;
|
|
101
|
-
/**
|
|
102
|
-
props
|
|
106
|
+
/** The component's own props. */
|
|
107
|
+
props?: UnknownProps;
|
|
108
|
+
/**
|
|
109
|
+
* The consumer's props, spread from `...rest`.
|
|
110
|
+
*
|
|
111
|
+
* A separate slot rather than a position in a list: precedence is then a property of
|
|
112
|
+
* this signature rather than a rule each component has to remember. A component
|
|
113
|
+
* cannot put a consumer's props before its own, because there is nowhere to put them.
|
|
114
|
+
*/
|
|
115
|
+
consumerProps?: UnknownProps;
|
|
103
116
|
/** The part's state, projected onto the DOM through `stateAttributes`. */
|
|
104
117
|
state?: State;
|
|
105
118
|
/** How each state field becomes `data-*` attributes. */
|
|
106
119
|
stateAttributes?: StateAttributeMapping<State>;
|
|
107
120
|
}
|
|
108
|
-
declare function useRender<State extends Record<string, unknown> = Record<string, never>>({ render, defaultTagName, props, state, stateAttributes, }: UseRenderParams<State>): ReactElement;
|
|
121
|
+
declare function useRender<State extends Record<string, unknown> = Record<string, never>>({ render, defaultTagName, props, consumerProps, state, stateAttributes, }: UseRenderParams<State>): ReactElement;
|
|
109
122
|
|
|
110
123
|
/**
|
|
111
124
|
* Supports both controlled and uncontrolled use of a single value.
|
package/dist/index.js
CHANGED
package/dist/switch/index.cjs
CHANGED
|
@@ -67,14 +67,33 @@ function isSyntheticEvent(event) {
|
|
|
67
67
|
return typeof event === "object" && event !== null && "nativeEvent" in event;
|
|
68
68
|
}
|
|
69
69
|
function makeEventPreventable(event) {
|
|
70
|
+
if (Object.prototype.hasOwnProperty.call(event, "preventComponentHandler")) return;
|
|
70
71
|
const target = event;
|
|
71
|
-
|
|
72
|
+
const prevent = () => {
|
|
72
73
|
target.componentHandlerPrevented = true;
|
|
73
74
|
};
|
|
75
|
+
target.preventComponentHandler = prevent;
|
|
76
|
+
const native = event.nativeEvent;
|
|
77
|
+
const stopImmediate = native?.stopImmediatePropagation?.bind(native);
|
|
78
|
+
if (native && stopImmediate) {
|
|
79
|
+
native.stopImmediatePropagation = () => {
|
|
80
|
+
stopImmediate();
|
|
81
|
+
prevent();
|
|
82
|
+
};
|
|
83
|
+
}
|
|
74
84
|
}
|
|
75
85
|
function isComponentHandlerPrevented(event) {
|
|
76
86
|
return typeof event === "object" && event !== null && event.componentHandlerPrevented === true;
|
|
77
87
|
}
|
|
88
|
+
function chainHandlers(earlier, value) {
|
|
89
|
+
return (...args) => {
|
|
90
|
+
const event = args[0];
|
|
91
|
+
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
92
|
+
value(...args);
|
|
93
|
+
if (isComponentHandlerPrevented(event)) return;
|
|
94
|
+
earlier(...args);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
78
97
|
function mergeProps(...objects) {
|
|
79
98
|
const merged = {};
|
|
80
99
|
for (const props of objects) {
|
|
@@ -84,13 +103,7 @@ function mergeProps(...objects) {
|
|
|
84
103
|
if (value === void 0) continue;
|
|
85
104
|
if (isEventHandler(key) && typeof value === "function") {
|
|
86
105
|
const earlier = merged[key];
|
|
87
|
-
merged[key] = typeof earlier === "function" ? (
|
|
88
|
-
const event = args[0];
|
|
89
|
-
if (isSyntheticEvent(event)) makeEventPreventable(event);
|
|
90
|
-
value(...args);
|
|
91
|
-
if (isComponentHandlerPrevented(event)) return;
|
|
92
|
-
earlier(...args);
|
|
93
|
-
} : value;
|
|
106
|
+
merged[key] = typeof earlier === "function" ? chainHandlers(earlier, value) : value;
|
|
94
107
|
} else if (key === "className") {
|
|
95
108
|
merged.className = merged.className ? `${String(merged.className)} ${String(value)}` : value;
|
|
96
109
|
} else if (key === "style") {
|
|
@@ -253,11 +266,12 @@ function useRender({
|
|
|
253
266
|
render,
|
|
254
267
|
defaultTagName,
|
|
255
268
|
props,
|
|
269
|
+
consumerProps,
|
|
256
270
|
state,
|
|
257
271
|
stateAttributes
|
|
258
272
|
}) {
|
|
259
273
|
const attributes = state ? getStateAttributes(state, stateAttributes) : {};
|
|
260
|
-
const merged = mergeProps(attributes,
|
|
274
|
+
const merged = mergeProps(attributes, props, consumerProps);
|
|
261
275
|
if ((0, import_react3.isValidElement)(render)) {
|
|
262
276
|
return (0, import_react3.cloneElement)(render, mergeProps(merged, render.props));
|
|
263
277
|
}
|
|
@@ -286,6 +300,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
286
300
|
function SwitchRoot({
|
|
287
301
|
checked: checkedProp,
|
|
288
302
|
defaultChecked,
|
|
303
|
+
nativeButton,
|
|
289
304
|
onCheckedChange,
|
|
290
305
|
disabled = false,
|
|
291
306
|
name,
|
|
@@ -302,7 +317,7 @@ function SwitchRoot({
|
|
|
302
317
|
state: "checked"
|
|
303
318
|
});
|
|
304
319
|
const state = (0, import_react5.useMemo)(() => ({ checked, disabled }), [checked, disabled]);
|
|
305
|
-
const isNativeButton = render === void 0 || render.type === "button";
|
|
320
|
+
const isNativeButton = nativeButton ?? (render === void 0 || render.type === "button");
|
|
306
321
|
const { props: consumerProps, ref: buttonRef } = useButton({
|
|
307
322
|
disabled,
|
|
308
323
|
native: isNativeButton,
|
|
@@ -314,22 +329,20 @@ function SwitchRoot({
|
|
|
314
329
|
defaultTagName: "button",
|
|
315
330
|
state,
|
|
316
331
|
stateAttributes: switchStateAttributes,
|
|
317
|
-
props:
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
{ ref: buttonRef }
|
|
332
|
-
]
|
|
332
|
+
props: {
|
|
333
|
+
role: "switch",
|
|
334
|
+
"aria-checked": checked,
|
|
335
|
+
className,
|
|
336
|
+
children,
|
|
337
|
+
ref: buttonRef,
|
|
338
|
+
onClick() {
|
|
339
|
+
if (disabled) return;
|
|
340
|
+
const next = !checked;
|
|
341
|
+
setChecked(next);
|
|
342
|
+
onCheckedChange?.(next);
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
consumerProps
|
|
333
346
|
});
|
|
334
347
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SwitchRootContext.Provider, { value: state, children: [
|
|
335
348
|
element,
|
|
@@ -350,7 +363,8 @@ function SwitchThumb({
|
|
|
350
363
|
defaultTagName: "span",
|
|
351
364
|
state,
|
|
352
365
|
stateAttributes: switchStateAttributes,
|
|
353
|
-
props:
|
|
366
|
+
props: { "aria-hidden": true, className, children },
|
|
367
|
+
consumerProps: rest
|
|
354
368
|
});
|
|
355
369
|
}
|
|
356
370
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/switch/index.d.cts
CHANGED
|
@@ -12,6 +12,15 @@ interface SwitchRootProps {
|
|
|
12
12
|
checked?: boolean;
|
|
13
13
|
/** Initial state when uncontrolled. Read once, at mount. */
|
|
14
14
|
defaultChecked?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the rendered element is a native `<button>`.
|
|
17
|
+
*
|
|
18
|
+
* Inferred from `render`, which is right for an element literal. Set it explicitly
|
|
19
|
+
* when rendering a *component* — `render={<Tooltip.Trigger />}` cannot be inspected,
|
|
20
|
+
* so it is treated as non-native and picks up attributes it does not need. A mismatch
|
|
21
|
+
* logs a development warning.
|
|
22
|
+
*/
|
|
23
|
+
nativeButton?: boolean;
|
|
15
24
|
onCheckedChange?: (checked: boolean) => void;
|
|
16
25
|
disabled?: boolean;
|
|
17
26
|
/**
|
|
@@ -21,6 +30,16 @@ interface SwitchRootProps {
|
|
|
21
30
|
name?: string;
|
|
22
31
|
/** Value submitted when checked. Defaults to `"on"`, as a native checkbox does. */
|
|
23
32
|
value?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Names the switch when paired with a `<label htmlFor>`.
|
|
35
|
+
*
|
|
36
|
+
* Declared rather than left to the prop spread because it is how a switch gets an
|
|
37
|
+
* accessible name: `Switch.Root` renders a `<button>`, which a wrapping `<label>`
|
|
38
|
+
* would name implicitly, but `jsx-a11y/label-has-associated-control` rejects a
|
|
39
|
+
* `<button>` as a nested control. The explicit association keeps the rule quiet
|
|
40
|
+
* without a disable at the call site.
|
|
41
|
+
*/
|
|
42
|
+
id?: string;
|
|
24
43
|
className?: string;
|
|
25
44
|
children?: ReactNode;
|
|
26
45
|
/**
|
|
@@ -38,11 +57,11 @@ interface SwitchRootProps {
|
|
|
38
57
|
* activation, and the disabled semantics for free. Per the WAI-ARIA switch pattern
|
|
39
58
|
* it carries `role="switch"` and `aria-checked`.
|
|
40
59
|
*
|
|
41
|
-
* It has no accessible name of its own —
|
|
42
|
-
* or `aria-labelledby`. That is the consumer's decision, not
|
|
60
|
+
* It has no accessible name of its own — pair it with a `<label htmlFor>` by `id`, or
|
|
61
|
+
* pass `aria-label` or `aria-labelledby`. That is the consumer's decision, not a headless
|
|
43
62
|
* component should guess.
|
|
44
63
|
*/
|
|
45
|
-
declare function SwitchRoot({ checked: checkedProp, defaultChecked, onCheckedChange, disabled, name, value, className, children, render, ...rest }: SwitchRootProps & Record<string, unknown>): react.JSX.Element;
|
|
64
|
+
declare function SwitchRoot({ checked: checkedProp, defaultChecked, nativeButton, onCheckedChange, disabled, name, value, className, children, render, ...rest }: SwitchRootProps & Record<string, unknown>): react.JSX.Element;
|
|
46
65
|
|
|
47
66
|
interface SwitchThumbProps {
|
|
48
67
|
className?: string;
|
package/dist/switch/index.d.ts
CHANGED
|
@@ -12,6 +12,15 @@ interface SwitchRootProps {
|
|
|
12
12
|
checked?: boolean;
|
|
13
13
|
/** Initial state when uncontrolled. Read once, at mount. */
|
|
14
14
|
defaultChecked?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the rendered element is a native `<button>`.
|
|
17
|
+
*
|
|
18
|
+
* Inferred from `render`, which is right for an element literal. Set it explicitly
|
|
19
|
+
* when rendering a *component* — `render={<Tooltip.Trigger />}` cannot be inspected,
|
|
20
|
+
* so it is treated as non-native and picks up attributes it does not need. A mismatch
|
|
21
|
+
* logs a development warning.
|
|
22
|
+
*/
|
|
23
|
+
nativeButton?: boolean;
|
|
15
24
|
onCheckedChange?: (checked: boolean) => void;
|
|
16
25
|
disabled?: boolean;
|
|
17
26
|
/**
|
|
@@ -21,6 +30,16 @@ interface SwitchRootProps {
|
|
|
21
30
|
name?: string;
|
|
22
31
|
/** Value submitted when checked. Defaults to `"on"`, as a native checkbox does. */
|
|
23
32
|
value?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Names the switch when paired with a `<label htmlFor>`.
|
|
35
|
+
*
|
|
36
|
+
* Declared rather than left to the prop spread because it is how a switch gets an
|
|
37
|
+
* accessible name: `Switch.Root` renders a `<button>`, which a wrapping `<label>`
|
|
38
|
+
* would name implicitly, but `jsx-a11y/label-has-associated-control` rejects a
|
|
39
|
+
* `<button>` as a nested control. The explicit association keeps the rule quiet
|
|
40
|
+
* without a disable at the call site.
|
|
41
|
+
*/
|
|
42
|
+
id?: string;
|
|
24
43
|
className?: string;
|
|
25
44
|
children?: ReactNode;
|
|
26
45
|
/**
|
|
@@ -38,11 +57,11 @@ interface SwitchRootProps {
|
|
|
38
57
|
* activation, and the disabled semantics for free. Per the WAI-ARIA switch pattern
|
|
39
58
|
* it carries `role="switch"` and `aria-checked`.
|
|
40
59
|
*
|
|
41
|
-
* It has no accessible name of its own —
|
|
42
|
-
* or `aria-labelledby`. That is the consumer's decision, not
|
|
60
|
+
* It has no accessible name of its own — pair it with a `<label htmlFor>` by `id`, or
|
|
61
|
+
* pass `aria-label` or `aria-labelledby`. That is the consumer's decision, not a headless
|
|
43
62
|
* component should guess.
|
|
44
63
|
*/
|
|
45
|
-
declare function SwitchRoot({ checked: checkedProp, defaultChecked, onCheckedChange, disabled, name, value, className, children, render, ...rest }: SwitchRootProps & Record<string, unknown>): react.JSX.Element;
|
|
64
|
+
declare function SwitchRoot({ checked: checkedProp, defaultChecked, nativeButton, onCheckedChange, disabled, name, value, className, children, render, ...rest }: SwitchRootProps & Record<string, unknown>): react.JSX.Element;
|
|
46
65
|
|
|
47
66
|
interface SwitchThumbProps {
|
|
48
67
|
className?: string;
|
package/dist/switch/index.js
CHANGED
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
retractActivationProps,
|
|
6
6
|
useButton
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-TNMGZWHA.js";
|
|
8
8
|
import {
|
|
9
9
|
__export,
|
|
10
10
|
booleanAttribute,
|
|
11
11
|
disabledAttribute,
|
|
12
12
|
useRender
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-PYLPZVWQ.js";
|
|
14
14
|
|
|
15
15
|
// src/switch/index.parts.ts
|
|
16
16
|
var index_parts_exports = {};
|
|
@@ -44,6 +44,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
44
44
|
function SwitchRoot({
|
|
45
45
|
checked: checkedProp,
|
|
46
46
|
defaultChecked,
|
|
47
|
+
nativeButton,
|
|
47
48
|
onCheckedChange,
|
|
48
49
|
disabled = false,
|
|
49
50
|
name,
|
|
@@ -60,7 +61,7 @@ function SwitchRoot({
|
|
|
60
61
|
state: "checked"
|
|
61
62
|
});
|
|
62
63
|
const state = useMemo(() => ({ checked, disabled }), [checked, disabled]);
|
|
63
|
-
const isNativeButton = render === void 0 || render.type === "button";
|
|
64
|
+
const isNativeButton = nativeButton ?? (render === void 0 || render.type === "button");
|
|
64
65
|
const { props: consumerProps, ref: buttonRef } = useButton({
|
|
65
66
|
disabled,
|
|
66
67
|
native: isNativeButton,
|
|
@@ -72,22 +73,20 @@ function SwitchRoot({
|
|
|
72
73
|
defaultTagName: "button",
|
|
73
74
|
state,
|
|
74
75
|
stateAttributes: switchStateAttributes,
|
|
75
|
-
props:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
{ ref: buttonRef }
|
|
90
|
-
]
|
|
76
|
+
props: {
|
|
77
|
+
role: "switch",
|
|
78
|
+
"aria-checked": checked,
|
|
79
|
+
className,
|
|
80
|
+
children,
|
|
81
|
+
ref: buttonRef,
|
|
82
|
+
onClick() {
|
|
83
|
+
if (disabled) return;
|
|
84
|
+
const next = !checked;
|
|
85
|
+
setChecked(next);
|
|
86
|
+
onCheckedChange?.(next);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
consumerProps
|
|
91
90
|
});
|
|
92
91
|
return /* @__PURE__ */ jsxs(SwitchRootContext.Provider, { value: state, children: [
|
|
93
92
|
element,
|
|
@@ -108,7 +107,8 @@ function SwitchThumb({
|
|
|
108
107
|
defaultTagName: "span",
|
|
109
108
|
state,
|
|
110
109
|
stateAttributes: switchStateAttributes,
|
|
111
|
-
props:
|
|
110
|
+
props: { "aria-hidden": true, className, children },
|
|
111
|
+
consumerProps: rest
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arun-dev/headless",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.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",
|