@symbiote-native/vue 3.0.4 → 3.2.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/composables/create-event-value-hook.d.ts +3 -0
- package/build/composables/create-event-value-hook.js +16 -0
- package/build/composables/create-permission-hook.d.ts +3 -0
- package/build/composables/create-permission-hook.js +22 -0
- package/build/composables/create-resource-hook.d.ts +7 -0
- package/build/composables/create-resource-hook.js +14 -0
- package/build/create-transition/index.d.ts +27 -0
- package/build/create-transition/index.js +84 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +7 -0
- package/build/runtime-helpers/index.d.ts +1 -0
- package/build/runtime-helpers/index.js +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type ShallowRef } from '@vue/runtime-core';
|
|
2
|
+
import type { IEventValueSource } from '@symbiote-native/engine';
|
|
3
|
+
export declare function createEventValueHook<TSource extends IEventValueSource<TValue, TEvent>, TValue, TEvent extends string = string>(event: TEvent, getValue: (source: TSource) => TValue): (getSource: () => TSource) => ShallowRef<TValue>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Every `useXStatus`-style composable (`useAudioPlayerStatus`, `useAudioPlaylistStatus`, ...)
|
|
2
|
+
// binds this to its own event name + initial-value getter instead of repeating the watch wiring
|
|
3
|
+
import { shallowRef, watch } from '@vue/runtime-core';
|
|
4
|
+
export function createEventValueHook(event, getValue) {
|
|
5
|
+
return function useEventValue(getSource) {
|
|
6
|
+
const value = shallowRef(getValue(getSource()));
|
|
7
|
+
watch(getSource, (source, _previous, onCleanup) => {
|
|
8
|
+
value.value = getValue(source);
|
|
9
|
+
const subscription = source.addListener(event, next => {
|
|
10
|
+
value.value = next;
|
|
11
|
+
});
|
|
12
|
+
onCleanup(() => subscription.remove());
|
|
13
|
+
}, { immediate: true });
|
|
14
|
+
return value;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type Ref } from '@vue/runtime-core';
|
|
2
|
+
import { type IPermissionHookBehavior, type IPermissionHookMethods } from '@symbiote-native/engine';
|
|
3
|
+
export declare function createPermissionHook<TPermission, TOptions extends object>(methods: IPermissionHookMethods<TPermission, TOptions>): (behavior?: IPermissionHookBehavior, methodOptions?: TOptions) => [Ref<TPermission | null>, () => Promise<TPermission>, () => Promise<TPermission>];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Every Expo-wrapper package's own permission composable (`useCameraPermissions`,
|
|
2
|
+
// `useCalendarPermissions`, `useRemindersPermissions`, ...) binds this factory to its `methods`
|
|
3
|
+
import { onMounted, shallowRef } from '@vue/runtime-core';
|
|
4
|
+
import { createPermissionApi, fetchInitialPermission, } from '@symbiote-native/engine';
|
|
5
|
+
export function createPermissionHook(methods) {
|
|
6
|
+
return function usePermission(behavior, methodOptions) {
|
|
7
|
+
const status = shallowRef(null);
|
|
8
|
+
const api = createPermissionApi(methods, value => {
|
|
9
|
+
status.value = value;
|
|
10
|
+
});
|
|
11
|
+
onMounted(() => {
|
|
12
|
+
fetchInitialPermission(methods, behavior, methodOptions, response => {
|
|
13
|
+
status.value = response;
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
return [
|
|
17
|
+
status,
|
|
18
|
+
() => api.request(methodOptions),
|
|
19
|
+
() => api.get(methodOptions),
|
|
20
|
+
];
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ComputedRef } from '@vue/runtime-core';
|
|
2
|
+
export type IResourceHookController<TArgs extends unknown[], TResource> = {
|
|
3
|
+
resolve: (...args: TArgs) => TResource;
|
|
4
|
+
flushDispose: () => void;
|
|
5
|
+
dispose: () => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function createResourceHook<TArgs extends unknown[], TResource>(createController: () => IResourceHookController<TArgs, TResource>): (getArgs: () => TArgs) => ComputedRef<TResource>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Every `useReleasingSharedObject`-style composable (`useAudioPlayer`, `useImageManipulator`, ...)
|
|
2
|
+
// binds this to its own `createXController()` instead of repeating the computed/watch wiring
|
|
3
|
+
import { computed, onUnmounted, watch, } from '@vue/runtime-core';
|
|
4
|
+
export function createResourceHook(createController) {
|
|
5
|
+
return function useResource(getArgs) {
|
|
6
|
+
const controller = createController();
|
|
7
|
+
const resource = computed(() => controller.resolve(...getArgs()));
|
|
8
|
+
watch(resource, () => {
|
|
9
|
+
controller.flushDispose();
|
|
10
|
+
});
|
|
11
|
+
onUnmounted(() => controller.dispose());
|
|
12
|
+
return resource;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type VNode } from '@vue/runtime-core';
|
|
2
|
+
export interface ITransitionProps {
|
|
3
|
+
duration?: number;
|
|
4
|
+
appear?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const Transition: import("vue").DefineComponent<{
|
|
7
|
+
duration: number;
|
|
8
|
+
appear: boolean;
|
|
9
|
+
}, () => VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
|
|
12
|
+
duration: number;
|
|
13
|
+
appear: boolean;
|
|
14
|
+
}> & Readonly<{}>, {
|
|
15
|
+
duration: number;
|
|
16
|
+
appear: boolean;
|
|
17
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
18
|
+
export declare const TransitionGroup: import("vue").DefineComponent<{
|
|
19
|
+
duration: number;
|
|
20
|
+
appear: boolean;
|
|
21
|
+
}, () => VNode, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
|
|
22
|
+
duration: number;
|
|
23
|
+
appear: boolean;
|
|
24
|
+
}> & Readonly<{}>, {
|
|
25
|
+
duration: number;
|
|
26
|
+
appear: boolean;
|
|
27
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Vue's own <Transition>/<TransitionGroup> live in @vue/runtime-dom (CSS class
|
|
2
|
+
// toggling), unreachable through this adapter's runtime-core-only "vue" import.
|
|
3
|
+
// Wires BaseTransition's (runtime-core) enter/leave hooks to Animated instead.
|
|
4
|
+
import { BaseTransition, defineComponent, Fragment, getCurrentInstance, getTransitionRawChildren, h, resolveTransitionHooks, setTransitionHooks, useTransitionState, } from '@vue/runtime-core';
|
|
5
|
+
import { AnimatedValue, isSymbioteNode, propOf, requestCommitFor, routeProp, timing, } from '@symbiote-native/engine';
|
|
6
|
+
const DEFAULT_DURATION_MS = 300;
|
|
7
|
+
const opacityOf = new WeakMap();
|
|
8
|
+
// routeProp, not setProp/setNativeProps: an AnimatedNode is only recognized and kept
|
|
9
|
+
// subscribed to per-frame updates through routeProp's own resolution
|
|
10
|
+
// (core/engine/src/animated/host-binding.ts).
|
|
11
|
+
function animatedOpacity(el, initial) {
|
|
12
|
+
const value = new AnimatedValue(initial);
|
|
13
|
+
opacityOf.set(el, value);
|
|
14
|
+
const style = propOf(el, 'style');
|
|
15
|
+
routeProp(el, 'style', {
|
|
16
|
+
...(typeof style === 'object' && style !== null ? style : {}),
|
|
17
|
+
opacity: value,
|
|
18
|
+
});
|
|
19
|
+
requestCommitFor(el);
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function fadeTo(el, toValue, duration, done) {
|
|
23
|
+
const value = opacityOf.get(el) ?? animatedOpacity(el, toValue === 1 ? 0 : 1);
|
|
24
|
+
timing(value, { toValue, duration }).start(({ finished }) => {
|
|
25
|
+
if (finished)
|
|
26
|
+
done();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// This project's native equivalent of Vue's CSS transition classes. Named per-`name`
|
|
30
|
+
// enter/leave effects are not implemented (see the gap-list for that decision).
|
|
31
|
+
function fadeHooks(duration) {
|
|
32
|
+
return {
|
|
33
|
+
onBeforeEnter: el => {
|
|
34
|
+
if (isSymbioteNode(el))
|
|
35
|
+
animatedOpacity(el, 0);
|
|
36
|
+
},
|
|
37
|
+
onEnter: (el, done) => {
|
|
38
|
+
if (isSymbioteNode(el))
|
|
39
|
+
fadeTo(el, 1, duration, done);
|
|
40
|
+
else
|
|
41
|
+
done();
|
|
42
|
+
},
|
|
43
|
+
onLeave: (el, done) => {
|
|
44
|
+
if (isSymbioteNode(el))
|
|
45
|
+
fadeTo(el, 0, duration, done);
|
|
46
|
+
else
|
|
47
|
+
done();
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export const Transition = defineComponent({
|
|
52
|
+
name: 'Transition',
|
|
53
|
+
props: {
|
|
54
|
+
duration: { type: Number, default: DEFAULT_DURATION_MS },
|
|
55
|
+
appear: { type: Boolean, default: false },
|
|
56
|
+
},
|
|
57
|
+
setup(props, { slots }) {
|
|
58
|
+
return () => h(BaseTransition, { appear: props.appear, ...fadeHooks(props.duration) }, slots);
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
// The move/reorder FLIP animation Vue's own TransitionGroup does over
|
|
62
|
+
// offsetLeft/offsetTop is DOM-measurement-specific and not implemented here.
|
|
63
|
+
export const TransitionGroup = defineComponent({
|
|
64
|
+
name: 'TransitionGroup',
|
|
65
|
+
props: {
|
|
66
|
+
duration: { type: Number, default: DEFAULT_DURATION_MS },
|
|
67
|
+
appear: { type: Boolean, default: false },
|
|
68
|
+
},
|
|
69
|
+
setup(props, { slots }) {
|
|
70
|
+
const instance = getCurrentInstance();
|
|
71
|
+
const state = useTransitionState();
|
|
72
|
+
return () => {
|
|
73
|
+
const children = slots.default
|
|
74
|
+
? getTransitionRawChildren(slots.default())
|
|
75
|
+
: [];
|
|
76
|
+
for (const child of children) {
|
|
77
|
+
if (child.key == null || !instance)
|
|
78
|
+
continue;
|
|
79
|
+
setTransitionHooks(child, resolveTransitionHooks(child, { appear: props.appear, ...fadeHooks(props.duration) }, state, instance));
|
|
80
|
+
}
|
|
81
|
+
return h(Fragment, null, children);
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
});
|
package/build/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { mount, unmount, setAppConfigurator } from './render';
|
|
|
4
4
|
export type { IAppConfigurator } from './render';
|
|
5
5
|
export { Teleport, type ITeleportTarget } from './create-portal';
|
|
6
6
|
export { createTunnel, type ITunnel } from './create-tunnel';
|
|
7
|
+
export { Transition, TransitionGroup, type ITransitionProps, } from './create-transition';
|
|
7
8
|
export type { IViewProps } from './components/view-props';
|
|
8
9
|
export type { ITextProps } from './components/text-props';
|
|
9
10
|
export type { ISymbioteIntrinsicTag, ISymbioteHostAttributes, } from './intrinsic-elements';
|
|
@@ -53,6 +54,9 @@ export { AppRegistry, setHostRegistrar } from './modules/app-registry';
|
|
|
53
54
|
export type { IComponentProvider, IAppParameters, IRunnable, IHostRegistrar, IWrapperComponentProvider, IRegistry, IHeadlessTask, ITaskProvider, ITaskCanceller, ITaskCancelProvider, } from './modules/app-registry';
|
|
54
55
|
export { useColorScheme } from './composables/use-color-scheme';
|
|
55
56
|
export { useWindowDimensions } from './composables/use-window-dimensions';
|
|
57
|
+
export { createPermissionHook } from './composables/create-permission-hook';
|
|
58
|
+
export { createResourceHook } from './composables/create-resource-hook';
|
|
59
|
+
export { createEventValueHook } from './composables/create-event-value-hook';
|
|
56
60
|
export { Alert, Share, ActionSheetIOS, Linking, Vibration, ToastAndroid, Settings, I18nManager, Dimensions, Appearance, AppState, Keyboard, KEYBOARD_EVENT, BackHandler, PermissionsAndroid, PERMISSIONS, RESULTS, AccessibilityInfo, LayoutAnimation, } from '@symbiote-native/engine';
|
|
57
61
|
export type { IAlertType, IAlertButtonStyle, IAlertButton, IAlertButtons, IAlertOptions, IShareContent, IShareOptions, IShareAction, IActionSheetIOSOptions, IShareActionSheetIOSOptions, IShareActionSheetError, IUrlEvent, II18nManagerConstants, IDisplayMetrics, IDisplayMetricsAndroid, IDimensionsPayload, IDimensionsSet, IDimensionsKey, IDimensionsChangeListener, IDimensionsStatic, IColorSchemeName, IColorSchemePreference, IAppStateStatus, IAppStateEvent, IKeyboardEventName, IKeyboardEvent, IKeyboardMetrics, IBackPressEventName, IBackPressHandler, IPermission, IPermissionStatus, IRationale, IAccessibilityChangeEvent, IAccessibilityChangeEventName, IAccessibilityChangeEventHandler, IAccessibilityAnnouncementFinishedEvent, IAnnounceForAccessibilityOptions, IAccessibilityEventType, ILayoutAnimationType, ILayoutAnimationProperty, ILayoutAnimationConfig, ILayoutAnimationAnim, } from '@symbiote-native/engine';
|
|
58
62
|
export { Platform, StyleSheet, processColor, setColorProcessor, dlog, isDebug, } from '@symbiote-native/engine';
|
package/build/index.js
CHANGED
|
@@ -36,6 +36,10 @@ export { mount, unmount, setAppConfigurator } from './render.js';
|
|
|
36
36
|
// into an <Out/> the destination has to render. See create-portal/index.ts.
|
|
37
37
|
export { Teleport } from './create-portal/index.js';
|
|
38
38
|
export { createTunnel } from './create-tunnel/index.js';
|
|
39
|
+
// Vue's own Transition/TransitionGroup are runtime-dom-only (CSS class toggling) and
|
|
40
|
+
// would otherwise come from the wildcard above as unusable DOM stubs. These fade over
|
|
41
|
+
// the engine's Animated graph instead. See create-transition/index.ts.
|
|
42
|
+
export { Transition, TransitionGroup, } from './create-transition/index.js';
|
|
39
43
|
// IHostInstance is the raw engine node (Vue host refs fall through to it; imperative methods
|
|
40
44
|
// live on each component's expose() handle).
|
|
41
45
|
export { findNodeHandle } from './host-instance/index.js';
|
|
@@ -69,6 +73,9 @@ export { AppRegistry, setHostRegistrar } from './modules/app-registry/index.js';
|
|
|
69
73
|
// Vue composables over the core device-state modules.
|
|
70
74
|
export { useColorScheme } from './composables/use-color-scheme.js';
|
|
71
75
|
export { useWindowDimensions } from './composables/use-window-dimensions.js';
|
|
76
|
+
export { createPermissionHook } from './composables/create-permission-hook.js';
|
|
77
|
+
export { createResourceHook } from './composables/create-resource-hook.js';
|
|
78
|
+
export { createEventValueHook } from './composables/create-event-value-hook.js';
|
|
72
79
|
// Imperative runtime modules: the SAME module both adapters share, re-exported from @symbiote-native/engine.
|
|
73
80
|
export { Alert, Share, ActionSheetIOS, Linking, Vibration, ToastAndroid, Settings, I18nManager, Dimensions, Appearance, AppState, Keyboard, KEYBOARD_EVENT, BackHandler, PermissionsAndroid, PERMISSIONS, RESULTS, AccessibilityInfo, LayoutAnimation, } from '@symbiote-native/engine';
|
|
74
81
|
// Re-export the framework-agnostic engine surface (pure utilities + diagnostics).
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from '@vue/runtime-core';
|
|
2
|
+
export { Transition, TransitionGroup } from '../create-transition';
|
|
2
3
|
import { type ObjectDirective } from '@vue/runtime-core';
|
|
3
4
|
import { type ISymbioteNode } from '@symbiote-native/engine';
|
|
4
5
|
export declare function normalizeProps(props: Record<string, unknown> | null | undefined): Record<string, unknown> | null;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// Scope: Vue's own template directives (v-show, Teleport) and `v-model` on an ELEMENT — see
|
|
10
10
|
// vModelText below for why that is in scope.
|
|
11
11
|
export * from '@vue/runtime-core';
|
|
12
|
+
export { Transition, TransitionGroup } from '../create-transition/index.js';
|
|
12
13
|
import { getCurrentInstance, mergeProps as baseMergeProps, normalizeClass, normalizeStyle as baseNormalizeStyle, warn, } from '@vue/runtime-core';
|
|
13
14
|
import { componentOf, propOf, requestCommitFor, setNativeProps, setProp, whenCommitted, } from '@symbiote-native/engine';
|
|
14
15
|
import { descriptorFor, SWITCH_TAG } from '@symbiote-native/components';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/vue",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "SymbioteNative's Vue adapter — a @vue/runtime-core createRenderer driving real native iOS/Android views through the same engine as the React adapter.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -70,18 +70,18 @@
|
|
|
70
70
|
"@vue/compiler-sfc": "^3.5.13",
|
|
71
71
|
"@vue/runtime-core": "^3.5.13",
|
|
72
72
|
"typescript": "~6.0.0",
|
|
73
|
-
"@symbiote-native/components": "3.1.
|
|
74
|
-
"@symbiote-native/css-parser": "0.5.
|
|
73
|
+
"@symbiote-native/components": "3.1.4",
|
|
74
|
+
"@symbiote-native/css-parser": "0.5.3"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"vue": ">=3.5.0",
|
|
78
78
|
"react-native": ">=0.86",
|
|
79
|
-
"@symbiote-native/engine": "^1.
|
|
79
|
+
"@symbiote-native/engine": "^1.5.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@babel/core": "^7.25.2",
|
|
83
|
-
"@symbiote-native/engine": "1.
|
|
84
|
-
"@symbiote-native/test-utils": "0.4.
|
|
83
|
+
"@symbiote-native/engine": "1.5.0",
|
|
84
|
+
"@symbiote-native/test-utils": "0.4.6"
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"typecheck": "tsc --build",
|