@symbiote-native/solid 3.0.0 → 3.0.2
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/build/components/flat-list/index.jsx +6 -4
- package/build/components/modal.jsx +20 -15
- package/build/components/scroll-view-props.js +1 -2
- package/build/components/virtualized-list/shared.d.ts +2 -0
- package/build/components/virtualized-list/shared.jsx +5 -1
- package/build/components/virtualized-section-list/index.d.ts +2 -0
- package/package.json +5 -5
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
// caller receives that list's own handle — FlatList's handle IS VirtualizedList's (RN says the
|
|
26
26
|
// same).
|
|
27
27
|
import { Index, Show, createMemo, splitProps, untrack, } from 'solid-js';
|
|
28
|
-
import { SINGLE_COLUMN, chunkIntoRows, expandRowViewability, firstItemOfRow, lastItemOfRow, rowKeyExtractor, } from '@symbiote-native/components';
|
|
29
|
-
import { dlog, resolveClassName, } from '@symbiote-native/engine';
|
|
28
|
+
import { SINGLE_COLUMN, chunkIntoRows, expandRowViewability, firstItemOfRow, lastItemOfRow, removeClippedSubviewsOrDefault, rowKeyExtractor, } from '@symbiote-native/components';
|
|
29
|
+
import { Platform, dlog, resolveClassName, } from '@symbiote-native/engine';
|
|
30
30
|
import { VirtualizedList, } from '../virtualized-list';
|
|
31
31
|
// What FlatList itself consumes or re-shapes. Everything NOT listed here is passthrough and rides
|
|
32
32
|
// down onto the inner list untouched — `ref` among it, which is why no delegate handle is needed.
|
|
@@ -46,6 +46,8 @@ const ROW_STYLE = { flexDirection: 'row' };
|
|
|
46
46
|
const COLUMN_STYLE = { flex: 1 };
|
|
47
47
|
export function FlatList(props) {
|
|
48
48
|
const [, passthrough] = splitProps(props, OWN_PROPS);
|
|
49
|
+
// FlatList.js always sends it, defaulted per platform.
|
|
50
|
+
const removeClippedSubviews = () => removeClippedSubviewsOrDefault(props.removeClippedSubviews, Platform.OS);
|
|
49
51
|
const columnCount = () => props.numColumns ?? SINGLE_COLUMN;
|
|
50
52
|
// RN treats anything at or below one column as an ordinary single-column list rather than an
|
|
51
53
|
// error, and so does adapters/react.
|
|
@@ -112,7 +114,7 @@ export function FlatList(props) {
|
|
|
112
114
|
// soundly for an arbitrary ItemT. <Show> memoizes on the flip alone, so a numColumns change
|
|
113
115
|
// rebuilds (RN documents changing it live as unsupported — "change the key prop" — which is the
|
|
114
116
|
// same fresh start) while every other prop change re-props the live list.
|
|
115
|
-
return (<Show when={isMultiColumn()} fallback={<VirtualizedList {...passthrough} data={props.data} getItem={(_source, index) => props.data[index]} getItemCount={() => props.data.length} renderItem={props.renderItem} keyExtractor={props.keyExtractor} ItemSeparatorComponent={props.ItemSeparatorComponent} onViewableItemsChanged={props.onViewableItemsChanged} viewabilityConfigCallbackPairs={props.viewabilityConfigCallbackPairs}/>}>
|
|
116
|
-
<VirtualizedList {...passthrough} data={rows()} getItem={(_source, index) => rows()[index]} getItemCount={() => rows().length} renderItem={renderRow} keyExtractor={(row) => rowKeyExtractor(row, props.keyExtractor)} ItemSeparatorComponent={rowSeparatorComponent()} onViewableItemsChanged={rowViewability()} viewabilityConfigCallbackPairs={rowViewabilityPairs()}/>
|
|
117
|
+
return (<Show when={isMultiColumn()} fallback={<VirtualizedList {...passthrough} removeClippedSubviews={removeClippedSubviews()} data={props.data} getItem={(_source, index) => props.data[index]} getItemCount={() => props.data.length} renderItem={props.renderItem} keyExtractor={props.keyExtractor} ItemSeparatorComponent={props.ItemSeparatorComponent} onViewableItemsChanged={props.onViewableItemsChanged} viewabilityConfigCallbackPairs={props.viewabilityConfigCallbackPairs}/>}>
|
|
118
|
+
<VirtualizedList {...passthrough} removeClippedSubviews={removeClippedSubviews()} data={rows()} getItem={(_source, index) => rows()[index]} getItemCount={() => rows().length} renderItem={renderRow} keyExtractor={(row) => rowKeyExtractor(row, props.keyExtractor)} ItemSeparatorComponent={rowSeparatorComponent()} onViewableItemsChanged={rowViewability()} viewabilityConfigCallbackPairs={rowViewabilityPairs()}/>
|
|
117
119
|
</Show>);
|
|
118
120
|
}
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
// SEED, which is a mount-time value by definition (React's useReducer lazy init and Svelte's
|
|
35
35
|
// $state(...) initializer read it exactly once too).
|
|
36
36
|
import { createEffect, createSignal, Show, splitProps } from 'solid-js';
|
|
37
|
-
import { createDescriptorShapeGuard, createInitialModalState, modalReducer, renderModal, resolveAccessibilityProps, shouldRenderModal, } from '@symbiote-native/components';
|
|
38
|
-
import { dlog, } from '@symbiote-native/engine';
|
|
37
|
+
import { createDescriptorShapeGuard, createInitialModalState, isModalVisible, modalReducer, modalVisibilityAction, renderModal, resolveAccessibilityProps, shouldRenderModal, } from '@symbiote-native/components';
|
|
38
|
+
import { dlog, Platform, } from '@symbiote-native/engine';
|
|
39
39
|
import { withStableKeys } from '../utils/stable-keys.js';
|
|
40
40
|
// Read by Modal itself; everything else (the four DirectEvents, testID/nativeID, every
|
|
41
41
|
// accessibility* and aria-* field) forwards onto the host node through `passthrough`, exactly as
|
|
@@ -54,28 +54,30 @@ const HANDLED_PROPS = [
|
|
|
54
54
|
'style',
|
|
55
55
|
'class',
|
|
56
56
|
'children',
|
|
57
|
+
'onDismiss',
|
|
57
58
|
];
|
|
58
59
|
const shape = createDescriptorShapeGuard('Modal');
|
|
59
60
|
export function Modal(props) {
|
|
60
61
|
const [local, rest] = splitProps(props, HANDLED_PROPS);
|
|
61
|
-
const isVisible = () => local.visible
|
|
62
|
+
const isVisible = () => isModalVisible(local.visible);
|
|
62
63
|
// The keep-alive seed is a mount-time value by contract (createInitialModalState: a modal that
|
|
63
64
|
// starts visible is rendered, one that starts hidden contributes no node), so this one read
|
|
64
65
|
// outside an accessor is correct rather than the frozen-props bug.
|
|
65
66
|
const [state, setState] = createSignal(createInitialModalState(isVisible()));
|
|
66
|
-
//
|
|
67
|
-
// is
|
|
68
|
-
// so a visible→hidden transition renders once more with isRendered still true (the keep-alive
|
|
69
|
-
// frame) before this drops it. A render effect would unmount immediately and kill the keep-alive.
|
|
70
|
-
// The reducer is identity-stable, so the mount run and any no-op transition write the same object
|
|
71
|
-
// back and nothing downstream recomputes.
|
|
72
|
-
//
|
|
73
|
-
// As on Svelte, and for the same reason: under this adapter's microtask-coalesced requestCommit()
|
|
74
|
-
// the whole cascade settles inside one flush, so the keep-alive frame is real but never lands as
|
|
75
|
-
// its own Fabric commit the way React's synchronous per-render commit makes it.
|
|
67
|
+
// Arms the iOS keep-alive on show; a hide is left to the native dismiss (state/modal.ts). The
|
|
68
|
+
// reducer is identity-stable, so the mount run writes the same object back.
|
|
76
69
|
createEffect(() => {
|
|
77
|
-
|
|
70
|
+
const action = modalVisibilityAction(isVisible());
|
|
71
|
+
if (action !== undefined)
|
|
72
|
+
setState(current => modalReducer(current, action));
|
|
78
73
|
});
|
|
74
|
+
// Modal.js: onDismiss is iOS-only — it drops the keep-alive, then tells the app.
|
|
75
|
+
const handleDismiss = () => {
|
|
76
|
+
if (Platform.OS !== 'ios')
|
|
77
|
+
return;
|
|
78
|
+
setState(current => modalReducer(current, { type: 'hide' }));
|
|
79
|
+
local.onDismiss?.();
|
|
80
|
+
};
|
|
79
81
|
const shouldRender = () => shouldRenderModal(isVisible(), state());
|
|
80
82
|
createEffect(() => {
|
|
81
83
|
if (!shouldRender())
|
|
@@ -98,7 +100,10 @@ export function Modal(props) {
|
|
|
98
100
|
navigationBarTranslucent: local.navigationBarTranslucent,
|
|
99
101
|
allowSwipeDismissal: local.allowSwipeDismissal,
|
|
100
102
|
style: local.style,
|
|
101
|
-
passthrough:
|
|
103
|
+
passthrough: {
|
|
104
|
+
...resolveAccessibilityProps(rest),
|
|
105
|
+
onDismiss: handleDismiss,
|
|
106
|
+
},
|
|
102
107
|
});
|
|
103
108
|
// root = modal > [container]; the user children nest UNDER the container View, never as
|
|
104
109
|
// a direct sibling of the host (RN's modal content layout, render-modal.ts).
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
// behaviors/scroll-view/shared.ts). Horizontal scroll is a separate native
|
|
17
17
|
// ViewManager on Android, so the axis is the tag; a prop contradicting it
|
|
18
18
|
// is dropped with a dlog. Typed here for parity and for a ported app.
|
|
19
|
-
// nestedScrollEnabled defaults to `true`
|
|
20
|
-
// wrapper used to write by hand.
|
|
19
|
+
// nestedScrollEnabled defaults to `true` only under an Android RefreshControl, as in RN.
|
|
21
20
|
//
|
|
22
21
|
// NO `refreshControl` PROP, deliberately — write a `<refresh-control>` CHILD instead; the
|
|
23
22
|
// behavior claims it and places it per platform. Nothing reads a prop by that name, so typing one
|
|
@@ -46,6 +46,8 @@ export interface IVirtualizedListProps<ItemT> extends IAccessibilityProps, IAria
|
|
|
46
46
|
scrollEventThrottle?: number;
|
|
47
47
|
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
48
48
|
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
49
|
+
removeClippedSubviews?: boolean;
|
|
50
|
+
nestedScrollEnabled?: boolean;
|
|
49
51
|
horizontal?: boolean;
|
|
50
52
|
inverted?: boolean;
|
|
51
53
|
style?: IStyleProp<IViewStyle>;
|
|
@@ -629,12 +629,16 @@ export function createVirtualizedList() {
|
|
|
629
629
|
const outerBag = withStableKeys(() => {
|
|
630
630
|
const bag = {
|
|
631
631
|
...resolveAccessibilityProps(accessibilityRest),
|
|
632
|
-
|
|
632
|
+
// VirtualizedList.js: `[inversionStyle, style]` — the app's style can override the flip.
|
|
633
|
+
style: [invertedStyle(), props.style],
|
|
633
634
|
class: props.class,
|
|
634
635
|
contentContainerStyle: contentContainerStyleForContent(),
|
|
635
636
|
onLayout: onViewportLayout,
|
|
636
637
|
onScroll: scrollHandler(),
|
|
637
638
|
};
|
|
639
|
+
// VirtualizedList.js:1111 — Android moves the scrollbar back after the `scale: -1` flip.
|
|
640
|
+
if (props.inverted === true)
|
|
641
|
+
bag.isInvertedVirtualizedList = true;
|
|
638
642
|
// forwarding's throttle, not the raw prop: it folds in the sticky-mode default (1 native / 16
|
|
639
643
|
// JS-fallback), without which a header rebuilt off too-sparse scroll events pins late.
|
|
640
644
|
if (forwarding().scrollEventThrottle !== undefined)
|
|
@@ -55,6 +55,8 @@ export interface IVirtualizedSectionListProps<ItemT> extends IAccessibilityProps
|
|
|
55
55
|
scrollEventThrottle?: number;
|
|
56
56
|
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
57
57
|
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
58
|
+
removeClippedSubviews?: boolean;
|
|
59
|
+
nestedScrollEnabled?: boolean;
|
|
58
60
|
style?: IStyleProp<IViewStyle>;
|
|
59
61
|
contentContainerStyle?: IStyleProp<IViewStyle> | string;
|
|
60
62
|
class?: IClassNameValue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/solid",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "SymbioteNative's Solid adapter — a solid-js/universal createRenderer driving real native iOS/Android views through the same engine as every other adapter.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -62,19 +62,19 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"babel-preset-solid": "^1.9.12",
|
|
64
64
|
"typescript": "~6.0.0",
|
|
65
|
-
"@symbiote-native/components": "3.
|
|
65
|
+
"@symbiote-native/components": "3.1.0",
|
|
66
66
|
"@symbiote-native/css-parser": "0.5.0"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"solid-js": ">=1.9.0",
|
|
70
70
|
"react-native": ">=0.86",
|
|
71
|
-
"@symbiote-native/engine": "^1.
|
|
71
|
+
"@symbiote-native/engine": "^1.3.0"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@babel/core": "^7.25.2",
|
|
75
75
|
"solid-js": "^1.9.14",
|
|
76
|
-
"@symbiote-native/engine": "1.
|
|
77
|
-
"@symbiote-native/test-utils": "0.
|
|
76
|
+
"@symbiote-native/engine": "1.3.0",
|
|
77
|
+
"@symbiote-native/test-utils": "0.4.2"
|
|
78
78
|
},
|
|
79
79
|
"scripts": {
|
|
80
80
|
"typecheck": "tsc --build",
|