@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.
Files changed (135) hide show
  1. package/README.md +21 -1
  2. package/assets/fonts/dejavu/DejaVuSans-Bold.ttf +0 -0
  3. package/assets/fonts/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
  4. package/assets/fonts/dejavu/DejaVuSans-Oblique.ttf +0 -0
  5. package/assets/fonts/dejavu/DejaVuSans.ttf +0 -0
  6. package/assets/fonts/dejavu/DejaVuSansMono-Bold.ttf +0 -0
  7. package/assets/fonts/dejavu/DejaVuSansMono.ttf +0 -0
  8. package/assets/fonts/dejavu/LICENSE +187 -0
  9. package/assets/fonts/dejavu/README.md +49 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +74 -0
  12. package/dist/engine-index.js +2 -0
  13. package/dist/preview/build-program.d.ts +7 -1
  14. package/dist/preview/build-program.js +94 -15
  15. package/dist/preview/host-gfx.d.ts +3 -0
  16. package/dist/preview/host-gfx.js +30 -3
  17. package/dist/preview/host-ui-runtime.d.ts +115 -0
  18. package/dist/preview/host-ui-runtime.js +928 -46
  19. package/dist/ui-engine/block-layout.js +25 -11
  20. package/dist/ui-engine/color.d.ts +6 -0
  21. package/dist/ui-engine/color.js +80 -2
  22. package/dist/ui-engine/compat-report.d.ts +8 -0
  23. package/dist/ui-engine/compat-report.js +124 -0
  24. package/dist/ui-engine/css-imports.d.ts +4 -0
  25. package/dist/ui-engine/css-imports.js +70 -0
  26. package/dist/ui-engine/css-parser.js +58 -14
  27. package/dist/ui-engine/default-font.d.ts +25 -0
  28. package/dist/ui-engine/default-font.js +80 -0
  29. package/dist/ui-engine/font-assets.d.ts +2 -2
  30. package/dist/ui-engine/font-assets.js +22 -5
  31. package/dist/ui-engine/html-parser.d.ts +4 -0
  32. package/dist/ui-engine/html-parser.js +241 -26
  33. package/dist/ui-engine/image-assets.d.ts +8 -1
  34. package/dist/ui-engine/image-assets.js +35 -2
  35. package/dist/ui-engine/image-decode.d.ts +22 -0
  36. package/dist/ui-engine/image-decode.js +194 -0
  37. package/dist/ui-engine/inline-parser.js +1 -1
  38. package/dist/ui-engine/layout-engine.d.ts +19 -0
  39. package/dist/ui-engine/layout-engine.js +59 -3
  40. package/dist/ui-engine/model.d.ts +18 -0
  41. package/dist/ui-engine/model.js +76 -8
  42. package/dist/ui-engine/runtime-header/blend-bodies.js +29 -9
  43. package/dist/ui-engine/runtime-header/canvas-helpers.js +5 -2
  44. package/dist/ui-engine/runtime-header/canvas-scrollbar.js +115 -111
  45. package/dist/ui-engine/runtime-header/cuttlefish-gfx.js +21 -0
  46. package/dist/ui-engine/runtime-header/dirty-scroll-mutators.js +182 -179
  47. package/dist/ui-engine/runtime-header/forward-decls.js +215 -167
  48. package/dist/ui-engine/runtime-header/init-press-input.js +138 -135
  49. package/dist/ui-engine/runtime-header/keyboard.js +682 -380
  50. package/dist/ui-engine/runtime-header/node-draw-body.js +1656 -1377
  51. package/dist/ui-engine/runtime-header/paint-order-coords.js +259 -214
  52. package/dist/ui-engine/runtime-header/paint-rects-repair.js +736 -568
  53. package/dist/ui-engine/runtime-header/scroll-physics.js +25 -1
  54. package/dist/ui-engine/runtime-header/state-bindings-nav.js +9 -0
  55. package/dist/ui-engine/runtime-header/structs.js +228 -216
  56. package/dist/ui-engine/runtime-header/text-rendering.js +888 -770
  57. package/dist/ui-engine/runtime-header/tick/bindings-phase.js +118 -116
  58. package/dist/ui-engine/runtime-header/tick/dirty-draw-phase.js +897 -633
  59. package/dist/ui-engine/runtime-header/tick/scroll-canvas-phase.js +24 -25
  60. package/dist/ui-engine/runtime-header/touch-keyboard-fwd.js +79 -23
  61. package/dist/ui-engine/runtime-header/types-defines.js +110 -93
  62. package/dist/ui-engine/shadcn-kit.d.ts +1 -0
  63. package/dist/ui-engine/shadcn-kit.js +502 -0
  64. package/dist/ui-engine/style-resolver.d.ts +4 -0
  65. package/dist/ui-engine/style-resolver.js +58 -6
  66. package/dist/ui-engine/transpile-ui.js +12 -5
  67. package/dist/ui-engine/ua-stylesheet.d.ts +22 -1
  68. package/dist/ui-engine/ua-stylesheet.js +119 -32
  69. package/dist/ui-engine/ui-lowering.js +37 -3
  70. package/dist/ui-engine/ui-registry.js +32 -4
  71. package/dist/ui-engine/yoga-layout.js +57 -52
  72. package/dist/wizard/config-writer.d.ts +49 -0
  73. package/dist/wizard/config-writer.js +366 -0
  74. package/dist/wizard/display-catalog.d.ts +75 -0
  75. package/dist/wizard/display-catalog.js +207 -0
  76. package/dist/wizard/index.d.ts +7 -0
  77. package/dist/wizard/index.js +10 -0
  78. package/dist/wizard/integration-wizard.d.ts +15 -0
  79. package/dist/wizard/integration-wizard.js +486 -0
  80. package/dist/wizard/prompts.d.ts +32 -0
  81. package/dist/wizard/prompts.js +95 -0
  82. package/dist/wizard/starter-ui.d.ts +1 -0
  83. package/dist/wizard/starter-ui.js +56 -0
  84. package/package.json +18 -5
  85. package/src/cli.ts +87 -0
  86. package/src/engine-index.ts +53 -51
  87. package/src/preview/build-program.ts +810 -734
  88. package/src/preview/host-gfx.ts +30 -3
  89. package/src/preview/host-ui-runtime.ts +4133 -3289
  90. package/src/ui-engine/block-layout.ts +24 -11
  91. package/src/ui-engine/color.ts +77 -2
  92. package/src/ui-engine/compat-report.ts +139 -0
  93. package/src/ui-engine/css-imports.ts +69 -0
  94. package/src/ui-engine/css-parser.ts +64 -15
  95. package/src/ui-engine/default-font.ts +95 -0
  96. package/src/ui-engine/font-assets.ts +545 -525
  97. package/src/ui-engine/html-parser.ts +615 -397
  98. package/src/ui-engine/image-assets.ts +37 -2
  99. package/src/ui-engine/image-decode.ts +244 -0
  100. package/src/ui-engine/inline-parser.ts +1 -1
  101. package/src/ui-engine/layout-engine.ts +61 -3
  102. package/src/ui-engine/model.ts +1317 -1230
  103. package/src/ui-engine/runtime-header/blend-bodies.ts +29 -9
  104. package/src/ui-engine/runtime-header/canvas-helpers.ts +5 -2
  105. package/src/ui-engine/runtime-header/canvas-scrollbar.ts +121 -117
  106. package/src/ui-engine/runtime-header/cuttlefish-gfx.ts +21 -0
  107. package/src/ui-engine/runtime-header/dirty-scroll-mutators.ts +188 -185
  108. package/src/ui-engine/runtime-header/forward-decls.ts +227 -179
  109. package/src/ui-engine/runtime-header/init-press-input.ts +144 -141
  110. package/src/ui-engine/runtime-header/keyboard.ts +689 -386
  111. package/src/ui-engine/runtime-header/node-draw-body.ts +1681 -1402
  112. package/src/ui-engine/runtime-header/paint-order-coords.ts +265 -220
  113. package/src/ui-engine/runtime-header/paint-rects-repair.ts +742 -574
  114. package/src/ui-engine/runtime-header/scroll-physics.ts +25 -1
  115. package/src/ui-engine/runtime-header/state-bindings-nav.ts +9 -0
  116. package/src/ui-engine/runtime-header/structs.ts +234 -222
  117. package/src/ui-engine/runtime-header/text-rendering.ts +894 -776
  118. package/src/ui-engine/runtime-header/tick/bindings-phase.ts +124 -122
  119. package/src/ui-engine/runtime-header/tick/dirty-draw-phase.ts +902 -638
  120. package/src/ui-engine/runtime-header/tick/scroll-canvas-phase.ts +30 -31
  121. package/src/ui-engine/runtime-header/touch-keyboard-fwd.ts +79 -23
  122. package/src/ui-engine/runtime-header/types-defines.ts +116 -99
  123. package/src/ui-engine/shadcn-kit.ts +503 -0
  124. package/src/ui-engine/style-resolver.ts +471 -416
  125. package/src/ui-engine/transpile-ui.ts +12 -5
  126. package/src/ui-engine/ua-stylesheet.ts +137 -31
  127. package/src/ui-engine/ui-lowering.ts +486 -452
  128. package/src/ui-engine/ui-registry.ts +556 -524
  129. package/src/ui-engine/yoga-layout.ts +307 -309
  130. package/src/wizard/config-writer.ts +404 -0
  131. package/src/wizard/display-catalog.ts +273 -0
  132. package/src/wizard/index.ts +38 -0
  133. package/src/wizard/integration-wizard.ts +619 -0
  134. package/src/wizard/prompts.ts +145 -0
  135. 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
+ }