@almadar/std 3.2.1 → 3.2.2

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 (262) hide show
  1. package/behaviors/exports/atoms/std-async.orb +41 -24
  2. package/behaviors/exports/atoms/std-browse.orb +12 -5
  3. package/behaviors/exports/atoms/std-cache-aside.orb +256 -42
  4. package/behaviors/exports/atoms/std-circuit-breaker.orb +577 -97
  5. package/behaviors/exports/atoms/std-collision.orb +278 -206
  6. package/behaviors/exports/atoms/std-combat-log.orb +6 -1
  7. package/behaviors/exports/atoms/std-combat.orb +6 -1
  8. package/behaviors/exports/atoms/std-confirmation.orb +212 -7
  9. package/behaviors/exports/atoms/std-dialogue-box.orb +6 -1
  10. package/behaviors/exports/atoms/std-display.orb +166 -21
  11. package/behaviors/exports/atoms/std-drawer.orb +208 -104
  12. package/behaviors/exports/atoms/std-filter.orb +211 -18
  13. package/behaviors/exports/atoms/std-game-audio.orb +6 -1
  14. package/behaviors/exports/atoms/std-game-canvas2d.orb +6 -1
  15. package/behaviors/exports/atoms/std-game-canvas3d.orb +6 -1
  16. package/behaviors/exports/atoms/std-game-hud.orb +6 -1
  17. package/behaviors/exports/atoms/std-game-menu.orb +6 -1
  18. package/behaviors/exports/atoms/std-game-over-screen.orb +6 -1
  19. package/behaviors/exports/atoms/std-gameflow.orb +100 -5
  20. package/behaviors/exports/atoms/std-input.orb +142 -137
  21. package/behaviors/exports/atoms/std-inventory-panel.orb +6 -1
  22. package/behaviors/exports/atoms/std-isometric-canvas.orb +6 -1
  23. package/behaviors/exports/atoms/std-loading.orb +27 -76
  24. package/behaviors/exports/atoms/std-modal.orb +177 -93
  25. package/behaviors/exports/atoms/std-movement.orb +401 -31
  26. package/behaviors/exports/atoms/std-notification.orb +46 -95
  27. package/behaviors/exports/atoms/std-overworld.orb +44 -16
  28. package/behaviors/exports/atoms/std-pagination.orb +26 -89
  29. package/behaviors/exports/atoms/std-physics2d.orb +6 -1
  30. package/behaviors/exports/atoms/std-platformer-canvas.orb +6 -1
  31. package/behaviors/exports/atoms/std-quest.orb +309 -34
  32. package/behaviors/exports/atoms/std-rate-limiter.orb +410 -157
  33. package/behaviors/exports/atoms/std-score-board.orb +6 -1
  34. package/behaviors/exports/atoms/std-score.orb +211 -11
  35. package/behaviors/exports/atoms/std-search.orb +28 -27
  36. package/behaviors/exports/atoms/std-selection.orb +160 -121
  37. package/behaviors/exports/atoms/std-simulation-canvas.orb +6 -1
  38. package/behaviors/exports/atoms/std-sort.orb +134 -24
  39. package/behaviors/exports/atoms/std-sprite.orb +6 -1
  40. package/behaviors/exports/atoms/std-tabs.orb +25 -15
  41. package/behaviors/exports/atoms/std-timer.orb +483 -91
  42. package/behaviors/exports/atoms/std-undo.orb +211 -81
  43. package/behaviors/exports/atoms/std-wizard.orb +31 -34
  44. package/behaviors/exports/molecules/std-builder-game.orb +6 -1
  45. package/behaviors/exports/molecules/std-cart.orb +6 -1
  46. package/behaviors/exports/molecules/std-classifier-game.orb +6 -1
  47. package/behaviors/exports/molecules/std-debugger-game.orb +6 -1
  48. package/behaviors/exports/molecules/std-detail.orb +12 -5
  49. package/behaviors/exports/molecules/std-event-handler-game.orb +6 -1
  50. package/behaviors/exports/molecules/std-geospatial.orb +28 -9
  51. package/behaviors/exports/molecules/std-inventory.orb +28 -9
  52. package/behaviors/exports/molecules/std-list.orb +392 -5
  53. package/behaviors/exports/molecules/std-messaging.orb +12 -5
  54. package/behaviors/exports/molecules/std-negotiator-game.orb +6 -1
  55. package/behaviors/exports/molecules/std-platformer-game.orb +40 -1
  56. package/behaviors/exports/molecules/std-puzzle-game.orb +26 -1
  57. package/behaviors/exports/molecules/std-sequencer-game.orb +6 -1
  58. package/behaviors/exports/molecules/std-simulator-game.orb +6 -1
  59. package/behaviors/exports/molecules/std-turn-based-battle.orb +40 -1
  60. package/behaviors/exports/organisms/std-api-gateway.orb +1145 -403
  61. package/behaviors/exports/organisms/std-arcade-game.orb +94 -4
  62. package/behaviors/exports/organisms/std-booking-system.orb +2165 -1605
  63. package/behaviors/exports/organisms/std-cicd-pipeline.orb +581 -47
  64. package/behaviors/exports/organisms/std-cms.orb +1713 -947
  65. package/behaviors/exports/organisms/std-coding-academy.orb +180 -380
  66. package/behaviors/exports/organisms/std-crm.orb +1669 -1153
  67. package/behaviors/exports/organisms/std-devops-dashboard.orb +1430 -378
  68. package/behaviors/exports/organisms/std-ecommerce.orb +2361 -1601
  69. package/behaviors/exports/organisms/std-finance-tracker.orb +622 -438
  70. package/behaviors/exports/organisms/std-healthcare.orb +1687 -1125
  71. package/behaviors/exports/organisms/std-helpdesk.orb +626 -407
  72. package/behaviors/exports/organisms/std-hr-portal.orb +1309 -714
  73. package/behaviors/exports/organisms/std-iot-dashboard.orb +1247 -335
  74. package/behaviors/exports/organisms/std-lms.orb +658 -362
  75. package/behaviors/exports/organisms/std-platformer-app.orb +56 -8
  76. package/behaviors/exports/organisms/std-project-manager.orb +1697 -1183
  77. package/behaviors/exports/organisms/std-puzzle-app.orb +20 -0
  78. package/behaviors/exports/organisms/std-realtime-chat.orb +552 -28
  79. package/behaviors/exports/organisms/std-rpg-game.orb +397 -56
  80. package/behaviors/exports/organisms/std-social-feed.orb +12 -8
  81. package/behaviors/exports/organisms/std-stem-lab.orb +175 -290
  82. package/behaviors/exports/organisms/std-strategy-game.orb +252 -395
  83. package/behaviors/exports/organisms/std-trading-dashboard.orb +718 -524
  84. package/behaviors/exports/validation-report.json +252 -252
  85. package/behaviors/exports/verify-results.json +13 -0
  86. package/dist/behaviors/exports/atoms/std-async.orb +41 -24
  87. package/dist/behaviors/exports/atoms/std-browse.orb +12 -5
  88. package/dist/behaviors/exports/atoms/std-cache-aside.orb +256 -42
  89. package/dist/behaviors/exports/atoms/std-circuit-breaker.orb +577 -97
  90. package/dist/behaviors/exports/atoms/std-collision.orb +278 -206
  91. package/dist/behaviors/exports/atoms/std-combat-log.orb +6 -1
  92. package/dist/behaviors/exports/atoms/std-combat.orb +6 -1
  93. package/dist/behaviors/exports/atoms/std-confirmation.orb +212 -7
  94. package/dist/behaviors/exports/atoms/std-dialogue-box.orb +6 -1
  95. package/dist/behaviors/exports/atoms/std-display.orb +166 -21
  96. package/dist/behaviors/exports/atoms/std-drawer.orb +208 -104
  97. package/dist/behaviors/exports/atoms/std-filter.orb +211 -18
  98. package/dist/behaviors/exports/atoms/std-game-audio.orb +6 -1
  99. package/dist/behaviors/exports/atoms/std-game-canvas2d.orb +6 -1
  100. package/dist/behaviors/exports/atoms/std-game-canvas3d.orb +6 -1
  101. package/dist/behaviors/exports/atoms/std-game-hud.orb +6 -1
  102. package/dist/behaviors/exports/atoms/std-game-menu.orb +6 -1
  103. package/dist/behaviors/exports/atoms/std-game-over-screen.orb +6 -1
  104. package/dist/behaviors/exports/atoms/std-gameflow.orb +100 -5
  105. package/dist/behaviors/exports/atoms/std-input.orb +142 -137
  106. package/dist/behaviors/exports/atoms/std-inventory-panel.orb +6 -1
  107. package/dist/behaviors/exports/atoms/std-isometric-canvas.orb +6 -1
  108. package/dist/behaviors/exports/atoms/std-loading.orb +27 -76
  109. package/dist/behaviors/exports/atoms/std-modal.orb +177 -93
  110. package/dist/behaviors/exports/atoms/std-movement.orb +401 -31
  111. package/dist/behaviors/exports/atoms/std-notification.orb +46 -95
  112. package/dist/behaviors/exports/atoms/std-overworld.orb +44 -16
  113. package/dist/behaviors/exports/atoms/std-pagination.orb +26 -89
  114. package/dist/behaviors/exports/atoms/std-physics2d.orb +6 -1
  115. package/dist/behaviors/exports/atoms/std-platformer-canvas.orb +6 -1
  116. package/dist/behaviors/exports/atoms/std-quest.orb +309 -34
  117. package/dist/behaviors/exports/atoms/std-rate-limiter.orb +410 -157
  118. package/dist/behaviors/exports/atoms/std-score-board.orb +6 -1
  119. package/dist/behaviors/exports/atoms/std-score.orb +211 -11
  120. package/dist/behaviors/exports/atoms/std-search.orb +28 -27
  121. package/dist/behaviors/exports/atoms/std-selection.orb +160 -121
  122. package/dist/behaviors/exports/atoms/std-simulation-canvas.orb +6 -1
  123. package/dist/behaviors/exports/atoms/std-sort.orb +134 -24
  124. package/dist/behaviors/exports/atoms/std-sprite.orb +6 -1
  125. package/dist/behaviors/exports/atoms/std-tabs.orb +25 -15
  126. package/dist/behaviors/exports/atoms/std-timer.orb +483 -91
  127. package/dist/behaviors/exports/atoms/std-undo.orb +211 -81
  128. package/dist/behaviors/exports/atoms/std-wizard.orb +31 -34
  129. package/dist/behaviors/exports/molecules/std-builder-game.orb +6 -1
  130. package/dist/behaviors/exports/molecules/std-cart.orb +6 -1
  131. package/dist/behaviors/exports/molecules/std-classifier-game.orb +6 -1
  132. package/dist/behaviors/exports/molecules/std-debugger-game.orb +6 -1
  133. package/dist/behaviors/exports/molecules/std-detail.orb +12 -5
  134. package/dist/behaviors/exports/molecules/std-event-handler-game.orb +6 -1
  135. package/dist/behaviors/exports/molecules/std-geospatial.orb +28 -9
  136. package/dist/behaviors/exports/molecules/std-inventory.orb +28 -9
  137. package/dist/behaviors/exports/molecules/std-list.orb +392 -5
  138. package/dist/behaviors/exports/molecules/std-messaging.orb +12 -5
  139. package/dist/behaviors/exports/molecules/std-negotiator-game.orb +6 -1
  140. package/dist/behaviors/exports/molecules/std-platformer-game.orb +40 -1
  141. package/dist/behaviors/exports/molecules/std-puzzle-game.orb +26 -1
  142. package/dist/behaviors/exports/molecules/std-sequencer-game.orb +6 -1
  143. package/dist/behaviors/exports/molecules/std-simulator-game.orb +6 -1
  144. package/dist/behaviors/exports/molecules/std-turn-based-battle.orb +40 -1
  145. package/dist/behaviors/exports/organisms/std-api-gateway.orb +1145 -403
  146. package/dist/behaviors/exports/organisms/std-arcade-game.orb +94 -4
  147. package/dist/behaviors/exports/organisms/std-booking-system.orb +2165 -1605
  148. package/dist/behaviors/exports/organisms/std-cicd-pipeline.orb +581 -47
  149. package/dist/behaviors/exports/organisms/std-cms.orb +1713 -947
  150. package/dist/behaviors/exports/organisms/std-coding-academy.orb +180 -380
  151. package/dist/behaviors/exports/organisms/std-crm.orb +1669 -1153
  152. package/dist/behaviors/exports/organisms/std-devops-dashboard.orb +1430 -378
  153. package/dist/behaviors/exports/organisms/std-ecommerce.orb +2361 -1601
  154. package/dist/behaviors/exports/organisms/std-finance-tracker.orb +622 -438
  155. package/dist/behaviors/exports/organisms/std-healthcare.orb +1687 -1125
  156. package/dist/behaviors/exports/organisms/std-helpdesk.orb +626 -407
  157. package/dist/behaviors/exports/organisms/std-hr-portal.orb +1309 -714
  158. package/dist/behaviors/exports/organisms/std-iot-dashboard.orb +1247 -335
  159. package/dist/behaviors/exports/organisms/std-lms.orb +658 -362
  160. package/dist/behaviors/exports/organisms/std-platformer-app.orb +56 -8
  161. package/dist/behaviors/exports/organisms/std-project-manager.orb +1697 -1183
  162. package/dist/behaviors/exports/organisms/std-puzzle-app.orb +20 -0
  163. package/dist/behaviors/exports/organisms/std-realtime-chat.orb +552 -28
  164. package/dist/behaviors/exports/organisms/std-rpg-game.orb +397 -56
  165. package/dist/behaviors/exports/organisms/std-social-feed.orb +12 -8
  166. package/dist/behaviors/exports/organisms/std-stem-lab.orb +175 -290
  167. package/dist/behaviors/exports/organisms/std-strategy-game.orb +252 -395
  168. package/dist/behaviors/exports/organisms/std-trading-dashboard.orb +718 -524
  169. package/dist/behaviors/exports/validation-report.json +252 -252
  170. package/dist/behaviors/exports/verify-results.json +13 -0
  171. package/dist/behaviors/functions/index.js +715 -593
  172. package/dist/behaviors/functions/index.js.map +1 -1
  173. package/dist/behaviors/index.js +715 -593
  174. package/dist/behaviors/index.js.map +1 -1
  175. package/dist/exports/atoms/std-async.orb +41 -24
  176. package/dist/exports/atoms/std-browse.orb +12 -5
  177. package/dist/exports/atoms/std-cache-aside.orb +256 -42
  178. package/dist/exports/atoms/std-circuit-breaker.orb +577 -97
  179. package/dist/exports/atoms/std-collision.orb +278 -206
  180. package/dist/exports/atoms/std-combat-log.orb +6 -1
  181. package/dist/exports/atoms/std-combat.orb +6 -1
  182. package/dist/exports/atoms/std-confirmation.orb +212 -7
  183. package/dist/exports/atoms/std-dialogue-box.orb +6 -1
  184. package/dist/exports/atoms/std-display.orb +166 -21
  185. package/dist/exports/atoms/std-drawer.orb +208 -104
  186. package/dist/exports/atoms/std-filter.orb +211 -18
  187. package/dist/exports/atoms/std-game-audio.orb +6 -1
  188. package/dist/exports/atoms/std-game-canvas2d.orb +6 -1
  189. package/dist/exports/atoms/std-game-canvas3d.orb +6 -1
  190. package/dist/exports/atoms/std-game-hud.orb +6 -1
  191. package/dist/exports/atoms/std-game-menu.orb +6 -1
  192. package/dist/exports/atoms/std-game-over-screen.orb +6 -1
  193. package/dist/exports/atoms/std-gameflow.orb +100 -5
  194. package/dist/exports/atoms/std-input.orb +142 -137
  195. package/dist/exports/atoms/std-inventory-panel.orb +6 -1
  196. package/dist/exports/atoms/std-isometric-canvas.orb +6 -1
  197. package/dist/exports/atoms/std-loading.orb +27 -76
  198. package/dist/exports/atoms/std-modal.orb +177 -93
  199. package/dist/exports/atoms/std-movement.orb +401 -31
  200. package/dist/exports/atoms/std-notification.orb +46 -95
  201. package/dist/exports/atoms/std-overworld.orb +44 -16
  202. package/dist/exports/atoms/std-pagination.orb +26 -89
  203. package/dist/exports/atoms/std-physics2d.orb +6 -1
  204. package/dist/exports/atoms/std-platformer-canvas.orb +6 -1
  205. package/dist/exports/atoms/std-quest.orb +309 -34
  206. package/dist/exports/atoms/std-rate-limiter.orb +410 -157
  207. package/dist/exports/atoms/std-score-board.orb +6 -1
  208. package/dist/exports/atoms/std-score.orb +211 -11
  209. package/dist/exports/atoms/std-search.orb +28 -27
  210. package/dist/exports/atoms/std-selection.orb +160 -121
  211. package/dist/exports/atoms/std-simulation-canvas.orb +6 -1
  212. package/dist/exports/atoms/std-sort.orb +134 -24
  213. package/dist/exports/atoms/std-sprite.orb +6 -1
  214. package/dist/exports/atoms/std-tabs.orb +25 -15
  215. package/dist/exports/atoms/std-timer.orb +483 -91
  216. package/dist/exports/atoms/std-undo.orb +211 -81
  217. package/dist/exports/atoms/std-wizard.orb +31 -34
  218. package/dist/exports/molecules/std-builder-game.orb +6 -1
  219. package/dist/exports/molecules/std-cart.orb +6 -1
  220. package/dist/exports/molecules/std-classifier-game.orb +6 -1
  221. package/dist/exports/molecules/std-debugger-game.orb +6 -1
  222. package/dist/exports/molecules/std-detail.orb +12 -5
  223. package/dist/exports/molecules/std-event-handler-game.orb +6 -1
  224. package/dist/exports/molecules/std-geospatial.orb +28 -9
  225. package/dist/exports/molecules/std-inventory.orb +28 -9
  226. package/dist/exports/molecules/std-list.orb +392 -5
  227. package/dist/exports/molecules/std-messaging.orb +12 -5
  228. package/dist/exports/molecules/std-negotiator-game.orb +6 -1
  229. package/dist/exports/molecules/std-platformer-game.orb +40 -1
  230. package/dist/exports/molecules/std-puzzle-game.orb +26 -1
  231. package/dist/exports/molecules/std-sequencer-game.orb +6 -1
  232. package/dist/exports/molecules/std-simulator-game.orb +6 -1
  233. package/dist/exports/molecules/std-turn-based-battle.orb +40 -1
  234. package/dist/exports/organisms/std-api-gateway.orb +1145 -403
  235. package/dist/exports/organisms/std-arcade-game.orb +94 -4
  236. package/dist/exports/organisms/std-booking-system.orb +2165 -1605
  237. package/dist/exports/organisms/std-cicd-pipeline.orb +581 -47
  238. package/dist/exports/organisms/std-cms.orb +1713 -947
  239. package/dist/exports/organisms/std-coding-academy.orb +180 -380
  240. package/dist/exports/organisms/std-crm.orb +1669 -1153
  241. package/dist/exports/organisms/std-devops-dashboard.orb +1430 -378
  242. package/dist/exports/organisms/std-ecommerce.orb +2361 -1601
  243. package/dist/exports/organisms/std-finance-tracker.orb +622 -438
  244. package/dist/exports/organisms/std-healthcare.orb +1687 -1125
  245. package/dist/exports/organisms/std-helpdesk.orb +626 -407
  246. package/dist/exports/organisms/std-hr-portal.orb +1309 -714
  247. package/dist/exports/organisms/std-iot-dashboard.orb +1247 -335
  248. package/dist/exports/organisms/std-lms.orb +658 -362
  249. package/dist/exports/organisms/std-platformer-app.orb +56 -8
  250. package/dist/exports/organisms/std-project-manager.orb +1697 -1183
  251. package/dist/exports/organisms/std-puzzle-app.orb +20 -0
  252. package/dist/exports/organisms/std-realtime-chat.orb +552 -28
  253. package/dist/exports/organisms/std-rpg-game.orb +397 -56
  254. package/dist/exports/organisms/std-social-feed.orb +12 -8
  255. package/dist/exports/organisms/std-stem-lab.orb +175 -290
  256. package/dist/exports/organisms/std-strategy-game.orb +252 -395
  257. package/dist/exports/organisms/std-trading-dashboard.orb +718 -524
  258. package/dist/exports/validation-report.json +252 -252
  259. package/dist/exports/verify-results.json +13 -0
  260. package/dist/index.js +715 -593
  261. package/dist/index.js.map +1 -1
  262. package/package.json +1 -1
@@ -173,10 +173,10 @@ function buildTrait(c) {
173
173
  align: "center",
174
174
  children: [
175
175
  { type: "icon", name: headerIcon, size: "sm" },
176
- { type: "typography", variant: "h4", content: `@entity.${listFields[0] ?? "id"}` }
176
+ { type: "typography", variant: "h4", content: `@item.${listFields[0] ?? "id"}` }
177
177
  ]
178
178
  },
179
- ...listFields.length > 1 ? [{ type: "badge", label: `@entity.${listFields[1]}` }] : []
179
+ ...listFields.length > 1 ? [{ type: "badge", label: `@item.${listFields[1]}` }] : []
180
180
  ]
181
181
  }
182
182
  ];
@@ -185,7 +185,7 @@ function buildTrait(c) {
185
185
  type: "typography",
186
186
  variant: "caption",
187
187
  color: "muted",
188
- content: `@entity.${listFields[2]}`
188
+ content: `@item.${listFields[2]}`
189
189
  });
190
190
  }
191
191
  const headerChildren = [
@@ -261,7 +261,7 @@ function buildTrait(c) {
261
261
  ...c.itemActions.length > 0 ? { itemActions: c.itemActions } : {},
262
262
  // hover lift: cards rise on hover for interactive feel
263
263
  className: "transition-shadow hover:shadow-md cursor-pointer",
264
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
264
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
265
265
  }
266
266
  ]
267
267
  }]
@@ -300,37 +300,33 @@ function resolve3(params) {
300
300
  const nonIdFields = fields.filter((f) => f.name !== "id");
301
301
  const p = plural(entityName);
302
302
  const defaultContent = {
303
- type: "stack",
304
- direction: "vertical",
305
- gap: "md",
303
+ type: "modal",
304
+ title: params.modalTitle ?? "Details",
305
+ isOpen: true,
306
306
  children: [
307
307
  {
308
308
  type: "stack",
309
- direction: "horizontal",
310
- gap: "sm",
311
- align: "center",
312
- children: [
313
- { type: "icon", name: params.headerIcon ?? "maximize-2", size: "md" },
314
- { type: "typography", content: params.modalTitle ?? "Details", variant: "h3" }
315
- ]
316
- },
317
- { type: "divider" },
318
- ...nonIdFields.map((f) => ({
319
- type: "stack",
320
- direction: "horizontal",
309
+ direction: "vertical",
321
310
  gap: "md",
322
311
  children: [
323
- { type: "typography", variant: "caption", content: f.name.charAt(0).toUpperCase() + f.name.slice(1) },
324
- { type: "typography", variant: "body", content: `@entity.${f.name}` }
312
+ ...nonIdFields.map((f) => ({
313
+ type: "stack",
314
+ direction: "horizontal",
315
+ gap: "md",
316
+ children: [
317
+ { type: "typography", variant: "caption", content: f.name.charAt(0).toUpperCase() + f.name.slice(1) },
318
+ { type: "typography", variant: "body", content: ["object/get", ["array/first", "@entity"], f.name] }
319
+ ]
320
+ })),
321
+ { type: "divider" },
322
+ {
323
+ type: "stack",
324
+ direction: "horizontal",
325
+ gap: "sm",
326
+ justify: "end",
327
+ children: [{ type: "button", label: "Close", event: params.closeEvent ?? "CLOSE", variant: "ghost" }]
328
+ }
325
329
  ]
326
- })),
327
- { type: "divider" },
328
- {
329
- type: "stack",
330
- direction: "horizontal",
331
- gap: "sm",
332
- justify: "end",
333
- children: [{ type: "button", label: "Close", event: params.closeEvent ?? "CLOSE", variant: "ghost" }]
334
330
  }
335
331
  ]
336
332
  };
@@ -341,7 +337,7 @@ function resolve3(params) {
341
337
  persistence: params.persistence ?? "runtime",
342
338
  traitName: params.traitName ?? `${entityName}Modal`,
343
339
  modalTitle: params.modalTitle ?? "Details",
344
- headerIcon: params.headerIcon ?? "maximize-2",
340
+ headerIcon: params.headerIcon ?? "layout-panel-top",
345
341
  openContent: params.openContent ?? defaultContent,
346
342
  openEvent: params.openEvent ?? "OPEN",
347
343
  openPayload: params.openPayload ?? [],
@@ -385,7 +381,9 @@ function buildTrait2(c) {
385
381
  { type: "typography", content: c.modalTitle, variant: "h2" }
386
382
  ] },
387
383
  { type: "button", label: "Open", event: c.openEvent, variant: "primary", icon: c.headerIcon }
388
- ] }
384
+ ] },
385
+ { type: "divider" },
386
+ { type: "empty-state", icon: c.headerIcon, title: "Nothing open", description: "Click Open to view details in a modal overlay." }
389
387
  ]
390
388
  }]] : [["fetch", c.entityName]]
391
389
  },
@@ -396,8 +394,26 @@ function buildTrait2(c) {
396
394
  event: c.openEvent,
397
395
  effects: [...c.openEffects, ["render-ui", "modal", c.openContent]]
398
396
  },
399
- // CLOSE: open → closed
400
- { from: "open", to: "closed", event: c.closeEvent, effects: [["render-ui", "modal", null]] }
397
+ // CLOSE: open → closed (re-render main to avoid stale content)
398
+ { from: "open", to: "closed", event: c.closeEvent, effects: [
399
+ ["render-ui", "modal", null],
400
+ ...c.standalone ? [["fetch", c.entityName], ["render-ui", "main", {
401
+ type: "stack",
402
+ direction: "vertical",
403
+ gap: "lg",
404
+ children: [
405
+ { type: "stack", direction: "horizontal", gap: "md", justify: "space-between", children: [
406
+ { type: "stack", direction: "horizontal", gap: "md", children: [
407
+ { type: "icon", name: c.headerIcon, size: "lg" },
408
+ { type: "typography", content: c.modalTitle, variant: "h2" }
409
+ ] },
410
+ { type: "button", label: "Open", event: c.openEvent, variant: "primary", icon: c.headerIcon }
411
+ ] },
412
+ { type: "divider" },
413
+ { type: "empty-state", icon: c.headerIcon, title: "Nothing open", description: "Click Open to view details in a modal overlay." }
414
+ ]
415
+ }]] : []
416
+ ] }
401
417
  ];
402
418
  if (c.saveEvent) {
403
419
  transitions.push({
@@ -456,7 +472,7 @@ function resolve4(params) {
456
472
  confirmMessage: params.confirmMessage ?? "Are you sure?",
457
473
  confirmLabel: params.confirmLabel ?? "Confirm",
458
474
  cancelLabel: params.cancelLabel ?? "Cancel",
459
- headerIcon: params.headerIcon ?? "alert-triangle",
475
+ headerIcon: params.headerIcon ?? "shield-check",
460
476
  requestEvent: params.requestEvent ?? "REQUEST",
461
477
  confirmEvent: params.confirmEvent ?? "CONFIRM",
462
478
  confirmEffects: params.confirmEffects ?? [],
@@ -476,6 +492,66 @@ function buildEntity3(c) {
476
492
  }
477
493
  function buildTrait3(c) {
478
494
  const { entityName, displayField, pluralName, confirmTitle, confirmMessage, confirmLabel, cancelLabel, headerIcon } = c;
495
+ const idleMainView = {
496
+ type: "stack",
497
+ direction: "vertical",
498
+ gap: "lg",
499
+ children: [
500
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
501
+ { type: "icon", name: headerIcon, size: "lg" },
502
+ { type: "typography", content: pluralName, variant: "h2" }
503
+ ] },
504
+ { type: "divider" },
505
+ {
506
+ type: "data-grid",
507
+ entity: entityName,
508
+ emptyIcon: "inbox",
509
+ emptyTitle: `No ${pluralName.toLowerCase()} yet`,
510
+ emptyDescription: "Items will appear here.",
511
+ itemActions: [{ label: confirmTitle, event: c.requestEvent, variant: "danger" }],
512
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: [
513
+ { type: "typography", variant: "h4", content: `@item.${displayField}` }
514
+ ] }]
515
+ }
516
+ ]
517
+ };
518
+ const confirmModalView = {
519
+ type: "stack",
520
+ direction: "vertical",
521
+ gap: "md",
522
+ children: [
523
+ {
524
+ type: "stack",
525
+ direction: "horizontal",
526
+ gap: "sm",
527
+ align: "center",
528
+ children: [
529
+ { type: "icon", name: "alert-triangle", size: "md" },
530
+ { type: "typography", content: confirmTitle, variant: "h3" }
531
+ ]
532
+ },
533
+ { type: "divider" },
534
+ {
535
+ type: "alert",
536
+ variant: "danger",
537
+ message: confirmMessage
538
+ },
539
+ {
540
+ type: "stack",
541
+ direction: "horizontal",
542
+ gap: "sm",
543
+ justify: "end",
544
+ children: [
545
+ { type: "button", label: cancelLabel, event: "CANCEL", variant: "ghost" },
546
+ { type: "button", label: confirmLabel, event: c.confirmEvent, variant: "danger", icon: "check" }
547
+ ]
548
+ }
549
+ ]
550
+ };
551
+ const dismissAndRefresh = [
552
+ ["render-ui", "modal", null],
553
+ ...c.standalone ? [["fetch", entityName], ["render-ui", "main", idleMainView]] : [["fetch", entityName]]
554
+ ];
479
555
  return {
480
556
  name: c.traitName,
481
557
  linkedEntity: entityName,
@@ -494,36 +570,12 @@ function buildTrait3(c) {
494
570
  { key: "CLOSE", name: "Close" }
495
571
  ],
496
572
  transitions: [
497
- // INIT: idle -> idle
498
573
  {
499
574
  from: "idle",
500
575
  to: "idle",
501
576
  event: "INIT",
502
- effects: c.standalone ? [["fetch", entityName], ["render-ui", "main", {
503
- type: "stack",
504
- direction: "vertical",
505
- gap: "lg",
506
- children: [
507
- { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
508
- { type: "icon", name: headerIcon, size: "lg" },
509
- { type: "typography", content: pluralName, variant: "h2" }
510
- ] },
511
- { type: "divider" },
512
- {
513
- type: "data-grid",
514
- entity: entityName,
515
- emptyIcon: "inbox",
516
- emptyTitle: `No ${pluralName.toLowerCase()} yet`,
517
- emptyDescription: "Items will appear here.",
518
- itemActions: [{ label: confirmTitle, event: c.requestEvent, variant: "danger" }],
519
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: [
520
- { type: "typography", variant: "h4", content: `@entity.${displayField}` }
521
- ] }]
522
- }
523
- ]
524
- }]] : [["fetch", entityName]]
577
+ effects: c.standalone ? [["fetch", entityName], ["render-ui", "main", idleMainView]] : [["fetch", entityName]]
525
578
  },
526
- // REQUEST: idle -> confirming (fetch entity by ID so server has context)
527
579
  {
528
580
  from: "idle",
529
581
  to: "confirming",
@@ -531,65 +583,30 @@ function buildTrait3(c) {
531
583
  effects: [
532
584
  ["set", "@entity.pendingId", "@payload.id"],
533
585
  ["fetch", entityName, "@payload.id"],
534
- ["render-ui", "modal", {
535
- type: "stack",
536
- direction: "vertical",
537
- gap: "md",
538
- children: [
539
- {
540
- type: "stack",
541
- direction: "horizontal",
542
- gap: "sm",
543
- align: "center",
544
- children: [
545
- { type: "icon", name: headerIcon, size: "md" },
546
- { type: "typography", content: confirmTitle, variant: "h3" }
547
- ]
548
- },
549
- { type: "divider" },
550
- { type: "typography", content: confirmMessage, variant: "body" },
551
- {
552
- type: "stack",
553
- direction: "horizontal",
554
- gap: "sm",
555
- justify: "end",
556
- children: [
557
- { type: "button", label: cancelLabel, event: "CANCEL", variant: "ghost" },
558
- { type: "button", label: confirmLabel, event: c.confirmEvent, variant: "danger", icon: "check" }
559
- ]
560
- }
561
- ]
562
- }]
586
+ ["render-ui", "modal", confirmModalView]
563
587
  ]
564
588
  },
565
- // CONFIRM: confirming -> idle (run injected effects, dismiss modal)
566
589
  {
567
590
  from: "confirming",
568
591
  to: "idle",
569
592
  event: c.confirmEvent,
570
593
  effects: [
571
594
  ...c.confirmEffects,
572
- ["render-ui", "modal", null],
595
+ ...dismissAndRefresh,
573
596
  ...c.emitOnConfirm ? [["emit", c.emitOnConfirm]] : []
574
597
  ]
575
598
  },
576
- // CANCEL: confirming -> idle (dismiss modal)
577
599
  {
578
600
  from: "confirming",
579
601
  to: "idle",
580
602
  event: "CANCEL",
581
- effects: [
582
- ["render-ui", "modal", null]
583
- ]
603
+ effects: dismissAndRefresh
584
604
  },
585
- // CLOSE: confirming -> idle (dismiss modal)
586
605
  {
587
606
  from: "confirming",
588
607
  to: "idle",
589
608
  event: "CLOSE",
590
- effects: [
591
- ["render-ui", "modal", null]
592
- ]
609
+ effects: dismissAndRefresh
593
610
  }
594
611
  ]
595
612
  }
@@ -619,8 +636,8 @@ function stdConfirmation(params) {
619
636
  function resolve5(params) {
620
637
  const { entityName } = params;
621
638
  const baseFields = ensureIdField(params.fields);
622
- const fields = baseFields.some((f) => f.name === "query") ? baseFields : [...baseFields, { name: "query", type: "string", default: "" }];
623
- const nonIdFields = baseFields.filter((f) => f.name !== "id" && f.name !== "query");
639
+ const fields = baseFields;
640
+ const nonIdFields = baseFields.filter((f) => f.name !== "id");
624
641
  const p = plural(entityName);
625
642
  return {
626
643
  entityName,
@@ -657,7 +674,8 @@ function buildTrait4(c) {
657
674
  ]
658
675
  },
659
676
  { type: "divider" },
660
- { type: "search-input", placeholder, event: "SEARCH" }
677
+ { type: "search-input", placeholder, event: "SEARCH" },
678
+ { type: "empty-state", icon: searchIcon, title: "Search to find results", description: `Type a query to search across ${pluralName.toLowerCase()}.` }
661
679
  ]
662
680
  };
663
681
  const resultsView = {
@@ -679,7 +697,7 @@ function buildTrait4(c) {
679
697
  align: "center",
680
698
  children: [
681
699
  { type: "icon", name: searchIcon, size: "lg" },
682
- { type: "typography", content: ["concat", 'Results for "', "@entity.query", '"'], variant: "h2" }
700
+ { type: "typography", content: ["concat", 'Results for "', "@payload.query", '"'], variant: "h2" }
683
701
  ]
684
702
  },
685
703
  { type: "button", label: "Clear", event: "CLEAR", variant: "ghost", icon: "x" }
@@ -692,12 +710,12 @@ function buildTrait4(c) {
692
710
  emptyIcon: searchIcon,
693
711
  emptyTitle: "No results found",
694
712
  emptyDescription: "Try a different search term.",
695
- children: [{
713
+ renderItem: ["fn", "item", {
696
714
  type: "stack",
697
715
  direction: "vertical",
698
716
  gap: "sm",
699
717
  children: [
700
- { type: "typography", variant: "h4", content: `@entity.${displayField}` }
718
+ { type: "typography", variant: "h4", content: `@item.${displayField}` }
701
719
  ]
702
720
  }]
703
721
  }
@@ -732,7 +750,6 @@ function buildTrait4(c) {
732
750
  to: "searching",
733
751
  event: "SEARCH",
734
752
  effects: [
735
- ["set", "@entity.query", "@payload.query"],
736
753
  ["fetch", entityName],
737
754
  ["render-ui", "main", resultsView]
738
755
  ]
@@ -742,7 +759,6 @@ function buildTrait4(c) {
742
759
  to: "searching",
743
760
  event: "SEARCH",
744
761
  effects: [
745
- ["set", "@entity.query", "@payload.query"],
746
762
  ["fetch", entityName],
747
763
  ["render-ui", "main", resultsView]
748
764
  ]
@@ -752,7 +768,6 @@ function buildTrait4(c) {
752
768
  to: "idle",
753
769
  event: "CLEAR",
754
770
  effects: [
755
- ["set", "@entity.query", ""],
756
771
  ["fetch", entityName],
757
772
  ["render-ui", "main", searchInputView]
758
773
  ]
@@ -810,61 +825,28 @@ function buildEntity5(c) {
810
825
  }
811
826
  function buildTrait5(c) {
812
827
  const { entityName, displayField, pluralName, headerIcon, pageTitle, filterableFields } = c;
813
- const filterButtons = filterableFields.map((f) => ({
814
- type: "stack",
815
- direction: "vertical",
816
- gap: "xs",
817
- children: [
818
- // overline group label for visual hierarchy
819
- {
820
- type: "typography",
821
- variant: "overline",
822
- color: "muted",
823
- content: f.name.charAt(0).toUpperCase() + f.name.slice(1)
824
- },
825
- {
826
- type: "stack",
827
- direction: "horizontal",
828
- gap: "sm",
829
- align: "center",
830
- children: (f.values ?? []).map((v) => ({
831
- type: "button",
832
- label: v,
833
- event: "FILTER",
834
- variant: "secondary"
835
- }))
836
- }
837
- ]
838
- }));
839
- const activeFilterButtons = filterableFields.map((f) => ({
828
+ const filterControls = filterableFields.length > 0 ? [{
829
+ type: "filter-group",
830
+ entity: entityName,
831
+ filters: filterableFields.map((f) => ({
832
+ field: f.name,
833
+ label: f.name.charAt(0).toUpperCase() + f.name.slice(1),
834
+ options: f.values ?? [],
835
+ filterType: f.type === "boolean" ? "toggle" : "select"
836
+ }))
837
+ }] : [{ type: "empty-state", icon: "filter-x", title: "No filter fields", description: "Add fields with predefined values to enable filtering." }];
838
+ const booleanFilters = filterableFields.filter((f) => f.type === "boolean");
839
+ const switchControls = booleanFilters.map((f) => ({
840
840
  type: "stack",
841
- direction: "vertical",
842
- gap: "xs",
841
+ direction: "horizontal",
842
+ gap: "sm",
843
+ align: "center",
844
+ justify: "space-between",
843
845
  children: [
844
- {
845
- type: "typography",
846
- variant: "overline",
847
- color: "muted",
848
- content: f.name.charAt(0).toUpperCase() + f.name.slice(1)
849
- },
850
- {
851
- type: "stack",
852
- direction: "horizontal",
853
- gap: "sm",
854
- align: "center",
855
- children: (f.values ?? []).map((v) => ({
856
- // active filter chip uses 'primary' variant so runtime highlights it
857
- type: "button",
858
- label: v,
859
- event: "FILTER",
860
- variant: "primary"
861
- }))
862
- }
846
+ { type: "typography", variant: "body", content: f.name.charAt(0).toUpperCase() + f.name.slice(1) },
847
+ { type: "switch", checked: false }
863
848
  ]
864
849
  }));
865
- if (filterButtons.length === 0) {
866
- filterButtons.push({ type: "badge", label: "No filter fields defined" });
867
- }
868
850
  const header = {
869
851
  type: "stack",
870
852
  direction: "horizontal",
@@ -886,17 +868,37 @@ function buildTrait5(c) {
886
868
  emptyTitle: `No ${pluralName.toLowerCase()} yet`,
887
869
  emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
888
870
  className: "transition-shadow hover:shadow-md cursor-pointer",
889
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: [
890
- { type: "typography", variant: "h4", content: `@entity.${displayField}` },
871
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: [
872
+ { type: "typography", variant: "h4", content: `@item.${displayField}` },
891
873
  // show the filterable field value to confirm what was filtered
892
- ...filterableFields[0] ? [{ type: "typography", variant: "caption", color: "muted", content: `@entity.${filterableFields[0].name}` }] : []
874
+ ...filterableFields[0] ? [{ type: "typography", variant: "caption", color: "muted", content: `@item.${filterableFields[0].name}` }] : []
893
875
  ] }]
894
876
  };
895
877
  const browsingView = {
896
878
  type: "stack",
897
879
  direction: "vertical",
898
880
  gap: "lg",
899
- children: [header, { type: "divider" }, ...filterButtons, { type: "divider" }, dataGrid]
881
+ children: [
882
+ header,
883
+ { type: "divider" },
884
+ ...filterControls,
885
+ ...switchControls.length > 0 ? [{ type: "divider" }, ...switchControls] : [],
886
+ { type: "divider" },
887
+ dataGrid
888
+ ]
889
+ };
890
+ const activeFilterIndicator = {
891
+ type: "stack",
892
+ direction: "horizontal",
893
+ gap: "sm",
894
+ align: "center",
895
+ children: [
896
+ { type: "icon", name: "filter", size: "sm" },
897
+ { type: "typography", variant: "caption", color: "muted", content: "Filtered by" },
898
+ { type: "badge", label: "@payload.field", variant: "secondary" },
899
+ { type: "typography", variant: "caption", content: "=" },
900
+ { type: "badge", label: "@payload.value", variant: "primary" }
901
+ ]
900
902
  };
901
903
  const filteredView = {
902
904
  type: "stack",
@@ -914,15 +916,16 @@ function buildTrait5(c) {
914
916
  { type: "icon", name: headerIcon, size: "lg" },
915
917
  { type: "typography", content: pageTitle, variant: "h2" }
916
918
  ] },
917
- { type: "stack", direction: "horizontal", gap: "sm", children: [
919
+ { type: "stack", direction: "horizontal", gap: "sm", align: "center", children: [
918
920
  { type: "badge", label: "Filtered", variant: "primary" },
919
- { type: "button", label: "Clear", event: "CLEAR_FILTERS", variant: "ghost", icon: "x" }
921
+ { type: "button", label: "Clear All", event: "CLEAR_FILTERS", variant: "ghost", icon: "x" }
920
922
  ] }
921
923
  ]
922
924
  },
925
+ activeFilterIndicator,
923
926
  { type: "divider" },
924
- // activeFilterButtons show primary variant for selected state
925
- ...activeFilterButtons,
927
+ ...filterControls,
928
+ ...switchControls.length > 0 ? [{ type: "divider" }, ...switchControls] : [],
926
929
  { type: "divider" },
927
930
  dataGrid
928
931
  ]
@@ -938,14 +941,29 @@ function buildTrait5(c) {
938
941
  ],
939
942
  events: [
940
943
  { key: "INIT", name: "Initialize" },
941
- { key: "FILTER", name: "Filter" },
944
+ { key: "FILTER", name: "Filter", payload: [
945
+ { name: "field", type: "string", required: true },
946
+ { name: "value", type: "string", required: true }
947
+ ] },
942
948
  { key: "CLEAR_FILTERS", name: "Clear Filters" }
943
949
  ],
944
950
  transitions: [
945
- { from: "browsing", to: "browsing", event: "INIT", effects: [["fetch", entityName], ["render-ui", "main", browsingView]] },
946
- { from: "browsing", to: "filtered", event: "FILTER", effects: [["fetch", entityName], ["render-ui", "main", filteredView]] },
947
- { from: "filtered", to: "filtered", event: "FILTER", effects: [["fetch", entityName], ["render-ui", "main", filteredView]] },
948
- { from: "filtered", to: "browsing", event: "CLEAR_FILTERS", effects: [["fetch", entityName], ["render-ui", "main", browsingView]] }
951
+ { from: "browsing", to: "browsing", event: "INIT", effects: [
952
+ ["fetch", entityName],
953
+ ["render-ui", "main", browsingView]
954
+ ] },
955
+ { from: "browsing", to: "filtered", event: "FILTER", effects: [
956
+ ["fetch", entityName, ["==", ["object/get", "@entity", "@payload.field"], "@payload.value"]],
957
+ ["render-ui", "main", filteredView]
958
+ ] },
959
+ { from: "filtered", to: "filtered", event: "FILTER", effects: [
960
+ ["fetch", entityName, ["==", ["object/get", "@entity", "@payload.field"], "@payload.value"]],
961
+ ["render-ui", "main", filteredView]
962
+ ] },
963
+ { from: "filtered", to: "browsing", event: "CLEAR_FILTERS", effects: [
964
+ ["fetch", entityName],
965
+ ["render-ui", "main", browsingView]
966
+ ] }
949
967
  ]
950
968
  }
951
969
  };
@@ -1002,7 +1020,7 @@ function buildTrait6(c) {
1002
1020
  type: "button",
1003
1021
  label: f.charAt(0).toUpperCase() + f.slice(1),
1004
1022
  event: "SORT",
1005
- // secondary in idle; molecules can override active to primary
1023
+ actionPayload: { field: f, direction: "asc" },
1006
1024
  variant: "secondary",
1007
1025
  icon: "arrow-up-down"
1008
1026
  }))
@@ -1019,6 +1037,7 @@ function buildTrait6(c) {
1019
1037
  type: "button",
1020
1038
  label: f.charAt(0).toUpperCase() + f.slice(1),
1021
1039
  event: "SORT",
1040
+ actionPayload: { field: f, direction: f === activeField ? "desc" : "asc" },
1022
1041
  // highlight the active sort field with primary + directional arrow
1023
1042
  variant: f === activeField ? "primary" : "secondary",
1024
1043
  icon: f === activeField ? "chevron-up" : "arrow-up-down"
@@ -1032,10 +1051,9 @@ function buildTrait6(c) {
1032
1051
  emptyTitle: `No ${pluralName.toLowerCase()} yet`,
1033
1052
  emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
1034
1053
  className: "transition-shadow hover:shadow-md cursor-pointer",
1035
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: [
1036
- { type: "typography", variant: "h4", content: `@entity.${displayField}` },
1037
- // Show the first sortable field as a secondary datum so sorting is visually meaningful
1038
- ...sortableFields[1] ? [{ type: "typography", variant: "caption", color: "muted", content: `@entity.${sortableFields[1]}` }] : []
1054
+ renderItem: ["fn", "item", { type: "stack", direction: "horizontal", gap: "md", align: "center", justify: "space-between", children: [
1055
+ { type: "typography", variant: "h4", content: `@item.${displayField}` },
1056
+ ...sortableFields[1] ? [{ type: "typography", variant: "caption", color: "muted", content: `@item.${sortableFields[1]}` }] : []
1039
1057
  ] }]
1040
1058
  };
1041
1059
  const mainView = {
@@ -1050,7 +1068,6 @@ function buildTrait6(c) {
1050
1068
  ] }
1051
1069
  ] },
1052
1070
  { type: "divider" },
1053
- // Sort toolbar lives just above the data list
1054
1071
  sortToolbar,
1055
1072
  dataGrid
1056
1073
  ]
@@ -1081,12 +1098,21 @@ function buildTrait6(c) {
1081
1098
  states: [{ name: "idle", isInitial: true }, { name: "sorted" }],
1082
1099
  events: [
1083
1100
  { key: "INIT", name: "Initialize" },
1084
- { key: "SORT", name: "Sort" }
1101
+ { key: "SORT", name: "Sort", payload: [
1102
+ { name: "field", type: "string", required: true },
1103
+ { name: "direction", type: "string" }
1104
+ ] }
1085
1105
  ],
1086
1106
  transitions: [
1087
1107
  { from: "idle", to: "idle", event: "INIT", effects: [["fetch", entityName], ["render-ui", "main", mainView]] },
1088
- { from: "idle", to: "sorted", event: "SORT", effects: [["fetch", entityName], ["render-ui", "main", mainSortedView]] },
1089
- { from: "sorted", to: "sorted", event: "SORT", effects: [["fetch", entityName], ["render-ui", "main", mainSortedView]] },
1108
+ { from: "idle", to: "sorted", event: "SORT", effects: [
1109
+ ["fetch", entityName, null, ["concat", "@payload.field", ":", "@payload.direction"]],
1110
+ ["render-ui", "main", mainSortedView]
1111
+ ] },
1112
+ { from: "sorted", to: "sorted", event: "SORT", effects: [
1113
+ ["fetch", entityName, null, ["concat", "@payload.field", ":", "@payload.direction"]],
1114
+ ["render-ui", "main", mainSortedView]
1115
+ ] },
1090
1116
  { from: "sorted", to: "idle", event: "INIT", effects: [["fetch", entityName], ["render-ui", "main", mainView]] }
1091
1117
  ]
1092
1118
  }
@@ -1111,12 +1137,8 @@ function stdSort(params) {
1111
1137
  function resolve8(params) {
1112
1138
  const { entityName } = params;
1113
1139
  const baseFields = ensureIdField(params.fields);
1114
- const fields = [
1115
- ...baseFields,
1116
- ...baseFields.some((f) => f.name === "currentPage") ? [] : [{ name: "currentPage", type: "number", default: 1 }],
1117
- ...baseFields.some((f) => f.name === "pageSize") ? [] : [{ name: "pageSize", type: "number", default: 10 }]
1118
- ];
1119
- const nonIdFields = baseFields.filter((f) => f.name !== "id" && f.name !== "currentPage" && f.name !== "pageSize");
1140
+ const fields = baseFields;
1141
+ const nonIdFields = baseFields.filter((f) => f.name !== "id");
1120
1142
  const p = plural(entityName);
1121
1143
  return {
1122
1144
  entityName,
@@ -1170,34 +1192,22 @@ function buildTrait7(c) {
1170
1192
  emptyTitle: `No ${pluralName.toLowerCase()} yet`,
1171
1193
  emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
1172
1194
  className: "transition-shadow hover:shadow-md cursor-pointer",
1173
- children: [{
1195
+ renderItem: ["fn", "item", {
1174
1196
  type: "stack",
1175
1197
  direction: "vertical",
1176
1198
  gap: "sm",
1177
1199
  children: [
1178
- { type: "typography", variant: "h4", content: `@entity.${displayField}` },
1179
- // secondary caption row to distinguish items
1180
- { type: "typography", variant: "caption", color: "muted", content: `@entity.id` }
1200
+ { type: "typography", variant: "h4", content: "@item.name" },
1201
+ { type: "typography", variant: "caption", color: "muted", content: "@item.id" }
1181
1202
  ]
1182
1203
  }]
1183
1204
  },
1184
1205
  {
1185
- // Pagination footer with context: "Page N" and Prev/Next nav
1186
- type: "stack",
1187
- direction: "horizontal",
1188
- gap: "sm",
1189
- justify: "center",
1190
- align: "center",
1191
- children: [
1192
- { type: "button", label: "Previous", event: "PAGE", variant: "ghost", icon: "chevron-left" },
1193
- {
1194
- type: "typography",
1195
- variant: "body",
1196
- color: "muted",
1197
- content: ["concat", "Page ", "@entity.currentPage"]
1198
- },
1199
- { type: "button", label: "Next", event: "PAGE", variant: "ghost", icon: "chevron-right" }
1200
- ]
1206
+ type: "pagination",
1207
+ currentPage: 1,
1208
+ totalPages: 10,
1209
+ onPageChange: "PAGE",
1210
+ showPageSize: false
1201
1211
  }
1202
1212
  ]
1203
1213
  };
@@ -1231,10 +1241,58 @@ function buildTrait7(c) {
1231
1241
  to: "idle",
1232
1242
  event: "PAGE",
1233
1243
  effects: [
1234
- ["set", "@entity.currentPage", "@payload.page"],
1235
- ["set", "@entity.pageSize", "@payload.pageSize"],
1236
1244
  ["fetch", entityName],
1237
- ["render-ui", "main", mainView]
1245
+ ["render-ui", "main", {
1246
+ type: "stack",
1247
+ direction: "vertical",
1248
+ gap: "lg",
1249
+ children: [
1250
+ {
1251
+ type: "stack",
1252
+ direction: "horizontal",
1253
+ gap: "sm",
1254
+ justify: "space-between",
1255
+ align: "center",
1256
+ children: [
1257
+ {
1258
+ type: "stack",
1259
+ direction: "horizontal",
1260
+ gap: "sm",
1261
+ align: "center",
1262
+ children: [
1263
+ { type: "icon", name: headerIcon, size: "lg" },
1264
+ { type: "typography", content: pageTitle, variant: "h2" }
1265
+ ]
1266
+ }
1267
+ ]
1268
+ },
1269
+ { type: "divider" },
1270
+ {
1271
+ type: "data-grid",
1272
+ entity: entityName,
1273
+ emptyIcon: "inbox",
1274
+ emptyTitle: `No ${pluralName.toLowerCase()} yet`,
1275
+ emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
1276
+ className: "transition-shadow hover:shadow-md cursor-pointer",
1277
+ renderItem: ["fn", "item", {
1278
+ type: "stack",
1279
+ direction: "vertical",
1280
+ gap: "sm",
1281
+ children: [
1282
+ { type: "typography", variant: "h4", content: "@item.name" },
1283
+ { type: "typography", variant: "caption", color: "muted", content: "@item.id" }
1284
+ ]
1285
+ }]
1286
+ },
1287
+ {
1288
+ type: "pagination",
1289
+ currentPage: "@payload.page",
1290
+ totalPages: 10,
1291
+ onPageChange: "PAGE",
1292
+ showPageSize: false
1293
+ }
1294
+ ]
1295
+ }]
1238
1296
  ]
1239
1297
  }
1240
1298
  ]
@@ -1285,6 +1343,7 @@ function resolve9(params) {
1285
1343
  function buildEntity8(c) {
1286
1344
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
1287
1345
  }
1346
+ var ef = (field) => ["object/get", ["array/first", "@entity"], field];
1288
1347
  function buildTrait8(c) {
1289
1348
  const { entityName, nonIdFields, displayField, pluralName, drawerTitle, headerIcon } = c;
1290
1349
  const closedView = {
@@ -1319,60 +1378,63 @@ function buildTrait8(c) {
1319
1378
  emptyIcon: "inbox",
1320
1379
  emptyTitle: `No ${pluralName.toLowerCase()} yet`,
1321
1380
  emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
1322
- children: [{
1381
+ renderItem: ["fn", "item", {
1323
1382
  type: "stack",
1324
1383
  direction: "vertical",
1325
1384
  gap: "sm",
1326
1385
  children: [
1327
- { type: "typography", variant: "h4", content: `@entity.${displayField}` }
1386
+ { type: "typography", variant: "h4", content: `@item.${displayField}` }
1328
1387
  ]
1329
1388
  }]
1330
1389
  }
1331
1390
  ]
1332
1391
  };
1333
1392
  const openView = {
1334
- type: "stack",
1335
- direction: "vertical",
1336
- gap: "md",
1393
+ type: "drawer",
1394
+ title: drawerTitle,
1395
+ isOpen: true,
1337
1396
  children: [
1338
1397
  {
1339
1398
  type: "stack",
1340
- direction: "horizontal",
1341
- gap: "sm",
1342
- justify: "space-between",
1343
- align: "center",
1399
+ direction: "vertical",
1400
+ gap: "md",
1344
1401
  children: [
1402
+ {
1403
+ type: "accordion",
1404
+ items: [
1405
+ {
1406
+ id: "details",
1407
+ title: "Details",
1408
+ content: {
1409
+ type: "stack",
1410
+ direction: "vertical",
1411
+ gap: "sm",
1412
+ children: nonIdFields.map((field) => ({
1413
+ type: "stack",
1414
+ direction: "horizontal",
1415
+ gap: "md",
1416
+ justify: "space-between",
1417
+ children: [
1418
+ { type: "typography", variant: "caption", content: field.name.charAt(0).toUpperCase() + field.name.slice(1) },
1419
+ { type: "typography", variant: "body", content: ef(field.name) }
1420
+ ]
1421
+ }))
1422
+ }
1423
+ }
1424
+ ],
1425
+ defaultOpen: [0],
1426
+ multiple: true
1427
+ },
1428
+ { type: "divider" },
1345
1429
  {
1346
1430
  type: "stack",
1347
1431
  direction: "horizontal",
1348
1432
  gap: "sm",
1349
- align: "center",
1433
+ justify: "end",
1350
1434
  children: [
1351
- { type: "icon", name: headerIcon, size: "md" },
1352
- { type: "typography", content: drawerTitle, variant: "h3" }
1435
+ { type: "button", label: "Close", event: "CLOSE", variant: "ghost" }
1353
1436
  ]
1354
- },
1355
- { type: "button", label: "Close", event: "CLOSE", variant: "ghost", icon: "x" }
1356
- ]
1357
- },
1358
- { type: "divider" },
1359
- ...nonIdFields.map((field) => ({
1360
- type: "stack",
1361
- direction: "horizontal",
1362
- gap: "md",
1363
- children: [
1364
- { type: "typography", variant: "caption", content: field.name.charAt(0).toUpperCase() + field.name.slice(1) },
1365
- { type: "typography", variant: "body", content: `@entity.${field.name}` }
1366
- ]
1367
- })),
1368
- { type: "divider" },
1369
- {
1370
- type: "stack",
1371
- direction: "horizontal",
1372
- gap: "sm",
1373
- justify: "end",
1374
- children: [
1375
- { type: "button", label: "Close", event: "CLOSE", variant: "ghost" }
1437
+ }
1376
1438
  ]
1377
1439
  }
1378
1440
  ]
@@ -1415,7 +1477,9 @@ function buildTrait8(c) {
1415
1477
  to: "closed",
1416
1478
  event: "CLOSE",
1417
1479
  effects: [
1418
- ["render-ui", "drawer", null]
1480
+ ["render-ui", "drawer", null],
1481
+ ["fetch", entityName],
1482
+ ["render-ui", "main", closedView]
1419
1483
  ]
1420
1484
  }
1421
1485
  ]
@@ -1468,6 +1532,7 @@ function resolve10(params) {
1468
1532
  function buildEntity9(c) {
1469
1533
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
1470
1534
  }
1535
+ var ef2 = (field) => ["object/get", ["array/first", "@entity"], field];
1471
1536
  function buildTrait9(c) {
1472
1537
  const { entityName, headerIcon, pageTitle } = c;
1473
1538
  const hiddenView = {
@@ -1486,17 +1551,7 @@ function buildTrait9(c) {
1486
1551
  ]
1487
1552
  },
1488
1553
  { type: "divider" },
1489
- {
1490
- type: "stack",
1491
- direction: "vertical",
1492
- gap: "md",
1493
- align: "center",
1494
- children: [
1495
- { type: "icon", name: "bell-off", size: "lg" },
1496
- { type: "typography", content: "No notifications", variant: "body" },
1497
- { type: "typography", content: "New notifications will appear here.", variant: "caption" }
1498
- ]
1499
- }
1554
+ { type: "empty-state", icon: "bell-off", title: "No notifications", description: "New notifications will appear here." }
1500
1555
  ]
1501
1556
  };
1502
1557
  const visibleView = {
@@ -1526,22 +1581,9 @@ function buildTrait9(c) {
1526
1581
  },
1527
1582
  { type: "divider" },
1528
1583
  {
1529
- type: "stack",
1530
- direction: "horizontal",
1531
- gap: "md",
1532
- align: "center",
1533
- children: [
1534
- { type: "icon", name: headerIcon, size: "md" },
1535
- {
1536
- type: "stack",
1537
- direction: "vertical",
1538
- gap: "xs",
1539
- children: [
1540
- { type: "typography", content: "@entity.message", variant: "body" },
1541
- { type: "badge", label: "@entity.notificationType" }
1542
- ]
1543
- }
1544
- ]
1584
+ type: "alert",
1585
+ variant: ef2("notificationType"),
1586
+ message: ef2("message")
1545
1587
  }
1546
1588
  ]
1547
1589
  };
@@ -1656,6 +1698,7 @@ function resolve11(params) {
1656
1698
  function buildEntity10(c) {
1657
1699
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
1658
1700
  }
1701
+ var ef3 = (field) => ["object/get", ["array/first", "@entity"], field];
1659
1702
  function buildTrait10(c) {
1660
1703
  const { entityName, timerTitle, headerIcon } = c;
1661
1704
  const timerDisplay = {
@@ -1675,13 +1718,11 @@ function buildTrait10(c) {
1675
1718
  ]
1676
1719
  },
1677
1720
  { type: "divider" },
1678
- // Large MM:SS time display the entity.remaining field drives this
1679
- { type: "typography", content: "@entity.remaining", variant: "h1" },
1680
- // Unit/label subtitle: shows what is being timed
1681
- { type: "typography", content: "seconds remaining", variant: "caption", color: "muted" },
1682
- // Progress bar track — always visible, filled as timer decrements
1683
- { type: "progress-bar", value: "@entity.remaining", max: c.duration, color: "primary" },
1684
- { type: "badge", label: "@entity.status" }
1721
+ { type: "animated-counter", value: ef3("remaining"), suffix: "s", duration: 500 },
1722
+ { type: "stat-display", label: "Time Remaining", value: ef3("remaining"), max: c.duration },
1723
+ { type: "meter", value: ef3("remaining"), min: 0, max: c.duration },
1724
+ { type: "progress-bar", value: ef3("remaining"), max: c.duration, color: "primary", showPercentage: true },
1725
+ { type: "badge", label: ef3("status") }
1685
1726
  ]
1686
1727
  };
1687
1728
  const idleButtons = {
@@ -1891,11 +1932,7 @@ function resolve12(params) {
1891
1932
  const { entityName } = params;
1892
1933
  const baseFields = ensureIdField(params.fields);
1893
1934
  const p = plural(entityName);
1894
- const domainFields = [
1895
- { name: "activeTab", type: "string", default: "" }
1896
- ];
1897
- const userFieldNames = new Set(baseFields.map((f) => f.name));
1898
- const fields = [...baseFields, ...domainFields.filter((f) => !userFieldNames.has(f.name))];
1935
+ const fields = baseFields;
1899
1936
  const nonIdFields = fields.filter((f) => f.name !== "id");
1900
1937
  const tabItems = params.tabItems ?? nonIdFields.filter((f) => f.name !== "activeTab").map((f) => ({
1901
1938
  label: f.name.charAt(0).toUpperCase() + f.name.slice(1),
@@ -1922,7 +1959,21 @@ function buildEntity11(c) {
1922
1959
  }
1923
1960
  function buildTrait11(c) {
1924
1961
  const { entityName, displayField, pluralName, headerIcon, pageTitle, tabItems } = c;
1925
- const mainView = {
1962
+ const tabContentChildren = [
1963
+ {
1964
+ type: "data-grid",
1965
+ entity: entityName,
1966
+ emptyIcon: "inbox",
1967
+ emptyTitle: `No ${pluralName.toLowerCase()} yet`,
1968
+ emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
1969
+ className: "transition-shadow hover:shadow-md cursor-pointer",
1970
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: [
1971
+ { type: "typography", variant: "h4", content: `@item.${displayField}` },
1972
+ { type: "typography", variant: "caption", color: "muted", content: `@item.${tabItems[0]?.value ?? displayField}` }
1973
+ ] }]
1974
+ }
1975
+ ];
1976
+ const initView = {
1926
1977
  type: "stack",
1927
1978
  direction: "vertical",
1928
1979
  gap: "lg",
@@ -1936,24 +1987,31 @@ function buildTrait11(c) {
1936
1987
  type: "tabs",
1937
1988
  tabs: tabItems,
1938
1989
  defaultActiveTab: tabItems[0]?.value ?? "",
1939
- // active tab gets primary color underline and text
1940
- activeTab: "@entity.activeTab",
1941
1990
  onTabChange: "SELECT_TAB"
1942
1991
  },
1943
- // divider separates tab bar from content
1992
+ { type: "divider" },
1993
+ ...tabContentChildren
1994
+ ]
1995
+ };
1996
+ const tabSelectedView = {
1997
+ type: "stack",
1998
+ direction: "vertical",
1999
+ gap: "lg",
2000
+ children: [
2001
+ { type: "stack", direction: "horizontal", gap: "sm", align: "center", children: [
2002
+ { type: "icon", name: headerIcon, size: "lg" },
2003
+ { type: "typography", content: pageTitle, variant: "h2" }
2004
+ ] },
1944
2005
  { type: "divider" },
1945
2006
  {
1946
- type: "data-grid",
1947
- entity: entityName,
1948
- emptyIcon: "inbox",
1949
- emptyTitle: `No ${pluralName.toLowerCase()} yet`,
1950
- emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
1951
- className: "transition-shadow hover:shadow-md cursor-pointer",
1952
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: [
1953
- { type: "typography", variant: "h4", content: `@entity.${displayField}` },
1954
- { type: "typography", variant: "caption", color: "muted", content: `@entity.${tabItems[0]?.value ?? displayField}` }
1955
- ] }]
1956
- }
2007
+ type: "tabs",
2008
+ tabs: tabItems,
2009
+ defaultActiveTab: tabItems[0]?.value ?? "",
2010
+ activeTab: "@payload.tab",
2011
+ onTabChange: "SELECT_TAB"
2012
+ },
2013
+ { type: "divider" },
2014
+ ...tabContentChildren
1957
2015
  ]
1958
2016
  };
1959
2017
  return {
@@ -1964,11 +2022,13 @@ function buildTrait11(c) {
1964
2022
  states: [{ name: "idle", isInitial: true }],
1965
2023
  events: [
1966
2024
  { key: "INIT", name: "Initialize" },
1967
- { key: "SELECT_TAB", name: "Select Tab" }
2025
+ { key: "SELECT_TAB", name: "Select Tab", payload: [
2026
+ { name: "tab", type: "string", required: true }
2027
+ ] }
1968
2028
  ],
1969
2029
  transitions: [
1970
- { from: "idle", to: "idle", event: "INIT", effects: [["fetch", entityName], ["render-ui", "main", mainView]] },
1971
- { from: "idle", to: "idle", event: "SELECT_TAB", effects: [["fetch", entityName], ["render-ui", "main", mainView]] }
2030
+ { from: "idle", to: "idle", event: "INIT", effects: [["fetch", entityName], ["render-ui", "main", initView]] },
2031
+ { from: "idle", to: "idle", event: "SELECT_TAB", effects: [["fetch", entityName], ["render-ui", "main", tabSelectedView]] }
1972
2032
  ]
1973
2033
  }
1974
2034
  };
@@ -2024,7 +2084,6 @@ function buildTrait12(c) {
2024
2084
  align: "center",
2025
2085
  children: [
2026
2086
  {
2027
- // Neutral icon in idle (not the spinner — that lives only in the loading state)
2028
2087
  type: "stack",
2029
2088
  direction: "horizontal",
2030
2089
  gap: "sm",
@@ -2035,41 +2094,24 @@ function buildTrait12(c) {
2035
2094
  ]
2036
2095
  },
2037
2096
  { type: "divider" },
2038
- // Contextual description of what this loading operation does
2039
2097
  {
2040
2098
  type: "typography",
2041
2099
  variant: "body",
2042
2100
  color: "muted",
2043
- content: `Ready to load ${title.toLowerCase()}. Click Start to begin.`
2044
- },
2045
- { type: "button", label: "Start", event: "START", variant: "primary", icon: "play" }
2046
- ]
2047
- };
2048
- const loadingView = {
2049
- type: "stack",
2050
- direction: "vertical",
2051
- gap: "lg",
2052
- align: "center",
2053
- children: [
2054
- {
2055
- // Spinner icon appears only in the loading state — not permanently
2056
- type: "stack",
2057
- direction: "horizontal",
2058
- gap: "sm",
2059
- align: "center",
2060
- children: [
2061
- { type: "icon", name: "loader", size: "lg" },
2062
- { type: "typography", content: "Loading...", variant: "h2" }
2063
- ]
2064
- },
2065
- { type: "divider" },
2066
- { type: "progress-bar", value: 50 },
2067
- {
2068
- type: "typography",
2069
- variant: "caption",
2070
- color: "muted",
2071
- content: "Please wait while the operation completes."
2072
- }
2101
+ content: `Ready to load ${title.toLowerCase()}. Click Start to begin.`
2102
+ },
2103
+ { type: "button", label: "Start", event: "START", variant: "primary", icon: "play" }
2104
+ ]
2105
+ };
2106
+ const loadingView = {
2107
+ type: "stack",
2108
+ direction: "vertical",
2109
+ gap: "lg",
2110
+ align: "center",
2111
+ children: [
2112
+ { type: "loading-state", title: "Loading", message: `Loading ${title.toLowerCase()}...` },
2113
+ { type: "progress-bar", value: 50, showPercentage: true },
2114
+ { type: "skeleton", variant: "text" }
2073
2115
  ]
2074
2116
  };
2075
2117
  const successView = {
@@ -2089,7 +2131,7 @@ function buildTrait12(c) {
2089
2131
  ]
2090
2132
  },
2091
2133
  { type: "divider" },
2092
- { type: "typography", variant: "body", content: "Operation completed successfully." },
2134
+ { type: "alert", variant: "success", message: "Operation completed successfully." },
2093
2135
  { type: "button", label: "Reset", event: "RESET", variant: "ghost", icon: "rotate-ccw" }
2094
2136
  ]
2095
2137
  };
@@ -2099,18 +2141,7 @@ function buildTrait12(c) {
2099
2141
  gap: "lg",
2100
2142
  align: "center",
2101
2143
  children: [
2102
- {
2103
- type: "stack",
2104
- direction: "horizontal",
2105
- gap: "md",
2106
- align: "center",
2107
- children: [
2108
- { type: "icon", name: "alert-circle", size: "lg" },
2109
- { type: "typography", content: "Error", variant: "h2" }
2110
- ]
2111
- },
2112
- { type: "divider" },
2113
- { type: "typography", variant: "body", content: "Something went wrong." },
2144
+ { type: "error-state", title: "Error", message: "Something went wrong. Please try again.", onRetry: "START" },
2114
2145
  {
2115
2146
  type: "stack",
2116
2147
  direction: "horizontal",
@@ -2233,11 +2264,8 @@ function stdLoading(params) {
2233
2264
  function resolve14(params) {
2234
2265
  const { entityName } = params;
2235
2266
  const baseFields = ensureIdField(params.fields);
2236
- const fields = [
2237
- ...baseFields,
2238
- ...baseFields.some((f) => f.name === "selectedId") ? [] : [{ name: "selectedId", type: "string", default: "" }]
2239
- ];
2240
- const nonIdFields = baseFields.filter((f) => f.name !== "id" && f.name !== "selectedId");
2267
+ const fields = baseFields;
2268
+ const nonIdFields = baseFields.filter((f) => f.name !== "id");
2241
2269
  const p = plural(entityName);
2242
2270
  return {
2243
2271
  entityName,
@@ -2274,7 +2302,6 @@ function buildTrait13(c) {
2274
2302
  ]
2275
2303
  },
2276
2304
  { type: "divider" },
2277
- // Meaningful action prompt using entity name
2278
2305
  {
2279
2306
  type: "typography",
2280
2307
  variant: "caption",
@@ -2288,16 +2315,14 @@ function buildTrait13(c) {
2288
2315
  emptyTitle: `No ${pluralName.toLowerCase()} yet`,
2289
2316
  emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
2290
2317
  className: "transition-shadow hover:shadow-md cursor-pointer",
2291
- children: [{
2292
- // Checkbox-style affordance on LEFT of each row, then the entity name
2318
+ itemActions: [{ label: "Select", event: "SELECT", icon: "check" }],
2319
+ renderItem: ["fn", "item", {
2293
2320
  type: "stack",
2294
2321
  direction: "horizontal",
2295
2322
  gap: "sm",
2296
2323
  align: "center",
2297
2324
  children: [
2298
- { type: "icon", name: "circle", size: "sm", color: "muted" },
2299
- { type: "typography", variant: "h4", content: `@entity.${displayField}` },
2300
- { type: "button", label: "Select", event: "SELECT", variant: "ghost", icon: "check" }
2325
+ { type: "checkbox", label: `@item.${displayField}` }
2301
2326
  ]
2302
2327
  }]
2303
2328
  }
@@ -2339,22 +2364,35 @@ function buildTrait13(c) {
2339
2364
  },
2340
2365
  { type: "divider" },
2341
2366
  {
2342
- type: "stack",
2343
- direction: "horizontal",
2344
- gap: "md",
2345
- align: "center",
2346
- children: [
2347
- { type: "typography", variant: "caption", content: "Selected ID:" },
2348
- { type: "typography", variant: "body", content: "@entity.selectedId" }
2349
- ]
2367
+ type: "alert",
2368
+ variant: "info",
2369
+ message: ["concat", "Selected: ", "@payload.id"]
2370
+ },
2371
+ {
2372
+ type: "data-grid",
2373
+ entity: entityName,
2374
+ emptyIcon: "inbox",
2375
+ emptyTitle: `No ${pluralName.toLowerCase()} yet`,
2376
+ emptyDescription: `Add ${pluralName.toLowerCase()} to see them here.`,
2377
+ itemActions: [{ label: "Select", event: "SELECT", icon: "check" }],
2378
+ renderItem: ["fn", "item", {
2379
+ type: "stack",
2380
+ direction: "horizontal",
2381
+ gap: "sm",
2382
+ align: "center",
2383
+ children: [
2384
+ { type: "checkbox", label: `@item.${displayField}`, checked: ["==", "@item.id", "@payload.id"] }
2385
+ ]
2386
+ }]
2350
2387
  },
2388
+ { type: "divider" },
2351
2389
  {
2352
2390
  type: "stack",
2353
2391
  direction: "horizontal",
2354
2392
  gap: "sm",
2355
2393
  justify: "center",
2356
2394
  children: [
2357
- { type: "button", label: "Confirm", event: "CONFIRM_SELECTION", variant: "primary", icon: "check" },
2395
+ { type: "button", label: "Confirm", event: "CONFIRM_SELECTION", actionPayload: { id: "@payload.id" }, variant: "primary", icon: "check" },
2358
2396
  { type: "button", label: "Deselect", event: "DESELECT", variant: "ghost", icon: "x" }
2359
2397
  ]
2360
2398
  }
@@ -2386,6 +2424,11 @@ function buildTrait13(c) {
2386
2424
  ]
2387
2425
  },
2388
2426
  { type: "divider" },
2427
+ {
2428
+ type: "alert",
2429
+ variant: "success",
2430
+ message: "Selection confirmed successfully."
2431
+ },
2389
2432
  {
2390
2433
  type: "stack",
2391
2434
  direction: "horizontal",
@@ -2393,7 +2436,7 @@ function buildTrait13(c) {
2393
2436
  align: "center",
2394
2437
  children: [
2395
2438
  { type: "typography", variant: "caption", content: "Selected ID:" },
2396
- { type: "typography", variant: "body", content: "@entity.selectedId" }
2439
+ { type: "typography", variant: "body", content: "@payload.id" }
2397
2440
  ]
2398
2441
  },
2399
2442
  { type: "button", label: "Clear Selection", event: "CLEAR", variant: "ghost", icon: "rotate-ccw" }
@@ -2416,7 +2459,9 @@ function buildTrait13(c) {
2416
2459
  ] },
2417
2460
  { key: "DESELECT", name: "Deselect" },
2418
2461
  { key: "CLEAR", name: "Clear" },
2419
- { key: "CONFIRM_SELECTION", name: "Confirm Selection" }
2462
+ { key: "CONFIRM_SELECTION", name: "Confirm Selection", payload: [
2463
+ { name: "id", type: "string", required: true }
2464
+ ] }
2420
2465
  ],
2421
2466
  transitions: [
2422
2467
  {
@@ -2433,7 +2478,7 @@ function buildTrait13(c) {
2433
2478
  to: "selecting",
2434
2479
  event: "SELECT",
2435
2480
  effects: [
2436
- ["set", "@entity.selectedId", "@payload.id"],
2481
+ ["fetch", entityName],
2437
2482
  ["render-ui", "main", selectingView]
2438
2483
  ]
2439
2484
  },
@@ -2442,7 +2487,7 @@ function buildTrait13(c) {
2442
2487
  to: "selecting",
2443
2488
  event: "SELECT",
2444
2489
  effects: [
2445
- ["set", "@entity.selectedId", "@payload.id"],
2490
+ ["fetch", entityName],
2446
2491
  ["render-ui", "main", selectingView]
2447
2492
  ]
2448
2493
  },
@@ -2451,7 +2496,6 @@ function buildTrait13(c) {
2451
2496
  to: "idle",
2452
2497
  event: "DESELECT",
2453
2498
  effects: [
2454
- ["set", "@entity.selectedId", ""],
2455
2499
  ["fetch", entityName],
2456
2500
  ["render-ui", "main", idleView]
2457
2501
  ]
@@ -2461,7 +2505,6 @@ function buildTrait13(c) {
2461
2505
  to: "idle",
2462
2506
  event: "CLEAR",
2463
2507
  effects: [
2464
- ["set", "@entity.selectedId", ""],
2465
2508
  ["fetch", entityName],
2466
2509
  ["render-ui", "main", idleView]
2467
2510
  ]
@@ -2479,7 +2522,6 @@ function buildTrait13(c) {
2479
2522
  to: "idle",
2480
2523
  event: "CLEAR",
2481
2524
  effects: [
2482
- ["set", "@entity.selectedId", ""],
2483
2525
  ["fetch", entityName],
2484
2526
  ["render-ui", "main", idleView]
2485
2527
  ]
@@ -2535,6 +2577,7 @@ function resolve15(params) {
2535
2577
  function buildEntity14(c) {
2536
2578
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
2537
2579
  }
2580
+ var ef4 = (field) => ["object/get", ["array/first", "@entity"], field];
2538
2581
  function buildTrait14(c) {
2539
2582
  const { entityName, headerIcon, pageTitle } = c;
2540
2583
  const mainView = {
@@ -2548,17 +2591,22 @@ function buildTrait14(c) {
2548
2591
  { type: "typography", content: pageTitle, variant: "h2" }
2549
2592
  ] },
2550
2593
  { type: "stack", direction: "horizontal", gap: "sm", align: "center", children: [
2551
- { type: "button", label: "Undo", event: "UNDO", variant: "ghost", icon: "undo" },
2552
- { type: "button", label: "Redo", event: "REDO", variant: "ghost", icon: "redo" },
2553
- // gap-6 spacer between Redo and Clear to prevent misclicking destructive action
2594
+ { type: "tooltip", content: "Undo the last action", children: [
2595
+ { type: "button", label: "Undo", event: "UNDO", variant: "ghost", icon: "undo" }
2596
+ ] },
2597
+ { type: "tooltip", content: "Redo the last undone action", children: [
2598
+ { type: "button", label: "Redo", event: "REDO", variant: "ghost", icon: "redo" }
2599
+ ] },
2554
2600
  { type: "divider", orientation: "vertical" },
2555
- { type: "button", label: "Clear", event: "CLEAR", variant: "ghost", icon: "trash-2" }
2601
+ { type: "tooltip", content: "Clear all history", children: [
2602
+ { type: "button", label: "Clear", event: "CLEAR", variant: "ghost", icon: "trash-2" }
2603
+ ] }
2556
2604
  ] }
2557
2605
  ] },
2558
2606
  { type: "divider" },
2559
2607
  { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
2560
2608
  { type: "typography", variant: "caption", color: "muted", content: "Last action:" },
2561
- { type: "badge", label: "@entity.current" }
2609
+ { type: "badge", label: ef4("current") }
2562
2610
  ] }
2563
2611
  ]
2564
2612
  };
@@ -2655,6 +2703,7 @@ function resolve16(params) {
2655
2703
  function buildEntity15(c) {
2656
2704
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
2657
2705
  }
2706
+ var ef5 = (field) => ["object/get", ["array/first", "@entity"], field];
2658
2707
  function buildTrait15(c) {
2659
2708
  const { entityName, inputLabel, placeholder, headerIcon } = c;
2660
2709
  const inputView = {
@@ -2674,22 +2723,14 @@ function buildTrait15(c) {
2674
2723
  },
2675
2724
  { type: "divider" },
2676
2725
  {
2677
- // Form field pattern: label above, input below, help text below input
2678
- type: "stack",
2679
- direction: "vertical",
2680
- gap: "sm",
2726
+ type: "form-field",
2727
+ label: inputLabel,
2728
+ hint: "Type to enter a value.",
2681
2729
  children: [
2682
- { type: "typography", variant: "caption", content: inputLabel },
2683
- { type: "input", placeholder, event: "CHANGE" },
2684
- // show current entered value as status below the field (not a mystery bar)
2685
- {
2686
- type: "typography",
2687
- variant: "caption",
2688
- color: "muted",
2689
- content: "@entity.value"
2690
- }
2730
+ { type: "input", placeholder, event: "CHANGE" }
2691
2731
  ]
2692
- }
2732
+ },
2733
+ { type: "typography", variant: "caption", color: "muted", content: ef5("value") }
2693
2734
  ]
2694
2735
  };
2695
2736
  const validatingView = {
@@ -2709,21 +2750,14 @@ function buildTrait15(c) {
2709
2750
  },
2710
2751
  { type: "divider" },
2711
2752
  {
2712
- type: "stack",
2713
- direction: "vertical",
2714
- gap: "sm",
2753
+ type: "form-field",
2754
+ label: inputLabel,
2755
+ hint: "Validating...",
2715
2756
  children: [
2716
- { type: "typography", variant: "caption", content: inputLabel },
2717
- { type: "input", placeholder, event: "CHANGE" },
2718
- // semantic validation message — shown only in validating state
2719
- {
2720
- type: "typography",
2721
- variant: "caption",
2722
- color: "muted",
2723
- content: "Validating..."
2724
- }
2757
+ { type: "input", placeholder, event: "CHANGE" }
2725
2758
  ]
2726
- }
2759
+ },
2760
+ { type: "alert", variant: "info", message: "Validating input..." }
2727
2761
  ]
2728
2762
  };
2729
2763
  return {
@@ -2876,7 +2910,6 @@ function buildEntity16(c) {
2876
2910
  }
2877
2911
  function buildStepUI(c, stepIndex) {
2878
2912
  const step = c.steps[stepIndex];
2879
- const stepNumber = stepIndex + 1;
2880
2913
  const isFirst = stepIndex === 0;
2881
2914
  const navButtons = [];
2882
2915
  if (!isFirst) {
@@ -2898,7 +2931,7 @@ function buildStepUI(c, stepIndex) {
2898
2931
  { type: "typography", content: c.wizardTitle, variant: "h2" }
2899
2932
  ]
2900
2933
  },
2901
- { type: "badge", label: `Step ${stepNumber} of ${c.totalSteps}` },
2934
+ { type: "progress-dots", count: c.totalSteps, currentIndex: stepIndex },
2902
2935
  { type: "wizard-progress", steps: c.wizardProgressSteps, currentStep: stepIndex },
2903
2936
  { type: "divider" },
2904
2937
  { type: "typography", content: step.name, variant: "h3" },
@@ -2921,7 +2954,7 @@ function buildReviewUI(c) {
2921
2954
  justify: "space-between",
2922
2955
  children: [
2923
2956
  { type: "typography", variant: "caption", content: field.name.charAt(0).toUpperCase() + field.name.slice(1) },
2924
- { type: "typography", variant: "body", content: `@entity.${field.name}` }
2957
+ { type: "typography", variant: "body", content: `@item.${field.name}` }
2925
2958
  ]
2926
2959
  }));
2927
2960
  return {
@@ -2945,24 +2978,20 @@ function buildReviewUI(c) {
2945
2978
  {
2946
2979
  type: "data-list",
2947
2980
  entity: c.entityName,
2948
- children: [
2949
- {
2950
- type: "stack",
2951
- direction: "vertical",
2952
- gap: "sm",
2953
- children: reviewDetailChildren
2954
- }
2955
- ]
2981
+ renderItem: ["fn", "item", {
2982
+ type: "stack",
2983
+ direction: "vertical",
2984
+ gap: "sm",
2985
+ children: reviewDetailChildren
2986
+ }]
2956
2987
  },
2957
2988
  {
2958
- type: "stack",
2959
- direction: "horizontal",
2960
- gap: "sm",
2961
- justify: "end",
2962
- children: [
2963
- { type: "button", label: "Back", event: "PREV", variant: "ghost", icon: "arrow-left" },
2964
- { type: "button", label: c.submitButtonLabel, event: "COMPLETE", variant: "primary", icon: "check" }
2965
- ]
2989
+ type: "wizard-navigation",
2990
+ currentStep: c.totalSteps,
2991
+ totalSteps: c.totalSteps + 1,
2992
+ showBack: true,
2993
+ showComplete: true,
2994
+ showNext: false
2966
2995
  }
2967
2996
  ]
2968
2997
  };
@@ -3128,20 +3157,28 @@ function resolve18(params) {
3128
3157
  isInitial: params.isInitial ?? false
3129
3158
  };
3130
3159
  }
3160
+ var ef6 = (field) => ["object/get", ["array/first", "@entity"], field];
3131
3161
  function buildTrait17(c) {
3132
3162
  const { entityName, displayFields, headerIcon, pageTitle, refreshButtonLabel, columns } = c;
3133
- const cardChildren = displayFields.map((f) => ({
3134
- type: "card",
3135
- children: [{
3136
- type: "stack",
3137
- direction: "vertical",
3138
- gap: "sm",
3139
- children: [
3140
- { type: "typography", variant: "caption", content: f.charAt(0).toUpperCase() + f.slice(1) },
3141
- { type: "typography", variant: "h3", content: `@entity.${f}` }
3142
- ]
3143
- }]
3144
- }));
3163
+ const cardChildren = displayFields.map((f) => {
3164
+ const field = c.nonIdFields.find((nf) => nf.name === f);
3165
+ const isNumeric = field?.type === "number";
3166
+ if (isNumeric) {
3167
+ return { type: "stat-display", label: f.charAt(0).toUpperCase() + f.slice(1), value: ef6(f) };
3168
+ }
3169
+ return {
3170
+ type: "card",
3171
+ children: [{
3172
+ type: "stack",
3173
+ direction: "vertical",
3174
+ gap: "sm",
3175
+ children: [
3176
+ { type: "typography", variant: "caption", content: f.charAt(0).toUpperCase() + f.slice(1) },
3177
+ { type: "typography", variant: "h3", content: ef6(f) }
3178
+ ]
3179
+ }]
3180
+ };
3181
+ });
3145
3182
  const mainView = {
3146
3183
  type: "stack",
3147
3184
  direction: "vertical",
@@ -3246,6 +3283,7 @@ function buildTrait18(c) {
3246
3283
  ]
3247
3284
  },
3248
3285
  { type: "divider" },
3286
+ { type: "typography", variant: "body", color: "muted", content: `Ready to start ${entityName.toLowerCase()} operation.` },
3249
3287
  { type: "button", label: "Start", event: "START", variant: "primary", icon: "play" }
3250
3288
  ]
3251
3289
  };
@@ -3255,8 +3293,8 @@ function buildTrait18(c) {
3255
3293
  gap: "lg",
3256
3294
  align: "center",
3257
3295
  children: [
3258
- { type: "icon", name: "loader", size: "lg" },
3259
- { type: "typography", content: loadingMessage, variant: "h3" }
3296
+ { type: "loading-state", title: loadingMessage, message: `Processing ${entityName.toLowerCase()}...` },
3297
+ { type: "skeleton", variant: "text" }
3260
3298
  ]
3261
3299
  };
3262
3300
  const successUI = {
@@ -3266,7 +3304,7 @@ function buildTrait18(c) {
3266
3304
  align: "center",
3267
3305
  children: [
3268
3306
  { type: "icon", name: "check-circle", size: "lg" },
3269
- { type: "typography", content: successMessage, variant: "h3" },
3307
+ { type: "alert", variant: "success", message: successMessage },
3270
3308
  {
3271
3309
  type: "stack",
3272
3310
  direction: "horizontal",
@@ -3290,8 +3328,7 @@ function buildTrait18(c) {
3290
3328
  gap: "lg",
3291
3329
  align: "center",
3292
3330
  children: [
3293
- { type: "icon", name: "alert-circle", size: "lg" },
3294
- { type: "typography", content: errorMessage, variant: "h3" },
3331
+ { type: "error-state", title: "Operation Failed", message: errorMessage, onRetry: retryable ? "RETRY" : void 0 },
3295
3332
  {
3296
3333
  type: "stack",
3297
3334
  direction: "horizontal",
@@ -3622,6 +3659,7 @@ function resolve21(params) {
3622
3659
  function buildEntity19(c) {
3623
3660
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence, collection: c.collection });
3624
3661
  }
3662
+ var ef7 = (field) => ["object/get", ["array/first", "@entity"], field];
3625
3663
  function buildTrait20(c) {
3626
3664
  const { entityName, gameTitle, menuTitle, pauseTitle, gameoverTitle } = c;
3627
3665
  const menuUI = {
@@ -3635,8 +3673,8 @@ function buildTrait20(c) {
3635
3673
  const playingUI = {
3636
3674
  type: "game-hud",
3637
3675
  stats: [
3638
- { label: "Score", value: "@entity.score" },
3639
- { label: "Level", value: "@entity.level" }
3676
+ { label: "Score", value: ef7("score") },
3677
+ { label: "Level", value: ef7("level") }
3640
3678
  ]
3641
3679
  };
3642
3680
  const pausedModalUI = {
@@ -3651,8 +3689,8 @@ function buildTrait20(c) {
3651
3689
  type: "game-over-screen",
3652
3690
  title: gameoverTitle,
3653
3691
  stats: [
3654
- { label: "Score", value: "@entity.score" },
3655
- { label: "Level", value: "@entity.level" }
3692
+ { label: "Score", value: ef7("score") },
3693
+ { label: "Level", value: ef7("level") }
3656
3694
  ],
3657
3695
  menuItems: [
3658
3696
  { label: "Play Again", event: "RESTART", variant: "primary" },
@@ -3718,19 +3756,19 @@ function buildTrait20(c) {
3718
3756
  event: "PAUSE",
3719
3757
  effects: [["render-ui", "modal", pausedModalUI]]
3720
3758
  },
3721
- // RESUME: paused -> playing
3759
+ // RESUME: paused -> playing (dismiss modal, re-render main with HUD)
3722
3760
  {
3723
3761
  from: "paused",
3724
3762
  to: "playing",
3725
3763
  event: "RESUME",
3726
- effects: [["render-ui", "modal", null]]
3764
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
3727
3765
  },
3728
3766
  // CLOSE: paused -> playing (modal exit requirement)
3729
3767
  {
3730
3768
  from: "paused",
3731
3769
  to: "playing",
3732
3770
  event: "CLOSE",
3733
- effects: [["render-ui", "modal", null]]
3771
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
3734
3772
  },
3735
3773
  // GAME_OVER: playing -> gameover
3736
3774
  {
@@ -3802,19 +3840,35 @@ function resolve22(params) {
3802
3840
  };
3803
3841
  }
3804
3842
  function buildEntity20(c) {
3805
- return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence, collection: c.collection });
3843
+ const fields = [
3844
+ ...c.fields.filter((f) => !["x", "y"].includes(f.name)),
3845
+ { name: "x", type: "number", default: 0 },
3846
+ { name: "y", type: "number", default: 0 }
3847
+ ];
3848
+ return makeEntity({ name: c.entityName, fields, persistence: c.persistence, collection: c.collection });
3806
3849
  }
3850
+ var ef8 = (field) => ["object/get", ["array/first", "@entity"], field];
3807
3851
  function buildTrait21(c) {
3808
3852
  const { entityName, nonIdFields, headerIcon, pageTitle } = c;
3809
- const fieldSummaryChildren = nonIdFields.slice(0, 4).map((field) => ({
3810
- type: "stack",
3811
- direction: "horizontal",
3812
- gap: "md",
3813
- children: [
3814
- { type: "typography", variant: "caption", content: field.name.charAt(0).toUpperCase() + field.name.slice(1) },
3815
- { type: "typography", variant: "body", content: `@entity.${field.name}` }
3816
- ]
3817
- }));
3853
+ const fieldSummaryChildren = [
3854
+ {
3855
+ type: "simple-grid",
3856
+ columns: 2,
3857
+ children: [
3858
+ { type: "stat-display", label: "X", value: ef8(nonIdFields.find((f) => f.name === "x")?.name ?? "x") },
3859
+ { type: "stat-display", label: "Y", value: ef8(nonIdFields.find((f) => f.name === "y")?.name ?? "y") }
3860
+ ]
3861
+ },
3862
+ ...nonIdFields.slice(0, 4).filter((f) => f.name !== "x" && f.name !== "y").map((field) => ({
3863
+ type: "stack",
3864
+ direction: "horizontal",
3865
+ gap: "md",
3866
+ children: [
3867
+ { type: "typography", variant: "caption", content: field.name.charAt(0).toUpperCase() + field.name.slice(1) },
3868
+ { type: "typography", variant: "body", content: ef8(field.name) }
3869
+ ]
3870
+ }))
3871
+ ];
3818
3872
  const idleMainUI = {
3819
3873
  type: "stack",
3820
3874
  direction: "vertical",
@@ -3835,7 +3889,7 @@ function buildTrait21(c) {
3835
3889
  { type: "typography", content: pageTitle, variant: "h2" }
3836
3890
  ]
3837
3891
  },
3838
- { type: "badge", label: "Idle" }
3892
+ { type: "status-dot", status: "inactive", label: "Idle" }
3839
3893
  ]
3840
3894
  },
3841
3895
  { type: "divider" },
@@ -3872,7 +3926,7 @@ function buildTrait21(c) {
3872
3926
  { type: "typography", content: pageTitle, variant: "h2" }
3873
3927
  ]
3874
3928
  },
3875
- { type: "badge", label: "Moving" }
3929
+ { type: "status-dot", status: "active", pulse: true, label: "Moving" }
3876
3930
  ]
3877
3931
  },
3878
3932
  { type: "divider" },
@@ -4078,15 +4132,15 @@ function buildTrait22(c) {
4078
4132
  align: "center",
4079
4133
  children: [
4080
4134
  { type: "icon", name: headerIcon, size: "sm" },
4081
- { type: "typography", variant: "h4", content: `@entity.${listFields[0] ?? "id"}` }
4135
+ { type: "typography", variant: "h4", content: `@item.${listFields[0] ?? "id"}` }
4082
4136
  ]
4083
4137
  },
4084
- ...listFields.length > 1 ? [{ type: "badge", label: `@entity.${listFields[1]}` }] : []
4138
+ ...listFields.length > 1 ? [{ type: "badge", label: `@item.${listFields[1]}` }] : []
4085
4139
  ]
4086
4140
  }
4087
4141
  ];
4088
4142
  if (listFields.length > 2) {
4089
- listItemChildren.push({ type: "typography", variant: "caption", content: `@entity.${listFields[2]}` });
4143
+ listItemChildren.push({ type: "typography", variant: "caption", content: `@item.${listFields[2]}` });
4090
4144
  }
4091
4145
  const headerBar = {
4092
4146
  type: "stack",
@@ -4113,13 +4167,14 @@ function buildTrait22(c) {
4113
4167
  headerBar,
4114
4168
  { type: "divider" },
4115
4169
  {
4116
- type: "data-grid",
4170
+ type: "data-list",
4117
4171
  entity: entityName,
4172
+ groupBy: "status",
4118
4173
  emptyIcon: "inbox",
4119
4174
  emptyTitle,
4120
4175
  emptyDescription,
4121
4176
  itemActions: [{ label: "Accept", event: "ACCEPT" }],
4122
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4177
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4123
4178
  }
4124
4179
  ]
4125
4180
  };
@@ -4147,6 +4202,7 @@ function buildTrait22(c) {
4147
4202
  ]
4148
4203
  },
4149
4204
  { type: "divider" },
4205
+ { type: "progress-bar", value: 50, showPercentage: true },
4150
4206
  {
4151
4207
  type: "data-grid",
4152
4208
  entity: entityName,
@@ -4158,7 +4214,7 @@ function buildTrait22(c) {
4158
4214
  { label: "Complete", event: "COMPLETE" },
4159
4215
  { label: "Fail", event: "FAIL", variant: "danger" }
4160
4216
  ],
4161
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4217
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4162
4218
  }
4163
4219
  ]
4164
4220
  };
@@ -4170,7 +4226,7 @@ function buildTrait22(c) {
4170
4226
  children: [
4171
4227
  { type: "icon", name: "check-circle", size: "lg" },
4172
4228
  { type: "typography", content: "Quest Complete", variant: "h2" },
4173
- { type: "typography", content: "Congratulations! The quest has been completed.", variant: "body" },
4229
+ { type: "alert", variant: "success", message: "Congratulations! The quest has been completed." },
4174
4230
  { type: "button", label: "View Quests", event: "RESET", variant: "primary", icon: "arrow-left" }
4175
4231
  ]
4176
4232
  };
@@ -4182,7 +4238,7 @@ function buildTrait22(c) {
4182
4238
  children: [
4183
4239
  { type: "icon", name: "x-circle", size: "lg" },
4184
4240
  { type: "typography", content: "Quest Failed", variant: "h2" },
4185
- { type: "typography", content: "The quest was not completed. You can try again.", variant: "body" },
4241
+ { type: "alert", variant: "danger", message: "The quest was not completed. You can try again." },
4186
4242
  { type: "button", label: "View Quests", event: "RESET", variant: "primary", icon: "arrow-left" }
4187
4243
  ]
4188
4244
  };
@@ -4279,19 +4335,27 @@ function buildTrait22(c) {
4279
4335
  ["render-ui", "main", activeMainUI]
4280
4336
  ]
4281
4337
  },
4282
- // CANCEL: progressing -> active
4338
+ // CANCEL: progressing -> active (re-render main to avoid stale content)
4283
4339
  {
4284
4340
  from: "progressing",
4285
4341
  to: "active",
4286
4342
  event: "CANCEL",
4287
- effects: [["render-ui", "modal", null]]
4343
+ effects: [
4344
+ ["render-ui", "modal", null],
4345
+ ["fetch", entityName],
4346
+ ["render-ui", "main", activeMainUI]
4347
+ ]
4288
4348
  },
4289
- // CLOSE: progressing -> active
4349
+ // CLOSE: progressing -> active (re-render main to avoid stale content)
4290
4350
  {
4291
4351
  from: "progressing",
4292
4352
  to: "active",
4293
4353
  event: "CLOSE",
4294
- effects: [["render-ui", "modal", null]]
4354
+ effects: [
4355
+ ["render-ui", "modal", null],
4356
+ ["fetch", entityName],
4357
+ ["render-ui", "main", activeMainUI]
4358
+ ]
4295
4359
  },
4296
4360
  // COMPLETE: active -> complete
4297
4361
  {
@@ -4399,15 +4463,15 @@ function buildTrait23(c) {
4399
4463
  align: "center",
4400
4464
  children: [
4401
4465
  { type: "icon", name: "map-pin", size: "sm" },
4402
- { type: "typography", variant: "h4", content: `@entity.${listFields[0] ?? "id"}` }
4466
+ { type: "typography", variant: "h4", content: `@item.${listFields[0] ?? "id"}` }
4403
4467
  ]
4404
4468
  },
4405
- ...listFields.length > 1 ? [{ type: "badge", label: `@entity.${listFields[1]}` }] : []
4469
+ ...listFields.length > 1 ? [{ type: "badge", label: `@item.${listFields[1]}` }] : []
4406
4470
  ]
4407
4471
  }
4408
4472
  ];
4409
4473
  if (listFields.length > 2) {
4410
- listItemChildren.push({ type: "typography", variant: "caption", content: `@entity.${listFields[2]}` });
4474
+ listItemChildren.push({ type: "typography", variant: "caption", content: `@item.${listFields[2]}` });
4411
4475
  }
4412
4476
  const exploringMainUI = {
4413
4477
  type: "stack",
@@ -4429,10 +4493,11 @@ function buildTrait23(c) {
4429
4493
  { type: "typography", content: worldTitle, variant: "h2" }
4430
4494
  ]
4431
4495
  },
4432
- { type: "badge", label: "Exploring" }
4496
+ { type: "status-dot", status: "active", pulse: false, label: "Exploring" }
4433
4497
  ]
4434
4498
  },
4435
4499
  { type: "divider" },
4500
+ { type: "map-view", markers: [], height: "200px", zoom: 10 },
4436
4501
  {
4437
4502
  type: "data-grid",
4438
4503
  entity: entityName,
@@ -4440,7 +4505,7 @@ function buildTrait23(c) {
4440
4505
  emptyTitle,
4441
4506
  emptyDescription,
4442
4507
  itemActions: [{ label: "Travel", event: "TRAVEL" }],
4443
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4508
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4444
4509
  }
4445
4510
  ]
4446
4511
  };
@@ -4483,7 +4548,7 @@ function buildTrait23(c) {
4483
4548
  { type: "typography", content: pageTitle, variant: "h2" }
4484
4549
  ]
4485
4550
  },
4486
- { type: "badge", label: "Entered" }
4551
+ { type: "status-dot", status: "success", label: "Entered" }
4487
4552
  ]
4488
4553
  },
4489
4554
  { type: "divider" },
@@ -4493,7 +4558,7 @@ function buildTrait23(c) {
4493
4558
  emptyIcon: "inbox",
4494
4559
  emptyTitle: "Nothing here",
4495
4560
  emptyDescription: "This zone is empty.",
4496
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4561
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4497
4562
  },
4498
4563
  { type: "divider" },
4499
4564
  {
@@ -4608,50 +4673,79 @@ function resolve25(params) {
4608
4673
  };
4609
4674
  }
4610
4675
  function buildEntity23(c) {
4611
- return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence, collection: c.collection });
4676
+ const fields = [
4677
+ ...c.fields.filter((f) => !["failureCount", "successCount", "threshold"].includes(f.name)),
4678
+ { name: "failureCount", type: "number", default: 0 },
4679
+ { name: "successCount", type: "number", default: 0 },
4680
+ { name: "threshold", type: "number", default: 5 }
4681
+ ];
4682
+ return makeEntity({ name: c.entityName, fields, persistence: c.persistence, collection: c.collection });
4612
4683
  }
4684
+ var ef9 = (field) => ["object/get", ["array/first", "@entity"], field];
4613
4685
  function buildTrait24(c) {
4614
4686
  const { entityName, headerIcon, closedLabel, openLabel, halfOpenLabel } = c;
4615
4687
  const closedUI = {
4616
4688
  type: "stack",
4617
4689
  direction: "vertical",
4618
4690
  gap: "lg",
4619
- align: "center",
4620
4691
  children: [
4621
4692
  {
4622
4693
  type: "stack",
4623
4694
  direction: "horizontal",
4624
4695
  gap: "md",
4625
4696
  align: "center",
4697
+ justify: "space-between",
4626
4698
  children: [
4627
- { type: "icon", name: headerIcon, size: "lg" },
4628
- { type: "typography", content: entityName, variant: "h2" }
4699
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
4700
+ { type: "icon", name: headerIcon, size: "lg" },
4701
+ { type: "typography", content: entityName, variant: "h2" }
4702
+ ] },
4703
+ { type: "status-dot", status: "success", pulse: false, label: closedLabel }
4629
4704
  ]
4630
4705
  },
4631
4706
  { type: "divider" },
4632
- { type: "badge", label: closedLabel },
4633
- { type: "typography", content: "Service is healthy. All requests are being processed.", variant: "body" }
4707
+ { type: "alert", variant: "success", message: "Service is healthy. All requests are being processed." },
4708
+ {
4709
+ type: "simple-grid",
4710
+ columns: 2,
4711
+ children: [
4712
+ { type: "stat-display", label: "Failures", value: ef9("failureCount") },
4713
+ { type: "stat-display", label: "Successes", value: ef9("successCount") }
4714
+ ]
4715
+ },
4716
+ { type: "meter", value: ef9("failureCount"), min: 0, max: ef9("threshold") }
4634
4717
  ]
4635
4718
  };
4636
4719
  const openUI = {
4637
4720
  type: "stack",
4638
4721
  direction: "vertical",
4639
4722
  gap: "lg",
4640
- align: "center",
4641
4723
  children: [
4642
4724
  {
4643
4725
  type: "stack",
4644
4726
  direction: "horizontal",
4645
4727
  gap: "md",
4646
4728
  align: "center",
4729
+ justify: "space-between",
4647
4730
  children: [
4648
- { type: "icon", name: "alert-triangle", size: "lg" },
4649
- { type: "typography", content: entityName, variant: "h2" }
4731
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
4732
+ { type: "icon", name: "alert-triangle", size: "lg" },
4733
+ { type: "typography", content: entityName, variant: "h2" }
4734
+ ] },
4735
+ { type: "status-dot", status: "error", pulse: true, label: openLabel }
4650
4736
  ]
4651
4737
  },
4652
4738
  { type: "divider" },
4653
- { type: "badge", label: openLabel },
4654
- { type: "typography", content: "Circuit is open. Requests are being rejected to prevent cascading failures.", variant: "body" },
4739
+ { type: "alert", variant: "danger", message: "Circuit is open. Requests are being rejected to prevent cascading failures." },
4740
+ {
4741
+ type: "simple-grid",
4742
+ columns: 2,
4743
+ children: [
4744
+ { type: "stat-display", label: "Failures", value: ef9("failureCount") },
4745
+ { type: "stat-display", label: "Successes", value: ef9("successCount") }
4746
+ ]
4747
+ },
4748
+ { type: "meter", value: ef9("failureCount"), min: 0, max: ef9("threshold") },
4655
4749
  { type: "button", label: "Reset", event: "RESET", variant: "ghost", icon: "rotate-ccw" }
4656
4750
  ]
4657
4751
  };
@@ -4659,21 +4753,31 @@ function buildTrait24(c) {
4659
4753
  type: "stack",
4660
4754
  direction: "vertical",
4661
4755
  gap: "lg",
4662
- align: "center",
4663
4756
  children: [
4664
4757
  {
4665
4758
  type: "stack",
4666
4759
  direction: "horizontal",
4667
4760
  gap: "md",
4668
4761
  align: "center",
4762
+ justify: "space-between",
4669
4763
  children: [
4670
- { type: "icon", name: "activity", size: "lg" },
4671
- { type: "typography", content: entityName, variant: "h2" }
4764
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
4765
+ { type: "icon", name: "activity", size: "lg" },
4766
+ { type: "typography", content: entityName, variant: "h2" }
4767
+ ] },
4768
+ { type: "status-dot", status: "warning", pulse: true, label: halfOpenLabel }
4672
4769
  ]
4673
4770
  },
4674
4771
  { type: "divider" },
4675
- { type: "badge", label: halfOpenLabel },
4676
- { type: "typography", content: "Testing recovery. Limited requests are being allowed through.", variant: "body" }
4772
+ { type: "alert", variant: "warning", message: "Testing recovery. Limited requests are being allowed through." },
4773
+ {
4774
+ type: "simple-grid",
4775
+ columns: 2,
4776
+ children: [
4777
+ { type: "stat-display", label: "Failures", value: ef9("failureCount") },
4778
+ { type: "stat-display", label: "Successes", value: ef9("successCount") }
4779
+ ]
4780
+ }
4677
4781
  ]
4678
4782
  };
4679
4783
  return {
@@ -4802,8 +4906,14 @@ function resolve26(params) {
4802
4906
  };
4803
4907
  }
4804
4908
  function buildEntity24(c) {
4805
- return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence, collection: c.collection });
4909
+ const fields = [
4910
+ ...c.fields.filter((f) => !["hitCount", "cacheAge"].includes(f.name)),
4911
+ { name: "hitCount", type: "number", default: 0 },
4912
+ { name: "cacheAge", type: "number", default: 0 }
4913
+ ];
4914
+ return makeEntity({ name: c.entityName, fields, persistence: c.persistence, collection: c.collection });
4806
4915
  }
4916
+ var ef10 = (field) => ["object/get", ["array/first", "@entity"], field];
4807
4917
  function buildTrait25(c) {
4808
4918
  const { entityName, listFields, headerIcon } = c;
4809
4919
  const { pageTitle, emptyTitle, emptyDescription } = c;
@@ -4821,15 +4931,15 @@ function buildTrait25(c) {
4821
4931
  align: "center",
4822
4932
  children: [
4823
4933
  { type: "icon", name: headerIcon, size: "sm" },
4824
- { type: "typography", variant: "h4", content: `@entity.${listFields[0] ?? "id"}` }
4934
+ { type: "typography", variant: "h4", content: `@item.${listFields[0] ?? "id"}` }
4825
4935
  ]
4826
4936
  },
4827
- ...listFields.length > 1 ? [{ type: "badge", label: `@entity.${listFields[1]}` }] : []
4937
+ ...listFields.length > 1 ? [{ type: "badge", label: `@item.${listFields[1]}` }] : []
4828
4938
  ]
4829
4939
  }
4830
4940
  ];
4831
4941
  if (listFields.length > 2) {
4832
- listItemChildren.push({ type: "typography", variant: "caption", content: `@entity.${listFields[2]}` });
4942
+ listItemChildren.push({ type: "typography", variant: "caption", content: `@item.${listFields[2]}` });
4833
4943
  }
4834
4944
  const headerBar = {
4835
4945
  type: "stack",
@@ -4854,7 +4964,16 @@ function buildTrait25(c) {
4854
4964
  direction: "vertical",
4855
4965
  gap: "lg",
4856
4966
  children: [
4857
- headerBar,
4967
+ {
4968
+ type: "stack",
4969
+ direction: "horizontal",
4970
+ gap: "md",
4971
+ justify: "space-between",
4972
+ children: [
4973
+ headerBar,
4974
+ { type: "status-dot", status: "inactive", pulse: false, label: "Empty" }
4975
+ ]
4976
+ },
4858
4977
  { type: "divider" },
4859
4978
  { type: "empty-state", icon: "inbox", title: emptyTitle, description: emptyDescription }
4860
4979
  ]
@@ -4883,21 +5002,30 @@ function buildTrait25(c) {
4883
5002
  type: "stack",
4884
5003
  direction: "horizontal",
4885
5004
  gap: "sm",
5005
+ align: "center",
4886
5006
  children: [
4887
- { type: "badge", label: "Cached" },
5007
+ { type: "status-dot", status: "success", pulse: false, label: "Cached" },
4888
5008
  { type: "button", label: "Invalidate", event: "INVALIDATE", variant: "ghost", icon: "trash" }
4889
5009
  ]
4890
5010
  }
4891
5011
  ]
4892
5012
  },
4893
5013
  { type: "divider" },
5014
+ {
5015
+ type: "simple-grid",
5016
+ columns: 2,
5017
+ children: [
5018
+ { type: "stat-display", label: "Hit Count", value: ef10("hitCount") },
5019
+ { type: "stat-display", label: "Cache Age", value: ef10("cacheAge") }
5020
+ ]
5021
+ },
4894
5022
  {
4895
5023
  type: "data-grid",
4896
5024
  entity: entityName,
4897
5025
  emptyIcon: "inbox",
4898
5026
  emptyTitle,
4899
5027
  emptyDescription,
4900
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
5028
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4901
5029
  }
4902
5030
  ]
4903
5031
  };
@@ -4925,21 +5053,23 @@ function buildTrait25(c) {
4925
5053
  type: "stack",
4926
5054
  direction: "horizontal",
4927
5055
  gap: "sm",
5056
+ align: "center",
4928
5057
  children: [
4929
- { type: "badge", label: "Stale" },
5058
+ { type: "status-dot", status: "warning", pulse: true, label: "Stale" },
4930
5059
  { type: "button", label: "Refresh", event: "REFRESH", variant: "primary", icon: "refresh-cw" }
4931
5060
  ]
4932
5061
  }
4933
5062
  ]
4934
5063
  },
4935
5064
  { type: "divider" },
5065
+ { type: "alert", variant: "warning", message: "Cache data is stale. Refresh to get the latest data." },
4936
5066
  {
4937
5067
  type: "data-grid",
4938
5068
  entity: entityName,
4939
5069
  emptyIcon: "inbox",
4940
5070
  emptyTitle,
4941
5071
  emptyDescription,
4942
- children: [{ type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
5072
+ renderItem: ["fn", "item", { type: "stack", direction: "vertical", gap: "sm", children: listItemChildren }]
4943
5073
  }
4944
5074
  ]
4945
5075
  };
@@ -5083,6 +5213,7 @@ function resolve27(params) {
5083
5213
  function buildEntity25(c) {
5084
5214
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
5085
5215
  }
5216
+ var ef11 = (field) => ["object/get", ["array/first", "@entity"], field];
5086
5217
  function buildTrait26(c) {
5087
5218
  const { entityName } = c;
5088
5219
  const scoreView = {
@@ -5093,12 +5224,14 @@ function buildTrait26(c) {
5093
5224
  children: [
5094
5225
  {
5095
5226
  type: "score-board",
5096
- score: "@entity.total",
5227
+ score: ef11("total"),
5097
5228
  highScore: 0,
5098
- combo: "@entity.combo",
5229
+ combo: ef11("combo"),
5099
5230
  multiplier: 1,
5100
5231
  level: 1
5101
5232
  },
5233
+ { type: "animated-counter", value: ef11("total"), prefix: "Score: ", duration: 300 },
5234
+ { type: "trend-indicator", value: ef11("points"), showValue: true },
5102
5235
  {
5103
5236
  type: "stack",
5104
5237
  direction: "horizontal",
@@ -5231,46 +5364,35 @@ function resolve28(params) {
5231
5364
  function buildEntity26(c) {
5232
5365
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
5233
5366
  }
5367
+ var ef12 = (field) => ["object/get", ["array/first", "@entity"], field];
5234
5368
  function buildTrait27(c) {
5235
5369
  const { entityName, headerIcon, pageTitle } = c;
5236
5370
  const idleView = {
5237
5371
  type: "stack",
5238
5372
  direction: "vertical",
5239
5373
  gap: "lg",
5240
- align: "center",
5241
5374
  children: [
5242
5375
  {
5243
5376
  type: "stack",
5244
5377
  direction: "horizontal",
5245
5378
  gap: "md",
5246
5379
  align: "center",
5380
+ justify: "space-between",
5247
5381
  children: [
5248
- { type: "icon", name: headerIcon, size: "lg" },
5249
- { type: "typography", content: pageTitle, variant: "h2" }
5382
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
5383
+ { type: "icon", name: headerIcon, size: "lg" },
5384
+ { type: "typography", content: pageTitle, variant: "h2" }
5385
+ ] },
5386
+ { type: "status-dot", status: "inactive", label: "Idle" }
5250
5387
  ]
5251
5388
  },
5252
5389
  { type: "divider" },
5253
5390
  {
5254
- type: "card",
5391
+ type: "simple-grid",
5392
+ columns: 2,
5255
5393
  children: [
5256
- {
5257
- type: "stack",
5258
- direction: "vertical",
5259
- gap: "sm",
5260
- children: [
5261
- { type: "typography", content: "Position", variant: "caption" },
5262
- {
5263
- type: "stack",
5264
- direction: "horizontal",
5265
- gap: "md",
5266
- children: [
5267
- { type: "typography", content: "@entity.x", variant: "body" },
5268
- { type: "typography", content: "@entity.y", variant: "body" }
5269
- ]
5270
- },
5271
- { type: "badge", label: "@entity.collisionStatus" }
5272
- ]
5273
- }
5394
+ { type: "stat-display", label: "X", value: ef12("x") },
5395
+ { type: "stat-display", label: "Y", value: ef12("y") }
5274
5396
  ]
5275
5397
  },
5276
5398
  {
@@ -5288,43 +5410,32 @@ function buildTrait27(c) {
5288
5410
  type: "stack",
5289
5411
  direction: "vertical",
5290
5412
  gap: "lg",
5291
- align: "center",
5292
5413
  children: [
5293
5414
  {
5294
5415
  type: "stack",
5295
5416
  direction: "horizontal",
5296
5417
  gap: "md",
5297
5418
  align: "center",
5419
+ justify: "space-between",
5298
5420
  children: [
5299
- { type: "icon", name: headerIcon, size: "lg" },
5300
- { type: "typography", content: pageTitle, variant: "h2" }
5421
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
5422
+ { type: "icon", name: headerIcon, size: "lg" },
5423
+ { type: "typography", content: pageTitle, variant: "h2" }
5424
+ ] },
5425
+ { type: "status-dot", status: "warning", pulse: true, label: "Detecting" }
5301
5426
  ]
5302
5427
  },
5303
5428
  { type: "divider" },
5429
+ { type: "alert", variant: "warning", message: "Collision detection in progress..." },
5304
5430
  {
5305
- type: "card",
5431
+ type: "simple-grid",
5432
+ columns: 2,
5306
5433
  children: [
5307
- {
5308
- type: "stack",
5309
- direction: "vertical",
5310
- gap: "sm",
5311
- children: [
5312
- { type: "typography", content: "Position", variant: "caption" },
5313
- {
5314
- type: "stack",
5315
- direction: "horizontal",
5316
- gap: "md",
5317
- children: [
5318
- { type: "typography", content: "@entity.x", variant: "body" },
5319
- { type: "typography", content: "@entity.y", variant: "body" }
5320
- ]
5321
- },
5322
- { type: "badge", label: "Detecting..." },
5323
- { type: "typography", content: "@entity.targetId", variant: "body" }
5324
- ]
5325
- }
5434
+ { type: "stat-display", label: "X", value: ef12("x") },
5435
+ { type: "stat-display", label: "Y", value: ef12("y") }
5326
5436
  ]
5327
5437
  },
5438
+ { type: "typography", variant: "caption", color: "muted", content: ef12("targetId") },
5328
5439
  {
5329
5440
  type: "stack",
5330
5441
  direction: "horizontal",
@@ -5617,40 +5728,39 @@ function resolve30(params) {
5617
5728
  function buildEntity28(c) {
5618
5729
  return makeEntity({ name: c.entityName, fields: c.fields, persistence: c.persistence });
5619
5730
  }
5731
+ var ef13 = (field) => ["object/get", ["array/first", "@entity"], field];
5620
5732
  function buildTrait29(c) {
5621
5733
  const { entityName, headerIcon, pageTitle } = c;
5622
5734
  const openView = {
5623
5735
  type: "stack",
5624
5736
  direction: "vertical",
5625
5737
  gap: "lg",
5626
- align: "center",
5627
5738
  children: [
5628
5739
  {
5629
5740
  type: "stack",
5630
5741
  direction: "horizontal",
5631
5742
  gap: "md",
5632
5743
  align: "center",
5744
+ justify: "space-between",
5633
5745
  children: [
5634
- { type: "icon", name: headerIcon, size: "lg" },
5635
- { type: "typography", content: pageTitle, variant: "h2" }
5746
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
5747
+ { type: "icon", name: headerIcon, size: "lg" },
5748
+ { type: "typography", content: pageTitle, variant: "h2" }
5749
+ ] },
5750
+ { type: "status-dot", status: "success", pulse: false, label: "Open" }
5636
5751
  ]
5637
5752
  },
5638
5753
  { type: "divider" },
5639
5754
  {
5640
- type: "card",
5755
+ type: "simple-grid",
5756
+ columns: 2,
5641
5757
  children: [
5642
- {
5643
- type: "stack",
5644
- direction: "vertical",
5645
- gap: "sm",
5646
- children: [
5647
- { type: "typography", content: "Requests", variant: "caption" },
5648
- { type: "typography", content: "@entity.count", variant: "h4" },
5649
- { type: "badge", label: "@entity.limiterStatus" }
5650
- ]
5651
- }
5758
+ { type: "stat-display", label: "Requests", value: ef13("count") },
5759
+ { type: "stat-display", label: "Window", value: ef13("window") }
5652
5760
  ]
5653
5761
  },
5762
+ { type: "meter", value: ef13("count"), min: 0, max: 100 },
5763
+ { type: "progress-bar", value: ef13("count"), max: 100, showPercentage: true },
5654
5764
  {
5655
5765
  type: "stack",
5656
5766
  direction: "horizontal",
@@ -5667,34 +5777,32 @@ function buildTrait29(c) {
5667
5777
  type: "stack",
5668
5778
  direction: "vertical",
5669
5779
  gap: "lg",
5670
- align: "center",
5671
5780
  children: [
5672
5781
  {
5673
5782
  type: "stack",
5674
5783
  direction: "horizontal",
5675
5784
  gap: "md",
5676
5785
  align: "center",
5786
+ justify: "space-between",
5677
5787
  children: [
5678
- { type: "icon", name: headerIcon, size: "lg" },
5679
- { type: "typography", content: pageTitle, variant: "h2" }
5788
+ { type: "stack", direction: "horizontal", gap: "md", align: "center", children: [
5789
+ { type: "icon", name: headerIcon, size: "lg" },
5790
+ { type: "typography", content: pageTitle, variant: "h2" }
5791
+ ] },
5792
+ { type: "status-dot", status: "error", pulse: true, label: "Throttled" }
5680
5793
  ]
5681
5794
  },
5682
5795
  { type: "divider" },
5796
+ { type: "alert", variant: "danger", message: "Rate limit exceeded. Requests are being throttled." },
5683
5797
  {
5684
- type: "card",
5798
+ type: "simple-grid",
5799
+ columns: 2,
5685
5800
  children: [
5686
- {
5687
- type: "stack",
5688
- direction: "vertical",
5689
- gap: "sm",
5690
- children: [
5691
- { type: "typography", content: "Requests", variant: "caption" },
5692
- { type: "typography", content: "@entity.count", variant: "h4" },
5693
- { type: "badge", label: "Throttled" }
5694
- ]
5695
- }
5801
+ { type: "stat-display", label: "Requests", value: ef13("count") },
5802
+ { type: "stat-display", label: "Window", value: ef13("window") }
5696
5803
  ]
5697
5804
  },
5805
+ { type: "meter", value: ef13("count"), min: 0, max: 100 },
5698
5806
  {
5699
5807
  type: "stack",
5700
5808
  direction: "horizontal",
@@ -7158,6 +7266,11 @@ function stdList(params) {
7158
7266
  if (!existingKeys.has("CONFIRM_DELETE")) sm.events.push({ key: "CONFIRM_DELETE", name: "Confirm Delete" });
7159
7267
  if (!existingKeys.has("CANCEL")) sm.events.push({ key: "CANCEL", name: "Cancel" });
7160
7268
  if (!existingKeys.has("CLOSE")) sm.events.push({ key: "CLOSE", name: "Close" });
7269
+ const initTransition = sm.transitions[0];
7270
+ const initRenderEffect = initTransition.effects.find(
7271
+ (e) => Array.isArray(e) && e[0] === "render-ui" && e[1] === "main"
7272
+ );
7273
+ const browseMainView = initRenderEffect ? initRenderEffect[2] : null;
7161
7274
  sm.transitions.push(
7162
7275
  // DELETE: browsing → deleting (fetch entity by ID, show confirmation modal)
7163
7276
  { from: "browsing", to: "deleting", event: "DELETE", effects: [
@@ -7180,15 +7293,24 @@ function stdList(params) {
7180
7293
  ]
7181
7294
  }]
7182
7295
  ] },
7183
- // CONFIRM_DELETE: deleting → browsing (persist delete using selected entity's ID)
7296
+ // CONFIRM_DELETE: deleting → browsing (persist delete, dismiss modal, re-render main)
7184
7297
  { from: "deleting", to: "browsing", event: "CONFIRM_DELETE", effects: [
7185
7298
  ["persist", "delete", entityName, "@entity.id"],
7186
7299
  ["render-ui", "modal", null],
7187
- ["fetch", entityName]
7300
+ ["fetch", entityName],
7301
+ ["render-ui", "main", browseMainView]
7302
+ ] },
7303
+ // CANCEL/CLOSE from deleting (dismiss modal, re-render main)
7304
+ { from: "deleting", to: "browsing", event: "CANCEL", effects: [
7305
+ ["render-ui", "modal", null],
7306
+ ["fetch", entityName],
7307
+ ["render-ui", "main", browseMainView]
7188
7308
  ] },
7189
- // CANCEL/CLOSE from deleting
7190
- { from: "deleting", to: "browsing", event: "CANCEL", effects: [["render-ui", "modal", null]] },
7191
- { from: "deleting", to: "browsing", event: "CLOSE", effects: [["render-ui", "modal", null]] }
7309
+ { from: "deleting", to: "browsing", event: "CLOSE", effects: [
7310
+ ["render-ui", "modal", null],
7311
+ ["fetch", entityName],
7312
+ ["render-ui", "main", browseMainView]
7313
+ ] }
7192
7314
  );
7193
7315
  const entity = makeEntity({ name: entityName, fields, persistence: c.persistence, collection: c.collection });
7194
7316
  const page = {
@@ -8132,19 +8254,19 @@ function buildBattleFlowTrait(c) {
8132
8254
  event: "PAUSE",
8133
8255
  effects: [["render-ui", "modal", pausedModalUI]]
8134
8256
  },
8135
- // RESUME: paused -> playing
8257
+ // RESUME: paused -> playing (dismiss modal, re-render main)
8136
8258
  {
8137
8259
  from: "paused",
8138
8260
  to: "playing",
8139
8261
  event: "RESUME",
8140
- effects: [["render-ui", "modal", null]]
8262
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
8141
8263
  },
8142
8264
  // CLOSE: paused -> playing (modal exit requirement)
8143
8265
  {
8144
8266
  from: "paused",
8145
8267
  to: "playing",
8146
8268
  event: "CLOSE",
8147
- effects: [["render-ui", "modal", null]]
8269
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
8148
8270
  },
8149
8271
  // GAME_OVER: playing -> gameover
8150
8272
  {
@@ -8399,19 +8521,19 @@ function buildPlatformerFlowTrait(c) {
8399
8521
  event: "PAUSE",
8400
8522
  effects: [["render-ui", "modal", pausedModalUI]]
8401
8523
  },
8402
- // RESUME: paused -> playing
8524
+ // RESUME: paused -> playing (dismiss modal, re-render main)
8403
8525
  {
8404
8526
  from: "paused",
8405
8527
  to: "playing",
8406
8528
  event: "RESUME",
8407
- effects: [["render-ui", "modal", null]]
8529
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
8408
8530
  },
8409
8531
  // CLOSE: paused -> playing (modal exit requirement)
8410
8532
  {
8411
8533
  from: "paused",
8412
8534
  to: "playing",
8413
8535
  event: "CLOSE",
8414
- effects: [["render-ui", "modal", null]]
8536
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
8415
8537
  },
8416
8538
  // GAME_OVER: playing -> gameover
8417
8539
  {
@@ -8651,19 +8773,19 @@ function buildPuzzleFlowTrait(c) {
8651
8773
  event: "PAUSE",
8652
8774
  effects: [["render-ui", "modal", pausedModalUI]]
8653
8775
  },
8654
- // RESUME: paused -> playing
8776
+ // RESUME: paused -> playing (dismiss modal, re-render main)
8655
8777
  {
8656
8778
  from: "paused",
8657
8779
  to: "playing",
8658
8780
  event: "RESUME",
8659
- effects: [["render-ui", "modal", null]]
8781
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
8660
8782
  },
8661
8783
  // CLOSE: paused -> playing (modal exit requirement)
8662
8784
  {
8663
8785
  from: "paused",
8664
8786
  to: "playing",
8665
8787
  event: "CLOSE",
8666
- effects: [["render-ui", "modal", null]]
8788
+ effects: [["render-ui", "modal", null], ["render-ui", "main", playingUI]]
8667
8789
  },
8668
8790
  // GAME_OVER: playing -> gameover
8669
8791
  {