@moku-labs/game 0.4.6 → 0.6.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 +16 -1
- package/bin/moku-game-index.mjs +4 -0
- package/dist/assets.d.mts +1 -1
- package/dist/{commands-C83eQ5B9.d.mts → commands-mzE9PX0H.d.mts} +14 -6
- package/dist/control.d.mts +3 -3
- package/dist/control.mjs +1 -1
- package/dist/{define-BKWjWgyQ.d.mts → define-BbgXv4cy.d.mts} +1 -1
- package/dist/hot.d.mts +85 -0
- package/dist/hot.mjs +108 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +624 -71
- package/dist/inspect.d.mts +6 -6
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/project.d.mts +267 -0
- package/dist/project.mjs +2744 -0
- package/dist/{run-D_R0oJ6g.mjs → run-Bcyg32M5.mjs} +40 -11
- package/dist/{runtime-Bhu442L8.d.mts → runtime-HTlmRb81.d.mts} +1 -1
- package/dist/testing.d.mts +5 -5
- package/dist/testing.mjs +19 -4
- package/dist/{types-Dy1xB68L.d.mts → types-BMEn0tSC.d.mts} +39 -4
- package/dist/{types-VErbiEXy.d.mts → types-BaUUcIaN.d.mts} +59 -6
- package/dist/{types-C-4f2jD_.d.mts → types-CXyipKhE.d.mts} +291 -249
- package/dist/{types-DtmFVCHf.d.mts → types-CYYKjvLn.d.mts} +1 -1
- package/dist/{types-w646dMeA.d.mts → types-ClF8say0.d.mts} +7 -3
- package/llms.txt +46 -7
- package/package.json +16 -3
|
@@ -1,243 +1,9 @@
|
|
|
1
|
-
import { $ as Ease, Gt as Events$
|
|
2
|
-
import { D as TextApi, H as InputApi, I as I18nApi, c as UiNode, i as Finding, n as ElementChange, o as JsxState, r as ElementMotion, v as StylesState } from "./types-
|
|
1
|
+
import { $ as Ease, Gt as Events$3, I as AnyComponentValue, K as Owner, Kt as Json, L as ComponentHandle, Nt as TypeTag, P as AnyComponent, Pt as Descriptor, Rt as Api, Ut as Api$5, V as Entity, _n as Events$2, ct as TrackSegment, et as LayerSort, it as NumericFields, k as Api$2, m as Api$3, o as Events$5, rt as MotionHandle, sn as Events$4, st as TrackOptions, t as Api$4, tt as LayerSpec, ut as Api$1, vn as Require, z as ComponentType } from "./types-BMEn0tSC.mjs";
|
|
2
|
+
import { D as TextApi, H as InputApi, I as I18nApi, c as UiNode, i as Finding, n as ElementChange, o as JsxState, r as ElementMotion, v as StylesState } from "./types-BaUUcIaN.mjs";
|
|
3
3
|
import { Log } from "@moku-labs/common/browser";
|
|
4
4
|
import { PluginCtx } from "@moku-labs/core";
|
|
5
5
|
import { Node, Yoga } from "yoga-layout/load";
|
|
6
6
|
|
|
7
|
-
//#region src/plugins/ui/layout/types.d.ts
|
|
8
|
-
/**
|
|
9
|
-
* layout module state. `nodes` is attach minus detach: Yoga 3.2.1 has no instance counter.
|
|
10
|
-
*/
|
|
11
|
-
type LayoutState = {
|
|
12
|
-
yoga: Yoga | undefined;
|
|
13
|
-
byEntity: Map<Entity, Node>;
|
|
14
|
-
nodes: number;
|
|
15
|
-
measured: number;
|
|
16
|
-
solves: number;
|
|
17
|
-
scrolling: Entity | undefined;
|
|
18
|
-
scrollStart: {
|
|
19
|
-
pointerY: number;
|
|
20
|
-
offset: number;
|
|
21
|
-
};
|
|
22
|
-
order: number;
|
|
23
|
-
cleanups: Array<() => void>;
|
|
24
|
-
};
|
|
25
|
-
declare namespace types_d_exports$3 {
|
|
26
|
-
export { Config$3 as Config, Deps$3 as Deps, ElementChange, ElementMotion, Finding, FocusRing, KernelSlice$3 as KernelSlice, State$3 as State, TextInputLook, UiApi, UiCtx, UiNode };
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* The look of the keyboard focus ring: a dashed ring with a solid halo under it, drawn around the
|
|
30
|
-
* focused control. Colours are `0xRRGGBB`, lengths reference units.
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```ts
|
|
34
|
-
* // A dashed ink ring with a cream halo, 9 u outside the control.
|
|
35
|
-
* const ring: FocusRing = {
|
|
36
|
-
* stroke: 0x3a2212, strokeWidth: 4, dash: 10, offset: 9, halo: 0xfff3d6, haloWidth: 12
|
|
37
|
-
* };
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
type FocusRing = {
|
|
41
|
-
/** The colour of the dashed ring. */stroke: number; /** The stroke width of the dashed ring. */
|
|
42
|
-
strokeWidth: number; /** The dash length of the ring, with gaps of half a dash; 0 draws it solid. */
|
|
43
|
-
dash: number; /** How far outside the control's rect the ring runs, on every side. */
|
|
44
|
-
offset: number; /** The colour of the solid halo drawn under the ring. */
|
|
45
|
-
halo: number; /** The stroke width of the halo, centred on the same path as the ring. */
|
|
46
|
-
haloWidth: number;
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* The look of a text field while it is edited: the caret, the selection box and the IME
|
|
50
|
-
* underline. Colours are `0xRRGGBB`, lengths reference units, `keyboardMargin` CSS px. The caret
|
|
51
|
-
* does not blink.
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```ts
|
|
55
|
-
* // A thick ink caret, a pale blue selection, the field 16 px above the keyboard.
|
|
56
|
-
* const look: TextInputLook = {
|
|
57
|
-
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
58
|
-
* composingUnderline: 3, keyboardMargin: 16
|
|
59
|
-
* };
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
type TextInputLook = {
|
|
63
|
-
/** The width of the caret. */caretWidth: number; /** The colour of the caret and of the underline under an IME composing range. */
|
|
64
|
-
caret: number; /** The colour of the selection box. */
|
|
65
|
-
selection: number; /** The alpha of the selection box. */
|
|
66
|
-
selectionAlpha: number; /** The height of the underline under an IME composing range. */
|
|
67
|
-
composingUnderline: number; /** How far above the keyboard the bottom of the edited field is lifted, in CSS px. */
|
|
68
|
-
keyboardMargin: number;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* ui plugin config.
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```ts
|
|
75
|
-
* createApp({ pluginConfigs: { ui: { tapTargetPt: 48, breakpoints: { tall: 2, wide: 1.5 } } } });
|
|
76
|
-
* // A game with a white focus ring on a dark board.
|
|
77
|
-
* createApp({
|
|
78
|
-
* pluginConfigs: {
|
|
79
|
-
* ui: {
|
|
80
|
-
* focusRing: {
|
|
81
|
-
* stroke: 0xffffff, strokeWidth: 4, dash: 10, offset: 9, halo: 0x000000, haloWidth: 12
|
|
82
|
-
* }
|
|
83
|
-
* }
|
|
84
|
-
* }
|
|
85
|
-
* });
|
|
86
|
-
* // A game whose text fields have an ink caret.
|
|
87
|
-
* createApp({
|
|
88
|
-
* pluginConfigs: {
|
|
89
|
-
* ui: {
|
|
90
|
-
* textInput: {
|
|
91
|
-
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
92
|
-
* composingUnderline: 3, keyboardMargin: 16
|
|
93
|
-
* }
|
|
94
|
-
* }
|
|
95
|
-
* }
|
|
96
|
-
* });
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
type Config$3 = {
|
|
100
|
-
/** Smallest tap target `lint()` accepts, in CSS px (points). */tapTargetPt: number; /** `when` flags: `tall` when height / width is at least `tall`, `wide` the other way round. */
|
|
101
|
-
breakpoints: {
|
|
102
|
-
tall: number;
|
|
103
|
-
wide: number;
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* The ring drawn around the control the keyboard focused. Shallow merge: a game that sets
|
|
107
|
-
* `focusRing` gives all six fields.
|
|
108
|
-
*/
|
|
109
|
-
focusRing: FocusRing;
|
|
110
|
-
/**
|
|
111
|
-
* The caret, the selection and the IME underline of a text field. Shallow merge: a game that
|
|
112
|
-
* sets `textInput` gives all six fields.
|
|
113
|
-
*/
|
|
114
|
-
textInput: TextInputLook;
|
|
115
|
-
};
|
|
116
|
-
/**
|
|
117
|
-
* ui plugin state: one branch per module.
|
|
118
|
-
*/
|
|
119
|
-
type State$3 = {
|
|
120
|
-
jsx: JsxState;
|
|
121
|
-
styles: StylesState;
|
|
122
|
-
layout: LayoutState;
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* Resolved dependency APIs. `anim` is not here: its edge is validation only, and its work
|
|
126
|
-
* reaches `ui` through the tween driver behind every `ViewHandle`.
|
|
127
|
-
*/
|
|
128
|
-
type Deps$3 = {
|
|
129
|
-
time: Api;
|
|
130
|
-
flow: Api$1;
|
|
131
|
-
world: Api$2;
|
|
132
|
-
renderer: Api$3;
|
|
133
|
-
input: InputApi;
|
|
134
|
-
i18n: I18nApi;
|
|
135
|
-
text: TextApi;
|
|
136
|
-
};
|
|
137
|
-
/**
|
|
138
|
-
* What the kernel context offers before the deps are attached.
|
|
139
|
-
*
|
|
140
|
-
* `ui` owns no event, so `emit` is the kernel's and never called here.
|
|
141
|
-
*/
|
|
142
|
-
type KernelSlice$3 = PluginCtx<Config$3, State$3> & {
|
|
143
|
-
readonly global: object;
|
|
144
|
-
readonly log: Log.LogApi;
|
|
145
|
-
readonly require: Require;
|
|
146
|
-
};
|
|
147
|
-
/**
|
|
148
|
-
* Domain context shared by the three modules: the kernel slice plus the resolved deps.
|
|
149
|
-
*/
|
|
150
|
-
type UiCtx = KernelSlice$3 & {
|
|
151
|
-
readonly deps: Deps$3;
|
|
152
|
-
};
|
|
153
|
-
/**
|
|
154
|
-
* ui plugin API, `app.ui`. The screen is one more projection, so three members read it the way a
|
|
155
|
-
* test reads the board: a snapshot, a key lookup and a list of findings; the fourth types into a
|
|
156
|
-
* text field.
|
|
157
|
-
*
|
|
158
|
-
* @example
|
|
159
|
-
* ```ts
|
|
160
|
-
* // A headless scenario taps the claim button of the reward popup.
|
|
161
|
-
* app.ui.tree().type; // "row", the root element of the HUD
|
|
162
|
-
* app.input.tap(app.ui.find("claim") ?? 0);
|
|
163
|
-
* app.ui.lint(); // []
|
|
164
|
-
* ```
|
|
165
|
-
*/
|
|
166
|
-
type UiApi = {
|
|
167
|
-
/**
|
|
168
|
-
* The live screen as plain data: every root in layer order, every element in child order, with
|
|
169
|
-
* its rect in root coordinates, its resolved style and its seven state flags. A rect is natural:
|
|
170
|
-
* under a `fit: "contain"` element it is the rect before that scale, and the fitted element
|
|
171
|
-
* adds `fitScale`. A windowed scroll adds `window`, and its content lists the live rows only.
|
|
172
|
-
* Works headless.
|
|
173
|
-
*
|
|
174
|
-
* @returns The root node; several roots come back under one `screen` node.
|
|
175
|
-
* @example
|
|
176
|
-
* ```ts
|
|
177
|
-
* // On an iPhone SE the 970 u board is drawn smaller to fit the slot between the bars.
|
|
178
|
-
* const screen = app.ui.tree();
|
|
179
|
-
* screen.children.map(child => child.key); // ["fitTop", "slot", "fitBottom"]
|
|
180
|
-
* const board = screen.children[1]?.children[0];
|
|
181
|
-
* board?.rect.w; // 970, the natural width
|
|
182
|
-
* board?.fitScale; // 0.805, the 781 u the slot leaves over 970 u
|
|
183
|
-
* ```
|
|
184
|
-
*/
|
|
185
|
-
tree(): UiNode;
|
|
186
|
-
/**
|
|
187
|
-
* The entity of a keyed element, so a test can tap it and `anim` can aim at it. Popup roots
|
|
188
|
-
* come first, then the projection roots in layer order.
|
|
189
|
-
*
|
|
190
|
-
* @param key - The `key` prop of the element.
|
|
191
|
-
* @returns The entity, or `undefined` for an unknown or exiting element.
|
|
192
|
-
* @example
|
|
193
|
-
* ```ts
|
|
194
|
-
* // A headless scenario answers the gate through the button of the popup.
|
|
195
|
-
* app.input.tap(app.ui.find("claim") ?? 0); // true
|
|
196
|
-
* app.ui.find("nothing"); // undefined
|
|
197
|
-
* ```
|
|
198
|
-
*/
|
|
199
|
-
find(key: string): Entity | undefined;
|
|
200
|
-
/**
|
|
201
|
-
* Reads the live screen against the five rules: a tap target under `tapTargetPt` at the size
|
|
202
|
-
* it is drawn (a `fit: "contain"` on it or above it shrinks it), a text that does not fit its
|
|
203
|
-
* box in some registered locale, an absolute element with no `reason`, a clipping element
|
|
204
|
-
* (`scroll`, `overflow: "hidden"`) whose style names a nine-slice it never draws, and a root
|
|
205
|
-
* element whose style sets a `zIndex` it ignores. Never throws; empty when nothing is mounted.
|
|
206
|
-
*
|
|
207
|
-
* @returns One finding per rule and element.
|
|
208
|
-
* @example
|
|
209
|
-
* ```ts
|
|
210
|
-
* // A game test keeps the board honest on an iPhone SE: a 140 u cell in the 0.8 slot.
|
|
211
|
-
* app.ui.lint(); // [{ rule: "tap-target", key: "cell", detail: "39 x 39 pt" }]
|
|
212
|
-
* // A list styled with a nine-slice: the clip keeps it from drawing.
|
|
213
|
-
* app.ui.lint(); // [{ rule: "nine-slice-clipped", key: "orders", detail: "scroll" }]
|
|
214
|
-
* // A screen root that asks to be drawn over the others: the layer decides that.
|
|
215
|
-
* app.ui.lint(); // [{ rule: "z-index-on-root", key: "board", detail: "zIndex 2" }]
|
|
216
|
-
* ```
|
|
217
|
-
*/
|
|
218
|
-
lint(): readonly Finding[];
|
|
219
|
-
/**
|
|
220
|
-
* Types into a text field the way a player does, for a headless test or an agent: the field
|
|
221
|
-
* becomes the one being edited, `value` cut to its `maxLength` is written into it, and the
|
|
222
|
-
* local field it names is written, so the component re-renders on the next frame. Nothing
|
|
223
|
-
* reaches the gate: Enter submits.
|
|
224
|
-
*
|
|
225
|
-
* @param key - The `key` prop of the `input` element.
|
|
226
|
-
* @param value - The text to type.
|
|
227
|
-
* @returns True when the field took the text; false with one warning when no live `input` has
|
|
228
|
-
* the key.
|
|
229
|
-
* @example
|
|
230
|
-
* ```ts
|
|
231
|
-
* // A headless test renames the player through the Rename popup.
|
|
232
|
-
* app.ui.fill("nameField", "Alex"); // true
|
|
233
|
-
* app.time.step(16);
|
|
234
|
-
* app.input.pressKey("Enter"); // true: the gate took { intent: "save", payload: { name: "Alex" } }
|
|
235
|
-
* app.ui.fill("nothing", "Alex"); // false, with the warning "ui:fill-without-input"
|
|
236
|
-
* ```
|
|
237
|
-
*/
|
|
238
|
-
fill(key: string, value: string): boolean;
|
|
239
|
-
};
|
|
240
|
-
//#endregion
|
|
241
7
|
//#region src/plugins/anim/tween/types.d.ts
|
|
242
8
|
/**
|
|
243
9
|
* One running track: the numeric fields of one component of one entity moving from the values
|
|
@@ -865,8 +631,8 @@ type RunningTimeline = {
|
|
|
865
631
|
readonly resolve: () => void;
|
|
866
632
|
ended: boolean;
|
|
867
633
|
};
|
|
868
|
-
declare namespace types_d_exports$
|
|
869
|
-
export { AnimApi, AnimCtx, AnimationDefinition, AnimationSpec, AnyAnimationDefinition, BuildTools, Config$
|
|
634
|
+
declare namespace types_d_exports$3 {
|
|
635
|
+
export { AnimApi, AnimCtx, AnimationDefinition, AnimationSpec, AnyAnimationDefinition, BuildTools, Config$3 as Config, Cursor, Deps$3 as Deps, ErasedFields, Events$1 as Events, ExternalPlayer, FrameLoop, FramesValue, FxStep, HapticDescriptor, HapticKind, KernelSlice$3 as KernelSlice, MarkListener, MotionKeyframe, PlayDescriptor, PlayHandle, Pose, RunningTimeline, SfxDescriptor, SlotRecord, SlotTags, SlotValue, SlotValues, State$3 as State, Step, StepMotion, Target, TimelineRuntime, Track };
|
|
870
636
|
}
|
|
871
637
|
/**
|
|
872
638
|
* What a step and a slot are pointed at: the projection key of a live view or of an element a
|
|
@@ -1118,7 +884,7 @@ type FrameLoop = {
|
|
|
1118
884
|
* createApp({ plugins: [...screen], pluginConfigs: { anim: { maxTracks: 500, reducedMotion: true } } });
|
|
1119
885
|
* ```
|
|
1120
886
|
*/
|
|
1121
|
-
type Config$
|
|
887
|
+
type Config$3 = {
|
|
1122
888
|
/** Dev guard: one warning each time the running track count rises past this number. */maxTracks: number;
|
|
1123
889
|
/**
|
|
1124
890
|
* Start value of reduced motion: every track but a loop takes 0 ms and every loop stands on
|
|
@@ -1130,7 +896,7 @@ type Config$2 = {
|
|
|
1130
896
|
* anim plugin state: the one track table, the field bookkeeping of the retarget policy and the
|
|
1131
897
|
* offsets accumulator, the running timelines and the animation registry.
|
|
1132
898
|
*/
|
|
1133
|
-
type State$
|
|
899
|
+
type State$3 = {
|
|
1134
900
|
/** The one track table. Insertion order is advance order. */tracks: Map<number, Track>; /** Ids of tracks and timelines. */
|
|
1135
901
|
nextId: number; /** `"<entity>:<component>:<field>"` to the id of the absolute track that drives the field. */
|
|
1136
902
|
owner: Map<string, number>; /** Per field key, the delta each additive track contributes. */
|
|
@@ -1271,6 +1037,24 @@ type AnimApi = {
|
|
|
1271
1037
|
* ```
|
|
1272
1038
|
*/
|
|
1273
1039
|
onMark(fn: MarkListener): () => void;
|
|
1040
|
+
/**
|
|
1041
|
+
* Swaps a registered animation for a new definition of the same id. The dev hot swap of `ui`
|
|
1042
|
+
* calls it when a saved `animations.ts` exports one. The next `play` effect of a node builds
|
|
1043
|
+
* the new definition; a timeline that runs now keeps the tree it was built with.
|
|
1044
|
+
*
|
|
1045
|
+
* @param definition - The new definition; its id names the animation it replaces.
|
|
1046
|
+
* @throws {Error} When no feature registered an animation with that id.
|
|
1047
|
+
* @example
|
|
1048
|
+
* ```ts
|
|
1049
|
+
* // The ui hot swap: a save of `board/animations.ts` brings a bigger merge burst.
|
|
1050
|
+
* const mergeBurst = defineAnimation("board.mergeBurst", { slots: { cell: type<Target>() },
|
|
1051
|
+
* build: ({ cell }) => tween(cell, Transform, { scale: 1.4 }, { ms: 300 }) });
|
|
1052
|
+
* ctx.require(animPlugin).replace(mergeBurst);
|
|
1053
|
+
* // A node then runs fx(play(mergeBurst, { cell: { projection: "board.items", key: "i3" } })):
|
|
1054
|
+
* // the play effect builds the new tree, and item i3 grows to scale 1.4 in 300 ms.
|
|
1055
|
+
* ```
|
|
1056
|
+
*/
|
|
1057
|
+
replace(definition: AnyAnimationDefinition): void;
|
|
1274
1058
|
};
|
|
1275
1059
|
/**
|
|
1276
1060
|
* Resolved dependency APIs. `renderer` is not among them: `anim` writes its `Sprite` and reads
|
|
@@ -1278,7 +1062,7 @@ type AnimApi = {
|
|
|
1278
1062
|
* of `at` with the pure `rootPoseOf` of `renderer/sync/pose.ts`, and turns the target of a
|
|
1279
1063
|
* `tween` in `space: "root"` local with the pure `localPoseOf` of the same module.
|
|
1280
1064
|
*/
|
|
1281
|
-
type Deps$
|
|
1065
|
+
type Deps$3 = {
|
|
1282
1066
|
time: Api;
|
|
1283
1067
|
flow: Api$1;
|
|
1284
1068
|
world: Api$2;
|
|
@@ -1290,7 +1074,7 @@ type Deps$2 = {
|
|
|
1290
1074
|
* row 8), so the own events reach the context the kernel hands the factories and `emit` is the
|
|
1291
1075
|
* kernel's own, anim-typed one. No member of the context is cast.
|
|
1292
1076
|
*/
|
|
1293
|
-
type KernelSlice$
|
|
1077
|
+
type KernelSlice$3 = PluginCtx<Config$3, State$3, Events$1> & {
|
|
1294
1078
|
readonly global: object;
|
|
1295
1079
|
readonly log: Log.LogApi;
|
|
1296
1080
|
readonly require: Require;
|
|
@@ -1298,9 +1082,244 @@ type KernelSlice$2 = PluginCtx<Config$2, State$2, Events$1> & {
|
|
|
1298
1082
|
/**
|
|
1299
1083
|
* Domain context of the anim plugin: the kernel slice and the three resolved dependencies.
|
|
1300
1084
|
*/
|
|
1301
|
-
type AnimCtx = KernelSlice$
|
|
1085
|
+
type AnimCtx = KernelSlice$3 & {
|
|
1086
|
+
readonly deps: Deps$3;
|
|
1087
|
+
};
|
|
1088
|
+
//#endregion
|
|
1089
|
+
//#region src/plugins/ui/layout/types.d.ts
|
|
1090
|
+
/**
|
|
1091
|
+
* layout module state. `nodes` is attach minus detach: Yoga 3.2.1 has no instance counter.
|
|
1092
|
+
*/
|
|
1093
|
+
type LayoutState = {
|
|
1094
|
+
yoga: Yoga | undefined;
|
|
1095
|
+
byEntity: Map<Entity, Node>;
|
|
1096
|
+
nodes: number;
|
|
1097
|
+
measured: number;
|
|
1098
|
+
solves: number;
|
|
1099
|
+
scrolling: Entity | undefined;
|
|
1100
|
+
scrollStart: {
|
|
1101
|
+
pointerY: number;
|
|
1102
|
+
offset: number;
|
|
1103
|
+
};
|
|
1104
|
+
order: number;
|
|
1105
|
+
cleanups: Array<() => void>;
|
|
1106
|
+
};
|
|
1107
|
+
declare namespace types_d_exports$2 {
|
|
1108
|
+
export { Config$2 as Config, Deps$2 as Deps, ElementChange, ElementMotion, Finding, FocusRing, KernelSlice$2 as KernelSlice, State$2 as State, TextInputLook, UiApi, UiCtx, UiNode };
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* The look of the keyboard focus ring: a dashed ring with a solid halo under it, drawn around the
|
|
1112
|
+
* focused control. Colours are `0xRRGGBB`, lengths reference units.
|
|
1113
|
+
*
|
|
1114
|
+
* @example
|
|
1115
|
+
* ```ts
|
|
1116
|
+
* // A dashed ink ring with a cream halo, 9 u outside the control.
|
|
1117
|
+
* const ring: FocusRing = {
|
|
1118
|
+
* stroke: 0x3a2212, strokeWidth: 4, dash: 10, offset: 9, halo: 0xfff3d6, haloWidth: 12
|
|
1119
|
+
* };
|
|
1120
|
+
* ```
|
|
1121
|
+
*/
|
|
1122
|
+
type FocusRing = {
|
|
1123
|
+
/** The colour of the dashed ring. */stroke: number; /** The stroke width of the dashed ring. */
|
|
1124
|
+
strokeWidth: number; /** The dash length of the ring, with gaps of half a dash; 0 draws it solid. */
|
|
1125
|
+
dash: number; /** How far outside the control's rect the ring runs, on every side. */
|
|
1126
|
+
offset: number; /** The colour of the solid halo drawn under the ring. */
|
|
1127
|
+
halo: number; /** The stroke width of the halo, centred on the same path as the ring. */
|
|
1128
|
+
haloWidth: number;
|
|
1129
|
+
};
|
|
1130
|
+
/**
|
|
1131
|
+
* The look of a text field while it is edited: the caret, the selection box and the IME
|
|
1132
|
+
* underline. Colours are `0xRRGGBB`, lengths reference units, `keyboardMargin` CSS px. The caret
|
|
1133
|
+
* does not blink.
|
|
1134
|
+
*
|
|
1135
|
+
* @example
|
|
1136
|
+
* ```ts
|
|
1137
|
+
* // A thick ink caret, a pale blue selection, the field 16 px above the keyboard.
|
|
1138
|
+
* const look: TextInputLook = {
|
|
1139
|
+
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
1140
|
+
* composingUnderline: 3, keyboardMargin: 16
|
|
1141
|
+
* };
|
|
1142
|
+
* ```
|
|
1143
|
+
*/
|
|
1144
|
+
type TextInputLook = {
|
|
1145
|
+
/** The width of the caret. */caretWidth: number; /** The colour of the caret and of the underline under an IME composing range. */
|
|
1146
|
+
caret: number; /** The colour of the selection box. */
|
|
1147
|
+
selection: number; /** The alpha of the selection box. */
|
|
1148
|
+
selectionAlpha: number; /** The height of the underline under an IME composing range. */
|
|
1149
|
+
composingUnderline: number; /** How far above the keyboard the bottom of the edited field is lifted, in CSS px. */
|
|
1150
|
+
keyboardMargin: number;
|
|
1151
|
+
};
|
|
1152
|
+
/**
|
|
1153
|
+
* ui plugin config.
|
|
1154
|
+
*
|
|
1155
|
+
* @example
|
|
1156
|
+
* ```ts
|
|
1157
|
+
* createApp({ pluginConfigs: { ui: { tapTargetPt: 48, breakpoints: { tall: 2, wide: 1.5 } } } });
|
|
1158
|
+
* // A game with a white focus ring on a dark board.
|
|
1159
|
+
* createApp({
|
|
1160
|
+
* pluginConfigs: {
|
|
1161
|
+
* ui: {
|
|
1162
|
+
* focusRing: {
|
|
1163
|
+
* stroke: 0xffffff, strokeWidth: 4, dash: 10, offset: 9, halo: 0x000000, haloWidth: 12
|
|
1164
|
+
* }
|
|
1165
|
+
* }
|
|
1166
|
+
* }
|
|
1167
|
+
* });
|
|
1168
|
+
* // A game whose text fields have an ink caret.
|
|
1169
|
+
* createApp({
|
|
1170
|
+
* pluginConfigs: {
|
|
1171
|
+
* ui: {
|
|
1172
|
+
* textInput: {
|
|
1173
|
+
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
1174
|
+
* composingUnderline: 3, keyboardMargin: 16
|
|
1175
|
+
* }
|
|
1176
|
+
* }
|
|
1177
|
+
* }
|
|
1178
|
+
* });
|
|
1179
|
+
* ```
|
|
1180
|
+
*/
|
|
1181
|
+
type Config$2 = {
|
|
1182
|
+
/** Smallest tap target `lint()` accepts, in CSS px (points). */tapTargetPt: number; /** `when` flags: `tall` when height / width is at least `tall`, `wide` the other way round. */
|
|
1183
|
+
breakpoints: {
|
|
1184
|
+
tall: number;
|
|
1185
|
+
wide: number;
|
|
1186
|
+
};
|
|
1187
|
+
/**
|
|
1188
|
+
* The ring drawn around the control the keyboard focused. Shallow merge: a game that sets
|
|
1189
|
+
* `focusRing` gives all six fields.
|
|
1190
|
+
*/
|
|
1191
|
+
focusRing: FocusRing;
|
|
1192
|
+
/**
|
|
1193
|
+
* The caret, the selection and the IME underline of a text field. Shallow merge: a game that
|
|
1194
|
+
* sets `textInput` gives all six fields.
|
|
1195
|
+
*/
|
|
1196
|
+
textInput: TextInputLook;
|
|
1197
|
+
};
|
|
1198
|
+
/**
|
|
1199
|
+
* ui plugin state: one branch per module.
|
|
1200
|
+
*/
|
|
1201
|
+
type State$2 = {
|
|
1202
|
+
jsx: JsxState;
|
|
1203
|
+
styles: StylesState;
|
|
1204
|
+
layout: LayoutState;
|
|
1205
|
+
};
|
|
1206
|
+
/**
|
|
1207
|
+
* Resolved dependency APIs. `anim` is here for the dev hot swap, which replaces animations; the
|
|
1208
|
+
* motions of `ui` reach `anim` through the tween driver behind every `ViewHandle`.
|
|
1209
|
+
*/
|
|
1210
|
+
type Deps$2 = {
|
|
1211
|
+
anim: AnimApi;
|
|
1212
|
+
time: Api;
|
|
1213
|
+
flow: Api$1;
|
|
1214
|
+
world: Api$2;
|
|
1215
|
+
renderer: Api$3;
|
|
1216
|
+
input: InputApi;
|
|
1217
|
+
i18n: I18nApi;
|
|
1218
|
+
text: TextApi;
|
|
1219
|
+
};
|
|
1220
|
+
/**
|
|
1221
|
+
* What the kernel context offers before the deps are attached.
|
|
1222
|
+
*
|
|
1223
|
+
* `ui` owns no event of its own; `emit` sends the global `ui:hot-swap` of the dev hot swap.
|
|
1224
|
+
*/
|
|
1225
|
+
type KernelSlice$2 = PluginCtx<Config$2, State$2, Events$2> & {
|
|
1226
|
+
readonly global: object;
|
|
1227
|
+
readonly log: Log.LogApi;
|
|
1228
|
+
readonly require: Require;
|
|
1229
|
+
};
|
|
1230
|
+
/**
|
|
1231
|
+
* Domain context shared by the three modules: the kernel slice plus the resolved deps.
|
|
1232
|
+
*/
|
|
1233
|
+
type UiCtx = KernelSlice$2 & {
|
|
1302
1234
|
readonly deps: Deps$2;
|
|
1303
1235
|
};
|
|
1236
|
+
/**
|
|
1237
|
+
* ui plugin API, `app.ui`. The screen is one more projection, so three members read it the way a
|
|
1238
|
+
* test reads the board: a snapshot, a key lookup and a list of findings; the fourth types into a
|
|
1239
|
+
* text field.
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
* ```ts
|
|
1243
|
+
* // A headless scenario taps the claim button of the reward popup.
|
|
1244
|
+
* app.ui.tree().type; // "row", the root element of the HUD
|
|
1245
|
+
* app.input.tap(app.ui.find("claim") ?? 0);
|
|
1246
|
+
* app.ui.lint(); // []
|
|
1247
|
+
* ```
|
|
1248
|
+
*/
|
|
1249
|
+
type UiApi = {
|
|
1250
|
+
/**
|
|
1251
|
+
* The live screen as plain data: every root in layer order, every element in child order, with
|
|
1252
|
+
* its rect in root coordinates, its resolved style and its seven state flags. A rect is natural:
|
|
1253
|
+
* under a `fit: "contain"` element it is the rect before that scale, and the fitted element
|
|
1254
|
+
* adds `fitScale`. A windowed scroll adds `window`, and its content lists the live rows only.
|
|
1255
|
+
* Works headless.
|
|
1256
|
+
*
|
|
1257
|
+
* @returns The root node; several roots come back under one `screen` node.
|
|
1258
|
+
* @example
|
|
1259
|
+
* ```ts
|
|
1260
|
+
* // On an iPhone SE the 970 u board is drawn smaller to fit the slot between the bars.
|
|
1261
|
+
* const screen = app.ui.tree();
|
|
1262
|
+
* screen.children.map(child => child.key); // ["fitTop", "slot", "fitBottom"]
|
|
1263
|
+
* const board = screen.children[1]?.children[0];
|
|
1264
|
+
* board?.rect.w; // 970, the natural width
|
|
1265
|
+
* board?.fitScale; // 0.805, the 781 u the slot leaves over 970 u
|
|
1266
|
+
* ```
|
|
1267
|
+
*/
|
|
1268
|
+
tree(): UiNode;
|
|
1269
|
+
/**
|
|
1270
|
+
* The entity of a keyed element, so a test can tap it and `anim` can aim at it. Popup roots
|
|
1271
|
+
* come first, then the projection roots in layer order.
|
|
1272
|
+
*
|
|
1273
|
+
* @param key - The `key` prop of the element.
|
|
1274
|
+
* @returns The entity, or `undefined` for an unknown or exiting element.
|
|
1275
|
+
* @example
|
|
1276
|
+
* ```ts
|
|
1277
|
+
* // A headless scenario answers the gate through the button of the popup.
|
|
1278
|
+
* app.input.tap(app.ui.find("claim") ?? 0); // true
|
|
1279
|
+
* app.ui.find("nothing"); // undefined
|
|
1280
|
+
* ```
|
|
1281
|
+
*/
|
|
1282
|
+
find(key: string): Entity | undefined;
|
|
1283
|
+
/**
|
|
1284
|
+
* Reads the live screen against the five rules: a tap target under `tapTargetPt` at the size
|
|
1285
|
+
* it is drawn (a `fit: "contain"` on it or above it shrinks it), a text that does not fit its
|
|
1286
|
+
* box in some registered locale, an absolute element with no `reason`, a clipping element
|
|
1287
|
+
* (`scroll`, `overflow: "hidden"`) whose style names a nine-slice it never draws, and a root
|
|
1288
|
+
* element whose style sets a `zIndex` it ignores. Never throws; empty when nothing is mounted.
|
|
1289
|
+
*
|
|
1290
|
+
* @returns One finding per rule and element.
|
|
1291
|
+
* @example
|
|
1292
|
+
* ```ts
|
|
1293
|
+
* // A game test keeps the board honest on an iPhone SE: a 140 u cell in the 0.8 slot.
|
|
1294
|
+
* app.ui.lint(); // [{ rule: "tap-target", key: "cell", detail: "39 x 39 pt" }]
|
|
1295
|
+
* // A list styled with a nine-slice: the clip keeps it from drawing.
|
|
1296
|
+
* app.ui.lint(); // [{ rule: "nine-slice-clipped", key: "orders", detail: "scroll" }]
|
|
1297
|
+
* // A screen root that asks to be drawn over the others: the layer decides that.
|
|
1298
|
+
* app.ui.lint(); // [{ rule: "z-index-on-root", key: "board", detail: "zIndex 2" }]
|
|
1299
|
+
* ```
|
|
1300
|
+
*/
|
|
1301
|
+
lint(): readonly Finding[];
|
|
1302
|
+
/**
|
|
1303
|
+
* Types into a text field the way a player does, for a headless test or an agent: the field
|
|
1304
|
+
* becomes the one being edited, `value` cut to its `maxLength` is written into it, and the
|
|
1305
|
+
* local field it names is written, so the component re-renders on the next frame. Nothing
|
|
1306
|
+
* reaches the gate: Enter submits.
|
|
1307
|
+
*
|
|
1308
|
+
* @param key - The `key` prop of the `input` element.
|
|
1309
|
+
* @param value - The text to type.
|
|
1310
|
+
* @returns True when the field took the text; false with one warning when no live `input` has
|
|
1311
|
+
* the key.
|
|
1312
|
+
* @example
|
|
1313
|
+
* ```ts
|
|
1314
|
+
* // A headless test renames the player through the Rename popup.
|
|
1315
|
+
* app.ui.fill("nameField", "Alex"); // true
|
|
1316
|
+
* app.time.step(16);
|
|
1317
|
+
* app.input.pressKey("Enter"); // true: the gate took { intent: "save", payload: { name: "Alex" } }
|
|
1318
|
+
* app.ui.fill("nothing", "Alex"); // false, with the warning "ui:fill-without-input"
|
|
1319
|
+
* ```
|
|
1320
|
+
*/
|
|
1321
|
+
fill(key: string, value: string): boolean;
|
|
1322
|
+
};
|
|
1304
1323
|
declare namespace types_d_exports$1 {
|
|
1305
1324
|
export { AnySceneProjection, CheckedProjections, Config$1 as Config, DefineScene, Deps$1 as Deps, Events, KernelSlice$1 as KernelSlice, LayerMap, RunContext, SceneDefinition, SceneLayer, SceneOwner, SceneProjection, SceneSpec, ScenesApi, ScenesCtx, SortRule, State$1 as State, UiLayer };
|
|
1306
1325
|
}
|
|
@@ -1473,7 +1492,12 @@ type Config$1 = Record<string, never>;
|
|
|
1473
1492
|
*/
|
|
1474
1493
|
type State$1 = {
|
|
1475
1494
|
/** Scene id to its declaration, filled in `onStart` from `flow.features`. */scenes: Map<string, SceneDefinition>; /** Id of the scene that is mounted now. */
|
|
1476
|
-
current: string | undefined;
|
|
1495
|
+
current: string | undefined;
|
|
1496
|
+
/**
|
|
1497
|
+
* The scene the next rest node without its own `scene` mounts: the one a transit node named in
|
|
1498
|
+
* fast mode, or the one the restore door expected with `expect`. A rest node clears it; an over
|
|
1499
|
+
* rest node takes it only while nothing is mounted.
|
|
1500
|
+
*/
|
|
1477
1501
|
pending: string | undefined;
|
|
1478
1502
|
owner: SceneOwner; /** The remover of the `onEnter` callback: set in `onStart`, run in `onStop`. */
|
|
1479
1503
|
teardown: (() => void) | undefined;
|
|
@@ -1499,7 +1523,7 @@ type Events = {
|
|
|
1499
1523
|
};
|
|
1500
1524
|
/**
|
|
1501
1525
|
* scenes plugin API, `app.scenes`. A scene is switched by the graph, never by a call, so the
|
|
1502
|
-
* plugin answers one question and takes
|
|
1526
|
+
* plugin answers one question and takes one order, for the restore door.
|
|
1503
1527
|
*
|
|
1504
1528
|
* @example
|
|
1505
1529
|
* ```ts
|
|
@@ -1520,6 +1544,24 @@ type ScenesApi = {
|
|
|
1520
1544
|
* ```
|
|
1521
1545
|
*/
|
|
1522
1546
|
current(): string | undefined;
|
|
1547
|
+
/**
|
|
1548
|
+
* Names the scene the next rest node without its own `scene` mounts. The restore door calls it
|
|
1549
|
+
* with the scene of a bookmark, so a bookmark at a popup comes back with the scene under it.
|
|
1550
|
+
* An over rest node takes the expected scene only while nothing is mounted; it never switches a
|
|
1551
|
+
* mounted one.
|
|
1552
|
+
*
|
|
1553
|
+
* @param id - Id of a scene a feature declared.
|
|
1554
|
+
* @throws {Error} For an id no feature declared, also before `onStart` filled the registry.
|
|
1555
|
+
* @example
|
|
1556
|
+
* ```ts
|
|
1557
|
+
* // A fresh page restores a bookmark taken at the Settings popup over Home.
|
|
1558
|
+
* app.scenes.expect("home");
|
|
1559
|
+
* await app.flow.restore(bookmark);
|
|
1560
|
+
* await app.flow.walk([]); // the scene stage runs after restore resolves
|
|
1561
|
+
* app.scenes.current(); // "home"
|
|
1562
|
+
* ```
|
|
1563
|
+
*/
|
|
1564
|
+
expect(id: string): void;
|
|
1523
1565
|
};
|
|
1524
1566
|
/**
|
|
1525
1567
|
* Resolved dependency APIs.
|
|
@@ -1925,7 +1967,7 @@ type AudioCtx = KernelSlice & {
|
|
|
1925
1967
|
/**
|
|
1926
1968
|
* Payload of the `model:committed` hook: the source of every volume a game sets.
|
|
1927
1969
|
*/
|
|
1928
|
-
type ModelCommitted = Events$
|
|
1970
|
+
type ModelCommitted = Events$3["model:committed"];
|
|
1929
1971
|
/**
|
|
1930
1972
|
* Payload of the `scenes:changed` hook: `music` is the track the next scene declared.
|
|
1931
1973
|
*/
|
|
@@ -1933,11 +1975,11 @@ type SceneChanged = Events["scenes:changed"];
|
|
|
1933
1975
|
/**
|
|
1934
1976
|
* Payload of the `lifecycle:changed` hook: the pause that holds every bus at zero.
|
|
1935
1977
|
*/
|
|
1936
|
-
type LifecycleChanged = Events$
|
|
1978
|
+
type LifecycleChanged = Events$4["lifecycle:changed"];
|
|
1937
1979
|
/**
|
|
1938
1980
|
* Payload of the `assets:bundle-unloaded` hook: `keys` names every decoded sound that is gone.
|
|
1939
1981
|
*/
|
|
1940
|
-
type BundleUnloaded = Events$
|
|
1982
|
+
type BundleUnloaded = Events$5["assets:bundle-unloaded"];
|
|
1941
1983
|
/**
|
|
1942
1984
|
* What one play of a sound asks for: the key and the bus the sound goes to.
|
|
1943
1985
|
*/
|
|
@@ -1953,4 +1995,4 @@ type MusicRequest = {
|
|
|
1953
1995
|
fadeMs: number;
|
|
1954
1996
|
};
|
|
1955
1997
|
//#endregion
|
|
1956
|
-
export {
|
|
1998
|
+
export { HAPTIC_KINDS as A, sfx as B, MotionKeyframe as C, HapticKind as D, types_d_exports$3 as E, mark as F, use as G, spawned as H, parallel as I, wait as K, play as L, external as M, frames as N, SfxDescriptor as O, haptic as P, sequence as R, FramesValue as S, Target as T, stagger as U, spawn as V, tween as W, State$2 as _, SoundEntry as a, AnimApi as b, AnySceneProjection as c, SceneDefinition as d, SceneSpec as f, Config$2 as g, types_d_exports$1 as h, MusicOptions as i, defineAnimation as j, Step as k, DefineScene as l, State$1 as m, Config as n, State as o, ScenesApi as p, MusicDescriptor as r, types_d_exports as s, AudioApi as t, LayerMap as u, UiApi as v, State$3 as w, Config$3 as x, types_d_exports$2 as y, set as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as JournalEntry, Kt as Json, Lt as Answer, Rt as Api, in as RngState, jt as RouteStep, kt as FlowState, tn as Snapshot, ut as Api$1 } from "./types-
|
|
1
|
+
import { At as JournalEntry, Kt as Json, Lt as Answer, Rt as Api, in as RngState, jt as RouteStep, kt as FlowState, tn as Snapshot, ut as Api$1 } from "./types-BMEn0tSC.mjs";
|
|
2
2
|
import { Log } from "@moku-labs/common/browser";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/flow/headless.d.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as Point, E as FilterSlot, L as ComponentHandle, V as Entity, _ as PixiModule, g as PixiFilter, k as Api$1, m as Api$2, o as Events, t as Api$3, ut as Api, v as PixiSprite, vn as Require, y as PixiTexture, z as ComponentType } from "./types-
|
|
2
|
-
import {
|
|
1
|
+
import { D as Point, E as FilterSlot, L as ComponentHandle, V as Entity, _ as PixiModule, _n as Events$1, g as PixiFilter, k as Api$1, m as Api$2, o as Events, t as Api$3, ut as Api, v as PixiSprite, vn as Require, y as PixiTexture, z as ComponentType } from "./types-BMEn0tSC.mjs";
|
|
2
|
+
import { b as AnimApi } from "./types-CXyipKhE.mjs";
|
|
3
3
|
import { Log } from "@moku-labs/common/browser";
|
|
4
4
|
import { PluginCtx } from "@moku-labs/core";
|
|
5
5
|
|
|
@@ -523,7 +523,7 @@ type EmitterInstance = {
|
|
|
523
523
|
readonly particleClass: PixiModule["Particle"];
|
|
524
524
|
};
|
|
525
525
|
declare namespace types_d_exports {
|
|
526
|
-
export { AlphaValue, BlurValue, BundleUnloaded, ColorMatrixValue, Config, CoreKind, Curve, Deps, DisplacementValue, EffectsApi, EffectsCtx, EffectsStats, EmitterConfig, EmitterDefinition, EmitterValue, FilterComponent, FilterDefinition, FilterSpec, FilterValueOf, GlowValue, KernelSlice, NoiseValue, OutlineValue, Range, ResolvedEmitterConfig, Shape, State, UniformDeclaration, UniformSpec, UniformValue };
|
|
526
|
+
export { AlphaValue, BlurValue, BundleUnloaded, ColorMatrixValue, Config, CoreKind, Curve, Deps, DisplacementValue, EffectsApi, EffectsCtx, EffectsStats, EmitterConfig, EmitterDefinition, EmitterValue, FilterComponent, FilterDefinition, FilterSpec, FilterValueOf, GlowValue, HotSwap, KernelSlice, NoiseValue, OutlineValue, Range, ResolvedEmitterConfig, Shape, State, UniformDeclaration, UniformSpec, UniformValue };
|
|
527
527
|
}
|
|
528
528
|
/**
|
|
529
529
|
* effects plugin config. `maxParticles` here is the global warning line; the `maxParticles` of an
|
|
@@ -644,5 +644,9 @@ type EffectsCtx = KernelSlice & {
|
|
|
644
644
|
* Payload of the `assets:bundle-unloaded` hook: `keys` names every texture that is gone.
|
|
645
645
|
*/
|
|
646
646
|
type BundleUnloaded = Events["assets:bundle-unloaded"];
|
|
647
|
+
/**
|
|
648
|
+
* Payload of the global `ui:hot-swap` hook: the saved file and its new exports.
|
|
649
|
+
*/
|
|
650
|
+
type HotSwap = Events$1["ui:hot-swap"];
|
|
647
651
|
//#endregion
|
|
648
652
|
export { NoiseValue as _, types_d_exports as a, EmitterValue as c, ColorMatrixValue as d, DisplacementValue as f, GlowValue as g, FilterValueOf as h, State as i, AlphaValue as l, FilterSpec as m, EffectsApi as n, EmitterConfig as o, FilterComponent as p, EffectsStats as r, EmitterDefinition as s, Config as t, BlurValue as u, OutlineValue as v, UniformDeclaration as y };
|