From 7dd3bf7d9e9a679942fde76c27caf0dc562baaad Mon Sep 17 00:00:00 2001 From: p-sw Date: Sat, 15 Jun 2024 01:25:00 +0900 Subject: [PATCH] fix: split component file --- .../{Toast.tsx => Toast/Component.tsx} | 157 ++---------------- packages/react/components/Toast/Hook.ts | 9 + packages/react/components/Toast/Store.ts | 100 +++++++++++ packages/react/components/Toast/Variant.ts | 40 +++++ packages/react/components/Toast/index.ts | 0 5 files changed, 163 insertions(+), 143 deletions(-) rename packages/react/components/{Toast.tsx => Toast/Component.tsx} (62%) create mode 100644 packages/react/components/Toast/Hook.ts create mode 100644 packages/react/components/Toast/Store.ts create mode 100644 packages/react/components/Toast/Variant.ts create mode 100644 packages/react/components/Toast/index.ts diff --git a/packages/react/components/Toast.tsx b/packages/react/components/Toast/Component.tsx similarity index 62% rename from packages/react/components/Toast.tsx rename to packages/react/components/Toast/Component.tsx index 669ca35..9200465 100644 --- a/packages/react/components/Toast.tsx +++ b/packages/react/components/Toast/Component.tsx @@ -2,148 +2,19 @@ import React, { useEffect, useId, useRef } from "react"; import ReactDOM from "react-dom"; import { VariantProps, vcn } from "@pswui-lib"; -interface ToastOption { - closeButton: boolean; - closeTimeout: number | null; -} - -const defaultToastOption: ToastOption = { - closeButton: true, - closeTimeout: 3000, -}; - -const toastColors = { - background: "bg-white dark:bg-black", - borders: { - default: "border-black/10 dark:border-white/20", - error: "border-red-500/80", - success: "border-green-500/80", - warning: "border-yellow-500/80", - loading: "border-black/50 dark:border-white/50 animate-pulse", - }, -}; - -const [toastVariant] = vcn({ - base: `flex flex-col gap-2 border p-4 rounded-lg pr-8 pointer-events-auto ${toastColors.background} relative transition-all duration-150`, - variants: { - status: { - default: toastColors.borders.default, - error: toastColors.borders.error, - success: toastColors.borders.success, - warning: toastColors.borders.warning, - loading: toastColors.borders.loading, - }, - life: { - born: "-translate-y-full md:translate-y-full scale-90 ease-[cubic-bezier(0,.6,.7,1)]", - normal: "translate-y-0 scale-100 ease-[cubic-bezier(0,.6,.7,1)]", - dead: "-translate-y-full md:translate-y-full scale-90 ease-[cubic-bezier(.6,0,1,.7)]", - }, - }, - defaults: { - status: "default", - life: "born", - }, -}); - -interface ToastBody extends Omit, "preset"> { - title: string; - description: string; -} - -let index = 0; -const toasts: Record< - `${number}`, - ToastBody & Partial & { subscribers: (() => void)[] } -> = {}; -let subscribers: (() => void)[] = []; - -/** - * ==== - * Controls - * ==== - */ - -function subscribe(callback: () => void) { - subscribers.push(callback); - return () => { - subscribers = subscribers.filter((subscriber) => subscriber !== callback); - }; -} - -function getSnapshot() { - return { ...toasts }; -} - -function subscribeSingle(id: `${number}`) { - return (callback: () => void) => { - toasts[id].subscribers.push(callback); - return () => { - toasts[id].subscribers = toasts[id].subscribers.filter( - (subscriber) => subscriber !== callback, - ); - }; - }; -} - -function getSingleSnapshot(id: `${number}`) { - return () => { - return { - ...toasts[id], - }; - }; -} - -function notify() { - subscribers.forEach((subscriber) => subscriber()); -} - -function notifySingle(id: `${number}`) { - toasts[id].subscribers.forEach((subscriber) => subscriber()); -} - -function close(id: `${number}`) { - toasts[id] = { - ...toasts[id], - life: "dead", - }; - notifySingle(id); -} - -function update( - id: `${number}`, - toast: Partial & Partial>, -) { - toasts[id] = { - ...toasts[id], - ...toast, - }; - notifySingle(id); -} - -function addToast(toast: Omit & Partial) { - const id: `${number}` = `${index}`; - toasts[id] = { - ...toast, - subscribers: [], - life: "born", - }; - index += 1; - notify(); - - return { - update: (toast: Partial & Partial>) => - update(id, toast), - close: () => close(id), - }; -} - -function useToast() { - return { - toast: addToast, - update, - close, - }; -} +import { toastVariant } from "./Variant"; +import { + ToastOption, + toasts, + subscribeSingle, + getSingleSnapshot, + notifySingle, + close, + notify, + defaultToastOption, + subscribe, + getSnapshot, +} from "./Store"; const ToastTemplate = ({ id, @@ -333,4 +204,4 @@ const Toaster = React.forwardRef((props, ref) => { ); }); -export { Toaster, useToast }; +export { Toaster }; diff --git a/packages/react/components/Toast/Hook.ts b/packages/react/components/Toast/Hook.ts new file mode 100644 index 0000000..f6d74a2 --- /dev/null +++ b/packages/react/components/Toast/Hook.ts @@ -0,0 +1,9 @@ +import { addToast, update, close } from "./Store"; + +export function useToast() { + return { + toast: addToast, + update, + close, + }; +} diff --git a/packages/react/components/Toast/Store.ts b/packages/react/components/Toast/Store.ts new file mode 100644 index 0000000..04fb4f2 --- /dev/null +++ b/packages/react/components/Toast/Store.ts @@ -0,0 +1,100 @@ +import { ToastBody } from "./Variant"; + +export interface ToastOption { + closeButton: boolean; + closeTimeout: number | null; +} + +export const defaultToastOption: ToastOption = { + closeButton: true, + closeTimeout: 3000, +}; + +let index = 0; +export const toasts: Record< + `${number}`, + ToastBody & Partial & { subscribers: (() => void)[] } +> = {}; +let subscribers: (() => void)[] = []; + +/** + * ==== + * Controls + * ==== + */ + +export function subscribe(callback: () => void) { + subscribers.push(callback); + return () => { + subscribers = subscribers.filter((subscriber) => subscriber !== callback); + }; +} + +export function getSnapshot() { + return { ...toasts }; +} + +export function subscribeSingle(id: `${number}`) { + return (callback: () => void) => { + toasts[id].subscribers.push(callback); + return () => { + toasts[id].subscribers = toasts[id].subscribers.filter( + (subscriber) => subscriber !== callback, + ); + }; + }; +} + +export function getSingleSnapshot(id: `${number}`) { + return () => { + return { + ...toasts[id], + }; + }; +} + +export function notify() { + subscribers.forEach((subscriber) => subscriber()); +} + +export function notifySingle(id: `${number}`) { + toasts[id].subscribers.forEach((subscriber) => subscriber()); +} + +export function close(id: `${number}`) { + toasts[id] = { + ...toasts[id], + life: "dead", + }; + notifySingle(id); +} + +export function update( + id: `${number}`, + toast: Partial & Partial>, +) { + toasts[id] = { + ...toasts[id], + ...toast, + }; + notifySingle(id); +} + +export function addToast( + toast: Omit & Partial, +) { + const id: `${number}` = `${index}`; + toasts[id] = { + ...toast, + subscribers: [], + life: "born", + }; + index += 1; + notify(); + + return { + update: (toast: Partial & Partial>) => + update(id, toast), + close: () => close(id), + }; +} diff --git a/packages/react/components/Toast/Variant.ts b/packages/react/components/Toast/Variant.ts new file mode 100644 index 0000000..2a0285c --- /dev/null +++ b/packages/react/components/Toast/Variant.ts @@ -0,0 +1,40 @@ +import { VariantProps, vcn } from "@pswui-lib"; + +const toastColors = { + background: "bg-white dark:bg-black", + borders: { + default: "border-black/10 dark:border-white/20", + error: "border-red-500/80", + success: "border-green-500/80", + warning: "border-yellow-500/80", + loading: "border-black/50 dark:border-white/50 animate-pulse", + }, +}; + +export const [toastVariant, resolveToastVariantProps] = vcn({ + base: `flex flex-col gap-2 border p-4 rounded-lg pr-8 pointer-events-auto ${toastColors.background} relative transition-all duration-150`, + variants: { + status: { + default: toastColors.borders.default, + error: toastColors.borders.error, + success: toastColors.borders.success, + warning: toastColors.borders.warning, + loading: toastColors.borders.loading, + }, + life: { + born: "-translate-y-full md:translate-y-full scale-90 ease-[cubic-bezier(0,.6,.7,1)]", + normal: "translate-y-0 scale-100 ease-[cubic-bezier(0,.6,.7,1)]", + dead: "-translate-y-full md:translate-y-full scale-90 ease-[cubic-bezier(.6,0,1,.7)]", + }, + }, + defaults: { + status: "default", + life: "born", + }, +}); + +export interface ToastBody + extends Omit, "preset"> { + title: string; + description: string; +} diff --git a/packages/react/components/Toast/index.ts b/packages/react/components/Toast/index.ts new file mode 100644 index 0000000..e69de29