UNPKG

@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
"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