@symbiote-native/vue 0.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +28 -13
  2. package/babel-jsx.cjs +52 -0
  3. package/build/components/activity-indicator-props.d.ts +5 -0
  4. package/build/components/activity-indicator-props.js +1 -0
  5. package/build/components/button-props.d.ts +5 -0
  6. package/build/components/button-props.js +1 -0
  7. package/build/components/flat-list/index.d.ts +3 -3
  8. package/build/components/flat-list/index.js +2 -2
  9. package/build/components/image-background-props.d.ts +7 -0
  10. package/build/components/image-background-props.js +1 -0
  11. package/build/components/image-props.d.ts +5 -0
  12. package/build/components/image-props.js +5 -0
  13. package/build/components/{input-accessory-view.d.ts → input-accessory-view-props.d.ts} +1 -3
  14. package/build/components/input-accessory-view-props.js +5 -0
  15. package/build/components/keyboard-avoiding-view.js +3 -3
  16. package/build/components/modal/index.js +1 -1
  17. package/build/components/pressable-props.d.ts +29 -0
  18. package/build/components/pressable-props.js +12 -0
  19. package/build/components/refresh-control-props.d.ts +16 -0
  20. package/build/components/refresh-control-props.js +9 -0
  21. package/build/components/safe-area-view-props.d.ts +6 -0
  22. package/build/components/safe-area-view-props.js +5 -0
  23. package/build/components/scroll-view/{shared.d.ts → scroll-view-props.d.ts} +4 -27
  24. package/build/components/scroll-view/scroll-view-props.js +1 -0
  25. package/build/components/section-list/index.d.ts +3 -3
  26. package/build/components/switch/switch-props.d.ts +6 -0
  27. package/build/components/switch/switch-props.js +1 -0
  28. package/build/components/text-input/text-input-props.d.ts +5 -0
  29. package/build/components/text-input/text-input-props.js +1 -0
  30. package/build/components/text-props.d.ts +24 -0
  31. package/build/components/text-props.js +6 -0
  32. package/build/components/touchable-native-feedback-props.d.ts +6 -0
  33. package/build/components/touchable-native-feedback-props.js +1 -0
  34. package/build/components/touchable-props.d.ts +15 -0
  35. package/build/components/touchable-props.js +1 -0
  36. package/build/components/touchable-without-feedback-props.d.ts +3 -0
  37. package/build/components/touchable-without-feedback-props.js +1 -0
  38. package/build/components/view-props.d.ts +29 -0
  39. package/build/components/view-props.js +5 -0
  40. package/build/components/virtualized-list/index.d.ts +3 -3
  41. package/build/components/virtualized-list/index.js +42 -37
  42. package/build/components/virtualized-section-list/index.d.ts +3 -3
  43. package/build/composables/use-raw-attrs.d.ts +1 -0
  44. package/build/composables/use-raw-attrs.js +26 -0
  45. package/build/descriptor-to-vue.js +2 -2
  46. package/build/host-instance/index.js +4 -5
  47. package/build/index.d.ts +25 -27
  48. package/build/index.js +35 -15
  49. package/build/intrinsic-elements.d.ts +19 -0
  50. package/build/intrinsic-elements.js +1 -0
  51. package/build/jsx-runtime.d.ts +67 -0
  52. package/build/jsx-runtime.js +1 -0
  53. package/build/modules/animated/create-animated-component.d.ts +1 -1
  54. package/build/modules/animated/create-animated-component.js +18 -4
  55. package/build/modules/animated/index.d.ts +3 -1
  56. package/build/modules/animated/index.js +20 -19
  57. package/build/modules/image/index.d.ts +3 -0
  58. package/build/modules/image/index.js +13 -0
  59. package/build/register.d.ts +1 -0
  60. package/build/register.js +15 -0
  61. package/build/renderer/index.js +112 -12
  62. package/build/runtime-helpers/index.d.ts +14 -1
  63. package/build/runtime-helpers/index.js +250 -9
  64. package/build/utils/normalize-attrs.d.ts +1 -0
  65. package/build/utils/normalize-attrs.js +21 -15
  66. package/intrinsic-tags.cjs +52 -0
  67. package/metro-css-parser.cjs +2 -1
  68. package/metro-vue-transformer.cjs +83 -13
  69. package/package.json +33 -8
  70. package/build/components/activity-indicator/index.android.d.ts +0 -4
  71. package/build/components/activity-indicator/index.android.js +0 -10
  72. package/build/components/activity-indicator/index.d.ts +0 -1
  73. package/build/components/activity-indicator/index.ios.d.ts +0 -4
  74. package/build/components/activity-indicator/index.ios.js +0 -10
  75. package/build/components/activity-indicator/index.js +0 -4
  76. package/build/components/activity-indicator/shared.d.ts +0 -8
  77. package/build/components/activity-indicator/shared.js +0 -48
  78. package/build/components/button.d.ts +0 -14
  79. package/build/components/button.js +0 -59
  80. package/build/components/image-background.d.ts +0 -9
  81. package/build/components/image-background.js +0 -103
  82. package/build/components/image.d.ts +0 -9
  83. package/build/components/image.js +0 -90
  84. package/build/components/input-accessory-view.js +0 -41
  85. package/build/components/pressable.d.ts +0 -58
  86. package/build/components/pressable.js +0 -214
  87. package/build/components/refresh-control.d.ts +0 -20
  88. package/build/components/refresh-control.js +0 -47
  89. package/build/components/safe-area-view.d.ts +0 -8
  90. package/build/components/safe-area-view.js +0 -33
  91. package/build/components/scroll-view/index.android.d.ts +0 -4
  92. package/build/components/scroll-view/index.android.js +0 -64
  93. package/build/components/scroll-view/index.d.ts +0 -1
  94. package/build/components/scroll-view/index.ios.d.ts +0 -4
  95. package/build/components/scroll-view/index.ios.js +0 -17
  96. package/build/components/scroll-view/index.js +0 -4
  97. package/build/components/scroll-view/shared.js +0 -271
  98. package/build/components/scroll-view/sticky-header.d.ts +0 -7
  99. package/build/components/scroll-view/sticky-header.js +0 -208
  100. package/build/components/switch/index.android.d.ts +0 -12
  101. package/build/components/switch/index.android.js +0 -13
  102. package/build/components/switch/index.d.ts +0 -2
  103. package/build/components/switch/index.ios.d.ts +0 -12
  104. package/build/components/switch/index.ios.js +0 -11
  105. package/build/components/switch/index.js +0 -5
  106. package/build/components/switch/shared.d.ts +0 -23
  107. package/build/components/switch/shared.js +0 -126
  108. package/build/components/text-input/index.d.ts +0 -24
  109. package/build/components/text-input/index.js +0 -242
  110. package/build/components/touchable-native-feedback.d.ts +0 -24
  111. package/build/components/touchable-native-feedback.js +0 -77
  112. package/build/components/touchable.d.ts +0 -50
  113. package/build/components/touchable.js +0 -278
  114. package/build/components.d.ts +0 -51
  115. package/build/components.js +0 -29
@@ -1,90 +0,0 @@
1
- // Image: the Vue lifecycle half. The full fold (source/src/srcSet resolution, width/height ->
2
- // style fold, resizeMode/tintColor, alt -> accessibility, and the native source array) lives
3
- // framework-agnostic in @symbiote-native/components, shared verbatim with React; Vue narrows the
4
- // untyped attrs into renderImage's typed view, folds aria/role, bridges the Descriptor to a
5
- // vnode, and carries the Image statics (getSize/prefetch/queryCache/...).
6
- //
7
- // FUNCTIONAL, not a stateful defineComponent: Animated.Image wraps it via createAnimatedComponent,
8
- // which captures the host node through a ref that only falls through on a functional component
9
- // (a defineComponent's ref resolves to a useless component proxy; see components.ts).
10
- import { imageStatics, renderImage, resolveAccessibilityProps, } from '@symbiote-native/components';
11
- import { descriptorToVue } from '../descriptor-to-vue.js';
12
- import { normalizeVueAttrs } from '../utils/normalize-attrs.js';
13
- export { setImageSourceResolver } from '@symbiote-native/components';
14
- function asString(value) {
15
- return typeof value === 'string' ? value : undefined;
16
- }
17
- function asNumber(value) {
18
- return typeof value === 'number' ? value : undefined;
19
- }
20
- function asSource(value) {
21
- if (typeof value === 'number')
22
- return value;
23
- if (typeof value === 'object' && value !== null)
24
- return value;
25
- return undefined;
26
- }
27
- function isResizeMode(value) {
28
- return (value === 'cover' ||
29
- value === 'contain' ||
30
- value === 'stretch' ||
31
- value === 'repeat' ||
32
- value === 'center');
33
- }
34
- function asResizeMode(value) {
35
- return isResizeMode(value) ? value : undefined;
36
- }
37
- function asCrossOrigin(value) {
38
- return value === 'anonymous' || value === 'use-credentials'
39
- ? value
40
- : undefined;
41
- }
42
- function isStyleProp(value) {
43
- return typeof value === 'object' && value !== null;
44
- }
45
- const HANDLED_ATTRS = [
46
- 'source',
47
- 'defaultSource',
48
- 'loadingIndicatorSource',
49
- 'style',
50
- 'resizeMode',
51
- 'tintColor',
52
- 'src',
53
- 'srcSet',
54
- 'alt',
55
- 'width',
56
- 'height',
57
- 'crossOrigin',
58
- 'referrerPolicy',
59
- ];
60
- function forwardAttrs(attrs) {
61
- const result = {};
62
- for (const key of Object.keys(attrs)) {
63
- if (!HANDLED_ATTRS.includes(key))
64
- result[key] = attrs[key];
65
- }
66
- return result;
67
- }
68
- const ImageComponent = (_props, { attrs: rawAttrs }) => {
69
- const attrs = normalizeVueAttrs(rawAttrs);
70
- return descriptorToVue(renderImage({
71
- source: asSource(attrs.source),
72
- defaultSource: asSource(attrs.defaultSource),
73
- loadingIndicatorSource: asSource(attrs.loadingIndicatorSource),
74
- style: isStyleProp(attrs.style) ? attrs.style : undefined,
75
- resizeMode: asResizeMode(attrs.resizeMode),
76
- tintColor: asString(attrs.tintColor),
77
- src: asString(attrs.src),
78
- srcSet: asString(attrs.srcSet),
79
- alt: asString(attrs.alt),
80
- width: asNumber(attrs.width),
81
- height: asNumber(attrs.height),
82
- crossOrigin: asCrossOrigin(attrs.crossOrigin),
83
- referrerPolicy: asString(attrs.referrerPolicy),
84
- passthrough: resolveAccessibilityProps(forwardAttrs(attrs)),
85
- }));
86
- };
87
- ImageComponent.displayName = 'Image';
88
- ImageComponent.inheritAttrs = false;
89
- // Statics attached like RN (Image.getSize/prefetch/...), shared verbatim with React.
90
- export const Image = Object.assign(ImageComponent, imageStatics);
@@ -1,41 +0,0 @@
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.js';
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;
@@ -1,58 +0,0 @@
1
- import { type EmitFn, type VNode } from '@vue/runtime-core';
2
- import { type IPressState, type IRectOffset, type IPressableAndroidRippleConfig, type IAccessibilityProps, type IAriaProps } from '@symbiote-native/components';
3
- import { type IClassNameValue, type ISymbioteEvent, type IStyleProp, type IViewStyle } from '@symbiote-native/engine';
4
- export type { IPressState, IPressableAndroidRippleConfig, } from '@symbiote-native/components';
5
- export type IPressableEmits = {
6
- press: (event: ISymbioteEvent) => boolean;
7
- pressIn: (event: ISymbioteEvent) => boolean;
8
- pressOut: (event: ISymbioteEvent) => boolean;
9
- pressMove: (event: ISymbioteEvent) => boolean;
10
- longPress: (event: ISymbioteEvent) => boolean;
11
- hoverIn: (event: ISymbioteEvent) => boolean;
12
- hoverOut: (event: ISymbioteEvent) => boolean;
13
- };
14
- export declare const PRESSABLE_EMITS: {
15
- press: (_event: ISymbioteEvent) => boolean;
16
- pressIn: (_event: ISymbioteEvent) => boolean;
17
- pressOut: (_event: ISymbioteEvent) => boolean;
18
- pressMove: (_event: ISymbioteEvent) => boolean;
19
- longPress: (_event: ISymbioteEvent) => boolean;
20
- hoverIn: (_event: ISymbioteEvent) => boolean;
21
- hoverOut: (_event: ISymbioteEvent) => boolean;
22
- };
23
- export declare function emitPressableEvents(emit: EmitFn<IPressableEmits>): Record<string, (event: ISymbioteEvent) => void>;
24
- export interface IPressableProps extends IAccessibilityProps, IAriaProps {
25
- delayLongPress?: number;
26
- disabled?: boolean;
27
- cancelable?: boolean;
28
- hitSlop?: IRectOffset;
29
- pressRetentionOffset?: IRectOffset;
30
- unstable_pressDelay?: number;
31
- android_ripple?: IPressableAndroidRippleConfig;
32
- android_disableSound?: boolean;
33
- delayHoverIn?: number;
34
- delayHoverOut?: number;
35
- testID?: string;
36
- style?: IStyleProp<IViewStyle> | ((state: IPressState) => IStyleProp<IViewStyle>);
37
- class?: IClassNameValue;
38
- }
39
- export type IPressableSlots = {
40
- default?: (state: IPressState) => VNode[] | VNode;
41
- };
42
- export declare const Pressable: import("vue").DefineSetupFnComponent<IPressableProps, {
43
- press: (_event: ISymbioteEvent) => boolean;
44
- pressIn: (_event: ISymbioteEvent) => boolean;
45
- pressOut: (_event: ISymbioteEvent) => boolean;
46
- pressMove: (_event: ISymbioteEvent) => boolean;
47
- longPress: (_event: ISymbioteEvent) => boolean;
48
- hoverIn: (_event: ISymbioteEvent) => boolean;
49
- hoverOut: (_event: ISymbioteEvent) => boolean;
50
- }, import("vue").SlotsType<IPressableSlots>, IPressableProps & {
51
- onPress?: ((_event: ISymbioteEvent) => any) | undefined;
52
- onPressIn?: ((_event: ISymbioteEvent) => any) | undefined;
53
- onPressOut?: ((_event: ISymbioteEvent) => any) | undefined;
54
- onPressMove?: ((_event: ISymbioteEvent) => any) | undefined;
55
- onLongPress?: ((_event: ISymbioteEvent) => any) | undefined;
56
- onHoverIn?: ((_event: ISymbioteEvent) => any) | undefined;
57
- onHoverOut?: ((_event: ISymbioteEvent) => any) | undefined;
58
- }, import("vue").PublicProps>;
@@ -1,214 +0,0 @@
1
- // Pressable, the Vue lifecycle half. The press lifecycle (long-press timer, unstable_press-
2
- // Delay deferral, pressRetentionOffset drift test, suppression flags) lives in
3
- // @symbiote-native/components/state as a pure machine over a runtime + host; the render
4
- // decisions (responder listeners, disabled->accessibilityState fold, ripple prop) in
5
- // @symbiote-native/components/view, both shared verbatim with React. Vue supplies the
6
- // reactivity: a `ref` holds `pressed`, a setup-scope object holds the press runtime, a function
7
- // ref grabs the responder View's host node.
8
- //
9
- // Inputs arrive as attrs (untyped), so each is narrowed with a runtime guard, never a cast. The
10
- // user's onPress/onPressIn/... are consumed by the machine and MUST be stripped from the
11
- // forwarded attrs (pure-JS callbacks); the machine's SYNTHESIZED handlers go on the View instead.
12
- // Children arrive as a (scoped) default slot so `v-slot="{ pressed }"` mirrors React's
13
- // children-as-function.
14
- import { defineComponent, h, ref, shallowRef, } from '@vue/runtime-core';
15
- import { createPressHandlers, createPressRuntime, rippleProps, buildPressableListeners, resolveDisabledAccessibilityState, noteHoverNoop, resolveAccessibilityProps, DEFAULT_DELAY_LONG_PRESS_MS, } from '@symbiote-native/components';
16
- import { measure, isSymbioteNode, } from '@symbiote-native/engine';
17
- import { View } from '../components.js';
18
- import { normalizeVueAttrs } from '../utils/normalize-attrs.js';
19
- // Reused verbatim as the `emits` of every Touchable* wrapper, so the runtime list lives once.
20
- export const PRESSABLE_EMITS = {
21
- press: (_event) => true,
22
- pressIn: (_event) => true,
23
- pressOut: (_event) => true,
24
- pressMove: (_event) => true,
25
- longPress: (_event) => true,
26
- hoverIn: (_event) => true,
27
- hoverOut: (_event) => true,
28
- };
29
- // Bridge the whole press surface onto a child Pressable: each host onX callback re-emits the
30
- // matching event on the wrapper. A wrapper that intercepts an event for its own state (e.g.
31
- // TouchableOpacity's opacity animation on press-in/out) overrides that one key AFTER the spread.
32
- export function emitPressableEvents(emit) {
33
- return {
34
- onPress: event => emit('press', event),
35
- onPressIn: event => emit('pressIn', event),
36
- onPressOut: event => emit('pressOut', event),
37
- onPressMove: event => emit('pressMove', event),
38
- onLongPress: event => emit('longPress', event),
39
- onHoverIn: event => emit('hoverIn', event),
40
- onHoverOut: event => emit('hoverOut', event),
41
- };
42
- }
43
- function isRecord(value) {
44
- return typeof value === 'object' && value !== null && !Array.isArray(value);
45
- }
46
- function isStyleFn(value) {
47
- return typeof value === 'function';
48
- }
49
- function numberOr(value, fallback) {
50
- return typeof value === 'number' ? value : fallback;
51
- }
52
- // A scalar offset, or the per-edge object; anything else is dropped (the machine reads undefined
53
- // as "no offset" -> RN's defaults).
54
- function asRectOffset(value) {
55
- if (typeof value === 'number')
56
- return value;
57
- if (!isRecord(value))
58
- return undefined;
59
- const rect = {};
60
- if (typeof value.top === 'number')
61
- rect.top = value.top;
62
- if (typeof value.left === 'number')
63
- rect.left = value.left;
64
- if (typeof value.bottom === 'number')
65
- rect.bottom = value.bottom;
66
- if (typeof value.right === 'number')
67
- rect.right = value.right;
68
- return rect;
69
- }
70
- // android_ripple arrives untyped; keep only the fields the shared rippleProps reads.
71
- function asRippleConfig(value) {
72
- if (!isRecord(value))
73
- return undefined;
74
- const config = {};
75
- if (typeof value.color === 'string')
76
- config.color = value.color;
77
- if (typeof value.borderless === 'boolean')
78
- config.borderless = value.borderless;
79
- if (typeof value.radius === 'number')
80
- config.radius = value.radius;
81
- if (typeof value.foreground === 'boolean')
82
- config.foreground = value.foreground;
83
- return config;
84
- }
85
- // The user's accessibilityState, narrowed to the known fields (the disabled merge happens after).
86
- function asAccessibilityState(value) {
87
- if (!isRecord(value))
88
- return undefined;
89
- const state = {};
90
- if (typeof value.disabled === 'boolean')
91
- state.disabled = value.disabled;
92
- if (typeof value.selected === 'boolean')
93
- state.selected = value.selected;
94
- if (value.checked === 'mixed' || typeof value.checked === 'boolean')
95
- state.checked = value.checked;
96
- if (typeof value.busy === 'boolean')
97
- state.busy = value.busy;
98
- if (typeof value.expanded === 'boolean')
99
- state.expanded = value.expanded;
100
- return state;
101
- }
102
- function resolveStyle(value, state) {
103
- if (isStyleFn(value))
104
- return value(state);
105
- return value;
106
- }
107
- // Everything else forwards onto the View. User press callbacks are pure JS and must never reach
108
- // the host; the machine's synthesized handlers go on via buildPressableListeners.
109
- const HANDLED_ATTRS = [
110
- 'onPress',
111
- 'onPressIn',
112
- 'onPressOut',
113
- 'onPressMove',
114
- 'onLongPress',
115
- 'delayLongPress',
116
- 'disabled',
117
- 'cancelable',
118
- 'pressRetentionOffset',
119
- 'unstable_pressDelay',
120
- 'android_ripple',
121
- 'android_disableSound',
122
- 'onHoverIn',
123
- 'onHoverOut',
124
- 'delayHoverIn',
125
- 'delayHoverOut',
126
- 'style',
127
- 'accessibilityState',
128
- ];
129
- function forwardAttrs(attrs) {
130
- const result = {};
131
- for (const key of Object.keys(attrs)) {
132
- if (!HANDLED_ATTRS.includes(key))
133
- result[key] = attrs[key];
134
- }
135
- return result;
136
- }
137
- export const Pressable = defineComponent((_props, { slots, attrs: rawAttrs, emit }) => {
138
- const pressed = ref(false);
139
- // The mutable press runtime (timers, suppression flags, measured region). A plain setup-scope
140
- // object, never a ref: mutated by the machine, never reactively read.
141
- const runtime = createPressRuntime();
142
- // shallowRef, NOT ref: a plain ref would wrap the node in a reactive Proxy, missing the
143
- // engine's WeakMap mirror and making measure() no-op.
144
- const nodeRef = shallowRef(null);
145
- const setNodeRef = (el) => {
146
- nodeRef.value = isSymbioteNode(el) ? el : null;
147
- };
148
- // The lifecycle seam the machine fills: flip the reactive `pressed`, and expose the responder
149
- // View's raw frame-measure (or undefined before the node commits, a radius fallback).
150
- const host = {
151
- setPressed: next => {
152
- pressed.value = next;
153
- },
154
- getMeasureFn: () => {
155
- const node = nodeRef.value;
156
- if (node === null)
157
- return undefined;
158
- return callback => measure(node, callback);
159
- },
160
- schedule: (callback, ms) => {
161
- const id = setTimeout(callback, ms);
162
- return () => clearTimeout(id);
163
- },
164
- };
165
- return () => {
166
- const attrs = normalizeVueAttrs(rawAttrs);
167
- const disabled = attrs.disabled === true ? true : undefined;
168
- const cancelable = typeof attrs.cancelable === 'boolean' ? attrs.cancelable : undefined;
169
- const config = {
170
- onPress: event => emit('press', event),
171
- onPressIn: event => emit('pressIn', event),
172
- onPressOut: event => emit('pressOut', event),
173
- onPressMove: event => emit('pressMove', event),
174
- onLongPress: event => emit('longPress', event),
175
- delayLongPress: numberOr(attrs.delayLongPress, DEFAULT_DELAY_LONG_PRESS_MS),
176
- unstable_pressDelay: numberOr(attrs.unstable_pressDelay, 0),
177
- hitSlop: asRectOffset(attrs.hitSlop),
178
- pressRetentionOffset: asRectOffset(attrs.pressRetentionOffset),
179
- };
180
- const handlers = createPressHandlers(config, runtime, host);
181
- noteHoverNoop(undefined, undefined);
182
- const state = { pressed: pressed.value };
183
- // Vue's View is a bare host primitive, so Pressable folds disabled into accessibilityState
184
- // and aria/role itself, rather than the View folding it (as React's does).
185
- const forwarded = forwardAttrs(attrs);
186
- forwarded.accessibilityState = resolveDisabledAccessibilityState(asAccessibilityState(attrs.accessibilityState), disabled);
187
- const folded = resolveAccessibilityProps(forwarded);
188
- const viewProps = {
189
- ...folded,
190
- ref: setNodeRef,
191
- style: resolveStyle(attrs.style, state),
192
- };
193
- if (typeof attrs.android_disableSound === 'boolean')
194
- viewProps.android_disableSound = attrs.android_disableSound;
195
- Object.assign(viewProps, buildPressableListeners(handlers, { disabled, cancelable }));
196
- const content = slots.default !== undefined ? slots.default(state) : [];
197
- // android_ripple rides a dedicated inner View; on iOS the prop is undefined, so the child
198
- // renders unwrapped, no extra node.
199
- const ripple = isRecord(attrs.android_ripple)
200
- ? rippleProps(asRippleConfig(attrs.android_ripple) ?? {})
201
- : undefined;
202
- const inner = ripple !== undefined ? [h(View, ripple, () => content)] : content;
203
- // Children go to the host View as a FUNCTION slot, never a raw array: View is a
204
- // functional component, and an array child makes Vue normalize it to a default
205
- // slot with a dev warn ("Prefer function slots"). Benign under SFC, but in JSX the
206
- // warn's trace formats the __self/__source dev props (native HostObjects) and that
207
- // read throws, unwinding the whole mount → blank screen. A function slot skips it.
208
- return h(View, viewProps, () => inner);
209
- };
210
- }, {
211
- name: 'Pressable',
212
- inheritAttrs: false,
213
- emits: PRESSABLE_EMITS,
214
- });
@@ -1,20 +0,0 @@
1
- import { type IClassNameValue } from '@symbiote-native/engine';
2
- import { type IAccessibilityProps, type IAriaProps } from '@symbiote-native/components';
3
- export interface IRefreshControlProps extends IAccessibilityProps, IAriaProps {
4
- refreshing: boolean;
5
- tintColor?: string;
6
- title?: string;
7
- titleColor?: string;
8
- progressViewOffset?: number;
9
- colors?: readonly string[];
10
- progressBackgroundColor?: string;
11
- size?: 'default' | 'large';
12
- enabled?: boolean;
13
- class?: IClassNameValue;
14
- }
15
- export type IRefreshControlEmits = {
16
- refresh: () => boolean;
17
- };
18
- export declare const RefreshControl: import("vue").DefineSetupFnComponent<IRefreshControlProps, IRefreshControlEmits, {}, IRefreshControlProps & {
19
- onRefresh?: (() => any) | undefined;
20
- }, import("vue").PublicProps>;
@@ -1,47 +0,0 @@
1
- // RefreshControl, the Vue lifecycle half. On iOS this is the PullToRefreshView Fabric node that
2
- // lives INSIDE a ScrollView (a sibling before the content container); on Android it is
3
- // AndroidSwipeRefreshLayout and WRAPS the scroll view (a ScrollView there hosts one child). Vue
4
- // takes the wrapped child via its DEFAULT SLOT (the seam the Android scroll-view wrap re-invokes
5
- // to host the scroll view inside it; iOS leaves the slot empty), folds aria/role through the
6
- // shared resolveAccessibilityProps, and forwards the native props onto the
7
- // symbiote-refresh-control host node.
8
- //
9
- // `refreshing` is a controlled prop the parent pushes down each commit; native reports the
10
- // gesture via the direct `topRefresh` event, routed to the host onRefresh prop and turned into
11
- // the typed Vue `refresh` emit.
12
- import { defineComponent, h } from '@vue/runtime-core';
13
- import { dlog } from '@symbiote-native/engine';
14
- import { resolveAccessibilityProps, } from '@symbiote-native/components';
15
- import { normalizeVueAttrs } from '../utils/normalize-attrs.js';
16
- // Built at the a11y-intersection type (a real narrowing, not a cast), then fold aria-*/role into
17
- // the canonical accessibility* props. Children cross via slots, never attrs.
18
- function foldAttrs(attrs) {
19
- const bag = {};
20
- for (const key of Object.keys(attrs)) {
21
- if (key !== 'onRefresh')
22
- bag[key] = attrs[key];
23
- }
24
- return resolveAccessibilityProps(bag);
25
- }
26
- export const RefreshControl = defineComponent((_props, { attrs: rawAttrs, emit, slots }) => {
27
- return () => {
28
- const nativeProps = foldAttrs(normalizeVueAttrs(rawAttrs));
29
- dlog('RefreshControl -> PullToRefreshView');
30
- dlog(`RefreshControl refreshing=${String(nativeProps.refreshing)}`);
31
- if (nativeProps.enabled !== undefined)
32
- dlog(`RefreshControl enabled=${String(nativeProps.enabled)} (Android-only)`);
33
- dlog('RefreshControl refresh emit wired');
34
- return h('symbiote-refresh-control', {
35
- ...nativeProps,
36
- onRefresh: () => {
37
- emit('refresh');
38
- },
39
- }, slots.default !== undefined ? slots.default() : undefined);
40
- };
41
- }, {
42
- name: 'RefreshControl',
43
- inheritAttrs: false,
44
- emits: {
45
- refresh: () => true,
46
- },
47
- });
@@ -1,8 +0,0 @@
1
- import { type IClassNameValue } from '@symbiote-native/engine';
2
- import { type IAccessibilityProps, type IAriaProps } from '@symbiote-native/components';
3
- export type ISafeAreaViewProps = IAccessibilityProps & IAriaProps & {
4
- class?: IClassNameValue;
5
- };
6
- export declare const SafeAreaView: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
7
- [key: string]: any;
8
- }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -1,33 +0,0 @@
1
- // SafeAreaView, the Vue lifecycle half. A plain view whose native side
2
- // insets its children to the safe area (notch, rounded corners, system bars); there is no
3
- // JS-side translation, so this maps style + children straight onto the intrinsic. The Vue twin
4
- // of the React adapter's SafeAreaView. Vue takes children via slots, folds aria/role through
5
- // the shared resolveAccessibilityProps (so every adapter normalizes the web aliases identically),
6
- // and forwards the rest onto the symbiote-safe-area-view host node.
7
- //
8
- // Inputs arrive as attrs (untyped), so the forwarded bag is BUILT at the a11y-intersection type
9
- // (a genuine narrowing, not a cast) before resolveAccessibilityProps folds aria-* into accessibility*.
10
- import { defineComponent, h } from '@vue/runtime-core';
11
- import { dlog } from '@symbiote-native/engine';
12
- import { resolveAccessibilityProps, } from '@symbiote-native/components';
13
- import { normalizeVueAttrs } from '../utils/normalize-attrs.js';
14
- // Copy every attr into a bag typed as the a11y intersection (the accumulator is BUILT at that
15
- // type, a real narrowing, not a cast), then fold aria-*/role into the canonical accessibility*
16
- // props before they reach the host. style / onLayout / testID forward unchanged.
17
- function foldAttrs(attrs) {
18
- const bag = {};
19
- for (const key of Object.keys(attrs))
20
- bag[key] = attrs[key];
21
- return resolveAccessibilityProps(bag);
22
- }
23
- export const SafeAreaView = defineComponent({
24
- name: 'SafeAreaView',
25
- inheritAttrs: false,
26
- setup(_props, { attrs: rawAttrs, slots }) {
27
- return () => {
28
- dlog('SafeAreaView -> SafeAreaView');
29
- const nativeProps = foldAttrs(normalizeVueAttrs(rawAttrs));
30
- return h('symbiote-safe-area-view', nativeProps, slots.default !== undefined ? slots.default() : undefined);
31
- };
32
- },
33
- });
@@ -1,4 +0,0 @@
1
- export type { IScrollViewProps, IScrollViewEmits, IScrollViewHandle, } from './shared';
2
- export declare const ScrollView: import("vue").DefineSetupFnComponent<import("./shared").IScrollViewProps, import("./shared").IScrollViewEmits, {}, import("./shared").IScrollViewProps & {
3
- onContentSizeChange?: ((width: number, height: number) => any) | undefined;
4
- }, import("vue").PublicProps>;
@@ -1,64 +0,0 @@
1
- // ScrollView on Android. An Android ScrollView accepts only ONE child, so a RefreshControl can't
2
- // be a sibling of the content the way iOS allows ("addViewAt: failed to insert view ... at index
3
- // 1"). Instead the RefreshControl (AndroidSwipeRefreshLayout) WRAPS the scroll view, nested
4
- // inside with nestedScrollEnabled so it handles the gesture before the refresh parent, mirroring
5
- // RN's ScrollView.js android branch.
6
- //
7
- // React does this with cloneElement(refreshControl, {style}, scrollView). Vue has no
8
- // cloneElement, so the analog is to RE-INVOKE the user's RefreshControl component type via h():
9
- // same .type, its own .props plus the injected outer/layout style, and the inner scroll view as
10
- // its DEFAULT SLOT. The node ref stays on the INNER scroll view (not the wrapper), so
11
- // dispatchViewCommand targets it. Metro picks this file on an Android host; no Platform.OS read.
12
- // device-verify-pending: the wrap shape mirrors RN, proven on a real host by the absence of the
13
- // "addViewAt: failed to insert" crash.
14
- import { h, isVNode } from '@vue/runtime-core';
15
- import { dlog } from '@symbiote-native/engine';
16
- import { splitLayoutProps } from '@symbiote-native/components';
17
- import { createScrollView } from './shared.js';
18
- function isRecord(value) {
19
- return typeof value === 'object' && value !== null && !Array.isArray(value);
20
- }
21
- // Narrows VNodeTypes (string | Component | nested VNode | the Fragment/Text/... symbol
22
- // constants) to what h() accepts. refreshControl is always a real component element in practice.
23
- function isHostType(type) {
24
- if (typeof type === 'string')
25
- return true;
26
- return ((typeof type === 'object' || typeof type === 'function') &&
27
- type !== null &&
28
- !isVNode(type));
29
- }
30
- export const ScrollView = createScrollView({
31
- assemble: input => {
32
- if (input.refreshControl === undefined) {
33
- dlog('Vue ScrollView.ANDROID refreshControl=NONE(1child)');
34
- return h(input.scrollViewIntrinsic, input.scrollProps, [input.content]);
35
- }
36
- // RN splits the flattened style across the two boxes: LAYOUT props (margin/flex/size/
37
- // position/...) drive the outer AndroidSwipeRefreshLayout frame; VISUAL props (background/
38
- // padding/border/...) paint the inner scroll view - not a hardcoded flex:1 that would
39
- // override an explicit user height/width.
40
- //
41
- // layoutSplitStyle (not userStyle): a class-only layout prop is invisible to userStyle (it
42
- // never carries the resolved `class` value - see isClassNameProp in shared.ts), so splitting
43
- // on userStyle alone would starve the wrapper of its layout style.
44
- const { outer, inner } = splitLayoutProps(input.layoutSplitStyle);
45
- // `class` is stripped here: layoutSplitStyle already folded its resolved value into
46
- // outer/inner above, so forwarding the raw prop too would re-apply its LAYOUT half a second time.
47
- const { class: _classAppliedViaSplit, ...innerScrollOuterProps } = input.scrollOuterProps;
48
- const innerScrollView = h(input.scrollViewIntrinsic, {
49
- ...innerScrollOuterProps,
50
- style: [input.scrollViewBaseStyle, inner],
51
- nestedScrollEnabled: true,
52
- ref: input.setNodeRef,
53
- }, [input.content]);
54
- const rc = input.refreshControl;
55
- if (!isHostType(rc.type)) {
56
- // Degrade to the unwrapped scroll view rather than crash (the node ref is already on it).
57
- dlog('Vue ScrollView.ANDROID refreshControl has no hostable type, rendering scroll view unwrapped');
58
- return innerScrollView;
59
- }
60
- const rcProps = isRecord(rc.props) ? rc.props : {};
61
- dlog('Vue ScrollView.ANDROID refreshControl=WRAP');
62
- return h(rc.type, { ...rcProps, style: outer }, { default: () => [innerScrollView] });
63
- },
64
- });
@@ -1 +0,0 @@
1
- export * from './index.ios';
@@ -1,4 +0,0 @@
1
- export type { IScrollViewProps, IScrollViewEmits, IScrollViewHandle, } from './shared';
2
- export declare const ScrollView: import("vue").DefineSetupFnComponent<import("./shared").IScrollViewProps, import("./shared").IScrollViewEmits, {}, import("./shared").IScrollViewProps & {
3
- onContentSizeChange?: ((width: number, height: number) => any) | undefined;
4
- }, import("vue").PublicProps>;
@@ -1,17 +0,0 @@
1
- // ScrollView on iOS. The RefreshControl is a CHILD of the scroll view, rendered
2
- // as a SIBLING BEFORE the content container (RN ScrollView.js: {refreshControl}{contentContainer}).
3
- // The user's RefreshControl VNode renders as-is; its default slot is empty on iOS, so it is a
4
- // childless sibling. Also the base (scroll-view.ts re-exports it) for headless / web. Metro picks
5
- // this on an iOS host; no Platform.OS read. Mirrors the React adapter's iOS binding.
6
- import { h } from '@vue/runtime-core';
7
- import { createScrollView } from './shared.js';
8
- export const ScrollView = createScrollView({
9
- assemble: input => {
10
- // Sibling placement: RefreshControl before content (RN iOS). The node ref stays on the scroll
11
- // view via input.scrollProps, so the imperative handle targets it whether or not refresh is on.
12
- const children = input.refreshControl === undefined
13
- ? [input.content]
14
- : [input.refreshControl, input.content];
15
- return h(input.scrollViewIntrinsic, input.scrollProps, children);
16
- },
17
- });
@@ -1,4 +0,0 @@
1
- // Base / default ScrollView. Re-exports the iOS build. Metro overrides this with
2
- // scroll-view.ios.ts / scroll-view.android.ts on a real host; under tsx / tsc / web the host
3
- // resolves here. Filename is the selector, no Platform.OS read.
4
- export * from './index.ios.js';