-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
overrides.ts
142 lines (132 loc) · 4.16 KB
/
overrides.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { Editor, objectMapEntries } from '@tldraw/editor'
import { useMemo } from 'react'
import { PORTRAIT_BREAKPOINT } from './constants'
import { ActionsProviderProps } from './context/actions'
import { useBreakpoint } from './context/breakpoints'
import { useDialogs } from './context/dialogs'
import { useToasts } from './context/toasts'
import { TLUiToolsProviderProps } from './hooks/useTools'
import { TLUiTranslationProviderProps, useTranslation } from './hooks/useTranslation/useTranslation'
/** @public */
export function useDefaultHelpers() {
const { addToast, removeToast, clearToasts } = useToasts()
const { addDialog, clearDialogs, removeDialog, updateDialog } = useDialogs()
const breakpoint = useBreakpoint()
const isMobile = breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM
const msg = useTranslation()
return useMemo(
() => ({
addToast,
removeToast,
clearToasts,
addDialog,
clearDialogs,
removeDialog,
updateDialog,
msg,
isMobile,
}),
[
addDialog,
addToast,
clearDialogs,
clearToasts,
msg,
removeDialog,
removeToast,
updateDialog,
isMobile,
]
)
}
type DefaultHelpers = ReturnType<typeof useDefaultHelpers>
export type TLUiOverride<Type, Helpers> = (editor: Editor, schema: Type, helpers: Helpers) => Type
type WithDefaultHelpers<T extends TLUiOverride<any, any>> =
T extends TLUiOverride<infer Type, infer Helpers>
? TLUiOverride<Type, Helpers extends undefined ? DefaultHelpers : Helpers & DefaultHelpers>
: never
/** @public */
export type TLUiOverrides = Partial<{
actions: WithDefaultHelpers<NonNullable<ActionsProviderProps['overrides']>>
tools: WithDefaultHelpers<NonNullable<TLUiToolsProviderProps['overrides']>>
translations: TLUiTranslationProviderProps['overrides']
}>
export type TLUiOverridesWithoutDefaults = Partial<{
actions: ActionsProviderProps['overrides']
tools: TLUiToolsProviderProps['overrides']
translations: TLUiTranslationProviderProps['overrides']
}>
export function mergeOverrides(
overrides: TLUiOverrides[],
defaultHelpers: DefaultHelpers
): TLUiOverridesWithoutDefaults {
const mergedTranslations: TLUiTranslationProviderProps['overrides'] = {}
for (const override of overrides) {
if (override.translations) {
for (const [key, value] of objectMapEntries(override.translations)) {
let strings = mergedTranslations[key]
if (!strings) {
strings = mergedTranslations[key] = {}
}
Object.assign(strings, value)
}
}
}
return {
actions: (editor, schema) => {
for (const override of overrides) {
if (override.actions) {
schema = override.actions(editor, schema, defaultHelpers)
}
}
return schema
},
tools: (editor, schema, helpers) => {
for (const override of overrides) {
if (override.tools) {
schema = override.tools(editor, schema, { ...defaultHelpers, ...helpers })
}
}
return schema
},
translations: mergedTranslations,
}
}
function useShallowArrayEquality<T extends unknown[]>(array: T): T {
// eslint-disable-next-line react-hooks/exhaustive-deps
return useMemo(() => array, array)
}
export function useMergedTranslationOverrides(
overrides?: TLUiOverrides[] | TLUiOverrides
): NonNullable<TLUiTranslationProviderProps['overrides']> {
const overridesArray = useShallowArrayEquality(
overrides == null ? [] : Array.isArray(overrides) ? overrides : [overrides]
)
return useMemo(() => {
const mergedTranslations: TLUiTranslationProviderProps['overrides'] = {}
for (const override of overridesArray) {
if (override.translations) {
for (const [key, value] of objectMapEntries(override.translations)) {
let strings = mergedTranslations[key]
if (!strings) {
strings = mergedTranslations[key] = {}
}
Object.assign(strings, value)
}
}
}
return mergedTranslations
}, [overridesArray])
}
export function useMergedOverrides(
overrides?: TLUiOverrides[] | TLUiOverrides
): TLUiOverridesWithoutDefaults {
const defaultHelpers = useDefaultHelpers()
const overridesArray = useShallowArrayEquality(
overrides == null ? [] : Array.isArray(overrides) ? overrides : [overrides]
)
return useMemo(
() => mergeOverrides(overridesArray, defaultHelpers),
[overridesArray, defaultHelpers]
)
}