yandel 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ ISC License Copyright (c) 2004-2010 by Internet Systems Consortium, Inc.
2
+ ("ISC")
3
+
4
+ Copyright (c) 1995-2003 by Internet Software Consortium
5
+
6
+ Permission to
7
+ use, copy, modify, and /or distribute this software for any purpose with or
8
+ without fee is hereby granted, provided that the above copyright notice and this
9
+ permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND
12
+ zzzeros0 DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
13
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL k4sp3r BE
14
+ LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
16
+ CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
17
+ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,525 @@
1
+ # Yandel
2
+
3
+ **Yandel is reactive lightweight** typescript library that eases the creation of small to complex user interfaces without the complexity of project setup with **0-deps**.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Introduction](#introduction)
9
+ - [Tags](#tags)
10
+ - [Text](#text)
11
+ - [Portal](#portal)
12
+ - [Templates](#templates)
13
+ - [Components](#components)
14
+ - [Reactivity](#reactivity)
15
+ - [Ref](#ref)
16
+ - [Key](#key)
17
+ - [Usage](#usage)
18
+
19
+ ## Installation
20
+
21
+ Add this package to your npm project:
22
+
23
+ ```
24
+ npm install yandel
25
+ ```
26
+
27
+ ## Introduction
28
+
29
+ Yandel is a client frontend library that helps you create web UI.
30
+
31
+ ### Tags
32
+
33
+ The default HTML Tag elements. They let you create different HTML Elements and customize them.
34
+
35
+ ```ts
36
+ import { div, span, section } from "yandel";
37
+
38
+ div();
39
+ /**
40
+ * <div/>
41
+ */
42
+ div({ id: "1234" });
43
+ /**
44
+ * <div id="1234"/>
45
+ */
46
+ div({ id: "1234", "aria-hidden": "true" }, span());
47
+ /**
48
+ * <div id="1234" aria-hidden="true">
49
+ * <span/>
50
+ * </div>
51
+ */
52
+ div(
53
+ { id: "1234", className: "myClass", style: { backgroundColor: "red" } },
54
+ span(),
55
+ section()
56
+ );
57
+ /**
58
+ * <div id="1234" class="myClass" style="background-color: red;">
59
+ * <span/>
60
+ * <section/>
61
+ * </div>
62
+ */
63
+ ```
64
+
65
+ ### Text
66
+
67
+ HTML text node.
68
+
69
+ ```ts
70
+ import { h1, div, p } from "yandel";
71
+
72
+ h1("I'm the text inside h1");
73
+ /**
74
+ * <h1>I'm the text inside h1</h1>
75
+ * */
76
+
77
+ div(p("I'm the text inside p"), "I'm the text inside div");
78
+ /**
79
+ * <div>
80
+ * <p>I'm the text inside p</p>I'm the text inside div
81
+ * </div>
82
+ * */
83
+ ```
84
+
85
+ ### Portal
86
+
87
+ Allows you to mount elements over a different parent, remaining in the same tree.
88
+
89
+ ```ts
90
+ import { Portal, div, span, h1 } from "yandel";
91
+
92
+
93
+ Portal(document.body, div());
94
+ // Renders a div inside body
95
+
96
+ Portal(document.querySelector("#someid")!, div(), span(), h1(), ...);
97
+
98
+ ```
99
+
100
+ Example:
101
+
102
+ ```ts
103
+ import { Portal, div, span, ValidTemplateReturn } from "yandel";
104
+
105
+ function Notification(): ValidTemplateReturn {
106
+ return div(
107
+ Portal(document.body, span("Notification 1"), span("Notification 2")),
108
+ button("Remove notifications")
109
+ );
110
+ }
111
+
112
+ // The span will be rendered inside body instead of the parent div.
113
+ // When the parent div is deleted, the portal is deleted as well.
114
+ ```
115
+
116
+ ### Templates
117
+
118
+ Templates are functions that return nodes. They help you customize and modularize:
119
+
120
+ ```ts
121
+ import { div, p, strong, span, button, ValidTemplateReturn } from "yandel";
122
+
123
+ function TotalPriceButton(
124
+ qTy: number,
125
+ uPrice: number,
126
+ onClick: VoidFunction
127
+ ): ValidTemplateReturn {
128
+ return div(
129
+ p(strong("Total is:"), span(`${qTy * uPrice} $`)),
130
+ button({ onclick: onClick }, "Buy")
131
+ );
132
+ }
133
+
134
+ TotalPriceButton(4, 2, () => buy());
135
+ /**
136
+ * <div>
137
+ * <p><strong>Total is:</strong>8 $</>
138
+ * <button>Buy</button>
139
+ * </div>
140
+ */
141
+ ```
142
+
143
+ ### Components
144
+
145
+ Components add the reactivity to the game. They are defined extending the `Context` class and must provide a `render` method (a template):
146
+
147
+ ```ts
148
+ import {
149
+ Component,
150
+ div,
151
+ p,
152
+ strong,
153
+ span,
154
+ button,
155
+ ValidTemplateReturn,
156
+ } from "yandel";
157
+
158
+ class TotalPriceButton extends Component {
159
+ private readonly total: number;
160
+ private readonly onClick: VoidFunction;
161
+ constructor(qTy: number, uPrice: number, onClick: VoidFunction) {
162
+ super();
163
+ this.total = qTy * uPrice;
164
+ this.onClick = onClick;
165
+ }
166
+ public render(): ValidTemplateReturn {
167
+ return div(
168
+ p(strong("Total is:"), span(`${this.total} $`)),
169
+ button({ onclick: this.onClick }, "Buy")
170
+ );
171
+ }
172
+ }
173
+ ```
174
+
175
+ To use a component, instantiate just like a common class:
176
+
177
+ ```ts
178
+ section(new TotalPriceButton(4, 2, buyFn));
179
+ /**
180
+ * <section>
181
+ * <div>
182
+ * <p><strong>Total is:</strong>8 $</>
183
+ * <button>Buy</button>
184
+ * </div>
185
+ * </section>
186
+ */
187
+ ```
188
+
189
+ Components can return an array:
190
+
191
+ ```ts
192
+ class TotalPriceButton extends Component {
193
+ private readonly total: number;
194
+ private readonly onClick: VoidFunction;
195
+ constructor(qTy: number, uPrice: number, onClick: VoidFunction) {
196
+ super();
197
+ this.total = qTy * uPrice;
198
+ this.onClick = onClick;
199
+ }
200
+ public render(): ValidTemplateReturn {
201
+ return [
202
+ p(strong("Total is:"), span(`${this.total} $`)),
203
+ button({ onclick: this.onClick }, "Buy"),
204
+ ];
205
+ }
206
+ }
207
+ ```
208
+
209
+ #### Reactivity
210
+
211
+ `State` object type is defined using the `Component's` generic argument. To set the `initial state`, `defineState` must be called in the constructor.
212
+
213
+ ```ts
214
+ import {
215
+ Component,
216
+ div,
217
+ p,
218
+ strong,
219
+ span,
220
+ button,
221
+ ValidTemplateReturn,
222
+ } from "yandel";
223
+
224
+ class TotalPriceButton extends Component<{
225
+ loading: boolean;
226
+ }> {
227
+ private readonly total: number;
228
+ private readonly onClick: VoidFunction;
229
+ constructor(qTy: number, uPrice: number, onClick: VoidFunction) {
230
+ super();
231
+ this.total = qTy * uPrice;
232
+ this.onClick = onClick;
233
+ // `defineState` must be called in the constructor.
234
+ // It should not be called elsewhere.
235
+ this.defineState({
236
+ loading: false,
237
+ });
238
+ }
239
+ public handleClick() {
240
+ // Perform state update
241
+ this.setState({
242
+ loading: true,
243
+ });
244
+ this.onClick();
245
+ }
246
+ public render(): ValidTemplateReturn {
247
+ return div(
248
+ p(strong("Total is:"), span(`${this.total} $`)),
249
+ button(
250
+ {
251
+ onclick: this.handleClick.bind(this), // Don't forget to bind if needed
252
+ disabled: this.state.loading,
253
+ },
254
+ "Buy"
255
+ )
256
+ );
257
+ }
258
+ }
259
+ ```
260
+
261
+ `State` can be changed and accessed via `this.state`, but only `this.setState` will perform an update:
262
+
263
+ ```ts
264
+ // This will set the value, but won't perform an update
265
+ this.state.loading = true;
266
+
267
+ // this will set the value and perform an update
268
+ this.setState({
269
+ loading: true,
270
+ });
271
+ ```
272
+
273
+ This is usefull when you want to change a state value without performing an state update.
274
+
275
+ `setState` can receive a function that provides the current value and returns the new value:
276
+
277
+ ```ts
278
+ this.setState((lastValue) => ({
279
+ ...lastValue,
280
+ loading: true,
281
+ }));
282
+ ```
283
+
284
+ **Important: Do not overwrite `state`**:
285
+
286
+ ```ts
287
+ this.state = { loading: false }; // state is a read-only property!
288
+ ```
289
+
290
+ ---
291
+
292
+ `Effects` are callbacks that are executed when the component is mounted or unmounted. They are created with `this.effect` and should be called inside the `render` method. Components can have more than one effect/cleanup and they're executed in the order they are defined (FIFO).
293
+
294
+ ```ts
295
+ import { Component, p, ValidTemplateReturn } from "yandel";
296
+ interface User {
297
+ name: string;
298
+ }
299
+ class UserData extends Component<{
300
+ user: User | undefined;
301
+ }> {
302
+ private userId: string;
303
+ constructor(id: string) {
304
+ super();
305
+ this.userId = id;
306
+ this.defineState({ user: undefined });
307
+ }
308
+ public render(): ValidTemplateReturn {
309
+ this.effect(() => {
310
+ // Executed when the component is mounted
311
+ if (!this.state.user)
312
+ requestUser(this.userId).then((user) => {
313
+ this.setState({
314
+ user,
315
+ });
316
+ });
317
+
318
+ if (this.state.user) {
319
+ // If a callback is returned in the effect
320
+ // It will be executed when the component unmounts
321
+ return () => {
322
+ sendUserAnalytics(this.state.user);
323
+ };
324
+ }
325
+ });
326
+ return p(
327
+ this.state.user
328
+ ? `Username is: ${this.state.user.name}`
329
+ : "User is undefined"
330
+ );
331
+ }
332
+ }
333
+ ```
334
+
335
+ Do not forget that calling `setState` inside an effect will perform an update. This example will create a never ending update loop:
336
+
337
+ ```ts
338
+
339
+ public render(): ValidTemplateReturn {
340
+ this.effect(() => {
341
+ this.setState(
342
+ // some state...
343
+ );
344
+ });
345
+ return ...;
346
+ }
347
+
348
+ ```
349
+
350
+ Add a condition to avoid a loop:
351
+
352
+ ```ts
353
+
354
+ public render(): ValidTemplateReturn {
355
+ this.effect(() => {
356
+ if (!condition)
357
+ this.setState(
358
+ // some state...
359
+ );
360
+ });
361
+ return ...;
362
+ }
363
+
364
+ ```
365
+
366
+ **Important:** You must handle calling `setState` or other actions if the component has been removed.
367
+
368
+ ```ts
369
+
370
+ public render(): ValidTemplateReturn {
371
+ this.effect(() => {
372
+ setTimeout(() => {
373
+ this.setState(
374
+ // some state
375
+ );
376
+ }, 2000)
377
+ });
378
+ return ...;
379
+ }
380
+
381
+ ```
382
+
383
+ In this example, if the component is removed, if not handled the timeout will run and an error will be thrown (`Error: Component is deleted`).
384
+ Handle timeouts, deletions and more in the cleanups to prevent weird behavior:
385
+
386
+ ```ts
387
+
388
+ public render(): ValidTemplateReturn {
389
+ this.effect(() => {
390
+ this.timeout = setTimeout(() => {
391
+ this.setState(
392
+ // some state
393
+ );
394
+ }, 2000)
395
+ return () => {
396
+ if (this.timeout) clearTimeout(this.timeout);
397
+ }
398
+ });
399
+ return ...;
400
+ }
401
+
402
+ ```
403
+
404
+ ### Ref
405
+
406
+ The `ref` prop allows you to have access to the element's reference:
407
+
408
+ ```ts
409
+ import { Component, ElementRef, Stores, input } from "yandel";
410
+
411
+ class InputWithRef extends Component {
412
+ private readonly inputRef: ElementRef<"input"> = new Stores(undefined);
413
+ public render() {
414
+ this.effect(() => {
415
+ console.log(this.inputRef.stores); // HTMLInputElement
416
+ });
417
+ return input({
418
+ ref: this.inputRef,
419
+ });
420
+ }
421
+ }
422
+ ```
423
+
424
+ ### Key
425
+
426
+ The `key` prop allows you to identify elements. Elements with the same key won't be diffed.
427
+
428
+ ```ts
429
+ // If keys are the same, node diffing won't be done,
430
+ // even if they are different tags
431
+ class WithKey extends Component {
432
+ public render() {
433
+ return condition
434
+ ? div({
435
+ key: "key1",
436
+ })
437
+ : section({
438
+ key: "key1",
439
+ });
440
+ }
441
+ }
442
+ ```
443
+
444
+ ## Usage
445
+
446
+ Define your own templates and components. Then, use `createRoot` to render your UI.
447
+
448
+ ```ts
449
+ import {
450
+ Component,
451
+ ElementRef,
452
+ Stores,
453
+ ValidTemplateReturn,
454
+ button,
455
+ createRoot,
456
+ div,
457
+ form,
458
+ input,
459
+ p,
460
+ } from "yandel";
461
+
462
+ function Message(msg: string) {
463
+ return p(`The message is: ${msg}`);
464
+ }
465
+
466
+ class MessageInput extends Component<{ message: string }> {
467
+ private readonly inputRef: ElementRef<"input"> = new Stores(undefined);
468
+ constructor() {
469
+ super();
470
+ this.defineState({
471
+ message: "Default message",
472
+ });
473
+ }
474
+ private handleSubmit(v: SubmitEvent) {
475
+ v.preventDefault();
476
+ if (
477
+ this.inputRef.stores &&
478
+ this.inputRef.stores.value !== this.state.message
479
+ ) {
480
+ this.setState({
481
+ message: this.inputRef.stores.value,
482
+ });
483
+ }
484
+ }
485
+ public render(): ValidTemplateReturn {
486
+ this.effect(() => {
487
+ return () => {
488
+ // Reset the input when user
489
+ // sets new message
490
+ if (this.inputRef.stores) this.inputRef.stores.value = "";
491
+ };
492
+ });
493
+ return div(
494
+ form(
495
+ {
496
+ onsubmit: this.handleSubmit.bind(this),
497
+ },
498
+ input({
499
+ ref: this.inputRef,
500
+ type: "text",
501
+ }),
502
+ button(
503
+ {
504
+ type: "submit",
505
+ },
506
+ "Set new message"
507
+ )
508
+ ),
509
+ Message(this.state.message)
510
+ );
511
+ }
512
+ }
513
+
514
+ // Entry point
515
+ createRoot(document.body).render(new MessageInput());
516
+
517
+ // Renders:
518
+ // <div>
519
+ // <form>
520
+ // <input type="text">
521
+ // <button type="submit">Set new message</button>
522
+ // </form>
523
+ // <p>The message is: Default message</p>
524
+ // </div>
525
+ ```
@@ -0,0 +1,2 @@
1
+ export { Component, createRoot, EffectHandler, Element, ElementRef, HTMLProps, HTMLTags, Portal, Stores, Styles, Template, TemplateWithProps, ValidNodeChild, ValidTemplateReturn, StateHandler, } from "./node";
2
+ export * from "./tags";
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { Component, createRoot, Portal, Stores, } from "./node";
2
+ export * from "./tags";
package/dist/node.d.ts ADDED
@@ -0,0 +1,116 @@
1
+ type KeyedObject = Record<string | symbol | number, any>;
2
+ type HTMLTags = keyof HTMLElementTagNameMap;
3
+ type Element<K extends HTMLTags = HTMLTags> = HTMLElementTagNameMap[K];
4
+ interface SwitchableNode<T extends Node> {
5
+ switch(t: T): boolean;
6
+ }
7
+ type ValidNodeChild = Node | Component | Component<KeyedObject> | null | string;
8
+ type ValidTemplateReturn = ValidNodeChild | ValidNodeChild[];
9
+ type TemplateWithProps<P extends KeyedObject = KeyedObject> = (props: P) => ValidTemplateReturn;
10
+ type Template<P extends KeyedObject | void = void> = P extends void ? () => ValidTemplateReturn : TemplateWithProps<P extends void ? KeyedObject : P>;
11
+ type EffectHandler = (() => void) | (() => () => void);
12
+ type ExcludeFunctions<T> = {
13
+ [K in keyof T as T[K] extends Function ? never : K]: T[K];
14
+ };
15
+ type Styles = Partial<CSSStyleDeclaration>;
16
+ type HTMLExcludedProperties = `aria${string}` | "tagName" | "shadowRoot" | "slot" | "classList" | "style" | "attributes" | "attributeStyleMap" | "ATTRIBUTE_NODE" | "CDATA_SECTION_NODE" | "COMMENT_NODE" | "childElementCount" | "childNodes" | "children" | "isConnected" | "ownerDocument" | "lastChild" | "lastElement" | "nextElementSibling" | "nextSibling" | "previousElementSibling" | "previousSibling" | "parentElement" | "parent" | "outerContent" | "firstChild" | "firstElementChild" | "lastChild" | "lastElementChild" | "innerHTML" | "outerHTML" | "innerContent" | "textContent" | `DOCUMENT_${string}` | "NOTATION_NODE" | "PROCESSING_INSTRUCTION_NODE" | "CONTENT_NODE" | "ELEMENT_NODE" | "TEXT_NODE" | `ENTITY_${string}`;
17
+ type AriaWidgetProperties = "aria-autocomplete" | "aria-checked" | "aria-disabled" | "aria-errormessage" | "aria-expanded" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-label" | "aria-level" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-placeholder" | "aria-pressed" | "aria-readonly" | "aria-required" | "aria-selected" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext";
18
+ type AriaLiveRegionProperties = "aria-busy" | "aria-live" | "aria-relevant" | "aria-atomic";
19
+ type AriaDragAndDropProperties = "aria-dropeffect" | "aria-grabbed";
20
+ type AriaRelatonshipProperties = "aria-activedescendant" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-describedby" | "aria-description" | "aria-details" | "aria-errormessage" | "aria-flowto" | "aria-labelledby" | "aria-owns" | "aria-posinset" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-setsize";
21
+ type AriaGlobalProperties = "aria-atomic" | "aria-busy" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-owns" | "aria-relevant" | "aria-roledescription";
22
+ type AriaProps = AriaWidgetProperties | AriaDragAndDropProperties | AriaLiveRegionProperties | AriaRelatonshipProperties | AriaGlobalProperties;
23
+ type AriaBoolean = "true" | "false";
24
+ type AriaValue = Exclude<string, AriaBoolean>;
25
+ type AriaValueMap = Partial<Record<AriaProps, AriaBoolean | AriaValue>>;
26
+ interface ElementOverridedProperties extends AriaValueMap {
27
+ style?: Styles;
28
+ }
29
+ type ElementRef<T extends HTMLTags = HTMLTags> = Stores<Element<T> | undefined>;
30
+ interface ElementProps<T extends HTMLTags = HTMLTags> {
31
+ ref?: ElementRef<T>;
32
+ key?: string | number | symbol;
33
+ }
34
+ type ExcludeProperties<T> = {
35
+ [K in keyof T as K extends HTMLExcludedProperties ? never : K]: T[K];
36
+ };
37
+ type HTMLProps<T extends HTMLTags = HTMLTags> = Partial<ExcludeProperties<ExcludeFunctions<Element<T>>> & ElementProps<T>> & ElementOverridedProperties;
38
+ type StateHandler<S extends KeyedObject | undefined = undefined> = S | ((l: S) => S);
39
+ declare const enum NodeType {
40
+ Tag = 0,
41
+ Content = 1,
42
+ Parent = 2,
43
+ Component = 3
44
+ }
45
+ declare class Stores<T> {
46
+ #private;
47
+ constructor(s: T);
48
+ get stores(): T;
49
+ set stores(s: T);
50
+ }
51
+ declare class Node {
52
+ readonly $typeof: NodeType;
53
+ private _index_of;
54
+ parent: Node | undefined;
55
+ needs_update: boolean;
56
+ protected _deleted: boolean;
57
+ constructor(t: NodeType);
58
+ get isTag(): boolean;
59
+ get isContent(): boolean;
60
+ get isParent(): boolean;
61
+ get isComponent(): boolean;
62
+ get deleted(): boolean;
63
+ get index_of(): number;
64
+ setIndex_of(i: number): this;
65
+ delete(): void;
66
+ }
67
+ declare class TagNode<T extends HTMLTags = HTMLTags> extends Node implements SwitchableNode<TagNode> {
68
+ static is(t: any): t is TagNode;
69
+ tag: T;
70
+ private _dom;
71
+ private _props;
72
+ private _children;
73
+ key: symbol | string | number | undefined;
74
+ index_length: number;
75
+ constructor(tag: T, props?: HTMLProps<T>, children?: ValidNodeChild[]);
76
+ private _apply_dom_props;
77
+ private _diff_dom_props;
78
+ private _clear_dom_props;
79
+ private _clear_dom_events;
80
+ get dom(): Element<T> | undefined;
81
+ get props(): HTMLProps<T> | undefined;
82
+ get children(): ValidNodeChild[] | undefined;
83
+ get hasChildren(): boolean;
84
+ create(): boolean;
85
+ clearChildren(): void;
86
+ clearDom(): void;
87
+ delete(): void;
88
+ switch(t: TagNode<HTMLTags>): boolean;
89
+ }
90
+ declare class ParentNode<T extends HTMLElement = HTMLElement> extends Node implements SwitchableNode<ParentNode> {
91
+ static is(t: any): t is ParentNode;
92
+ readonly dom: T;
93
+ private _children;
94
+ child_length: number;
95
+ constructor(root: T, children?: ValidNodeChild[]);
96
+ get children(): ValidNodeChild[] | undefined;
97
+ get hasChildren(): boolean;
98
+ clearChildren(): void;
99
+ delete(): void;
100
+ switch(t: ParentNode<HTMLElement>): boolean;
101
+ }
102
+ declare abstract class Component<S extends KeyedObject | void = void> {
103
+ static is(t: any): t is Component | Component<KeyedObject>;
104
+ constructor();
105
+ protected get state(): S;
106
+ protected set state(s: S);
107
+ protected setState(s: StateHandler<S extends void ? undefined : S>): void;
108
+ protected effect(effect: EffectHandler): void;
109
+ protected defineState(s: S): void;
110
+ abstract render(): ValidTemplateReturn;
111
+ }
112
+ declare function Portal<T extends HTMLElement>(root: T, ...children: ValidNodeChild[]): ParentNode<T>;
113
+ declare function createRoot<T extends Element>(root: T): {
114
+ render: (...children: ValidNodeChild[]) => void;
115
+ };
116
+ export { Component, createRoot, EffectHandler, Element, ElementRef, HTMLProps, HTMLTags, Node, Portal, Stores, Styles, TagNode, Template, TemplateWithProps, ValidNodeChild, ValidTemplateReturn, StateHandler, };