UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

208 lines (204 loc) • 6.37 kB
"use client"; import { useUpdateEffect } from "../../utils/effect.js"; import { utils_exports } from "../../utils/index.js"; import { varAttr } from "../../core/system/var.js"; import { createSlotComponent } from "../../core/components/create-component.js"; import { motion as motion$1 } from "../motion/factory.js"; import { createTransition } from "../motion/transition.js"; import { useTimeout } from "../../hooks/use-timeout/index.js"; import { AlertDescription, AlertIcon, AlertLoading, AlertRoot, AlertTitle } from "../alert/alert.js"; import { CloseButton } from "../close-button/close-button.js"; import { snacksStyle } from "./snacks.style.js"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import { AnimatePresence, useIsPresent } from "motion/react"; //#region src/components/snacks/snacks.tsx const { ComponentContext, PropsContext: SnacksPropsContext, useComponentContext, usePropsContext: useSnacksPropsContext, withContext, withProvider } = createSlotComponent("snacks", snacksStyle); const Snacks = withProvider(({ snacks: { direction = "start", items, startIndex = 0 }, listProps,...rest }) => { const count = items.length; const elMapRef = useRef(/* @__PURE__ */ new Map()); const [height, setHeight] = useState(0); const [exist, setExist] = useState(!!count); const show = !!count || exist; const context = useMemo(() => ({ direction, elMapRef, setExist, startIndex }), [direction, startIndex]); const onExitComplete = useCallback(() => { if (!count) setExist(false); }, [count]); useEffect(() => { let height$1 = 0; if (!count) return; const els = [...elMapRef.current.values()].slice(0, count); for (const el of els) { if (!el) continue; let { offsetHeight, offsetTop } = el; offsetHeight += offsetTop; if (offsetHeight > height$1) height$1 = offsetHeight; } setHeight(height$1); }, [count, direction]); useUpdateEffect(() => { if (!!count) setExist(true); }, [count]); return /* @__PURE__ */ jsx(ComponentContext, { value: context, children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: show ? /* @__PURE__ */ jsx(motion$1.div, { ...rest, children: /* @__PURE__ */ jsx(SnackList, { custom: { height }, ...listProps, children: /* @__PURE__ */ jsx(AnimatePresence, { onExitComplete, children: items.map((props, index) => { return /* @__PURE__ */ jsx(Snack, { index, lastIndex: count - index - 1, ...props }, props.id); }) }) }) }) : null }) }); }, "root")({ animate: "animate", exit: "exit", initial: "initial", variants: { animate: { padding: "var(--top) 0 var(--bottom)", transition: { duration: .4 } }, exit: { padding: 0 }, initial: { padding: 0 } } }, ({ gap, gutter = [0, "lg"], negativeMargins = true,...rest }) => ({ "data-negative": (0, utils_exports.dataAttr)(negativeMargins), "--bottom": varAttr(gutter[1], "spaces", "0px"), "--gap": varAttr(gap, "spaces"), "--top": varAttr(gutter[0], "spaces", "0px"), ...rest })); const SnackList = withContext(motion$1.div, "list")({ animate: "animate", exit: "exit", initial: "initial", role: "list", variants: { animate: ({ height }) => ({ height, opacity: 1, transition: { duration: .4 } }), exit: { height: 0, opacity: 0 }, initial: { height: 0, opacity: 1 } } }); const Snack = withContext(({ variant = "plain", closable = true, description, duration: durationProp = null, loadingScheme, status, title, withIcon = true, closeButtonProps, contentProps, descriptionProps, iconProps, loadingProps, titleProps, onClose: onCloseProp, onCloseComplete,...rest }) => { const [duration, setDuration] = useState(durationProp); const present = useIsPresent(); const onClose = present ? onCloseProp : utils_exports.noop; const onMouseEnter = useCallback(() => { setDuration(null); }, []); const onMouseLeave = useCallback(() => { setDuration(durationProp); }, [durationProp]); useUpdateEffect(() => { if (!present) onCloseComplete?.(); }, [present]); useUpdateEffect(() => { setDuration(durationProp); }, [durationProp]); useTimeout(onClose, duration); return /* @__PURE__ */ jsxs(AlertRoot, { as: motion$1.div, variant, status, ...rest, onMouseEnter: (0, utils_exports.handlerAll)(rest.onMouseEnter, onMouseEnter), onMouseLeave: (0, utils_exports.handlerAll)(rest.onMouseLeave, onMouseLeave), children: [ withIcon ? loadingScheme ? /* @__PURE__ */ jsx(AlertLoading, { loadingScheme, ...loadingProps }) : /* @__PURE__ */ jsx(AlertIcon, { ...iconProps }) : null, /* @__PURE__ */ jsxs(SnackContent, { "data-close-button": (0, utils_exports.dataAttr)(closable), ...contentProps, children: [title ? /* @__PURE__ */ jsx(AlertTitle, { me: "0", ...titleProps, children: title }) : null, description ? /* @__PURE__ */ jsx(AlertDescription, { ...descriptionProps, children: description }) : null] }), closable ? /* @__PURE__ */ jsx(SnackCloseButton, { "data-variant": variant, ...closeButtonProps, onClick: (0, utils_exports.handlerAll)(closeButtonProps?.onClick, onClose) }) : null ] }); }, "item")({ animate: "animate", exit: "exit", initial: "initial", layout: true, role: "listitem", variants: { animate: ({ index }) => ({ opacity: 1, transition: createTransition.enter()(!index ? .2 : 0, .4), y: 0 }), exit: { opacity: 0, transition: createTransition.exit()(void 0, .2) }, initial: ({ direction, index }) => ({ opacity: 0, ...index ? { y: (direction === "start" ? -1 : 1) * 16 } : {} }) } }, ({ index, lastIndex,...rest }) => { const ref = useRef(null); const { direction, elMapRef, startIndex } = useComponentContext(); useEffect(() => { const elMap = elMapRef.current; elMap.set(index, ref.current); return () => { elMap.delete(index); }; }, [elMapRef, index]); return { ref, "--index": direction === "start" ? lastIndex : index, "--z-index": startIndex + index, custom: { direction, index }, ...rest }; }); const SnackContent = withContext("div", "content")(); const SnackCloseButton = withContext(CloseButton, "closeButton")(); //#endregion export { Snacks }; //# sourceMappingURL=snacks.js.map