view-contracts 0.4.1 → 0.4.3
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/dist/dsl.js +2 -0
- package/dist/dsl.js.map +7 -0
- package/dist/preview.mjs +23 -23
- package/dist/preview.mjs.map +2 -2
- package/dist/view-contracts.bundle.mjs +16 -18
- package/dist/view-contracts.bundle.mjs.map +2 -2
- package/package.json +5 -4
- package/src/dsl/index.ts +16 -0
- package/src/dsl/screen.tsx +54 -0
- package/src/dsl/types.ts +68 -0
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "view-contracts",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Contract-first UI design toolchain — restricted TSX to View IR to platform renderers",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"workspaces": [
|
|
7
|
-
"packages/*"
|
|
8
|
-
],
|
|
9
6
|
"bin": {
|
|
10
7
|
"view-contracts": "dist/view-contracts.bundle.mjs"
|
|
11
8
|
},
|
|
12
9
|
"exports": {
|
|
13
10
|
".": "./dist/view-contracts.bundle.mjs",
|
|
11
|
+
"./dsl": "./dist/dsl.js",
|
|
14
12
|
"./preview": "./dist/preview.mjs",
|
|
15
13
|
"./package.json": "./package.json"
|
|
16
14
|
},
|
|
17
15
|
"files": [
|
|
18
16
|
"dist/view-contracts.bundle.mjs",
|
|
19
17
|
"dist/view-contracts.bundle.mjs.map",
|
|
18
|
+
"dist/dsl.js",
|
|
19
|
+
"dist/dsl.js.map",
|
|
20
20
|
"dist/preview.mjs",
|
|
21
21
|
"dist/preview.mjs.map",
|
|
22
22
|
"dist/preview-style-helpers.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"renderers/react/runtime",
|
|
25
25
|
"renderers/react/defaults",
|
|
26
26
|
"src/generated/schema",
|
|
27
|
+
"src/dsl",
|
|
27
28
|
"spec",
|
|
28
29
|
"renderers",
|
|
29
30
|
"cli-contract.yaml",
|
package/src/dsl/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { screen, view } from './screen.js';
|
|
2
|
+
export type {
|
|
3
|
+
ViewAction,
|
|
4
|
+
ActionHandlers,
|
|
5
|
+
ScreenContext,
|
|
6
|
+
ViewContract,
|
|
7
|
+
ViewPartial,
|
|
8
|
+
ViewScreenProps,
|
|
9
|
+
CommonProps,
|
|
10
|
+
Option,
|
|
11
|
+
Tone,
|
|
12
|
+
Align,
|
|
13
|
+
Justify,
|
|
14
|
+
ButtonVariant,
|
|
15
|
+
FieldSize,
|
|
16
|
+
} from './types.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { FC } from 'react';
|
|
3
|
+
import type { ScreenContext, ViewContract, ViewPartial, ViewScreenProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
ViewAction,
|
|
7
|
+
ActionHandlers,
|
|
8
|
+
ScreenContext,
|
|
9
|
+
ViewContract,
|
|
10
|
+
ViewPartial,
|
|
11
|
+
ViewScreenProps,
|
|
12
|
+
CommonProps,
|
|
13
|
+
Option,
|
|
14
|
+
Tone,
|
|
15
|
+
Align,
|
|
16
|
+
Justify,
|
|
17
|
+
ButtonVariant,
|
|
18
|
+
FieldSize,
|
|
19
|
+
} from './types.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Wrap a restricted view-contract TSX definition.
|
|
23
|
+
*
|
|
24
|
+
* - **Preview runtime**: returns a React component (`vm` + `actions` props).
|
|
25
|
+
* - **Compiler**: statically extracts JSX from the render callback → View IR.
|
|
26
|
+
*/
|
|
27
|
+
export function screen<TViewModel>(
|
|
28
|
+
render: (ctx: ScreenContext<TViewModel>) => ReactNode,
|
|
29
|
+
): FC<ViewScreenProps<TViewModel>> {
|
|
30
|
+
function ViewScreen({ vm, actions = {} }: ViewScreenProps<TViewModel>) {
|
|
31
|
+
return <>{render({ vm, actions })}</>;
|
|
32
|
+
}
|
|
33
|
+
return Object.assign(ViewScreen, {
|
|
34
|
+
__viewContract: true as const,
|
|
35
|
+
render,
|
|
36
|
+
}) as FC<ViewScreenProps<TViewModel>>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Reusable view-contract sub-component (composable inside screen() or other view()).
|
|
41
|
+
*
|
|
42
|
+
* Compiled by inlining into the parent View IR; preview runtime renders as a normal React FC.
|
|
43
|
+
*/
|
|
44
|
+
export function view<TProps>(
|
|
45
|
+
render: (props: TProps) => ReactNode,
|
|
46
|
+
): FC<TProps> & ViewPartial<TProps> {
|
|
47
|
+
function ViewComponent(props: TProps) {
|
|
48
|
+
return <>{render(props)}</>;
|
|
49
|
+
}
|
|
50
|
+
return Object.assign(ViewComponent, {
|
|
51
|
+
__viewPartial: true as const,
|
|
52
|
+
render,
|
|
53
|
+
}) as FC<TProps> & ViewPartial<TProps>;
|
|
54
|
+
}
|
package/src/dsl/types.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/** Action descriptor referenced from view contracts (names must match OpenAPI operationId). */
|
|
4
|
+
export interface ViewAction {
|
|
5
|
+
name: string;
|
|
6
|
+
params?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type ActionHandlers = Record<string, (params?: unknown) => void | Promise<void>>;
|
|
10
|
+
|
|
11
|
+
export interface ScreenContext<TViewModel> {
|
|
12
|
+
vm: TViewModel;
|
|
13
|
+
actions: ActionHandlers;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ViewContract<TViewModel> {
|
|
17
|
+
readonly __viewContract: true;
|
|
18
|
+
readonly render: (ctx: ScreenContext<TViewModel>) => ReactNode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type Tone = 'default' | 'muted' | 'primary' | 'success' | 'warning' | 'danger';
|
|
22
|
+
export type Align = 'start' | 'center' | 'end' | 'stretch';
|
|
23
|
+
export type Justify = 'start' | 'center' | 'end' | 'between' | 'around';
|
|
24
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';
|
|
25
|
+
export type FieldSize = 'sm' | 'md' | 'lg';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Shared layout/visual props.
|
|
29
|
+
* Dimension props (width, height, gap, padding, …) are numbers in logical units;
|
|
30
|
+
* the web preview maps them to px.
|
|
31
|
+
*/
|
|
32
|
+
export interface CommonProps {
|
|
33
|
+
id?: string;
|
|
34
|
+
testId?: string;
|
|
35
|
+
ariaLabel?: string;
|
|
36
|
+
children?: ReactNode;
|
|
37
|
+
hidden?: boolean;
|
|
38
|
+
width?: number;
|
|
39
|
+
minWidth?: number;
|
|
40
|
+
maxWidth?: number;
|
|
41
|
+
height?: number;
|
|
42
|
+
minHeight?: number;
|
|
43
|
+
maxHeight?: number;
|
|
44
|
+
padding?: number;
|
|
45
|
+
margin?: number;
|
|
46
|
+
gap?: number;
|
|
47
|
+
radius?: number;
|
|
48
|
+
border?: boolean;
|
|
49
|
+
shadow?: boolean;
|
|
50
|
+
tone?: Tone;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface Option {
|
|
54
|
+
label: string;
|
|
55
|
+
value: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ViewPartial<TProps> {
|
|
59
|
+
readonly __viewPartial: true;
|
|
60
|
+
readonly render: (props: TProps) => ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type ViewScreenProps<TViewModel> = {
|
|
64
|
+
vm: TViewModel;
|
|
65
|
+
actions?: ActionHandlers;
|
|
66
|
+
/** Optional theme id — propagated from App element for future multi-theme runtime. */
|
|
67
|
+
theme?: string;
|
|
68
|
+
};
|