veles 0.0.9 → 1.0.0-alpha.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/README.md +4 -10
- package/package.json +4 -12
- package/dist/chunk-2KPVWPOL.js +0 -285
- package/dist/chunk-VW64LMPA.js +0 -928
- package/dist/index-BkD2Za6F.d.cts +0 -69
- package/dist/index-DBdVF_11.d.ts +0 -69
- package/dist/index.cjs +0 -1254
- package/dist/index.d.cts +0 -39
- package/dist/index.d.ts +0 -39
- package/dist/index.js +0 -48
- package/dist/jsx-runtime.cjs +0 -242
- package/dist/jsx-runtime.d.cts +0 -10
- package/dist/jsx-runtime.d.ts +0 -10
- package/dist/jsx-runtime.js +0 -10
- package/dist/types.d-CjiJHqth.d.cts +0 -3954
- package/dist/types.d-CjiJHqth.d.ts +0 -3954
- package/dist/utils/index.cjs +0 -1211
- package/dist/utils/index.d.cts +0 -18
- package/dist/utils/index.d.ts +0 -18
- package/dist/utils/index.js +0 -37
package/README.md
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
[](https://bundlephobia.com/result?p=veles)
|
|
5
5
|
[](https://www.npmjs.com/package/veles)
|
|
6
6
|
|
|
7
|
-
> This library is still in early stages, so the API is not 100% finalized
|
|
8
|
-
|
|
9
7
|
`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
8
|
|
|
11
9
|
## Performance
|
|
@@ -30,16 +28,16 @@ Types are installed automatically with the same package.
|
|
|
30
28
|
import { createState } from "veles";
|
|
31
29
|
|
|
32
30
|
function NameComponent() {
|
|
33
|
-
const
|
|
31
|
+
const name$ = createState("");
|
|
34
32
|
return (
|
|
35
33
|
<div>
|
|
36
34
|
<input
|
|
37
35
|
type="text"
|
|
38
36
|
name="name"
|
|
39
|
-
value={
|
|
40
|
-
onInput={(e) =>
|
|
37
|
+
value={name$.attribute()}
|
|
38
|
+
onInput={(e) => name$.set(e.target.value)}
|
|
41
39
|
/>
|
|
42
|
-
<p>{
|
|
40
|
+
<p>{name$.render()}</p>
|
|
43
41
|
</div>
|
|
44
42
|
);
|
|
45
43
|
}
|
|
@@ -55,7 +53,3 @@ This will render an input and will update the Text node dynamically, without re-
|
|
|
55
53
|
- [Differences from other frameworks](https://bloomca.github.io/veles/frameworks-difference.html)
|
|
56
54
|
|
|
57
55
|
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.
|
|
58
|
-
|
|
59
|
-
### Features
|
|
60
|
-
|
|
61
|
-
The library is under development, so some features are not available yet. Namely the TypeScript type inferring is not the best (although the library does support TypeScript), and Portals are not implemented yet.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "veles",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
4
|
"description": "UI library with main focus on performance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,15 +19,10 @@
|
|
|
19
19
|
"types": "./dist/jsx-runtime.d.ts",
|
|
20
20
|
"import": "./dist/jsx-runtime.js",
|
|
21
21
|
"require": "./dist/jsx-runtime.cjs"
|
|
22
|
-
},
|
|
23
|
-
"./utils": {
|
|
24
|
-
"types": "./dist/utils/index.d.ts",
|
|
25
|
-
"import": "./dist/utils/index.js",
|
|
26
|
-
"require": "./dist/utils/index.cjs"
|
|
27
22
|
}
|
|
28
23
|
},
|
|
29
24
|
"scripts": {
|
|
30
|
-
"test": "
|
|
25
|
+
"test": "vitest run",
|
|
31
26
|
"build": "tsup",
|
|
32
27
|
"ts-compile-check": "tsc -p tsconfig.json"
|
|
33
28
|
},
|
|
@@ -50,11 +45,8 @@
|
|
|
50
45
|
"@testing-library/dom": "^10.1.0",
|
|
51
46
|
"@testing-library/jest-dom": "^6.4.5",
|
|
52
47
|
"@testing-library/user-event": "^14.5.2",
|
|
53
|
-
"@types/jest": "^29.5.12",
|
|
54
|
-
"jest": "^29.7.0",
|
|
55
|
-
"jest-environment-jsdom": "^29.7.0",
|
|
56
48
|
"jsdom": "^24.0.0",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
49
|
+
"tsup": "^8.0.2",
|
|
50
|
+
"vitest": "^3.2.4"
|
|
59
51
|
}
|
|
60
52
|
}
|
package/dist/chunk-2KPVWPOL.js
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
// src/hooks/lifecycle.ts
|
|
2
|
-
var contextStack = [];
|
|
3
|
-
var currentContext = null;
|
|
4
|
-
function addContext(newContext) {
|
|
5
|
-
contextStack.push(newContext);
|
|
6
|
-
currentContext = newContext;
|
|
7
|
-
}
|
|
8
|
-
function popContext() {
|
|
9
|
-
contextStack.pop();
|
|
10
|
-
currentContext = contextStack[contextStack.length - 1];
|
|
11
|
-
}
|
|
12
|
-
function onMount(cb) {
|
|
13
|
-
if (currentContext) {
|
|
14
|
-
currentContext.onMount(cb);
|
|
15
|
-
} else {
|
|
16
|
-
console.error("missing current context");
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function onUnmount(cb) {
|
|
20
|
-
if (currentContext) {
|
|
21
|
-
currentContext.onUnmount(cb);
|
|
22
|
-
} else {
|
|
23
|
-
console.error("missing current context");
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
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
|
-
}
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// src/create-element/parse-children.ts
|
|
54
|
-
function parseChildren({
|
|
55
|
-
children,
|
|
56
|
-
htmlElement,
|
|
57
|
-
velesNode
|
|
58
|
-
}) {
|
|
59
|
-
const childComponents = [];
|
|
60
|
-
if (children === void 0 || children === null) {
|
|
61
|
-
return childComponents;
|
|
62
|
-
}
|
|
63
|
-
let lastInsertedNode = null;
|
|
64
|
-
(Array.isArray(children) ? children : [children]).forEach(
|
|
65
|
-
(childComponent) => {
|
|
66
|
-
if (typeof childComponent === "string") {
|
|
67
|
-
const textNode = createTextElement(childComponent);
|
|
68
|
-
htmlElement.append(textNode.html);
|
|
69
|
-
lastInsertedNode = textNode.html;
|
|
70
|
-
childComponents.push(textNode);
|
|
71
|
-
} else if (typeof childComponent === "number") {
|
|
72
|
-
const textNode = createTextElement(String(childComponent));
|
|
73
|
-
htmlElement.append(textNode.html);
|
|
74
|
-
lastInsertedNode = textNode.html;
|
|
75
|
-
childComponents.push(textNode);
|
|
76
|
-
} else if (typeof childComponent === "object" && childComponent && "velesNode" in childComponent && (childComponent == null ? void 0 : childComponent.velesNode)) {
|
|
77
|
-
if (childComponent.phantom) {
|
|
78
|
-
childComponent.childComponents.forEach((childComponentofPhantom) => {
|
|
79
|
-
if ("velesNode" in childComponentofPhantom) {
|
|
80
|
-
htmlElement.append(childComponentofPhantom.html);
|
|
81
|
-
childComponentofPhantom.parentVelesElement = velesNode;
|
|
82
|
-
lastInsertedNode = childComponentofPhantom.html;
|
|
83
|
-
} else if ("velesStringElement" in childComponentofPhantom) {
|
|
84
|
-
const velesElementNode = childComponentofPhantom;
|
|
85
|
-
if (!velesElementNode) {
|
|
86
|
-
console.error("can't find HTML tree in a component chain");
|
|
87
|
-
} else {
|
|
88
|
-
htmlElement.append(velesElementNode.html);
|
|
89
|
-
lastInsertedNode = velesElementNode.html;
|
|
90
|
-
velesElementNode.parentVelesElement = velesNode;
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
childComponent.parentVelesElement = velesNode;
|
|
96
|
-
childComponents.push(childComponent);
|
|
97
|
-
} else {
|
|
98
|
-
htmlElement.append(childComponent.html);
|
|
99
|
-
childComponent.parentVelesElement = velesNode;
|
|
100
|
-
childComponents.push(childComponent);
|
|
101
|
-
lastInsertedNode = childComponent.html;
|
|
102
|
-
}
|
|
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;
|
|
108
|
-
} else if (typeof childComponent === "object" && childComponent && "velesStringElement" in childComponent && (childComponent == null ? void 0 : childComponent.velesStringElement)) {
|
|
109
|
-
htmlElement.append(childComponent.html);
|
|
110
|
-
childComponent.parentVelesElement = velesNode;
|
|
111
|
-
childComponents.push(childComponent);
|
|
112
|
-
lastInsertedNode = childComponent.html;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
);
|
|
116
|
-
return childComponents;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// src/create-element/assign-attributes.ts
|
|
120
|
-
function assignAttributes({
|
|
121
|
-
props,
|
|
122
|
-
htmlElement,
|
|
123
|
-
velesNode
|
|
124
|
-
}) {
|
|
125
|
-
Object.entries(props).forEach(([key, value]) => {
|
|
126
|
-
const isFunction = typeof value === "function";
|
|
127
|
-
if (isFunction && value.velesAttribute === true) {
|
|
128
|
-
const attributeValue = value(htmlElement, key, velesNode);
|
|
129
|
-
assignAttribute({ key, value: attributeValue, htmlElement });
|
|
130
|
-
} else {
|
|
131
|
-
assignAttribute({ key, value, htmlElement });
|
|
132
|
-
}
|
|
133
|
-
});
|
|
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(key.slice(2).toLocaleLowerCase(), value);
|
|
145
|
-
} else {
|
|
146
|
-
if (typeof value === "boolean") {
|
|
147
|
-
if (value)
|
|
148
|
-
htmlElement.setAttribute(key, "");
|
|
149
|
-
} else {
|
|
150
|
-
htmlElement.setAttribute(key, value);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// src/create-element/parse-component.ts
|
|
156
|
-
function parseComponent({
|
|
157
|
-
element,
|
|
158
|
-
props
|
|
159
|
-
}) {
|
|
160
|
-
const mountCbs = [];
|
|
161
|
-
const unmountCbs = [];
|
|
162
|
-
return {
|
|
163
|
-
velesComponentObject: true,
|
|
164
|
-
element,
|
|
165
|
-
props,
|
|
166
|
-
_privateMethods: {
|
|
167
|
-
_addMountHandler(cb) {
|
|
168
|
-
mountCbs.push(cb);
|
|
169
|
-
},
|
|
170
|
-
_addUnmountHandler: (cb) => {
|
|
171
|
-
unmountCbs.push(cb);
|
|
172
|
-
},
|
|
173
|
-
_callMountHandlers: () => {
|
|
174
|
-
mountCbs.forEach((cb) => cb());
|
|
175
|
-
},
|
|
176
|
-
_callUnmountHandlers: () => {
|
|
177
|
-
unmountCbs.forEach((cb) => cb());
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function executeComponent({
|
|
183
|
-
element,
|
|
184
|
-
props
|
|
185
|
-
}) {
|
|
186
|
-
let componentUnmountCbs = [];
|
|
187
|
-
let componentMountCbs = [];
|
|
188
|
-
const componentAPI = {
|
|
189
|
-
onMount: (cb) => {
|
|
190
|
-
componentMountCbs.push(cb);
|
|
191
|
-
},
|
|
192
|
-
onUnmount: (cb) => {
|
|
193
|
-
componentUnmountCbs.push(cb);
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
addContext(componentAPI);
|
|
197
|
-
const _componentTree = element(props, componentAPI);
|
|
198
|
-
const componentTree = typeof _componentTree === "string" || !_componentTree ? createTextElement(_componentTree) : _componentTree;
|
|
199
|
-
popContext();
|
|
200
|
-
const velesComponent = {
|
|
201
|
-
velesComponent: true,
|
|
202
|
-
tree: componentTree,
|
|
203
|
-
_privateMethods: {
|
|
204
|
-
_addMountHandler(cb) {
|
|
205
|
-
componentMountCbs.push(cb);
|
|
206
|
-
},
|
|
207
|
-
_addUnmountHandler: (cb) => {
|
|
208
|
-
componentAPI.onUnmount(cb);
|
|
209
|
-
},
|
|
210
|
-
_callMountHandlers: () => {
|
|
211
|
-
componentMountCbs.forEach((cb) => {
|
|
212
|
-
const mountCbResult = cb();
|
|
213
|
-
if (typeof mountCbResult === "function") {
|
|
214
|
-
componentAPI.onUnmount(mountCbResult);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
},
|
|
218
|
-
_callUnmountHandlers: () => {
|
|
219
|
-
componentUnmountCbs.forEach((cb) => cb());
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
return velesComponent;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// src/create-element/create-element.ts
|
|
227
|
-
function createElement(element, props = {}) {
|
|
228
|
-
if (typeof element === "string") {
|
|
229
|
-
const { children, ref, phantom = false, ...otherProps } = props;
|
|
230
|
-
const newElement = document.createElement(element);
|
|
231
|
-
const velesNode = {};
|
|
232
|
-
if (ref == null ? void 0 : ref.velesRef) {
|
|
233
|
-
ref.current = newElement;
|
|
234
|
-
}
|
|
235
|
-
const childComponents = parseChildren({
|
|
236
|
-
children,
|
|
237
|
-
htmlElement: newElement,
|
|
238
|
-
velesNode
|
|
239
|
-
});
|
|
240
|
-
const unmountHandlers = [];
|
|
241
|
-
velesNode.html = newElement;
|
|
242
|
-
velesNode.velesNode = true;
|
|
243
|
-
velesNode.childComponents = childComponents;
|
|
244
|
-
velesNode.phantom = phantom;
|
|
245
|
-
const mountHandlers = [];
|
|
246
|
-
velesNode._privateMethods = {
|
|
247
|
-
_addMountHandler(cb) {
|
|
248
|
-
mountHandlers.push(cb);
|
|
249
|
-
},
|
|
250
|
-
_callMountHandlers() {
|
|
251
|
-
mountHandlers.forEach((cb) => cb());
|
|
252
|
-
},
|
|
253
|
-
_addUnmountHandler(cb) {
|
|
254
|
-
unmountHandlers.push(cb);
|
|
255
|
-
},
|
|
256
|
-
_callUnmountHandlers() {
|
|
257
|
-
unmountHandlers.forEach((cb) => cb());
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
assignAttributes({ props: otherProps, htmlElement: newElement, velesNode });
|
|
261
|
-
return velesNode;
|
|
262
|
-
} else if (typeof element === "function") {
|
|
263
|
-
return parseComponent({ element, props });
|
|
264
|
-
}
|
|
265
|
-
throw new Error(
|
|
266
|
-
"Veles createElement expects a valid DOM string or another component"
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// src/fragment.ts
|
|
271
|
-
function Fragment({ children }) {
|
|
272
|
-
return createElement("div", {
|
|
273
|
-
phantom: true,
|
|
274
|
-
children
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
export {
|
|
279
|
-
onMount,
|
|
280
|
-
onUnmount,
|
|
281
|
-
createTextElement,
|
|
282
|
-
executeComponent,
|
|
283
|
-
createElement,
|
|
284
|
-
Fragment
|
|
285
|
-
};
|