@symbiote-native/components 0.1.0 → 0.1.1
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/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @symbiote-native/components
|
|
2
2
|
|
|
3
|
-
The **framework-agnostic component layer** of [
|
|
3
|
+
The **framework-agnostic component layer** of [SymbioteNative](../../README.md) — pure state machines
|
|
4
4
|
and pure render functions for every visual component (`Switch`, `Modal`, `ScrollView`, the
|
|
5
5
|
`FlatList`/`SectionList` family, …), written **once** and inherited by every framework adapter
|
|
6
6
|
(`@symbiote-native/react`, `@symbiote-native/vue`, `@symbiote-native/angular`, and the ones after them). It
|
|
7
7
|
exists so that "add component X to a new adapter" means writing a thin lifecycle + descriptor
|
|
8
8
|
bridge, not re-implementing X's logic per framework.
|
|
9
9
|
|
|
10
|
-
> New to
|
|
10
|
+
> New to SymbioteNative? The [root README](../../README.md) has the architecture. This package is
|
|
11
11
|
> "Workstream B" — the piece that makes cross-adapter feature parity **structural** instead of a
|
|
12
12
|
> promise kept by hand.
|
|
13
13
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/components",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Framework-agnostic component logic (state machines + render functions) for
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Framework-agnostic component logic (state machines + render functions) for SymbioteNative — written once, inherited by every adapter (React, Vue, Angular, ...).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@symbiote-native/engine": "0.1.
|
|
32
|
+
"@symbiote-native/engine": "0.1.1"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"typecheck": "tsc --build",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { type ISymbioteEvent, type ISymbioteNode } from '@symbiote/engine';
|
|
2
|
-
export type IDrawerPosition = 'left' | 'right';
|
|
3
|
-
export type IDrawerLockMode = 'unlocked' | 'locked-closed' | 'locked-open';
|
|
4
|
-
export type IKeyboardDismissMode = 'none' | 'on-drag';
|
|
5
|
-
export type IDrawerState = 'Idle' | 'Dragging' | 'Settling';
|
|
6
|
-
export interface IDrawerSlideEvent {
|
|
7
|
-
offset: number;
|
|
8
|
-
}
|
|
9
|
-
export interface IDrawerLayoutAndroidHandle {
|
|
10
|
-
openDrawer(): void;
|
|
11
|
-
closeDrawer(): void;
|
|
12
|
-
}
|
|
13
|
-
export declare const DRAWER_VIEW_NAME = "AndroidDrawerLayout";
|
|
14
|
-
export declare const OPEN_DRAWER_COMMAND = "openDrawer";
|
|
15
|
-
export declare const CLOSE_DRAWER_COMMAND = "closeDrawer";
|
|
16
|
-
export declare const DRAWER_STATES: ReadonlyArray<IDrawerState>;
|
|
17
|
-
export declare const DEFAULT_DRAWER_BACKGROUND_COLOR = "white";
|
|
18
|
-
export declare const DEFAULT_DRAWER_POSITION: IDrawerPosition;
|
|
19
|
-
export declare function offsetFromSlide(event: ISymbioteEvent): number;
|
|
20
|
-
export declare function stateFromChange(event: ISymbioteEvent): IDrawerState;
|
|
21
|
-
export declare function dispatchDrawerCommand(node: ISymbioteNode | null, command: string): void;
|
|
22
|
-
export declare function buildDrawerHandle(getNode: () => ISymbioteNode | null): IDrawerLayoutAndroidHandle;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// DrawerLayoutAndroid: the framework-agnostic logic half. AndroidDrawerLayout is Android-only, so
|
|
2
|
-
// this module holds only the platform-invariant contract every adapter shares — the drawer-position
|
|
3
|
-
// / lock-mode / keyboard-dismiss / state TYPES, the native view + command NAMES, the slide/state
|
|
4
|
-
// event NORMALIZATION, and the imperative open/close HANDLE. The adapter supplies only its lifecycle
|
|
5
|
-
// (refs / reactivity) + the descriptor→element bridge; the view (style/prop) math lives in
|
|
6
|
-
// view/render-drawer-layout-android.ts. No Platform.OS read; the adapter's filename selects the build
|
|
7
|
-
// (ADR 0019). The wolf-tui twin shape is the shared state module pulled out of each reconciler.
|
|
8
|
-
import { dispatchViewCommand, dlog, } from '@symbiote/engine';
|
|
9
|
-
// The native view name registered by AndroidDrawerLayoutNativeComponent's
|
|
10
|
-
// codegenNativeComponent('AndroidDrawerLayout'): the derive-by-default name (any non-`symbiote-*`
|
|
11
|
-
// type flows through descriptorFor untouched, the engine deriving its events from the ViewConfig).
|
|
12
|
-
export const DRAWER_VIEW_NAME = 'AndroidDrawerLayout';
|
|
13
|
-
export const OPEN_DRAWER_COMMAND = 'openDrawer';
|
|
14
|
-
export const CLOSE_DRAWER_COMMAND = 'closeDrawer';
|
|
15
|
-
// RN's drawerState int -> string mapping (android DRAWER_STATES indexed by the native drawerState):
|
|
16
|
-
// 0=Idle, 1=Dragging, 2=Settling.
|
|
17
|
-
export const DRAWER_STATES = ['Idle', 'Dragging', 'Settling'];
|
|
18
|
-
export const DEFAULT_DRAWER_BACKGROUND_COLOR = 'white';
|
|
19
|
-
export const DEFAULT_DRAWER_POSITION = 'left';
|
|
20
|
-
// Slide-event normalization: pull the native drag offset (RN onDrawerSlide nativeEvent.offset).
|
|
21
|
-
export function offsetFromSlide(event) {
|
|
22
|
-
const offset = event.nativeEvent.offset;
|
|
23
|
-
return typeof offset === 'number' ? offset : 0;
|
|
24
|
-
}
|
|
25
|
-
// State-change normalization: map the native drawerState int onto its DRAWER_STATES label.
|
|
26
|
-
export function stateFromChange(event) {
|
|
27
|
-
const index = event.nativeEvent.drawerState;
|
|
28
|
-
if (typeof index === 'number' && index >= 0 && index < DRAWER_STATES.length) {
|
|
29
|
-
return DRAWER_STATES[index];
|
|
30
|
-
}
|
|
31
|
-
return 'Idle';
|
|
32
|
-
}
|
|
33
|
-
// Issue a drawer command against the committed host node, or log a silent no-op when there is no
|
|
34
|
-
// node yet (the first render has not committed). Mirrors Switch's dispatchViewCommand path.
|
|
35
|
-
export function dispatchDrawerCommand(node, command) {
|
|
36
|
-
if (node === null) {
|
|
37
|
-
dlog(`DrawerLayoutAndroid ${command} no-op: no committed host node`);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
dlog(`DrawerLayoutAndroid dispatch ${command}`);
|
|
41
|
-
dispatchViewCommand(node, command, []);
|
|
42
|
-
}
|
|
43
|
-
// The imperative handle is identical across adapters: openDrawer / closeDrawer dispatch the matching
|
|
44
|
-
// view command on the SAME host node. Built once here; each adapter backs it with its lazy node
|
|
45
|
-
// getter (React `() => ref.current`, Vue `() => nodeRef.value`), read on every call — the node is
|
|
46
|
-
// null until the element commits, so an eager capture would freeze null and every command no-op.
|
|
47
|
-
// The Vue twin of React's useImperativeHandle(ref, …); mirrors buildScrollViewHandle.
|
|
48
|
-
export function buildDrawerHandle(getNode) {
|
|
49
|
-
return {
|
|
50
|
-
openDrawer: () => dispatchDrawerCommand(getNode(), OPEN_DRAWER_COMMAND),
|
|
51
|
-
closeDrawer: () => dispatchDrawerCommand(getNode(), CLOSE_DRAWER_COMMAND),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { IStyleProp, IViewStyle } from '@symbiote/engine';
|
|
2
|
-
import { type IDrawerLockMode, type IDrawerPosition, type IKeyboardDismissMode } from '../state/drawer-layout-android';
|
|
3
|
-
export declare const DRAWER_HOST_STYLE: Readonly<IViewStyle>;
|
|
4
|
-
export declare const DRAWER_MAIN_SUBVIEW_STYLE: Readonly<IViewStyle>;
|
|
5
|
-
export interface IDrawerLayoutResolveInput {
|
|
6
|
-
drawerWidth?: number;
|
|
7
|
-
drawerPosition?: IDrawerPosition;
|
|
8
|
-
drawerLockMode?: IDrawerLockMode;
|
|
9
|
-
keyboardDismissMode?: IKeyboardDismissMode;
|
|
10
|
-
drawerBackgroundColor?: string;
|
|
11
|
-
statusBarBackgroundColor?: string;
|
|
12
|
-
drawerOpened: boolean;
|
|
13
|
-
style?: IStyleProp<IViewStyle>;
|
|
14
|
-
passthrough: Record<string, unknown>;
|
|
15
|
-
}
|
|
16
|
-
export interface IDrawerLayoutResolved {
|
|
17
|
-
viewName: string;
|
|
18
|
-
hostProps: Record<string, unknown>;
|
|
19
|
-
contentWrapperStyle: Readonly<IViewStyle>;
|
|
20
|
-
navigationWrapperStyle: IViewStyle;
|
|
21
|
-
navigationPointerEvents: 'auto' | 'none';
|
|
22
|
-
}
|
|
23
|
-
export declare function resolveDrawerLayout(input: IDrawerLayoutResolveInput): IDrawerLayoutResolved;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// DrawerLayoutAndroid: the framework-agnostic view (style/prop) math. AndroidDrawerLayout is an
|
|
2
|
-
// ordinary Fabric host node committing through the same childSet as the rest of the tree (like
|
|
3
|
-
// Modal / Switch): a content wrapper FIRST and a navigation wrapper SECOND, mirroring RN's android
|
|
4
|
-
// render order {childrenWrapper}{drawerViewWrapper}. This builds the host prop bag + the two wrapper
|
|
5
|
-
// styles from the resolved props; the adapter overlays its ref + the wrapped event handlers and
|
|
6
|
-
// supplies the framework children / navigation elements. The logic half (event normalization,
|
|
7
|
-
// imperative handle, constants, types) lives in state/drawer-layout-android.ts.
|
|
8
|
-
import { DEFAULT_DRAWER_BACKGROUND_COLOR, DEFAULT_DRAWER_POSITION, DRAWER_VIEW_NAME, } from '../state/drawer-layout-android';
|
|
9
|
-
// RN styles.base on the host: flex:1 plus the Android drop-shadow that floats the drawer over
|
|
10
|
-
// content (android styles.base { flex:1, elevation:16 }).
|
|
11
|
-
export const DRAWER_HOST_STYLE = {
|
|
12
|
-
flex: 1,
|
|
13
|
-
elevation: 16,
|
|
14
|
-
};
|
|
15
|
-
// RN styles.mainSubview: the content wrapper fills the host (absolute, all edges 0).
|
|
16
|
-
export const DRAWER_MAIN_SUBVIEW_STYLE = {
|
|
17
|
-
position: 'absolute',
|
|
18
|
-
top: 0,
|
|
19
|
-
left: 0,
|
|
20
|
-
right: 0,
|
|
21
|
-
bottom: 0,
|
|
22
|
-
};
|
|
23
|
-
// RN styles.drawerSubview: the navigation wrapper is absolute and full-height; its width comes from
|
|
24
|
-
// drawerWidth and its background from drawerBackgroundColor (both folded in by resolveDrawerLayout).
|
|
25
|
-
const DRAWER_SUBVIEW_STYLE = {
|
|
26
|
-
position: 'absolute',
|
|
27
|
-
top: 0,
|
|
28
|
-
bottom: 0,
|
|
29
|
-
};
|
|
30
|
-
// Build the AndroidDrawerLayout host prop bag + the two wrapper styles from the resolved props. The
|
|
31
|
-
// adapter overlays its ref + the four wrapped event handlers (onDrawerOpen / Close / Slide /
|
|
32
|
-
// StateChanged) and nests [contentWrapper, navigationWrapper] under the host IN THAT ORDER.
|
|
33
|
-
export function resolveDrawerLayout(input) {
|
|
34
|
-
const drawerBackgroundColor = input.drawerBackgroundColor ?? DEFAULT_DRAWER_BACKGROUND_COLOR;
|
|
35
|
-
const hostProps = {
|
|
36
|
-
...input.passthrough,
|
|
37
|
-
drawerWidth: input.drawerWidth,
|
|
38
|
-
drawerPosition: input.drawerPosition ?? DEFAULT_DRAWER_POSITION,
|
|
39
|
-
drawerLockMode: input.drawerLockMode,
|
|
40
|
-
keyboardDismissMode: input.keyboardDismissMode,
|
|
41
|
-
drawerBackgroundColor,
|
|
42
|
-
statusBarBackgroundColor: input.statusBarBackgroundColor,
|
|
43
|
-
style: [DRAWER_HOST_STYLE, input.style],
|
|
44
|
-
};
|
|
45
|
-
return {
|
|
46
|
-
viewName: DRAWER_VIEW_NAME,
|
|
47
|
-
hostProps,
|
|
48
|
-
contentWrapperStyle: DRAWER_MAIN_SUBVIEW_STYLE,
|
|
49
|
-
navigationWrapperStyle: {
|
|
50
|
-
...DRAWER_SUBVIEW_STYLE,
|
|
51
|
-
width: input.drawerWidth,
|
|
52
|
-
backgroundColor: drawerBackgroundColor,
|
|
53
|
-
},
|
|
54
|
-
navigationPointerEvents: input.drawerOpened ? 'auto' : 'none',
|
|
55
|
-
};
|
|
56
|
-
}
|