@typecad/ui 1.0.0-alpha.6 → 1.0.0-alpha.8

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 (86) hide show
  1. package/README.md +6 -0
  2. package/dist/engine-index.js +2 -2
  3. package/dist/preview/host-ui-runtime.d.ts +1 -0
  4. package/dist/preview/host-ui-runtime.js +56 -11
  5. package/dist/ui-engine/font-assets.d.ts +8 -0
  6. package/dist/ui-engine/font-assets.js +13 -0
  7. package/dist/ui-engine/layout-engine.js +19 -6
  8. package/dist/ui-engine/model.d.ts +1 -1
  9. package/dist/ui-engine/model.js +10 -4
  10. package/dist/ui-engine/runtime-header/antialiasing.js +52 -32
  11. package/dist/ui-engine/runtime-header/blend-bodies.js +4 -4
  12. package/dist/ui-engine/runtime-header/canvas-helpers.js +42 -69
  13. package/dist/ui-engine/runtime-header/canvas-scrollbar.js +22 -10
  14. package/dist/ui-engine/runtime-header/color-mono-refresh.js +10 -10
  15. package/dist/ui-engine/runtime-header/cuttlefish-gfx.d.ts +1 -0
  16. package/dist/ui-engine/runtime-header/cuttlefish-gfx.js +563 -0
  17. package/dist/ui-engine/runtime-header/dirty-scroll-mutators.js +26 -10
  18. package/dist/ui-engine/runtime-header/display-shim.js +8 -8
  19. package/dist/ui-engine/runtime-header/forward-decls.js +52 -10
  20. package/dist/ui-engine/runtime-header/image-drawing.js +154 -84
  21. package/dist/ui-engine/runtime-header/init-press-input.js +20 -5
  22. package/dist/ui-engine/runtime-header/keyboard.js +62 -18
  23. package/dist/ui-engine/runtime-header/node-decoration.js +8 -9
  24. package/dist/ui-engine/runtime-header/node-draw-body.d.ts +1 -0
  25. package/dist/ui-engine/runtime-header/node-draw-body.js +1402 -0
  26. package/dist/ui-engine/runtime-header/paint-order-coords.js +48 -18
  27. package/dist/ui-engine/runtime-header/paint-rects-repair.js +38 -17
  28. package/dist/ui-engine/runtime-header/scroll-physics.js +15 -18
  29. package/dist/ui-engine/runtime-header/state-bindings-nav.js +23 -13
  30. package/dist/ui-engine/runtime-header/structs.js +12 -10
  31. package/dist/ui-engine/runtime-header/text-rendering.js +132 -71
  32. package/dist/ui-engine/runtime-header/tick/bindings-phase.js +29 -10
  33. package/dist/ui-engine/runtime-header/tick/dirty-draw-phase.js +336 -749
  34. package/dist/ui-engine/runtime-header/tick/flush-phase.js +7 -3
  35. package/dist/ui-engine/runtime-header/tick/scroll-canvas-phase.js +19 -3
  36. package/dist/ui-engine/runtime-header/tick/transitions-phase.js +31 -24
  37. package/dist/ui-engine/runtime-header/touch-keyboard-fwd.js +46 -41
  38. package/dist/ui-engine/runtime-header/types-defines.js +23 -3
  39. package/dist/ui-engine/runtime-header.d.ts +10 -1
  40. package/dist/ui-engine/runtime-header.js +7 -1
  41. package/dist/ui-engine/transpile-ui.js +2 -2
  42. package/dist/ui-engine/ua-stylesheet.js +46 -3
  43. package/dist/ui-engine/ui-lowering.d.ts +1 -3
  44. package/dist/ui-engine/ui-lowering.js +18 -24
  45. package/dist/ui-engine/ui-registry.js +1 -6
  46. package/package.json +2 -2
  47. package/src/engine-index.ts +2 -2
  48. package/src/preview/host-ui-runtime.ts +56 -12
  49. package/src/ui-engine/font-assets.ts +13 -0
  50. package/src/ui-engine/layout-engine.ts +19 -6
  51. package/src/ui-engine/model.ts +10 -5
  52. package/src/ui-engine/runtime-header/antialiasing.ts +52 -32
  53. package/src/ui-engine/runtime-header/blend-bodies.ts +4 -4
  54. package/src/ui-engine/runtime-header/canvas-helpers.ts +42 -69
  55. package/src/ui-engine/runtime-header/canvas-scrollbar.ts +22 -10
  56. package/src/ui-engine/runtime-header/color-mono-refresh.ts +10 -10
  57. package/src/ui-engine/runtime-header/cuttlefish-gfx.ts +566 -0
  58. package/src/ui-engine/runtime-header/dirty-scroll-mutators.ts +26 -10
  59. package/src/ui-engine/runtime-header/display-shim.ts +8 -8
  60. package/src/ui-engine/runtime-header/forward-decls.ts +52 -10
  61. package/src/ui-engine/runtime-header/image-drawing.ts +154 -84
  62. package/src/ui-engine/runtime-header/init-press-input.ts +20 -5
  63. package/src/ui-engine/runtime-header/keyboard.ts +62 -18
  64. package/src/ui-engine/runtime-header/node-decoration.ts +8 -9
  65. package/src/ui-engine/runtime-header/node-draw-body.ts +1402 -0
  66. package/src/ui-engine/runtime-header/paint-order-coords.ts +48 -18
  67. package/src/ui-engine/runtime-header/paint-rects-repair.ts +38 -17
  68. package/src/ui-engine/runtime-header/scroll-physics.ts +15 -18
  69. package/src/ui-engine/runtime-header/state-bindings-nav.ts +23 -13
  70. package/src/ui-engine/runtime-header/structs.ts +12 -10
  71. package/src/ui-engine/runtime-header/text-rendering.ts +132 -71
  72. package/src/ui-engine/runtime-header/tick/bindings-phase.ts +29 -10
  73. package/src/ui-engine/runtime-header/tick/dirty-draw-phase.ts +336 -749
  74. package/src/ui-engine/runtime-header/tick/flush-phase.ts +7 -3
  75. package/src/ui-engine/runtime-header/tick/scroll-canvas-phase.ts +19 -3
  76. package/src/ui-engine/runtime-header/tick/transitions-phase.ts +31 -24
  77. package/src/ui-engine/runtime-header/touch-keyboard-fwd.ts +46 -41
  78. package/src/ui-engine/runtime-header/types-defines.ts +23 -3
  79. package/src/ui-engine/runtime-header.ts +17 -1
  80. package/src/ui-engine/transpile-ui.ts +2 -2
  81. package/src/ui-engine/ua-stylesheet.ts +46 -3
  82. package/src/ui-engine/ui-lowering.ts +19 -26
  83. package/src/ui-engine/ui-registry.ts +1 -7
  84. package/dist/ui-engine/scroll-memory-diagnostics.d.ts +0 -16
  85. package/dist/ui-engine/scroll-memory-diagnostics.js +0 -58
  86. package/src/ui-engine/scroll-memory-diagnostics.ts +0 -79
@@ -49,7 +49,7 @@ static inline void ui_kb_insert(char c) {
49
49
  if (__ui_kb_target >= 0) {
50
50
  strncpy(__ui_nodes[__ui_kb_target].textBuffer, __ui_kb_buffer, UI_TEXT_BUF);
51
51
  __ui_nodes[__ui_kb_target].textBuffer[UI_TEXT_BUF] = 0;
52
- ui_mark_dirty((uint16_t)__ui_kb_target);
52
+ ui_mark_dirty(static_cast<uint16_t>(__ui_kb_target));
53
53
  }
54
54
  #endif
55
55
  }
@@ -62,7 +62,7 @@ static inline void ui_kb_delete() {
62
62
  if (__ui_kb_target >= 0) {
63
63
  strncpy(__ui_nodes[__ui_kb_target].textBuffer, __ui_kb_buffer, UI_TEXT_BUF);
64
64
  __ui_nodes[__ui_kb_target].textBuffer[UI_TEXT_BUF] = 0;
65
- ui_mark_dirty((uint16_t)__ui_kb_target);
65
+ ui_mark_dirty(static_cast<uint16_t>(__ui_kb_target));
66
66
  }
67
67
  #endif
68
68
  }
@@ -92,7 +92,7 @@ static inline void ui_kb_open(uint16_t nodeIdx, uint8_t inputPosition) {
92
92
  __ui_kb_buffer[UI_TEXT_BUF] = 0;
93
93
  __ui_kb_len = strlen(__ui_kb_buffer);
94
94
  uint16_t ml = __ui_nodes[nodeIdx].maxlen;
95
- __ui_kb_maxlen = (ml > 0 && ml <= UI_TEXT_BUF) ? (uint8_t)ml : UI_TEXT_BUF;
95
+ __ui_kb_maxlen = (ml > 0 && ml <= UI_TEXT_BUF) ? static_cast<uint8_t>(ml) : UI_TEXT_BUF;
96
96
  __ui_kb_shift = 0;
97
97
  __ui_kb_bs_held = 0;
98
98
  // Load the key set via the dispatch table.
@@ -113,7 +113,7 @@ static inline void ui_kb_open(uint16_t nodeIdx, uint8_t inputPosition) {
113
113
  // keystroke. (The full-screen-flash concern above doesn't apply — there's no
114
114
  // opaque overlay being skipped.) Seed the blink phase so the caret is ON for
115
115
  // the first ~530ms (bit 0x20 set → visible), so focus feels immediate.
116
- if (__ui_kb_target >= 0) ui_mark_dirty((uint16_t)__ui_kb_target);
116
+ if (__ui_kb_target >= 0) ui_mark_dirty(static_cast<uint16_t>(__ui_kb_target));
117
117
  __ui_kb_blink = 0x20;
118
118
  #endif
119
119
  }
@@ -140,7 +140,7 @@ static inline void ui_kb_close() {
140
140
  int16_t screenRoot = -1;
141
141
  for (uint16_t i = 0; i < __ui_node_count; i++) {
142
142
  if (__ui_nodes[i].parent == UI_NO_PARENT && __ui_nodes[i].screenId == __ui_active_screen) {
143
- screenRoot = (int16_t)i;
143
+ screenRoot = static_cast<int16_t>(i);
144
144
  break;
145
145
  }
146
146
  }
@@ -156,7 +156,7 @@ static inline void ui_kb_close() {
156
156
  // scroll clipping — safe here since these nodes are bounded in size, unlike
157
157
  // the screen root.
158
158
  for (uint16_t i = 0; i < __ui_node_count; i++) {
159
- if ((int16_t)i == screenRoot) continue;
159
+ if (static_cast<int16_t>(i) == screenRoot) continue;
160
160
  UIRect r;
161
161
  ui_node_current_paint_rect(i, &r);
162
162
  if (r.w > 0 && r.h > 0 &&
@@ -173,8 +173,8 @@ static inline void ui_kb_key_rect(uint8_t idx, UIRect* out) {
173
173
  uint8_t col = idx % __ui_kb_cols;
174
174
  uint8_t row = idx / __ui_kb_cols;
175
175
  int16_t keysH = __ui_kb_box.h - UI_KB_TEXT_H; // key area height (below text row)
176
- out->x = __ui_kb_box.x + (int16_t)col * __ui_kb_box.w / __ui_kb_cols;
177
- out->y = __ui_kb_box.y + UI_KB_TEXT_H + (int16_t)row * keysH / __ui_kb_rows;
176
+ out->x = __ui_kb_box.x + static_cast<int16_t>(col) * __ui_kb_box.w / __ui_kb_cols;
177
+ out->y = __ui_kb_box.y + UI_KB_TEXT_H + static_cast<int16_t>(row) * keysH / __ui_kb_rows;
178
178
  out->w = __ui_kb_box.w / __ui_kb_cols;
179
179
  out->h = keysH / __ui_kb_rows;
180
180
  }
@@ -192,8 +192,8 @@ static inline void ui_kb_handle_touch(int16_t tx, int16_t ty) {
192
192
  UIRect r;
193
193
  ui_kb_key_rect(i, &r);
194
194
  if (tx >= r.x && tx < r.x + r.w && ty >= r.y && ty < r.y + r.h) {
195
- __ui_kb_pressed_key = (int8_t)i; // remember for release
196
- __ui_kb_repaint_key = (int8_t)i;
195
+ __ui_kb_pressed_key = static_cast<int8_t>(i); // remember for release
196
+ __ui_kb_repaint_key = static_cast<int8_t>(i);
197
197
  __ui_kb_dirty = 2; // targeted: redraw just this key's highlight
198
198
  // Backspace starts deleting immediately + arms auto-repeat.
199
199
  if (k.special == 2) {
@@ -273,7 +273,7 @@ static inline void ui_kb_draw_key(uint8_t i) {
273
273
  UI_COLOR_T border = ks.borderColor;
274
274
  // Shift-active highlight: brighten the shift key's background — but only
275
275
  // when not pressed, so the press inversion stays high-contrast.
276
- if (k.special == 1 && __ui_kb_shift && (int8_t)i != __ui_kb_pressed_key) {
276
+ if (k.special == 1 && __ui_kb_shift && static_cast<int8_t>(i) != __ui_kb_pressed_key) {
277
277
  #if UI_COLOR_DEPTH == 888
278
278
  bg = 0xBDEFFF;
279
279
  #else
@@ -281,7 +281,7 @@ static inline void ui_kb_draw_key(uint8_t i) {
281
281
  #endif
282
282
  }
283
283
  // Pressed key: invert colors for clear tap feedback.
284
- if ((int8_t)i == __ui_kb_pressed_key) { UI_COLOR_T t = bg; bg = fg; fg = t; }
284
+ if (static_cast<int8_t>(i) == __ui_kb_pressed_key) { UI_COLOR_T t = bg; bg = fg; fg = t; }
285
285
  ui_display_fill_rect(r.x + 1, r.y + 1, r.w - 2, r.h - 2, bg);
286
286
  ui_display_draw_rect(r.x + 1, r.y + 1, r.w - 2, r.h - 2, border);
287
287
  ui_display_set_text_color(fg, bg);
@@ -295,14 +295,14 @@ static inline void ui_kb_draw_key(uint8_t i) {
295
295
  case 3: labelStr = "OK"; break;
296
296
  case 4: labelStr = __ui_kb_cols <= 4 ? "ABC" : "123"; break;
297
297
  default:
298
- single[0] = (__ui_kb_shift && k.ch >= 'a' && k.ch <= 'z') ? (char)(k.ch - 32) : k.ch;
298
+ single[0] = (__ui_kb_shift && k.ch >= 'a' && k.ch <= 'z') ? static_cast<char>(k.ch - 32) : k.ch;
299
299
  single[1] = 0;
300
300
  labelStr = single;
301
301
  break;
302
302
  }
303
303
  // Center: textW = len * 6px, textH = 8px. Position inside the key rect.
304
304
  uint8_t len = strlen(labelStr);
305
- int16_t textW = (int16_t)len * 6;
305
+ int16_t textW = static_cast<int16_t>(len) * 6;
306
306
  int16_t textH = 8;
307
307
  int16_t cx = r.x + (r.w - textW) / 2;
308
308
  int16_t cy = r.y + (r.h - textH) / 2;
@@ -328,15 +328,59 @@ static inline void ui_kb_draw_text_row() {
328
328
  }
329
329
 
330
330
  // Draw the full keyboard overlay (background + text row + all keys).
331
+ // Renders into a dedicated offscreen canvas first, then pushes in a single
332
+ // SPI transaction — avoids the per-key/per-rect display writes that show up
333
+ // as visible row-by-row painting on SPI TFTs.
334
+ // (__ui_kb_canvas is forward-declared in the touch-keyboard-fwd slice.)
331
335
  static inline void ui_kb_draw() {
332
- // Opaque background over the keyboard box.
333
- ui_display_fill_rect(__ui_kb_box.x, __ui_kb_box.y, __ui_kb_box.w, __ui_kb_box.h, __ui_kb_bg);
336
+ int16_t kw = __ui_kb_box.w;
337
+ int16_t kh = __ui_kb_box.h;
338
+ if (kw <= 0 || kh <= 0) return;
339
+ // (Re)allocate the keyboard canvas to exact size (see repair-canvas comment
340
+ // — stride mismatch corrupts the push when reusing a differently-sized canvas).
341
+ // ui_create_canvas_best prefers PSRAM when available (a full-width keyboard
342
+ // canvas can be ~30KB, too big for no-PSRAM internal SRAM) and falls back to
343
+ // SRAM — same policy as the list/scroll viewport canvases.
344
+ if (!__ui_kb_canvas || !display_canvasBuffer(__ui_kb_canvas) ||
345
+ display_canvasWidth(__ui_kb_canvas) != kw ||
346
+ display_canvasHeight(__ui_kb_canvas) != kh) {
347
+ display_deleteCanvas(__ui_kb_canvas);
348
+ __ui_kb_canvas = ui_create_canvas_best(kw, kh);
349
+ }
350
+ if (!__ui_kb_canvas || !display_canvasBuffer(__ui_kb_canvas)) {
351
+ // Canvas alloc failed — fall back to direct draw (slow but correct).
352
+ ui_display_fill_rect(__ui_kb_box.x, __ui_kb_box.y, kw, kh, __ui_kb_bg);
353
+ ui_kb_draw_text_row();
354
+ for (uint8_t i = 0; i < __ui_kb_keyCount; i++) {
355
+ if (__ui_kb_keys[i].special == 255) continue;
356
+ ui_kb_draw_key(i);
357
+ }
358
+ return;
359
+ }
360
+ // Redirect drawing into the canvas. All ui_display_* calls below go to RAM.
361
+ CuttlefishDisplayTarget* __kb_prev_target = ui_display_get_target();
362
+ ui_display_set_target(__ui_kb_canvas);
363
+ // Opaque background over the keyboard box (canvas-local 0,0).
364
+ ui_display_fill_rect(0, 0, kw, kh, __ui_kb_bg);
365
+ // Text row + keys: temporarily shift box origin to canvas-local so the
366
+ // existing draw_text_row / draw_key functions compute coords at (0,0).
367
+ int16_t saveBoxX = __ui_kb_box.x;
368
+ int16_t saveBoxY = __ui_kb_box.y;
369
+ __ui_kb_box.x = 0;
370
+ __ui_kb_box.y = 0;
334
371
  ui_kb_draw_text_row();
335
- // Keys: one rect per key, label centered.
336
372
  for (uint8_t i = 0; i < __ui_kb_keyCount; i++) {
337
- if (__ui_kb_keys[i].special == 255) continue; // padding cell, skip
373
+ if (__ui_kb_keys[i].special == 255) continue;
338
374
  ui_kb_draw_key(i);
339
375
  }
376
+ __ui_kb_box.x = saveBoxX;
377
+ __ui_kb_box.y = saveBoxY;
378
+ // Restore display target and push the canvas in one transaction.
379
+ ui_display_set_target(__kb_prev_target);
380
+ display_startWrite();
381
+ display_setAddrWindow(saveBoxX, saveBoxY, kw, kh);
382
+ display_writePixels(display_canvasBuffer(__ui_kb_canvas), static_cast<uint32_t>(kw) * kh);
383
+ display_endWrite();
340
384
  }
341
385
  `;
342
386
  }
@@ -18,19 +18,19 @@ static inline void ui_draw_gradient_fill(uint16_t i, int16_t drawY) {
18
18
  uint8_t dir = __ui_nodes[i].gradientEnabled; // 1=vertical, 2=horizontal
19
19
  if (dir == 1) {
20
20
  // Vertical: top=c1, bottom=c2. Draw row by row.
21
- int16_t yStart = (int16_t)(clipY - by);
22
- int16_t yEnd = (int16_t)(clipY + clipH - by);
21
+ int16_t yStart = static_cast<int16_t>(clipY - by);
22
+ int16_t yEnd = static_cast<int16_t>(clipY + clipH - by);
23
23
  for (int16_t y = yStart; y < yEnd; y++) {
24
- uint8_t op = (uint8_t)((uint16_t)y * 100 / (bh > 1 ? bh - 1 : 1));
24
+ uint8_t op = static_cast<uint8_t>(static_cast<uint16_t>(y) * 100 / (bh > 1 ? bh - 1 : 1));
25
25
  uint32_t col = ui_blend(c1, c2, op);
26
26
  ui_display_draw_fast_hline(clipX, by + y, clipW, col);
27
27
  }
28
28
  } else {
29
29
  // Horizontal: left=c1, right=c2. Draw column by column.
30
- int16_t xStart = (int16_t)(clipX - bx);
31
- int16_t xEnd = (int16_t)(clipX + clipW - bx);
30
+ int16_t xStart = static_cast<int16_t>(clipX - bx);
31
+ int16_t xEnd = static_cast<int16_t>(clipX + clipW - bx);
32
32
  for (int16_t x = xStart; x < xEnd; x++) {
33
- uint8_t op = (uint8_t)((uint16_t)x * 100 / (bw > 1 ? bw - 1 : 1));
33
+ uint8_t op = static_cast<uint8_t>(static_cast<uint16_t>(x) * 100 / (bw > 1 ? bw - 1 : 1));
34
34
  uint32_t col = ui_blend(c1, c2, op);
35
35
  ui_display_draw_fast_vline(bx + x, clipY, clipH, col);
36
36
  }
@@ -79,7 +79,7 @@ static inline void ui_draw_shadow(uint16_t i, int16_t drawY, uint8_t insetOnly)
79
79
  }
80
80
 
81
81
  for (int8_t pass = blur; pass >= 1; pass--) {
82
- uint8_t opacity = (uint8_t)((uint16_t)baseAlpha / (pass + 1));
82
+ uint8_t opacity = static_cast<uint8_t>(static_cast<uint16_t>(baseAlpha) / (pass + 1));
83
83
  uint32_t col = ui_blend(shadowCol, inset ? (__ui_nodes[i].hasBg ? __ui_nodes[i].bg : clearCol) : clearCol, opacity);
84
84
  if (inset) {
85
85
  // Inset: draw inside the element, shrinking inward by pass.
@@ -104,7 +104,7 @@ static inline void ui_draw_shadow(uint16_t i, int16_t drawY, uint8_t insetOnly)
104
104
  int16_t sw = bw + 2 * pass;
105
105
  int16_t sh_ = bh + 2 * pass;
106
106
  if (radius > 0) {
107
- uint8_t r = radius + (uint8_t)pass;
107
+ uint8_t r = radius + static_cast<uint8_t>(pass);
108
108
  if (r > sw / 2) r = sw / 2;
109
109
  if (r > sh_ / 2) r = sh_ / 2;
110
110
  ui_display_fill_round_rect(sx, sy, sw, sh_, r, col);
@@ -176,7 +176,6 @@ static inline void ui_draw_node_border(uint16_t i, int16_t drawX, int16_t drawY,
176
176
  if (__ui_nodes[i].hasPerSideBorder) {
177
177
  int16_t w = __ui_nodes[i].box.w;
178
178
  int16_t h = __ui_nodes[i].box.h;
179
- uint8_t st = __ui_nodes[i].borderStyle;
180
179
  // Top edge
181
180
  if (__ui_nodes[i].borderTopWidth > 0) {
182
181
  ui_display_fill_rect(drawX, drawY, w, __ui_nodes[i].borderTopWidth, color);
@@ -0,0 +1 @@
1
+ export declare function emitNodeDrawBody(): string;