@typecad/ui 1.0.0-alpha.11 → 1.0.0-alpha.13
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 +21 -1
- package/assets/fonts/dejavu/DejaVuSans-Bold.ttf +0 -0
- package/assets/fonts/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
- package/assets/fonts/dejavu/DejaVuSans-Oblique.ttf +0 -0
- package/assets/fonts/dejavu/DejaVuSans.ttf +0 -0
- package/assets/fonts/dejavu/DejaVuSansMono-Bold.ttf +0 -0
- package/assets/fonts/dejavu/DejaVuSansMono.ttf +0 -0
- package/assets/fonts/dejavu/LICENSE +187 -0
- package/assets/fonts/dejavu/README.md +49 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +74 -0
- package/dist/engine-index.js +2 -0
- package/dist/preview/build-program.d.ts +7 -1
- package/dist/preview/build-program.js +94 -15
- package/dist/preview/host-gfx.d.ts +3 -0
- package/dist/preview/host-gfx.js +30 -3
- package/dist/preview/host-ui-runtime.d.ts +115 -0
- package/dist/preview/host-ui-runtime.js +928 -46
- package/dist/ui-engine/block-layout.js +25 -11
- package/dist/ui-engine/color.d.ts +6 -0
- package/dist/ui-engine/color.js +80 -2
- package/dist/ui-engine/compat-report.d.ts +8 -0
- package/dist/ui-engine/compat-report.js +124 -0
- package/dist/ui-engine/css-imports.d.ts +4 -0
- package/dist/ui-engine/css-imports.js +70 -0
- package/dist/ui-engine/css-parser.js +58 -14
- package/dist/ui-engine/default-font.d.ts +25 -0
- package/dist/ui-engine/default-font.js +80 -0
- package/dist/ui-engine/font-assets.d.ts +2 -2
- package/dist/ui-engine/font-assets.js +22 -5
- package/dist/ui-engine/html-parser.d.ts +4 -0
- package/dist/ui-engine/html-parser.js +241 -26
- package/dist/ui-engine/image-assets.d.ts +8 -1
- package/dist/ui-engine/image-assets.js +35 -2
- package/dist/ui-engine/image-decode.d.ts +22 -0
- package/dist/ui-engine/image-decode.js +194 -0
- package/dist/ui-engine/inline-parser.js +1 -1
- package/dist/ui-engine/layout-engine.d.ts +19 -0
- package/dist/ui-engine/layout-engine.js +59 -3
- package/dist/ui-engine/model.d.ts +18 -0
- package/dist/ui-engine/model.js +76 -8
- package/dist/ui-engine/runtime-header/blend-bodies.js +29 -9
- package/dist/ui-engine/runtime-header/canvas-helpers.js +5 -2
- package/dist/ui-engine/runtime-header/canvas-scrollbar.js +115 -111
- package/dist/ui-engine/runtime-header/cuttlefish-gfx.js +21 -0
- package/dist/ui-engine/runtime-header/dirty-scroll-mutators.js +182 -179
- package/dist/ui-engine/runtime-header/forward-decls.js +215 -167
- package/dist/ui-engine/runtime-header/init-press-input.js +138 -135
- package/dist/ui-engine/runtime-header/keyboard.js +682 -380
- package/dist/ui-engine/runtime-header/node-draw-body.js +1656 -1377
- package/dist/ui-engine/runtime-header/paint-order-coords.js +259 -214
- package/dist/ui-engine/runtime-header/paint-rects-repair.js +736 -568
- package/dist/ui-engine/runtime-header/scroll-physics.js +25 -1
- package/dist/ui-engine/runtime-header/state-bindings-nav.js +9 -0
- package/dist/ui-engine/runtime-header/structs.js +228 -216
- package/dist/ui-engine/runtime-header/text-rendering.js +888 -770
- package/dist/ui-engine/runtime-header/tick/bindings-phase.js +118 -116
- package/dist/ui-engine/runtime-header/tick/dirty-draw-phase.js +897 -633
- package/dist/ui-engine/runtime-header/tick/scroll-canvas-phase.js +24 -25
- package/dist/ui-engine/runtime-header/touch-keyboard-fwd.js +79 -23
- package/dist/ui-engine/runtime-header/types-defines.js +110 -93
- package/dist/ui-engine/shadcn-kit.d.ts +1 -0
- package/dist/ui-engine/shadcn-kit.js +502 -0
- package/dist/ui-engine/style-resolver.d.ts +4 -0
- package/dist/ui-engine/style-resolver.js +58 -6
- package/dist/ui-engine/transpile-ui.js +12 -5
- package/dist/ui-engine/ua-stylesheet.d.ts +22 -1
- package/dist/ui-engine/ua-stylesheet.js +119 -32
- package/dist/ui-engine/ui-lowering.js +37 -3
- package/dist/ui-engine/ui-registry.js +32 -4
- package/dist/ui-engine/yoga-layout.js +57 -52
- package/dist/wizard/config-writer.d.ts +49 -0
- package/dist/wizard/config-writer.js +366 -0
- package/dist/wizard/display-catalog.d.ts +75 -0
- package/dist/wizard/display-catalog.js +207 -0
- package/dist/wizard/index.d.ts +7 -0
- package/dist/wizard/index.js +10 -0
- package/dist/wizard/integration-wizard.d.ts +15 -0
- package/dist/wizard/integration-wizard.js +486 -0
- package/dist/wizard/prompts.d.ts +32 -0
- package/dist/wizard/prompts.js +95 -0
- package/dist/wizard/starter-ui.d.ts +1 -0
- package/dist/wizard/starter-ui.js +56 -0
- package/package.json +18 -5
- package/src/cli.ts +87 -0
- package/src/engine-index.ts +53 -51
- package/src/preview/build-program.ts +810 -734
- package/src/preview/host-gfx.ts +30 -3
- package/src/preview/host-ui-runtime.ts +4133 -3289
- package/src/ui-engine/block-layout.ts +24 -11
- package/src/ui-engine/color.ts +77 -2
- package/src/ui-engine/compat-report.ts +139 -0
- package/src/ui-engine/css-imports.ts +69 -0
- package/src/ui-engine/css-parser.ts +64 -15
- package/src/ui-engine/default-font.ts +95 -0
- package/src/ui-engine/font-assets.ts +545 -525
- package/src/ui-engine/html-parser.ts +615 -397
- package/src/ui-engine/image-assets.ts +37 -2
- package/src/ui-engine/image-decode.ts +244 -0
- package/src/ui-engine/inline-parser.ts +1 -1
- package/src/ui-engine/layout-engine.ts +61 -3
- package/src/ui-engine/model.ts +1317 -1230
- package/src/ui-engine/runtime-header/blend-bodies.ts +29 -9
- package/src/ui-engine/runtime-header/canvas-helpers.ts +5 -2
- package/src/ui-engine/runtime-header/canvas-scrollbar.ts +121 -117
- package/src/ui-engine/runtime-header/cuttlefish-gfx.ts +21 -0
- package/src/ui-engine/runtime-header/dirty-scroll-mutators.ts +188 -185
- package/src/ui-engine/runtime-header/forward-decls.ts +227 -179
- package/src/ui-engine/runtime-header/init-press-input.ts +144 -141
- package/src/ui-engine/runtime-header/keyboard.ts +689 -386
- package/src/ui-engine/runtime-header/node-draw-body.ts +1681 -1402
- package/src/ui-engine/runtime-header/paint-order-coords.ts +265 -220
- package/src/ui-engine/runtime-header/paint-rects-repair.ts +742 -574
- package/src/ui-engine/runtime-header/scroll-physics.ts +25 -1
- package/src/ui-engine/runtime-header/state-bindings-nav.ts +9 -0
- package/src/ui-engine/runtime-header/structs.ts +234 -222
- package/src/ui-engine/runtime-header/text-rendering.ts +894 -776
- package/src/ui-engine/runtime-header/tick/bindings-phase.ts +124 -122
- package/src/ui-engine/runtime-header/tick/dirty-draw-phase.ts +902 -638
- package/src/ui-engine/runtime-header/tick/scroll-canvas-phase.ts +30 -31
- package/src/ui-engine/runtime-header/touch-keyboard-fwd.ts +79 -23
- package/src/ui-engine/runtime-header/types-defines.ts +116 -99
- package/src/ui-engine/shadcn-kit.ts +503 -0
- package/src/ui-engine/style-resolver.ts +471 -416
- package/src/ui-engine/transpile-ui.ts +12 -5
- package/src/ui-engine/ua-stylesheet.ts +137 -31
- package/src/ui-engine/ui-lowering.ts +486 -452
- package/src/ui-engine/ui-registry.ts +556 -524
- package/src/ui-engine/yoga-layout.ts +307 -309
- package/src/wizard/config-writer.ts +404 -0
- package/src/wizard/display-catalog.ts +273 -0
- package/src/wizard/index.ts +38 -0
- package/src/wizard/integration-wizard.ts +619 -0
- package/src/wizard/prompts.ts +145 -0
- package/src/wizard/starter-ui.ts +58 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Interactive prompt helpers for the @typecad/ui integration wizard.
|
|
3
|
+
//
|
|
4
|
+
// Deliberately mirrors the prompt vocabulary of cuttlefish's `init` wizard
|
|
5
|
+
// (readline/promises + chalk, numbered selects) so the two CLIs feel the same.
|
|
6
|
+
// No external prompt framework — embedded installs should stay light.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
import * as readline from "node:readline/promises";
|
|
10
|
+
import chalk from "chalk";
|
|
11
|
+
|
|
12
|
+
export type ReadlineInterface = ReturnType<typeof readline.createInterface>;
|
|
13
|
+
|
|
14
|
+
export interface PromptTextOptions {
|
|
15
|
+
/** Value used when the answer is blank. Omit to require input. */
|
|
16
|
+
defaultValue?: string;
|
|
17
|
+
/** Allow an empty answer (returns ""). Implied when defaultValue is set. */
|
|
18
|
+
allowBlank?: boolean;
|
|
19
|
+
validate?: (value: string) => string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function promptText(
|
|
23
|
+
rl: ReadlineInterface,
|
|
24
|
+
prompt: string,
|
|
25
|
+
options: PromptTextOptions = {},
|
|
26
|
+
): Promise<string> {
|
|
27
|
+
// An empty-string default is "no default" for display purposes — otherwise
|
|
28
|
+
// blank-allowed prompts render a stray "()" suffix.
|
|
29
|
+
const hasDefault = options.defaultValue !== undefined && options.defaultValue !== "";
|
|
30
|
+
while (true) {
|
|
31
|
+
const suffix = hasDefault ? ` (${options.defaultValue})` : "";
|
|
32
|
+
const answer = await rl.question(`${chalk.cyan("?")} ${prompt}${suffix}: `);
|
|
33
|
+
const trimmed = answer.trim();
|
|
34
|
+
const value = trimmed === "" && hasDefault ? options.defaultValue! : trimmed;
|
|
35
|
+
|
|
36
|
+
if (value === "" && !options.allowBlank && !hasDefault) {
|
|
37
|
+
console.log(` ${chalk.red("✗")} Please enter a value.`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (options.validate) {
|
|
41
|
+
const error = options.validate(value);
|
|
42
|
+
if (error) {
|
|
43
|
+
console.log(` ${chalk.red("✗")} ${error}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface PromptIntOptions {
|
|
52
|
+
defaultValue?: number;
|
|
53
|
+
/** Allow a blank answer (returns undefined). */
|
|
54
|
+
allowBlank?: boolean;
|
|
55
|
+
min?: number;
|
|
56
|
+
max?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function promptInt(
|
|
60
|
+
rl: ReadlineInterface,
|
|
61
|
+
prompt: string,
|
|
62
|
+
options: PromptIntOptions = {},
|
|
63
|
+
): Promise<number | undefined> {
|
|
64
|
+
const hasDefault = options.defaultValue !== undefined;
|
|
65
|
+
while (true) {
|
|
66
|
+
const suffix = hasDefault ? ` (${options.defaultValue})` : "";
|
|
67
|
+
const answer = await rl.question(`${chalk.cyan("?")} ${prompt}${suffix}: `);
|
|
68
|
+
const trimmed = answer.trim();
|
|
69
|
+
|
|
70
|
+
if (trimmed === "" ) {
|
|
71
|
+
if (options.allowBlank) return undefined;
|
|
72
|
+
if (hasDefault) return options.defaultValue;
|
|
73
|
+
console.log(` ${chalk.red("✗")} Please enter a number.`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const value = Number(trimmed);
|
|
78
|
+
if (!Number.isFinite(value)) {
|
|
79
|
+
console.log(` ${chalk.red("✗")} "${trimmed}" is not a number.`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (options.min !== undefined && value < options.min) {
|
|
83
|
+
console.log(` ${chalk.red("✗")} Must be ≥ ${options.min}.`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (options.max !== undefined && value > options.max) {
|
|
87
|
+
console.log(` ${chalk.red("✗")} Must be ≤ ${options.max}.`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface SelectOption<T extends string> {
|
|
95
|
+
label: string;
|
|
96
|
+
value: T;
|
|
97
|
+
hint?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function promptSelect<T extends string>(
|
|
101
|
+
rl: ReadlineInterface,
|
|
102
|
+
prompt: string,
|
|
103
|
+
options: SelectOption<T>[],
|
|
104
|
+
): Promise<T> {
|
|
105
|
+
console.log(`${chalk.cyan("?")} ${prompt}:`);
|
|
106
|
+
for (let i = 0; i < options.length; i++) {
|
|
107
|
+
const option = options[i]!;
|
|
108
|
+
const hint = option.hint ? chalk.dim(` — ${option.hint}`) : "";
|
|
109
|
+
console.log(` ${chalk.dim(`${i + 1})`)} ${option.label}${hint}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
while (true) {
|
|
113
|
+
const answer = await rl.question(` Enter number (1-${options.length}): `);
|
|
114
|
+
const idx = parseInt(answer.trim(), 10) - 1;
|
|
115
|
+
if (idx >= 0 && idx < options.length) {
|
|
116
|
+
return options[idx]!.value;
|
|
117
|
+
}
|
|
118
|
+
console.log(` ${chalk.red("✗")} Please enter a number between 1 and ${options.length}.`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function promptConfirm(
|
|
123
|
+
rl: ReadlineInterface,
|
|
124
|
+
prompt: string,
|
|
125
|
+
defaultValue: boolean,
|
|
126
|
+
): Promise<boolean> {
|
|
127
|
+
const suffix = defaultValue ? " (Y/n)" : " (y/N)";
|
|
128
|
+
const answer = await rl.question(`${chalk.cyan("?")} ${prompt}${suffix}: `);
|
|
129
|
+
const trimmed = answer.trim().toLowerCase();
|
|
130
|
+
if (trimmed === "") return defaultValue;
|
|
131
|
+
return trimmed === "y" || trimmed === "yes";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Create the readline interface the wizard prompts run against. Streams are
|
|
136
|
+
* resolved lazily and injectable so the wizard can be driven end-to-end by
|
|
137
|
+
* tests (Node's readline hangs on a second question() when stdin is a pipe
|
|
138
|
+
* on some platforms, so scripted pipes are fed through a PassThrough).
|
|
139
|
+
*/
|
|
140
|
+
export function createPromptInterface(
|
|
141
|
+
inputStream: NodeJS.ReadableStream = process.stdin,
|
|
142
|
+
outputStream: NodeJS.WritableStream = process.stdout,
|
|
143
|
+
): ReadlineInterface {
|
|
144
|
+
return readline.createInterface({ input: inputStream, output: outputStream });
|
|
145
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Starter .ui file emitted by the integration wizard when the config's entry
|
|
3
|
+
// file does not exist yet. Uses only README-documented syntax: the Svelte-
|
|
4
|
+
// style single-file component shape, ui.mount(screen), a ui.signal, an
|
|
5
|
+
// on:click handler, and {signal} interpolation in the template.
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
export function renderStarterUi(displayWidth = 320, displayHeight = 240): string {
|
|
9
|
+
// Keep text sizes sane on small mono panels (128×64 OLEDs).
|
|
10
|
+
const compact = displayWidth <= 160 || displayHeight <= 160;
|
|
11
|
+
const titleSize = compact ? 12 : 22;
|
|
12
|
+
const countSize = compact ? 10 : 16;
|
|
13
|
+
const buttonSize = compact ? 10 : 16;
|
|
14
|
+
|
|
15
|
+
return [
|
|
16
|
+
"<script>",
|
|
17
|
+
" // Starter screen generated by `npx @typecad/ui --config`.",
|
|
18
|
+
" // Edit freely — this is ordinary cuttlefish source, not generated output.",
|
|
19
|
+
"",
|
|
20
|
+
" import { ui } from '@typecad/ui';",
|
|
21
|
+
"",
|
|
22
|
+
" ui.mount(screen);",
|
|
23
|
+
"",
|
|
24
|
+
" export const taps = ui.signal(0);",
|
|
25
|
+
"",
|
|
26
|
+
" export function onTap() {",
|
|
27
|
+
" taps.set(taps() + 1);",
|
|
28
|
+
" }",
|
|
29
|
+
"</script>",
|
|
30
|
+
"",
|
|
31
|
+
"<style>",
|
|
32
|
+
" screen {",
|
|
33
|
+
" background: #101418;",
|
|
34
|
+
" display: flex;",
|
|
35
|
+
" flex-direction: column;",
|
|
36
|
+
" align-items: center;",
|
|
37
|
+
" justify-content: center;",
|
|
38
|
+
" gap: 16px;",
|
|
39
|
+
" }",
|
|
40
|
+
` #title { color: #e8eef2; font-size: ${titleSize}px; }`,
|
|
41
|
+
` #count { color: #38bdf8; font-size: ${countSize}px; }`,
|
|
42
|
+
" #tap {",
|
|
43
|
+
` padding: 10px 24px;`,
|
|
44
|
+
" border-radius: 8px;",
|
|
45
|
+
" background: #1f6feb;",
|
|
46
|
+
" color: #ffffff;",
|
|
47
|
+
` font-size: ${buttonSize}px;`,
|
|
48
|
+
" }",
|
|
49
|
+
"</style>",
|
|
50
|
+
"",
|
|
51
|
+
"<screen>",
|
|
52
|
+
" <text id=\"title\">@typecad/ui is running</text>",
|
|
53
|
+
" <text id=\"count\">taps: {taps}</text>",
|
|
54
|
+
" <button id=\"tap\" on:click={onTap}>Tap me</button>",
|
|
55
|
+
"</screen>",
|
|
56
|
+
"",
|
|
57
|
+
].join("\n");
|
|
58
|
+
}
|