@flighthq/node 0.3.0 → 0.3.1-next.1041.35b950c
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/boundsRectangle.d.ts +3 -3
- package/dist/boundsRectangle.d.ts.map +1 -1
- package/dist/boundsRectangle.js +63 -11
- package/dist/boundsRectangle.js.map +1 -1
- package/dist/contract.d.ts +1 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -0
- package/dist/contract.js.map +1 -1
- package/dist/enableNodeGuards.d.ts +4 -0
- package/dist/enableNodeGuards.d.ts.map +1 -0
- package/dist/enableNodeGuards.js +29 -0
- package/dist/enableNodeGuards.js.map +1 -0
- package/dist/hasAppearance.d.ts +2 -1
- package/dist/hasAppearance.d.ts.map +1 -1
- package/dist/hasAppearance.js +10 -0
- package/dist/hasAppearance.js.map +1 -1
- package/dist/hasBoundsRectangle.d.ts.map +1 -1
- package/dist/hasBoundsRectangle.js +4 -0
- package/dist/hasBoundsRectangle.js.map +1 -1
- package/dist/hasTransform3d.d.ts.map +1 -1
- package/dist/hasTransform3d.js +11 -4
- package/dist/hasTransform3d.js.map +1 -1
- package/dist/hierarchy.d.ts +15 -7
- package/dist/hierarchy.d.ts.map +1 -1
- package/dist/hierarchy.js +46 -25
- package/dist/hierarchy.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/nodeColorAdjustment.d.ts.map +1 -1
- package/dist/nodeColorAdjustment.js +1 -7
- package/dist/nodeColorAdjustment.js.map +1 -1
- package/dist/nodeOrderList.d.ts.map +1 -1
- package/dist/nodeOrderList.js +9 -2
- package/dist/nodeOrderList.js.map +1 -1
- package/dist/nodeTransform2d.d.ts.map +1 -1
- package/dist/nodeTransform2d.js +1 -1
- package/dist/nodeTransform2d.js.map +1 -1
- package/dist/revision.d.ts +2 -1
- package/dist/revision.d.ts.map +1 -1
- package/dist/revision.js +9 -4
- package/dist/revision.js.map +1 -1
- package/dist/stageFit.d.ts.map +1 -1
- package/dist/stageFit.js +8 -2
- package/dist/stageFit.js.map +1 -1
- package/package.json +9 -7
- package/src/boundsRectangle.test.ts +320 -7
- package/src/enableNodeGuards.test.ts +78 -0
- package/src/hasAppearance.test.ts +33 -3
- package/src/hasTransform2d.test.ts +6 -0
- package/src/hasTransform3d.test.ts +40 -8
- package/src/hierarchy.test.ts +223 -3
- package/src/node.test.ts +11 -1
- package/src/nodeColorAdjustment.test.ts +11 -0
- package/src/nodeOrderList.test.ts +84 -18
- package/src/nodeTransform2d.test.ts +45 -0
- package/src/revision.test.ts +26 -0
- package/src/stageFit.test.ts +56 -1
- package/src/traversal.test.ts +32 -2
package/src/revision.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createNode, getNodeRuntime } from '@flighthq/node/contract';
|
|
2
2
|
import type { Node, NodeRuntime } from '@flighthq/types/contract';
|
|
3
3
|
|
|
4
|
+
import { addNodeChild } from './hierarchy';
|
|
4
5
|
import {
|
|
5
6
|
computeNodeWorldTransformRevision,
|
|
6
7
|
getNodeAppearanceRevision,
|
|
@@ -41,6 +42,7 @@ describe('computeNodeWorldTransformRevision', () => {
|
|
|
41
42
|
computeNodeWorldTransformRevision(runtime);
|
|
42
43
|
expect(runtime.worldTransformUsingLocalTransformId).toBe(3);
|
|
43
44
|
expect(runtime.worldTransformUsingParentTransformId).toBe(0);
|
|
45
|
+
expect(runtime.worldTransformId).not.toBe(0);
|
|
44
46
|
});
|
|
45
47
|
|
|
46
48
|
it('incorporates parent worldTransformId when provided', () => {
|
|
@@ -51,6 +53,17 @@ describe('computeNodeWorldTransformRevision', () => {
|
|
|
51
53
|
computeNodeWorldTransformRevision(runtime, parentRuntime);
|
|
52
54
|
expect(runtime.worldTransformUsingParentTransformId).toBe(7);
|
|
53
55
|
});
|
|
56
|
+
|
|
57
|
+
it('assigns the next monotonic world revision on every recompute', () => {
|
|
58
|
+
const runtime = getEntityRuntime(node);
|
|
59
|
+
computeNodeWorldTransformRevision(runtime);
|
|
60
|
+
const first = runtime.worldTransformId;
|
|
61
|
+
|
|
62
|
+
computeNodeWorldTransformRevision(runtime);
|
|
63
|
+
|
|
64
|
+
const next = (first + 1) >>> 0;
|
|
65
|
+
expect(runtime.worldTransformId).toBe(next === 0 ? 1 : next);
|
|
66
|
+
});
|
|
54
67
|
});
|
|
55
68
|
|
|
56
69
|
describe('getNodeAppearanceRevision', () => {
|
|
@@ -246,6 +259,19 @@ describe('invalidateNodeWorldBounds', () => {
|
|
|
246
259
|
expect(runtime.worldBoundsUsingWorldTransformId).toBe(-1);
|
|
247
260
|
expect(runtime.worldBoundsUsingLocalBoundsId).toBe(-1);
|
|
248
261
|
});
|
|
262
|
+
|
|
263
|
+
it('invalidates every ancestor whose aggregate includes the target', () => {
|
|
264
|
+
const parent = createTestNode();
|
|
265
|
+
addNodeChild(parent, node);
|
|
266
|
+
const parentRuntime = getEntityRuntime(parent);
|
|
267
|
+
parentRuntime.worldBoundsUsingWorldTransformId = 1;
|
|
268
|
+
parentRuntime.worldBoundsUsingLocalBoundsId = 1;
|
|
269
|
+
|
|
270
|
+
invalidateNodeWorldBounds(node);
|
|
271
|
+
|
|
272
|
+
expect(parentRuntime.worldBoundsUsingWorldTransformId).toBe(-1);
|
|
273
|
+
expect(parentRuntime.worldBoundsUsingLocalBoundsId).toBe(-1);
|
|
274
|
+
});
|
|
249
275
|
});
|
|
250
276
|
|
|
251
277
|
type TestNode = Node;
|
package/src/stageFit.test.ts
CHANGED
|
@@ -18,10 +18,12 @@ import {
|
|
|
18
18
|
|
|
19
19
|
const TestNodeKind = 'TestNode';
|
|
20
20
|
|
|
21
|
-
function makeNodeWithBounds(width: number, height: number) {
|
|
21
|
+
function makeNodeWithBounds(width: number, height: number, x = 0, y = 0) {
|
|
22
22
|
const node = createNode(TestNodeKind);
|
|
23
23
|
const runtime = getNodeRuntime(node) as unknown as HasBoundsRectangleRuntime;
|
|
24
24
|
runtime.computeLocalBoundsRectangle = (out) => {
|
|
25
|
+
out.x = x;
|
|
26
|
+
out.y = y;
|
|
25
27
|
out.width = width;
|
|
26
28
|
out.height = height;
|
|
27
29
|
};
|
|
@@ -137,6 +139,18 @@ describe('computeScene2DFitTransform', () => {
|
|
|
137
139
|
expect(m.d).toBe(1);
|
|
138
140
|
});
|
|
139
141
|
|
|
142
|
+
it('sets identity when only the content width is zero', () => {
|
|
143
|
+
const m = createMatrix(2, 3, 4, 5, 6, 7);
|
|
144
|
+
computeScene2DFitTransform(m, fit({ root: makeNodeWithBounds(0, 50), scaleMode: 'exactfit' }), 800, 600);
|
|
145
|
+
expect(m).toMatchObject({ a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('sets identity when only the content height is zero', () => {
|
|
149
|
+
const m = createMatrix(2, 3, 4, 5, 6, 7);
|
|
150
|
+
computeScene2DFitTransform(m, fit({ root: makeNodeWithBounds(100, 0), scaleMode: 'exactfit' }), 800, 600);
|
|
151
|
+
expect(m).toMatchObject({ a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 });
|
|
152
|
+
});
|
|
153
|
+
|
|
140
154
|
it('noscale with topleft: identity scale at origin', () => {
|
|
141
155
|
const m = createMatrix();
|
|
142
156
|
computeScene2DFitTransform(
|
|
@@ -226,4 +240,45 @@ describe('computeScene2DFitTransform', () => {
|
|
|
226
240
|
expect(m.b).toBe(0);
|
|
227
241
|
expect(m.c).toBe(0);
|
|
228
242
|
});
|
|
243
|
+
|
|
244
|
+
it('maps a nonzero content-bounds origin to the selected alignment', () => {
|
|
245
|
+
const m = createMatrix();
|
|
246
|
+
computeScene2DFitTransform(
|
|
247
|
+
m,
|
|
248
|
+
fit({ align: 'topleft', root: makeNodeWithBounds(100, 50, 10, -20), scaleMode: 'exactfit' }),
|
|
249
|
+
200,
|
|
250
|
+
100,
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
expect(m.a).toBe(2);
|
|
254
|
+
expect(m.d).toBe(2);
|
|
255
|
+
expect(m.tx).toBe(-20);
|
|
256
|
+
expect(m.ty).toBe(40);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('uses scaled width before subtracting a nonzero origin on a centered horizontal axis', () => {
|
|
260
|
+
const m = createMatrix();
|
|
261
|
+
computeScene2DFitTransform(
|
|
262
|
+
m,
|
|
263
|
+
fit({ align: 'top', root: makeNodeWithBounds(100, 50, 10, -20), scaleMode: 'exactfit' }),
|
|
264
|
+
200,
|
|
265
|
+
100,
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
expect(m.tx).toBe(-20);
|
|
269
|
+
expect(m.ty).toBe(40);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('uses scaled height before subtracting a nonzero origin on a centered vertical axis', () => {
|
|
273
|
+
const m = createMatrix();
|
|
274
|
+
computeScene2DFitTransform(
|
|
275
|
+
m,
|
|
276
|
+
fit({ align: 'left', root: makeNodeWithBounds(100, 50, 10, -20), scaleMode: 'exactfit' }),
|
|
277
|
+
200,
|
|
278
|
+
100,
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
expect(m.tx).toBe(-20);
|
|
282
|
+
expect(m.ty).toBe(40);
|
|
283
|
+
});
|
|
229
284
|
});
|
package/src/traversal.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Node, NodeTraits } from '@flighthq/types/contract';
|
|
1
|
+
import type { Node, NodeRuntime, NodeTraits } from '@flighthq/types/contract';
|
|
2
2
|
import { NodeKind } from '@flighthq/types/contract';
|
|
3
3
|
|
|
4
4
|
import { addNodeChild } from './hierarchy';
|
|
5
|
-
import { createNode } from './node';
|
|
5
|
+
import { createNode, getNodeRuntime } from './node';
|
|
6
6
|
import {
|
|
7
7
|
findNode,
|
|
8
8
|
findNodeByName,
|
|
@@ -190,6 +190,18 @@ describe('getNodeNextSibling', () => {
|
|
|
190
190
|
it('returns the next sibling', () => {
|
|
191
191
|
expect(getNodeNextSibling(childA)).toBe(childB);
|
|
192
192
|
});
|
|
193
|
+
|
|
194
|
+
it('returns null for a stale parent whose child list is absent', () => {
|
|
195
|
+
(getNodeRuntime(root) as NodeRuntime).children = null;
|
|
196
|
+
|
|
197
|
+
expect(getNodeNextSibling(childA)).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('returns null for a stale parent whose nonempty child list omits the source', () => {
|
|
201
|
+
(getNodeRuntime(root) as NodeRuntime).children = [childB];
|
|
202
|
+
|
|
203
|
+
expect(getNodeNextSibling(childA)).toBeNull();
|
|
204
|
+
});
|
|
193
205
|
});
|
|
194
206
|
|
|
195
207
|
describe('getNodePreviousSibling', () => {
|
|
@@ -204,6 +216,12 @@ describe('getNodePreviousSibling', () => {
|
|
|
204
216
|
it('returns the previous sibling', () => {
|
|
205
217
|
expect(getNodePreviousSibling(childB)).toBe(childA);
|
|
206
218
|
});
|
|
219
|
+
|
|
220
|
+
it('returns null for a stale parent whose child list is absent', () => {
|
|
221
|
+
(getNodeRuntime(root) as NodeRuntime).children = null;
|
|
222
|
+
|
|
223
|
+
expect(getNodePreviousSibling(childB)).toBeNull();
|
|
224
|
+
});
|
|
207
225
|
});
|
|
208
226
|
|
|
209
227
|
describe('walkNodeDescendants', () => {
|
|
@@ -242,4 +260,16 @@ describe('walkNodeDescendants', () => {
|
|
|
242
260
|
expect(visited).not.toContain(grandchild);
|
|
243
261
|
expect(visited).not.toContain(childB);
|
|
244
262
|
});
|
|
263
|
+
|
|
264
|
+
it('propagates an early stop from a nested descendant', () => {
|
|
265
|
+
const visited: Node<NodeTraits>[] = [];
|
|
266
|
+
|
|
267
|
+
const result = walkNodeDescendants(root, (node) => {
|
|
268
|
+
visited.push(node);
|
|
269
|
+
return node !== grandchild;
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
expect(result).toBe(false);
|
|
273
|
+
expect(visited).toEqual([childA, grandchild]);
|
|
274
|
+
});
|
|
245
275
|
});
|