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.
- package/README.md +114 -0
- package/dist/global.d.ts +503 -0
- package/dist/host.d.ts +61 -0
- package/dist/inject.js +4730 -0
- package/dist/types/animate/animate.d.ts +20 -0
- package/dist/types/animate/bezier.d.ts +2 -0
- package/dist/types/animate/easings.d.ts +21 -0
- package/dist/types/canvas/Canvas.d.ts +168 -0
- package/dist/types/core/Aspect.d.ts +171 -0
- package/dist/types/core/InspectorUI.d.ts +88 -0
- package/dist/types/core/StateMachine.d.ts +81 -0
- package/dist/types/core/color.d.ts +13 -0
- package/dist/types/core/compWrite.d.ts +11 -0
- package/dist/types/core/events.d.ts +11 -0
- package/dist/types/core/fields.d.ts +58 -0
- package/dist/types/core/registry.d.ts +7 -0
- package/dist/types/core/signals.d.ts +29 -0
- package/dist/types/core/time.d.ts +31 -0
- package/dist/types/g2/Camera2D.d.ts +19 -0
- package/dist/types/g2/CharacterController2D.d.ts +134 -0
- package/dist/types/g2/Node2D.d.ts +91 -0
- package/dist/types/g2/OneWay2D.d.ts +24 -0
- package/dist/types/g2/Physics2D.d.ts +147 -0
- package/dist/types/g2/Scene2D.d.ts +72 -0
- package/dist/types/g2/Shape2D.d.ts +58 -0
- package/dist/types/g2/Sprite.d.ts +51 -0
- package/dist/types/g2/SpriteAnimation.d.ts +50 -0
- package/dist/types/g2/SpriteSheet.d.ts +69 -0
- package/dist/types/g2/Texture2D.d.ts +16 -0
- package/dist/types/g2/Tilemap.d.ts +20 -0
- package/dist/types/g2/Tileset.d.ts +32 -0
- package/dist/types/g2/Trigger2D.d.ts +20 -0
- package/dist/types/g2/autotile.d.ts +133 -0
- package/dist/types/g2/cells.d.ts +14 -0
- package/dist/types/g2/defineScene2d.d.ts +141 -0
- package/dist/types/g2/groups2d.d.ts +16 -0
- package/dist/types/g2/loop.d.ts +4 -0
- package/dist/types/g2/scenarios2d.d.ts +30 -0
- package/dist/types/g2/touch.d.ts +2 -0
- package/dist/types/gl/Camera.d.ts +79 -0
- package/dist/types/gl/CameraPlace.d.ts +26 -0
- package/dist/types/gl/CharacterController.d.ts +98 -0
- package/dist/types/gl/Gearbox.d.ts +86 -0
- package/dist/types/gl/Geometry.d.ts +39 -0
- package/dist/types/gl/IK.d.ts +53 -0
- package/dist/types/gl/InstancedMesh.d.ts +46 -0
- package/dist/types/gl/Light.d.ts +73 -0
- package/dist/types/gl/Lightmap.d.ts +85 -0
- package/dist/types/gl/Locomotion.d.ts +279 -0
- package/dist/types/gl/Material.d.ts +100 -0
- package/dist/types/gl/Mesh.d.ts +33 -0
- package/dist/types/gl/Model.d.ts +53 -0
- package/dist/types/gl/NavAgent.d.ts +99 -0
- package/dist/types/gl/NavMesh.d.ts +169 -0
- package/dist/types/gl/Node.d.ts +99 -0
- package/dist/types/gl/Noise.d.ts +20 -0
- package/dist/types/gl/Particles.d.ts +277 -0
- package/dist/types/gl/Physics.d.ts +91 -0
- package/dist/types/gl/Plane.d.ts +19 -0
- package/dist/types/gl/Ragdoll.d.ts +86 -0
- package/dist/types/gl/Ray.d.ts +8 -0
- package/dist/types/gl/Scene.d.ts +221 -0
- package/dist/types/gl/Shape.d.ts +122 -0
- package/dist/types/gl/Terrain.d.ts +280 -0
- package/dist/types/gl/Texture.d.ts +27 -0
- package/dist/types/gl/Trigger.d.ts +10 -0
- package/dist/types/gl/Vehicle.d.ts +191 -0
- package/dist/types/gl/Wheel.d.ts +95 -0
- package/dist/types/gl/animation/AnimationClip.d.ts +60 -0
- package/dist/types/gl/animation/Animator.d.ts +219 -0
- package/dist/types/gl/animation/Layer.d.ts +31 -0
- package/dist/types/gl/animation/Loop.d.ts +17 -0
- package/dist/types/gl/animation/Playback.d.ts +36 -0
- package/dist/types/gl/animation/core.d.ts +367 -0
- package/dist/types/gl/controls.d.ts +19 -0
- package/dist/types/gl/physicsEvents.d.ts +1 -0
- package/dist/types/gl/scenarios.d.ts +98 -0
- package/dist/types/gl/state.d.ts +5 -0
- package/dist/types/gl/terrainMesh.d.ts +46 -0
- package/dist/types/gl/touch.d.ts +2 -0
- package/dist/types/inject.d.ts +123 -0
- package/dist/types/math/Mathf.d.ts +39 -0
- package/dist/types/math/mat4.d.ts +66 -0
- package/dist/types/math/quat.d.ts +53 -0
- package/dist/types/math/vec.d.ts +129 -0
- package/dist/types/net/codec.d.ts +25 -0
- package/dist/types/net/core.d.ts +106 -0
- package/dist/types/net/index.d.ts +80 -0
- package/dist/types/net/replication.d.ts +101 -0
- package/dist/types/plugins/camera.d.ts +25 -0
- package/dist/types/plugins/geolocation.d.ts +39 -0
- package/dist/types/plugins/oauth.d.ts +25 -0
- package/dist/types/plugins/permission.d.ts +1 -0
- package/dist/types/plugins/push.d.ts +46 -0
- package/dist/types/plugins/qr.d.ts +21 -0
- package/dist/types/plugins/service.d.ts +33 -0
- package/dist/types/runtime/app.d.ts +67 -0
- package/dist/types/runtime/appEvents.d.ts +7 -0
- package/dist/types/runtime/channel.d.ts +1 -0
- package/dist/types/runtime/clipboard.d.ts +7 -0
- package/dist/types/runtime/datetime.d.ts +80 -0
- package/dist/types/runtime/device.d.ts +126 -0
- package/dist/types/runtime/fetch.d.ts +31 -0
- package/dist/types/runtime/files.d.ts +33 -0
- package/dist/types/runtime/input.d.ts +121 -0
- package/dist/types/runtime/media.d.ts +46 -0
- package/dist/types/runtime/misc.d.ts +11 -0
- package/dist/types/runtime/net.d.ts +15 -0
- package/dist/types/runtime/rpc.d.ts +44 -0
- package/dist/types/runtime/service.d.ts +1 -0
- package/dist/types/runtime/share.d.ts +2 -0
- package/dist/types/runtime/storage.d.ts +5 -0
- package/dist/types/runtime/touch.d.ts +56 -0
- package/dist/types/scene/defineScene.d.ts +296 -0
- package/dist/types/scene/editorPlugins.d.ts +82 -0
- package/dist/types/scene/gizmos.d.ts +56 -0
- package/dist/types/scene/grammar.d.ts +56 -0
- package/dist/types/scene/level.d.ts +98 -0
- package/dist/types/scene/material.d.ts +76 -0
- package/dist/types/server/auth/appConfig.d.ts +16 -0
- package/dist/types/server/auth/global.d.ts +56 -0
- package/dist/types/server/auth/models.d.ts +164 -0
- package/dist/types/server/auth/types.d.ts +56 -0
- package/dist/types/server/channel.d.ts +28 -0
- package/dist/types/server/context.d.ts +27 -0
- package/dist/types/server/db/defineDb.d.ts +36 -0
- package/dist/types/server/db/fields.d.ts +146 -0
- package/dist/types/server/db/index.d.ts +6 -0
- package/dist/types/server/db/marci/query.d.ts +326 -0
- package/dist/types/server/db/types.d.ts +163 -0
- package/dist/types/server/errors.d.ts +8 -0
- package/dist/types/server/inject.d.ts +5 -0
- package/dist/types/ui/NativeView.d.ts +38 -0
- package/dist/types/ui/UI.d.ts +27 -0
- package/dist/types/ui/UIBottomSheet.d.ts +71 -0
- package/dist/types/ui/UIButton.d.ts +30 -0
- package/dist/types/ui/UIContainer.d.ts +33 -0
- package/dist/types/ui/UIImage.d.ts +35 -0
- package/dist/types/ui/UIInput.d.ts +110 -0
- package/dist/types/ui/UIModal.d.ts +70 -0
- package/dist/types/ui/UINode.d.ts +363 -0
- package/dist/types/ui/UIPager.d.ts +123 -0
- package/dist/types/ui/UIPopover.d.ts +39 -0
- package/dist/types/ui/UIScreen.d.ts +57 -0
- package/dist/types/ui/UIScrollable.d.ts +40 -0
- package/dist/types/ui/UISpacer.d.ts +9 -0
- package/dist/types/ui/UITabs.d.ts +96 -0
- package/dist/types/ui/UIText.d.ts +19 -0
- package/dist/types/ui/UIVideo.d.ts +28 -0
- package/dist/types/ui/UIVirtualizedList.d.ts +97 -0
- package/dist/types/ui/UIWidget.d.ts +65 -0
- package/dist/types/ui/fonts.d.ts +9 -0
- package/dist/types/ui/presentable.d.ts +68 -0
- package/dist/types/ui/router.d.ts +40 -0
- package/dist/types/ui/theme.d.ts +26 -0
- package/dist/types.json +1 -0
- package/package.json +46 -0
- package/prompts/2d.md +395 -0
- package/prompts/3d-scene-files.md +113 -0
- package/prompts/3d-scene.md +119 -0
- package/prompts/3d.md +303 -0
- package/prompts/README.md +142 -0
- package/prompts/ar.md +109 -0
- package/prompts/canvas.md +27 -0
- package/prompts/compose.ts +46 -0
- package/prompts/concept.md +49 -0
- package/prompts/core-design.md +75 -0
- package/prompts/core.md +264 -0
- package/prompts/design.md +218 -0
- package/prompts/dist/2d-game.md +1530 -0
- package/prompts/dist/3d-app.md +1672 -0
- package/prompts/dist/ar-app.md +1548 -0
- package/prompts/dist/concept.md +49 -0
- package/prompts/dist/design.md +498 -0
- package/prompts/dist/ui-app.md +1134 -0
- package/prompts/index.md +37 -0
- package/prompts/intake-prompt.md +33 -0
- package/prompts/namer-prompt.md +12 -0
- package/prompts/router-prompt.md +50 -0
- package/prompts/select.ts +111 -0
- package/prompts/ui-design.md +203 -0
- package/prompts/ui.md +803 -0
- package/src/animate/animate.ts +238 -0
- package/src/animate/bezier.ts +138 -0
- package/src/animate/easings.ts +126 -0
- package/src/bridges.d.ts +1345 -0
- package/src/canvas/Canvas.ts +305 -0
- package/src/compile/__tests__/assetIconMacro.test.ts +219 -0
- package/src/compile/__tests__/assetMacro.test.ts +74 -0
- package/src/compile/__tests__/assetName.test.ts +55 -0
- package/src/compile/__tests__/compile.test.ts +287 -0
- package/src/compile/__tests__/detectEntry.test.ts +132 -0
- package/src/compile/__tests__/fontMacro.test.ts +199 -0
- package/src/compile/aspectMacro.ts +86 -0
- package/src/compile/assetIconMacro.ts +384 -0
- package/src/compile/assetMacro.ts +146 -0
- package/src/compile/assetName.ts +50 -0
- package/src/compile/bundler.ts +287 -0
- package/src/compile/compileProject.ts +127 -0
- package/src/compile/detectEntry.ts +128 -0
- package/src/compile/fontMacro.ts +459 -0
- package/src/compile/fontRegistry.ts +78 -0
- package/src/compile/header.ts +67 -0
- package/src/compile/index.ts +100 -0
- package/src/compile/libraryImports.ts +52 -0
- package/src/compile/liteMaterial.ts +247 -0
- package/src/compile/sceneEditor.ts +88 -0
- package/src/compile/serverSplit.ts +233 -0
- package/src/compile/serverTypes.ts +227 -0
- package/src/compile/sfnt.ts +98 -0
- package/src/compile/shaderSchema.ts +202 -0
- package/src/compile/shaderTargets.ts +77 -0
- package/src/compile/sourcemap.ts +25 -0
- package/src/core/Aspect.ts +568 -0
- package/src/core/InspectorUI.ts +212 -0
- package/src/core/StateMachine.ts +308 -0
- package/src/core/__tests__/stateMachine.test.ts +132 -0
- package/src/core/color.ts +66 -0
- package/src/core/compWrite.ts +42 -0
- package/src/core/events.ts +38 -0
- package/src/core/fields.ts +120 -0
- package/src/core/registry.ts +23 -0
- package/src/core/signals.ts +277 -0
- package/src/core/time.ts +84 -0
- package/src/g2/Camera2D.ts +40 -0
- package/src/g2/CharacterController2D.ts +276 -0
- package/src/g2/Node2D.ts +267 -0
- package/src/g2/OneWay2D.ts +66 -0
- package/src/g2/Physics2D.ts +346 -0
- package/src/g2/Scene2D.ts +209 -0
- package/src/g2/Shape2D.ts +259 -0
- package/src/g2/Sprite.ts +89 -0
- package/src/g2/SpriteAnimation.ts +171 -0
- package/src/g2/SpriteSheet.ts +166 -0
- package/src/g2/Texture2D.ts +47 -0
- package/src/g2/Tilemap.ts +41 -0
- package/src/g2/Tileset.ts +71 -0
- package/src/g2/Trigger2D.ts +77 -0
- package/src/g2/autotile.ts +433 -0
- package/src/g2/cells.ts +91 -0
- package/src/g2/defineScene2d.ts +381 -0
- package/src/g2/groups2d.ts +106 -0
- package/src/g2/loop.ts +50 -0
- package/src/g2/scenarios2d.ts +69 -0
- package/src/g2/touch.ts +83 -0
- package/src/gl/Camera.ts +160 -0
- package/src/gl/CameraPlace.ts +52 -0
- package/src/gl/CharacterController.ts +238 -0
- package/src/gl/Gearbox.ts +212 -0
- package/src/gl/Geometry.ts +279 -0
- package/src/gl/IK.ts +193 -0
- package/src/gl/InstancedMesh.ts +132 -0
- package/src/gl/Light.ts +135 -0
- package/src/gl/Lightmap.ts +402 -0
- package/src/gl/Locomotion.ts +498 -0
- package/src/gl/Material.ts +279 -0
- package/src/gl/Mesh.ts +83 -0
- package/src/gl/Model.ts +124 -0
- package/src/gl/NavAgent.ts +337 -0
- package/src/gl/NavMesh.ts +397 -0
- package/src/gl/Node.ts +350 -0
- package/src/gl/Noise.ts +30 -0
- package/src/gl/Particles.ts +676 -0
- package/src/gl/Physics.ts +222 -0
- package/src/gl/Plane.ts +53 -0
- package/src/gl/Ragdoll.ts +270 -0
- package/src/gl/Ray.ts +16 -0
- package/src/gl/Scene.ts +505 -0
- package/src/gl/Shape.ts +409 -0
- package/src/gl/Terrain.ts +1092 -0
- package/src/gl/Texture.ts +63 -0
- package/src/gl/Trigger.ts +45 -0
- package/src/gl/Vehicle.ts +473 -0
- package/src/gl/Wheel.ts +240 -0
- package/src/gl/animation/AnimationClip.ts +204 -0
- package/src/gl/animation/Animator.ts +329 -0
- package/src/gl/animation/Layer.ts +39 -0
- package/src/gl/animation/Loop.ts +31 -0
- package/src/gl/animation/Playback.ts +52 -0
- package/src/gl/animation/core.ts +670 -0
- package/src/gl/controls.ts +95 -0
- package/src/gl/physicsEvents.ts +20 -0
- package/src/gl/scenarios.ts +291 -0
- package/src/gl/state.ts +6 -0
- package/src/gl/terrainMesh.ts +219 -0
- package/src/gl/touch.ts +68 -0
- package/src/host.d.ts +61 -0
- package/src/inject.ts +203 -0
- package/src/math/Mathf.ts +118 -0
- package/src/math/mat4.ts +278 -0
- package/src/math/quat.ts +232 -0
- package/src/math/vec.ts +255 -0
- package/src/net/codec.ts +119 -0
- package/src/net/core.ts +384 -0
- package/src/net/index.ts +181 -0
- package/src/net/replication.ts +622 -0
- package/src/plugins/camera.ts +81 -0
- package/src/plugins/geolocation.ts +123 -0
- package/src/plugins/oauth.ts +61 -0
- package/src/plugins/permission.ts +7 -0
- package/src/plugins/push.ts +132 -0
- package/src/plugins/qr.ts +73 -0
- package/src/plugins/service.ts +47 -0
- package/src/runtime/app.ts +101 -0
- package/src/runtime/appEvents.ts +54 -0
- package/src/runtime/channel.ts +61 -0
- package/src/runtime/clipboard.ts +20 -0
- package/src/runtime/datetime.ts +329 -0
- package/src/runtime/device.ts +293 -0
- package/src/runtime/fetch.ts +77 -0
- package/src/runtime/files.ts +108 -0
- package/src/runtime/input.ts +175 -0
- package/src/runtime/media.ts +111 -0
- package/src/runtime/misc.ts +16 -0
- package/src/runtime/net.ts +36 -0
- package/src/runtime/rpc.ts +218 -0
- package/src/runtime/service.ts +83 -0
- package/src/runtime/share.ts +9 -0
- package/src/runtime/storage.ts +13 -0
- package/src/runtime/touch.ts +76 -0
- package/src/scene/defineScene.ts +1396 -0
- package/src/scene/editorPlugins.ts +110 -0
- package/src/scene/gizmos.ts +148 -0
- package/src/scene/grammar.ts +120 -0
- package/src/scene/level.ts +296 -0
- package/src/scene/material.ts +188 -0
- package/src/server/auth/appConfig.ts +12 -0
- package/src/server/auth/global.ts +80 -0
- package/src/server/auth/host.ts +318 -0
- package/src/server/auth/models.ts +83 -0
- package/src/server/auth/types.ts +50 -0
- package/src/server/channel.ts +56 -0
- package/src/server/context.ts +36 -0
- package/src/server/db/defineDb.ts +237 -0
- package/src/server/db/fields.ts +132 -0
- package/src/server/db/httpTransport.ts +93 -0
- package/src/server/db/index.ts +7 -0
- package/src/server/db/marci/query.ts +412 -0
- package/src/server/db/types.ts +202 -0
- package/src/server/errors.ts +12 -0
- package/src/server/host.ts +74 -0
- package/src/server/inject.ts +13 -0
- package/src/server/runtime.ts +133 -0
- package/src/server/validate.ts +87 -0
- package/src/ui/NativeView.ts +142 -0
- package/src/ui/UI.ts +39 -0
- package/src/ui/UIBottomSheet.ts +139 -0
- package/src/ui/UIButton.ts +101 -0
- package/src/ui/UIContainer.ts +60 -0
- package/src/ui/UIImage.ts +83 -0
- package/src/ui/UIInput.ts +185 -0
- package/src/ui/UIModal.ts +139 -0
- package/src/ui/UINode.ts +830 -0
- package/src/ui/UIPager.ts +362 -0
- package/src/ui/UIPopover.ts +100 -0
- package/src/ui/UIScreen.ts +123 -0
- package/src/ui/UIScrollable.ts +87 -0
- package/src/ui/UISpacer.ts +14 -0
- package/src/ui/UITabs.ts +236 -0
- package/src/ui/UIText.ts +51 -0
- package/src/ui/UIVideo.ts +88 -0
- package/src/ui/UIVirtualizedList.ts +241 -0
- package/src/ui/UIWidget.ts +127 -0
- package/src/ui/fonts.ts +13 -0
- package/src/ui/presentable.ts +117 -0
- package/src/ui/router.ts +132 -0
- package/src/ui/theme.ts +84 -0
package/prompts/index.md
ADDED
|
@@ -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
|