pixifact 0.3.0 → 0.5.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 +14 -0
- package/dist/compiler/builtinScenes.d.ts +0 -5
- package/dist/compiler/builtinScenes.js +0 -26
- package/dist/compiler/commands/index.js +8 -5
- package/dist/compiler/compileScenes.d.ts +4 -1
- package/dist/compiler/compileScenes.js +40 -11
- package/dist/compiler/index.d.ts +0 -5
- package/dist/compiler/index.js +0 -5
- package/dist/compiler/pixiNodeSchema.d.ts +4 -3
- package/dist/compiler/pixiNodeSchema.js +60 -6
- package/dist/compiler/sceneValidation.d.ts +3 -1
- package/dist/compiler/sceneValidation.js +105 -6
- package/dist/compiler/spec.d.ts +19 -8
- package/dist/compiler/spec.js +3 -1
- package/dist/compiler/templateParser.js +19 -0
- package/dist/compiler/templateSerializer.js +7 -1
- package/dist/compiler/typescriptCompiler.js +118 -51
- package/dist/compiler-node/builtinSceneInterfaces.d.ts +6 -0
- package/dist/compiler-node/builtinSceneInterfaces.js +27 -0
- package/dist/compiler-node/index.d.ts +2 -0
- package/dist/compiler-node/index.js +2 -0
- package/dist/{compiler → compiler-node}/scriptInterfaceExtractor.d.ts +1 -1
- package/dist/{compiler → compiler-node}/scriptInterfaceExtractor.js +157 -25
- package/dist/compiler-node/vite.d.ts +2 -1
- package/dist/compiler-node/vite.js +29 -2
- package/dist/platform/wechat/adapter.d.ts +316 -0
- package/dist/platform/wechat/adapter.js +26 -0
- package/dist/platform/wechat/application.d.ts +32 -0
- package/dist/platform/wechat/application.js +79 -0
- package/dist/platform/wechat/fetch.d.ts +1 -0
- package/dist/platform/wechat/fetch.js +145 -0
- package/dist/platform/wechat/index.d.ts +4 -0
- package/dist/platform/wechat/index.js +3 -0
- package/dist/platform/wechat/input.d.ts +12 -0
- package/dist/platform/wechat/input.js +93 -0
- package/dist/platform/wechat/lifecycle.d.ts +14 -0
- package/dist/platform/wechat/lifecycle.js +42 -0
- package/dist/platform/wechat/runtime.d.ts +49 -0
- package/dist/platform/wechat/runtime.js +189 -0
- package/dist/platform/wechat/subpackage.d.ts +1 -0
- package/dist/platform/wechat/subpackage.js +27 -0
- package/dist/platform/wechat/types.d.ts +105 -0
- package/dist/platform/wechat/types.js +3 -0
- package/dist/project/index.d.ts +23 -0
- package/dist/project/index.js +69 -0
- package/dist/runtime/BitmapLabel.d.ts +9 -0
- package/dist/runtime/BitmapLabel.js +7 -0
- package/dist/runtime/Label.d.ts +9 -0
- package/dist/runtime/Label.js +7 -0
- package/dist/runtime/ScrollContainer.d.ts +2 -0
- package/dist/runtime/ScrollContainer.js +12 -2
- package/dist/runtime/TextBoxControl.d.ts +48 -0
- package/dist/runtime/TextBoxControl.js +162 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/runtimeBehavior.d.ts +3 -0
- package/dist/runtime/runtimeBehavior.js +11 -0
- package/dist/{compiler → scene}/decorators.d.ts +2 -1
- package/dist/{compiler → scene}/decorators.js +12 -7
- package/dist/scene/index.d.ts +6 -0
- package/dist/scene/index.js +6 -0
- package/dist/scene/sceneAssetRuntime.d.ts +11 -0
- package/dist/scene/sceneAssetRuntime.js +43 -0
- package/dist/scene/sceneBindingRuntime.d.ts +10 -0
- package/dist/scene/sceneBindingRuntime.js +124 -0
- package/dist/{compiler → scene}/sceneRuntime.d.ts +7 -0
- package/dist/scene/sceneRuntime.js +85 -0
- package/package.json +11 -1
- package/dist/compiler/sceneRuntime.js +0 -22
- /package/dist/{compiler → scene}/eventRuntime.d.ts +0 -0
- /package/dist/{compiler → scene}/eventRuntime.js +0 -0
- /package/dist/{compiler → scene}/slotRuntime.d.ts +0 -0
- /package/dist/{compiler → scene}/slotRuntime.js +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export interface WechatCanvas {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
isConnected?: boolean;
|
|
5
|
+
style?: Record<string, string>;
|
|
6
|
+
getContext(contextId: string, options?: Record<string, unknown>): unknown;
|
|
7
|
+
getBoundingClientRect?(): {
|
|
8
|
+
bottom: number;
|
|
9
|
+
height: number;
|
|
10
|
+
left: number;
|
|
11
|
+
right: number;
|
|
12
|
+
top: number;
|
|
13
|
+
width: number;
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
};
|
|
17
|
+
requestAnimationFrame?(callback: FrameRequestCallback): number;
|
|
18
|
+
cancelAnimationFrame?(requestId: number): void;
|
|
19
|
+
addEventListener?(type: string, listener: EventListenerOrEventListenerObject, options?: unknown): void;
|
|
20
|
+
removeEventListener?(type: string, listener: EventListenerOrEventListenerObject, options?: unknown): void;
|
|
21
|
+
dispatchEvent?(event: Event): boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface WechatImage {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
complete?: boolean;
|
|
27
|
+
crossOrigin?: string | null;
|
|
28
|
+
src: string;
|
|
29
|
+
onload: (() => void) | null;
|
|
30
|
+
onerror: ((error: unknown) => void) | null;
|
|
31
|
+
}
|
|
32
|
+
export interface WechatTouch {
|
|
33
|
+
clientX?: number;
|
|
34
|
+
clientY?: number;
|
|
35
|
+
force?: number;
|
|
36
|
+
identifier?: number;
|
|
37
|
+
pageX?: number;
|
|
38
|
+
pageY?: number;
|
|
39
|
+
x?: number;
|
|
40
|
+
y?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface WechatTouchEvent {
|
|
43
|
+
changedTouches?: WechatTouch[];
|
|
44
|
+
touches?: WechatTouch[];
|
|
45
|
+
}
|
|
46
|
+
export interface WechatMiniGameApi {
|
|
47
|
+
createCanvas(): WechatCanvas;
|
|
48
|
+
createImage(): WechatImage;
|
|
49
|
+
createOffscreenCanvas?(options: {
|
|
50
|
+
type: '2d' | 'webgl';
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
}): WechatCanvas;
|
|
54
|
+
getDeviceInfo?(): Record<string, unknown>;
|
|
55
|
+
getFileSystemManager(): {
|
|
56
|
+
readFile(options: {
|
|
57
|
+
filePath: string;
|
|
58
|
+
fail(error: {
|
|
59
|
+
errMsg: string;
|
|
60
|
+
}): void;
|
|
61
|
+
success(result: {
|
|
62
|
+
data: ArrayBuffer | string;
|
|
63
|
+
}): void;
|
|
64
|
+
}): void;
|
|
65
|
+
};
|
|
66
|
+
getSystemInfoSync?(): Record<string, unknown>;
|
|
67
|
+
getWindowInfo?(): Record<string, unknown>;
|
|
68
|
+
loadSubpackage(options: {
|
|
69
|
+
name: string;
|
|
70
|
+
fail(error: {
|
|
71
|
+
errMsg: string;
|
|
72
|
+
}): void;
|
|
73
|
+
success(): void;
|
|
74
|
+
}): {
|
|
75
|
+
onProgressUpdate(callback: (progress: {
|
|
76
|
+
progress: number;
|
|
77
|
+
}) => void): void;
|
|
78
|
+
};
|
|
79
|
+
request(options: {
|
|
80
|
+
url: string;
|
|
81
|
+
method: 'GET';
|
|
82
|
+
responseType: 'arraybuffer';
|
|
83
|
+
fail(error: {
|
|
84
|
+
errMsg: string;
|
|
85
|
+
}): void;
|
|
86
|
+
success(result: {
|
|
87
|
+
data: ArrayBuffer | string | Record<string, unknown>;
|
|
88
|
+
header: Record<string, string>;
|
|
89
|
+
statusCode: number;
|
|
90
|
+
}): void;
|
|
91
|
+
}): void;
|
|
92
|
+
onHide(callback: () => void): void;
|
|
93
|
+
offHide?(callback: () => void): void;
|
|
94
|
+
onShow(callback: () => void): void;
|
|
95
|
+
offShow?(callback: () => void): void;
|
|
96
|
+
onTouchStart(callback: (event: WechatTouchEvent) => void): void;
|
|
97
|
+
offTouchStart?(callback: (event: WechatTouchEvent) => void): void;
|
|
98
|
+
onTouchMove(callback: (event: WechatTouchEvent) => void): void;
|
|
99
|
+
offTouchMove?(callback: (event: WechatTouchEvent) => void): void;
|
|
100
|
+
onTouchEnd(callback: (event: WechatTouchEvent) => void): void;
|
|
101
|
+
offTouchEnd?(callback: (event: WechatTouchEvent) => void): void;
|
|
102
|
+
onTouchCancel(callback: (event: WechatTouchEvent) => void): void;
|
|
103
|
+
offTouchCancel?(callback: (event: WechatTouchEvent) => void): void;
|
|
104
|
+
}
|
|
105
|
+
export declare function wechatApi(): WechatMiniGameApi;
|
package/dist/project/index.d.ts
CHANGED
|
@@ -10,12 +10,33 @@ export interface PixifactProjectResolution {
|
|
|
10
10
|
width: number;
|
|
11
11
|
height: number;
|
|
12
12
|
}
|
|
13
|
+
export interface PixifactProjectResourcePack {
|
|
14
|
+
root: string;
|
|
15
|
+
}
|
|
16
|
+
export type PixifactWechatResourcePack = {
|
|
17
|
+
delivery: 'subpackage';
|
|
18
|
+
root: string;
|
|
19
|
+
} | {
|
|
20
|
+
delivery: 'remote';
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
};
|
|
23
|
+
export interface PixifactWechatTargetConfig {
|
|
24
|
+
entry: string;
|
|
25
|
+
configDir: string;
|
|
26
|
+
outDir: string;
|
|
27
|
+
resourcePacks: Record<string, PixifactWechatResourcePack>;
|
|
28
|
+
}
|
|
29
|
+
export interface PixifactProjectTargets {
|
|
30
|
+
wechat?: PixifactWechatTargetConfig;
|
|
31
|
+
}
|
|
13
32
|
export interface PixifactProjectConfig {
|
|
14
33
|
version: 1;
|
|
15
34
|
name: string;
|
|
16
35
|
resolution: PixifactProjectResolution;
|
|
17
36
|
viewport: PixifactProjectViewport;
|
|
18
37
|
scenes: Record<string, string>;
|
|
38
|
+
resourcePacks?: Record<string, PixifactProjectResourcePack>;
|
|
39
|
+
targets?: PixifactProjectTargets;
|
|
19
40
|
run?: PixifactProjectRunConfig;
|
|
20
41
|
}
|
|
21
42
|
export type PixifactProjectViewport = PixifactViewportConfig;
|
|
@@ -24,6 +45,8 @@ export interface PixifactProjectSummary {
|
|
|
24
45
|
resolution: PixifactProjectResolution;
|
|
25
46
|
viewport: PixifactProjectViewport;
|
|
26
47
|
scenes: Record<string, string>;
|
|
48
|
+
resourcePacks?: Record<string, PixifactProjectResourcePack>;
|
|
49
|
+
targets?: PixifactProjectTargets;
|
|
27
50
|
run?: PixifactProjectRunConfig;
|
|
28
51
|
}
|
|
29
52
|
export declare const defaultPixifactProjectResolution: PixifactProjectResolution;
|
package/dist/project/index.js
CHANGED
|
@@ -49,6 +49,13 @@ function normalizeRunCwd(value) {
|
|
|
49
49
|
}
|
|
50
50
|
return normalizeProjectPath(input, 'run.cwd');
|
|
51
51
|
}
|
|
52
|
+
function normalizeProjectChildPath(value, name) {
|
|
53
|
+
const input = normalizeProjectPath(value, name);
|
|
54
|
+
if (input === '.') {
|
|
55
|
+
throw new Error(`${name} must not be projectRoot.`);
|
|
56
|
+
}
|
|
57
|
+
return input;
|
|
58
|
+
}
|
|
52
59
|
function parseScenes(value) {
|
|
53
60
|
const scenes = assertRecord(value, 'scenes');
|
|
54
61
|
return Object.fromEntries(Object.entries(scenes).map(([key, scenePath]) => [
|
|
@@ -97,17 +104,77 @@ function parseRun(value) {
|
|
|
97
104
|
...(run.url === undefined ? {} : { url: assertString(run.url, 'run.url') }),
|
|
98
105
|
};
|
|
99
106
|
}
|
|
107
|
+
function parseResourcePacks(value) {
|
|
108
|
+
if (value === undefined) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const packs = assertRecord(value, 'resourcePacks');
|
|
112
|
+
return Object.fromEntries(Object.entries(packs).map(([name, packValue]) => {
|
|
113
|
+
const pack = assertRecord(packValue, `resourcePacks.${name}`);
|
|
114
|
+
return [assertString(name, 'resource pack name'), {
|
|
115
|
+
root: normalizeProjectChildPath(pack.root, `resourcePacks.${name}.root`),
|
|
116
|
+
}];
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
function parseWechatResourcePacks(value) {
|
|
120
|
+
const packs = assertRecord(value, 'targets.wechat.resourcePacks');
|
|
121
|
+
return Object.fromEntries(Object.entries(packs).map(([name, packValue]) => {
|
|
122
|
+
const pack = assertRecord(packValue, `targets.wechat.resourcePacks.${name}`);
|
|
123
|
+
const delivery = assertString(pack.delivery, `targets.wechat.resourcePacks.${name}.delivery`);
|
|
124
|
+
if (delivery === 'subpackage') {
|
|
125
|
+
return [name, {
|
|
126
|
+
delivery,
|
|
127
|
+
root: normalizeProjectChildPath(pack.root, `targets.wechat.resourcePacks.${name}.root`),
|
|
128
|
+
}];
|
|
129
|
+
}
|
|
130
|
+
if (delivery === 'remote') {
|
|
131
|
+
return [name, {
|
|
132
|
+
delivery,
|
|
133
|
+
baseUrl: assertString(pack.baseUrl, `targets.wechat.resourcePacks.${name}.baseUrl`).replace(/\/+$/, ''),
|
|
134
|
+
}];
|
|
135
|
+
}
|
|
136
|
+
throw new Error(`targets.wechat.resourcePacks.${name}.delivery must be subpackage or remote.`);
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
function parseTargets(value) {
|
|
140
|
+
if (value === undefined) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
const targets = assertRecord(value, 'targets');
|
|
144
|
+
if (targets.wechat === undefined) {
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
const wechat = assertRecord(targets.wechat, 'targets.wechat');
|
|
148
|
+
const outDir = normalizeProjectChildPath(wechat.outDir, 'targets.wechat.outDir');
|
|
149
|
+
return {
|
|
150
|
+
wechat: {
|
|
151
|
+
entry: normalizeProjectPath(wechat.entry, 'targets.wechat.entry'),
|
|
152
|
+
configDir: normalizeProjectPath(wechat.configDir, 'targets.wechat.configDir'),
|
|
153
|
+
outDir,
|
|
154
|
+
resourcePacks: parseWechatResourcePacks(wechat.resourcePacks),
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
100
158
|
export function parsePixifactProjectConfig(value) {
|
|
101
159
|
const config = assertRecord(value, 'pixifact.project.json');
|
|
102
160
|
if (config.version !== 1) {
|
|
103
161
|
throw new Error('pixifact.project.json version must be 1.');
|
|
104
162
|
}
|
|
163
|
+
const resourcePacks = parseResourcePacks(config.resourcePacks);
|
|
164
|
+
const targets = parseTargets(config.targets);
|
|
165
|
+
for (const name of Object.keys(targets?.wechat?.resourcePacks ?? {})) {
|
|
166
|
+
if (!resourcePacks?.[name]) {
|
|
167
|
+
throw new Error(`targets.wechat.resourcePacks.${name} must reference resourcePacks.${name}.`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
105
170
|
return {
|
|
106
171
|
version: 1,
|
|
107
172
|
name: assertString(config.name, 'name'),
|
|
108
173
|
resolution: parseResolution(config.resolution),
|
|
109
174
|
viewport: parseViewport(config.viewport),
|
|
110
175
|
scenes: parseScenes(config.scenes),
|
|
176
|
+
...(resourcePacks === undefined ? {} : { resourcePacks }),
|
|
177
|
+
...(targets === undefined ? {} : { targets }),
|
|
111
178
|
run: parseRun(config.run),
|
|
112
179
|
};
|
|
113
180
|
}
|
|
@@ -117,6 +184,8 @@ export function summarizePixifactProjectConfig(config) {
|
|
|
117
184
|
resolution: config.resolution,
|
|
118
185
|
viewport: config.viewport,
|
|
119
186
|
scenes: config.scenes,
|
|
187
|
+
...(config.resourcePacks === undefined ? {} : { resourcePacks: config.resourcePacks }),
|
|
188
|
+
...(config.targets === undefined ? {} : { targets: config.targets }),
|
|
120
189
|
...(config.run === undefined ? {} : { run: config.run }),
|
|
121
190
|
};
|
|
122
191
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BitmapText } from 'pixi.js';
|
|
2
|
+
import { TextBoxControl, type TextBoxAlign, type TextBoxFontWeight, type TextBoxOptions, type TextBoxOverflow } from './TextBoxControl.js';
|
|
3
|
+
export type BitmapLabelAlign = TextBoxAlign;
|
|
4
|
+
export type BitmapLabelOverflow = TextBoxOverflow;
|
|
5
|
+
export type BitmapLabelFontWeight = TextBoxFontWeight;
|
|
6
|
+
export type BitmapLabelOptions = TextBoxOptions;
|
|
7
|
+
export declare class BitmapLabel extends TextBoxControl<BitmapText> {
|
|
8
|
+
constructor(options?: BitmapLabelOptions);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Text } from 'pixi.js';
|
|
2
|
+
import { TextBoxControl, type TextBoxAlign, type TextBoxFontWeight, type TextBoxOptions, type TextBoxOverflow } from './TextBoxControl.js';
|
|
3
|
+
export type LabelAlign = TextBoxAlign;
|
|
4
|
+
export type LabelOverflow = TextBoxOverflow;
|
|
5
|
+
export type LabelFontWeight = TextBoxFontWeight;
|
|
6
|
+
export type LabelOptions = TextBoxOptions;
|
|
7
|
+
export declare class Label extends TextBoxControl<Text> {
|
|
8
|
+
constructor(options?: LabelOptions);
|
|
9
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Container, type ContainerChild, type DestroyOptions } from 'pixi.js';
|
|
2
2
|
import { Control } from './Control.js';
|
|
3
3
|
import type { GroupOptions } from './Group.js';
|
|
4
|
+
import { runtimeBehavior } from './runtimeBehavior.js';
|
|
4
5
|
export type ScrollDirection = 'vertical' | 'horizontal' | 'both';
|
|
5
6
|
export type ScrollContainerOptions = GroupOptions & {
|
|
6
7
|
direction?: ScrollDirection;
|
|
@@ -11,6 +12,7 @@ export declare class ScrollContainer extends Control {
|
|
|
11
12
|
#private;
|
|
12
13
|
readonly contentLayer: Container<ContainerChild>;
|
|
13
14
|
constructor(options?: ScrollContainerOptions);
|
|
15
|
+
[runtimeBehavior](): void;
|
|
14
16
|
get direction(): ScrollDirection;
|
|
15
17
|
set direction(value: ScrollDirection);
|
|
16
18
|
get scrollX(): number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Container, Graphics, Ticker, } from 'pixi.js';
|
|
2
2
|
import { Control } from './Control.js';
|
|
3
|
+
import { runtimeBehavior } from './runtimeBehavior.js';
|
|
3
4
|
const elasticResistance = 0.5;
|
|
4
5
|
const inertiaFriction = 0.92;
|
|
5
6
|
const springStrength = 0.18;
|
|
@@ -26,19 +27,21 @@ export class ScrollContainer extends Control {
|
|
|
26
27
|
this.#direction = direction ?? this.#direction;
|
|
27
28
|
this.#targetScrollX = scrollX ?? this.#targetScrollX;
|
|
28
29
|
this.#targetScrollY = scrollY ?? this.#targetScrollY;
|
|
29
|
-
this.eventMode = 'static';
|
|
30
30
|
this.contentLayer.mask = this.#mask;
|
|
31
31
|
this.contentLayer.on('childAdded', this.#handleContentChildAdded, this);
|
|
32
32
|
this.contentLayer.on('childRemoved', this.#handleContentChildRemoved, this);
|
|
33
33
|
super.addChild(this.contentLayer);
|
|
34
34
|
super.addChild(this.#mask);
|
|
35
|
+
this.layout();
|
|
36
|
+
}
|
|
37
|
+
[runtimeBehavior]() {
|
|
38
|
+
this.eventMode = 'static';
|
|
35
39
|
this.on('wheel', this.#handleWheel, this);
|
|
36
40
|
this.on('pointerdown', this.#handlePointerDown, this);
|
|
37
41
|
this.on('globalpointermove', this.#handleGlobalPointerMove, this);
|
|
38
42
|
this.on('pointerup', this.#handlePointerUp, this);
|
|
39
43
|
this.on('pointerupoutside', this.#handlePointerUp, this);
|
|
40
44
|
this.on('pointercancel', this.#handlePointerUp, this);
|
|
41
|
-
this.layout();
|
|
42
45
|
}
|
|
43
46
|
get direction() {
|
|
44
47
|
return this.#direction;
|
|
@@ -116,6 +119,13 @@ export class ScrollContainer extends Control {
|
|
|
116
119
|
destroy(options) {
|
|
117
120
|
this.#destroying = true;
|
|
118
121
|
this.#stopMomentum();
|
|
122
|
+
this.#drag = undefined;
|
|
123
|
+
this.off('wheel', this.#handleWheel, this);
|
|
124
|
+
this.off('pointerdown', this.#handlePointerDown, this);
|
|
125
|
+
this.off('globalpointermove', this.#handleGlobalPointerMove, this);
|
|
126
|
+
this.off('pointerup', this.#handlePointerUp, this);
|
|
127
|
+
this.off('pointerupoutside', this.#handlePointerUp, this);
|
|
128
|
+
this.off('pointercancel', this.#handlePointerUp, this);
|
|
119
129
|
this.contentLayer.off('childAdded', this.#handleContentChildAdded, this);
|
|
120
130
|
this.contentLayer.off('childRemoved', this.#handleContentChildRemoved, this);
|
|
121
131
|
for (const child of this.#watchedContent) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BitmapText, Text, type TextOptions } from 'pixi.js';
|
|
2
|
+
import { Control } from './Control.js';
|
|
3
|
+
import type { GroupOptions } from './Group.js';
|
|
4
|
+
export type TextBoxAlign = 'start' | 'center' | 'end';
|
|
5
|
+
export type TextBoxOverflow = 'visible' | 'clip';
|
|
6
|
+
export type TextBoxFontWeight = 400 | 500 | 600 | 700 | '400' | '500' | '600' | '700' | 'bold';
|
|
7
|
+
export type TextBoxOptions = GroupOptions & {
|
|
8
|
+
text?: string;
|
|
9
|
+
fontFamily?: string;
|
|
10
|
+
fontSize?: number;
|
|
11
|
+
fontWeight?: TextBoxFontWeight;
|
|
12
|
+
fill?: number;
|
|
13
|
+
lineHeight?: number;
|
|
14
|
+
letterSpacing?: number;
|
|
15
|
+
wordWrap?: boolean;
|
|
16
|
+
alignX?: TextBoxAlign;
|
|
17
|
+
alignY?: TextBoxAlign;
|
|
18
|
+
overflow?: TextBoxOverflow;
|
|
19
|
+
};
|
|
20
|
+
type TextBoxRenderer = Text | BitmapText;
|
|
21
|
+
export declare class TextBoxControl<T extends TextBoxRenderer> extends Control {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(options: TextBoxOptions, createTextNode: (options: TextOptions) => T);
|
|
24
|
+
get text(): string;
|
|
25
|
+
set text(value: string);
|
|
26
|
+
get fontFamily(): string;
|
|
27
|
+
set fontFamily(value: string);
|
|
28
|
+
get fontSize(): number;
|
|
29
|
+
set fontSize(value: number);
|
|
30
|
+
get fontWeight(): TextBoxFontWeight;
|
|
31
|
+
set fontWeight(value: TextBoxFontWeight);
|
|
32
|
+
get fill(): number;
|
|
33
|
+
set fill(value: number);
|
|
34
|
+
get lineHeight(): number;
|
|
35
|
+
set lineHeight(value: number);
|
|
36
|
+
get letterSpacing(): number;
|
|
37
|
+
set letterSpacing(value: number);
|
|
38
|
+
get wordWrap(): boolean;
|
|
39
|
+
set wordWrap(value: boolean);
|
|
40
|
+
get alignX(): TextBoxAlign;
|
|
41
|
+
set alignX(value: TextBoxAlign);
|
|
42
|
+
get alignY(): TextBoxAlign;
|
|
43
|
+
set alignY(value: TextBoxAlign);
|
|
44
|
+
get overflow(): TextBoxOverflow;
|
|
45
|
+
set overflow(value: TextBoxOverflow);
|
|
46
|
+
layout(): void;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { Graphics, } from 'pixi.js';
|
|
2
|
+
import { Control } from './Control.js';
|
|
3
|
+
export class TextBoxControl extends Control {
|
|
4
|
+
#textNode;
|
|
5
|
+
#clipMask = new Graphics();
|
|
6
|
+
#fontFamily = 'Arial';
|
|
7
|
+
#fontSize = 16;
|
|
8
|
+
#fontWeight = 400;
|
|
9
|
+
#fill = 0x111827;
|
|
10
|
+
#lineHeight = 0;
|
|
11
|
+
#letterSpacing = 0;
|
|
12
|
+
#wordWrap = false;
|
|
13
|
+
#alignX = 'start';
|
|
14
|
+
#alignY = 'start';
|
|
15
|
+
#overflow = 'visible';
|
|
16
|
+
constructor(options, createTextNode) {
|
|
17
|
+
const { text = 'Text', width = 120, height = 28, fontFamily = 'Arial', fontSize = 16, fontWeight = 400, fill = 0x111827, lineHeight = 0, letterSpacing = 0, wordWrap = false, alignX = 'start', alignY = 'start', overflow = 'visible', ...groupOptions } = options;
|
|
18
|
+
super({ ...groupOptions, width, height });
|
|
19
|
+
this.#fontFamily = fontFamily;
|
|
20
|
+
this.#fontSize = fontSize;
|
|
21
|
+
this.#fontWeight = fontWeight;
|
|
22
|
+
this.#fill = fill;
|
|
23
|
+
this.#lineHeight = lineHeight;
|
|
24
|
+
this.#letterSpacing = letterSpacing;
|
|
25
|
+
this.#wordWrap = wordWrap;
|
|
26
|
+
this.#alignX = alignX;
|
|
27
|
+
this.#alignY = alignY;
|
|
28
|
+
this.#overflow = overflow;
|
|
29
|
+
this.#textNode = createTextNode({
|
|
30
|
+
text,
|
|
31
|
+
style: {
|
|
32
|
+
fontFamily,
|
|
33
|
+
fontSize,
|
|
34
|
+
fontWeight: String(fontWeight),
|
|
35
|
+
fill,
|
|
36
|
+
lineHeight,
|
|
37
|
+
letterSpacing,
|
|
38
|
+
wordWrap,
|
|
39
|
+
wordWrapWidth: width,
|
|
40
|
+
align: horizontalTextAlign(alignX),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
super.addChild(this.#textNode, this.#clipMask);
|
|
44
|
+
this.layout();
|
|
45
|
+
}
|
|
46
|
+
get text() {
|
|
47
|
+
return this.#textNode.text;
|
|
48
|
+
}
|
|
49
|
+
set text(value) {
|
|
50
|
+
this.#textNode.text = value;
|
|
51
|
+
this.layout();
|
|
52
|
+
}
|
|
53
|
+
get fontFamily() {
|
|
54
|
+
return this.#fontFamily;
|
|
55
|
+
}
|
|
56
|
+
set fontFamily(value) {
|
|
57
|
+
this.#fontFamily = value;
|
|
58
|
+
this.#textNode.style.fontFamily = value;
|
|
59
|
+
this.layout();
|
|
60
|
+
}
|
|
61
|
+
get fontSize() {
|
|
62
|
+
return this.#fontSize;
|
|
63
|
+
}
|
|
64
|
+
set fontSize(value) {
|
|
65
|
+
this.#fontSize = value;
|
|
66
|
+
this.#textNode.style.fontSize = value;
|
|
67
|
+
this.layout();
|
|
68
|
+
}
|
|
69
|
+
get fontWeight() {
|
|
70
|
+
return this.#fontWeight;
|
|
71
|
+
}
|
|
72
|
+
set fontWeight(value) {
|
|
73
|
+
this.#fontWeight = value;
|
|
74
|
+
this.#textNode.style.fontWeight = String(value);
|
|
75
|
+
this.layout();
|
|
76
|
+
}
|
|
77
|
+
get fill() {
|
|
78
|
+
return this.#fill;
|
|
79
|
+
}
|
|
80
|
+
set fill(value) {
|
|
81
|
+
this.#fill = value;
|
|
82
|
+
this.#textNode.style.fill = value;
|
|
83
|
+
this.layout();
|
|
84
|
+
}
|
|
85
|
+
get lineHeight() {
|
|
86
|
+
return this.#lineHeight;
|
|
87
|
+
}
|
|
88
|
+
set lineHeight(value) {
|
|
89
|
+
this.#lineHeight = value;
|
|
90
|
+
this.#textNode.style.lineHeight = value;
|
|
91
|
+
this.layout();
|
|
92
|
+
}
|
|
93
|
+
get letterSpacing() {
|
|
94
|
+
return this.#letterSpacing;
|
|
95
|
+
}
|
|
96
|
+
set letterSpacing(value) {
|
|
97
|
+
this.#letterSpacing = value;
|
|
98
|
+
this.#textNode.style.letterSpacing = value;
|
|
99
|
+
this.layout();
|
|
100
|
+
}
|
|
101
|
+
get wordWrap() {
|
|
102
|
+
return this.#wordWrap;
|
|
103
|
+
}
|
|
104
|
+
set wordWrap(value) {
|
|
105
|
+
this.#wordWrap = value;
|
|
106
|
+
this.#textNode.style.wordWrap = value;
|
|
107
|
+
this.layout();
|
|
108
|
+
}
|
|
109
|
+
get alignX() {
|
|
110
|
+
return this.#alignX;
|
|
111
|
+
}
|
|
112
|
+
set alignX(value) {
|
|
113
|
+
this.#alignX = value;
|
|
114
|
+
this.#textNode.style.align = horizontalTextAlign(value);
|
|
115
|
+
this.layout();
|
|
116
|
+
}
|
|
117
|
+
get alignY() {
|
|
118
|
+
return this.#alignY;
|
|
119
|
+
}
|
|
120
|
+
set alignY(value) {
|
|
121
|
+
this.#alignY = value;
|
|
122
|
+
this.layout();
|
|
123
|
+
}
|
|
124
|
+
get overflow() {
|
|
125
|
+
return this.#overflow;
|
|
126
|
+
}
|
|
127
|
+
set overflow(value) {
|
|
128
|
+
this.#overflow = value;
|
|
129
|
+
this.layout();
|
|
130
|
+
}
|
|
131
|
+
layout() {
|
|
132
|
+
super.layout();
|
|
133
|
+
if (!this.#textNode) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.#textNode.style.wordWrapWidth = this.width;
|
|
137
|
+
this.#textNode.anchor.set(alignmentFactor(this.#alignX), alignmentFactor(this.#alignY));
|
|
138
|
+
this.#textNode.position.set(this.width * alignmentFactor(this.#alignX), this.height * alignmentFactor(this.#alignY));
|
|
139
|
+
this.#clipMask.clear().rect(0, 0, this.width, this.height).fill(0xffffff);
|
|
140
|
+
const clip = this.#overflow === 'clip';
|
|
141
|
+
this.#clipMask.visible = clip;
|
|
142
|
+
this.#textNode.mask = clip ? this.#clipMask : null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function horizontalTextAlign(align) {
|
|
146
|
+
if (align === 'center') {
|
|
147
|
+
return 'center';
|
|
148
|
+
}
|
|
149
|
+
if (align === 'end') {
|
|
150
|
+
return 'right';
|
|
151
|
+
}
|
|
152
|
+
return 'left';
|
|
153
|
+
}
|
|
154
|
+
function alignmentFactor(align) {
|
|
155
|
+
if (align === 'center') {
|
|
156
|
+
return 0.5;
|
|
157
|
+
}
|
|
158
|
+
if (align === 'end') {
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
package/dist/runtime/index.d.ts
CHANGED
package/dist/runtime/index.js
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const runtimeBehavior = Symbol('pixifact.runtimeBehavior');
|
|
2
|
+
const activatedContainers = new WeakSet();
|
|
3
|
+
export function activateRuntimeTree(root) {
|
|
4
|
+
if (runtimeBehavior in root && !activatedContainers.has(root)) {
|
|
5
|
+
activatedContainers.add(root);
|
|
6
|
+
root[runtimeBehavior]();
|
|
7
|
+
}
|
|
8
|
+
for (const child of root.children) {
|
|
9
|
+
activateRuntimeTree(child);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { SceneClassDecorator, SceneEventDecoratorOptions, SceneMemberDecorator, ScenePartDecoratorOptions, ScenePropDecoratorOptions, SceneSlotDecoratorOptions } from '
|
|
1
|
+
import type { SceneClassDecorator, SceneEventDecoratorOptions, SceneMemberDecorator, ScenePartDecoratorOptions, ScenePropDecoratorOptions, SceneSlotDecoratorOptions, SceneVariants } from '../compiler/spec.js';
|
|
2
2
|
export declare function scene(): SceneClassDecorator;
|
|
3
3
|
export declare function prop(options: ScenePropDecoratorOptions): SceneMemberDecorator;
|
|
4
|
+
export declare function defineVariants<const TVariants extends SceneVariants>(variants: TVariants): TVariants;
|
|
4
5
|
export declare function event(_options?: SceneEventDecoratorOptions): SceneMemberDecorator;
|
|
5
6
|
export declare function slot(options?: SceneSlotDecoratorOptions): SceneMemberDecorator;
|
|
6
7
|
export declare function part(options?: ScenePartDecoratorOptions): SceneMemberDecorator;
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import { activateRuntimeTree } from '../runtime/runtimeBehavior.js';
|
|
1
2
|
import { mountSceneClass } from './sceneRuntime.js';
|
|
3
|
+
import { initializeSceneProps } from './sceneBindingRuntime.js';
|
|
2
4
|
const metadataByConstructor = new WeakMap();
|
|
3
5
|
export function scene() {
|
|
4
6
|
return ((constructor) => {
|
|
5
7
|
const SceneClass = class extends constructor {
|
|
6
8
|
constructor(...args) {
|
|
7
|
-
super(
|
|
9
|
+
super();
|
|
8
10
|
if (new.target !== SceneClass) {
|
|
9
11
|
return;
|
|
10
12
|
}
|
|
11
|
-
const result = mountSceneClass(this, SceneClass);
|
|
12
13
|
const metadata = sceneMetadata(constructor);
|
|
14
|
+
const initialProps = args[0] && typeof args[0] === 'object'
|
|
15
|
+
? args[0]
|
|
16
|
+
: {};
|
|
17
|
+
initializeSceneProps(this, metadata.props, initialProps);
|
|
18
|
+
const result = mountSceneClass(this, SceneClass);
|
|
13
19
|
for (const [property, id] of metadata.parts) {
|
|
14
20
|
Object.defineProperty(this, property, {
|
|
15
21
|
configurable: true,
|
|
@@ -26,11 +32,7 @@ export function scene() {
|
|
|
26
32
|
writable: false,
|
|
27
33
|
});
|
|
28
34
|
}
|
|
29
|
-
|
|
30
|
-
if (propOptions.default !== undefined) {
|
|
31
|
-
this[property] = propOptions.default;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
35
|
+
activateRuntimeTree(this);
|
|
34
36
|
const ready = this.onMounted;
|
|
35
37
|
if (ready) {
|
|
36
38
|
ready.call(this);
|
|
@@ -46,6 +48,9 @@ export function prop(options) {
|
|
|
46
48
|
sceneMetadata(target.constructor).props.set(memberName(propertyKey), options);
|
|
47
49
|
});
|
|
48
50
|
}
|
|
51
|
+
export function defineVariants(variants) {
|
|
52
|
+
return variants;
|
|
53
|
+
}
|
|
49
54
|
export function event(_options = {}) {
|
|
50
55
|
return noopMemberDecorator;
|
|
51
56
|
}
|