UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

143 lines (139 loc) 5.22 kB
"use client"; import { mergeRefs } from "../../utils/ref.js"; import { utils_exports } from "../../utils/index.js"; import { styled } from "../../core/system/factory.js"; import { mergeCSS } from "../../core/css/merge-css.js"; import { getClassName } from "../../core/components/utils.js"; import { createComponent } from "../../core/components/create-component.js"; import { getLoadingComponent, isLoadingScheme } from "../loading/use-loading-component.js"; import { buttonStyle } from "./button.style.js"; import { Ripple } from "../ripple/ripple.js"; import { useRipple } from "../ripple/use-ripple.js"; import { Children, cloneElement, isValidElement, useCallback, useMemo, useRef } from "react"; import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime"; //#region src/components/button/button.tsx const useButtonType = (value) => { const buttonRef = useRef(!value); return { ref: useCallback((node) => { if (node) buttonRef.current = node.tagName === "BUTTON"; }, []), type: buttonRef.current ? "button" : void 0 }; }; const { component, ComponentContext, PropsContext: ButtonPropsContext, useComponentContext, usePropsContext: useButtonPropsContext, withContext } = createComponent("button", buttonStyle); /** * `Button` is an interactive component that allows users to perform actions such as submitting forms and toggling modals. * * @see https://yamada-ui.com/docs/components/button */ const Button = withContext(({ ref, as, active, children, disabled, disableRipple, endIcon = null, loading, loadingIcon = "oval", loadingMessage, loadingPlacement = "start", startIcon = null, iconProps, loadingProps,...rest }) => { const trulyDisabled = disabled || loading; const { ref: buttonRef, type } = useButtonType(as); const { onClick,...rippleProps } = useRipple({ ...rest, disabled: disableRipple || trulyDisabled }); const startLoading = loading && loadingPlacement === "start"; const endLoading = loading && loadingPlacement === "end"; return /* @__PURE__ */ jsx(ComponentContext, { value: useMemo(() => ({ endIcon, loadingIcon, loadingMessage, startIcon, iconProps }), [ loadingIcon, loadingMessage, startIcon, endIcon, iconProps ]), children: /* @__PURE__ */ jsxs(styled.button, { ref: mergeRefs(ref, buttonRef), as, type, "data-active": (0, utils_exports.dataAttr)(active), "data-loading": (0, utils_exports.dataAttr)(loading), disabled: trulyDisabled, ...rest, onClick, children: [ startLoading ? /* @__PURE__ */ jsx(ButtonStartLoading, { ...loadingProps }) : null, loading ? loadingMessage || /* @__PURE__ */ jsx(styled.span, { opacity: 0, children: /* @__PURE__ */ jsx(ButtonContent, { children }) }) : /* @__PURE__ */ jsx(ButtonContent, { children }), endLoading ? /* @__PURE__ */ jsx(ButtonEndLoading, { ...loadingProps }) : null, /* @__PURE__ */ jsx(Ripple, { ...rippleProps }) ] }) }); })(); const ButtonContent = component(({ children }) => { const { endIcon, startIcon, iconProps } = useComponentContext(); return /* @__PURE__ */ jsxs(Fragment$1, { children: [ startIcon ? /* @__PURE__ */ jsx(ButtonStartIcon, { ...iconProps, children: startIcon }) : null, children, endIcon ? /* @__PURE__ */ jsx(ButtonEndIcon, { ...iconProps, children: endIcon }) : null ] }); }, { name: "ButtonContent", className: getClassName((0, utils_exports.bem)("button", "content")) })(); const ButtonLoading = component((props) => { const { loadingIcon, loadingMessage } = useComponentContext(); const css = useMemo(() => ({ position: loadingMessage ? "relative" : "absolute" }), [loadingMessage]); if (isLoadingScheme(loadingIcon)) return /* @__PURE__ */ jsx(getLoadingComponent(loadingIcon), { color: "currentColor", ...props, css: mergeCSS(css, props.css) }); if (isValidElement(loadingIcon)) return cloneElement(loadingIcon, { ...props, ...loadingIcon.props, css: mergeCSS(css, props.css, loadingIcon.props.css) }); return null; }, { name: "ButtonLoading", className: getClassName((0, utils_exports.bem)("button", "loading")) })(); const ButtonStartLoading = component(ButtonLoading, { name: "ButtonStartLoading", className: getClassName((0, utils_exports.bem)("button", "loading", "start")) })(); const ButtonEndLoading = component(ButtonLoading, { name: "ButtonEndLoading", className: getClassName((0, utils_exports.bem)("button", "loading", "end")) })(); const ButtonIcon = component(({ children,...rest }) => { if (isValidElement(children)) return cloneElement(children, { "aria-hidden": true, role: "img", ...rest, ...children.props }); return Children.count(children) > 1 ? Children.only(null) : null; }, { name: "ButtonIcon", className: getClassName((0, utils_exports.bem)("button", "icon")) })(); const ButtonStartIcon = component(ButtonIcon, { name: "ButtonStartIcon", className: getClassName((0, utils_exports.bem)("button", "icon", "start")) })(); const ButtonEndIcon = component(ButtonIcon, { name: "ButtonEndIcon", className: getClassName((0, utils_exports.bem)("button", "icon", "end")) })(); //#endregion export { Button, ButtonPropsContext, useButtonPropsContext }; //# sourceMappingURL=button.js.map