@symbiote-native/solid 3.1.0 → 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/components/checkbox-props.d.ts +6 -0
- package/build/components/checkbox-props.js +1 -0
- package/build/components.d.ts +1 -0
- package/build/define-descriptor-component.d.ts +6 -0
- package/build/define-descriptor-component.js +10 -0
- package/build/define-optional-descriptor-component.d.ts +3 -0
- package/build/define-optional-descriptor-component.js +12 -0
- package/build/descriptor-to-solid.d.ts +2 -1
- package/build/descriptor-to-solid.js +7 -3
- package/build/index.d.ts +4 -0
- package/build/index.js +4 -0
- package/build/jsx-runtime.d.ts +2 -0
- package/build/primitives/define-native-view-component.d.ts +5 -0
- package/build/primitives/define-native-view-component.js +22 -0
- package/build/primitives/use-event.d.ts +6 -0
- package/build/primitives/use-event.js +18 -0
- package/package.json +6 -6
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IClassNameValue } from '@symbiote-native/engine';
|
|
2
|
+
import type { ICheckboxProps as ICheckboxBaseProps } from '@symbiote-native/components';
|
|
3
|
+
import type { IViewProps } from './view-props';
|
|
4
|
+
export type ICheckboxProps = ICheckboxBaseProps & Omit<IViewProps, keyof ICheckboxBaseProps | 'children' | 'ref'> & {
|
|
5
|
+
class?: IClassNameValue;
|
|
6
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/build/components.d.ts
CHANGED
|
@@ -29,5 +29,6 @@ export { TouchableNativeFeedback } from '@symbiote-native/components';
|
|
|
29
29
|
export type { INativeFeedbackBackground, IThemeAttrBackground, IRippleBackground, } from '@symbiote-native/components';
|
|
30
30
|
export type { ITouchableNativeFeedbackProps } from './components/touchable-native-feedback/touchable-native-feedback-props';
|
|
31
31
|
export type { IButtonProps } from './components/button-props';
|
|
32
|
+
export type { ICheckboxProps } from './components/checkbox-props';
|
|
32
33
|
export type { IImageBackgroundProps } from './components/image-background-props';
|
|
33
34
|
export type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
3
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
4
|
+
export declare function defineDescriptorComponent<P extends {
|
|
5
|
+
children?: JSX.Element;
|
|
6
|
+
}>(render: (props: object) => IDescriptor): (props: P) => ISymbioteNode;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { splitProps } from 'solid-js';
|
|
2
|
+
import { descriptorToSolid } from './descriptor-to-solid.js';
|
|
3
|
+
// A component whose host is one shared render function: children are the caller's own and go
|
|
4
|
+
// inside the host, every other prop reaches the render function
|
|
5
|
+
export function defineDescriptorComponent(render) {
|
|
6
|
+
return props => {
|
|
7
|
+
const [, rest] = splitProps(props, ['children']);
|
|
8
|
+
return descriptorToSolid(() => render({ ...rest }), () => props.children);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
2
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
3
|
+
export declare function defineOptionalDescriptorComponent<P extends object>(render: (props: object) => IDescriptor | null): (props: P) => ISymbioteNode | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { descriptorToSolid } from './descriptor-to-solid.js';
|
|
2
|
+
// A childless component whose render function may answer `null`, for a native view that exists
|
|
3
|
+
// on one platform only. The answer is decided once at mount: the bridge builds the node once
|
|
4
|
+
// and then only diffs prop values, so the descriptor's shape must not change afterwards
|
|
5
|
+
export function defineOptionalDescriptorComponent(render) {
|
|
6
|
+
return props => {
|
|
7
|
+
const initial = render({ ...props });
|
|
8
|
+
if (!initial)
|
|
9
|
+
return null;
|
|
10
|
+
return descriptorToSolid(() => render({ ...props }) ?? initial);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
1
2
|
import { type ISymbioteNode } from '@symbiote-native/engine';
|
|
2
3
|
import type { IDescriptor } from '@symbiote-native/components';
|
|
3
|
-
export declare function descriptorToSolid(descriptor: () => IDescriptor): ISymbioteNode;
|
|
4
|
+
export declare function descriptorToSolid(descriptor: () => IDescriptor, children?: () => JSX.Element): ISymbioteNode;
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
import { createMemo, createRenderEffect } from 'solid-js';
|
|
24
24
|
import { isSymbioteNode } from '@symbiote-native/engine';
|
|
25
25
|
import { createDescriptorShapeGuard } from '@symbiote-native/components';
|
|
26
|
-
import { createElement, createTextNode, insertNode, replaceText, spread, } from './renderer.js';
|
|
26
|
+
import { createElement, createTextNode, insert, insertNode, replaceText, spread, } from './renderer.js';
|
|
27
27
|
// The vanished-key widening the render effect below stands on. Shared with the host primitives
|
|
28
28
|
// (components/view, components/text), which fold their props through the same two-branch
|
|
29
29
|
// resolveAccessibilityProps — see that module's header.
|
|
@@ -86,6 +86,10 @@ function mountChildren(parent, children) {
|
|
|
86
86
|
}
|
|
87
87
|
// The memo is what keeps the render fn running ONCE per change no matter how many accessors read
|
|
88
88
|
// it — the root's props, every child's props, every text child all derive from the same call.
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
// `children` is a component's own slot, inserted after the descriptor's children
|
|
90
|
+
export function descriptorToSolid(descriptor, children) {
|
|
91
|
+
const root = buildNode(createMemo(descriptor));
|
|
92
|
+
if (children)
|
|
93
|
+
insert(root, children);
|
|
94
|
+
return root;
|
|
91
95
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export * from './components';
|
|
|
6
6
|
export type { IAccessibilityProps, IAriaProps, IAccessibilityRole, IRole, IAccessibilityStateValue, IAccessibilityValue, IAccessibilityActionInfo, IResponderProps, IImageSource, IImageSourceProp, IResizeMode, IImageSize, IImageCacheStatus, IEnterKeyHint, IInputMode, ISubmitBehavior, } from '@symbiote-native/components';
|
|
7
7
|
export { setImageSourceResolver } from '@symbiote-native/components';
|
|
8
8
|
export { descriptorToSolid } from './descriptor-to-solid';
|
|
9
|
+
export { defineDescriptorComponent } from './define-descriptor-component';
|
|
10
|
+
export { defineOptionalDescriptorComponent } from './define-optional-descriptor-component';
|
|
9
11
|
export { AppRegistry, setHostRegistrar } from './modules/app-registry';
|
|
10
12
|
export type { IComponentProvider, IWrapperComponentProvider, IAppParameters, IRunnable, IHostRegistrar, IRegistry, IHeadlessTask, ITaskProvider, ITaskCanceller, ITaskCancelProvider, } from './modules/app-registry';
|
|
11
13
|
export { StatusBar } from './modules/status-bar';
|
|
@@ -19,7 +21,9 @@ export { createColorScheme } from './primitives/create-color-scheme';
|
|
|
19
21
|
export { createWindowDimensions } from './primitives/create-window-dimensions';
|
|
20
22
|
export { createPermissionHook } from './primitives/create-permission-hook';
|
|
21
23
|
export { createResourceHook } from './primitives/create-resource-hook';
|
|
24
|
+
export { defineNativeViewComponent } from './primitives/define-native-view-component';
|
|
22
25
|
export { createEventValueHook } from './primitives/create-event-value-hook';
|
|
26
|
+
export { useEvent, useEventListener } from './primitives/use-event';
|
|
23
27
|
export { Animated, createAnimatedComponent } from './modules/animated';
|
|
24
28
|
export type { IAnimatedComponentProps } from './modules/animated';
|
|
25
29
|
export { Platform, StyleSheet, PixelRatio, PlatformColor, DynamicColorIOS, processColor, } from '@symbiote-native/engine';
|
package/build/index.js
CHANGED
|
@@ -33,6 +33,8 @@ export { setImageSourceResolver } from '@symbiote-native/components';
|
|
|
33
33
|
// the same reason React exports descriptorToReact — an external wrapper package over a third-party
|
|
34
34
|
// native view maps its shared render fn's Descriptor through the SAME bridge the adapter uses.
|
|
35
35
|
export { descriptorToSolid } from './descriptor-to-solid.js';
|
|
36
|
+
export { defineDescriptorComponent } from './define-descriptor-component.js';
|
|
37
|
+
export { defineOptionalDescriptorComponent } from './define-optional-descriptor-component.js';
|
|
36
38
|
// Safe in the barrel (unlike ./bootstrap, which imports react-native): the registry seam itself
|
|
37
39
|
// only reaches the engine and solid-js.
|
|
38
40
|
export { AppRegistry, setHostRegistrar } from './modules/app-registry/index.js';
|
|
@@ -64,7 +66,9 @@ export { createColorScheme } from './primitives/create-color-scheme.js';
|
|
|
64
66
|
export { createWindowDimensions } from './primitives/create-window-dimensions.js';
|
|
65
67
|
export { createPermissionHook } from './primitives/create-permission-hook.js';
|
|
66
68
|
export { createResourceHook } from './primitives/create-resource-hook.js';
|
|
69
|
+
export { defineNativeViewComponent } from './primitives/define-native-view-component.js';
|
|
67
70
|
export { createEventValueHook } from './primitives/create-event-value-hook.js';
|
|
71
|
+
export { useEvent, useEventListener } from './primitives/use-event.js';
|
|
68
72
|
export { Animated, createAnimatedComponent } from './modules/animated/index.js';
|
|
69
73
|
// Everything below is re-exported VERBATIM from the shared packages — no Solid half exists or is
|
|
70
74
|
// wanted, so a passthrough stub file would only add a hop (.claude/rules/barrel-passthrough.md).
|
package/build/jsx-runtime.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { IViewProps } from './components/view-props';
|
|
|
4
4
|
import type { ITextProps } from './components/text-props';
|
|
5
5
|
import type { IPressableProps } from './components/pressable-props';
|
|
6
6
|
import type { IButtonProps } from './components/button-props';
|
|
7
|
+
import type { ICheckboxProps } from './components/checkbox-props';
|
|
7
8
|
import type { IImageProps } from './components/image-props';
|
|
8
9
|
import type { IImageBackgroundProps } from './components/image-background-props';
|
|
9
10
|
import type { IInputAccessoryViewProps } from './components/input-accessory-view-props';
|
|
@@ -26,6 +27,7 @@ interface ICrossedPrimitiveProps {
|
|
|
26
27
|
text: ITextProps;
|
|
27
28
|
pressable: IPressableProps;
|
|
28
29
|
button: IButtonProps;
|
|
30
|
+
checkbox: ICheckboxProps;
|
|
29
31
|
image: IImageProps;
|
|
30
32
|
'image-background': IImageBackgroundProps;
|
|
31
33
|
'input-accessory-view': IInputAccessoryViewProps;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ICreateNativeViewController } from '@symbiote-native/components';
|
|
2
|
+
import type { ISymbioteNode } from '@symbiote-native/engine';
|
|
3
|
+
export declare function defineNativeViewComponent<THandle, TProps extends object>(createController: ICreateNativeViewController<THandle>): (props: TProps & {
|
|
4
|
+
ref?: (handle: THandle) => void;
|
|
5
|
+
}) => ISymbioteNode | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { onCleanup, splitProps } from 'solid-js';
|
|
2
|
+
import { createHostNodeHolder } from '@symbiote-native/components';
|
|
3
|
+
import { descriptorToSolid } from '../descriptor-to-solid.js';
|
|
4
|
+
// A Solid component over a package's native view: the props go to the controller, its handle goes
|
|
5
|
+
// to `ref`. The shape of the descriptor is decided once at mount, only values change afterwards
|
|
6
|
+
export function defineNativeViewComponent(createController) {
|
|
7
|
+
return (props) => {
|
|
8
|
+
const [own, viewProps] = splitProps(props, ['ref']);
|
|
9
|
+
const host = createHostNodeHolder();
|
|
10
|
+
const controller = createController(host.getNode);
|
|
11
|
+
onCleanup(() => controller.dispose?.());
|
|
12
|
+
const render = () => {
|
|
13
|
+
const descriptor = controller.render({ ...viewProps });
|
|
14
|
+
return descriptor && host.capture(descriptor);
|
|
15
|
+
};
|
|
16
|
+
const initial = render();
|
|
17
|
+
if (!initial)
|
|
18
|
+
return null;
|
|
19
|
+
own.ref?.(controller.handle);
|
|
20
|
+
return descriptorToSolid(() => render() ?? initial);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import type { IEventEmitterOf, IEventName, IEventPayload, IEventsMap } from '@symbiote-native/engine';
|
|
3
|
+
/** Calls the listener for each event, the latest one, and stops when the owner is disposed */
|
|
4
|
+
export declare function useEventListener<TEventsMap extends IEventsMap, TName extends IEventName<TEventsMap>>(emitter: Accessor<IEventEmitterOf<TEventsMap>>, eventName: Accessor<TName>, listener: Accessor<TEventsMap[TName]>): void;
|
|
5
|
+
/** The payload of the last event, `initialValue` (or `null`) until the first one */
|
|
6
|
+
export declare function useEvent<TEventsMap extends IEventsMap, TName extends IEventName<TEventsMap>>(emitter: Accessor<IEventEmitterOf<TEventsMap>>, eventName: Accessor<TName>, initialValue?: IEventPayload<TEventsMap, TName> | null): Accessor<IEventPayload<TEventsMap, TName> | null>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Solid twins of `useEvent` and `useEventListener` of the `expo` package, for any emitter
|
|
2
|
+
import { createEffect, createSignal, on, onCleanup } from 'solid-js';
|
|
3
|
+
import { bindEventListener } from '@symbiote-native/engine';
|
|
4
|
+
/** Calls the listener for each event, the latest one, and stops when the owner is disposed */
|
|
5
|
+
export function useEventListener(emitter, eventName, listener) {
|
|
6
|
+
createEffect(on([emitter, eventName], ([source, name]) => {
|
|
7
|
+
// The listener is read at each event, a new one is not a new subscription
|
|
8
|
+
onCleanup(bindEventListener(source, name, listener));
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
11
|
+
/** The payload of the last event, `initialValue` (or `null`) until the first one */
|
|
12
|
+
export function useEvent(emitter, eventName, initialValue = null) {
|
|
13
|
+
const [event, setEvent] = createSignal(initialValue);
|
|
14
|
+
createEffect(on([emitter, eventName], ([source, name]) => {
|
|
15
|
+
onCleanup(bindEventListener(source, name, () => (next) => setEvent(() => next)));
|
|
16
|
+
}));
|
|
17
|
+
return event;
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/solid",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "SymbioteNative's Solid adapter — a solid-js/universal createRenderer driving real native iOS/Android views through the same engine as every other adapter.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -62,19 +62,19 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"babel-preset-solid": "^1.9.12",
|
|
64
64
|
"typescript": "~6.0.0",
|
|
65
|
-
"@symbiote-native/components": "3.
|
|
66
|
-
"@symbiote-native/css-parser": "0.5.
|
|
65
|
+
"@symbiote-native/components": "3.2.0",
|
|
66
|
+
"@symbiote-native/css-parser": "0.5.4"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"solid-js": ">=1.9.0",
|
|
70
70
|
"react-native": ">=0.86",
|
|
71
|
-
"@symbiote-native/engine": "^1.
|
|
71
|
+
"@symbiote-native/engine": "^1.6.0"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@babel/core": "^7.25.2",
|
|
75
75
|
"solid-js": "^1.9.14",
|
|
76
|
-
"@symbiote-native/engine": "1.
|
|
77
|
-
"@symbiote-native/test-utils": "0.4.
|
|
76
|
+
"@symbiote-native/engine": "1.6.0",
|
|
77
|
+
"@symbiote-native/test-utils": "0.4.7"
|
|
78
78
|
},
|
|
79
79
|
"scripts": {
|
|
80
80
|
"typecheck": "tsc --build",
|