lecodes-sdk 1.1.0 → 2.0.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 +5 -2
- package/dist/editor.d.ts +12 -0
- package/dist/global.d.ts +4 -8
- package/dist/host.d.ts +2 -3
- package/dist/types/animate/tween/Animation.d.ts +0 -3
- package/dist/types/animate/tween/animateValue.d.ts +4 -2
- package/dist/types/animate/tween/easing.d.ts +8 -0
- package/dist/types/animate/tween/spec.d.ts +15 -7
- package/dist/types/audio/audio.d.ts +2 -1
- package/dist/types/canvas/Canvas.d.ts +40 -108
- package/dist/types/canvas/gen/cssColor.d.ts +17 -0
- package/dist/types/canvas/gen/recorder.d.ts +118 -0
- package/dist/types/canvas/gen/spec.d.ts +144 -0
- package/dist/types/core/color.d.ts +3 -1
- package/dist/types/core/pins.d.ts +18 -0
- package/dist/types/g2/Node2D.d.ts +5 -8
- package/dist/types/g2/Scene2D.d.ts +6 -2
- package/dist/types/gl/Foliage.d.ts +30 -7
- package/dist/types/gl/Light.d.ts +11 -0
- package/dist/types/gl/Lightmap.d.ts +13 -2
- package/dist/types/gl/Material.d.ts +17 -3
- package/dist/types/gl/Model.d.ts +6 -2
- package/dist/types/gl/Node.d.ts +3 -6
- package/dist/types/gl/Particles.d.ts +15 -0
- package/dist/types/gl/Scene.d.ts +41 -13
- package/dist/types/gl/Texture.d.ts +1 -1
- package/dist/types/gl/animation/Locomotion.d.ts +59 -3
- package/dist/types/gl/terrain/Terrain.d.ts +8 -0
- package/dist/types/inject.d.ts +11 -11
- package/dist/types/inject.editor.d.ts +1 -0
- package/dist/types/net/core.d.ts +7 -0
- package/dist/types/plugin.d.ts +76 -0
- package/dist/types/plugins/gen/camera/sdk/camera.d.ts +24 -0
- package/dist/types/plugins/gen/camera/sdk/camera.gen.d.ts +25 -0
- package/dist/types/plugins/{geolocation.d.ts → gen/geolocation/sdk/geolocation.d.ts} +2 -20
- package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +31 -0
- package/dist/types/plugins/{map.d.ts → gen/map/sdk/map.d.ts} +9 -50
- package/dist/types/plugins/gen/map/sdk/map.gen.d.ts +53 -0
- package/dist/types/plugins/gen/push/sdk/push.d.ts +23 -0
- package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +35 -0
- package/dist/types/plugins/{qr.d.ts → gen/qr-scanner/sdk/qr-scanner.d.ts} +2 -3
- package/dist/types/plugins/gen/qr-scanner/sdk/qr-scanner.gen.d.ts +15 -0
- package/dist/types/runtime/app.d.ts +9 -2
- package/dist/types/runtime/fetch.d.ts +2 -0
- package/dist/types/runtime/input.d.ts +8 -1
- package/dist/types/runtime/media.d.ts +6 -10
- package/dist/types/runtime/misc.d.ts +4 -1
- package/dist/types/runtime/net.d.ts +3 -2
- package/dist/types/runtime/touch.d.ts +32 -0
- package/dist/types/scene/defineScene.d.ts +43 -2
- package/dist/types/scene/editor.d.ts +52 -0
- package/dist/types/scene/gizmos.d.ts +7 -4
- package/dist/types/ui/NativeView.d.ts +6 -4
- package/dist/types/ui/UI.d.ts +1 -1
- package/dist/types/ui/UIBottomSheet.d.ts +6 -12
- package/dist/types/ui/UIButton.d.ts +12 -14
- package/dist/types/ui/UIContainer.d.ts +0 -6
- package/dist/types/ui/UIImage.d.ts +1 -4
- package/dist/types/ui/UIInput.d.ts +8 -24
- package/dist/types/ui/UIModal.d.ts +0 -2
- package/dist/types/ui/UINode.d.ts +70 -56
- package/dist/types/ui/UIPager.d.ts +28 -27
- package/dist/types/ui/UIPopover.d.ts +0 -2
- package/dist/types/ui/UIScreen.d.ts +12 -17
- package/dist/types/ui/UIScrollable.d.ts +1 -4
- package/dist/types/ui/UIText.d.ts +0 -2
- package/dist/types/ui/UIVideo.d.ts +3 -5
- package/dist/types/ui/UIVirtualizedList.d.ts +14 -16
- package/dist/types/ui/UIWidget.d.ts +10 -9
- package/dist/types/ui/colorKeys.gen.d.ts +9 -0
- package/dist/types/ui/presentable.d.ts +46 -32
- package/dist/types/ui/router.d.ts +18 -7
- package/dist/types/ui/styleColor.d.ts +1 -0
- package/dist/types/ui/transitions.d.ts +18 -0
- package/dist/types/ui/tree.d.ts +75 -0
- package/dist/types/version.d.ts +10 -0
- package/dist/types.json +1 -1
- package/package.json +12 -3
- package/prompts/2d.md +2 -6
- package/prompts/3d.md +1 -5
- package/prompts/README.md +142 -142
- package/prompts/canvas.md +9 -8
- package/prompts/compose.ts +1 -1
- package/prompts/core.md +3 -3
- package/prompts/design.md +1 -1
- package/prompts/dist/2d-game.md +77 -54
- package/prompts/dist/3d-app.md +75 -52
- package/prompts/dist/ar-app.md +74 -51
- package/prompts/dist/design.md +30 -8
- package/prompts/dist/ui-app.md +73 -46
- package/prompts/ui-design.md +2 -3
- package/prompts/ui.md +45 -37
- package/src/animate/tween/Animation.ts +262 -378
- package/src/animate/tween/animateValue.ts +103 -100
- package/src/animate/tween/easing.ts +10 -3
- package/src/animate/tween/spec.ts +505 -479
- package/src/audio/Sound.ts +3 -3
- package/src/audio/audio.ts +162 -161
- package/src/bridges/2d.d.ts +317 -0
- package/src/bridges/app.d.ts +91 -0
- package/src/bridges/audio.d.ts +97 -0
- package/src/bridges/canvas.d.ts +79 -0
- package/src/bridges/device.d.ts +72 -0
- package/src/bridges/fetch.d.ts +80 -0
- package/src/bridges/files.d.ts +70 -0
- package/src/bridges/gl.d.ts +1133 -0
- package/src/bridges/input.d.ts +72 -0
- package/src/bridges/media.d.ts +55 -0
- package/src/bridges/nav.d.ts +71 -0
- package/src/bridges/net.d.ts +52 -0
- package/src/bridges/service.d.ts +52 -0
- package/src/bridges/socket.d.ts +31 -0
- package/src/bridges/storage.d.ts +33 -0
- package/src/bridges/tree.d.ts +301 -0
- package/src/bridges/types.d.ts +49 -0
- package/src/canvas/Canvas.ts +114 -159
- package/src/canvas/gen/cssColor.ts +224 -0
- package/src/canvas/gen/recorder.ts +212 -0
- package/src/canvas/gen/spec.ts +201 -0
- package/src/chisel.ts +193 -0
- package/src/compile/assetMacro.ts +1 -1
- package/src/compile/bundler.ts +11 -2
- package/src/compile/compileProject.ts +43 -4
- package/src/compile/fontMacro.ts +3 -4
- package/src/compile/header.ts +26 -5
- package/src/compile/index.ts +3 -1
- package/src/compile/liteMaterial.ts +1 -1
- package/src/compile/sceneEditor.ts +11 -26
- package/src/core/color.ts +73 -30
- package/src/core/pins.ts +51 -0
- package/src/core/signals.ts +8 -1
- package/src/g2/CharacterController2D.ts +3 -3
- package/src/g2/Node2D.ts +57 -39
- package/src/g2/Physics2D.ts +2 -2
- package/src/g2/Scene2D.ts +35 -23
- package/src/g2/Texture2D.ts +1 -1
- package/src/g2/loop.ts +4 -4
- package/src/gl/Foliage.ts +72 -17
- package/src/gl/Geometry.ts +1 -2
- package/src/gl/Light.ts +13 -0
- package/src/gl/Lightmap.ts +45 -29
- package/src/gl/Material.ts +95 -51
- package/src/gl/Model.ts +172 -167
- package/src/gl/Node.ts +91 -24
- package/src/gl/Particles.ts +20 -1
- package/src/gl/Scene.ts +100 -44
- package/src/gl/Texture.ts +8 -7
- package/src/gl/animation/AnimationClip.ts +1 -1
- package/src/gl/animation/Locomotion.ts +77 -8
- package/src/gl/nav/NavMesh.ts +3 -4
- package/src/gl/physics/Physics.ts +2 -2
- package/src/gl/physics/physicsEvents.ts +3 -3
- package/src/gl/terrain/Terrain.ts +33 -5
- package/src/gl/touch.ts +14 -15
- package/src/host.d.ts +2 -3
- package/src/inject.editor.ts +7 -0
- package/src/inject.ts +233 -236
- package/src/net/core.ts +6 -5
- package/src/net/index.ts +1 -1
- package/src/net/replication.ts +1 -1
- package/src/plugin.ts +191 -0
- package/src/plugins/gen/camera/contract.d.ts +27 -0
- package/src/plugins/gen/camera/sdk/camera.gen.ts +46 -0
- package/src/plugins/gen/camera/sdk/camera.ts +57 -0
- package/src/plugins/gen/geolocation/contract.d.ts +50 -0
- package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +54 -0
- package/src/plugins/{geolocation.ts → gen/geolocation/sdk/geolocation.ts} +22 -43
- package/src/plugins/gen/map/contract.d.ts +144 -0
- package/src/plugins/gen/map/sdk/map.gen.ts +88 -0
- package/src/plugins/{map.ts → gen/map/sdk/map.ts} +68 -102
- package/src/plugins/gen/push/contract.d.ts +61 -0
- package/src/plugins/gen/push/sdk/push.gen.ts +60 -0
- package/src/plugins/gen/push/sdk/push.ts +105 -0
- package/src/plugins/gen/qr-scanner/contract.d.ts +16 -0
- package/src/plugins/gen/qr-scanner/sdk/qr-scanner.gen.ts +29 -0
- package/src/plugins/gen/qr-scanner/sdk/qr-scanner.ts +52 -0
- package/src/plugins/permission.ts +5 -4
- package/src/runtime/app.ts +20 -9
- package/src/runtime/appEvents.ts +5 -4
- package/src/runtime/channel.ts +18 -15
- package/src/runtime/clipboard.ts +4 -3
- package/src/runtime/datetime.ts +2 -1
- package/src/runtime/device.ts +17 -15
- package/src/runtime/fetch.ts +30 -20
- package/src/runtime/files.ts +16 -15
- package/src/runtime/input.ts +21 -8
- package/src/runtime/media.ts +50 -46
- package/src/runtime/misc.ts +7 -3
- package/src/runtime/net.ts +8 -7
- package/src/runtime/rpc.ts +1 -3
- package/src/runtime/service.ts +19 -14
- package/src/runtime/share.ts +4 -3
- package/src/runtime/storage.ts +6 -4
- package/src/runtime/touch.ts +32 -0
- package/src/scene/defineScene.ts +61 -365
- package/src/scene/editor.ts +408 -0
- package/src/scene/editorPlugins.ts +3 -3
- package/src/scene/gizmos.ts +154 -148
- package/src/server/db/marci/query.ts +1 -1
- package/src/server/host.ts +1 -1
- package/src/server/runtime.ts +1 -1
- package/src/ui/NativeView.ts +72 -25
- package/src/ui/UI.ts +3 -3
- package/src/ui/UIBottomSheet.ts +16 -17
- package/src/ui/UIButton.ts +54 -16
- package/src/ui/UIContainer.ts +0 -6
- package/src/ui/UIImage.ts +34 -30
- package/src/ui/UIInput.ts +29 -37
- package/src/ui/UIModal.ts +1 -3
- package/src/ui/UINode.ts +347 -297
- package/src/ui/UIPager.ts +93 -78
- package/src/ui/UIPopover.ts +0 -2
- package/src/ui/UIScreen.ts +41 -36
- package/src/ui/UIScrollable.ts +19 -13
- package/src/ui/UISpacer.ts +1 -1
- package/src/ui/UITabs.ts +8 -6
- package/src/ui/UIText.ts +7 -17
- package/src/ui/UIVideo.ts +30 -27
- package/src/ui/UIVirtualizedList.ts +58 -59
- package/src/ui/UIWidget.ts +38 -18
- package/src/ui/colorKeys.gen.ts +37 -0
- package/src/ui/fonts.ts +2 -2
- package/src/ui/presentable.ts +59 -42
- package/src/ui/router.ts +52 -35
- package/src/ui/styleColor.ts +56 -0
- package/src/ui/theme.ts +7 -6
- package/src/ui/transitions.ts +249 -0
- package/src/ui/tree.ts +346 -0
- package/src/version.ts +24 -0
- package/tests/helpers/engineWorld.ts +11 -0
- package/tests/helpers/fakeTree.ts +353 -0
- package/tests/helpers/hostStubs.ts +31 -0
- package/tests/helpers/index.ts +14 -0
- package/tests/helpers/memoryMarci.ts +124 -0
- package/tests/helpers/phases.ts +23 -0
- package/tests/helpers/preload.ts +18 -0
- package/tests/helpers/stubApp.ts +2 -0
- package/tests/helpers/stubDevice.ts +2 -0
- package/tests/helpers/stubFetch.ts +2 -0
- package/tests/helpers/stubInput.ts +2 -0
- package/dist/inject.js +0 -4730
- package/dist/types/core/registry.d.ts +0 -7
- package/dist/types/plugins/camera.d.ts +0 -25
- package/dist/types/plugins/push.d.ts +0 -46
- package/src/bridges.d.ts +0 -1760
- package/src/compile/__tests__/assetIconMacro.test.ts +0 -219
- package/src/compile/__tests__/assetMacro.test.ts +0 -100
- package/src/compile/__tests__/assetName.test.ts +0 -55
- package/src/compile/__tests__/compile.test.ts +0 -310
- package/src/compile/__tests__/detectEntry.test.ts +0 -151
- package/src/compile/__tests__/fontMacro.test.ts +0 -199
- package/src/compile/__tests__/serverSplit.test.ts +0 -27
- package/src/core/__tests__/stateMachine.test.ts +0 -132
- package/src/core/registry.ts +0 -23
- package/src/plugins/camera.ts +0 -81
- package/src/plugins/push.ts +0 -132
- package/src/plugins/qr.ts +0 -73
package/src/scene/gizmos.ts
CHANGED
|
@@ -1,148 +1,154 @@
|
|
|
1
|
-
// Editor gizmos: immediate-mode line drawing for code that runs while a scene is EDITED — a
|
|
2
|
-
// generator aspect's `rebuild()`, a `make()` factory, an editor tool's hooks. Nothing here touches
|
|
3
|
-
// the scene: calls accumulate WORLD-space line segments into the buffer of the run that is
|
|
4
|
-
// currently executing (an ambient scope the scene loader opens around each synchronous call), and
|
|
5
|
-
// the scene editor pushes those buffers to the lite engine's overlay layer, which draws them over
|
|
6
|
-
// the picture — never outlined, never picked, never rendered by Filament, absent in play mode.
|
|
7
|
-
//
|
|
8
|
-
// rebuild() {
|
|
9
|
-
// Gizmos.polyline(points, { color: "#5b8ef0", closed: true })
|
|
10
|
-
// for (const p of points) Gizmos.cross(p, 0.07)
|
|
11
|
-
// }
|
|
12
|
-
//
|
|
13
|
-
// Every run starts with an EMPTY buffer — what a call draws is the whole picture (like
|
|
14
|
-
// `generated.clear()`, only implicit). Outside any scope (play mode, hand-attached aspects, a call
|
|
15
|
-
// after an `await` inside rebuild) the calls are no-ops: rebuild is synchronous by contract.
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
alpha
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
1
|
+
// Editor gizmos: immediate-mode line drawing for code that runs while a scene is EDITED — a
|
|
2
|
+
// generator aspect's `rebuild()`, a `make()` factory, an editor tool's hooks. Nothing here touches
|
|
3
|
+
// the scene: calls accumulate WORLD-space line segments into the buffer of the run that is
|
|
4
|
+
// currently executing (an ambient scope the scene loader opens around each synchronous call), and
|
|
5
|
+
// the scene editor pushes those buffers to the lite engine's overlay layer, which draws them over
|
|
6
|
+
// the picture — never outlined, never picked, never rendered by Filament, absent in play mode.
|
|
7
|
+
//
|
|
8
|
+
// rebuild() {
|
|
9
|
+
// Gizmos.polyline(points, { color: "#5b8ef0", closed: true })
|
|
10
|
+
// for (const p of points) Gizmos.cross(p, 0.07)
|
|
11
|
+
// }
|
|
12
|
+
//
|
|
13
|
+
// Every run starts with an EMPTY buffer — what a call draws is the whole picture (like
|
|
14
|
+
// `generated.clear()`, only implicit). Outside any scope (play mode, hand-attached aspects, a call
|
|
15
|
+
// after an `await` inside rebuild) the calls are no-ops: rebuild is synchronous by contract. In a
|
|
16
|
+
// shipped bundle they are no-ops by COMPILE: `target` folds to null with `EDITOR`, and the buffer
|
|
17
|
+
// and the scope (the editor's — ./editor.ts) are not in the bundle.
|
|
18
|
+
//
|
|
19
|
+
// ANCHORED gizmos (`{ node }` in the style): points are in that node's LOCAL frame and the engine
|
|
20
|
+
// follows the node live — through a gizmo drag, not only after it — with the node's scale
|
|
21
|
+
// stripped (an empty scaled ×10 for its children keeps a normal-sized cross). An anchored picture
|
|
22
|
+
// is the node's own: clicking it in the viewport selects the node, and it draws in the selection
|
|
23
|
+
// accent while selected. World-space calls (path lines) are never pickable.
|
|
24
|
+
|
|
25
|
+
import { Color, type ColorInput } from "../core/color"
|
|
26
|
+
import { Mat4, type Mat4Like } from "../math/mat4"
|
|
27
|
+
import type { Vec3Like } from "../math/vec"
|
|
28
|
+
|
|
29
|
+
/** The anchor of a gizmo call: any object with an engine entity id (a `Node`). */
|
|
30
|
+
export type GizmoAnchor = { readonly id: number }
|
|
31
|
+
|
|
32
|
+
export type GizmoStyle = {
|
|
33
|
+
/** Any color (a CSS color string, `0xRRGGBB`, `[r, g, b(, a)]`; its alpha multiplies `alpha`);
|
|
34
|
+
* default a neutral light gray. */
|
|
35
|
+
color?: ColorInput
|
|
36
|
+
/** 0..1, default 1. */
|
|
37
|
+
alpha?: number
|
|
38
|
+
/** Anchor: points are in this node's LOCAL frame (scale ignored); the lines follow the node
|
|
39
|
+
* live, are pickable (a click selects the node) and turn the selection accent when it is
|
|
40
|
+
* selected. Omit for world-space lines (not pickable). */
|
|
41
|
+
node?: GizmoAnchor | null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** One color batch of LINES (flat `[x,y,z, x,y,z]` per segment) — what a host hands the engine
|
|
45
|
+
* (`color` a CSS color string, '#rrggbbaa' from here). With `entityId` the segments are in that
|
|
46
|
+
* entity's local frame (see GizmoStyle.node). */
|
|
47
|
+
export type GizmoBatch = { color: string, alpha: number, segments: number[], entityId?: number }
|
|
48
|
+
|
|
49
|
+
const DEFAULT_COLOR = "#cfd4ddff"
|
|
50
|
+
|
|
51
|
+
/** The per-run collector (owned by the scene loader's EditorRun). Batches are keyed by style so a
|
|
52
|
+
* hundred same-colored segments cost one draw. */
|
|
53
|
+
export class GizmoBuffer {
|
|
54
|
+
batches: GizmoBatch[] = []
|
|
55
|
+
private _byStyle = new Map<string, GizmoBatch>()
|
|
56
|
+
|
|
57
|
+
clear(): void {
|
|
58
|
+
this.batches = []
|
|
59
|
+
this._byStyle.clear()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
segments(style: GizmoStyle | undefined): number[] {
|
|
63
|
+
// one spelling per color, so 'red' and '#f00' share a batch
|
|
64
|
+
const color = style?.color != null ? Color.toHexString(style.color) : DEFAULT_COLOR
|
|
65
|
+
const alpha = Math.max(0, Math.min(1, style?.alpha ?? 1))
|
|
66
|
+
const entityId = style?.node?.id
|
|
67
|
+
const key = `${color}@${alpha}@${entityId ?? ""}`
|
|
68
|
+
let b = this._byStyle.get(key)
|
|
69
|
+
if (!b) {
|
|
70
|
+
b = entityId ? { color, alpha, segments: [], entityId } : { color, alpha, segments: [] }
|
|
71
|
+
this._byStyle.set(key, b)
|
|
72
|
+
this.batches.push(b)
|
|
73
|
+
}
|
|
74
|
+
return b.segments
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let current: GizmoBuffer | null = null
|
|
79
|
+
let warnedOutOfScope = false
|
|
80
|
+
|
|
81
|
+
const xyz = (p: Vec3Like): [number, number, number] =>
|
|
82
|
+
Array.isArray(p) ? [ p[0] ?? 0, p[1] ?? 0, p[2] ?? 0 ] : [ (p as { x: number }).x, (p as { y: number }).y, (p as { z: number }).z ]
|
|
83
|
+
|
|
84
|
+
const target = (style: GizmoStyle | undefined): number[] | null => {
|
|
85
|
+
if (EDITOR && current) return current.segments(style)
|
|
86
|
+
if (EDITOR && !warnedOutOfScope && (globalThis as { __lecodesSceneEdit?: boolean }).__lecodesSceneEdit) {
|
|
87
|
+
warnedOutOfScope = true
|
|
88
|
+
console.warn("[Gizmos] draw call outside an editor run — gizmos must be drawn synchronously inside rebuild() / a make() factory / a tool hook")
|
|
89
|
+
}
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** @internal Run `fn` with `buffer` as the ambient gizmo target (cleared first). Nested scopes
|
|
94
|
+
* restore the outer one. */
|
|
95
|
+
export const withGizmoScope = <T>(buffer: GizmoBuffer, fn: () => T): T => {
|
|
96
|
+
const prev = current
|
|
97
|
+
buffer.clear()
|
|
98
|
+
current = buffer
|
|
99
|
+
try { return fn() } finally { current = prev }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Editor-only line drawing, available inside generator `rebuild()`, `make()` factories and editor
|
|
104
|
+
* tool hooks. Points are WORLD space. Drawn by the scene editor's viewport overlay (depth-test
|
|
105
|
+
* off — a path through a wall is still a path); invisible everywhere else.
|
|
106
|
+
*/
|
|
107
|
+
export const Gizmos = {
|
|
108
|
+
/** One segment from `a` to `b`. */
|
|
109
|
+
line(a: Vec3Like, b: Vec3Like, style?: GizmoStyle): void {
|
|
110
|
+
const out = target(style)
|
|
111
|
+
if (!out) return
|
|
112
|
+
out.push(...xyz(a), ...xyz(b))
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
/** Consecutive segments through `points`; `closed` joins the last point back to the first. */
|
|
116
|
+
polyline(points: readonly Vec3Like[], style?: GizmoStyle & { closed?: boolean }): void {
|
|
117
|
+
if (points.length < 2) return
|
|
118
|
+
const out = target(style)
|
|
119
|
+
if (!out) return
|
|
120
|
+
const n = points.length
|
|
121
|
+
const last = style?.closed ? n : n - 1
|
|
122
|
+
for (let i = 0; i < last; i++) out.push(...xyz(points[i]!), ...xyz(points[(i + 1) % n]!))
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
/** A wireframe camera frustum looking down −Z: the four edges from the origin to a rect
|
|
126
|
+
* `length` metres ahead sized by `fov` (vertical, degrees) × `aspect` (default 16:9), plus an
|
|
127
|
+
* "up" fin above the rect. Anchor it (`{ node }`) for a camera node's marker — the frustum
|
|
128
|
+
* then follows the node's pose; `matrix` places an unanchored one in world space. */
|
|
129
|
+
frustum(fov: number, style?: GizmoStyle & { aspect?: number, length?: number, matrix?: Mat4Like }): void {
|
|
130
|
+
const out = target(style)
|
|
131
|
+
if (!out) return
|
|
132
|
+
const aspect = style?.aspect ?? 16 / 9, length = style?.length ?? 0.6
|
|
133
|
+
const m = style?.matrix ? new Mat4(style.matrix) : null
|
|
134
|
+
const h = Math.tan((fov * Math.PI) / 360) * length, w = h * aspect, z = -length
|
|
135
|
+
const P = (x: number, y: number, zz: number): [number, number, number] => {
|
|
136
|
+
if (!m) return [ x, y, zz ]
|
|
137
|
+
const v = m.transformPoint([ x, y, zz ])
|
|
138
|
+
return [ v.x, v.y, v.z ]
|
|
139
|
+
}
|
|
140
|
+
const o = P(0, 0, 0)
|
|
141
|
+
const c = [ P(-w, -h, z), P(w, -h, z), P(w, h, z), P(-w, h, z) ]
|
|
142
|
+
for (const q of c) out.push(...o, ...q)
|
|
143
|
+
for (let i = 0; i < 4; i++) out.push(...c[i]!, ...c[(i + 1) % 4]!)
|
|
144
|
+
out.push(...P(-w * 0.4, h, z), ...P(0, h * 1.6, z), ...P(0, h * 1.6, z), ...P(w * 0.4, h, z))
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/** A three-axis cross centred on `p` (a point marker); `size` = half extent, default 0.1. */
|
|
148
|
+
cross(p: Vec3Like, size = 0.1, style?: GizmoStyle): void {
|
|
149
|
+
const out = target(style)
|
|
150
|
+
if (!out) return
|
|
151
|
+
const [ x, y, z ] = xyz(p)
|
|
152
|
+
out.push(x - size, y, z, x + size, y, z, x, y - size, z, x, y + size, z, x, y, z - size, x, y, z + size)
|
|
153
|
+
},
|
|
154
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// per-model type bags and MODELS metadata this file is parametrised by.
|
|
8
8
|
//
|
|
9
9
|
// Keep it dependency-free: besides shipping in `marcidb-client/runtime`, this file is vendored verbatim
|
|
10
|
-
// into the lecodes SDK (`
|
|
10
|
+
// into the lecodes SDK (`sdk/src/server/db/marci/query.ts`, `bun run sync:marcidb` there), which
|
|
11
11
|
// derives its model types from TS builders instead of codegen and plugs them into the same generics.
|
|
12
12
|
|
|
13
13
|
// ───────────────────────────── query language types ─────────────────────────────
|
package/src/server/host.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `sdk/server` — the HOST side of the app backend, imported normally by the runner
|
|
3
|
-
* (
|
|
3
|
+
* (tools/runner), the backend and tests. Nothing here is bundled into project code; the
|
|
4
4
|
* bundle carries its own SDK copy and meets this module only through the `globalThis.__lecodes*`
|
|
5
5
|
* seams (see ./runtime.ts).
|
|
6
6
|
*/
|
package/src/server/runtime.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Host side of a compiled server bundle — used by the runner (
|
|
2
|
+
* Host side of a compiled server bundle — used by the runner (tools/runner) and by tests.
|
|
3
3
|
* Imported normally (Node/Bun), NOT through chisel: the bundle carries its own SDK copy and talks
|
|
4
4
|
* to this module only through globals (`__lecodesServer`, `__lecodesRequest`, `__lecodesPublish`).
|
|
5
5
|
*
|
package/src/ui/NativeView.ts
CHANGED
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
// wrapper convention.
|
|
11
11
|
|
|
12
12
|
import { _channelCall, _channelEmit, _channelOff, _channelOn, type ChannelListeners } from "../runtime/channel"
|
|
13
|
-
import { _bumpNavEpoch,
|
|
13
|
+
import { _bumpNavEpoch, _setCurrent, Presentable, type DestTuple, type DismissOptions, type PresentOptions } from "./presentable"
|
|
14
|
+
import { _transitionId, TRANSITION_NONE } from "./transitions"
|
|
14
15
|
import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from "./UINode"
|
|
16
|
+
import { TREE_DEST_NATIVE, registerDest, registerNativeView, tree, unregisterNativeView } from "./tree"
|
|
15
17
|
|
|
16
18
|
export type UINativeViewStyle = ElementStyle & DrawableStyle
|
|
17
19
|
|
|
@@ -28,25 +30,30 @@ export interface NativeView extends UIElementBase<UINativeViewStyle, DrawableSty
|
|
|
28
30
|
/** Show fullscreen as the current destination (see Presentable). */
|
|
29
31
|
open(options?: PresentOptions): void,
|
|
30
32
|
/** Dismiss if this is the visible destination. */
|
|
31
|
-
close(): void,
|
|
33
|
+
close(options?: DismissOptions): void,
|
|
32
34
|
|
|
33
35
|
/** Became the visible destination. */
|
|
34
36
|
onOpen(callback: () => void): this
|
|
35
37
|
/** Stopped being the visible destination. */
|
|
36
38
|
onClose(callback: () => void): this
|
|
37
39
|
/** Hardware/system back while current. */
|
|
38
|
-
|
|
40
|
+
onBack(callback: () => void): this
|
|
39
41
|
|
|
40
42
|
/** Invoke a method on the native view (`map.call("setCenter", [lng, lat])`). Args and the
|
|
41
|
-
* result are
|
|
43
|
+
* result are plain data (and Uint8Array). Rejects if the host has no such view/method. */
|
|
42
44
|
call(method: string, ...args: any[]): Promise<any>
|
|
43
45
|
/** Subscribe to an event the native view emits (`map.on("markerTap", cb)`). */
|
|
44
46
|
on(event: string, callback: (data?: any) => void): this
|
|
45
47
|
off(event: string, callback: (data?: any) => void): this
|
|
48
|
+
/** @internal The destination tuple (Presentable). */
|
|
49
|
+
_dest(): DestTuple
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
let nextViewId = 1
|
|
49
53
|
|
|
54
|
+
const PRESENTED = 1
|
|
55
|
+
const MOUNTED = 2
|
|
56
|
+
|
|
50
57
|
/** @internal Base for typed plugin wrappers (QRScanner, CameraView — src/plugins/): subclass it,
|
|
51
58
|
* pin the viewName/params, and layer typed methods over the raw `call`/`on` channel. Not a
|
|
52
59
|
* public global — apps use the `NativeView(name)` factory below. */
|
|
@@ -55,37 +62,41 @@ export class NativeViewElement extends Element<"native"> implements Presentable
|
|
|
55
62
|
readonly params: any
|
|
56
63
|
/** @internal stable per-instance handle for the viewCall channel + promotion identity. */
|
|
57
64
|
readonly _viewId: number
|
|
58
|
-
/** @internal event listeners by event name
|
|
59
|
-
* or calls _emitViewEvent. */
|
|
65
|
+
/** @internal event listeners by event name (host → view events come through the tree emitter). */
|
|
60
66
|
readonly nvl: ChannelListeners = {}
|
|
61
67
|
readonly ol: (() => void)[] = []
|
|
62
68
|
readonly cl: (() => void)[] = []
|
|
63
|
-
_backButtonCallback?: () => void
|
|
64
|
-
private
|
|
69
|
+
private _backButtonCallback?: () => void
|
|
70
|
+
private readonly _paramsJson: string
|
|
71
|
+
/** @internal Where the host has a view of this instance: PRESENTED | MOUNTED. */
|
|
72
|
+
private _shown = 0
|
|
65
73
|
|
|
66
74
|
constructor(viewName: string, params: any) {
|
|
67
75
|
super("native", {})
|
|
68
76
|
this.viewName = viewName
|
|
69
77
|
this.params = params
|
|
70
78
|
this._viewId = nextViewId++
|
|
79
|
+
this._paramsJson = JSON.stringify(params ?? {})
|
|
80
|
+
tree().setString(this._h.id, "viewName", viewName)
|
|
81
|
+
tree().setString(this._h.id, "viewParams", this._paramsJson)
|
|
82
|
+
tree().setInt(this._h.id, "viewId", this._viewId)
|
|
83
|
+
registerDest(TREE_DEST_NATIVE, this._viewId, this)
|
|
71
84
|
}
|
|
72
85
|
|
|
73
|
-
/** @internal
|
|
74
|
-
|
|
75
|
-
return this._vd ??= { type: "native", viewName: this.viewName, params: this.params, viewId: this._viewId, _p: this }
|
|
76
|
-
}
|
|
86
|
+
/** @internal */
|
|
87
|
+
_dest(): DestTuple { return [TREE_DEST_NATIVE, this._viewId, this.viewName, this._paramsJson] }
|
|
77
88
|
|
|
78
89
|
open(options?: PresentOptions): void {
|
|
79
|
-
if (!
|
|
80
|
-
throw new Error(`NativeView("${this.viewName}") is not supported on this host (
|
|
90
|
+
if (!tree().isViewSupported(this.viewName)) {
|
|
91
|
+
throw new Error(`NativeView("${this.viewName}") is not supported on this host (no registered view)`)
|
|
81
92
|
}
|
|
82
93
|
_bumpNavEpoch()
|
|
83
|
-
|
|
94
|
+
tree().open(TREE_DEST_NATIVE, this._viewId, this.viewName, this._paramsJson, _transitionId(options?.transition, TRANSITION_NONE))
|
|
84
95
|
_setCurrent(this)
|
|
85
96
|
}
|
|
86
|
-
close(): void {
|
|
97
|
+
close(options?: DismissOptions): void {
|
|
87
98
|
_bumpNavEpoch()
|
|
88
|
-
|
|
99
|
+
tree().close(TREE_DEST_NATIVE, this._viewId, _transitionId(options?.transition, TRANSITION_NONE))
|
|
89
100
|
if (Presentable.current === this) _setCurrent(null)
|
|
90
101
|
}
|
|
91
102
|
|
|
@@ -97,15 +108,47 @@ export class NativeViewElement extends Element<"native"> implements Presentable
|
|
|
97
108
|
this.cl.push(callback)
|
|
98
109
|
return this
|
|
99
110
|
}
|
|
100
|
-
|
|
111
|
+
onBack(callback: () => void): this {
|
|
101
112
|
this._backButtonCallback = callback
|
|
102
113
|
return this
|
|
103
114
|
}
|
|
115
|
+
/** @internal */
|
|
116
|
+
// The host has a view that can send events while the instance is presented OR mounted among a
|
|
117
|
+
// screen's children: findable by viewId while it is either (owned handles) — a promoted view that
|
|
118
|
+
// closes is still the embedded one.
|
|
119
|
+
private _reach(where: number, on: boolean): void {
|
|
120
|
+
const was = this._shown
|
|
121
|
+
this._shown = on ? was | where : was & ~where
|
|
122
|
+
if (was === 0 && this._shown !== 0) registerNativeView(this._viewId, this)
|
|
123
|
+
else if (was !== 0 && this._shown === 0) unregisterNativeView(this._viewId)
|
|
124
|
+
}
|
|
125
|
+
/** @internal */
|
|
126
|
+
_emitOpen(): void { this._reach(PRESENTED, true); for (const cb of this.ol.slice()) cb() }
|
|
127
|
+
/** @internal */
|
|
128
|
+
_emitClose(): void { this._reach(PRESENTED, false); for (const cb of this.cl.slice()) cb() }
|
|
129
|
+
/** @internal */
|
|
130
|
+
_pinned(): void { this._reach(MOUNTED, true) }
|
|
131
|
+
/** @internal */
|
|
132
|
+
_unpinned(): void { this._reach(MOUNTED, false) }
|
|
133
|
+
/** @internal */
|
|
134
|
+
override _freed(): void {
|
|
135
|
+
this._reach(MOUNTED, false)
|
|
136
|
+
super._freed()
|
|
137
|
+
}
|
|
138
|
+
/** @internal */
|
|
139
|
+
_emitBack(): boolean {
|
|
140
|
+
if (!this._backButtonCallback) return false
|
|
141
|
+
this._backButtonCallback()
|
|
142
|
+
return true
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
call(method: string, ...args: any[]): Promise<any> { return this._channelSend(method, args) }
|
|
104
146
|
|
|
105
|
-
call
|
|
147
|
+
/** @internal One call over the channel (runtime/channel.ts). */
|
|
148
|
+
_channelSend(method: string, args: any[]): Promise<any> {
|
|
106
149
|
return _channelCall(
|
|
107
|
-
typeof
|
|
108
|
-
`NativeView("${this.viewName}") is not supported on this host (requires
|
|
150
|
+
typeof _creatorTree !== "undefined" ? _creatorTree : undefined, "viewCall",
|
|
151
|
+
`NativeView("${this.viewName}") is not supported on this host (requires _creatorTree.viewCall)`,
|
|
109
152
|
this._viewId, method, args)
|
|
110
153
|
}
|
|
111
154
|
|
|
@@ -117,9 +160,9 @@ export class NativeViewElement extends Element<"native"> implements Presentable
|
|
|
117
160
|
_channelOff(this.nvl, event, callback)
|
|
118
161
|
return this
|
|
119
162
|
}
|
|
120
|
-
/** @internal host entry: deliver a native event (payload
|
|
121
|
-
_emitViewEvent(event: string,
|
|
122
|
-
_channelEmit(this.nvl, event,
|
|
163
|
+
/** @internal host entry: deliver a native event (its payload, or none). */
|
|
164
|
+
_emitViewEvent(event: string, data?: unknown): void {
|
|
165
|
+
_channelEmit(this.nvl, event, data)
|
|
123
166
|
}
|
|
124
167
|
}
|
|
125
168
|
|
|
@@ -133,10 +176,14 @@ export const NativeView: {
|
|
|
133
176
|
(name: string, params?: object): NativeView
|
|
134
177
|
/** Whether this host registered a `registerView` factory under `name`. */
|
|
135
178
|
isSupported(name: string): boolean
|
|
179
|
+
/** The contract version of the host's view `name`: 0 when it has none, 1 for one written by hand. */
|
|
180
|
+
version(name: string): number
|
|
136
181
|
} = /*#__PURE__*/ (() => {
|
|
137
182
|
const factory = (name: string, params: object = {}): NativeView =>
|
|
138
183
|
new NativeViewElement(name, params) as unknown as NativeView
|
|
139
184
|
factory.isSupported = (name: string): boolean =>
|
|
140
|
-
typeof
|
|
185
|
+
typeof _creatorTree !== "undefined" && _creatorTree.isViewSupported(name)
|
|
186
|
+
factory.version = (name: string): number =>
|
|
187
|
+
typeof _creatorTree !== "undefined" ? _creatorTree.viewVersion(name) : 0
|
|
141
188
|
return factory
|
|
142
189
|
})()
|
package/src/ui/UI.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// The UI surface: every element the SDK exports. The host side of each is the runtime's tree
|
|
2
|
+
// (docs/tree.md); the renderers implement HostUI over node ids.
|
|
3
3
|
export { UIButton, type UIButtonStyle } from './UIButton'
|
|
4
4
|
export { UIScreen, type UIScreenStyle } from './UIScreen'
|
|
5
5
|
export { UISpacer, type UISpacerStyle } from './UISpacer'
|
|
@@ -25,7 +25,7 @@ export { Router } from './router'
|
|
|
25
25
|
export { NativeView, type UINativeViewStyle } from './NativeView'
|
|
26
26
|
// Presentable is both the interface and its runtime companion (Presentable.current).
|
|
27
27
|
export { Presentable } from './presentable'
|
|
28
|
-
export type { PresentOptions, Transition, TransitionName,
|
|
28
|
+
export type { DismissOptions, PresentOptions, Transition, TransitionName, TransitionPose, TransitionSpec } from './presentable'
|
|
29
29
|
|
|
30
30
|
// Internal: memoized map for reactive children — the chisel `reactiveUi` pass rewrites
|
|
31
31
|
// `list.map(fn)` inside children bindings to `__uiMap(list, fn, slot)` calls.
|
package/src/ui/UIBottomSheet.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ModalElement, type UIModalStyle } from "./UIModal"
|
|
2
2
|
import type { UIWidget } from "./UIWidget"
|
|
3
3
|
import { buildUI, type ChildrenFn, type UIChildArg, type UINodeChild } from "./UINode"
|
|
4
|
+
import { TREE_FLAG_DETENT } from "./tree"
|
|
4
5
|
|
|
5
6
|
export type UIBottomSheetStyle = UIModalStyle
|
|
6
7
|
|
|
@@ -18,11 +19,11 @@ const SHEET_ANIM_MS = 250
|
|
|
18
19
|
* modal machinery.
|
|
19
20
|
*
|
|
20
21
|
* ```ts
|
|
21
|
-
* const actions = UIBottomSheet({ bgColor: "#1c1c1e", borderRadius: 16 }
|
|
22
|
+
* const actions = UIBottomSheet(rows).style({ bgColor: "#1c1c1e", borderRadius: 16 }) // content-sized
|
|
22
23
|
*
|
|
23
|
-
* const mapSheet = UIBottomSheet({ bgColor: "#1c1c1e", borderRadius: 16 }
|
|
24
|
+
* const mapSheet = UIBottomSheet(results).style({ bgColor: "#1c1c1e", borderRadius: 16 })
|
|
24
25
|
* .detents([0.3, 0.6, 1])
|
|
25
|
-
* .
|
|
26
|
+
* .onDetent(i => map.setPadding(...))
|
|
26
27
|
* ```
|
|
27
28
|
*/
|
|
28
29
|
export interface UIBottomSheet extends UIWidget {
|
|
@@ -30,12 +31,12 @@ export interface UIBottomSheet extends UIWidget {
|
|
|
30
31
|
* the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet
|
|
31
32
|
* is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */
|
|
32
33
|
detents(list: number[]): this,
|
|
33
|
-
/** Snap to a detent (animated). Clamped to the detents range; fires `
|
|
34
|
+
/** Snap to a detent (animated). Clamped to the detents range; fires `onDetent`. */
|
|
34
35
|
setDetent(index: number): void,
|
|
35
36
|
/** Current detent index. */
|
|
36
37
|
readonly detent: number,
|
|
37
38
|
/** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */
|
|
38
|
-
|
|
39
|
+
onDetent(callback: (index: number) => void): this,
|
|
39
40
|
|
|
40
41
|
/** Mount and slide in to the current detent. No-op while already open. */
|
|
41
42
|
show(): void,
|
|
@@ -56,10 +57,6 @@ export interface UIBottomSheet extends UIWidget {
|
|
|
56
57
|
export class BottomSheetElement extends ModalElement {
|
|
57
58
|
_detents: number[] = [1]
|
|
58
59
|
_detent = 0
|
|
59
|
-
/** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the
|
|
60
|
-
* settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.
|
|
61
|
-
* `-1` = dragged below the lowest detent while dismissible. */
|
|
62
|
-
readonly dtl: any[] = []
|
|
63
60
|
readonly _detentListeners: ((index: number) => void)[] = []
|
|
64
61
|
|
|
65
62
|
constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn) {
|
|
@@ -70,11 +67,15 @@ export class BottomSheetElement extends ModalElement {
|
|
|
70
67
|
// The inherited show/hide pose animates ONLY the scrim: sheet geometry rides the
|
|
71
68
|
// sheetDetent style key, never the pose system.
|
|
72
69
|
this._transition = { duration: SHEET_ANIM_MS }
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
this._addFlags(TREE_FLAG_DETENT)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @internal The host's GESTURE settles only (programmatic `setDetent` fires JS-side); `-1` =
|
|
74
|
+
* dragged below the lowest detent while dismissible. */
|
|
75
|
+
_emitDetent(index: number): void {
|
|
76
|
+
if (index < 0) { this.hide(); return }
|
|
77
|
+
this._detent = index
|
|
78
|
+
for (const callback of this._detentListeners) callback(index)
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
detents(list: number[]): this {
|
|
@@ -101,7 +102,7 @@ export class BottomSheetElement extends ModalElement {
|
|
|
101
102
|
for (const callback of this._detentListeners) callback(clamped)
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
|
|
105
|
+
onDetent(callback: (index: number) => void): this {
|
|
105
106
|
this._detentListeners.push(callback)
|
|
106
107
|
return this
|
|
107
108
|
}
|
|
@@ -132,8 +133,6 @@ const makeBottomSheet = (style: any, children: any) => new BottomSheetElement(st
|
|
|
132
133
|
* `.detents([...])` for snap positions. Same argument forms as `UIColumn`. */
|
|
133
134
|
export function UIBottomSheet(...children: UIChildArg[]): UIBottomSheet;
|
|
134
135
|
export function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;
|
|
135
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
136
|
-
export function UIBottomSheet(style: UIBottomSheetStyle, children?: UINodeChild[] | ChildrenFn): UIBottomSheet;
|
|
137
136
|
export function UIBottomSheet(...args: any[]): UIBottomSheet {
|
|
138
137
|
return buildUI(args, null, makeBottomSheet)
|
|
139
138
|
}
|