lecodes-sdk 0.19.0

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 (367) hide show
  1. package/README.md +114 -0
  2. package/dist/global.d.ts +503 -0
  3. package/dist/host.d.ts +61 -0
  4. package/dist/inject.js +4730 -0
  5. package/dist/types/animate/animate.d.ts +20 -0
  6. package/dist/types/animate/bezier.d.ts +2 -0
  7. package/dist/types/animate/easings.d.ts +21 -0
  8. package/dist/types/canvas/Canvas.d.ts +168 -0
  9. package/dist/types/core/Aspect.d.ts +171 -0
  10. package/dist/types/core/InspectorUI.d.ts +88 -0
  11. package/dist/types/core/StateMachine.d.ts +81 -0
  12. package/dist/types/core/color.d.ts +13 -0
  13. package/dist/types/core/compWrite.d.ts +11 -0
  14. package/dist/types/core/events.d.ts +11 -0
  15. package/dist/types/core/fields.d.ts +58 -0
  16. package/dist/types/core/registry.d.ts +7 -0
  17. package/dist/types/core/signals.d.ts +29 -0
  18. package/dist/types/core/time.d.ts +31 -0
  19. package/dist/types/g2/Camera2D.d.ts +19 -0
  20. package/dist/types/g2/CharacterController2D.d.ts +134 -0
  21. package/dist/types/g2/Node2D.d.ts +91 -0
  22. package/dist/types/g2/OneWay2D.d.ts +24 -0
  23. package/dist/types/g2/Physics2D.d.ts +147 -0
  24. package/dist/types/g2/Scene2D.d.ts +72 -0
  25. package/dist/types/g2/Shape2D.d.ts +58 -0
  26. package/dist/types/g2/Sprite.d.ts +51 -0
  27. package/dist/types/g2/SpriteAnimation.d.ts +50 -0
  28. package/dist/types/g2/SpriteSheet.d.ts +69 -0
  29. package/dist/types/g2/Texture2D.d.ts +16 -0
  30. package/dist/types/g2/Tilemap.d.ts +20 -0
  31. package/dist/types/g2/Tileset.d.ts +32 -0
  32. package/dist/types/g2/Trigger2D.d.ts +20 -0
  33. package/dist/types/g2/autotile.d.ts +133 -0
  34. package/dist/types/g2/cells.d.ts +14 -0
  35. package/dist/types/g2/defineScene2d.d.ts +141 -0
  36. package/dist/types/g2/groups2d.d.ts +16 -0
  37. package/dist/types/g2/loop.d.ts +4 -0
  38. package/dist/types/g2/scenarios2d.d.ts +30 -0
  39. package/dist/types/g2/touch.d.ts +2 -0
  40. package/dist/types/gl/Camera.d.ts +79 -0
  41. package/dist/types/gl/CameraPlace.d.ts +26 -0
  42. package/dist/types/gl/CharacterController.d.ts +98 -0
  43. package/dist/types/gl/Gearbox.d.ts +86 -0
  44. package/dist/types/gl/Geometry.d.ts +39 -0
  45. package/dist/types/gl/IK.d.ts +53 -0
  46. package/dist/types/gl/InstancedMesh.d.ts +46 -0
  47. package/dist/types/gl/Light.d.ts +73 -0
  48. package/dist/types/gl/Lightmap.d.ts +85 -0
  49. package/dist/types/gl/Locomotion.d.ts +279 -0
  50. package/dist/types/gl/Material.d.ts +100 -0
  51. package/dist/types/gl/Mesh.d.ts +33 -0
  52. package/dist/types/gl/Model.d.ts +53 -0
  53. package/dist/types/gl/NavAgent.d.ts +99 -0
  54. package/dist/types/gl/NavMesh.d.ts +169 -0
  55. package/dist/types/gl/Node.d.ts +99 -0
  56. package/dist/types/gl/Noise.d.ts +20 -0
  57. package/dist/types/gl/Particles.d.ts +277 -0
  58. package/dist/types/gl/Physics.d.ts +91 -0
  59. package/dist/types/gl/Plane.d.ts +19 -0
  60. package/dist/types/gl/Ragdoll.d.ts +86 -0
  61. package/dist/types/gl/Ray.d.ts +8 -0
  62. package/dist/types/gl/Scene.d.ts +221 -0
  63. package/dist/types/gl/Shape.d.ts +122 -0
  64. package/dist/types/gl/Terrain.d.ts +280 -0
  65. package/dist/types/gl/Texture.d.ts +27 -0
  66. package/dist/types/gl/Trigger.d.ts +10 -0
  67. package/dist/types/gl/Vehicle.d.ts +191 -0
  68. package/dist/types/gl/Wheel.d.ts +95 -0
  69. package/dist/types/gl/animation/AnimationClip.d.ts +60 -0
  70. package/dist/types/gl/animation/Animator.d.ts +219 -0
  71. package/dist/types/gl/animation/Layer.d.ts +31 -0
  72. package/dist/types/gl/animation/Loop.d.ts +17 -0
  73. package/dist/types/gl/animation/Playback.d.ts +36 -0
  74. package/dist/types/gl/animation/core.d.ts +367 -0
  75. package/dist/types/gl/controls.d.ts +19 -0
  76. package/dist/types/gl/physicsEvents.d.ts +1 -0
  77. package/dist/types/gl/scenarios.d.ts +98 -0
  78. package/dist/types/gl/state.d.ts +5 -0
  79. package/dist/types/gl/terrainMesh.d.ts +46 -0
  80. package/dist/types/gl/touch.d.ts +2 -0
  81. package/dist/types/inject.d.ts +123 -0
  82. package/dist/types/math/Mathf.d.ts +39 -0
  83. package/dist/types/math/mat4.d.ts +66 -0
  84. package/dist/types/math/quat.d.ts +53 -0
  85. package/dist/types/math/vec.d.ts +129 -0
  86. package/dist/types/net/codec.d.ts +25 -0
  87. package/dist/types/net/core.d.ts +106 -0
  88. package/dist/types/net/index.d.ts +80 -0
  89. package/dist/types/net/replication.d.ts +101 -0
  90. package/dist/types/plugins/camera.d.ts +25 -0
  91. package/dist/types/plugins/geolocation.d.ts +39 -0
  92. package/dist/types/plugins/oauth.d.ts +25 -0
  93. package/dist/types/plugins/permission.d.ts +1 -0
  94. package/dist/types/plugins/push.d.ts +46 -0
  95. package/dist/types/plugins/qr.d.ts +21 -0
  96. package/dist/types/plugins/service.d.ts +33 -0
  97. package/dist/types/runtime/app.d.ts +67 -0
  98. package/dist/types/runtime/appEvents.d.ts +7 -0
  99. package/dist/types/runtime/channel.d.ts +1 -0
  100. package/dist/types/runtime/clipboard.d.ts +7 -0
  101. package/dist/types/runtime/datetime.d.ts +80 -0
  102. package/dist/types/runtime/device.d.ts +126 -0
  103. package/dist/types/runtime/fetch.d.ts +31 -0
  104. package/dist/types/runtime/files.d.ts +33 -0
  105. package/dist/types/runtime/input.d.ts +121 -0
  106. package/dist/types/runtime/media.d.ts +46 -0
  107. package/dist/types/runtime/misc.d.ts +11 -0
  108. package/dist/types/runtime/net.d.ts +15 -0
  109. package/dist/types/runtime/rpc.d.ts +44 -0
  110. package/dist/types/runtime/service.d.ts +1 -0
  111. package/dist/types/runtime/share.d.ts +2 -0
  112. package/dist/types/runtime/storage.d.ts +5 -0
  113. package/dist/types/runtime/touch.d.ts +56 -0
  114. package/dist/types/scene/defineScene.d.ts +296 -0
  115. package/dist/types/scene/editorPlugins.d.ts +82 -0
  116. package/dist/types/scene/gizmos.d.ts +56 -0
  117. package/dist/types/scene/grammar.d.ts +56 -0
  118. package/dist/types/scene/level.d.ts +98 -0
  119. package/dist/types/scene/material.d.ts +76 -0
  120. package/dist/types/server/auth/appConfig.d.ts +16 -0
  121. package/dist/types/server/auth/global.d.ts +56 -0
  122. package/dist/types/server/auth/models.d.ts +164 -0
  123. package/dist/types/server/auth/types.d.ts +56 -0
  124. package/dist/types/server/channel.d.ts +28 -0
  125. package/dist/types/server/context.d.ts +27 -0
  126. package/dist/types/server/db/defineDb.d.ts +36 -0
  127. package/dist/types/server/db/fields.d.ts +146 -0
  128. package/dist/types/server/db/index.d.ts +6 -0
  129. package/dist/types/server/db/marci/query.d.ts +326 -0
  130. package/dist/types/server/db/types.d.ts +163 -0
  131. package/dist/types/server/errors.d.ts +8 -0
  132. package/dist/types/server/inject.d.ts +5 -0
  133. package/dist/types/ui/NativeView.d.ts +38 -0
  134. package/dist/types/ui/UI.d.ts +27 -0
  135. package/dist/types/ui/UIBottomSheet.d.ts +71 -0
  136. package/dist/types/ui/UIButton.d.ts +30 -0
  137. package/dist/types/ui/UIContainer.d.ts +33 -0
  138. package/dist/types/ui/UIImage.d.ts +35 -0
  139. package/dist/types/ui/UIInput.d.ts +110 -0
  140. package/dist/types/ui/UIModal.d.ts +70 -0
  141. package/dist/types/ui/UINode.d.ts +363 -0
  142. package/dist/types/ui/UIPager.d.ts +123 -0
  143. package/dist/types/ui/UIPopover.d.ts +39 -0
  144. package/dist/types/ui/UIScreen.d.ts +57 -0
  145. package/dist/types/ui/UIScrollable.d.ts +40 -0
  146. package/dist/types/ui/UISpacer.d.ts +9 -0
  147. package/dist/types/ui/UITabs.d.ts +96 -0
  148. package/dist/types/ui/UIText.d.ts +19 -0
  149. package/dist/types/ui/UIVideo.d.ts +28 -0
  150. package/dist/types/ui/UIVirtualizedList.d.ts +97 -0
  151. package/dist/types/ui/UIWidget.d.ts +65 -0
  152. package/dist/types/ui/fonts.d.ts +9 -0
  153. package/dist/types/ui/presentable.d.ts +68 -0
  154. package/dist/types/ui/router.d.ts +40 -0
  155. package/dist/types/ui/theme.d.ts +26 -0
  156. package/dist/types.json +1 -0
  157. package/package.json +46 -0
  158. package/prompts/2d.md +395 -0
  159. package/prompts/3d-scene-files.md +113 -0
  160. package/prompts/3d-scene.md +119 -0
  161. package/prompts/3d.md +303 -0
  162. package/prompts/README.md +142 -0
  163. package/prompts/ar.md +109 -0
  164. package/prompts/canvas.md +27 -0
  165. package/prompts/compose.ts +46 -0
  166. package/prompts/concept.md +49 -0
  167. package/prompts/core-design.md +75 -0
  168. package/prompts/core.md +264 -0
  169. package/prompts/design.md +218 -0
  170. package/prompts/dist/2d-game.md +1530 -0
  171. package/prompts/dist/3d-app.md +1672 -0
  172. package/prompts/dist/ar-app.md +1548 -0
  173. package/prompts/dist/concept.md +49 -0
  174. package/prompts/dist/design.md +498 -0
  175. package/prompts/dist/ui-app.md +1134 -0
  176. package/prompts/index.md +37 -0
  177. package/prompts/intake-prompt.md +33 -0
  178. package/prompts/namer-prompt.md +12 -0
  179. package/prompts/router-prompt.md +50 -0
  180. package/prompts/select.ts +111 -0
  181. package/prompts/ui-design.md +203 -0
  182. package/prompts/ui.md +803 -0
  183. package/src/animate/animate.ts +238 -0
  184. package/src/animate/bezier.ts +138 -0
  185. package/src/animate/easings.ts +126 -0
  186. package/src/bridges.d.ts +1345 -0
  187. package/src/canvas/Canvas.ts +305 -0
  188. package/src/compile/__tests__/assetIconMacro.test.ts +219 -0
  189. package/src/compile/__tests__/assetMacro.test.ts +74 -0
  190. package/src/compile/__tests__/assetName.test.ts +55 -0
  191. package/src/compile/__tests__/compile.test.ts +287 -0
  192. package/src/compile/__tests__/detectEntry.test.ts +132 -0
  193. package/src/compile/__tests__/fontMacro.test.ts +199 -0
  194. package/src/compile/aspectMacro.ts +86 -0
  195. package/src/compile/assetIconMacro.ts +384 -0
  196. package/src/compile/assetMacro.ts +146 -0
  197. package/src/compile/assetName.ts +50 -0
  198. package/src/compile/bundler.ts +287 -0
  199. package/src/compile/compileProject.ts +127 -0
  200. package/src/compile/detectEntry.ts +128 -0
  201. package/src/compile/fontMacro.ts +459 -0
  202. package/src/compile/fontRegistry.ts +78 -0
  203. package/src/compile/header.ts +67 -0
  204. package/src/compile/index.ts +100 -0
  205. package/src/compile/libraryImports.ts +52 -0
  206. package/src/compile/liteMaterial.ts +247 -0
  207. package/src/compile/sceneEditor.ts +88 -0
  208. package/src/compile/serverSplit.ts +233 -0
  209. package/src/compile/serverTypes.ts +227 -0
  210. package/src/compile/sfnt.ts +98 -0
  211. package/src/compile/shaderSchema.ts +202 -0
  212. package/src/compile/shaderTargets.ts +77 -0
  213. package/src/compile/sourcemap.ts +25 -0
  214. package/src/core/Aspect.ts +568 -0
  215. package/src/core/InspectorUI.ts +212 -0
  216. package/src/core/StateMachine.ts +308 -0
  217. package/src/core/__tests__/stateMachine.test.ts +132 -0
  218. package/src/core/color.ts +66 -0
  219. package/src/core/compWrite.ts +42 -0
  220. package/src/core/events.ts +38 -0
  221. package/src/core/fields.ts +120 -0
  222. package/src/core/registry.ts +23 -0
  223. package/src/core/signals.ts +277 -0
  224. package/src/core/time.ts +84 -0
  225. package/src/g2/Camera2D.ts +40 -0
  226. package/src/g2/CharacterController2D.ts +276 -0
  227. package/src/g2/Node2D.ts +267 -0
  228. package/src/g2/OneWay2D.ts +66 -0
  229. package/src/g2/Physics2D.ts +346 -0
  230. package/src/g2/Scene2D.ts +209 -0
  231. package/src/g2/Shape2D.ts +259 -0
  232. package/src/g2/Sprite.ts +89 -0
  233. package/src/g2/SpriteAnimation.ts +171 -0
  234. package/src/g2/SpriteSheet.ts +166 -0
  235. package/src/g2/Texture2D.ts +47 -0
  236. package/src/g2/Tilemap.ts +41 -0
  237. package/src/g2/Tileset.ts +71 -0
  238. package/src/g2/Trigger2D.ts +77 -0
  239. package/src/g2/autotile.ts +433 -0
  240. package/src/g2/cells.ts +91 -0
  241. package/src/g2/defineScene2d.ts +381 -0
  242. package/src/g2/groups2d.ts +106 -0
  243. package/src/g2/loop.ts +50 -0
  244. package/src/g2/scenarios2d.ts +69 -0
  245. package/src/g2/touch.ts +83 -0
  246. package/src/gl/Camera.ts +160 -0
  247. package/src/gl/CameraPlace.ts +52 -0
  248. package/src/gl/CharacterController.ts +238 -0
  249. package/src/gl/Gearbox.ts +212 -0
  250. package/src/gl/Geometry.ts +279 -0
  251. package/src/gl/IK.ts +193 -0
  252. package/src/gl/InstancedMesh.ts +132 -0
  253. package/src/gl/Light.ts +135 -0
  254. package/src/gl/Lightmap.ts +402 -0
  255. package/src/gl/Locomotion.ts +498 -0
  256. package/src/gl/Material.ts +279 -0
  257. package/src/gl/Mesh.ts +83 -0
  258. package/src/gl/Model.ts +124 -0
  259. package/src/gl/NavAgent.ts +337 -0
  260. package/src/gl/NavMesh.ts +397 -0
  261. package/src/gl/Node.ts +350 -0
  262. package/src/gl/Noise.ts +30 -0
  263. package/src/gl/Particles.ts +676 -0
  264. package/src/gl/Physics.ts +222 -0
  265. package/src/gl/Plane.ts +53 -0
  266. package/src/gl/Ragdoll.ts +270 -0
  267. package/src/gl/Ray.ts +16 -0
  268. package/src/gl/Scene.ts +505 -0
  269. package/src/gl/Shape.ts +409 -0
  270. package/src/gl/Terrain.ts +1092 -0
  271. package/src/gl/Texture.ts +63 -0
  272. package/src/gl/Trigger.ts +45 -0
  273. package/src/gl/Vehicle.ts +473 -0
  274. package/src/gl/Wheel.ts +240 -0
  275. package/src/gl/animation/AnimationClip.ts +204 -0
  276. package/src/gl/animation/Animator.ts +329 -0
  277. package/src/gl/animation/Layer.ts +39 -0
  278. package/src/gl/animation/Loop.ts +31 -0
  279. package/src/gl/animation/Playback.ts +52 -0
  280. package/src/gl/animation/core.ts +670 -0
  281. package/src/gl/controls.ts +95 -0
  282. package/src/gl/physicsEvents.ts +20 -0
  283. package/src/gl/scenarios.ts +291 -0
  284. package/src/gl/state.ts +6 -0
  285. package/src/gl/terrainMesh.ts +219 -0
  286. package/src/gl/touch.ts +68 -0
  287. package/src/host.d.ts +61 -0
  288. package/src/inject.ts +203 -0
  289. package/src/math/Mathf.ts +118 -0
  290. package/src/math/mat4.ts +278 -0
  291. package/src/math/quat.ts +232 -0
  292. package/src/math/vec.ts +255 -0
  293. package/src/net/codec.ts +119 -0
  294. package/src/net/core.ts +384 -0
  295. package/src/net/index.ts +181 -0
  296. package/src/net/replication.ts +622 -0
  297. package/src/plugins/camera.ts +81 -0
  298. package/src/plugins/geolocation.ts +123 -0
  299. package/src/plugins/oauth.ts +61 -0
  300. package/src/plugins/permission.ts +7 -0
  301. package/src/plugins/push.ts +132 -0
  302. package/src/plugins/qr.ts +73 -0
  303. package/src/plugins/service.ts +47 -0
  304. package/src/runtime/app.ts +101 -0
  305. package/src/runtime/appEvents.ts +54 -0
  306. package/src/runtime/channel.ts +61 -0
  307. package/src/runtime/clipboard.ts +20 -0
  308. package/src/runtime/datetime.ts +329 -0
  309. package/src/runtime/device.ts +293 -0
  310. package/src/runtime/fetch.ts +77 -0
  311. package/src/runtime/files.ts +108 -0
  312. package/src/runtime/input.ts +175 -0
  313. package/src/runtime/media.ts +111 -0
  314. package/src/runtime/misc.ts +16 -0
  315. package/src/runtime/net.ts +36 -0
  316. package/src/runtime/rpc.ts +218 -0
  317. package/src/runtime/service.ts +83 -0
  318. package/src/runtime/share.ts +9 -0
  319. package/src/runtime/storage.ts +13 -0
  320. package/src/runtime/touch.ts +76 -0
  321. package/src/scene/defineScene.ts +1396 -0
  322. package/src/scene/editorPlugins.ts +110 -0
  323. package/src/scene/gizmos.ts +148 -0
  324. package/src/scene/grammar.ts +120 -0
  325. package/src/scene/level.ts +296 -0
  326. package/src/scene/material.ts +188 -0
  327. package/src/server/auth/appConfig.ts +12 -0
  328. package/src/server/auth/global.ts +80 -0
  329. package/src/server/auth/host.ts +318 -0
  330. package/src/server/auth/models.ts +83 -0
  331. package/src/server/auth/types.ts +50 -0
  332. package/src/server/channel.ts +56 -0
  333. package/src/server/context.ts +36 -0
  334. package/src/server/db/defineDb.ts +237 -0
  335. package/src/server/db/fields.ts +132 -0
  336. package/src/server/db/httpTransport.ts +93 -0
  337. package/src/server/db/index.ts +7 -0
  338. package/src/server/db/marci/query.ts +412 -0
  339. package/src/server/db/types.ts +202 -0
  340. package/src/server/errors.ts +12 -0
  341. package/src/server/host.ts +74 -0
  342. package/src/server/inject.ts +13 -0
  343. package/src/server/runtime.ts +133 -0
  344. package/src/server/validate.ts +87 -0
  345. package/src/ui/NativeView.ts +142 -0
  346. package/src/ui/UI.ts +39 -0
  347. package/src/ui/UIBottomSheet.ts +139 -0
  348. package/src/ui/UIButton.ts +101 -0
  349. package/src/ui/UIContainer.ts +60 -0
  350. package/src/ui/UIImage.ts +83 -0
  351. package/src/ui/UIInput.ts +185 -0
  352. package/src/ui/UIModal.ts +139 -0
  353. package/src/ui/UINode.ts +830 -0
  354. package/src/ui/UIPager.ts +362 -0
  355. package/src/ui/UIPopover.ts +100 -0
  356. package/src/ui/UIScreen.ts +123 -0
  357. package/src/ui/UIScrollable.ts +87 -0
  358. package/src/ui/UISpacer.ts +14 -0
  359. package/src/ui/UITabs.ts +236 -0
  360. package/src/ui/UIText.ts +51 -0
  361. package/src/ui/UIVideo.ts +88 -0
  362. package/src/ui/UIVirtualizedList.ts +241 -0
  363. package/src/ui/UIWidget.ts +127 -0
  364. package/src/ui/fonts.ts +13 -0
  365. package/src/ui/presentable.ts +117 -0
  366. package/src/ui/router.ts +132 -0
  367. package/src/ui/theme.ts +84 -0
@@ -0,0 +1,37 @@
1
+ ## Full API index
2
+
3
+ Every global that exists in LeCodes, one line each. Areas that have no detailed section elsewhere
4
+ in this prompt are NOT loaded: their globals exist, but you do not know their exact signatures —
5
+ never guess or invent them. If the task genuinely needs an unloaded area, say so briefly and
6
+ implement what you can with the loaded ones.
7
+
8
+ // Host: setLoop/clearLoop (dt seconds), setTimeout/setInterval/clearTimeout/clearInterval (ms),
9
+ // console.log/warn/info/error, asset('./path') macro, DEG2RAD/RAD2DEG
10
+ // Math: Mathf (clamp/lerp/damp/random), Vec2, Vec3, Quat, Mat4, Color — pure-method value math
11
+ // Runtime: fetch/fetchLocal (sync body reads), FormData, File, WebSocket, localStorage,
12
+ // device (platform/size/resize), Input.key(), toast, share, openFilePicker,
13
+ // AudioPlayer, VideoPlayer, SvgSource, ClickEvent/TouchStartEvent (+ ev.track drags),
14
+ // CameraView / QRScanner (host-optional camera views: open()/Router.push/embed)
15
+ // Animate: animate/animateMat4/stopAnimation/pauseAnimation/resumeAnimation (ms),
16
+ // easeIn/easeOut/easeInOut/cubicBezier
17
+ // Canvas: Canvas (retained 2D drawing baked to a texture — sprites/UI images), Bitmap
18
+ // Aspects: Aspect base — attachable node capabilities: node.aspect(Class, opts), custom aspects
19
+ // with per-frame update(dt)
20
+ // UI: UIScreen, Router, UITabs (bottom-tab shell), UIPager (tabs + per-tab stacks), UIRow,
21
+ // UIColumn, UIScrollable, UISpacer, UIText, UIImage, UIVideo,
22
+ // UIButton, UIInput, UITextArea, UIWidget/UIModal/UIPopover/UIBottomSheet (floating
23
+ // overlays: HUD / dialog / anchored menu / draggable sheet), UIVirtualizedList,
24
+ // registerFont; UIBox (deprecated)
25
+ // 2D engine: Scene2D, Node2D, Camera2D, Sprite, SpriteAnimation, Tilemap, Texture2D,
26
+ // Shape2D + Physics2D + Trigger2D + CharacterController2D (Box2D physics, sensors,
27
+ // raycast/overlap queries, picking),
28
+ // defineScene2d (declarative *.scene2d.ts files) + cells + CameraFollow
29
+ // 3D engine: Scene, Node, Camera, Mesh (box/sphere/cylinder/plane), Model (.glb) + ModelAnimation,
30
+ // Geometry, Material (lit/unlit/custom shaders), Texture, Light.sun(),
31
+ // Shape + Physics + Trigger + CharacterController (Jolt physics, raycast),
32
+ // Particles + dynamic/dynamicColor, Ray, Plane, Noise
33
+ // 3D scene files: defineScene (declarative *.scene.ts read/written by the visual scene editor;
34
+ // default export is a SceneHandle: load()/open()) + use/ref/make in the def,
35
+ // scenario aspects MoveTo/FollowPath/Spin/LookAt/PlayAnimation;
36
+ // *.editor.ts + EDITOR/InspectorUI are editor-plugin files — never edit or import them
37
+ // AR: ARScene (camera passthrough, anchors, placement gestures via addControls)
@@ -0,0 +1,33 @@
1
+ You are the intake step for LeCodes — a platform where a user describes a mobile app and an AI code generator builds it. The user has just sent the first request for a new project. Before generation starts, you ask a few clarifying questions, then write a short brief the user confirms. You work in two turns, and you reply with ONLY a JSON object — no prose, no code fences, in both turns.
2
+
3
+ TURN 1 — questions:
4
+
5
+ {"kind": "ui", "lead": "...", "questions": [{"id": "visual", "question": "...", "options": ["...", "..."]}]}
6
+
7
+ lead — one short line introducing the questions (the spirit of "A couple of quick questions before I build:"), in the user's language.
8
+
9
+ kind — your best guess of the project type:
10
+ - "ui" — an app made of screens: forms, lists, feeds, tools, commerce. The default; most requests.
11
+ - "2d" — a flat 2D game or a drawing/physics toy.
12
+ - "3d" — a 3D game, scene, or product viewer.
13
+ - "ar" — augmented reality.
14
+
15
+ questions — 2 to 4, ONLY what would change what gets built; never filler:
16
+ - Each question has 2–4 options. The FIRST option is your recommendation. Make every option concrete and opinionated ("Dark, near-black with one electric-teal accent", not "dark"). The user can always type their own answer instead, so options don't need to cover everything.
17
+ - Almost always worth asking: the visual direction (palette + mood) — unless an [Existing design] already fixes it.
18
+ - Ask about the app kind ONLY when the request is genuinely ambiguous between kinds (e.g. "a chess app" — a playable 2D game, or a UI app around a board?). Then make it the FIRST question and add "kinds": an array parallel to options, each "ui" | "2d" | "3d" | "ar", so the choice resolves the kind.
19
+ - Other good subjects: which implied feature is the core of the first version; what data is real vs mocked; content language if unclear. Bad subjects: anything technical (frameworks, storage engines), anything the request already answers, a second question about looks.
20
+ - "id" is a short kebab-case slug. Write questions and options in the user's language.
21
+ - If the request is already fully specified, "questions": [] is correct — don't invent doubts.
22
+
23
+ TURN 2 — the user's answers arrive as "id: answer" lines. Reply with:
24
+
25
+ {"kind": "ui", "lead": "...", "brief": "- ...\n- ...\n- ..."}
26
+
27
+ lead — one short line presenting the brief for confirmation (the spirit of "Here's what I'll build — confirm or adjust:"), in the user's language.
28
+
29
+ brief — a short markdown summary of what will be built, in the user's language: 5–8 "- " bullet lines covering what the app is, the core screens/flows of the first version, the visual direction (folding in the answers), and the key data/entities. It is shown to the user to confirm and saved as the project's concept — state decisions, never ask anything in it, no headings.
30
+
31
+ An [Existing design] section in the first message means the project already has design files (concept spec, design tokens, screens). Don't ask what they already answer — existing tokens fix the visual direction, an existing spec fixes the concept — and write the brief as "implementing the existing design": extend what's there, don't restate or contradict it.
32
+
33
+ Reply with the JSON object only — any other text breaks the platform.
@@ -0,0 +1,12 @@
1
+ You name new projects for LeCodes, a platform where people build apps and games by describing them.
2
+ Input: the user's first request, in any language. Reply with ONLY a JSON object — no code fences, no other text:
3
+ {"name": "...", "emoji": "..."}
4
+
5
+ Rules:
6
+ - name: the app's product name — 1–3 words, max 24 characters, Title Case, in the language of the request. Name the app, don't describe it: "Pizza Express", not "An app for ordering pizza". No quotes or emoji inside the name; avoid generic words like "App"/"Приложение" unless they read naturally.
7
+ - emoji: exactly one emoji that best represents the app. Prefer a concrete object over an abstract symbol.
8
+
9
+ Examples:
10
+ "сделай игру где шарик прыгает по платформам" → {"name": "Прыгучий Шарик", "emoji": "🏀"}
11
+ "make a todo list with reminders" → {"name": "Taskly", "emoji": "✅"}
12
+ "AR viewer to place furniture in your room" → {"name": "Room Furnish", "emoji": "🛋️"}
@@ -0,0 +1,50 @@
1
+ # Router prompt — bundle classification for empty projects
2
+
3
+ Used ONLY when `select.ts` returns null (a brand-new project with no code to inspect). One cheap,
4
+ fast call — recommended: `claude-haiku-4-5`, `temperature: 0`, `max_tokens: 8`. The user message
5
+ may be in any language; the classifier reasons about meaning, not keywords.
6
+
7
+ Send the block below as the **system prompt**, and the user's request verbatim as the
8
+ **user message**. Parse the reply with `/\b(ui|2d|3d|ar)\b/` — anything unparseable → `ui`.
9
+
10
+ ---
11
+
12
+ You classify a user's request for the LeCodes app platform into exactly one project kind. The
13
+ request may be in any language (English, Russian, or others) — judge by meaning.
14
+
15
+ Reply with exactly one word — one of: `ui`, `2d`, `3d`, `ar`. No other text.
16
+
17
+ Definitions:
18
+ - `ui` — an application: screens, lists, forms, buttons, chat, shop, dashboard, notes, timers,
19
+ quizzes, utilities. Anything that is not a game or a 3D/AR experience.
20
+ - `2d` — a flat game or graphics toy: platformer, top-down, puzzle with a play field, arcade,
21
+ pixel art, sprites, tilemaps, drawing/painting apps on a canvas.
22
+ - `3d` — a game or experience with 3D content: 3D models (.glb), first/third-person view,
23
+ 3D physics, product viewers/configurators with a 3D model.
24
+ - `ar` — augmented reality: placing objects in the real world through the camera, AR try-on,
25
+ AR markers.
26
+
27
+ Rules, in priority order:
28
+ 1. Any mention of augmented reality / placing content in the real camera view → `ar` — even when
29
+ the request also talks about 3D models or files (AR apps use 3D models; AR still wins).
30
+ 2. Explicit 3D content (3D models, 3D world, first-person, "объёмный", "3D-сцена") → `3d`.
31
+ 3. A game whose dimensionality is unstated or flat (platformer, tetris, snake, match-3,
32
+ card game, "аркада", "платформер") → `2d`. A game is `3d` only when 3D is asked for.
33
+ 4. Everything else — apps, tools, content, commerce, communication → `ui`.
34
+ 5. A mixed request (an app that contains a mini-game, a game with menus) → the game's engine
35
+ decides (`2d`/`3d`), because game bundles already include the full UI module.
36
+ 6. Genuinely uncertain → `ui`.
37
+
38
+ Examples:
39
+ - "Make a todo list with reminders" → ui
40
+ - "Сделай приложение для учёта расходов с графиками" → ui
41
+ - "A platformer where a fox collects coins" → 2d
42
+ - "Игра типа тетриса" → 2d
43
+ - "Рисовалка пальцем с кистями" → 2d
44
+ - "A game where you throw a basketball into a hoop with physics" → 3d
45
+ - "Просмотрщик наших 3D-моделей мебели с вращением" → 3d
46
+ - "Расставлять мебель у себя в комнате через камеру" → ar
47
+ - "Try on sneakers in AR" → ar
48
+ - "Создай приложение для дополненной реальности, используй 3D модель из файлов" → ar
49
+ - "Магазин кроссовок с корзиной и оплатой" → ui
50
+ - "Викторина с таймером и мини-игрой в конце" → 2d
@@ -0,0 +1,111 @@
1
+ // Bundle selection from PROJECT CODE — the primary, deterministic signal.
2
+ //
3
+ // Scans the project's TypeScript sources for SDK globals and maps them to a prompt bundle.
4
+ // Language-independent (works whatever language the user writes requests in), free, and exact:
5
+ // if the project already renders a Scene2D, no model needs to guess anything.
6
+ //
7
+ // Returns null when the code carries no signal (empty/new project) — the caller then falls back
8
+ // to the router model (see router-prompt.md) with the user's first message.
9
+ //
10
+ // const bundle = detectBundle(files) ?? await routeWithModel(userMessage)
11
+ //
12
+ // Keep the global lists in sync with sdk/src/inject.ts (docs/index.md is the human-readable map).
13
+
14
+ export type Bundle = "ui-app" | "2d-game" | "3d-app" | "ar-app"
15
+
16
+ export interface ProjectFile {
17
+ path: string
18
+ content: string
19
+ }
20
+
21
+ // Globals that unambiguously identify an engine. Deliberately only DISTINCTIVE names: generic
22
+ // words a user might declare themselves (Model, Shape, Physics, Trigger, Ray, Plane, Sprite) are
23
+ // excluded — any real engine project necessarily also references one of the distinctive globals
24
+ // (a body/model is useless without a Scene/Mesh/Scene2D somewhere in the project).
25
+ // Word-boundary matching keeps `Scene` from matching `Scene2D` (a digit is a word char, so
26
+ // \bScene\b does not match inside "Scene2D" — and \bdefineScene\b not inside "defineScene2d").
27
+ // defineScene/defineScene2d matter because a scene-editor project's code can be JUST a .scene.ts
28
+ // plus a lowercase 3-line entry (`import scene …; scene.open()`) — no capitalized global
29
+ // anywhere, which used to route visual-editor projects onto the UI bundle.
30
+ const AR_GLOBALS = ["ARScene"]
31
+ const GL_GLOBALS = [
32
+ "Scene", "Mesh", "ModelAnimation", "Material", "Light", "Geometry", "Particles",
33
+ "CharacterController", "defineScene",
34
+ ]
35
+ const G2_GLOBALS = [
36
+ "Scene2D", "Node2D", "Camera2D", "SpriteAnimation", "Tilemap", "Texture2D",
37
+ "Shape2D", "Physics2D", "Trigger2D", "CharacterController2D", "defineScene2d",
38
+ ]
39
+
40
+ const matcher = (names: string[]) => new RegExp(`\\b(?:${names.join("|")})\\b`)
41
+ const AR_RE = matcher(AR_GLOBALS)
42
+ const GL_RE = matcher(GL_GLOBALS)
43
+ const G2_RE = matcher(G2_GLOBALS)
44
+
45
+ // Strip line/block comments and string/template literals so a mention in prose ("// TODO: try
46
+ // Scene2D some day", a localized UI label) can't select an engine the code doesn't use.
47
+ // Heuristic, not a parser — good enough for signal detection.
48
+ const stripNoise = (src: string): string =>
49
+ src
50
+ .replace(/\/\*[\s\S]*?\*\//g, " ")
51
+ .replace(/\/\/[^\n]*/g, " ")
52
+ .replace(/`(?:\\.|[^`\\])*`/g, '""')
53
+ .replace(/"(?:\\.|[^"\\\n])*"/g, '""')
54
+ .replace(/'(?:\\.|[^'\\\n])*'/g, '""')
55
+
56
+ const isSource = (path: string): boolean =>
57
+ path.endsWith(".ts") && !path.includes(".lecodes") && !path.endsWith(".d.ts")
58
+
59
+ /**
60
+ * Detect the prompt bundle from project sources, or null if the code has no engine signal
61
+ * (typically an empty or UI-less new project with no UI code yet either).
62
+ *
63
+ * Priority: AR > 3D > 2D > UI. AR implies 3D; every game bundle includes the UI module, so
64
+ * over-selection is safe and under-selection is what we guard against.
65
+ */
66
+ export function detectBundle(files: ProjectFile[]): Bundle | null {
67
+ let sawAny = false
68
+ let ar = false, gl = false, g2 = false
69
+
70
+ for (const f of files) {
71
+ if (!isSource(f.path)) continue
72
+ sawAny = true
73
+ const code = stripNoise(f.content)
74
+ ar ||= AR_RE.test(code)
75
+ gl ||= GL_RE.test(code)
76
+ g2 ||= G2_RE.test(code)
77
+ if (ar) break // strongest signal — nothing can override it
78
+ }
79
+
80
+ if (ar) return "ar-app"
81
+ if (gl) return "3d-app"
82
+ if (g2) return "2d-game"
83
+ // Sources exist and reference no engine → it's a UI app (UI globals or not-yet-written code;
84
+ // the ui-app bundle is the correct default for both).
85
+ if (sawAny) return "ui-app"
86
+ return null // empty project — route by the user's message (router-prompt.md)
87
+ }
88
+
89
+ /**
90
+ * Sticky per-conversation upgrade: once a bundle is chosen, only ever move UP the specificity
91
+ * ladder (ui → 2d/3d → ar) mid-conversation — never down, so the prompt-cache prefix stays
92
+ * stable while a project grows from "empty" to "3D game with a HUD".
93
+ */
94
+ export function upgradeBundle(current: Bundle, detected: Bundle): Bundle {
95
+ const rank: Record<Bundle, number> = { "ui-app": 0, "2d-game": 1, "3d-app": 1, "ar-app": 2 }
96
+ return rank[detected] > rank[current] ? detected : current
97
+ }
98
+
99
+ const DIRECTIVE_WORD: Record<string, Bundle> = { "2d": "2d-game", "3d": "3d-app", "ar": "ar-app" }
100
+
101
+ /**
102
+ * The `<bundle>ar</bundle>` escalation directive (core.md "Missing engine"): a misrouted model
103
+ * saw a request for engine APIs its prompt doesn't document and asks to be re-run with the right
104
+ * bundle instead of inventing APIs. Counts only when the reply IS the directive (a sentence of
105
+ * preamble is tolerated) — a reply that also carries code operations never triggers a re-send.
106
+ */
107
+ export function parseBundleDirective(reply: string): Bundle | null {
108
+ if (reply.length > 500 || /<(?:file|edit|remove)[\s>]/.test(reply)) return null
109
+ const m = /<bundle>\s*(2d|3d|ar)\s*<\/bundle>/.exec(reply)
110
+ return m ? DIRECTIVE_WORD[m[1]!]! : null
111
+ }
@@ -0,0 +1,203 @@
1
+ // ===== UI RULES =====
2
+ // (Curated for design mode from ui.md — the mockup-relevant surface. KEEP IN SYNC when styling or
3
+ // component contracts change there.)
4
+ // - Default screen background is BLACK — always set bgColor and text color explicitly
5
+ // - Only use style properties listed below — never invent new ones, they may not exist in the engine
6
+ // - Extract repeated styles into Style<T> objects and repeated UI into factory functions
7
+ // - Keep layout minimal — no wrapper containers that exist only to align something (alignment is a container property)
8
+
9
+ // ===== UI COMPONENTS =====
10
+ // Every element is created by a global factory function (never `new`) that takes only the element's
11
+ // CONTENT — children as plain arguments (or text/src/...). Everything else — styles — is configured
12
+ // by chaining: every configuring method returns the element itself, so construction reads as one chain.
13
+ UIColumn(UIText("Title"), UIButton(UIText("Go")))
14
+ // An ARRAY argument is flattened into the children — pass items.map(Row) directly, no spread:
15
+ UIColumn(header, items.map(Row), footer)
16
+
17
+ // UIRow, UIColumn — containers (UIColumn stacks vertically, UIRow horizontally)
18
+ UIRow(...children) / UIColumn(...children)
19
+
20
+ // UIScreen — root screen, always fills the device. Behaves as a UIColumn.
21
+ UIScreen(...children)
22
+ // Screens NEVER scroll — one vertical flow (article, long form, feed) = fixed chrome + ONE UIScrollable body
23
+ // with flexGrow: 1: UIScreen(Header(), UIScrollable(content).style({ flexGrow: 1 }))
24
+ // Note: a screen always fills the device — sizing styles on it (width, height, flexGrow, position) are no-ops
25
+ // A design screen is returned from the file's default export — never call .open()
26
+
27
+ // UIWidget — floating overlay above the screen, position: fixed in device coordinates
28
+ UIWidget(...children)
29
+ // .show(), .hide(), .onOverlayTap(cb)
30
+ // extra style: overlayColor — full-screen scrim BEHIND the widget that blocks taps underneath, turning it
31
+ // into a modal (dialog / bottom sheet). Size the widget box to the CONTENT only (bottom-anchor a sheet
32
+ // via left/right/bottom, or center a dialog card inside a full-inset box) — the scrim paints full-screen.
33
+ // .onOverlayTap usually () => widget.hide() — a sheet dismisses; a confirm dialog that demands an explicit
34
+ // choice takes NO onOverlayTap.
35
+ // In a design, show() an overlay from a screen state branch (see design rules) — never embed a sheet as an
36
+ // absolutely-positioned child of the screen.
37
+
38
+ // UIScrollable — THE scroll container: a screen's scrolling body, a list under a pinned header, a
39
+ // horizontal chip row / carousel
40
+ UIScrollable(...children)
41
+ // extra styles: scrollDirection ("horizontal" | "vertical", default vertical), showScrollbar: boolean
42
+ // Note: defaults flexShrink: 1 (scrolls instead of overflowing) — wrapping ancestors still need flexShrink: 1
43
+
44
+ // UIText
45
+ UIText(text)
46
+ // extra styles: fontSize (default 14), fontWeight (number | "normal" | "bold"), fontFamily, color,
47
+ // textAlign ("start"|"center"|"end"|"left"|"right", default left), lineHeight, fontStyle ("normal"|"italic"),
48
+ // textDecoration ("underline"|"line-through"|"none"), letterSpacing
49
+
50
+ // UIImage
51
+ UIImage(src) // src: string url | SvgSource | imported asset
52
+ // extra styles: objectFit ("cover"|"contain"|"fill"), tintColor (SVG only), borderRadius (number px only on UIImage)
53
+ // Note: tintColor applies only to SVG sources — it replaces ALL fill and stroke colors (monochrome icons only)
54
+ // Note: a bare relative path string won't resolve — plain strings are for https:// URLs; project files go
55
+ // through import or asset('./photo.jpg')
56
+
57
+ // UIButton — the only TAPPABLE container: a UIRow with children centered on both axes by default.
58
+ // Anything clickable in the prototype (a card, a list row, an icon) — wrap it in a UIButton.
59
+ UIButton(...children)
60
+ // extra styles: onPressed: { bgColor, opacity, ... } — style while the finger is down (press feedback is
61
+ // OPT-IN; set it so the live prototype feels real)
62
+ // Note: buttons render no chrome of their own — style bgColor/borderRadius/padding yourself, and give a
63
+ // button an explicit height (on its own it is only as tall as its text). flexDirection: "column" for cards.
64
+
65
+ // Text fields in a MOCKUP are drawn, not functional: render the value/placeholder as a styled UIText
66
+ // inside a field-shaped UIRow (a real UIInput's imperatively-set value doesn't render in the board's
67
+ // preview, and a mockup never needs one). Draw a password as dots ("••••••••"), a focused field with
68
+ // an accent border, a placeholder in muted color.
69
+
70
+ // UISpacer — flexible empty space (defaults flexGrow: 1), eats free space along the main axis.
71
+ // Only when plain alignment can't express it (one item pushed to the far end while the rest stay put):
72
+ UIRow(title, UISpacer(), closeButton)
73
+ // If ALL children move together, justifyContent ("space-between", "flex-end", ...) does it with no extra element.
74
+
75
+ // ===== STYLING =====
76
+ // Every UI element has a .style() method. It MERGES the given styles (does not replace) and RETURNS the
77
+ // element, so calls chain and later calls only override the keys they mention:
78
+ UIText("Hi").style({ color: "white" }).style({ fontSize: 20 })
79
+ // (You may see older code passing a style object as the FIRST factory argument — legacy; always use .style().)
80
+
81
+ // Style<T> is a global helper type for reusable style objects, no import needed:
82
+ const label: Style<UIText> = { fontSize: 12, fontWeight: 600, letterSpacing: 2 }
83
+
84
+ // --- Style vocabulary ---
85
+ // Layout is Flexbox-only (Yoga engine). No CSS grid, no block layout.
86
+ // Every element is a flex container, position: relative, flexDirection: column by default (UIRow AND UIButton flip to row).
87
+ // Container layout: flexDirection, justifyContent ("flex-start"|"center"|"flex-end"|"space-between"|"space-evenly"),
88
+ // alignItems ("flex-start"|"center"|"flex-end"|"stretch", default "stretch"), gap, flexWrap
89
+ // Flex child: flex, flexGrow (default 0), flexShrink (default 0), flexBase (NOT flexBasis), alignSelf, aspectRatio
90
+ // Size: width, height, minWidth, maxWidth, minHeight, maxHeight
91
+ // Position: position ("relative"|"absolute"|"static"), top, left, right, bottom
92
+ // Padding: p, px, py, pt, pb, pl, pr (≡ padding, paddingHorizontal, paddingVertical, paddingTop, ...)
93
+ // Margin: m, mx, my, mt, mb, ml, mr — margins also accept "auto" (mx: "auto" centers a fixed-width element)
94
+ // Background (containers/screen/button; UIText/UIImage/UISpacer have bgColor only):
95
+ // bgColor, bgImage (string | imported asset), bgSize ("cover"|"contain"|"tile"), bgGradient
96
+ // bgGradient: a CSS linear-gradient() or radial-gradient() string, e.g. "linear-gradient(to top, rgba(0,0,0,0.7), transparent)".
97
+ // Layers paint bottom-to-top: bgColor → bgImage → bgGradient (gradient over image = text scrim).
98
+ // bgImage is decoration BEHIND children — an image that IS the content belongs in UIImage.
99
+ // Border: border ("1px solid #333" or bare width), borderWidth, borderColor,
100
+ // borderRadius (UIValue, or per-corner string "0 0 20 20"), per-side shorthands (borderTop, ...) and
101
+ // longhands (borderTopWidth, borderTopColor, borderLeftColor, borderTopLeftRadius, ...)
102
+ // Other: display ("none" | "flex"), opacity (0..1), transform (CSS string, e.g. `translateY(12px)`),
103
+ // overflow ("hidden" | "visible"), pointerEvents ("all" | "none")
104
+
105
+ // --- Values & units (UIValue) ---
106
+ // number (px) | "50%" | "50vw" | "50vh" | "1.5em" | "calc(...)" | "min(...)" | "max(...)" | "clamp(min, val, max)" | "var(--name)" / "var(--name, fallback)"
107
+ // Note: number value → logical px; string value → same semantics as on the web
108
+ // Note: "em" resolves against the element's OWN fontSize (default 14) — there is NO style inheritance
109
+ // Note: calc()/min()/max() do NOT support % ("calc(100% - 20px)" is invalid; use "calc(100vw - 20px)")
110
+
111
+ // --- Colors in UI styles ---
112
+ // hex "#f33"/"#f33c"/"#ff3333"/"#ff3333cc" (8 digits = alpha), packed int 0xff3333, "rgb(...)"/"rgba(...)",
113
+ // and exactly these names: white black red green blue yellow orange purple gray cyan magenta brown transparent clear
114
+
115
+ // --- Safe areas ---
116
+ // Env keywords resolving to the device insets (notch, home indicator):
117
+ // "safe-top" | "safe-bottom" | "safe-left" | "safe-right"; "safe-all" — p / m shorthands only
118
+ // Comfort tokens — where content comfortably starts (inset + a small margin, never 0):
119
+ // "comfort-top" | "comfort-bottom" | "comfort-left" | "comfort-right" | "comfort-x" | "comfort-y" | "comfort-all"
120
+ // Accepted on per-side padding & margin, position offsets, and inside calc()/min()/max():
121
+ .style({ pt: "safe-top" }) // screen root clearing the notch
122
+ .style({ pb: "safe-bottom" }) // tab bar clearing the home indicator
123
+
124
+ // --- Theme variables ---
125
+ // theme({...}) merges app vars into one table; styles read them with "var(--name)" (numbers are px):
126
+ const T = theme({ primaryColor: "#0A84FF" })
127
+ label.style({ color: T.primaryColor }) // or "var(--primaryColor)"
128
+ // theme({ color, fontFamily }) drive the DEFAULT text color/font app-wide. "var(--name, fallback)"
129
+ // applies the fallback while the key is unset — how the SDK tab bar (defineTabs) stays themeable.
130
+
131
+ // --- Defaults that surprise ---
132
+ // flexShrink: 0 — elements don't shrink to fit (exception: UIScrollable defaults flexShrink: 1 so it scrolls
133
+ // instead of overflowing; wrapping ancestors still default to 0).
134
+ // flexGrow: 0 — nothing grows along the main axis without asking; no implicit min-sizes either.
135
+ // alignItems: "stretch" — children FILL the cross axis by default; set a size or alignSelf to opt out.
136
+ // overflow: "hidden" — children are clipped to the parent's box; set overflow: "visible" to let them escape
137
+ // (a badge nudged outside its button's corner needs it).
138
+ // Screen background is black, default fontSize is 14, default text color is WHITE. On any light
139
+ // surface — white cards, sheets — that default renders invisible text: use dark text there ("#111").
140
+ // Check every UIText against the surface it actually sits on, not the screen.
141
+
142
+ // --- Screen size ---
143
+ // Units are logical px (iOS pt / Android dp) — fontSize: 16 looks the same on every device.
144
+ // Design for a phone canvas: width ~360–430 (use 390 as default), height ~670–930.
145
+ // Vertical space is scarce — long content goes in a UIScrollable body (screens never scroll).
146
+
147
+ // ===== REUSABLE COMPONENTS =====
148
+ // Extract repeated UI into factory functions — they return elements you can chain on:
149
+ const StatusPill = (label: string, color: string, filled = false) =>
150
+ UIColumn(UIText(label).style({ fontSize: 12, fontWeight: 600, color: filled ? "#05201f" : color }))
151
+ .style({ height: 26, px: 10, borderRadius: 999, justifyContent: "center", alignItems: "center",
152
+ bgColor: filled ? color : "transparent", border: filled ? undefined : `1px solid ${color}`,
153
+ alignSelf: "flex-start" })
154
+
155
+ // ===== CONDITIONAL CHILDREN =====
156
+ // A null / undefined / false child is skipped — no element, no layout slot.
157
+ UIColumn(header, item.unread ? dot : null, items.map(Card))
158
+
159
+ // ===== SIZING: the two axes behave differently =====
160
+ // MAIN axis (row → width, column → height): elements stay as small as their content — nothing grows
161
+ // without flexGrow: 1.
162
+ // CROSS axis: children fill the parent by default (alignItems: "stretch"); set an explicit size
163
+ // or alignSelf to opt out.
164
+ // A text column beside fixed-width siblings needs flexGrow: 1, flexShrink: 1, flexBase: 0 to take
165
+ // the remaining width AND wrap instead of pushing them out.
166
+
167
+ // ===== SVG IMAGES =====
168
+ // SvgSource wraps raw SVG XML for use as an image source: UIImage(SvgSource(`<svg ...>`)).
169
+ // Rendered natively — only basic geometry works (path, rect, circle, line, polygon, solid
170
+ // fill/stroke, opacity, transform, gradients). No text, filters or CSS — they vanish on device.
171
+ // Prefer a separate .svg file (a brand logo traced once in shared/) over inline XML.
172
+ UIImage(logoSvg).style({ height: 24, tintColor: "#00BFC2", objectFit: "contain" })
173
+
174
+ // ===== COMMON MISTAKES — DO NOT DO THESE =====
175
+
176
+ // ❌ CSS that doesn't exist here
177
+ display: "grid" // WRONG — Flexbox only (Yoga)
178
+ calc(100% - 20px) // WRONG — calc() can't mix with %
179
+ lineHeight: 1.5 // WRONG — number is px (=1.5px); for a multiplier use "1.5em"
180
+
181
+ // ❌ scrollable that overflows the screen
182
+ // A wrapping container between the scrollable and the screen is missing flexShrink: 1
183
+
184
+ // ❌ empty containers as spacers to align children (web habit)
185
+ UIRow(UIColumn().style({ flexGrow: 1 }), label) // WRONG
186
+ // ✅ alignment is a CONTAINER property, not an extra element
187
+ UIRow(label).style({ justifyContent: "flex-end" })
188
+
189
+ // ❌ empty element as a placeholder for a conditional child
190
+ UIRow(isSelected ? check : UIColumn()) // WRONG
191
+ // ✅ null is skipped in children — no phantom element
192
+ UIRow(isSelected ? check : null)
193
+
194
+ // ❌ pointing UIImage / bgImage at a project file by bare path — it won't resolve to the bundled asset
195
+ UIImage("./photo.jpg") // WRONG (a plain string works only for remote http(s) URLs)
196
+ // ✅ import the asset, or wrap its path in asset()
197
+ UIImage(asset('./assets/avatars/alina.jpg'))
198
+
199
+ // ❌ setting a UIImage's content through bgImage
200
+ // bgImage is a container background, not image content — pass the source to UIImage(...)
201
+
202
+ // ❌ a card row where the title column has no flexBase — long titles push the price off-screen
203
+ // ✅ middle column: flexGrow: 1, flexShrink: 1, flexBase: 0