@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
112 lines (108 loc) • 3.92 kB
JavaScript
"use client";
import { getValidChildren } from "../../utils/children.js";
import { mergeRefs } from "../../utils/ref.js";
import { styled } from "../../core/system/factory.js";
import { mergeCSS } from "../../core/css/merge-css.js";
import { useInjectVarsIntoCss, useInjectVarsIntoProps } from "../../core/css/use-inject-vars.js";
import { createComponent } from "../../core/components/create-component.js";
import { zStackStyle } from "./z-stack.style.js";
import { Fragment, cloneElement, createRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { jsx } from "react/jsx-runtime";
//#region src/components/stack/z-stack.tsx
const { PropsContext: ZStackPropsContext, usePropsContext: useZStackPropsContext, withContext } = createComponent("stack--depth", zStackStyle);
/**
* `ZStack` is a component that groups elements and provides space between child elements.
*
* @see https://yamada-ui.com/docs/components/stack
*/
const ZStack = withContext(({ css, children, direction = "end", fit = true, reverse = false, startIndex = 0,...rest }) => {
if (direction === "start-center") direction = "start";
if (direction === "end-center") direction = "end";
const refMap = useRef(/* @__PURE__ */ new Map());
const [rect, setRect] = useState({
height: 0,
width: 0
});
const vertical = useCallback((space) => {
if (direction.startsWith("start")) return { [!reverse ? "bottom" : "top"]: space };
else if (direction.startsWith("end")) return { [!reverse ? "top" : "bottom"]: space };
else return { [!reverse ? "top" : "bottom"]: 0 };
}, [direction, reverse]);
const horizontal = useCallback((space) => {
if (direction.endsWith("-start")) return { [!reverse ? "right" : "left"]: space };
else if (direction.endsWith("-end")) return { [!reverse ? "left" : "right"]: space };
else return { [!reverse ? "left" : "right"]: 0 };
}, [direction, reverse]);
const cloneChildren = useMemo(() => {
return getValidChildren(children).map((child, index) => {
const ref = createRef();
refMap.current.set(index, ref);
const key = child.key ?? index;
const zIndex = startIndex + index;
const space = `calc({space} * ${index})`;
const css$1 = {
position: "absolute",
zIndex,
...vertical(space),
...horizontal(space)
};
return /* @__PURE__ */ jsx(Fragment, { children: cloneElement(child, {
...child.props,
ref: mergeRefs(child.props.ref, ref),
css: mergeCSS(child.props.css, css$1)
}) }, key);
});
}, [
children,
startIndex,
vertical,
horizontal
]);
useEffect(() => {
if (!fit) return;
let negativeLeft = direction.endsWith("-start");
let negativeTop = direction.startsWith("start");
let width = 0;
let height = 0;
if (reverse) {
negativeLeft = !negativeLeft;
negativeTop = !negativeTop;
}
for (const ref of refMap.current.values()) {
if (!ref.current) continue;
let { offsetHeight, offsetLeft, offsetParent, offsetTop, offsetWidth } = ref.current;
if (!offsetParent && true) continue;
if (negativeLeft) offsetLeft = (offsetParent?.offsetWidth ?? 0) - offsetLeft - offsetWidth;
if (negativeTop) offsetTop = (offsetParent?.offsetHeight ?? 0) - offsetTop - offsetHeight;
offsetWidth += offsetLeft;
offsetHeight += offsetTop;
if (offsetWidth > width) width = offsetWidth;
if (offsetHeight > height) height = offsetHeight;
}
setRect({
height,
width
});
}, [
cloneChildren,
direction,
reverse,
fit
]);
return /* @__PURE__ */ jsx(styled.div, {
css,
minHeight: fit ? `${rect.height}px` : void 0,
minWidth: fit ? `${rect.width}px` : void 0,
...rest,
children: cloneChildren
});
})(void 0, (props) => {
const css = useInjectVarsIntoCss(props.css, { gap: "space" });
return {
...useInjectVarsIntoProps(props, { gap: "space" }),
css
};
});
//#endregion
export { ZStack, ZStackPropsContext, useZStackPropsContext };
//# sourceMappingURL=z-stack.js.map