@arun-dev/headless 2.0.0 → 3.0.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/README.md +32 -22
- package/dist/button/index.cjs +25 -126
- package/dist/button/index.d.cts +31 -23
- package/dist/button/index.d.ts +31 -23
- package/dist/button/index.js +23 -16
- package/dist/{chunk-IGKX2XWC.js → chunk-OQTWWZ4B.js} +3 -28
- package/dist/index.cjs +3 -33
- package/dist/index.d.cts +19 -57
- package/dist/index.d.ts +19 -57
- package/dist/index.js +1 -7
- package/dist/switch/index.cjs +80 -189
- package/dist/switch/index.d.cts +35 -27
- package/dist/switch/index.d.ts +35 -27
- package/dist/switch/index.js +37 -40
- package/package.json +1 -1
- package/dist/chunk-ER7IAVR5.js +0 -96
package/dist/switch/index.d.cts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ReactElement, Ref, ComponentPropsWithRef } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Switch.Root's own props. Everything else — `id`, `className`, `children`, `aria-*`,
|
|
6
|
+
* `data-*`, event handlers — comes from React's own `<button>` props, so it is typed
|
|
7
|
+
* and checked without being declared here.
|
|
8
|
+
*
|
|
9
|
+
* `id` in particular is how a switch gets an accessible name, paired with a
|
|
10
|
+
* `<label htmlFor>`: the rendered `<button>` is not named implicitly by a wrapping
|
|
11
|
+
* `<label>`, and `jsx-a11y/label-has-associated-control` rejects it as a nested control.
|
|
12
|
+
*/
|
|
13
|
+
type SwitchRootOwnProps = {
|
|
5
14
|
/**
|
|
6
15
|
* Controlled state. Provide `onCheckedChange` alongside it.
|
|
7
16
|
*
|
|
@@ -12,15 +21,6 @@ interface SwitchRootProps {
|
|
|
12
21
|
checked?: boolean;
|
|
13
22
|
/** Initial state when uncontrolled. Read once, at mount. */
|
|
14
23
|
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;
|
|
24
24
|
onCheckedChange?: (checked: boolean) => void;
|
|
25
25
|
disabled?: boolean;
|
|
26
26
|
/**
|
|
@@ -30,36 +30,44 @@ interface SwitchRootProps {
|
|
|
30
30
|
name?: string;
|
|
31
31
|
/** Value submitted when checked. Defaults to `"on"`, as a native checkbox does. */
|
|
32
32
|
value?: string;
|
|
33
|
-
className?: string;
|
|
34
|
-
children?: ReactNode;
|
|
35
33
|
/**
|
|
36
|
-
*
|
|
34
|
+
* Component to render instead of the default `<button>`. Props, className, event
|
|
37
35
|
* handlers and ref are merged onto it.
|
|
36
|
+
*
|
|
37
|
+
* It must render a native `<button>` — a wrapper such as `<Tooltip.Trigger />` that
|
|
38
|
+
* forwards its props to one. Anything else is reported in development.
|
|
38
39
|
*/
|
|
39
40
|
render?: ReactElement;
|
|
41
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
40
42
|
ref?: Ref<HTMLElement>;
|
|
41
|
-
}
|
|
43
|
+
};
|
|
44
|
+
type SwitchRootProps = SwitchRootOwnProps & Omit<ComponentPropsWithRef<'button'>, keyof SwitchRootOwnProps>;
|
|
42
45
|
/**
|
|
43
46
|
* A switch — an immediate on/off control, distinct from a checkbox in that it takes
|
|
44
47
|
* effect at once rather than on submit.
|
|
45
48
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* it carries `role="switch"`
|
|
49
|
+
* Always a native `<button>`, which is the whole reason this component is short: the
|
|
50
|
+
* platform supplies focusability, Space and Enter activation, and `disabled`, so none
|
|
51
|
+
* of it is synthesised here. Per the WAI-ARIA switch pattern it carries `role="switch"`
|
|
52
|
+
* and `aria-checked`.
|
|
49
53
|
*
|
|
50
|
-
* It has no accessible name of its own —
|
|
51
|
-
* or `aria-labelledby`. That is the consumer's decision, not
|
|
52
|
-
* component should guess.
|
|
54
|
+
* It has no accessible name of its own — pair it with a `<label htmlFor>` by `id`, or
|
|
55
|
+
* pass `aria-label` or `aria-labelledby`. That is the consumer's decision, not one a
|
|
56
|
+
* headless component should guess.
|
|
53
57
|
*/
|
|
54
|
-
declare function SwitchRoot({ checked: checkedProp, defaultChecked,
|
|
58
|
+
declare function SwitchRoot({ checked: checkedProp, defaultChecked, onCheckedChange, disabled, name, value, className, children, render, ...rest }: SwitchRootProps): react.JSX.Element;
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Switch.Thumb's own props. Everything else — `id`, `className`, `children`, `aria-*`,
|
|
62
|
+
* `data-*` — comes from React's own `<span>` props.
|
|
63
|
+
*/
|
|
64
|
+
type SwitchThumbOwnProps = {
|
|
59
65
|
/** Element to render instead of the default `<span>`. */
|
|
60
66
|
render?: ReactElement;
|
|
67
|
+
/** Ref to the rendered element, whatever `render` makes it. */
|
|
61
68
|
ref?: Ref<HTMLElement>;
|
|
62
|
-
}
|
|
69
|
+
};
|
|
70
|
+
type SwitchThumbProps = SwitchThumbOwnProps & Omit<ComponentPropsWithRef<'span'>, keyof SwitchThumbOwnProps>;
|
|
63
71
|
/**
|
|
64
72
|
* The moving part of the switch.
|
|
65
73
|
*
|
|
@@ -73,7 +81,7 @@ interface SwitchThumbProps {
|
|
|
73
81
|
* Purely presentational — hidden from assistive technology, since the Root already
|
|
74
82
|
* announces the state.
|
|
75
83
|
*/
|
|
76
|
-
declare function SwitchThumb({ className, children, render, ...rest }: SwitchThumbProps
|
|
84
|
+
declare function SwitchThumb({ className, children, render, ...rest }: SwitchThumbProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
77
85
|
|
|
78
86
|
declare namespace index_parts {
|
|
79
87
|
export { SwitchRoot as Root, SwitchThumb as Thumb };
|
package/dist/switch/index.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ReactElement, Ref, ComponentPropsWithRef } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Switch.Root's own props. Everything else — `id`, `className`, `children`, `aria-*`,
|
|
6
|
+
* `data-*`, event handlers — comes from React's own `<button>` props, so it is typed
|
|
7
|
+
* and checked without being declared here.
|
|
8
|
+
*
|
|
9
|
+
* `id` in particular is how a switch gets an accessible name, paired with a
|
|
10
|
+
* `<label htmlFor>`: the rendered `<button>` is not named implicitly by a wrapping
|
|
11
|
+
* `<label>`, and `jsx-a11y/label-has-associated-control` rejects it as a nested control.
|
|
12
|
+
*/
|
|
13
|
+
type SwitchRootOwnProps = {
|
|
5
14
|
/**
|
|
6
15
|
* Controlled state. Provide `onCheckedChange` alongside it.
|
|
7
16
|
*
|
|
@@ -12,15 +21,6 @@ interface SwitchRootProps {
|
|
|
12
21
|
checked?: boolean;
|
|
13
22
|
/** Initial state when uncontrolled. Read once, at mount. */
|
|
14
23
|
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;
|
|
24
24
|
onCheckedChange?: (checked: boolean) => void;
|
|
25
25
|
disabled?: boolean;
|
|
26
26
|
/**
|
|
@@ -30,36 +30,44 @@ interface SwitchRootProps {
|
|
|
30
30
|
name?: string;
|
|
31
31
|
/** Value submitted when checked. Defaults to `"on"`, as a native checkbox does. */
|
|
32
32
|
value?: string;
|
|
33
|
-
className?: string;
|
|
34
|
-
children?: ReactNode;
|
|
35
33
|
/**
|
|
36
|
-
*
|
|
34
|
+
* Component to render instead of the default `<button>`. Props, className, event
|
|
37
35
|
* handlers and ref are merged onto it.
|
|
36
|
+
*
|
|
37
|
+
* It must render a native `<button>` — a wrapper such as `<Tooltip.Trigger />` that
|
|
38
|
+
* forwards its props to one. Anything else is reported in development.
|
|
38
39
|
*/
|
|
39
40
|
render?: ReactElement;
|
|
41
|
+
/** Ref to the rendered element. Merged with any ref on the `render` element. */
|
|
40
42
|
ref?: Ref<HTMLElement>;
|
|
41
|
-
}
|
|
43
|
+
};
|
|
44
|
+
type SwitchRootProps = SwitchRootOwnProps & Omit<ComponentPropsWithRef<'button'>, keyof SwitchRootOwnProps>;
|
|
42
45
|
/**
|
|
43
46
|
* A switch — an immediate on/off control, distinct from a checkbox in that it takes
|
|
44
47
|
* effect at once rather than on submit.
|
|
45
48
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* it carries `role="switch"`
|
|
49
|
+
* Always a native `<button>`, which is the whole reason this component is short: the
|
|
50
|
+
* platform supplies focusability, Space and Enter activation, and `disabled`, so none
|
|
51
|
+
* of it is synthesised here. Per the WAI-ARIA switch pattern it carries `role="switch"`
|
|
52
|
+
* and `aria-checked`.
|
|
49
53
|
*
|
|
50
|
-
* It has no accessible name of its own —
|
|
51
|
-
* or `aria-labelledby`. That is the consumer's decision, not
|
|
52
|
-
* component should guess.
|
|
54
|
+
* It has no accessible name of its own — pair it with a `<label htmlFor>` by `id`, or
|
|
55
|
+
* pass `aria-label` or `aria-labelledby`. That is the consumer's decision, not one a
|
|
56
|
+
* headless component should guess.
|
|
53
57
|
*/
|
|
54
|
-
declare function SwitchRoot({ checked: checkedProp, defaultChecked,
|
|
58
|
+
declare function SwitchRoot({ checked: checkedProp, defaultChecked, onCheckedChange, disabled, name, value, className, children, render, ...rest }: SwitchRootProps): react.JSX.Element;
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Switch.Thumb's own props. Everything else — `id`, `className`, `children`, `aria-*`,
|
|
62
|
+
* `data-*` — comes from React's own `<span>` props.
|
|
63
|
+
*/
|
|
64
|
+
type SwitchThumbOwnProps = {
|
|
59
65
|
/** Element to render instead of the default `<span>`. */
|
|
60
66
|
render?: ReactElement;
|
|
67
|
+
/** Ref to the rendered element, whatever `render` makes it. */
|
|
61
68
|
ref?: Ref<HTMLElement>;
|
|
62
|
-
}
|
|
69
|
+
};
|
|
70
|
+
type SwitchThumbProps = SwitchThumbOwnProps & Omit<ComponentPropsWithRef<'span'>, keyof SwitchThumbOwnProps>;
|
|
63
71
|
/**
|
|
64
72
|
* The moving part of the switch.
|
|
65
73
|
*
|
|
@@ -73,7 +81,7 @@ interface SwitchThumbProps {
|
|
|
73
81
|
* Purely presentational — hidden from assistive technology, since the Root already
|
|
74
82
|
* announces the state.
|
|
75
83
|
*/
|
|
76
|
-
declare function SwitchThumb({ className, children, render, ...rest }: SwitchThumbProps
|
|
84
|
+
declare function SwitchThumb({ className, children, render, ...rest }: SwitchThumbProps): ReactElement<unknown, string | react.JSXElementConstructor<any>>;
|
|
77
85
|
|
|
78
86
|
declare namespace index_parts {
|
|
79
87
|
export { SwitchRoot as Root, SwitchThumb as Thumb };
|
package/dist/switch/index.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useControlled
|
|
3
3
|
} from "../chunk-UEIB3I3T.js";
|
|
4
|
-
import {
|
|
5
|
-
retractActivationProps,
|
|
6
|
-
useButton
|
|
7
|
-
} from "../chunk-ER7IAVR5.js";
|
|
8
4
|
import {
|
|
9
5
|
__export,
|
|
10
|
-
booleanAttribute,
|
|
11
|
-
disabledAttribute,
|
|
12
6
|
useRender
|
|
13
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-OQTWWZ4B.js";
|
|
14
8
|
|
|
15
9
|
// src/switch/index.parts.ts
|
|
16
10
|
var index_parts_exports = {};
|
|
@@ -19,8 +13,8 @@ __export(index_parts_exports, {
|
|
|
19
13
|
Thumb: () => SwitchThumb
|
|
20
14
|
});
|
|
21
15
|
|
|
22
|
-
// src/switch/
|
|
23
|
-
import {
|
|
16
|
+
// src/switch/SwitchRoot.tsx
|
|
17
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
24
18
|
|
|
25
19
|
// src/switch/SwitchRootContext.ts
|
|
26
20
|
import { createContext, useContext } from "react";
|
|
@@ -33,18 +27,20 @@ function useSwitchRootContext() {
|
|
|
33
27
|
return context;
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
// src/switch/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
// src/switch/switchDataAttributes.ts
|
|
31
|
+
function switchDataAttributes({ checked, disabled }) {
|
|
32
|
+
return {
|
|
33
|
+
"data-checked": checked ? "" : void 0,
|
|
34
|
+
"data-unchecked": checked ? void 0 : "",
|
|
35
|
+
"data-disabled": disabled ? "" : void 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
41
38
|
|
|
42
|
-
// src/switch/
|
|
39
|
+
// src/switch/SwitchRoot.tsx
|
|
43
40
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
44
41
|
function SwitchRoot({
|
|
45
42
|
checked: checkedProp,
|
|
46
43
|
defaultChecked,
|
|
47
|
-
nativeButton,
|
|
48
44
|
onCheckedChange,
|
|
49
45
|
disabled = false,
|
|
50
46
|
name,
|
|
@@ -61,53 +57,54 @@ function SwitchRoot({
|
|
|
61
57
|
state: "checked"
|
|
62
58
|
});
|
|
63
59
|
const state = useMemo(() => ({ checked, disabled }), [checked, disabled]);
|
|
64
|
-
const
|
|
65
|
-
const { props: consumerProps, ref: buttonRef } = useButton({
|
|
66
|
-
disabled,
|
|
67
|
-
native: isNativeButton,
|
|
68
|
-
props: rest
|
|
69
|
-
});
|
|
70
|
-
const safeRender = disabled && !isNativeButton && render !== void 0 ? cloneElement(render, retractActivationProps(render.props)) : render;
|
|
60
|
+
const elementRef = useNativeButtonWarning();
|
|
71
61
|
const element = useRender({
|
|
72
|
-
render
|
|
62
|
+
render,
|
|
73
63
|
defaultTagName: "button",
|
|
74
|
-
state,
|
|
75
|
-
stateAttributes: switchStateAttributes,
|
|
76
64
|
props: {
|
|
65
|
+
// Without this a switch inside a form would submit it on every toggle.
|
|
66
|
+
type: "button",
|
|
77
67
|
role: "switch",
|
|
78
68
|
"aria-checked": checked,
|
|
69
|
+
// The platform suppresses activation, focus and the click handler below.
|
|
70
|
+
disabled: disabled || void 0,
|
|
71
|
+
...switchDataAttributes(state),
|
|
79
72
|
className,
|
|
80
73
|
children,
|
|
81
|
-
ref:
|
|
74
|
+
ref: elementRef,
|
|
82
75
|
onClick() {
|
|
83
|
-
if (disabled) return;
|
|
84
76
|
const next = !checked;
|
|
85
77
|
setChecked(next);
|
|
86
78
|
onCheckedChange?.(next);
|
|
87
79
|
}
|
|
88
80
|
},
|
|
89
|
-
consumerProps
|
|
81
|
+
consumerProps: rest
|
|
90
82
|
});
|
|
91
83
|
return /* @__PURE__ */ jsxs(SwitchRootContext.Provider, { value: state, children: [
|
|
92
84
|
element,
|
|
93
|
-
name !== void 0
|
|
85
|
+
name !== void 0 ? /* @__PURE__ */ jsx("input", { type: "checkbox", hidden: true, readOnly: true, name, value, checked }) : null
|
|
94
86
|
] });
|
|
95
87
|
}
|
|
88
|
+
function useNativeButtonWarning() {
|
|
89
|
+
const elementRef = useRef(null);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (process.env.NODE_ENV === "production") return;
|
|
92
|
+
const element = elementRef.current;
|
|
93
|
+
if (!element || element.tagName === "BUTTON") return;
|
|
94
|
+
console.error(
|
|
95
|
+
`Switch.Root rendered <${element.tagName.toLowerCase()}> instead of <button>. Focus, Space and Enter activation and \`disabled\` all come from the button element; pass a \`render\` component that forwards its props to one.`
|
|
96
|
+
);
|
|
97
|
+
}, []);
|
|
98
|
+
return elementRef;
|
|
99
|
+
}
|
|
96
100
|
|
|
97
|
-
// src/switch/
|
|
98
|
-
function SwitchThumb({
|
|
99
|
-
className,
|
|
100
|
-
children,
|
|
101
|
-
render,
|
|
102
|
-
...rest
|
|
103
|
-
}) {
|
|
101
|
+
// src/switch/SwitchThumb.tsx
|
|
102
|
+
function SwitchThumb({ className, children, render, ...rest }) {
|
|
104
103
|
const state = useSwitchRootContext();
|
|
105
104
|
return useRender({
|
|
106
105
|
render,
|
|
107
106
|
defaultTagName: "span",
|
|
108
|
-
state,
|
|
109
|
-
stateAttributes: switchStateAttributes,
|
|
110
|
-
props: { "aria-hidden": true, className, children },
|
|
107
|
+
props: { "aria-hidden": true, ...switchDataAttributes(state), className, children },
|
|
111
108
|
consumerProps: rest
|
|
112
109
|
});
|
|
113
110
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arun-dev/headless",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.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",
|
package/dist/chunk-ER7IAVR5.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
mergeProps
|
|
3
|
-
} from "./chunk-IGKX2XWC.js";
|
|
4
|
-
|
|
5
|
-
// src/useButton.ts
|
|
6
|
-
import { useEffect, useRef } from "react";
|
|
7
|
-
var ACTIVATION_HANDLERS = [
|
|
8
|
-
"onClick",
|
|
9
|
-
"onDoubleClick",
|
|
10
|
-
"onMouseDown",
|
|
11
|
-
"onMouseUp",
|
|
12
|
-
"onPointerDown",
|
|
13
|
-
"onPointerUp",
|
|
14
|
-
"onTouchStart",
|
|
15
|
-
"onTouchEnd",
|
|
16
|
-
"onKeyDown",
|
|
17
|
-
"onKeyUp",
|
|
18
|
-
"onKeyPress"
|
|
19
|
-
];
|
|
20
|
-
function activationHandlers() {
|
|
21
|
-
return {
|
|
22
|
-
onKeyDown(event) {
|
|
23
|
-
if (event.target !== event.currentTarget || event.defaultPrevented) return;
|
|
24
|
-
if (event.key === " ") {
|
|
25
|
-
event.preventDefault();
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (event.key === "Enter") {
|
|
29
|
-
event.preventDefault();
|
|
30
|
-
click(event.currentTarget);
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
onKeyUp(event) {
|
|
34
|
-
if (event.target !== event.currentTarget || event.defaultPrevented) return;
|
|
35
|
-
if (event.key === " ") click(event.currentTarget);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function click(element) {
|
|
40
|
-
if (element && typeof element.click === "function") {
|
|
41
|
-
element.click();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function useButton({
|
|
45
|
-
disabled = false,
|
|
46
|
-
native,
|
|
47
|
-
props = {}
|
|
48
|
-
}) {
|
|
49
|
-
const elementRef = useRef(null);
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (process.env.NODE_ENV === "production") return;
|
|
52
|
-
const element = elementRef.current;
|
|
53
|
-
if (!element) return;
|
|
54
|
-
const isButtonTag = element.tagName === "BUTTON";
|
|
55
|
-
if (native && !isButtonTag) {
|
|
56
|
-
console.error(
|
|
57
|
-
`A component expected a native <button> but rendered <${element.tagName.toLowerCase()}>. Focus, keyboard activation and \`disabled\` will not behave natively.`
|
|
58
|
-
);
|
|
59
|
-
} else if (!native && isButtonTag) {
|
|
60
|
-
console.error(
|
|
61
|
-
"A component rendered a native <button> while treating it as a non-native element, so it carries synthesised attributes it does not need."
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
}, [native]);
|
|
65
|
-
return { props: buttonProps({ disabled, native, props }), ref: elementRef };
|
|
66
|
-
}
|
|
67
|
-
function buttonProps({ disabled, native, props }) {
|
|
68
|
-
if (!disabled) {
|
|
69
|
-
return native ? mergeProps({ type: "button" }, props) : mergeProps({ tabIndex: 0 }, activationHandlers(), props);
|
|
70
|
-
}
|
|
71
|
-
if (native) return mergeProps({ type: "button" }, props, { disabled: true, "data-disabled": "" });
|
|
72
|
-
const sanitised = {};
|
|
73
|
-
for (const key of Object.keys(props)) {
|
|
74
|
-
if (key === "href" || ACTIVATION_HANDLERS.includes(key)) continue;
|
|
75
|
-
sanitised[key] = props[key];
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
...sanitised,
|
|
79
|
-
"aria-disabled": true,
|
|
80
|
-
"data-disabled": "",
|
|
81
|
-
// Mirrors a native disabled button, which is not focusable.
|
|
82
|
-
tabIndex: -1
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
function retractActivationProps(props) {
|
|
86
|
-
const overrides = {};
|
|
87
|
-
for (const key of Object.keys(props)) {
|
|
88
|
-
if (key === "href" || ACTIVATION_HANDLERS.includes(key)) overrides[key] = void 0;
|
|
89
|
-
}
|
|
90
|
-
return overrides;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export {
|
|
94
|
-
useButton,
|
|
95
|
-
retractActivationProps
|
|
96
|
-
};
|