@symbiote-native/react 1.0.0 → 2.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.
Files changed (100) hide show
  1. package/README.md +12 -11
  2. package/build/components/activity-indicator-props.d.ts +4 -0
  3. package/build/components/{button.d.ts → button-props.d.ts} +0 -2
  4. package/build/components/button-props.js +1 -0
  5. package/build/components/flat-list/index.js +2 -2
  6. package/build/components/image/image-props.d.ts +4 -0
  7. package/build/components/image/image-props.js +1 -0
  8. package/build/components/image-background-props.d.ts +9 -0
  9. package/build/components/image-background-props.js +1 -0
  10. package/build/components/input-accessory-view-props.d.ts +10 -0
  11. package/build/components/input-accessory-view-props.js +1 -0
  12. package/build/components/keyboard-avoiding-view/index.js +4 -4
  13. package/build/components/modal/index.js +3 -3
  14. package/build/components/pressable/{index.d.ts → pressable-props.d.ts} +4 -5
  15. package/build/components/pressable/pressable-props.js +1 -0
  16. package/build/components/{refresh-control/index.d.ts → refresh-control-props.d.ts} +3 -3
  17. package/build/components/refresh-control-props.js +1 -0
  18. package/build/components/safe-area-view-props.d.ts +11 -0
  19. package/build/components/safe-area-view-props.js +1 -0
  20. package/build/components/scroll-view/{shared.d.ts → scroll-view-props.d.ts} +4 -26
  21. package/build/components/scroll-view/scroll-view-props.js +1 -0
  22. package/build/components/switch/switch-props.d.ts +4 -0
  23. package/build/components/switch/switch-props.js +1 -0
  24. package/build/components/text-input/text-input-props.d.ts +4 -0
  25. package/build/components/text-input/text-input-props.js +1 -0
  26. package/build/components/touchable/touchable-props.d.ts +17 -0
  27. package/build/components/touchable/touchable-props.js +1 -0
  28. package/build/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +8 -0
  29. package/build/components/touchable-native-feedback/touchable-native-feedback-props.js +1 -0
  30. package/build/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +6 -0
  31. package/build/components/touchable-without-feedback/touchable-without-feedback-props.js +1 -0
  32. package/build/components/virtualized-list/index.js +83 -38
  33. package/build/components.d.ts +1 -2
  34. package/build/components.js +5 -19
  35. package/build/create-portal/index.js +1 -1
  36. package/build/create-tunnel/index.js +1 -1
  37. package/build/descriptor-to-react/index.js +1 -1
  38. package/build/host-config.js +22 -4
  39. package/build/index.d.ts +23 -28
  40. package/build/index.js +14 -14
  41. package/build/jsx-dev-runtime.d.ts +3 -0
  42. package/build/jsx-dev-runtime.js +10 -0
  43. package/build/jsx-namespace.type-check.d.ts +1 -0
  44. package/build/jsx-namespace.type-check.js +7 -0
  45. package/build/jsx-runtime.d.ts +62 -0
  46. package/build/jsx-runtime.js +1 -0
  47. package/build/modules/animated/index.d.ts +0 -1
  48. package/build/modules/animated/index.js +16 -22
  49. package/build/modules/image/index.d.ts +3 -0
  50. package/build/modules/image/index.js +14 -0
  51. package/build/register.d.ts +1 -0
  52. package/build/register.js +15 -0
  53. package/metro-css-parser.cjs +2 -1
  54. package/package.json +12 -8
  55. package/build/components/activity-indicator/index.android.d.ts +0 -3
  56. package/build/components/activity-indicator/index.android.js +0 -17
  57. package/build/components/activity-indicator/index.d.ts +0 -1
  58. package/build/components/activity-indicator/index.ios.d.ts +0 -3
  59. package/build/components/activity-indicator/index.ios.js +0 -16
  60. package/build/components/activity-indicator/index.js +0 -4
  61. package/build/components/activity-indicator/shared.d.ts +0 -6
  62. package/build/components/activity-indicator/shared.js +0 -22
  63. package/build/components/button.js +0 -42
  64. package/build/components/image/index.d.ts +0 -9
  65. package/build/components/image/index.js +0 -28
  66. package/build/components/image-background/index.d.ts +0 -10
  67. package/build/components/image-background/index.js +0 -46
  68. package/build/components/input-accessory-view/index.d.ts +0 -11
  69. package/build/components/input-accessory-view/index.js +0 -19
  70. package/build/components/pressable/index.js +0 -112
  71. package/build/components/refresh-control/index.js +0 -21
  72. package/build/components/safe-area-view/index.d.ts +0 -12
  73. package/build/components/safe-area-view/index.js +0 -18
  74. package/build/components/scroll-view/index.android.d.ts +0 -3
  75. package/build/components/scroll-view/index.android.js +0 -61
  76. package/build/components/scroll-view/index.d.ts +0 -1
  77. package/build/components/scroll-view/index.ios.d.ts +0 -3
  78. package/build/components/scroll-view/index.ios.js +0 -29
  79. package/build/components/scroll-view/index.js +0 -4
  80. package/build/components/scroll-view/shared.js +0 -240
  81. package/build/components/scroll-view/sticky-header.d.ts +0 -18
  82. package/build/components/scroll-view/sticky-header.js +0 -227
  83. package/build/components/switch/index.android.d.ts +0 -3
  84. package/build/components/switch/index.android.js +0 -18
  85. package/build/components/switch/index.d.ts +0 -1
  86. package/build/components/switch/index.ios.d.ts +0 -3
  87. package/build/components/switch/index.ios.js +0 -16
  88. package/build/components/switch/index.js +0 -6
  89. package/build/components/switch/shared.d.ts +0 -9
  90. package/build/components/switch/shared.js +0 -60
  91. package/build/components/text-input/index.d.ts +0 -50
  92. package/build/components/text-input/index.js +0 -180
  93. package/build/components/touchable/index.d.ts +0 -22
  94. package/build/components/touchable/index.js +0 -165
  95. package/build/components/touchable-native-feedback/index.d.ts +0 -18
  96. package/build/components/touchable-native-feedback/index.js +0 -32
  97. package/build/jsx.d.ts +0 -18
  98. package/build/state-style.d.ts +0 -1
  99. package/build/state-style.js +0 -13
  100. /package/build/{jsx.js → components/activity-indicator-props.js} +0 -0
@@ -1,19 +1,5 @@
1
- // Host primitives exposed to user code. They ARE the intrinsic tags — a capitalized export whose
2
- // value is the tag string — so an app writes `<View>` and React commits a host element directly,
3
- // with no component instance in between. The reconciler maps the tag through
4
- // `descriptorFor` to a Fabric view name at commit.
5
- // `View` and `Text` are the intrinsic TAGS, not components wrapping them. JSX resolves a
6
- // capitalized tag to the value in scope, and a value that is a STRING is a host element to React —
7
- // so `<View/>` compiles to `_jsx('symbiote-view', …)` with no component instance, while
8
- // `JSX.IntrinsicElements['symbiote-view']` still supplies the strict props (a bad prop is TS2322).
9
- //
10
- // The two folds their component bodies used to apply both moved down a layer, which is what let
11
- // the bodies go:
12
- //
13
- // aria / accessibility the engine folds every node in `fabricProps` (accessibility-props.ts)
14
- // id -> nativeID, the renderer folds by spec in `host-config`'s createInstance
15
- // Text's defaults (`foldHostBag`, driven by HOST_PRIMITIVES)
16
- //
17
- // A type annotation rather than `as const`: same literal type, no cast (`ts-js-best-practices`).
18
- export const View = 'symbiote-view';
19
- export const Text = 'symbiote-text';
1
+ // The public PROP TYPES for the two strict intrinsics, and nothing else. There is no component and
2
+ // no capitalized alias: an app writes `<view>` / `<text>`, React commits a host element directly,
3
+ // and `JSX.IntrinsicElements` (jsx-runtime.ts) is what supplies these types to it. The reconciler
4
+ // maps the tag through `descriptorFor` to a Fabric view name at commit.
5
+ export {};
@@ -14,7 +14,7 @@ import { isSymbioteNode, SymbioteSurface, } from '@symbiote-native/engine';
14
14
  import reconciler from '../host-config.js';
15
15
  export function createPortal(children, container, key) {
16
16
  if (!(container instanceof SymbioteSurface) && !isSymbioteNode(container)) {
17
- throw new Error('createPortal target must be an already-mounted host node (e.g. a ref to a rendered <View>) — got something else. Did you forget `.current`/`.value`, or pass a CSS-selector-style string?');
17
+ throw new Error('createPortal target must be an already-mounted host node (e.g. a ref to a rendered <view>) — got something else. Did you forget `.current`/`.value`, or pass a CSS-selector-style string?');
18
18
  }
19
19
  // @ts-expect-error @types/react-reconciler's ReactPortal (containerInfo/implementation) and
20
20
  // react's own ReactPortal (type/props, a ReactElement) are different interfaces describing the
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "@symbiote-native/react/jsx-runtime";
2
2
  // createTunnel - the cross-surface answer to createPortal's same-surface-only scope. A real
3
3
  // createPortal cannot reach across two separate reconciler roots (see
4
4
  // github.com/facebook/react/issues/17147); the fix, same as pmndrs/tunnel-rat, is to not
@@ -1,6 +1,6 @@
1
1
  // The descriptor→element bridge. A render function in @symbiote-native/components returns a
2
2
  // framework-agnostic `Descriptor` tree; this maps it onto React elements. The resulting
3
- // host element (`symbiote-view`, `symbiote-activity-indicator`, …) flows on through the
3
+ // host element (`view`, `activity-indicator`, …) flows on through the
4
4
  // react-reconciler host config → engine → Fabric, exactly like a hand-written JSX host
5
5
  // element.
6
6
  import { createElement } from 'react';
@@ -99,17 +99,35 @@ const reconciler = createReconciler({
99
99
  },
100
100
  shouldSetTextContent: () => false,
101
101
  createInstance(type, props, _container, hostContext) {
102
- const descriptor = descriptorFor(resolveIntrinsicTag(type, props));
102
+ // The INTRINSIC tag, kept in a binding rather than inlined, because it is needed twice: once
103
+ // to resolve the Fabric view name and once to hand the engine below. The host-behavior
104
+ // registry is keyed by TAG and never by Fabric name — `pressable` and a plain `View`
105
+ // both resolve to `RCTView`, so keying by the resolved name would put a press machine on every
106
+ // view in the app (`core/engine/src/host-behavior.ts`).
107
+ const tag = resolveIntrinsicTag(type, props);
108
+ const descriptor = descriptorFor(tag);
103
109
  if (hostContext.isInsideText && !descriptor.isText) {
104
- throw new Error(`<${type}> can't be nested inside <Text>`);
110
+ throw new Error(`<${type}> can't be nested inside <text>`);
105
111
  }
106
- const node = createElement(descriptor.component, descriptor.isText);
112
+ // The third argument is what makes a host behavior reachable AT ALL on this adapter. Dropping
113
+ // it degrades silently: `createElement`'s default is `tag = component`, so the lookup runs
114
+ // against `RCTView` / `RCTImageView`, matches nothing, and every behavior simply never
115
+ // attaches — no throw, no log, and no test goes red, because React ships no `register` entry
116
+ // today and so has never had a behavior to lose. That absence is exactly what hid this: the
117
+ // other four adapters all pass it (vue `renderer/index.ts`, svelte `dom-shim/element.ts`,
118
+ // solid `renderer.ts`, angular `renderer/index.ts`), and React is the one that did not.
119
+ //
120
+ // Inert on landing and deliberately so — nothing registers a behavior under a tag React emits.
121
+ // The `-managed` split is what keeps it inert once something does: React's TextInput and
122
+ // Switch wrappers emit `text-input-managed` / `switch-managed`, so a machine
123
+ // registered on the lowered tag cannot also attach to a wrapper-built node and run twice.
124
+ const node = createElement(descriptor.component, descriptor.isText, tag);
107
125
  applyProps(node, foldHostBag(type, props));
108
126
  return node;
109
127
  },
110
128
  createTextInstance(text, _container, hostContext) {
111
129
  if (!hostContext.isInsideText) {
112
- throw new Error(`Text string "${text}" must be rendered inside a <Text>`);
130
+ throw new Error(`Text string "${text}" must be rendered inside a <text>`);
113
131
  }
114
132
  return createRawText(text);
115
133
  },
package/build/index.d.ts CHANGED
@@ -1,38 +1,32 @@
1
- export type { ISymbioteIntrinsicTag } from './jsx';
2
- export { View, Text } from './components';
1
+ import './register';
2
+ export type { ISymbioteIntrinsicTag } from './jsx-runtime';
3
3
  export type { IViewProps, ITextProps } from './components';
4
4
  export type { IAccessibilityProps, IAriaProps, IAccessibilityRole, IRole, IAccessibilityStateValue, IAccessibilityValue, IAccessibilityActionInfo, } from '@symbiote-native/components';
5
5
  export type { IResponderProps } from './utils/responder-props';
6
- export { Image, setImageSourceResolver } from './components/image';
7
- export type { IImageProps, IImageSource, IImageSourceProp, IResizeMode, IImageSize, IImageCacheStatus, } from './components/image';
8
- export { ImageBackground } from './components/image-background';
9
- export type { IImageBackgroundProps } from './components/image-background';
10
- export { ScrollView } from './components/scroll-view';
11
- export type { IScrollViewProps, IScrollViewHandle, } from './components/scroll-view';
12
- export { TextInput } from './components/text-input';
13
- export type { ITextInputProps, ITextInputHandle, } from './components/text-input';
14
- export { InputAccessoryView } from './components/input-accessory-view';
15
- export type { IInputAccessoryViewProps } from './components/input-accessory-view';
6
+ export { Image } from './modules/image';
7
+ export { setImageSourceResolver } from '@symbiote-native/components';
8
+ export type { IImageProps } from './components/image/image-props';
9
+ export type { IImageSource, IImageSourceProp, IResizeMode, IImageSize, IImageCacheStatus, } from '@symbiote-native/components';
10
+ export type { IImageBackgroundProps } from './components/image-background-props';
11
+ export type { IScrollViewProps, IScrollViewHandle, } from './components/scroll-view/scroll-view-props';
12
+ export type { ITextInputProps } from './components/text-input/text-input-props';
13
+ export type { ITextInputHandle, ITextInputChangeEvent, } from '@symbiote-native/components';
14
+ export type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
16
15
  export { KeyboardAvoidingView } from './components/keyboard-avoiding-view';
17
16
  export type { IKeyboardAvoidingViewProps, IKeyboardAvoidingBehavior, } from './components/keyboard-avoiding-view';
18
17
  export { StatusBar } from './modules/status-bar';
19
18
  export type { IStatusBarProps, IStatusBarStyle } from './modules/status-bar';
20
- export { Switch } from './components/switch';
21
- export type { ISwitchProps, ISwitchTrackColor } from './components/switch';
22
- export { ActivityIndicator } from './components/activity-indicator';
23
- export type { IActivityIndicatorProps } from './components/activity-indicator';
24
- export { SafeAreaView } from './components/safe-area-view';
25
- export type { ISafeAreaViewProps } from './components/safe-area-view';
26
- export { RefreshControl } from './components/refresh-control';
27
- export type { IRefreshControlProps } from './components/refresh-control';
19
+ export type { ISwitchProps } from './components/switch/switch-props';
20
+ export type { ISwitchTrackColor, ISwitchChangeEvent, } from '@symbiote-native/components';
21
+ export type { IActivityIndicatorProps } from './components/activity-indicator-props';
22
+ export type { ISafeAreaViewProps } from './components/safe-area-view-props';
23
+ export type { IRefreshControlProps } from './components/refresh-control-props';
28
24
  export { Modal } from './components/modal';
29
25
  export type { IModalProps, IModalAnimationType, IModalPresentationStyle, IModalOrientation, } from './components/modal';
30
- export { Pressable } from './components/pressable';
31
- export type { IPressableProps, IPressState } from './components/pressable';
32
- export { TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback, } from './components/touchable';
33
- export type { ITouchableOpacityProps, ITouchableHighlightProps, ITouchableWithoutFeedbackProps, } from './components/touchable';
34
- export { Button } from './components/button';
35
- export type { IButtonProps } from './components/button';
26
+ export type { IPressableProps, IPressState, } from './components/pressable/pressable-props';
27
+ export type { ITouchableOpacityProps, ITouchableHighlightProps, } from './components/touchable/touchable-props';
28
+ export type { ITouchableWithoutFeedbackProps } from './components/touchable-without-feedback/touchable-without-feedback-props';
29
+ export type { IButtonProps } from './components/button-props';
36
30
  export { FlatList } from './components/flat-list';
37
31
  export type { IFlatListProps, IFlatListHandle } from './components/flat-list';
38
32
  export { SectionList } from './components/section-list';
@@ -68,7 +62,8 @@ export { PanResponder } from '@symbiote-native/engine';
68
62
  export type { IPanResponderGestureState, IPanResponderCallbacks, IGestureResponderHandlers, IPanResponderInstance, } from '@symbiote-native/engine';
69
63
  export { InteractionManager } from '@symbiote-native/engine';
70
64
  export type { IInteractionEvent, ISimpleTask, IPromiseTask, ITask, IHandle, } from '@symbiote-native/engine';
71
- export { TouchableNativeFeedback } from './components/touchable-native-feedback';
72
- export type { ITouchableNativeFeedbackProps, INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from './components/touchable-native-feedback';
65
+ export { TouchableNativeFeedback } from '@symbiote-native/components';
66
+ export type { INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from '@symbiote-native/components';
67
+ export type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
73
68
  export type { ISymbioteEvent, ISymbioteNode, IRootTag, } from '@symbiote-native/engine';
74
69
  export type { ICellLayout, ISeparatorProps, ISeparators, IModalOrientationChangeEvent, IPressableAndroidRippleConfig, IEnterKeyHint, IInputMode, ISubmitBehavior, ITextInputSelection, IImageStatics, } from '@symbiote-native/components';
package/build/index.js CHANGED
@@ -1,22 +1,19 @@
1
1
  // @symbiote-native/react: a react-reconciler host config (mutation mode) over
2
2
  // @symbiote-native/engine. React is a known-good driver: it proves the native pipe
3
3
  // and the shared clone-on-write engine before any non-React adapter has to.
4
- export { View, Text } from './components.js';
5
- export { Image, setImageSourceResolver } from './components/image/index.js';
6
- export { ImageBackground } from './components/image-background/index.js';
7
- export { ScrollView } from './components/scroll-view';
8
- export { TextInput } from './components/text-input/index.js';
9
- export { InputAccessoryView } from './components/input-accessory-view/index.js';
4
+ // Bare side-effect import, deliberately NOT a re-export and deliberately not beside one of the
5
+ // same specifier: it installs the engine's host behaviors, which is what makes a bare
6
+ // `<pressable>` / `<text-input>` / `<switch>` carry its machine. Any other shape is dropped by
7
+ // Metro's inlineRequires in a release build — see register.ts.
8
+ import './register.js';
9
+ // `Image` is a TAG — `<image>` — and the name now carries only RN's STATICS
10
+ // (`Image.getSize(...)`), an imperative API with no view. The wrapper's whole source/style
11
+ // translation runs on the tag as the engine's `registerImageBehavior`.
12
+ export { Image } from './modules/image/index.js';
13
+ export { setImageSourceResolver } from '@symbiote-native/components';
10
14
  export { KeyboardAvoidingView } from './components/keyboard-avoiding-view/index.js';
11
15
  export { StatusBar } from './modules/status-bar';
12
- export { Switch } from './components/switch';
13
- export { ActivityIndicator } from './components/activity-indicator';
14
- export { SafeAreaView } from './components/safe-area-view/index.js';
15
- export { RefreshControl } from './components/refresh-control/index.js';
16
16
  export { Modal } from './components/modal/index.js';
17
- export { Pressable } from './components/pressable/index.js';
18
- export { TouchableOpacity, TouchableHighlight, TouchableWithoutFeedback, } from './components/touchable/index.js';
19
- export { Button } from './components/button.js';
20
17
  export { FlatList } from './components/flat-list/index.js';
21
18
  export { SectionList } from './components/section-list/index.js';
22
19
  export { VirtualizedSectionList } from './components/virtualized-section-list/index.js';
@@ -74,4 +71,7 @@ export { InteractionManager } from '@symbiote-native/engine';
74
71
  // Android-only surface (the second-platform pass): a thin JS shim over an Android Fabric view,
75
72
  // inert on iOS (no native view -> degrades to a plain container). The Android-only MODULES
76
73
  // (ToastAndroid, PermissionsAndroid, BackHandler) sit in the engine block above.
77
- export { TouchableNativeFeedback } from './components/touchable-native-feedback/index.js';
74
+ // `TouchableNativeFeedback` is now RN's STATIC NAMESPACE, not a component: the element is the tag
75
+ // `<touchable-native-feedback>`, which commits no node of its own and clones onto its single child.
76
+ // `TouchableNativeFeedback.Ripple(…)` / `.SelectableBackground(…)` are unchanged.
77
+ export { TouchableNativeFeedback } from '@symbiote-native/components';
@@ -0,0 +1,3 @@
1
+ export { jsxDEV } from 'react/jsx-dev-runtime';
2
+ export { Fragment } from 'react/jsx-runtime';
3
+ export type { JSX } from './jsx-runtime';
@@ -0,0 +1,10 @@
1
+ // The dev twin of `./jsx-runtime`, and it has to be its own file rather than an alias of it.
2
+ //
3
+ // TypeScript resolves the namespace from `<jsxImportSource>/jsx-dev-runtime` whenever `jsx` is
4
+ // `react-jsxdev`, and Babel's automatic runtime imports `jsxDEV` — not `jsx`/`jsxs` — from that
5
+ // same path in a development build. Solid points both subpaths at one file because its emitted
6
+ // runtime is empty either way; ours carries real factories, so the two entries export different
7
+ // names and pointing them at one file would leave a dev build importing a `jsxDEV` that is not
8
+ // there.
9
+ export { jsxDEV } from 'react/jsx-dev-runtime';
10
+ export { Fragment } from 'react/jsx-runtime';
@@ -0,0 +1 @@
1
+ export declare const JSX_NAMESPACE_CHECK: number;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "@symbiote-native/react/jsx-runtime";
2
+ const strictIntrinsicAcceptsItsOwnProp = (_jsx("view", { testID: "jsx-namespace-check" }));
3
+ const strictIntrinsicRejectsAnUnknownProp = (_jsx("view", { definitelyNotAViewProp: 1 }));
4
+ export const JSX_NAMESPACE_CHECK = [
5
+ strictIntrinsicAcceptsItsOwnProp,
6
+ strictIntrinsicRejectsAnUnknownProp,
7
+ ].length;
@@ -0,0 +1,62 @@
1
+ import type { ICrossTypedIntrinsics } from '@symbiote-native/components';
2
+ import type { Key } from 'react';
3
+ import type { IViewProps, ITextProps } from './components';
4
+ import type { IPressableProps } from './components/pressable/pressable-props';
5
+ import type { IButtonProps } from './components/button-props';
6
+ import type { IImageProps } from './components/image/image-props';
7
+ import type { IImageBackgroundProps } from './components/image-background-props';
8
+ import type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
9
+ import type { IRefreshControlProps } from './components/refresh-control-props';
10
+ import type { ISafeAreaViewProps } from './components/safe-area-view-props';
11
+ import type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
12
+ import type { ITouchableOpacityProps, ITouchableHighlightProps } from './components/touchable/touchable-props';
13
+ import type { ITouchableWithoutFeedbackProps } from './components/touchable-without-feedback/touchable-without-feedback-props';
14
+ import type { IScrollViewProps } from './components/scroll-view/scroll-view-props';
15
+ import type { ISwitchProps } from './components/switch/switch-props';
16
+ import type { ITextInputProps } from './components/text-input/text-input-props';
17
+ import type { IModalProps } from './components/modal';
18
+ import type { IActivityIndicatorProps } from './components/activity-indicator-props';
19
+ export { Fragment, jsx, jsxs } from 'react/jsx-runtime';
20
+ interface IHostProps {
21
+ style?: unknown;
22
+ children?: import('react').ReactNode;
23
+ [key: string]: unknown;
24
+ }
25
+ export interface ICrossedPrimitiveProps {
26
+ view: IViewProps;
27
+ text: ITextProps;
28
+ pressable: IPressableProps;
29
+ button: IButtonProps;
30
+ image: IImageProps;
31
+ 'image-background': IImageBackgroundProps;
32
+ 'input-accessory-view': IInputAccessoryViewProps;
33
+ 'refresh-control': IRefreshControlProps;
34
+ 'safe-area-view': ISafeAreaViewProps;
35
+ 'touchable-native-feedback': ITouchableNativeFeedbackProps;
36
+ 'touchable-opacity': ITouchableOpacityProps;
37
+ 'touchable-highlight': ITouchableHighlightProps;
38
+ 'touchable-without-feedback': ITouchableWithoutFeedbackProps;
39
+ 'scroll-view': IScrollViewProps;
40
+ switch: ISwitchProps;
41
+ 'text-input': ITextInputProps;
42
+ modal: IModalProps;
43
+ 'activity-indicator': IActivityIndicatorProps;
44
+ }
45
+ type IWithKey<Props> = Props & {
46
+ key?: Key | null;
47
+ };
48
+ export declare namespace JSX {
49
+ type ElementType = import('react').JSX.ElementType;
50
+ type Element = import('react').JSX.Element;
51
+ type ElementClass = import('react').JSX.ElementClass;
52
+ type ElementAttributesProperty = import('react').JSX.ElementAttributesProperty;
53
+ type ElementChildrenAttribute = import('react').JSX.ElementChildrenAttribute;
54
+ type LibraryManagedAttributes<C, P> = import('react').JSX.LibraryManagedAttributes<C, P>;
55
+ type IntrinsicAttributes = import('react').JSX.IntrinsicAttributes;
56
+ type IntrinsicClassAttributes<T> = import('react').JSX.IntrinsicClassAttributes<T>;
57
+ interface IntrinsicElements extends ICrossTypedIntrinsics<IHostProps, {
58
+ [K in keyof ICrossedPrimitiveProps]: IWithKey<ICrossedPrimitiveProps[K]>;
59
+ }> {
60
+ }
61
+ }
62
+ export type ISymbioteIntrinsicTag = keyof JSX.IntrinsicElements;
@@ -0,0 +1 @@
1
+ export { Fragment, jsx, jsxs } from 'react/jsx-runtime';
@@ -45,7 +45,6 @@ export declare const Animated: {
45
45
  View: import("react").ComponentType<import("./create-animated-component").IAnimatedComponentProps>;
46
46
  Text: import("react").ComponentType<import("./create-animated-component").IAnimatedComponentProps>;
47
47
  Image: import("react").ComponentType<import("./create-animated-component").IAnimatedComponentProps>;
48
- ScrollView: ReturnType<typeof createAnimatedComponent>;
49
48
  FlatList: ReturnType<typeof createAnimatedComponent>;
50
49
  SectionList: ReturnType<typeof createAnimatedComponent>;
51
50
  createAnimatedComponent: typeof createAnimatedComponent;
@@ -4,9 +4,6 @@
4
4
  // JS-driven). Both halves meet here in one `Animated` object so the
5
5
  // familiar surface (`Animated.timing(new Animated.Value(0), …).start()`) works.
6
6
  import { AnimatedValue, AnimatedValueXY, AnimatedColor, Easing, Platform, timing, spring, decay, parallel, sequence, stagger, loop, delay, add, subtract, multiply, divide, modulo, diffClamp, event, forkEvent, unforkEvent, } from '@symbiote-native/engine';
7
- import { View, Text } from '../../components.js';
8
- import { Image } from '../../components/image/index.js';
9
- import { ScrollView } from '../../components/scroll-view';
10
7
  import { FlatList } from '../../components/flat-list/index.js';
11
8
  import { SectionList } from '../../components/section-list/index.js';
12
9
  import { createAnimatedComponent } from './create-animated-component.js';
@@ -15,21 +12,22 @@ export { createAnimatedComponent } from './create-animated-component.js';
15
12
  // The pure graph leaves now live in @symbiote-native/engine (they extend AnimatedWithChildren,
16
13
  // no React); re-exported here so @symbiote-native/react's Animated surface is unchanged.
17
14
  export { AnimatedProps, AnimatedStyle, AnimatedTransform, } from '@symbiote-native/engine';
18
- // View/Text/Image are pure host primitives, so wrap them eagerly.
19
- const AnimatedView = createAnimatedComponent(View);
20
- const AnimatedText = createAnimatedComponent(Text);
21
- const AnimatedImage = createAnimatedComponent(Image);
22
- // RN's AnimatedExports.js:13-58 exposes all six animated components. The scrolling
23
- // containers (ScrollView/FlatList/SectionList) are wrapped behind LAZY getters,
24
- // mirroring RN's `get ScrollView() { return require(...) }`: ScrollView's module
25
- // chain pulls in scroll-view/sticky-header, which imports this Animated namespace
26
- // back, and a static `createAnimatedComponent(ScrollView)` at init would read ScrollView
27
- // inside its own TDZ. A memoized getter defers the wrap past module init, so the
28
- // cycle never fires. The wrappers carry no per-component animation logic; they only
29
- // add animated-prop support, keeping the adapter a thin layer over the engine.
30
- // The native scroll-event attach (Animated.event onto contentOffset) is owned by
31
- // ScrollView itself.
32
- let animatedScrollView;
15
+ // The tags themselves: View/Text/Image are pure host primitives, so wrap them eagerly.
16
+ const AnimatedView = createAnimatedComponent('view');
17
+ const AnimatedText = createAnimatedComponent('text');
18
+ // The tag, not the `Image` name: that one is the STATICS namespace now (`modules/image`).
19
+ const AnimatedImage = createAnimatedComponent('image');
20
+ // There is no `Animated.ScrollView` any more, and nothing replaced it — the whole API is
21
+ // `<scroll-view style={{ opacity: v }} onScroll={Animated.event(…)}>`. A scroll wrapper's one
22
+ // remaining animated job looked like the native scroll-event attach, and that is engine-side for
23
+ // EVERY host node: `setEventListener` calls `bindAnimatedEvent` on any `on*` prop
24
+ // (`core/engine/src/node.ts`), and an AnimatedNode written into any style key is resolved by
25
+ // `routeProp`. Its lazy getter existed only to dodge a TDZ through `scroll-view/sticky-header`,
26
+ // which is deleted with the wrapper.
27
+ //
28
+ // The two below REMAIN because the list family is tier 3: a render prop decides their output shape
29
+ // in JS, so there is no tag for `<Animated.X>` to be an alias of. Both stay LAZY, mirroring RN's
30
+ // own `get FlatList() { return require(...) }`.
33
31
  let animatedFlatList;
34
32
  let animatedSectionList;
35
33
  // The live, JS-driven driver namespace (real frames). RN's AnimatedImplementation.
@@ -67,10 +65,6 @@ export const Animated = {
67
65
  View: AnimatedView,
68
66
  Text: AnimatedText,
69
67
  Image: AnimatedImage,
70
- get ScrollView() {
71
- animatedScrollView ??= createAnimatedComponent(ScrollView);
72
- return animatedScrollView;
73
- },
74
68
  get FlatList() {
75
69
  animatedFlatList ??= createAnimatedComponent(FlatList);
76
70
  return animatedFlatList;
@@ -0,0 +1,3 @@
1
+ import { type IImageStatics } from '@symbiote-native/components';
2
+ export type { IImageStatics };
3
+ export declare const Image: IImageStatics;
@@ -0,0 +1,14 @@
1
+ // RN's Image STATICS — `getSize`, `getSizeWithHeaders`, `prefetch`, `abortPrefetch`, `queryCache`,
2
+ // `resolveAssetSource`.
3
+ //
4
+ // IN `modules/`, NOT `components/`. The primitive is the `<image>` tag and its fold runs in the
5
+ // engine (`behaviors/image.ts`); what is left under the name `Image` is an imperative API with no
6
+ // view, which is what this bucket is for (<adapter_src_follows_framework_idioms>). Sitting in
7
+ // `components/` was what made a statics object read as a component.
8
+ //
9
+ // A NAMESPACE OBJECT rather than six bare functions, deliberately: `Alert`, `Share`, `Linking` and
10
+ // `AppState` all take that shape, and an app porting from RN writes `Image.getSize(...)` verbatim.
11
+ //
12
+ // Shared verbatim via `imageStatics`, the same source every other adapter's Image uses.
13
+ import { imageStatics } from '@symbiote-native/components';
14
+ export const Image = imageStatics;
@@ -0,0 +1 @@
1
+ import '@symbiote-native/components/register';
@@ -0,0 +1,15 @@
1
+ // Side-effect ONLY. Exports nothing, and must never be re-exported from the barrel.
2
+ //
3
+ // The fourteen calls live once, in `@symbiote-native/components/register` — they were identical in
4
+ // all five adapters, and each copy carried a migration ledger justifying a call against a wrapper
5
+ // that no longer exists. What is per-adapter is only the SPELLING of the import below: every
6
+ // `*-tag.test.*` here reaches the registry through `import './register';`, and this adapter's own
7
+ // barrel guard pins that line.
8
+ //
9
+ // WHY A SIDE-EFFECT SUBPATH AND NOT A BARREL EXPORT. Metro turns on `inlineRequires` for PRODUCTION
10
+ // only: it moves a `require` down to the first place its binding is used as a VALUE, and
11
+ // `export { X } from './x'` compiles to a lazy getter. A registration reached that way never
12
+ // evaluates in a Release build — invisible to tsc, to vitest, and to grepping the bundle. A bare
13
+ // `import` placed NEXT TO a re-export of the same specifier does not help either: Babel merges the
14
+ // two into one dependency and the merged dependency stays lazy.
15
+ import '@symbiote-native/components/register';
@@ -5,4 +5,5 @@
5
5
  // .cjs, not .js: this package is "type": "module", but Metro's babelTransformerPath loading needs
6
6
  // a require()-able file. createCssMetroTransformer() is a factory — Metro needs the actual
7
7
  // {transform, getCacheKey} object it returns, not the css-parser package barrel.
8
- module.exports = require('@symbiote-native/css-parser').createCssMetroTransformer();
8
+ module.exports =
9
+ require('@symbiote-native/css-parser').createCssMetroTransformer();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/react",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "SymbioteNative's React adapter — a react-reconciler host config (mutation mode) driving real native iOS/Android views through stock React Native Fabric.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -39,9 +39,13 @@
39
39
  "default": "./build/bootstrap.js"
40
40
  },
41
41
  "./metro-css-parser": "./metro-css-parser.cjs",
42
- "./state-style": {
43
- "types": "./build/state-style.d.ts",
44
- "default": "./build/state-style.js"
42
+ "./jsx-runtime": {
43
+ "types": "./build/jsx-runtime.d.ts",
44
+ "default": "./build/jsx-runtime.js"
45
+ },
46
+ "./jsx-dev-runtime": {
47
+ "types": "./build/jsx-dev-runtime.d.ts",
48
+ "default": "./build/jsx-dev-runtime.js"
45
49
  }
46
50
  },
47
51
  "files": [
@@ -53,20 +57,20 @@
53
57
  },
54
58
  "dependencies": {
55
59
  "react-reconciler": "^0.33.0",
56
- "@symbiote-native/components": "1.0.0",
60
+ "@symbiote-native/components": "2.0.0",
57
61
  "@symbiote-native/css-parser": "0.5.0"
58
62
  },
59
63
  "peerDependencies": {
60
64
  "react": ">=19.0.0",
61
65
  "react-native": ">=0.86",
62
- "@symbiote-native/engine": "^0.4.0"
66
+ "@symbiote-native/engine": "^0.5.0"
63
67
  },
64
68
  "devDependencies": {
65
69
  "@types/react": "^19.2.0",
66
70
  "@types/react-reconciler": "^0.32.2",
67
71
  "react": "19.2.3",
68
- "@symbiote-native/test-utils": "0.3.0",
69
- "@symbiote-native/engine": "0.4.0"
72
+ "@symbiote-native/engine": "0.5.0",
73
+ "@symbiote-native/test-utils": "0.3.0"
70
74
  },
71
75
  "scripts": {
72
76
  "typecheck": "tsc --build",
@@ -1,3 +0,0 @@
1
- import type { IActivityIndicatorProps } from './shared';
2
- export type { IActivityIndicatorProps } from './shared';
3
- export declare function ActivityIndicator(rawProps: IActivityIndicatorProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -1,17 +0,0 @@
1
- // AndroidProgressBar needs `styleAttr` (drives ProgressBar.setStyle(); missing it throws
2
- // "setStyle() not called") and `indeterminate: true`; default color is the theme (null) —
3
- // mirrors RN's ActivityIndicator.js android branch. Metro selects this file on an Android
4
- // host, no Platform.OS read needed.
5
- // device-verify-pending: confirmed by the absence of the setStyle() red box on a real host.
6
- import { descriptorToReact } from '../../descriptor-to-react/index.js';
7
- import { useActivityIndicatorLogic } from './shared.js';
8
- const PLATFORM = {
9
- // RN: `color = Platform.OS === 'ios' ? GRAY : null`; Android lets the theme color it.
10
- defaultColor: null,
11
- nativeExtras: { styleAttr: 'Normal', indeterminate: true },
12
- };
13
- // A top-level named function, not a factory-returned closure: React Compiler's
14
- // component detection only walks top-level declarations (see shared.ts).
15
- export function ActivityIndicator(rawProps) {
16
- return descriptorToReact(useActivityIndicatorLogic(rawProps, PLATFORM));
17
- }
@@ -1 +0,0 @@
1
- export * from './index.ios';
@@ -1,3 +0,0 @@
1
- import type { IActivityIndicatorProps } from './shared';
2
- export type { IActivityIndicatorProps } from './shared';
3
- export declare function ActivityIndicator(rawProps: IActivityIndicatorProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -1,16 +0,0 @@
1
- // ActivityIndicator on iOS: RCTActivityIndicatorView takes the size enum + a GRAY
2
- // default color and no extra native props. Also the base (activity-indicator.ts
3
- // re-exports it) for headless / web.
4
- import { descriptorToReact } from '../../descriptor-to-react/index.js';
5
- import { useActivityIndicatorLogic } from './shared.js';
6
- // RN's iOS default spinner color (Libraries/.../ActivityIndicator.js GRAY).
7
- const IOS_DEFAULT_COLOR = '#999999';
8
- const PLATFORM = {
9
- defaultColor: IOS_DEFAULT_COLOR,
10
- nativeExtras: {},
11
- };
12
- // A top-level named function, not a factory-returned closure: React Compiler's
13
- // component detection only walks top-level declarations (see shared.ts).
14
- export function ActivityIndicator(rawProps) {
15
- return descriptorToReact(useActivityIndicatorLogic(rawProps, PLATFORM));
16
- }
@@ -1,4 +0,0 @@
1
- // Base / default ActivityIndicator: re-exports the iOS build. Metro overrides this with
2
- // activity-indicator.ios.ts / .android.ts on a real host; under tsx / tsc / web the host
3
- // config resolves here. Filename is the selector, no Platform.OS read.
4
- export * from './index.ios.js';
@@ -1,6 +0,0 @@
1
- import type { IActivityIndicatorPlatform, IActivityIndicatorProps as IActivityIndicatorBaseProps } from '@symbiote-native/components';
2
- export type { IActivityIndicatorPlatform } from '@symbiote-native/components';
3
- export type IActivityIndicatorProps = IActivityIndicatorBaseProps & {
4
- className?: string;
5
- };
6
- export declare function useActivityIndicatorLogic(rawProps: IActivityIndicatorProps, platform: IActivityIndicatorPlatform): import("@symbiote-native/components").IDescriptor;
@@ -1,22 +0,0 @@
1
- // ActivityIndicator is the React lifecycle half. The render (size translation, wrapper +
2
- // spinner, color omission) lives framework-agnostic in @symbiote-native/components; here the
3
- // adapter only resolves props (accessibility, defaults), calls the render fn, and bridges
4
- // the Descriptor to a React element. No state, no effects: this component is render-only.
5
- //
6
- // The per-platform bits (iOS GRAY default + no extras; Android theme/null + styleAttr +
7
- // indeterminate) are supplied by the .ios/.android files via `IActivityIndicatorPlatform`.
8
- //
9
- // useActivityIndicatorLogic is a plain top-level hook, not a component factory returning a
10
- // closure: React Compiler's component/hook detection only walks top-level declarations, so
11
- // index.ios.ts / index.android.ts each declare their OWN top-level `ActivityIndicator`
12
- // function that calls this hook, rather than exporting whatever a factory here returns (same
13
- // shape as switch/shared.ts's useSwitchLogic).
14
- import { renderActivityIndicator, resolveAccessibilityProps, } from '@symbiote-native/components';
15
- export function useActivityIndicatorLogic(rawProps, platform) {
16
- // The wrapper is a raw symbiote-view, not the View FC, so it never runs
17
- // resolveAccessibilityProps itself, so fold aria/role here, then forward the resolved
18
- // accessibility* surface (plus testID / onLayout) onto the wrapper via `passthrough`.
19
- const props = resolveAccessibilityProps(rawProps);
20
- const { animating = true, color, hidesWhenStopped = true, size = 'small', style, ...passthrough } = props;
21
- return renderActivityIndicator({ animating, color, hidesWhenStopped, size, style, passthrough }, platform);
22
- }