@moku-labs/game 0.4.6 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -192,7 +192,9 @@ createApp({ plugins: [...screen, effectsPlugin, audioPlugin, platformPlugin] });
192
192
  | `@moku-labs/game/assets` | Node and Bun | Asset keys, the manifest, strings, the pack |
193
193
  | `@moku-labs/game/inspect` | anywhere | Read a running game |
194
194
  | `@moku-labs/game/control` | dev builds | Drive a running game |
195
+ | `@moku-labs/game/hot` | the Bun dev server | The `bunfig.toml` plugin that hot swaps views. See [Hot swap](./docs/hot-swap.md) |
195
196
  | `@moku-labs/game/lint` | oxlint | The game lint rules, as an oxlint JS plugin |
197
+ | `@moku-labs/game/project` | Node and Bun | Where every engine id of a game is defined, line fresh at the call. The bin `moku-game-index`. See [Project index](./docs/project-index.md) |
196
198
  | `@moku-labs/game/jsx-runtime`, `/jsx-dev-runtime` | anywhere | The JSX runtime. A game never imports it by hand. |
197
199
 
198
200
  ### Lint for games
@@ -224,9 +226,11 @@ Each rule takes `{ "files": [...], "ignores": [...] }`. The defaults follow the
224
226
  | [Plugins](./docs/plugins.md) | The dependency graph, the plugin table, every root export |
225
227
  | [Interface in JSX](./docs/jsx.md) | Tags, components, styles, popups |
226
228
  | [Doors for the editor](./docs/doors.md) | `/inspect` and `/control`, base sources and commands |
229
+ | [Hot swap](./docs/hot-swap.md) | Save a view, see it in the running page, no reload |
227
230
  | [Events](./docs/events.md) | Every event and its payload |
228
231
  | [Configuration](./docs/configuration.md) | Every config field and its default |
229
232
  | [Lint for games](./docs/lint.md) | The `moku-game` oxlint rules, their options and defaults |
233
+ | [Project index](./docs/project-index.md) | `openProject`, the key scheme, `find` and `watch`, the `moku-game-index` bin |
230
234
  | [Testing](./docs/testing.md) | Headless and visual tests, all scripts, test layout, lint rules |
231
235
  | [`llms.txt`](./llms.txt) | The engine in one page, for an AI that writes a game |
232
236
 
@@ -248,11 +252,22 @@ bun run release # moku-release
248
252
 
249
253
  Every script is in [docs/testing.md](./docs/testing.md#scripts).
250
254
 
255
+ ### Hot swap
256
+
257
+ A save of a view file swaps it in the running page, with the same state. One line in the game's `bunfig.toml`:
258
+
259
+ ```toml
260
+ [serve.static]
261
+ plugins = ["@moku-labs/game/hot"]
262
+ ```
263
+
264
+ A save of a logic file reloads the page. What swaps and what reloads: [docs/hot-swap.md](./docs/hot-swap.md).
265
+
251
266
  ## Requirements
252
267
 
253
268
  - **Node `>= 24`** and **Bun `>= 1.3.14`**. Use `bun` only.
254
269
  - **TypeScript** in strict mode, with `exactOptionalPropertyTypes` and `noUncheckedIndexedAccess`.
255
- - **`pixi.js` `^8.0.0`** as a peer dependency. `playwright-core` for visual tests and `sharp` for the asset pack are optional peers. `yoga-layout` is loaded lazily by `ui`. The string compiler uses `@formatjs/icu-messageformat-parser` at build time only.
270
+ - **`pixi.js` `^8.0.0`** as a peer dependency. `playwright-core` for visual tests, `sharp` for the asset pack and `typescript` for the project index are optional peers. `yoga-layout` is loaded lazily by `ui`. The string compiler uses `@formatjs/icu-messageformat-parser` at build time only.
256
271
  - **[`@moku-labs/core`](https://github.com/moku-labs/core)** is the kernel. **[`@moku-labs/common`](https://github.com/moku-labs/common)** brings `log` and `env`.
257
272
 
258
273
  ## License
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bun
2
+ import { runCli } from "../dist/project.mjs";
3
+
4
+ process.exitCode = await runCli(process.argv.slice(2));
package/dist/assets.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { l as Manifest } from "./types-Dy1xB68L.mjs";
1
+ import { l as Manifest } from "./types-BMEn0tSC.mjs";
2
2
 
3
3
  //#region src/plugins/assets/scan/cli.d.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
- import { C as Captured, Et as Bookmark, T as DebugSwitches, Vt as Time, an as Api, k as Api$2, kt as FlowState, m as Api$1 } from "./types-Dy1xB68L.mjs";
2
- import { d as HeadlessApp, n as Command, r as ControlApp } from "./types-DtmFVCHf.mjs";
3
- import { H as InputApi } from "./types-VErbiEXy.mjs";
4
- import { G as UiApi, g as AnimApi, t as AudioApi } from "./types-C-4f2jD_.mjs";
1
+ import { C as Captured, Et as Bookmark, T as DebugSwitches, Vt as Time, an as Api, k as Api$2, kt as FlowState, m as Api$1 } from "./types-BMEn0tSC.mjs";
2
+ import { d as HeadlessApp, n as Command, r as ControlApp } from "./types-CYYKjvLn.mjs";
3
+ import { H as InputApi } from "./types-BaUUcIaN.mjs";
4
+ import { b as AnimApi, p as ScenesApi, t as AudioApi, v as UiApi } from "./types-CXyipKhE.mjs";
5
5
 
6
6
  //#region src/plugins/flow/doors/commands.d.ts
7
7
  /**
@@ -48,11 +48,19 @@ declare const commands: Readonly<{
48
48
  walk: Command<{
49
49
  route: "json";
50
50
  }, FlowState, ControlApp>;
51
- bookmark: Command<{}, Bookmark, ControlApp>;
51
+ bookmark: Command<{}, Bookmark, HeadlessApp & {
52
+ readonly log: import("@moku-labs/common/browser").LogApi;
53
+ } & {
54
+ readonly scenes?: ScenesApi;
55
+ }>;
52
56
  restore: Command<{
53
57
  bookmark: "json?";
54
58
  repro: "json?";
55
- }, FlowState, ControlApp>;
59
+ }, FlowState, HeadlessApp & {
60
+ readonly log: import("@moku-labs/common/browser").LogApi;
61
+ } & {
62
+ readonly scenes?: ScenesApi;
63
+ }>;
56
64
  step: Command<{
57
65
  frames: "number";
58
66
  deltaMs: "number?";
@@ -1,6 +1,6 @@
1
- import { d as HeadlessApp, i as InputArguments, n as Command, o as InputSchema, s as Ran } from "./types-DtmFVCHf.mjs";
2
- import { t as commands } from "./commands-C83eQ5B9.mjs";
3
- import { t as defineCommand } from "./define-BKWjWgyQ.mjs";
1
+ import { d as HeadlessApp, i as InputArguments, n as Command, o as InputSchema, s as Ran } from "./types-CYYKjvLn.mjs";
2
+ import { t as commands } from "./commands-mzE9PX0H.mjs";
3
+ import { t as defineCommand } from "./define-BbgXv4cy.mjs";
4
4
 
5
5
  //#region src/plugins/flow/doors/dev.d.ts
6
6
  /**
package/dist/control.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  import { t as controlRefused } from "./dev-wKLgOw7c.mjs";
2
- import { n as commands, t as run } from "./run-D_R0oJ6g.mjs";
2
+ import { n as commands, t as run } from "./run-Bcyg32M5.mjs";
3
3
  import { s as defineCommand } from "./input-CK4nxBO1.mjs";
4
4
  export { commands, controlRefused, defineCommand, run };
@@ -1,4 +1,4 @@
1
- import { c as Source, d as HeadlessApp, n as Command, o as InputSchema } from "./types-DtmFVCHf.mjs";
1
+ import { c as Source, d as HeadlessApp, n as Command, o as InputSchema } from "./types-CYYKjvLn.mjs";
2
2
 
3
3
  //#region src/plugins/flow/doors/define.d.ts
4
4
  /**
package/dist/hot.d.mts ADDED
@@ -0,0 +1,85 @@
1
+ //#region src/hot.d.ts
2
+ /**
3
+ * Which files get the hot swap footer. A file has to match `include` and must not match
4
+ * `exclude`. Only the game's own files can get it: the game root is the working directory of
5
+ * the dev server, and a file outside it (the engine source, a linked package) always loads
6
+ * unchanged.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // A game keeps its views in `look/` folders instead of `.tsx` files.
11
+ * const options: HotOptions = { include: /\/look\/.*\.ts$/ };
12
+ * ```
13
+ */
14
+ type HotOptions = {
15
+ /**
16
+ * The files that get the footer. Default: `.tsx` files, `styles.ts`, `view.ts`,
17
+ * `animations.ts`, `effects.ts` and `generated/strings.<locale>.ts`. Bun runs it as the load
18
+ * filter on the absolute path, so it should not anchor at the start.
19
+ */
20
+ include?: RegExp;
21
+ /**
22
+ * The files that load unchanged although they match `include`. Default: anything under
23
+ * `node_modules/`, `web/`, `generated/`, `__tests__/` or `tests/`, and `.test`/`.spec` files.
24
+ * Tested on the path relative to the game root with a leading `/` and `/` separators, also on
25
+ * Windows: `/features/home/view.tsx`. A folder above the game root never excludes a file. A
26
+ * `generated/strings.<locale>.ts` file is never excluded: the generated strings swap.
27
+ */
28
+ exclude?: RegExp;
29
+ };
30
+ /**
31
+ * The part of Bun's plugin builder the hot plugin uses. Bun's `PluginBuilder` fits it, so the
32
+ * shipped types need no `bun` import.
33
+ */
34
+ type HotBuild = {
35
+ /**
36
+ * Registers a load callback for the files whose path matches `filter`.
37
+ *
38
+ * @param options - The filter on the absolute path of a module.
39
+ * @param options.filter - Only a path that matches it loads through the callback.
40
+ * @param callback - Reads the module and returns its source and loader.
41
+ */
42
+ onLoad(options: {
43
+ filter: RegExp;
44
+ }, callback: (args: {
45
+ path: string;
46
+ }) => Promise<{
47
+ contents: string;
48
+ loader: "ts" | "tsx";
49
+ }>): void;
50
+ };
51
+ /**
52
+ * A Bun plugin object, as `[serve.static] plugins` in `bunfig.toml` loads it.
53
+ */
54
+ type HotPlugin = {
55
+ /** The plugin name Bun reports in its errors. */name: string;
56
+ /**
57
+ * Registers the load callback that appends the footer.
58
+ *
59
+ * @param build - Bun's plugin builder.
60
+ */
61
+ setup(build: HotBuild): void;
62
+ };
63
+ /**
64
+ * Creates the Bun plugin that hot swaps the views of a running game in the dev server. The
65
+ * default export is `hot()`; call it with options for another folder layout. The dev server runs
66
+ * in the game root: `exclude` is tested on the path relative to it, and a file outside it loads
67
+ * unchanged.
68
+ *
69
+ * @param options - The files that get the footer; both filters have defaults.
70
+ * @returns The Bun plugin object.
71
+ * @example
72
+ * ```ts
73
+ * // bunfig.toml of a game with the default layout:
74
+ * // [serve.static]
75
+ * // plugins = ["@moku-labs/game/hot"]
76
+ * // A game that keeps its views in `look/` folders exports its own plugin from `hot.ts`
77
+ * // and lists `plugins = ["./hot.ts"]` instead:
78
+ * export default hot({ include: /\/look\/.*\.ts$/ });
79
+ * ```
80
+ */
81
+ declare function hot(options?: HotOptions): HotPlugin;
82
+ /** The Bun plugin with the default filters, for `plugins = ["@moku-labs/game/hot"]` in `bunfig.toml`. */
83
+ declare const _default: HotPlugin;
84
+ //#endregion
85
+ export { HotBuild, HotOptions, HotPlugin, _default as default, hot };
package/dist/hot.mjs ADDED
@@ -0,0 +1,108 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ //#region src/hot.ts
4
+ /**
5
+ * @file Hot entry (subpath `./hot`): the Bun plugin of the dev server that hot swaps the views of
6
+ * a running game. It appends a footer to every view module it loads: the module accepts its own
7
+ * update and hands the new exports to the running game through `globalThis.__moku_hot`. The `ui`
8
+ * plugin installs that handler in dev builds only. What swaps: styles, components, projections,
9
+ * animations, text styles, emitters and generated strings. A view module is a `.tsx` file, a
10
+ * `styles.ts`, a `view.ts`, an `animations.ts`, an `effects.ts` or a generated
11
+ * `generated/strings.<locale>.ts`; a logic module never gets the footer, so its save reaches the
12
+ * root and the page reloads and restores its state. The plugin lives in `[serve.static]` of
13
+ * `bunfig.toml`, the dev server only: `Bun.build` of a production build never loads it.
14
+ */
15
+ /**
16
+ * The default view modules: `.tsx` files, `styles.ts`, `view.ts`, `animations.ts`, `effects.ts`
17
+ * and the generated strings of a locale.
18
+ */
19
+ const DEFAULT_INCLUDE = /(\.tsx|\/styles\.ts|\/view\.ts|\/animations\.ts|\/effects\.ts|\/generated\/strings\.[\w-]+\.ts)$/;
20
+ /** The generated strings of one locale, the one file under `generated/` that swaps. */
21
+ const STRINGS = /\/generated\/strings\.[\w-]+\.ts$/;
22
+ /** The default folders and test files that never hot swap. The outer group only scopes the `$`. */
23
+ const DEFAULT_EXCLUDE = /(\/(node_modules|web|generated|__tests__|tests)\/|\.(test|spec)\.tsx?$)/;
24
+ /**
25
+ * Gives the path of a module relative to the game root, the working directory of the dev server.
26
+ *
27
+ * @param file - The absolute path of the module.
28
+ * @param root - The game root.
29
+ * @returns The path with a leading `/` and `/` separators, or `undefined` outside the game root.
30
+ * @example
31
+ * ```ts
32
+ * gamePath("/work/tests/game/features/home/view.tsx", "/work/tests/game"); // "/features/home/view.tsx"
33
+ * ```
34
+ */
35
+ function gamePath(file, root) {
36
+ const inGame = path.relative(root, file).replaceAll("\\", "/");
37
+ if (inGame.startsWith("../") || path.isAbsolute(inGame)) return void 0;
38
+ return `/${inGame}`;
39
+ }
40
+ /**
41
+ * Builds the footer that makes a module accept its own update and hand it to the running game.
42
+ * Bun only sees `import.meta.hot.accept(...)` written out in full, so the footer never aliases it.
43
+ *
44
+ * @param file - The absolute path of the module.
45
+ * @returns The footer source, one line per statement.
46
+ * @example
47
+ * ```ts
48
+ * footerOf("/game/features/home/view.tsx").includes('swap(next, "/game/features/home/view.tsx");'); // true
49
+ * ```
50
+ */
51
+ function footerOf(file) {
52
+ return [
53
+ "if (import.meta.hot) {",
54
+ " import.meta.hot.accept();",
55
+ " import.meta.hot.accept(next => {",
56
+ " const swap = globalThis.__moku_hot;",
57
+ String.raw` if (typeof swap !== "function") throw new Error("[game] No running game takes the hot swap.\n Open the game page, then save again.");`,
58
+ ` swap(next, ${JSON.stringify(file)});`,
59
+ " });",
60
+ "}",
61
+ ""
62
+ ].join("\n");
63
+ }
64
+ /**
65
+ * Creates the Bun plugin that hot swaps the views of a running game in the dev server. The
66
+ * default export is `hot()`; call it with options for another folder layout. The dev server runs
67
+ * in the game root: `exclude` is tested on the path relative to it, and a file outside it loads
68
+ * unchanged.
69
+ *
70
+ * @param options - The files that get the footer; both filters have defaults.
71
+ * @returns The Bun plugin object.
72
+ * @example
73
+ * ```ts
74
+ * // bunfig.toml of a game with the default layout:
75
+ * // [serve.static]
76
+ * // plugins = ["@moku-labs/game/hot"]
77
+ * // A game that keeps its views in `look/` folders exports its own plugin from `hot.ts`
78
+ * // and lists `plugins = ["./hot.ts"]` instead:
79
+ * export default hot({ include: /\/look\/.*\.ts$/ });
80
+ * ```
81
+ */
82
+ function hot(options = {}) {
83
+ const include = options.include ?? DEFAULT_INCLUDE;
84
+ const exclude = options.exclude ?? DEFAULT_EXCLUDE;
85
+ return {
86
+ name: "@moku-labs/game/hot",
87
+ setup: (build) => {
88
+ build.onLoad({ filter: include }, async ({ path: file }) => {
89
+ const source = await readFile(file, "utf8");
90
+ const loader = file.endsWith(".tsx") ? "tsx" : "ts";
91
+ const inGame = gamePath(file, process.cwd());
92
+ const strings = STRINGS.test(inGame ?? "");
93
+ if (inGame === void 0 || !strings && exclude.test(inGame)) return {
94
+ contents: source,
95
+ loader
96
+ };
97
+ return {
98
+ contents: `${source}\n${footerOf(file)}`,
99
+ loader
100
+ };
101
+ });
102
+ }
103
+ };
104
+ }
105
+ /** The Bun plugin with the default filters, for `plugins = ["@moku-labs/game/hot"]` in `bunfig.toml`. */
106
+ var hot_default = hot();
107
+ //#endregion
108
+ export { hot_default as default, hot };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { $ as Ease, A as Config$8, B as ComponentValue, Bt as State$7, Ct as to, Dt as DefineNode, Ft as GuideOptions, G as Narrowed, Ht as types_d_exports$14, It as Hint, J as ResourceType, Jt as State$5, Kt as Json, L as ComponentHandle, M as State$8, Mt as SceneIdOf, N as types_d_exports$16, O as ViewportSize, Pt as Descriptor, Q as DescriptionNode, Rt as Api$5, S as types_d_exports$11, St as slot, Tt as FeatureDescription, W as Mut, Wt as Config$5, X as TagType, Xt as Patch, Y as SystemDefinition, Yt as types_d_exports$9, _n as Events$1, _t as State$3, a as DefineBundles, an as Api$3, at as ProjectionMotion, b as State$6, bt as defineFlow, c as LoadReason, cn as PauseReason, d as Tier, dn as Api$1, dt as BundlesOf, en as SaveUnreadableError, fn as Config$2, ft as Config$3, gn as Config$9, h as Config$6, hn as types_d_exports$3, ht as GameTypes, i as Config$1, it as NumericFields, k as Api$6, ln as State$4, m as Api$4, mn as State$2, mt as FeaturePlugin, n as BundleMap, nn as StoreApi, on as Config$4, ot as ProjectionSpec, p as types_d_exports$1, pt as EmitterIdOf, q as QueryTerm, qt as Root, r as BundleSpec, rn as RngApi, s as LoadBundles, sn as Events, t as Api, u as State$1, un as types_d_exports$8, ut as Api$2, vn as Require, vt as TextStylesOf, wt as type, xt as exit, yt as types_d_exports$5, z as ComponentType, zt as Config$7 } from "./types-Dy1xB68L.mjs";
2
- import { $ as SpriteValue, A as TextStyleInput, B as types_d_exports$6, C as Config$12, D as TextApi, E as State$11, F as Config$10, G as Display, H as InputApi, I as I18nApi, J as Parent, K as NineSlice, L as Message, M as TextValue, N as types_d_exports$13, O as TextBind, P as Argument, Q as SpriteOptions, R as State$9, S as BindOptions, T as Point, U as State$10, V as Config$11, W as types_d_exports$7, X as ShapeValue, Y as Shape, Z as Sprite, _ as Style, b as defineComponent, d as popup, et as Transform, f as defineTokens, g as ResolvedStyle, h as IsFlags, j as TextStyles, k as TextFormat, l as Box, nt as sprite, p as IntrinsicElementsFor, q as NineSliceValue, s as PopupComponent, tt as TransformValue, u as LocalWrite, w as CountdownValue, x as BindField, y as WhenFlags, z as TypedTr } from "./types-VErbiEXy.mjs";
3
- import { A as haptic, B as tween, C as HapticKind, D as defineAnimation, E as HAPTIC_KINDS, F as set, G as UiApi, H as wait, I as sfx, K as types_d_exports$15, L as spawn, M as parallel, N as play, O as external, P as sequence, R as spawned, S as types_d_exports, T as Step, U as Config$15, V as use, W as State$15, _ as Config$13, b as State$12, c as AnySceneProjection, d as SceneDefinition, f as SceneSpec, g as AnimApi, h as types_d_exports$12, i as MusicOptions, j as mark, k as frames, l as DefineScene, m as State$14, n as Config$14, o as State$13, p as ScenesApi, r as MusicDescriptor, s as types_d_exports$2, t as AudioApi, u as LayerMap, v as FramesValue, w as SfxDescriptor, x as Target, y as MotionKeyframe, z as stagger } from "./types-C-4f2jD_.mjs";
4
- import { _ as NoiseValue, a as types_d_exports$4, c as EmitterValue, d as ColorMatrixValue, f as DisplacementValue, g as GlowValue, h as FilterValueOf, i as State$16, l as AlphaValue, m as FilterSpec, n as EffectsApi, o as EmitterConfig, p as FilterComponent, s as EmitterDefinition, t as Config$16, u as BlurValue, v as OutlineValue, y as UniformDeclaration } from "./types-w646dMeA.mjs";
1
+ import { $ as Ease, A as Config$8, B as ComponentValue, Bt as State$7, Ct as to, Dt as DefineNode, Ft as GuideOptions, G as Narrowed, Ht as types_d_exports$14, It as Hint, J as ResourceType, Jt as State$5, Kt as Json, L as ComponentHandle, M as State$8, Mt as SceneIdOf, N as types_d_exports$16, O as ViewportSize, Pt as Descriptor, Q as DescriptionNode, Rt as Api$5, S as types_d_exports$11, St as slot, Tt as FeatureDescription, W as Mut, Wt as Config$5, X as TagType, Xt as Patch, Y as SystemDefinition, Yt as types_d_exports$9, _n as Events$1, _t as State$3, a as DefineBundles, an as Api$3, at as ProjectionMotion, b as State$6, bt as defineFlow, c as LoadReason, cn as PauseReason, d as Tier, dn as Api$1, dt as BundlesOf, en as SaveUnreadableError, fn as Config$2, ft as Config$3, gn as Config$9, h as Config$6, hn as types_d_exports$3, ht as GameTypes, i as Config$1, it as NumericFields, k as Api$6, ln as State$4, m as Api$4, mn as State$2, mt as FeaturePlugin, n as BundleMap, nn as StoreApi, on as Config$4, ot as ProjectionSpec, p as types_d_exports$1, pt as EmitterIdOf, q as QueryTerm, qt as Root, r as BundleSpec, rn as RngApi, s as LoadBundles, sn as Events, t as Api, u as State$1, un as types_d_exports$8, ut as Api$2, vn as Require, vt as TextStylesOf, wt as type, xt as exit, yt as types_d_exports$5, z as ComponentType, zt as Config$7 } from "./types-BMEn0tSC.mjs";
2
+ import { $ as SpriteValue, A as TextStyleInput, B as types_d_exports$6, C as Config$12, D as TextApi, E as State$11, F as Config$10, G as Display, H as InputApi, I as I18nApi, J as Parent, K as NineSlice, L as Message, M as TextValue, N as types_d_exports$13, O as TextBind, P as Argument, Q as SpriteOptions, R as State$9, S as BindOptions, T as Point, U as State$10, V as Config$11, W as types_d_exports$7, X as ShapeValue, Y as Shape, Z as Sprite, _ as Style, b as defineComponent, d as popup, et as Transform, f as defineTokens, g as ResolvedStyle, h as IsFlags, j as TextStyles, k as TextFormat, l as Box, nt as sprite, p as IntrinsicElementsFor, q as NineSliceValue, s as PopupComponent, tt as TransformValue, u as LocalWrite, w as CountdownValue, x as BindField, y as WhenFlags, z as TypedTr } from "./types-BaUUcIaN.mjs";
3
+ import { A as HAPTIC_KINDS, B as sfx, C as MotionKeyframe, D as HapticKind, E as types_d_exports, F as mark, G as use, H as spawned, I as parallel, K as wait, L as play, M as external, N as frames, O as SfxDescriptor, P as haptic, R as sequence, S as FramesValue, T as Target, U as stagger, V as spawn, W as tween, _ as State$15, b as AnimApi, c as AnySceneProjection, d as SceneDefinition, f as SceneSpec, g as Config$15, h as types_d_exports$12, i as MusicOptions, j as defineAnimation, k as Step, l as DefineScene, m as State$14, n as Config$14, o as State$13, p as ScenesApi, r as MusicDescriptor, s as types_d_exports$2, t as AudioApi, u as LayerMap, v as UiApi, w as State$12, x as Config$13, y as types_d_exports$15, z as set } from "./types-CXyipKhE.mjs";
4
+ import { _ as NoiseValue, a as types_d_exports$4, c as EmitterValue, d as ColorMatrixValue, f as DisplacementValue, g as GlowValue, h as FilterValueOf, i as State$16, l as AlphaValue, m as FilterSpec, n as EffectsApi, o as EmitterConfig, p as FilterComponent, s as EmitterDefinition, t as Config$16, u as BlurValue, v as OutlineValue, y as UniformDeclaration } from "./types-ClF8say0.mjs";
5
5
  import { Log } from "@moku-labs/common/browser";
6
6
  import { PluginCtx } from "@moku-labs/core";
7
7