@symbiote-native/engine 0.2.0 → 0.4.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.
Files changed (75) hide show
  1. package/README.md +24 -11
  2. package/build/accessibility-props.d.ts +19 -0
  3. package/build/accessibility-props.js +209 -0
  4. package/build/action-sheet-ios/index.js +4 -1
  5. package/build/animated/animations/composition.js +3 -1
  6. package/build/animated/animations/spring-config.js +4 -1
  7. package/build/animated/animations/spring.js +23 -9
  8. package/build/animated/animations/timing.js +3 -2
  9. package/build/animated/bezier.js +2 -1
  10. package/build/animated/color.js +4 -2
  11. package/build/animated/event.js +7 -3
  12. package/build/animated/graph.js +8 -3
  13. package/build/animated/index.d.ts +2 -2
  14. package/build/animated/index.js +2 -2
  15. package/build/animated/interpolation.js +7 -2
  16. package/build/animated/mock.js +1 -1
  17. package/build/animated/native/native-animated.js +1 -1
  18. package/build/animated/operators.js +27 -6
  19. package/build/animated/props.js +1 -1
  20. package/build/animated/rgba.js +18 -3
  21. package/build/animated/style.js +13 -3
  22. package/build/animated/value-xy.d.ts +8 -5
  23. package/build/animated/value-xy.js +4 -1
  24. package/build/app-registry/index.d.ts +1 -0
  25. package/build/app-registry/index.js +15 -5
  26. package/build/appearance/index.js +4 -1
  27. package/build/commit.d.ts +35 -0
  28. package/build/commit.js +613 -74
  29. package/build/debug.js +10 -4
  30. package/build/events/index.js +142 -88
  31. package/build/fabric-props.js +171 -11
  32. package/build/fabric.d.ts +10 -3
  33. package/build/fabric.js +11 -2
  34. package/build/host-behavior.d.ts +47 -0
  35. package/build/host-behavior.js +262 -0
  36. package/build/host-instance/index.d.ts +2 -10
  37. package/build/host-instance/index.js +13 -46
  38. package/build/image-loader.js +3 -2
  39. package/build/index.d.ts +24 -17
  40. package/build/index.js +27 -13
  41. package/build/interaction-manager/index.js +2 -1
  42. package/build/layout-animation/index.js +12 -4
  43. package/build/native-events.js +2 -1
  44. package/build/native-modules/index.js +3 -1
  45. package/build/node.d.ts +121 -2
  46. package/build/node.js +623 -41
  47. package/build/pan-responder/index.js +20 -9
  48. package/build/permissions-android/index.js +3 -1
  49. package/build/platform/index.android.d.ts +1 -1
  50. package/build/platform/index.android.js +1 -1
  51. package/build/platform/index.ios.d.ts +1 -1
  52. package/build/platform-color/index.js +3 -1
  53. package/build/post-commit.d.ts +1 -0
  54. package/build/post-commit.js +6 -0
  55. package/build/process-background-image/index.js +30 -9
  56. package/build/process-filter.js +11 -4
  57. package/build/registry.js +10 -2
  58. package/build/report-error.js +4 -1
  59. package/build/share/index.android.js +1 -1
  60. package/build/share/index.ios.js +1 -1
  61. package/build/status-bar/index.android.js +3 -4
  62. package/build/status-bar/index.ios.js +1 -1
  63. package/build/style-registry/index.d.ts +11 -2
  64. package/build/style-registry/index.js +223 -169
  65. package/build/style-registry/scope.d.ts +15 -1
  66. package/build/style-registry/scope.js +29 -27
  67. package/build/styles.d.ts +11 -1
  68. package/build/surface.d.ts +1 -1
  69. package/build/surface.js +8 -0
  70. package/build/tags.d.ts +1 -0
  71. package/build/tags.js +31 -1
  72. package/build/touch-history.js +9 -2
  73. package/build/vibration/index.ios.js +1 -1
  74. package/build/view-config.js +20 -2
  75. package/package.json +12 -2
@@ -57,7 +57,10 @@ export class AnimatedAddition extends AnimatedBinaryOp {
57
57
  return a + b;
58
58
  }
59
59
  __getNativeConfig() {
60
- return { type: 'addition', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
60
+ return {
61
+ type: 'addition',
62
+ input: [this.a.__getNativeTag(), this.b.__getNativeTag()],
63
+ };
61
64
  }
62
65
  }
63
66
  export class AnimatedSubtraction extends AnimatedBinaryOp {
@@ -65,7 +68,10 @@ export class AnimatedSubtraction extends AnimatedBinaryOp {
65
68
  return a - b;
66
69
  }
67
70
  __getNativeConfig() {
68
- return { type: 'subtraction', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
71
+ return {
72
+ type: 'subtraction',
73
+ input: [this.a.__getNativeTag(), this.b.__getNativeTag()],
74
+ };
69
75
  }
70
76
  }
71
77
  export class AnimatedMultiplication extends AnimatedBinaryOp {
@@ -73,7 +79,10 @@ export class AnimatedMultiplication extends AnimatedBinaryOp {
73
79
  return a * b;
74
80
  }
75
81
  __getNativeConfig() {
76
- return { type: 'multiplication', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
82
+ return {
83
+ type: 'multiplication',
84
+ input: [this.a.__getNativeTag(), this.b.__getNativeTag()],
85
+ };
77
86
  }
78
87
  }
79
88
  export class AnimatedDivision extends AnimatedBinaryOp {
@@ -97,7 +106,10 @@ export class AnimatedDivision extends AnimatedBinaryOp {
97
106
  return a / b;
98
107
  }
99
108
  __getNativeConfig() {
100
- return { type: 'division', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
109
+ return {
110
+ type: 'division',
111
+ input: [this.a.__getNativeTag(), this.b.__getNativeTag()],
112
+ };
101
113
  }
102
114
  }
103
115
  export class AnimatedModulo extends AnimatedWithChildren {
@@ -127,7 +139,11 @@ export class AnimatedModulo extends AnimatedWithChildren {
127
139
  super.__makeNative(platformConfig);
128
140
  }
129
141
  __getNativeConfig() {
130
- return { type: 'modulus', input: this.a.__getNativeTag(), modulus: this.modulus };
142
+ return {
143
+ type: 'modulus',
144
+ input: this.a.__getNativeTag(),
145
+ modulus: this.modulus,
146
+ };
131
147
  }
132
148
  }
133
149
  export class AnimatedDiffClamp extends AnimatedWithChildren {
@@ -167,7 +183,12 @@ export class AnimatedDiffClamp extends AnimatedWithChildren {
167
183
  super.__makeNative(platformConfig);
168
184
  }
169
185
  __getNativeConfig() {
170
- return { type: 'diffclamp', input: this.a.__getNativeTag(), min: this.min, max: this.max };
186
+ return {
187
+ type: 'diffclamp',
188
+ input: this.a.__getNativeTag(),
189
+ min: this.min,
190
+ max: this.max,
191
+ };
171
192
  }
172
193
  }
173
194
  export function add(a, b) {
@@ -15,7 +15,7 @@ import { AnimatedNode, AnimatedWithChildren } from './graph.js';
15
15
  import { setNativeProps, getNativeTag } from '../commit.js';
16
16
  import { isSymbioteNode } from '../node.js';
17
17
  import { registerPostCommit } from '../post-commit.js';
18
- import { nativeAnimated } from './native/native-animated.js';
18
+ import { nativeAnimated, } from './native/native-animated.js';
19
19
  import { AnimatedStyle } from './style.js';
20
20
  function isAnimatedNode(value) {
21
21
  return value instanceof AnimatedNode;
@@ -16,7 +16,12 @@ export const DEFAULT_COLOR = { r: 0, g: 0, b: 0, a: 1 };
16
16
  export function normalizeColor(color) {
17
17
  if (typeof color === 'number') {
18
18
  const c = color >>> 0;
19
- return { r: (c >>> 24) & 255, g: (c >>> 16) & 255, b: (c >>> 8) & 255, a: (c & 255) / 255 };
19
+ return {
20
+ r: (c >>> 24) & 255,
21
+ g: (c >>> 16) & 255,
22
+ b: (c >>> 8) & 255,
23
+ a: (c & 255) / 255,
24
+ };
20
25
  }
21
26
  const trimmed = color.trim();
22
27
  if (trimmed.startsWith('#'))
@@ -42,7 +47,12 @@ function parseHex(hex) {
42
47
  return { r: (int >>> 16) & 255, g: (int >>> 8) & 255, b: int & 255, a: 1 };
43
48
  }
44
49
  const c = int >>> 0;
45
- return { r: (c >>> 24) & 255, g: (c >>> 16) & 255, b: (c >>> 8) & 255, a: (c & 255) / 255 };
50
+ return {
51
+ r: (c >>> 24) & 255,
52
+ g: (c >>> 16) & 255,
53
+ b: (c >>> 8) & 255,
54
+ a: (c & 255) / 255,
55
+ };
46
56
  }
47
57
  function parseRgb(str) {
48
58
  const match = /^rgba?\(([^)]+)\)$/i.exec(str);
@@ -51,5 +61,10 @@ function parseRgb(str) {
51
61
  const parts = match[1].split(',').map(part => Number.parseFloat(part.trim()));
52
62
  if (parts.length < 3 || parts.some(n => Number.isNaN(n)))
53
63
  return undefined;
54
- return { r: parts[0], g: parts[1], b: parts[2], a: parts.length >= 4 ? parts[3] : 1 };
64
+ return {
65
+ r: parts[0],
66
+ g: parts[1],
67
+ b: parts[2],
68
+ a: parts.length >= 4 ? parts[3] : 1,
69
+ };
55
70
  }
@@ -73,7 +73,9 @@ export class AnimatedTransform extends AnimatedWithChildren {
73
73
  const result = {};
74
74
  for (const key of Object.keys(entry)) {
75
75
  const value = entry[key];
76
- result[key] = isAnimatedNode(value) ? value.__getAnimatedValue() : value;
76
+ result[key] = isAnimatedNode(value)
77
+ ? value.__getAnimatedValue()
78
+ : value;
77
79
  }
78
80
  return result;
79
81
  });
@@ -96,10 +98,18 @@ export class AnimatedTransform extends AnimatedWithChildren {
96
98
  const value = entry[key];
97
99
  if (isAnimatedNode(value)) {
98
100
  // __getNativeTag only: creation is edge-free; the connect is a later phase.
99
- transforms.push({ type: 'animated', property: key, nodeTag: value.__getNativeTag() });
101
+ transforms.push({
102
+ type: 'animated',
103
+ property: key,
104
+ nodeTag: value.__getNativeTag(),
105
+ });
100
106
  }
101
107
  else {
102
- transforms.push({ type: 'static', property: key, value: transformDataType(value) });
108
+ transforms.push({
109
+ type: 'static',
110
+ property: key,
111
+ value: transformDataType(value),
112
+ });
103
113
  }
104
114
  }
105
115
  }
@@ -26,10 +26,13 @@ export declare class AnimatedValueXY {
26
26
  left: AnimatedValue;
27
27
  top: AnimatedValue;
28
28
  };
29
- getTranslateTransform(): [{
30
- translateX: AnimatedValue;
31
- }, {
32
- translateY: AnimatedValue;
33
- }];
29
+ getTranslateTransform(): [
30
+ {
31
+ translateX: AnimatedValue;
32
+ },
33
+ {
34
+ translateY: AnimatedValue;
35
+ }
36
+ ];
34
37
  }
35
38
  export {};
@@ -17,7 +17,10 @@ export class AnimatedValueXY {
17
17
  // Each joint id maps to the two per-axis listener ids it registered, so
18
18
  // removeListener can tear both down together.
19
19
  jointListeners = new Map();
20
- constructor(value = { x: 0, y: 0 }) {
20
+ constructor(value = {
21
+ x: 0,
22
+ y: 0,
23
+ }) {
21
24
  if (typeof value.x === 'number' && typeof value.y === 'number') {
22
25
  this.x = new AnimatedValue(value.x);
23
26
  this.y = new AnimatedValue(value.y);
@@ -14,6 +14,7 @@ export type ITaskCanceller = () => void;
14
14
  export type ITaskCancelProvider = () => ITaskCanceller;
15
15
  export interface IHostRegistrar {
16
16
  registerRunnable(appKey: string, run: IRunnable): string;
17
+ registerCancellableHeadlessTask?(taskKey: string, taskProvider: ITaskProvider, taskCancelProvider: ITaskCancelProvider): void;
17
18
  unmountAtRootTag?(rootTag: IRootTag): void;
18
19
  }
19
20
  export interface IAppRegistry<TComponentProvider, TWrapperComponentProvider> {
@@ -6,11 +6,9 @@
6
6
  // the one thing each adapter supplies; everything else (registry bookkeeping, sections, the
7
7
  // host-registrar bridge, headless tasks) is byte-identical across adapters and lives here once.
8
8
  //
9
- // The catch: the native Fabric host invokes RN's AppRegistry (a registered callable module) by
10
- // app key, and it can't see ours. So registerComponent must also hand its runnable to RN's
11
- // registrar. Reached the same way shared reaches processColor: a dependency-injected seam
12
- // (setHostRegistrar), so the core stays react-native-free and the app glue wires the host once
13
- // at startup.
9
+ // The catch: native invokes RN's registered callable AppRegistry for both surface runnables and
10
+ // headless tasks; it cannot see this local registry. `setHostRegistrar` mirrors those native-facing
11
+ // registrations there while the core remains react-native-free.
14
12
  import { getNativeModule } from '../native-modules/index.js';
15
13
  import { dlog } from '../debug.js';
16
14
  const HEADLESS_TASK_MODULE = 'HeadlessJsTaskSupport';
@@ -121,6 +119,7 @@ export function createAppRegistry(runnableFor) {
121
119
  }
122
120
  taskProviders.set(taskKey, taskProvider);
123
121
  taskCancelProviders.set(taskKey, taskCancelProvider);
122
+ hostRegistrar?.registerCancellableHeadlessTask?.(taskKey, taskProvider, taskCancelProvider);
124
123
  },
125
124
  startHeadlessTask(taskId, taskKey, data) {
126
125
  runHeadlessTask(taskId, taskKey, data);
@@ -138,7 +137,18 @@ export function createAppRegistry(runnableFor) {
138
137
  return {
139
138
  AppRegistry,
140
139
  setHostRegistrar(registrar) {
140
+ if (hostRegistrar === registrar)
141
+ return;
141
142
  hostRegistrar = registrar;
143
+ // Headless tasks are commonly registered before adapter bootstrap attaches RN's callable
144
+ // AppRegistry. Replay only this missing native-facing registry; app runnables retain their
145
+ // existing register-after-bootstrap contract.
146
+ for (const [taskKey, taskProvider] of taskProviders) {
147
+ const taskCancelProvider = taskCancelProviders.get(taskKey);
148
+ if (taskCancelProvider !== undefined) {
149
+ registrar.registerCancellableHeadlessTask?.(taskKey, taskProvider, taskCancelProvider);
150
+ }
151
+ }
142
152
  },
143
153
  };
144
154
  }
@@ -62,7 +62,10 @@ export const Appearance = {
62
62
  return;
63
63
  }
64
64
  module.setColorScheme(colorScheme);
65
- cachedScheme = colorScheme === 'unspecified' ? (module.getColorScheme() ?? null) : colorScheme;
65
+ cachedScheme =
66
+ colorScheme === 'unspecified'
67
+ ? (module.getColorScheme() ?? null)
68
+ : colorScheme;
66
69
  },
67
70
  // Subscribe to color-scheme changes. The listener receives `{ colorScheme }`.
68
71
  addChangeListener(listener) {
package/build/commit.d.ts CHANGED
@@ -1,9 +1,44 @@
1
1
  import { type IFabricNode, type IRootTag, type IMeasureOnSuccess, type IMeasureInWindowOnSuccess, type IMeasureLayoutOnSuccess } from './fabric';
2
2
  import { type ISymbioteNode } from './node';
3
3
  export { processColor, setColorProcessor } from './platform-color';
4
+ declare global {
5
+ var __SYMBIOTE_BATCH_CREATE__: boolean | undefined;
6
+ }
4
7
  export declare function disposeRoot(rootTag: IRootTag): void;
5
8
  export declare function commitChildren(rootTag: IRootTag, children: readonly ISymbioteNode[]): void;
9
+ export interface ICommitProfile {
10
+ commits: number;
11
+ walkMs: number;
12
+ nodesVisited: number;
13
+ /** Update-path nodes that rebuilt their Fabric payload and deep-compared it. */
14
+ propsBuilt: number;
15
+ /** Update-path nodes that re-cloned for a child but reused the committed payload by reference. */
16
+ propsReused: number;
17
+ propWrites: number;
18
+ propNoops: number;
19
+ childScans: number;
20
+ childScanProbed: number;
21
+ childFlattens: number;
22
+ childFlattenProbed: number;
23
+ childFlattenWidest: number;
24
+ }
25
+ export declare function readCommitProfile(): ICommitProfile;
26
+ export declare function flushNativeProps(): void;
6
27
  export declare function setNativeProps(node: ISymbioteNode, partial: Record<string, unknown>): void;
28
+ /**
29
+ * Publish a node whose props were changed OUTSIDE any renderer mutation.
30
+ *
31
+ * Dirtying is not publishing. Every other write reaches Fabric because the framework's own commit
32
+ * follows it; a change driven by a NATIVE EVENT has no such follow-up — `native-events.ts`
33
+ * requests no commit and no adapter does either, so a node marked dirty from an event handler
34
+ * simply stays dirty. The host-behavior press path (`setNodePressed` for `:active`) is the first
35
+ * caller that is not `setNativeProps`, and `setNodeHidden`'s React twin never needed it because
36
+ * the reconciler is already in its commit phase when it calls.
37
+ *
38
+ * Queued rather than committed on the spot, sharing `setNativeProps`' batch: several writes in one
39
+ * task publish together at the microtask boundary, one commit per surface.
40
+ */
41
+ export declare function requestCommitFor(node: ISymbioteNode): void;
7
42
  export declare function getNativeTag(node: ISymbioteNode): number | undefined;
8
43
  export declare function whenCommitted(node: ISymbioteNode, action: () => void): () => void;
9
44
  export declare function getNativeNode(node: ISymbioteNode): IFabricNode | undefined;