lecodes-sdk 1.2.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 +8 -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/Scene.d.ts +41 -13
- package/dist/types/gl/Texture.d.ts +1 -1
- package/dist/types/gl/animation/Locomotion.d.ts +8 -1
- 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 +1 -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 +1 -1
- 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 +473 -239
- package/prompts/dist/3d-app.md +553 -205
- package/prompts/dist/ar-app.md +435 -202
- package/prompts/dist/design.md +113 -95
- package/prompts/dist/ui-app.md +386 -170
- package/prompts/ui-design.md +2 -3
- package/prompts/ui.md +45 -37
- package/src/animate/tween/Animation.ts +34 -150
- package/src/animate/tween/Timeline.ts +175 -175
- package/src/animate/tween/animateValue.ts +6 -3
- package/src/animate/tween/easing.ts +10 -3
- package/src/animate/tween/spec.ts +41 -15
- package/src/audio/Sound.ts +3 -3
- package/src/audio/audio.ts +2 -1
- 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/CameraPlace.ts +52 -52
- package/src/gl/Foliage.ts +72 -17
- package/src/gl/Geometry.ts +1 -2
- package/src/gl/Light.ts +10 -0
- package/src/gl/Lightmap.ts +45 -29
- package/src/gl/Material.ts +95 -51
- package/src/gl/Mesh.ts +120 -120
- package/src/gl/Model.ts +21 -16
- package/src/gl/Node.ts +91 -24
- package/src/gl/Particles.ts +1 -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/DynamicBone.ts +482 -482
- package/src/gl/animation/Locomotion.ts +8 -3
- 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/scenarios.ts +291 -291
- package/src/gl/terrain/Terrain.ts +4 -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 +13 -16
- 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 +12 -10
- 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 +15 -9
- 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 -4629
- 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 -1769
- 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/ui/UIText.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createBinding } from "../core/signals"
|
|
2
2
|
import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type TextStyle, type UIElementBase } from "./UINode"
|
|
3
|
+
import { tree } from "./tree"
|
|
3
4
|
|
|
4
5
|
export type UITextStyle = ElementStyle & TextStyle & DrawableStyle
|
|
5
6
|
|
|
@@ -11,19 +12,17 @@ export interface UIText extends UIElementBase<UITextStyle, DrawableStyle & BaseS
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export class TextElement extends Element<"text"> {
|
|
14
|
-
private _text
|
|
15
|
+
private _text = ""
|
|
15
16
|
constructor(style: any, text: string | (() => string)) {
|
|
16
17
|
super("text", style)
|
|
17
18
|
if (typeof text === "function") {
|
|
18
|
-
// Reactive content: re-runs when a signal `text()` read changes
|
|
19
|
-
// _creatorUI.updateNode when mounted and just keeps _text current when not.
|
|
20
|
-
this._text = ""
|
|
19
|
+
// Reactive content: re-runs when a signal `text()` read changes.
|
|
21
20
|
createBinding(this, "#text", () => {
|
|
22
21
|
const value = text()
|
|
23
22
|
if (value !== this._text) this.text = value
|
|
24
23
|
})
|
|
25
24
|
} else {
|
|
26
|
-
this.
|
|
25
|
+
this.text = text
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
get text(): string {
|
|
@@ -31,21 +30,12 @@ export class TextElement extends Element<"text"> {
|
|
|
31
30
|
}
|
|
32
31
|
set text(value) {
|
|
33
32
|
this._text = value
|
|
34
|
-
if (this.
|
|
35
|
-
_creatorUI.updateNode(this._id, "text", value)
|
|
36
|
-
}
|
|
33
|
+
if (this._h.id !== 0) tree().setString(this._h.id, "text", value)
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
/** Create a text label — a string, or `() => string` for reactive text that re-renders when a
|
|
41
38
|
* signal it read changes. */
|
|
42
|
-
export function UIText(text: string | (() => string)): UIText
|
|
43
|
-
|
|
44
|
-
export function UIText(style: UITextStyle, text: string | (() => string)): UIText;
|
|
45
|
-
export function UIText(...args: [string | (() => string)] | [UITextStyle, string | (() => string)]): UIText {
|
|
46
|
-
if (args.length === 1) {
|
|
47
|
-
return new TextElement({}, args[0])
|
|
48
|
-
} else {
|
|
49
|
-
return new TextElement(args[0], args[1])
|
|
50
|
-
}
|
|
39
|
+
export function UIText(text: string | (() => string)): UIText {
|
|
40
|
+
return new TextElement({}, text)
|
|
51
41
|
}
|
package/src/ui/UIVideo.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { VideoPlayer } from "../runtime/media"
|
|
2
|
-
import { _bumpNavEpoch,
|
|
2
|
+
import { _bumpNavEpoch, _setCurrent, Presentable, type DestTuple, type DismissOptions, type PresentOptions } from "./presentable"
|
|
3
|
+
import { _transitionId, TRANSITION_NONE } from "./transitions"
|
|
3
4
|
import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from "./UINode"
|
|
5
|
+
import { TREE_DEST_VIDEO, TREE_FLAG_BACK, pin, tree } from "./tree"
|
|
4
6
|
|
|
5
7
|
export type UIVideoStyle = ElementStyle & DrawableStyle & { objectFit?: "cover" | "contain" | "fill" }
|
|
6
8
|
|
|
@@ -15,22 +17,23 @@ export interface UIVideo extends UIElementBase<UIVideoStyle, DrawableStyle & Bas
|
|
|
15
17
|
* the SAME native player moves fullscreen — playback uninterrupted; a pop moves it back. */
|
|
16
18
|
open(options?: PresentOptions): void
|
|
17
19
|
/** Dismiss if this is the visible destination. */
|
|
18
|
-
close(): void
|
|
20
|
+
close(options?: DismissOptions): void
|
|
19
21
|
/** Became the visible destination. */
|
|
20
22
|
onOpen(callback: () => void): this
|
|
21
23
|
/** Stopped being the visible destination. */
|
|
22
24
|
onClose(callback: () => void): this
|
|
23
25
|
/** Hardware/system back while current. */
|
|
24
|
-
|
|
26
|
+
onBack(callback: () => void): this
|
|
27
|
+
/** @internal The destination tuple (Presentable). */
|
|
28
|
+
_dest(): DestTuple
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
class VideoElement extends Element<"video"> implements Presentable {
|
|
28
|
-
private _playerId: number
|
|
29
32
|
private _player: VideoPlayer
|
|
30
33
|
constructor(style: any, player: VideoPlayer) {
|
|
31
34
|
super("video", style)
|
|
32
35
|
this._player = player
|
|
33
|
-
this.
|
|
36
|
+
tree().setInt(this._h.id, "playerId", (player as any)._h.id)
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
get player() {
|
|
@@ -40,25 +43,21 @@ class VideoElement extends Element<"video"> implements Presentable {
|
|
|
40
43
|
// ---- Presentable (docs/navigation-presentable-plan.md) ----
|
|
41
44
|
readonly ol: (() => void)[] = []
|
|
42
45
|
readonly cl: (() => void)[] = []
|
|
43
|
-
_backButtonCallback?: () => void
|
|
44
|
-
private _vd?: object
|
|
46
|
+
private _backButtonCallback?: () => void
|
|
45
47
|
|
|
46
|
-
/** @internal
|
|
47
|
-
|
|
48
|
-
return this._vd ??= { type: "videoView", node: this, _p: this }
|
|
49
|
-
}
|
|
48
|
+
/** @internal */
|
|
49
|
+
_dest(): DestTuple { return [TREE_DEST_VIDEO, this._h.id, "", ""] }
|
|
50
50
|
|
|
51
51
|
open(options?: PresentOptions): void {
|
|
52
|
-
if (
|
|
53
|
-
throw new Error("Fullscreen video is not supported on this host (requires _creatorUI.openView)")
|
|
54
|
-
}
|
|
52
|
+
if (this._h.id === 0) return
|
|
55
53
|
_bumpNavEpoch()
|
|
56
|
-
|
|
54
|
+
pin(this)
|
|
55
|
+
tree().open(TREE_DEST_VIDEO, this._h.id, "", "", _transitionId(options?.transition, TRANSITION_NONE))
|
|
57
56
|
_setCurrent(this)
|
|
58
57
|
}
|
|
59
|
-
close(): void {
|
|
58
|
+
close(options?: DismissOptions): void {
|
|
60
59
|
_bumpNavEpoch()
|
|
61
|
-
|
|
60
|
+
tree().close(TREE_DEST_VIDEO, this._h.id, _transitionId(options?.transition, TRANSITION_NONE))
|
|
62
61
|
if (Presentable.current === this) _setCurrent(null)
|
|
63
62
|
}
|
|
64
63
|
onOpen(callback: () => void): this {
|
|
@@ -69,20 +68,24 @@ class VideoElement extends Element<"video"> implements Presentable {
|
|
|
69
68
|
this.cl.push(callback)
|
|
70
69
|
return this
|
|
71
70
|
}
|
|
72
|
-
|
|
71
|
+
onBack(callback: () => void): this {
|
|
73
72
|
this._backButtonCallback = callback
|
|
73
|
+
this._addFlags(TREE_FLAG_BACK)
|
|
74
74
|
return this
|
|
75
75
|
}
|
|
76
|
+
/** @internal */
|
|
77
|
+
_emitOpen(): void { for (const cb of this.ol.slice()) cb() }
|
|
78
|
+
/** @internal */
|
|
79
|
+
_emitClose(): void { for (const cb of this.cl.slice()) cb() }
|
|
80
|
+
/** @internal */
|
|
81
|
+
_emitBack(): boolean {
|
|
82
|
+
if (!this._backButtonCallback) return false
|
|
83
|
+
this._backButtonCallback()
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
/** Create a video node showing `player`'s output. */
|
|
79
|
-
export function UIVideo(player: VideoPlayer): UIVideo
|
|
80
|
-
|
|
81
|
-
export function UIVideo(style: UIVideoStyle, player: VideoPlayer): UIVideo
|
|
82
|
-
export function UIVideo(...args: [VideoPlayer] | [UIVideoStyle, VideoPlayer]): UIVideo {
|
|
83
|
-
if (args.length === 1) {
|
|
84
|
-
return new VideoElement({}, args[0])
|
|
85
|
-
} else {
|
|
86
|
-
return new VideoElement(args[0], args[1])
|
|
87
|
-
}
|
|
89
|
+
export function UIVideo(player: VideoPlayer): UIVideo {
|
|
90
|
+
return new VideoElement({}, player)
|
|
88
91
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Element, type Color, type DrawableStyle, type ElementStyle, type UIElementBase, type UINodeChild } from "./UINode"
|
|
2
|
+
import { TREE_FLAG_REFRESH, TREE_FLAG_SCROLL, TREE_FLAG_VLIST_END, TREE_FLAG_VLIST_START, pin, tree, unpin } from "./tree"
|
|
2
3
|
|
|
3
4
|
export type UIVirtualizedListStyle = DrawableStyle & ElementStyle & {
|
|
4
5
|
/** Tint of the native pull-to-refresh spinner (pairs with `onRefresh`). */
|
|
@@ -30,11 +31,11 @@ export interface VListConfig<T> {
|
|
|
30
31
|
export interface UIVirtualizedList<T = unknown> extends UIElementBase<UIVirtualizedListStyle> {
|
|
31
32
|
readonly type: "vlist"
|
|
32
33
|
|
|
33
|
-
/** Replace the data wholesale — vanished keys are unmounted by the
|
|
34
|
+
/** Replace the data wholesale — vanished keys are unmounted by the window sync. */
|
|
34
35
|
setData(items: T[]): this
|
|
35
36
|
/** Append items to the end (auto-scrolls when `inverted` and resting at the bottom). */
|
|
36
37
|
append(...items: T[]): this
|
|
37
|
-
/** Insert at the start WITHOUT a scroll jump (the
|
|
38
|
+
/** Insert at the start WITHOUT a scroll jump (the runtime compensates the offset). */
|
|
38
39
|
prepend(...items: T[]): this
|
|
39
40
|
/** Update items with the same keys: mounted ones re-render; the cached height persists until
|
|
40
41
|
* re-measured. */
|
|
@@ -56,37 +57,31 @@ export interface UIVirtualizedList<T = unknown> extends UIElementBase<UIVirtuali
|
|
|
56
57
|
|
|
57
58
|
/** Scroll position changed (px from the start edge). */
|
|
58
59
|
onScroll(callback: (scrollPosition: number) => void): this
|
|
59
|
-
/** Pull-to-refresh: the spinner stays until the returned promise settles.
|
|
60
|
-
* node mounts (hosts read it at creation). Native hosts only — no-op on web. */
|
|
60
|
+
/** Pull-to-refresh: the spinner stays until the returned promise settles. */
|
|
61
61
|
onRefresh(callback: () => void | Promise<void>): this
|
|
62
62
|
/** Fires within `thresholdPx` of the content's bottom edge — once, re-armed after leaving the
|
|
63
|
-
* edge (
|
|
63
|
+
* edge (a runtime-side latch). Infinite-scroll loading. */
|
|
64
64
|
onEndReached(thresholdPx: number, callback: () => void): this
|
|
65
65
|
/** Same, for the top edge — chat history loading. */
|
|
66
66
|
onStartReached(thresholdPx: number, callback: () => void): this
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export class VListElement<T> extends Element<"vlist"> implements UIVirtualizedList<T> {
|
|
70
|
+
private readonly sl: ((scrollPosition: number) => void)[] = [] // scroll
|
|
71
|
+
private readonly erl: (() => void)[] = [] // endReached
|
|
72
|
+
private readonly strl: (() => void)[] = [] // startReached
|
|
73
|
+
private _refreshCallback?: () => void | Promise<void>
|
|
70
74
|
|
|
71
|
-
// --- read by native side in createUINode (copyProperty / copyNodePtr) ---
|
|
72
|
-
_overscan: number
|
|
73
|
-
_inverted: boolean
|
|
74
|
-
_keys: string[] = []
|
|
75
|
-
_estimates: number[] = []
|
|
76
|
-
_endThreshold = 0
|
|
77
|
-
_startThreshold = 0
|
|
78
|
-
|
|
79
|
-
// --- списки слушателей, нативка забирает через copyPropertyListPtr ---
|
|
80
|
-
protected sl: ((scrollPosition: number) => void)[] = [] // scroll
|
|
81
|
-
protected erl: (() => void)[] = [] // endReached
|
|
82
|
-
protected strl: (() => void)[] = [] // startReached
|
|
83
|
-
|
|
84
|
-
// --- приватное состояние JS-стороны ---
|
|
85
75
|
private items = new Map<string, T>()
|
|
86
|
-
private mounted = new Map<string,
|
|
76
|
+
private mounted = new Map<string, any>()
|
|
87
77
|
private keyOf: (item: T) => string
|
|
88
78
|
private renderItem: (item: T) => UINodeChild
|
|
89
79
|
private estimate: (item: T) => number
|
|
80
|
+
private readonly _overscan: number
|
|
81
|
+
private readonly _inverted: boolean
|
|
82
|
+
private _endThreshold = 0
|
|
83
|
+
private _startThreshold = 0
|
|
84
|
+
private _inited = false
|
|
90
85
|
|
|
91
86
|
constructor(config: VListConfig<T>) {
|
|
92
87
|
// flexShrink: 1 default (SDK-owned, same as UIScrollable): an explicit height/flexBasis
|
|
@@ -102,8 +97,12 @@ export class VListElement<T> extends Element<"vlist"> implements UIVirtualizedLi
|
|
|
102
97
|
this._inverted = config.inverted ?? false
|
|
103
98
|
}
|
|
104
99
|
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
// The runtime's list state is created on the first data write — after the app had its chance to
|
|
101
|
+
// set the edge thresholds (onEndReached / onStartReached come before setData in practice).
|
|
102
|
+
private _ensure(): void {
|
|
103
|
+
if (this._inited || this._h.id === 0) return
|
|
104
|
+
this._inited = true
|
|
105
|
+
tree().vlistInit(this._h.id, this._overscan, this._inverted, this._startThreshold, this._endThreshold)
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
private register(items: T[]): [string[], number[]] {
|
|
@@ -123,14 +122,12 @@ export class VListElement<T> extends Element<"vlist"> implements UIVirtualizedLi
|
|
|
123
122
|
const prevMounted = [...this.mounted.keys()]
|
|
124
123
|
this.items.clear()
|
|
125
124
|
const [keys, estimates] = this.register(items)
|
|
126
|
-
this.
|
|
127
|
-
this.
|
|
128
|
-
|
|
129
|
-
_creatorUI.vlistSetKeys(this, keys, estimates)
|
|
130
|
-
|
|
125
|
+
this._ensure()
|
|
126
|
+
if (this._h.id !== 0) {
|
|
127
|
+
tree().vlistSetKeys(this._h.id, keys, estimates)
|
|
131
128
|
for (const k of prevMounted) {
|
|
132
129
|
if (this.mounted.has(k) && this.items.get(k) !== prevItems.get(k)) {
|
|
133
|
-
|
|
130
|
+
tree().vlistInvalidate(this._h.id, k)
|
|
134
131
|
}
|
|
135
132
|
}
|
|
136
133
|
}
|
|
@@ -139,21 +136,15 @@ export class VListElement<T> extends Element<"vlist"> implements UIVirtualizedLi
|
|
|
139
136
|
|
|
140
137
|
append(...items: T[]): this {
|
|
141
138
|
const [keys, estimates] = this.register(items)
|
|
142
|
-
this.
|
|
143
|
-
this.
|
|
144
|
-
if (this.isAttached) {
|
|
145
|
-
_creatorUI.vlistInsertKeys(this, -1, keys, estimates)
|
|
146
|
-
}
|
|
139
|
+
this._ensure()
|
|
140
|
+
if (this._h.id !== 0) tree().vlistInsertKeys(this._h.id, -1, keys, estimates)
|
|
147
141
|
return this
|
|
148
142
|
}
|
|
149
143
|
|
|
150
144
|
prepend(...items: T[]): this {
|
|
151
145
|
const [keys, estimates] = this.register(items)
|
|
152
|
-
this.
|
|
153
|
-
this.
|
|
154
|
-
if (this.isAttached) {
|
|
155
|
-
_creatorUI.vlistInsertKeys(this, 0, keys, estimates)
|
|
156
|
-
}
|
|
146
|
+
this._ensure()
|
|
147
|
+
if (this._h.id !== 0) tree().vlistInsertKeys(this._h.id, 0, keys, estimates)
|
|
157
148
|
return this
|
|
158
149
|
}
|
|
159
150
|
|
|
@@ -162,74 +153,82 @@ export class VListElement<T> extends Element<"vlist"> implements UIVirtualizedLi
|
|
|
162
153
|
const k = this.keyOf(item)
|
|
163
154
|
if (!this.items.has(k)) continue
|
|
164
155
|
this.items.set(k, item)
|
|
165
|
-
if (this.
|
|
166
|
-
_creatorUI.vlistInvalidate(this, k)
|
|
167
|
-
}
|
|
156
|
+
if (this._h.id !== 0 && this.mounted.has(k)) tree().vlistInvalidate(this._h.id, k)
|
|
168
157
|
}
|
|
169
158
|
return this
|
|
170
159
|
}
|
|
171
160
|
|
|
172
161
|
removeByKey(...keys: string[]): this {
|
|
162
|
+
const gone: string[] = []
|
|
173
163
|
for (const k of keys) {
|
|
174
164
|
if (!this.items.delete(k)) continue
|
|
175
|
-
|
|
176
|
-
if (i >= 0) { this._keys.splice(i, 1); this._estimates.splice(i, 1) }
|
|
177
|
-
}
|
|
178
|
-
if (this.isAttached) {
|
|
179
|
-
_creatorUI.vlistRemoveKeys(this, keys)
|
|
165
|
+
gone.push(k)
|
|
180
166
|
}
|
|
167
|
+
if (this._h.id !== 0 && gone.length > 0) tree().vlistRemoveKeys(this._h.id, gone)
|
|
181
168
|
return this
|
|
182
169
|
}
|
|
183
170
|
|
|
184
171
|
get itemCount(): number { return this.items.size }
|
|
185
172
|
getItem(key: string): T | undefined { return this.items.get(key) }
|
|
186
173
|
|
|
187
|
-
// ---
|
|
174
|
+
// --- commands: offsets and positions are the runtime's (prefix sums) ---
|
|
188
175
|
scrollTo(offset: number, animated = true): void {
|
|
189
|
-
|
|
176
|
+
if (this._h.id !== 0) tree().vlistScrollTo(this._h.id, offset, animated)
|
|
190
177
|
}
|
|
191
178
|
scrollToKey(key: string, animated = true): void {
|
|
192
|
-
|
|
179
|
+
if (this._h.id !== 0) tree().vlistScrollToKey(this._h.id, key, animated)
|
|
193
180
|
}
|
|
194
181
|
scrollToEnd(animated = true): void {
|
|
195
|
-
|
|
182
|
+
if (this._h.id !== 0) tree().vlistScrollToEnd(this._h.id, animated)
|
|
196
183
|
}
|
|
197
184
|
|
|
198
185
|
onScroll(callback: (scrollPosition: number) => void): this {
|
|
199
186
|
this.sl.push(callback)
|
|
187
|
+
this._addFlags(TREE_FLAG_SCROLL)
|
|
200
188
|
return this
|
|
201
189
|
}
|
|
202
|
-
// Читается нативкой при маунте (тот же контракт, что у UIScrollable).
|
|
203
|
-
declare _refreshCallback: any
|
|
204
190
|
onRefresh(callback: () => void | Promise<void>): this {
|
|
205
191
|
this._refreshCallback = callback
|
|
192
|
+
this._addFlags(TREE_FLAG_REFRESH)
|
|
206
193
|
return this
|
|
207
194
|
}
|
|
208
195
|
onEndReached(thresholdPx: number, callback: () => void): this {
|
|
209
196
|
this._endThreshold = thresholdPx
|
|
210
197
|
this.erl.push(callback)
|
|
198
|
+
this._addFlags(TREE_FLAG_VLIST_END)
|
|
211
199
|
return this
|
|
212
200
|
}
|
|
213
201
|
onStartReached(thresholdPx: number, callback: () => void): this {
|
|
214
202
|
this._startThreshold = thresholdPx
|
|
215
203
|
this.strl.push(callback)
|
|
204
|
+
this._addFlags(TREE_FLAG_VLIST_START)
|
|
216
205
|
return this
|
|
217
206
|
}
|
|
218
207
|
|
|
219
|
-
/** @internal
|
|
220
|
-
|
|
221
|
-
|
|
208
|
+
/** @internal */
|
|
209
|
+
_emitScroll(position: number): void { for (const cb of this.sl.slice()) cb(position) }
|
|
210
|
+
/** @internal */
|
|
211
|
+
_emitRefresh(): unknown { return this._refreshCallback?.() }
|
|
212
|
+
/** @internal */
|
|
213
|
+
_emitEdge(end: boolean): void { for (const cb of (end ? this.erl : this.strl).slice()) cb() }
|
|
214
|
+
|
|
215
|
+
/** @internal The runtime's window sync (synchronous). Order: unmounts first (the runtime already
|
|
216
|
+
* detached those subtrees — they are plain roots again and go with their elements), then mounts:
|
|
217
|
+
* each rendered subtree is handed to the runtime under its key on this same stack. */
|
|
222
218
|
_syncWindow(unmountKeys: string[], mountKeys: string[]): void {
|
|
223
219
|
for (const k of unmountKeys) {
|
|
220
|
+
const node = this.mounted.get(k)
|
|
224
221
|
this.mounted.delete(k)
|
|
222
|
+
if (node) unpin(node._h.id)
|
|
225
223
|
}
|
|
226
224
|
for (const k of mountKeys) {
|
|
227
225
|
const item = this.items.get(k)
|
|
228
226
|
if (item === undefined) continue
|
|
229
|
-
const node = this.renderItem(item)
|
|
227
|
+
const node: any = this.renderItem(item)
|
|
228
|
+
if (!node || node._h.id === 0) continue
|
|
230
229
|
this.mounted.set(k, node)
|
|
231
|
-
|
|
232
|
-
|
|
230
|
+
pin(node)
|
|
231
|
+
tree().vlistMount(this._h.id, k, node._h.id)
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
}
|
|
@@ -238,4 +237,4 @@ export class VListElement<T> extends Element<"vlist"> implements UIVirtualizedLi
|
|
|
238
237
|
* then feed it via `setData`/`append`/`prepend`. Give it a size (`flexGrow: 1` as a screen body). */
|
|
239
238
|
export function UIVirtualizedList<T>(config: VListConfig<T>): UIVirtualizedList<T> {
|
|
240
239
|
return new VListElement<T>(config)
|
|
241
|
-
}
|
|
240
|
+
}
|
package/src/ui/UIWidget.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TouchStartEvent } from "../runtime/touch"
|
|
2
|
-
import {
|
|
2
|
+
import { Presentable } from "./presentable"
|
|
3
3
|
import { ContainerElement, buildUI, type BaseStyle, type Color, type ContainerStyle, type DrawableStyle, type PaddingStyle, type PositionStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from "./UINode"
|
|
4
|
+
import { TREE_DEST_NONE, TREE_FLAG_BACK, TREE_FLAG_INTERACTIVE, TREE_FLAG_OVERLAY_TAP, pin, tree, unpin } from "./tree"
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
export type UIWidgetStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle & PositionStyle & {
|
|
@@ -23,8 +24,7 @@ export interface UIWidget extends UIContainerBase<UIWidgetStyle, DrawableStyle &
|
|
|
23
24
|
* (= back to a global overlay). Set it while the widget is hidden. The widget is always its own
|
|
24
25
|
* overlay root mounted into the owner's page view — it never becomes a child of the owner, so it
|
|
25
26
|
* stays topmost and its updates never trigger the owner's relayout. Works with a `UIScreen` that
|
|
26
|
-
* is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe.
|
|
27
|
-
* and hides it with the owner but does not yet ride the transition.)
|
|
27
|
+
* is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe.
|
|
28
28
|
*/
|
|
29
29
|
attachTo(owner: Presentable | null): this,
|
|
30
30
|
|
|
@@ -37,13 +37,16 @@ export interface UIWidget extends UIContainerBase<UIWidgetStyle, DrawableStyle &
|
|
|
37
37
|
hide(): void,
|
|
38
38
|
|
|
39
39
|
/** Mounted right now (`show()` ran, `hide()` hasn't). */
|
|
40
|
-
readonly
|
|
40
|
+
readonly isShown: boolean,
|
|
41
41
|
|
|
42
42
|
/** Touch began on the widget; `ev.track(...)` takes over the rest of the gesture. */
|
|
43
43
|
onTouchStart(callback: (ev: TouchStartEvent<UIWidget>) => void): this,
|
|
44
44
|
/** Tap on the overlay layer (requires an `overlayColor`). */
|
|
45
45
|
onOverlayTap(callback: () => void): this,
|
|
46
46
|
/** Hardware/system back while the widget is shown. */
|
|
47
|
+
onBack(callback: () => void): this
|
|
48
|
+
/** @deprecated Renamed `onBack` (2026-09-26). An alias for the projects compiled before the
|
|
49
|
+
* rename; removed with the release that recompiles them. */
|
|
47
50
|
onBackPressed(callback: () => void): this
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -51,6 +54,7 @@ export interface UIWidget extends UIContainerBase<UIWidgetStyle, DrawableStyle &
|
|
|
51
54
|
export class WidgetElement extends ContainerElement<"widget"> {
|
|
52
55
|
scrollable = false as const
|
|
53
56
|
_owner?: Presentable
|
|
57
|
+
private _shown = false
|
|
54
58
|
constructor(type: "widget", style: UIWidgetStyle, children: UINodeChild[] | ChildrenFn) {
|
|
55
59
|
// Widgets are absolutely positioned in device coordinates — in the constructor (not the
|
|
56
60
|
// factory) so subclasses like ModalElement inherit it.
|
|
@@ -65,27 +69,33 @@ export class WidgetElement extends ContainerElement<"widget"> {
|
|
|
65
69
|
// content) — never a child of the owner, so it stays topmost, its updates never relayout the
|
|
66
70
|
// owner, and it doesn't pollute the owner's children. `attachTo(owner)` just tells the host
|
|
67
71
|
// which page view to mount that root into; ownerless widgets are global overlays.
|
|
68
|
-
if (this.
|
|
69
|
-
|
|
72
|
+
if (this._h.id === 0 || this._shown) return
|
|
73
|
+
this._shown = true
|
|
74
|
+
pin(this)
|
|
75
|
+
if (this._owner) {
|
|
76
|
+
const [kind, id] = this._owner._dest()
|
|
77
|
+
tree().showWidget(this._h.id, kind, id)
|
|
70
78
|
} else {
|
|
71
|
-
|
|
72
|
-
_creatorUI.showWidget(this)
|
|
79
|
+
tree().showWidget(this._h.id, TREE_DEST_NONE, 0)
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
hide(): void {
|
|
76
|
-
|
|
83
|
+
if (this._h.id === 0 || !this._shown) return
|
|
84
|
+
this._shown = false
|
|
85
|
+
tree().hideWidget(this._h.id)
|
|
86
|
+
unpin(this._h.id)
|
|
77
87
|
}
|
|
78
|
-
get
|
|
79
|
-
return this.
|
|
88
|
+
get isShown(): boolean {
|
|
89
|
+
return this._shown
|
|
80
90
|
}
|
|
81
91
|
|
|
82
|
-
_interactive = false
|
|
83
92
|
readonly touchStartListeners: any[] = []
|
|
84
93
|
onTouchStart (callback: any): this {
|
|
85
|
-
this._interactive = true
|
|
86
94
|
this.touchStartListeners.push(callback)
|
|
95
|
+
this._addFlags(TREE_FLAG_INTERACTIVE)
|
|
87
96
|
return this
|
|
88
97
|
}
|
|
98
|
+
/** @internal */
|
|
89
99
|
_emitTouchStart(pointerId: number, clientX: number, clientY: number): any {
|
|
90
100
|
const touchEvent = new TouchStartEvent(clientX, clientY, pointerId)
|
|
91
101
|
touchEvent.target = this
|
|
@@ -100,14 +110,26 @@ export class WidgetElement extends ContainerElement<"widget"> {
|
|
|
100
110
|
readonly otl: (() => void)[] = []
|
|
101
111
|
onOverlayTap(callback: () => void): this {
|
|
102
112
|
this.otl.push(callback)
|
|
113
|
+
this._addFlags(TREE_FLAG_OVERLAY_TAP)
|
|
103
114
|
return this
|
|
104
115
|
}
|
|
116
|
+
/** @internal */
|
|
117
|
+
_emitOverlayTap(): void { for (const cb of this.otl.slice()) cb() }
|
|
105
118
|
|
|
106
|
-
_backButtonCallback?: () => void
|
|
107
|
-
|
|
119
|
+
private _backButtonCallback?: () => void
|
|
120
|
+
onBack(callback: any): this {
|
|
108
121
|
this._backButtonCallback = callback
|
|
122
|
+
this._addFlags(TREE_FLAG_BACK)
|
|
109
123
|
return this
|
|
110
124
|
}
|
|
125
|
+
/** @deprecated see the interface */
|
|
126
|
+
onBackPressed(callback: any): this { return this.onBack(callback) }
|
|
127
|
+
/** @internal the runtime's back chain: true = handled. */
|
|
128
|
+
_emitBack(): boolean {
|
|
129
|
+
if (!this._backButtonCallback) return false
|
|
130
|
+
this._backButtonCallback()
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
111
133
|
}
|
|
112
134
|
|
|
113
135
|
|
|
@@ -120,8 +142,6 @@ export const __UIWidget = (children: UINodeChild[] | ChildrenFn): UIWidget => ma
|
|
|
120
142
|
* (`top`/`left`/`bottom`/`right`), then `show()`/`hide()`. */
|
|
121
143
|
export function UIWidget(...children: UIChildArg[]): UIWidget;
|
|
122
144
|
export function UIWidget(children: UINodeChild[] | ChildrenFn): UIWidget;
|
|
123
|
-
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
|
|
124
|
-
export function UIWidget(style: UIWidgetStyle, children?: UINodeChild[] | ChildrenFn): UIWidget;
|
|
125
145
|
export function UIWidget(...args: any[]): UIWidget {
|
|
126
146
|
return buildUI(args, null, makeWidget)
|
|
127
|
-
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// AUTO-GENERATED from engines/ui/properties.mjs — DO NOT EDIT. Regenerate: bun run gen:ui-props
|
|
2
|
+
//
|
|
3
|
+
// The UI style keys that carry a color (engines/ui/properties.mjs). The SDK sends colors to the
|
|
4
|
+
// core as '#rrggbbaa' strings only: the UI core rejects a NUMBER on a color property (a warning,
|
|
5
|
+
// the write dropped) and parses strings with AnyCanvas's CSS parser (the SDK's twin: canvas/gen).
|
|
6
|
+
|
|
7
|
+
/** The keys whose value IS a color — every color property with its aliases: normalize the value
|
|
8
|
+
* to '#rrggbbaa'. Pass-throughs: null / undefined (a reset), any string containing "var(" (the
|
|
9
|
+
* core resolves theme vars), rippleColor's "default" (a core keyword). */
|
|
10
|
+
export const COLOR_KEYS: ReadonlySet<string> = new Set([
|
|
11
|
+
"color",
|
|
12
|
+
"backgroundColor",
|
|
13
|
+
"bgColor",
|
|
14
|
+
"borderColor",
|
|
15
|
+
"borderTopColor",
|
|
16
|
+
"borderRightColor",
|
|
17
|
+
"borderBottomColor",
|
|
18
|
+
"borderLeftColor",
|
|
19
|
+
"placeholderColor",
|
|
20
|
+
"refreshControlColor",
|
|
21
|
+
"tintColor",
|
|
22
|
+
"rippleColor",
|
|
23
|
+
"overlayColor",
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
/** The shorthands that expand into a color property. A color is only ONE of their value forms:
|
|
27
|
+
* never normalize the value whole — "2px solid red", a gradient or an image path go to the core
|
|
28
|
+
* raw (its shorthand parsers read the colors inside with the same grammar), a number on
|
|
29
|
+
* `border*` is a WIDTH; only a number / color array on `background` is a color. */
|
|
30
|
+
export const COLOR_SHORTHAND_KEYS: ReadonlySet<string> = new Set([
|
|
31
|
+
"background",
|
|
32
|
+
"border",
|
|
33
|
+
"borderTop",
|
|
34
|
+
"borderRight",
|
|
35
|
+
"borderBottom",
|
|
36
|
+
"borderLeft",
|
|
37
|
+
])
|
package/src/ui/fonts.ts
CHANGED
|
@@ -8,6 +8,6 @@ type FontOptions = {
|
|
|
8
8
|
* dynamic escape hatch. */
|
|
9
9
|
export async function registerFont (fontFamily: string, url: string, options: FontOptions = {}): Promise<void> {
|
|
10
10
|
return new Promise<void>((res, rej) => {
|
|
11
|
-
|
|
11
|
+
_creatorTree.registerFont(fontFamily, url, options.weight ?? 400, options.style === "italic" ? 2 : 0, res, rej)
|
|
12
12
|
})
|
|
13
|
-
}
|
|
13
|
+
}
|