@symbiote-native/solid 3.1.0 → 3.3.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/build/components/checkbox-props.d.ts +6 -0
- package/build/components/checkbox-props.js +1 -0
- package/build/components/flat-list/index.d.ts +3 -2
- package/build/components/flat-list/index.jsx +8 -10
- package/build/components/input-accessory-view-props.d.ts +4 -4
- package/build/components/keyboard-avoiding-view.d.ts +2 -2
- package/build/components/keyboard-avoiding-view.jsx +34 -114
- package/build/components/layout-conformance-props.d.ts +6 -0
- package/build/components/layout-conformance-props.js +1 -0
- package/build/components/modal.d.ts +4 -4
- package/build/components/modal.jsx +11 -11
- package/build/components/refresh-control-props.d.ts +7 -7
- package/build/components/scroll-view-props.d.ts +8 -5
- package/build/components/text-input-props.d.ts +2 -1
- package/build/components/text-props.d.ts +3 -3
- package/build/components/touchable-props.d.ts +6 -6
- package/build/components/virtualized-list/index.android.d.ts +2 -2
- package/build/components/virtualized-list/index.ios.d.ts +2 -2
- package/build/components/virtualized-list/item-content.d.ts +6 -0
- package/build/components/virtualized-list/item-content.jsx +9 -0
- package/build/components/virtualized-list/list-body.d.ts +15 -0
- package/build/components/virtualized-list/list-body.jsx +20 -0
- package/build/components/virtualized-list/list-parts.d.ts +14 -0
- package/build/components/virtualized-list/list-parts.js +27 -0
- package/build/components/virtualized-list/list-rows.d.ts +18 -0
- package/build/components/virtualized-list/list-rows.jsx +91 -0
- package/build/components/virtualized-list/list-window.d.ts +11 -0
- package/build/components/virtualized-list/list-window.js +29 -0
- package/build/components/virtualized-list/nested-scope.d.ts +7 -0
- package/build/components/virtualized-list/nested-scope.js +21 -0
- package/build/components/virtualized-list/scroll-handlers.d.ts +12 -0
- package/build/components/virtualized-list/scroll-handlers.js +31 -0
- package/build/components/virtualized-list/scroll-tree.d.ts +18 -0
- package/build/components/virtualized-list/scroll-tree.jsx +143 -0
- package/build/components/virtualized-list/shared.d.ts +3 -74
- package/build/components/virtualized-list/shared.jsx +53 -752
- package/build/components/virtualized-list/sticky-binding.d.ts +13 -0
- package/build/components/virtualized-list/sticky-binding.js +111 -0
- package/build/components/virtualized-list/sticky-header.d.ts +1 -0
- package/build/components/virtualized-list/sticky-header.jsx +11 -159
- package/build/components/virtualized-list/sticky-state.d.ts +14 -0
- package/build/components/virtualized-list/sticky-state.js +54 -0
- package/build/components/virtualized-list/use-list-driver.d.ts +22 -0
- package/build/components/virtualized-list/use-list-driver.js +128 -0
- package/build/components/virtualized-list/use-separators.d.ts +7 -0
- package/build/components/virtualized-list/use-separators.js +22 -0
- package/build/components/virtualized-list/virtualized-list-props.d.ts +86 -0
- package/build/components/virtualized-list/virtualized-list-props.js +53 -0
- package/build/components/virtualized-section-list/index.d.ts +22 -9
- package/build/components/virtualized-section-list/index.jsx +87 -115
- package/build/components/virtualized-section-list/section-item-cell.d.ts +18 -0
- package/build/components/virtualized-section-list/section-item-cell.jsx +37 -0
- package/build/components.d.ts +6 -1
- package/build/components.js +1 -0
- package/build/define-descriptor-component.d.ts +6 -0
- package/build/define-descriptor-component.js +10 -0
- package/build/define-optional-descriptor-component.d.ts +3 -0
- package/build/define-optional-descriptor-component.js +12 -0
- package/build/descriptor-to-solid.d.ts +2 -1
- package/build/descriptor-to-solid.js +7 -3
- package/build/index.d.ts +13 -4
- package/build/index.js +24 -37
- package/build/jsx-runtime.d.ts +2 -0
- package/build/modules/animated/index.d.ts +54 -41
- package/build/modules/animated/index.js +2 -26
- package/build/modules/app-registry/index.d.ts +3 -3
- package/build/modules/app-registry/index.js +2 -2
- package/build/modules/status-bar.js +14 -27
- package/build/primitives/create-color-scheme.d.ts +1 -1
- package/build/primitives/define-native-view-component.d.ts +5 -0
- package/build/primitives/define-native-view-component.js +22 -0
- package/build/primitives/use-event.d.ts +6 -0
- package/build/primitives/use-event.js +18 -0
- package/package.json +6 -6
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// The public prop contract of the Solid VirtualizedList
|
|
2
|
+
// Consumed by the lifecycle itself, everything LEFT OVER is the accessibility surface that rides
|
|
3
|
+
// down onto the scroll host
|
|
4
|
+
export const HANDLED_PROPS = [
|
|
5
|
+
'data',
|
|
6
|
+
'getItem',
|
|
7
|
+
'getItemCount',
|
|
8
|
+
'renderItem',
|
|
9
|
+
'ListItemComponent',
|
|
10
|
+
'getItemLayout',
|
|
11
|
+
'initialNumToRender',
|
|
12
|
+
'windowSize',
|
|
13
|
+
'disableVirtualization',
|
|
14
|
+
'ListHeaderComponent',
|
|
15
|
+
'ListFooterComponent',
|
|
16
|
+
'ListEmptyComponent',
|
|
17
|
+
'ItemSeparatorComponent',
|
|
18
|
+
'CellRendererComponent',
|
|
19
|
+
'ref',
|
|
20
|
+
'onEndReached',
|
|
21
|
+
'onEndReachedThreshold',
|
|
22
|
+
'onStartReached',
|
|
23
|
+
'onStartReachedThreshold',
|
|
24
|
+
'keyExtractor',
|
|
25
|
+
'onViewableItemsChanged',
|
|
26
|
+
'viewabilityConfig',
|
|
27
|
+
'viewabilityConfigCallbackPairs',
|
|
28
|
+
'onScroll',
|
|
29
|
+
'onScrollBeginDrag',
|
|
30
|
+
'onScrollEndDrag',
|
|
31
|
+
'onMomentumScrollBegin',
|
|
32
|
+
'onMomentumScrollEnd',
|
|
33
|
+
'scrollEventThrottle',
|
|
34
|
+
'keyboardShouldPersistTaps',
|
|
35
|
+
'keyboardDismissMode',
|
|
36
|
+
'horizontal',
|
|
37
|
+
'inverted',
|
|
38
|
+
'style',
|
|
39
|
+
'contentContainerStyle',
|
|
40
|
+
'ListHeaderComponentStyle',
|
|
41
|
+
'ListFooterComponentStyle',
|
|
42
|
+
'class',
|
|
43
|
+
'onScrollToIndexFailed',
|
|
44
|
+
'onRefresh',
|
|
45
|
+
'refreshing',
|
|
46
|
+
'progressViewOffset',
|
|
47
|
+
'stickyHeaderIndices',
|
|
48
|
+
'maintainVisibleContentPosition',
|
|
49
|
+
'initialScrollIndex',
|
|
50
|
+
'maxToRenderPerBatch',
|
|
51
|
+
'updateCellsBatchingPeriod',
|
|
52
|
+
'extraData',
|
|
53
|
+
];
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import { type Accessor, type Ref } from 'solid-js';
|
|
2
2
|
import type { JSX } from '../../jsx-runtime';
|
|
3
|
-
import { type ISection, type IAccessibilityProps, type IAriaProps, type ISeparatorProps, type ISeparators, type IVirtualizedSectionListHandle } from '@symbiote-native/components';
|
|
3
|
+
import { type ISection as ICoreSection, type IAccessibilityProps, type IAriaProps, type IInnerViewRef, type ISeparatorProps, type ISeparators, type IVirtualizedSectionListHandle } from '@symbiote-native/components';
|
|
4
4
|
import { type IClassNameValue, type IStyleProp, type ISymbioteEvent, type IViewStyle } from '@symbiote-native/engine';
|
|
5
|
-
|
|
6
|
-
export
|
|
5
|
+
import { type ICellRendererComponent } from '../virtualized-list';
|
|
6
|
+
export type { IVirtualizedSectionListHandle };
|
|
7
|
+
export type ISection<ItemT> = ICoreSection<ItemT> & {
|
|
8
|
+
renderItem?: (info: Accessor<ISectionCellInfo<ItemT>>) => JSX.Element;
|
|
9
|
+
ItemSeparatorComponent?: (props: ISeparatorProps<ItemT>) => JSX.Element;
|
|
10
|
+
};
|
|
11
|
+
export type ISectionHeaderInfo<ItemT> = {
|
|
7
12
|
section: ISection<ItemT>;
|
|
8
|
-
}
|
|
9
|
-
export
|
|
13
|
+
};
|
|
14
|
+
export type ISectionCellInfo<ItemT> = {
|
|
10
15
|
item: ItemT;
|
|
11
16
|
index: number;
|
|
12
17
|
section: ISection<ItemT>;
|
|
13
18
|
separators: ISeparators;
|
|
14
|
-
}
|
|
15
|
-
export
|
|
19
|
+
};
|
|
20
|
+
export type IVirtualizedSectionListProps<ItemT> = IAccessibilityProps & IAriaProps & {
|
|
16
21
|
sections: ReadonlyArray<ISection<ItemT>>;
|
|
17
22
|
renderItem: (info: Accessor<ISectionCellInfo<ItemT>>) => JSX.Element;
|
|
18
23
|
renderSectionHeader?: (info: Accessor<ISectionHeaderInfo<ItemT>>) => JSX.Element;
|
|
19
24
|
renderSectionFooter?: (info: Accessor<ISectionHeaderInfo<ItemT>>) => JSX.Element;
|
|
20
25
|
stickySectionHeadersEnabled?: boolean;
|
|
21
|
-
SectionSeparatorComponent?: () => JSX.Element;
|
|
26
|
+
SectionSeparatorComponent?: (props: ISeparatorProps<ItemT>) => JSX.Element;
|
|
22
27
|
keyExtractor?: (item: ItemT, index: number) => string;
|
|
23
28
|
ItemSeparatorComponent?: (props: ISeparatorProps<ItemT>) => JSX.Element;
|
|
24
29
|
ref?: Ref<IVirtualizedSectionListHandle>;
|
|
25
30
|
ListHeaderComponent?: JSX.Element;
|
|
26
31
|
ListFooterComponent?: JSX.Element;
|
|
27
32
|
ListEmptyComponent?: JSX.Element;
|
|
33
|
+
ListHeaderComponentStyle?: IStyleProp<IViewStyle>;
|
|
34
|
+
ListFooterComponentStyle?: IStyleProp<IViewStyle>;
|
|
28
35
|
extraData?: unknown;
|
|
29
36
|
onEndReached?: (info: {
|
|
30
37
|
distanceFromEnd: number;
|
|
@@ -42,7 +49,10 @@ export interface IVirtualizedSectionListProps<ItemT> extends IAccessibilityProps
|
|
|
42
49
|
maxToRenderPerBatch?: number;
|
|
43
50
|
updateCellsBatchingPeriod?: number;
|
|
44
51
|
windowSize?: number;
|
|
52
|
+
disableVirtualization?: boolean;
|
|
53
|
+
CellRendererComponent?: ICellRendererComponent<unknown>;
|
|
45
54
|
inverted?: boolean;
|
|
55
|
+
horizontal?: boolean;
|
|
46
56
|
maintainVisibleContentPosition?: {
|
|
47
57
|
minIndexForVisible: number;
|
|
48
58
|
autoscrollToTopThreshold?: number;
|
|
@@ -52,13 +62,16 @@ export interface IVirtualizedSectionListProps<ItemT> extends IAccessibilityProps
|
|
|
52
62
|
onScrollEndDrag?: (event: ISymbioteEvent) => void;
|
|
53
63
|
onMomentumScrollBegin?: (event: ISymbioteEvent) => void;
|
|
54
64
|
onMomentumScrollEnd?: (event: ISymbioteEvent) => void;
|
|
65
|
+
onContentSizeChange?: (width: number, height: number) => void;
|
|
55
66
|
scrollEventThrottle?: number;
|
|
56
67
|
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
57
68
|
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
58
69
|
removeClippedSubviews?: boolean;
|
|
59
70
|
nestedScrollEnabled?: boolean;
|
|
71
|
+
stickyHeaderHiddenOnScroll?: boolean;
|
|
72
|
+
innerViewRef?: IInnerViewRef;
|
|
60
73
|
style?: IStyleProp<IViewStyle>;
|
|
61
74
|
contentContainerStyle?: IStyleProp<IViewStyle> | string;
|
|
62
75
|
class?: IClassNameValue;
|
|
63
|
-
}
|
|
76
|
+
};
|
|
64
77
|
export declare function VirtualizedSectionList<ItemT>(props: IVirtualizedSectionListProps<ItemT>): JSX.Element;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// VirtualizedList as a single list, so headers, items and footers are windowed by the same
|
|
4
|
-
// machinery. The flattening, entry keying, separator-item unwrap and scrollToLocation mapping are
|
|
5
|
-
// shared verbatim from @symbiote-native/components; this file wires only Solid's lifecycle.
|
|
1
|
+
// Sections flattened into one virtualized stream: header, items and footer per section
|
|
2
|
+
// Flattening, keying and `scrollToLocation` are shared, this file wires Solid's lifecycle
|
|
6
3
|
import { createMemo, splitProps } from 'solid-js';
|
|
7
|
-
import { flattenSections, resolveStickySectionHeaders,
|
|
4
|
+
import { cellGapsFor, createSeparatorBoard, flattenSections, renderSectionEntry, resolveScrollLocation, resolveStickySectionHeaders, routeScrollHandle, SECTION_ENTRY_KIND, SEPARATOR_GAP_KIND, sectionEntryKey, } from '@symbiote-native/components';
|
|
8
5
|
import { Platform, dlog, } from '@symbiote-native/engine';
|
|
9
6
|
import { VirtualizedList, } from '../virtualized-list';
|
|
7
|
+
import { SectionItemCell } from './section-item-cell.jsx';
|
|
10
8
|
// Consumed by this layer; everything LEFT OVER is VirtualizedList's own surface (the scroll host,
|
|
11
9
|
// the list chrome, the windowing knobs, the accessibility props) and rides down untouched, exactly
|
|
12
10
|
// as React's VirtualizedSectionList spreads its `...rest` onto the inner list.
|
|
@@ -21,125 +19,99 @@ const HANDLED_PROPS = [
|
|
|
21
19
|
'stickySectionHeadersEnabled',
|
|
22
20
|
'ref',
|
|
23
21
|
];
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
22
|
+
// Every entry kind carries its section, so a row whose index briefly points at a neighbour
|
|
23
|
+
// still reads a valid one
|
|
24
|
+
function sectionInfoOf(info) {
|
|
25
|
+
return createMemo(() => ({ section: info().item.section }));
|
|
26
|
+
}
|
|
27
|
+
function cellInfoOf(info, initial) {
|
|
28
|
+
return createMemo((previous) => {
|
|
29
|
+
const entry = info().item;
|
|
30
|
+
if (entry.kind !== SECTION_ENTRY_KIND.item)
|
|
31
|
+
return previous;
|
|
32
|
+
return {
|
|
33
|
+
item: entry.item,
|
|
34
|
+
index: entry.itemIndex,
|
|
35
|
+
section: entry.section,
|
|
36
|
+
separators: initial.separators,
|
|
37
|
+
};
|
|
38
|
+
}, initial);
|
|
39
|
+
}
|
|
40
|
+
// The separator for a gap: the section one, or the item one where a section's own beats the list's
|
|
41
|
+
function separatorRenderFor(gap, props) {
|
|
42
|
+
if (gap.props === undefined)
|
|
43
|
+
return undefined;
|
|
44
|
+
const gapProps = gap.props;
|
|
45
|
+
const Separator = gap.kind === SEPARATOR_GAP_KIND.section
|
|
46
|
+
? props.SectionSeparatorComponent
|
|
47
|
+
: (gapProps.section.ItemSeparatorComponent ??
|
|
48
|
+
props.ItemSeparatorComponent);
|
|
49
|
+
if (Separator === undefined)
|
|
50
|
+
return undefined;
|
|
51
|
+
return ({ isHighlighted, override }) => (<Separator highlighted={isHighlighted} {...gapProps} {...override}/>);
|
|
52
|
+
}
|
|
53
|
+
// An item entry becomes a cell that paints its own separators around the row
|
|
54
|
+
function itemCellFor(rendering, info, entry) {
|
|
55
|
+
const { props, entries, keyOf } = rendering;
|
|
56
|
+
const gaps = createMemo(() => cellGapsFor(entries(), info().index));
|
|
57
|
+
const renderItem = entry.section.renderItem ?? props.renderItem;
|
|
58
|
+
return (<SectionItemCell board={rendering.board} cellKey={createMemo(() => keyOf(info().item))} prevCellKey={createMemo(() => {
|
|
59
|
+
const previous = entries()[info().index - 1];
|
|
60
|
+
return previous === undefined ? undefined : keyOf(previous);
|
|
61
|
+
})} renderItem={separators => renderItem(cellInfoOf(info, {
|
|
62
|
+
item: entry.item,
|
|
63
|
+
index: entry.itemIndex,
|
|
64
|
+
section: entry.section,
|
|
65
|
+
separators,
|
|
66
|
+
}))} leadingSeparator={createMemo(() => separatorRenderFor(gaps().leading, props))} trailingSeparator={createMemo(() => separatorRenderFor(gaps().trailing, props))} isInverted={props.inverted === true}/>);
|
|
67
|
+
}
|
|
68
|
+
// Called once per cell, `buildCell` of `VirtualizedList` already untracks it
|
|
69
|
+
function entryRendererFor(rendering) {
|
|
70
|
+
const { props } = rendering;
|
|
71
|
+
return info => renderSectionEntry({
|
|
72
|
+
header: () => props.renderSectionHeader?.(sectionInfoOf(info)),
|
|
73
|
+
footer: () => props.renderSectionFooter?.(sectionInfoOf(info)),
|
|
74
|
+
item: entry => itemCellFor(rendering, info, entry),
|
|
75
|
+
}, info().item);
|
|
76
|
+
}
|
|
77
|
+
// This handle adds the (section, item) to flat index resolution over the list's own handle
|
|
78
|
+
// The rest routes straight through the shared `IScrollRoutingHandle` tail
|
|
79
|
+
function buildSectionHandle(getInner, locate) {
|
|
80
|
+
return {
|
|
61
81
|
scrollToLocation: (params) => {
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
82
|
+
const target = locate(params);
|
|
83
|
+
if (target === undefined) {
|
|
64
84
|
dlog(`VirtualizedSectionList scrollToLocation: section ${params.sectionIndex} out of range`);
|
|
65
85
|
return;
|
|
66
86
|
}
|
|
67
87
|
dlog(`VirtualizedSectionList scrollToLocation section=${params.sectionIndex} ` +
|
|
68
|
-
`item=${params.itemIndex} -> flat ${
|
|
69
|
-
|
|
70
|
-
index: flatIndex,
|
|
71
|
-
viewOffset: params.viewOffset,
|
|
72
|
-
viewPosition: params.viewPosition,
|
|
73
|
-
animated: params.animated,
|
|
74
|
-
});
|
|
75
|
-
},
|
|
76
|
-
flashScrollIndicators: () => {
|
|
77
|
-
inner?.flashScrollIndicators();
|
|
78
|
-
},
|
|
79
|
-
getNativeScrollRef: () => inner?.getNativeScrollRef() ?? null,
|
|
80
|
-
getScrollableNode: () => inner?.getScrollableNode() ?? null,
|
|
81
|
-
getScrollResponder: () => inner?.getScrollResponder() ?? null,
|
|
82
|
-
getScrollNode: () => inner?.getScrollNode() ?? null,
|
|
83
|
-
recordInteraction: () => {
|
|
84
|
-
inner?.recordInteraction();
|
|
88
|
+
`item=${params.itemIndex} -> flat ${target.index}`);
|
|
89
|
+
getInner()?.scrollToIndex(target);
|
|
85
90
|
},
|
|
91
|
+
...routeScrollHandle(getInner),
|
|
86
92
|
};
|
|
93
|
+
}
|
|
94
|
+
export function VirtualizedSectionList(props) {
|
|
95
|
+
const [, listRest] = splitProps(props, HANDLED_PROPS);
|
|
96
|
+
const flattened = createMemo(() => flattenSections(props.sections));
|
|
97
|
+
const entries = () => flattened().entries;
|
|
98
|
+
// RN sticks section headers by default only on iOS; Android does not unless asked. The
|
|
99
|
+
// headerIndices are the flat positions of every section header, which the inner list wraps.
|
|
100
|
+
const stickyHeaderIndices = () => resolveStickySectionHeaders(props.stickySectionHeadersEnabled, flattened().headerIndices, Platform.OS);
|
|
101
|
+
// The inner list, held by identity in a plain variable
|
|
102
|
+
let inner;
|
|
103
|
+
const handle = buildSectionHandle(() => inner, params => resolveScrollLocation(flattened().headerIndices, stickyHeaderIndices(), params));
|
|
87
104
|
if (typeof props.ref === 'function')
|
|
88
105
|
props.ref(handle);
|
|
89
|
-
// Section chrome keys off its section
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
...entryProps,
|
|
97
|
-
leadingItem: unwrapEntryItem(entryProps.leadingItem),
|
|
98
|
-
trailingItem: unwrapEntryItem(entryProps.trailingItem),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
// The user's separator is typed on ItemT while the inner stream carries the entry wrapper, so
|
|
102
|
-
// each side is unwrapped back to its item — undefined for a gap next to section chrome, which has
|
|
103
|
-
// no item on that side.
|
|
104
|
-
const entrySeparatorComponent = createMemo(() => {
|
|
105
|
-
const ItemSeparator = props.ItemSeparatorComponent;
|
|
106
|
-
if (ItemSeparator === undefined)
|
|
107
|
-
return undefined;
|
|
108
|
-
// ONE bag, not a spread plus two overriding attributes: Solid's mergeProps resolves a key by
|
|
109
|
-
// scanning its sources back to front and taking the first NON-undefined value, so an override
|
|
110
|
-
// that unwraps to `undefined` (every gap next to section chrome) falls back to the raw entry
|
|
111
|
-
// instead of clearing it, and the user's `leadingItem` reads as the wrapper object. Building the
|
|
112
|
-
// whole bag in one function keeps a single source — and, being a spread of a CALL, it compiles
|
|
113
|
-
// to mergeProps(() => …) so the separator's props stay live.
|
|
114
|
-
return (entryProps) => (<ItemSeparator {...entrySeparatorProps(entryProps)}/>);
|
|
106
|
+
// Section chrome keys off its section and never reaches the user's extractor, typed on ItemT
|
|
107
|
+
const entryKeyExtractor = (entry) => sectionEntryKey(entry, props.keyExtractor);
|
|
108
|
+
const renderEntry = entryRendererFor({
|
|
109
|
+
props,
|
|
110
|
+
entries,
|
|
111
|
+
board: createSeparatorBoard(),
|
|
112
|
+
keyOf: entryKeyExtractor,
|
|
115
113
|
});
|
|
116
|
-
|
|
117
|
-
function renderEntry(info) {
|
|
118
|
-
const entry = info().item;
|
|
119
|
-
if (entry.kind === 'header') {
|
|
120
|
-
const header = props.renderSectionHeader;
|
|
121
|
-
return header === undefined
|
|
122
|
-
? undefined
|
|
123
|
-
: header(sectionInfo(info, entry.section));
|
|
124
|
-
}
|
|
125
|
-
if (entry.kind === 'footer') {
|
|
126
|
-
const footer = props.renderSectionFooter;
|
|
127
|
-
return footer === undefined
|
|
128
|
-
? undefined
|
|
129
|
-
: footer(sectionInfo(info, entry.section));
|
|
130
|
-
}
|
|
131
|
-
if (entry.kind === 'section-separator') {
|
|
132
|
-
const SectionSeparator = props.SectionSeparatorComponent;
|
|
133
|
-
return SectionSeparator === undefined ? undefined : <SectionSeparator />;
|
|
134
|
-
}
|
|
135
|
-
return props.renderItem(cellInfo(info, {
|
|
136
|
-
item: entry.item,
|
|
137
|
-
index: entry.itemIndex,
|
|
138
|
-
section: entry.section,
|
|
139
|
-
separators: info().separators,
|
|
140
|
-
}));
|
|
141
|
-
}
|
|
142
|
-
return (<VirtualizedList {...listRest} data={entries()} getItem={(_source, index) => entries()[index]} getItemCount={() => entries().length} renderItem={renderEntry} stickyHeaderIndices={stickyHeaderIndices()} keyExtractor={entryKeyExtractor} ItemSeparatorComponent={entrySeparatorComponent()} ref={list => {
|
|
114
|
+
return (<VirtualizedList {...listRest} data={entries()} getItem={(_source, index) => entries()[index]} getItemCount={() => entries().length} renderItem={renderEntry} stickyHeaderIndices={stickyHeaderIndices()} keyExtractor={entryKeyExtractor} ref={list => {
|
|
143
115
|
inner = list;
|
|
144
116
|
}}/>);
|
|
145
117
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Accessor } from 'solid-js';
|
|
2
|
+
import type { JSX } from '../../jsx-runtime';
|
|
3
|
+
import { type ISeparatorBoard, type ISeparators } from '@symbiote-native/components';
|
|
4
|
+
export type ISeparatorState = {
|
|
5
|
+
isHighlighted: boolean;
|
|
6
|
+
override: Record<string, unknown> | undefined;
|
|
7
|
+
};
|
|
8
|
+
export type ISeparatorRender = (state: ISeparatorState) => JSX.Element;
|
|
9
|
+
export type ISectionItemCellProps = {
|
|
10
|
+
board: ISeparatorBoard<Record<string, unknown>>;
|
|
11
|
+
cellKey: Accessor<string>;
|
|
12
|
+
prevCellKey: Accessor<string | undefined>;
|
|
13
|
+
renderItem: (separators: ISeparators) => JSX.Element;
|
|
14
|
+
leadingSeparator: Accessor<ISeparatorRender | undefined>;
|
|
15
|
+
trailingSeparator: Accessor<ISeparatorRender | undefined>;
|
|
16
|
+
isInverted: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare function SectionItemCell(props: ISectionItemCellProps): JSX.Element;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Item cell with its separators around it, as in RN's `ItemWithSeparator`
|
|
2
|
+
// Their state sits in a shared board, т.к. `highlight()` also lights the previous cell's one
|
|
3
|
+
import { createEffect, createSignal, onCleanup, untrack, } from 'solid-js';
|
|
4
|
+
import { createCellSeparators, } from '@symbiote-native/components';
|
|
5
|
+
export function SectionItemCell(props) {
|
|
6
|
+
const { board } = props;
|
|
7
|
+
const [state, setState] = createSignal(untrack(() => board.read(props.cellKey())));
|
|
8
|
+
createEffect(() => {
|
|
9
|
+
const cellKey = props.cellKey();
|
|
10
|
+
setState(board.read(cellKey));
|
|
11
|
+
const unsubscribe = board.subscribe(cellKey, () => setState(board.read(cellKey)));
|
|
12
|
+
onCleanup(() => {
|
|
13
|
+
unsubscribe();
|
|
14
|
+
board.release(cellKey);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
const separators = createCellSeparators(board, () => ({
|
|
18
|
+
cellKey: props.cellKey(),
|
|
19
|
+
prevCellKey: props.prevCellKey(),
|
|
20
|
+
has: {
|
|
21
|
+
leading: props.leadingSeparator() !== undefined,
|
|
22
|
+
trailing: props.trailingSeparator() !== undefined,
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
const content = untrack(() => props.renderItem(separators));
|
|
26
|
+
const leading = () => props.leadingSeparator()?.({
|
|
27
|
+
isHighlighted: state().leadingHighlighted,
|
|
28
|
+
override: state().leadingOverride,
|
|
29
|
+
});
|
|
30
|
+
const trailing = () => props.trailingSeparator()?.({
|
|
31
|
+
isHighlighted: state().trailingHighlighted,
|
|
32
|
+
override: state().trailingOverride,
|
|
33
|
+
});
|
|
34
|
+
return props.isInverted
|
|
35
|
+
? [trailing, content, leading]
|
|
36
|
+
: [leading, content, trailing];
|
|
37
|
+
}
|
package/build/components.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export type { IViewProps } from './components/view-props';
|
|
2
2
|
export type { ITextProps } from './components/text-props';
|
|
3
3
|
export type { ISafeAreaViewProps } from './components/safe-area-view-props';
|
|
4
|
+
export type { ILayoutConformanceProps } from './components/layout-conformance-props';
|
|
5
|
+
export type { ILayoutConformanceMode } from '@symbiote-native/components';
|
|
4
6
|
export type { IImageProps } from './components/image-props';
|
|
5
7
|
export type { IPressableProps } from './components/pressable-props';
|
|
6
8
|
export type { IActivityIndicatorProps } from './components/activity-indicator-props';
|
|
@@ -16,7 +18,9 @@ export type { IRefreshControlProps } from './components/refresh-control-props';
|
|
|
16
18
|
export type { IScrollViewProps } from './components/scroll-view-props';
|
|
17
19
|
export type { IScrollViewHandle } from '@symbiote-native/components';
|
|
18
20
|
export { VirtualizedList } from './components/virtualized-list';
|
|
19
|
-
export
|
|
21
|
+
export { useVirtualizedListScope } from './components/virtualized-list/nested-scope';
|
|
22
|
+
export type { IListScope } from '@symbiote-native/components';
|
|
23
|
+
export type { IVirtualizedListProps, IVirtualizedListHandle, ICellRendererComponent, ICellRendererProps, IVirtualizedListCellInfo, IVirtualizedListRenderItem, ICellLayout, ISeparators, ISeparatorProps, IViewToken, IViewableItemsChangedInfo, IViewabilityConfig, IViewabilityConfigCallbackPair, } from './components/virtualized-list';
|
|
20
24
|
export { FlatList } from './components/flat-list';
|
|
21
25
|
export type { IFlatListProps, IFlatListHandle } from './components/flat-list';
|
|
22
26
|
export { VirtualizedSectionList } from './components/virtualized-section-list';
|
|
@@ -29,5 +33,6 @@ export { TouchableNativeFeedback } from '@symbiote-native/components';
|
|
|
29
33
|
export type { INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from '@symbiote-native/components';
|
|
30
34
|
export type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
|
|
31
35
|
export type { IButtonProps } from './components/button-props';
|
|
36
|
+
export type { ICheckboxProps } from './components/checkbox-props';
|
|
32
37
|
export type { IImageBackgroundProps } from './components/image-background-props';
|
|
33
38
|
export type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
|
package/build/components.js
CHANGED
|
@@ -8,6 +8,7 @@ export { KeyboardAvoidingView } from './components/keyboard-avoiding-view.jsx';
|
|
|
8
8
|
// for the same import as the component. `IVirtualizedListComponent` stays internal — it is the
|
|
9
9
|
// platform factory's return type, not API.
|
|
10
10
|
export { VirtualizedList } from './components/virtualized-list';
|
|
11
|
+
export { useVirtualizedListScope } from './components/virtualized-list/nested-scope.js';
|
|
11
12
|
// FlatList carries no platform split of its own — the iOS/Android divergence is
|
|
12
13
|
// VirtualizedList's refreshControlMode, inherited by importing that folder, so Metro picks the
|
|
13
14
|
// right variant with nothing here to switch on. IFlatListProps is an Omit over
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
3
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
4
|
+
export declare function defineDescriptorComponent<P extends {
|
|
5
|
+
children?: JSX.Element;
|
|
6
|
+
}>(render: (props: object) => IDescriptor): (props: P) => ISymbioteNode;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { splitProps } from 'solid-js';
|
|
2
|
+
import { descriptorToSolid } from './descriptor-to-solid.js';
|
|
3
|
+
// A component whose host is one shared render function: children are the caller's own and go
|
|
4
|
+
// inside the host, every other prop reaches the render function
|
|
5
|
+
export function defineDescriptorComponent(render) {
|
|
6
|
+
return props => {
|
|
7
|
+
const [, rest] = splitProps(props, ['children']);
|
|
8
|
+
return descriptorToSolid(() => render({ ...rest }), () => props.children);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
2
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
3
|
+
export declare function defineOptionalDescriptorComponent<P extends object>(render: (props: object) => IDescriptor | null): (props: P) => ISymbioteNode | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { descriptorToSolid } from './descriptor-to-solid.js';
|
|
2
|
+
// A childless component whose render function may answer `null`, for a native view that exists
|
|
3
|
+
// on one platform only. The answer is decided once at mount: the bridge builds the node once
|
|
4
|
+
// and then only diffs prop values, so the descriptor's shape must not change afterwards
|
|
5
|
+
export function defineOptionalDescriptorComponent(render) {
|
|
6
|
+
return props => {
|
|
7
|
+
const initial = render({ ...props });
|
|
8
|
+
if (!initial)
|
|
9
|
+
return null;
|
|
10
|
+
return descriptorToSolid(() => render({ ...props }) ?? initial);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
1
2
|
import { type ISymbioteNode } from '@symbiote-native/engine';
|
|
2
3
|
import type { IDescriptor } from '@symbiote-native/components';
|
|
3
|
-
export declare function descriptorToSolid(descriptor: () => IDescriptor): ISymbioteNode;
|
|
4
|
+
export declare function descriptorToSolid(descriptor: () => IDescriptor, children?: () => JSX.Element): ISymbioteNode;
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
import { createMemo, createRenderEffect } from 'solid-js';
|
|
24
24
|
import { isSymbioteNode } from '@symbiote-native/engine';
|
|
25
25
|
import { createDescriptorShapeGuard } from '@symbiote-native/components';
|
|
26
|
-
import { createElement, createTextNode, insertNode, replaceText, spread, } from './renderer.js';
|
|
26
|
+
import { createElement, createTextNode, insert, insertNode, replaceText, spread, } from './renderer.js';
|
|
27
27
|
// The vanished-key widening the render effect below stands on. Shared with the host primitives
|
|
28
28
|
// (components/view, components/text), which fold their props through the same two-branch
|
|
29
29
|
// resolveAccessibilityProps — see that module's header.
|
|
@@ -86,6 +86,10 @@ function mountChildren(parent, children) {
|
|
|
86
86
|
}
|
|
87
87
|
// The memo is what keeps the render fn running ONCE per change no matter how many accessors read
|
|
88
88
|
// it — the root's props, every child's props, every text child all derive from the same call.
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
// `children` is a component's own slot, inserted after the descriptor's children
|
|
90
|
+
export function descriptorToSolid(descriptor, children) {
|
|
91
|
+
const root = buildNode(createMemo(descriptor));
|
|
92
|
+
if (children)
|
|
93
|
+
insert(root, children);
|
|
94
|
+
return root;
|
|
91
95
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -6,8 +6,10 @@ export * from './components';
|
|
|
6
6
|
export type { IAccessibilityProps, IAriaProps, IAccessibilityRole, IRole, IAccessibilityStateValue, IAccessibilityValue, IAccessibilityActionInfo, IResponderProps, IImageSource, IImageSourceProp, IResizeMode, IImageSize, IImageCacheStatus, IEnterKeyHint, IInputMode, ISubmitBehavior, } from '@symbiote-native/components';
|
|
7
7
|
export { setImageSourceResolver } from '@symbiote-native/components';
|
|
8
8
|
export { descriptorToSolid } from './descriptor-to-solid';
|
|
9
|
-
export {
|
|
10
|
-
export
|
|
9
|
+
export { defineDescriptorComponent } from './define-descriptor-component';
|
|
10
|
+
export { defineOptionalDescriptorComponent } from './define-optional-descriptor-component';
|
|
11
|
+
export { AppRegistry, HeadlessJsTaskError, setHostRegistrar, } from './modules/app-registry';
|
|
12
|
+
export type { IComponentProvider, IWrapperComponentProvider, IAppConfig, IAppParameters, IRunnable, IHostRegistrar, IRegistry, IHeadlessTask, ITaskProvider, ITaskCanceller, ITaskCancelProvider, } from './modules/app-registry';
|
|
11
13
|
export { StatusBar } from './modules/status-bar';
|
|
12
14
|
export type { IStatusBarProps, IStatusBarStyle } from './modules/status-bar';
|
|
13
15
|
export { Image } from './modules/image';
|
|
@@ -17,19 +19,26 @@ export { createTunnel } from './create-tunnel';
|
|
|
17
19
|
export type { ITunnel, ITunnelInProps } from './create-tunnel';
|
|
18
20
|
export { createColorScheme } from './primitives/create-color-scheme';
|
|
19
21
|
export { createWindowDimensions } from './primitives/create-window-dimensions';
|
|
22
|
+
export { createAnimatedColor, createAnimatedValue, createAnimatedValueXY, } from '@symbiote-native/engine';
|
|
20
23
|
export { createPermissionHook } from './primitives/create-permission-hook';
|
|
21
24
|
export { createResourceHook } from './primitives/create-resource-hook';
|
|
25
|
+
export { defineNativeViewComponent } from './primitives/define-native-view-component';
|
|
22
26
|
export { createEventValueHook } from './primitives/create-event-value-hook';
|
|
27
|
+
export { useEvent, useEventListener } from './primitives/use-event';
|
|
23
28
|
export { Animated, createAnimatedComponent } from './modules/animated';
|
|
24
29
|
export type { IAnimatedComponentProps } from './modules/animated';
|
|
25
30
|
export { Platform, StyleSheet, PixelRatio, PlatformColor, DynamicColorIOS, processColor, } from '@symbiote-native/engine';
|
|
26
|
-
export { setNativeViewConfigSource, setColorProcessor,
|
|
31
|
+
export { setNativeViewConfigSource, setColorProcessor, } from '@symbiote-native/engine';
|
|
27
32
|
export { dlog, isDebug } from '@symbiote-native/engine';
|
|
28
33
|
export type { IViewStyle, ITextStyle, IFlexAlign, IFlexJustify, ISymbioteEvent, ISymbioteNode, IRootTag, INativeViewConfig, INativeViewConfigSource, IColorValue, IOpaqueColorValue, IDynamicColorIOSTuple, IPixelRatioStatic, IPlatformStatic, IPlatformOSType, IPlatformConstantsIOS, IPlatformConstantsAndroid, IPlatformSelectSpec, } from '@symbiote-native/engine';
|
|
29
|
-
export { Alert, Share, ActionSheetIOS, Linking, Vibration, ToastAndroid, Settings, I18nManager, Dimensions, Appearance, AppState, Keyboard, KEYBOARD_EVENT, BackHandler, PermissionsAndroid, PERMISSIONS, RESULTS, LayoutAnimation, InteractionManager, } from '@symbiote-native/engine';
|
|
34
|
+
export { Alert, Share, ActionSheetIOS, Linking, Vibration, ToastAndroid, Settings, I18nManager, Dimensions, Appearance, AppState, Keyboard, KEYBOARD_EVENT, TextInputState, BackHandler, PermissionsAndroid, PERMISSIONS, RESULTS, LayoutAnimation, InteractionManager, } from '@symbiote-native/engine';
|
|
30
35
|
export type { IAlertType, IAlertButtonStyle, IAlertButton, IAlertButtons, IAlertOptions, IShareContent, IShareOptions, IShareAction, IActionSheetIOSOptions, IShareActionSheetIOSOptions, IShareActionSheetError, IUrlEvent, II18nManagerConstants, IDisplayMetrics, IDisplayMetricsAndroid, IDimensionsPayload, IDimensionsSet, IDimensionsKey, IDimensionsChangeListener, IDimensionsStatic, IColorSchemeName, IColorSchemePreference, IAppStateStatus, IAppStateEvent, IKeyboardEventName, IKeyboardEvent, IKeyboardMetrics, IBackPressEventName, IBackPressHandler, IPermission, IPermissionStatus, IRationale, ILayoutAnimationType, ILayoutAnimationProperty, ILayoutAnimationConfig, ILayoutAnimationAnim, IInteractionEvent, ISimpleTask, IPromiseTask, ITask, IHandle, } from '@symbiote-native/engine';
|
|
31
36
|
export { PanResponder } from '@symbiote-native/engine';
|
|
32
37
|
export type { IPanResponderGestureState, IPanResponderCallbacks, IGestureResponderHandlers, IPanResponderInstance, } from '@symbiote-native/engine';
|
|
33
38
|
export { AccessibilityInfo } from '@symbiote-native/engine';
|
|
34
39
|
export type { IAccessibilityChangeEvent, IAccessibilityChangeEventName, IAccessibilityChangeEventHandler, IAccessibilityAnnouncementFinishedEvent, IAnnounceForAccessibilityOptions, IAccessibilityEventType, } from '@symbiote-native/engine';
|
|
35
40
|
export { For, Index, Show, ErrorBoundary, Suspense, SuspenseList, } from 'solid-js';
|
|
41
|
+
export { DeviceEventEmitter, Easing, EventEmitter, NativeAppEventEmitter, NativeEventEmitter, } from '@symbiote-native/engine';
|
|
42
|
+
export type { IEasing, IEasingFunction, IEmitterSubscription, IEventEmitter, IEventEmitterModule, IEventSubscription, INativeEventListener, } from '@symbiote-native/engine';
|
|
43
|
+
export { codegenNativeCommands, codegenNativeComponent, DevMenu, DevSettings, LogBox, NativeComponentRegistry, NativeModules, Networking, PushNotificationIOS, ReactNativeVersion, registerCallableModule, requireNativeComponent, Systrace, Touchable, TurboModuleRegistry, UIManager, UTFSequence, } from '@symbiote-native/engine';
|
|
44
|
+
export type { IDevSettings } from '@symbiote-native/engine';
|