@threlte/flex 0.0.8 → 0.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/dist/Box/Box.svelte
CHANGED
|
@@ -23,6 +23,8 @@ parentNodeContext?.insertNode(node, order);
|
|
|
23
23
|
onDestroy(() => {
|
|
24
24
|
parentNodeContext?.removeNode(node);
|
|
25
25
|
});
|
|
26
|
+
// update the order of the node
|
|
27
|
+
$: parentNodeContext?.updateNodeOrder(node, order);
|
|
26
28
|
addNode(node, group, $$restProps);
|
|
27
29
|
updateNodeProps(node, { ...classParser?.(_class, {}), ...$$restProps }, true);
|
|
28
30
|
$: updateNodeProps(node, { ...classParser?.(_class, {}), ...$$restProps });
|
|
@@ -22,8 +22,6 @@ export { _class as class };
|
|
|
22
22
|
const dispatch = createRawEventDispatcher();
|
|
23
23
|
const rootGroup = new Group();
|
|
24
24
|
rootGroup.userData.isNode = true;
|
|
25
|
-
const rootNode = yoga.Node.create();
|
|
26
|
-
createNodeContext(rootNode);
|
|
27
25
|
const boundingBox = new Box3();
|
|
28
26
|
const vec3 = new Vector3();
|
|
29
27
|
/**
|
|
@@ -115,6 +113,8 @@ const flexContext = createFlexContext({
|
|
|
115
113
|
reflow,
|
|
116
114
|
classParser
|
|
117
115
|
});
|
|
116
|
+
const rootNode = yoga.Node.create();
|
|
117
|
+
createNodeContext(rootNode);
|
|
118
118
|
const { mainAxis, crossAxis, depthAxis } = flexContext;
|
|
119
119
|
$: rootNode.setWidth(width * scaleFactor), rootNode.setHeight(height * scaleFactor);
|
|
120
120
|
// prettier-ignore
|
package/dist/nodes/context.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Node } from 'yoga-layout';
|
|
|
2
2
|
export type NodeContext = {
|
|
3
3
|
insertNode: (childNode: Node, order?: number) => void;
|
|
4
4
|
removeNode: (childNode: Node) => void;
|
|
5
|
+
updateNodeOrder: (childNode: Node, order?: number) => void;
|
|
5
6
|
};
|
|
6
7
|
export declare const nodeContextName = "__threlte-node";
|
|
7
8
|
export declare const createNodeContext: (node: Node) => NodeContext | undefined;
|
package/dist/nodes/context.js
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
import { getContext, setContext } from 'svelte';
|
|
2
|
+
import { useReflow } from '..';
|
|
2
3
|
export const nodeContextName = '__threlte-node';
|
|
3
4
|
export const createNodeContext = (node) => {
|
|
5
|
+
const reflow = useReflow();
|
|
6
|
+
/** Set to keep track of all child nodes */
|
|
4
7
|
const childNodes = new Set();
|
|
8
|
+
/** Map to keep track of the requested order of nodes */
|
|
5
9
|
const childNodesOrderMap = new Map();
|
|
6
10
|
const parentNodeContext = getContext(nodeContextName);
|
|
11
|
+
const removeAllChildNodes = () => {
|
|
12
|
+
childNodes.forEach((childNode) => {
|
|
13
|
+
node.removeChild(childNode);
|
|
14
|
+
});
|
|
15
|
+
};
|
|
7
16
|
setContext(nodeContextName, {
|
|
8
17
|
insertNode(childNode, order) {
|
|
9
18
|
// we want to keep track of all child nodes
|
|
10
19
|
childNodes.add(childNode);
|
|
11
|
-
// Additionally, we need to keep track of child nodes that need to be
|
|
20
|
+
// Additionally, we need to keep track of child nodes that need to be
|
|
21
|
+
// inserted at a specific order
|
|
12
22
|
if (order !== undefined) {
|
|
13
23
|
childNodesOrderMap.set(childNode, {
|
|
14
24
|
requestedOrder: order
|
|
15
25
|
});
|
|
16
26
|
}
|
|
17
27
|
if (childNodesOrderMap.size) {
|
|
18
|
-
// we need to sort the child nodes by their requested order. We leave
|
|
28
|
+
// we need to sort the child nodes by their requested order. We leave
|
|
29
|
+
// the nodes that don't have a requested order untouched.
|
|
19
30
|
const sorted = Array.from(childNodes)
|
|
20
31
|
.map((node, index) => {
|
|
21
32
|
return {
|
|
@@ -25,10 +36,9 @@ export const createNodeContext = (node) => {
|
|
|
25
36
|
})
|
|
26
37
|
.sort((a, b) => a.order - b.order)
|
|
27
38
|
.map(({ node }) => node);
|
|
28
|
-
// Then we need to remove all child nodes from the node and insert them
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
});
|
|
39
|
+
// Then we need to remove all child nodes from the node and insert them
|
|
40
|
+
// in the correct order.
|
|
41
|
+
removeAllChildNodes();
|
|
32
42
|
sorted.forEach((childNode, index) => {
|
|
33
43
|
node.insertChild(childNode, index);
|
|
34
44
|
});
|
|
@@ -36,11 +46,57 @@ export const createNodeContext = (node) => {
|
|
|
36
46
|
else {
|
|
37
47
|
node.insertChild(childNode, node.getChildCount());
|
|
38
48
|
}
|
|
49
|
+
reflow();
|
|
39
50
|
},
|
|
40
51
|
removeNode(childNode) {
|
|
41
52
|
node.removeChild(childNode);
|
|
42
53
|
childNodes.delete(childNode);
|
|
43
54
|
childNodesOrderMap.delete(childNode);
|
|
55
|
+
reflow();
|
|
56
|
+
},
|
|
57
|
+
updateNodeOrder(childNode, order) {
|
|
58
|
+
let update = false;
|
|
59
|
+
const oldOrder = childNodesOrderMap.get(childNode)?.requestedOrder;
|
|
60
|
+
if (order === undefined) {
|
|
61
|
+
// if the order is undefined, we remove the node from the map
|
|
62
|
+
if (oldOrder !== undefined) {
|
|
63
|
+
childNodesOrderMap.delete(childNode);
|
|
64
|
+
update = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// if the order is defined, we update the node in the map
|
|
69
|
+
const oldOrder = childNodesOrderMap.get(childNode)?.requestedOrder;
|
|
70
|
+
if (oldOrder !== order) {
|
|
71
|
+
childNodesOrderMap.set(childNode, {
|
|
72
|
+
requestedOrder: order
|
|
73
|
+
});
|
|
74
|
+
update = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// if there's no update, return early
|
|
78
|
+
if (!update)
|
|
79
|
+
return;
|
|
80
|
+
// remove all child nodes from the node
|
|
81
|
+
removeAllChildNodes();
|
|
82
|
+
// we need to sort the child nodes by their requested order. We leave the
|
|
83
|
+
// nodes that don't have a requested order untouched.
|
|
84
|
+
const sorted = Array.from(childNodes)
|
|
85
|
+
.map((node, index) => {
|
|
86
|
+
return {
|
|
87
|
+
order: childNodesOrderMap.get(node)?.requestedOrder ?? index,
|
|
88
|
+
node
|
|
89
|
+
};
|
|
90
|
+
})
|
|
91
|
+
.sort((a, b) => a.order - b.order)
|
|
92
|
+
.map(({ node }) => node);
|
|
93
|
+
// Then we need to remove all child nodes from the node and insert them in
|
|
94
|
+
// the correct order.
|
|
95
|
+
removeAllChildNodes();
|
|
96
|
+
sorted.forEach((childNode, index) => {
|
|
97
|
+
node.insertChild(childNode, index);
|
|
98
|
+
});
|
|
99
|
+
reflow();
|
|
44
100
|
}
|
|
45
101
|
});
|
|
46
102
|
return parentNodeContext;
|
|
@@ -1,124 +1,143 @@
|
|
|
1
1
|
import { createClassParser } from './createClassParser';
|
|
2
|
+
const parseNumericOrAutoOrPercentageValue = (value) => {
|
|
3
|
+
if (value === 'auto') {
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
else if (value.endsWith('%')) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
else if (value === 'full') {
|
|
10
|
+
return '100%';
|
|
11
|
+
}
|
|
12
|
+
else if (value.match(/^\d+\/\d+$/)) {
|
|
13
|
+
const [width, height] = value.split('/');
|
|
14
|
+
const percentage = Math.round((Number(width) / Number(height)) * 100);
|
|
15
|
+
return `${percentage}%`;
|
|
16
|
+
}
|
|
17
|
+
return Number(value);
|
|
18
|
+
};
|
|
19
|
+
const parseNumericOrPercentageValue = (value) => {
|
|
20
|
+
if (value.endsWith('%')) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
else if (value === 'full') {
|
|
24
|
+
return '100%';
|
|
25
|
+
}
|
|
26
|
+
else if (value.match(/^\d+\/\d+$/)) {
|
|
27
|
+
const [width, height] = value.split('/');
|
|
28
|
+
const percentage = Math.round((Number(width) / Number(height)) * 100);
|
|
29
|
+
return `${percentage}%`;
|
|
30
|
+
}
|
|
31
|
+
return Number(value);
|
|
32
|
+
};
|
|
2
33
|
export const tailwindParser = createClassParser((string, props) => {
|
|
3
34
|
const classes = string.split(' ').map((className) => className.trim());
|
|
4
|
-
const parseNumericOrAutoOrPercentageValue = (value) => {
|
|
5
|
-
if (value === 'auto') {
|
|
6
|
-
return value;
|
|
7
|
-
}
|
|
8
|
-
else if (value.endsWith('%')) {
|
|
9
|
-
return value;
|
|
10
|
-
}
|
|
11
|
-
else if (value === 'full') {
|
|
12
|
-
return '100%';
|
|
13
|
-
}
|
|
14
|
-
else if (value.match(/^\d+\/\d+$/)) {
|
|
15
|
-
const [width, height] = value.split('/');
|
|
16
|
-
const percentage = Math.round((Number(width) / Number(height)) * 100);
|
|
17
|
-
return `${percentage}%`;
|
|
18
|
-
}
|
|
19
|
-
return Number(value);
|
|
20
|
-
};
|
|
21
|
-
const parseNumericOrPercentageValue = (value) => {
|
|
22
|
-
if (value.endsWith('%')) {
|
|
23
|
-
return value;
|
|
24
|
-
}
|
|
25
|
-
else if (value === 'full') {
|
|
26
|
-
return '100%';
|
|
27
|
-
}
|
|
28
|
-
else if (value.match(/^\d+\/\d+$/)) {
|
|
29
|
-
const [width, height] = value.split('/');
|
|
30
|
-
const percentage = Math.round((Number(width) / Number(height)) * 100);
|
|
31
|
-
return `${percentage}%`;
|
|
32
|
-
}
|
|
33
|
-
return Number(value);
|
|
34
|
-
};
|
|
35
35
|
classes.forEach((className) => {
|
|
36
36
|
// padding
|
|
37
37
|
if (className.startsWith('p-')) {
|
|
38
38
|
const [, value] = className.split('-');
|
|
39
39
|
props.padding = parseNumericOrPercentageValue(value);
|
|
40
|
+
return;
|
|
40
41
|
}
|
|
41
42
|
if (className.startsWith('px-')) {
|
|
42
43
|
const [, value] = className.split('-');
|
|
43
44
|
props.paddingLeft = parseNumericOrPercentageValue(value);
|
|
44
45
|
props.paddingRight = parseNumericOrPercentageValue(value);
|
|
46
|
+
return;
|
|
45
47
|
}
|
|
46
48
|
if (className.startsWith('py-')) {
|
|
47
49
|
const [, value] = className.split('-');
|
|
48
50
|
props.paddingTop = parseNumericOrPercentageValue(value);
|
|
49
51
|
props.paddingBottom = parseNumericOrPercentageValue(value);
|
|
52
|
+
return;
|
|
50
53
|
}
|
|
51
54
|
if (className.startsWith('pt-')) {
|
|
52
55
|
const [, value] = className.split('-');
|
|
53
56
|
props.paddingTop = parseNumericOrPercentageValue(value);
|
|
57
|
+
return;
|
|
54
58
|
}
|
|
55
59
|
if (className.startsWith('pr-')) {
|
|
56
60
|
const [, value] = className.split('-');
|
|
57
61
|
props.paddingRight = parseNumericOrPercentageValue(value);
|
|
62
|
+
return;
|
|
58
63
|
}
|
|
59
64
|
if (className.startsWith('pb-')) {
|
|
60
65
|
const [, value] = className.split('-');
|
|
61
66
|
props.paddingBottom = parseNumericOrPercentageValue(value);
|
|
67
|
+
return;
|
|
62
68
|
}
|
|
63
69
|
if (className.startsWith('pl-')) {
|
|
64
70
|
const [, value] = className.split('-');
|
|
65
71
|
props.paddingLeft = parseNumericOrPercentageValue(value);
|
|
72
|
+
return;
|
|
66
73
|
}
|
|
67
74
|
// margin
|
|
68
75
|
if (className.startsWith('m-')) {
|
|
69
76
|
const [, value] = className.split('-');
|
|
70
77
|
props.margin = parseNumericOrAutoOrPercentageValue(value);
|
|
78
|
+
return;
|
|
71
79
|
}
|
|
72
80
|
if (className.startsWith('mx-')) {
|
|
73
81
|
const [, value] = className.split('-');
|
|
74
82
|
props.marginLeft = parseNumericOrAutoOrPercentageValue(value);
|
|
75
83
|
props.marginRight = parseNumericOrAutoOrPercentageValue(value);
|
|
84
|
+
return;
|
|
76
85
|
}
|
|
77
86
|
if (className.startsWith('my-')) {
|
|
78
87
|
const [, value] = className.split('-');
|
|
79
88
|
props.marginTop = parseNumericOrAutoOrPercentageValue(value);
|
|
80
89
|
props.marginBottom = parseNumericOrAutoOrPercentageValue(value);
|
|
90
|
+
return;
|
|
81
91
|
}
|
|
82
92
|
if (className.startsWith('mt-')) {
|
|
83
93
|
const [, value] = className.split('-');
|
|
84
94
|
props.marginTop = parseNumericOrAutoOrPercentageValue(value);
|
|
95
|
+
return;
|
|
85
96
|
}
|
|
86
97
|
if (className.startsWith('mr-')) {
|
|
87
98
|
const [, value] = className.split('-');
|
|
88
99
|
props.marginRight = parseNumericOrAutoOrPercentageValue(value);
|
|
100
|
+
return;
|
|
89
101
|
}
|
|
90
102
|
if (className.startsWith('mb-')) {
|
|
91
103
|
const [, value] = className.split('-');
|
|
92
104
|
props.marginBottom = parseNumericOrAutoOrPercentageValue(value);
|
|
105
|
+
return;
|
|
93
106
|
}
|
|
94
107
|
if (className.startsWith('ml-')) {
|
|
95
108
|
const [, value] = className.split('-');
|
|
96
109
|
props.marginLeft = parseNumericOrAutoOrPercentageValue(value);
|
|
110
|
+
return;
|
|
97
111
|
}
|
|
98
112
|
// width
|
|
99
113
|
if (className.startsWith('w-')) {
|
|
100
114
|
const [, value] = className.split('-');
|
|
101
115
|
props.width = parseNumericOrAutoOrPercentageValue(value);
|
|
116
|
+
return;
|
|
102
117
|
}
|
|
103
118
|
// height
|
|
104
119
|
if (className.startsWith('h-')) {
|
|
105
120
|
const [, value] = className.split('-');
|
|
106
121
|
props.height = parseNumericOrAutoOrPercentageValue(value);
|
|
122
|
+
return;
|
|
107
123
|
}
|
|
108
124
|
// flex-basis
|
|
109
125
|
if (className.startsWith('basis-')) {
|
|
110
126
|
const [, value] = className.split('-');
|
|
111
127
|
props.flexBasis = parseNumericOrAutoOrPercentageValue(value);
|
|
128
|
+
return;
|
|
112
129
|
}
|
|
113
130
|
// flex-grow
|
|
114
131
|
if (className.startsWith('grow-')) {
|
|
115
132
|
const [, value] = className.split('-');
|
|
116
133
|
props.flexGrow = Number(value);
|
|
134
|
+
return;
|
|
117
135
|
}
|
|
118
136
|
// flex-shrink
|
|
119
137
|
if (className.startsWith('shrink-')) {
|
|
120
138
|
const [, value] = className.split('-');
|
|
121
139
|
props.flexShrink = Number(value);
|
|
140
|
+
return;
|
|
122
141
|
}
|
|
123
142
|
// flex-direction
|
|
124
143
|
if (className.startsWith('flex-')) {
|
|
@@ -150,6 +169,7 @@ export const tailwindParser = createClassParser((string, props) => {
|
|
|
150
169
|
const [, value] = className.split('-');
|
|
151
170
|
props.flex = Number(value);
|
|
152
171
|
}
|
|
172
|
+
return;
|
|
153
173
|
}
|
|
154
174
|
// justify-content
|
|
155
175
|
if (className.startsWith('justify-')) {
|
|
@@ -173,6 +193,7 @@ export const tailwindParser = createClassParser((string, props) => {
|
|
|
173
193
|
props.justifyContent = 'SpaceEvenly';
|
|
174
194
|
break;
|
|
175
195
|
}
|
|
196
|
+
return;
|
|
176
197
|
}
|
|
177
198
|
// align-items
|
|
178
199
|
if (className.startsWith('items-')) {
|
|
@@ -193,6 +214,7 @@ export const tailwindParser = createClassParser((string, props) => {
|
|
|
193
214
|
props.alignItems = 'Stretch';
|
|
194
215
|
break;
|
|
195
216
|
}
|
|
217
|
+
return;
|
|
196
218
|
}
|
|
197
219
|
// align-content
|
|
198
220
|
if (className.startsWith('content-')) {
|
|
@@ -222,6 +244,7 @@ export const tailwindParser = createClassParser((string, props) => {
|
|
|
222
244
|
props.alignContent = 'Baseline';
|
|
223
245
|
break;
|
|
224
246
|
}
|
|
247
|
+
return;
|
|
225
248
|
}
|
|
226
249
|
// align-self
|
|
227
250
|
if (className.startsWith('self-')) {
|
|
@@ -245,36 +268,44 @@ export const tailwindParser = createClassParser((string, props) => {
|
|
|
245
268
|
props.alignSelf = 'Baseline';
|
|
246
269
|
break;
|
|
247
270
|
}
|
|
271
|
+
return;
|
|
248
272
|
}
|
|
249
273
|
// Gaps
|
|
250
274
|
if (className.startsWith('gap-x-')) {
|
|
251
275
|
const [, value] = className.split('-');
|
|
252
276
|
props.gapColumn = Number(value);
|
|
277
|
+
return;
|
|
253
278
|
}
|
|
254
279
|
else if (className.startsWith('gap-y-')) {
|
|
255
280
|
const [, value] = className.split('-');
|
|
256
281
|
props.gapRow = Number(value);
|
|
282
|
+
return;
|
|
257
283
|
}
|
|
258
284
|
else if (className.startsWith('gap-')) {
|
|
259
285
|
const [, value] = className.split('-');
|
|
260
286
|
props.gap = Number(value);
|
|
287
|
+
return;
|
|
261
288
|
}
|
|
262
289
|
// Position
|
|
263
290
|
if (className.startsWith('top-')) {
|
|
264
291
|
const [, value] = className.split('-');
|
|
265
292
|
props.top = parseNumericOrPercentageValue(value);
|
|
293
|
+
return;
|
|
266
294
|
}
|
|
267
295
|
if (className.startsWith('right-')) {
|
|
268
296
|
const [, value] = className.split('-');
|
|
269
297
|
props.right = parseNumericOrPercentageValue(value);
|
|
298
|
+
return;
|
|
270
299
|
}
|
|
271
300
|
if (className.startsWith('bottom-')) {
|
|
272
301
|
const [, value] = className.split('-');
|
|
273
302
|
props.bottom = parseNumericOrPercentageValue(value);
|
|
303
|
+
return;
|
|
274
304
|
}
|
|
275
305
|
if (className.startsWith('left-')) {
|
|
276
306
|
const [, value] = className.split('-');
|
|
277
307
|
props.left = parseNumericOrPercentageValue(value);
|
|
308
|
+
return;
|
|
278
309
|
}
|
|
279
310
|
// aspect ratio
|
|
280
311
|
if (className.startsWith('aspect-')) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threlte/flex",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"author": "Grischa Erbe <hello@legrisch.com> (https://legrisch.com)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"devDependencies": {
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"tslib": "^2.4.1",
|
|
28
28
|
"typescript": "^5.0.0",
|
|
29
29
|
"vite": "^4.3.6",
|
|
30
|
-
"@threlte/core": "6.0
|
|
31
|
-
"@threlte/extras": "
|
|
30
|
+
"@threlte/core": "6.1.0",
|
|
31
|
+
"@threlte/extras": "7.3.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"mitt": "^3.0.1",
|