@yamada-ui/notice
Version:
Yamada UI notice component
251 lines (249 loc) • 7.57 kB
JavaScript
"use client"
// src/notice.tsx
import {
Alert,
AlertDescription,
AlertIcon,
AlertTitle
} from "@yamada-ui/alert";
import { CloseButton } from "@yamada-ui/close-button";
import { ui, useTheme } from "@yamada-ui/core";
import { cx, merge } from "@yamada-ui/utils";
import { useMemo } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
var findId = (options, id) => options.find((notice) => notice.id === id);
var findNotice = (state, id) => {
const placement = getNoticePlacement(state, id);
const index = placement ? state[placement].findIndex((notice) => notice.id === id) : -1;
return { index, placement };
};
var getNoticePlacement = (state, id) => {
for (const [placement, values] of Object.entries(state)) {
if (findId(values, id)) return placement;
}
};
var counter = 0;
var createNotice = (message, {
id,
style,
duration,
placement = "top",
status,
onCloseComplete
}) => {
counter += 1;
id != null ? id : id = counter;
return {
id,
style,
duration,
isDelete: false,
message,
placement,
status,
onCloseComplete,
onDelete: () => noticeStore.remove(String(id), placement)
};
};
var createRender = (options) => {
const { component } = options;
const Render = (props) => {
if (typeof component === "function") {
return component({ ...props, ...options });
} else {
return /* @__PURE__ */ jsx(Notice, { ...props, ...options });
}
};
return Render;
};
var createNoticeFunc = (defaultOptions, theme) => {
var _a, _b, _c;
const themeOptions = (_c = (_b = (_a = theme.__config) == null ? void 0 : _a.notice) == null ? void 0 : _b.options) != null ? _c : {};
const computedOptions = (options) => merge(themeOptions, merge(defaultOptions, options));
const notice = (options = {}) => {
options = computedOptions(options);
const message = createRender(options);
return noticeStore.create(message, options);
};
notice.update = (id, options) => {
options = computedOptions(options);
noticeStore.update(id, options);
};
notice.closeAll = noticeStore.closeAll;
notice.close = noticeStore.close;
notice.isActive = noticeStore.isActive;
return notice;
};
var useNotice = (defaultOptions) => {
const { theme } = useTheme();
return useMemo(
() => createNoticeFunc(defaultOptions != null ? defaultOptions : {}, theme),
[defaultOptions, theme]
);
};
var initialState = {
bottom: [],
"bottom-left": [],
"bottom-right": [],
top: [],
"top-left": [],
"top-right": []
};
var createNoticeStore = (initialState2) => {
let state = initialState2;
const storeChangeCache = /* @__PURE__ */ new Set();
const setState = (setStateFunc) => {
state = setStateFunc(state);
storeChangeCache.forEach((onStoreChange) => onStoreChange());
};
return {
close: (id) => {
setState((prev) => {
const placement = getNoticePlacement(prev, id);
if (!placement) return prev;
return {
...prev,
[placement]: prev[placement].map(
(notice) => notice.id == id ? { ...notice, isDelete: true } : notice
)
};
});
},
closeAll: ({ placement } = {}) => {
setState((prev) => {
let placements = [
"bottom",
"bottom-right",
"bottom-left",
"top",
"top-left",
"top-right"
];
if (placement) placements = placement;
return placements.reduce(
(acc, placement2) => {
acc[placement2] = prev[placement2].map((notice) => ({
...notice,
isDelete: true
}));
return acc;
},
{ ...prev }
);
});
},
create: (message, options) => {
const limit = options.limit;
const notice = createNotice(message, options);
const { id, placement } = notice;
setState((prev) => {
let prevNotices = prev[placement];
if (limit !== void 0 && limit > 0 && prevNotices.length > limit - 1) {
const n = prevNotices.length - (limit - 1);
const notices2 = placement.includes("top") ? prevNotices.slice(n * -1) : prevNotices.slice(0, n);
const ids = notices2.map(({ id: id2 }) => id2);
prevNotices = prevNotices.map(
(notice2) => ids.includes(notice2.id) ? { ...notice2, isDelete: true } : notice2
);
}
const notices = placement.includes("top") ? [notice, ...prevNotices] : [...prevNotices, notice];
return { ...prev, [placement]: notices };
});
return id;
},
getSnapshot: () => state,
isActive: (id) => Boolean(findNotice(noticeStore.getSnapshot(), id).placement),
remove: (id, placement) => {
setState((prevState) => ({
...prevState,
[placement]: prevState[placement].filter((notice) => notice.id != id)
}));
},
subscribe: (onStoreChange) => {
storeChangeCache.add(onStoreChange);
return () => {
setState(() => initialState2);
storeChangeCache.delete(onStoreChange);
};
},
update: (id, options) => {
setState((prev) => {
const next = { ...prev };
const { index, placement } = findNotice(next, id);
if (placement && index !== -1 && next[placement][index]) {
next[placement][index] = {
...next[placement][index],
...options,
message: createRender(options)
};
}
return next;
});
}
};
};
var noticeStore = createNoticeStore(initialState);
var Notice = ({
className,
colorScheme,
variant = "basic",
closeStrategy = "button",
description,
icon,
isClosable,
status,
title,
onClose
}) => {
const isButtonClosable = isClosable && (closeStrategy === "button" || closeStrategy === "both");
const isElementClosable = isClosable && (closeStrategy === "element" || closeStrategy === "both");
return /* @__PURE__ */ jsxs(
Alert,
{
className: cx("ui-notice", className),
colorScheme,
variant,
alignItems: "start",
boxShadow: "fallback(lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05))",
pe: isButtonClosable ? 8 : void 0,
status,
onClick: isElementClosable ? onClose : void 0,
children: [
/* @__PURE__ */ jsx(
AlertIcon,
{
className: "ui-notice__icon",
variant: icon == null ? void 0 : icon.variant,
...(icon == null ? void 0 : icon.color) ? { color: icon.color } : {},
children: icon == null ? void 0 : icon.children
}
),
/* @__PURE__ */ jsxs(ui.div, { flex: "1", children: [
title ? /* @__PURE__ */ jsx(AlertTitle, { className: "ui-notice__title", lineClamp: 1, children: title }) : null,
description ? /* @__PURE__ */ jsx(AlertDescription, { className: "ui-notice__desc", lineClamp: 3, children: description }) : null
] }),
isButtonClosable ? /* @__PURE__ */ jsx(
CloseButton,
{
className: "ui-notice__close-button",
size: "sm",
position: "absolute",
right: 2,
top: 2,
onClick: (ev) => {
ev.stopPropagation();
onClose == null ? void 0 : onClose();
}
}
) : null
]
}
);
};
Notice.displayName = "Notice";
Notice.__ui__ = "Notice";
export {
useNotice,
noticeStore
};
//# sourceMappingURL=chunk-UPOKQ3L5.mjs.map