@hyper-elements/react 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GUIDE.md +47 -28
- package/README.md +24 -5
- package/REFERENCE.md +487 -485
- package/dist/builder.cjs +795 -206
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.js +795 -206
- package/dist/builder.js.map +1 -1
- package/dist/image.cjs +1 -1
- package/dist/image.cjs.map +1 -1
- package/dist/image.js +1 -1
- package/dist/image.js.map +1 -1
- package/dist/inspect.cjs +3601 -0
- package/dist/inspect.cjs.map +1 -0
- package/dist/inspect.d.cts +472 -0
- package/dist/inspect.d.ts +472 -0
- package/dist/inspect.js +3572 -0
- package/dist/inspect.js.map +1 -0
- package/dist/pdf.cjs +54 -9
- package/dist/pdf.cjs.map +1 -1
- package/dist/pdf.js +54 -9
- package/dist/pdf.js.map +1 -1
- package/dist/primitives.cjs +738 -142
- package/dist/primitives.cjs.map +1 -1
- package/dist/primitives.d.cts +558 -158
- package/dist/primitives.d.ts +558 -158
- package/dist/primitives.js +736 -143
- package/dist/primitives.js.map +1 -1
- package/package.json +10 -1
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The template tree: what a template's JSX is collected into inside one
|
|
5
|
+
* render, and what layout and every writer read. Internal, never public; plain
|
|
6
|
+
* data (no functions, no React elements).
|
|
7
|
+
*/
|
|
8
|
+
type Json = string | number | boolean | null | Json[] | {
|
|
9
|
+
[key: string]: Json;
|
|
10
|
+
};
|
|
11
|
+
interface Node {
|
|
12
|
+
/** Only when the author gives one; unique in the template, and written to the HTML as is. */
|
|
13
|
+
id?: string;
|
|
14
|
+
/** A defined component: "Email", "Row", "Heading", … */
|
|
15
|
+
type: string;
|
|
16
|
+
/** Meaning: href, src, alt, level. */
|
|
17
|
+
props?: Record<string, Json>;
|
|
18
|
+
/** Appearance, in the value kinds the component's definition gives. */
|
|
19
|
+
style?: Record<string, Json>;
|
|
20
|
+
/** Style overrides on phones (Email and Page). */
|
|
21
|
+
mobile?: Record<string, Json>;
|
|
22
|
+
/** Style while the pointer is over it, where the definition allows. */
|
|
23
|
+
hover?: Record<string, Json>;
|
|
24
|
+
hidden?: {
|
|
25
|
+
mobile?: boolean;
|
|
26
|
+
desktop?: boolean;
|
|
27
|
+
};
|
|
28
|
+
children?: Child[];
|
|
29
|
+
}
|
|
30
|
+
/** A string is text, where the parent takes text. */
|
|
31
|
+
type Child = Node | string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The email clients Elements checks an Email for. Four were captured showing Elements 0.3.0 emails they weren't tuned
|
|
35
|
+
* on (unlayer/email-renderer), which says how closely each is measured; what's known of the rest is from caniemail's
|
|
36
|
+
* tables (caniemail.com, MIT), which test the CSS and HTML each client keeps. Either way a problem is said at its own
|
|
37
|
+
* severity; only one Elements assumes, unchecked, is a note.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
type EmailClient = "outlook" | "outlook-com" | "outlook-mac" | "outlook-app" | "gmail" | "gmail-app" | "gmail-app-other" | "apple-mail" | "yahoo" | "aol" | "samsung-email" | "thunderbird" | "protonmail" | "fastmail" | "hey" | "gmx" | "web-de" | "orange" | "sfr" | "laposte" | "free-fr" | "t-online-de" | "mail-ru" | "ionos" | "wp-pl" | "rainloop";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* What validation, resolution and conversion found: one list, each entry
|
|
44
|
+
* naming the node (by id where it has one) and the path to the value.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
type Severity = "error" | "warning" | "info";
|
|
48
|
+
interface Diagnostic {
|
|
49
|
+
/** Stable, for tools to match on: "prop/unknown", "layout/overflow", … */
|
|
50
|
+
code: string;
|
|
51
|
+
severity: Severity;
|
|
52
|
+
message: string;
|
|
53
|
+
/** Where in the input: `root.children[1].style.padding`. */
|
|
54
|
+
path: string;
|
|
55
|
+
/** The node's id, once it has one. */
|
|
56
|
+
nodeId?: string;
|
|
57
|
+
/** The email clients it's about; absent: every email, never left out by `emailClients`. */
|
|
58
|
+
clients?: EmailClient[];
|
|
59
|
+
/** What to change. */
|
|
60
|
+
fix?: string;
|
|
61
|
+
/** Where to see it: for a problem known from caniemail's tables, its page there. */
|
|
62
|
+
see?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Value kinds: what a prop or style property accepts, what it's normalized to,
|
|
67
|
+
* the editor that edits it, and a JSON Schema of its values (for property
|
|
68
|
+
* discovery). Component definitions are made of these, so types, validation
|
|
69
|
+
* and editors come from one place.
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
type JsonSchema = {
|
|
73
|
+
[key: string]: unknown;
|
|
74
|
+
};
|
|
75
|
+
/** Conceptual editors, mapped by each editor (the builder, others) to its own widgets. */
|
|
76
|
+
type EditorKind = "color" | "length" | "insets" | "border" | "radius" | "choice" | "fontFamily" | "fontFaces" | "items" | "fontWeight" | "lineHeight" | "image" | "link" | "text" | "number" | "toggle";
|
|
77
|
+
type Parsed<T> = {
|
|
78
|
+
ok: true;
|
|
79
|
+
value: T;
|
|
80
|
+
} | {
|
|
81
|
+
ok: false;
|
|
82
|
+
message: string;
|
|
83
|
+
};
|
|
84
|
+
interface Kind<In = unknown, Out extends Json = Json> {
|
|
85
|
+
readonly name: string;
|
|
86
|
+
readonly editor: EditorKind;
|
|
87
|
+
/** What it accepts, in words (for messages and descriptions). */
|
|
88
|
+
readonly accepts: string;
|
|
89
|
+
parse(input: unknown): Parsed<Out>;
|
|
90
|
+
/** Whether a value it parsed sets nothing (`breakpoints={{}}`): the prop is then left out, as if not given. */
|
|
91
|
+
empty?(value: Out): boolean;
|
|
92
|
+
jsonSchema(): JsonSchema;
|
|
93
|
+
/** Type only: what it accepts as input. */
|
|
94
|
+
readonly __in?: In;
|
|
95
|
+
}
|
|
96
|
+
type OutputOf<K> = K extends Kind<unknown, infer O> ? O : never;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Component definitions: one per component, the source of its props, styles,
|
|
100
|
+
* children, targets, support in each output and editors. Types, validation,
|
|
101
|
+
* the support pass and property discovery are all read from these.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/** What a component is, for the nesting rules: a component belongs to one or more. */
|
|
105
|
+
type Category = "root" | "section" | "layout" | "block" | "inline" | "shape";
|
|
106
|
+
/** The outputs Elements renders. */
|
|
107
|
+
type Target = "email" | "web" | "print" | "pdf" | "image";
|
|
108
|
+
/** The roots a template can have: each decides the output (`render()` writes an Email's HTML, a Page's, …). */
|
|
109
|
+
type RootName = "Email" | "Page" | "Document" | "Canvas";
|
|
110
|
+
/** What a style is about, for the guide and `describeComponents()`: the group it's listed in. */
|
|
111
|
+
type StyleGroup = "Layout" | "Size" | "Position" | "Spacing" | "Typography" | "Background" | "Border" | "Effects";
|
|
112
|
+
interface PropSpec<K extends Kind<any, any> = Kind<any, any>, R extends boolean = boolean> {
|
|
113
|
+
kind: K;
|
|
114
|
+
required?: R;
|
|
115
|
+
label: string;
|
|
116
|
+
description?: string;
|
|
117
|
+
/**
|
|
118
|
+
* The roots it may be given under (default: every root its component goes in). Under another root it's a
|
|
119
|
+
* `prop/not-supported` error naming these.
|
|
120
|
+
*/
|
|
121
|
+
roots?: readonly RootName[];
|
|
122
|
+
/** Used where the prop isn't given (not written into the document). */
|
|
123
|
+
default?: OutputOf<K>;
|
|
124
|
+
/** Editors may change it (default true). */
|
|
125
|
+
editable?: boolean;
|
|
126
|
+
/** How each output shows it: required for every output its component renders to (a test checks). */
|
|
127
|
+
support?: SupportByTarget;
|
|
128
|
+
}
|
|
129
|
+
/** A style's or prop's support, by output. */
|
|
130
|
+
type SupportByTarget = Partial<Record<Target, Support | readonly Support[]>>;
|
|
131
|
+
/**
|
|
132
|
+
* Where what an output shows of a style or prop is known from: captures of
|
|
133
|
+
* real classic Outlook for Windows; caniemail's client tables
|
|
134
|
+
* (caniemail.com); the output's writer itself, which turns it into markup the
|
|
135
|
+
* output shows (checked in Chromium, for email with and without <style>, and
|
|
136
|
+
* against a model of Outlook's layout built from those captures); captures of
|
|
137
|
+
* Gmail, Outlook.com or Apple Mail; CSS written as is, which browsers show as
|
|
138
|
+
* asked; or assumed, not yet checked.
|
|
139
|
+
*/
|
|
140
|
+
type SupportSource = "outlook-captures" | "gmail-captures" | "outlook-com-captures" | "apple-mail-captures" | "caniemail" | "writer" | "css" | "assumed";
|
|
141
|
+
/**
|
|
142
|
+
* How an output shows a style or prop, or some of its values (`values`, or
|
|
143
|
+
* `when` the value, on a node with such props, is such): as asked (`full`); as asked but in classic
|
|
144
|
+
* Outlook, which shows something else (`outlook`, email only: what it shows);
|
|
145
|
+
* not quite as asked anywhere it's shown (`partial`: what it shows); or not at
|
|
146
|
+
* all (`none`: what it does instead). Read by the support pass every output
|
|
147
|
+
* runs: `outlook` and `partial` are notes, `none` a warning, whether the email
|
|
148
|
+
* clients it names were captured or are from caniemail's tables; one `assumed`
|
|
149
|
+
* is only ever a note.
|
|
150
|
+
*/
|
|
151
|
+
type Support = {
|
|
152
|
+
level: "full";
|
|
153
|
+
source: SupportSource;
|
|
154
|
+
} | {
|
|
155
|
+
level: "outlook" | "partial" | "none";
|
|
156
|
+
shows: string;
|
|
157
|
+
values?: readonly Json[];
|
|
158
|
+
when?: (value: Json, node: {
|
|
159
|
+
props: Record<string, Json>;
|
|
160
|
+
}) => boolean;
|
|
161
|
+
source: SupportSource;
|
|
162
|
+
/** For email, the clients it's about (`outlook`: classic Outlook); absent, every email client. */
|
|
163
|
+
clients?: readonly EmailClient[];
|
|
164
|
+
/** caniemail's feature the clients are from (its slug), checked against its tables (test/caniemail.test.ts). */
|
|
165
|
+
feature?: string;
|
|
166
|
+
/** What to change. */
|
|
167
|
+
fix?: string;
|
|
168
|
+
};
|
|
169
|
+
interface StyleSpec<K extends Kind<any, any> = Kind<any, any>> {
|
|
170
|
+
kind: K;
|
|
171
|
+
label: string;
|
|
172
|
+
description?: string;
|
|
173
|
+
/** Passed down to children that don't set it (text styles). */
|
|
174
|
+
inherited?: boolean;
|
|
175
|
+
/** May be overridden on phones (`mobile`). */
|
|
176
|
+
mobile?: boolean;
|
|
177
|
+
/**
|
|
178
|
+
* The roots it may be set under (default: every root its component goes in). Under another root it's a
|
|
179
|
+
* `style/not-supported` error naming these, in `style` and in its condition blocks alike.
|
|
180
|
+
*/
|
|
181
|
+
roots?: readonly RootName[];
|
|
182
|
+
/** The group it's listed in; default: the group of its name (`STYLE_GROUP_OF`), as a style's name is CSS's. */
|
|
183
|
+
group?: StyleGroup;
|
|
184
|
+
editable?: boolean;
|
|
185
|
+
/** How each output shows it: required for every output its component renders to (a test checks). */
|
|
186
|
+
support?: SupportByTarget;
|
|
187
|
+
}
|
|
188
|
+
type PropSpecs = Record<string, PropSpec>;
|
|
189
|
+
type StyleSpecs = Record<string, StyleSpec>;
|
|
190
|
+
interface ChildrenRule {
|
|
191
|
+
/** Text (strings) may be children. */
|
|
192
|
+
text?: boolean;
|
|
193
|
+
/** Components of these categories may be children. */
|
|
194
|
+
categories?: readonly Category[];
|
|
195
|
+
/** These types may be children, whatever their category. */
|
|
196
|
+
types?: readonly string[];
|
|
197
|
+
}
|
|
198
|
+
interface TargetSupport {
|
|
199
|
+
/** What's different in this target, for docs and diagnostics. */
|
|
200
|
+
note?: string;
|
|
201
|
+
}
|
|
202
|
+
/** A change to a node: what a composite editor writes. */
|
|
203
|
+
interface NodePatch {
|
|
204
|
+
props?: Record<string, Json | undefined>;
|
|
205
|
+
style?: Record<string, Json | undefined>;
|
|
206
|
+
hover?: Record<string, Json | undefined>;
|
|
207
|
+
}
|
|
208
|
+
/** An editor that reads and writes several props at once (a button's colors). */
|
|
209
|
+
interface CompositeEditor<V = any> {
|
|
210
|
+
/** The conceptual editor ("buttonColors"); editors map it to a widget. */
|
|
211
|
+
editor: string;
|
|
212
|
+
/** The paths it reads and writes ("style.color", "hover.backgroundColor"). */
|
|
213
|
+
covers: readonly string[];
|
|
214
|
+
read(node: Pick<Node, "props" | "style" | "hover">): V;
|
|
215
|
+
write(value: V): NodePatch;
|
|
216
|
+
}
|
|
217
|
+
type EditorGroup = {
|
|
218
|
+
title: string;
|
|
219
|
+
paths: readonly string[];
|
|
220
|
+
} | {
|
|
221
|
+
title: string;
|
|
222
|
+
composite: CompositeEditor;
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* A component's definition. `H` is its hover styles' keys: a definition made with `defineComponent()` keeps the list it
|
|
226
|
+
* gives (none: `readonly []`), so the types of its `style.hover` can be exactly those; the default is any of its styles.
|
|
227
|
+
*/
|
|
228
|
+
interface ComponentDefinition<P extends PropSpecs = PropSpecs, S extends StyleSpecs = StyleSpecs, H extends readonly (keyof S & string)[] = readonly (keyof S & string)[]> {
|
|
229
|
+
type: string;
|
|
230
|
+
label: string;
|
|
231
|
+
description: string;
|
|
232
|
+
categories: readonly Category[];
|
|
233
|
+
props: P;
|
|
234
|
+
style: S;
|
|
235
|
+
/** The component's own style, under what the author sets and over what's inherited (as a browser's defaults are). */
|
|
236
|
+
defaultStyle?: {
|
|
237
|
+
[K in keyof S]?: OutputOf<S[K]["kind"]>;
|
|
238
|
+
};
|
|
239
|
+
/** Default style that depends on a prop's value (a Heading's size on its level), over `defaultStyle`. */
|
|
240
|
+
defaultStyleBy?: {
|
|
241
|
+
prop: keyof P & string;
|
|
242
|
+
values: Record<string, {
|
|
243
|
+
[K in keyof S]?: OutputOf<S[K]["kind"]>;
|
|
244
|
+
}>;
|
|
245
|
+
};
|
|
246
|
+
/** Style keys that may be set for `hover`. */
|
|
247
|
+
hover?: H;
|
|
248
|
+
/**
|
|
249
|
+
* Styles a condition takes on this component that an output doesn't show under it, by condition, style and
|
|
250
|
+
* output (a Page root's phone font size): reported when the template is expanded, before a Grid is arranged.
|
|
251
|
+
*/
|
|
252
|
+
conditionSupport?: Partial<Record<"mobile" | "hover", Partial<Record<keyof S & string, SupportByTarget>>>>;
|
|
253
|
+
children: ChildrenRule;
|
|
254
|
+
/**
|
|
255
|
+
* How wide it is where nothing sets its width: `stretch` fills its parent's
|
|
256
|
+
* content width; `shrink` takes its own size (an image's, a button's
|
|
257
|
+
* content).
|
|
258
|
+
*/
|
|
259
|
+
sizing: "stretch" | "shrink" | "none";
|
|
260
|
+
/** A root that has a phone width (Email, Page): `mobile` and `hidden` apply under it. */
|
|
261
|
+
responsive?: boolean;
|
|
262
|
+
/**
|
|
263
|
+
* A built-in that lays its children out with other components (a Grid's Rows of Columns): its node as those,
|
|
264
|
+
* before layout. Its children (and their ids) are kept as they are.
|
|
265
|
+
*/
|
|
266
|
+
arrange?: (node: Node) => Node;
|
|
267
|
+
/** Where it renders; a target left out is a diagnostic. */
|
|
268
|
+
targets: Partial<Record<Target, TargetSupport>>;
|
|
269
|
+
/**
|
|
270
|
+
* The roots it may go in, of those whose output it renders to (default: every one whose children reach it). Under
|
|
271
|
+
* another such root it's the `notAllowed` error, by default `component/not-supported` naming these; under a root
|
|
272
|
+
* whose output it doesn't render to, it's `target/unsupported`, as for any component.
|
|
273
|
+
*/
|
|
274
|
+
roots?: readonly RootName[];
|
|
275
|
+
notAllowed?: {
|
|
276
|
+
code: string;
|
|
277
|
+
message: (root: string) => string;
|
|
278
|
+
};
|
|
279
|
+
/** Why a target it doesn't render can't, and what to do instead (in the diagnostic). */
|
|
280
|
+
unsupported?: Partial<Record<Target, string>>;
|
|
281
|
+
editor?: {
|
|
282
|
+
groups: readonly EditorGroup[];
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The conditions a component's styles can be set for besides its own: on phones (`mobile`) and while the pointer is
|
|
288
|
+
* over it (`hover`). Each says where it's allowed, which styles it takes, where its rules go in the stylesheet, and
|
|
289
|
+
* how each output shows it, so reading a template, expanding composites, the support diagnostics and the writers all
|
|
290
|
+
* go through this one list. A condition joins it with its support for every output (test/writers/support.test.ts).
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
type ConditionName = "mobile" | "hover";
|
|
294
|
+
/** On any child, read by the Row it's in. */
|
|
295
|
+
declare const placementStyle: {
|
|
296
|
+
flex: {
|
|
297
|
+
kind: Kind<number | "none", number | "none">;
|
|
298
|
+
label: string;
|
|
299
|
+
description: string;
|
|
300
|
+
support: {
|
|
301
|
+
email: {
|
|
302
|
+
level: "full";
|
|
303
|
+
source: SupportSource;
|
|
304
|
+
};
|
|
305
|
+
web: {
|
|
306
|
+
level: "full";
|
|
307
|
+
source: SupportSource;
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
/** Props that always have a value: required ones, and ones with a default (see `prop`). */
|
|
313
|
+
type RequiredOrDefaulted<P extends PropSpecs> = {
|
|
314
|
+
[K in keyof P]: Exclude<P[K]["required"], undefined> extends true ? K : [P[K]["default"]] extends [undefined] ? never : K;
|
|
315
|
+
}[keyof P];
|
|
316
|
+
/** The props `expand` (or a `render`) gets: normalized, with defaults applied. */
|
|
317
|
+
type ExpandProps<P extends PropSpecs> = {
|
|
318
|
+
[K in RequiredOrDefaulted<P>]: OutputOf<P[K]["kind"]>;
|
|
319
|
+
} & {
|
|
320
|
+
[K in Exclude<keyof P, RequiredOrDefaulted<P>>]?: OutputOf<P[K]["kind"]>;
|
|
321
|
+
};
|
|
322
|
+
/** What `expand` may do besides returning its node, and what it may read besides its props. */
|
|
323
|
+
interface ExpandContext {
|
|
324
|
+
/** Makes custom components the expansion uses known (ones not passed in the components option). */
|
|
325
|
+
register(definition: CustomDefinition<any>): void;
|
|
326
|
+
/** The node's style, with its definition's defaults: a built-in made of primitives (Social, Menu) styles them by it. */
|
|
327
|
+
style: Record<string, Json>;
|
|
328
|
+
/** Whether the template has phones (an Email or a Page): what's hidden on phones is only hidden there. */
|
|
329
|
+
responsive: boolean;
|
|
330
|
+
/** A problem found while expanding that doesn't stop it (a warning or a note), said once at the expansion's place. */
|
|
331
|
+
report(diagnostic: Diagnostic): void;
|
|
332
|
+
}
|
|
333
|
+
interface CustomDefinition<P extends PropSpecs = PropSpecs> extends ComponentDefinition<P, typeof placementStyle> {
|
|
334
|
+
custom: true;
|
|
335
|
+
/**
|
|
336
|
+
* The component as primitives: one node of the template tree
|
|
337
|
+
* (`{ type, props, style, children }`). Pure: the same props give the same node.
|
|
338
|
+
*/
|
|
339
|
+
expand(props: ExpandProps<P>, context: ExpandContext): unknown;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Property discovery: what a component takes and how each thing is edited, as
|
|
344
|
+
* plain data for editors, docs and agents. Each component, prop and style says
|
|
345
|
+
* which roots take it, read from the definitions (the same ones validation reads).
|
|
346
|
+
*/
|
|
347
|
+
|
|
348
|
+
interface PropertyDescription {
|
|
349
|
+
/** "props.href", "style.padding", "hover.color". */
|
|
350
|
+
path: string;
|
|
351
|
+
label: string;
|
|
352
|
+
description?: string;
|
|
353
|
+
kind: string;
|
|
354
|
+
accepts: string;
|
|
355
|
+
editor: EditorKind;
|
|
356
|
+
editable: boolean;
|
|
357
|
+
required: boolean;
|
|
358
|
+
default?: Json;
|
|
359
|
+
inherited: boolean;
|
|
360
|
+
mobile: boolean;
|
|
361
|
+
/** The roots it may be given under: those of its component's that it's declared for. */
|
|
362
|
+
roots: RootName[];
|
|
363
|
+
/** A style's group ("Typography", "Spacing", …); props have none. */
|
|
364
|
+
group?: StyleGroup;
|
|
365
|
+
schema: JsonSchema;
|
|
366
|
+
}
|
|
367
|
+
interface ComponentDescription {
|
|
368
|
+
type: string;
|
|
369
|
+
label: string;
|
|
370
|
+
description: string;
|
|
371
|
+
categories: readonly Category[];
|
|
372
|
+
properties: PropertyDescription[];
|
|
373
|
+
children: {
|
|
374
|
+
text: boolean;
|
|
375
|
+
categories: readonly Category[];
|
|
376
|
+
types: readonly string[];
|
|
377
|
+
};
|
|
378
|
+
targets: Target[];
|
|
379
|
+
/** The roots it may go in: those whose output it renders to, whose children reach it, and that it's declared for. */
|
|
380
|
+
roots: RootName[];
|
|
381
|
+
/** Editor groups: the paths each shows, or the composite editor and the paths it covers. */
|
|
382
|
+
groups: Array<{
|
|
383
|
+
title: string;
|
|
384
|
+
paths: readonly string[];
|
|
385
|
+
composite?: string;
|
|
386
|
+
}>;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* `@hyper-elements/react/inspect`: what each root takes, and what a template holds, as data, without rendering
|
|
391
|
+
* anything. For an agent's tool call or an editor: "can I use this here?" before writing, and "is each part of this
|
|
392
|
+
* template allowed in its root?" after. Read from the components' definitions, the same ones validation and the
|
|
393
|
+
* generated guide read, so the three agree. Synchronous; it loads no engine, browser or network.
|
|
394
|
+
*
|
|
395
|
+
* Every result carries `version`: its shape changes only with a new version.
|
|
396
|
+
*/
|
|
397
|
+
|
|
398
|
+
/** The shape of what this entry returns: a new version is a new shape. */
|
|
399
|
+
declare const INSPECT_VERSION = 1;
|
|
400
|
+
/** A template's own component (made with `component()`), described alongside the built-in ones. */
|
|
401
|
+
interface WithDefinition {
|
|
402
|
+
definition: CustomDefinition<any>;
|
|
403
|
+
}
|
|
404
|
+
interface DescribeOptions {
|
|
405
|
+
/** Only what this root takes, with phone styles only under a root that has phones. */
|
|
406
|
+
root?: RootName;
|
|
407
|
+
/** A template's own components (made with `component()`), described with the built-in ones. */
|
|
408
|
+
components?: readonly WithDefinition[];
|
|
409
|
+
}
|
|
410
|
+
interface ConditionDescription {
|
|
411
|
+
/** "mobile", "hover": the block of `style` it's written in. */
|
|
412
|
+
name: ConditionName;
|
|
413
|
+
/** "on phones", "on hover". */
|
|
414
|
+
on: string;
|
|
415
|
+
/** The roots it may be set under. */
|
|
416
|
+
roots: RootName[];
|
|
417
|
+
}
|
|
418
|
+
interface ComponentsDescription {
|
|
419
|
+
version: typeof INSPECT_VERSION;
|
|
420
|
+
/** The root it's narrowed to, if one was given. */
|
|
421
|
+
root?: RootName;
|
|
422
|
+
/** The roots a template can have. */
|
|
423
|
+
roots: RootName[];
|
|
424
|
+
/** Each component, with its props and styles: their kinds, groups, defaults and the roots that take them. */
|
|
425
|
+
components: ComponentDescription[];
|
|
426
|
+
/** The style blocks a component may have besides its own style, and the roots that take each. */
|
|
427
|
+
conditions: ConditionDescription[];
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Every component a template can use (the built-in ones and those given), each with its props and styles: what
|
|
431
|
+
* each takes, its group, its default, and the roots that take it. With `root`, only what that root takes.
|
|
432
|
+
*/
|
|
433
|
+
declare function describeComponents(options?: DescribeOptions): ComponentsDescription;
|
|
434
|
+
/** One component, as `describeComponents()` describes it; undefined where there's no such component, or `root` doesn't take it. */
|
|
435
|
+
declare function describeComponent(type: string, options?: DescribeOptions): (ComponentDescription & {
|
|
436
|
+
version: typeof INSPECT_VERSION;
|
|
437
|
+
}) | undefined;
|
|
438
|
+
interface InspectedNode {
|
|
439
|
+
/** Where it is, as diagnostics say it: "root", "root.children[2]". */
|
|
440
|
+
path: string;
|
|
441
|
+
type: string;
|
|
442
|
+
id?: string;
|
|
443
|
+
/** The roots its component may go in. */
|
|
444
|
+
roots: RootName[];
|
|
445
|
+
/** Whether the template's root takes it. */
|
|
446
|
+
allowed: boolean;
|
|
447
|
+
/** What it's given, as written: "props.href", "style.padding", "mobile.fontSize", "hover.color", "hidden.mobile". */
|
|
448
|
+
given: string[];
|
|
449
|
+
/** The problems found on it (its props, styles and blocks, and what it renders), not on its children. */
|
|
450
|
+
problems: Diagnostic[];
|
|
451
|
+
}
|
|
452
|
+
interface Inspection {
|
|
453
|
+
version: typeof INSPECT_VERSION;
|
|
454
|
+
/** The template's root, or null where it has none Elements knows. */
|
|
455
|
+
root: RootName | null;
|
|
456
|
+
/** No errors (there may be warnings and notes), as `validate()` says. */
|
|
457
|
+
valid: boolean;
|
|
458
|
+
/**
|
|
459
|
+
* Each component in the template, in document order, as written: one its root doesn't take is here too, with
|
|
460
|
+
* `allowed: false` and its error in `problems`. Each `path` is the one diagnostics give.
|
|
461
|
+
*/
|
|
462
|
+
nodes: InspectedNode[];
|
|
463
|
+
/** Everything found, as `validate()` finds it. */
|
|
464
|
+
diagnostics: Diagnostic[];
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* What a template holds, as data: each component, what it's given, whether its root takes it, and the problems
|
|
468
|
+
* found on it. It checks what `validate()` checks, without rendering.
|
|
469
|
+
*/
|
|
470
|
+
declare function inspect(element: React.ReactElement): Inspection;
|
|
471
|
+
|
|
472
|
+
export { type ComponentDescription, type ComponentsDescription, type ConditionDescription, type ConditionName, type DescribeOptions, type Diagnostic, INSPECT_VERSION, type InspectedNode, type Inspection, type PropertyDescription, type RootName, type StyleGroup, describeComponent, describeComponents, inspect };
|