@symbiote-native/engine 1.4.0 → 1.5.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/event-value-source.d.ts +4 -0
- package/build/event-value-source.js +3 -0
- package/build/expo-native-view.d.ts +2 -0
- package/build/expo-native-view.js +19 -0
- package/build/index.d.ts +7 -0
- package/build/index.js +3 -0
- package/build/permission-hook-runtime.d.ts +27 -0
- package/build/permission-hook-runtime.js +37 -0
- package/build/resource-controller.d.ts +6 -0
- package/build/resource-controller.js +30 -0
- package/package.json +2 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// The Fabric name `requireNativeViewManager` registers: the adapter prefix plus the module name,
|
|
2
|
+
// and the app identifier when the host sets one
|
|
3
|
+
export function expoViewManagerName(moduleName) {
|
|
4
|
+
const appIdentifier = Reflect.get(Reflect.get(globalThis, 'expo') ?? {}, '__expo_app_identifier__');
|
|
5
|
+
const suffix = typeof appIdentifier === 'string' && appIdentifier !== ''
|
|
6
|
+
? `_${appIdentifier}`
|
|
7
|
+
: '';
|
|
8
|
+
return `ViewManagerAdapter_${moduleName}${suffix}`;
|
|
9
|
+
}
|
|
10
|
+
// A missing view config must not crash the render, the view just renders nothing
|
|
11
|
+
export function tryRegisterNativeView(register) {
|
|
12
|
+
try {
|
|
13
|
+
register();
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
package/build/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export { reportUncaughtError } from './report-error';
|
|
|
52
52
|
export type { IUncaughtErrorInfo } from './report-error';
|
|
53
53
|
export { getNativeModule, getEnforcingNativeModule } from './native-modules';
|
|
54
54
|
export { installDeviceEventHub, NativeEventEmitter, setDeviceEventSource, } from './native-events';
|
|
55
|
+
export type { IEventValueSource } from './event-value-source';
|
|
55
56
|
export type { IEventSubscription, IEventEmitterModule, INativeEventListener, IDeviceEventSource, } from './native-events';
|
|
56
57
|
export { AnimatedNode, AnimatedWithChildren, AnimatedValue, AnimatedValueXY, AnimatedColor, AnimatedInterpolation, AnimatedAddition, AnimatedSubtraction, AnimatedMultiplication, AnimatedDivision, AnimatedModulo, AnimatedDiffClamp, AnimatedEvent, add, subtract, multiply, divide, modulo, diffClamp, event, forkEvent, unforkEvent, attachNativeEvent, attachNativeEventHandler, flushValue, Easing, createNumericInterpolation, checkValidRanges, TimingAnimation, SpringAnimation, DecayAnimation, AnimatedTracking, timing, spring, decay, parallel, sequence, stagger, loop, delay, nativeAnimated, isNativeAnimatedAvailable, AnimatedProps, createAnimatedLeafLifecycle, AnimatedStyle, AnimatedTransform, AnimatedMock, reduceProps, isAnimatedNode, readPassthroughStyle, resolveHostNode, } from './animated';
|
|
57
58
|
export type { IAnimatedLeafLifecycle, IValueXY, IRgbaValue, IColorInput, IEventConfig, IEventListener, IAnimatedEventHandler, INativeEventAttachment, IValueListener, IEasing, IEasingFunction, IInterpolationConfig, IExtrapolateType, IAnimation, IEndCallback, IEndResult, ICompositeAnimation, ITimingConfig, ISpringConfig, IDecayConfig, IParallelConfig, ILoopAnimationConfig, INativeNodeConfig, INativeAnimationConfig, INativeEventMapping, IPlatformConfig, } from './animated';
|
|
@@ -106,3 +107,9 @@ export type { IClaimMode, IHostBehavior, IPayloadFold } from './host-behavior';
|
|
|
106
107
|
export { setBehaviorListener, markPropsDirty, setNodeDispatch } from './node';
|
|
107
108
|
export { hasListenerFor, listenerFor } from './node';
|
|
108
109
|
export type { IEventDispatch } from './node';
|
|
110
|
+
export { createPermissionApi, resolveInitialPermission, fetchInitialPermission, splitWriteOnlyPermissionOptions, } from './permission-hook-runtime';
|
|
111
|
+
export type { IWriteOnlyPermissionOptions } from './permission-hook-runtime';
|
|
112
|
+
export { expoViewManagerName, tryRegisterNativeView } from './expo-native-view';
|
|
113
|
+
export { createResourceController } from './resource-controller';
|
|
114
|
+
export type { IResourceController } from './resource-controller';
|
|
115
|
+
export type { IPermissionHookBehavior, IPermissionHookMethods, IPermissionHookOptions, IPermissionApi, IPermissionHookResult, } from './permission-hook-runtime';
|
package/build/index.js
CHANGED
|
@@ -139,3 +139,6 @@ export { setBehaviorListener, markPropsDirty, setNodeDispatch } from './node.js'
|
|
|
139
139
|
// The only correct way to ask what would receive an event: a behavior may answer a name through
|
|
140
140
|
// one shared `IEventDispatch` rather than a closure in `node.listeners`
|
|
141
141
|
export { hasListenerFor, listenerFor } from './node.js';
|
|
142
|
+
export { createPermissionApi, resolveInitialPermission, fetchInitialPermission, splitWriteOnlyPermissionOptions, } from './permission-hook-runtime.js';
|
|
143
|
+
export { expoViewManagerName, tryRegisterNativeView } from './expo-native-view.js';
|
|
144
|
+
export { createResourceController } from './resource-controller.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type IPermissionHookBehavior = {
|
|
2
|
+
/** Auto-fetch the current status on mount without asking the user. @default true */
|
|
3
|
+
get?: boolean;
|
|
4
|
+
/** Auto-request the user to grant permission on mount. @default false */
|
|
5
|
+
request?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type IPermissionHookMethods<TPermission, TOptions extends object> = {
|
|
8
|
+
getMethod: (options?: TOptions) => Promise<TPermission>;
|
|
9
|
+
requestMethod: (options?: TOptions) => Promise<TPermission>;
|
|
10
|
+
};
|
|
11
|
+
export type IPermissionHookOptions<TOptions extends object> = IPermissionHookBehavior & TOptions;
|
|
12
|
+
export type IPermissionApi<TPermission, TOptions extends object> = {
|
|
13
|
+
get: (methodOptions?: TOptions) => Promise<TPermission>;
|
|
14
|
+
request: (methodOptions?: TOptions) => Promise<TPermission>;
|
|
15
|
+
};
|
|
16
|
+
export declare function createPermissionApi<TPermission, TOptions extends object>(methods: IPermissionHookMethods<TPermission, TOptions>, setStatus: (value: TPermission) => void): IPermissionApi<TPermission, TOptions>;
|
|
17
|
+
export declare function resolveInitialPermission<TPermission, TOptions extends object>(methods: IPermissionHookMethods<TPermission, TOptions>, behavior: IPermissionHookBehavior, methodOptions: TOptions | undefined): Promise<TPermission | null>;
|
|
18
|
+
export type IPermissionHookResult<TPermission> = [
|
|
19
|
+
TPermission | null,
|
|
20
|
+
() => Promise<TPermission>,
|
|
21
|
+
() => Promise<TPermission>
|
|
22
|
+
];
|
|
23
|
+
export type IWriteOnlyPermissionOptions = {
|
|
24
|
+
writeOnly?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export declare function splitWriteOnlyPermissionOptions(options?: IPermissionHookOptions<IWriteOnlyPermissionOptions>): [IPermissionHookBehavior, IWriteOnlyPermissionOptions | undefined];
|
|
27
|
+
export declare function fetchInitialPermission<TPermission, TOptions extends object>(methods: IPermissionHookMethods<TPermission, TOptions>, behavior: IPermissionHookBehavior | undefined, methodOptions: TOptions | undefined, commit: (value: TPermission) => void): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Framework-agnostic twin of expo-modules-core's `usePermission` method-dispatch. Every Expo
|
|
2
|
+
// wrapper package's hook/composable/primitive/service imports this, no per-package copy left
|
|
3
|
+
// The one piece every adapter's hook/composable/primitive would otherwise re-wrap by hand:
|
|
4
|
+
// call the method, commit its response to whichever state primitive `setStatus` closes over
|
|
5
|
+
export function createPermissionApi(methods, setStatus) {
|
|
6
|
+
async function run(method, methodOptions) {
|
|
7
|
+
const response = await method(methodOptions);
|
|
8
|
+
setStatus(response);
|
|
9
|
+
return response;
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
get: methodOptions => run(methods.getMethod, methodOptions),
|
|
13
|
+
request: methodOptions => run(methods.requestMethod, methodOptions),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function resolveInitialPermission(methods, behavior, methodOptions) {
|
|
17
|
+
const { get = true, request = false } = behavior;
|
|
18
|
+
if (!request && !get)
|
|
19
|
+
return null;
|
|
20
|
+
const method = request ? methods.requestMethod : methods.getMethod;
|
|
21
|
+
return methodOptions !== undefined && Object.keys(methodOptions).length > 0
|
|
22
|
+
? method(methodOptions)
|
|
23
|
+
: method();
|
|
24
|
+
}
|
|
25
|
+
export function splitWriteOnlyPermissionOptions(options) {
|
|
26
|
+
const { get, request, writeOnly } = options ?? {};
|
|
27
|
+
return [
|
|
28
|
+
{ get, request },
|
|
29
|
+
writeOnly === undefined ? undefined : { writeOnly },
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
export function fetchInitialPermission(methods, behavior, methodOptions, commit) {
|
|
33
|
+
resolveInitialPermission(methods, { get: behavior?.get ?? true, request: behavior?.request ?? false }, methodOptions).then(response => {
|
|
34
|
+
if (response)
|
|
35
|
+
commit(response);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type IResourceController<TKey, TResource> = {
|
|
2
|
+
resolve: (key: TKey) => TResource;
|
|
3
|
+
flushDispose: () => void;
|
|
4
|
+
dispose: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function createResourceController<TKey, TResource>(create: (key: TKey) => TResource, dispose: (resource: TResource) => void, isSameKey?: (a: TKey, b: TKey) => boolean): IResourceController<TKey, TResource>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Generic twin of expo-modules-core's `useReleasingSharedObject`. `resolve()` never disposes
|
|
2
|
+
// inline - the stale resource waits in `flushDispose()`, called from each adapter's own
|
|
3
|
+
// commit/effect phase, matching upstream's own "release outside of render" invariant
|
|
4
|
+
export function createResourceController(create, dispose, isSameKey = Object.is) {
|
|
5
|
+
let current = null;
|
|
6
|
+
let pendingDispose = null;
|
|
7
|
+
function resolve(key) {
|
|
8
|
+
if (current && isSameKey(current.key, key))
|
|
9
|
+
return current.resource;
|
|
10
|
+
if (current)
|
|
11
|
+
pendingDispose = current.resource;
|
|
12
|
+
const resource = create(key);
|
|
13
|
+
current = { key, resource };
|
|
14
|
+
return resource;
|
|
15
|
+
}
|
|
16
|
+
function flushDispose() {
|
|
17
|
+
if (pendingDispose) {
|
|
18
|
+
dispose(pendingDispose);
|
|
19
|
+
pendingDispose = null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function disposeAll() {
|
|
23
|
+
flushDispose();
|
|
24
|
+
if (current) {
|
|
25
|
+
dispose(current.resource);
|
|
26
|
+
current = null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return { resolve, flushDispose, dispose: disposeAll };
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "SymbioteNative's retained shadow-tree engine — clone-on-write commit path + event normalization over React Native Fabric, shared by every framework adapter.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
},
|
|
72
72
|
"peerDependenciesMeta": {},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@symbiote-native/test-utils": "0.4.
|
|
74
|
+
"@symbiote-native/test-utils": "0.4.6"
|
|
75
75
|
},
|
|
76
76
|
"scripts": {
|
|
77
77
|
"typecheck": "tsc --build",
|