@moku-labs/game 0.15.11 → 0.15.12

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/dist/app/page.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { r as systemSource, t as memory } from "../memory-CWlqhS7l.mjs";
2
2
  import { t as applyTo } from "../drafts-BawpSaVp.mjs";
3
3
  import { i as isControl } from "../dev-BNndV-hU.mjs";
4
- import { n as read, r as watch, t as sources } from "../sources-CJgUypyC.mjs";
4
+ import { n as read, r as watch, t as sources } from "../sources-Fbq_PFVH.mjs";
5
5
  import { t as resolveConfig } from "../config-B87aFTW-.mjs";
6
6
  //#region src/app/save.ts
7
7
  /**
package/dist/app.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { Bt as audioPlugin, J as platformPlugin, i as screen, kt as effectsPlugin, m as flattenFeatures, t as createApp } from "./src-0m2mjRDI.mjs";
1
+ import { Nt as audioPlugin, St as effectsPlugin, V as platformPlugin, i as screen, m as flattenFeatures, t as createApp } from "./src-FIcYaXro.mjs";
2
2
  import { t as memory } from "./memory-CWlqhS7l.mjs";
3
3
  import { n as isFakeClock, t as fakeClock } from "./fake-6mazmHK3.mjs";
4
4
  //#region src/app/define.ts
@@ -0,0 +1,44 @@
1
+ //#region src/plugins/ui/jsx/component.ts
2
+ /** The local state a component that declares none starts every instance with. */
3
+ const noLocal = {};
4
+ /**
5
+ * Tells a component definition from a plain function component, which JSX calls at build time.
6
+ *
7
+ * @param type - What stood in the tag position.
8
+ * @returns True when `defineComponent` built it.
9
+ * @example
10
+ * ```ts
11
+ * isComponentDefinition(() => ({ type: "row", props: {}, children: [] })); // false
12
+ * ```
13
+ */
14
+ function isComponentDefinition(type) {
15
+ return typeof type === "function" && type.isUiComponent === true;
16
+ }
17
+ /**
18
+ * The one implementation behind the two overloads.
19
+ *
20
+ * @param name - Component name.
21
+ * @param spec - What the game declared.
22
+ * @returns The callable definition.
23
+ */
24
+ function defineComponent(name, spec) {
25
+ const local = spec.local ?? noLocal;
26
+ const call = (props) => ({
27
+ type: name,
28
+ props,
29
+ children: []
30
+ });
31
+ const definition = Object.assign(call, {
32
+ outcomes: spec.outcomes,
33
+ local,
34
+ view: spec.view,
35
+ isUiComponent: true
36
+ });
37
+ Object.defineProperty(definition, "name", {
38
+ value: name,
39
+ configurable: true
40
+ });
41
+ return definition;
42
+ }
43
+ //#endregion
44
+ export { isComponentDefinition as n, defineComponent as t };
@@ -1,46 +1,3 @@
1
- //#region src/plugins/ui/jsx/component.ts
2
- /** The local state a component that declares none starts every instance with. */
3
- const noLocal = {};
4
- /**
5
- * Tells a component definition from a plain function component, which JSX calls at build time.
6
- *
7
- * @param type - What stood in the tag position.
8
- * @returns True when `defineComponent` built it.
9
- * @example
10
- * ```ts
11
- * isComponentDefinition(() => ({ type: "row", props: {}, children: [] })); // false
12
- * ```
13
- */
14
- function isComponentDefinition(type) {
15
- return typeof type === "function" && type.isUiComponent === true;
16
- }
17
- /**
18
- * The one implementation behind the two overloads.
19
- *
20
- * @param name - Component name.
21
- * @param spec - What the game declared.
22
- * @returns The callable definition.
23
- */
24
- function defineComponent(name, spec) {
25
- const local = spec.local ?? noLocal;
26
- const call = (props) => ({
27
- type: name,
28
- props,
29
- children: []
30
- });
31
- const definition = Object.assign(call, {
32
- outcomes: spec.outcomes,
33
- local,
34
- view: spec.view,
35
- isUiComponent: true
36
- });
37
- Object.defineProperty(definition, "name", {
38
- value: name,
39
- configurable: true
40
- });
41
- return definition;
42
- }
43
- //#endregion
44
1
  //#region src/plugins/ui/jsx/flatten.ts
45
2
  /** The type of the node `Fragment` builds. It never reaches a reconcile: `flatten` lifts it. */
46
3
  const FRAGMENT = "#fragment";
@@ -97,4 +54,4 @@ function flatten(child) {
97
54
  return [child];
98
55
  }
99
56
  //#endregion
100
- export { isComponentDefinition as i, flatten as n, defineComponent as r, FRAGMENT as t };
57
+ export { flatten as n, FRAGMENT as t };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as haptic, $t as PERF_LOG_VERSION, A as types_exports$6, At as Emitter, B as Box, Bt as audioPlugin, C as types_exports$13, Ct as Touchable, D as types_exports$9, Dt as messageArgument, E as types_exports$10, Et as i18nPlugin, F as types_exports$1, Ft as Glow, G as defineTokens, Gt as Animation, H as LocalWrite, Ht as assetsPlugin, I as types_exports, It as Noise, J as platformPlugin, Jt as PASS_KINDS, K as defineStyle, Kt as Frames, L as uiPlugin, Lt as Outline, M as types_exports$4, Mt as Blur, N as types_exports$3, Nt as ColorMatrix, O as types_exports$8, Ot as messageDuration, P as types_exports$2, Pt as Displacement, Q as frames, Qt as PERF_GAP_BUCKETS, R as resolve, Rt as defineFilter, S as types_exports$14, St as Tappable, T as types_exports$11, Tt as Traced, U as ScrollState, Ut as animPlugin, V as DebugTrigger, Vt as scenesPlugin, W as popup, Wt as AnimPlayer, X as defineAnimation, Xt as MONITOR_SECTIONS, Y as HAPTIC_KINDS, Yt as frameAt, Z as external, Zt as PERF_CAUSES, _ as defineBundles, _t as Pointer, a as cubicBezier, at as sfx, b as types_exports$16, bt as Pressed, c as hint, cn as to, ct as stagger, d as defineScene, dn as SaveUnreadableError, dt as wait, en as PROBLEM_RULES, et as mark, f as tr, fn as lifecyclePlugin, ft as inputPlugin, g as music, gt as Hovered, h as defineEmitter, ht as Held, i as screen, in as flowPlugin, it as set, j as types_exports$5, jt as Alpha, k as types_exports$7, kt as effectsPlugin, l as schedule, ln as type, lt as tween, m as flattenFeatures, mn as clockPlugin, mt as DropTarget, n as createPlugin, nn as DEMAND_REASONS, nt as play, o as defineEffect, on as exit, ot as spawn, p as defineFeature, pn as timePlugin, pt as Draggable, q as textPlugin, qt as rendererPlugin, r as defineGame, rn as worldPlugin, rt as sequence, s as guide, sn as slot, st as spawned, t as createApp, tn as SHADER_WHATS, tt as parallel, u as projection, un as modelPlugin, ut as use, v as load, vt as PointerOver, w as types_exports$12, wt as Traceable, x as types_exports$15, xt as Swipeable, y as types_exports$17, yt as Pressable, z as defineMotion, zt as debugPlugin } from "./src-0m2mjRDI.mjs";
2
- import { A as Now, C as Sprite, D as sprite, F as resource, I as system, M as Tree, N as component, O as Exiting, P as mut, R as tag, S as Shape, _ as HudPart, c as Countdown, f as defineTextStyles, g as Display, j as Order, k as Layer, l as Text, p as label, u as bind, v as NineSlice, w as Transform, x as Parent, y as Overlay } from "./visual-Dwfy9wDb.mjs";
3
- import { r as defineComponent } from "./flatten-BkXuscAV.mjs";
1
+ import { $ as spawn, $t as exit, A as types_exports$6, At as Outline, B as textPlugin, Bt as rendererPlugin, C as types_exports$13, Ct as Emitter, D as types_exports$9, Dt as Displacement, E as types_exports$10, Et as ColorMatrix, F as types_exports$1, Ft as assetsPlugin, G as frames, Gt as PERF_GAP_BUCKETS, H as HAPTIC_KINDS, Ht as frameAt, I as types_exports, It as animPlugin, J as parallel, Jt as SHADER_WHATS, K as haptic, Kt as PERF_LOG_VERSION, L as uiPlugin, Lt as AnimPlayer, M as types_exports$4, Mt as debugPlugin, N as types_exports$3, Nt as audioPlugin, O as types_exports$8, Ot as Glow, P as types_exports$2, Pt as scenesPlugin, Q as sfx, R as resolve, Rt as Animation, S as types_exports$14, St as effectsPlugin, T as types_exports$11, Tt as Blur, U as defineAnimation, Ut as MONITOR_SECTIONS, V as platformPlugin, Vt as PASS_KINDS, W as external, Wt as PERF_CAUSES, X as sequence, Xt as worldPlugin, Y as play, Yt as DEMAND_REASONS, Z as set, Zt as flowPlugin, _ as defineBundles, _t as Traceable, a as cubicBezier, an as lifecyclePlugin, at as inputPlugin, b as types_exports$16, bt as messageArgument, c as hint, ct as Held, d as defineScene, dt as PointerOver, en as slot, et as spawned, f as tr, ft as Pressable, g as music, gt as Touchable, h as defineEmitter, ht as Tappable, i as screen, in as SaveUnreadableError, it as wait, j as types_exports$5, jt as defineFilter, k as types_exports$7, kt as Noise, l as schedule, lt as Hovered, m as flattenFeatures, mt as Swipeable, n as createPlugin, nn as type, nt as tween, o as defineEffect, on as timePlugin, ot as Draggable, p as defineFeature, pt as Pressed, q as mark, qt as PROBLEM_RULES, r as defineGame, rn as modelPlugin, rt as use, s as guide, sn as clockPlugin, st as DropTarget, t as createApp, tn as to, tt as stagger, u as projection, ut as Pointer, v as load, vt as Traced, w as types_exports$12, wt as Alpha, x as types_exports$15, xt as messageDuration, y as types_exports$17, yt as i18nPlugin, z as defineMotion, zt as Frames } from "./src-FIcYaXro.mjs";
2
+ import { $ as component, H as Shape, I as Display, J as Exiting, L as HudPart, Q as Tree, R as NineSlice, S as bind, T as label, U as Sprite, V as Parent, W as Transform, X as Now, Y as Layer, Z as Order, b as Countdown, d as LocalWrite, et as mut, g as popup, it as tag, l as DebugTrigger, nt as system, p as ScrollState, q as sprite, s as Box, tt as resource, v as defineTokens, w as defineTextStyles, x as Text, y as defineStyle, z as Overlay } from "./visual-CbGKzlj0.mjs";
3
+ import { t as defineComponent } from "./component-DGg5DqKK.mjs";
4
4
  export { Alpha, types_exports as Anim, AnimPlayer, Animation, types_exports$1 as Assets, types_exports$2 as Audio, Blur, Box, types_exports$3 as Clock, ColorMatrix, Countdown, DEMAND_REASONS, types_exports$4 as Debug, DebugTrigger, Displacement, Display, Draggable, DropTarget, types_exports$5 as Effects, Emitter, Exiting, types_exports$6 as Flow, Frames, Glow, HAPTIC_KINDS, Held, Hovered, HudPart, types_exports$7 as I18n, types_exports$8 as Input, Layer, types_exports$9 as Lifecycle, LocalWrite, MONITOR_SECTIONS, types_exports$10 as Model, NineSlice, Noise, Now, Order, Outline, Overlay, PASS_KINDS, PERF_CAUSES, PERF_GAP_BUCKETS, PERF_LOG_VERSION, PROBLEM_RULES, Parent, types_exports$11 as Platform, Pointer, PointerOver, Pressable, Pressed, types_exports$12 as Renderer, SHADER_WHATS, SaveUnreadableError, types_exports$13 as Scenes, ScrollState, Shape, Sprite, Swipeable, Tappable, Text, types_exports$14 as TextTypes, types_exports$15 as Time, Touchable, Traceable, Traced, Transform, Tree, types_exports$16 as Ui, types_exports$17 as World, animPlugin, assetsPlugin, audioPlugin, bind, clockPlugin, component, createApp, createPlugin, cubicBezier, debugPlugin, defineAnimation, defineBundles, defineComponent, defineEffect, defineEmitter, defineFeature, defineFilter, defineGame, defineMotion, defineScene, defineStyle, defineTextStyles, defineTokens, effectsPlugin, exit, external, flattenFeatures, flowPlugin, frameAt, frames, guide, haptic, hint, i18nPlugin, inputPlugin, label, lifecyclePlugin, load, mark, messageArgument, messageDuration, modelPlugin, music, mut, parallel, platformPlugin, play, popup, projection, rendererPlugin, resolve, resource, scenesPlugin, schedule, screen, sequence, set, sfx, slot, spawn, spawned, sprite, stagger, system, tag, textPlugin, timePlugin, to, tr, tween, type, uiPlugin, use, wait, worldPlugin };
@@ -86,7 +86,6 @@ declare const sources: Readonly<{
86
86
  } | undefined, HeadlessApp & {
87
87
  readonly ui: UiApi;
88
88
  readonly renderer: Api$2;
89
- } & {
90
89
  readonly world: Api$1;
91
90
  }>;
92
91
  render: Source<{}, RenderStats, HeadlessApp & {
package/dist/inspect.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  import { c as defineSource } from "./session-CeKgO2hy.mjs";
2
- import { n as read, r as watch, t as sources } from "./sources-CJgUypyC.mjs";
2
+ import { n as read, r as watch, t as sources } from "./sources-Fbq_PFVH.mjs";
3
3
  import "./inspect-la_KkjCS.mjs";
4
4
  export { defineSource, read, sources, watch };
@@ -1,2 +1,2 @@
1
- import { i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./runtime-CBZgWgzx.mjs";
1
+ import { i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./runtime-DnM9i73o.mjs";
2
2
  export { Fragment, jsx, jsxDEV, jsxs };
@@ -1,2 +1,2 @@
1
- import { i as jsxs, n as jsx, t as Fragment } from "./runtime-CBZgWgzx.mjs";
1
+ import { i as jsxs, n as jsx, t as Fragment } from "./runtime-DnM9i73o.mjs";
2
2
  export { Fragment, jsx, jsxs };
@@ -1,4 +1,5 @@
1
- import { i as isComponentDefinition, n as flatten, t as FRAGMENT } from "./flatten-BkXuscAV.mjs";
1
+ import { n as isComponentDefinition } from "./component-DGg5DqKK.mjs";
2
+ import { n as flatten, t as FRAGMENT } from "./flatten-nUX9PpGo.mjs";
2
3
  //#region src/plugins/ui/jsx/runtime.ts
3
4
  /**
4
5
  * @file ui/jsx — the JSX runtime itself: the three factories a TypeScript build calls, the
@@ -1,4 +1,4 @@
1
- import { a as scaleByFits, k as Layer } from "./visual-Dwfy9wDb.mjs";
1
+ import { F as rootPoseOf, H as Shape, R as NineSlice, Y as Layer, j as parentOf, n as drawnRect, s as Box } from "./visual-CbGKzlj0.mjs";
2
2
  import { o as notInstalled } from "./dev-BNndV-hU.mjs";
3
3
  import { a as readTarget, c as defineSource, n as isTainted, o as inputOrEmpty, t as cheatsOf } from "./session-CeKgO2hy.mjs";
4
4
  //#region src/plugins/flow/doors/read.ts
@@ -304,36 +304,80 @@ const atSource = defineSource({
304
304
  * @file ui plugin — the ui sources of the `/inspect` door: the live screen as data, and where an
305
305
  * element or a view is on the page. Production-safe: every one only reads.
306
306
  */
307
+ /** How deep a parent chain is followed for clips; deeper is treated as a loop. */
308
+ const MAX_DEPTH = 32;
309
+ /**
310
+ * Where a box of an entity's own space lands in root space: `0, 0, w, h` through its root pose,
311
+ * which composes every `Transform` up its `Parent` chain (a scroll's offset, a fit, a slot, a
312
+ * motion). The rotation is left out, as the guide does.
313
+ *
314
+ * @param ecs - The world read.
315
+ * @param entity - The entity.
316
+ * @param w - The width of the box in the entity's own units.
317
+ * @param h - The height of the box.
318
+ * @returns The rect in root coordinates.
319
+ */
320
+ function rootBoxOf(ecs, entity, w, h) {
321
+ return drawnRect(rootPoseOf(ecs, entity), {
322
+ x: 0,
323
+ y: 0,
324
+ w,
325
+ h
326
+ });
327
+ }
307
328
  /**
308
- * Finds a keyed node and the nodes above it.
329
+ * The box an entity clips its children to, the way the renderer masks them: the `width × height`
330
+ * of a clipping `NineSlice`, the `w × h` of a clipping `Shape`, in root coordinates.
309
331
  *
310
- * @param node - Where the search starts.
311
- * @param key - The key of the element.
312
- * @returns The node and its ancestors, nearest first, or `undefined` when no node has the key.
332
+ * @param ecs - The world read.
333
+ * @param entity - The entity.
334
+ * @returns The clip in root coordinates, or `undefined` when the entity clips nothing.
313
335
  */
314
- function chainTo(node, key) {
315
- if (node.key === key) return [node];
316
- for (const child of node.children) {
317
- const chain = chainTo(child, key);
318
- if (chain !== void 0) {
319
- chain.push(node);
320
- return chain;
321
- }
322
- }
336
+ function clipOf(ecs, entity) {
337
+ const panel = ecs.get(entity, NineSlice);
338
+ if (panel?.clip === true) return rootBoxOf(ecs, entity, panel.width, panel.height);
339
+ const shape = ecs.get(entity, Shape);
340
+ return shape?.clip === true ? rootBoxOf(ecs, entity, shape.w, shape.h) : void 0;
323
341
  }
324
342
  /**
325
- * Where an element is drawn at rest, in root coordinates. Its rect in the snapshot is natural,
326
- * so every fitted node on the way up, the element itself included, scales it about its centre,
327
- * the way ui draws a `fit: "contain"`.
328
- *
329
- * @param chain - The element and its ancestors, nearest first.
330
- * @returns The drawn rect.
331
- */
332
- function drawnRect(chain) {
333
- return scaleByFits(chain[0].rect, chain.map((node) => ({
334
- rect: node.rect,
335
- fit: node.fitScale ?? 1
336
- })));
343
+ * The part of a rect inside another.
344
+ *
345
+ * @param rect - The rect to cut.
346
+ * @param clip - The rect it is cut to.
347
+ * @returns The overlap, or `undefined` when they do not overlap.
348
+ */
349
+ function intersect(rect, clip) {
350
+ const x = Math.max(rect.x, clip.x);
351
+ const y = Math.max(rect.y, clip.y);
352
+ const right = Math.min(rect.x + rect.w, clip.x + clip.w);
353
+ const bottom = Math.min(rect.y + rect.h, clip.y + clip.h);
354
+ return right > x && bottom > y ? {
355
+ x,
356
+ y,
357
+ w: right - x,
358
+ h: bottom - y
359
+ } : void 0;
360
+ }
361
+ /**
362
+ * Where an element is drawn, in root coordinates: its `Box` size through its root pose, cut by
363
+ * every clipping entity above it (a `scroll`, an `overflow: "hidden"`), as the renderer masks it.
364
+ * Its own clip masks only its children, so it never cuts the element itself.
365
+ *
366
+ * @param ecs - The world read.
367
+ * @param entity - The element's entity.
368
+ * @returns The drawn rect, or `undefined` when no part of it shows: cut away by a clip, or drawn
369
+ * at no size (an element entering from scale 0), as `renderer.sync.boundsOf` answers a view.
370
+ */
371
+ function drawnRectOf(ecs, entity) {
372
+ const box = ecs.get(entity, Box);
373
+ if (box === void 0) return void 0;
374
+ const own = rootBoxOf(ecs, entity, box.w, box.h);
375
+ let drawn = own.w > 0 && own.h > 0 ? own : void 0;
376
+ for (let above = parentOf(ecs, entity), depth = 0; above !== 0 && drawn !== void 0 && depth < MAX_DEPTH; above = parentOf(ecs, above), depth += 1) {
377
+ const clip = clipOf(ecs, above);
378
+ if (clip !== void 0) drawn = intersect(drawn, clip);
379
+ }
380
+ return drawn;
337
381
  }
338
382
  /**
339
383
  * Maps a rect in reference units to CSS px of the page through both of its corners.
@@ -359,16 +403,19 @@ function onPage(renderer, rect) {
359
403
  };
360
404
  }
361
405
  /**
362
- * Where a live ui element is on the page: its layout box, scaled by every fitted element above
363
- * it, through the viewport.
406
+ * Where a live ui element is on the page: where it is drawn (its layout box through its root pose,
407
+ * so a scroll's offset, a fit and a slot move it), cut by every clipping element above it,
408
+ * through the viewport.
364
409
  *
365
- * @param app - The app with ui and renderer.
410
+ * @param app - The app with ui, renderer and world.
366
411
  * @param key - The `key` prop of the element.
367
- * @returns The rect in CSS px, or `undefined` when no live element has the key.
412
+ * @returns The rect in CSS px, or `undefined` when no live element has the key or a clip above
413
+ * hides all of it.
368
414
  */
369
415
  function locateKey(app, key) {
370
- const chain = app.ui.find(key) !== void 0 ? chainTo(app.ui.tree(), key) : void 0;
371
- return chain === void 0 ? void 0 : onPage(app.renderer, drawnRect(chain));
416
+ const entity = app.ui.find(key);
417
+ const drawn = entity === void 0 ? void 0 : drawnRectOf(app.world.ecs, entity);
418
+ return drawn === void 0 ? void 0 : onPage(app.renderer, drawn);
372
419
  }
373
420
  /**
374
421
  * Where a view is on the page: the box the renderer draws for the entity of its projection key,
@@ -408,9 +455,9 @@ const uiSource = defineSource({
408
455
  });
409
456
  /**
410
457
  * Where something is on the page, in CSS px, by either of the two addresses the doors use: a ui
411
- * element by its `key` (its layout box, scaled by every fitted element above it, so a bare button
412
- * with no fill has one), or a view by its `target` projection key (the box the renderer draws for
413
- * it). Both go through the viewport, so the numbers are what Playwright clicks. In reference units
458
+ * element by its `key` (its layout box through its drawn pose, so a scroll's offset and a fit move
459
+ * it and a bare button with no fill has one, cut by every clip above it), or a view by its `target`
460
+ * projection key (the box the renderer draws for it). Both go through the viewport, so the numbers are what Playwright clicks. In reference units
414
461
  * while the renderer is inert; a view has no drawn box then.
415
462
  *
416
463
  * @example
@@ -2,9 +2,10 @@ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
2
  import { r as systemSource, t as memory } from "./memory-CWlqhS7l.mjs";
3
3
  import { a as finishDrafts, i as enableDraftPatches, n as deepFreeze$1, o as openDrafts, r as dropDrafts } from "./drafts-BawpSaVp.mjs";
4
4
  import { d as graphHash, f as isRestCheckpoint, h as pushEntry, i as servePaused, l as findNode, m as compact, n as captureFrame, o as collectFlows, p as slotNames, r as serveCaptures, s as describeGraph, t as cancelCaptures, u as framePath } from "./capture-D7XvoHdH.mjs";
5
- import { A as Now, C as Sprite, E as componentsFor, F as resource, I as system, L as systemsFor, M as Tree, N as component, O as Exiting, R as tag, S as Shape, T as arcDefaults, _ as HudPart, b as OverlayLevel, c as Countdown, d as builtInStyles, g as Display, h as textFor, i as samePose, j as Order, k as Layer, l as Text, m as readStyle, n as drawnRect, o as visualOf$1, r as fitScaleOf, s as visualRectOf, t as CONTENT$1, v as NineSlice, w as Transform, x as Parent, y as Overlay } from "./visual-Dwfy9wDb.mjs";
5
+ import { $ as component, A as localPoseOf, B as OverlayLevel, C as builtInStyles, D as textFor, E as readStyle, F as rootPoseOf, G as arcDefaults, H as Shape, I as Display, J as Exiting, K as componentsFor, L as HudPart, M as poseUnder, N as rootPointOf, O as applyPose, P as rootPoseInto, Q as Tree, R as NineSlice, U as Sprite, V as Parent, W as Transform, X as Now, Y as Layer, Z as Order, _ as uiFor, a as visualOf$1, b as Countdown, c as Covered, d as LocalWrite, f as Scroll, h as UiCounters, i as samePose, it as tag, j as parentOf$1, k as isLeaving, l as DebugTrigger, m as UI_OWNER, n as drawnRect, nt as system, o as visualRectOf, p as ScrollState, r as fitScaleOf, rt as systemsFor, s as Box, t as CONTENT$1, tt as resource, u as Escapable, x as Text, z as Overlay } from "./visual-CbGKzlj0.mjs";
6
6
  import { a as isDev } from "./dev-BNndV-hU.mjs";
7
- import { i as isComponentDefinition, n as flatten, r as defineComponent } from "./flatten-BkXuscAV.mjs";
7
+ import { n as isComponentDefinition } from "./component-DGg5DqKK.mjs";
8
+ import { n as flatten } from "./flatten-nUX9PpGo.mjs";
8
9
  import { envPlugin, logPlugin } from "@moku-labs/common/browser";
9
10
  import { createCoreConfig } from "@moku-labs/core";
10
11
  /**
@@ -24379,250 +24380,6 @@ function destroyPools(state) {
24379
24380
  state.pooled = 0;
24380
24381
  }
24381
24382
  //#endregion
24382
- //#region src/plugins/renderer/sync/pose.ts
24383
- /**
24384
- * @file renderer/sync — the pose helpers: where an entity really is, in root (reference) space,
24385
- * and the local pose that puts it there under a parent. Pure component math over `world.ecs.get`,
24386
- * the same math the renderer draws with: `position` is where the `pivot` lands, and the pivot is
24387
- * the local point the view turns and scales around.
24388
- *
24389
- * Engine-internal, not a root export. `input`, `anim` and `ui` import `rootPoseOf` and
24390
- * `localPoseOf` from this module path (`../renderer/sync/pose`) and never walk the `Parent` chain
24391
- * themselves; a per-frame reader (`effects`' following emitters) writes the root pose into its own
24392
- * object with `rootPoseInto`, which allocates nothing; `input` places a carried view under the last pose of a despawned held view with
24393
- * `poseUnder`; `sync` places a box with `rootPointOf`. `input` places the drop lookup of an aimed
24394
- * view with `applyPose`.
24395
- */
24396
- /** How deep a parent chain is followed; deeper is treated as a loop. */
24397
- const MAX_DEPTH$6 = 32;
24398
- /**
24399
- * The parent an entity moves with.
24400
- *
24401
- * @param ecs - The world read.
24402
- * @param entity - The entity.
24403
- * @returns The parent entity, or `0` when it has none or names itself.
24404
- */
24405
- function parentOf$1(ecs, entity) {
24406
- const parent = ecs.get(entity, Parent)?.entity ?? 0;
24407
- return parent === entity ? 0 : parent;
24408
- }
24409
- /**
24410
- * Tells whether an entity is on its way out: it or an ancestor of its `Parent` chain carries `Exiting` (a ui element
24411
- * whose exit plays, a world view in its exit queue). Its despawn is coming; nothing else of the teardown is owed.
24412
- *
24413
- * @param ecs - The world read.
24414
- * @param entity - The entity.
24415
- * @returns True while it, or what it hangs under, leaves.
24416
- */
24417
- function isLeaving(ecs, entity) {
24418
- let current = entity;
24419
- for (let depth = 0; depth < MAX_DEPTH$6 && current !== 0; depth += 1) {
24420
- if (ecs.has(current, Exiting)) return true;
24421
- current = parentOf$1(ecs, current);
24422
- }
24423
- return false;
24424
- }
24425
- /**
24426
- * A fresh copy of a pose, so a caller may change what it got without touching the world.
24427
- *
24428
- * @param pose - The pose to copy.
24429
- * @returns The same numbers in new objects.
24430
- * @example
24431
- * ```ts
24432
- * copyPose({ x: 1, y: 2, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } }).pivot.x; // 0
24433
- * ```
24434
- */
24435
- function copyPose(pose) {
24436
- return {
24437
- x: pose.x,
24438
- y: pose.y,
24439
- rotation: pose.rotation,
24440
- scale: pose.scale,
24441
- pivot: {
24442
- x: pose.pivot.x,
24443
- y: pose.pivot.y
24444
- }
24445
- };
24446
- }
24447
- /**
24448
- * Moves a point out of the local space of a pose, into the space the pose sits in.
24449
- *
24450
- * @param pose - The pose whose local space the point is in.
24451
- * @param point - The local point.
24452
- * @returns The point one space higher.
24453
- * @example
24454
- * ```ts
24455
- * applyPose({ x: 10, y: 0, rotation: 0, scale: 2, pivot: { x: 5, y: 0 } }, { x: 5, y: 1 });
24456
- * // { x: 10, y: 2 }
24457
- * ```
24458
- */
24459
- function applyPose(pose, point) {
24460
- const cos = Math.cos(pose.rotation);
24461
- const sin = Math.sin(pose.rotation);
24462
- const dx = point.x - pose.pivot.x;
24463
- const dy = point.y - pose.pivot.y;
24464
- return {
24465
- x: pose.x + pose.scale * (dx * cos - dy * sin),
24466
- y: pose.y + pose.scale * (dx * sin + dy * cos)
24467
- };
24468
- }
24469
- /**
24470
- * Places a local pose under a parent pose: the pose in the space the parent sits in. The step
24471
- * `rootPoseOf` takes once per parent: the position through the parent's pivot, rotation, scale
24472
- * and position, the rotations added and the scales multiplied.
24473
- *
24474
- * @param above - The parent pose.
24475
- * @param local - The pose under it.
24476
- * @returns The composed pose; it keeps the local pivot.
24477
- * @example
24478
- * ```ts
24479
- * poseUnder(
24480
- * { x: 400, y: 300, rotation: 0, scale: 2, pivot: { x: 0, y: 0 } },
24481
- * { x: 0, y: 30, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } }
24482
- * ); // { x: 400, y: 360, rotation: 0, scale: 2, pivot: { x: 0, y: 0 } }
24483
- * ```
24484
- */
24485
- function poseUnder(above, local) {
24486
- const landed = applyPose(above, local);
24487
- return {
24488
- x: landed.x,
24489
- y: landed.y,
24490
- rotation: local.rotation + above.rotation,
24491
- scale: local.scale * above.scale,
24492
- pivot: {
24493
- x: local.pivot.x,
24494
- y: local.pivot.y
24495
- }
24496
- };
24497
- }
24498
- /**
24499
- * Where an entity really is, written into the caller's pose: its `Transform` composed through the `Parent` chain,
24500
- * every pivot on the way applied, the numbers of `rootPoseOf` (the same steps in the same order). The answer keeps the
24501
- * entity's own pivot. Allocates nothing: a reader that asks every frame passes the same object.
24502
- *
24503
- * @param ecs - The world read, `world.ecs`.
24504
- * @param entity - The entity to place.
24505
- * @param out - The pose to write, its `pivot` object included; it may be `own`.
24506
- * @param own - A pose to use in place of the entity's own `Transform`, such as its rest pose.
24507
- * @returns `out`, in root space. An entity without a `Transform` sits at the identity pose.
24508
- * @example
24509
- * ```ts
24510
- * // `effects` follows a host every frame: the slot sits at (40, 60) scaled 0.5, the host at (100, 200) inside it.
24511
- * const pose = { x: 0, y: 0, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } };
24512
- * rootPoseInto(ctx.require(worldPlugin).ecs, host, pose);
24513
- * // pose is { x: 90, y: 160, rotation: 0, scale: 0.5, pivot: { x: 0, y: 0 } }
24514
- * ```
24515
- */
24516
- function rootPoseInto(ecs, entity, out, own) {
24517
- const start = own ?? ecs.get(entity, Transform) ?? Transform.defaults;
24518
- out.x = start.x;
24519
- out.y = start.y;
24520
- out.rotation = start.rotation;
24521
- out.scale = start.scale;
24522
- out.pivot.x = start.pivot.x;
24523
- out.pivot.y = start.pivot.y;
24524
- let current = entity;
24525
- for (let depth = 0; depth < MAX_DEPTH$6; depth += 1) {
24526
- const parent = parentOf$1(ecs, current);
24527
- if (parent === 0) break;
24528
- const above = ecs.get(parent, Transform) ?? Transform.defaults;
24529
- const cos = Math.cos(above.rotation);
24530
- const sin = Math.sin(above.rotation);
24531
- const dx = out.x - above.pivot.x;
24532
- const dy = out.y - above.pivot.y;
24533
- out.x = above.x + above.scale * (dx * cos - dy * sin);
24534
- out.y = above.y + above.scale * (dx * sin + dy * cos);
24535
- out.rotation = out.rotation + above.rotation;
24536
- out.scale = out.scale * above.scale;
24537
- current = parent;
24538
- }
24539
- return out;
24540
- }
24541
- /**
24542
- * Where an entity really is: its `Transform` composed through the `Parent` chain, every pivot on
24543
- * the way applied. The answer keeps the entity's own pivot, so it can be written straight into the
24544
- * `Transform` of an entity without a parent and the view does not move.
24545
- *
24546
- * @param ecs - The world read, `world.ecs`.
24547
- * @param entity - The entity to place.
24548
- * @param own - A pose to use in place of the entity's own `Transform`, such as its rest pose.
24549
- * @returns The pose in root space, a fresh object. An entity without a `Transform` sits at the identity pose.
24550
- * @example
24551
- * ```ts
24552
- * // `input` lifts a board cell out of its slot: the slot sits at (40, 60) scaled 0.5,
24553
- * // the cell at (100, 200) inside it.
24554
- * rootPoseOf(ctx.require(worldPlugin).ecs, cell);
24555
- * // { x: 90, y: 160, rotation: 0, scale: 0.5, pivot: { x: 0, y: 0 } }
24556
- * ```
24557
- */
24558
- function rootPoseOf(ecs, entity, own) {
24559
- return rootPoseInto(ecs, entity, {
24560
- x: 0,
24561
- y: 0,
24562
- rotation: 0,
24563
- scale: 1,
24564
- pivot: {
24565
- x: 0,
24566
- y: 0
24567
- }
24568
- }, own);
24569
- }
24570
- /**
24571
- * The inverse of `rootPoseOf`: the local pose under `parent` that puts an entity at a root pose.
24572
- * The pivot is kept, as it is a local point of the entity itself.
24573
- *
24574
- * @param ecs - The world read, `world.ecs`.
24575
- * @param parent - The entity to hang under; `0` for none, which answers the root pose itself.
24576
- * @param root - The pose in root space.
24577
- * @returns The local pose. A parent collapsed to scale 0 counts as scale 1, so the answer stays
24578
- * finite.
24579
- * @example
24580
- * ```ts
24581
- * // `input` drops the cell back into the slot at (40, 60) scaled 0.5, where the finger left it.
24582
- * localPoseOf(ctx.require(worldPlugin).ecs, slot, {
24583
- * x: 90, y: 160, rotation: 0, scale: 0.5, pivot: { x: 0, y: 0 }
24584
- * });
24585
- * // { x: 100, y: 200, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } }
24586
- * ```
24587
- */
24588
- function localPoseOf(ecs, parent, root) {
24589
- if (parent === 0) return copyPose(root);
24590
- const above = rootPoseOf(ecs, parent);
24591
- const scale = above.scale === 0 ? 1 : above.scale;
24592
- const cos = Math.cos(-above.rotation);
24593
- const sin = Math.sin(-above.rotation);
24594
- const dx = root.x - above.x;
24595
- const dy = root.y - above.y;
24596
- return {
24597
- x: above.pivot.x + (dx * cos - dy * sin) / scale,
24598
- y: above.pivot.y + (dx * sin + dy * cos) / scale,
24599
- rotation: root.rotation - above.rotation,
24600
- scale: root.scale / scale,
24601
- pivot: {
24602
- x: root.pivot.x,
24603
- y: root.pivot.y
24604
- }
24605
- };
24606
- }
24607
- /**
24608
- * Where a local point of an entity lands in root (reference) space: the point posed through the
24609
- * entity's own `Transform` and its whole `Parent` chain, the forward walk of the hit test's
24610
- * `localPoseOf`. The scale is the real one, so a view collapsed to scale 0 lands on one point.
24611
- *
24612
- * @param ecs - The world read, `world.ecs`.
24613
- * @param entity - The entity whose local space the point is in.
24614
- * @param point - The local point.
24615
- * @returns The point in root space, a fresh object.
24616
- * @example
24617
- * ```ts
24618
- * // The corner of a 64 x 64 cell at (100, 200) inside a slot at (40, 60) scaled 0.5.
24619
- * rootPointOf(ctx.require(worldPlugin).ecs, cell, { x: -32, y: -32 }); // { x: 74, y: 144 }
24620
- * ```
24621
- */
24622
- function rootPointOf(ecs, entity, point) {
24623
- return applyPose(rootPoseOf(ecs, entity), point);
24624
- }
24625
- //#endregion
24626
24383
  //#region src/plugins/renderer/sync/layers.ts
24627
24384
  /**
24628
24385
  * @file renderer/sync — the layers. `scenes` declares them through `world.projection.setLayers`;
@@ -32186,13 +31943,14 @@ function localTargetOf(ecs, entity, component, to) {
32186
31943
  const parent = parentOf$1(ecs, entity);
32187
31944
  if (component !== asComponent(Transform) || parent === 0) return local;
32188
31945
  const now = rootPoseOf(ecs, entity);
32189
- const landed = localPoseOf(ecs, parent, {
31946
+ const root = {
32190
31947
  x: to.x ?? now.x,
32191
31948
  y: to.y ?? now.y,
32192
31949
  rotation: to.rotation ?? now.rotation,
32193
31950
  scale: to.scale ?? now.scale,
32194
31951
  pivot: now.pivot
32195
- });
31952
+ };
31953
+ const landed = localPoseOf(ecs, parent, root);
32196
31954
  for (const field of POSE_FIELDS) if (to[field] !== void 0) local[field] = landed[field];
32197
31955
  return local;
32198
31956
  }
@@ -50454,204 +50212,6 @@ const textPlugin = /*#__PURE__*/ createPlugin$1("text", {
50454
50212
  onStop: ({ state }) => stopText(state)
50455
50213
  });
50456
50214
  //#endregion
50457
- //#region src/plugins/ui/styles/define.ts
50458
- /**
50459
- * Declares one style. The work is the type: a field outside the vocabulary, or a value outside
50460
- * its union, is an error where the style is written, not where it is used.
50461
- *
50462
- * @param style - The style, with its `is` and `when` variants.
50463
- * @returns The same object, frozen.
50464
- * @example
50465
- * ```ts
50466
- * defineStyle({ direction: "row", gap: 12 }).gap; // 12
50467
- * ```
50468
- */
50469
- function defineStyle(style) {
50470
- return Object.freeze(style);
50471
- }
50472
- //#endregion
50473
- //#region src/plugins/ui/styles/tokens.ts
50474
- /**
50475
- * Declares the design tokens of a game: spaces, colours, radii and font keys, flat and plain.
50476
- *
50477
- * @param tokens - The four groups; every key inside them is the game's own.
50478
- * @returns The same object, frozen.
50479
- * @example
50480
- * ```ts
50481
- * defineTokens({ space: { md: 16 } }).space.md; // 16
50482
- * ```
50483
- */
50484
- function defineTokens(tokens) {
50485
- return Object.freeze(tokens);
50486
- }
50487
- //#endregion
50488
- //#region src/plugins/ui/components.ts
50489
- /**
50490
- * Who owns every entity `ui` spawns. The projection module checks it before it hands out a view
50491
- * handle, so only `ui` may move a ui element.
50492
- */
50493
- const UI_OWNER = {
50494
- kind: "plugin",
50495
- name: "ui"
50496
- };
50497
- /** Fresh defaults for the patch, so no two buttons share one object. */
50498
- const localWriteDefaults = { patch: {} };
50499
- /**
50500
- * The rect of a ui element in root coordinates. Written by the solve, read by `tree()`, `lint()`
50501
- * and the hit test of `guide`.
50502
- */
50503
- const Box = /*#__PURE__*/ component("Box", {
50504
- x: 0,
50505
- y: 0,
50506
- w: 0,
50507
- h: 0
50508
- });
50509
- /**
50510
- * On a button that writes local state instead of naming an intent. `input.onTap` reports the tap
50511
- * and `ui` merges the patch into the nearest component instance.
50512
- */
50513
- const LocalWrite = /*#__PURE__*/ component("LocalWrite", localWriteDefaults);
50514
- /**
50515
- * On a scroll container. Internal to `ui`: not exported from the package root.
50516
- */
50517
- const Scroll = /*#__PURE__*/ component("Scroll", {
50518
- axis: "y",
50519
- offset: 0,
50520
- min: 0
50521
- });
50522
- /**
50523
- * On every scroll container: where it stands and whether it moves, for a game system and the
50524
- * read door. `ui` writes it in a frame where the offset or `max` changed, and once more with
50525
- * `moving: false` when it stops; a game reads it and never writes it.
50526
- *
50527
- * @example
50528
- * ```ts
50529
- * // A board system dims the events of the order strip while it rests on the orders.
50530
- * export const stripMist = system({
50531
- * name: "board.stripMist",
50532
- * phase: "animate",
50533
- * query: [ScrollState, OrderStrip],
50534
- * run: entities => {
50535
- * for (const [entity, scroll] of entities) {
50536
- * // scroll: { offset: 318, max: 390, moving: false }
50537
- * }
50538
- * }
50539
- * });
50540
- * ```
50541
- */
50542
- const ScrollState = /*#__PURE__*/ component("ScrollState", {
50543
- offset: 0,
50544
- max: 0,
50545
- moving: false
50546
- });
50547
- /**
50548
- * On the root entity of a popup kept beneath another popup (`popup(..., { over })`). Internal to
50549
- * `ui`: not exported from the package root. Every element of that root resolves `is.covered`.
50550
- */
50551
- const Covered = /*#__PURE__*/ tag("Covered");
50552
- /**
50553
- * On a button with the `escape` prop: the control the Escape key taps while its root is the top
50554
- * one, meant for the close button or the backdrop of a dismissable popup. Internal to `ui`: the
50555
- * game writes the prop, never the tag.
50556
- */
50557
- const Escapable = /*#__PURE__*/ tag("Escapable");
50558
- /**
50559
- * On the view a player taps five times within three seconds to open the editor's overlay on a debug build: the
50560
- * version line of the settings, usually. One helper on top of `app.debug.overlay.open()`; a game that wants another
50561
- * gesture calls that itself. The view must take a press (a `button`, or any element with `Touchable`); a `button`
50562
- * that names no intent is the plain choice. Without the agent flag the tag does nothing.
50563
- *
50564
- * @example
50565
- * ```tsx
50566
- * // The version line of the settings sheet. Five taps open the overlay of `moku-game build --debug` on the phone.
50567
- * <button key="versionLine" style={versionLineStyle} components={[DebugTrigger()]}>
50568
- * <text key="version" style="settings.version" content={tr("settings.version", { version: "1.4.0" })} />
50569
- * </button>
50570
- * ```
50571
- */
50572
- const DebugTrigger = /*#__PURE__*/ tag("DebugTrigger");
50573
- /**
50574
- * The three Yoga counters, the reconcile count of the frame, the range re-renders of the windowed
50575
- * lists, and the style and write passes of the reconcile. Written by the two systems of `ui`, read
50576
- * by the acceptance tests. Not part of `app.ui`.
50577
- */
50578
- const UiCounters = /*#__PURE__*/ resource("UiCounters", {
50579
- solves: 0,
50580
- nodes: 0,
50581
- measured: 0,
50582
- reconciles: 0,
50583
- windowRenders: 0,
50584
- styled: 0,
50585
- written: 0
50586
- });
50587
- /**
50588
- * Builds the effect a node awaits to show a popup. The gate opens for the outcomes of the
50589
- * component, so the node resolves with the intent one of its buttons answered. `over` names the
50590
- * component of a popup that stays mounted beneath this one, drawn covered, until this one is gone.
50591
- *
50592
- * @param component - A component declared with `outcomes`.
50593
- * @param props - What its view is called with.
50594
- * @param options - How the popup stands to the others.
50595
- * @param options.over - The component name of the popup kept beneath this one.
50596
- * @returns The descriptor `fx()` takes.
50597
- * @example
50598
- * ```ts
50599
- * const Reward = defineComponent("Reward", {
50600
- * outcomes: { claim: {} },
50601
- * view: () => ({ type: "panel", props: {}, children: [] })
50602
- * });
50603
- * popup(Reward, { gold: 5 });
50604
- * // { kind: "popup", payload: { component: "Reward", props: { gold: 5 } }, answers: ["claim"] }
50605
- * await fx(popup(Reward, { gold: 5 })); // Answer<"claim">: { intent: "claim" }
50606
- * ```
50607
- * @example
50608
- * ```ts
50609
- * // The settings node asks before a reset; the settings stay beneath, covered.
50610
- * const Confirm = defineComponent("Confirm", {
50611
- * outcomes: { reset: {}, cancel: {} },
50612
- * view: () => ({ type: "panel", props: {}, children: [] })
50613
- * });
50614
- * popup(Confirm, {}, { over: "Settings" });
50615
- * // { kind: "popup", payload: { component: "Confirm", props: {}, over: "Settings" },
50616
- * // answers: ["reset", "cancel"] }
50617
- * ```
50618
- */
50619
- function popup(component, props, options) {
50620
- const over = options?.over;
50621
- return {
50622
- kind: "popup",
50623
- payload: over === void 0 ? {
50624
- component: component.name,
50625
- props
50626
- } : {
50627
- component: component.name,
50628
- props,
50629
- over
50630
- },
50631
- answers: Object.keys(component.outcomes)
50632
- };
50633
- }
50634
- /**
50635
- * Binds the four ui helpers to one game. Type-only: the same four functions, plus the intrinsic
50636
- * table this game's tags are checked against.
50637
- *
50638
- * @returns The helpers and the intrinsic type carrier.
50639
- * @example
50640
- * ```ts
50641
- * const { defineStyle } = uiFor<"ui.coin", "digits", "hud.coins">();
50642
- * defineStyle({ gap: 8 }).gap; // 8
50643
- * ```
50644
- */
50645
- function uiFor() {
50646
- return {
50647
- defineComponent,
50648
- defineStyle,
50649
- defineTokens,
50650
- popup,
50651
- intrinsics: {}
50652
- };
50653
- }
50654
- //#endregion
50655
50215
  //#region src/plugins/ui/jsx/field-layout.ts
50656
50216
  /**
50657
50217
  * The four edges of a resolved padding.
@@ -61349,4 +60909,4 @@ const screen = [
61349
60909
  uiPlugin
61350
60910
  ];
61351
60911
  //#endregion
61352
- export { haptic as $, PERF_LOG_VERSION as $t, types_exports$11 as A, Emitter as At, Box as B, audioPlugin as Bt, types_exports$4 as C, Touchable as Ct, types_exports$8 as D, messageArgument as Dt, types_exports$7 as E, i18nPlugin as Et, types_exports$16 as F, Glow as Ft, defineTokens as G, Animation as Gt, LocalWrite as H, assetsPlugin as Ht, types_exports$17 as I, Noise as It, platformPlugin as J, PASS_KINDS as Jt, defineStyle as K, Frames as Kt, uiPlugin as L, Outline as Lt, types_exports$13 as M, Blur as Mt, types_exports$14 as N, ColorMatrix as Nt, types_exports$9 as O, messageDuration as Ot, types_exports$15 as P, Displacement as Pt, frames as Q, PERF_GAP_BUCKETS as Qt, resolve as R, defineFilter as Rt, types_exports$3 as S, Tappable as St, types_exports$6 as T, Traced as Tt, ScrollState as U, animPlugin as Ut, DebugTrigger as V, scenesPlugin as Vt, popup as W, AnimPlayer as Wt, defineAnimation as X, MONITOR_SECTIONS as Xt, HAPTIC_KINDS as Y, frameAt as Yt, external as Z, PERF_CAUSES as Zt, defineBundles as _, Pointer as _t, cubicBezier as a, refuseStart as an, sfx as at, types_exports$1 as b, Pressed as bt, hint as c, to as cn, stagger as ct, defineScene as d, SaveUnreadableError as dn, wait as dt, PROBLEM_RULES as en, mark as et, tr as f, lifecyclePlugin as fn, inputPlugin as ft, music as g, Hovered as gt, defineEmitter as h, Held as ht, screen as i, flowPlugin as in, set as it, types_exports$12 as j, Alpha as jt, types_exports$10 as k, effectsPlugin as kt, schedule as l, type as ln, tween as lt, flattenFeatures as m, clockPlugin as mn, DropTarget as mt, createPlugin as n, DEMAND_REASONS as nn, play$1 as nt, defineEffect as o, exit as on, spawn as ot, defineFeature as p, timePlugin as pn, Draggable as pt, textPlugin as q, rendererPlugin as qt, defineGame as r, worldPlugin as rn, sequence as rt, guide as s, slot as sn, spawned as st, createApp as t, SHADER_WHATS as tn, parallel as tt, projection as u, modelPlugin as un, use as ut, load as v, PointerOver as vt, types_exports$5 as w, Traceable as wt, types_exports$2 as x, Swipeable as xt, types_exports as y, Pressable as yt, defineMotion as z, debugPlugin as zt };
60912
+ export { spawn as $, exit as $t, types_exports$11 as A, Outline as At, textPlugin as B, rendererPlugin as Bt, types_exports$4 as C, Emitter as Ct, types_exports$8 as D, Displacement as Dt, types_exports$7 as E, ColorMatrix as Et, types_exports$16 as F, assetsPlugin as Ft, frames as G, PERF_GAP_BUCKETS as Gt, HAPTIC_KINDS as H, frameAt as Ht, types_exports$17 as I, animPlugin as It, parallel as J, SHADER_WHATS as Jt, haptic as K, PERF_LOG_VERSION as Kt, uiPlugin as L, AnimPlayer as Lt, types_exports$13 as M, debugPlugin as Mt, types_exports$14 as N, audioPlugin as Nt, types_exports$9 as O, Glow as Ot, types_exports$15 as P, scenesPlugin as Pt, sfx as Q, refuseStart as Qt, resolve as R, Animation as Rt, types_exports$3 as S, effectsPlugin as St, types_exports$6 as T, Blur as Tt, defineAnimation as U, MONITOR_SECTIONS as Ut, platformPlugin as V, PASS_KINDS as Vt, external as W, PERF_CAUSES as Wt, sequence as X, worldPlugin as Xt, play$1 as Y, DEMAND_REASONS as Yt, set as Z, flowPlugin as Zt, defineBundles as _, Traceable as _t, cubicBezier as a, lifecyclePlugin as an, inputPlugin as at, types_exports$1 as b, messageArgument as bt, hint as c, Held as ct, defineScene as d, PointerOver as dt, slot as en, spawned as et, tr as f, Pressable as ft, music as g, Touchable as gt, defineEmitter as h, Tappable as ht, screen as i, SaveUnreadableError as in, wait as it, types_exports$12 as j, defineFilter as jt, types_exports$10 as k, Noise as kt, schedule as l, Hovered as lt, flattenFeatures as m, Swipeable as mt, createPlugin as n, type as nn, tween as nt, defineEffect as o, timePlugin as on, Draggable as ot, defineFeature as p, Pressed as pt, mark as q, PROBLEM_RULES as qt, defineGame as r, modelPlugin as rn, use as rt, guide as s, clockPlugin as sn, DropTarget as st, createApp as t, to as tn, stagger as tt, projection as u, Pointer as ut, load as v, Traced as vt, types_exports$5 as w, Alpha as wt, types_exports$2 as x, messageDuration as xt, types_exports as y, i18nPlugin as yt, defineMotion as z, Frames as zt };
package/dist/testing.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { an as refuseStart, ln as type, m as flattenFeatures, on as exit, t as createApp } from "./src-0m2mjRDI.mjs";
1
+ import { $t as exit, Qt as refuseStart, m as flattenFeatures, nn as type, t as createApp } from "./src-FIcYaXro.mjs";
2
2
  import { n as saveOf, t as memory } from "./memory-CWlqhS7l.mjs";
3
3
  import { t as fakeClock } from "./fake-6mazmHK3.mjs";
4
4
  import { i as stepFrames, r as runRepro, t as createHeadless } from "./headless-BA6ffzqD.mjs";
@@ -1,3 +1,4 @@
1
+ import { t as defineComponent } from "./component-DGg5DqKK.mjs";
1
2
  //#region src/plugins/world/ecs/define.ts
2
3
  /**
3
4
  * Declares a component type. The defaults give the TypeScript type, the JSON shape and the
@@ -369,6 +370,250 @@ function componentsFor() {
369
370
  HudPart
370
371
  };
371
372
  }
373
+ //#endregion
374
+ //#region src/plugins/renderer/sync/pose.ts
375
+ /**
376
+ * @file renderer/sync — the pose helpers: where an entity really is, in root (reference) space,
377
+ * and the local pose that puts it there under a parent. Pure component math over `world.ecs.get`,
378
+ * the same math the renderer draws with: `position` is where the `pivot` lands, and the pivot is
379
+ * the local point the view turns and scales around.
380
+ *
381
+ * Engine-internal, not a root export. `input`, `anim` and `ui` import `rootPoseOf` and
382
+ * `localPoseOf` from this module path (`../renderer/sync/pose`) and never walk the `Parent` chain
383
+ * themselves; a per-frame reader (`effects`' following emitters) writes the root pose into its own
384
+ * object with `rootPoseInto`, which allocates nothing; `input` places a carried view under the last pose of a despawned held view with
385
+ * `poseUnder`; `sync` places a box with `rootPointOf`. `input` places the drop lookup of an aimed
386
+ * view with `applyPose`.
387
+ */
388
+ /** How deep a parent chain is followed; deeper is treated as a loop. */
389
+ const MAX_DEPTH = 32;
390
+ /**
391
+ * The parent an entity moves with.
392
+ *
393
+ * @param ecs - The world read.
394
+ * @param entity - The entity.
395
+ * @returns The parent entity, or `0` when it has none or names itself.
396
+ */
397
+ function parentOf(ecs, entity) {
398
+ const parent = ecs.get(entity, Parent)?.entity ?? 0;
399
+ return parent === entity ? 0 : parent;
400
+ }
401
+ /**
402
+ * Tells whether an entity is on its way out: it or an ancestor of its `Parent` chain carries `Exiting` (a ui element
403
+ * whose exit plays, a world view in its exit queue). Its despawn is coming; nothing else of the teardown is owed.
404
+ *
405
+ * @param ecs - The world read.
406
+ * @param entity - The entity.
407
+ * @returns True while it, or what it hangs under, leaves.
408
+ */
409
+ function isLeaving(ecs, entity) {
410
+ let current = entity;
411
+ for (let depth = 0; depth < MAX_DEPTH && current !== 0; depth += 1) {
412
+ if (ecs.has(current, Exiting)) return true;
413
+ current = parentOf(ecs, current);
414
+ }
415
+ return false;
416
+ }
417
+ /**
418
+ * A fresh copy of a pose, so a caller may change what it got without touching the world.
419
+ *
420
+ * @param pose - The pose to copy.
421
+ * @returns The same numbers in new objects.
422
+ * @example
423
+ * ```ts
424
+ * copyPose({ x: 1, y: 2, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } }).pivot.x; // 0
425
+ * ```
426
+ */
427
+ function copyPose(pose) {
428
+ return {
429
+ x: pose.x,
430
+ y: pose.y,
431
+ rotation: pose.rotation,
432
+ scale: pose.scale,
433
+ pivot: {
434
+ x: pose.pivot.x,
435
+ y: pose.pivot.y
436
+ }
437
+ };
438
+ }
439
+ /**
440
+ * Moves a point out of the local space of a pose, into the space the pose sits in.
441
+ *
442
+ * @param pose - The pose whose local space the point is in.
443
+ * @param point - The local point.
444
+ * @returns The point one space higher.
445
+ * @example
446
+ * ```ts
447
+ * applyPose({ x: 10, y: 0, rotation: 0, scale: 2, pivot: { x: 5, y: 0 } }, { x: 5, y: 1 });
448
+ * // { x: 10, y: 2 }
449
+ * ```
450
+ */
451
+ function applyPose(pose, point) {
452
+ const cos = Math.cos(pose.rotation);
453
+ const sin = Math.sin(pose.rotation);
454
+ const dx = point.x - pose.pivot.x;
455
+ const dy = point.y - pose.pivot.y;
456
+ return {
457
+ x: pose.x + pose.scale * (dx * cos - dy * sin),
458
+ y: pose.y + pose.scale * (dx * sin + dy * cos)
459
+ };
460
+ }
461
+ /**
462
+ * Places a local pose under a parent pose: the pose in the space the parent sits in. The step
463
+ * `rootPoseOf` takes once per parent: the position through the parent's pivot, rotation, scale
464
+ * and position, the rotations added and the scales multiplied.
465
+ *
466
+ * @param above - The parent pose.
467
+ * @param local - The pose under it.
468
+ * @returns The composed pose; it keeps the local pivot.
469
+ * @example
470
+ * ```ts
471
+ * poseUnder(
472
+ * { x: 400, y: 300, rotation: 0, scale: 2, pivot: { x: 0, y: 0 } },
473
+ * { x: 0, y: 30, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } }
474
+ * ); // { x: 400, y: 360, rotation: 0, scale: 2, pivot: { x: 0, y: 0 } }
475
+ * ```
476
+ */
477
+ function poseUnder(above, local) {
478
+ const landed = applyPose(above, local);
479
+ return {
480
+ x: landed.x,
481
+ y: landed.y,
482
+ rotation: local.rotation + above.rotation,
483
+ scale: local.scale * above.scale,
484
+ pivot: {
485
+ x: local.pivot.x,
486
+ y: local.pivot.y
487
+ }
488
+ };
489
+ }
490
+ /**
491
+ * Where an entity really is, written into the caller's pose: its `Transform` composed through the `Parent` chain,
492
+ * every pivot on the way applied, the numbers of `rootPoseOf` (the same steps in the same order). The answer keeps the
493
+ * entity's own pivot. Allocates nothing: a reader that asks every frame passes the same object.
494
+ *
495
+ * @param ecs - The world read, `world.ecs`.
496
+ * @param entity - The entity to place.
497
+ * @param out - The pose to write, its `pivot` object included; it may be `own`.
498
+ * @param own - A pose to use in place of the entity's own `Transform`, such as its rest pose.
499
+ * @returns `out`, in root space. An entity without a `Transform` sits at the identity pose.
500
+ * @example
501
+ * ```ts
502
+ * // `effects` follows a host every frame: the slot sits at (40, 60) scaled 0.5, the host at (100, 200) inside it.
503
+ * const pose = { x: 0, y: 0, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } };
504
+ * rootPoseInto(ctx.require(worldPlugin).ecs, host, pose);
505
+ * // pose is { x: 90, y: 160, rotation: 0, scale: 0.5, pivot: { x: 0, y: 0 } }
506
+ * ```
507
+ */
508
+ function rootPoseInto(ecs, entity, out, own) {
509
+ const start = own ?? ecs.get(entity, Transform) ?? Transform.defaults;
510
+ out.x = start.x;
511
+ out.y = start.y;
512
+ out.rotation = start.rotation;
513
+ out.scale = start.scale;
514
+ out.pivot.x = start.pivot.x;
515
+ out.pivot.y = start.pivot.y;
516
+ let current = entity;
517
+ for (let depth = 0; depth < MAX_DEPTH; depth += 1) {
518
+ const parent = parentOf(ecs, current);
519
+ if (parent === 0) break;
520
+ const above = ecs.get(parent, Transform) ?? Transform.defaults;
521
+ const cos = Math.cos(above.rotation);
522
+ const sin = Math.sin(above.rotation);
523
+ const dx = out.x - above.pivot.x;
524
+ const dy = out.y - above.pivot.y;
525
+ out.x = above.x + above.scale * (dx * cos - dy * sin);
526
+ out.y = above.y + above.scale * (dx * sin + dy * cos);
527
+ out.rotation = out.rotation + above.rotation;
528
+ out.scale = out.scale * above.scale;
529
+ current = parent;
530
+ }
531
+ return out;
532
+ }
533
+ /**
534
+ * Where an entity really is: its `Transform` composed through the `Parent` chain, every pivot on
535
+ * the way applied. The answer keeps the entity's own pivot, so it can be written straight into the
536
+ * `Transform` of an entity without a parent and the view does not move.
537
+ *
538
+ * @param ecs - The world read, `world.ecs`.
539
+ * @param entity - The entity to place.
540
+ * @param own - A pose to use in place of the entity's own `Transform`, such as its rest pose.
541
+ * @returns The pose in root space, a fresh object. An entity without a `Transform` sits at the identity pose.
542
+ * @example
543
+ * ```ts
544
+ * // `input` lifts a board cell out of its slot: the slot sits at (40, 60) scaled 0.5,
545
+ * // the cell at (100, 200) inside it.
546
+ * rootPoseOf(ctx.require(worldPlugin).ecs, cell);
547
+ * // { x: 90, y: 160, rotation: 0, scale: 0.5, pivot: { x: 0, y: 0 } }
548
+ * ```
549
+ */
550
+ function rootPoseOf(ecs, entity, own) {
551
+ return rootPoseInto(ecs, entity, {
552
+ x: 0,
553
+ y: 0,
554
+ rotation: 0,
555
+ scale: 1,
556
+ pivot: {
557
+ x: 0,
558
+ y: 0
559
+ }
560
+ }, own);
561
+ }
562
+ /**
563
+ * The inverse of `rootPoseOf`: the local pose under `parent` that puts an entity at a root pose.
564
+ * The pivot is kept, as it is a local point of the entity itself.
565
+ *
566
+ * @param ecs - The world read, `world.ecs`.
567
+ * @param parent - The entity to hang under; `0` for none, which answers the root pose itself.
568
+ * @param root - The pose in root space.
569
+ * @returns The local pose. A parent collapsed to scale 0 counts as scale 1, so the answer stays
570
+ * finite.
571
+ * @example
572
+ * ```ts
573
+ * // `input` drops the cell back into the slot at (40, 60) scaled 0.5, where the finger left it.
574
+ * localPoseOf(ctx.require(worldPlugin).ecs, slot, {
575
+ * x: 90, y: 160, rotation: 0, scale: 0.5, pivot: { x: 0, y: 0 }
576
+ * });
577
+ * // { x: 100, y: 200, rotation: 0, scale: 1, pivot: { x: 0, y: 0 } }
578
+ * ```
579
+ */
580
+ function localPoseOf(ecs, parent, root) {
581
+ if (parent === 0) return copyPose(root);
582
+ const above = rootPoseOf(ecs, parent);
583
+ const scale = above.scale === 0 ? 1 : above.scale;
584
+ const cos = Math.cos(-above.rotation);
585
+ const sin = Math.sin(-above.rotation);
586
+ const dx = root.x - above.x;
587
+ const dy = root.y - above.y;
588
+ return {
589
+ x: above.pivot.x + (dx * cos - dy * sin) / scale,
590
+ y: above.pivot.y + (dx * sin + dy * cos) / scale,
591
+ rotation: root.rotation - above.rotation,
592
+ scale: root.scale / scale,
593
+ pivot: {
594
+ x: root.pivot.x,
595
+ y: root.pivot.y
596
+ }
597
+ };
598
+ }
599
+ /**
600
+ * Where a local point of an entity lands in root (reference) space: the point posed through the
601
+ * entity's own `Transform` and its whole `Parent` chain, the forward walk of the hit test's
602
+ * `localPoseOf`. The scale is the real one, so a view collapsed to scale 0 lands on one point.
603
+ *
604
+ * @param ecs - The world read, `world.ecs`.
605
+ * @param entity - The entity whose local space the point is in.
606
+ * @param point - The local point.
607
+ * @returns The point in root space, a fresh object.
608
+ * @example
609
+ * ```ts
610
+ * // The corner of a 64 x 64 cell at (100, 200) inside a slot at (40, 60) scaled 0.5.
611
+ * rootPointOf(ctx.require(worldPlugin).ecs, cell, { x: -32, y: -32 }); // { x: 74, y: 144 }
612
+ * ```
613
+ */
614
+ function rootPointOf(ecs, entity, point) {
615
+ return applyPose(rootPoseOf(ecs, entity), point);
616
+ }
372
617
  /**
373
618
  * Words on the screen: a string or a message, the style it is drawn in, and the string `text`
374
619
  * resolved out of it. A game writes `content`, `style`, `bind`, `anchor` and `alpha`; `resolved`
@@ -666,6 +911,204 @@ function textFor() {
666
911
  };
667
912
  }
668
913
  //#endregion
914
+ //#region src/plugins/ui/styles/define.ts
915
+ /**
916
+ * Declares one style. The work is the type: a field outside the vocabulary, or a value outside
917
+ * its union, is an error where the style is written, not where it is used.
918
+ *
919
+ * @param style - The style, with its `is` and `when` variants.
920
+ * @returns The same object, frozen.
921
+ * @example
922
+ * ```ts
923
+ * defineStyle({ direction: "row", gap: 12 }).gap; // 12
924
+ * ```
925
+ */
926
+ function defineStyle(style) {
927
+ return Object.freeze(style);
928
+ }
929
+ //#endregion
930
+ //#region src/plugins/ui/styles/tokens.ts
931
+ /**
932
+ * Declares the design tokens of a game: spaces, colours, radii and font keys, flat and plain.
933
+ *
934
+ * @param tokens - The four groups; every key inside them is the game's own.
935
+ * @returns The same object, frozen.
936
+ * @example
937
+ * ```ts
938
+ * defineTokens({ space: { md: 16 } }).space.md; // 16
939
+ * ```
940
+ */
941
+ function defineTokens(tokens) {
942
+ return Object.freeze(tokens);
943
+ }
944
+ //#endregion
945
+ //#region src/plugins/ui/components.ts
946
+ /**
947
+ * Who owns every entity `ui` spawns. The projection module checks it before it hands out a view
948
+ * handle, so only `ui` may move a ui element.
949
+ */
950
+ const UI_OWNER = {
951
+ kind: "plugin",
952
+ name: "ui"
953
+ };
954
+ /** Fresh defaults for the patch, so no two buttons share one object. */
955
+ const localWriteDefaults = { patch: {} };
956
+ /**
957
+ * The rect of a ui element in root coordinates. Written by the solve, read by `tree()`, `lint()`
958
+ * and the hit test of `guide`.
959
+ */
960
+ const Box = /*#__PURE__*/ component("Box", {
961
+ x: 0,
962
+ y: 0,
963
+ w: 0,
964
+ h: 0
965
+ });
966
+ /**
967
+ * On a button that writes local state instead of naming an intent. `input.onTap` reports the tap
968
+ * and `ui` merges the patch into the nearest component instance.
969
+ */
970
+ const LocalWrite = /*#__PURE__*/ component("LocalWrite", localWriteDefaults);
971
+ /**
972
+ * On a scroll container. Internal to `ui`: not exported from the package root.
973
+ */
974
+ const Scroll = /*#__PURE__*/ component("Scroll", {
975
+ axis: "y",
976
+ offset: 0,
977
+ min: 0
978
+ });
979
+ /**
980
+ * On every scroll container: where it stands and whether it moves, for a game system and the
981
+ * read door. `ui` writes it in a frame where the offset or `max` changed, and once more with
982
+ * `moving: false` when it stops; a game reads it and never writes it.
983
+ *
984
+ * @example
985
+ * ```ts
986
+ * // A board system dims the events of the order strip while it rests on the orders.
987
+ * export const stripMist = system({
988
+ * name: "board.stripMist",
989
+ * phase: "animate",
990
+ * query: [ScrollState, OrderStrip],
991
+ * run: entities => {
992
+ * for (const [entity, scroll] of entities) {
993
+ * // scroll: { offset: 318, max: 390, moving: false }
994
+ * }
995
+ * }
996
+ * });
997
+ * ```
998
+ */
999
+ const ScrollState = /*#__PURE__*/ component("ScrollState", {
1000
+ offset: 0,
1001
+ max: 0,
1002
+ moving: false
1003
+ });
1004
+ /**
1005
+ * On the root entity of a popup kept beneath another popup (`popup(..., { over })`). Internal to
1006
+ * `ui`: not exported from the package root. Every element of that root resolves `is.covered`.
1007
+ */
1008
+ const Covered = /*#__PURE__*/ tag("Covered");
1009
+ /**
1010
+ * On a button with the `escape` prop: the control the Escape key taps while its root is the top
1011
+ * one, meant for the close button or the backdrop of a dismissable popup. Internal to `ui`: the
1012
+ * game writes the prop, never the tag.
1013
+ */
1014
+ const Escapable = /*#__PURE__*/ tag("Escapable");
1015
+ /**
1016
+ * On the view a player taps five times within three seconds to open the editor's overlay on a debug build: the
1017
+ * version line of the settings, usually. One helper on top of `app.debug.overlay.open()`; a game that wants another
1018
+ * gesture calls that itself. The view must take a press (a `button`, or any element with `Touchable`); a `button`
1019
+ * that names no intent is the plain choice. Without the agent flag the tag does nothing.
1020
+ *
1021
+ * @example
1022
+ * ```tsx
1023
+ * // The version line of the settings sheet. Five taps open the overlay of `moku-game build --debug` on the phone.
1024
+ * <button key="versionLine" style={versionLineStyle} components={[DebugTrigger()]}>
1025
+ * <text key="version" style="settings.version" content={tr("settings.version", { version: "1.4.0" })} />
1026
+ * </button>
1027
+ * ```
1028
+ */
1029
+ const DebugTrigger = /*#__PURE__*/ tag("DebugTrigger");
1030
+ /**
1031
+ * The three Yoga counters, the reconcile count of the frame, the range re-renders of the windowed
1032
+ * lists, and the style and write passes of the reconcile. Written by the two systems of `ui`, read
1033
+ * by the acceptance tests. Not part of `app.ui`.
1034
+ */
1035
+ const UiCounters = /*#__PURE__*/ resource("UiCounters", {
1036
+ solves: 0,
1037
+ nodes: 0,
1038
+ measured: 0,
1039
+ reconciles: 0,
1040
+ windowRenders: 0,
1041
+ styled: 0,
1042
+ written: 0
1043
+ });
1044
+ /**
1045
+ * Builds the effect a node awaits to show a popup. The gate opens for the outcomes of the
1046
+ * component, so the node resolves with the intent one of its buttons answered. `over` names the
1047
+ * component of a popup that stays mounted beneath this one, drawn covered, until this one is gone.
1048
+ *
1049
+ * @param component - A component declared with `outcomes`.
1050
+ * @param props - What its view is called with.
1051
+ * @param options - How the popup stands to the others.
1052
+ * @param options.over - The component name of the popup kept beneath this one.
1053
+ * @returns The descriptor `fx()` takes.
1054
+ * @example
1055
+ * ```ts
1056
+ * const Reward = defineComponent("Reward", {
1057
+ * outcomes: { claim: {} },
1058
+ * view: () => ({ type: "panel", props: {}, children: [] })
1059
+ * });
1060
+ * popup(Reward, { gold: 5 });
1061
+ * // { kind: "popup", payload: { component: "Reward", props: { gold: 5 } }, answers: ["claim"] }
1062
+ * await fx(popup(Reward, { gold: 5 })); // Answer<"claim">: { intent: "claim" }
1063
+ * ```
1064
+ * @example
1065
+ * ```ts
1066
+ * // The settings node asks before a reset; the settings stay beneath, covered.
1067
+ * const Confirm = defineComponent("Confirm", {
1068
+ * outcomes: { reset: {}, cancel: {} },
1069
+ * view: () => ({ type: "panel", props: {}, children: [] })
1070
+ * });
1071
+ * popup(Confirm, {}, { over: "Settings" });
1072
+ * // { kind: "popup", payload: { component: "Confirm", props: {}, over: "Settings" },
1073
+ * // answers: ["reset", "cancel"] }
1074
+ * ```
1075
+ */
1076
+ function popup(component, props, options) {
1077
+ const over = options?.over;
1078
+ return {
1079
+ kind: "popup",
1080
+ payload: over === void 0 ? {
1081
+ component: component.name,
1082
+ props
1083
+ } : {
1084
+ component: component.name,
1085
+ props,
1086
+ over
1087
+ },
1088
+ answers: Object.keys(component.outcomes)
1089
+ };
1090
+ }
1091
+ /**
1092
+ * Binds the four ui helpers to one game. Type-only: the same four functions, plus the intrinsic
1093
+ * table this game's tags are checked against.
1094
+ *
1095
+ * @returns The helpers and the intrinsic type carrier.
1096
+ * @example
1097
+ * ```ts
1098
+ * const { defineStyle } = uiFor<"ui.coin", "digits", "hud.coins">();
1099
+ * defineStyle({ gap: 8 }).gap; // 8
1100
+ * ```
1101
+ */
1102
+ function uiFor() {
1103
+ return {
1104
+ defineComponent,
1105
+ defineStyle,
1106
+ defineTokens,
1107
+ popup,
1108
+ intrinsics: {}
1109
+ };
1110
+ }
1111
+ //#endregion
669
1112
  //#region src/plugins/ui/visual.ts
670
1113
  /**
671
1114
  * @file ui plugin — the look of an element: the visual component it is drawn with, and where a
@@ -919,4 +1362,4 @@ function drawnRect(pose, local) {
919
1362
  };
920
1363
  }
921
1364
  //#endregion
922
- export { Now as A, Sprite as C, sprite as D, componentsFor as E, resource as F, system as I, systemsFor as L, Tree as M, component as N, Exiting as O, mut as P, tag as R, Shape as S, arcDefaults as T, HudPart as _, scaleByFits as a, OverlayLevel as b, Countdown as c, builtInStyles as d, defineTextStyles as f, Display as g, textFor as h, samePose as i, Order as j, Layer as k, Text as l, readStyle as m, drawnRect as n, visualOf as o, label as p, fitScaleOf as r, visualRectOf as s, CONTENT as t, bind as u, NineSlice as v, Transform as w, Parent as x, Overlay as y };
1365
+ export { component as $, localPoseOf as A, OverlayLevel as B, builtInStyles as C, textFor as D, readStyle as E, rootPoseOf as F, arcDefaults as G, Shape as H, Display as I, Exiting as J, componentsFor as K, HudPart as L, poseUnder as M, rootPointOf as N, applyPose as O, rootPoseInto as P, Tree as Q, NineSlice as R, bind as S, label as T, Sprite as U, Parent as V, Transform as W, Now as X, Layer as Y, Order as Z, uiFor as _, visualOf as a, Countdown as b, Covered as c, LocalWrite as d, mut as et, Scroll as f, popup as g, UiCounters as h, samePose as i, tag as it, parentOf as j, isLeaving as k, DebugTrigger as l, UI_OWNER as m, drawnRect as n, system as nt, visualRectOf as o, ScrollState as p, sprite as q, fitScaleOf as r, systemsFor as rt, Box as s, CONTENT as t, resource as tt, Escapable as u, defineTokens as v, defineTextStyles as w, Text as x, defineStyle as y, Overlay as z };
package/dist/visual.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as read, t as sources } from "./sources-CJgUypyC.mjs";
1
+ import { n as read, t as sources } from "./sources-Fbq_PFVH.mjs";
2
2
  import { n as commands, t as run } from "./run-BqYmcNo7.mjs";
3
3
  import path from "node:path";
4
4
  import { createBrandConsole } from "@moku-labs/common/cli";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moku-labs/game",
3
- "version": "0.15.11",
3
+ "version": "0.15.12",
4
4
  "description": "2D puzzle game engine on TypeScript and PixiJS, built on @moku-labs/core.",
5
5
  "type": "module",
6
6
  "sideEffects": [