| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import { createContext, useContext, type ParentProps, Show } from "solid-js"
- import { createStore } from "solid-js/store"
- import { useTheme } from "@tui/context/theme"
- import { SplitBorder } from "../component/border"
- import { TextAttributes } from "@opentui/core"
- import z from "zod"
- import { TuiEvent } from "../event"
- export type ToastOptions = z.infer<typeof TuiEvent.ToastShow.properties>
- export function Toast() {
- const toast = useToast()
- const { theme } = useTheme()
- return (
- <Show when={toast.currentToast}>
- {(current) => (
- <box
- position="absolute"
- justifyContent="center"
- alignItems="flex-start"
- top={2}
- right={2}
- paddingLeft={2}
- paddingRight={2}
- paddingTop={1}
- paddingBottom={1}
- backgroundColor={theme.backgroundPanel}
- borderColor={theme[current().variant]}
- border={["left", "right"]}
- customBorderChars={SplitBorder.customBorderChars}
- >
- <Show when={current().title}>
- <text attributes={TextAttributes.BOLD} marginBottom={1}>
- {current().title}
- </text>
- </Show>
- <text>{current().message}</text>
- </box>
- )}
- </Show>
- )
- }
- function init() {
- const [store, setStore] = createStore({
- currentToast: null as ToastOptions | null,
- })
- let timeoutHandle: NodeJS.Timeout | null = null
- const toast = {
- show(options: ToastOptions) {
- const parsedOptions = TuiEvent.ToastShow.properties.parse(options)
- const { duration, ...currentToast } = parsedOptions
- setStore("currentToast", currentToast)
- if (timeoutHandle) clearTimeout(timeoutHandle)
- timeoutHandle = setTimeout(() => {
- setStore("currentToast", null)
- }, duration).unref()
- },
- error: (err: any) => {
- if (err instanceof Error)
- return toast.show({
- variant: "error",
- message: err.message,
- })
- toast.show({
- variant: "error",
- message: "An unknown error has occurred",
- })
- },
- get currentToast(): ToastOptions | null {
- return store.currentToast
- },
- }
- return toast
- }
- export type ToastContext = ReturnType<typeof init>
- const ctx = createContext<ToastContext>()
- export function ToastProvider(props: ParentProps) {
- const value = init()
- return <ctx.Provider value={value}>{props.children}</ctx.Provider>
- }
- export function useToast() {
- const value = useContext(ctx)
- if (!value) {
- throw new Error("useToast must be used within a ToastProvider")
- }
- return value
- }
|