@moku-labs/game 0.9.0 → 0.10.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.
Files changed (53) hide show
  1. package/README.md +81 -22
  2. package/bin/moku-game.mjs +4 -0
  3. package/dist/app/page.d.mts +41 -0
  4. package/dist/app/page.mjs +376 -0
  5. package/dist/app/system.d.mts +129 -0
  6. package/dist/app/system.mjs +307 -0
  7. package/dist/app.d.mts +37 -0
  8. package/dist/app.mjs +235 -0
  9. package/dist/assets-BHwTLVta.mjs +7391 -0
  10. package/dist/assets.d.mts +1 -1
  11. package/dist/assets.mjs +1 -7390
  12. package/dist/cli.d.mts +70 -0
  13. package/dist/cli.mjs +1650 -0
  14. package/dist/{commands-DuwCxK5t.d.mts → commands-C4QlqijJ.d.mts} +5 -5
  15. package/dist/config-CdARrrhU.mjs +81 -0
  16. package/dist/control.d.mts +11 -10
  17. package/dist/control.mjs +3 -3
  18. package/dist/{define-B6pHpdBi.d.mts → define-CCc0ozKe.d.mts} +2 -2
  19. package/dist/{dev-wKLgOw7c.mjs → dev-Cc50Dk7H.mjs} +1 -1
  20. package/dist/drafts-BawpSaVp.mjs +156 -0
  21. package/dist/fake-MpzwZhIZ.mjs +87 -0
  22. package/dist/{headless-SCQXJxQf.d.mts → headless-G4nuZ-xz.d.mts} +1 -1
  23. package/dist/hot.d.mts +4 -6
  24. package/dist/hot.mjs +8 -9
  25. package/dist/{index-BO9kZzY3.d.mts → index-xxSxKJJW.d.mts} +17 -17
  26. package/dist/index.d.mts +5 -5
  27. package/dist/index.mjs +1 -1
  28. package/dist/inspect-la_KkjCS.mjs +1 -0
  29. package/dist/inspect.d.mts +7 -7
  30. package/dist/inspect.mjs +3 -2
  31. package/dist/jsx-dev-runtime.d.mts +1 -1
  32. package/dist/jsx-runtime.d.mts +1 -1
  33. package/dist/lint.mjs +10 -6
  34. package/dist/memory-CWlqhS7l.mjs +136 -0
  35. package/dist/memory-DwDhfFWK.d.mts +50 -0
  36. package/dist/project.mjs +3 -3
  37. package/dist/{run-CofJEdYx.mjs → run-wYty_Lwo.mjs} +2 -2
  38. package/dist/{runtime-CdNJ0UBm.d.mts → runtime-DOBYM6g4.d.mts} +1 -1
  39. package/dist/{input-z_35Jwfn.mjs → session-DgukhR_7.mjs} +20 -20
  40. package/dist/{sources-DNnzyCYf.mjs → sources-Duzj6lhV.mjs} +2 -2
  41. package/dist/{src-536arXjV.mjs → src-DSl1eNB1.mjs} +14 -292
  42. package/dist/testing.d.mts +4 -50
  43. package/dist/testing.mjs +3 -87
  44. package/dist/{types-VZVWwqCg.d.mts → types-BM4shh8K.d.mts} +259 -259
  45. package/dist/{types-xXfyk56Q.d.mts → types-BUwDHKXm.d.mts} +1377 -1377
  46. package/dist/{types-CQueODzo.d.mts → types-CefgYzFt.d.mts} +2 -2
  47. package/dist/{types-DUMoYPYe.d.mts → types-DAdwEJMp.d.mts} +2 -2
  48. package/dist/{types-B0v5VVa3.d.mts → types-ZQLYXo5X.d.mts} +304 -304
  49. package/dist/types-hQgI_wrq.d.mts +544 -0
  50. package/dist/visual.d.mts +6 -6
  51. package/dist/visual.mjs +5 -5
  52. package/llms.txt +119 -43
  53. package/package.json +30 -2
@@ -1,5 +1,5 @@
1
- import { $ as Ease, Bt as Api, Ft as TypeTag, Gt as Api$5, I as AnyComponentValue, It as Descriptor, Jt as Json, K as Owner, L as ComponentHandle, P as AnyComponent, V as Entity, bn as Events$2, ct as TrackSegment, et as LayerSort, it as NumericFields, k as Api$2, ln as Events$4, m as Api$3, o as Events$5, qt as Events$3, rt as MotionHandle, st as TrackOptions, t as Api$4, tt as LayerSpec, ut as Api$1, xn as Require, z as ComponentType } from "./types-B0v5VVa3.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-xXfyk56Q.mjs";
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, ElementChange, ElementMotion, Finding, FocusRing, KernelSlice$2 as KernelSlice, State$2 as State, TextInputLook, UiApi, UiCtx, UiNode };
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$1 = Record<string, never>;
1292
+ type Config$2 = Record<string, never>;
1528
1293
  /**
1529
1294
  * scenes plugin state.
1530
1295
  */
1531
- type State$1 = {
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$1 = {
1372
+ type Deps$2 = {
1608
1373
  flow: Api$1;
1609
1374
  world: Api$2;
1610
- assets: Api$4;
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$1 = PluginCtx<Config$1, State$1, Events> & {
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$1 & {
1629
- readonly deps: Deps$1;
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$4;
1986
- model: Api$5;
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$3["model:committed"];
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$4["lifecycle:changed"];
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$5["assets:bundle-unloaded"];
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
- export { Step as A, set as B, FramesValue as C, types_d_exports$3 as D, Target as E, haptic as F, tween as G, spawn as H, mark as I, use as K, parallel as L, defineAnimation as M, external as N, HapticKind as O, frames as P, play as R, Config$3 as S, State$3 as T, spawned as U, sfx as V, stagger 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, HAPTIC_KINDS as j, SfxDescriptor as k, DefineScene as l, State$1 as m, Config as n, State as o, ScenesApi as p, wait as q, MusicDescriptor as r, types_d_exports as s, AudioApi as t, LayerMap as u, UiApi as v, MotionKeyframe as w, AnimPlayerValue as x, types_d_exports$2 as y, sequence as z };
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 };