UNPKG

8.42 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4Object.defineProperty(exports, "__esModule", {
5 value: true
6});
7exports.default = useButton;
8var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9var React = _interopRequireWildcard(require("react"));
10var _utils = require("@mui/utils");
11var _extractEventHandlers = _interopRequireDefault(require("../utils/extractEventHandlers"));
12function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14/**
15 *
16 * Demos:
17 *
18 * - [Button](https://mui.com/base/react-button/#hook)
19 *
20 * API:
21 *
22 * - [useButton API](https://mui.com/base/react-button/hooks-api/#use-button)
23 */
24function useButton(parameters = {}) {
25 const {
26 disabled = false,
27 focusableWhenDisabled,
28 href,
29 rootRef: externalRef,
30 tabIndex,
31 to,
32 type
33 } = parameters;
34 const buttonRef = React.useRef();
35 const [active, setActive] = React.useState(false);
36 const {
37 isFocusVisibleRef,
38 onFocus: handleFocusVisible,
39 onBlur: handleBlurVisible,
40 ref: focusVisibleRef
41 } = (0, _utils.unstable_useIsFocusVisible)();
42 const [focusVisible, setFocusVisible] = React.useState(false);
43 if (disabled && !focusableWhenDisabled && focusVisible) {
44 setFocusVisible(false);
45 }
46 React.useEffect(() => {
47 isFocusVisibleRef.current = focusVisible;
48 }, [focusVisible, isFocusVisibleRef]);
49 const [hostElementName, setHostElementName] = React.useState('');
50 const createHandleMouseLeave = otherHandlers => event => {
51 var _otherHandlers$onMous;
52 if (focusVisible) {
53 event.preventDefault();
54 }
55 (_otherHandlers$onMous = otherHandlers.onMouseLeave) == null ? void 0 : _otherHandlers$onMous.call(otherHandlers, event);
56 };
57 const createHandleBlur = otherHandlers => event => {
58 var _otherHandlers$onBlur;
59 handleBlurVisible(event);
60 if (isFocusVisibleRef.current === false) {
61 setFocusVisible(false);
62 }
63 (_otherHandlers$onBlur = otherHandlers.onBlur) == null ? void 0 : _otherHandlers$onBlur.call(otherHandlers, event);
64 };
65 const createHandleFocus = otherHandlers => event => {
66 var _otherHandlers$onFocu2;
67 // Fix for https://github.com/facebook/react/issues/7769
68 if (!buttonRef.current) {
69 buttonRef.current = event.currentTarget;
70 }
71 handleFocusVisible(event);
72 if (isFocusVisibleRef.current === true) {
73 var _otherHandlers$onFocu;
74 setFocusVisible(true);
75 (_otherHandlers$onFocu = otherHandlers.onFocusVisible) == null ? void 0 : _otherHandlers$onFocu.call(otherHandlers, event);
76 }
77 (_otherHandlers$onFocu2 = otherHandlers.onFocus) == null ? void 0 : _otherHandlers$onFocu2.call(otherHandlers, event);
78 };
79 const isNativeButton = () => {
80 const button = buttonRef.current;
81 return hostElementName === 'BUTTON' || hostElementName === 'INPUT' && ['button', 'submit', 'reset'].includes(button == null ? void 0 : button.type) || hostElementName === 'A' && (button == null ? void 0 : button.href);
82 };
83 const createHandleClick = otherHandlers => event => {
84 if (!disabled) {
85 var _otherHandlers$onClic;
86 (_otherHandlers$onClic = otherHandlers.onClick) == null ? void 0 : _otherHandlers$onClic.call(otherHandlers, event);
87 }
88 };
89 const createHandleMouseDown = otherHandlers => event => {
90 var _otherHandlers$onMous2;
91 if (!disabled) {
92 setActive(true);
93 document.addEventListener('mouseup', () => {
94 setActive(false);
95 }, {
96 once: true
97 });
98 }
99 (_otherHandlers$onMous2 = otherHandlers.onMouseDown) == null ? void 0 : _otherHandlers$onMous2.call(otherHandlers, event);
100 };
101 const createHandleKeyDown = otherHandlers => event => {
102 var _otherHandlers$onKeyD;
103 (_otherHandlers$onKeyD = otherHandlers.onKeyDown) == null ? void 0 : _otherHandlers$onKeyD.call(otherHandlers, event);
104 if (event.defaultMuiPrevented) {
105 return;
106 }
107 if (event.target === event.currentTarget && !isNativeButton() && event.key === ' ') {
108 event.preventDefault();
109 }
110 if (event.target === event.currentTarget && event.key === ' ' && !disabled) {
111 setActive(true);
112 }
113
114 // Keyboard accessibility for non interactive elements
115 if (event.target === event.currentTarget && !isNativeButton() && event.key === 'Enter' && !disabled) {
116 var _otherHandlers$onClic2;
117 (_otherHandlers$onClic2 = otherHandlers.onClick) == null ? void 0 : _otherHandlers$onClic2.call(otherHandlers, event);
118 event.preventDefault();
119 }
120 };
121 const createHandleKeyUp = otherHandlers => event => {
122 var _otherHandlers$onKeyU;
123 // calling preventDefault in keyUp on a <button> will not dispatch a click event if Space is pressed
124 // https://codesandbox.io/s/button-keyup-preventdefault-dn7f0
125
126 if (event.target === event.currentTarget) {
127 setActive(false);
128 }
129 (_otherHandlers$onKeyU = otherHandlers.onKeyUp) == null ? void 0 : _otherHandlers$onKeyU.call(otherHandlers, event);
130
131 // Keyboard accessibility for non interactive elements
132 if (event.target === event.currentTarget && !isNativeButton() && !disabled && event.key === ' ' && !event.defaultMuiPrevented) {
133 var _otherHandlers$onClic3;
134 (_otherHandlers$onClic3 = otherHandlers.onClick) == null ? void 0 : _otherHandlers$onClic3.call(otherHandlers, event);
135 }
136 };
137 const updateHostElementName = React.useCallback(instance => {
138 var _instance$tagName;
139 setHostElementName((_instance$tagName = instance == null ? void 0 : instance.tagName) != null ? _instance$tagName : '');
140 }, []);
141 const handleRef = (0, _utils.unstable_useForkRef)(updateHostElementName, externalRef, focusVisibleRef, buttonRef);
142 const buttonProps = {};
143 if (hostElementName === 'BUTTON') {
144 buttonProps.type = type != null ? type : 'button';
145 if (focusableWhenDisabled) {
146 buttonProps['aria-disabled'] = disabled;
147 } else {
148 buttonProps.disabled = disabled;
149 }
150 } else if (hostElementName !== '') {
151 if (!href && !to) {
152 buttonProps.role = 'button';
153 buttonProps.tabIndex = tabIndex != null ? tabIndex : 0;
154 }
155 if (disabled) {
156 buttonProps['aria-disabled'] = disabled;
157 buttonProps.tabIndex = focusableWhenDisabled ? tabIndex != null ? tabIndex : 0 : -1;
158 }
159 }
160 const getRootProps = (otherHandlers = {}) => {
161 const propsEventHandlers = (0, _extractEventHandlers.default)(parameters);
162 const externalEventHandlers = (0, _extends2.default)({}, propsEventHandlers, otherHandlers);
163
164 // onFocusVisible can be present on the props, but since it's not a valid React event handler,
165 // it must not be forwarded to the inner component.
166 delete externalEventHandlers.onFocusVisible;
167 return (0, _extends2.default)({
168 type
169 }, externalEventHandlers, buttonProps, {
170 onBlur: createHandleBlur(externalEventHandlers),
171 onClick: createHandleClick(externalEventHandlers),
172 onFocus: createHandleFocus(externalEventHandlers),
173 onKeyDown: createHandleKeyDown(externalEventHandlers),
174 onKeyUp: createHandleKeyUp(externalEventHandlers),
175 onMouseDown: createHandleMouseDown(externalEventHandlers),
176 onMouseLeave: createHandleMouseLeave(externalEventHandlers),
177 ref: handleRef
178 });
179 };
180 return {
181 getRootProps,
182 focusVisible,
183 setFocusVisible,
184 active,
185 rootRef: handleRef
186 };
187}
\No newline at end of file