@moku-labs/game 0.9.0 → 0.11.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 +81 -22
- package/bin/moku-game.mjs +4 -0
- package/dist/app/page.d.mts +44 -0
- package/dist/app/page.mjs +379 -0
- package/dist/app/system.d.mts +144 -0
- package/dist/app/system.mjs +329 -0
- package/dist/app.d.mts +37 -0
- package/dist/app.mjs +235 -0
- package/dist/assets-BHwTLVta.mjs +7391 -0
- package/dist/assets.d.mts +1 -1
- package/dist/assets.mjs +1 -7390
- package/dist/cli.d.mts +70 -0
- package/dist/cli.mjs +1685 -0
- package/dist/{commands-DuwCxK5t.d.mts → commands-C4QlqijJ.d.mts} +5 -5
- package/dist/config-CdARrrhU.mjs +81 -0
- package/dist/control.d.mts +11 -10
- package/dist/control.mjs +3 -3
- package/dist/{define-B6pHpdBi.d.mts → define-CCc0ozKe.d.mts} +2 -2
- package/dist/{dev-wKLgOw7c.mjs → dev-Cc50Dk7H.mjs} +1 -1
- package/dist/drafts-BawpSaVp.mjs +156 -0
- package/dist/fake-MpzwZhIZ.mjs +87 -0
- package/dist/{headless-SCQXJxQf.d.mts → headless-G4nuZ-xz.d.mts} +1 -1
- package/dist/hot.d.mts +4 -6
- package/dist/hot.mjs +8 -9
- package/dist/{index-BO9kZzY3.d.mts → index-8TiJQjQA.d.mts} +30 -17
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +1 -1
- package/dist/inspect-la_KkjCS.mjs +1 -0
- package/dist/inspect.d.mts +7 -7
- package/dist/inspect.mjs +3 -2
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/lint.mjs +10 -6
- package/dist/memory-CWlqhS7l.mjs +136 -0
- package/dist/memory-DwDhfFWK.d.mts +50 -0
- package/dist/project.mjs +3 -3
- package/dist/{run-CofJEdYx.mjs → run-wYty_Lwo.mjs} +2 -2
- package/dist/{runtime-CdNJ0UBm.d.mts → runtime-DOBYM6g4.d.mts} +1 -1
- package/dist/{input-z_35Jwfn.mjs → session-DgukhR_7.mjs} +20 -20
- package/dist/{sources-DNnzyCYf.mjs → sources-Duzj6lhV.mjs} +2 -2
- package/dist/{src-536arXjV.mjs → src-BSbtHZWk.mjs} +35 -300
- package/dist/testing.d.mts +4 -50
- package/dist/testing.mjs +3 -87
- package/dist/{types-VZVWwqCg.d.mts → types-BM4shh8K.d.mts} +259 -259
- package/dist/{types-xXfyk56Q.d.mts → types-BUwDHKXm.d.mts} +1377 -1377
- package/dist/types-Ca_z_4tQ.d.mts +586 -0
- package/dist/{types-CQueODzo.d.mts → types-CefgYzFt.d.mts} +2 -2
- package/dist/{types-DUMoYPYe.d.mts → types-DAdwEJMp.d.mts} +2 -2
- package/dist/{types-B0v5VVa3.d.mts → types-ZQLYXo5X.d.mts} +304 -304
- package/dist/visual.d.mts +6 -6
- package/dist/visual.mjs +5 -5
- package/llms.txt +120 -43
- package/package.json +30 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { A as Api$2, B as ComponentType, F as AnyComponent, H as Entity, It as TypeTag, L as AnyComponentValue, Lt as Descriptor, R as ComponentHandle, Sn as Require, Xt as Json, Yt as Events$2, at as NumericFields, ct as TrackOptions, dn as Events$3, dt as Api$1, et as Ease, h as Api$5, hn as Api, it as MotionHandle, lt as TrackSegment, nt as LayerSpec, q as Owner, qt as Api$4, s as Events$4, t as Api$3, tt as LayerSort, xn as Events$5 } from "./types-ZQLYXo5X.mjs";
|
|
2
|
+
import { A as InputApi, c as UiNode, i as Finding, n as ElementChange, o as JsxState, q as I18nApi, r as ElementMotion, tt as StylesState, x as TextApi } from "./types-BUwDHKXm.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";
|
|
@@ -1123,243 +1123,8 @@ type KernelSlice$3 = PluginCtx<Config$3, State$3, Events$1> & {
|
|
|
1123
1123
|
type AnimCtx = KernelSlice$3 & {
|
|
1124
1124
|
readonly deps: Deps$3;
|
|
1125
1125
|
};
|
|
1126
|
-
//#endregion
|
|
1127
|
-
//#region src/plugins/ui/layout/types.d.ts
|
|
1128
|
-
/**
|
|
1129
|
-
* layout module state. `nodes` is attach minus detach: Yoga 3.2.1 has no instance counter.
|
|
1130
|
-
*/
|
|
1131
|
-
type LayoutState = {
|
|
1132
|
-
yoga: Yoga | undefined;
|
|
1133
|
-
byEntity: Map<Entity, Node>;
|
|
1134
|
-
nodes: number;
|
|
1135
|
-
measured: number;
|
|
1136
|
-
solves: number;
|
|
1137
|
-
scrolling: Entity | undefined;
|
|
1138
|
-
scrollStart: {
|
|
1139
|
-
pointerY: number;
|
|
1140
|
-
offset: number;
|
|
1141
|
-
};
|
|
1142
|
-
order: number;
|
|
1143
|
-
cleanups: Array<() => void>;
|
|
1144
|
-
};
|
|
1145
1126
|
declare namespace types_d_exports$2 {
|
|
1146
|
-
export { Config$2 as Config, Deps$2 as Deps,
|
|
1147
|
-
}
|
|
1148
|
-
/**
|
|
1149
|
-
* The look of the keyboard focus ring: a dashed ring with a solid halo under it, drawn around the
|
|
1150
|
-
* focused control. Colours are `0xRRGGBB`, lengths reference units.
|
|
1151
|
-
*
|
|
1152
|
-
* @example
|
|
1153
|
-
* ```ts
|
|
1154
|
-
* // A dashed ink ring with a cream halo, 9 u outside the control.
|
|
1155
|
-
* const ring: FocusRing = {
|
|
1156
|
-
* stroke: 0x3a2212, strokeWidth: 4, dash: 10, offset: 9, halo: 0xfff3d6, haloWidth: 12
|
|
1157
|
-
* };
|
|
1158
|
-
* ```
|
|
1159
|
-
*/
|
|
1160
|
-
type FocusRing = {
|
|
1161
|
-
/** The colour of the dashed ring. */stroke: number; /** The stroke width of the dashed ring. */
|
|
1162
|
-
strokeWidth: number; /** The dash length of the ring, with gaps of half a dash; 0 draws it solid. */
|
|
1163
|
-
dash: number; /** How far outside the control's rect the ring runs, on every side. */
|
|
1164
|
-
offset: number; /** The colour of the solid halo drawn under the ring. */
|
|
1165
|
-
halo: number; /** The stroke width of the halo, centred on the same path as the ring. */
|
|
1166
|
-
haloWidth: number;
|
|
1167
|
-
};
|
|
1168
|
-
/**
|
|
1169
|
-
* The look of a text field while it is edited: the caret, the selection box and the IME
|
|
1170
|
-
* underline. Colours are `0xRRGGBB`, lengths reference units, `keyboardMargin` CSS px. The caret
|
|
1171
|
-
* does not blink.
|
|
1172
|
-
*
|
|
1173
|
-
* @example
|
|
1174
|
-
* ```ts
|
|
1175
|
-
* // A thick ink caret, a pale blue selection, the field 16 px above the keyboard.
|
|
1176
|
-
* const look: TextInputLook = {
|
|
1177
|
-
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
1178
|
-
* composingUnderline: 3, keyboardMargin: 16
|
|
1179
|
-
* };
|
|
1180
|
-
* ```
|
|
1181
|
-
*/
|
|
1182
|
-
type TextInputLook = {
|
|
1183
|
-
/** The width of the caret. */caretWidth: number; /** The colour of the caret and of the underline under an IME composing range. */
|
|
1184
|
-
caret: number; /** The colour of the selection box. */
|
|
1185
|
-
selection: number; /** The alpha of the selection box. */
|
|
1186
|
-
selectionAlpha: number; /** The height of the underline under an IME composing range. */
|
|
1187
|
-
composingUnderline: number; /** How far above the keyboard the bottom of the edited field is lifted, in CSS px. */
|
|
1188
|
-
keyboardMargin: number;
|
|
1189
|
-
};
|
|
1190
|
-
/**
|
|
1191
|
-
* ui plugin config.
|
|
1192
|
-
*
|
|
1193
|
-
* @example
|
|
1194
|
-
* ```ts
|
|
1195
|
-
* createApp({ pluginConfigs: { ui: { tapTargetPt: 48, breakpoints: { tall: 2, wide: 1.5 } } } });
|
|
1196
|
-
* // A game with a white focus ring on a dark board.
|
|
1197
|
-
* createApp({
|
|
1198
|
-
* pluginConfigs: {
|
|
1199
|
-
* ui: {
|
|
1200
|
-
* focusRing: {
|
|
1201
|
-
* stroke: 0xffffff, strokeWidth: 4, dash: 10, offset: 9, halo: 0x000000, haloWidth: 12
|
|
1202
|
-
* }
|
|
1203
|
-
* }
|
|
1204
|
-
* }
|
|
1205
|
-
* });
|
|
1206
|
-
* // A game whose text fields have an ink caret.
|
|
1207
|
-
* createApp({
|
|
1208
|
-
* pluginConfigs: {
|
|
1209
|
-
* ui: {
|
|
1210
|
-
* textInput: {
|
|
1211
|
-
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
1212
|
-
* composingUnderline: 3, keyboardMargin: 16
|
|
1213
|
-
* }
|
|
1214
|
-
* }
|
|
1215
|
-
* }
|
|
1216
|
-
* });
|
|
1217
|
-
* ```
|
|
1218
|
-
*/
|
|
1219
|
-
type Config$2 = {
|
|
1220
|
-
/** 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. */
|
|
1221
|
-
breakpoints: {
|
|
1222
|
-
tall: number;
|
|
1223
|
-
wide: number;
|
|
1224
|
-
};
|
|
1225
|
-
/**
|
|
1226
|
-
* The ring drawn around the control the keyboard focused. Shallow merge: a game that sets
|
|
1227
|
-
* `focusRing` gives all six fields.
|
|
1228
|
-
*/
|
|
1229
|
-
focusRing: FocusRing;
|
|
1230
|
-
/**
|
|
1231
|
-
* The caret, the selection and the IME underline of a text field. Shallow merge: a game that
|
|
1232
|
-
* sets `textInput` gives all six fields.
|
|
1233
|
-
*/
|
|
1234
|
-
textInput: TextInputLook;
|
|
1235
|
-
};
|
|
1236
|
-
/**
|
|
1237
|
-
* ui plugin state: one branch per module.
|
|
1238
|
-
*/
|
|
1239
|
-
type State$2 = {
|
|
1240
|
-
jsx: JsxState;
|
|
1241
|
-
styles: StylesState;
|
|
1242
|
-
layout: LayoutState;
|
|
1243
|
-
};
|
|
1244
|
-
/**
|
|
1245
|
-
* Resolved dependency APIs. `anim` is here for the dev hot swap, which replaces animations; the
|
|
1246
|
-
* motions of `ui` reach `anim` through the tween driver behind every `ViewHandle`.
|
|
1247
|
-
*/
|
|
1248
|
-
type Deps$2 = {
|
|
1249
|
-
anim: AnimApi;
|
|
1250
|
-
time: Api;
|
|
1251
|
-
flow: Api$1;
|
|
1252
|
-
world: Api$2;
|
|
1253
|
-
renderer: Api$3;
|
|
1254
|
-
input: InputApi;
|
|
1255
|
-
i18n: I18nApi;
|
|
1256
|
-
text: TextApi;
|
|
1257
|
-
};
|
|
1258
|
-
/**
|
|
1259
|
-
* What the kernel context offers before the deps are attached.
|
|
1260
|
-
*
|
|
1261
|
-
* `ui` owns no event of its own; `emit` sends the global `ui:hot-swap` of the dev hot swap.
|
|
1262
|
-
*/
|
|
1263
|
-
type KernelSlice$2 = PluginCtx<Config$2, State$2, Events$2> & {
|
|
1264
|
-
readonly global: object;
|
|
1265
|
-
readonly log: Log.LogApi;
|
|
1266
|
-
readonly require: Require;
|
|
1267
|
-
};
|
|
1268
|
-
/**
|
|
1269
|
-
* Domain context shared by the three modules: the kernel slice plus the resolved deps.
|
|
1270
|
-
*/
|
|
1271
|
-
type UiCtx = KernelSlice$2 & {
|
|
1272
|
-
readonly deps: Deps$2;
|
|
1273
|
-
};
|
|
1274
|
-
/**
|
|
1275
|
-
* ui plugin API, `app.ui`. The screen is one more projection, so three members read it the way a
|
|
1276
|
-
* test reads the board: a snapshot, a key lookup and a list of findings; the fourth types into a
|
|
1277
|
-
* text field.
|
|
1278
|
-
*
|
|
1279
|
-
* @example
|
|
1280
|
-
* ```ts
|
|
1281
|
-
* // A headless scenario taps the claim button of the reward popup.
|
|
1282
|
-
* app.ui.tree().type; // "row", the root element of the HUD
|
|
1283
|
-
* app.input.tap(app.ui.find("claim") ?? 0);
|
|
1284
|
-
* app.ui.lint(); // []
|
|
1285
|
-
* ```
|
|
1286
|
-
*/
|
|
1287
|
-
type UiApi = {
|
|
1288
|
-
/**
|
|
1289
|
-
* The live screen as plain data: every root in layer order, every element in child order, with
|
|
1290
|
-
* its rect in root coordinates, its resolved style and its seven state flags. A rect is natural:
|
|
1291
|
-
* under a `fit: "contain"` element it is the rect before that scale, and the fitted element
|
|
1292
|
-
* adds `fitScale`. A windowed scroll adds `window`, and its content lists the live rows only.
|
|
1293
|
-
* Works headless.
|
|
1294
|
-
*
|
|
1295
|
-
* @returns The root node; several roots come back under one `screen` node.
|
|
1296
|
-
* @example
|
|
1297
|
-
* ```ts
|
|
1298
|
-
* // On an iPhone SE the 970 u board is drawn smaller to fit the slot between the bars.
|
|
1299
|
-
* const screen = app.ui.tree();
|
|
1300
|
-
* screen.children.map(child => child.key); // ["fitTop", "slot", "fitBottom"]
|
|
1301
|
-
* const board = screen.children[1]?.children[0];
|
|
1302
|
-
* board?.rect.w; // 970, the natural width
|
|
1303
|
-
* board?.fitScale; // 0.805, the 781 u the slot leaves over 970 u
|
|
1304
|
-
* ```
|
|
1305
|
-
*/
|
|
1306
|
-
tree(): UiNode;
|
|
1307
|
-
/**
|
|
1308
|
-
* The entity of a keyed element, so a test can tap it and `anim` can aim at it. Popup roots
|
|
1309
|
-
* come first, then the projection roots in layer order.
|
|
1310
|
-
*
|
|
1311
|
-
* @param key - The `key` prop of the element.
|
|
1312
|
-
* @returns The entity, or `undefined` for an unknown or exiting element.
|
|
1313
|
-
* @example
|
|
1314
|
-
* ```ts
|
|
1315
|
-
* // A headless scenario answers the gate through the button of the popup.
|
|
1316
|
-
* app.input.tap(app.ui.find("claim") ?? 0); // true
|
|
1317
|
-
* app.ui.find("nothing"); // undefined
|
|
1318
|
-
* ```
|
|
1319
|
-
*/
|
|
1320
|
-
find(key: string): Entity | undefined;
|
|
1321
|
-
/**
|
|
1322
|
-
* Reads the live screen against the five rules: a tap target under `tapTargetPt` at the size
|
|
1323
|
-
* it is drawn (a `fit: "contain"` on it or above it shrinks it), a text that does not fit its
|
|
1324
|
-
* box in some registered locale, an absolute element with no `reason`, a clipping element
|
|
1325
|
-
* (`scroll`, `overflow: "hidden"`) whose style names a nine-slice it never draws, and a root
|
|
1326
|
-
* element whose style sets a `zIndex` it ignores. Never throws; empty when nothing is mounted.
|
|
1327
|
-
*
|
|
1328
|
-
* @returns One finding per rule and element.
|
|
1329
|
-
* @example
|
|
1330
|
-
* ```ts
|
|
1331
|
-
* // A game test keeps the board honest on an iPhone SE: a 140 u cell in the 0.8 slot.
|
|
1332
|
-
* app.ui.lint(); // [{ rule: "tap-target", key: "cell", detail: "39 x 39 pt" }]
|
|
1333
|
-
* // A list styled with a nine-slice: the clip keeps it from drawing.
|
|
1334
|
-
* app.ui.lint(); // [{ rule: "nine-slice-clipped", key: "orders", detail: "scroll" }]
|
|
1335
|
-
* // A screen root that asks to be drawn over the others: the layer decides that.
|
|
1336
|
-
* app.ui.lint(); // [{ rule: "z-index-on-root", key: "board", detail: "zIndex 2" }]
|
|
1337
|
-
* ```
|
|
1338
|
-
*/
|
|
1339
|
-
lint(): readonly Finding[];
|
|
1340
|
-
/**
|
|
1341
|
-
* Types into a text field the way a player does, for a headless test or an agent: the field
|
|
1342
|
-
* becomes the one being edited, `value` cut to its `maxLength` is written into it, and the
|
|
1343
|
-
* local field it names is written, so the component re-renders on the next frame. Nothing
|
|
1344
|
-
* reaches the gate: Enter submits.
|
|
1345
|
-
*
|
|
1346
|
-
* @param key - The `key` prop of the `input` element.
|
|
1347
|
-
* @param value - The text to type.
|
|
1348
|
-
* @returns True when the field took the text; false with one warning when no live `input` has
|
|
1349
|
-
* the key.
|
|
1350
|
-
* @example
|
|
1351
|
-
* ```ts
|
|
1352
|
-
* // A headless test renames the player through the Rename popup.
|
|
1353
|
-
* app.ui.fill("nameField", "Alex"); // true
|
|
1354
|
-
* app.time.step(16);
|
|
1355
|
-
* app.input.pressKey("Enter"); // true: the gate took { intent: "save", payload: { name: "Alex" } }
|
|
1356
|
-
* app.ui.fill("nothing", "Alex"); // false, with the warning "ui:fill-without-input"
|
|
1357
|
-
* ```
|
|
1358
|
-
*/
|
|
1359
|
-
fill(key: string, value: string): boolean;
|
|
1360
|
-
};
|
|
1361
|
-
declare namespace types_d_exports$1 {
|
|
1362
|
-
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 };
|
|
1127
|
+
export { AnySceneProjection, CheckedProjections, Config$2 as Config, DefineScene, Deps$2 as Deps, Events, KernelSlice$2 as KernelSlice, LayerMap, RunContext, SceneDefinition, SceneLayer, SceneOwner, SceneProjection, SceneSpec, ScenesApi, ScenesCtx, SortRule, State$2 as State, UiLayer };
|
|
1363
1128
|
}
|
|
1364
1129
|
/**
|
|
1365
1130
|
* How a layer orders what is drawn in it. The scene's name for the rule `world` stores.
|
|
@@ -1524,11 +1289,11 @@ type SceneOwner = Owner & {
|
|
|
1524
1289
|
* const config: Config = {};
|
|
1525
1290
|
* ```
|
|
1526
1291
|
*/
|
|
1527
|
-
type Config$
|
|
1292
|
+
type Config$2 = Record<string, never>;
|
|
1528
1293
|
/**
|
|
1529
1294
|
* scenes plugin state.
|
|
1530
1295
|
*/
|
|
1531
|
-
type State$
|
|
1296
|
+
type State$2 = {
|
|
1532
1297
|
/** Scene id to its declaration, filled in `onStart` from `flow.features`. */scenes: Map<string, SceneDefinition>; /** Id of the scene that is mounted now. */
|
|
1533
1298
|
current: string | undefined;
|
|
1534
1299
|
/**
|
|
@@ -1604,10 +1369,10 @@ type ScenesApi = {
|
|
|
1604
1369
|
/**
|
|
1605
1370
|
* Resolved dependency APIs.
|
|
1606
1371
|
*/
|
|
1607
|
-
type Deps$
|
|
1372
|
+
type Deps$2 = {
|
|
1608
1373
|
flow: Api$1;
|
|
1609
1374
|
world: Api$2;
|
|
1610
|
-
assets: Api$
|
|
1375
|
+
assets: Api$3;
|
|
1611
1376
|
time: Api;
|
|
1612
1377
|
};
|
|
1613
1378
|
/**
|
|
@@ -1617,7 +1382,7 @@ type Deps$1 = {
|
|
|
1617
1382
|
* row 8), so the own event reaches the context the kernel hands the factories and `emit` is the
|
|
1618
1383
|
* kernel's own, scenes-typed one. No member of the context is cast.
|
|
1619
1384
|
*/
|
|
1620
|
-
type KernelSlice$
|
|
1385
|
+
type KernelSlice$2 = PluginCtx<Config$2, State$2, Events> & {
|
|
1621
1386
|
readonly global: object;
|
|
1622
1387
|
readonly log: Log.LogApi;
|
|
1623
1388
|
readonly require: Require;
|
|
@@ -1625,8 +1390,8 @@ type KernelSlice$1 = PluginCtx<Config$1, State$1, Events> & {
|
|
|
1625
1390
|
/**
|
|
1626
1391
|
* Domain context shared by the files of the plugin.
|
|
1627
1392
|
*/
|
|
1628
|
-
type ScenesCtx = KernelSlice$
|
|
1629
|
-
readonly deps: Deps$
|
|
1393
|
+
type ScenesCtx = KernelSlice$2 & {
|
|
1394
|
+
readonly deps: Deps$2;
|
|
1630
1395
|
};
|
|
1631
1396
|
/**
|
|
1632
1397
|
* The mode and the abort signal `flow.onEnter` hands every callback.
|
|
@@ -1640,8 +1405,8 @@ type RunContext = {
|
|
|
1640
1405
|
mode: "live" | "fast";
|
|
1641
1406
|
signal: AbortSignal;
|
|
1642
1407
|
};
|
|
1643
|
-
declare namespace types_d_exports {
|
|
1644
|
-
export { AudioApi, AudioContextLike, AudioCtx, AudioSessionLike, AudioSessionType, BundleUnloaded, Bus, BusState, Config, Deps, KernelSlice, LifecycleChanged, ModelCommitted, MusicDescriptor, MusicMode, MusicOptions, MusicRequest, MusicSwitch, MusicTrack, RetiringTrack, SceneChanged, SfxRequest, SoundEntry, State, StreamTrack, Volumes };
|
|
1408
|
+
declare namespace types_d_exports$1 {
|
|
1409
|
+
export { AudioApi, AudioContextLike, AudioCtx, AudioSessionLike, AudioSessionType, BundleUnloaded, Bus, BusState, Config$1 as Config, Deps$1 as Deps, KernelSlice$1 as KernelSlice, LifecycleChanged, ModelCommitted, MusicDescriptor, MusicMode, MusicOptions, MusicRequest, MusicSwitch, MusicTrack, RetiringTrack, SceneChanged, SfxRequest, SoundEntry, State$1 as State, StreamTrack, Volumes };
|
|
1645
1410
|
}
|
|
1646
1411
|
/**
|
|
1647
1412
|
* The three volume buses. `master` carries the whole game, `music` the scene track, `sfx` every
|
|
@@ -1779,7 +1544,7 @@ type RetiringTrack = {
|
|
|
1779
1544
|
* });
|
|
1780
1545
|
* ```
|
|
1781
1546
|
*/
|
|
1782
|
-
type Config = {
|
|
1547
|
+
type Config$1 = {
|
|
1783
1548
|
/** Start gain of each bus, 0..1. Overridden per commit when `volumes` is set. */buses: {
|
|
1784
1549
|
master: number;
|
|
1785
1550
|
music: number;
|
|
@@ -1852,7 +1617,7 @@ type MusicSwitch = {
|
|
|
1852
1617
|
/**
|
|
1853
1618
|
* audio plugin state.
|
|
1854
1619
|
*/
|
|
1855
|
-
type State = {
|
|
1620
|
+
type State$1 = {
|
|
1856
1621
|
/** `undefined` means headless: no graph, no sound, every member still keeps its value. */context: AudioContextLike | undefined;
|
|
1857
1622
|
buses: Record<Bus, BusState>; /** A lifecycle push is in force: every bus is held at zero. */
|
|
1858
1623
|
paused: boolean;
|
|
@@ -1980,10 +1745,10 @@ type AudioApi = {
|
|
|
1980
1745
|
/**
|
|
1981
1746
|
* Resolved dependency APIs.
|
|
1982
1747
|
*/
|
|
1983
|
-
type Deps = {
|
|
1748
|
+
type Deps$1 = {
|
|
1984
1749
|
flow: Api$1;
|
|
1985
|
-
assets: Api$
|
|
1986
|
-
model: Api$
|
|
1750
|
+
assets: Api$3;
|
|
1751
|
+
model: Api$4;
|
|
1987
1752
|
time: Api;
|
|
1988
1753
|
};
|
|
1989
1754
|
/**
|
|
@@ -1991,7 +1756,7 @@ type Deps = {
|
|
|
1991
1756
|
*
|
|
1992
1757
|
* `audio` owns no event, so `emit` is the kernel's and never called here.
|
|
1993
1758
|
*/
|
|
1994
|
-
type KernelSlice = PluginCtx<Config, State> & {
|
|
1759
|
+
type KernelSlice$1 = PluginCtx<Config$1, State$1> & {
|
|
1995
1760
|
readonly global: object;
|
|
1996
1761
|
readonly log: Log.LogApi;
|
|
1997
1762
|
readonly require: Require;
|
|
@@ -1999,13 +1764,13 @@ type KernelSlice = PluginCtx<Config, State> & {
|
|
|
1999
1764
|
/**
|
|
2000
1765
|
* Domain context shared by the files of the plugin: the kernel slice plus the resolved deps.
|
|
2001
1766
|
*/
|
|
2002
|
-
type AudioCtx = KernelSlice & {
|
|
2003
|
-
readonly deps: Deps;
|
|
1767
|
+
type AudioCtx = KernelSlice$1 & {
|
|
1768
|
+
readonly deps: Deps$1;
|
|
2004
1769
|
};
|
|
2005
1770
|
/**
|
|
2006
1771
|
* Payload of the `model:committed` hook: the source of every volume a game sets.
|
|
2007
1772
|
*/
|
|
2008
|
-
type ModelCommitted = Events$
|
|
1773
|
+
type ModelCommitted = Events$2["model:committed"];
|
|
2009
1774
|
/**
|
|
2010
1775
|
* Payload of the `scenes:changed` hook: `music` is the track the next scene declared.
|
|
2011
1776
|
*/
|
|
@@ -2013,11 +1778,11 @@ type SceneChanged = Events["scenes:changed"];
|
|
|
2013
1778
|
/**
|
|
2014
1779
|
* Payload of the `lifecycle:changed` hook: the pause that holds every bus at zero.
|
|
2015
1780
|
*/
|
|
2016
|
-
type LifecycleChanged = Events$
|
|
1781
|
+
type LifecycleChanged = Events$3["lifecycle:changed"];
|
|
2017
1782
|
/**
|
|
2018
1783
|
* Payload of the `assets:bundle-unloaded` hook: `keys` names every decoded sound that is gone.
|
|
2019
1784
|
*/
|
|
2020
|
-
type BundleUnloaded = Events$
|
|
1785
|
+
type BundleUnloaded = Events$4["assets:bundle-unloaded"];
|
|
2021
1786
|
/**
|
|
2022
1787
|
* What one play of a sound asks for: the key and the bus the sound goes to.
|
|
2023
1788
|
*/
|
|
@@ -2033,4 +1798,239 @@ type MusicRequest = {
|
|
|
2033
1798
|
fadeMs: number;
|
|
2034
1799
|
};
|
|
2035
1800
|
//#endregion
|
|
2036
|
-
|
|
1801
|
+
//#region src/plugins/ui/layout/types.d.ts
|
|
1802
|
+
/**
|
|
1803
|
+
* layout module state. `nodes` is attach minus detach: Yoga 3.2.1 has no instance counter.
|
|
1804
|
+
*/
|
|
1805
|
+
type LayoutState = {
|
|
1806
|
+
yoga: Yoga | undefined;
|
|
1807
|
+
byEntity: Map<Entity, Node>;
|
|
1808
|
+
nodes: number;
|
|
1809
|
+
measured: number;
|
|
1810
|
+
solves: number;
|
|
1811
|
+
scrolling: Entity | undefined;
|
|
1812
|
+
scrollStart: {
|
|
1813
|
+
pointerY: number;
|
|
1814
|
+
offset: number;
|
|
1815
|
+
};
|
|
1816
|
+
order: number;
|
|
1817
|
+
cleanups: Array<() => void>;
|
|
1818
|
+
};
|
|
1819
|
+
declare namespace types_d_exports {
|
|
1820
|
+
export { Config, Deps, ElementChange, ElementMotion, Finding, FocusRing, KernelSlice, State, TextInputLook, UiApi, UiCtx, UiNode };
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* The look of the keyboard focus ring: a dashed ring with a solid halo under it, drawn around the
|
|
1824
|
+
* focused control. Colours are `0xRRGGBB`, lengths reference units.
|
|
1825
|
+
*
|
|
1826
|
+
* @example
|
|
1827
|
+
* ```ts
|
|
1828
|
+
* // A dashed ink ring with a cream halo, 9 u outside the control.
|
|
1829
|
+
* const ring: FocusRing = {
|
|
1830
|
+
* stroke: 0x3a2212, strokeWidth: 4, dash: 10, offset: 9, halo: 0xfff3d6, haloWidth: 12
|
|
1831
|
+
* };
|
|
1832
|
+
* ```
|
|
1833
|
+
*/
|
|
1834
|
+
type FocusRing = {
|
|
1835
|
+
/** The colour of the dashed ring. */stroke: number; /** The stroke width of the dashed ring. */
|
|
1836
|
+
strokeWidth: number; /** The dash length of the ring, with gaps of half a dash; 0 draws it solid. */
|
|
1837
|
+
dash: number; /** How far outside the control's rect the ring runs, on every side. */
|
|
1838
|
+
offset: number; /** The colour of the solid halo drawn under the ring. */
|
|
1839
|
+
halo: number; /** The stroke width of the halo, centred on the same path as the ring. */
|
|
1840
|
+
haloWidth: number;
|
|
1841
|
+
};
|
|
1842
|
+
/**
|
|
1843
|
+
* The look of a text field while it is edited: the caret, the selection box and the IME
|
|
1844
|
+
* underline. Colours are `0xRRGGBB`, lengths reference units, `keyboardMargin` CSS px. The caret
|
|
1845
|
+
* does not blink.
|
|
1846
|
+
*
|
|
1847
|
+
* @example
|
|
1848
|
+
* ```ts
|
|
1849
|
+
* // A thick ink caret, a pale blue selection, the field 16 px above the keyboard.
|
|
1850
|
+
* const look: TextInputLook = {
|
|
1851
|
+
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
1852
|
+
* composingUnderline: 3, keyboardMargin: 16
|
|
1853
|
+
* };
|
|
1854
|
+
* ```
|
|
1855
|
+
*/
|
|
1856
|
+
type TextInputLook = {
|
|
1857
|
+
/** The width of the caret. */caretWidth: number; /** The colour of the caret and of the underline under an IME composing range. */
|
|
1858
|
+
caret: number; /** The colour of the selection box. */
|
|
1859
|
+
selection: number; /** The alpha of the selection box. */
|
|
1860
|
+
selectionAlpha: number; /** The height of the underline under an IME composing range. */
|
|
1861
|
+
composingUnderline: number; /** How far above the keyboard the bottom of the edited field is lifted, in CSS px. */
|
|
1862
|
+
keyboardMargin: number;
|
|
1863
|
+
};
|
|
1864
|
+
/**
|
|
1865
|
+
* ui plugin config.
|
|
1866
|
+
*
|
|
1867
|
+
* @example
|
|
1868
|
+
* ```ts
|
|
1869
|
+
* createApp({ pluginConfigs: { ui: { tapTargetPt: 48, breakpoints: { tall: 2, wide: 1.5 } } } });
|
|
1870
|
+
* // A game with a white focus ring on a dark board.
|
|
1871
|
+
* createApp({
|
|
1872
|
+
* pluginConfigs: {
|
|
1873
|
+
* ui: {
|
|
1874
|
+
* focusRing: {
|
|
1875
|
+
* stroke: 0xffffff, strokeWidth: 4, dash: 10, offset: 9, halo: 0x000000, haloWidth: 12
|
|
1876
|
+
* }
|
|
1877
|
+
* }
|
|
1878
|
+
* }
|
|
1879
|
+
* });
|
|
1880
|
+
* // A game whose text fields have an ink caret.
|
|
1881
|
+
* createApp({
|
|
1882
|
+
* pluginConfigs: {
|
|
1883
|
+
* ui: {
|
|
1884
|
+
* textInput: {
|
|
1885
|
+
* caretWidth: 3, caret: 0x3a2212, selection: 0x3390ff, selectionAlpha: 0.35,
|
|
1886
|
+
* composingUnderline: 3, keyboardMargin: 16
|
|
1887
|
+
* }
|
|
1888
|
+
* }
|
|
1889
|
+
* }
|
|
1890
|
+
* });
|
|
1891
|
+
* ```
|
|
1892
|
+
*/
|
|
1893
|
+
type Config = {
|
|
1894
|
+
/** 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. */
|
|
1895
|
+
breakpoints: {
|
|
1896
|
+
tall: number;
|
|
1897
|
+
wide: number;
|
|
1898
|
+
};
|
|
1899
|
+
/**
|
|
1900
|
+
* The ring drawn around the control the keyboard focused. Shallow merge: a game that sets
|
|
1901
|
+
* `focusRing` gives all six fields.
|
|
1902
|
+
*/
|
|
1903
|
+
focusRing: FocusRing;
|
|
1904
|
+
/**
|
|
1905
|
+
* The caret, the selection and the IME underline of a text field. Shallow merge: a game that
|
|
1906
|
+
* sets `textInput` gives all six fields.
|
|
1907
|
+
*/
|
|
1908
|
+
textInput: TextInputLook;
|
|
1909
|
+
};
|
|
1910
|
+
/**
|
|
1911
|
+
* ui plugin state: one branch per module.
|
|
1912
|
+
*/
|
|
1913
|
+
type State = {
|
|
1914
|
+
jsx: JsxState;
|
|
1915
|
+
styles: StylesState;
|
|
1916
|
+
layout: LayoutState;
|
|
1917
|
+
};
|
|
1918
|
+
/**
|
|
1919
|
+
* Resolved dependency APIs. `anim` is here for the dev hot swap, which replaces animations; the
|
|
1920
|
+
* motions of `ui` reach `anim` through the tween driver behind every `ViewHandle`.
|
|
1921
|
+
*/
|
|
1922
|
+
type Deps = {
|
|
1923
|
+
anim: AnimApi;
|
|
1924
|
+
time: Api;
|
|
1925
|
+
flow: Api$1;
|
|
1926
|
+
world: Api$2;
|
|
1927
|
+
renderer: Api$5;
|
|
1928
|
+
input: InputApi;
|
|
1929
|
+
i18n: I18nApi;
|
|
1930
|
+
text: TextApi;
|
|
1931
|
+
};
|
|
1932
|
+
/**
|
|
1933
|
+
* What the kernel context offers before the deps are attached.
|
|
1934
|
+
*
|
|
1935
|
+
* `ui` owns no event of its own; `emit` sends the global `ui:hot-swap` of the dev hot swap.
|
|
1936
|
+
*/
|
|
1937
|
+
type KernelSlice = PluginCtx<Config, State, Events$5> & {
|
|
1938
|
+
readonly global: object;
|
|
1939
|
+
readonly log: Log.LogApi;
|
|
1940
|
+
readonly require: Require;
|
|
1941
|
+
};
|
|
1942
|
+
/**
|
|
1943
|
+
* Domain context shared by the three modules: the kernel slice plus the resolved deps.
|
|
1944
|
+
*/
|
|
1945
|
+
type UiCtx = KernelSlice & {
|
|
1946
|
+
readonly deps: Deps;
|
|
1947
|
+
};
|
|
1948
|
+
/**
|
|
1949
|
+
* ui plugin API, `app.ui`. The screen is one more projection, so three members read it the way a
|
|
1950
|
+
* test reads the board: a snapshot, a key lookup and a list of findings; the fourth types into a
|
|
1951
|
+
* text field.
|
|
1952
|
+
*
|
|
1953
|
+
* @example
|
|
1954
|
+
* ```ts
|
|
1955
|
+
* // A headless scenario taps the claim button of the reward popup.
|
|
1956
|
+
* app.ui.tree().type; // "row", the root element of the HUD
|
|
1957
|
+
* app.input.tap(app.ui.find("claim") ?? 0);
|
|
1958
|
+
* app.ui.lint(); // []
|
|
1959
|
+
* ```
|
|
1960
|
+
*/
|
|
1961
|
+
type UiApi = {
|
|
1962
|
+
/**
|
|
1963
|
+
* The live screen as plain data: every root in layer order, every element in child order, with
|
|
1964
|
+
* its rect in root coordinates, its resolved style and its seven state flags. A rect is natural:
|
|
1965
|
+
* under a `fit: "contain"` element it is the rect before that scale, and the fitted element
|
|
1966
|
+
* adds `fitScale`. A windowed scroll adds `window`, and its content lists the live rows only.
|
|
1967
|
+
* Works headless.
|
|
1968
|
+
*
|
|
1969
|
+
* @returns The root node; several roots come back under one `screen` node.
|
|
1970
|
+
* @example
|
|
1971
|
+
* ```ts
|
|
1972
|
+
* // On an iPhone SE the 970 u board is drawn smaller to fit the slot between the bars.
|
|
1973
|
+
* const screen = app.ui.tree();
|
|
1974
|
+
* screen.children.map(child => child.key); // ["fitTop", "slot", "fitBottom"]
|
|
1975
|
+
* const board = screen.children[1]?.children[0];
|
|
1976
|
+
* board?.rect.w; // 970, the natural width
|
|
1977
|
+
* board?.fitScale; // 0.805, the 781 u the slot leaves over 970 u
|
|
1978
|
+
* ```
|
|
1979
|
+
*/
|
|
1980
|
+
tree(): UiNode;
|
|
1981
|
+
/**
|
|
1982
|
+
* The entity of a keyed element, so a test can tap it and `anim` can aim at it. Popup roots
|
|
1983
|
+
* come first, then the projection roots in layer order.
|
|
1984
|
+
*
|
|
1985
|
+
* @param key - The `key` prop of the element.
|
|
1986
|
+
* @returns The entity, or `undefined` for an unknown or exiting element.
|
|
1987
|
+
* @example
|
|
1988
|
+
* ```ts
|
|
1989
|
+
* // A headless scenario answers the gate through the button of the popup.
|
|
1990
|
+
* app.input.tap(app.ui.find("claim") ?? 0); // true
|
|
1991
|
+
* app.ui.find("nothing"); // undefined
|
|
1992
|
+
* ```
|
|
1993
|
+
*/
|
|
1994
|
+
find(key: string): Entity | undefined;
|
|
1995
|
+
/**
|
|
1996
|
+
* Reads the live screen against the five rules: a tap target under `tapTargetPt` at the size
|
|
1997
|
+
* it is drawn (a `fit: "contain"` on it or above it shrinks it), a text that does not fit its
|
|
1998
|
+
* box in some registered locale, an absolute element with no `reason`, a clipping element
|
|
1999
|
+
* (`scroll`, `overflow: "hidden"`) whose style names a nine-slice it never draws, and a root
|
|
2000
|
+
* element whose style sets a `zIndex` it ignores. Never throws; empty when nothing is mounted.
|
|
2001
|
+
*
|
|
2002
|
+
* @returns One finding per rule and element.
|
|
2003
|
+
* @example
|
|
2004
|
+
* ```ts
|
|
2005
|
+
* // A game test keeps the board honest on an iPhone SE: a 140 u cell in the 0.8 slot.
|
|
2006
|
+
* app.ui.lint(); // [{ rule: "tap-target", key: "cell", detail: "39 x 39 pt" }]
|
|
2007
|
+
* // A list styled with a nine-slice: the clip keeps it from drawing.
|
|
2008
|
+
* app.ui.lint(); // [{ rule: "nine-slice-clipped", key: "orders", detail: "scroll" }]
|
|
2009
|
+
* // A screen root that asks to be drawn over the others: the layer decides that.
|
|
2010
|
+
* app.ui.lint(); // [{ rule: "z-index-on-root", key: "board", detail: "zIndex 2" }]
|
|
2011
|
+
* ```
|
|
2012
|
+
*/
|
|
2013
|
+
lint(): readonly Finding[];
|
|
2014
|
+
/**
|
|
2015
|
+
* Types into a text field the way a player does, for a headless test or an agent: the field
|
|
2016
|
+
* becomes the one being edited, `value` cut to its `maxLength` is written into it, and the
|
|
2017
|
+
* local field it names is written, so the component re-renders on the next frame. Nothing
|
|
2018
|
+
* reaches the gate: Enter submits.
|
|
2019
|
+
*
|
|
2020
|
+
* @param key - The `key` prop of the `input` element.
|
|
2021
|
+
* @param value - The text to type.
|
|
2022
|
+
* @returns True when the field took the text; false with one warning when no live `input` has
|
|
2023
|
+
* the key.
|
|
2024
|
+
* @example
|
|
2025
|
+
* ```ts
|
|
2026
|
+
* // A headless test renames the player through the Rename popup.
|
|
2027
|
+
* app.ui.fill("nameField", "Alex"); // true
|
|
2028
|
+
* app.time.step(16);
|
|
2029
|
+
* app.input.pressKey("Enter"); // true: the gate took { intent: "save", payload: { name: "Alex" } }
|
|
2030
|
+
* app.ui.fill("nothing", "Alex"); // false, with the warning "ui:fill-without-input"
|
|
2031
|
+
* ```
|
|
2032
|
+
*/
|
|
2033
|
+
fill(key: string, value: string): boolean;
|
|
2034
|
+
};
|
|
2035
|
+
//#endregion
|
|
2036
|
+
export { SfxDescriptor as A, sequence as B, Config$3 as C, Target as D, State$3 as E, frames as F, stagger as G, sfx as H, haptic as I, wait as J, tween as K, mark as L, HAPTIC_KINDS as M, defineAnimation as N, types_d_exports$3 as O, external as P, parallel as R, AnimPlayerValue as S, MotionKeyframe as T, spawn as U, set as V, spawned as W, SceneSpec as _, AudioApi as a, types_d_exports$2 as b, MusicDescriptor as c, State$1 as d, types_d_exports$1 as f, SceneDefinition as g, LayerMap as h, types_d_exports as i, Step as j, HapticKind as k, MusicOptions as l, DefineScene as m, State as n, AudioContextLike as o, AnySceneProjection as p, use as q, UiApi as r, Config$1 as s, Config as t, SoundEntry as u, ScenesApi as v, FramesValue as w, AnimApi as x, State$2 as y, play as z };
|