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,185 @@
|
|
|
1
|
+
import { type ElementStyle, type DrawableStyle, Element, type TextStyle, type Color, type BaseStyle, type UIElementBase } from "./UINode";
|
|
2
|
+
|
|
3
|
+
type InputStyle = {
|
|
4
|
+
placeholder?: string,
|
|
5
|
+
placeholderColor?: Color,
|
|
6
|
+
/**
|
|
7
|
+
* Keyboard hint, NOT a validator — `number` does not block pasted letters; validate in your own
|
|
8
|
+
* onChange. The phone-pad value is `phone` (LeCodes has no `tel`).
|
|
9
|
+
*
|
|
10
|
+
* `date` / `time` are PICKER kinds, not keyboards: the host opens its native picker in the
|
|
11
|
+
* keyboard slot (iOS wheels / browser calendar) and free typing is disabled. `value` is always
|
|
12
|
+
* canonical — `YYYY-MM-DD` for `date`, `HH:MM` (24h) for `time` — while the field displays a
|
|
13
|
+
* localized string; set/compare values in the canonical form only.
|
|
14
|
+
*/
|
|
15
|
+
type?: "text" | "password" | "search" | "phone" | "email" | "number" | "decimal" | "url"
|
|
16
|
+
| "date" | "time",
|
|
17
|
+
/**
|
|
18
|
+
* What the layout does while the keyboard is up (decided by the FOCUSED input). `true` (default):
|
|
19
|
+
* the layout viewport shrinks to the area above the keyboard — one relayout. `false`: the keyboard
|
|
20
|
+
* overlays the UI with NO layout recalculation — for chat composers that manage their own inset
|
|
21
|
+
* (pair with `app.keyboardHeight` / the app `"keyboard"` event) and full-screen canvases where a
|
|
22
|
+
* reflow is worse than overlap.
|
|
23
|
+
*/
|
|
24
|
+
keyboardShrink?: boolean,
|
|
25
|
+
/**
|
|
26
|
+
* Whether a tap on a non-interactive area dismisses the keyboard while THIS input is focused
|
|
27
|
+
* (like `keyboardShrink`, the policy of the focused input). `true` (default): tapping dead
|
|
28
|
+
* space blurs — but a tap on a button or another input NEVER dismisses; the control acts and
|
|
29
|
+
* focus stays. `false`: taps never dismiss — the chat-composer policy. `blur()`, the return
|
|
30
|
+
* key (per `enterKey`), and the platform's own gestures (iOS drag-down over the keyboard)
|
|
31
|
+
* still work in both modes. Scrolling never dismisses the keyboard on any setting.
|
|
32
|
+
*/
|
|
33
|
+
keyboardDismiss?: boolean,
|
|
34
|
+
/** Hard cap on the text length — enforced by the host while typing/pasting. */
|
|
35
|
+
maxLength?: number,
|
|
36
|
+
/** Auto-capitalization hint; omitted = platform default. */
|
|
37
|
+
autocapitalize?: "none" | "words" | "sentences" | "characters",
|
|
38
|
+
/** Enable/disable the platform autocorrection & suggestions; omitted = platform default. */
|
|
39
|
+
autocorrect?: boolean,
|
|
40
|
+
}
|
|
41
|
+
export type UIInputStyle = ElementStyle & DrawableStyle & TextStyle & InputStyle
|
|
42
|
+
|
|
43
|
+
/** UIInput-only (a UITextArea's Enter is a newline, period): the return-key label. */
|
|
44
|
+
type SubmitStyle = {
|
|
45
|
+
/**
|
|
46
|
+
* Return-key label. On submit the keyboard dismisses UNLESS `enterKey` is `"next"` — then the
|
|
47
|
+
* app is expected to call `otherInput.focus()` from `onSubmit`, so the keyboard never blinks.
|
|
48
|
+
*/
|
|
49
|
+
enterKey?: "done" | "go" | "next" | "search" | "send",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** A single-line text input. Keyboard/picker kind via the `type` style, return-key behavior via
|
|
53
|
+
* `enterKey` + `onSubmit`; keyboard policy on `keyboardShrink`/`keyboardDismiss`. */
|
|
54
|
+
export interface UIInput extends UIElementBase<UIInputStyle & SubmitStyle & { onFocused?: UIInputStyle & { duration?: number } }, DrawableStyle & BaseStyle> {
|
|
55
|
+
readonly type: "input",
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The field's text. Writable at any time — set it BEFORE the screen opens to pre-fill a form
|
|
59
|
+
* (settings, edit-profile); the value is stashed on the node and applied when the host builds
|
|
60
|
+
* it. Reads return the live text while the screen is open, and the last value you set while it
|
|
61
|
+
* isn't. The user's typing is not preserved across close/open (use `keepAlive()` for that).
|
|
62
|
+
*/
|
|
63
|
+
value: string
|
|
64
|
+
|
|
65
|
+
/** The text changed — fires on every user edit. */
|
|
66
|
+
onChange(callback: (value: string) => void): UIInput
|
|
67
|
+
/** Gained focus (keyboard opens). */
|
|
68
|
+
onFocus(callback: () => void): UIInput
|
|
69
|
+
/** Lost focus. */
|
|
70
|
+
onBlur(callback: () => void): UIInput
|
|
71
|
+
/** The keyboard's return key was pressed. `value` is the current text. See `enterKey`. */
|
|
72
|
+
onSubmit(callback: (value: string) => void): UIInput
|
|
73
|
+
|
|
74
|
+
/** Focus the input (opens the keyboard). No-op before mount. */
|
|
75
|
+
focus(): void
|
|
76
|
+
/** Release focus (dismisses the keyboard when this input held it). */
|
|
77
|
+
blur(): void
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** A multi-line text field — see the {@link UITextArea} factory for the auto-grow contract. */
|
|
81
|
+
export interface UITextArea extends UIElementBase<UIInputStyle & { onFocused?: UIInputStyle & { duration?: number } }, DrawableStyle & BaseStyle> {
|
|
82
|
+
readonly type: "textarea",
|
|
83
|
+
|
|
84
|
+
/** The field's text — same contract as {@link UIInput.value}: settable before mount to pre-fill. */
|
|
85
|
+
value: string
|
|
86
|
+
|
|
87
|
+
/** The text changed — fires on every user edit. */
|
|
88
|
+
onChange(callback: (value: string) => void): UITextArea
|
|
89
|
+
/** Gained focus (keyboard opens). */
|
|
90
|
+
onFocus(callback: () => void): UITextArea
|
|
91
|
+
/** Lost focus. */
|
|
92
|
+
onBlur(callback: () => void): UITextArea
|
|
93
|
+
|
|
94
|
+
/** Focus the text area (opens the keyboard). No-op before mount. */
|
|
95
|
+
focus(): void
|
|
96
|
+
/** Release focus (dismisses the keyboard when this text area held it). */
|
|
97
|
+
blur(): void
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class InputElement<T extends "input" | "textarea"> extends Element<T> {
|
|
101
|
+
|
|
102
|
+
readonly cl: Function[] = []
|
|
103
|
+
readonly fl: Function[] = []
|
|
104
|
+
readonly bl: Function[] = []
|
|
105
|
+
readonly sl: Function[] = []
|
|
106
|
+
|
|
107
|
+
/** @internal The value as last set by CODE. Hosts read it at node creation (after the initial
|
|
108
|
+
* style, so a `date` field's canonical parse and `maxLength` are already in place), which is
|
|
109
|
+
* what makes a value assigned before mount — a pre-filled settings form — land on the field.
|
|
110
|
+
* Same pre-mount stash as UIImage's `_sourceRect`. Typing does NOT sync back here: while
|
|
111
|
+
* mounted the HOST owns the text (IME composition, paste, the maxLength clamp, date/time
|
|
112
|
+
* canonicalization) and the getter reads it over the bridge. So on a remount the field comes
|
|
113
|
+
* back with the last code-set value, not what the user typed — screens that must keep live
|
|
114
|
+
* editing state across close/open use `keepAlive()`, the mechanism built for it. */
|
|
115
|
+
_value = ""
|
|
116
|
+
|
|
117
|
+
get value() {
|
|
118
|
+
// Mounted: the host is authoritative. Unmounted: what code last set (0 => never mounted).
|
|
119
|
+
return this._id !== 0 ? _creatorUI.getTextValue(this._id) : this._value
|
|
120
|
+
}
|
|
121
|
+
set value(value: string) {
|
|
122
|
+
this._value = value
|
|
123
|
+
if (this._id !== 0) {
|
|
124
|
+
_creatorUI.updateNode(this._id, "value", value)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// `phone` is SDK-surface only — hosts (and the web's verbatim `el.type`) keep HTML's `tel` as
|
|
129
|
+
// the wire format, so the rename never reaches them.
|
|
130
|
+
_mapStyle(style: any): void {
|
|
131
|
+
if (style.type === "phone") style.type = "tel"
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
onChange (callback: (value: string) => void): this {
|
|
135
|
+
this.cl.push(callback)
|
|
136
|
+
return this
|
|
137
|
+
}
|
|
138
|
+
onFocus(callback: () => void): this {
|
|
139
|
+
this.fl.push(callback)
|
|
140
|
+
return this
|
|
141
|
+
}
|
|
142
|
+
onBlur(callback: () => void): this {
|
|
143
|
+
this.bl.push(callback)
|
|
144
|
+
return this
|
|
145
|
+
}
|
|
146
|
+
onSubmit(callback: (value: string) => void): this {
|
|
147
|
+
this.sl.push(callback)
|
|
148
|
+
return this
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Focus rides the existing value channel (updateNode "focus") — no new ABI method.
|
|
152
|
+
focus(): void {
|
|
153
|
+
if (this._id !== 0) {
|
|
154
|
+
_creatorUI.updateNode(this._id, "focus", true)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
blur(): void {
|
|
158
|
+
if (this._id !== 0) {
|
|
159
|
+
_creatorUI.updateNode(this._id, "focus", false)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Create a single-line text input. Read/write the text via `.value`, listen with
|
|
165
|
+
* `onChange`/`onSubmit`; style keys `placeholder`, `type`, `enterKey`, … configure it. */
|
|
166
|
+
export function UIInput(): UIInput;
|
|
167
|
+
export function UIInput(style: UIInputStyle): UIInput;
|
|
168
|
+
export function UIInput(style?: UIInputStyle): UIInput {
|
|
169
|
+
// One text line as the floor — an unstyled input must never collapse to 0 height.
|
|
170
|
+
return new InputElement("input", { minHeight: "1.2em", ...style })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Multi-line text field. Enter is a newline (submit lives on UIInput / your own button).
|
|
175
|
+
*
|
|
176
|
+
* Auto-grow: with no explicit `height` the field measures its own content and grows line by
|
|
177
|
+
* line — clamp the range with `minHeight` / `maxHeight` (past `maxHeight` the text scrolls
|
|
178
|
+
* inside). A fixed `height` opts out and scrolls internally from the start. Chat composers are
|
|
179
|
+
* the canonical use: a bare textarea in a padded pill, `maxHeight` at ~5 lines.
|
|
180
|
+
*/
|
|
181
|
+
export function UITextArea(): UITextArea;
|
|
182
|
+
export function UITextArea(style: UIInputStyle): UITextArea;
|
|
183
|
+
export function UITextArea(style?: UIInputStyle): UITextArea {
|
|
184
|
+
return new InputElement("textarea", { minHeight: "1.2em", ...style })
|
|
185
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { type UIWidget, type UIWidgetStyle, WidgetElement } from "./UIWidget"
|
|
2
|
+
import { buildUI, type BaseStyle, type ChildrenFn, type Color, type DrawableStyle, type UIChildArg, type UINodeChild } from "./UINode"
|
|
3
|
+
|
|
4
|
+
export type UIModalStyle = UIWidgetStyle
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The modal's hidden pose: `show()` animates from it, `hide()` animates to it. `duration` (ms)
|
|
8
|
+
* applies to both directions.
|
|
9
|
+
*/
|
|
10
|
+
export type UIModalTransition = DrawableStyle & BaseStyle & {
|
|
11
|
+
overlayColor?: Color | null,
|
|
12
|
+
duration?: number,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const MODAL_ANIM_MS = 200
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A dialog: a `UIWidget` with the modal boilerplate built in. Comes with a scrim
|
|
19
|
+
* (`overlayColor: "rgba(0, 0, 0, 0.5)"` unless overridden), animates on `show()`/`hide()`
|
|
20
|
+
* (a 200 ms fade by default — swap the pose via `transition()`; the exit plays with
|
|
21
|
+
* `commit: false`, so the style is intact for the next show), and closes itself on a scrim tap
|
|
22
|
+
* or the Android back button (disable via `dismissible(false)`). Everything else is a plain
|
|
23
|
+
* widget — same styling, children, touch and `attachTo()` surface; create it **once** at module
|
|
24
|
+
* scope and reuse it.
|
|
25
|
+
*/
|
|
26
|
+
export interface UIModal extends UIWidget {
|
|
27
|
+
/** Mount as an overlay and play the entrance transition. No-op while already open. */
|
|
28
|
+
show(): void,
|
|
29
|
+
/** Play the exit transition, then unmount. No-op while closed or already closing. */
|
|
30
|
+
hide(): void,
|
|
31
|
+
/** True from `show()` until `hide()` starts (already false during the exit animation). */
|
|
32
|
+
readonly isOpen: boolean,
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Replace the show/hide animation. `hidden` is the off-screen pose — `show()` animates from
|
|
36
|
+
* it, `hide()` animates to it. Default `{ opacity: 0, duration: 200 }` (a fade); the pose
|
|
37
|
+
* replaces it wholesale, so a slide without a fade is just the slide. The scrim keeps its own
|
|
38
|
+
* fade unless the pose sets `overlayColor` itself.
|
|
39
|
+
*
|
|
40
|
+
* ```ts
|
|
41
|
+
* sheet.transition({ transform: "translateY(480px)", duration: 250 }) // bottom sheet
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
transition(hidden: UIModalTransition): this,
|
|
45
|
+
|
|
46
|
+
/** Called when `show()` mounts the modal. */
|
|
47
|
+
onOpen(callback: () => void): this,
|
|
48
|
+
/** Called when the modal starts closing — scrim tap, back button, or a `hide()` call. */
|
|
49
|
+
onClose(callback: () => void): this,
|
|
50
|
+
/** `dismissible(false)` keeps scrim taps and the back button from closing the modal
|
|
51
|
+
* (forced-choice dialogs). Default `true`. */
|
|
52
|
+
dismissible(enabled: boolean): this,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class ModalElement extends WidgetElement {
|
|
56
|
+
_open = false
|
|
57
|
+
_dismissible = true
|
|
58
|
+
_transition: UIModalTransition = { opacity: 0 }
|
|
59
|
+
_closeTimer?: ReturnType<typeof setTimeout>
|
|
60
|
+
readonly _openListeners: (() => void)[] = []
|
|
61
|
+
readonly _closeListeners: (() => void)[] = []
|
|
62
|
+
|
|
63
|
+
constructor(style: UIModalStyle, children: UINodeChild[] | ChildrenFn) {
|
|
64
|
+
super("widget", { overlayColor: "rgba(0, 0, 0, 0.5)", ...style }, children)
|
|
65
|
+
this.onOverlayTap(() => { if (this._dismissible) this.hide() })
|
|
66
|
+
this.onBackPressed(() => { if (this._dismissible) this.hide() })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The full animate argument: hidden pose + duration, plus the scrim fade — only when the
|
|
70
|
+
// modal actually has a scrim (overlayColor: null opts out; animating a null scrim would
|
|
71
|
+
// create the intercepting layer) and the pose doesn't drive the scrim itself.
|
|
72
|
+
private _pose(extra?: Record<string, unknown>): Record<string, unknown> {
|
|
73
|
+
const pose: Record<string, unknown> = { duration: MODAL_ANIM_MS, ...this._transition, ...extra }
|
|
74
|
+
const overlayColor = (this._style as UIModalStyle).overlayColor
|
|
75
|
+
if (pose.overlayColor === undefined && overlayColor !== undefined && overlayColor !== null) {
|
|
76
|
+
pose.overlayColor = "transparent"
|
|
77
|
+
}
|
|
78
|
+
return pose
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private get _duration(): number {
|
|
82
|
+
return this._transition.duration ?? MODAL_ANIM_MS
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
transition(hidden: UIModalTransition): this {
|
|
86
|
+
this._transition = hidden
|
|
87
|
+
return this
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
show(): void {
|
|
91
|
+
if (this._open) return
|
|
92
|
+
if (this._closeTimer !== undefined) { // reopened mid exit: finish that hide now
|
|
93
|
+
clearTimeout(this._closeTimer)
|
|
94
|
+
this._closeTimer = undefined
|
|
95
|
+
super.hide()
|
|
96
|
+
}
|
|
97
|
+
this._open = true
|
|
98
|
+
super.show()
|
|
99
|
+
this.animateFrom(this._pose())
|
|
100
|
+
for (const callback of this._openListeners) callback()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
hide(): void {
|
|
104
|
+
if (!this._open) return
|
|
105
|
+
this._open = false
|
|
106
|
+
this.animateTo(this._pose({ commit: false }))
|
|
107
|
+
this._closeTimer = setTimeout(() => { this._closeTimer = undefined; super.hide() }, this._duration)
|
|
108
|
+
for (const callback of this._closeListeners) callback()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get isOpen(): boolean {
|
|
112
|
+
return this._open
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
onOpen(callback: () => void): this {
|
|
116
|
+
this._openListeners.push(callback)
|
|
117
|
+
return this
|
|
118
|
+
}
|
|
119
|
+
onClose(callback: () => void): this {
|
|
120
|
+
this._closeListeners.push(callback)
|
|
121
|
+
return this
|
|
122
|
+
}
|
|
123
|
+
dismissible(enabled: boolean): this {
|
|
124
|
+
this._dismissible = enabled
|
|
125
|
+
return this
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const makeModal = (style: any, children: any) => new ModalElement(style, children)
|
|
130
|
+
|
|
131
|
+
/** Create a modal dialog (see {@link UIModal}) — create once at module scope, then
|
|
132
|
+
* `show()`/`hide()`. Same argument forms as `UIColumn`. */
|
|
133
|
+
export function UIModal(...children: UIChildArg[]): UIModal;
|
|
134
|
+
export function UIModal(children: UINodeChild[] | ChildrenFn): UIModal;
|
|
135
|
+
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
136
|
+
export function UIModal(style: UIModalStyle, children?: UINodeChild[] | ChildrenFn): UIModal;
|
|
137
|
+
export function UIModal(...args: any[]): UIModal {
|
|
138
|
+
return buildUI(args, null, makeModal)
|
|
139
|
+
}
|