@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
157 lines (153 loc) • 4.93 kB
JavaScript
"use client";
import { useUpdateEffect } from "../../utils/effect.js";
import { assignRef } from "../../utils/ref.js";
import { utils_exports } from "../../utils/index.js";
import { Portal } from "../portal/portal.js";
import { Background } from "./background.js";
import { Page } from "./page.js";
import { Screen } from "./screen.js";
import { createContext, createRef, use, useMemo, useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { AnimatePresence } from "motion/react";
import { RemoveScroll } from "react-remove-scroll";
//#region src/components/loading/loading-provider.tsx
const LoadingContext = createContext({});
const createController = () => ({
finish: createRef(),
force: createRef(),
start: createRef(),
update: createRef()
});
const createMethods = (refs) => ({
finish: () => refs.current.finish.current?.(),
force: (state) => refs.current.force.current?.(state),
start: (props) => refs.current.start.current?.(props),
update: (props) => refs.current.update.current?.(props)
});
const incrementCount = (prev) => prev + 1;
const decrementCount = (prev) => prev === 0 ? prev : prev - 1;
const LoadingProvider = ({ background: backgroundConfig, children, page: pageConfig, screen: screenConfig }) => {
const screen = useRef(createController());
const page = useRef(createController());
const background = useRef(createController());
return /* @__PURE__ */ jsxs(LoadingContext, {
value: useMemo(() => ({
background: createMethods(background),
page: createMethods(page),
screen: createMethods(screen)
}), []),
children: [
children,
/* @__PURE__ */ jsx(Controller, {
ref: screen,
...screenConfig,
component: Screen
}),
/* @__PURE__ */ jsx(Controller, {
ref: page,
...pageConfig,
component: Page
}),
/* @__PURE__ */ jsx(Controller, {
ref: background,
...backgroundConfig,
blockScrollOnMount: backgroundConfig?.blockScrollOnMount ?? false,
component: Background
})
]
});
};
const Controller = ({ ref, allowPinchZoom = false, blockScrollOnMount = true, component: Component, duration: durationProp = null, loadingCount: loadingCountProp = 0, loadingScheme: loadingSchemeProp = "oval" }) => {
const loading = useRef(false);
const [{ duration, loadingCount, loadingScheme, message }, setState] = useState({
duration: durationProp,
loadingCount: loadingCountProp,
loadingScheme: loadingSchemeProp,
message: void 0
});
const { finish, force, start, update } = useMemo(() => ({
finish: () => {
loading.current = false;
setState(({ loadingCount: loadingCount$1 }) => ({
duration: durationProp,
loadingCount: decrementCount(loadingCount$1),
loadingScheme: loadingSchemeProp,
message: void 0
}));
},
force: ({ duration: duration$1 = durationProp, loadingCount: loadingCount$1 = 0, loadingScheme: loadingScheme$1 = loadingSchemeProp, message: message$1 }) => {
loading.current = !!loadingCount$1;
setState({
duration: duration$1,
loadingCount: loadingCount$1,
loadingScheme: loadingScheme$1,
message: message$1
});
},
start: ({ duration: duration$1 = durationProp, loadingScheme: loadingScheme$1 = loadingSchemeProp, message: message$1 } = {}) => {
loading.current = true;
setState(({ loadingCount: loadingCount$1 }) => ({
duration: duration$1,
loadingCount: incrementCount(loadingCount$1),
loadingScheme: loadingScheme$1,
message: message$1
}));
},
update: (next) => setState((prev) => ({
...prev,
...next
}))
}), [durationProp, loadingSchemeProp]);
assignRef(ref.current.start, start);
assignRef(ref.current.finish, finish);
assignRef(ref.current.update, update);
assignRef(ref.current.force, force);
const props = {
duration,
initial: loadingCountProp > 0 ? false : "initial",
loadingScheme,
message,
onFinish: finish
};
useUpdateEffect(() => {
if (loadingCountProp > 0 || (0, utils_exports.isNumber)(durationProp)) setState({
duration: durationProp,
loadingCount: loadingCountProp,
loadingScheme: loadingSchemeProp,
message: void 0
});
}, [
loadingCountProp,
durationProp,
loadingSchemeProp
]);
return /* @__PURE__ */ jsx(AnimatePresence, {
initial: false,
children: loadingCount ? /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(RemoveScroll, {
allowPinchZoom,
enabled: blockScrollOnMount,
forwardProps: true,
children: /* @__PURE__ */ jsx(Component, { ...props })
}) }) : null
});
};
/**
* `useLoading` is a custom hook for controlling the loading of the application.
*
* @see https://yamada-ui.com/docs/hooks/use-loading
*/
const useLoading = () => {
const { background, page, screen } = use(LoadingContext);
return useMemo(() => ({
background,
page,
screen
}), [
background,
page,
screen
]);
};
//#endregion
export { LoadingProvider, useLoading };
//# sourceMappingURL=loading-provider.js.map