mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-26 12:14:20 +01:00
96 lines
2.6 KiB
TypeScript
96 lines
2.6 KiB
TypeScript
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
|
|
}
|