@arolariu/components
Version:
🎨 70+ beautiful, accessible React components built on Base UI. TypeScript-first, CSS Modules styling, tree-shakeable, SSR-ready. Perfect for modern web apps, design systems & rapid prototyping. Zero config, maximum flexibility! ⚡
457 lines (456 loc) • 18.5 kB
JavaScript
"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { Toast } from "@base-ui/react/toast";
import { AlertCircle, BellRing, CheckCircle2, Info, LoaderCircle, TriangleAlert, X } from "lucide-react";
import { cn } from "../../lib/utilities.js";
import toast_module from "./toast.module.js";
import * as __rspack_external_react from "react";
const DEFAULT_TOAST_DURATION = 5000;
const DEFAULT_TOAST_LIMIT = 3;
const DEFAULT_TOAST_CLOSE_LABEL = "Close notification";
const DEFAULT_VIEWPORT_ARIA_LABEL = "Notifications";
const positionStyles = {
"bottom-center": toast_module.viewportBottomCenter,
"bottom-left": toast_module.viewportBottomLeft,
"bottom-right": toast_module.viewportBottomRight,
"top-center": toast_module.viewportTopCenter,
"top-left": toast_module.viewportTopLeft,
"top-right": toast_module.viewportTopRight
};
const variantStyles = {
default: toast_module["default"],
error: toast_module.error,
info: toast_module.info,
loading: toast_module.loading,
success: toast_module.success,
warning: toast_module.warning
};
const toastManager = Toast.createToastManager();
const toastHistory = [];
const activeToasts = new Map();
const toastRecords = new Map();
const toasterRegistrations = new Map();
let toastSequence = 0;
function createToastIdentifier(identifier) {
if (void 0 !== identifier) return String(identifier);
if ("function" == typeof globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();
toastSequence += 1;
return `toast-${String(toastSequence)}`;
}
function isRenderableFactory(value) {
return "function" == typeof value;
}
function resolveRenderable(value) {
const resolvedValue = isRenderableFactory(value) ? value() : value;
return resolvedValue;
}
function getSnapshot(id, variant, title, description) {
return {
description,
id,
title,
variant
};
}
function registerToast(snapshot) {
activeToasts.set(snapshot.id, snapshot);
toastHistory.push(snapshot);
}
function registerToastRecord(record) {
toastRecords.set(record.snapshot.id, record);
registerToast(record.snapshot);
}
function replaceToastHistorySnapshot(snapshot) {
for(let index = toastHistory.length - 1; index >= 0; index -= 1)if (toastHistory[index]?.id === snapshot.id) {
toastHistory[index] = snapshot;
return;
}
toastHistory.push(snapshot);
}
function replaceToastRecord(record) {
toastRecords.set(record.snapshot.id, record);
activeToasts.set(record.snapshot.id, record.snapshot);
replaceToastHistorySnapshot(record.snapshot);
}
function unregisterToast(toastId) {
if (!toastId) {
activeToasts.clear();
toastRecords.clear();
return;
}
activeToasts.delete(toastId);
toastRecords.delete(toastId);
}
function getActiveToasterRegistration() {
const registrations = [
...toasterRegistrations.values()
];
return registrations.at(-1) ?? {
closeButton: true,
toastOptions: {}
};
}
function mergeToastOptions(options) {
return {
...getActiveToasterRegistration().toastOptions,
...options
};
}
function isToastVariant(value) {
return "default" === value || "error" === value || "info" === value || "loading" === value || "success" === value || "warning" === value;
}
function createToastMetadata(variant, options, closeButton, customContent) {
return {
action: options.action,
cancel: options.cancel,
className: options.className,
closeButton,
closeButtonAriaLabel: options.closeButtonAriaLabel ?? DEFAULT_TOAST_CLOSE_LABEL,
customContent,
descriptionClassName: options.descriptionClassName,
style: options.style,
variant
};
}
function createToastRecord({ id, message, options, variant, customContent }) {
const activeRegistration = getActiveToasterRegistration();
const closeButton = options.closeButton ?? activeRegistration.closeButton;
const title = void 0 === message ? void 0 : resolveRenderable(message);
const description = resolveRenderable(options.description);
const snapshot = getSnapshot(id, variant, title, description);
return {
metadata: createToastMetadata(variant, options, closeButton, customContent),
options,
snapshot
};
}
function createToastLifecycleHandlers(toastId, record) {
return {
onClose: ()=>{
record.options.onDismiss?.(activeToasts.get(toastId) ?? record.snapshot);
},
onRemove: ()=>{
const snapshot = activeToasts.get(toastId) ?? record.snapshot;
unregisterToast(toastId);
record.options.onAutoClose?.(snapshot);
}
};
}
function createToastAddPayload(record) {
const lifecycleHandlers = createToastLifecycleHandlers(record.snapshot.id, record);
return {
description: record.snapshot.description,
id: record.snapshot.id,
priority: record.options.priority,
timeout: record.options.duration,
title: record.snapshot.title,
type: record.snapshot.variant,
data: record.metadata,
...lifecycleHandlers
};
}
function buildToastOptions(message, variant, options) {
const mergedOptions = mergeToastOptions(options);
const toastId = createToastIdentifier(mergedOptions.id);
const record = createToastRecord({
id: toastId,
message,
options: mergedOptions,
variant
});
registerToastRecord(record);
return createToastAddPayload(record);
}
function showToast(message, variant, options) {
const payload = buildToastOptions(message, variant, options);
return toastManager.add(payload);
}
function dismissToast(toastId) {
if (void 0 === toastId) {
unregisterToast();
toastManager.close();
return;
}
const normalizedToastId = String(toastId);
unregisterToast(normalizedToastId);
toastManager.close(normalizedToastId);
return normalizedToastId;
}
function updateToast(toastId, options) {
const normalizedToastId = String(toastId);
const existingRecord = toastRecords.get(normalizedToastId);
const mergedOptions = {
...existingRecord?.options,
...options
};
const variant = options.variant ?? existingRecord?.snapshot.variant ?? "default";
const nextMessage = void 0 === options.message ? existingRecord?.snapshot.title : resolveRenderable(options.message);
const nextDescription = void 0 === options.description ? existingRecord?.snapshot.description : resolveRenderable(options.description);
const metadata = createToastMetadata(variant, mergedOptions, mergedOptions.closeButton ?? existingRecord?.metadata.closeButton ?? getActiveToasterRegistration().closeButton, existingRecord?.metadata.customContent);
const record = {
metadata,
options: mergedOptions,
snapshot: getSnapshot(normalizedToastId, variant, nextMessage, nextDescription)
};
replaceToastRecord(record);
const payload = {
description: record.snapshot.description,
priority: record.options.priority,
timeout: record.options.duration,
title: record.snapshot.title,
type: record.snapshot.variant,
data: record.metadata,
...createToastLifecycleHandlers(normalizedToastId, record)
};
toastManager.update(normalizedToastId, payload);
return normalizedToastId;
}
function resolvePromiseState(state, value) {
if ("function" == typeof state) return Promise.resolve(state(value));
return Promise.resolve(state);
}
function isPromiseResolvedOptions(value) {
return "object" == typeof value && null !== value && "message" in value;
}
function isToastAction(value) {
if (/*#__PURE__*/ __rspack_external_react.isValidElement(value)) return false;
return "object" == typeof value && null !== value && "label" in value && "onClick" in value;
}
function getVariantIcon(variant) {
const icons = {
default: /*#__PURE__*/ jsx(BellRing, {
"aria-hidden": "true",
className: toast_module.icon
}),
error: /*#__PURE__*/ jsx(AlertCircle, {
"aria-hidden": "true",
className: toast_module.icon
}),
info: /*#__PURE__*/ jsx(Info, {
"aria-hidden": "true",
className: toast_module.icon
}),
loading: /*#__PURE__*/ jsx(LoaderCircle, {
"aria-hidden": "true",
className: cn(toast_module.icon, toast_module.iconSpin)
}),
success: /*#__PURE__*/ jsx(CheckCircle2, {
"aria-hidden": "true",
className: toast_module.icon
}),
warning: /*#__PURE__*/ jsx(TriangleAlert, {
"aria-hidden": "true",
className: toast_module.icon
})
};
return icons[variant];
}
function ToastActions({ toastId, action, cancel }) {
if (!action && !cancel) return null;
const renderAction = (value, className)=>{
if (!value) return null;
if (/*#__PURE__*/ __rspack_external_react.isValidElement(value)) return value;
if (isToastAction(value)) return /*#__PURE__*/ jsx("button", {
className: className,
type: "button",
onClick: (event)=>{
value.onClick(event);
dismissToast(toastId);
},
children: value.label
});
return null;
};
return /*#__PURE__*/ jsxs("div", {
className: toast_module.actions,
children: [
renderAction(cancel, toast_module.secondaryAction),
renderAction(action, toast_module.primaryAction)
]
});
}
function ToastViewportContent() {
const { toasts } = Toast.useToastManager();
return /*#__PURE__*/ jsx(Fragment, {
children: toasts.map((toastItem)=>{
const variant = isToastVariant(toastItem.type) ? toastItem.type : "default";
const action = toastItem.data?.action;
const cancel = toastItem.data?.cancel;
return /*#__PURE__*/ jsx(Toast.Root, {
toast: toastItem,
className: cn(toast_module.root, variantStyles[variant], toastItem.data?.className),
"data-variant": variant,
style: toastItem.data?.style,
children: /*#__PURE__*/ jsx(Toast.Content, {
className: toast_module.content,
children: toastItem.data?.customContent ?? /*#__PURE__*/ jsxs(Fragment, {
children: [
/*#__PURE__*/ jsx("div", {
className: toast_module.leading,
children: getVariantIcon(variant)
}),
/*#__PURE__*/ jsxs("div", {
className: toast_module.body,
children: [
toastItem.title ? /*#__PURE__*/ jsx(Toast.Title, {
className: toast_module.title,
children: toastItem.title
}) : null,
toastItem.description ? /*#__PURE__*/ jsx(Toast.Description, {
className: cn(toast_module.description, toastItem.data?.descriptionClassName),
children: toastItem.description
}) : null,
/*#__PURE__*/ jsx(ToastActions, {
action: action,
cancel: cancel,
toastId: toastItem.id
})
]
}),
toastItem.data?.closeButton ? /*#__PURE__*/ jsx(Toast.Close, {
"aria-label": toastItem.data.closeButtonAriaLabel,
className: toast_module.close,
children: /*#__PURE__*/ jsx(X, {
"aria-hidden": "true",
className: toast_module.closeIcon
})
}) : null
]
})
})
}, toastItem.id);
})
});
}
const Toaster = /*#__PURE__*/ __rspack_external_react.forwardRef(({ className, closeButton = true, containerAriaLabel = DEFAULT_VIEWPORT_ARIA_LABEL, duration = DEFAULT_TOAST_DURATION, position = "bottom-right", style, toastOptions, visibleToasts = DEFAULT_TOAST_LIMIT }, forwardedRef)=>{
const toasterId = __rspack_external_react.useId();
__rspack_external_react.useEffect(()=>{
toasterRegistrations.set(toasterId, {
closeButton,
toastOptions: toastOptions ?? {}
});
return ()=>{
toasterRegistrations.delete(toasterId);
};
}, [
closeButton,
toastOptions,
toasterId
]);
return /*#__PURE__*/ jsx(Toast.Provider, {
limit: visibleToasts,
timeout: duration,
toastManager: toastManager,
children: /*#__PURE__*/ jsx(Toast.Portal, {
children: /*#__PURE__*/ jsx(Toast.Viewport, {
ref: forwardedRef,
"aria-label": containerAriaLabel,
className: cn(toast_module.viewport, positionStyles[position], className),
style: style,
children: /*#__PURE__*/ jsx(ToastViewportContent, {})
})
})
});
});
Toaster.displayName = "Toaster";
const toast = (message, options)=>showToast(message, "default", options);
toast.success = (message, options)=>showToast(message, "success", options);
toast.error = (message, options)=>showToast(message, "error", options);
toast.info = (message, options)=>showToast(message, "info", options);
toast.warning = (message, options)=>showToast(message, "warning", options);
toast.loading = (message, options)=>showToast(message, "loading", options);
toast.message = (message, options)=>showToast(message, "default", options);
toast.update = (toastId, options)=>updateToast(toastId, options);
toast.dismiss = (toastId)=>dismissToast(toastId);
toast.custom = (renderer, options)=>{
const mergedOptions = mergeToastOptions(options);
const toastId = createToastIdentifier(mergedOptions.id);
const record = createToastRecord({
customContent: renderer(toastId),
id: toastId,
options: mergedOptions,
variant: "default"
});
registerToastRecord(record);
toastManager.add(createToastAddPayload(record));
return toastId;
};
function mergePromiseToastOptions(baseOptions, override) {
if (!override) return baseOptions;
return {
action: override.action ?? baseOptions.action,
cancel: override.cancel ?? baseOptions.cancel,
className: override.className ?? baseOptions.className,
closeButton: override.closeButton ?? baseOptions.closeButton,
closeButtonAriaLabel: override.closeButtonAriaLabel ?? baseOptions.closeButtonAriaLabel,
description: override.description ?? baseOptions.description,
descriptionClassName: override.descriptionClassName ?? baseOptions.descriptionClassName,
duration: override.duration ?? baseOptions.duration,
id: override.id ?? baseOptions.id,
onAutoClose: override.onAutoClose ?? baseOptions.onAutoClose,
onDismiss: override.onDismiss ?? baseOptions.onDismiss,
priority: override.priority ?? baseOptions.priority,
style: override.style ?? baseOptions.style
};
}
function getPromiseBaseOptions(options) {
return {
action: options?.action,
cancel: options?.cancel,
className: options?.className,
closeButton: options?.closeButton,
closeButtonAriaLabel: options?.closeButtonAriaLabel,
description: options?.description,
descriptionClassName: options?.descriptionClassName,
duration: options?.duration,
id: options?.id,
onAutoClose: options?.onAutoClose,
onDismiss: options?.onDismiss,
priority: options?.priority,
style: options?.style
};
}
function showResolvedPromiseToast(loadingToastId, variant, resolvedState, baseOptions) {
if (!resolvedState) {
if (loadingToastId) dismissToast(loadingToastId);
return;
}
const overrideOptions = isPromiseResolvedOptions(resolvedState) ? resolvedState : void 0;
const message = isPromiseResolvedOptions(resolvedState) ? resolvedState.message : resolvedState;
const mergedOptions = mergePromiseToastOptions(baseOptions, overrideOptions);
if (loadingToastId) return void toast.update(loadingToastId, {
...mergedOptions,
message,
variant
});
showToast(message, variant, mergedOptions);
}
toast.promise = async function(promiseValue, options) {
const pendingPromise = "function" == typeof promiseValue ? promiseValue() : promiseValue;
const baseOptions = getPromiseBaseOptions(options);
const loadingState = options?.loading;
const loadingOptions = isPromiseResolvedOptions(loadingState) ? loadingState : void 0;
const loadingMessage = isPromiseResolvedOptions(loadingState) ? loadingState.message : loadingState;
const loadingToastId = loadingMessage ? toast.loading(loadingMessage, mergePromiseToastOptions(baseOptions, loadingOptions)) : void 0;
try {
const result = await pendingPromise;
const successState = await resolvePromiseState(options?.success, result);
showResolvedPromiseToast(loadingToastId, "success", successState, baseOptions);
return result;
} catch (error) {
const errorState = await resolvePromiseState(options?.error, error);
showResolvedPromiseToast(loadingToastId, "error", errorState, baseOptions);
throw error;
} finally{
const handleFinally = options?.finally;
if (handleFinally) await handleFinally();
}
};
toast.getToasts = ()=>[
...activeToasts.values()
];
toast.getHistory = ()=>[
...toastHistory
];
export { Toaster, toast };
//# sourceMappingURL=toast.js.map