@symbiote-native/vue 3.2.0 → 3.4.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 +3 -0
- package/build/components/checkbox-props.js +1 -0
- package/build/components/flat-list/index.d.ts +4 -3
- package/build/components/flat-list/index.js +18 -21
- package/build/components/input-accessory-view-props.d.ts +4 -4
- package/build/components/keyboard-avoiding-view.d.ts +11 -3
- package/build/components/keyboard-avoiding-view.js +38 -69
- package/build/components/layout-conformance-props.d.ts +4 -0
- package/build/components/layout-conformance-props.js +1 -0
- package/build/components/modal/index.d.ts +18 -5
- package/build/components/modal/index.js +53 -24
- package/build/components/refresh-control-props.d.ts +7 -7
- package/build/components/scroll-view/scroll-view-props.d.ts +8 -5
- package/build/components/section-list/index.d.ts +1 -1
- package/build/components/section-list/index.js +2 -6
- package/build/components/text-props.d.ts +3 -3
- package/build/components/touchable-props.d.ts +6 -6
- package/build/components/virtualized-list/index.d.ts +5 -75
- package/build/components/virtualized-list/index.js +130 -558
- package/build/components/virtualized-list/list-children.d.ts +18 -0
- package/build/components/virtualized-list/list-children.js +81 -0
- package/build/components/virtualized-list/list-elements.d.ts +7 -0
- package/build/components/virtualized-list/list-elements.js +29 -0
- package/build/components/virtualized-list/list-scroll-props.d.ts +20 -0
- package/build/components/virtualized-list/list-scroll-props.js +9 -0
- package/build/components/virtualized-list/narrow-props.d.ts +79 -0
- package/build/components/virtualized-list/narrow-props.js +89 -0
- package/build/components/virtualized-list/nested-scope.d.ts +3 -0
- package/build/components/virtualized-list/nested-scope.js +12 -0
- package/build/components/virtualized-list/user-handlers.d.ts +3 -0
- package/build/components/virtualized-list/user-handlers.js +24 -0
- package/build/components/virtualized-list/virtualized-list-props.d.ts +82 -0
- package/build/components/virtualized-list/virtualized-list-props.js +41 -0
- package/build/components/virtualized-section-list/index.d.ts +20 -5
- package/build/components/virtualized-section-list/index.js +81 -95
- package/build/components/virtualized-section-list/section-item-cell.d.ts +18 -0
- package/build/components/virtualized-section-list/section-item-cell.js +52 -0
- package/build/composables/define-native-view-component.d.ts +3 -0
- package/build/composables/define-native-view-component.js +23 -0
- package/build/composables/use-animated-value.d.ts +7 -0
- package/build/composables/use-animated-value.js +14 -0
- package/build/composables/use-color-scheme.d.ts +1 -1
- package/build/composables/use-event.d.ts +6 -0
- package/build/composables/use-event.js +22 -0
- package/build/create-transition/index.d.ts +2 -2
- package/build/create-transition/index.js +1 -1
- package/build/descriptor-to-vue.d.ts +1 -1
- package/build/descriptor-to-vue.js +6 -2
- package/build/index.d.ts +16 -4
- package/build/index.js +18 -31
- 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 +22 -24
- package/build/utils/normalize-attrs.js +10 -4
- package/metro-vue-transformer.cjs +165 -224
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { type VNode } from '@vue/runtime-core';
|
|
1
|
+
import { type Component, type VNode } from '@vue/runtime-core';
|
|
2
2
|
import { type ISeparatorProps, type ISeparators, type IViewabilityConfigCallbackPair, type IViewableItemsChangedInfo, type IVirtualizedListHandle } from '@symbiote-native/components';
|
|
3
3
|
import { type IStyleProp, type IViewStyle } from '@symbiote-native/engine';
|
|
4
4
|
export type IFlatListHandle = IVirtualizedListHandle;
|
|
5
|
-
export
|
|
5
|
+
export type IFlatListProps<ItemT> = {
|
|
6
6
|
data: readonly ItemT[];
|
|
7
7
|
keyExtractor?: (item: ItemT, index: number) => string;
|
|
8
|
+
listItemComponent?: Component;
|
|
8
9
|
numColumns?: number;
|
|
9
10
|
columnWrapperStyle?: IStyleProp<IViewStyle> | string;
|
|
10
11
|
viewabilityConfigCallbackPairs?: IViewabilityConfigCallbackPair<ItemT>[];
|
|
11
12
|
[key: string]: unknown;
|
|
12
|
-
}
|
|
13
|
+
};
|
|
13
14
|
export type IFlatListSlots<ItemT> = {
|
|
14
15
|
item: (info: {
|
|
15
16
|
item: ItemT;
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
// $attrs onto the inner VirtualizedList. The inner list still GATES RefreshControl + viewability
|
|
11
11
|
// on callback presence, so each emit bridge is wired ONLY when the consumer actually listens.
|
|
12
12
|
import { defineComponent, getCurrentInstance, h, shallowRef, } from '@vue/runtime-core';
|
|
13
|
-
import { SINGLE_COLUMN, chunkIntoRows, expandRowViewability, firstItemOfRow, lastItemOfRow, removeClippedSubviewsOrDefault, rowKeyExtractor, } from '@symbiote-native/components';
|
|
13
|
+
import { SINGLE_COLUMN, arrayLikeLength, chunkIntoRows, expandRowViewability, firstItemOfRow, lastItemOfRow, removeClippedSubviewsOrDefault, routeScrollHandle, rowKeyExtractor, } from '@symbiote-native/components';
|
|
14
14
|
import { Platform, dlog, resolveClassName, } from '@symbiote-native/engine';
|
|
15
15
|
import { VirtualizedList } from '../virtualized-list/index.js';
|
|
16
|
+
import { renderCellContent } from '../virtualized-list/list-elements.js';
|
|
16
17
|
import { normalizeVueAttrs } from '../../utils/normalize-attrs.js';
|
|
17
18
|
// VirtualizedList's generic construct signature can't be resolved by h()'s overloads, so drive
|
|
18
19
|
// it through a loose functional-component handle (the ItemT surface is proven at the typed
|
|
@@ -23,6 +24,7 @@ const VirtualizedListHost = VirtualizedList;
|
|
|
23
24
|
const PROP_KEYS = [
|
|
24
25
|
'data',
|
|
25
26
|
'keyExtractor',
|
|
27
|
+
'listItemComponent',
|
|
26
28
|
'numColumns',
|
|
27
29
|
'columnWrapperStyle',
|
|
28
30
|
'viewabilityConfigCallbackPairs',
|
|
@@ -40,6 +42,12 @@ function isRecord(value) {
|
|
|
40
42
|
function isVirtualizedListHandle(value) {
|
|
41
43
|
return isRecord(value) && typeof value.scrollToOffset === 'function';
|
|
42
44
|
}
|
|
45
|
+
// A bare string is a registered class name, an object or array is a style, anything else is none
|
|
46
|
+
function wrapperStyleOf(style) {
|
|
47
|
+
if (typeof style === 'string')
|
|
48
|
+
return resolveClassName(style);
|
|
49
|
+
return isRecord(style) || Array.isArray(style) ? style : undefined;
|
|
50
|
+
}
|
|
43
51
|
// The handle FlatList exposes delegates to the inner VirtualizedList's handle (Vue resolves a
|
|
44
52
|
// parent ref to the exposed object, so the wrapper must re-expose rather than forward the ref).
|
|
45
53
|
function buildDelegateHandle(getInner) {
|
|
@@ -48,12 +56,7 @@ function buildDelegateHandle(getInner) {
|
|
|
48
56
|
scrollToIndex: params => getInner()?.scrollToIndex(params),
|
|
49
57
|
scrollToItem: params => getInner()?.scrollToItem(params),
|
|
50
58
|
scrollToEnd: params => getInner()?.scrollToEnd(params),
|
|
51
|
-
|
|
52
|
-
getNativeScrollRef: () => getInner()?.getNativeScrollRef() ?? null,
|
|
53
|
-
getScrollableNode: () => getInner()?.getScrollableNode() ?? null,
|
|
54
|
-
getScrollResponder: () => getInner()?.getScrollResponder() ?? null,
|
|
55
|
-
getScrollNode: () => getInner()?.getScrollNode() ?? null,
|
|
56
|
-
recordInteraction: () => getInner()?.recordInteraction(),
|
|
59
|
+
...routeScrollHandle(getInner),
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
export const FlatList = defineComponent((props, { attrs, expose, emit, slots, }) => {
|
|
@@ -70,10 +73,10 @@ export const FlatList = defineComponent((props, { attrs, expose, emit, slots, })
|
|
|
70
73
|
return vnodeProps != null && typeof vnodeProps[onName] === 'function';
|
|
71
74
|
};
|
|
72
75
|
return () => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
: [];
|
|
76
|
+
// RN takes any array-like, and a null or a non-list as an empty one
|
|
77
|
+
const data = props.data;
|
|
76
78
|
const keyExtractor = props.keyExtractor;
|
|
79
|
+
const listItemComponent = props.listItemComponent;
|
|
77
80
|
const numColumns = typeof props.numColumns === 'number' ? props.numColumns : SINGLE_COLUMN;
|
|
78
81
|
const viewabilityPairs = props.viewabilityConfigCallbackPairs;
|
|
79
82
|
const chromeSlots = {
|
|
@@ -87,7 +90,7 @@ export const FlatList = defineComponent((props, { attrs, expose, emit, slots, })
|
|
|
87
90
|
...normalizedAttrs,
|
|
88
91
|
removeClippedSubviews: removeClippedSubviewsOrDefault(normalizedAttrs.removeClippedSubviews, Platform.OS),
|
|
89
92
|
};
|
|
90
|
-
dlog(`Vue FlatList over ${data
|
|
93
|
+
dlog(`Vue FlatList over ${arrayLikeLength(data)} items, ${numColumns} column(s)`);
|
|
91
94
|
const endReached = listens('onEndReached')
|
|
92
95
|
? (info) => emit('endReached', info)
|
|
93
96
|
: undefined;
|
|
@@ -110,8 +113,9 @@ export const FlatList = defineComponent((props, { attrs, expose, emit, slots, })
|
|
|
110
113
|
ref: setInner,
|
|
111
114
|
data,
|
|
112
115
|
getItem: (_source, index) => data[index],
|
|
113
|
-
getItemCount: () => data
|
|
116
|
+
getItemCount: () => arrayLikeLength(data),
|
|
114
117
|
keyExtractor,
|
|
118
|
+
listItemComponent: props.listItemComponent,
|
|
115
119
|
onEndReached: endReached,
|
|
116
120
|
onStartReached: startReached,
|
|
117
121
|
onRefresh: refresh,
|
|
@@ -125,12 +129,7 @@ export const FlatList = defineComponent((props, { attrs, expose, emit, slots, })
|
|
|
125
129
|
const rows = chunkIntoRows(data, numColumns);
|
|
126
130
|
const rowStyle = [
|
|
127
131
|
{ flexDirection: 'row' },
|
|
128
|
-
|
|
129
|
-
? resolveClassName(props.columnWrapperStyle)
|
|
130
|
-
: isRecord(props.columnWrapperStyle) ||
|
|
131
|
-
Array.isArray(props.columnWrapperStyle)
|
|
132
|
-
? props.columnWrapperStyle
|
|
133
|
-
: undefined,
|
|
132
|
+
wrapperStyleOf(props.columnWrapperStyle),
|
|
134
133
|
];
|
|
135
134
|
const rowItemSlot = (info) => {
|
|
136
135
|
const cells = info.item.items.map((item, column) => {
|
|
@@ -138,9 +137,7 @@ export const FlatList = defineComponent((props, { attrs, expose, emit, slots, })
|
|
|
138
137
|
const key = keyExtractor ? keyExtractor(item, index) : String(index);
|
|
139
138
|
// The row IS the virtualized cell, so every item in it shares the row's separators
|
|
140
139
|
// handle (the divider sits between rows, not columns), like RN's multi-column FlatList.
|
|
141
|
-
return h('view', { key, style: { flex: 1 } }, slots.item
|
|
142
|
-
? slots.item({ item, index, separators: info.separators })
|
|
143
|
-
: []);
|
|
140
|
+
return h('view', { key, style: { flex: 1 } }, renderCellContent({ renderItem: slots.item, listItemComponent }, { item, index, separators: info.separators }) ?? []);
|
|
144
141
|
});
|
|
145
142
|
return [h('view', { style: rowStyle }, cells)];
|
|
146
143
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { IAccessibilityProps, IAriaProps } from '@symbiote-native/components';
|
|
2
|
-
import type { IClassNameValue, IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
3
|
-
export
|
|
2
|
+
import type { IClassNameValue, IColorValue, IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
3
|
+
export type IInputAccessoryViewProps = IAccessibilityProps & IAriaProps & {
|
|
4
4
|
nativeID?: string;
|
|
5
|
-
backgroundColor?:
|
|
5
|
+
backgroundColor?: IColorValue;
|
|
6
6
|
style?: IStyleProp<IViewStyle>;
|
|
7
7
|
class?: IClassNameValue;
|
|
8
|
-
}
|
|
8
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ISymbioteEvent, type IClassNameValue, type IStyleProp, type IViewStyle } from '@symbiote-native/engine';
|
|
2
2
|
import { type IAccessibilityProps, type IAriaProps, type IKeyboardAvoidingBehavior } from '@symbiote-native/components';
|
|
3
|
-
export
|
|
3
|
+
export type IKeyboardAvoidingViewProps = IAccessibilityProps & IAriaProps & {
|
|
4
4
|
behavior?: IKeyboardAvoidingBehavior;
|
|
5
5
|
enabled?: boolean;
|
|
6
6
|
keyboardVerticalOffset?: number;
|
|
@@ -8,11 +8,19 @@ export interface IKeyboardAvoidingViewProps extends IAccessibilityProps, IAriaPr
|
|
|
8
8
|
style?: IStyleProp<IViewStyle>;
|
|
9
9
|
class?: IClassNameValue;
|
|
10
10
|
testID?: string;
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
export type IKeyboardAvoidingViewEmits = {
|
|
13
13
|
layout: (event: ISymbioteEvent) => boolean;
|
|
14
14
|
};
|
|
15
15
|
export type { IKeyboardAvoidingBehavior } from '@symbiote-native/components';
|
|
16
|
-
export declare const KeyboardAvoidingView: import("vue").DefineSetupFnComponent<IKeyboardAvoidingViewProps, IKeyboardAvoidingViewEmits, {},
|
|
16
|
+
export declare const KeyboardAvoidingView: import("vue").DefineSetupFnComponent<IKeyboardAvoidingViewProps, IKeyboardAvoidingViewEmits, {}, IAccessibilityProps & IAriaProps & {
|
|
17
|
+
behavior?: IKeyboardAvoidingBehavior;
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
keyboardVerticalOffset?: number;
|
|
20
|
+
contentContainerStyle?: IStyleProp<IViewStyle>;
|
|
21
|
+
style?: IStyleProp<IViewStyle>;
|
|
22
|
+
class?: IClassNameValue;
|
|
23
|
+
testID?: string;
|
|
24
|
+
} & {
|
|
17
25
|
onLayout?: ((event: ISymbioteEvent) => any) | undefined;
|
|
18
26
|
}, import("vue").PublicProps>;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
// KeyboardAvoidingView: the Vue lifecycle half
|
|
2
|
-
//
|
|
3
|
-
// with React; Vue supplies only the reactivity: a ref holds the inset, onMounted subscribes to
|
|
4
|
-
// this host's two keyboard notifications (keyboardAvoidingEventNamesFor — will* on iOS, did* on
|
|
5
|
-
// Android, and never changeFrame), onUnmounted tears the subscriptions down, and onLayout
|
|
6
|
-
// measures the wrapper frame that feeds the next event's inset.
|
|
7
|
-
//
|
|
8
|
-
// Inputs arrive as attrs (untyped), so each is narrowed with a runtime guard, never a cast.
|
|
9
|
-
// rawAttrs runs through normalizeVueAttrs so a template `:keyboard-vertical-offset` resolves.
|
|
1
|
+
// KeyboardAvoidingView: the Vue lifecycle half over the shared `createKeyboardAvoidingModel`
|
|
2
|
+
// Inputs arrive as attrs and are narrowed with runtime guards, never a cast
|
|
10
3
|
import { defineComponent, h, ref, onMounted, onUnmounted, } from '@vue/runtime-core';
|
|
11
|
-
import { Keyboard, Platform,
|
|
12
|
-
import {
|
|
4
|
+
import { Keyboard, Platform, } from '@symbiote-native/engine';
|
|
5
|
+
import { createKeyboardAvoidingModel, keyboardAvoidingEventNamesFor, readPrefersCrossFadeTransitions, resolveKeyboardAvoidingLayout, resolveAccessibilityProps, DEFAULT_VERTICAL_OFFSET, } from '@symbiote-native/components';
|
|
13
6
|
import { normalizeVueAttrs } from '../utils/normalize-attrs.js';
|
|
14
7
|
function isStyleProp(value) {
|
|
15
8
|
return typeof value === 'object' && value !== null;
|
|
@@ -35,55 +28,31 @@ function forwardAttrs(attrs) {
|
|
|
35
28
|
}
|
|
36
29
|
return result;
|
|
37
30
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
// next keyboard event's inset math.
|
|
42
|
-
let frame;
|
|
43
|
-
let initialHeight;
|
|
44
|
-
// A device accessibility setting, read once per mount. Deliberately a plain variable, not a
|
|
45
|
-
// ref: it cannot change during a session, so nothing should re-render when it resolves.
|
|
31
|
+
// The model with its keyboard subscriptions, kept apart so the setup reads as the render
|
|
32
|
+
function useKeyboardModel(currentAttrs, setInset) {
|
|
33
|
+
// A device setting read once per mount, a plain variable since nothing should re-render for it
|
|
46
34
|
let prefersCrossFadeTransitions = false;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// in 'height' mode the wrapper is shrunk by it, so the next onLayout under-reports the
|
|
61
|
-
// frame by exactly that much and core adds it back.
|
|
62
|
-
previousInset,
|
|
63
|
-
prefersCrossFadeTransitions,
|
|
64
|
-
});
|
|
65
|
-
// RN's `_updateBottomIfNecessary` skips the animation when the inset did not change.
|
|
66
|
-
if (next !== previousInset)
|
|
67
|
-
configureKeyboardAvoidingAnimation(readKeyboardAnimationTiming(payload), currentAttrs().enabled !== false);
|
|
68
|
-
dlog(`KeyboardAvoidingView show -> inset ${next}`);
|
|
69
|
-
inset.value = next;
|
|
70
|
-
};
|
|
71
|
-
const onHide = () => {
|
|
72
|
-
dlog('KeyboardAvoidingView hide -> inset 0');
|
|
73
|
-
inset.value = 0;
|
|
74
|
-
};
|
|
35
|
+
const model = createKeyboardAvoidingModel({
|
|
36
|
+
options: () => {
|
|
37
|
+
const attrs = currentAttrs();
|
|
38
|
+
const offset = attrs.keyboardVerticalOffset;
|
|
39
|
+
return {
|
|
40
|
+
behavior: asBehavior(attrs.behavior),
|
|
41
|
+
enabled: attrs.enabled !== false,
|
|
42
|
+
keyboardVerticalOffset: typeof offset === 'number' ? offset : DEFAULT_VERTICAL_OFFSET,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
setInset,
|
|
46
|
+
prefersCrossFade: () => prefersCrossFadeTransitions,
|
|
47
|
+
});
|
|
75
48
|
let subscriptions = [];
|
|
76
49
|
onMounted(() => {
|
|
77
|
-
// TWO notifications, per host: iOS takes the will* pair so the view rides up with the
|
|
78
|
-
// keyboard animation, Android the did* pair. changeFrame is deliberately absent — with an
|
|
79
|
-
// undocked/split/floating iOS keyboard it fires BEFORE the hide, mid-dismissal.
|
|
80
50
|
const events = keyboardAvoidingEventNamesFor(Platform.OS);
|
|
81
51
|
subscriptions = [
|
|
82
|
-
Keyboard.addListener(events.show,
|
|
83
|
-
Keyboard.addListener(events.hide,
|
|
52
|
+
Keyboard.addListener(events.show, model.keyboardShown),
|
|
53
|
+
Keyboard.addListener(events.hide, model.keyboardHidden),
|
|
84
54
|
];
|
|
85
|
-
// Nobody awaits this,
|
|
86
|
-
// native read instead of leaving an unhandled rejection.
|
|
55
|
+
// Nobody awaits this, the core wrapper answers false on a failed native read
|
|
87
56
|
void readPrefersCrossFadeTransitions().then(enabled => {
|
|
88
57
|
prefersCrossFadeTransitions = enabled;
|
|
89
58
|
});
|
|
@@ -93,38 +62,38 @@ export const KeyboardAvoidingView = defineComponent((_props, { attrs: rawAttrs,
|
|
|
93
62
|
subscription.remove();
|
|
94
63
|
subscriptions = [];
|
|
95
64
|
});
|
|
65
|
+
return model;
|
|
66
|
+
}
|
|
67
|
+
export const KeyboardAvoidingView = defineComponent((_props, { attrs: rawAttrs, slots, emit }) => {
|
|
68
|
+
const inset = ref(0);
|
|
69
|
+
// Read at event time, the attrs are live
|
|
70
|
+
const currentAttrs = () => normalizeVueAttrs(rawAttrs);
|
|
71
|
+
const model = useKeyboardModel(currentAttrs, value => {
|
|
72
|
+
inset.value = value;
|
|
73
|
+
});
|
|
96
74
|
const handleLayout = (event) => {
|
|
97
|
-
|
|
98
|
-
if (measured !== undefined) {
|
|
99
|
-
frame = measured;
|
|
100
|
-
if (initialHeight === undefined)
|
|
101
|
-
initialHeight = measured.height;
|
|
102
|
-
}
|
|
75
|
+
model.laidOut(event.nativeEvent.layout);
|
|
103
76
|
emit('layout', event);
|
|
104
77
|
};
|
|
105
78
|
return () => {
|
|
106
79
|
const attrs = currentAttrs();
|
|
107
|
-
|
|
108
|
-
// RN gates every inset on `enabled ?? true`; only an explicit `false` disables.
|
|
80
|
+
// RN gates every inset on `enabled ?? true`, only an explicit `false` disables
|
|
109
81
|
const isEnabled = attrs.enabled !== false;
|
|
110
|
-
const effectiveInset = isEnabled ? inset.value : 0;
|
|
111
82
|
const layout = resolveKeyboardAvoidingLayout({
|
|
112
|
-
behavior,
|
|
113
|
-
effectiveInset,
|
|
114
|
-
initialHeight,
|
|
83
|
+
behavior: asBehavior(attrs.behavior),
|
|
84
|
+
effectiveInset: isEnabled ? inset.value : 0,
|
|
85
|
+
initialHeight: model.initialHeight(),
|
|
115
86
|
style: isStyleProp(attrs.style) ? attrs.style : undefined,
|
|
116
87
|
contentContainerStyle: isStyleProp(attrs.contentContainerStyle)
|
|
117
88
|
? attrs.contentContainerStyle
|
|
118
89
|
: undefined,
|
|
119
90
|
});
|
|
120
|
-
const childNodes = slots.default
|
|
91
|
+
const childNodes = slots.default?.();
|
|
121
92
|
const wrapperProps = {
|
|
122
93
|
...resolveAccessibilityProps(forwardAttrs(attrs)),
|
|
123
94
|
style: layout.wrapperStyle,
|
|
124
95
|
onLayout: handleLayout,
|
|
125
96
|
};
|
|
126
|
-
// 'nested' pushes the children in an inner view by `bottom: inset`; the wrapper modes
|
|
127
|
-
// adjust the single wrapper directly.
|
|
128
97
|
if (layout.kind === 'nested') {
|
|
129
98
|
return h('view', wrapperProps, [
|
|
130
99
|
h('view', { style: layout.innerStyle }, childNodes),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type IAccessibilityProps, type IAriaProps, type IModalAnimationType, type IModalOrientation, type IModalPresentationStyle } from '@symbiote-native/components';
|
|
2
|
-
import { type IClassNameValue, type IStyleProp, type ISymbioteEvent, type IViewStyle } from '@symbiote-native/engine';
|
|
2
|
+
import { type IClassNameValue, type IColorValue, type IStyleProp, type ISymbioteEvent, type IViewStyle } from '@symbiote-native/engine';
|
|
3
3
|
export type { IModalAnimationType, IModalPresentationStyle, IModalOrientation, IModalOrientationChangeEvent, } from '@symbiote-native/components';
|
|
4
|
-
export
|
|
4
|
+
export type IModalProps = IAccessibilityProps & IAriaProps & {
|
|
5
5
|
visible?: boolean;
|
|
6
6
|
transparent?: boolean;
|
|
7
|
-
backdropColor?:
|
|
7
|
+
backdropColor?: IColorValue;
|
|
8
8
|
animationType?: IModalAnimationType;
|
|
9
9
|
presentationStyle?: IModalPresentationStyle;
|
|
10
10
|
supportedOrientations?: ReadonlyArray<IModalOrientation>;
|
|
@@ -14,14 +14,27 @@ export interface IModalProps extends IAccessibilityProps, IAriaProps {
|
|
|
14
14
|
allowSwipeDismissal?: boolean;
|
|
15
15
|
style?: IStyleProp<IViewStyle>;
|
|
16
16
|
class?: IClassNameValue;
|
|
17
|
-
}
|
|
17
|
+
};
|
|
18
18
|
export type IModalEmits = {
|
|
19
19
|
show: () => boolean;
|
|
20
20
|
dismiss: () => boolean;
|
|
21
21
|
requestClose: () => boolean;
|
|
22
22
|
orientationChange: (event: ISymbioteEvent) => boolean;
|
|
23
23
|
};
|
|
24
|
-
export declare const Modal: import("vue").DefineSetupFnComponent<IModalProps, IModalEmits, {},
|
|
24
|
+
export declare const Modal: import("vue").DefineSetupFnComponent<IModalProps, IModalEmits, {}, IAccessibilityProps & IAriaProps & {
|
|
25
|
+
visible?: boolean;
|
|
26
|
+
transparent?: boolean;
|
|
27
|
+
backdropColor?: IColorValue;
|
|
28
|
+
animationType?: IModalAnimationType;
|
|
29
|
+
presentationStyle?: IModalPresentationStyle;
|
|
30
|
+
supportedOrientations?: ReadonlyArray<IModalOrientation>;
|
|
31
|
+
hardwareAccelerated?: boolean;
|
|
32
|
+
statusBarTranslucent?: boolean;
|
|
33
|
+
navigationBarTranslucent?: boolean;
|
|
34
|
+
allowSwipeDismissal?: boolean;
|
|
35
|
+
style?: IStyleProp<IViewStyle>;
|
|
36
|
+
class?: IClassNameValue;
|
|
37
|
+
} & {
|
|
25
38
|
onShow?: (() => any) | undefined;
|
|
26
39
|
onDismiss?: (() => any) | undefined;
|
|
27
40
|
onRequestClose?: (() => any) | undefined;
|
|
@@ -10,16 +10,14 @@
|
|
|
10
10
|
// Inputs arrive as attrs (untyped), each narrowed with a runtime guard rather than a cast. The
|
|
11
11
|
// events (onShow/onDismiss/onRequestClose/onOrientationChange) are real ViewConfig DirectEvents,
|
|
12
12
|
// so, unlike Switch's pure-JS onValueChange, they forward to the host raw via passthrough.
|
|
13
|
-
import { defineComponent, h, ref, watch } from '@vue/runtime-core';
|
|
14
|
-
import { createInitialModalState, isModalVisible, modalReducer, modalVisibilityAction, renderModal, resolveAccessibilityProps, shouldRenderModal, } from '@symbiote-native/components';
|
|
15
|
-
import { dlog, Platform, } from '@symbiote-native/engine';
|
|
13
|
+
import { defineComponent, getCurrentInstance, h, ref, watch, watchEffect, } from '@vue/runtime-core';
|
|
14
|
+
import { createInitialModalState, isModalVisible, modalReducer, modalVisibilityAction, renderModal, resolveAccessibilityProps, shouldRenderModal, warnAboutModalProps, } from '@symbiote-native/components';
|
|
15
|
+
import { dlog, isProcessableColor, Platform, } from '@symbiote-native/engine';
|
|
16
16
|
import { normalizeVueAttrs } from '../../utils/normalize-attrs.js';
|
|
17
|
+
import { provideVirtualizedListScope } from '../virtualized-list/nested-scope.js';
|
|
17
18
|
function asBoolean(value) {
|
|
18
19
|
return typeof value === 'boolean' ? value : undefined;
|
|
19
20
|
}
|
|
20
|
-
function asString(value) {
|
|
21
|
-
return typeof value === 'string' ? value : undefined;
|
|
22
|
-
}
|
|
23
21
|
function asAnimationType(value) {
|
|
24
22
|
return value === 'none' || value === 'slide' || value === 'fade'
|
|
25
23
|
? value
|
|
@@ -78,15 +76,59 @@ function forwardAttrs(attrs) {
|
|
|
78
76
|
}
|
|
79
77
|
return result;
|
|
80
78
|
}
|
|
81
|
-
|
|
79
|
+
// Arms the iOS keep-alive on show; a hide is left to the native dismiss (state/modal.ts). The
|
|
80
|
+
// reducer is identity-stable, so a no-op transition triggers no extra render.
|
|
81
|
+
function useKeepAlive(rawAttrs) {
|
|
82
82
|
const state = ref(createInitialModalState(isModalVisible(rawAttrs.visible)));
|
|
83
|
-
// Arms the iOS keep-alive on show; a hide is left to the native dismiss (state/modal.ts). The
|
|
84
|
-
// reducer is identity-stable, so a no-op transition triggers no extra render.
|
|
85
83
|
watch(() => isModalVisible(rawAttrs.visible), isVisible => {
|
|
86
84
|
const action = modalVisibilityAction(isVisible);
|
|
87
85
|
if (action !== undefined)
|
|
88
86
|
state.value = modalReducer(state.value, action);
|
|
89
87
|
}, { flush: 'post' });
|
|
88
|
+
return state;
|
|
89
|
+
}
|
|
90
|
+
// The attrs the render and the dev warnings both read
|
|
91
|
+
function modalFlagsOf(attrs) {
|
|
92
|
+
return {
|
|
93
|
+
transparent: asBoolean(attrs.transparent),
|
|
94
|
+
presentationStyle: asPresentationStyle(attrs.presentationStyle),
|
|
95
|
+
statusBarTranslucent: asBoolean(attrs.statusBarTranslucent),
|
|
96
|
+
navigationBarTranslucent: asBoolean(attrs.navigationBarTranslucent),
|
|
97
|
+
allowSwipeDismissal: asBoolean(attrs.allowSwipeDismissal),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Kept apart so the setup reads as lifecycle: the attrs narrowed into what `renderModal` takes
|
|
101
|
+
function modalRootOf(attrs) {
|
|
102
|
+
return renderModal({
|
|
103
|
+
...modalFlagsOf(attrs),
|
|
104
|
+
visible: asBoolean(attrs.visible),
|
|
105
|
+
backdropColor: isProcessableColor(attrs.backdropColor)
|
|
106
|
+
? attrs.backdropColor
|
|
107
|
+
: undefined,
|
|
108
|
+
animationType: asAnimationType(attrs.animationType),
|
|
109
|
+
supportedOrientations: asSupportedOrientations(attrs.supportedOrientations),
|
|
110
|
+
hardwareAccelerated: asBoolean(attrs.hardwareAccelerated),
|
|
111
|
+
style: isStyleProp(attrs.style) ? attrs.style : undefined,
|
|
112
|
+
passthrough: resolveAccessibilityProps(forwardAttrs(attrs)),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// RN checks on mount and on every update, a dev build only
|
|
116
|
+
// The `requestClose` emit is stripped from the attrs, so the vnode props tell if it is listened to
|
|
117
|
+
function useModalWarnings(rawAttrs) {
|
|
118
|
+
const listeners = getCurrentInstance()?.vnode.props;
|
|
119
|
+
watchEffect(() => {
|
|
120
|
+
const attrs = normalizeVueAttrs(rawAttrs);
|
|
121
|
+
warnAboutModalProps({
|
|
122
|
+
...modalFlagsOf(attrs),
|
|
123
|
+
onRequestClose: typeof listeners?.onRequestClose === 'function',
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
export const Modal = defineComponent((_props, { attrs: rawAttrs, slots, emit }) => {
|
|
128
|
+
// The content sits outside the list's scroll, so a list in it is not nested in that list
|
|
129
|
+
provideVirtualizedListScope(null);
|
|
130
|
+
useModalWarnings(rawAttrs);
|
|
131
|
+
const state = useKeepAlive(rawAttrs);
|
|
90
132
|
// Modal.js: onDismiss is iOS-only — it drops the keep-alive, then tells the app.
|
|
91
133
|
const handleDismiss = () => {
|
|
92
134
|
if (Platform.OS !== 'ios')
|
|
@@ -101,26 +143,13 @@ export const Modal = defineComponent((_props, { attrs: rawAttrs, slots, emit })
|
|
|
101
143
|
return null;
|
|
102
144
|
}
|
|
103
145
|
const attrs = normalizeVueAttrs(rawAttrs);
|
|
104
|
-
const root =
|
|
105
|
-
visible: asBoolean(attrs.visible),
|
|
106
|
-
transparent: asBoolean(attrs.transparent),
|
|
107
|
-
backdropColor: asString(attrs.backdropColor),
|
|
108
|
-
animationType: asAnimationType(attrs.animationType),
|
|
109
|
-
presentationStyle: asPresentationStyle(attrs.presentationStyle),
|
|
110
|
-
supportedOrientations: asSupportedOrientations(attrs.supportedOrientations),
|
|
111
|
-
hardwareAccelerated: asBoolean(attrs.hardwareAccelerated),
|
|
112
|
-
statusBarTranslucent: asBoolean(attrs.statusBarTranslucent),
|
|
113
|
-
navigationBarTranslucent: asBoolean(attrs.navigationBarTranslucent),
|
|
114
|
-
allowSwipeDismissal: asBoolean(attrs.allowSwipeDismissal),
|
|
115
|
-
style: isStyleProp(attrs.style) ? attrs.style : undefined,
|
|
116
|
-
passthrough: resolveAccessibilityProps(forwardAttrs(attrs)),
|
|
117
|
-
});
|
|
146
|
+
const root = modalRootOf(attrs);
|
|
118
147
|
// root = modal > [container]; the slot children nest UNDER the container View, never
|
|
119
148
|
// as a direct sibling of the host (RN's modal content layout).
|
|
120
149
|
const [container] = root.children;
|
|
121
150
|
if (typeof container === 'string')
|
|
122
151
|
return null;
|
|
123
|
-
const slotChildren = slots.default
|
|
152
|
+
const slotChildren = slots.default?.() ?? [];
|
|
124
153
|
return h(root.type, {
|
|
125
154
|
...root.props,
|
|
126
155
|
key: root.key,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type { IClassNameValue } from '@symbiote-native/engine';
|
|
1
|
+
import type { IClassNameValue, IColorValue } from '@symbiote-native/engine';
|
|
2
2
|
import type { IAccessibilityProps, IAriaProps } from '@symbiote-native/components';
|
|
3
|
-
export
|
|
3
|
+
export type IRefreshControlProps = IAccessibilityProps & IAriaProps & {
|
|
4
4
|
refreshing: boolean;
|
|
5
5
|
id?: string;
|
|
6
6
|
onRefresh?: () => void | Promise<void>;
|
|
7
|
-
tintColor?:
|
|
7
|
+
tintColor?: IColorValue;
|
|
8
8
|
title?: string;
|
|
9
|
-
titleColor?:
|
|
9
|
+
titleColor?: IColorValue;
|
|
10
10
|
progressViewOffset?: number;
|
|
11
|
-
colors?: readonly
|
|
12
|
-
progressBackgroundColor?:
|
|
11
|
+
colors?: readonly IColorValue[];
|
|
12
|
+
progressBackgroundColor?: IColorValue;
|
|
13
13
|
size?: 'default' | 'large';
|
|
14
14
|
enabled?: boolean;
|
|
15
15
|
class?: IClassNameValue;
|
|
16
|
-
}
|
|
16
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { IClassNameValue, ISymbioteEvent, IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
2
|
-
import type { IAccessibilityProps, IAriaProps } from '@symbiote-native/components';
|
|
1
|
+
import type { IClassNameValue, IColorValue, ISymbioteEvent, IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
2
|
+
import type { IAccessibilityProps, IAriaProps, IInnerViewRef, IScrollViewNativeOnlyProps } from '@symbiote-native/components';
|
|
3
3
|
export type { IScrollViewHandle } from '@symbiote-native/components';
|
|
4
4
|
type IScrollHandler = (event: ISymbioteEvent) => void;
|
|
5
|
-
export
|
|
5
|
+
export type IScrollViewProps = IAccessibilityProps & IAriaProps & IScrollViewNativeOnlyProps & {
|
|
6
6
|
style?: IStyleProp<IViewStyle>;
|
|
7
7
|
contentContainerStyle?: IStyleProp<IViewStyle> | string;
|
|
8
8
|
horizontal?: boolean;
|
|
@@ -31,8 +31,11 @@ export interface IScrollViewProps extends IAccessibilityProps, IAriaProps {
|
|
|
31
31
|
snapToStart?: boolean;
|
|
32
32
|
snapToEnd?: boolean;
|
|
33
33
|
disableIntervalMomentum?: boolean;
|
|
34
|
+
experimental_endDraggingSensitivityMultiplier?: number;
|
|
34
35
|
stickyHeaderIndices?: number[];
|
|
35
36
|
invertStickyHeaders?: boolean;
|
|
37
|
+
stickyHeaderHiddenOnScroll?: boolean;
|
|
38
|
+
innerViewRef?: IInnerViewRef;
|
|
36
39
|
keyboardDismissMode?: 'none' | 'on-drag' | 'interactive';
|
|
37
40
|
keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
|
|
38
41
|
maintainVisibleContentPosition?: {
|
|
@@ -61,7 +64,7 @@ export interface IScrollViewProps extends IAccessibilityProps, IAriaProps {
|
|
|
61
64
|
overScrollMode?: 'auto' | 'always' | 'never';
|
|
62
65
|
fadingEdgeLength?: number;
|
|
63
66
|
persistentScrollbar?: boolean;
|
|
64
|
-
endFillColor?:
|
|
67
|
+
endFillColor?: IColorValue;
|
|
65
68
|
onLayout?: IScrollHandler;
|
|
66
69
|
onScroll?: IScrollHandler;
|
|
67
70
|
onScrollBeginDrag?: IScrollHandler;
|
|
@@ -70,4 +73,4 @@ export interface IScrollViewProps extends IAccessibilityProps, IAriaProps {
|
|
|
70
73
|
onMomentumScrollEnd?: IScrollHandler;
|
|
71
74
|
onScrollToTop?: IScrollHandler;
|
|
72
75
|
class?: IClassNameValue;
|
|
73
|
-
}
|
|
76
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type IVirtualizedSectionListHandle } from '@symbiote-native/components';
|
|
2
2
|
import { type IVirtualizedSectionListEmits, type IVirtualizedSectionListProps, type IVirtualizedSectionListSlots } from '../virtualized-section-list';
|
|
3
3
|
export type { ISection } from '../virtualized-section-list';
|
|
4
4
|
export type ISectionListHandle = IVirtualizedSectionListHandle;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// straight onto VirtualizedSectionList; only the three synthesized events are bridged, gated on
|
|
10
10
|
// listener presence so the inner list keeps its RefreshControl/edge-reached gating.
|
|
11
11
|
import { defineComponent, getCurrentInstance, h, shallowRef, } from '@vue/runtime-core';
|
|
12
|
+
import { routeScrollHandle, } from '@symbiote-native/components';
|
|
12
13
|
import { VirtualizedSectionList, } from '../virtualized-section-list/index.js';
|
|
13
14
|
import { normalizeVueAttrs } from '../../utils/normalize-attrs.js';
|
|
14
15
|
// VirtualizedSectionList's generic construct signature can't be resolved by h()'s overloads, so
|
|
@@ -24,12 +25,7 @@ const EMIT_KEYS = ['endReached', 'startReached', 'refresh'];
|
|
|
24
25
|
function buildDelegate(getInner) {
|
|
25
26
|
return {
|
|
26
27
|
scrollToLocation: params => getInner()?.scrollToLocation(params),
|
|
27
|
-
|
|
28
|
-
getNativeScrollRef: () => getInner()?.getNativeScrollRef() ?? null,
|
|
29
|
-
getScrollableNode: () => getInner()?.getScrollableNode() ?? null,
|
|
30
|
-
getScrollResponder: () => getInner()?.getScrollResponder() ?? null,
|
|
31
|
-
getScrollNode: () => getInner()?.getScrollNode() ?? null,
|
|
32
|
-
recordInteraction: () => getInner()?.recordInteraction(),
|
|
28
|
+
...routeScrollHandle(getInner),
|
|
33
29
|
};
|
|
34
30
|
}
|
|
35
31
|
export const SectionList = defineComponent(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { IClassNameValue, IStyleProp, ISymbioteEvent, ITextStyle } from '@symbiote-native/engine';
|
|
2
|
-
import type { IAccessibilityProps, IAriaProps } from '@symbiote-native/components';
|
|
2
|
+
import type { IAccessibilityProps, IAriaProps, ITextNativeOnlyProps } from '@symbiote-native/components';
|
|
3
3
|
import type { VNodeRef } from '@vue/runtime-core';
|
|
4
|
-
export
|
|
4
|
+
export type ITextProps = IAccessibilityProps & IAriaProps & ITextNativeOnlyProps & {
|
|
5
5
|
style?: IStyleProp<ITextStyle>;
|
|
6
6
|
class?: IClassNameValue;
|
|
7
7
|
onPress?: (event: ISymbioteEvent) => void;
|
|
@@ -21,4 +21,4 @@ export interface ITextProps extends IAccessibilityProps, IAriaProps {
|
|
|
21
21
|
selectionColor?: string;
|
|
22
22
|
ref?: VNodeRef;
|
|
23
23
|
key?: string | number | symbol;
|
|
24
|
-
}
|
|
24
|
+
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
1
|
+
import type { IColorValue, IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
2
2
|
import type { IPressTimingProps } from '@symbiote-native/components';
|
|
3
3
|
import type { IPressableProps } from './pressable-props';
|
|
4
4
|
export type ITouchableBaseProps = Omit<IPressableProps, 'style'> & IPressTimingProps & {
|
|
5
5
|
style?: IStyleProp<IViewStyle>;
|
|
6
6
|
};
|
|
7
|
-
export
|
|
7
|
+
export type ITouchableOpacityProps = ITouchableBaseProps & {
|
|
8
8
|
activeOpacity?: number;
|
|
9
|
-
}
|
|
10
|
-
export
|
|
9
|
+
};
|
|
10
|
+
export type ITouchableHighlightProps = ITouchableBaseProps & {
|
|
11
11
|
activeOpacity?: number;
|
|
12
|
-
underlayColor?:
|
|
12
|
+
underlayColor?: IColorValue;
|
|
13
13
|
touchSoundDisabled?: boolean;
|
|
14
14
|
testOnly_pressed?: boolean;
|
|
15
15
|
onShowUnderlay?: () => void;
|
|
16
16
|
onHideUnderlay?: () => void;
|
|
17
|
-
}
|
|
17
|
+
};
|