@gfazioli/mantine-flip
Version:
Flip component is a wrapper for any component that can be flipped. It is used to create cards, flip boxes and more.
125 lines (122 loc) • 3.88 kB
JavaScript
'use client';
import React, { useRef, useState } from 'react';
import { createVarsResolver, polymorphicFactory, useProps, useStyles, Box } from '@mantine/core';
import { useUncontrolled, useDidUpdate } from '@mantine/hooks';
import { FlipContextProvider } from './Flip.context.mjs';
import { FlipTarget } from './FlipTarget/FlipTarget.mjs';
import classes from './Flip.module.css.mjs';
const defaultProps = {
direction: "horizontal",
directionFlipIn: "negative",
directionFlipOut: "positive"
};
const varsResolver = createVarsResolver((_, { perspective, easing, duration }) => ({
root: {
"--flip-perspective": perspective === void 0 ? "1000px" : perspective,
"--flip-transition-duration": duration === void 0 ? ".8s" : `${duration}s`,
"--flip-transition-timing-function": easing === void 0 ? "ease-in-out" : easing
}
}));
const Flip = polymorphicFactory((_props, ref) => {
const props = useProps("Flip", defaultProps, _props);
const {
perspective,
duration,
easing,
classNames,
style,
styles,
unstyled,
vars,
children,
className,
flipped,
defaultFlipped,
direction,
directionFlipIn,
directionFlipOut,
onChange,
onBack,
onFront,
...others
} = props;
const containerRef = useRef(null);
const [rotateValue, setRotateValue] = useState(defaultFlipped ? -180 : 0);
const [_flipped, setFlipped] = useUncontrolled({
value: flipped,
defaultValue: defaultFlipped,
finalValue: false,
onChange
});
const getStyles = useStyles({
name: "Flip",
props,
classes,
className,
style,
classNames,
styles,
unstyled,
vars,
varsResolver
});
useDidUpdate(() => {
setRotateValue(0);
}, [directionFlipIn, directionFlipOut, direction]);
useDidUpdate(() => {
if (directionFlipIn === "negative" && directionFlipOut === "positive") {
setRotateValue((v) => v ? v + 180 : -180);
}
if (directionFlipIn === "negative" && directionFlipOut === "negative") {
setRotateValue((v) => v - 180);
}
if (directionFlipIn === "positive" && directionFlipOut === "negative") {
setRotateValue((v) => v ? v - 180 : 180);
}
if (directionFlipIn === "positive" && directionFlipOut === "positive") {
setRotateValue((v) => v + 180);
}
}, [_flipped]);
const childrenArray = React.Children.toArray(children);
if (childrenArray.length !== 2) {
throw new Error("Flip component must have exactly two children");
}
function getDirectionIn() {
if (direction === "horizontal") {
return { transform: `rotateY(${rotateValue}deg)` };
}
return { transform: `rotateX(${rotateValue}deg)` };
}
function getBackRotation() {
if (direction === "horizontal") {
return { transform: "rotateY(180deg)" };
}
return { transform: "rotateX(180deg)" };
}
const frontChild = childrenArray[0];
const backChild = childrenArray[1];
const front = () => {
setFlipped(false);
_flipped && onFront?.();
};
const back = () => {
setFlipped(true);
!_flipped && onBack?.();
};
const toggleFlip = () => _flipped ? front() : back();
return /* @__PURE__ */ React.createElement(
FlipContextProvider,
{
value: {
toggleFlip,
flipped: _flipped
}
},
/* @__PURE__ */ React.createElement(Box, { ref, ...getStyles("root"), ...others }, /* @__PURE__ */ React.createElement("div", { ref: containerRef, ...getStyles("flip-inner"), style: getDirectionIn() }, /* @__PURE__ */ React.createElement("div", { ...getStyles("flip-content"), style: { zIndex: 0 } }, frontChild), /* @__PURE__ */ React.createElement("div", { ...getStyles("flip-content"), style: getBackRotation() }, backChild)))
);
});
Flip.classes = classes;
Flip.displayName = "Flip";
Flip.Target = FlipTarget;
export { Flip };
//# sourceMappingURL=Flip.mjs.map