stagnate 1.0.7 → 1.1.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/Component.d.ts ADDED
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Stagnate Component class
3
+ *
4
+ * @typeParam REFS - interface describing jsx references stored on this component, see {@link Component.refs}
5
+ * @typeParam PROPS - interface describing jsx props passed to this component
6
+ * @typeParam ROOT - type of the html root element
7
+ */
8
+ export declare class Component<REFS = {}, PROPS = undefined, ROOT extends SVGElement | HTMLElement = SVGElement | HTMLElement> {
9
+ /** properties received from jsx (or set via constructor) */
10
+ readonly props: PROPS extends undefined ? {} : PROPS;
11
+ private _components;
12
+ private _attached;
13
+ /** html root element, only accessible after {@link build} was called */
14
+ protected root: ROOT;
15
+ /**
16
+ * parent component, only accessible after {@link bind} was called
17
+ * for self-bound components `this.parent = this`
18
+ */
19
+ protected parent: Component<any, any>;
20
+ /**
21
+ * jsx references stored on this component,
22
+ * the REFS type should be set to a interface describing what references the component will use
23
+ * see {@link ref} for how to set references
24
+ */
25
+ protected refs: REFS;
26
+ /**
27
+ * if component is to be used from jsx it has to have one constructor argument being the props,
28
+ * any other constructor signature will fail when used from jsx
29
+ */
30
+ constructor(...props: PROPS extends undefined ? [] : [props: PROPS]);
31
+ private attach;
32
+ private detach;
33
+ /**
34
+ * component render function, should return the component JSX
35
+ * if null is returned {@link build} call will fail with an exception
36
+ */
37
+ protected render(): Element | null;
38
+ /** called in {@link build} before render is called */
39
+ protected onBeforeRender(): void;
40
+ /** called in {@link build} after render is called and root is set */
41
+ protected onRender(): void;
42
+ /**
43
+ * called when component if fully attached (children are attached and `this.attached = true`),
44
+ * `onAttach` will be called only if the component is bound to a parent component or the component
45
+ * is self-bound
46
+ */
47
+ protected onAttach(): void;
48
+ /**
49
+ * called when component if fully detached (children are detached and `this.attached = false`),
50
+ * `onDetach` will be called only if the component is bound to a parent component or it {@link destroy} was
51
+ * called on the component directly
52
+ */
53
+ protected onDetach(): void;
54
+ /**
55
+ * function meant to be used in jsx for binding references
56
+ *
57
+ * the following will bind the div under `this.refs.foo` and requires the `REFS` type to include `{foo: HTMLDivElement}`
58
+ * ```
59
+ * <div ref={this.ref("foo")} />
60
+ * ```
61
+ *
62
+ * the following will bind the child component under `this.refs.bar` and requires the `REFS` type to include `{bar: BarComponent}`
63
+ * ```
64
+ * <BarComponent ref={this.ref("bar")} />
65
+ * ```
66
+ *
67
+ * the following will bind the child component without adding it to refs
68
+ * ```
69
+ * <BarComponent ref={this.ref()} />
70
+ * ```
71
+ */
72
+ protected ref<T extends keyof REFS | undefined = undefined>(key?: T): (x: REFS[NonNullable<T>] extends never ? any : REFS[NonNullable<T>]) => void;
73
+ /**
74
+ * calls {@link render} and sets {@link root}
75
+ * @returns the created DOM element ({@link root})
76
+ */
77
+ build(): Element;
78
+ /**
79
+ * add component to a parent component,
80
+ * attach component if parent component is attached
81
+ *
82
+ * a component can be self-bound by passing itself as parent (`x.bind(x)`),
83
+ * self-bound components get automatically attached
84
+ */
85
+ bind(parent: Component<any, any>): void;
86
+ /**
87
+ * render the component, add it as a child of {@link parent} and insert it into DOM
88
+ *
89
+ * calls {@link build} and {@link bind} internally
90
+ *
91
+ * @param parent - parent component
92
+ * @param target - DOM element to add the component to, if unset or null `parent.root` is used, if a component is passed it's root will be used
93
+ * @param before - add the element before the given DOM child, a number can be used as a child index, if unset adds the element as the last child
94
+ */
95
+ create(parent: Component<any, any>, target?: Element | Component<any, any> | null, before?: Element | Component<any, any> | number): void;
96
+ /**
97
+ * render the component, add it as a child of {@link parent} and add it to DOM by replacing a existing element or component
98
+ *
99
+ * calls {@link build} and {@link bind} internally
100
+ *
101
+ * @param parent - parent component
102
+ * @param target - component or DOM element to replace, if component is passed {@link destroy} will be called on it
103
+ */
104
+ replace(parent: Component<any, any>, target: Element | Component<any, any>): void;
105
+ /**
106
+ * render the component, add it to DOM and self-bound, meant to be used for creating the root component
107
+ *
108
+ * calls {@link build} and {@link bind} internally
109
+ *
110
+ * @param target - DOM target to append the component to
111
+ */
112
+ createOrphanized(target: Node): void;
113
+ /** remove this component from DOM and its parent component */
114
+ destroy(): void;
115
+ /** true if component is attached */
116
+ get attached(): boolean;
117
+ /** public accessor for {@link root} */
118
+ get htmlRoot(): ROOT;
119
+ /** child component list accessor */
120
+ get components(): Readonly<Component<any, any, any>[]>;
121
+ }
package/Component.js ADDED
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Stagnate Component class
3
+ *
4
+ * @typeParam REFS - interface describing jsx references stored on this component, see {@link Component.refs}
5
+ * @typeParam PROPS - interface describing jsx props passed to this component
6
+ * @typeParam ROOT - type of the html root element
7
+ */
8
+ export class Component {
9
+ constructor(props) {
10
+ this._components = [];
11
+ this._attached = false;
12
+ this.refs = {};
13
+ this.props = props;
14
+ }
15
+ attach() {
16
+ for (let i = 0; i < this._components.length; i += 1) {
17
+ const component = this._components[i];
18
+ if (!component._attached) {
19
+ component.attach();
20
+ }
21
+ }
22
+ this._attached = true;
23
+ this.onAttach();
24
+ }
25
+ detach() {
26
+ this._components.forEach(x => x.detach());
27
+ this._components = [];
28
+ this._attached = false;
29
+ this.refs = {};
30
+ this.parent = null;
31
+ this.root = null;
32
+ this.onDetach();
33
+ }
34
+ /**
35
+ * component render function, should return the component JSX
36
+ * if null is returned {@link build} call will fail with an exception
37
+ */
38
+ render() {
39
+ return null;
40
+ }
41
+ /** called in {@link build} before render is called */
42
+ onBeforeRender() {
43
+ }
44
+ /** called in {@link build} after render is called and root is set */
45
+ onRender() {
46
+ }
47
+ /**
48
+ * called when component if fully attached (children are attached and `this.attached = true`),
49
+ * `onAttach` will be called only if the component is bound to a parent component or the component
50
+ * is self-bound
51
+ */
52
+ onAttach() {
53
+ }
54
+ /**
55
+ * called when component if fully detached (children are detached and `this.attached = false`),
56
+ * `onDetach` will be called only if the component is bound to a parent component or it {@link destroy} was
57
+ * called on the component directly
58
+ */
59
+ onDetach() {
60
+ }
61
+ /**
62
+ * function meant to be used in jsx for binding references
63
+ *
64
+ * the following will bind the div under `this.refs.foo` and requires the `REFS` type to include `{foo: HTMLDivElement}`
65
+ * ```
66
+ * <div ref={this.ref("foo")} />
67
+ * ```
68
+ *
69
+ * the following will bind the child component under `this.refs.bar` and requires the `REFS` type to include `{bar: BarComponent}`
70
+ * ```
71
+ * <BarComponent ref={this.ref("bar")} />
72
+ * ```
73
+ *
74
+ * the following will bind the child component without adding it to refs
75
+ * ```
76
+ * <BarComponent ref={this.ref()} />
77
+ * ```
78
+ */
79
+ ref(key) {
80
+ return (x) => {
81
+ if (x instanceof Component) {
82
+ x.parent = this;
83
+ this._components.push(x);
84
+ if (this._attached) {
85
+ x.attach();
86
+ }
87
+ }
88
+ if (key) {
89
+ this.refs[key] = x;
90
+ }
91
+ };
92
+ }
93
+ /**
94
+ * calls {@link render} and sets {@link root}
95
+ * @returns the created DOM element ({@link root})
96
+ */
97
+ build() {
98
+ this.onBeforeRender();
99
+ const html = this.render();
100
+ if (!html) {
101
+ throw new Error("can not render component: render function returned null");
102
+ }
103
+ this.root = html;
104
+ this.onRender();
105
+ return html;
106
+ }
107
+ /**
108
+ * add component to a parent component,
109
+ * attach component if parent component is attached
110
+ *
111
+ * a component can be self-bound by passing itself as parent (`x.bind(x)`),
112
+ * self-bound components get automatically attached
113
+ */
114
+ bind(parent) {
115
+ this.parent = parent;
116
+ if (parent != this) {
117
+ parent._components.push(this);
118
+ if (parent._attached) {
119
+ this.attach();
120
+ }
121
+ }
122
+ else {
123
+ this.attach();
124
+ }
125
+ }
126
+ /**
127
+ * render the component, add it as a child of {@link parent} and insert it into DOM
128
+ *
129
+ * calls {@link build} and {@link bind} internally
130
+ *
131
+ * @param parent - parent component
132
+ * @param target - DOM element to add the component to, if unset or null `parent.root` is used, if a component is passed it's root will be used
133
+ * @param before - add the element before the given DOM child, a number can be used as a child index, if unset adds the element as the last child
134
+ */
135
+ create(parent, target, before) {
136
+ if (!target) {
137
+ target = parent.root;
138
+ }
139
+ else if (target instanceof Component) {
140
+ target = target.root;
141
+ }
142
+ if (typeof before === "number") {
143
+ before = before < target.children.length ? target.children[Math.max(0, before)] : undefined;
144
+ }
145
+ else if (before instanceof Component) {
146
+ before = before.root;
147
+ }
148
+ target.insertBefore(this.build(), before === undefined ? null : before);
149
+ this.bind(parent);
150
+ }
151
+ /**
152
+ * render the component, add it as a child of {@link parent} and add it to DOM by replacing a existing element or component
153
+ *
154
+ * calls {@link build} and {@link bind} internally
155
+ *
156
+ * @param parent - parent component
157
+ * @param target - component or DOM element to replace, if component is passed {@link destroy} will be called on it
158
+ */
159
+ replace(parent, target) {
160
+ if (target instanceof Component) {
161
+ target.root.replaceWith(this.build());
162
+ target.destroy();
163
+ }
164
+ else {
165
+ target.replaceWith(this.build());
166
+ }
167
+ this.bind(parent);
168
+ }
169
+ /**
170
+ * render the component, add it to DOM and self-bound, meant to be used for creating the root component
171
+ *
172
+ * calls {@link build} and {@link bind} internally
173
+ *
174
+ * @param target - DOM target to append the component to
175
+ */
176
+ createOrphanized(target) {
177
+ target.appendChild(this.build());
178
+ this.bind(this);
179
+ }
180
+ /** remove this component from DOM and its parent component */
181
+ destroy() {
182
+ if (this.root) {
183
+ this.root.remove();
184
+ }
185
+ if (this.parent) {
186
+ const index = this.parent._components.indexOf(this);
187
+ if (index >= 0) {
188
+ this.parent._components.splice(index, 1);
189
+ }
190
+ }
191
+ this.detach();
192
+ }
193
+ /** true if component is attached */
194
+ get attached() {
195
+ return this._attached;
196
+ }
197
+ /** public accessor for {@link root} */
198
+ get htmlRoot() {
199
+ return this.root;
200
+ }
201
+ /** child component list accessor */
202
+ get components() {
203
+ return this._components;
204
+ }
205
+ }
206
+ //# sourceMappingURL=Component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Component.js","sourceRoot":"","sources":["../src/Component.ts"],"names":[],"mappings":"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"}
package/README.md CHANGED
@@ -99,13 +99,11 @@ Same as `create` but replaces `target` instead of being appended to it.
99
99
  #### The `createOrphanized` member function
100
100
 
101
101
  ```typescript
102
- createOrphanized(target?: Element | null)
102
+ createOrphanized(target?: Node)
103
103
  ```
104
104
 
105
105
  Same as `create` but intended to create the root component. The component is automatically set as attached after render.
106
106
 
107
- If `target` is `null` then component is appended to `document.body`.
108
-
109
107
  ## JSX attribute handling
110
108
 
111
109
  ### `ref` attribute
@@ -174,58 +172,137 @@ Primary used to avoid passing nested JSX elements as props.
174
172
 
175
173
  ### Component class
176
174
  ```typescript
177
- declare class Component<REFS = {}, PROPS = undefined, ROOT extends SVGElement | HTMLElement = SVGElement | HTMLElement> {
178
- // props from JSX (set via constructor)
179
- readonly props: PROPS extends undefined ? {} : PROPS
180
- // HTML root element of this component (can be not set if not attached)
181
- protected root: ROOT
182
- // parent of this component (can be not set if not attached)
183
- protected parent: Component<any, any>
184
- // the refs object containing bound elements created during render
185
- protected refs: REFS
186
- // overcomplicated constructor signature made so props is optional only if component has no props defined
187
- constructor(...props: PROPS extends undefined ? [] : [never])
188
- // the render function, called to get the component root element, null can be returned if component
189
- // has nothing to render but will result with exception if component is being created via create or replace
190
- protected render(): Element | null
191
- // the ref callback generation function with a overcomplicated signature, used to bind JSX elements to refs
192
- protected ref<T extends keyof REFS | undefined = undefined>(key?: T): (x: REFS[NonNullable<T>] extends never ? any : REFS[NonNullable<T>]) => void
193
- // create component and replace target element
194
- replace(parent: Component<any, any>, target?: Element | Component<any, any> | null): void
195
- // create component and insert to target
196
- create(parent: Component<any, any>, target?: Element | Component<any, any> | null, before?: Element | Component<any, any> | number): void
197
- // crate component as root (attached set on creation)
198
- createOrphanized(target?: Element | null): void
199
- // bind component to a already existing element (called internally on JSX ref binding)
200
- bind(parent: Component<any, any>, target?: Element): void
201
- // destroy component and it child components
202
- destroy(): void
203
- // check if component is attached
204
- get attached(): boolean
205
- // get the root element of this component
206
- get htmlRoot(): ROOT;
207
- // get and array of child components
208
- protected get components(): Readonly<Component<any, any, any>[]>
209
- // called before render is called
210
- protected onBeforeRender(): void
211
- // called after render is called
212
- protected onRender(): void
213
- // called when parent becomes attached (or on parent assignment if parent is attached)
214
- protected onAttach(): void
215
- // called when element is destroyed
216
- protected onDetach(): void;
175
+ /**
176
+ * Stagnate Component class
177
+ *
178
+ * @typeParam REFS - interface describing jsx references stored on this component, see {@link Component.refs}
179
+ * @typeParam PROPS - interface describing jsx props passed to this component
180
+ * @typeParam ROOT - type of the html root element
181
+ */
182
+ class Component<REFS = {}, PROPS = undefined, ROOT extends SVGElement | HTMLElement = SVGElement | HTMLElement> {
183
+ /** properties received from jsx (or set via constructor) */
184
+ readonly props: PROPS extends undefined ? {} : PROPS
185
+
186
+ /** html root element, only accessible after {@link build} was called */
187
+ protected root: ROOT
188
+
189
+ /**
190
+ * parent component, only accessible after {@link bind} was called
191
+ * for self-bound components `this.parent = this`
192
+ */
193
+ protected parent: Component<any, any>
194
+
195
+ /**
196
+ * jsx references stored on this component,
197
+ * the REFS type should be set to a interface describing what references the component will use
198
+ * see {@link ref} for how to set references
199
+ */
200
+ protected refs: REFS
201
+
202
+ /**
203
+ * if component is to be used from jsx it has to have one constructor argument being the props,
204
+ * any other constructor signature will fail when used from jsx
205
+ */
206
+ constructor(props: PROPS)
207
+
208
+ /**
209
+ * component render function, should return the component JSX
210
+ * if null is returned {@link build} call will fail with an exception
211
+ */
212
+ protected render(): Element | null
213
+
214
+ /** called in {@link build} before render is called */
215
+ protected onBeforeRender(): void
216
+
217
+ /** called in {@link build} after render is called and root is set */
218
+ protected onRender(): void
219
+
220
+ /**
221
+ * called when component if fully attached (children are attached and `this.attached = true`),
222
+ * `onAttach` will be called only if the component is bound to a parent component or the component
223
+ * is self-bound
224
+ */
225
+ protected onAttach(): void
226
+
227
+ /**
228
+ * called when component if fully detached (children are detached and `this.attached = false`),
229
+ * `onDetach` will be called only if the component is bound to a parent component or it {@link destroy} was
230
+ * called on the component directly
231
+ */
232
+ protected onDetach(): void
233
+
234
+ /** function meant to be used in jsx for binding references */
235
+ protected ref<T extends keyof REFS | undefined = undefined>(key?: T): (x: REFS[NonNullable<T>] extends never ? any : REFS[NonNullable<T>]) => void
236
+
237
+ /**
238
+ * calls {@link render} and sets {@link root}
239
+ * @returns the created DOM element ({@link root})
240
+ */
241
+ build(): Element
242
+
243
+ /**
244
+ * add component to a parent component,
245
+ * attach component if parent component is attached
246
+ *
247
+ * a component can be self-bound by passing itself as parent (`x.bind(x)`),
248
+ * self-bound components get automatically attached
249
+ */
250
+ bind(parent: Component<any, any>): void
251
+
252
+ /**
253
+ * render the component, add it as a child of {@link parent} and insert it into DOM
254
+ *
255
+ * calls {@link build} and {@link bind} internally
256
+ *
257
+ * @param parent - parent component
258
+ * @param target - DOM element to add the component to, if unset or null `parent.root` is used, if a component is passed it's root will be used
259
+ * @param before - add the element before the given DOM child, a number can be used as a child index, if unset adds the element as the last child
260
+ */
261
+ create(parent: Component<any, any>, target?: Element | Component<any, any> | null, before?: Element | Component<any, any> | number): void
262
+
263
+ /**
264
+ * render the component, add it as a child of {@link parent} and add it to DOM by replacing a existing element or component
265
+ *
266
+ * calls {@link build} and {@link bind} internally
267
+ *
268
+ * @param parent - parent component
269
+ * @param target - component or DOM element to replace, if component is passed {@link destroy} will be called on it
270
+ */
271
+ replace(parent: Component<any, any>, target: Element | Component<any, any>): void
272
+
273
+ /**
274
+ * render the component, add it to DOM and self-bound, meant to be used for creating the root component
275
+ *
276
+ * calls {@link build} and {@link bind} internally
277
+ *
278
+ * @param target - DOM target to append the component to
279
+ */
280
+ createOrphanized(target: Node): void
281
+
282
+ /** remove this component from DOM and its parent component */
283
+ destroy(): void
284
+
285
+ /** true if component is attached */
286
+ get attached(): boolean
287
+
288
+ /** public accessor for {@link root} */
289
+ get htmlRoot(): ROOT
290
+
291
+ /** child component list accessor */
292
+ get components(): Readonly<Component<any, any, any>[]>
217
293
  }
218
-
219
294
  ```
220
295
 
221
296
  ### Utility Types
222
297
 
223
298
  ```typescript
224
- // get props of an JSX element or component function / class
299
+ /** get props of an JSX element or component function / class */
225
300
  type ComponentProps<IntrinsicElement | ClassElement | FunctionElement>
226
- // anything that can be legally used in JSX
301
+
302
+ /** any value that can be used in JSX */
227
303
  type StagnateNode
228
- // the JSX element css class attribute
304
+
305
+ /** the JSX element css class attribute */
229
306
  type ClassAttribute
230
307
  ```
231
308
 
package/Slot.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ import type { JSX, StagnateNode } from "./types";
2
+ /**
3
+ * Pseudo component used to create named slots.
4
+ *
5
+ * example use:
6
+ * ```typescript
7
+ * function Foo(props: {children: StagnateNode}) {
8
+ * const slots = Slot.extract<{foo: HTMLElement, bar: HTMLElement}>(props.children)
9
+ * return <div>
10
+ * <div>{slots.foo}</div>
11
+ * <div>{slots.bar}</div>
12
+ * </div>
13
+ * }
14
+ *
15
+ * const example = <Foo>
16
+ * <Slot name="foo">FOO</Slot>
17
+ * <Slot name="bar">BAR</Slot>
18
+ * </Foo>
19
+ * ```
20
+ */
21
+ export declare function Slot(props: {
22
+ name: string;
23
+ children: StagnateNode;
24
+ }): JSX.Element;
25
+ export declare namespace Slot {
26
+ /**
27
+ * This function extracts slotted children from the child list,
28
+ * it has to be called if slots are in the child list or render will fail on un-extracted slot data.
29
+ *
30
+ * see {@link Slot} for a usage example
31
+ */
32
+ function extract<T = Record<string, any>>(input: StagnateNode, slots?: Record<string, any>): T;
33
+ }
package/Slot.js ADDED
@@ -0,0 +1,60 @@
1
+ class SlotArray extends Array {
2
+ constructor(name, elements) {
3
+ super();
4
+ this.name = name;
5
+ this.push(elements);
6
+ }
7
+ }
8
+ /**
9
+ * Pseudo component used to create named slots.
10
+ *
11
+ * example use:
12
+ * ```typescript
13
+ * function Foo(props: {children: StagnateNode}) {
14
+ * const slots = Slot.extract<{foo: HTMLElement, bar: HTMLElement}>(props.children)
15
+ * return <div>
16
+ * <div>{slots.foo}</div>
17
+ * <div>{slots.bar}</div>
18
+ * </div>
19
+ * }
20
+ *
21
+ * const example = <Foo>
22
+ * <Slot name="foo">FOO</Slot>
23
+ * <Slot name="bar">BAR</Slot>
24
+ * </Foo>
25
+ * ```
26
+ */
27
+ export function Slot(props) {
28
+ return new SlotArray(props.name, props.children);
29
+ }
30
+ (function (Slot) {
31
+ /**
32
+ * This function extracts slotted children from the child list,
33
+ * it has to be called if slots are in the child list or render will fail on un-extracted slot data.
34
+ *
35
+ * see {@link Slot} for a usage example
36
+ */
37
+ function extract(input, slots = {}) {
38
+ if (input instanceof SlotArray && input.length) {
39
+ slots[input.name] = input[0];
40
+ input.pop();
41
+ }
42
+ else if (Array.isArray(input)) {
43
+ for (let i = 0; i < input.length; i += 1) {
44
+ const item = input[i];
45
+ if (item instanceof SlotArray) {
46
+ if (item.length) {
47
+ slots[item.name] = item[0];
48
+ }
49
+ input[i] = null;
50
+ }
51
+ else if (Array.isArray(item)) {
52
+ extract(item, slots);
53
+ }
54
+ }
55
+ }
56
+ return slots;
57
+ }
58
+ Slot.extract = extract;
59
+ })(Slot || (Slot = {}));
60
+ //# sourceMappingURL=Slot.js.map
package/Slot.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Slot.js","sourceRoot":"","sources":["../src/Slot.ts"],"names":[],"mappings":"AAEA,MAAM,SAAU,SAAQ,KAAmB;IAE1C,YAAa,IAAY,EAAE,QAAsB;QAChD,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACpB,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,IAAI,CAAC,KAA6C;IACjE,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAQ,CAAA;AACxD,CAAC;AAED,WAAiB,IAAI;IACpB;;;;;OAKG;IACH,SAAgB,OAAO,CAA0B,KAAmB,EAAE,QAA6B,EAAE;QACpG,IAAI,KAAK,YAAY,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAChD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;YAC5B,KAAK,CAAC,GAAG,EAAE,CAAA;QACZ,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;gBACrB,IAAI,IAAI,YAAY,SAAS,EAAE,CAAC;oBAC/B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBACjB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;oBAC3B,CAAC;oBACD,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;gBAChB,CAAC;qBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBACrB,CAAC;YACF,CAAC;QACF,CAAC;QACD,OAAO,KAAU,CAAA;IAClB,CAAC;IAlBe,YAAO,UAkBtB,CAAA;AACF,CAAC,EA1BgB,IAAI,KAAJ,IAAI,QA0BpB"}
@@ -1,5 +1,4 @@
1
- export * from "./types";
1
+ export type * from "./types";
2
2
  export * from "./Component";
3
3
  export * from "./Slot";
4
4
  export { Fragment, createElement } from "./jsx-runtime";
5
- export * as default from "./index";
@@ -1,6 +1,4 @@
1
- export * from "./types";
2
1
  export * from "./Component";
3
2
  export * from "./Slot";
4
3
  export { Fragment, createElement } from "./jsx-runtime";
5
- export * as default from "./index";
6
4
  //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,cAAc,QAAQ,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA"}
@@ -1,8 +1,9 @@
1
1
  import type { JSX, StagnateNode } from "./types";
2
2
  export declare function jsx(type: any, props: any): any;
3
3
  export declare function createElement(type: any, props: any, ...children: any[]): any;
4
+ /** JSX fragment component, <> can be used as an alias */
4
5
  export declare function Fragment(props: {
5
6
  children: StagnateNode;
6
7
  }): JSX.Element;
7
8
  export { jsx as jsxs };
8
- export { JSX };
9
+ export type { JSX };