-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
context.ts
52 lines (45 loc) · 1.5 KB
/
context.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
import { raw } from '../helper/html/index.ts'
import type { HtmlEscapedString } from '../utils/html.ts'
import { JSXFragmentNode } from './base.ts'
import { DOM_RENDERER } from './constants.ts'
import { createContextProviderFunction } from './dom/context.ts'
import type { FC, PropsWithChildren } from './index.ts'
export interface Context<T> {
values: T[]
Provider: FC<PropsWithChildren<{ value: T }>>
}
export const globalContexts: Context<unknown>[] = []
export const createContext = <T>(defaultValue: T): Context<T> => {
const values = [defaultValue]
const context: Context<T> = {
values,
Provider(props): HtmlEscapedString | Promise<HtmlEscapedString> {
values.push(props.value)
let string
try {
string = props.children
? (Array.isArray(props.children)
? new JSXFragmentNode('', {}, props.children)
: props.children
).toString()
: ''
} finally {
values.pop()
}
if (string instanceof Promise) {
return string.then((resString) =>
raw(resString, (resString as HtmlEscapedString).callbacks)
)
} else {
return raw(string)
}
},
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(context.Provider as any)[DOM_RENDERER] = createContextProviderFunction(values)
globalContexts.push(context as Context<unknown>)
return context
}
export const useContext = <T>(context: Context<T>): T => {
return context.values.at(-1) as T
}