@symbiote-native/vue 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/build/components/activity-indicator/index.android.d.ts +4 -0
  4. package/build/components/activity-indicator/index.android.js +10 -0
  5. package/build/components/activity-indicator/index.d.ts +1 -0
  6. package/build/components/activity-indicator/index.ios.d.ts +4 -0
  7. package/build/components/activity-indicator/index.ios.js +10 -0
  8. package/build/components/activity-indicator/index.js +4 -0
  9. package/build/components/activity-indicator/shared.d.ts +8 -0
  10. package/build/components/activity-indicator/shared.js +48 -0
  11. package/build/components/button.d.ts +14 -0
  12. package/build/components/button.js +59 -0
  13. package/build/components/drawer-layout-android/index.android.d.ts +8 -0
  14. package/build/components/drawer-layout-android/index.android.js +144 -0
  15. package/build/components/drawer-layout-android/index.d.ts +8 -0
  16. package/build/components/drawer-layout-android/index.js +36 -0
  17. package/build/components/drawer-layout-android/shared.d.ts +18 -0
  18. package/build/components/drawer-layout-android/shared.js +6 -0
  19. package/build/components/flat-list/index.d.ts +88 -0
  20. package/build/components/flat-list/index.js +189 -0
  21. package/build/components/image-background.d.ts +9 -0
  22. package/build/components/image-background.js +114 -0
  23. package/build/components/image.d.ts +9 -0
  24. package/build/components/image.js +99 -0
  25. package/build/components/input-accessory-view.d.ts +10 -0
  26. package/build/components/input-accessory-view.js +41 -0
  27. package/build/components/keyboard-avoiding-view.d.ts +18 -0
  28. package/build/components/keyboard-avoiding-view.js +121 -0
  29. package/build/components/modal.d.ts +29 -0
  30. package/build/components/modal.js +134 -0
  31. package/build/components/pressable.d.ts +58 -0
  32. package/build/components/pressable.js +221 -0
  33. package/build/components/refresh-control.d.ts +20 -0
  34. package/build/components/refresh-control.js +53 -0
  35. package/build/components/safe-area-view.d.ts +8 -0
  36. package/build/components/safe-area-view.js +33 -0
  37. package/build/components/scroll-view/index.android.d.ts +4 -0
  38. package/build/components/scroll-view/index.android.js +74 -0
  39. package/build/components/scroll-view/index.d.ts +1 -0
  40. package/build/components/scroll-view/index.ios.d.ts +4 -0
  41. package/build/components/scroll-view/index.ios.js +15 -0
  42. package/build/components/scroll-view/index.js +4 -0
  43. package/build/components/scroll-view/shared.d.ts +96 -0
  44. package/build/components/scroll-view/shared.js +297 -0
  45. package/build/components/scroll-view/sticky-header.d.ts +7 -0
  46. package/build/components/scroll-view/sticky-header.js +195 -0
  47. package/build/components/section-list/index.d.ts +39 -0
  48. package/build/components/section-list/index.js +77 -0
  49. package/build/components/switch/index.android.d.ts +12 -0
  50. package/build/components/switch/index.android.js +13 -0
  51. package/build/components/switch/index.d.ts +2 -0
  52. package/build/components/switch/index.ios.d.ts +12 -0
  53. package/build/components/switch/index.ios.js +11 -0
  54. package/build/components/switch/index.js +5 -0
  55. package/build/components/switch/shared.d.ts +23 -0
  56. package/build/components/switch/shared.js +129 -0
  57. package/build/components/text-input/index.d.ts +24 -0
  58. package/build/components/text-input/index.js +257 -0
  59. package/build/components/touchable-native-feedback.d.ts +24 -0
  60. package/build/components/touchable-native-feedback.js +75 -0
  61. package/build/components/touchable.d.ts +44 -0
  62. package/build/components/touchable.js +150 -0
  63. package/build/components/virtualized-list/index.d.ts +121 -0
  64. package/build/components/virtualized-list/index.js +687 -0
  65. package/build/components/virtualized-section-list/index.d.ts +96 -0
  66. package/build/components/virtualized-section-list/index.js +160 -0
  67. package/build/components.d.ts +51 -0
  68. package/build/components.js +26 -0
  69. package/build/composables/use-color-scheme.d.ts +3 -0
  70. package/build/composables/use-color-scheme.js +24 -0
  71. package/build/composables/use-window-dimensions.d.ts +3 -0
  72. package/build/composables/use-window-dimensions.js +34 -0
  73. package/build/create-tunnel.d.ts +9 -0
  74. package/build/create-tunnel.js +37 -0
  75. package/build/descriptor-to-vue.d.ts +3 -0
  76. package/build/descriptor-to-vue.js +14 -0
  77. package/build/host-instance/index.d.ts +2 -0
  78. package/build/host-instance/index.js +34 -0
  79. package/build/index.d.ts +67 -0
  80. package/build/index.js +90 -0
  81. package/build/modules/animated/create-animated-component.d.ts +4 -0
  82. package/build/modules/animated/create-animated-component.js +169 -0
  83. package/build/modules/animated/index.d.ts +55 -0
  84. package/build/modules/animated/index.js +66 -0
  85. package/build/modules/app-registry/index.d.ts +7 -0
  86. package/build/modules/app-registry/index.js +32 -0
  87. package/build/modules/status-bar.d.ts +17 -0
  88. package/build/modules/status-bar.js +65 -0
  89. package/build/render.d.ts +7 -0
  90. package/build/render.js +43 -0
  91. package/build/renderer.d.ts +4 -0
  92. package/build/renderer.js +129 -0
  93. package/build/runtime-helpers.d.ts +28 -0
  94. package/build/runtime-helpers.js +68 -0
  95. package/build/utils/component-helpers.d.ts +2 -0
  96. package/build/utils/component-helpers.js +13 -0
  97. package/build/utils/model-binding.d.ts +4 -0
  98. package/build/utils/model-binding.js +17 -0
  99. package/build/utils/normalize-attrs.d.ts +1 -0
  100. package/build/utils/normalize-attrs.js +30 -0
  101. package/build/utils/slots-to-render-props.d.ts +4 -0
  102. package/build/utils/slots-to-render-props.js +18 -0
  103. package/metro-css-parser.cjs +12 -0
  104. package/package.json +54 -0
@@ -0,0 +1,88 @@
1
+ import { type VNode } from '@vue/runtime-core';
2
+ import { type ISeparatorProps, type ISeparators, type IViewabilityConfigCallbackPair, type IViewableItemsChangedInfo, type IVirtualizedListHandle } from '@symbiote-native/components';
3
+ import { type IStyleProp, type IViewStyle } from '@symbiote-native/engine';
4
+ export type IFlatListHandle = IVirtualizedListHandle;
5
+ export interface IFlatListProps<ItemT> {
6
+ data: readonly ItemT[];
7
+ keyExtractor?: (item: ItemT, index: number) => string;
8
+ numColumns?: number;
9
+ columnWrapperStyle?: IStyleProp<IViewStyle> | string;
10
+ viewabilityConfigCallbackPairs?: IViewabilityConfigCallbackPair<ItemT>[];
11
+ [key: string]: unknown;
12
+ }
13
+ export type IFlatListSlots<ItemT> = {
14
+ item: (info: {
15
+ item: ItemT;
16
+ index: number;
17
+ separators: ISeparators;
18
+ }) => VNode[] | VNode;
19
+ separator?: (props: ISeparatorProps<ItemT>) => VNode[] | VNode;
20
+ header?: () => VNode[] | VNode;
21
+ footer?: () => VNode[] | VNode;
22
+ empty?: () => VNode[] | VNode;
23
+ };
24
+ export type IFlatListEmits<ItemT> = {
25
+ viewableItemsChanged: (info: IViewableItemsChangedInfo<ItemT>) => void;
26
+ endReached: (info: {
27
+ distanceFromEnd: number;
28
+ }) => void;
29
+ startReached: (info: {
30
+ distanceFromStart: number;
31
+ }) => void;
32
+ refresh: () => void;
33
+ scrollToIndexFailed: (info: {
34
+ index: number;
35
+ highestMeasuredFrameIndex: number;
36
+ averageItemLength: number;
37
+ }) => void;
38
+ };
39
+ export declare const FlatList: new <ItemT>(props: (IFlatListProps<ItemT> & ({} | {
40
+ onRefresh?: (() => any) | undefined;
41
+ onViewableItemsChanged?: ((info: IViewableItemsChangedInfo<ItemT>) => any) | undefined;
42
+ onEndReached?: ((info: {
43
+ distanceFromEnd: number;
44
+ }) => any) | undefined;
45
+ onStartReached?: ((info: {
46
+ distanceFromStart: number;
47
+ }) => any) | undefined;
48
+ onScrollToIndexFailed?: ((info: {
49
+ index: number;
50
+ highestMeasuredFrameIndex: number;
51
+ averageItemLength: number;
52
+ }) => any) | undefined;
53
+ })) & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps) => import("vue").CreateComponentPublicInstanceWithMixins<IFlatListProps<ItemT> & ({} | {
54
+ onRefresh?: (() => any) | undefined;
55
+ onViewableItemsChanged?: ((info: IViewableItemsChangedInfo<ItemT>) => any) | undefined;
56
+ onEndReached?: ((info: {
57
+ distanceFromEnd: number;
58
+ }) => any) | undefined;
59
+ onStartReached?: ((info: {
60
+ distanceFromStart: number;
61
+ }) => any) | undefined;
62
+ onScrollToIndexFailed?: ((info: {
63
+ index: number;
64
+ highestMeasuredFrameIndex: number;
65
+ averageItemLength: number;
66
+ }) => any) | undefined;
67
+ }), {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} | IFlatListEmits<ItemT>, import("vue").PublicProps, {}, false, {}, import("vue").SlotsType<IFlatListSlots<ItemT>>, {}, {}, string, {}, any, import("vue").ComponentProvideOptions, {
68
+ P: {};
69
+ B: {};
70
+ D: {};
71
+ C: {};
72
+ M: {};
73
+ Defaults: {};
74
+ }, (IFlatListProps<ItemT> & {}) | (IFlatListProps<ItemT> & {
75
+ onRefresh?: (() => any) | undefined;
76
+ onViewableItemsChanged?: ((info: IViewableItemsChangedInfo<ItemT>) => any) | undefined;
77
+ onEndReached?: ((info: {
78
+ distanceFromEnd: number;
79
+ }) => any) | undefined;
80
+ onStartReached?: ((info: {
81
+ distanceFromStart: number;
82
+ }) => any) | undefined;
83
+ onScrollToIndexFailed?: ((info: {
84
+ index: number;
85
+ highestMeasuredFrameIndex: number;
86
+ averageItemLength: number;
87
+ }) => any) | undefined;
88
+ }), {}, {}, {}, {}, {}>;
@@ -0,0 +1,189 @@
1
+ // FlatList, the Vue convenience surface over VirtualizedList. It takes a plain `data` array
2
+ // and derives getItem/getItemCount; numColumns packs items into rows (a horizontal sub-View),
3
+ // so the virtualized stream is rows, not items (RN's FlatList). All windowing / viewability /
4
+ // batching / imperative scrolling are inherited from VirtualizedList; the data shaping and the
5
+ // row/viewability/separator transforms are shared from @symbiote-native/components.
6
+ //
7
+ // This is the FIRST generic component on the typed-emits pattern (the symbiote port of pd-web-kit):
8
+ // a GENERIC setup function `<ItemT,>(props, ctx: ICtx<IFlatListEmits<ItemT>>)` so the events emit
9
+ // with ItemT-typed payloads (`@viewable-items-changed` carries `ItemT`, not `unknown`). For that to
10
+ // infer at the call site, the generic INPUTS (data/renderItem/keyExtractor/…) must be typed `props`,
11
+ // not `$attrs` — so they are declared in the runtime `props` array; the long passthrough tail
12
+ // (horizontal/inverted/style/getItemLayout/raw scroll/…) still rides through `$attrs` onto the inner
13
+ // VirtualizedList. The inner list still GATES RefreshControl + viewability on callback presence, so
14
+ // each emit bridge is wired to it ONLY when the consumer actually listens (read off the instance
15
+ // vnode props), keeping behavior identical to the prop-callback era.
16
+ import { defineComponent, getCurrentInstance, h, shallowRef, } from '@vue/runtime-core';
17
+ import { SINGLE_COLUMN, chunkIntoRows, expandRowViewability, firstItemOfRow, lastItemOfRow, rowKeyExtractor, } from '@symbiote-native/components';
18
+ import { dlog, resolveClassName, } from '@symbiote-native/engine';
19
+ import { VirtualizedList } from '../virtualized-list';
20
+ import { normalizeVueAttrs } from '../../utils/normalize-attrs';
21
+ // VirtualizedList is itself a generic component (generic construct signature), which h()'s overloads
22
+ // can't resolve. Drive it through a loose functional-component handle (generic-component h()
23
+ // limitation — the ItemT surface is proven at the typed FlatList boundary above).
24
+ const VirtualizedListHost = VirtualizedList;
25
+ // The typed inputs FlatList reads off `props`; everything else falls through $attrs onto the inner
26
+ // VirtualizedList. Listed for the runtime `props` declaration (keyof can't derive it: the index
27
+ // signature widens keyof to `string`).
28
+ const PROP_KEYS = [
29
+ 'data',
30
+ 'keyExtractor',
31
+ 'numColumns',
32
+ 'columnWrapperStyle',
33
+ 'viewabilityConfigCallbackPairs',
34
+ ];
35
+ const EMIT_KEYS = [
36
+ 'viewableItemsChanged',
37
+ 'endReached',
38
+ 'startReached',
39
+ 'refresh',
40
+ 'scrollToIndexFailed',
41
+ ];
42
+ function isRecord(value) {
43
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
44
+ }
45
+ function isVirtualizedListHandle(value) {
46
+ return isRecord(value) && typeof value.scrollToOffset === 'function';
47
+ }
48
+ // The handle FlatList exposes delegates to the inner VirtualizedList's handle (Vue resolves a
49
+ // parent ref to the exposed object, so the wrapper must re-expose rather than forward the ref).
50
+ function buildDelegateHandle(getInner) {
51
+ return {
52
+ scrollToOffset: params => getInner()?.scrollToOffset(params),
53
+ scrollToIndex: params => getInner()?.scrollToIndex(params),
54
+ scrollToItem: params => getInner()?.scrollToItem(params),
55
+ scrollToEnd: params => getInner()?.scrollToEnd(params),
56
+ flashScrollIndicators: () => getInner()?.flashScrollIndicators(),
57
+ getNativeScrollRef: () => getInner()?.getNativeScrollRef() ?? null,
58
+ getScrollableNode: () => getInner()?.getScrollableNode() ?? null,
59
+ getScrollResponder: () => getInner()?.getScrollResponder() ?? null,
60
+ getScrollNode: () => getInner()?.getScrollNode() ?? null,
61
+ recordInteraction: () => getInner()?.recordInteraction(),
62
+ };
63
+ }
64
+ export const FlatList = defineComponent((props, { attrs, expose, emit, slots }) => {
65
+ const inner = shallowRef(null);
66
+ const setInner = (instance) => {
67
+ inner.value = isVirtualizedListHandle(instance) ? instance : null;
68
+ };
69
+ expose(buildDelegateHandle(() => inner.value));
70
+ // VirtualizedList gates RefreshControl + viewability on callback presence, so a bridge is wired
71
+ // ONLY when the consumer actually listens. Declared emits are stripped from $attrs, so read the
72
+ // listener off the instance's own vnode props (what the parent passed) instead.
73
+ const instance = getCurrentInstance();
74
+ const listens = (onName) => {
75
+ const vnodeProps = instance?.vnode.props;
76
+ return vnodeProps != null && typeof vnodeProps[onName] === 'function';
77
+ };
78
+ return () => {
79
+ const data = Array.isArray(props.data) ? props.data : [];
80
+ const keyExtractor = props.keyExtractor;
81
+ const numColumns = typeof props.numColumns === 'number' ? props.numColumns : SINGLE_COLUMN;
82
+ const viewabilityPairs = props.viewabilityConfigCallbackPairs;
83
+ // The chrome slots ride straight down to the inner list; #item/#separator are forwarded as-is
84
+ // for a single column and re-wrapped per cell for multi-column below.
85
+ const chromeSlots = { header: slots.header, footer: slots.footer, empty: slots.empty };
86
+ // The passthrough tail: declared props + declared emits' onX are already removed from $attrs,
87
+ // so what's left is the VirtualizedList passthrough (kebab-folded for the inner list).
88
+ const forwarded = normalizeVueAttrs(attrs);
89
+ dlog(`Vue FlatList over ${data.length} items, ${numColumns} column(s)`);
90
+ // The synthesized list events become VL handlers ONLY when listened, so the inner list keeps
91
+ // gating (no parasitic RefreshControl / viewability work for an unlistened event).
92
+ const endReached = listens('onEndReached')
93
+ ? (info) => emit('endReached', info)
94
+ : undefined;
95
+ const startReached = listens('onStartReached')
96
+ ? (info) => emit('startReached', info)
97
+ : undefined;
98
+ const refresh = listens('onRefresh') ? () => emit('refresh') : undefined;
99
+ const scrollToIndexFailed = listens('onScrollToIndexFailed')
100
+ ? (info) => emit('scrollToIndexFailed', info)
101
+ : undefined;
102
+ const wantsViewability = listens('onViewableItemsChanged');
103
+ if (numColumns <= SINGLE_COLUMN) {
104
+ const onViewableItemsChanged = wantsViewability
105
+ ? (info) => emit('viewableItemsChanged', info)
106
+ : undefined;
107
+ return h(VirtualizedListHost, {
108
+ ...forwarded,
109
+ ref: setInner,
110
+ data,
111
+ getItem: (_source, index) => data[index],
112
+ getItemCount: () => data.length,
113
+ keyExtractor,
114
+ onEndReached: endReached,
115
+ onStartReached: startReached,
116
+ onRefresh: refresh,
117
+ onScrollToIndexFailed: scrollToIndexFailed,
118
+ onViewableItemsChanged,
119
+ viewabilityConfigCallbackPairs: viewabilityPairs,
120
+ },
121
+ // A single column forwards the consumer's slots untouched (#item info shape is identical).
122
+ { ...chromeSlots, item: slots.item, separator: slots.separator });
123
+ }
124
+ // Multi-column: the virtualized stream is rows. Each cell renders its items side by side
125
+ // in a flex-row View so windowing accounts for whole rows.
126
+ const rows = chunkIntoRows(data, numColumns);
127
+ // A class-name string resolves through the shared style registry; an object/array is
128
+ // already style-shaped and passes through as-is.
129
+ const rowStyle = [
130
+ { flexDirection: 'row' },
131
+ typeof props.columnWrapperStyle === 'string'
132
+ ? resolveClassName(props.columnWrapperStyle)
133
+ : isRecord(props.columnWrapperStyle) || Array.isArray(props.columnWrapperStyle)
134
+ ? props.columnWrapperStyle
135
+ : undefined,
136
+ ];
137
+ const rowItemSlot = (info) => {
138
+ const cells = info.item.items.map((item, column) => {
139
+ const index = info.item.startIndex + column;
140
+ const key = keyExtractor ? keyExtractor(item, index) : String(index);
141
+ // The row IS the virtualized cell, so every item in it shares the row's separators
142
+ // handle (the divider sits between rows, not columns), like RN's multi-column FlatList.
143
+ return h('symbiote-view', { key, style: { flex: 1 } }, slots.item !== undefined
144
+ ? slots.item({ item, index, separators: info.separators })
145
+ : []);
146
+ });
147
+ return [h('symbiote-view', { style: rowStyle }, cells)];
148
+ };
149
+ // Viewability over rows expands back to per-item tokens so the caller sees item-level
150
+ // visibility, not row-level (shared expandRowViewability).
151
+ const rowOnViewableItemsChanged = wantsViewability
152
+ ? (rowInfo) => emit('viewableItemsChanged', expandRowViewability(rowInfo, keyExtractor))
153
+ : undefined;
154
+ const rowViewabilityPairs = viewabilityPairs?.map(pair => ({
155
+ viewabilityConfig: pair.viewabilityConfig,
156
+ onViewableItemsChanged: (rowInfo) => {
157
+ pair.onViewableItemsChanged?.(expandRowViewability(rowInfo, keyExtractor));
158
+ },
159
+ }));
160
+ // The divider between rows shows real items (last of the row above, first of the row below),
161
+ // so the user's #separator slot, typed on ItemT, sees items rather than the IRow wrapper.
162
+ const rowSeparatorSlot = slots.separator === undefined
163
+ ? undefined
164
+ : (rowProps) => slots.separator({
165
+ ...rowProps,
166
+ leadingItem: lastItemOfRow(rowProps.leadingItem),
167
+ trailingItem: firstItemOfRow(rowProps.trailingItem),
168
+ });
169
+ return h(VirtualizedListHost, {
170
+ ...forwarded,
171
+ ref: setInner,
172
+ data: rows,
173
+ getItem: (_source, index) => rows[index],
174
+ getItemCount: () => rows.length,
175
+ keyExtractor: rowKeyExtractor,
176
+ onEndReached: endReached,
177
+ onStartReached: startReached,
178
+ onRefresh: refresh,
179
+ onScrollToIndexFailed: scrollToIndexFailed,
180
+ onViewableItemsChanged: rowOnViewableItemsChanged,
181
+ viewabilityConfigCallbackPairs: rowViewabilityPairs,
182
+ }, { ...chromeSlots, item: rowItemSlot, separator: rowSeparatorSlot });
183
+ };
184
+ }, {
185
+ name: 'FlatList',
186
+ inheritAttrs: false,
187
+ props: PROP_KEYS,
188
+ emits: EMIT_KEYS,
189
+ });
@@ -0,0 +1,9 @@
1
+ import { type FunctionalComponent } from '@vue/runtime-core';
2
+ import { type IImageProps } from '@symbiote-native/components';
3
+ import { type IClassNameValue, type IStyleProp, type IViewStyle } from '@symbiote-native/engine';
4
+ export interface IImageBackgroundProps extends Omit<IImageProps, 'style'> {
5
+ style?: IStyleProp<IViewStyle>;
6
+ imageStyle?: IStyleProp<IViewStyle> | string;
7
+ class?: IClassNameValue;
8
+ }
9
+ export declare const ImageBackground: FunctionalComponent<{}, {}, any, {}>;
@@ -0,0 +1,114 @@
1
+ // ImageBackground: the Vue lifecycle half. The composition (the absolute-fill Image behind the
2
+ // children, the dimension-proxy + style-merge math) lives framework-agnostic in
3
+ // @symbiote-native/components/renderImageBackground and is shared verbatim with React; here Vue only
4
+ // narrows the untyped attrs into the typed Image view, folds aria/role, bridges the Descriptor to
5
+ // vnodes, and appends the slot children ON TOP of the inner image.
6
+ //
7
+ // FUNCTIONAL, not a stateful defineComponent: ImageBackground is render-only (no state). Inputs
8
+ // arrive as attrs (untyped); the typed transform fields are narrowed with runtime guards, the
9
+ // forward-only rest is folded so resolveAccessibilityProps lands aria-* onto the inner image.
10
+ import { h } from '@vue/runtime-core';
11
+ import { renderImageBackground, resolveAccessibilityProps, } from '@symbiote-native/components';
12
+ import { resolveClassName, } from '@symbiote-native/engine';
13
+ import { descriptorToVue } from '../descriptor-to-vue';
14
+ import { normalizeVueAttrs } from '../utils/normalize-attrs';
15
+ function asString(value) {
16
+ return typeof value === 'string' ? value : undefined;
17
+ }
18
+ function asNumber(value) {
19
+ return typeof value === 'number' ? value : undefined;
20
+ }
21
+ // A source is a structured object/array or an opaque require() id (number) the engine's injected
22
+ // resolver expands; any object/array/number is a valid source to forward.
23
+ function asSource(value) {
24
+ if (typeof value === 'number')
25
+ return value;
26
+ if (typeof value === 'object' && value !== null)
27
+ return value;
28
+ return undefined;
29
+ }
30
+ function isResizeMode(value) {
31
+ return (value === 'cover' ||
32
+ value === 'contain' ||
33
+ value === 'stretch' ||
34
+ value === 'repeat' ||
35
+ value === 'center');
36
+ }
37
+ function asResizeMode(value) {
38
+ return isResizeMode(value) ? value : undefined;
39
+ }
40
+ function asCrossOrigin(value) {
41
+ return value === 'anonymous' || value === 'use-credentials' ? value : undefined;
42
+ }
43
+ // Object OR array (a style list) passes through: the engine flattens either; primitives degrade
44
+ // to undefined (parity with React, which preserves the StyleProp).
45
+ function isStyleProp(value) {
46
+ return typeof value === 'object' && value !== null;
47
+ }
48
+ function toChildVNode(child) {
49
+ return typeof child === 'string' ? child : descriptorToVue(child);
50
+ }
51
+ // `style` is the WRAPPER View style; `imageStyle` targets the inner Image. The image transform
52
+ // fields are consumed by the source/style fold; everything else forwards onto the inner image.
53
+ const HANDLED_ATTRS = [
54
+ 'style',
55
+ 'imageStyle',
56
+ 'class',
57
+ 'source',
58
+ 'defaultSource',
59
+ 'loadingIndicatorSource',
60
+ 'resizeMode',
61
+ 'tintColor',
62
+ 'src',
63
+ 'srcSet',
64
+ 'alt',
65
+ 'width',
66
+ 'height',
67
+ 'crossOrigin',
68
+ 'referrerPolicy',
69
+ ];
70
+ function forwardAttrs(attrs) {
71
+ const result = {};
72
+ for (const key of Object.keys(attrs)) {
73
+ if (!HANDLED_ATTRS.includes(key))
74
+ result[key] = attrs[key];
75
+ }
76
+ return result;
77
+ }
78
+ const ImageBackgroundComponent = (_props, { attrs: rawAttrs, slots }) => {
79
+ const attrs = normalizeVueAttrs(rawAttrs);
80
+ const wrapper = renderImageBackground({
81
+ style: isStyleProp(attrs.style) ? attrs.style : undefined,
82
+ // A class-name string resolves through the shared style registry, same as `class` above;
83
+ // an object/array is already style-shaped and passes through as-is.
84
+ imageStyle: typeof attrs.imageStyle === 'string'
85
+ ? resolveClassName(attrs.imageStyle)
86
+ : isStyleProp(attrs.imageStyle)
87
+ ? attrs.imageStyle
88
+ : undefined,
89
+ image: {
90
+ source: asSource(attrs.source),
91
+ defaultSource: asSource(attrs.defaultSource),
92
+ loadingIndicatorSource: asSource(attrs.loadingIndicatorSource),
93
+ resizeMode: asResizeMode(attrs.resizeMode),
94
+ tintColor: asString(attrs.tintColor),
95
+ src: asString(attrs.src),
96
+ srcSet: asString(attrs.srcSet),
97
+ alt: asString(attrs.alt),
98
+ width: asNumber(attrs.width),
99
+ height: asNumber(attrs.height),
100
+ crossOrigin: asCrossOrigin(attrs.crossOrigin),
101
+ referrerPolicy: asString(attrs.referrerPolicy),
102
+ passthrough: resolveAccessibilityProps(forwardAttrs(attrs)),
103
+ },
104
+ });
105
+ // wrapper = symbiote-view > [imageDescriptor]; the slot children paint AFTER the image (on top).
106
+ const slotChildren = slots.default !== undefined ? slots.default() : [];
107
+ return h(wrapper.type, { ...wrapper.props, key: wrapper.key, class: attrs.class }, [
108
+ ...wrapper.children.map(toChildVNode),
109
+ ...slotChildren,
110
+ ]);
111
+ };
112
+ ImageBackgroundComponent.displayName = 'ImageBackground';
113
+ ImageBackgroundComponent.inheritAttrs = false;
114
+ export const ImageBackground = ImageBackgroundComponent;
@@ -0,0 +1,9 @@
1
+ import type { FunctionalComponent } from '@vue/runtime-core';
2
+ import { type IImageProps as IImageBaseProps, type IImageStatics } from '@symbiote-native/components';
3
+ import type { IClassNameValue } from '@symbiote-native/engine';
4
+ export { setImageSourceResolver } from '@symbiote-native/components';
5
+ export type { IImageSource, IImageSourceProp, IResizeMode, IImageSize, IImageCacheStatus, } from '@symbiote-native/components';
6
+ export type IImageProps = IImageBaseProps & {
7
+ class?: IClassNameValue;
8
+ };
9
+ export declare const Image: FunctionalComponent<IImageProps> & IImageStatics;
@@ -0,0 +1,99 @@
1
+ // Image: the Vue lifecycle half. The full fold (source / src / srcSet resolution, the
2
+ // width/height → style fold, resizeMode/tintColor, alt → accessibility, and the native source
3
+ // array) lives framework-agnostic in @symbiote-native/components and is shared verbatim with React;
4
+ // here Vue only narrows the untyped attrs into renderImage's typed view, folds aria/role, bridges
5
+ // the Descriptor to a vnode, and carries the Image statics (getSize / prefetch / queryCache / …).
6
+ //
7
+ // FUNCTIONAL, not a stateful defineComponent: Image is render-only, and Animated.Image wraps it
8
+ // via createAnimatedComponent, which captures the host
9
+ // node through a ref that only falls through on a functional component (a defineComponent's ref
10
+ // resolves to a useless component proxy; see components.ts). So Image must stay functional.
11
+ //
12
+ // Inputs arrive as attrs (untyped). The typed transform fields are narrowed with runtime guards;
13
+ // the forward-only rest (events, blurRadius, capInsets, testID, accessibility*) is typed as the
14
+ // a11y intersection so resolveAccessibilityProps folds aria-* into accessibility* over it.
15
+ import { imageStatics, renderImage, resolveAccessibilityProps, } from '@symbiote-native/components';
16
+ import { descriptorToVue } from '../descriptor-to-vue';
17
+ import { normalizeVueAttrs } from '../utils/normalize-attrs';
18
+ export { setImageSourceResolver } from '@symbiote-native/components';
19
+ function asString(value) {
20
+ return typeof value === 'string' ? value : undefined;
21
+ }
22
+ function asNumber(value) {
23
+ return typeof value === 'number' ? value : undefined;
24
+ }
25
+ // A source is a structured object/array or an opaque require() id (number) the engine's injected
26
+ // resolver expands; any object/array/number is a valid source to forward (IImageSource is all-optional).
27
+ function asSource(value) {
28
+ if (typeof value === 'number')
29
+ return value;
30
+ if (typeof value === 'object' && value !== null)
31
+ return value;
32
+ return undefined;
33
+ }
34
+ function isResizeMode(value) {
35
+ return (value === 'cover' ||
36
+ value === 'contain' ||
37
+ value === 'stretch' ||
38
+ value === 'repeat' ||
39
+ value === 'center');
40
+ }
41
+ function asResizeMode(value) {
42
+ return isResizeMode(value) ? value : undefined;
43
+ }
44
+ function asCrossOrigin(value) {
45
+ return value === 'anonymous' || value === 'use-credentials' ? value : undefined;
46
+ }
47
+ // Object OR array (a style list) passes through; readStyleString flattens either, and arrays must
48
+ // survive so `style={[a, b]}` reaches Fabric (parity with React, which preserves the StyleProp).
49
+ function isStyleProp(value) {
50
+ return typeof value === 'object' && value !== null;
51
+ }
52
+ // The typed transform fields renderImage folds; everything else forwards via passthrough.
53
+ const HANDLED_ATTRS = [
54
+ 'source',
55
+ 'defaultSource',
56
+ 'loadingIndicatorSource',
57
+ 'style',
58
+ 'resizeMode',
59
+ 'tintColor',
60
+ 'src',
61
+ 'srcSet',
62
+ 'alt',
63
+ 'width',
64
+ 'height',
65
+ 'crossOrigin',
66
+ 'referrerPolicy',
67
+ ];
68
+ function forwardAttrs(attrs) {
69
+ const result = {};
70
+ for (const key of Object.keys(attrs)) {
71
+ if (!HANDLED_ATTRS.includes(key))
72
+ result[key] = attrs[key];
73
+ }
74
+ return result;
75
+ }
76
+ const ImageComponent = (_props, { attrs: rawAttrs }) => {
77
+ const attrs = normalizeVueAttrs(rawAttrs);
78
+ return descriptorToVue(renderImage({
79
+ source: asSource(attrs.source),
80
+ defaultSource: asSource(attrs.defaultSource),
81
+ loadingIndicatorSource: asSource(attrs.loadingIndicatorSource),
82
+ style: isStyleProp(attrs.style) ? attrs.style : undefined,
83
+ resizeMode: asResizeMode(attrs.resizeMode),
84
+ tintColor: asString(attrs.tintColor),
85
+ src: asString(attrs.src),
86
+ srcSet: asString(attrs.srcSet),
87
+ alt: asString(attrs.alt),
88
+ width: asNumber(attrs.width),
89
+ height: asNumber(attrs.height),
90
+ crossOrigin: asCrossOrigin(attrs.crossOrigin),
91
+ referrerPolicy: asString(attrs.referrerPolicy),
92
+ passthrough: resolveAccessibilityProps(forwardAttrs(attrs)),
93
+ }));
94
+ };
95
+ ImageComponent.displayName = 'Image';
96
+ ImageComponent.inheritAttrs = false;
97
+ // Statics attached like RN (Image.getSize / prefetch / …), shared verbatim with React via
98
+ // the engine-resolved imageStatics. The component value doubles as the statics namespace.
99
+ export const Image = Object.assign(ImageComponent, imageStatics);
@@ -0,0 +1,10 @@
1
+ import { type FunctionalComponent } from '@vue/runtime-core';
2
+ import { type IAccessibilityProps, type IAriaProps } from '@symbiote-native/components';
3
+ import type { IClassNameValue, IStyleProp, IViewStyle } from '@symbiote-native/engine';
4
+ export interface IInputAccessoryViewProps extends IAccessibilityProps, IAriaProps {
5
+ nativeID?: string;
6
+ backgroundColor?: string;
7
+ style?: IStyleProp<IViewStyle>;
8
+ class?: IClassNameValue;
9
+ }
10
+ export declare const InputAccessoryView: FunctionalComponent<{}, {}, any, {}>;
@@ -0,0 +1,41 @@
1
+ // InputAccessoryView: the Vue lifecycle half (iOS). The host-node assembly (nativeID /
2
+ // backgroundColor / style / accessibility forwarding) lives framework-agnostic in
3
+ // @symbiote-native/components/renderInputAccessoryView and is shared verbatim with React; here Vue only
4
+ // narrows the untyped attrs, folds aria/role, bridges the Descriptor, and nests the slot children
5
+ // under the host.
6
+ //
7
+ // FUNCTIONAL, not a stateful defineComponent: render-only (no state). Inputs arrive as attrs
8
+ // (untyped); the typed fields are narrowed with runtime guards, the forward-only rest is folded
9
+ // so resolveAccessibilityProps lands aria-* onto the host node.
10
+ import { h } from '@vue/runtime-core';
11
+ import { renderInputAccessoryView, resolveAccessibilityProps, } from '@symbiote-native/components';
12
+ import { normalizeVueAttrs } from '../utils/normalize-attrs';
13
+ function asString(value) {
14
+ return typeof value === 'string' ? value : undefined;
15
+ }
16
+ function isStyleProp(value) {
17
+ return typeof value === 'object' && value !== null;
18
+ }
19
+ const HANDLED_ATTRS = ['nativeID', 'backgroundColor', 'style'];
20
+ function forwardAttrs(attrs) {
21
+ const result = {};
22
+ for (const key of Object.keys(attrs)) {
23
+ if (!HANDLED_ATTRS.includes(key))
24
+ result[key] = attrs[key];
25
+ }
26
+ return result;
27
+ }
28
+ const InputAccessoryViewComponent = (_props, { attrs: rawAttrs, slots }) => {
29
+ const attrs = normalizeVueAttrs(rawAttrs);
30
+ const host = renderInputAccessoryView({
31
+ nativeID: asString(attrs.nativeID),
32
+ backgroundColor: asString(attrs.backgroundColor),
33
+ style: isStyleProp(attrs.style) ? attrs.style : undefined,
34
+ passthrough: resolveAccessibilityProps(forwardAttrs(attrs)),
35
+ });
36
+ const slotChildren = slots.default !== undefined ? slots.default() : [];
37
+ return h(host.type, { ...host.props, key: host.key }, slotChildren);
38
+ };
39
+ InputAccessoryViewComponent.displayName = 'InputAccessoryView';
40
+ InputAccessoryViewComponent.inheritAttrs = false;
41
+ export const InputAccessoryView = InputAccessoryViewComponent;
@@ -0,0 +1,18 @@
1
+ import { type ISymbioteEvent, type IClassNameValue, type IStyleProp, type IViewStyle } from '@symbiote-native/engine';
2
+ import { type IAccessibilityProps, type IAriaProps, type IKeyboardAvoidingBehavior } from '@symbiote-native/components';
3
+ export interface IKeyboardAvoidingViewProps extends IAccessibilityProps, IAriaProps {
4
+ behavior?: IKeyboardAvoidingBehavior;
5
+ enabled?: boolean;
6
+ keyboardVerticalOffset?: number;
7
+ contentContainerStyle?: IStyleProp<IViewStyle>;
8
+ style?: IStyleProp<IViewStyle>;
9
+ class?: IClassNameValue;
10
+ testID?: string;
11
+ }
12
+ export type IKeyboardAvoidingViewEmits = {
13
+ layout: (event: ISymbioteEvent) => boolean;
14
+ };
15
+ export type { IKeyboardAvoidingBehavior } from '@symbiote-native/components';
16
+ export declare const KeyboardAvoidingView: import("vue").DefineSetupFnComponent<IKeyboardAvoidingViewProps, IKeyboardAvoidingViewEmits, {}, IKeyboardAvoidingViewProps & {
17
+ onLayout?: ((event: ISymbioteEvent) => any) | undefined;
18
+ }, import("vue").PublicProps>;