@symbiote-native/navigation 4.0.1 → 5.0.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 -0
- package/package.json +15 -15
- package/src/svelte/fabric-tree.test-helper.ts +59 -85
package/README.md
CHANGED
|
@@ -18,6 +18,10 @@ logic/view/lifecycle split every other SymbioteNative component follows.
|
|
|
18
18
|
npm install @symbiote-native/navigation
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
Scaffolding or extending a SymbioteNative app? `npx @symbiote-native/cli new --navigation` (or
|
|
22
|
+
`add --navigation` in an existing app) installs and wires this for you — see
|
|
23
|
+
[`@symbiote-native/cli`](../cli).
|
|
24
|
+
|
|
21
25
|
Only this package — never `react-native-screens` directly. `@symbiote-native/navigation` depends
|
|
22
26
|
on it and ships as the sole autolinked native proxy (`react-native.config.cjs` +
|
|
23
27
|
`symbiote-navigation.podspec`), the same one-dependency packaging as `@symbiote-native/slider` and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/navigation",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Native stack navigator for SymbioteNative, built on react-native-screens' native view primitives (RNSScreen/RNSScreenStack) — one framework-agnostic core, reachable from the React, Vue, Svelte, Solid, and Angular adapters.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
},
|
|
161
161
|
"dependencies": {
|
|
162
162
|
"react-native-screens": "4.26.0",
|
|
163
|
-
"@symbiote-native/components": "
|
|
163
|
+
"@symbiote-native/components": "3.0.0"
|
|
164
164
|
},
|
|
165
165
|
"peerDependencies": {
|
|
166
166
|
"@angular/common": ">=20",
|
|
@@ -171,12 +171,12 @@
|
|
|
171
171
|
"solid-js": ">=1.9.0",
|
|
172
172
|
"svelte": ">=5.56.0",
|
|
173
173
|
"vue": ">=3.5.0",
|
|
174
|
-
"@symbiote-native/
|
|
175
|
-
"@symbiote-native/
|
|
176
|
-
"@symbiote-native/
|
|
177
|
-
"@symbiote-native/
|
|
178
|
-
"@symbiote-native/
|
|
179
|
-
"@symbiote-native/
|
|
174
|
+
"@symbiote-native/angular": "^3.0.0",
|
|
175
|
+
"@symbiote-native/engine": "^1.0.0",
|
|
176
|
+
"@symbiote-native/react": "^3.0.0",
|
|
177
|
+
"@symbiote-native/solid": "^3.0.0",
|
|
178
|
+
"@symbiote-native/svelte": "^3.0.0",
|
|
179
|
+
"@symbiote-native/vue": "^3.0.0"
|
|
180
180
|
},
|
|
181
181
|
"peerDependenciesMeta": {
|
|
182
182
|
"@angular/common": {
|
|
@@ -228,13 +228,13 @@
|
|
|
228
228
|
"solid-js": "^1.9.14",
|
|
229
229
|
"svelte": "^5.56.0",
|
|
230
230
|
"typescript": "~6.0.0",
|
|
231
|
-
"@symbiote-native/angular": "
|
|
232
|
-
"@symbiote-native/engine": "0.
|
|
233
|
-
"@symbiote-native/react": "
|
|
234
|
-
"@symbiote-native/solid": "
|
|
235
|
-
"@symbiote-native/
|
|
236
|
-
"@symbiote-native/
|
|
237
|
-
"@symbiote-native/
|
|
231
|
+
"@symbiote-native/angular": "3.0.0",
|
|
232
|
+
"@symbiote-native/engine": "1.0.0",
|
|
233
|
+
"@symbiote-native/react": "3.0.0",
|
|
234
|
+
"@symbiote-native/solid": "3.0.0",
|
|
235
|
+
"@symbiote-native/svelte": "3.0.0",
|
|
236
|
+
"@symbiote-native/test-utils": "0.3.1",
|
|
237
|
+
"@symbiote-native/vue": "3.0.0"
|
|
238
238
|
},
|
|
239
239
|
"scripts": {
|
|
240
240
|
"clean": "rm -rf build-ngc",
|
|
@@ -1,95 +1,69 @@
|
|
|
1
|
-
//
|
|
1
|
+
// The live-tree walkers the smoke tests in this folder share, over the shared reader.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// title" - therefore walks `fabric.appRoot()` instead.
|
|
3
|
+
// Everything general — walking the LIVE child links instead of the creation log, flattening
|
|
4
|
+
// anchors the way the commit walk does, the two readings of a node — lives in
|
|
5
|
+
// `@symbiote-native/test-utils`'s `createLiveTree`. See its header for why each of those is not
|
|
6
|
+
// optional. What stays here is the two questions only this folder asks.
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
function isFabricNode(value: unknown): value is IFabricNode {
|
|
17
|
-
return typeof value === 'object' && value !== null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function walkLive(
|
|
21
|
-
root: unknown,
|
|
22
|
-
visit: (node: IFabricNode) => void,
|
|
23
|
-
): void {
|
|
24
|
-
if (!isFabricNode(root)) return;
|
|
25
|
-
visit(root);
|
|
26
|
-
for (const child of root.children ?? []) walkLive(child, visit);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function findAllLive(root: unknown, viewName: string): IFabricNode[] {
|
|
30
|
-
const found: IFabricNode[] = [];
|
|
31
|
-
walkLive(root, node => {
|
|
32
|
-
if (node.viewName === viewName) found.push(node);
|
|
33
|
-
});
|
|
34
|
-
return found;
|
|
35
|
-
}
|
|
8
|
+
import {
|
|
9
|
+
createLiveTree,
|
|
10
|
+
type IRecordingHost,
|
|
11
|
+
} from '@symbiote-native/test-utils';
|
|
12
|
+
import type { ILiveNode, ILiveTree } from '@symbiote-native/test-utils';
|
|
13
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
36
14
|
|
|
37
|
-
export
|
|
38
|
-
root: unknown,
|
|
39
|
-
viewName: string,
|
|
40
|
-
): IFabricNode | undefined {
|
|
41
|
-
return findAllLive(root, viewName)[0];
|
|
42
|
-
}
|
|
15
|
+
export type IFabricNode = ILiveNode;
|
|
43
16
|
|
|
44
|
-
export
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (found === undefined && node.props?.testID === testID) found = node;
|
|
55
|
-
});
|
|
56
|
-
return found;
|
|
57
|
-
}
|
|
17
|
+
export type INavigationLiveTree = ILiveTree & {
|
|
18
|
+
findAllLive: (root: ISymbioteNode, viewName: string) => ILiveNode[];
|
|
19
|
+
findLive: (root: ISymbioteNode, viewName: string) => ILiveNode | undefined;
|
|
20
|
+
countLive: (root: ISymbioteNode, viewName: string) => number;
|
|
21
|
+
findLiveByTestId: (
|
|
22
|
+
root: ISymbioteNode,
|
|
23
|
+
testID: string,
|
|
24
|
+
) => ILiveNode | undefined;
|
|
25
|
+
rawTextsOutsideTextContainer: (root: ISymbioteNode) => string[];
|
|
26
|
+
};
|
|
58
27
|
|
|
59
28
|
const TEXT_CONTAINER_VIEW_NAMES = new Set(['RCTText', 'RCTVirtualText']);
|
|
60
29
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(
|
|
75
|
-
) {
|
|
76
|
-
found.push(`${String(parentName)} > ${JSON.stringify(node.props?.text)}`);
|
|
77
|
-
}
|
|
78
|
-
for (const child of node.children ?? []) visit(child, node);
|
|
79
|
-
};
|
|
80
|
-
visit(root, undefined);
|
|
81
|
-
return found;
|
|
82
|
-
}
|
|
30
|
+
export function createNavigationLiveTree(
|
|
31
|
+
fabric: IRecordingHost,
|
|
32
|
+
): INavigationLiveTree {
|
|
33
|
+
const live = createLiveTree(fabric);
|
|
34
|
+
const byName = (root: ISymbioteNode, viewName: string): ILiveNode[] =>
|
|
35
|
+
live.findAllLive(root, node => node.viewName === viewName);
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
...live,
|
|
39
|
+
findAllLive: byName,
|
|
40
|
+
findLive: (root, viewName) => byName(root, viewName)[0],
|
|
41
|
+
countLive: (root, viewName) => byName(root, viewName).length,
|
|
42
|
+
findLiveByTestId: (root, testID) =>
|
|
43
|
+
live.findLive(root, node => node.props.testID === testID),
|
|
83
44
|
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
45
|
+
// Every raw text under a parent that cannot hold one - an invalid Fabric child. The gap Svelte
|
|
46
|
+
// leaves between two sibling tags compiles to a ' ' text node, and the shim drops it exactly
|
|
47
|
+
// when the parent takes no raw text (dom-shim/text.ts, svelte-adapter-dom-shim §16b); inside an
|
|
48
|
+
// RCTText the same string is a real word separator and must survive. So the parent, not the
|
|
49
|
+
// string, is what makes a raw text legal, and this returns the ones that are not. Formatted
|
|
50
|
+
// `viewName > "text"` so a failure names the offender.
|
|
51
|
+
rawTextsOutsideTextContainer: (root): string[] => {
|
|
52
|
+
const found: string[] = [];
|
|
53
|
+
const visit = (node: ILiveNode, parentName: string | undefined): void => {
|
|
54
|
+
if (
|
|
55
|
+
node.viewName === 'RCTRawText' &&
|
|
56
|
+
(parentName === undefined ||
|
|
57
|
+
!TEXT_CONTAINER_VIEW_NAMES.has(parentName))
|
|
58
|
+
) {
|
|
59
|
+
found.push(
|
|
60
|
+
`${String(parentName)} > ${JSON.stringify(node.props.text)}`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
for (const child of node.children) visit(child, node.viewName);
|
|
64
|
+
};
|
|
65
|
+
visit(live.nodeOf(root), undefined);
|
|
66
|
+
return found;
|
|
67
|
+
},
|
|
92
68
|
};
|
|
93
|
-
visit(root, 0);
|
|
94
|
-
return lines;
|
|
95
69
|
}
|