@symbiote-native/engine 0.1.1 → 0.1.3

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 (85) hide show
  1. package/README.md +10 -0
  2. package/build/accessibility-info/index.android.js +8 -9
  3. package/build/accessibility-info/index.ios.js +8 -9
  4. package/build/accessibility-info/index.js +1 -1
  5. package/build/accessibility-info/shared.js +2 -1
  6. package/build/action-sheet-ios/index.js +4 -4
  7. package/build/alert/index.android.js +9 -9
  8. package/build/alert/index.ios.js +5 -5
  9. package/build/alert/index.js +2 -2
  10. package/build/alert/shared.js +1 -1
  11. package/build/animated/animated-component-shared.js +3 -4
  12. package/build/animated/animations/base.js +5 -5
  13. package/build/animated/animations/composition.js +9 -9
  14. package/build/animated/animations/decay.js +5 -5
  15. package/build/animated/animations/spring.js +5 -5
  16. package/build/animated/animations/timing.js +5 -5
  17. package/build/animated/animations/tracking.js +1 -1
  18. package/build/animated/color.js +2 -2
  19. package/build/animated/easing.js +1 -1
  20. package/build/animated/event.js +5 -5
  21. package/build/animated/graph.js +3 -4
  22. package/build/animated/index.js +24 -24
  23. package/build/animated/interpolation-node.js +2 -2
  24. package/build/animated/interpolation.js +2 -2
  25. package/build/animated/mock.js +8 -8
  26. package/build/animated/native/native-animated.js +6 -6
  27. package/build/animated/operators.js +4 -4
  28. package/build/animated/props.js +10 -10
  29. package/build/animated/style.js +5 -5
  30. package/build/animated/value-xy.js +2 -2
  31. package/build/animated/value.js +4 -4
  32. package/build/app-registry/index.js +2 -2
  33. package/build/app-state/index.js +3 -3
  34. package/build/appearance/index.js +3 -3
  35. package/build/back-handler/index.js +5 -6
  36. package/build/commit.js +21 -21
  37. package/build/dimensions/index.js +4 -5
  38. package/build/events/index.js +5 -5
  39. package/build/fabric.js +1 -1
  40. package/build/host-instance/index.js +3 -3
  41. package/build/i18n-manager/index.js +4 -5
  42. package/build/index.js +49 -49
  43. package/build/interaction-manager/index.js +1 -1
  44. package/build/keyboard/index.js +5 -5
  45. package/build/layout-animation/index.js +3 -4
  46. package/build/linking/index.android.js +2 -2
  47. package/build/linking/index.ios.js +1 -1
  48. package/build/linking/index.js +2 -2
  49. package/build/linking/shared.js +4 -4
  50. package/build/native-events.js +3 -3
  51. package/build/native-modules.js +2 -2
  52. package/build/node.js +5 -4
  53. package/build/pan-responder/index.js +1 -1
  54. package/build/permissions-android/index.js +5 -6
  55. package/build/pixel-ratio/index.js +1 -1
  56. package/build/platform/index.android.js +2 -2
  57. package/build/platform/index.ios.js +2 -2
  58. package/build/platform/index.js +1 -2
  59. package/build/platform/shared.js +2 -3
  60. package/build/process-aspect-ratio.js +1 -1
  61. package/build/process-background-image/index.js +3 -3
  62. package/build/process-box-shadow/index.js +3 -3
  63. package/build/process-filter.js +3 -3
  64. package/build/process-transform/index.js +1 -1
  65. package/build/process-transform-origin/index.js +1 -1
  66. package/build/settings/index.js +5 -7
  67. package/build/share/index.android.js +4 -5
  68. package/build/share/index.ios.js +4 -4
  69. package/build/share/index.js +2 -2
  70. package/build/share/shared.js +1 -1
  71. package/build/status-bar/index.android.js +5 -5
  72. package/build/status-bar/index.ios.js +4 -5
  73. package/build/status-bar/index.js +1 -1
  74. package/build/status-bar/shared.js +1 -1
  75. package/build/style-registry/index.js +12 -16
  76. package/build/style-sheet/index.js +3 -3
  77. package/build/surface.js +3 -3
  78. package/build/text-input-state.js +2 -2
  79. package/build/toast-android/index.js +5 -5
  80. package/build/vibration/index.android.js +2 -3
  81. package/build/vibration/index.ios.js +1 -1
  82. package/build/vibration/index.js +2 -2
  83. package/build/vibration/shared.js +6 -7
  84. package/build/view-config.js +1 -1
  85. package/package.json +2 -2
@@ -2,8 +2,8 @@
2
2
  // is the static 'ios'; everything else derives from the PlatformConstants native module
3
3
  // (RN spec NativePlatformConstantsIOS.js), read lazily and cached via the shared
4
4
  // resolver. Metro picks this on an iOS host; it is also the base re-export target
5
- // (platform.ts) so tsc / tsx / web (no Metro) land here too. See .docs/decisions/0022.
6
- import { createConstantsResolver, UNKNOWN_VERSION, } from './shared';
5
+ // (platform.ts) so tsc / tsx / web (no Metro) land here too.
6
+ import { createConstantsResolver, UNKNOWN_VERSION, } from './shared.js';
7
7
  // interfaceIdiom values RN compares against for the device-class getters.
8
8
  const IDIOM_PAD = 'pad';
9
9
  const IDIOM_TV = 'tv';
@@ -1,5 +1,4 @@
1
1
  // Base / default Platform: re-exports the iOS implementation. Metro overrides this
2
2
  // with platform.ios.ts / platform.android.ts on a real host; under tsc / tsx / web
3
3
  // (no Metro) resolution lands here. The filename is the selector, no Platform.OS read.
4
- // See .docs/decisions/0022 (and 0020 for the same split on component names).
5
- export * from './index.ios';
4
+ export * from './index.ios.js';
@@ -4,9 +4,8 @@
4
4
  // owns only what genuinely differs: the OS literal, the constants shape + guard, the
5
5
  // select precedence, and the device-class getters. The filename is the selector (Metro
6
6
  // picks platform.ios / platform.android by host); no Platform.OS read lives here.
7
- // See .docs/decisions/0022 (and 0020 for the same split on component names).
8
- import { dlog } from '../debug';
9
- import { getNativeModule } from '../native-modules';
7
+ import { dlog } from '../debug.js';
8
+ import { getNativeModule } from '../native-modules.js';
10
9
  // The native module name RN registers PlatformConstants under, identical on both
11
10
  // platforms; only getConstants()'s SHAPE differs, which each platform file guards.
12
11
  export const PLATFORM_CONSTANTS = 'PlatformConstants';
@@ -5,7 +5,7 @@
5
5
  // already-working form) passes through untouched; this is a no-op for it.
6
6
  //
7
7
  // RN throws via invariant() in __DEV__ on a malformed value; we dlog and return undefined.
8
- import { dlog } from './debug';
8
+ import { dlog } from './debug.js';
9
9
  // RN processAspectRatio.js:15-63. number → number; ratio string → number; invalid → undefined.
10
10
  export function processAspectRatio(aspectRatio) {
11
11
  if (typeof aspectRatio === 'number') {
@@ -7,9 +7,9 @@
7
7
  // processColor is referenced from ../commit at RUNTIME only (inside function bodies), never at
8
8
  // module-init, so the cyclic import (commit -> here -> commit) has no TDZ hazard — same pattern
9
9
  // as process-box-shadow/process-filter.
10
- import { processColor } from '../commit';
11
- import { isOpaqueColorValue } from '../platform-color';
12
- import { dlog } from '../debug';
10
+ import { processColor } from '../commit.js';
11
+ import { isOpaqueColorValue } from '../platform-color.js';
12
+ import { dlog } from '../debug.js';
13
13
  // RN processBackgroundImage.js: pre-compiled patterns.
14
14
  const NEWLINE_REGEX = /\n/g;
15
15
  const GRADIENT_REGEX = /^(linear|radial)-gradient\(((?:\([^)]*\)|[^()])*)\)/;
@@ -7,9 +7,9 @@
7
7
  //
8
8
  // processColor is referenced from ./commit at RUNTIME only (inside the function bodies),
9
9
  // never at module-init, so the cyclic import (commit -> here -> commit) has no TDZ hazard.
10
- import { processColor } from '../commit';
11
- import { isOpaqueColorValue } from '../platform-color';
12
- import { dlog } from '../debug';
10
+ import { processColor } from '../commit.js';
11
+ import { isOpaqueColorValue } from '../platform-color.js';
12
+ import { dlog } from '../debug.js';
13
13
  // RN processBoxShadow.js:16-19: split args only on the delimiters that are NOT inside
14
14
  // a parenthesized color like rgba(0,0,0,1).
15
15
  const COMMA_SPLIT_REGEX = /,(?![^()]*\))/;
@@ -7,9 +7,9 @@
7
7
  //
8
8
  // processColor is referenced from ./commit at RUNTIME only (inside function bodies),
9
9
  // never at module-init, so the cyclic import (commit -> here -> commit) has no TDZ hazard.
10
- import { processColor } from './commit';
11
- import { isOpaqueColorValue } from './platform-color';
12
- import { dlog } from './debug';
10
+ import { processColor } from './commit.js';
11
+ import { isOpaqueColorValue } from './platform-color.js';
12
+ import { dlog } from './debug.js';
13
13
  // RN processFilter.js:19-24: pre-compiled patterns.
14
14
  const NEWLINE_REGEX = /\n/g;
15
15
  const FILTER_FUNCTION_REGEX = /([\w-]+)\(([^()]*|\([^()]*\)|[^()]*\([^()]*\)[^()]*)\)/g;
@@ -14,7 +14,7 @@
14
14
  // _validateTransforms, which is __DEV__-only and THROWS via invariant; we never throw
15
15
  // into the commit path, so we run a non-throwing check that dlogs and still returns the
16
16
  // array unchanged (matching the boxShadow/transformOrigin idiom).
17
- import { dlog } from '../debug';
17
+ import { dlog } from '../debug.js';
18
18
  // RN processTransform.js:28: matches each `name(args)` in the CSS string.
19
19
  const TRANSFORM_REGEX = /(\w+)\(([^)]+)\)/g;
20
20
  // RN processTransform.js:59: splits one arg into [, number, , unit?].
@@ -9,7 +9,7 @@
9
9
  //
10
10
  // RN throws via invariant() on a malformed value; we instead dlog and keep the partial array
11
11
  // (matching the boxShadow/filter idiom of never throwing into the commit path).
12
- import { dlog } from '../debug';
12
+ import { dlog } from '../debug.js';
13
13
  // RN processTransformOrigin.js:14, pre-compiled pattern matching each keyword / length token.
14
14
  const TRANSFORM_ORIGIN_REGEX = /(top|bottom|left|right|center|\d+(?:%|px)|0)/gi;
15
15
  // RN processTransformOrigin.js:16-18.
@@ -5,15 +5,13 @@
5
5
  // watched key's value changes. Native re-broadcasts external edits through the
6
6
  // device event `settingsUpdated`, which feeds the same change->fire path. Mirrors
7
7
  // RN's Libraries/Settings/Settings.ios.js, iOS surface only.
8
- import { installDeviceEventHub, NativeEventEmitter, } from '../native-events';
9
- import { getNativeModule } from '../native-modules';
10
- import { dlog } from '../debug';
8
+ import { installDeviceEventHub, NativeEventEmitter, } from '../native-events.js';
9
+ import { getNativeModule } from '../native-modules.js';
10
+ import { dlog } from '../debug.js';
11
11
  // The iOS native module name RN registers this under. NOTE: this is the name the
12
12
  // iOS JS wrapper resolves via `TurboModuleRegistry.getEnforcing('SettingsManager')`.
13
- // The spec filename is `INativeSettingsManager`. Per the symbiote invariant, a
14
- // module name is only provable on a real host (a headless fake answers to any
15
- // name); this iOS name is device-verify-pending.
16
- // See .docs/native-module-platform-routing.md.
13
+ // The spec filename is `INativeSettingsManager`. A module name is only provable on a
14
+ // real host (a headless fake answers to any name); this iOS name is device-verify-pending.
17
15
  const SETTINGS_MODULE = 'SettingsManager';
18
16
  // The device event native emits when the app's defaults change out from under JS
19
17
  // (e.g. a Settings.bundle edit). Its payload is a record of changed key->value.
@@ -2,15 +2,14 @@
2
2
  // `share(content, dialogTitle?) -> Promise<{ action }>`. We validate content, build the
3
3
  // content dict (title/message), forward the dialog title, and map the resolved action
4
4
  // onto the shared IShareAction shape; Android has no dismiss path, so RN fills the
5
- // missing activityType with null. Metro picks this file on an Android host. See ADR 0019.
5
+ // missing activityType with null. Metro picks this file on an Android host.
6
6
  //
7
7
  // device-verify-pending: the `ShareModule` name matches NativeShareModule's
8
8
  // TurboModuleRegistry.get('ShareModule') from RN source, but headless fakes resolve any
9
9
  // name, so it is only proven on a real Android host (a bridgeless resolution log there).
10
- // See .docs/native-module-platform-routing.md, ADR 0012.
11
- import { dlog } from '../debug';
12
- import { getNativeModule } from '../native-modules';
13
- import { validateContent, shareActions, SHARED_ACTION, DISMISSED_ACTION } from './shared';
10
+ import { dlog } from '../debug.js';
11
+ import { getNativeModule } from '../native-modules.js';
12
+ import { validateContent, shareActions, SHARED_ACTION, DISMISSED_ACTION } from './shared.js';
14
13
  const SHARE_MODULE = 'ShareModule';
15
14
  // ShareModule.share resolves an untyped value at the native boundary; narrow it before
16
15
  // reading `action` (no `as`).
@@ -3,10 +3,10 @@
3
3
  // `showShareActionSheetWithOptions(options, failure, success)`. We validate content, map
4
4
  // options onto the native share options, and resolve the IShareAction from the success
5
5
  // callback. Metro picks this file on an iOS host; the base share.ts re-exports it for
6
- // web/headless. See ADR 0019.
7
- import { dlog } from '../debug';
8
- import { getNativeModule } from '../native-modules';
9
- import { validateContent, shareActions, SHARED_ACTION, DISMISSED_ACTION } from './shared';
6
+ // web/headless.
7
+ import { dlog } from '../debug.js';
8
+ import { getNativeModule } from '../native-modules.js';
9
+ import { validateContent, shareActions, SHARED_ACTION, DISMISSED_ACTION } from './shared.js';
10
10
  const ACTION_SHEET_MANAGER = 'ActionSheetManager';
11
11
  export const Share = {
12
12
  ...shareActions,
@@ -2,5 +2,5 @@
2
2
  // platform file). Metro overrides this with share.ios.ts / share.android.ts on a real
3
3
  // iOS/Android host; off those, the iOS build is the fallback (its ActionSheetManager
4
4
  // resolves null elsewhere → graceful reject). The barrel imports './share', which
5
- // resolves here under tsc/tsx and to the platform file under Metro. See ADR 0019.
6
- export * from './index.ios';
5
+ // resolves here under tsc/tsx and to the platform file under Metro.
6
+ export * from './index.ios.js';
@@ -6,7 +6,7 @@
6
6
  //
7
7
  // Metro selects the platform file on a real host (share.android.ts > share.ts); the base
8
8
  // share.ts re-exports the iOS build for web/headless. There is no runtime `Platform.OS`
9
- // read: the filename is the selector. See ADR 0019.
9
+ // read: the filename is the selector.
10
10
  // RN's Share action constants (RN Share.js ~173/179). These back the documented
11
11
  // `result.action === Share.dismissedAction` pattern. True statically-known literals,
12
12
  // so CONSTANT_CASE; the public fields (Share.sharedAction / Share.dismissedAction) are
@@ -9,11 +9,11 @@
9
9
  // not installed" because RN installs global.RN$stopSurface from its own renderer, which we
10
10
  // replace. Now that render.ts installs RN$stopSurface and tears surfaces down cleanly, the
11
11
  // relayout survives and the bar updates without blanking (verified on device: show/hide +
12
- // light/dark text). See render.ts installStopSurfaceGlobal + native-module-platform-routing.
13
- import { getNativeModule } from '../native-modules';
14
- import { processColor } from '../commit';
15
- import { dlog } from '../debug';
16
- import { STATUS_BAR_MANAGER } from './shared';
12
+ // light/dark text). See render.ts's installStopSurfaceGlobal.
13
+ import { getNativeModule } from '../native-modules.js';
14
+ import { processColor } from '../commit.js';
15
+ import { dlog } from '../debug.js';
16
+ import { STATUS_BAR_MANAGER } from './shared.js';
17
17
  // processColor returns `unknown` (its result is platform-dependent); narrow to the
18
18
  // number Fabric/native expects, like RN's invariant before setColor. A non-number
19
19
  // (null for an unparseable color, headless identity passthrough of a string) is dropped.
@@ -1,7 +1,6 @@
1
1
  // StatusBar on iOS drives the iOS `StatusBarManager` TurboModule from props (via
2
2
  // applyStatusBarProps) and from the static methods (statusBarImperative). The native
3
- // contract is RN's spec at
4
- // .vendors/react-native/.../src/private/specs_DEPRECATED/modules/NativeStatusBarManagerIOS.js:
3
+ // contract mirrors RN's own NativeStatusBarManagerIOS spec:
5
4
  // setStyle(statusBarStyle?: string, animated: boolean)
6
5
  // setHidden(hidden: boolean, withAnimation: 'none' | 'fade' | 'slide')
7
6
  // setNetworkActivityIndicatorVisible(visible: boolean)
@@ -9,9 +8,9 @@
9
8
  // boundary getNativeModule<T> resolves against. Metro picks this on an iOS host; the base
10
9
  // status-bar.ts re-exports it for tsc / tsx / headless. Each adapter wraps these with its own
11
10
  // declarative component.
12
- import { getNativeModule } from '../native-modules';
13
- import { dlog } from '../debug';
14
- import { STATUS_BAR_MANAGER, STATIC_HIDE_TRANSITION, hideTransition, } from './shared';
11
+ import { getNativeModule } from '../native-modules.js';
12
+ import { dlog } from '../debug.js';
13
+ import { STATUS_BAR_MANAGER, STATIC_HIDE_TRANSITION, hideTransition, } from './shared.js';
15
14
  // Apply a StatusBar component's props to the native module. The adapter calls this from its
16
15
  // declarative component's effect, on mount and on every prop change. Resolves lazily inside
17
16
  // the call, not at import; keeps this module importable headless before a fake
@@ -1,4 +1,4 @@
1
1
  // Base / default StatusBar engine surface; re-exports the iOS build. Metro overrides this
2
2
  // with status-bar.ios.ts / .android.ts on a real host; under tsx / tsc / web the host config
3
3
  // resolves here. Filename is the selector, no Platform.OS read. See status-bar-shared.ts.
4
- export * from './index.ios';
4
+ export * from './index.ios.js';
@@ -6,7 +6,7 @@
6
6
  // flags from our bridgeless surface blanks it (a window-insets relayout detaches the Fabric
7
7
  // surface). So the .ios/.android files own the native calls (applyStatusBarProps +
8
8
  // statusBarImperative); the types + the framework-agnostic imperative surface live here.
9
- // Filename selects, no Platform.OS read (see ADR 0012 + native_module_name_is_platform_specific).
9
+ // Filename selects, no Platform.OS read.
10
10
  //
11
11
  // This is the engine half: pure types + the imperative API. Each adapter wraps it with a
12
12
  // per-framework declarative component (React FC + useEffect, Vue defineComponent + watchEffect)
@@ -1,20 +1,17 @@
1
- // Runtime style registry, ported from wolf-tui's internal/shared/src/styles/registry.ts.
2
- // Side-effect CSS imports (compiled by the sibling CSS-to-style build package, not
3
- // this module) call registerStyles() with camelCase keys; components look them up
4
- // by resolveClassName(). No CSS parsing happens here — this is a Map<string, ...>
5
- // lookup, nothing more.
1
+ // Runtime style registry. Side-effect CSS imports (compiled by the sibling CSS-to-style
2
+ // build package, not this module) call registerStyles() with camelCase keys; components
3
+ // look them up by resolveClassName(). No CSS parsing happens here — this is a
4
+ // Map<string, ...> lookup, nothing more.
6
5
  //
7
- // Dropped vs the wolf-tui original: all Tailwind-utility detection (registerTailwind-
8
- // Metadata / isTailwindUtility / custom prefix-static sets) — this repo's style
9
- // surface has no Tailwind layer, so compound lookup below always runs for 2-4-part
10
- // class strings instead of being gated behind "no part looks like a utility class".
6
+ // This registry has no Tailwind-utility detection layer — this repo's style surface has
7
+ // no Tailwind layer, so the compound lookup below always runs for 2-4-part class strings
8
+ // instead of being gated behind "no part looks like a utility class".
11
9
  //
12
10
  // kebab-case authoring: a CSS selector `.section-label` always registers under the
13
11
  // camelCase key `sectionLabel` (@symbiote-native/css-parser's extractClassName), so a template
14
12
  // can write EITHER `class="sectionLabel"` OR `class="section-label"` — resolveOne below
15
- // falls back to the kebab->camel form on a miss. Reinstated (wolf-tui had this, an
16
- // earlier port here dropped it on the assumption authors would always match the
17
- // camelCase key exactly) once that assumption proved wrong in practice.
13
+ // falls back to the kebab->camel form on a miss. The fallback matters because assuming
14
+ // authors would always match the camelCase key exactly proved wrong in practice.
18
15
  // Compound lookup tries every ordering of 2-4 space-separated class parts joined by
19
16
  // '.' (e.g. "btn primary" -> "btn.primary" / "primary.btn") before falling back to a
20
17
  // per-class merge, mirroring CSS compound-selector registration (`.btn.primary { }`).
@@ -93,10 +90,9 @@ function generateKPermutations(parts, size) {
93
90
  helper([], parts, 0);
94
91
  return result;
95
92
  }
96
- // wolf-tui joins a compound permutation with '.' ("btn.primary") because its CSS
97
- // pipeline registers dot-joined selector strings. This repo's CSS-to-style compiler
98
- // emits plain camelCase keys for every class, single or compound, so "btn primary"
99
- // must resolve against a registered "btnPrimary" instead.
93
+ // Compound permutations join as camelCase ("btn primary" -> "btnPrimary") because this
94
+ // repo's CSS-to-style compiler emits plain camelCase keys for every class, single or
95
+ // compound, so "btn primary" must resolve against a registered "btnPrimary".
100
96
  function toCompoundKey(parts) {
101
97
  return parts.reduce((key, part, index) => (index === 0 ? part : key + capitalize(part)), '');
102
98
  }
@@ -4,9 +4,9 @@
4
4
  // array, `compose` picks/pairs two styles, plus the `hairlineWidth` / `absoluteFill`
5
5
  // constants. The typed ViewStyle/TextStyle live next door in styles.ts, so `create`
6
6
  // is typed against them like RN's, not left generic over a plain Record.
7
- import { dlog } from '../debug';
8
- import { getNativeModule } from '../native-modules';
9
- import { flattenStyle } from '../style';
7
+ import { dlog } from '../debug.js';
8
+ import { getNativeModule } from '../native-modules.js';
9
+ import { flattenStyle } from '../style/index.js';
10
10
  // RN's hairline factor: a "1 physical pixel" line is ~0.4 logical px, rounded to the
11
11
  // nearest device pixel. Named so the 0.4 isn't a bare magic number (RN source uses
12
12
  // the same literal in PixelRatio.roundToNearestPixel(0.4)).
package/build/surface.js CHANGED
@@ -1,9 +1,9 @@
1
1
  // A surface is one mounted root: it owns the rootTag handed down by the native
2
2
  // Fabric host and the list of top-level retained nodes. Adapters mutate it and
3
3
  // ask it to commit; the surface coalesces commits and drives the engine.
4
- import { commitChildren } from './commit';
5
- import { dlog } from './debug';
6
- import { installEventHandler } from './events';
4
+ import { commitChildren } from './commit.js';
5
+ import { dlog } from './debug.js';
6
+ import { installEventHandler } from './events/index.js';
7
7
  export class SymbioteSurface {
8
8
  rootTag;
9
9
  children = [];
@@ -2,8 +2,8 @@
2
2
  // JS-side because native exposes no focus getter. TextInput reports focus/blur here so
3
3
  // Keyboard.dismiss can blur whatever holds focus without a ref, exactly how RN's
4
4
  // dismissKeyboard() works (blurTextInput(currentlyFocusedInput())).
5
- import { dispatchViewCommand } from './commit';
6
- import { dlog } from './debug';
5
+ import { dispatchViewCommand } from './commit.js';
6
+ import { dlog } from './debug.js';
7
7
  let currentlyFocused = null;
8
8
  // The input that last reported focus and hasn't reported blur, or null.
9
9
  export function currentlyFocusedInput() {
@@ -13,13 +13,13 @@
13
13
  // show(message: string, duration: number)
14
14
  // showWithGravity(message: string, duration: number, gravity: number)
15
15
  // showWithGravityAndOffset(message, duration, gravity, xOffset, yOffset)
16
- import { dlog } from '../debug';
17
- import { getNativeModule } from '../native-modules';
16
+ import { dlog } from '../debug.js';
17
+ import { getNativeModule } from '../native-modules.js';
18
18
  // The native module name RN registers this under. NOTE: this is the name the spec
19
19
  // resolves via `TurboModuleRegistry.getEnforcing<Spec>('ToastAndroid')`, NOT the
20
- // spec filename `INativeToastAndroid`. Per the symbiote invariant, a module name is
21
- // only provable on a real host (a headless fake answers to any name); this Android
22
- // name is device-verify-pending. See .docs/native-module-platform-routing.md.
20
+ // spec filename `INativeToastAndroid`. A module name is only provable on a real
21
+ // host (a headless fake answers to any name); this Android name is confirmed from
22
+ // RN source but not yet exercised on a device.
23
23
  const TOAST_MODULE = 'ToastAndroid';
24
24
  // Conventional RN values for SHORT/LONG/TOP/BOTTOM/CENTER. On a real device the
25
25
  // numbers come from native getConstants() (resolved below); these are the fallbacks
@@ -5,9 +5,8 @@
5
5
  //
6
6
  // device-verify-pending: the `Vibration` name and the `vibrateByPattern` routing are
7
7
  // confirmed from RN source but not yet exercised on a real Android host: only a
8
- // bridgeless resolution log there can prove the name. See
9
- // .docs/native-module-platform-routing.md.
10
- import { createVibration } from './shared';
8
+ // bridgeless resolution log there can prove the name.
9
+ import { createVibration } from './shared.js';
11
10
  // RN encodes "do not repeat" as -1 and "repeat from start" as 0 in vibrateByPattern.
12
11
  const REPEAT_NONE = -1;
13
12
  const REPEAT_FROM_START = 0;
@@ -3,7 +3,7 @@
3
3
  // Everything else (the single-number buzz, cancel, the module resolver) is the shared
4
4
  // core. Metro picks this file on an iOS host; the base vibration.ts re-exports it for
5
5
  // web/headless.
6
- import { createVibration, DEFAULT_VIBRATION_LENGTH } from './shared';
6
+ import { createVibration, DEFAULT_VIBRATION_LENGTH } from './shared.js';
7
7
  // JS scheduler state, mirroring RN's _vibrating / _id. `scheduleId` guards against a
8
8
  // stale timer from a previous run firing into a new one.
9
9
  let vibrating = false;
@@ -2,5 +2,5 @@
2
2
  // platform file). Metro overrides this with vibration.ios.ts / vibration.android.ts on a
3
3
  // real iOS/Android host; off those, the iOS build is the fallback (its Vibration module
4
4
  // resolves null elsewhere → graceful no-op). The barrel imports './vibration', which
5
- // resolves here under tsc/tsx and to the platform file under Metro. See ADR 0019.
6
- export * from './index.ios';
5
+ // resolves here under tsc/tsx and to the platform file under Metro.
6
+ export * from './index.ios.js';
@@ -5,19 +5,18 @@
5
5
  // `createVibration`. Mirrors RN's Libraries/Vibration/Vibration.js: a number is a single
6
6
  // buzz, an array is a pattern.
7
7
  //
8
- // Native module name is `Vibration` on BOTH iOS and Android (see
9
- // .docs/native-module-platform-routing.md), so unlike Linking the module name is shared,
10
- // not divergent. The TurboModule spec lives at specs_DEPRECATED/modules/INativeVibration.js:
8
+ // Native module name is `Vibration` on BOTH iOS and Android, so unlike Linking the
9
+ // module name is shared, not divergent. The TurboModule spec lives at
10
+ // specs_DEPRECATED/modules/INativeVibration.js:
11
11
  // vibrate(pattern: number)
12
12
  // vibrateByPattern(pattern: number[], repeat: number)
13
13
  // cancel()
14
14
  //
15
15
  // Metro selects the platform file on a real host (vibration.android.ts > vibration.ts);
16
16
  // the base vibration.ts re-exports the iOS build for web/headless. There is no runtime
17
- // `Platform.OS` read; the filename is the selector. See ADR 0019. No Fabric view,
18
- // pure JS->native.
19
- import { dlog } from '../debug';
20
- import { getNativeModule } from '../native-modules';
17
+ // `Platform.OS` read; the filename is the selector. No Fabric view, pure JS->native.
18
+ import { dlog } from '../debug.js';
19
+ import { getNativeModule } from '../native-modules.js';
21
20
  const VIBRATION_MODULE = 'Vibration';
22
21
  // RN's _default_vibration_length: the single-buzz duration when no pattern is given,
23
22
  // and the per-segment buzz length the iOS scheduler emits between waits.
@@ -11,7 +11,7 @@
11
11
  // reaches Fabric). Structural adapters (Svelte `addEventListener`, Angular
12
12
  // `Renderer2.listen`) deliver events pre-separated and call `setEventListener`
13
13
  // directly, bypassing this entirely.
14
- import { isRegisteredEvent } from './registry';
14
+ import { isRegisteredEvent } from './registry.js';
15
15
  // Accessibility events from RN's base ViewConfig: every view can emit them.
16
16
  // accessibilityAction fires on iOS + Android; the other three are iOS-only and inert
17
17
  // on Android (no native producer), exactly like `scrollToTop` below.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/engine",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "SymbioteNative's retained shadow-tree engine — clone-on-write commit path + event normalization over React Native Fabric, shared by every framework adapter.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,7 +32,7 @@
32
32
  "react-native": ">=0.86"
33
33
  },
34
34
  "devDependencies": {
35
- "@symbiote-native/test-utils": "0.0.0"
35
+ "@symbiote-native/test-utils": "0.1.3"
36
36
  },
37
37
  "scripts": {
38
38
  "typecheck": "tsc --build",