feat(ui): add updateDescription flag to toast API

If false, when updating a toast, the description is left alone. The count will still tick up.
This commit is contained in:
psychedelicious 2024-05-22 07:20:58 +10:00
parent 4a394c60cf
commit 57743239d7

View File

@ -22,6 +22,18 @@ type ToastArg = ToastConfig & {
* // second toast: 'Hello (2)'
*/
withCount?: boolean;
/**
* Whether to update the description when updating the toast. Defaults to true.
* @example
* // updateDescription: true
* toast({ title: 'Hello', description: 'Foo' }); // Foo
* toast({ title: 'Hello', description: 'Bar' }); // Bar
* @example
* // updateDescription: false
* toast({ title: 'Hello', description: 'Foo' }); // Foo
* toast({ title: 'Hello', description: 'Bar' }); // Foo
*/
updateDescription?: boolean;
};
type ToastInternalState = {
@ -48,6 +60,7 @@ const getGetState = (id: string) => () => $toastMap.get()[id] ?? null;
/**
* Creates a toast with the given config. If the toast with the same id already exists, it will be updated.
* When a toast is updated, its title, description, status and duration will be overwritten by the new config.
* Use `updateDescription: false` to keep the description when updating.
* Set duration to `null` to make the toast persistent.
* @param arg The toast config.
* @returns An object with methods to get the toast state, close the toast and check if the toast is active
@ -61,17 +74,20 @@ export const toast = (arg: ToastArg): ToastApi => {
if (arg.withCount === undefined) {
arg.withCount = true;
}
if (arg.updateDescription === undefined) {
arg.updateDescription = true;
}
let state = $toastMap.get()[arg.id];
if (!state) {
// First time caller, create and set the state
state = { id, config: parseConfig(id, arg, 1), count: 1 };
state = { id, config: parseConfig(null, id, arg, 1), count: 1 };
$toastMap.setKey(id, state);
// Create the toast
toastApi(state.config);
} else {
// This toast is already active, update its state
state.count += 1;
state.config = parseConfig(id, arg, state.count);
state.config = parseConfig(state, id, arg, state.count);
$toastMap.setKey(id, state);
// Update the toast itself
toastApi.update(id, state.config);
@ -81,18 +97,26 @@ export const toast = (arg: ToastArg): ToastApi => {
/**
* Give a toast id, arg and current count, returns the parsed toast config (including dynamic title and description)
* @param state The current state of the toast or null if it doesn't exist
* @param id The id of the toast
* @param arg The arg passed to the toast function
* @param count The current call count of the toast
* @returns The parsed toast config
*/
const parseConfig = (id: string, arg: ToastArg, count: number): ToastConfig => {
const title = arg.withCount && count > 1 ? `${arg.title} (${count})` : arg.title;
const parseConfig = (state: ToastInternalState | null, id: string, arg: ToastArg, count: number): ToastConfig => {
const onCloseComplete = () => {
$toastMap.setKey(id, undefined);
if (arg.onCloseComplete) {
arg.onCloseComplete();
}
};
return { ...arg, title, onCloseComplete };
const title = arg.withCount && count > 1 ? `${arg.title} (${count})` : arg.title;
const description = !arg.updateDescription && state ? state.config.description : arg.description;
const config: ToastConfig = {
...arg,
title,
description,
onCloseComplete,
};
return config;
};