view-contracts 0.3.3 → 0.3.5
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 +6 -6
- package/cli-contract.yaml +1 -1
- package/dist/view-contracts.bundle.mjs +169 -153
- package/dist/view-contracts.bundle.mjs.map +4 -4
- package/docs/cli-reference.md +1 -1
- package/package.json +1 -1
- package/renderers/NATIVE_THEME_EMIT.md +73 -0
- package/renderers/compose/README.md +7 -0
- package/renderers/compose/templates/Screen.kt.hbs +3 -5
- package/renderers/compose/templates/VcTheme.kt.hbs +7 -13
- package/renderers/react/defaults/theme.yaml +7 -0
- package/renderers/react/defaults/tokens.yaml +11 -0
- package/renderers/react/lowering/foldStyle.ts +87 -0
- package/renderers/react/lowering/lowerToJsx.ts +58 -69
- package/renderers/react/renderComponents.ts +180 -24
- package/renderers/react/renderRuntime.ts +36 -43
- package/renderers/react/routes.yaml +2 -2
- package/renderers/react/runtime/index.ts +1 -1
- package/renderers/react/runtime/style.ts +3 -55
- package/renderers/react/runtime/theme.css +1 -1
- package/renderers/react/runtime/types.ts +0 -24
- package/renderers/react/style/foldLiterals.ts +129 -0
- package/renderers/react/syncGeneratedRuntime.ts +35 -47
- package/renderers/react/templates/components-index.ts.hbs +2 -2
- package/renderers/react/templates/runtime.ts.hbs +10 -0
- package/renderers/react/templates/style-helpers.ts.hbs +2 -2
- package/renderers/swiftui/README.md +7 -0
- package/renderers/swiftui/templates/Screen.swift.hbs +3 -5
- package/renderers/swiftui/templates/VcTheme.swift.hbs +8 -16
- package/spec/ui-dsl.schema.json +1331 -345
- package/src/generated/schema/allowed-components.ts +1 -1
- package/src/generated/schema/dsl-enums.ts +1 -1
- package/src/generated/schema/dsl-properties.ts +1 -1
- package/src/generated/schema/index.ts +1 -1
- package/src/generated/schema/lowering-style-properties.ts +9 -2
- package/src/generated/schema/react-renderer-element-config.ts +1 -1
- package/src/generated/schema/schema-document.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFile, writeFile, mkdir, stat, rm } from 'node:fs/promises';
|
|
1
|
+
import { readFile, writeFile, mkdir, stat, rm, unlink } from 'node:fs/promises';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import type { ViewContractsConfig } from '../../src/config.js';
|
|
4
4
|
import { projectRoot } from '../../src/config.js';
|
|
@@ -14,64 +14,52 @@ async function pathExists(target: string): Promise<boolean> {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
/** Remove legacy generated layout under generated/react/. */
|
|
18
|
+
export async function removeLegacyReactRuntimeLayout(reactDir: string): Promise<void> {
|
|
19
|
+
const generatedRoot = resolve(reactDir, '..');
|
|
20
|
+
for (const dir of [resolve(reactDir, 'runtime'), resolve(generatedRoot, 'components'), resolve(generatedRoot, 'runtime')]) {
|
|
21
|
+
if (await pathExists(dir)) {
|
|
22
|
+
await rm(dir, { recursive: true, force: true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (const name of ['extensions.tsx', 'extensions.ts', 'contracts.ts'] as const) {
|
|
26
|
+
const stale = resolve(reactDir, name);
|
|
27
|
+
if (await pathExists(stale)) {
|
|
28
|
+
await unlink(stale);
|
|
29
|
+
}
|
|
21
30
|
}
|
|
22
31
|
}
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
await writeFile(resolve(componentsDir, 'style.ts'), await readFile(resolve(runtimeSrc, 'style.ts'), 'utf-8'), 'utf-8');
|
|
27
|
-
await writeFile(resolve(componentsDir, 'types.ts'), await readFile(resolve(runtimeSrc, 'types.ts'), 'utf-8'), 'utf-8');
|
|
33
|
+
function stripDispatchImport(dispatchSource: string): string {
|
|
34
|
+
return dispatchSource.replace(/^import type \{ DispatchableAction \} from [^;]+;\n/gm, '');
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
/**
|
|
31
|
-
export async function
|
|
37
|
+
/** Emit generated/react/runtime.ts — fixed system runtime only (dispatch + style helpers). */
|
|
38
|
+
export async function writeGeneratedRuntimeBundle(
|
|
32
39
|
configPath: string,
|
|
33
40
|
config: ViewContractsConfig,
|
|
34
41
|
templatesDir?: string,
|
|
35
|
-
): Promise<{
|
|
42
|
+
): Promise<{ runtimePath: string }> {
|
|
36
43
|
const root = projectRoot(configPath);
|
|
44
|
+
const reactDir = config.generated.reactDir;
|
|
37
45
|
const templates = reactTemplatesDir(templatesDir ?? (config.rendererTemplatesDir ? resolve(root, config.rendererTemplatesDir) : undefined));
|
|
38
|
-
const
|
|
39
|
-
const runtimeDir = resolve(config.generated.reactDir, '../runtime');
|
|
46
|
+
const runtimeSrc = reactRuntimeDir();
|
|
40
47
|
|
|
41
|
-
await mkdir(
|
|
42
|
-
await
|
|
48
|
+
await mkdir(reactDir, { recursive: true });
|
|
49
|
+
await removeLegacyReactRuntimeLayout(reactDir);
|
|
43
50
|
|
|
44
|
-
await
|
|
45
|
-
await
|
|
46
|
-
await
|
|
47
|
-
|
|
48
|
-
await renderTemplate(templates, 'style-helpers.ts.hbs', {}),
|
|
49
|
-
'utf-8',
|
|
50
|
-
);
|
|
51
|
-
await writeFile(
|
|
52
|
-
resolve(componentsDir, 'index.ts'),
|
|
53
|
-
await renderTemplate(templates, 'components-index.ts.hbs', {}),
|
|
54
|
-
'utf-8',
|
|
55
|
-
);
|
|
56
|
-
await writeFile(
|
|
57
|
-
resolve(runtimeDir, 'types.ts'),
|
|
58
|
-
await renderTemplate(templates, 'runtime-types.ts.hbs', {}),
|
|
59
|
-
'utf-8',
|
|
60
|
-
);
|
|
61
|
-
await writeFile(
|
|
62
|
-
resolve(runtimeDir, 'dispatch.ts'),
|
|
63
|
-
await renderTemplate(templates, 'dispatch.ts.hbs', {}),
|
|
64
|
-
'utf-8',
|
|
65
|
-
);
|
|
51
|
+
const typesBody = await readFile(resolve(runtimeSrc, 'types.ts'), 'utf-8');
|
|
52
|
+
const styleBody = await readFile(resolve(runtimeSrc, 'style.ts'), 'utf-8');
|
|
53
|
+
const dispatchRaw = await renderTemplate(templates, 'dispatch.ts.hbs', {});
|
|
54
|
+
const dispatchBody = stripDispatchImport(dispatchRaw);
|
|
66
55
|
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
const content = await renderTemplate(templates, 'runtime.ts.hbs', {
|
|
57
|
+
typesBody: typesBody.trim(),
|
|
58
|
+
styleBody: styleBody.trim(),
|
|
59
|
+
dispatchBody: dispatchBody.trim(),
|
|
60
|
+
});
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return
|
|
73
|
-
.replace(/from 'view-contracts:runtime\/dispatch'/g, "from '../runtime/dispatch.js'")
|
|
74
|
-
.replace(/from "view-contracts:runtime\/dispatch"/g, 'from "../runtime/dispatch.js"')
|
|
75
|
-
.replace(/from 'view-contracts:runtime\/types'/g, "from './types.js'")
|
|
76
|
-
.replace(/from "view-contracts:runtime\/types"/g, 'from "./types.js"');
|
|
62
|
+
const runtimePath = resolve(reactDir, 'runtime.ts');
|
|
63
|
+
await writeFile(runtimePath, content, 'utf-8');
|
|
64
|
+
return { runtimePath };
|
|
77
65
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Auto-generated component barrel — DO NOT EDIT */
|
|
2
2
|
export * from './extensions.js';
|
|
3
3
|
export type { TableColumn } from './extensions.js';
|
|
4
|
-
export {
|
|
5
|
-
export type { Action, Option
|
|
4
|
+
export { extensionClassName, resolveExtensionVariant, isHidden, toneClass } from './style.js';
|
|
5
|
+
export type { Action, Option } from './types.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** Auto-generated style helpers for
|
|
2
|
-
export {
|
|
1
|
+
/** Auto-generated style helpers for extensions — DO NOT EDIT */
|
|
2
|
+
export { extensionClassName, resolveExtensionVariant } from './style.js';
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# SwiftUI renderer scaffold
|
|
2
2
|
|
|
3
|
+
**Not implemented yet** beyond theme / screen stubs. View IR lowering and modifier emission are future work.
|
|
4
|
+
|
|
5
|
+
SwiftUI `ViewModifier` chains are **compositional** (not CSS-style override). view-contracts may later introduce a separate **modifier pipeline** concept (wrapper-style transforms, analogous to nested HTML layout shells) — that is **out of scope for the current phase**. When styling is implemented, defaults + variant + instance props will be **folded at compile time** into resolved values, not chained for cascade-like override. See [docs/ARCHITECTURE.md](../../docs/ARCHITECTURE.md) § Native renderers.
|
|
6
|
+
|
|
3
7
|
- Maps: `elements.yaml`, `properties.yaml` (hand-maintained under this directory)
|
|
4
8
|
- Routes: `routes.yaml`
|
|
5
9
|
- Templates: `templates/`
|
|
10
|
+
- Theme codegen spec: [../NATIVE_THEME_EMIT.md](../NATIVE_THEME_EMIT.md)
|
|
6
11
|
|
|
7
12
|
Implement SwiftUI code generation by reading View IR + renderer maps.
|
|
13
|
+
Theme is emitted at build time via `src/design/emit/swiftui.ts` and `templates/theme/*.hbs` — same Token IR + Theme IR as React `theme.css`, not runtime JSON.
|
|
14
|
+
|
|
8
15
|
Extend vocabulary via `spec/ui-dsl.schema.json` (from `ui-dsl-*.csv`), then update renderer maps.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
// {{screenName}} — SwiftUI scaffold
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// TODO(Phase B): Load theme.json and emit PrimaryButtonStyle(), vcTextMuted(), etc.
|
|
1
|
+
// {{screenName}} — SwiftUI scaffold
|
|
2
|
+
// View IR lowering: renderers/swiftui/lowerToSwiftUI.ts (planned)
|
|
3
|
+
// Theme: renderers/NATIVE_THEME_EMIT.md
|
|
6
4
|
|
|
7
5
|
import SwiftUI
|
|
8
6
|
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
// VcTheme — SwiftUI theme scaffold
|
|
2
|
-
// Load Token IR + Theme IR from bundle resources:
|
|
3
|
-
// {{tokensJsonPath}}
|
|
4
|
-
// {{themeJsonPath}}
|
|
1
|
+
// VcTheme — SwiftUI theme (scaffold placeholder)
|
|
5
2
|
//
|
|
6
|
-
//
|
|
3
|
+
// Theme is emitted at build time from Token IR + Theme IR via Handlebars templates.
|
|
4
|
+
// See renderers/NATIVE_THEME_EMIT.md — not loaded from JSON at runtime.
|
|
5
|
+
//
|
|
6
|
+
// Implementation: src/design/emit/swiftui.ts + renderers/swiftui/templates/theme/*.hbs
|
|
7
|
+
// Output target: generated/swiftui/Theme/
|
|
7
8
|
|
|
8
|
-
import
|
|
9
|
+
import SwiftUI
|
|
9
10
|
|
|
10
11
|
enum VcTheme {
|
|
11
|
-
|
|
12
|
-
static let themeResource = "{{themeJsonPath}}"
|
|
13
|
-
|
|
14
|
-
/// Placeholder — decode theme.json into Swift types in Phase B.
|
|
15
|
-
static func loadThemeJson() -> Data? {
|
|
16
|
-
guard let url = Bundle.main.url(forResource: themeResource, withExtension: nil) else {
|
|
17
|
-
return nil
|
|
18
|
-
}
|
|
19
|
-
return try? Data(contentsOf: url)
|
|
20
|
-
}
|
|
12
|
+
// Populated by emitSwiftUITheme() when swiftui target is enabled.
|
|
21
13
|
}
|