@yamada-ui/use-clickable
Version:
Yamada UI useClickable custom hook
214 lines (213 loc) • 6.5 kB
JavaScript
"use client"
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
useClickable: () => useClickable
});
module.exports = __toCommonJS(index_exports);
var import_use_event_listener = require("@yamada-ui/use-event-listener");
var import_utils = require("@yamada-ui/utils");
var import_react = require("react");
var isValidElement = (ev) => {
const { isContentEditable, tagName } = ev.target;
return tagName !== "INPUT" && tagName !== "TEXTAREA" && !isContentEditable;
};
var useClickable = ({
ref,
clickOnEnter = true,
clickOnSpace = true,
isDisabled,
disabled = isDisabled,
disableTouchBehavior = true,
isFocusable,
focusable = isFocusable,
focusOnClick = true,
tabIndex: _tabIndex,
onClick,
onKeyDown,
onKeyUp,
onMouseDown,
onMouseLeave,
onMouseOver,
onMouseUp,
...props
} = {}) => {
const [button, setButton] = (0, import_react.useState)(true);
const [pressed, setPressed] = (0, import_react.useState)(false);
const listeners = (0, import_use_event_listener.useEventListeners)();
const tabIndex = button ? _tabIndex : _tabIndex || 0;
const trulyDisabled = disabled && !focusable;
const refCb = (node) => {
if (!node) return;
if (node.tagName !== "BUTTON") setButton(false);
};
const handleClick = (0, import_react.useCallback)(
(ev) => {
if (disabled) {
ev.stopPropagation();
ev.preventDefault();
return;
}
if (focusOnClick) ev.currentTarget.focus();
onClick == null ? void 0 : onClick(ev);
},
[disabled, focusOnClick, onClick]
);
const onDocumentKeyUp = (0, import_react.useCallback)(
(ev) => {
if (pressed && isValidElement(ev)) {
ev.preventDefault();
ev.stopPropagation();
setPressed(false);
listeners.remove(document, "keyup", onDocumentKeyUp, false);
}
},
[pressed, listeners]
);
const handleKeyDown = (0, import_react.useCallback)(
(ev) => {
onKeyDown == null ? void 0 : onKeyDown(ev);
if (disabled || ev.defaultPrevented || ev.metaKey) return;
if (!isValidElement(ev.nativeEvent) || button) return;
if (clickOnSpace && ev.key === " ") {
ev.preventDefault();
setPressed(true);
}
if (clickOnEnter && ev.key === "Enter") {
ev.preventDefault();
ev.currentTarget.click();
}
listeners.add(document, "keyup", onDocumentKeyUp, false);
},
[
disabled,
button,
onKeyDown,
clickOnEnter,
clickOnSpace,
listeners,
onDocumentKeyUp
]
);
const handleKeyUp = (0, import_react.useCallback)(
(ev) => {
onKeyUp == null ? void 0 : onKeyUp(ev);
if (disabled || ev.defaultPrevented || ev.metaKey) return;
if (!isValidElement(ev.nativeEvent) || button) return;
if (clickOnSpace && ev.key === " ") {
ev.preventDefault();
setPressed(false);
ev.currentTarget.click();
}
},
[clickOnSpace, button, disabled, onKeyUp]
);
const onDocumentMouseUp = (0, import_react.useCallback)(
(ev) => {
if (ev.button !== 0) return;
setPressed(false);
listeners.remove(document, "mouseup", onDocumentMouseUp, false);
},
[listeners]
);
const handleMouseDown = (0, import_react.useCallback)(
(ev) => {
if (ev.button !== 0) return;
if (disabled) {
ev.stopPropagation();
ev.preventDefault();
return;
}
if (!button) setPressed(true);
if (focusOnClick) ev.currentTarget.focus({ preventScroll: true });
listeners.add(document, "mouseup", onDocumentMouseUp, false);
onMouseDown == null ? void 0 : onMouseDown(ev);
},
[disabled, button, focusOnClick, onMouseDown, listeners, onDocumentMouseUp]
);
const handleMouseUp = (0, import_react.useCallback)(
(ev) => {
if (ev.button !== 0) return;
if (!button) setPressed(false);
onMouseUp == null ? void 0 : onMouseUp(ev);
},
[onMouseUp, button]
);
const handleMouseOver = (0, import_react.useCallback)(
(ev) => {
if (disabled) {
ev.preventDefault();
return;
}
if (disableTouchBehavior && (0, import_utils.isTouchDevice)()) return;
onMouseOver == null ? void 0 : onMouseOver(ev);
},
[disabled, onMouseOver, disableTouchBehavior]
);
const handleMouseLeave = (0, import_react.useCallback)(
(ev) => {
if (pressed) {
ev.preventDefault();
setPressed(false);
}
if (disableTouchBehavior && (0, import_utils.isTouchDevice)()) return;
onMouseLeave == null ? void 0 : onMouseLeave(ev);
},
[pressed, onMouseLeave, disableTouchBehavior]
);
if (button) {
return {
...props,
ref: (0, import_utils.mergeRefs)(ref, refCb),
type: "button",
"aria-disabled": trulyDisabled ? void 0 : disabled,
disabled: trulyDisabled,
onClick: handleClick,
onKeyDown,
onKeyUp,
onMouseDown,
onMouseLeave,
onMouseOver,
onMouseUp
};
} else {
return {
...props,
ref: (0, import_utils.mergeRefs)(ref, refCb),
"aria-disabled": disabled ? "true" : void 0,
"data-active": (0, import_utils.dataAttr)(pressed),
role: "button",
tabIndex: trulyDisabled ? void 0 : tabIndex,
onClick: handleClick,
onKeyDown: handleKeyDown,
onKeyUp: handleKeyUp,
onMouseDown: handleMouseDown,
onMouseLeave: handleMouseLeave,
onMouseOver: handleMouseOver,
onMouseUp: handleMouseUp
};
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
useClickable
});
//# sourceMappingURL=index.js.map