@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
132 lines (129 loc) • 4.29 kB
JavaScript
'use client';
import { useMotionComponent } from "../MotionProvider/index.mjs";
import { rootVariants, styles, thumbVariants } from "./style.mjs";
import { createContext, useContext, useMemo, useRef, useState } from "react";
import { jsx } from "react/jsx-runtime";
import { cx } from "antd-style";
import useControlledState from "use-merge-value";
import { Switch } from "@base-ui/react/switch";
//#region src/LobeSwitch/atoms.tsx
const LobeSwitchContext = createContext(null);
const useLobeSwitchContext = () => {
const context = useContext(LobeSwitchContext);
if (!context) throw new Error("useLobeSwitchContext must be used within a LobeSwitchRoot");
return context;
};
const LobeSwitchRoot = ({ checked, className, defaultChecked, onCheckedChange, onClick, size = "default", children, disabled, readOnly, required, inputRef, id, name, ...rest }) => {
const Motion = useMotionComponent();
const [isPressed, setIsPressed] = useState(false);
const lastEventRef = useRef(null);
const [isChecked, setIsChecked] = useControlledState(defaultChecked ?? false, {
defaultValue: defaultChecked,
onChange: (value) => {
if (lastEventRef.current) onCheckedChange?.(value, lastEventRef.current);
},
value: checked
});
const baseClassName = rootVariants({ size });
const contextValue = useMemo(() => ({
isChecked: Boolean(isChecked),
isPressed,
setIsChecked: (value) => setIsChecked(value),
setIsPressed
}), [
isChecked,
isPressed,
setIsChecked
]);
const handleClick = (event) => {
lastEventRef.current = event;
onClick?.(!isChecked, event);
};
const handleKeyDown = (event) => {
if (event.key === "Enter" || event.key === " ") lastEventRef.current = event;
rest.onKeyDown?.(event);
};
return /* @__PURE__ */ jsx(LobeSwitchContext.Provider, {
value: contextValue,
children: /* @__PURE__ */ jsx(Switch.Root, {
checked: isChecked,
defaultChecked,
disabled,
id,
inputRef,
name,
onCheckedChange: setIsChecked,
readOnly,
render: /* @__PURE__ */ jsx(Motion.button, {
...rest,
className: cx(baseClassName, className),
initial: false,
onClick: handleClick,
onKeyDown: handleKeyDown,
onTap: () => setIsPressed(false),
onTapCancel: () => setIsPressed(false),
onTapStart: () => setIsPressed(true),
whileTap: "tap"
}),
required,
children
})
});
};
LobeSwitchRoot.displayName = "LobeSwitchRoot";
const LobeSwitchThumb = ({ className, pressedAnimation, size = "default", transition = {
damping: 25,
stiffness: 300,
type: "spring"
}, children, ...rest }) => {
const Motion = useMotionComponent();
const { isPressed } = useLobeSwitchContext();
const baseClassName = thumbVariants({ size });
const defaultPressedAnimation = { width: size === "small" ? 16 : 22 };
return /* @__PURE__ */ jsx(Switch.Thumb, { render: /* @__PURE__ */ jsx(Motion.span, {
animate: isPressed ? pressedAnimation || defaultPressedAnimation : void 0,
className: cx(baseClassName, className),
layout: true,
transition,
...rest,
children
}) });
};
LobeSwitchThumb.displayName = "LobeSwitchThumb";
const getIconPositionClass = (position, size) => {
if (position === "thumb") return styles.iconThumb;
if (position === "left") return size === "small" ? styles.iconLeftSmall : styles.iconLeft;
return size === "small" ? styles.iconRightSmall : styles.iconRight;
};
const LobeSwitchIcon = ({ children, className, position, transition = {
bounce: 0,
type: "spring"
}, ...rest }) => {
const Motion = useMotionComponent();
const { isChecked } = useLobeSwitchContext();
const size = rest.size || "default";
const isAnimated = useMemo(() => {
if (position === "right") return !isChecked;
if (position === "left") return isChecked;
if (position === "thumb") return true;
return false;
}, [position, isChecked]);
const positionClass = getIconPositionClass(position, size);
return /* @__PURE__ */ jsx(Motion.span, {
animate: isAnimated ? {
opacity: 1,
scale: 1
} : {
opacity: 0,
scale: 0
},
className: cx(styles.icon, positionClass, className),
transition,
...rest,
children
});
};
LobeSwitchIcon.displayName = "LobeSwitchIcon";
//#endregion
export { LobeSwitchIcon, LobeSwitchRoot, LobeSwitchThumb, useLobeSwitchContext };
//# sourceMappingURL=atoms.mjs.map