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
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import type { FetchResponse } from "../runtime/fetch";
|
|
2
|
+
export interface UINode {
|
|
3
|
+
readonly type: string;
|
|
4
|
+
/** Author-given semantic name (a stable selector for tests + AI review feedback). */
|
|
5
|
+
readonly name?: string;
|
|
6
|
+
style: Style<this, any>;
|
|
7
|
+
/** Style-class proxy — read/set/toggle/bind the `$`-classes declared in `.style()`. See {@link Classes}. */
|
|
8
|
+
readonly class: Classes<this>;
|
|
9
|
+
}
|
|
10
|
+
/** A child slot value: a node, or falsy (conditional rendering — falsy entries are skipped). */
|
|
11
|
+
export type UINodeChild = UINode | null | undefined | false;
|
|
12
|
+
/** A factory child argument: a node (or falsy for conditionals), or an array of them — arrays are
|
|
13
|
+
* flattened one level at the argument position, so `UIColumn(header, items.map(row), footer)`
|
|
14
|
+
* needs no spread. */
|
|
15
|
+
export type UIChildArg = UINodeChild | UINodeChild[];
|
|
16
|
+
/** A color: CSS-style string (`"#1c1c1e"`, `"rgba(0,0,0,0.5)"`, `"var(--primaryColor)"`) or
|
|
17
|
+
* packed number; `null` clears. */
|
|
18
|
+
export type Color = number | string | null;
|
|
19
|
+
/** Style props every element accepts. */
|
|
20
|
+
export type BaseStyle = {
|
|
21
|
+
opacity?: number | `${number}`;
|
|
22
|
+
transform?: string | null;
|
|
23
|
+
/** Pivot of `transform` (CSS `transform-origin` subset): one or two values, each a keyword
|
|
24
|
+
* (`left`/`center`/`right`, `top`/`center`/`bottom`), a percentage of the box, or a px length
|
|
25
|
+
* (bare numbers are px). One value sets x, y stays `50%`. Default `"50% 50%"` = the centre. */
|
|
26
|
+
transformOrigin?: string | null;
|
|
27
|
+
backgroundColor?: Color | null;
|
|
28
|
+
bgColor?: Color | null;
|
|
29
|
+
overflow?: "visible" | "hidden";
|
|
30
|
+
boxSizing?: "border-box" | "content-box";
|
|
31
|
+
/**
|
|
32
|
+
* Author-given semantic name — a stable selector for tests and for marking elements in the AI
|
|
33
|
+
* code-review feedback loop. NOT a style: it's extracted at construction (never sent to the layout
|
|
34
|
+
* engine) and surfaced on the node + in the renderer's serialized output. Available on every element.
|
|
35
|
+
*/
|
|
36
|
+
name?: string;
|
|
37
|
+
};
|
|
38
|
+
/** Painted-box props: background, gradient, border, radius. */
|
|
39
|
+
export type DrawableStyle = {
|
|
40
|
+
backgroundImage?: FetchResponse | File | string | null;
|
|
41
|
+
bgGradient?: string;
|
|
42
|
+
backgroundGradient?: string;
|
|
43
|
+
bgImage?: FetchResponse | File | string | null;
|
|
44
|
+
backgroundSize?: "cover" | "contain" | "tile";
|
|
45
|
+
bgSize?: "cover" | "contain" | "tile";
|
|
46
|
+
border?: string | number | null;
|
|
47
|
+
borderWidth?: number;
|
|
48
|
+
borderColor?: Color;
|
|
49
|
+
borderLeft?: string | number | null;
|
|
50
|
+
borderLeftWidth?: number;
|
|
51
|
+
borderLeftColor?: Color;
|
|
52
|
+
borderTop?: string | number | null;
|
|
53
|
+
borderTopWidth?: number;
|
|
54
|
+
borderTopColor?: Color;
|
|
55
|
+
borderRight?: string | number | null;
|
|
56
|
+
borderRightWidth?: number;
|
|
57
|
+
borderRightColor?: Color;
|
|
58
|
+
borderBottom?: string | number | null;
|
|
59
|
+
borderBottomWidth?: number;
|
|
60
|
+
borderBottomColor?: Color;
|
|
61
|
+
borderRadius?: UIValue | string;
|
|
62
|
+
borderTopLeftRadius?: UIValue;
|
|
63
|
+
borderTopRightRadius?: UIValue;
|
|
64
|
+
borderBottomLeftRadius?: UIValue;
|
|
65
|
+
borderBottomRightRadius?: UIValue;
|
|
66
|
+
pointerEvents?: "all" | "none";
|
|
67
|
+
};
|
|
68
|
+
/** Flex-layout props of a container (how it lays out its children). */
|
|
69
|
+
export type ContainerStyle = {
|
|
70
|
+
flexDirection?: "row" | "column";
|
|
71
|
+
justifyContent?: "flex-start" | "center" | "flex-end" | "space-between" | "space-evenly";
|
|
72
|
+
alignItems?: "flex-start" | "center" | "flex-end" | "stretch";
|
|
73
|
+
gap?: UIValue;
|
|
74
|
+
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
|
|
75
|
+
};
|
|
76
|
+
/** A dimension: a number (logical px) or a CSS-style unit / function string. */
|
|
77
|
+
type UIValue = number | `${number}px` | `${number}vw` | `${number}vh` | `${number}vmin` | `${number}vmax` | `${number}em` | `calc(${string})` | `min(${string})` | `max(${string})` | `${string}%` | `clamp(${string})` | `var(--${string})`;
|
|
78
|
+
/** Padding, with `p`/`px`/`pl`… shorthands. `safe-*` insets by the device safe area,
|
|
79
|
+
* `comfort-*` by the theme's comfort knobs (max of both). */
|
|
80
|
+
export type PaddingStyle = {
|
|
81
|
+
paddingLeft?: UIValue | "safe-left" | "comfort-left";
|
|
82
|
+
paddingTop?: UIValue | "safe-top" | "comfort-top";
|
|
83
|
+
paddingRight?: UIValue | "safe-right" | "comfort-right";
|
|
84
|
+
paddingBottom?: UIValue | "safe-bottom" | "comfort-bottom";
|
|
85
|
+
padding?: UIValue | "safe-all" | "comfort-all";
|
|
86
|
+
paddingHorizontal?: UIValue | "comfort-x";
|
|
87
|
+
paddingVertical?: UIValue | "comfort-y";
|
|
88
|
+
pl?: UIValue | "safe-left" | "comfort-left";
|
|
89
|
+
pt?: UIValue | "safe-top" | "comfort-top";
|
|
90
|
+
pr?: UIValue | "safe-right" | "comfort-right";
|
|
91
|
+
pb?: UIValue | "safe-bottom" | "comfort-bottom";
|
|
92
|
+
p?: UIValue | "safe-all" | "comfort-all";
|
|
93
|
+
px?: UIValue | "comfort-x";
|
|
94
|
+
py?: UIValue | "comfort-y";
|
|
95
|
+
};
|
|
96
|
+
/** Margin, with `m`/`mx`/`ml`… shorthands; `"auto"` centers/pushes like CSS. */
|
|
97
|
+
export type MarginStyle = {
|
|
98
|
+
marginLeft?: UIValue | "auto" | "safe-left" | "comfort-left";
|
|
99
|
+
marginTop?: UIValue | "auto" | "safe-top" | "comfort-top";
|
|
100
|
+
marginRight?: UIValue | "auto" | "safe-right" | "comfort-right";
|
|
101
|
+
marginBottom?: UIValue | "auto" | "safe-bottom" | "comfort-bottom";
|
|
102
|
+
margin?: UIValue | "auto" | "safe-all" | "comfort-all";
|
|
103
|
+
marginHorizontal?: UIValue | "auto" | "comfort-x";
|
|
104
|
+
marginVertical?: UIValue | "auto" | "comfort-y";
|
|
105
|
+
ml?: UIValue | "auto" | "safe-left" | "comfort-left";
|
|
106
|
+
mt?: UIValue | "auto" | "safe-top" | "comfort-top";
|
|
107
|
+
mr?: UIValue | "auto" | "safe-right" | "comfort-right";
|
|
108
|
+
mb?: UIValue | "auto" | "safe-bottom" | "comfort-bottom";
|
|
109
|
+
m?: UIValue | "auto" | "safe-all" | "comfort-all";
|
|
110
|
+
mx?: UIValue | "auto" | "comfort-x";
|
|
111
|
+
my?: UIValue | "auto" | "comfort-y";
|
|
112
|
+
};
|
|
113
|
+
/** Box position (for `position: "absolute"`) and size constraints. */
|
|
114
|
+
export type PositionStyle = {
|
|
115
|
+
top?: UIValue | `${number}%` | 'safe-top' | 'comfort-top';
|
|
116
|
+
left?: UIValue | `${number}%` | 'safe-left' | 'comfort-left';
|
|
117
|
+
bottom?: UIValue | `${number}%` | 'safe-bottom' | 'comfort-bottom';
|
|
118
|
+
right?: UIValue | `${number}%` | 'safe-right' | 'comfort-right';
|
|
119
|
+
/** Shorthand for all four edges at one value. A longhand (`top`, `left`, …) overrides it. */
|
|
120
|
+
inset?: UIValue | `${number}%` | "auto";
|
|
121
|
+
width?: UIValue | `${number}%` | "auto";
|
|
122
|
+
height?: UIValue | `${number}%` | "auto";
|
|
123
|
+
maxWidth?: UIValue | `${number}%` | "auto";
|
|
124
|
+
maxHeight?: UIValue | `${number}%` | "auto";
|
|
125
|
+
minWidth?: UIValue | `${number}%` | "auto";
|
|
126
|
+
minHeight?: UIValue | `${number}%` | "auto";
|
|
127
|
+
};
|
|
128
|
+
/** The base style of every element: box + flex-child props. */
|
|
129
|
+
export type ElementStyle = PaddingStyle & MarginStyle & BaseStyle & PositionStyle & {
|
|
130
|
+
position?: "absolute" | "static" | "relative";
|
|
131
|
+
aspectRatio?: number;
|
|
132
|
+
flex?: number | string;
|
|
133
|
+
flexGrow?: number;
|
|
134
|
+
flexShrink?: number;
|
|
135
|
+
flexBase?: UIValue | `${number}%` | "auto";
|
|
136
|
+
alignSelf?: "flex-start" | "center" | "flex-end" | "stretch";
|
|
137
|
+
display?: "none" | "flex";
|
|
138
|
+
};
|
|
139
|
+
/** Typography props. */
|
|
140
|
+
export type TextStyle = {
|
|
141
|
+
textAlign?: "start" | "center" | "end" | "left" | "right";
|
|
142
|
+
fontFamily?: string;
|
|
143
|
+
fontSize?: UIValue;
|
|
144
|
+
lineHeight?: UIValue | "normal";
|
|
145
|
+
fontWeight?: number | `${number}` | "normal" | "bold";
|
|
146
|
+
fontStyle?: "normal" | "italic";
|
|
147
|
+
color?: Color;
|
|
148
|
+
textDecoration?: "underline" | "line-through" | "none";
|
|
149
|
+
letterSpacing?: UIValue;
|
|
150
|
+
/** Cap the text at N lines; the box is measured to the clamped height. 0 / omitted = unbounded. */
|
|
151
|
+
lineClamp?: number;
|
|
152
|
+
/** How a clamped line ends. Only meaningful together with `lineClamp`. Default "ellipsis". */
|
|
153
|
+
textOverflow?: "ellipsis" | "clip";
|
|
154
|
+
};
|
|
155
|
+
/** Reactive style input: every primitive-valued prop also accepts a `() => value` binding that
|
|
156
|
+
* re-applies when a signal it read changes. Nested state blocks (onPressed, onLandscape, …) stay
|
|
157
|
+
* static — bindings are extracted at the top level only. */
|
|
158
|
+
export type Reactive<T> = {
|
|
159
|
+
[K in keyof T]: NonNullable<T[K]> extends object ? T[K] : T[K] | (() => T[K]);
|
|
160
|
+
};
|
|
161
|
+
/** User-defined style classes: any `$`-prefixed key in `.style()` declares a state block toggled
|
|
162
|
+
* from code via the `el.class` proxy; `duration`/`delay` animate the swap. Class state INHERITS
|
|
163
|
+
* down the tree (CSS-`.dark`-on-body style): a class set on a node also activates same-name `$`
|
|
164
|
+
* blocks on all descendants within the same root (docs/style-class-cascade-plan.md).
|
|
165
|
+
* `$pressed`/`$focused` are reserved — hosts toggle them on press/focus (they beat other
|
|
166
|
+
* classes, lose to onPressed/onFocused), so children can react to an ancestor's press.
|
|
167
|
+
*
|
|
168
|
+
* Instantiated with the node's FULL style `T` — a class block accepts everything the node's
|
|
169
|
+
* `.style()` does, like `onLandscape`. Narrowing it wrongly rejects valid props such as
|
|
170
|
+
* `$active: { color }`; guarded by tests/ui-types.test.ts. */
|
|
171
|
+
export type ClassStyles<T> = {
|
|
172
|
+
[key: `$${string}`]: T & {
|
|
173
|
+
duration?: number;
|
|
174
|
+
delay?: number;
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
/** Value accepted by a `el.class` write: a boolean sets the class, a `() => boolean` binds it —
|
|
178
|
+
* the class then tracks the signals the function reads (re-evaluated on change). Reads through
|
|
179
|
+
* the proxy always return a plain boolean, never the bound function. */
|
|
180
|
+
export type ClassValue = boolean | (() => boolean);
|
|
181
|
+
/** The `el.class` proxy — the runtime switch for `$`-class blocks declared in `.style()`
|
|
182
|
+
* (see {@link ClassStyles}). One surface, mirroring `el.style`:
|
|
183
|
+
*
|
|
184
|
+
* ```ts
|
|
185
|
+
* el.class.checked // read: is it active on THIS element? → boolean
|
|
186
|
+
* el.class.checked = true // activate (false deactivates)
|
|
187
|
+
* el.class.open = !el.class.open // toggle
|
|
188
|
+
* el.class.done = () => todo.done.value // reactive binding (signals)
|
|
189
|
+
* el.class({ checked: true, done: () => … }) // batch form — returns the element, chainable
|
|
190
|
+
* ```
|
|
191
|
+
*
|
|
192
|
+
* Class names are accepted with or without the declaration-site `$` prefix. `R` is the concrete
|
|
193
|
+
* node type, so the batch form chains like `.style()`.
|
|
194
|
+
*
|
|
195
|
+
* Typing note: property access is `any` because an index signature can't give reads (`boolean`)
|
|
196
|
+
* and writes ({@link ClassValue}) different types — the batch form is the fully typed path;
|
|
197
|
+
* single-key writes are runtime-coerced with `!!`. */
|
|
198
|
+
export type Classes<R> = ((classes: Record<string, ClassValue>) => R) & {
|
|
199
|
+
[key: string]: any;
|
|
200
|
+
};
|
|
201
|
+
/** Members every UI element shares — element interfaces extend this so docs and types live in one
|
|
202
|
+
* place. `S` is the element's style object; `A` is the subset `animateTo` accepts (defaults to `S`). */
|
|
203
|
+
export interface UIElementBase<S extends object, A extends object = S> {
|
|
204
|
+
/** Style: `.style({...})` merges (chainable); `el.style.key = v` writes one prop, a `() => v`
|
|
205
|
+
* value binds it to signals — see {@link Style}. */
|
|
206
|
+
style: Style<this, S>;
|
|
207
|
+
/** Tween to the target style — meta keys `duration`/`delay`/`loop`/…, see {@link AnimateStyle}. */
|
|
208
|
+
animateTo: AnimateStyle<this, A>;
|
|
209
|
+
/** Tween from the given style to the current one (entrance animations). */
|
|
210
|
+
animateFrom: AnimateStyle<this, A>;
|
|
211
|
+
/** Fires after every layout pass with the parent-relative box. */
|
|
212
|
+
onLayout(onLayout: OnLayoutCallback): this;
|
|
213
|
+
/** Absolute rect in device space, read live (includes scroll); `null` before mount. */
|
|
214
|
+
getBoundingClientRect(): BoundingClientRect | null;
|
|
215
|
+
/** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with
|
|
216
|
+
* `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.
|
|
217
|
+
* Classes cascade to descendants. See {@link Classes}. */
|
|
218
|
+
readonly class: Classes<this>;
|
|
219
|
+
}
|
|
220
|
+
/** {@link UIElementBase} plus the child-management surface every container shares. */
|
|
221
|
+
export interface UIContainerBase<S extends object, A extends object = S> extends UIElementBase<S, A> {
|
|
222
|
+
/** Append children. */
|
|
223
|
+
append(...nodes: UINodeChild[]): this;
|
|
224
|
+
/** Insert children at `index`. */
|
|
225
|
+
insert(index: number, ...nodes: UINodeChild[]): this;
|
|
226
|
+
/** Remove (unmount) the given children. */
|
|
227
|
+
remove(...nodes: UINodeChild[]): this;
|
|
228
|
+
/** Replace all children — an array, or a function for reactive children. */
|
|
229
|
+
setContent(nodes: UINodeChild[] | ChildrenFn): this;
|
|
230
|
+
/** The children array — mutate via `append`/`insert`/`remove`/`setContent`. */
|
|
231
|
+
readonly children: UINodeChild[];
|
|
232
|
+
}
|
|
233
|
+
/** Orientation state blocks — override props applied only in landscape / portrait (like a
|
|
234
|
+
* `$`-class, keyed by device orientation instead of `el.class`). Same full-`T` rule as class
|
|
235
|
+
* blocks. */
|
|
236
|
+
export type OrientationStyles<T> = {
|
|
237
|
+
onLandscape?: T;
|
|
238
|
+
onPortrait?: T;
|
|
239
|
+
/** @deprecated Misspelling of `onPortrait` (no second "r"). Kept so existing projects and published
|
|
240
|
+
* bundles keep working — hosts still honour it — but new code should use `onPortrait`. */
|
|
241
|
+
onPortait?: T;
|
|
242
|
+
};
|
|
243
|
+
export type StyleFn<R, T extends object> = ((style: Reactive<T> & OrientationStyles<T> & ClassStyles<T>) => R);
|
|
244
|
+
/** The `el.style` surface: callable — `.style({...})` merges and returns the element for
|
|
245
|
+
* chaining — and per-key readable/writable (`el.style.opacity = 0.5`; a `() => value` write
|
|
246
|
+
* installs a reactive binding). */
|
|
247
|
+
export type Style<R, T extends object> = StyleFn<R, T> & T & OrientationStyles<T> & ClassStyles<T>;
|
|
248
|
+
/** The `animateTo`/`animateFrom` surface: target style props plus the flat meta keys below
|
|
249
|
+
* (stripped before the commit into the element's style). */
|
|
250
|
+
export type AnimateStyle<R, T extends object> = ((style: T & {
|
|
251
|
+
/** Tween length in **milliseconds** (default 225). */
|
|
252
|
+
duration?: number;
|
|
253
|
+
/** Wait before starting, in **milliseconds**. A looping animation delays once, not per cycle. */
|
|
254
|
+
delay?: number;
|
|
255
|
+
/** Escape hatch: target an internal style layer (the onPressed/orientation mechanism). Not part of the supported surface. */
|
|
256
|
+
layer?: number;
|
|
257
|
+
/** `false` = animate without writing the targets into the element's style (e.g. a fade-out right before `.hide()`). */
|
|
258
|
+
commit?: boolean;
|
|
259
|
+
/** Repeat the animation: `true` = forever, a number = that many cycles. A looping animation is an
|
|
260
|
+
* effect, not a state change — it never commits, and the element ends back at its base style.
|
|
261
|
+
* The loop stops when a later `animateTo`/`animateFrom` runs on the element or it leaves the screen. */
|
|
262
|
+
loop?: boolean | number;
|
|
263
|
+
/** `"ping-pong"` (default) animates there and back each cycle — no jump. `"restart"` snaps back and
|
|
264
|
+
* replays forward — for full-turn spinners (`transform: "rotate(360deg)"`) and shimmers. Only meaningful with `loop`. */
|
|
265
|
+
loopMode?: "restart" | "ping-pong";
|
|
266
|
+
}) => R);
|
|
267
|
+
export type AppearStyle<R, T> = (arg: {
|
|
268
|
+
from: T;
|
|
269
|
+
duration?: number;
|
|
270
|
+
delay?: number;
|
|
271
|
+
}) => R;
|
|
272
|
+
export type DisappearStyle<R, T> = (arg: {
|
|
273
|
+
to: T;
|
|
274
|
+
duration?: number;
|
|
275
|
+
delay?: number;
|
|
276
|
+
}) => R;
|
|
277
|
+
/** `onLayout` payload — the node's box in PARENT-relative coordinates. */
|
|
278
|
+
export type OnLayoutCallback = (layout: {
|
|
279
|
+
left: number;
|
|
280
|
+
top: number;
|
|
281
|
+
width: number;
|
|
282
|
+
height: number;
|
|
283
|
+
}) => void;
|
|
284
|
+
/** Web-DOMRect shape on purpose (getBoundingClientRect priors must hold): all eight fields, with
|
|
285
|
+
* right/bottom/x/y derived SDK-side — hosts only report [left, top, width, height]. */
|
|
286
|
+
export type BoundingClientRect = {
|
|
287
|
+
x: number;
|
|
288
|
+
y: number;
|
|
289
|
+
left: number;
|
|
290
|
+
top: number;
|
|
291
|
+
right: number;
|
|
292
|
+
bottom: number;
|
|
293
|
+
width: number;
|
|
294
|
+
height: number;
|
|
295
|
+
};
|
|
296
|
+
export declare class Element<T extends string> {
|
|
297
|
+
readonly type: T;
|
|
298
|
+
/** Author-given semantic name (LeCodes `name`) — see BaseStyle.name. Extracted from the options
|
|
299
|
+
* object so it never reaches the layout engine; the renderer reads it off the node. */
|
|
300
|
+
readonly name?: string;
|
|
301
|
+
protected _style: any;
|
|
302
|
+
protected _id: number;
|
|
303
|
+
protected _styleProxy: any;
|
|
304
|
+
protected _appear: any;
|
|
305
|
+
protected _disappear: any;
|
|
306
|
+
constructor(type: T, style: any);
|
|
307
|
+
get style(): any;
|
|
308
|
+
/** Tween to the target style and commit it (unless `commit: false` or looping — a loop is an
|
|
309
|
+
* effect, not a state change). Meta keys: `duration`/`delay`/`loop`/… — see {@link AnimateStyle}. */
|
|
310
|
+
animateTo(style: any): this;
|
|
311
|
+
/** Tween FROM the given style to the element's current one (entrance animations). */
|
|
312
|
+
animateFrom(style: any): this;
|
|
313
|
+
protected _classProxy?: any;
|
|
314
|
+
/** Style-class control — flips the `$`-class blocks declared in `.style()`. One proxy, same
|
|
315
|
+
* contract as `el.style`:
|
|
316
|
+
*
|
|
317
|
+
* - `el.class.checked` — read: is the class active on THIS element? → `boolean`
|
|
318
|
+
* - `el.class.checked = true` / `= false` — activate / deactivate
|
|
319
|
+
* - `el.class.open = !el.class.open` — toggle
|
|
320
|
+
* - `el.class.done = () => todo.done.value` — reactive: the class tracks the signals the
|
|
321
|
+
* function reads; a later write to the same class (plain or function) replaces the binding
|
|
322
|
+
* - `el.class({ checked: true, done: () => … })` — batch form, returns the element (chainable)
|
|
323
|
+
*
|
|
324
|
+
* Names are accepted with or without the leading `$`. A class set on an element CASCADES: it is
|
|
325
|
+
* also active on every descendant (their same-name `$` blocks light up), until the subtree's
|
|
326
|
+
* root — hosted screens/widgets don't inherit. Reads reflect only this element's own classes;
|
|
327
|
+
* there is no opt-out below an active ancestor. `Object.keys(el.class)` lists the active names. */
|
|
328
|
+
get class(): any;
|
|
329
|
+
protected ll?: OnLayoutCallback[];
|
|
330
|
+
/** Observe layout: fires after every host layout pass with the parent-relative box. */
|
|
331
|
+
onLayout(onLayout: OnLayoutCallback): this;
|
|
332
|
+
/** Absolute rect in device space — the space `UIWidget` positions in and touch events report
|
|
333
|
+
* `clientX`/`clientY` in — including scroll offsets, read live at call time (unlike `onLayout`,
|
|
334
|
+
* whose coordinates are parent-relative and go stale when an ancestor scrolls). `null` before
|
|
335
|
+
* the element is mounted and on hosts without the bridge read. Anchor popovers position-once
|
|
336
|
+
* at open; don't poll per frame. */
|
|
337
|
+
getBoundingClientRect(): BoundingClientRect | null;
|
|
338
|
+
}
|
|
339
|
+
/** Reactive children: re-runs when a signal it read changes; the result is reconciled against
|
|
340
|
+
* the mounted children (kept nodes stay mounted, state intact). */
|
|
341
|
+
export type ChildrenFn = () => UINodeChild[];
|
|
342
|
+
/**
|
|
343
|
+
* Compiler-emitted memoized map for reactive children. The chisel `reactiveUi` pass rewrites
|
|
344
|
+
* `list.map(fn)` inside a children binding to `__uiMap(list, fn, "<file>:<offset>")`, so unchanged
|
|
345
|
+
* items keep their element identity across re-runs (the reconciler then leaves them mounted).
|
|
346
|
+
* Cache: per (binding owner, call-site slot), keyed by item reference; duplicate items consume
|
|
347
|
+
* cached nodes in order. Outside a children binding, for non-array inputs, or for non-element
|
|
348
|
+
* results it behaves exactly like Array.prototype.map — a wrong rewrite can't change behavior.
|
|
349
|
+
*/
|
|
350
|
+
export declare function __uiMap(list: any, render: (item: any, index: number) => any, slot: string): any[];
|
|
351
|
+
export declare class ContainerElement<T extends string> extends Element<T> {
|
|
352
|
+
children: any[];
|
|
353
|
+
constructor(type: T, style: any, children: any[] | ChildrenFn);
|
|
354
|
+
/** Append children (falsy entries are kept in the array but never mounted). */
|
|
355
|
+
append(...nodes: UINodeChild[]): this;
|
|
356
|
+
/** Insert children at `index` of the children array. */
|
|
357
|
+
insert(index: number, ...nodes: UINodeChild[]): this;
|
|
358
|
+
/** Remove (unmount) the given children. */
|
|
359
|
+
remove(...nodesToDelete: UINode[]): this;
|
|
360
|
+
/** Replace all children — a plain array, or a function for reactive children. */
|
|
361
|
+
setContent(children: UINodeChild[] | ChildrenFn): this;
|
|
362
|
+
}
|
|
363
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { ContainerElement, type BaseStyle, type ChildrenFn, type DrawableStyle, type ElementStyle, type UIElementBase, type UINodeChild } from "./UINode";
|
|
2
|
+
import type { UIScreen } from "./UIScreen";
|
|
3
|
+
/** Styles a pager accepts — layout box + drawable (background, borders, …). Pages style
|
|
4
|
+
* themselves; the pager only owns its own slot. */
|
|
5
|
+
export type UIPagerStyle = ElementStyle & DrawableStyle;
|
|
6
|
+
/**
|
|
7
|
+
* The screen-navigation element: sibling **tabs** that swipe natively side to side, each with its
|
|
8
|
+
* own navigation **stack**. `push` opens a screen on top of the current tab (within the pager);
|
|
9
|
+
* `pop` / the native edge back-swipe unwinds it. A one-tab pager is a plain navigation stack.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const pager = UIPager([ HomeScreen(), ProfileScreen() ]) // two tabs, side by side
|
|
13
|
+
* Router.init(UIScreen([ pager.style({ flexGrow: 1 }), tabBar ]))
|
|
14
|
+
*
|
|
15
|
+
* // from anywhere inside a hosted screen — no reference threading:
|
|
16
|
+
* UIPager.push(PostScreen(id))
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* To open something over *everything* (above bars, above the pager), use `Router.push` instead.
|
|
20
|
+
*/
|
|
21
|
+
export interface UIPager extends UIElementBase<UIPagerStyle, DrawableStyle & BaseStyle> {
|
|
22
|
+
readonly type: "pager";
|
|
23
|
+
/** Replace the pager's tabs — one screen per tab, in order. Every tab becomes a fresh
|
|
24
|
+
* one-screen stack (pushed screens are dropped) and the selection is clamped into range;
|
|
25
|
+
* screens that were already tabs keep their state. Pass a function for reactive tabs. */
|
|
26
|
+
setContent(tabs: UIScreen[] | (() => UIScreen[])): this;
|
|
27
|
+
/** Switch to tab `index`. **Instant by default** — the tab-bar convention (tabs are parallel
|
|
28
|
+
* modes, not neighbors); pass `animated: true` for the direction-aware slide of top-tab /
|
|
29
|
+
* pager UIs. Out-of-range and same-index calls are no-ops. Tabs keep their stacks: selecting
|
|
30
|
+
* away and back restores the tab exactly where it was, pushed screens included. */
|
|
31
|
+
select(index: number, animated?: boolean): this;
|
|
32
|
+
/** The selected tab index (0-based). */
|
|
33
|
+
readonly index: number;
|
|
34
|
+
/** Fires when the selected tab changes and has settled — a user swipe or `select()`. */
|
|
35
|
+
onSelect(callback: (index: number) => void): this;
|
|
36
|
+
/** Push `screen` on top of the **current tab** — slides in natively; the edge back-swipe (or
|
|
37
|
+
* `pop()`) removes it. Other tabs are unaffected. */
|
|
38
|
+
push(screen: UIScreen): this;
|
|
39
|
+
/** Pop the current tab's top screen (no-op at the tab root — the root never pops). The
|
|
40
|
+
* programmatic twin of the native edge back-swipe. */
|
|
41
|
+
pop(): this;
|
|
42
|
+
/** Unwind the current tab back to its root screen in one step. */
|
|
43
|
+
popToRoot(): this;
|
|
44
|
+
/** Swap the current tab's top screen for `screen` without growing the stack (at depth 1 this
|
|
45
|
+
* swaps the tab's root). */
|
|
46
|
+
replace(screen: UIScreen): this;
|
|
47
|
+
/** The current tab's screens, root → top (read-only snapshot). */
|
|
48
|
+
readonly stack: UIScreen[];
|
|
49
|
+
/** The current tab's stack depth — 1 means only the root. While `depth > 1`, swiping between
|
|
50
|
+
* tabs is disabled (the horizontal gesture belongs to the back-swipe). */
|
|
51
|
+
readonly depth: number;
|
|
52
|
+
/** Fires when the current tab's depth changes — push, pop, replace, or a back-swipe. */
|
|
53
|
+
onChange(callback: (depth: number) => void): this;
|
|
54
|
+
}
|
|
55
|
+
export declare class PagerElement extends ContainerElement<"pager"> {
|
|
56
|
+
/** Per-tab stack lengths — partitions the flat tab-major `children`. Named `_*` so chisel
|
|
57
|
+
* keeps it (the host reads it live). */
|
|
58
|
+
_lens: number[];
|
|
59
|
+
/** Selected tab. */
|
|
60
|
+
_index: number;
|
|
61
|
+
_openCount: number;
|
|
62
|
+
private scl;
|
|
63
|
+
private ncl;
|
|
64
|
+
constructor(style: UIPagerStyle | null, tabs: UIScreen[]);
|
|
65
|
+
/** Start offset of tab `i`'s segment in the flat `children`. */
|
|
66
|
+
private _offset;
|
|
67
|
+
get index(): number;
|
|
68
|
+
get stack(): UIScreen[];
|
|
69
|
+
get depth(): number;
|
|
70
|
+
onSelect(callback: (index: number) => void): this;
|
|
71
|
+
onChange(callback: (depth: number) => void): this;
|
|
72
|
+
select(index: number, animated?: boolean): this;
|
|
73
|
+
push(screen: UIScreen): this;
|
|
74
|
+
pop(): this;
|
|
75
|
+
popToRoot(): this;
|
|
76
|
+
replace(screen: UIScreen): this;
|
|
77
|
+
private _rebuild;
|
|
78
|
+
setContent(children: UINodeChild[] | ChildrenFn): this;
|
|
79
|
+
append(...nodes: UINodeChild[]): this;
|
|
80
|
+
insert(index: number, ...nodes: UINodeChild[]): this;
|
|
81
|
+
remove(...nodesToDelete: UIScreen[]): this;
|
|
82
|
+
_reconcile(next: UINodeChild[]): void;
|
|
83
|
+
_hostDidSelect(index: number): void;
|
|
84
|
+
_hostDidPop(depth: number): void;
|
|
85
|
+
private _emitSelect;
|
|
86
|
+
private _emitChange;
|
|
87
|
+
private _track;
|
|
88
|
+
_activate(): void;
|
|
89
|
+
_deactivate(): void;
|
|
90
|
+
}
|
|
91
|
+
/** Callable factory + ambient statics. The name `UIPager` is a value (this factory) and a type
|
|
92
|
+
* (the instance interface above) — a standard value/type merge. */
|
|
93
|
+
interface UIPagerConstructor {
|
|
94
|
+
/** Tabs — each argument is a screen or an array of screens (arrays flatten one level, falsy
|
|
95
|
+
* entries are skipped). One screen → a plain navigation stack rooted at it (push/pop, no tab
|
|
96
|
+
* swiping); several → swipeable sibling tabs, fixed at construction, each starting as its own
|
|
97
|
+
* one-screen stack. */
|
|
98
|
+
(...tabs: (UIScreen | UIScreen[] | false | null | undefined)[]): UIPager;
|
|
99
|
+
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
100
|
+
(style: UIPagerStyle, content?: UIScreen | UIScreen[]): UIPager;
|
|
101
|
+
/** The pager that owns the currently visible screen, or `null` when the visible screen isn't
|
|
102
|
+
* hosted by one. With pagers nested inside pages, resolves to the **innermost** — so ambient
|
|
103
|
+
* calls act on the pager the user is actually looking at. */
|
|
104
|
+
readonly current: UIPager | null;
|
|
105
|
+
/** `UIPager.current.push(screen)` — push onto the pager owning the visible screen, no
|
|
106
|
+
* reference threading. No-op with a console warning when there is no current pager. */
|
|
107
|
+
push(screen: UIScreen): void;
|
|
108
|
+
/** `UIPager.current.pop()` — pop the visible pager's current tab (no-op at the tab root, or
|
|
109
|
+
* with a warning when there is no current pager). */
|
|
110
|
+
pop(): void;
|
|
111
|
+
/** `UIPager.current.popToRoot()` — unwind the visible pager's current tab to its root. */
|
|
112
|
+
popToRoot(): void;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a pager — THE screen-navigation element: an array of screens becomes swipeable sibling
|
|
116
|
+
* tabs, a single screen becomes a plain stack. Navigate within it via `pager.push/pop/replace`
|
|
117
|
+
* (per-tab) and `pager.select(i)` (between tabs), or from any child screen via the ambient
|
|
118
|
+
* `UIPager.push` / `UIPager.pop` / `UIPager.current`. Pages are full `UIScreen`s (own
|
|
119
|
+
* `onOpen`/`onClose`); give the pager `flexGrow: 1` or a size so it doesn't
|
|
120
|
+
* collapse. `Router` stays the way to open a destination ON TOP of the pager.
|
|
121
|
+
*/
|
|
122
|
+
export declare const UIPager: UIPagerConstructor;
|
|
123
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ModalElement, type UIModal, type UIModalStyle } from "./UIModal";
|
|
2
|
+
import { type BoundingClientRect, type ChildrenFn, type UIChildArg, type UINodeChild } from "./UINode";
|
|
3
|
+
export type UIPopoverStyle = UIModalStyle;
|
|
4
|
+
/** What a popover can anchor to: any element (it reads `getBoundingClientRect()`), or a raw
|
|
5
|
+
* `{x, y}` point — a long-press context menu anchors to the touch position. */
|
|
6
|
+
export type UIPopoverAnchor = {
|
|
7
|
+
getBoundingClientRect(): BoundingClientRect | null;
|
|
8
|
+
} | {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* An anchored menu: a `UIModal` whose scrim is transparent (invisible but still intercepting —
|
|
14
|
+
* an outside tap dismisses, and nothing underneath can scroll while it's open) and whose
|
|
15
|
+
* position comes from the anchor passed to `show(anchor)`: below the anchor's left edge,
|
|
16
|
+
* flipped above when there's no room, clamped into the viewport. Position is computed once per
|
|
17
|
+
* show — anchored popovers don't follow their anchor. Backs dropdowns, context menus, and
|
|
18
|
+
* tooltips; create it **once** at module scope and reuse it.
|
|
19
|
+
*/
|
|
20
|
+
export interface UIPopover extends UIModal {
|
|
21
|
+
/** Position next to `anchor` (an element or an `{x, y}` point), attach to
|
|
22
|
+
* `Presentable.current` (unless an owner was set via `attachTo`), and play the entrance
|
|
23
|
+
* transition. Without an anchor the popover shows wherever its own style puts it. */
|
|
24
|
+
show(anchor?: UIPopoverAnchor): void;
|
|
25
|
+
}
|
|
26
|
+
export declare class PopoverElement extends ModalElement {
|
|
27
|
+
private _anchorRect?;
|
|
28
|
+
private _placedLeft?;
|
|
29
|
+
private _placedTop?;
|
|
30
|
+
constructor(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn);
|
|
31
|
+
show(anchor?: UIPopoverAnchor): void;
|
|
32
|
+
private _place;
|
|
33
|
+
}
|
|
34
|
+
/** Create an anchored popover (see {@link UIPopover}) — create once at module scope, then
|
|
35
|
+
* `show(anchor)` next to an element or `{x, y}` point. Same argument forms as `UIColumn`. */
|
|
36
|
+
export declare function UIPopover(...children: UIChildArg[]): UIPopover;
|
|
37
|
+
export declare function UIPopover(children: UINodeChild[] | ChildrenFn): UIPopover;
|
|
38
|
+
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
39
|
+
export declare function UIPopover(style: UIPopoverStyle, children?: UINodeChild[] | ChildrenFn): UIPopover;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { TouchStartEvent } from "../runtime/touch";
|
|
2
|
+
import { type PresentOptions } from "./presentable";
|
|
3
|
+
import { ContainerElement, type BaseStyle, type ContainerStyle, type DrawableStyle, type PaddingStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from "./UINode";
|
|
4
|
+
export type UIScreenStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle;
|
|
5
|
+
/** A screen — the root the router/host mounts, sized to its slot. A screen NEVER scrolls: it is
|
|
6
|
+
* fixed chrome (header, tab bar) plus, when the content overflows, one `UIScrollable` body child
|
|
7
|
+
* (`flexGrow: 1`). Scroll events and pull-to-refresh live on the scroll containers
|
|
8
|
+
* (`UIScrollable`, `UIVirtualizedList`). */
|
|
9
|
+
export interface UIScreen extends UIContainerBase<UIScreenStyle, DrawableStyle & BaseStyle> {
|
|
10
|
+
readonly type: "screen";
|
|
11
|
+
/** Show this screen as the current destination (replaces whatever is visible — a screen, a
|
|
12
|
+
* scene, a native view — suspending an active Router until `Router.restore()`). */
|
|
13
|
+
open(options?: PresentOptions): void;
|
|
14
|
+
/** Dismiss if this screen is the visible destination. */
|
|
15
|
+
close(): void;
|
|
16
|
+
/** Hardware/system back while this screen is current. */
|
|
17
|
+
onBackPressed(callback: () => void): this;
|
|
18
|
+
/** The screen became the visible destination (first open, or revealed by a pop). */
|
|
19
|
+
onOpen(callback: () => void): this;
|
|
20
|
+
/** The screen stopped being visible — closed, replaced, or covered by a push. */
|
|
21
|
+
onClose(callback: () => void): this;
|
|
22
|
+
/**
|
|
23
|
+
* Keep this screen's built native tree alive when a host detaches it: instead of being destroyed,
|
|
24
|
+
* its views + layout + live state (scroll position, input text) are retained, so re-hosting the
|
|
25
|
+
* SAME screen object restores it in place rather than rebuilding. `onClose`/`onOpen` still fire on
|
|
26
|
+
* detach/re-attach. You own the lifetime — a kept tree is freed only by `dispose()` or when the
|
|
27
|
+
* project unloads. (Native-only today; web rebuilds.)
|
|
28
|
+
*/
|
|
29
|
+
keepAlive(enabled?: boolean): this;
|
|
30
|
+
/** Free a `keepAlive()` screen's retained tree now. No-op unless it's currently detached-and-kept. */
|
|
31
|
+
dispose(): this;
|
|
32
|
+
/** Touch began on the screen; `ev.track(...)` takes over the rest of the gesture. */
|
|
33
|
+
onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;
|
|
34
|
+
}
|
|
35
|
+
export declare class ScreenElement extends ContainerElement<"screen"> {
|
|
36
|
+
open(options?: PresentOptions): void;
|
|
37
|
+
close(): void;
|
|
38
|
+
protected ol: (() => void)[];
|
|
39
|
+
onOpen(callback: () => void): this;
|
|
40
|
+
protected cl: (() => void)[];
|
|
41
|
+
onClose(callback: () => void): this;
|
|
42
|
+
_keepAlive: boolean;
|
|
43
|
+
keepAlive(enabled?: boolean): this;
|
|
44
|
+
dispose(): this;
|
|
45
|
+
readonly touchStartListeners: any[];
|
|
46
|
+
_interactive: boolean;
|
|
47
|
+
onTouchStart(callback: any): this;
|
|
48
|
+
_emitTouchStart(pointerId: number, clientX: number, clientY: number): any;
|
|
49
|
+
_backButtonCallback?: () => void;
|
|
50
|
+
onBackPressed(callback: any): this;
|
|
51
|
+
}
|
|
52
|
+
/** Create a screen. Present it with `.open()`, or via `Router` / `UIPager`. Same argument forms
|
|
53
|
+
* as `UIColumn`. */
|
|
54
|
+
export declare function UIScreen(...children: UIChildArg[]): UIScreen;
|
|
55
|
+
export declare function UIScreen(children: UINodeChild[] | ChildrenFn): UIScreen;
|
|
56
|
+
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
57
|
+
export declare function UIScreen(style: UIScreenStyle, children?: UINodeChild[] | ChildrenFn): UIScreen;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { UIContainerStyle } from "./UIContainer";
|
|
2
|
+
import { type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type Color } from "./UINode";
|
|
3
|
+
export type ScrollStyle = {
|
|
4
|
+
showScrollbar?: boolean;
|
|
5
|
+
overscrollMode?: "none" | "absorb" | "default";
|
|
6
|
+
/** Tint of the native pull-to-refresh spinner (pairs with `onRefresh`). */
|
|
7
|
+
refreshControlColor?: Color;
|
|
8
|
+
/** How a scroll gesture in THIS scrollable dismisses the keyboard: `"interactive"` (default) —
|
|
9
|
+
* dragging over the keyboard slides it away (chat feel); `"scroll"` — any drag dismisses
|
|
10
|
+
* immediately; `"none"` — never (tap-outside policy still applies). */
|
|
11
|
+
keyboardDismissMode?: "interactive" | "scroll" | "none";
|
|
12
|
+
/** Paging: when the drag ends, rest on a direct child's boundary along the scroll axis — the
|
|
13
|
+
* value picks where the child sits in the viewport; `"none"` (default) is free scrolling. Snap
|
|
14
|
+
* targets are the children themselves, so item widths can differ (card-carousel-with-peek); a
|
|
15
|
+
* carousel is a horizontal scrollable of full-width children + `snap: "start"`. */
|
|
16
|
+
snap?: "none" | "start" | "center" | "end";
|
|
17
|
+
};
|
|
18
|
+
export type UIScrollableStyle = UIContainerStyle & ScrollStyle & {
|
|
19
|
+
scrollDirection?: "horizontal" | "vertical";
|
|
20
|
+
};
|
|
21
|
+
/** A scroll container — vertical by default, `scrollDirection: "horizontal"` for carousels/chip
|
|
22
|
+
* rows. The scrolling body of a screen (screens themselves never scroll). */
|
|
23
|
+
export interface UIScrollable extends UIContainerBase<UIScrollableStyle> {
|
|
24
|
+
readonly type: "scrollable";
|
|
25
|
+
/** Scroll position changed (px from the start edge). */
|
|
26
|
+
onScroll(callback: (scrollPosition: number) => void): UIScrollable;
|
|
27
|
+
/** The scroll gesture ended (finger lifted). */
|
|
28
|
+
onScrollRelease(callback: () => void): UIScrollable;
|
|
29
|
+
/** Pulled past the content edge by `delta` px. */
|
|
30
|
+
onOverscroll(callback: (delta: number) => void): UIScrollable;
|
|
31
|
+
/** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the
|
|
32
|
+
* node mounts (hosts read it at creation). Vertical only; native hosts — no-op on web. */
|
|
33
|
+
onRefresh(callback: () => void | Promise<void>): UIScrollable;
|
|
34
|
+
}
|
|
35
|
+
/** Create a scroll container (same argument forms as `UIColumn`). As a screen body, pair with
|
|
36
|
+
* `flexGrow: 1`. */
|
|
37
|
+
export declare function UIScrollable(...children: UIChildArg[]): UIScrollable;
|
|
38
|
+
export declare function UIScrollable(children: UINodeChild[] | ChildrenFn): UIScrollable;
|
|
39
|
+
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
40
|
+
export declare function UIScrollable(style: UIScrollableStyle, children?: UINodeChild[] | ChildrenFn): UIScrollable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ElementStyle, type UIElementBase } from "./UINode";
|
|
2
|
+
export type UISpacerStyle = ElementStyle;
|
|
3
|
+
/** A flexible gap — `flexGrow: 1` by default, pushes its siblings apart. */
|
|
4
|
+
export interface UISpacer extends UIElementBase<UISpacerStyle> {
|
|
5
|
+
readonly type: "spacer";
|
|
6
|
+
}
|
|
7
|
+
/** Create a flexible gap (`flexGrow: 1`) — e.g. between a header's title and its actions. */
|
|
8
|
+
export declare function UISpacer(): UISpacer;
|
|
9
|
+
export declare function UISpacer(style: UISpacerStyle): UISpacer;
|