@symbiote-native/engine 0.1.4 → 0.1.5

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 (62) hide show
  1. package/build/accessibility-info/index.android.js +17 -29
  2. package/build/accessibility-info/index.ios.js +23 -37
  3. package/build/accessibility-info/shared.d.ts +3 -2
  4. package/build/accessibility-info/shared.js +25 -2
  5. package/build/action-sheet-ios/index.d.ts +6 -0
  6. package/build/action-sheet-ios/index.js +1 -1
  7. package/build/alert/index.android.js +1 -3
  8. package/build/animated/animations/base.js +5 -14
  9. package/build/animated/event.js +7 -9
  10. package/build/animated/graph.d.ts +6 -0
  11. package/build/animated/graph.js +14 -0
  12. package/build/animated/interpolation-node.d.ts +0 -1
  13. package/build/animated/interpolation-node.js +5 -4
  14. package/build/animated/native/native-animated.js +1 -3
  15. package/build/animated/operators.d.ts +14 -34
  16. package/build/animated/operators.js +19 -95
  17. package/build/animated/value.d.ts +2 -4
  18. package/build/animated/value.js +17 -5
  19. package/build/app-state/index.js +17 -22
  20. package/build/appearance/index.js +17 -25
  21. package/build/back-handler/index.js +15 -18
  22. package/build/commit.d.ts +1 -3
  23. package/build/commit.js +10 -207
  24. package/build/dimensions/index.js +25 -20
  25. package/build/events/index.js +6 -151
  26. package/build/fabric-props.d.ts +3 -0
  27. package/build/fabric-props.js +186 -0
  28. package/build/i18n-manager/index.js +3 -5
  29. package/build/image-loader.d.ts +24 -0
  30. package/build/image-loader.js +175 -0
  31. package/build/image-source-resolver.d.ts +9 -0
  32. package/build/image-source-resolver.js +16 -0
  33. package/build/index.d.ts +10 -3
  34. package/build/index.js +11 -2
  35. package/build/keyboard/index.js +19 -34
  36. package/build/layout-animation/index.d.ts +1 -0
  37. package/build/layout-animation/index.js +53 -35
  38. package/build/native-modules.d.ts +12 -0
  39. package/build/native-modules.js +64 -1
  40. package/build/node.d.ts +1 -0
  41. package/build/node.js +9 -0
  42. package/build/pan-responder/index.js +1 -3
  43. package/build/permissions-android/index.js +1 -3
  44. package/build/platform-color.d.ts +3 -0
  45. package/build/platform-color.js +24 -0
  46. package/build/process-background-image/index.js +7 -14
  47. package/build/process-box-shadow/index.js +1 -5
  48. package/build/process-filter.js +2 -8
  49. package/build/registry.js +3 -5
  50. package/build/settings/index.js +1 -3
  51. package/build/share/index.ios.js +1 -1
  52. package/build/status-bar/index.android.js +1 -1
  53. package/build/style/index.js +2 -4
  54. package/build/style-registry/index.d.ts +1 -3
  55. package/build/style-registry/index.js +15 -48
  56. package/build/style-registry/scope.d.ts +3 -0
  57. package/build/style-registry/scope.js +41 -0
  58. package/build/touch-history.d.ts +23 -0
  59. package/build/touch-history.js +150 -0
  60. package/build/type-guards.d.ts +4 -0
  61. package/build/type-guards.js +15 -0
  62. package/package.json +1 -1
@@ -10,7 +10,6 @@
10
10
  // each input's native tag (creating the input node) but issues no connect.
11
11
  import { AnimatedNode, AnimatedWithChildren } from './graph.js';
12
12
  import { AnimatedValue } from './value.js';
13
- import { AnimatedInterpolation } from './interpolation-node.js';
14
13
  import { dlog } from '../debug.js';
15
14
  // Wrap a bare number in an AnimatedValue so every input is a graph node.
16
15
  function toNode(input) {
@@ -23,7 +22,10 @@ function numericValue(node) {
23
22
  }
24
23
  return value;
25
24
  }
26
- export class AnimatedAddition extends AnimatedWithChildren {
25
+ // Shared shape of add/subtract/multiply/divide: two operand nodes, wired into the
26
+ // graph identically (attach/detach both as children, makeNative both natively).
27
+ // Each subclass supplies only its arithmetic (`compute`) and its native config type.
28
+ class AnimatedBinaryOp extends AnimatedWithChildren {
27
29
  a;
28
30
  b;
29
31
  constructor(a, b) {
@@ -32,10 +34,7 @@ export class AnimatedAddition extends AnimatedWithChildren {
32
34
  this.b = toNode(b);
33
35
  }
34
36
  __getValue() {
35
- return numericValue(this.a) + numericValue(this.b);
36
- }
37
- interpolate(config) {
38
- return new AnimatedInterpolation(this, config);
37
+ return this.compute(numericValue(this.a), numericValue(this.b));
39
38
  }
40
39
  __attach() {
41
40
  this.a.__addChild(this);
@@ -52,91 +51,40 @@ export class AnimatedAddition extends AnimatedWithChildren {
52
51
  this.b.__makeNative(platformConfig);
53
52
  super.__makeNative(platformConfig);
54
53
  }
54
+ }
55
+ export class AnimatedAddition extends AnimatedBinaryOp {
56
+ compute(a, b) {
57
+ return a + b;
58
+ }
55
59
  __getNativeConfig() {
56
60
  return { type: 'addition', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
57
61
  }
58
62
  }
59
- export class AnimatedSubtraction extends AnimatedWithChildren {
60
- a;
61
- b;
62
- constructor(a, b) {
63
- super();
64
- this.a = toNode(a);
65
- this.b = toNode(b);
66
- }
67
- __getValue() {
68
- return numericValue(this.a) - numericValue(this.b);
69
- }
70
- interpolate(config) {
71
- return new AnimatedInterpolation(this, config);
72
- }
73
- __attach() {
74
- this.a.__addChild(this);
75
- this.b.__addChild(this);
76
- super.__attach();
77
- }
78
- __detach() {
79
- this.a.__removeChild(this);
80
- this.b.__removeChild(this);
81
- super.__detach();
82
- }
83
- __makeNative(platformConfig) {
84
- this.a.__makeNative(platformConfig);
85
- this.b.__makeNative(platformConfig);
86
- super.__makeNative(platformConfig);
63
+ export class AnimatedSubtraction extends AnimatedBinaryOp {
64
+ compute(a, b) {
65
+ return a - b;
87
66
  }
88
67
  __getNativeConfig() {
89
68
  return { type: 'subtraction', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
90
69
  }
91
70
  }
92
- export class AnimatedMultiplication extends AnimatedWithChildren {
93
- a;
94
- b;
95
- constructor(a, b) {
96
- super();
97
- this.a = toNode(a);
98
- this.b = toNode(b);
99
- }
100
- __getValue() {
101
- return numericValue(this.a) * numericValue(this.b);
102
- }
103
- interpolate(config) {
104
- return new AnimatedInterpolation(this, config);
105
- }
106
- __attach() {
107
- this.a.__addChild(this);
108
- this.b.__addChild(this);
109
- super.__attach();
110
- }
111
- __detach() {
112
- this.a.__removeChild(this);
113
- this.b.__removeChild(this);
114
- super.__detach();
115
- }
116
- __makeNative(platformConfig) {
117
- this.a.__makeNative(platformConfig);
118
- this.b.__makeNative(platformConfig);
119
- super.__makeNative(platformConfig);
71
+ export class AnimatedMultiplication extends AnimatedBinaryOp {
72
+ compute(a, b) {
73
+ return a * b;
120
74
  }
121
75
  __getNativeConfig() {
122
76
  return { type: 'multiplication', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
123
77
  }
124
78
  }
125
- export class AnimatedDivision extends AnimatedWithChildren {
126
- a;
127
- b;
79
+ export class AnimatedDivision extends AnimatedBinaryOp {
128
80
  warnedAboutDivideByZero = false;
129
81
  constructor(a, b) {
130
- super();
82
+ super(a, b);
131
83
  if (b === 0 || (b instanceof AnimatedNode && b.__getValue() === 0)) {
132
84
  dlog('AnimatedDivision: detected potential division by zero');
133
85
  }
134
- this.a = toNode(a);
135
- this.b = toNode(b);
136
86
  }
137
- __getValue() {
138
- const a = numericValue(this.a);
139
- const b = numericValue(this.b);
87
+ compute(a, b) {
140
88
  if (b === 0) {
141
89
  // A divide-by-zero yields Infinity/NaN, which crashes Fabric, so clamp to 0.
142
90
  if (!this.warnedAboutDivideByZero) {
@@ -148,24 +96,6 @@ export class AnimatedDivision extends AnimatedWithChildren {
148
96
  this.warnedAboutDivideByZero = false;
149
97
  return a / b;
150
98
  }
151
- interpolate(config) {
152
- return new AnimatedInterpolation(this, config);
153
- }
154
- __attach() {
155
- this.a.__addChild(this);
156
- this.b.__addChild(this);
157
- super.__attach();
158
- }
159
- __detach() {
160
- this.a.__removeChild(this);
161
- this.b.__removeChild(this);
162
- super.__detach();
163
- }
164
- __makeNative(platformConfig) {
165
- this.a.__makeNative(platformConfig);
166
- this.b.__makeNative(platformConfig);
167
- super.__makeNative(platformConfig);
168
- }
169
99
  __getNativeConfig() {
170
100
  return { type: 'division', input: [this.a.__getNativeTag(), this.b.__getNativeTag()] };
171
101
  }
@@ -184,9 +114,6 @@ export class AnimatedModulo extends AnimatedWithChildren {
184
114
  const a = numericValue(this.a);
185
115
  return ((a % this.modulus) + this.modulus) % this.modulus;
186
116
  }
187
- interpolate(config) {
188
- return new AnimatedInterpolation(this, config);
189
- }
190
117
  __attach() {
191
118
  this.a.__addChild(this);
192
119
  super.__attach();
@@ -227,9 +154,6 @@ export class AnimatedDiffClamp extends AnimatedWithChildren {
227
154
  this.value = Math.min(Math.max(this.value + diff, this.min), this.max);
228
155
  return this.value;
229
156
  }
230
- interpolate(config) {
231
- return new AnimatedInterpolation(this, config);
232
- }
233
157
  __attach() {
234
158
  this.a.__addChild(this);
235
159
  super.__attach();
@@ -1,9 +1,7 @@
1
1
  import type { IAnimation, IEndCallback } from './animation';
2
2
  import { AnimatedWithChildren, type IValueListener } from './graph';
3
3
  import type { AnimatedTracking } from './animations/tracking';
4
- import { AnimatedInterpolation } from './interpolation-node';
5
- import type { IInterpolationConfig } from './interpolation';
6
- import { type INativeNodeConfig, type IPlatformConfig } from './native/native-animated';
4
+ import { type INativeAnimationConfig, type INativeNodeConfig, type IPlatformConfig } from './native/native-animated';
7
5
  export declare class AnimatedValue extends AnimatedWithChildren {
8
6
  private value;
9
7
  private readonly startingValue;
@@ -25,12 +23,12 @@ export declare class AnimatedValue extends AnimatedWithChildren {
25
23
  flattenOffset(): void;
26
24
  extractOffset(): void;
27
25
  __onNativeUpdate(value: number, offset?: number): void;
26
+ __startNativeAnimation(config: INativeAnimationConfig, nativeId: number, onEnd: (finished: boolean) => void, platformConfig?: IPlatformConfig): void;
28
27
  __getNativeConfig(): INativeNodeConfig;
29
28
  stopAnimation(callback?: (value: number) => void): void;
30
29
  track(tracking: AnimatedTracking): void;
31
30
  private stopTracking;
32
31
  resetAnimation(callback?: (value: number) => void): void;
33
- interpolate(config: IInterpolationConfig): AnimatedInterpolation;
34
32
  animate(animation: IAnimation, callback?: IEndCallback): void;
35
33
  private updateValue;
36
34
  }
@@ -4,7 +4,6 @@
4
4
  // AnimatedValue.js with the native-driver branches removed; tracking
5
5
  // (animating toward another animated node) is deferred.
6
6
  import { AnimatedWithChildren, flushValue } from './graph.js';
7
- import { AnimatedInterpolation } from './interpolation-node.js';
8
7
  import { nativeAnimated, } from './native/native-animated.js';
9
8
  export class AnimatedValue extends AnimatedWithChildren {
10
9
  value;
@@ -120,6 +119,23 @@ export class AnimatedValue extends AnimatedWithChildren {
120
119
  this.offset = offset;
121
120
  }
122
121
  }
122
+ // Own the native-driver "start" handshake end-to-end: make this value native, mint
123
+ // its tag, hand the curve to the native module, and on completion sync the JS value
124
+ // (no re-flush to bound leaves' native side; native already moved the view). A
125
+ // driver (BaseAnimation.startNativeIfNeeded) supplies only what IT owns: the curve
126
+ // config, its own animation id, its platform bag, and its own end callback, never
127
+ // touching __makeNative / __getNativeTag / __onNativeUpdate / flushValue directly.
128
+ // Information Expert: this value is the one object that actually holds those internals.
129
+ __startNativeAnimation(config, nativeId, onEnd, platformConfig) {
130
+ this.__makeNative(platformConfig);
131
+ nativeAnimated.startAnimatingNode(nativeId, this.__getNativeTag(), config, result => {
132
+ onEnd(result.finished);
133
+ if (result.value !== undefined) {
134
+ this.__onNativeUpdate(result.value, result.offset);
135
+ flushValue(this);
136
+ }
137
+ });
138
+ }
123
139
  __getNativeConfig() {
124
140
  return { type: 'value', value: this.value, offset: this.offset };
125
141
  }
@@ -153,10 +169,6 @@ export class AnimatedValue extends AnimatedWithChildren {
153
169
  this.stopAnimation(callback);
154
170
  this.value = this.startingValue;
155
171
  }
156
- // Map the value before it reaches a prop, e.g. 0..1 -> 0..10.
157
- interpolate(config) {
158
- return new AnimatedInterpolation(this, config);
159
- }
160
172
  // Drive this value with an animation. Typically called by Animated.timing /
161
173
  // spring / decay rather than directly.
162
174
  animate(animation, callback) {
@@ -5,8 +5,8 @@
5
5
  // NativeEventEmitter bound to the AppState native module and maps them onto the
6
6
  // public 'change'/'memoryWarning'/'focus'/'blur' listeners, mirroring RN's
7
7
  // Libraries/AppState/AppState.js.
8
- import { getNativeModule } from '../native-modules.js';
9
- import { installDeviceEventHub, NativeEventEmitter, } from '../native-events.js';
8
+ import { createDeviceEventModule } from '../native-modules.js';
9
+ import {} from '../native-events.js';
10
10
  import { dlog } from '../debug.js';
11
11
  // The native module name RN registers AppState under, confirmed from its spec
12
12
  // (specs_DEPRECATED/modules/INativeAppState.js, `TurboModuleRegistry.getEnforcing('AppState')`).
@@ -30,36 +30,31 @@ function isStateChangePayload(value) {
30
30
  // Lazily resolved so importing this module has no native side effect: a headless
31
31
  // run without a fake __turboModuleProxy still loads it; resolution happens on first
32
32
  // use. `null` when the module isn't linked.
33
- let appStateModule;
34
- let emitter;
35
33
  let currentState = null;
36
- function getModule() {
37
- if (appStateModule === undefined) {
38
- appStateModule = getNativeModule(APP_STATE_MODULE);
39
- dlog(`AppState: module ${appStateModule ? 'resolved' : 'NOT resolved (null)'}`);
40
- }
41
- return appStateModule;
42
- }
43
- function getEmitter() {
44
- if (emitter === undefined) {
45
- // WHY lazy: install on first use so the hub exists before native emits, without
46
- // a hard bootstrap-order dependency. Idempotent.
47
- installDeviceEventHub();
48
- const module = getModule();
34
+ // The self-subscription policy that diverges from a plain lazy-resolve+emitter:
35
+ // AppState hydrates `currentState` from the module's initial constants, then keeps it
36
+ // fresh forever via a permanent 'appStateDidChange' listener, so a read after a native
37
+ // change returns the new value even with nobody else listening (RN parity).
38
+ const deviceEventModule = createDeviceEventModule({
39
+ moduleName: APP_STATE_MODULE,
40
+ moduleLogPrefix: 'AppState: module',
41
+ onEmitterCreated: (emitter, module) => {
49
42
  if (module !== null) {
50
43
  currentState = module.getConstants().initialAppState;
51
44
  }
52
- emitter = new NativeEventEmitter(module ?? undefined);
53
- // Keep `currentState` fresh even when nobody listens, so a read after a state
54
- // change returns the new value; RN registers the same always-on observer.
55
45
  emitter.addListener(NATIVE_EVENT.stateDidChange, payload => {
56
46
  if (!isStateChangePayload(payload))
57
47
  return;
58
48
  dlog(`AppState: ${NATIVE_EVENT.stateDidChange} -> ${payload.app_state}`);
59
49
  currentState = payload.app_state;
60
50
  });
61
- }
62
- return emitter;
51
+ },
52
+ });
53
+ function getModule() {
54
+ return deviceEventModule.getModule();
55
+ }
56
+ function getEmitter() {
57
+ return deviceEventModule.getEmitter();
63
58
  }
64
59
  class AppStateImpl {
65
60
  // Feature-detect: true when the native AppState module resolved, false when it
@@ -4,8 +4,8 @@
4
4
  // native module (which RN keys its appearance events off of) and re-broadcasts to
5
5
  // JS listeners as a plain `{ colorScheme }` payload. Mirrors RN's
6
6
  // Libraries/Utilities/Appearance.js, slimmed to the parts we need.
7
- import { getNativeModule } from '../native-modules.js';
8
- import { installDeviceEventHub, NativeEventEmitter, } from '../native-events.js';
7
+ import { createDeviceEventModule } from '../native-modules.js';
8
+ import {} from '../native-events.js';
9
9
  import { dlog } from '../debug.js';
10
10
  // The native module name RN registers the appearance module under, confirmed from
11
11
  // its spec (specs_DEPRECATED/modules/INativeAppearance.js, `TurboModuleRegistry.get('Appearance')`).
@@ -16,37 +16,29 @@ const APPEARANCE_CHANGED_EVENT = 'appearanceChanged';
16
16
  function isAppearancePreferences(value) {
17
17
  return typeof value === 'object' && value !== null && 'colorScheme' in value;
18
18
  }
19
- // Lazily resolved so importing this module has no native side effect: a headless
20
- // run without a fake __turboModuleProxy still loads it; resolution happens on the
21
- // first use. `null` when the module isn't linked.
22
- let appearanceModule;
23
- let emitter;
24
19
  // Cached scheme, kept fresh by the change listener; mirrors RN's `state.appearance`.
25
20
  let cachedScheme;
26
- function getModule() {
27
- if (appearanceModule === undefined) {
28
- appearanceModule = getNativeModule(APPEARANCE_MODULE);
29
- dlog(`Appearance: module ${appearanceModule ? 'resolved' : 'NOT resolved (null)'}`);
30
- }
31
- return appearanceModule;
32
- }
33
- function getEmitter() {
34
- if (emitter === undefined) {
35
- // WHY lazy: install on first subscribe so the hub exists before native emits,
36
- // without a hard bootstrap-order dependency. Idempotent.
37
- installDeviceEventHub();
38
- const module = getModule();
39
- emitter = new NativeEventEmitter(module ?? undefined);
40
- // Keep the cached scheme fresh even when nobody is listening, so a later
41
- // getColorScheme() after a system change reads the new value. RN does the same.
21
+ // The self-subscription policy that diverges from a plain lazy-resolve+emitter:
22
+ // Appearance keeps `cachedScheme` fresh forever via a permanent change listener, so a
23
+ // later getColorScheme() after a system change reads the new value even with nobody
24
+ // else listening. RN does the same.
25
+ const deviceEventModule = createDeviceEventModule({
26
+ moduleName: APPEARANCE_MODULE,
27
+ moduleLogPrefix: 'Appearance: module',
28
+ onEmitterCreated: emitter => {
42
29
  emitter.addListener(APPEARANCE_CHANGED_EVENT, payload => {
43
30
  if (!isAppearancePreferences(payload))
44
31
  return;
45
32
  dlog(`Appearance: ${APPEARANCE_CHANGED_EVENT} -> ${String(payload.colorScheme)}`);
46
33
  cachedScheme = payload.colorScheme;
47
34
  });
48
- }
49
- return emitter;
35
+ },
36
+ });
37
+ function getModule() {
38
+ return deviceEventModule.getModule();
39
+ }
40
+ function getEmitter() {
41
+ return deviceEventModule.getEmitter();
50
42
  }
51
43
  export const Appearance = {
52
44
  // The current color scheme, or null when no module is linked / the device is in
@@ -6,8 +6,8 @@
6
6
  // Android-only by intent: iOS has no hardware back button, so the whole module
7
7
  // degrades to a no-op when the native module is absent, matching RN's
8
8
  // BackHandler.ios.js stub. Mirrors RN's Libraries/Utilities/BackHandler.android.js.
9
- import { getNativeModule } from '../native-modules.js';
10
- import { installDeviceEventHub, NativeEventEmitter, } from '../native-events.js';
9
+ import { createDeviceEventModule } from '../native-modules.js';
10
+ import {} from '../native-events.js';
11
11
  import { dlog } from '../debug.js';
12
12
  // The native module name RN registers this under. NOTE: this is the name the
13
13
  // INativeDeviceEventManager spec resolves via
@@ -31,25 +31,22 @@ function isHandled(result) {
31
31
  // Lazily resolved so importing this module has no native side effect: a headless
32
32
  // run without a fake __turboModuleProxy still loads it; resolution happens on the
33
33
  // first use. `null` when the module isn't linked (e.g. iOS).
34
- let deviceEventManager;
35
- let emitter;
34
+ //
35
+ // The self-subscription policy that diverges from a plain lazy-resolve+emitter:
36
+ // BackHandler wires the native back-press event to the reverse-order chain exactly
37
+ // once, permanently.
38
+ const deviceEventModule = createDeviceEventModule({
39
+ moduleName: DEVICE_EVENT_MANAGER_MODULE,
40
+ moduleLogPrefix: 'BackHandler: module',
41
+ onEmitterCreated: emitter => {
42
+ emitter.addListener(DEVICE_BACK_EVENT, dispatchBackPress);
43
+ },
44
+ });
36
45
  function getModule() {
37
- if (deviceEventManager === undefined) {
38
- deviceEventManager = getNativeModule(DEVICE_EVENT_MANAGER_MODULE);
39
- dlog(`BackHandler: module ${deviceEventManager ? 'resolved' : 'NOT resolved (null)'}`);
40
- }
41
- return deviceEventManager;
46
+ return deviceEventModule.getModule();
42
47
  }
43
48
  function getEmitter() {
44
- if (emitter === undefined) {
45
- // WHY lazy: install on first subscribe so the hub exists before native emits,
46
- // without a hard bootstrap-order dependency. Idempotent.
47
- installDeviceEventHub();
48
- emitter = new NativeEventEmitter(getModule() ?? undefined);
49
- // Wire the native back-press event to the reverse-order chain exactly once.
50
- emitter.addListener(DEVICE_BACK_EVENT, dispatchBackPress);
51
- }
52
- return emitter;
49
+ return deviceEventModule.getEmitter();
53
50
  }
54
51
  // Run handlers last-registered-first; the first to return true consumes the press
55
52
  // and the rest are skipped. If none consume it, fall through to the native default.
package/build/commit.d.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  import { type IFabricNode, type IRootTag, type IMeasureOnSuccess, type IMeasureInWindowOnSuccess, type IMeasureLayoutOnSuccess } from './fabric';
2
2
  import { type ISymbioteNode } from './node';
3
- import { type IColorValue } from './platform-color';
4
- export declare function setColorProcessor(process: (value: IColorValue) => unknown): void;
5
- export declare function processColor(color: IColorValue): unknown;
3
+ export { processColor, setColorProcessor } from './platform-color';
6
4
  export declare function disposeRoot(rootTag: IRootTag): void;
7
5
  export declare function commitChildren(rootTag: IRootTag, children: readonly ISymbioteNode[]): void;
8
6
  export declare function setNativeProps(node: ISymbioteNode, partial: Record<string, unknown>): void;