File size: 6,175 Bytes
e8a57cb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Intentionally not using a relative path to take advantage of
// the TS version resolution mechanism
import * as preact from 'preact';

export enum HookType {
	useState = 1,
	useReducer = 2,
	useEffect = 3,
	useLayoutEffect = 4,
	useRef = 5,
	useImperativeHandle = 6,
	useMemo = 7,
	useCallback = 8,
	useContext = 9,
	useErrorBoundary = 10,
	// Not a real hook, but the devtools treat is as such
	useDebugvalue = 11
}

export interface DevSource {
	fileName: string;
	lineNumber: number;
}

export interface ErrorInfo {
	componentStack?: string;
}

export interface Options extends preact.Options {
	/** Attach a hook that is invoked before render, mainly to check the arguments. */
	_root?(vnode: ComponentChild, parent: preact.ContainerNode): void;
	/** Attach a hook that is invoked before a vnode is diffed. */
	_diff?(vnode: VNode): void;
	/** Attach a hook that is invoked after a tree was mounted or was updated. */
	_commit?(vnode: VNode, commitQueue: Component[]): void;
	/** Attach a hook that is invoked before a vnode has rendered. */
	_render?(vnode: VNode): void;
	/** Attach a hook that is invoked before a hook's state is queried. */
	_hook?(component: Component, index: number, type: HookType): void;
	/** Bypass effect execution. Currenty only used in devtools for hooks inspection */
	_skipEffects?: boolean;
	/** Attach a hook that is invoked after an error is caught in a component but before calling lifecycle hooks */
	_catchError(
		error: any,
		vnode: VNode,
		oldVNode?: VNode | undefined,
		errorInfo?: ErrorInfo | undefined
	): void;
	/** Attach a hook that fires when hydration can't find a proper DOM-node to match with */
	_hydrationMismatch?(
		vnode: VNode,
		excessDomChildren: Array<PreactElement | null>
	): void;
}

export type ComponentChild =
	| VNode<any>
	| string
	| number
	| boolean
	| null
	| undefined;
export type ComponentChildren = ComponentChild[] | ComponentChild;

export interface FunctionComponent<P = {}>
	extends preact.FunctionComponent<P> {
	// Internally, createContext uses `contextType` on a Function component to
	// implement the Consumer component
	contextType?: PreactContext;

	// Internally, createContext stores a ref to the context object on the Provider
	// Function component to help devtools
	_contextRef?: PreactContext;

	// Define these properties as undefined on FunctionComponent to get rid of
	// some errors in `diff()`
	getDerivedStateFromProps?: undefined;
	getDerivedStateFromError?: undefined;
}

export interface ComponentClass<P = {}> extends preact.ComponentClass<P> {
	_contextRef?: any;

	// Override public contextType with internal PreactContext type
	contextType?: PreactContext;
}

// Redefine ComponentType using our new internal FunctionComponent interface above
export type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;

export interface PreactElement extends preact.ContainerNode {
	// Namespace detection
	readonly namespaceURI?: string;
	// Property used to update Text nodes
	data?: CharacterData['data'];
	// Property to set __dangerouslySetInnerHTML
	innerHTML?: Element['innerHTML'];

	// Attribute reading and setting
	readonly attributes?: Element['attributes'];
	setAttribute?: Element['setAttribute'];
	removeAttribute?: Element['removeAttribute'];

	// Event listeners
	addEventListener?: Element['addEventListener'];
	removeEventListener?: Element['removeEventListener'];

	// Setting styles
	readonly style?: CSSStyleDeclaration;

	// nextSibling required for inserting nodes
	readonly nextSibling: PreactElement | null;

	// Used to match DOM nodes to VNodes during hydration. Note: doesn't exist
	// on Text nodes
	readonly localName?: string;

	// Input handling
	value?: HTMLInputElement['value'];
	checked?: HTMLInputElement['checked'];

	// Internal properties
	_children?: VNode<any> | null;
	/** Event listeners to support event delegation */
	_listeners?: Record<string, (e: Event) => void>;
}

export interface PreactEvent extends Event {
	_dispatched?: number;
}

// We use the `current` property to differentiate between the two kinds of Refs so
// internally we'll define `current` on both to make TypeScript happy
type RefObject<T> = { current: T | null };
type RefCallback<T> = {
	(instance: T | null): void | (() => void);
	current: undefined;
};
export type Ref<T> = RefObject<T> | RefCallback<T>;

export interface VNode<P = {}> extends preact.VNode<P> {
	// Redefine type here using our internal ComponentType type, and specify
	// string has an undefined `defaultProps` property to make TS happy
	type: (string & { defaultProps: undefined }) | ComponentType<P>;
	props: P & { children: ComponentChildren };
	ref?: Ref<any> | null;
	_children: Array<VNode<any>> | null;
	_parent: VNode | null;
	_depth: number | null;
	/**
	 * The [first (for Fragments)] DOM child of a VNode
	 */
	_dom: PreactElement | null;
	_component: Component | null;
	constructor: undefined;
	_original: number;
	_index: number;
	_flags: number;
}

export interface Component<P = {}, S = {}> extends Omit<preact.Component<P, S>, 'base'> {
	// When component is functional component, this is reset to functional component
	constructor: ComponentType<P>;
	state: S; // Override Component["state"] to not be readonly for internal use, specifically Hooks
	base?: PreactElement;

	_dirty: boolean;
	_force?: boolean;
	_renderCallbacks: Array<() => void>; // Only class components
	_stateCallbacks: Array<() => void>; // Only class components
	_globalContext?: any;
	_vnode?: VNode<P> | null;
	_nextState?: S | null; // Only class components
	/** Only used in the devtools to later dirty check if state has changed */
	_prevState?: S | null;
	/**
	 * Pointer to the parent dom node. This is only needed for top-level Fragment
	 * components or array returns.
	 */
	_parentDom?: PreactElement | null;
	// Always read, set only when handling error
	_processingException?: Component<any, any> | null;
	// Always read, set only when handling error. This is used to indicate at diffTime to set _processingException
	_pendingError?: Component<any, any> | null;
}

export interface PreactContext extends preact.Context<any> {
	_id: string;
	_defaultValue: any;
}