@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
116 lines (112 loc) • 3.74 kB
JavaScript
"use client";
import { useSafeLayoutEffect } from "../../utils/effect.js";
import { utils_exports } from "../../utils/index.js";
import { createSlotComponent } from "../../core/components/create-component.js";
import { motion } from "../motion/factory.js";
import { useControllableState } from "../../hooks/use-controllable-state/index.js";
import { flipStyle } from "./flip.style.js";
import { useMemo, useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
//#region src/components/flip/flip.tsx
const flipVariants = {
enter: ({ ident, orientation, visible }) => ({ [orientation === "horizontal" ? "rotateY" : "rotateX"]: ident === "from" ? visible ? 180 : 0 : visible ? 0 : 180 }),
exit: ({ ident, orientation }) => ({ [orientation === "horizontal" ? "rotateY" : "rotateX"]: ident === "from" ? 0 : 180 })
};
const { PropsContext: FlipPropsContext, usePropsContext: useFlipPropsContext, withContext, withProvider } = createSlotComponent("flip", flipStyle);
/**
* `Flip` is an animation component that alternates between flipping two elements.
*
* @see https://yamada-ui.com/docs/components/flip
*/
const Flip = withProvider(({ defaultValue = "from", delay = 0, disabled, duration = .4, from, orientation = "horizontal", readOnly, to, transition = {}, value: valueProp, onChange, onClick: onClickProp,...rest }) => {
const [{ height, width }, setRect] = useState({});
const fromRef = useRef(null);
const toRef = useRef(null);
const [value, setValue] = useControllableState({
defaultValue,
value: valueProp,
onChange
});
const visible = value === "to";
const style = useMemo(() => ({
height: height ? `${height}px` : "auto",
width: width ? `${width}px` : "auto"
}), [width, height]);
const onClick = () => {
if (readOnly) return;
setValue((prev) => prev === "from" ? "to" : "from");
};
useSafeLayoutEffect(() => {
const from$1 = fromRef.current;
const to$1 = toRef.current;
if (!from$1 || !to$1) return;
if (from$1.offsetWidth !== to$1.offsetWidth || from$1.offsetHeight !== to$1.offsetHeight) console.warn(`Flip: "from" element (width: ${from$1.offsetWidth}px, height: ${from$1.offsetHeight}px) does not match "to" element (width: ${to$1.offsetWidth}px, height: ${to$1.offsetHeight}px). Please ensure both elements have the same dimensions.`);
setRect({
height: from$1.offsetHeight,
width: from$1.offsetWidth
});
}, [fromRef, toRef]);
return /* @__PURE__ */ jsxs(motion.button, {
type: "button",
style,
"data-disabled": (0, utils_exports.dataAttr)(disabled),
"data-orientation": orientation,
"data-readonly": (0, utils_exports.dataAttr)(readOnly),
"data-value": value,
disabled,
onClick: (0, utils_exports.handlerAll)(onClickProp, onClick),
...rest,
children: [/* @__PURE__ */ jsx(FlipFrom, {
ref: fromRef,
custom: {
orientation,
visible
},
transition: {
delay,
duration,
...transition
},
children: from
}), /* @__PURE__ */ jsx(FlipTo, {
ref: toRef,
custom: {
orientation,
visible
},
transition: {
delay,
duration,
...transition
},
children: to
})]
});
}, "root")();
const FlipFrom = withContext(({ custom,...rest }) => {
return /* @__PURE__ */ jsx(motion.span, {
animate: "enter",
custom: {
ident: "from",
...custom
},
initial: "exit",
variants: flipVariants,
...rest
});
}, ["item", "from"])();
const FlipTo = withContext(({ custom,...rest }) => {
return /* @__PURE__ */ jsx(motion.span, {
animate: "enter",
custom: {
ident: "to",
...custom
},
initial: "exit",
variants: flipVariants,
...rest
});
}, ["item", "to"])();
//#endregion
export { Flip, FlipPropsContext, useFlipPropsContext };
//# sourceMappingURL=flip.js.map