@yamada-ui/loading
Version:
Yamada UI loading components
393 lines (391 loc) • 12 kB
JavaScript
"use client"
import {
Loading
} from "./chunk-FS4WFG6W.mjs";
// src/loading-provider.tsx
import { forwardRef, memo, ui } from "@yamada-ui/core";
import { AnimatePresence, motion } from "@yamada-ui/motion";
import { Portal } from "@yamada-ui/portal";
import { useTimeout } from "@yamada-ui/use-timeout";
import {
assignRef,
isNumber,
isValidElement,
useUpdateEffect
} from "@yamada-ui/utils";
import {
createContext,
createRef,
useContext,
useMemo,
useRef,
useState
} from "react";
import { RemoveScroll } from "react-remove-scroll";
import { jsx, jsxs } from "react/jsx-runtime";
var LoadingContext = createContext({});
var createLoadingRefs = () => ({
finish: createRef(),
force: createRef(),
isLoading: createRef(),
start: createRef(),
update: createRef()
});
var createLoadingFunc = (refs) => ({
finish: () => {
var _a, _b;
return (_b = (_a = refs.current.finish).current) == null ? void 0 : _b.call(_a);
},
force: (state) => {
var _a, _b;
return (_b = (_a = refs.current.force).current) == null ? void 0 : _b.call(_a, state);
},
isLoading: () => {
var _a, _b, _c;
return (_c = (_b = (_a = refs.current.isLoading).current) == null ? void 0 : _b.call(_a)) != null ? _c : false;
},
start: (props) => {
var _a, _b;
return (_b = (_a = refs.current.start).current) == null ? void 0 : _b.call(_a, props);
},
update: (props) => {
var _a, _b;
return (_b = (_a = refs.current.update).current) == null ? void 0 : _b.call(_a, props);
}
});
var incrementCount = (prev) => prev + 1;
var decrementCount = (prev) => prev === 0 ? prev : prev - 1;
var LoadingProvider = ({
background,
children,
custom,
page,
screen
}) => {
var _a, _b, _c, _d, _e;
const screenRefs = useRef(createLoadingRefs());
const pageRefs = useRef(createLoadingRefs());
const backgroundRefs = useRef(createLoadingRefs());
const customRefs = useRef(createLoadingRefs());
const screenLoadingFunc = createLoadingFunc(screenRefs);
const pageLoadingFunc = createLoadingFunc(pageRefs);
const backgroundLoadingFunc = createLoadingFunc(backgroundRefs);
const customLoadingFunc = createLoadingFunc(customRefs);
const value = {
background: backgroundLoadingFunc,
custom: customLoadingFunc,
page: pageLoadingFunc,
screen: screenLoadingFunc
};
return /* @__PURE__ */ jsxs(LoadingContext.Provider, { value, children: [
children,
/* @__PURE__ */ jsx(
Controller,
{
controlRefs: screenRefs,
...screen,
component: (_a = screen == null ? void 0 : screen.component) != null ? _a : (props, ref) => /* @__PURE__ */ jsx(ScreenComponent, { ref, ...props })
}
),
/* @__PURE__ */ jsx(
Controller,
{
controlRefs: pageRefs,
...page,
component: (_b = page == null ? void 0 : page.component) != null ? _b : (props, ref) => /* @__PURE__ */ jsx(PageComponent, { ref, ...props })
}
),
/* @__PURE__ */ jsx(
Controller,
{
controlRefs: backgroundRefs,
...background,
blockScrollOnMount: (_c = background == null ? void 0 : background.blockScrollOnMount) != null ? _c : false,
component: (_d = background == null ? void 0 : background.component) != null ? _d : (props, ref) => /* @__PURE__ */ jsx(BackgroundComponent, { ref, ...props })
}
),
/* @__PURE__ */ jsx(
Controller,
{
blockScrollOnMount: (_e = background == null ? void 0 : background.blockScrollOnMount) != null ? _e : false,
controlRefs: customRefs,
...custom,
component: custom == null ? void 0 : custom.component
}
)
] });
};
LoadingProvider.__ui__ = "LoadingProvider";
var Controller = ({
allowPinchZoom = false,
appendToParentPortal,
blockScrollOnMount = true,
component,
containerRef,
controlRefs,
duration: durationProps = null,
icon,
initialState,
text
}) => {
const isLoadingRef = useRef(false);
const [{ duration, loadingCount, message }, setState] = useState({
duration: durationProps,
loadingCount: initialState ? 1 : 0,
message: void 0
});
const { finish, force, isLoading, start, update } = useMemo(
() => ({
finish: () => {
isLoadingRef.current = false;
setState(({ loadingCount: loadingCount2 }) => ({
duration: durationProps,
loadingCount: decrementCount(loadingCount2),
message: void 0
}));
},
force: ({ duration: duration2 = durationProps, loadingCount: loadingCount2 = 0, message: message2 }) => {
isLoadingRef.current = !!loadingCount2;
setState({
duration: duration2,
loadingCount: loadingCount2,
message: message2
});
},
isLoading: () => isLoadingRef.current,
start: ({ duration: duration2 = durationProps, message: message2 } = {}) => {
isLoadingRef.current = true;
setState(({ loadingCount: loadingCount2 }) => ({
duration: duration2,
loadingCount: incrementCount(loadingCount2),
message: message2
}));
},
update: (next) => setState((prev) => ({ ...prev, ...next }))
}),
[durationProps]
);
assignRef(controlRefs.current.isLoading, isLoading);
assignRef(controlRefs.current.start, start);
assignRef(controlRefs.current.finish, finish);
assignRef(controlRefs.current.update, update);
assignRef(controlRefs.current.force, force);
const props = {
duration,
icon,
initialState,
message,
text,
onFinish: finish
};
useUpdateEffect(() => {
if (initialState || isNumber(durationProps))
setState({
duration: durationProps,
loadingCount: initialState ? 1 : 0,
message: void 0
});
}, [initialState, durationProps]);
return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: loadingCount ? /* @__PURE__ */ jsx(
Portal,
{
appendToParentPortal,
containerRef,
children: /* @__PURE__ */ jsx(
RemoveScroll,
{
allowPinchZoom,
enabled: blockScrollOnMount,
forwardProps: true,
children: /* @__PURE__ */ jsx(Render, { component, ...props })
}
)
}
) : null });
};
Controller.__ui__ = "Controller";
var Render = forwardRef(
({ component, ...props }, ref) => {
if (typeof component === "function") {
return component(props, ref);
} else {
return null;
}
}
);
Render.displayName = "Render";
Render.__ui__ = "Render";
var Message = ({ message, ...rest }) => {
return message ? isValidElement(message) ? message : /* @__PURE__ */ jsx(ui.p, { ...rest, children: message }) : null;
};
var getVariants = (type = "fade") => ({
animate: {
opacity: 1,
scale: type === "scaleFade" ? 1 : void 0,
transition: {
duration: 0.4,
ease: [0.4, 0, 0.2, 1]
}
},
exit: {
opacity: 0,
scale: type === "scaleFade" ? 0.95 : void 0,
transition: {
duration: 0.4,
ease: [0.4, 0, 1, 1]
}
},
initial: {
opacity: 0,
scale: type === "scaleFade" ? 0.95 : void 0
}
});
var getOverlayStyle = (type = "fill") => ({
alignItems: "center",
bg: type === "fill" ? ["fallback(white, #fbfbfb)", "fallback(black, #141414)"] : "fallback(blackAlpha.600, rgba(0, 0, 0, 0.48))",
bottom: 0,
display: "flex",
h: "100dvh",
justifyContent: "center",
left: 0,
p: "fallback(4, 1rem)",
position: "fixed",
right: 0,
top: 0,
w: "100vw",
zIndex: "fallback(beerus, 9999)"
});
var getMotionProps = (initialState, type = "fade") => ({
animate: "animate",
exit: "exit",
initial: initialState ? false : "initial",
variants: getVariants(type)
});
var ScreenComponent = memo(
forwardRef(
({ duration, icon, initialState, message, text, onFinish }, ref) => {
const css = {
alignItems: "center",
display: "flex",
flexDirection: "column",
gap: "fallback(2, 0.5rem)",
justifyContent: "center",
maxW: "24rem"
};
useTimeout(onFinish, duration);
return /* @__PURE__ */ jsx(
motion.div,
{
ref,
className: "ui-loading-screen",
...getMotionProps(initialState),
__css: getOverlayStyle(),
children: /* @__PURE__ */ jsxs(ui.div, { __css: css, children: [
/* @__PURE__ */ jsx(Loading, { fontSize: "6xl", ...icon }),
/* @__PURE__ */ jsx(Message, { lineClamp: 3, message, ...text })
] })
}
);
}
)
);
ScreenComponent.displayName = "ScreenComponent";
ScreenComponent.__ui__ = "ScreenComponent";
var PageComponent = memo(
forwardRef(
({ duration, icon, initialState, message, text, onFinish }, ref) => {
const css = {
alignItems: "center",
bg: ["fallback(white, #fbfbfb)", "fallback(black, #141414)"],
boxShadow: [
"fallback(lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05))",
"fallback(dark-lg, 0px 0px 0px 1px rgba(0, 0, 0, 0.1), 0px 5px 10px rgba(0, 0, 0, 0.2), 0px 15px 40px rgba(0, 0, 0, 0.4))"
],
display: "flex",
flexDirection: "column",
gap: "fallback(2, 0.5rem)",
justifyContent: "center",
maxW: "24rem",
p: "fallback(4, 1rem)",
rounded: "fallback(md, 0.375rem)"
};
useTimeout(onFinish, duration);
return /* @__PURE__ */ jsx(
motion.div,
{
ref,
className: "ui-loading-page",
...getMotionProps(initialState),
__css: getOverlayStyle("transparent"),
children: /* @__PURE__ */ jsxs(
motion.div,
{
className: "ui-loading-page__inner",
...getMotionProps(initialState, "scaleFade"),
__css: css,
children: [
/* @__PURE__ */ jsx(Loading, { fontSize: "6xl", ...icon }),
/* @__PURE__ */ jsx(Message, { lineClamp: 3, message, ...text })
]
}
)
}
);
}
)
);
PageComponent.displayName = "PageComponent";
PageComponent.__ui__ = "PageComponent";
var BackgroundComponent = memo(
forwardRef(
({ duration, icon, initialState, message, text, onFinish }, ref) => {
const css = {
alignItems: "center",
bg: ["fallback(white, #fbfbfb)", "fallback(black, #141414)"],
bottom: "fallback(4, 1rem)",
boxShadow: [
"fallback(3xl, 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 -25px 50px -12px rgba(0, 0, 0, 0.25))",
"fallback(dark-lg, 0px 0px 0px 1px rgba(0, 0, 0, 0.1), 0px 5px 10px rgba(0, 0, 0, 0.2), 0px 15px 40px rgba(0, 0, 0, 0.4))"
],
display: "flex",
gap: "fallback(2, 0.5rem)",
justifyContent: "center",
maxW: "20rem",
p: "fallback(2, 0.5rem)",
position: "fixed",
right: "fallback(4, 1rem)",
rounded: "fallback(md, 0.375rem)",
zIndex: "fallback(beerus, 9999)"
};
useTimeout(onFinish, duration);
return /* @__PURE__ */ jsxs(
motion.div,
{
ref,
className: "ui-loading-background",
...getMotionProps(initialState, "scaleFade"),
__css: css,
children: [
/* @__PURE__ */ jsx(Loading, { fontSize: "xl", ...icon }),
/* @__PURE__ */ jsx(Message, { fontSize: "sm", lineClamp: 1, message, ...text })
]
}
);
}
)
);
BackgroundComponent.displayName = "BackgroundComponent";
BackgroundComponent.__ui__ = "BackgroundComponent";
var useLoading = () => {
const { background, custom, page, screen } = useContext(LoadingContext);
const context = useMemo(
() => ({ background, custom, page, screen }),
[background, custom, page, screen]
);
return context;
};
export {
LoadingProvider,
useLoading
};
//# sourceMappingURL=chunk-W3VLBPVB.mjs.map