@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
@@ -62,6 +62,12 @@ export class HostAdafruitGFX {
62
62
  // When true (mono/e-ink target), draw primitives snap color values to black/
63
63
  // white by luminance — mirrors the device's UI_MAYBE_SNAP_MONO565 choke-point.
64
64
  monoSnap = false;
65
+ // Storage depth of values written into the buffer. rgb565 targets store
66
+ // packed 565 (expanded at the canvas push); rgb888/rgb666 targets store
67
+ // packed RGB888, with rgb666 quantizing channels to 6 bits at the push
68
+ // boundary — mirroring the device's panel. Set by PreviewUIRuntime from the
69
+ // snapshot's colorFormat before the first frame.
70
+ storage = "rgb565";
65
71
  textSizeX = 1;
66
72
  textSizeY = 1;
67
73
  wrap = true;
@@ -81,6 +87,10 @@ export class HostAdafruitGFX {
81
87
  setMonoSnap(on) {
82
88
  this.monoSnap = on;
83
89
  }
90
+ /** Set the buffer's storage depth (see the `storage` field). */
91
+ setStorageMode(mode) {
92
+ this.storage = mode;
93
+ }
84
94
  snap(c) {
85
95
  if (!this.monoSnap)
86
96
  return c;
@@ -228,7 +238,11 @@ export class HostAdafruitGFX {
228
238
  }
229
239
  r = Math.min(r, Math.trunc(Math.min(w, h) / 2));
230
240
  this.fillRect(x + r, y, w - 2 * r, h, color);
231
- const delta = Math.max(0, h - 2 * r - 1);
241
+ // No max(0, ·) clamp: for a perfect pill (h == 2r) the raw value is -1 and
242
+ // fillCircleHelper's delta++ turns it into 0, landing the arc lines exactly
243
+ // on the box. Clamping to 0 first made every arc line one row too tall —
244
+ // a 1px orphan stub under each corner of pill-shaped badges.
245
+ const delta = h - 2 * r - 1;
232
246
  this.fillCircleHelper(x + w - r - 1, y + r, r, 1, delta, color);
233
247
  this.fillCircleHelper(x + r, y + r, r, 2, delta, color);
234
248
  }
@@ -538,13 +552,26 @@ export class HostAdafruitGFX {
538
552
  out[p + 1] = (c >> 8) & 0xff;
539
553
  out[p + 2] = c & 0xff;
540
554
  }
541
- else {
542
- // 565 target: unpack to 888.
555
+ else if (this.storage === "rgb565") {
556
+ // 565 target: buffer holds packed 565 — unpack to 888.
543
557
  const { r, g, b } = rgb565ToRgb888(c);
544
558
  out[p] = r;
545
559
  out[p + 1] = g;
546
560
  out[p + 2] = b;
547
561
  }
562
+ else {
563
+ // rgb888/rgb666 target: buffer holds packed RGB888. rgb666
564
+ // quantizes to 6 bits/channel at the push (device panel parity).
565
+ let r = (c >> 16) & 0xff, g = (c >> 8) & 0xff, b = c & 0xff;
566
+ if (this.storage === "rgb666") {
567
+ r = (r & 0xfc) | (r >> 6);
568
+ g = (g & 0xfc) | (g >> 6);
569
+ b = (b & 0xfc) | (b >> 6);
570
+ }
571
+ out[p] = r;
572
+ out[p + 1] = g;
573
+ out[p + 2] = b;
574
+ }
548
575
  out[p + 3] = 255;
549
576
  }
550
577
  return out;
@@ -12,6 +12,11 @@ interface RuntimeOptions {
12
12
  onFrame?: (rgba: Uint8ClampedArray) => void;
13
13
  onDiagnostics?: (message: string) => void;
14
14
  }
15
+ /** Linear color lerp at the ACTIVE depth (module runtimeColorFormat): 888
16
+ * targets lerp per 8-bit channel; 565 targets lerp per 5/6-bit channel
17
+ * (device parity — the C++ ui_lerp macro switches the same way). Exported
18
+ * for tests. */
19
+ export declare function lerpColor(a: number, b: number, k100: number): number;
15
20
  export declare class PreviewUIRuntime {
16
21
  private readonly snapshot;
17
22
  readonly gfx: HostAdafruitGFX;
@@ -63,6 +68,10 @@ export declare class PreviewUIRuntime {
63
68
  private settleFromScrollY;
64
69
  private rangeNode;
65
70
  private keyboardVisible;
71
+ /** Modal <select> option list: node index while open, -1 when closed. */
72
+ private selectMenuNode;
73
+ /** True while the select modal overlay needs (re)stamping this frame. */
74
+ private selectMenuDirty;
66
75
  private keyboardDirty;
67
76
  private keyboardTarget;
68
77
  private keyboardKeys;
@@ -92,6 +101,11 @@ export declare class PreviewUIRuntime {
92
101
  pointerDown(x: number, y: number): void;
93
102
  pointerMove(x: number, y: number): void;
94
103
  pointerUp(): void;
104
+ /** Mouse-wheel scroll: a discrete delta applied to the scroll owner under
105
+ * (x, y) — the same hit-scan a drag uses, without the gesture state
106
+ * machine. Wheel-down (positive deltaPx) shows later content; any
107
+ * overscroll from the tick bounces back via the standard settle. */
108
+ wheel(x: number, y: number, deltaPx: number): void;
95
109
  triggerPin(control: PreviewPinControlSpec): void;
96
110
  private createScreenProxy;
97
111
  private applyInitialAssignments;
@@ -103,6 +117,12 @@ export declare class PreviewUIRuntime {
103
117
  private uiInit;
104
118
  private isActiveNode;
105
119
  private isEffectivelyVisible;
120
+ /** Effective stacking z, CSS-style: a non-zero zIndex raises the node AND
121
+ * its subtree — a z-raised panel forms a stacking context, so its
122
+ * descendants stack WITH it (above lower-z siblings), never
123
+ * independently UNDER it (a flat (z, index) sort painted a dialog card
124
+ * over its own children). 0 = "auto" — keep walking ancestors. */
125
+ private stackingZ;
106
126
  private drawsBefore;
107
127
  private compareDrawOrder;
108
128
  private navigate;
@@ -141,6 +161,12 @@ export declare class PreviewUIRuntime {
141
161
  private tryRepairGeometryFill;
142
162
  private clearCurrentSubtreePaint;
143
163
  private setVisible;
164
+ private subtreeFlowExtent;
165
+ private shiftSubtreeMain;
166
+ private restackFlowContainer;
167
+ private reflowScrollContent;
168
+ private reflowAfterVisibility;
169
+ private classifyDirtyAgainstOpenDrawers;
144
170
  private scrollClipForNode;
145
171
  private rectIntersectsClip;
146
172
  private intersectClipRect;
@@ -170,6 +196,43 @@ export declare class PreviewUIRuntime {
170
196
  private markScrollViewDirty;
171
197
  private invalidateScrollCanvasForNode;
172
198
  private drawDirty;
199
+ /** Enable/disable per-frame debug geometry capture (the client overlay
200
+ * reads it; zero cost while off). */
201
+ setDebugCapture(on: boolean): void;
202
+ /** Current-frame debug geometry for the client overlay: every visible node
203
+ * on the active screen at its CURRENT draw position (transform/press/
204
+ * drawer/scroll offsets applied), the scroll viewport clips, and the
205
+ * regions painted this tick (dirty-flash). Coordinates are logical
206
+ * display pixels, matching the app canvas 1:1. */
207
+ debugInfo(): {
208
+ nodes: Array<{
209
+ i: number;
210
+ id?: string;
211
+ tag: string;
212
+ kind: string;
213
+ x: number;
214
+ y: number;
215
+ w: number;
216
+ h: number;
217
+ tappable: boolean;
218
+ }>;
219
+ clips: Array<{
220
+ x: number;
221
+ y: number;
222
+ w: number;
223
+ h: number;
224
+ }>;
225
+ painted: Array<{
226
+ x: number;
227
+ y: number;
228
+ w: number;
229
+ h: number;
230
+ }>;
231
+ };
232
+ /** Inspect-on-tap: topmost node (draw order) whose CURRENT draw box
233
+ * contains the point — unlike hitTest, containers count too. Returns the
234
+ * index, or -1. */
235
+ debugHit(tx: number, ty: number): number;
173
236
  private lineX;
174
237
  private textInsets;
175
238
  private drawTextLines;
@@ -208,6 +271,54 @@ export declare class PreviewUIRuntime {
208
271
  private handleNoTouch;
209
272
  private dispatchBuiltInClick;
210
273
  private keyboardTemplateForNode;
274
+ /** node index -> { open, progress } for every <drawer>; absent = closed. */
275
+ private readonly drawerStates;
276
+ /** True while the client wants per-frame debug geometry + paint rects. */
277
+ private debugCapture;
278
+ /** Node paint rects drawn during this tick (cleared at tick start). */
279
+ private debugPaintedRects;
280
+ /** Drawer animation step per tick (~180ms full slide). */
281
+ /** <toast> auto-close windows, keyed by drawer slot node index. */
282
+ private readonly toastElapsed;
283
+ private applyDrawers;
284
+ private drawerNodeById;
285
+ private drawerOpen;
286
+ private drawerClose;
287
+ /** Slide extent for a drawer or toast: the panel must clear the display
288
+ * edge completely — its own height parks a bottom:0 panel's top row at
289
+ * the fold (a visible sliver after close). Centered dialogs don't slide. */
290
+ private drawerExtent;
291
+ /** Apply a slide progress to the drawer subtree: offsets shift from the
292
+ * edge; the subtree is hidden at 0. Erases the previous frame's region via
293
+ * the standard subtree clear + marks descendants dirty (same contract as
294
+ * animated transform changes). */
295
+ private setDrawerProgress;
296
+ /** True while the node sits inside a fully-closed drawer (skip in draws and
297
+ * hit tests). Drawers with no state entry are closed. */
298
+ private insideClosedDrawer;
299
+ /** Walk ancestors: any drawer ancestor without an open/animating state. */
300
+ private drawerAncestorClosed;
301
+ /** Apply the closed slide offsets to every drawer subtree (initial seed and
302
+ * post-navigate reset) so closed drawers never paint at rest position. */
303
+ private seedDrawersClosed;
304
+ /** Shared geometry of the select modal: a centered list panel sized to
305
+ * the options (capped to ~60% of the screen height). Rows are option
306
+ * text, the current one inverted (fill = select bg, text = inverted). */
307
+ private selectMenuGeometry;
308
+ private openSelectMenu;
309
+ /** Close the modal. When `repaint`, mark the whole tree dirty so the
310
+ * overlay is erased by a full redraw (navigate() clears the screen
311
+ * itself, so it passes false). */
312
+ private closeSelectMenu;
313
+ /** Stamp the modal overlay on top of the current framebuffer. Idempotent
314
+ * per frame — the close path full-repaints beneath it. */
315
+ private drawSelectMenu;
316
+ /** Panel fill: the select's effective background, falling back to a
317
+ * near-black card on unstyled selects. */
318
+ private selectMenuPanelColor;
319
+ /** Route a tap while the modal is open: a row selects + closes; anything
320
+ * else just closes (dismiss on outside tap). */
321
+ private selectMenuHandleTouch;
211
322
  private keyboardOpen;
212
323
  private keyboardClose;
213
324
  private keyboardComputeBox;
@@ -229,6 +340,10 @@ export declare class PreviewUIRuntime {
229
340
  private markDirty;
230
341
  private scriptTreeNames;
231
342
  private normalizeScript;
343
+ /** Apply `re` to code segments only: skip '..'/".." literal contents, and
344
+ * inside `..` templates recurse into ${...} interpolations (their
345
+ * expressions are code; the literal text between them is not). */
346
+ private rewriteOutsideLiterals;
232
347
  /** Rewrite signal getter/setter syntax to plain variable reads/writes. See
233
348
  * normalizeScript for the lowering contract; this is the preview counterpart
234
349
  * of ui-callback-lowering.ts's rules 2 and 3. */