@symbiote-native/solid 1.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +159 -86
- package/babel-preset.cjs +0 -5
- package/build/components/activity-indicator-props.d.ts +5 -0
- package/build/components/activity-indicator-props.js +1 -0
- package/build/components/button-props.d.ts +5 -0
- package/build/components/button-props.js +1 -0
- package/build/components/flat-list/index.jsx +4 -4
- package/build/components/{image-background.d.ts → image-background-props.d.ts} +2 -3
- package/build/components/image-background-props.js +1 -0
- package/build/components/image-props.d.ts +5 -0
- package/build/components/image-props.js +6 -0
- package/build/components/{input-accessory-view.d.ts → input-accessory-view-props.d.ts} +1 -2
- package/build/components/input-accessory-view-props.js +5 -0
- package/build/components/keyboard-avoiding-view.jsx +15 -6
- package/build/components/modal.jsx +6 -6
- package/build/components/{pressable.d.ts → pressable-props.d.ts} +10 -7
- package/build/components/pressable-props.js +13 -0
- package/build/components/{refresh-control.d.ts → refresh-control-props.d.ts} +3 -3
- package/build/components/refresh-control-props.js +7 -0
- package/build/components/safe-area-view-props.d.ts +10 -0
- package/build/components/safe-area-view-props.js +5 -0
- package/build/components/{scroll-view/shared.d.ts → scroll-view-props.d.ts} +7 -13
- package/build/components/scroll-view-props.js +29 -0
- package/build/components/switch-props.d.ts +6 -0
- package/build/components/switch-props.js +5 -0
- package/build/components/text-input-props.d.ts +8 -0
- package/build/components/text-input-props.js +1 -0
- package/build/components/{text.d.ts → text-props.d.ts} +3 -3
- package/build/components/text-props.js +11 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback-props.d.ts +9 -0
- package/build/components/touchable-native-feedback/touchable-native-feedback-props.js +1 -0
- package/build/components/touchable-props.d.ts +20 -0
- package/build/components/touchable-props.js +1 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.d.ts +7 -0
- package/build/components/touchable-without-feedback/touchable-without-feedback-props.js +1 -0
- package/build/components/{view.d.ts → view-props.d.ts} +2 -3
- package/build/components/view-props.js +11 -0
- package/build/components/virtualized-list/index.android.js +5 -4
- package/build/components/virtualized-list/index.ios.js +6 -6
- package/build/components/virtualized-list/shared.d.ts +1 -3
- package/build/components/virtualized-list/shared.jsx +95 -102
- package/build/components/virtualized-list/sticky-header.d.ts +6 -0
- package/build/components/{scroll-view → virtualized-list}/sticky-header.jsx +28 -36
- package/build/components.d.ts +20 -30
- package/build/components.js +6 -33
- package/build/create-portal/index.jsx +3 -3
- package/build/descriptor-to-solid.js +1 -1
- package/build/host-instance.js +2 -2
- package/build/index.d.ts +1 -0
- package/build/index.js +11 -3
- package/build/jsx-runtime.d.ts +39 -2
- package/build/modules/animated/index.d.ts +26 -23
- package/build/modules/animated/index.js +16 -22
- package/build/modules/image.d.ts +3 -0
- package/build/modules/image.js +12 -0
- package/build/register.d.ts +1 -1
- package/build/register.js +12 -28
- package/build/renderer.js +74 -61
- package/build/utils/stable-keys.d.ts +1 -1
- package/build/utils/stable-keys.js +6 -5
- package/metro-css-parser.cjs +2 -1
- package/package.json +6 -11
- package/babel-lower-host-primitives.cjs +0 -323
- package/build/components/activity-indicator/index.android.d.ts +0 -2
- package/build/components/activity-indicator/index.android.js +0 -11
- package/build/components/activity-indicator/index.d.ts +0 -1
- package/build/components/activity-indicator/index.ios.d.ts +0 -2
- package/build/components/activity-indicator/index.ios.js +0 -10
- package/build/components/activity-indicator/index.js +0 -4
- package/build/components/activity-indicator/shared.d.ts +0 -8
- package/build/components/activity-indicator/shared.js +0 -51
- package/build/components/button.d.ts +0 -7
- package/build/components/button.jsx +0 -45
- package/build/components/image-background.jsx +0 -74
- package/build/components/image.d.ts +0 -9
- package/build/components/image.js +0 -75
- package/build/components/input-accessory-view.jsx +0 -39
- package/build/components/pressable.jsx +0 -211
- package/build/components/refresh-control.jsx +0 -36
- package/build/components/safe-area-view.d.ts +0 -11
- package/build/components/safe-area-view.jsx +0 -24
- package/build/components/scroll-view/index.android.d.ts +0 -2
- package/build/components/scroll-view/index.android.js +0 -11
- package/build/components/scroll-view/index.d.ts +0 -2
- package/build/components/scroll-view/index.ios.d.ts +0 -2
- package/build/components/scroll-view/index.ios.js +0 -8
- package/build/components/scroll-view/index.js +0 -9
- package/build/components/scroll-view/shared.jsx +0 -334
- package/build/components/scroll-view/sticky-header.d.ts +0 -18
- package/build/components/switch/index.android.d.ts +0 -2
- package/build/components/switch/index.android.js +0 -12
- package/build/components/switch/index.d.ts +0 -1
- package/build/components/switch/index.ios.d.ts +0 -2
- package/build/components/switch/index.ios.js +0 -11
- package/build/components/switch/index.js +0 -4
- package/build/components/switch/shared.d.ts +0 -11
- package/build/components/switch/shared.js +0 -87
- package/build/components/text-input.d.ts +0 -10
- package/build/components/text-input.js +0 -290
- package/build/components/text.jsx +0 -27
- package/build/components/touchable/index.d.ts +0 -22
- package/build/components/touchable/index.jsx +0 -247
- package/build/components/touchable-native-feedback/index.d.ts +0 -16
- package/build/components/touchable-native-feedback/index.jsx +0 -68
- package/build/components/view.jsx +0 -49
- package/build/state-style.d.ts +0 -1
- package/build/state-style.js +0 -13
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
// Sticky headers — the Solid lifecycle half of the JS layer RN implements in ScrollView.js /
|
|
2
2
|
// ScrollViewStickyHeader.js.
|
|
3
3
|
//
|
|
4
|
+
// PRIVATE TO VIRTUALIZED-LIST since 2026-09-11. It used to live under `../scroll-view` and back
|
|
5
|
+
// that component's `stickyHeaderIndices` too; the tag `<scroll-view>` now honors that prop through
|
|
6
|
+
// the engine's own `sticky-header` intrinsic (`core/components/src/behaviors/scroll-view/sticky.ts`)
|
|
7
|
+
// with no adapter code at all — see that primitive's props header. VirtualizedList still needs its
|
|
8
|
+
// OWN implementation because it hand-builds its scroll host (`shared.tsx`'s own header explains
|
|
9
|
+
// why) rather than emitting the tag, so it wraps a flagged CELL itself instead of leaning on the
|
|
10
|
+
// engine's per-child walk. `wrapStickyHeaders`/`IStickyWrapInputs` — the generic child-array wrapper
|
|
11
|
+
// ScrollView used and this file never called — were dropped with the move; `virtualized-list/
|
|
12
|
+
// shared.tsx` wraps the cell it already owns directly.
|
|
13
|
+
//
|
|
4
14
|
// RN does stickiness PURELY IN JS: ScrollView wraps each flagged child in a ScrollViewStickyHeader
|
|
5
15
|
// fed by ONE scroll AnimatedValue, and the native scroll view ignores `stickyHeaderIndices`
|
|
6
16
|
// entirely — forwarding that array to Fabric is a silent no-op, so we replicate the JS layer
|
|
@@ -21,8 +31,7 @@
|
|
|
21
31
|
// underneath; Solid does not (.claude/rules/solid-descriptor-bridge.md §4).
|
|
22
32
|
import { createEffect, createMemo, createSignal, onCleanup } from 'solid-js';
|
|
23
33
|
import { createInitialStickyState, readLayoutNumber, reduceSticky, STICKY_HEADER_Z_INDEX, } from '@symbiote-native/components';
|
|
24
|
-
import { AnimatedInterpolation, Platform, dlog,
|
|
25
|
-
import { Animated } from '../../modules/animated/index.js';
|
|
34
|
+
import { AnimatedInterpolation, Platform, dlog, } from '@symbiote-native/engine';
|
|
26
35
|
// One sticky header. Measures its own y/height through onLayout, interpolates the shared scroll
|
|
27
36
|
// offset into a translateY that pins it to the top (or the bottom, inverted) until the next header
|
|
28
37
|
// collides with it, and drives that translate through the native driver when available so the pin
|
|
@@ -137,46 +146,29 @@ export function ScrollViewStickyHeader(props) {
|
|
|
137
146
|
props.onLayout(event);
|
|
138
147
|
};
|
|
139
148
|
// The EXPLICIT debounced translateY overrides the committed transform for hit-testing, while
|
|
140
|
-
// animatedTranslateY does the smooth (native-driven) pin.
|
|
149
|
+
// animatedTranslateY does the smooth (native-driven) pin. It rides the style ARRAY now rather
|
|
150
|
+
// than `passthroughAnimatedPropExplicitValues`: that prop was read by `createAnimatedComponent`,
|
|
151
|
+
// and the host is a bare tag, where the engine ignores it
|
|
152
|
+
// (core/engine/src/animated/host-binding.ts calls it a wrapper-ism by name). The wrapper did
|
|
153
|
+
// exactly this merge — `[reduced.style, passthroughStyle]` — so a later array entry overriding
|
|
154
|
+
// the transform is the same semantics, one layer down, and the engine still binds the
|
|
155
|
+
// interpolation it finds in entry 0.
|
|
141
156
|
const passthrough = createMemo(() => {
|
|
142
157
|
// Read the bump so a committed translateY repaints.
|
|
143
158
|
version();
|
|
144
159
|
if (state.translateY === null)
|
|
145
|
-
return
|
|
146
|
-
return {
|
|
160
|
+
return undefined;
|
|
161
|
+
return { transform: [{ translateY: state.translateY }] };
|
|
147
162
|
});
|
|
148
163
|
// collapsable:false keeps the wrapper a real Yoga node; zIndex makes the pinned header paint OVER
|
|
149
164
|
// the rows scrolling up under it.
|
|
150
|
-
return (<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
165
|
+
return (<view style={[
|
|
166
|
+
{
|
|
167
|
+
transform: [{ translateY: animatedTranslateY() }],
|
|
168
|
+
zIndex: STICKY_HEADER_Z_INDEX,
|
|
169
|
+
},
|
|
170
|
+
passthrough(),
|
|
171
|
+
]} onLayout={onLayout} collapsable={false}>
|
|
154
172
|
{props.children}
|
|
155
|
-
</
|
|
156
|
-
}
|
|
157
|
-
// Wrap each child flagged by `stickyHeaderIndices` in the sticky header component, fed by the shared
|
|
158
|
-
// scroll AnimatedValue (RN ScrollView.js's render-time children.map). Unflagged children pass
|
|
159
|
-
// through untouched.
|
|
160
|
-
//
|
|
161
|
-
// Cross-talk (RN's _headerLayoutYs + _onStickyHeaderLayout): each header reports its own y through
|
|
162
|
-
// `onHeaderLayoutY`, and every header is fed the y of the NEXT flagged one — the point past which it
|
|
163
|
-
// gets pushed off. The LAST flagged header has no successor, so its nextHeaderLayoutY stays
|
|
164
|
-
// undefined and it sticks indefinitely, which is correct.
|
|
165
|
-
export function wrapStickyHeaders(children, inputs) {
|
|
166
|
-
const Wrapper = inputs.StickyHeaderComponent ?? ScrollViewStickyHeader;
|
|
167
|
-
return children.map((child, index) => {
|
|
168
|
-
const indexOfIndex = inputs.stickyHeaderIndices.indexOf(index);
|
|
169
|
-
// A non-node child (a bare string or number in a scroll view) has no frame to pin and cannot be
|
|
170
|
-
// wrapped meaningfully, so it passes through like an unflagged one.
|
|
171
|
-
if (indexOfIndex === -1 || !isSymbioteNode(child))
|
|
172
|
-
return child;
|
|
173
|
-
dlog(`Solid ScrollView sticky-header wrap index=${index}`);
|
|
174
|
-
return (<Wrapper nextHeaderLayoutY={inputs.readNextHeaderLayoutY(indexOfIndex)} onLayout={(event) => {
|
|
175
|
-
const y = readLayoutNumber(event, 'y');
|
|
176
|
-
if (y !== undefined)
|
|
177
|
-
inputs.onHeaderLayoutY(index, y);
|
|
178
|
-
}} scrollAnimatedValue={inputs.scrollAnimatedValue} inverted={inputs.readInverted()} scrollViewHeight={inputs.readScrollViewHeight()}>
|
|
179
|
-
{child}
|
|
180
|
-
</Wrapper>);
|
|
181
|
-
});
|
|
173
|
+
</view>);
|
|
182
174
|
}
|
package/build/components.d.ts
CHANGED
|
@@ -1,28 +1,20 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
5
|
-
export {
|
|
6
|
-
export type {
|
|
7
|
-
export { Image } from './components/image';
|
|
8
|
-
export type { IImageProps } from './components/image';
|
|
9
|
-
export { Pressable } from './components/pressable';
|
|
10
|
-
export type { IPressableProps } from './components/pressable';
|
|
11
|
-
export { ActivityIndicator } from './components/activity-indicator';
|
|
12
|
-
export type { IActivityIndicatorProps } from './components/activity-indicator';
|
|
1
|
+
export type { IViewProps } from './components/view-props';
|
|
2
|
+
export type { ITextProps } from './components/text-props';
|
|
3
|
+
export type { ISafeAreaViewProps } from './components/safe-area-view-props';
|
|
4
|
+
export type { IImageProps } from './components/image-props';
|
|
5
|
+
export type { IPressableProps } from './components/pressable-props';
|
|
6
|
+
export type { IActivityIndicatorProps } from './components/activity-indicator-props';
|
|
13
7
|
export type { IImageStatics, IPressState, IPressableAndroidRippleConfig, } from '@symbiote-native/components';
|
|
14
|
-
export {
|
|
15
|
-
export type {
|
|
16
|
-
export {
|
|
17
|
-
export type { ITextInputProps, ITextInputHandle, ITextInputSelection, } from './components/text-input';
|
|
8
|
+
export type { ISwitchProps, ISwitchTrackColor, ISwitchChangeEvent, } from './components/switch-props';
|
|
9
|
+
export type { ITextInputProps } from './components/text-input-props';
|
|
10
|
+
export type { ITextInputHandle, ITextInputSelection, ITextInputChangeEvent, } from '@symbiote-native/components';
|
|
18
11
|
export { Modal } from './components/modal';
|
|
19
12
|
export type { IModalProps, IModalAnimationType, IModalPresentationStyle, IModalOrientation, IModalOrientationChangeEvent, } from './components/modal';
|
|
20
13
|
export { KeyboardAvoidingView } from './components/keyboard-avoiding-view';
|
|
21
14
|
export type { IKeyboardAvoidingViewProps, IKeyboardAvoidingBehavior, } from './components/keyboard-avoiding-view';
|
|
22
|
-
export {
|
|
23
|
-
export type {
|
|
24
|
-
export {
|
|
25
|
-
export type { IScrollViewProps, IScrollViewHandle, } from './components/scroll-view';
|
|
15
|
+
export type { IRefreshControlProps } from './components/refresh-control-props';
|
|
16
|
+
export type { IScrollViewProps } from './components/scroll-view-props';
|
|
17
|
+
export type { IScrollViewHandle } from '@symbiote-native/components';
|
|
26
18
|
export { VirtualizedList } from './components/virtualized-list';
|
|
27
19
|
export type { IVirtualizedListProps, IVirtualizedListHandle, IVirtualizedListCellInfo, IVirtualizedListRenderItem, ICellLayout, ISeparators, ISeparatorProps, IViewToken, IViewableItemsChangedInfo, IViewabilityConfig, IViewabilityConfigCallbackPair, } from './components/virtualized-list';
|
|
28
20
|
export { FlatList } from './components/flat-list';
|
|
@@ -31,13 +23,11 @@ export { VirtualizedSectionList } from './components/virtualized-section-list';
|
|
|
31
23
|
export type { IVirtualizedSectionListProps, IVirtualizedSectionListHandle, ISectionHeaderInfo, ISectionCellInfo, ISection, } from './components/virtualized-section-list';
|
|
32
24
|
export { SectionList } from './components/section-list';
|
|
33
25
|
export type { ISectionListProps, ISectionListHandle, } from './components/section-list';
|
|
34
|
-
export {
|
|
35
|
-
export type {
|
|
36
|
-
export { TouchableNativeFeedback } from '
|
|
37
|
-
export type {
|
|
38
|
-
export {
|
|
39
|
-
export type { IButtonProps } from './components/button';
|
|
40
|
-
export {
|
|
41
|
-
export type {
|
|
42
|
-
export { InputAccessoryView } from './components/input-accessory-view';
|
|
43
|
-
export type { IInputAccessoryViewProps } from './components/input-accessory-view';
|
|
26
|
+
export type { ITouchableOpacityProps, ITouchableHighlightProps, } from './components/touchable-props';
|
|
27
|
+
export type { ITouchableWithoutFeedbackProps } from './components/touchable-without-feedback/touchable-without-feedback-props';
|
|
28
|
+
export { TouchableNativeFeedback } from '@symbiote-native/components';
|
|
29
|
+
export type { INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from '@symbiote-native/components';
|
|
30
|
+
export type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
|
|
31
|
+
export type { IButtonProps } from './components/button-props';
|
|
32
|
+
export type { IImageBackgroundProps } from './components/image-background-props';
|
|
33
|
+
export type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
|
package/build/components.js
CHANGED
|
@@ -1,31 +1,12 @@
|
|
|
1
1
|
// The component re-export barrel, flat at the package root like every other adapter's. Grouping
|
|
2
2
|
// under components/ is internal; this file plus src/index.ts is the whole public surface.
|
|
3
|
-
export { View } from './components/view.jsx';
|
|
4
|
-
export { Text } from './components/text.jsx';
|
|
5
|
-
export { SafeAreaView } from './components/safe-area-view.jsx';
|
|
6
|
-
export { Image } from './components/image.js';
|
|
7
|
-
export { Pressable } from './components/pressable.jsx';
|
|
8
|
-
export { ActivityIndicator } from './components/activity-indicator';
|
|
9
|
-
export { Switch } from './components/switch';
|
|
10
|
-
export { TextInput } from './components/text-input.js';
|
|
11
3
|
export { Modal } from './components/modal.jsx';
|
|
12
4
|
export { KeyboardAvoidingView } from './components/keyboard-avoiding-view.jsx';
|
|
13
|
-
export { RefreshControl } from './components/refresh-control.jsx';
|
|
14
|
-
// ScrollViewStickyHeader is NOT exported, matching react-native itself: it lives at
|
|
15
|
-
// Libraries/Components/ScrollView/ScrollViewStickyHeader.js and is absent from RN's public
|
|
16
|
-
// index.js, so it is ScrollView's internal, not part of the public surface. React's and Vue's
|
|
17
|
-
// barrels agree. Svelte's and Angular's do export it, but as a WORKAROUND rather than an API
|
|
18
|
-
// decision — Svelte documents `stickyHeaderIndices` as a KNOWN GAP, so its apps have to compose the
|
|
19
|
-
// wrapper by hand. This adapter auto-wraps flagged children the way React and Vue do, so the escape
|
|
20
|
-
// hatch has nothing to escape. `IStickyHeaderComponentType` stays internal for the same reason even
|
|
21
|
-
// though `IScrollViewProps.StickyHeaderComponent` is typed by it — React has the identical shape.
|
|
22
|
-
export { ScrollView } from './components/scroll-view';
|
|
23
5
|
// The shared list detail types (ISeparators, IViewToken, IViewabilityConfig…) come through the
|
|
24
6
|
// component module rather than straight from '@symbiote-native/components', matching React's own
|
|
25
7
|
// virtualized-list barrel: a consumer typing a renderItem callback or a viewability config reaches
|
|
26
8
|
// for the same import as the component. `IVirtualizedListComponent` stays internal — it is the
|
|
27
|
-
// platform factory's return type, not API
|
|
28
|
-
// out of this barrel.
|
|
9
|
+
// platform factory's return type, not API.
|
|
29
10
|
export { VirtualizedList } from './components/virtualized-list';
|
|
30
11
|
// FlatList carries no platform split of its own — the iOS/Android divergence is
|
|
31
12
|
// VirtualizedList's refreshControlMode, inherited by importing that folder, so Metro picks the
|
|
@@ -39,16 +20,8 @@ export { VirtualizedSectionList } from './components/virtualized-section-list/in
|
|
|
39
20
|
// SectionList declares no input of its own — it is the preset over VirtualizedSectionList, the same
|
|
40
21
|
// relation React's 25-line section-list has to its 262-line virtualized twin.
|
|
41
22
|
export { SectionList } from './components/section-list/index.jsx';
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
export { TouchableNativeFeedback } from './components/touchable-native-feedback/index.jsx';
|
|
48
|
-
// IButtonProps is agnostic and lives in @symbiote-native/components; this re-exports it rather
|
|
49
|
-
// than redeclaring it, matching react/vue/svelte/angular (CLAUDE.md prop-type split).
|
|
50
|
-
export { Button } from './components/button.jsx';
|
|
51
|
-
// Both take `children`, a framework value, so their public prop types are declared per-adapter
|
|
52
|
-
// over the shared agnostic field base — never imported from another adapter.
|
|
53
|
-
export { ImageBackground } from './components/image-background.jsx';
|
|
54
|
-
export { InputAccessoryView } from './components/input-accessory-view.jsx';
|
|
23
|
+
// Android's native ripple/theme-attr feedback. `TouchableNativeFeedback` is now RN's STATIC
|
|
24
|
+
// NAMESPACE, not a component: the element is the tag `<touchable-native-feedback>`, which commits no
|
|
25
|
+
// node of its own and clones onto its single child. `.Ripple(…)` / `.SelectableBackground(…)` are
|
|
26
|
+
// unchanged, and are the SHARED functions every adapter already offered.
|
|
27
|
+
export { TouchableNativeFeedback } from '@symbiote-native/components';
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
// structurally the same silent no-paint React documents for its own resetAfterCommit. Cross-
|
|
36
36
|
// surface content sharing is a different mechanism entirely: `createTunnel` (../create-tunnel).
|
|
37
37
|
import { createMemo, createRenderEffect, onCleanup } from 'solid-js';
|
|
38
|
-
import { createAnchor, dlog, isSymbioteNode, SymbioteSurface, } from '@symbiote-native/engine';
|
|
38
|
+
import { componentOf, createAnchor, dlog, isSymbioteNode, SymbioteSurface, } from '@symbiote-native/engine';
|
|
39
39
|
import { insert, insertNode, removeNode } from '../renderer.js';
|
|
40
40
|
// The Solid flavour of React's isSymbioteNode guard, and it needs its own wording: React tells the
|
|
41
41
|
// caller to check for a forgotten `.current`, which does not exist here. A Solid `ref` is a plain
|
|
@@ -45,7 +45,7 @@ import { insert, insertNode, removeNode } from '../renderer.js';
|
|
|
45
45
|
function assertPortalTarget(target) {
|
|
46
46
|
if (target instanceof SymbioteSurface || isSymbioteNode(target))
|
|
47
47
|
return target;
|
|
48
|
-
throw new Error('Portal `mount` must be an already-mounted host node (a ref off a rendered <
|
|
48
|
+
throw new Error('Portal `mount` must be an already-mounted host node (a ref off a rendered <view>) or a surface — got something else. Did you pass the signal instead of CALLING it (`mount={overlay()}`), read it before the target element existed (gate the Portal behind <Show when={overlay()}>), or pass a CSS-selector-style string?');
|
|
49
49
|
}
|
|
50
50
|
export function Portal(props) {
|
|
51
51
|
// One engine ANCHOR per Portal instance, used as a fragment host: it is a real retained node, so
|
|
@@ -68,7 +68,7 @@ export function Portal(props) {
|
|
|
68
68
|
// deferred createEffect because a DOM append IS the paint.
|
|
69
69
|
createRenderEffect(() => {
|
|
70
70
|
const to = target();
|
|
71
|
-
dlog(`solid portal -> ${to instanceof SymbioteSurface ? 'surface' : to
|
|
71
|
+
dlog(`solid portal -> ${to instanceof SymbioteSurface ? 'surface' : componentOf(to)}`);
|
|
72
72
|
insertNode(to, host);
|
|
73
73
|
// Runs both on a `mount` change (before the effect re-attaches elsewhere) and on the Portal's
|
|
74
74
|
// own disposal — the content leaves the target either way.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// So the tree is built ONCE and every node's props are wired through the renderer's own `spread`,
|
|
15
15
|
// which is a render effect that diffs prop-by-prop against the previous values and calls
|
|
16
16
|
// setProperty -> routeProp only for the ones that actually changed. Same mechanism, same node
|
|
17
|
-
// identity, as compiled `<
|
|
17
|
+
// identity, as compiled `<switch value={v()} />`.
|
|
18
18
|
//
|
|
19
19
|
// This relies on `render-*.ts` producing a SHAPE-STABLE Descriptor: same type, same child count,
|
|
20
20
|
// text where text was — only prop VALUES vary between calls. That is already the contract the
|
package/build/host-instance.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// The node -> tag resolution itself belongs to the engine (getNativeTag, keyed on the raw node in the
|
|
10
10
|
// commit mirror); this only unwraps the Solid-shaped inputs onto it. An uncommitted or unknown input
|
|
11
11
|
// has no tag yet and surfaces as null.
|
|
12
|
-
import { getNativeTag, isSymbioteNode, dlog } from '@symbiote-native/engine';
|
|
12
|
+
import { componentOf, getNativeTag, isSymbioteNode, dlog, } from '@symbiote-native/engine';
|
|
13
13
|
// Solid's counterpart to Vue's isRef branch. Solid has no ref wrapper — `ref={el}` writes the node
|
|
14
14
|
// straight into a variable — but holding that node in a signal is idiomatic, and a signal reads as a
|
|
15
15
|
// zero-argument accessor. Calling it is the only way to unwrap one (there is no isSignal predicate:
|
|
@@ -28,7 +28,7 @@ export function findNodeHandle(componentOrHandle) {
|
|
|
28
28
|
return candidate;
|
|
29
29
|
if (isSymbioteNode(candidate)) {
|
|
30
30
|
const tag = getNativeTag(candidate) ?? null;
|
|
31
|
-
dlog(`findNodeHandle: component=${candidate
|
|
31
|
+
dlog(`findNodeHandle: component=${componentOf(candidate)} tag=${tag}`);
|
|
32
32
|
return tag;
|
|
33
33
|
}
|
|
34
34
|
dlog('findNodeHandle: input did not resolve to a symbiote host node');
|
package/build/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { AppRegistry, setHostRegistrar } from './modules/app-registry';
|
|
|
10
10
|
export type { IComponentProvider, IWrapperComponentProvider, IAppParameters, IRunnable, IHostRegistrar, IRegistry, IHeadlessTask, ITaskProvider, ITaskCanceller, ITaskCancelProvider, } from './modules/app-registry';
|
|
11
11
|
export { StatusBar } from './modules/status-bar';
|
|
12
12
|
export type { IStatusBarProps, IStatusBarStyle } from './modules/status-bar';
|
|
13
|
+
export { Image } from './modules/image';
|
|
13
14
|
export { Portal } from './create-portal';
|
|
14
15
|
export type { IPortalProps, IPortalTarget } from './create-portal';
|
|
15
16
|
export { createTunnel } from './create-tunnel';
|
package/build/index.js
CHANGED
|
@@ -36,11 +36,19 @@ export { descriptorToSolid } from './descriptor-to-solid.js';
|
|
|
36
36
|
// Safe in the barrel (unlike ./bootstrap, which imports react-native): the registry seam itself
|
|
37
37
|
// only reaches the engine and solid-js.
|
|
38
38
|
export { AppRegistry, setHostRegistrar } from './modules/app-registry/index.js';
|
|
39
|
-
// Animated: the
|
|
40
|
-
// graph.
|
|
41
|
-
//
|
|
39
|
+
// Animated: the three list/scroll components that are still components, over the engine's
|
|
40
|
+
// framework-agnostic value graph. There is no `Animated.View` / `Animated.Text` / `Animated.Image`
|
|
41
|
+
// — those primitives are tags, and `<view style={{ opacity: someAnimatedValue }}>` is the whole
|
|
42
|
+
// API (.claude/rules/animated-values-resolve-in-the-engine.md). Solid's JSX takes the dotted form
|
|
43
|
+
// of what remains directly — `<Animated.ScrollView/>` compiles to
|
|
44
|
+
// createComponent(Animated.ScrollView, …) — so no local alias is needed, unlike Angular, whose AOT
|
|
42
45
|
// compiler cannot trace a class through property access (.claude/rules/dotted-component-tags.md).
|
|
43
46
|
export { StatusBar } from './modules/status-bar.js';
|
|
47
|
+
// What survives of `Image` once the primitive is the `<image>` tag: RN's statics namespace, no
|
|
48
|
+
// view. Grouped with the runtime modules rather than the components for exactly that reason.
|
|
49
|
+
// `IImageStatics` is not re-exported here — `./components` already carries it, straight from the
|
|
50
|
+
// shared package, and a second export of one name is a build error rather than a convenience.
|
|
51
|
+
export { Image } from './modules/image.js';
|
|
44
52
|
// Portal: same-surface content relocation, the twin of React's createPortal and Angular's
|
|
45
53
|
// PortalDirective/PortalOutletDirective. `mount` takes an already-mounted host node in THIS
|
|
46
54
|
// surface (a ref off a rendered component) or the surface itself; reaching a second, separately
|
package/build/jsx-runtime.d.ts
CHANGED
|
@@ -1,9 +1,46 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ICrossTypedIntrinsics } from '@symbiote-native/components';
|
|
2
2
|
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
3
|
+
import type { IViewProps } from './components/view-props';
|
|
4
|
+
import type { ITextProps } from './components/text-props';
|
|
5
|
+
import type { IPressableProps } from './components/pressable-props';
|
|
6
|
+
import type { IButtonProps } from './components/button-props';
|
|
7
|
+
import type { IImageProps } from './components/image-props';
|
|
8
|
+
import type { IImageBackgroundProps } from './components/image-background-props';
|
|
9
|
+
import type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
|
|
10
|
+
import type { IRefreshControlProps } from './components/refresh-control-props';
|
|
11
|
+
import type { ISafeAreaViewProps } from './components/safe-area-view-props';
|
|
12
|
+
import type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
|
|
13
|
+
import type { ITouchableOpacityProps, ITouchableHighlightProps } from './components/touchable-props';
|
|
14
|
+
import type { ITouchableWithoutFeedbackProps } from './components/touchable-without-feedback/touchable-without-feedback-props';
|
|
15
|
+
import type { IScrollViewProps } from './components/scroll-view-props';
|
|
16
|
+
import type { ISwitchProps } from './components/switch-props';
|
|
17
|
+
import type { ITextInputProps } from './components/text-input-props';
|
|
18
|
+
import type { IModalProps } from './components/modal';
|
|
19
|
+
import type { IActivityIndicatorProps } from './components/activity-indicator-props';
|
|
3
20
|
type ISymbioteHostAttributes = {
|
|
4
21
|
readonly children?: JSX.Element;
|
|
5
22
|
readonly [attribute: string]: unknown;
|
|
6
23
|
};
|
|
24
|
+
interface ICrossedPrimitiveProps {
|
|
25
|
+
view: IViewProps;
|
|
26
|
+
text: ITextProps;
|
|
27
|
+
pressable: IPressableProps;
|
|
28
|
+
button: IButtonProps;
|
|
29
|
+
image: IImageProps;
|
|
30
|
+
'image-background': IImageBackgroundProps;
|
|
31
|
+
'input-accessory-view': IInputAccessoryViewProps;
|
|
32
|
+
'refresh-control': IRefreshControlProps;
|
|
33
|
+
'safe-area-view': ISafeAreaViewProps;
|
|
34
|
+
'touchable-native-feedback': ITouchableNativeFeedbackProps;
|
|
35
|
+
'touchable-opacity': ITouchableOpacityProps;
|
|
36
|
+
'touchable-highlight': ITouchableHighlightProps;
|
|
37
|
+
'touchable-without-feedback': ITouchableWithoutFeedbackProps;
|
|
38
|
+
'scroll-view': IScrollViewProps;
|
|
39
|
+
switch: ISwitchProps;
|
|
40
|
+
'text-input': ITextInputProps;
|
|
41
|
+
modal: IModalProps;
|
|
42
|
+
'activity-indicator': IActivityIndicatorProps;
|
|
43
|
+
}
|
|
7
44
|
export declare namespace JSX {
|
|
8
45
|
type Element = ISymbioteNode | IArrayElement | IFunctionElement | (string & {}) | number | boolean | null | undefined;
|
|
9
46
|
interface IArrayElement extends Array<Element> {
|
|
@@ -20,7 +57,7 @@ export declare namespace JSX {
|
|
|
20
57
|
}
|
|
21
58
|
interface IntrinsicAttributes {
|
|
22
59
|
}
|
|
23
|
-
interface IntrinsicElements extends
|
|
60
|
+
interface IntrinsicElements extends ICrossTypedIntrinsics<ISymbioteHostAttributes, ICrossedPrimitiveProps> {
|
|
24
61
|
}
|
|
25
62
|
}
|
|
26
63
|
export {};
|
|
@@ -8,25 +8,7 @@ export declare const Animated: {
|
|
|
8
8
|
Value: typeof AnimatedValue;
|
|
9
9
|
ValueXY: typeof AnimatedValueXY;
|
|
10
10
|
Color: typeof AnimatedColor;
|
|
11
|
-
Easing:
|
|
12
|
-
step0(n: number): number;
|
|
13
|
-
step1(n: number): number;
|
|
14
|
-
linear(t: number): number;
|
|
15
|
-
ease(t: number): number;
|
|
16
|
-
quad(t: number): number;
|
|
17
|
-
cubic(t: number): number;
|
|
18
|
-
poly(n: number): import("@symbiote-native/engine").IEasingFunction;
|
|
19
|
-
sin(t: number): number;
|
|
20
|
-
circle(t: number): number;
|
|
21
|
-
exp(t: number): number;
|
|
22
|
-
elastic(bounciness?: number): import("@symbiote-native/engine").IEasingFunction;
|
|
23
|
-
back(s?: number): import("@symbiote-native/engine").IEasingFunction;
|
|
24
|
-
bounce(t: number): number;
|
|
25
|
-
bezier(x1: number, y1: number, x2: number, y2: number): import("@symbiote-native/engine").IEasingFunction;
|
|
26
|
-
in(easing: import("@symbiote-native/engine").IEasingFunction): import("@symbiote-native/engine").IEasingFunction;
|
|
27
|
-
out(easing: import("@symbiote-native/engine").IEasingFunction): import("@symbiote-native/engine").IEasingFunction;
|
|
28
|
-
inOut(easing: import("@symbiote-native/engine").IEasingFunction): import("@symbiote-native/engine").IEasingFunction;
|
|
29
|
-
};
|
|
11
|
+
Easing: import("@symbiote-native/engine").IEasing;
|
|
30
12
|
timing: typeof timing;
|
|
31
13
|
spring: typeof spring;
|
|
32
14
|
decay: typeof decay;
|
|
@@ -44,10 +26,31 @@ export declare const Animated: {
|
|
|
44
26
|
event: typeof event;
|
|
45
27
|
forkEvent: typeof forkEvent;
|
|
46
28
|
unforkEvent: typeof unforkEvent;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
29
|
+
FlatList: IAnimatedComponent;
|
|
30
|
+
SectionList: IAnimatedComponent;
|
|
31
|
+
createAnimatedComponent: typeof createAnimatedComponent;
|
|
32
|
+
} | {
|
|
33
|
+
Value: typeof AnimatedValue;
|
|
34
|
+
ValueXY: typeof AnimatedValueXY;
|
|
35
|
+
Color: typeof AnimatedColor;
|
|
36
|
+
Easing: import("@symbiote-native/engine").IEasing;
|
|
37
|
+
timing: (value: AnimatedValue, config: import("@symbiote-native/engine").ITimingConfig) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
38
|
+
spring: (value: AnimatedValue, config: import("@symbiote-native/engine").ISpringConfig) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
39
|
+
decay: (_value: AnimatedValue, _config: import("@symbiote-native/engine").IDecayConfig) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
40
|
+
parallel: (animations: import("@symbiote-native/engine").ICompositeAnimation[], _config?: import("@symbiote-native/engine").IParallelConfig) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
41
|
+
sequence: (animations: import("@symbiote-native/engine").ICompositeAnimation[]) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
42
|
+
stagger: (_time: number, animations: import("@symbiote-native/engine").ICompositeAnimation[]) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
43
|
+
loop: (_animation: import("@symbiote-native/engine").ICompositeAnimation) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
44
|
+
delay: (_time: number) => import("@symbiote-native/engine").ICompositeAnimation;
|
|
45
|
+
add: typeof add;
|
|
46
|
+
subtract: typeof subtract;
|
|
47
|
+
multiply: typeof multiply;
|
|
48
|
+
divide: typeof divide;
|
|
49
|
+
modulo: typeof modulo;
|
|
50
|
+
diffClamp: typeof diffClamp;
|
|
51
|
+
event: typeof event;
|
|
52
|
+
forkEvent: typeof forkEvent;
|
|
53
|
+
unforkEvent: typeof unforkEvent;
|
|
51
54
|
FlatList: IAnimatedComponent;
|
|
52
55
|
SectionList: IAnimatedComponent;
|
|
53
56
|
createAnimatedComponent: typeof createAnimatedComponent;
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
// The Animated namespace for @symbiote-native/solid.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// The Animated namespace for @symbiote-native/solid. The value graph, easing and imperative drivers
|
|
2
|
+
// come from @symbiote-native/engine (framework-agnostic), so both halves meet here in one object and
|
|
3
|
+
// `Animated.timing(new Animated.Value(0), …).start()` reads as it does in RN.
|
|
4
|
+
//
|
|
5
|
+
// THERE IS NO `Animated.View` / `Animated.Text` / `Animated.Image` / `Animated.ScrollView`, and
|
|
6
|
+
// nothing replaced any of them: `<view style={{ opacity: someAnimatedValue }}>` is the whole API
|
|
7
|
+
// for style, and `<scroll-view onScroll={Animated.event(…)}>` is the whole API for a native-driven
|
|
8
|
+
// scroll listener. The engine resolves an AnimatedNode written into any prop of any host node
|
|
9
|
+
// (`core/engine/src/animated/host-binding.ts`) — it publishes the current value, subscribes the
|
|
10
|
+
// leaf, writes each frame through its own targeted setNativeProps commit, and releases at the
|
|
11
|
+
// commit sweep; `setEventListener` calls `bindAnimatedEvent` on any `on*` prop for EVERY host node,
|
|
12
|
+
// not just a scroll one. Those four were aliases of the wrappers, and a wrapper is a tag now, which
|
|
13
|
+
// is not a value `<Animated.X>` can call.
|
|
14
|
+
//
|
|
15
|
+
// The two below REMAIN because they are tier 3: a render prop decides the list family's output
|
|
16
|
+
// shape in JS, so there is no tag for `<Animated.X>` to be an alias of.
|
|
7
17
|
//
|
|
8
18
|
// The NATIVE DRIVER is not this module's doing and must not be re-derived here. A
|
|
9
19
|
// useNativeDriver animation promotes the value graph itself (animations/base.ts ->
|
|
10
20
|
// value.__startNativeAnimation -> graph.__makeNative), and the props leaf follows automatically
|
|
11
21
|
// through graph.__addChild. This file only assembles the surface.
|
|
12
22
|
import { AnimatedValue, AnimatedValueXY, AnimatedColor, AnimatedMock, Easing, Platform, timing, spring, decay, parallel, sequence, stagger, loop, delay, add, subtract, multiply, divide, modulo, diffClamp, event, forkEvent, unforkEvent, } from '@symbiote-native/engine';
|
|
13
|
-
import { View } from '../../components/view.jsx';
|
|
14
|
-
import { Text } from '../../components/text.jsx';
|
|
15
|
-
import { Image } from '../../components/image.js';
|
|
16
|
-
import { ScrollView } from '../../components/scroll-view';
|
|
17
23
|
import { FlatList } from '../../components/flat-list/index.jsx';
|
|
18
24
|
import { SectionList } from '../../components/section-list/index.jsx';
|
|
19
25
|
import { createAnimatedComponent } from './create-animated-component.jsx';
|
|
@@ -21,11 +27,6 @@ export { createAnimatedComponent } from './create-animated-component.jsx';
|
|
|
21
27
|
// The pure graph leaves live in the engine (they extend AnimatedWithChildren, no framework);
|
|
22
28
|
// re-exported so this adapter's Animated surface matches React's.
|
|
23
29
|
export { AnimatedProps, AnimatedStyle, AnimatedTransform, } from '@symbiote-native/engine';
|
|
24
|
-
// View/Text/Image are pure host primitives with no cycle back to here, so wrap them eagerly.
|
|
25
|
-
const AnimatedView = createAnimatedComponent(View);
|
|
26
|
-
const AnimatedText = createAnimatedComponent(Text);
|
|
27
|
-
const AnimatedImage = createAnimatedComponent(Image);
|
|
28
|
-
let animatedScrollView;
|
|
29
30
|
let animatedFlatList;
|
|
30
31
|
let animatedSectionList;
|
|
31
32
|
// The live, JS-driven driver half. RN's AnimatedImplementation.
|
|
@@ -58,13 +59,6 @@ const liveDrivers = {
|
|
|
58
59
|
// spreads `...Animated` over the same component getters.
|
|
59
60
|
const drivers = Platform.isDisableAnimations ? AnimatedMock : liveDrivers;
|
|
60
61
|
export const Animated = {
|
|
61
|
-
View: AnimatedView,
|
|
62
|
-
Text: AnimatedText,
|
|
63
|
-
Image: AnimatedImage,
|
|
64
|
-
get ScrollView() {
|
|
65
|
-
animatedScrollView ??= createAnimatedComponent(ScrollView);
|
|
66
|
-
return animatedScrollView;
|
|
67
|
-
},
|
|
68
62
|
get FlatList() {
|
|
69
63
|
animatedFlatList ??= createAnimatedComponent(FlatList);
|
|
70
64
|
return animatedFlatList;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// RN's Image STATICS — `getSize`, `prefetch`, `queryCache`, `abortPrefetch`, `resolveAssetSource`.
|
|
2
|
+
//
|
|
3
|
+
// IN `modules/`, NOT `components/`. The primitive is the `<image>` tag and its fold runs in the
|
|
4
|
+
// engine (`behaviors/image.ts`); what survives under the name `Image` is an imperative API with no
|
|
5
|
+
// view, which is what this bucket is for. Sitting in `components/` was what made a statics object
|
|
6
|
+
// read as a component.
|
|
7
|
+
//
|
|
8
|
+
// A NAMESPACE OBJECT rather than five bare functions, deliberately: `Alert`, `Share`, `Linking`
|
|
9
|
+
// and `Vibration` all take that shape, and an app porting from RN writes `Image.getSize(...)`
|
|
10
|
+
// verbatim. Shared verbatim via `imageStatics`, the same source every other adapter attaches.
|
|
11
|
+
import { imageStatics } from '@symbiote-native/components';
|
|
12
|
+
export const Image = imageStatics;
|
package/build/register.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import '@symbiote-native/components/register';
|
package/build/register.js
CHANGED
|
@@ -1,31 +1,15 @@
|
|
|
1
1
|
// Side-effect ONLY. Exports nothing, and must never be re-exported from the barrel.
|
|
2
2
|
//
|
|
3
|
-
// The
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// invisible to tsc, to vitest, and to grepping the bundle.
|
|
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.
|
|
9
8
|
//
|
|
10
|
-
// A
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Only the LOWERED tags carry this — the wrapper renders `symbiote-text-input-managed` and
|
|
18
|
-
// keeps running its own lifecycle. One owner per node; see `component-names/shared.ts`.
|
|
19
|
-
registerTextInputBehavior();
|
|
20
|
-
// Same reason as TextInput: the wrapper renders `symbiote-switch-managed` and runs its own
|
|
21
|
-
// lastNativeReport/snap-back lifecycle, so the engine's copy attaches only to the bare tag.
|
|
22
|
-
registerSwitchBehavior();
|
|
23
|
-
// Image owns no runtime — its behavior is a prop FOLD and nothing else, and it is registered on the
|
|
24
|
-
// same `symbiote-image` the wrapper already emits rather than on a `-managed` twin. That is safe
|
|
25
|
-
// only because the mapping is idempotent, which `core/components/src/behaviors/image.test.ts`
|
|
26
|
-
// asserts rather than assumes; a wrapper-built node simply folds a second time and nothing moves.
|
|
27
|
-
registerImageBehavior();
|
|
28
|
-
// Fold-only, and it shares the wrapper's tag for the same reason Image does: the mapping has no
|
|
29
|
-
// aliasing at all, so a wrapper-built node folding a second time moves nothing.
|
|
30
|
-
// `core/components/src/behaviors/input-accessory-view.test.ts` asserts that rather than assuming it.
|
|
31
|
-
registerInputAccessoryViewBehavior();
|
|
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';
|