kopia lustrzana https://github.com/Tldraw/Tldraw
129 wiersze
2.6 KiB
TypeScript
129 wiersze
2.6 KiB
TypeScript
import { App, uniqueId, useApp } from '@tldraw/editor'
|
|
import { createContext, useCallback, useContext, useState } from 'react'
|
|
import { useEvents } from './useEventsProvider'
|
|
|
|
/** @public */
|
|
export interface DialogProps {
|
|
onClose: () => void
|
|
}
|
|
|
|
/** @public */
|
|
export interface TLDialog {
|
|
id: string
|
|
onClose?: () => void
|
|
component: (props: DialogProps) => any
|
|
}
|
|
|
|
/** @public */
|
|
export type DialogsContextType = {
|
|
addDialog: (dialog: Omit<TLDialog, 'id'> & { id?: string }) => string
|
|
removeDialog: (id: string) => string
|
|
updateDialog: (id: string, newDialogData: Partial<TLDialog>) => string
|
|
clearDialogs: () => void
|
|
dialogs: TLDialog[]
|
|
}
|
|
|
|
/** @public */
|
|
export const DialogsContext = createContext({} as DialogsContextType)
|
|
|
|
/** @public */
|
|
export type DialogsProviderProps = {
|
|
overrides?: (app: App) => DialogsContextType
|
|
children: any
|
|
}
|
|
|
|
/** @public */
|
|
export function DialogsProvider({ children }: DialogsProviderProps) {
|
|
const app = useApp()
|
|
const trackEvent = useEvents()
|
|
|
|
const [dialogs, setDialogs] = useState<TLDialog[]>([])
|
|
|
|
const addDialog = useCallback(
|
|
(dialog: Omit<TLDialog, 'id'> & { id?: string }) => {
|
|
const id = dialog.id ?? uniqueId()
|
|
setDialogs((d) => {
|
|
return [...d.filter((m) => m.id !== dialog.id), { ...dialog, id }]
|
|
})
|
|
|
|
trackEvent('dialog', 'open-menu', { id })
|
|
app.addOpenMenu(id)
|
|
|
|
return id
|
|
},
|
|
[app, trackEvent]
|
|
)
|
|
|
|
const updateDialog = useCallback(
|
|
(id: string, newDialogData: Partial<TLDialog>) => {
|
|
setDialogs((d) =>
|
|
d.map((m) => {
|
|
if (m.id === id) {
|
|
return {
|
|
...m,
|
|
...newDialogData,
|
|
}
|
|
}
|
|
return m
|
|
})
|
|
)
|
|
|
|
trackEvent('dialog', 'open-menu', { id })
|
|
app.addOpenMenu(id)
|
|
|
|
return id
|
|
},
|
|
[app, trackEvent]
|
|
)
|
|
|
|
const removeDialog = useCallback(
|
|
(id: string) => {
|
|
setDialogs((d) =>
|
|
d.filter((m) => {
|
|
if (m.id === id) {
|
|
m.onClose?.()
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
)
|
|
|
|
trackEvent('dialog', 'close-menu', { id })
|
|
app.deleteOpenMenu(id)
|
|
|
|
return id
|
|
},
|
|
[app, trackEvent]
|
|
)
|
|
|
|
const clearDialogs = useCallback(() => {
|
|
setDialogs((d) => {
|
|
d.forEach((m) => {
|
|
m.onClose?.()
|
|
trackEvent('dialog', 'close-menu', { id: m.id })
|
|
app.deleteOpenMenu(m.id)
|
|
})
|
|
return []
|
|
})
|
|
}, [app, trackEvent])
|
|
|
|
return (
|
|
<DialogsContext.Provider
|
|
value={{ dialogs, addDialog, removeDialog, clearDialogs, updateDialog }}
|
|
>
|
|
{children}
|
|
</DialogsContext.Provider>
|
|
)
|
|
}
|
|
|
|
/** @public */
|
|
export function useDialogs() {
|
|
const ctx = useContext(DialogsContext)
|
|
|
|
if (!ctx) {
|
|
throw new Error('useDialogs must be used within a DialogsProvider')
|
|
}
|
|
|
|
return ctx
|
|
}
|