veles 0.0.7 → 0.0.8

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Build Size](https://img.shields.io/bundlephobia/minzip/veles?label=bundle%20size)](https://bundlephobia.com/result?p=veles)
5
5
  [![Version](https://img.shields.io/npm/v/veles)](https://www.npmjs.com/package/veles)
6
6
 
7
- > The library is in very early stages and some features, like proper TypeScript support, are not fully implemented yet
7
+ > This library is very early stages, so the API is not 100% finalized
8
8
 
9
9
  `Veles` is a component-based performance-focused UI library. The main goal of this library is to provide a composable way to build highly interactive interfaces, which should be performant out of the box, as long as you follow the recommendations.
10
10
 
@@ -14,270 +14,47 @@ This library's primary focus is in performance. What this means is that it allow
14
14
 
15
15
  It is important to note that the performance benefits will only be observed (and relevant as well) in case of a pretty high interactivity. It might not be faster than any other UI framework on the first render, the biggest improvement lies in the power of subscribing to individual changes.
16
16
 
17
- ## API
17
+ ## Installation
18
18
 
19
- ### AttachComponent
19
+ The library is available on npm. To add it to your project, execute this in your project folder:
20
20
 
21
- Attach Veles tree to a regular DOM Node.
22
-
23
- > [!NOTE]
24
- > As of right now, this method will wrap the component's HTML into one additional `div`. This will probably go away in the future, but for now it simplifies some things significantly.
25
-
26
- ```js
27
- import { attachComponent } from "veles";
28
-
29
- const App () => <div>App</div>
30
-
31
- const appContainer = document.getElementById("app");
32
- attachComponent({ htmlElement: appContainer, component: <App /> });
33
- ```
34
-
35
- ### JSX support
36
-
37
- Veles supports JSX transformation, so as long as you specify `importSource: "veles"` (this is for Babel, the other JS transpilers should have similar options) it will work as expected.
38
-
39
- ```jsx
40
- function App() {
41
- return (
42
- <div class="app-container">
43
- <h1>Veles App</h1>
44
- <p>Random description</p>
45
- </div>
46
- );
47
- }
48
- ```
49
-
50
- ### createState
51
-
52
- `createState` is the API which is responsible for the interactivity in Veles applications, and it is the only one. You can either pass the initial value and then update it manually in callbacks or some other subscriptions, or you can pass a function as the second argument and you can subscribe to any external data store and update the state reacting to it.
53
-
54
- `createState` returns an object with a variety of subscription methods. It is important to understand that just creating the state object does not affect the component at all. When the state value updates, only the components which are rendered by these subscription methods will update, but the component where the state was created is not affected.
55
-
56
- The simplest way to react to state changes in the UI is to use `useValue` method from the state object. Let's build a simple counter to demonstrate:
57
-
58
- ```jsx
59
- import { createState } from "veles";
60
-
61
- function Counter() {
62
- const counterState = createState(0);
63
- const increment = () =>
64
- counterState.setValue((currentValue) => currentValue + 1);
65
- const decrement = () =>
66
- counterState.setValue((currentValue) => currentValue - 1);
67
- return (
68
- <div>
69
- <h1>Counter</h1>
70
- <div>
71
- {counterState.useValue(
72
- (counterValue) => `counter value is: ${counterValue}`
73
- )}
74
- </div>
75
- <button onClick={increment}>+</button>
76
- <button onClick={decrement}>-</button>
77
- </div>
78
- );
79
- }
80
- ```
81
-
82
- ### createState and partial subscriptions
83
-
84
- If you have an object in your store, even atomic updates will be wasteful. Let's say you have an object with several fields, but you are only interested in the `title` property. If you use `useValue`, it will do unnecessary work. To help with that, there is a `useValueSelector` state method, which accepts a selector function as the first parameter. Here is an example:
85
-
86
- ```jsx
87
- import { createState } from "veles";
88
-
89
- function App() {
90
- const taskState = createState({
91
- id: 5,
92
- title: "title",
93
- description: "long description",
94
- });
95
- return (
96
- <div>
97
- <h1>App</h1>
98
- <div>
99
- {taskState.useSelectorValue(
100
- (task) => task.title,
101
- (title) => `task title: ${title}`
102
- )}
103
- </div>
104
- </div>
105
- );
106
- }
107
- ```
108
-
109
- The component which listens for `title` will only be rendered again when the title changes.
110
-
111
- ### createState and lists
112
-
113
- Lists performance is one of the cornerstones of this library, and to help with that, it provides a special state method `useValueIterator`. This method ensures that when the state changes, instead of re-rendering the whole list, it checks each list element individually, moves them into correct order without unnecessary re-renders, and in case of changes element data, it will update the passed state object, so that only subscribed parts will re-render.
114
-
115
- > [!NOTE]
116
- > the library determines the uniqueness by calculating the key. You can either pass a string which will be a property name, or you can pass a function which will be executed with the element and the index. If the result is different from any previous calculations, it treats it as a new component.
117
-
118
- Let's build a simple list component:
119
-
120
- ```jsx
121
- import { createState } from "veles";
122
-
123
- function List() {
124
- const listState = createState([
125
- { id: 1, name: "first task" },
126
- { id: 2, name: "second task" },
127
- { id: 3, name: "third task" },
128
- ]);
129
-
130
- return <div>
131
- <h1>List</h1>
132
- {listState.useValueIterator<{ id: number; name: string }>(
133
- { key: "id" },
134
- ({ elementState }) => <div>
135
- {elementState.useValueSelector(
136
- (element) => element.name,
137
- (name) => <div>{name}</div>
138
- )}
139
- </div>
140
- )}
141
- </div>
142
- }
143
- ```
144
-
145
- ### createState and attributes
146
-
147
- In order to avoid unnecessary re-renders when you to change properties on a wrapper element/component, there is a special state method `useAttribute`. It allows to recalculate value for an attribute every time the state changes, but instead of re-rendering, it calls the `htmlNode.setAttribute` method. Here is an example:
148
-
149
- ```jsx
150
- import { createState } from "veles";
151
-
152
- function Counter() {
153
- const counterState = createState(0);
154
- const increment = () =>
155
- counterState.setValue((currentValue) => currentValue + 1);
156
- return (
157
- <div>
158
- <h1>Counter</h1>
159
- <div>{counterState.useValue((value) => `counter value is ${value}`)}</div>
160
- <button
161
- onClick={increment}
162
- style={counterState.useAttribute(
163
- (currentValue) => `width: ${50 + currentValue}px;`
164
- )}
165
- >
166
- +
167
- </button>
168
- </div>
169
- );
170
- }
21
+ ```sh
22
+ npm install --save veles
171
23
  ```
172
24
 
173
- You can see that we dynamically change the width of the button with every press. This will be the only change, the rest of the application will not be re-rendered or any code will not be executed. You still need to be mindful what are you changing, as with some CSS changes you can force reflows/repaints and that can still cause some performance issues.
25
+ Types are installed automatically with the same package.
174
26
 
175
- ### createState and subscribing to updates
176
-
177
- What if you don't want to render anything when the value changes, but you want to call your code? The state provides `trackValue` method, which does exactly that. Here is an example:
27
+ ## A basic example
178
28
 
179
29
  ```jsx
180
30
  import { createState } from "veles";
181
31
 
182
- function Counter() {
183
- const counterState = createState(0);
184
-
185
- counterState.trackValue((counterValue) => {
186
- console.log(`new counter value is ${counterValue}`);
187
- });
188
- const increment = () =>
189
- counterState.setValue((currentValue) => currentValue + 1);
190
- const decrement = () =>
191
- counterState.setValue((currentValue) => currentValue - 1);
192
-
32
+ function NameComponent() {
33
+ const nameState = createState("");
193
34
  return (
194
35
  <div>
195
- <h1>Counter</h1>
196
- <div>
197
- {counterState.useValue(
198
- (counterValue) => `counter value is: ${counterValue}`
199
- )}
200
- </div>
201
- <button onClick={increment}>+</button>
202
- <button onClick={decrement}>-</button>
36
+ <input
37
+ type="text"
38
+ name="name"
39
+ value={nameState.useAttribute()}
40
+ onInput={(e) => nameState.setValue(e.target.value)}
41
+ />
42
+ <p>{nameState.useValue()}</p>
203
43
  </div>
204
44
  );
205
45
  }
206
46
  ```
207
47
 
208
- This subscription will not cause any re-renders. By default, the first call will happen during the component initialization, and you can pass a second options object to alter this behaviour. You can either set `{ skipFirstCall: true }` to completely skip it, or you can specify to run it when the component is mounted in DOM: `{ callOnMount: true }`.
48
+ This will render an input and will update the Text node dynamically, without re-rendering the whole component. For a more advanced example, please head to [the docs](https://bloomca.github.io/veles/#advanced-example).
209
49
 
210
- ### Subscribing to partial updates
50
+ ### Resources
211
51
 
212
- In case you don't want to subscribe to the whole state, you have 2 options. You can either provide a `{ comparator: (prevValue, nextValue) => prevValue === nextValue }` property in the options object, or you can use `state.trackValueSelector()` method. You can also combine them, if you need that for some reason.
52
+ - [Getting started](https://bloomca.github.io/veles/)
53
+ - [API docs](https://bloomca.github.io/veles/api/)
54
+ - [Differences from other frameworks](https://bloomca.github.io/veles/frameworks-difference.html)
213
55
 
214
- ### Combining different states
56
+ There also a companion app ([veles-calendar-app](https://github.com/Bloomca/veles-calendar-app)), which is developed using Veles and is supposed to push it to the limits, identify the issues and ideally improve performance even more.
215
57
 
216
- Since `createState` is the only way to add dynamic behaviour to the application, sooner or later you'll need to build UI which depends on several states. To do so, you can use `combineState` function which accepts any amount of state objects, and returns an array with all combined values in it.
217
-
218
- ```jsx
219
- import { createState } from "veles";
58
+ ### Features
220
59
 
221
- function Counter() {
222
- const firstcounterState = createState(0);
223
- const secondCounterState = createState(0);
224
- const combinedCounterState = combineState(
225
- firstcounterState,
226
- secondCounterState
227
- );
228
- const incrementFirstCounter = () =>
229
- firstcounterState.setValue(
230
- (currentCounterValue) => currentCounterValue + 1
231
- );
232
- const incrementSecondCounter = () =>
233
- secondCounterState.setValue(
234
- (currentCounterValue) => currentCounterValue + 1
235
- );
236
- return (
237
- <div>
238
- <h1>Counters</h1>
239
- <div>
240
- {firstcounterState.useValue(
241
- (value) => `first counter value is: ${value}`
242
- )}
243
- </div>
244
- <div>
245
- {secondCounterState.useValue(
246
- (value) => `second counter value is: ${value}`
247
- )}
248
- </div>
249
- <div>
250
- {combinedCounterState.useValueSelector(
251
- ([firstValue, secondValue]) => firstValue + secondValue,
252
- (counterValue) => `combined counter value is: ${counterValue}`
253
- )}
254
- </div>
255
- <button onClick={incrementFirstCounter}>Increment first counter</button>
256
- <button onClick={incrementSecondCounter}>Increment second counter</button>
257
- </div>
258
- );
259
- }
260
- ```
261
-
262
- ### Components lifecycle
263
-
264
- Right now there are `onMount` and `onUnmount` lifecycle hooks. In your component, just import and call them to add a callback.
265
-
266
- > [!NOTE]
267
- > You can only use them during the original initialization of the component. If you want to add some callbacks later, use the same version passed as a second argument to your component
268
-
269
- ```jsx
270
- import { onMount, onUnmount } from "veles";
271
-
272
- function App(_props, componentAPI) {
273
- // could be used as `componentAPI.onMount()`
274
- onMount(() => {
275
- console.log("called when the component mounts");
276
- });
277
- // could be used as `componentAPI.onUnmount()`
278
- onUnmount(() => {
279
- console.log("called when the component unmounts");
280
- });
281
- return <div>Application<div>
282
- }
283
- ```
60
+ The library is under development, so some features are not available yet, namely Context and Portals.
@@ -24,56 +24,30 @@ function onUnmount(cb) {
24
24
  }
25
25
  }
26
26
 
27
- // src/_utils.ts
28
- function getComponentVelesNode(component) {
29
- const componentsTree = [];
30
- if ("velesStringElement" in component) {
31
- return {
32
- velesElementNode: component,
33
- componentsTree: []
34
- };
35
- }
36
- let childNode = component;
37
- while ("velesComponent" in childNode) {
38
- componentsTree.push(childNode);
39
- if ("velesStringElement" in childNode.tree) {
40
- return {
41
- velesElementNode: childNode.tree,
42
- componentsTree
43
- };
44
- } else {
45
- childNode = childNode.tree;
27
+ // src/create-element/create-text-element.ts
28
+ function createTextElement(text) {
29
+ const mountHandlers = [];
30
+ const unmountHandlers = [];
31
+ return {
32
+ velesStringElement: true,
33
+ // in case there is no text, we create an empty Text node, so we still can
34
+ // have a reference to it, replace it, call lifecycle methods, etc
35
+ html: document.createTextNode(text || ""),
36
+ _privateMethods: {
37
+ _addMountHandler(cb) {
38
+ mountHandlers.push(cb);
39
+ },
40
+ _callMountHandlers() {
41
+ mountHandlers.forEach((cb) => cb());
42
+ },
43
+ _addUnmountHandler: (cb) => {
44
+ unmountHandlers.push(cb);
45
+ },
46
+ _callUnmountHandlers: () => {
47
+ unmountHandlers.forEach((cb) => cb());
48
+ }
46
49
  }
47
- }
48
- return { velesElementNode: childNode, componentsTree };
49
- }
50
- function callMountHandlers(component) {
51
- if ("velesStringElement" in component) {
52
- return;
53
- }
54
- if ("velesComponent" in component) {
55
- component._privateMethods._callMountHandlers();
56
- callMountHandlers(component.tree);
57
- }
58
- if ("velesNode" in component) {
59
- component.childComponents.forEach(
60
- (childComponent) => callMountHandlers(childComponent)
61
- );
62
- }
63
- }
64
- function identity(value1, value2) {
65
- return value1 === value2;
66
- }
67
- function unique(arr) {
68
- const map = /* @__PURE__ */ new Map();
69
- const resultArr = [];
70
- arr.forEach((element) => {
71
- if (map.has(element))
72
- return;
73
- map.set(element, true);
74
- resultArr.push(element);
75
- });
76
- return resultArr;
50
+ };
77
51
  }
78
52
 
79
53
  // src/create-element/parse-children.ts
@@ -86,30 +60,36 @@ function parseChildren({
86
60
  if (children === void 0 || children === null) {
87
61
  return childComponents;
88
62
  }
63
+ let lastInsertedNode = null;
89
64
  (Array.isArray(children) ? children : [children]).forEach(
90
65
  (childComponent) => {
91
66
  if (typeof childComponent === "string") {
92
- const text = document.createTextNode(childComponent);
93
- htmlElement.append(text);
67
+ const textNode = createTextElement(childComponent);
68
+ htmlElement.append(textNode.html);
69
+ lastInsertedNode = textNode.html;
70
+ childComponents.push(textNode);
94
71
  } else if (typeof childComponent === "number") {
95
- const text = document.createTextNode(String(childComponent));
96
- htmlElement.append(text);
72
+ const textNode = createTextElement(String(childComponent));
73
+ htmlElement.append(textNode.html);
74
+ lastInsertedNode = textNode.html;
75
+ childComponents.push(textNode);
97
76
  } else if (typeof childComponent === "object" && childComponent && "velesNode" in childComponent && (childComponent == null ? void 0 : childComponent.velesNode)) {
98
77
  if (childComponent.phantom) {
99
78
  childComponent.childComponents.forEach((childComponentofPhantom) => {
100
79
  if ("velesNode" in childComponentofPhantom) {
101
80
  htmlElement.append(childComponentofPhantom.html);
102
81
  childComponentofPhantom.parentVelesElement = velesNode;
103
- } else {
104
- const { velesElementNode } = getComponentVelesNode(
105
- childComponentofPhantom
106
- );
82
+ lastInsertedNode = childComponentofPhantom.html;
83
+ } else if ("velesStringElement" in childComponentofPhantom) {
84
+ const velesElementNode = childComponentofPhantom;
107
85
  if (!velesElementNode) {
108
86
  console.error("can't find HTML tree in a component chain");
109
87
  } else {
110
88
  htmlElement.append(velesElementNode.html);
89
+ lastInsertedNode = velesElementNode.html;
111
90
  velesElementNode.parentVelesElement = velesNode;
112
91
  }
92
+ } else {
113
93
  }
114
94
  });
115
95
  childComponent.parentVelesElement = velesNode;
@@ -118,39 +98,18 @@ function parseChildren({
118
98
  htmlElement.append(childComponent.html);
119
99
  childComponent.parentVelesElement = velesNode;
120
100
  childComponents.push(childComponent);
101
+ lastInsertedNode = childComponent.html;
121
102
  }
122
- } else if (typeof childComponent === "object" && childComponent && "velesComponent" in childComponent && (childComponent == null ? void 0 : childComponent.velesComponent)) {
123
- const { componentsTree, velesElementNode } = getComponentVelesNode(childComponent);
124
- if (!velesElementNode) {
125
- console.error("can't find HTML tree in a component chain");
126
- } else {
127
- if ("velesNode" in velesElementNode && velesElementNode.phantom) {
128
- velesElementNode.childComponents.forEach(
129
- (childComponentofPhantom) => {
130
- if ("velesNode" in childComponentofPhantom) {
131
- htmlElement.append(childComponentofPhantom.html);
132
- childComponentofPhantom.parentVelesElement = velesNode;
133
- } else {
134
- const { componentsTree: componentsTree2, velesElementNode: velesElementNode2 } = getComponentVelesNode(childComponentofPhantom);
135
- if (!velesElementNode2) {
136
- console.error("can't find HTML tree in a component chain");
137
- } else {
138
- htmlElement.append(velesElementNode2.html);
139
- velesElementNode2.parentVelesElement = velesNode;
140
- }
141
- }
142
- }
143
- );
144
- } else {
145
- htmlElement.append(velesElementNode.html);
146
- }
147
- velesElementNode.parentVelesElement = velesNode;
148
- childComponents.push(childComponent);
149
- }
103
+ } else if (typeof childComponent === "object" && childComponent && "velesComponentObject" in childComponent) {
104
+ childComponent.insertAfter = lastInsertedNode;
105
+ childComponent.parentVelesElement = velesNode;
106
+ childComponents.push(childComponent);
107
+ lastInsertedNode = childComponent;
150
108
  } else if (typeof childComponent === "object" && childComponent && "velesStringElement" in childComponent && (childComponent == null ? void 0 : childComponent.velesStringElement)) {
151
109
  htmlElement.append(childComponent.html);
152
110
  childComponent.parentVelesElement = velesNode;
153
111
  childComponents.push(childComponent);
112
+ lastInsertedNode = childComponent.html;
154
113
  }
155
114
  }
156
115
  );
@@ -167,28 +126,68 @@ function assignAttributes({
167
126
  const isFunction = typeof value === "function";
168
127
  if (isFunction && value.velesAttribute === true) {
169
128
  const attributeValue = value(htmlElement, key, velesNode);
170
- htmlElement.setAttribute(key, attributeValue);
171
- } else if (
172
- // basically, any form of `on` handlers, like `onClick`, `onCopy`, etc
173
- isFunction && key.length > 2 && key.startsWith("on")
174
- ) {
175
- htmlElement.addEventListener(
176
- key[2].toLocaleLowerCase() + key.slice(3),
177
- value
178
- );
129
+ assignAttribute({ key, value: attributeValue, htmlElement });
179
130
  } else {
180
- htmlElement.setAttribute(key, value);
131
+ assignAttribute({ key, value, htmlElement });
181
132
  }
182
133
  });
183
134
  }
135
+ function assignAttribute({
136
+ key,
137
+ value,
138
+ htmlElement
139
+ }) {
140
+ if (
141
+ // basically, any form of `on` handlers, like `onClick`, `onCopy`, etc
142
+ typeof value === "function" && key.startsWith("on")
143
+ ) {
144
+ htmlElement.addEventListener(
145
+ key[2].toLocaleLowerCase() + key.slice(3),
146
+ value
147
+ );
148
+ } else {
149
+ if (typeof value === "boolean") {
150
+ if (value)
151
+ htmlElement.setAttribute(key, "");
152
+ } else {
153
+ htmlElement.setAttribute(key, value);
154
+ }
155
+ }
156
+ }
184
157
 
185
158
  // src/create-element/parse-component.ts
186
159
  function parseComponent({
187
160
  element,
188
161
  props
189
162
  }) {
190
- const componentUnmountCbs = [];
191
- const componentMountCbs = [];
163
+ const mountCbs = [];
164
+ const unmountCbs = [];
165
+ return {
166
+ velesComponentObject: true,
167
+ element,
168
+ props,
169
+ _privateMethods: {
170
+ _addMountHandler(cb) {
171
+ mountCbs.push(cb);
172
+ },
173
+ _addUnmountHandler: (cb) => {
174
+ unmountCbs.push(cb);
175
+ },
176
+ _callMountHandlers: () => {
177
+ mountCbs.forEach((cb) => cb());
178
+ },
179
+ _callUnmountHandlers: () => {
180
+ unmountCbs.forEach((cb) => cb());
181
+ }
182
+ }
183
+ };
184
+ }
185
+ function executeComponent({
186
+ element,
187
+ props
188
+ }) {
189
+ let componentUnmountCbs = [];
190
+ let componentMountCbs = [];
192
191
  const componentAPI = {
193
192
  onMount: (cb) => {
194
193
  componentMountCbs.push(cb);
@@ -199,17 +198,15 @@ function parseComponent({
199
198
  };
200
199
  addContext(componentAPI);
201
200
  const _componentTree = element(props, componentAPI);
202
- const componentTree = typeof _componentTree === "string" || !_componentTree ? {
203
- velesStringElement: true,
204
- html: document.createTextNode(
205
- typeof _componentTree === "string" ? _componentTree : ""
206
- )
207
- } : _componentTree;
201
+ const componentTree = typeof _componentTree === "string" || !_componentTree ? createTextElement(_componentTree) : _componentTree;
208
202
  popContext();
209
203
  const velesComponent = {
210
204
  velesComponent: true,
211
205
  tree: componentTree,
212
206
  _privateMethods: {
207
+ _addMountHandler(cb) {
208
+ componentMountCbs.push(cb);
209
+ },
213
210
  _addUnmountHandler: (cb) => {
214
211
  componentAPI.onUnmount(cb);
215
212
  },
@@ -223,9 +220,6 @@ function parseComponent({
223
220
  },
224
221
  _callUnmountHandlers: () => {
225
222
  componentUnmountCbs.forEach((cb) => cb());
226
- if ("_privateMethods" in velesComponent.tree) {
227
- velesComponent.tree._privateMethods._callUnmountHandlers();
228
- }
229
223
  }
230
224
  }
231
225
  };
@@ -246,23 +240,25 @@ function createElement(element, props = {}) {
246
240
  htmlElement: newElement,
247
241
  velesNode
248
242
  });
249
- let unmountHandlers = [];
250
- const callUnmountHandlers = () => {
251
- unmountHandlers.forEach((cb) => cb());
252
- unmountHandlers = [];
253
- childComponents.forEach((childComponent) => {
254
- childComponent._privateMethods._callUnmountHandlers();
255
- });
256
- };
243
+ const unmountHandlers = [];
257
244
  velesNode.html = newElement;
258
245
  velesNode.velesNode = true;
259
246
  velesNode.childComponents = childComponents;
260
247
  velesNode.phantom = phantom;
248
+ const mountHandlers = [];
261
249
  velesNode._privateMethods = {
262
- _addUnmountHandler: (cb) => {
250
+ _addMountHandler(cb) {
251
+ mountHandlers.push(cb);
252
+ },
253
+ _callMountHandlers() {
254
+ mountHandlers.forEach((cb) => cb());
255
+ },
256
+ _addUnmountHandler(cb) {
263
257
  unmountHandlers.push(cb);
264
258
  },
265
- _callUnmountHandlers: callUnmountHandlers
259
+ _callUnmountHandlers() {
260
+ unmountHandlers.forEach((cb) => cb());
261
+ }
266
262
  };
267
263
  assignAttributes({ props: otherProps, htmlElement: newElement, velesNode });
268
264
  return velesNode;
@@ -274,12 +270,19 @@ function createElement(element, props = {}) {
274
270
  );
275
271
  }
276
272
 
273
+ // src/fragment.ts
274
+ function Fragment({ children }) {
275
+ return createElement("div", {
276
+ phantom: true,
277
+ children
278
+ });
279
+ }
280
+
277
281
  export {
278
- getComponentVelesNode,
279
- callMountHandlers,
280
- identity,
281
- unique,
282
282
  onMount,
283
283
  onUnmount,
284
- createElement
284
+ createTextElement,
285
+ executeComponent,
286
+ createElement,
287
+ Fragment
285
288
  };