@threlte/flex 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/dist/Box/Box.svelte +10 -4
- package/dist/Box/Box.svelte.d.ts +1 -1
- package/dist/Flex/InnerFlex.svelte +13 -23
- package/dist/lib/propsChanged.d.ts +8 -0
- package/dist/lib/propsChanged.js +26 -0
- package/dist/nodes/context.d.ts +3 -5
- package/dist/nodes/context.js +39 -23
- package/package.json +1 -1
package/dist/Box/Box.svelte
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { onDestroy } from 'svelte';
|
|
3
3
|
import { Group } from 'three';
|
|
4
4
|
import { useFlex } from '../Flex/context';
|
|
5
|
-
import { createNodeContext } from '../nodes/context';
|
|
6
5
|
import { createUseDimensionsContext } from '../hooks/useDimensions';
|
|
6
|
+
import { createNodeContext } from '../nodes/context';
|
|
7
7
|
export let order = undefined;
|
|
8
8
|
let _class = '';
|
|
9
9
|
export { _class as class };
|
|
@@ -13,10 +13,16 @@ const dispatch = createRawEventDispatcher();
|
|
|
13
13
|
*/
|
|
14
14
|
const dimensionsContext = createUseDimensionsContext();
|
|
15
15
|
const { scaleFactor, onEvent, addNode, removeNode, updateNodeProps, mainAxis, crossAxis, depthAxis, classParser, reflow } = useFlex();
|
|
16
|
-
|
|
17
|
-
export const contentGroup = new Group();
|
|
16
|
+
const group = new Group();
|
|
18
17
|
group.userData.isNode = true;
|
|
19
|
-
|
|
18
|
+
const contentGroup = new Group();
|
|
19
|
+
const { yoga } = useFlex();
|
|
20
|
+
const node = yoga.Node.create();
|
|
21
|
+
const parentNodeContext = createNodeContext(node);
|
|
22
|
+
parentNodeContext?.insertNode(node, order);
|
|
23
|
+
onDestroy(() => {
|
|
24
|
+
parentNodeContext?.removeNode(node);
|
|
25
|
+
});
|
|
20
26
|
addNode(node, group, $$restProps);
|
|
21
27
|
updateNodeProps(node, { ...classParser?.(_class, {}), ...$$restProps }, true);
|
|
22
28
|
$: updateNodeProps(node, { ...classParser?.(_class, {}), ...$$restProps });
|
package/dist/Box/Box.svelte.d.ts
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
import { onDestroy } from 'svelte';
|
|
3
3
|
import { Box3, Group, Vector3 } from 'three';
|
|
4
4
|
import { Direction } from 'yoga-layout';
|
|
5
|
+
import { createUseDimensionsContext } from '../hooks/useDimensions';
|
|
5
6
|
import { getDepthAxis } from '../lib/getDepthAxis';
|
|
6
7
|
import { getOrientedBoundingBoxSize } from '../lib/getOrientedBoundingBoxSize';
|
|
7
8
|
import { getRootShift } from '../lib/getRootShift';
|
|
8
9
|
import { applyNodeProps } from '../lib/props';
|
|
10
|
+
import { propsChanged } from '../lib/propsChanged';
|
|
9
11
|
import { createNodeContext } from '../nodes/context';
|
|
10
12
|
import { createFlexContext } from './context';
|
|
11
|
-
import { createUseDimensionsContext } from '../hooks/useDimensions';
|
|
12
13
|
export let yoga;
|
|
13
14
|
export let width = 1;
|
|
14
15
|
export let height = 1;
|
|
@@ -21,6 +22,8 @@ export { _class as class };
|
|
|
21
22
|
const dispatch = createRawEventDispatcher();
|
|
22
23
|
const rootGroup = new Group();
|
|
23
24
|
rootGroup.userData.isNode = true;
|
|
25
|
+
const rootNode = yoga.Node.create();
|
|
26
|
+
createNodeContext(rootNode);
|
|
24
27
|
const boundingBox = new Box3();
|
|
25
28
|
const vec3 = new Vector3();
|
|
26
29
|
/**
|
|
@@ -90,25 +93,13 @@ const flexContext = createFlexContext({
|
|
|
90
93
|
},
|
|
91
94
|
updateNodeProps(node, props, force = false) {
|
|
92
95
|
const nodeData = flexContext.nodes.get(node);
|
|
93
|
-
if (!nodeData)
|
|
94
|
-
return;
|
|
95
96
|
// Updating the props can be forced and is done so on the initial call.
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const previousKeys = Object.keys(nodeData.props);
|
|
102
|
-
const currentKeys = Object.keys(props);
|
|
103
|
-
if (previousKeys.length === currentKeys.length &&
|
|
104
|
-
currentKeys.every((key) => previousKeys.includes(key)) &&
|
|
105
|
-
previousKeys.every((key) => nodeData.props[key] === props[key])) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
97
|
+
if (force || propsChanged(node, props)) {
|
|
98
|
+
applyNodeProps(node, props, scaleFactor);
|
|
99
|
+
reflow();
|
|
100
|
+
if (nodeData)
|
|
101
|
+
nodeData.props = props;
|
|
108
102
|
}
|
|
109
|
-
applyNodeProps(node, props, scaleFactor);
|
|
110
|
-
nodeData.props = props;
|
|
111
|
-
reflow();
|
|
112
103
|
},
|
|
113
104
|
removeNode(node) {
|
|
114
105
|
flexContext.nodes.delete(node);
|
|
@@ -125,12 +116,11 @@ const flexContext = createFlexContext({
|
|
|
125
116
|
classParser
|
|
126
117
|
});
|
|
127
118
|
const { mainAxis, crossAxis, depthAxis } = flexContext;
|
|
128
|
-
const { node: rootNode } = createNodeContext();
|
|
129
119
|
$: rootNode.setWidth(width * scaleFactor), rootNode.setHeight(height * scaleFactor);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
120
|
+
// prettier-ignore
|
|
121
|
+
flexContext.updateNodeProps(rootNode, { ...classParser?.(_class, {}), ...$$restProps }, true);
|
|
122
|
+
// prettier-ignore
|
|
123
|
+
$: flexContext.updateNodeProps(rootNode, { ...classParser?.(_class, {}), ...$$restProps });
|
|
134
124
|
$: flexContext.rootWidth.set(width), flexContext.reflow();
|
|
135
125
|
$: flexContext.rootHeight.set(height), flexContext.reflow();
|
|
136
126
|
$: flexContext.mainAxis.set(plane[0]), flexContext.reflow();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NodeProps } from './props';
|
|
2
|
+
/**
|
|
3
|
+
* Because all NodeProps are primitive types, we can make a simple comparison
|
|
4
|
+
* and only request a reflow when necessary. We do that by checking the length
|
|
5
|
+
* of the props object and then checking if all keys are the same and all values
|
|
6
|
+
* are the same.
|
|
7
|
+
*/
|
|
8
|
+
export declare const propsChanged: (node: Node, props: NodeProps) => boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const nodePropsMap = new WeakMap();
|
|
2
|
+
/**
|
|
3
|
+
* Because all NodeProps are primitive types, we can make a simple comparison
|
|
4
|
+
* and only request a reflow when necessary. We do that by checking the length
|
|
5
|
+
* of the props object and then checking if all keys are the same and all values
|
|
6
|
+
* are the same.
|
|
7
|
+
*/
|
|
8
|
+
export const propsChanged = (node, props) => {
|
|
9
|
+
// get a reference to the props data for this node
|
|
10
|
+
const propsData = nodePropsMap.get(node);
|
|
11
|
+
// assume that the props have changed
|
|
12
|
+
let changed = true;
|
|
13
|
+
if (propsData) {
|
|
14
|
+
// compare the keys and values of the previous and current props
|
|
15
|
+
const previousKeys = Object.keys(propsData);
|
|
16
|
+
const currentKeys = Object.keys(props);
|
|
17
|
+
if (previousKeys.length === currentKeys.length &&
|
|
18
|
+
currentKeys.every((key) => previousKeys.includes(key)) &&
|
|
19
|
+
previousKeys.every((key) => propsData[key] === props[key])) {
|
|
20
|
+
changed = false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// update the props data for this node
|
|
24
|
+
nodePropsMap.set(node, props);
|
|
25
|
+
return changed;
|
|
26
|
+
};
|
package/dist/nodes/context.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { Node } from 'yoga-layout';
|
|
2
2
|
export type NodeContext = {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
removeChild: (child: Node) => void;
|
|
3
|
+
insertNode: (childNode: Node, order?: number) => void;
|
|
4
|
+
removeNode: (childNode: Node) => void;
|
|
6
5
|
};
|
|
7
6
|
export declare const nodeContextName = "__threlte-node";
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const createNodeContext: (order?: number) => NodeContext;
|
|
7
|
+
export declare const createNodeContext: (node: Node) => NodeContext | undefined;
|
package/dist/nodes/context.js
CHANGED
|
@@ -1,31 +1,47 @@
|
|
|
1
|
-
import { getContext,
|
|
2
|
-
import { useFlex } from '../Flex/context';
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
3
2
|
export const nodeContextName = '__threlte-node';
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
parentNodeContext?.removeChild(node);
|
|
14
|
-
});
|
|
15
|
-
const data = {
|
|
16
|
-
node,
|
|
17
|
-
insertChild(child, order) {
|
|
3
|
+
export const createNodeContext = (node) => {
|
|
4
|
+
const childNodes = new Set();
|
|
5
|
+
const childNodesOrderMap = new Map();
|
|
6
|
+
const parentNodeContext = getContext(nodeContextName);
|
|
7
|
+
setContext(nodeContextName, {
|
|
8
|
+
insertNode(childNode, order) {
|
|
9
|
+
// we want to keep track of all child nodes
|
|
10
|
+
childNodes.add(childNode);
|
|
11
|
+
// Additionally, we need to keep track of child nodes that need to be inserted at a specific order
|
|
18
12
|
if (order !== undefined) {
|
|
19
|
-
|
|
13
|
+
childNodesOrderMap.set(childNode, {
|
|
14
|
+
requestedOrder: order
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (childNodesOrderMap.size) {
|
|
18
|
+
// we need to sort the child nodes by their requested order. We leave the nodes that don't have a requested order untouched.
|
|
19
|
+
const sorted = Array.from(childNodes)
|
|
20
|
+
.map((node, index) => {
|
|
21
|
+
return {
|
|
22
|
+
order: childNodesOrderMap.get(node)?.requestedOrder ?? index,
|
|
23
|
+
node
|
|
24
|
+
};
|
|
25
|
+
})
|
|
26
|
+
.sort((a, b) => a.order - b.order)
|
|
27
|
+
.map(({ node }) => node);
|
|
28
|
+
// Then we need to remove all child nodes from the node and insert them in the correct order.
|
|
29
|
+
sorted.forEach((childNode) => {
|
|
30
|
+
node.removeChild(childNode);
|
|
31
|
+
});
|
|
32
|
+
sorted.forEach((childNode, index) => {
|
|
33
|
+
node.insertChild(childNode, index);
|
|
34
|
+
});
|
|
20
35
|
}
|
|
21
36
|
else {
|
|
22
|
-
|
|
37
|
+
node.insertChild(childNode, node.getChildCount());
|
|
23
38
|
}
|
|
24
39
|
},
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
removeNode(childNode) {
|
|
41
|
+
node.removeChild(childNode);
|
|
42
|
+
childNodes.delete(childNode);
|
|
43
|
+
childNodesOrderMap.delete(childNode);
|
|
27
44
|
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
return data;
|
|
45
|
+
});
|
|
46
|
+
return parentNodeContext;
|
|
31
47
|
};
|