@dxos/plugin-game 0.10.0 → 0.11.1

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 (102) hide show
  1. package/dist/lib/GamePlugin.mjs +18 -0
  2. package/dist/lib/GamePlugin.mjs.map +1 -0
  3. package/dist/lib/GamePlugin.node.mjs +17 -0
  4. package/dist/lib/GamePlugin.node.mjs.map +1 -0
  5. package/dist/lib/GamePlugin.workerd.mjs +10 -0
  6. package/dist/lib/GamePlugin.workerd.mjs.map +1 -0
  7. package/dist/lib/capabilities.mjs +8 -0
  8. package/dist/lib/capabilities.mjs.map +1 -0
  9. package/dist/lib/chunk-GameArticle.mjs +33 -0
  10. package/dist/lib/chunk-GameArticle.mjs.map +1 -0
  11. package/dist/lib/chunk-GameCard.mjs +26 -0
  12. package/dist/lib/chunk-GameCard.mjs.map +1 -0
  13. package/dist/lib/chunk-create-object.mjs +45 -0
  14. package/dist/lib/chunk-create-object.mjs.map +1 -0
  15. package/dist/lib/chunk-load-game.mjs +38 -0
  16. package/dist/lib/chunk-load-game.mjs.map +1 -0
  17. package/dist/lib/{neutral/chunk-R4V5PVU7.mjs → chunk-meta.mjs} +20 -28
  18. package/dist/lib/chunk-meta.mjs.map +1 -0
  19. package/dist/lib/chunk-react-surface.mjs +29 -0
  20. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  21. package/dist/lib/chunk-types.mjs +83 -0
  22. package/dist/lib/chunk-types.mjs.map +1 -0
  23. package/dist/lib/components.mjs +82 -0
  24. package/dist/lib/components.mjs.map +1 -0
  25. package/dist/lib/containers.mjs +8 -0
  26. package/dist/lib/containers.mjs.map +1 -0
  27. package/dist/lib/index.mjs +4 -0
  28. package/dist/lib/meta.mjs +2 -0
  29. package/dist/lib/plugin.mjs +8 -0
  30. package/dist/lib/plugin.mjs.map +1 -0
  31. package/dist/lib/translations.mjs +28 -0
  32. package/dist/lib/translations.mjs.map +1 -0
  33. package/dist/lib/types.mjs +3 -0
  34. package/dist/lib/util.mjs +2 -0
  35. package/dist/types/src/GamePlugin.workerd.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/create-object.d.ts +1 -1
  37. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  38. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  39. package/dist/types/src/components/CreateGamePanel.stories.d.ts.map +1 -1
  40. package/dist/types/src/containers/GameArticle/GameArticle.d.ts +5 -2
  41. package/dist/types/src/containers/GameArticle/GameArticle.d.ts.map +1 -1
  42. package/dist/types/src/containers/GameCard/GameCard.d.ts +5 -2
  43. package/dist/types/src/containers/GameCard/GameCard.d.ts.map +1 -1
  44. package/dist/types/src/types/Game.d.ts.map +1 -1
  45. package/dist/types/src/types/index.d.ts +1 -1
  46. package/dist/types/src/types/index.d.ts.map +1 -1
  47. package/dist/types/src/types/types.d.ts +9 -5
  48. package/dist/types/src/types/types.d.ts.map +1 -1
  49. package/dist/types/src/util/load-game.d.ts +3 -3
  50. package/dist/types/src/util/load-game.d.ts.map +1 -1
  51. package/dist/types/tsconfig.tsbuildinfo +1 -1
  52. package/dx.config.ts +1 -0
  53. package/package.json +34 -33
  54. package/src/GamePlugin.node.tsx +1 -1
  55. package/src/GamePlugin.tsx +1 -1
  56. package/src/GamePlugin.workerd.tsx +1 -1
  57. package/src/capabilities/create-object.ts +3 -3
  58. package/src/capabilities/{react-surface.tsx → react-surface.ts} +7 -8
  59. package/src/components/CreateGamePanel.stories.tsx +2 -1
  60. package/src/containers/GameArticle/GameArticle.tsx +7 -9
  61. package/src/containers/GameCard/GameCard.tsx +7 -7
  62. package/src/translations.ts +1 -1
  63. package/src/types/Game.ts +4 -2
  64. package/src/types/index.ts +1 -1
  65. package/src/types/types.ts +9 -5
  66. package/src/util/load-game.ts +3 -3
  67. package/dist/lib/neutral/GameArticle-AUJ4YDKW.mjs +0 -40
  68. package/dist/lib/neutral/GameArticle-AUJ4YDKW.mjs.map +0 -7
  69. package/dist/lib/neutral/GameCard-QBKHIL4Q.mjs +0 -32
  70. package/dist/lib/neutral/GameCard-QBKHIL4Q.mjs.map +0 -7
  71. package/dist/lib/neutral/GamePlugin.mjs +0 -38
  72. package/dist/lib/neutral/GamePlugin.mjs.map +0 -7
  73. package/dist/lib/neutral/GamePlugin.node.mjs +0 -21
  74. package/dist/lib/neutral/GamePlugin.node.mjs.map +0 -7
  75. package/dist/lib/neutral/GamePlugin.workerd.mjs +0 -18
  76. package/dist/lib/neutral/GamePlugin.workerd.mjs.map +0 -7
  77. package/dist/lib/neutral/capabilities/index.mjs +0 -11
  78. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  79. package/dist/lib/neutral/chunk-DSUJWWNN.mjs +0 -98
  80. package/dist/lib/neutral/chunk-DSUJWWNN.mjs.map +0 -7
  81. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  82. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  83. package/dist/lib/neutral/chunk-R4V5PVU7.mjs.map +0 -7
  84. package/dist/lib/neutral/components/index.mjs +0 -96
  85. package/dist/lib/neutral/components/index.mjs.map +0 -7
  86. package/dist/lib/neutral/containers/index.mjs +0 -11
  87. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  88. package/dist/lib/neutral/create-object-NXKZWZLR.mjs +0 -51
  89. package/dist/lib/neutral/create-object-NXKZWZLR.mjs.map +0 -7
  90. package/dist/lib/neutral/index.mjs +0 -24
  91. package/dist/lib/neutral/index.mjs.map +0 -7
  92. package/dist/lib/neutral/meta.json +0 -1
  93. package/dist/lib/neutral/meta.mjs +0 -8
  94. package/dist/lib/neutral/meta.mjs.map +0 -7
  95. package/dist/lib/neutral/plugin.mjs +0 -12
  96. package/dist/lib/neutral/plugin.mjs.map +0 -7
  97. package/dist/lib/neutral/react-surface-GO3SKEMA.mjs +0 -35
  98. package/dist/lib/neutral/react-surface-GO3SKEMA.mjs.map +0 -7
  99. package/dist/lib/neutral/translations.mjs +0 -34
  100. package/dist/lib/neutral/translations.mjs.map +0 -7
  101. package/dist/lib/neutral/types/index.mjs +0 -20
  102. package/dist/lib/neutral/types/index.mjs.map +0 -7
@@ -0,0 +1,18 @@
1
+ import { Plugin } from "@dxos/app-framework";
2
+ import { meta } from "#meta";
3
+ import { AppPlugin } from "@dxos/app-toolkit";
4
+ import { CreateObject, ReactSurface } from "#capabilities";
5
+ import { translations } from "#translations";
6
+ import { Game } from "#types";
7
+ //#endregion
8
+ //#region src/GamePlugin.tsx
9
+ var GamePlugin = Plugin.define(meta).pipe(AppPlugin.addCreateObjectModule({ activate: CreateObject }), AppPlugin.addSchemaModule({ schema: [Game.Game] }), AppPlugin.addSurfaceModule({ activate: ReactSurface }), AppPlugin.addTranslationsModule({ translations }), AppPlugin.addPluginAssetModule({ asset: {
10
+ pluginId: meta.profile.key,
11
+ path: "PLUGIN.mdl",
12
+ content: "---\nid: org.dxos.plugin.game\nname: GamePlugin\nversion: 0.1.0\n---\n\nA generic game host plugin for `DXOS` Composer that provides shared infrastructure for\nmulti-player, local-first turn-based games. Variant plugins (e.g. plugin-chess,\nplugin-tictactoe) contribute a `GameVariant` capability and game-specific surfaces;\nplugin-game supplies the `Game` ECHO type, create flow, and dispatch scaffolding.\n\n## Extensions\n\nThe following extension dialects are used in this document.\nEach extension is defined in the Appendix or resolved via its URI.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `test` | `org.dxos.mdl.test@1.0` |\n| `component` | `org.dxos.mdl.component@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n\n## Types\n\n```mdl\ntype Player\n fields:\n role: string # variant-defined (e.g. \"white\", \"x\"); required\n identity?: string # DID of a human player; absent for AI / empty seats\n name?: string # display label for AI or guest players\n```\n\n```mdl\ntype Game\n fields:\n name?: string\n players?: Player[] # populated during or after creation\n variant: Ref<Unknown> # reference to variant-specific state object (e.g. Chess.State)\n typename: org.dxos.type.game\n version: 0.1.0\n```\n\n```mdl\ntype GameVariant\n desc: |\n Contribution interface from a variant plugin. Registered via\n `Capability.contributes(GameCapabilities.VariantProvider, variant)`.\n fields:\n id: string # stable variant id; matches the variant state typename\n label: string # human-readable name shown in the picker\n icon?: string # Phosphor icon name\n variantSchema: Schema # Effect/Schema for the ECHO state object\n inputSchema?: Schema # optional form schema shown after variant is selected\n roles: string[] # player roles (e.g. [\"white\", \"black\"])\n createVariant: Effect # factory that builds the variant ECHO state object\n card?: ComponentType # optional Card surface component\n article?: ComponentType # optional Article/Section surface component\n```\n\n## Components\n\n```mdl\ncomponent CreateGamePanel\n desc: |\n Two-stage creation panel. Stage 1 shows a searchable variant picker.\n Stage 2 (optional) shows a form rendered from the variant's inputSchema.\n props:\n target: Space | Obj\n onCreateObject: (args: { variantId: string; input?: Record }) => void\n variants?: GameVariant[] # override; defaults to GameCapabilities.VariantProvider\n state:\n selectedId?: string # id of the variant chosen in stage 1\n actions:\n selectVariant(id: string)\n submitForm(input: Record)\n layout: |\n ┌─────────────────────────┐\n │ Stage 1: Variant Picker │\n │ ┌───────────────────┐ │\n │ │ Search input │ │\n │ ├───────────────────┤ │\n │ │ variant row │ │\n │ │ variant row │ │\n │ └───────────────────┘ │\n ├─────────────────────────┤\n │ Stage 2: Input Form │\n │ (rendered from schema) │\n │ [Submit] │\n └─────────────────────────┘\n```\n\n```mdl\ncomponent GameArticle\n desc: |\n Article / Section surface for Game objects. Resolves the variant via\n `game.variant` ref, finds the matching `GameVariant` by typename, and\n delegates rendering to `variant.article`.\n props:\n game: Game\n role?: string\n attendableId?: string\n state:\n variant: Unknown # live variant state object from the Ref\n match?: GameVariant # resolved GameVariant from capabilities\n layout: |\n ┌─────────────────────────┐\n │ [variant.article] │\n │ (fallback: unsupported │\n │ variant message) │\n └─────────────────────────┘\n```\n\n```mdl\ncomponent GameCard\n desc: |\n Card surface for Game objects. Follows the same variant-resolution\n logic as GameArticle and delegates to `variant.card`.\n props:\n game: Game\n role?: string\n state:\n variant: Unknown\n match?: GameVariant\n```\n\n## Operations\n\n```mdl\nop createGame\n desc: |\n Creates a variant state object via `variant.createVariant`, adds it\n to the space as a hidden object, then wraps it in a top-level Game.\n If the second write fails the variant state object is rolled back.\n input:\n variantId: string\n input?: Record # variant-specific form values\n target: Space | Obj\n targetNodeId?: string\n output: Game\n errors:\n UnknownVariant: no registered GameVariant matches variantId\n effects: [echo:write]\n requires: [GameCapabilities.VariantProvider, SpaceOperation.AddObject, SpaceOperation.RemoveObjects]\n note: |\n Invoked by CreateObjectEntry.createObject.\n Variant state is added with `hidden: true` so it does not appear\n as a top-level item in the user's space graph.\n```\n\n## Features\n\n```mdl\nfeat F-1: Variant Registration\n\n req F-1.1:\n when: a variant plugin loads\n then: it contributes a GameVariant via `Capability.contributes(GameCapabilities.VariantProvider, …)`\n\n req F-1.2:\n when: GameCapabilities.VariantProvider contributions are queried\n then: all registered variants are returned as an ordered list\n```\n\n```mdl\nfeat F-2: Game Creation\n\n req F-2.1:\n when: user opens the create-object flow for type `org.dxos.type.game`\n then: CreateGamePanel is shown with a searchable list of available variants\n\n req F-2.2:\n when: user selects a variant with no inputSchema\n then: op:createGame is invoked immediately with empty input\n\n req F-2.3:\n when: user selects a variant that has an inputSchema\n then: a form rendered from the schema is shown; op:createGame is invoked on submit\n\n req F-2.4:\n when: op:createGame completes\n then: a Game object appears in the space graph; variant state is hidden\n```\n\n```mdl\nfeat F-3: Game Article / Card Rendering\n\n req F-3.1:\n when: Composer navigates to a Game object\n then: GameArticle resolves `game.variant` and delegates to the matching `variant.article`\n\n req F-3.2:\n when: a Game object is shown in a Card layout\n then: GameCard resolves `game.variant` and delegates to `variant.card`\n\n req F-3.3:\n when: no matching variant is found for the loaded state object\n then: GameArticle renders an \"Unsupported game variant\" fallback message\n\n req F-3.4:\n when: the variant ref is not yet loaded\n then: neither GameArticle nor GameCard renders (returns null)\n```\n\n## Acceptance\n\n```mdl\ntest T-1: Variant picker shows all contributions\n given: two variant plugins have contributed GameVariants\n when: the user opens the create-game panel\n then:\n - CreateGamePanel lists both variants\n - variants are sorted alphabetically\n```\n\n```mdl\ntest T-2: Create game without form\n given: a variant with no inputSchema is selected\n when: user clicks the variant item\n then:\n - onCreateObject is called immediately with { variantId }\n - no form is shown\n```\n\n```mdl\ntest T-3: Create game with form\n given: a variant with an inputSchema is selected\n when: user fills and submits the form\n then:\n - onCreateObject is called with { variantId, input: <form values> }\n```\n\n```mdl\ntest T-4: Atomic game creation\n given: a valid variantId and target space\n when: op:createGame is invoked\n then:\n - variant state object added to space (hidden)\n - Game object added with game.variant pointing to the state object\n - both writes are visible to other peers via ECHO replication\n```\n\n```mdl\ntest T-5: Rollback on second write failure\n given: variant state is successfully written\n when: the second write (Game object) fails\n then:\n - RemoveObjects is invoked for the variant state\n - no orphaned state object remains in the space\n```\n\n```mdl\ntest T-6: Unknown variant rejected\n given: op:createGame is invoked with an unregistered variantId\n when: the handler runs\n then: UnknownVariant error is returned; no ECHO writes occur\n```\n\n```mdl\ntest T-7: Unsupported variant fallback\n given: a Game whose variant typename has no registered GameVariant\n when: GameArticle renders\n then: \"Unsupported game variant\" message is shown instead of crashing\n```\n\n---\n\n## Appendix: Extension Definitions\n\nExtension block types used in this document are defined below using\nthe core `ext` primitive — the only construct the base language provides.\n\n```mdl\next type\n uri: org.dxos.mdl.type@1.0\n desc: A named data structure with typed fields and optional literals.\n fields:\n desc?: Prose\n fields?: FieldMap # name[?]: TypeExpr (# inline comment)\n literals?: UnionList # a | b | c\n extends?: TypeRef[]\n```\n\n```mdl\next feat\n uri: org.dxos.mdl.feat@1.0\n desc: A named feature grouping one or more requirements.\n fields:\n desc?: Prose\n req: RequirementList\n nesting: self # feat blocks may contain feat blocks\n```\n\n```mdl\next test\n uri: org.dxos.mdl.test@1.0\n desc: An acceptance scenario expressed as given / when / then steps.\n fields:\n given?: Step | Step[]\n when?: Step | Step[]\n then: Step | Step[]\n tags?: TagList\n```\n\n```mdl\next component\n uri: org.dxos.mdl.component@1.0\n desc: A UI component with props, internal state, slots, actions, and events.\n fields:\n desc?: Prose\n props?: FieldMap # external inputs (immutable inside component)\n state?: FieldMap # internal reactive state\n slots?: FieldMap # named ReactNode injection points\n actions?: ActionMap # methods the component exposes or handles\n emits?: EventMap # events the component raises to its parent\n layout?: CodeBlock # ASCII sketch of visual structure (non-normative)\n```\n\n```mdl\next op\n uri: org.dxos.mdl.op@1.0\n desc: |\n A named operation with typed inputs, outputs, and declared errors.\n Pure ops have no effects or requires. Effectful ops declare both.\n fields:\n desc?: Prose\n input?: FieldMap # named input parameters\n output?: TypeExpr # return type\n errors?: ErrorMap # name: Prose (when this error occurs)\n effects?: EffectList # echo:read | echo:write | http | fs | ...\n requires?: ServiceList # injected service dependencies\n note?: Prose # implementation guidance (non-normative)\n```\n",
13
+ mimeType: "application/x-mdl"
14
+ } }), Plugin.make);
15
+ //#endregion
16
+ export { GamePlugin, GamePlugin as default };
17
+
18
+ //# sourceMappingURL=GamePlugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GamePlugin.mjs","names":[],"sources":["../../src/GamePlugin.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\n\nimport { CreateObject, ReactSurface } from '#capabilities';\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { Game } from '#types';\n\n// eslint-disable-next-line import/no-relative-packages\nimport pluginSpec from '../PLUGIN.mdl?raw';\n\nexport const GamePlugin = Plugin.define(meta).pipe(\n AppPlugin.addCreateObjectModule({ activate: CreateObject }),\n AppPlugin.addSchemaModule({ schema: [Game.Game] }),\n AppPlugin.addSurfaceModule({ activate: ReactSurface }),\n AppPlugin.addTranslationsModule({ translations }),\n AppPlugin.addPluginAssetModule({\n asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },\n }),\n Plugin.make,\n);\n\nexport default GamePlugin;\n"],"mappings":";;;;;;;;AAeA,IAAa,aAAa,OAAO,OAAO,IAAI,CAAC,CAAC,KAC5C,UAAU,sBAAsB,EAAE,UAAU,aAAa,CAAC,GAC1D,UAAU,gBAAgB,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,GACjD,UAAU,iBAAiB,EAAE,UAAU,aAAa,CAAC,GACrD,UAAU,sBAAsB,EAAE,aAAa,CAAC,GAChD,UAAU,qBAAqB,EAC7B,OAAO;CAAE,UAAU,KAAK,QAAQ;CAAK,MAAM;CAAc,SAAS;CAAY,UAAU;AAAoB,EAC9G,CAAC,GACD,OAAO,IACT"}
@@ -0,0 +1,17 @@
1
+ import { Plugin } from "@dxos/app-framework";
2
+ import { meta } from "#meta";
3
+ import { AppPlugin } from "@dxos/app-toolkit";
4
+ import { translations } from "#translations";
5
+ import { Game } from "#types";
6
+ //#region src/GamePlugin.node.tsx
7
+ /**
8
+ * Headless variant of GamePlugin (no React surfaces / CreateObject panel).
9
+ * Used in node contexts (CLI, agents, tests) where rendering is unavailable —
10
+ * the full variant lazy-loads `CreateGamePanel` from `react-ui-search` which
11
+ * downstream bundlers don't resolve cleanly under nested pnpm symlinks.
12
+ */
13
+ var GamePlugin = Plugin.define(meta).pipe(AppPlugin.addSchemaModule({ schema: [Game.Game] }), AppPlugin.addTranslationsModule({ translations }), Plugin.make);
14
+ //#endregion
15
+ export { GamePlugin, GamePlugin as default };
16
+
17
+ //# sourceMappingURL=GamePlugin.node.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GamePlugin.node.mjs","names":[],"sources":["../../src/GamePlugin.node.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\n\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { Game } from '#types';\n\n/**\n * Headless variant of GamePlugin (no React surfaces / CreateObject panel).\n * Used in node contexts (CLI, agents, tests) where rendering is unavailable —\n * the full variant lazy-loads `CreateGamePanel` from `react-ui-search` which\n * downstream bundlers don't resolve cleanly under nested pnpm symlinks.\n */\nexport const GamePlugin = Plugin.define(meta).pipe(\n AppPlugin.addSchemaModule({ schema: [Game.Game] }),\n AppPlugin.addTranslationsModule({ translations }),\n Plugin.make,\n);\n\nexport default GamePlugin;\n"],"mappings":";;;;;;;;;;;;AAiBA,IAAa,aAAa,OAAO,OAAO,IAAI,CAAC,CAAC,KAC5C,UAAU,gBAAgB,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,GACjD,UAAU,sBAAsB,EAAE,aAAa,CAAC,GAChD,OAAO,IACT"}
@@ -0,0 +1,10 @@
1
+ import { Plugin } from "@dxos/app-framework";
2
+ import { meta } from "#meta";
3
+ import { AppPlugin } from "@dxos/app-toolkit";
4
+ import { Game } from "#types";
5
+ //#region src/GamePlugin.workerd.tsx
6
+ var GamePlugin = Plugin.define(meta).pipe(AppPlugin.addSchemaModule({ schema: [Game.Game] }), Plugin.make);
7
+ //#endregion
8
+ export { GamePlugin, GamePlugin as default };
9
+
10
+ //# sourceMappingURL=GamePlugin.workerd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GamePlugin.workerd.mjs","names":[],"sources":["../../src/GamePlugin.workerd.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\n\nimport { meta } from '#meta';\nimport { Game } from '#types';\n\nexport const GamePlugin = Plugin.define(meta).pipe(AppPlugin.addSchemaModule({ schema: [Game.Game] }), Plugin.make);\n\nexport default GamePlugin;\n"],"mappings":";;;;;AAUA,IAAa,aAAa,OAAO,OAAO,IAAI,CAAC,CAAC,KAAK,UAAU,gBAAgB,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,OAAO,IAAI"}
@@ -0,0 +1,8 @@
1
+ import { Capability } from "@dxos/app-framework";
2
+ //#region src/capabilities/index.ts
3
+ var CreateObject = Capability.lazy("CreateObject", () => import("./chunk-create-object.mjs"));
4
+ var ReactSurface = Capability.lazy("ReactSurface", () => import("./chunk-react-surface.mjs"));
5
+ //#endregion
6
+ export { CreateObject, ReactSurface };
7
+
8
+ //# sourceMappingURL=capabilities.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.mjs","names":[],"sources":["../../src/capabilities/index.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\n\nexport const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));\nexport const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));\n"],"mappings":";;AAMA,IAAa,eAAe,WAAW,KAAK,sBAAsB,OAAO,4BAAkB;AAC3F,IAAa,eAAe,WAAW,KAAK,sBAAsB,OAAO,4BAAkB"}
@@ -0,0 +1,33 @@
1
+ import { Obj } from "@dxos/echo";
2
+ import { meta } from "#meta";
3
+ import { GameCapabilities } from "#types";
4
+ import "react";
5
+ import { useCapabilities } from "@dxos/app-framework/ui";
6
+ import { useTranslation } from "@dxos/react-ui";
7
+ import { jsx } from "react/jsx-runtime";
8
+ import { useResolveRef } from "@dxos/echo-react";
9
+ //#region src/containers/GameArticle/GameArticle.tsx
10
+ var GameArticle = ({ role, attendableId, subject: game }) => {
11
+ const { t } = useTranslation(meta.profile.key);
12
+ const variants = useCapabilities(GameCapabilities.VariantProvider);
13
+ const variant = useResolveRef(game.variant);
14
+ if (!variant) return null;
15
+ const variantTypename = Obj.getTypename(variant);
16
+ const match = variants.find((v) => v.id === variantTypename);
17
+ if (!match?.article) return /* @__PURE__ */ jsx("div", {
18
+ className: "p-4 text-sm",
19
+ children: t("unsupported-variant.label", { defaultValue: "Unsupported game variant" })
20
+ });
21
+ const Component = match.article;
22
+ return /* @__PURE__ */ jsx(Component, {
23
+ game,
24
+ variant,
25
+ role,
26
+ attendableId
27
+ });
28
+ };
29
+ GameArticle.displayName = "GameArticle";
30
+ //#endregion
31
+ export { GameArticle as default };
32
+
33
+ //# sourceMappingURL=chunk-GameArticle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-GameArticle.mjs","names":[],"sources":["../../src/containers/GameArticle/GameArticle.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/ui';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Obj } from '@dxos/echo';\nimport { useResolveRef } from '@dxos/echo-react';\nimport { useTranslation } from '@dxos/react-ui';\n\nimport { meta } from '#meta';\nimport { type Game, GameCapabilities } from '#types';\n\nexport type GameArticleProps = AppSurface.ObjectArticleProps<Game.Game>;\n\nexport const GameArticle = ({ role, attendableId, subject: game }: GameArticleProps) => {\n const { t } = useTranslation(meta.profile.key);\n const variants = useCapabilities(GameCapabilities.VariantProvider);\n // Resolved live rather than as a snapshot: variants mutate their state, and a snapshot is frozen.\n const variant = useResolveRef(game.variant);\n\n if (!variant) {\n return null;\n }\n\n const variantTypename = Obj.getTypename(variant);\n const match = variants.find((v) => v.id === variantTypename);\n if (!match?.article) {\n return (\n <div className='p-4 text-sm'>{t('unsupported-variant.label', { defaultValue: 'Unsupported game variant' })}</div>\n );\n }\n\n const Component = match.article;\n return <Component game={game} variant={variant} role={role} attendableId={attendableId} />;\n};\n\nGameArticle.displayName = 'GameArticle';\n"],"mappings":";;;;;;;;;AAiBA,IAAa,eAAe,EAAE,MAAM,cAAc,SAAS,WAA6B;CACtF,MAAM,EAAE,MAAM,eAAe,KAAK,QAAQ,GAAG;CAC7C,MAAM,WAAW,gBAAgB,iBAAiB,eAAe;CAEjE,MAAM,UAAU,cAAc,KAAK,OAAO;CAE1C,IAAI,CAAC,SACH,OAAO;CAGT,MAAM,kBAAkB,IAAI,YAAY,OAAO;CAC/C,MAAM,QAAQ,SAAS,MAAM,MAAM,EAAE,OAAO,eAAe;CAC3D,IAAI,CAAC,OAAO,SACV,OACE,oBAAC,OAAD;EAAK,WAAU;YAAe,EAAE,6BAA6B,EAAE,cAAc,2BAA2B,CAAC;CAAO,CAAA;CAIpH,MAAM,YAAY,MAAM;CACxB,OAAO,oBAAC,WAAD;EAAiB;EAAe;EAAe;EAAoB;CAAe,CAAA;AAC3F;AAEA,YAAY,cAAc"}
@@ -0,0 +1,26 @@
1
+ import { Obj } from "@dxos/echo";
2
+ import { GameCapabilities } from "#types";
3
+ import "react";
4
+ import { useCapabilities } from "@dxos/app-framework/ui";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import { useResolveRef } from "@dxos/echo-react";
7
+ //#region src/containers/GameCard/GameCard.tsx
8
+ var GameCard = ({ role, subject: game }) => {
9
+ const variants = useCapabilities(GameCapabilities.VariantProvider);
10
+ const variant = useResolveRef(game.variant);
11
+ if (!variant) return null;
12
+ const variantTypename = Obj.getTypename(variant);
13
+ const match = variants.find((v) => v.id === variantTypename);
14
+ if (!match?.card) return null;
15
+ const Component = match.card;
16
+ return /* @__PURE__ */ jsx(Component, {
17
+ game,
18
+ variant,
19
+ role
20
+ });
21
+ };
22
+ GameCard.displayName = "GameCard";
23
+ //#endregion
24
+ export { GameCard as default };
25
+
26
+ //# sourceMappingURL=chunk-GameCard.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-GameCard.mjs","names":[],"sources":["../../src/containers/GameCard/GameCard.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/ui';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Obj } from '@dxos/echo';\nimport { useResolveRef } from '@dxos/echo-react';\n\nimport { type Game, GameCapabilities } from '#types';\n\nexport type GameCardProps = AppSurface.ObjectCardProps<Game.Game>;\n\nexport const GameCard = ({ role, subject: game }: GameCardProps) => {\n const variants = useCapabilities(GameCapabilities.VariantProvider);\n // Resolved live rather than as a snapshot: variants mutate their state, and a snapshot is frozen.\n const variant = useResolveRef(game.variant);\n\n if (!variant) {\n return null;\n }\n\n const variantTypename = Obj.getTypename(variant);\n const match = variants.find((v) => v.id === variantTypename);\n if (!match?.card) {\n return null;\n }\n\n const Component = match.card;\n return <Component game={game} variant={variant} role={role} />;\n};\n\nGameCard.displayName = 'GameCard';\n"],"mappings":";;;;;;;AAeA,IAAa,YAAY,EAAE,MAAM,SAAS,WAA0B;CAClE,MAAM,WAAW,gBAAgB,iBAAiB,eAAe;CAEjE,MAAM,UAAU,cAAc,KAAK,OAAO;CAE1C,IAAI,CAAC,SACH,OAAO;CAGT,MAAM,kBAAkB,IAAI,YAAY,OAAO;CAC/C,MAAM,QAAQ,SAAS,MAAM,MAAM,EAAE,OAAO,eAAe;CAC3D,IAAI,CAAC,OAAO,MACV,OAAO;CAGT,MAAM,YAAY,MAAM;CACxB,OAAO,oBAAC,WAAD;EAAiB;EAAe;EAAe;CAAO,CAAA;AAC/D;AAEA,SAAS,cAAc"}
@@ -0,0 +1,45 @@
1
+ import { a as make, n as VariantProvider, r as Game } from "./chunk-types.mjs";
2
+ import { Capability } from "@dxos/app-framework";
3
+ import { Database, Type } from "@dxos/echo";
4
+ import * as Effect from "effect/Effect";
5
+ import { Operation } from "@dxos/compute";
6
+ import { invariant } from "@dxos/invariant";
7
+ import { SpaceCapabilities, SpaceOperation } from "@dxos/plugin-space";
8
+ import { CreateGamePanel } from "#components";
9
+ //#region src/capabilities/create-object.ts
10
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-game/src/capabilities/create-object.ts";
11
+ var create_object_default = Capability.makeModule(Effect.fnUntraced(function* () {
12
+ return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {
13
+ id: Type.getTypename(Game),
14
+ customPanel: CreateGamePanel,
15
+ createObject: ({ variantId, input }, options) => Effect.gen(function* () {
16
+ const variant = (yield* Capability.getAll(VariantProvider)).find((v) => v.id === variantId);
17
+ invariant(variant, `Unknown game variant: ${variantId}`, {
18
+ "~LogMeta": "~LogMeta",
19
+ F: __dxlog_file,
20
+ L: 32,
21
+ S: this,
22
+ A: ["variant", "`Unknown game variant: ${variantId}`"]
23
+ });
24
+ const stateObject = yield* variant.createVariant(input ?? {}).pipe(Effect.provideService(Database.Service, Database.makeService(options.db)));
25
+ yield* Operation.invoke(SpaceOperation.AddObject, {
26
+ object: stateObject,
27
+ target: options.target,
28
+ targetNodeId: options.targetNodeId
29
+ });
30
+ const game = make({
31
+ name: typeof input?.name === "string" ? input.name : void 0,
32
+ variant: stateObject
33
+ });
34
+ return yield* Operation.invoke(SpaceOperation.AddObject, {
35
+ object: game,
36
+ target: options.target,
37
+ targetNodeId: options.targetNodeId
38
+ }).pipe(Effect.tapError(() => Operation.invoke(SpaceOperation.RemoveObjects, { objects: [stateObject] }).pipe(Effect.ignore)));
39
+ })
40
+ });
41
+ }));
42
+ //#endregion
43
+ export { create_object_default as default };
44
+
45
+ //# sourceMappingURL=chunk-create-object.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-create-object.mjs","names":[],"sources":["../../src/capabilities/create-object.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { Operation } from '@dxos/compute';\nimport { Database, Type } from '@dxos/echo';\nimport { invariant } from '@dxos/invariant';\nimport { SpaceOperation } from '@dxos/plugin-space';\nimport { SpaceCapabilities } from '@dxos/plugin-space';\n\nimport { CreateGamePanel } from '#components';\n\nimport { Game, GameCapabilities } from '../types';\n\ntype CreateOptions = Parameters<SpaceCapabilities.CreateObjectEntry['createObject']>[1];\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {\n id: Type.getTypename(Game.Game),\n customPanel: CreateGamePanel,\n createObject: (\n { variantId, input }: { variantId: string; input?: Record<string, any> },\n options: CreateOptions,\n ) =>\n Effect.gen(function* () {\n const variants = yield* Capability.getAll(GameCapabilities.VariantProvider);\n const variant = variants.find((v) => v.id === variantId);\n invariant(variant, `Unknown game variant: ${variantId}`);\n\n // Build variant state object via the variant's factory.\n const stateObject = yield* variant\n .createVariant(input ?? {})\n .pipe(Effect.provideService(Database.Service, Database.makeService(options.db)));\n\n // Add variant state to the database. Stays hidden — it's referenced by Game and\n // shouldn't appear as a top-level item in the user's space.\n yield* Operation.invoke(SpaceOperation.AddObject, {\n object: stateObject,\n target: options.target,\n targetNodeId: options.targetNodeId,\n });\n\n const game = Game.make({\n name: typeof input?.name === 'string' ? input.name : undefined,\n variant: stateObject,\n });\n\n // Add the user-facing Game wrapper. Not hidden — this is the object the user sees\n // and navigates to. If this second write fails, roll back the variant state so we\n // don't leak an orphaned object into the space.\n return yield* Operation.invoke(SpaceOperation.AddObject, {\n object: game,\n target: options.target,\n targetNodeId: options.targetNodeId,\n }).pipe(\n Effect.tapError(() =>\n Operation.invoke(SpaceOperation.RemoveObjects, { objects: [stateObject] }).pipe(Effect.ignore),\n ),\n );\n }),\n });\n }),\n);\n"],"mappings":";;;;;;;;;;AAmBA,IAAA,wBAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,OAAO,WAAW,YAAY,kBAAkB,mBAAmB;EACjE,IAAI,KAAK,YAAY,IAAS;EAC9B,aAAa;EACb,eACE,EAAE,WAAW,SACb,YAEA,OAAO,IAAI,aAAa;GAEtB,MAAM,WAAU,OADQ,WAAW,OAAO,eAAgC,EAAA,CACjD,MAAM,MAAM,EAAE,OAAO,SAAS;GACvD,UAAU,SAAS,yBAAyB,aAAU;IAAA,YAAA;IAAA,GAAA;IAAA,GAAA;IAAA,GAAA;IAAA,GAAA,CAAA,WAAA,sCAAA;GAAA,CAAC;GAGvD,MAAM,cAAc,OAAO,QACxB,cAAc,SAAS,CAAC,CAAC,CAAA,CACzB,KAAK,OAAO,eAAe,SAAS,SAAS,SAAS,YAAY,QAAQ,EAAE,CAAC,CAAC;GAIjF,OAAO,UAAU,OAAO,eAAe,WAAW;IAChD,QAAQ;IACR,QAAQ,QAAQ;IAChB,cAAc,QAAQ;GACxB,CAAC;GAED,MAAM,OAAO,KAAU;IACrB,MAAM,OAAO,OAAO,SAAS,WAAW,MAAM,OAAO,KAAA;IACrD,SAAS;GACX,CAAC;GAKD,OAAO,OAAO,UAAU,OAAO,eAAe,WAAW;IACvD,QAAQ;IACR,QAAQ,QAAQ;IAChB,cAAc,QAAQ;GACxB,CAAC,CAAC,CAAC,KACD,OAAO,eACL,UAAU,OAAO,eAAe,eAAe,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM,CAC/F,CACF;EACF,CAAC;CACL,CAAC;AACH,CAAC,CACH"}
@@ -0,0 +1,38 @@
1
+ import { Database, Obj, Type } from "@dxos/echo";
2
+ import * as Effect from "effect/Effect";
3
+ //#region src/util/load-game.ts
4
+ var GameVariantMismatchError = class extends Error {
5
+ gameId;
6
+ expectedTypename;
7
+ actualTypename;
8
+ _tag = "GameVariantMismatchError";
9
+ constructor(gameId, expectedTypename, actualTypename) {
10
+ super(`Game ${gameId} variant typename mismatch: expected ${expectedTypename}, got ${actualTypename}.`);
11
+ this.gameId = gameId;
12
+ this.expectedTypename = expectedTypename;
13
+ this.actualTypename = actualTypename;
14
+ }
15
+ };
16
+ /**
17
+ * Loads a Game from a Ref and resolves its variant state, asserting the variant matches
18
+ * the expected type. Returns the typed pair.
19
+ *
20
+ * Use in operation handlers that declare `input.game: GameRef<MyVariantState>`.
21
+ */
22
+ var loadGame = (ref, variantType) => Effect.gen(function* () {
23
+ const game = yield* Database.load(ref);
24
+ const variant = yield* Database.load(game.variant);
25
+ if (!Obj.instanceOf(variantType, variant)) {
26
+ const expected = Type.getTypename(variantType) ?? "unknown";
27
+ const actual = Obj.getTypename(variant) ?? "unknown";
28
+ return yield* Effect.fail(new GameVariantMismatchError(game.id, expected, actual));
29
+ }
30
+ return {
31
+ game,
32
+ variant
33
+ };
34
+ });
35
+ //#endregion
36
+ export { loadGame as n, GameVariantMismatchError as t };
37
+
38
+ //# sourceMappingURL=chunk-load-game.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-load-game.mjs","names":[],"sources":["../../src/util/load-game.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Database, Obj, type Ref, Type } from '@dxos/echo';\n\nimport * as Game from '../types/Game';\n\nexport class GameVariantMismatchError extends Error {\n readonly _tag = 'GameVariantMismatchError';\n constructor(\n readonly gameId: string,\n readonly expectedTypename: string,\n readonly actualTypename: string,\n ) {\n super(`Game ${gameId} variant typename mismatch: expected ${expectedTypename}, got ${actualTypename}.`);\n }\n}\n\n/**\n * Loads a Game from a Ref and resolves its variant state, asserting the variant matches\n * the expected type. Returns the typed pair.\n *\n * Use in operation handlers that declare `input.game: GameRef<MyVariantState>`.\n */\nexport const loadGame = <S extends Type.AnyObj>(\n ref: Ref.Ref<Game.Game>,\n variantType: S,\n): Effect.Effect<{ game: Game.Game; variant: Type.InstanceType<S> }, Error, Database.Service> =>\n Effect.gen(function* () {\n const game = yield* Database.load(ref);\n const variant = yield* Database.load(game.variant);\n if (!Obj.instanceOf(variantType, variant)) {\n const expected = Type.getTypename(variantType) ?? 'unknown';\n const actual = Obj.getTypename(variant as Obj.Any) ?? 'unknown';\n return yield* Effect.fail(new GameVariantMismatchError(game.id, expected, actual));\n }\n return { game, variant: variant as Type.InstanceType<S> };\n });\n"],"mappings":";;;AAUA,IAAa,2BAAb,cAA8C,MAAM;CAGvC;CACA;CACA;CAJX,OAAgB;CAChB,YACE,QACA,kBACA,gBACA;EACA,MAAM,QAAQ,OAAO,uCAAuC,iBAAiB,QAAQ,eAAe,EAAE;EAJ7F,KAAA,SAAA;EACA,KAAA,mBAAA;EACA,KAAA,iBAAA;CAGX;AACF;;;;;;;AAQA,IAAa,YACX,KACA,gBAEA,OAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAO,SAAS,KAAK,GAAG;CACrC,MAAM,UAAU,OAAO,SAAS,KAAK,KAAK,OAAO;CACjD,IAAI,CAAC,IAAI,WAAW,aAAa,OAAO,GAAG;EACzC,MAAM,WAAW,KAAK,YAAY,WAAW,KAAK;EAClD,MAAM,SAAS,IAAI,YAAY,OAAkB,KAAK;EACtD,OAAO,OAAO,OAAO,KAAK,IAAI,yBAAyB,KAAK,IAAI,UAAU,MAAM,CAAC;CACnF;CACA,OAAO;EAAE;EAAe;CAAgC;AAC1D,CAAC"}
@@ -1,15 +1,12 @@
1
- // src/meta.ts
2
1
  import { Plugin } from "@dxos/app-framework";
3
-
4
- // dx.config.ts
5
2
  import { Config2 } from "@dxos/app-framework/config";
6
3
  import { trim } from "@dxos/util";
7
- var dx_config_default = Config2.make({
8
- plugin: {
9
- key: "org.dxos.plugin.game",
10
- name: "Game",
11
- author: "DXOS",
12
- description: trim`
4
+ //#region dx.config.ts
5
+ var dx_config_default = Config2.make({ plugin: {
6
+ key: "org.dxos.plugin.game",
7
+ name: "Game",
8
+ author: "DXOS",
9
+ description: trim`
13
10
  Generic game host plugin that provides shared infrastructure for local-first,
14
11
  multi-player turn-based games inside DXOS Composer. The plugin owns the base
15
12
  \`Game\` ECHO type — which stores players and a reference to variant-specific
@@ -27,24 +24,19 @@ var dx_config_default = Config2.make({
27
24
  items in the user's space graph. The entire creation flow is atomic: if the
28
25
  Game write fails, the variant state is rolled back automatically.
29
26
  `,
30
- source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-game",
31
- icon: {
32
- key: "ph--sword--regular",
33
- hue: "indigo"
34
- },
35
- spec: "PLUGIN.mdl",
36
- screenshots: [
37
- {
38
- dark: "https://customer-5rxcjpyab08avpmn.cloudflarestream.com/2797d56edc9658d018ad75fe48a47f27/iframe?poster=https%3A%2F%2Fcustomer-5rxcjpyab08avpmn.cloudflarestream.com%2F2797d56edc9658d018ad75fe48a47f27%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600"
39
- }
40
- ]
41
- }
42
- });
43
-
44
- // src/meta.ts
27
+ source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-game",
28
+ icon: {
29
+ key: "ph--sword--regular",
30
+ hue: "indigo"
31
+ },
32
+ spec: "PLUGIN.mdl",
33
+ screenshots: [{ dark: "https://customer-5rxcjpyab08avpmn.cloudflarestream.com/2797d56edc9658d018ad75fe48a47f27/iframe?poster=https%3A%2F%2Fcustomer-5rxcjpyab08avpmn.cloudflarestream.com%2F2797d56edc9658d018ad75fe48a47f27%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600" }],
34
+ tags: ["alpha"]
35
+ } });
36
+ //#endregion
37
+ //#region src/meta.ts
45
38
  var meta = Plugin.getMetaFromConfig(dx_config_default);
39
+ //#endregion
40
+ export { meta as t };
46
41
 
47
- export {
48
- meta
49
- };
50
- //# sourceMappingURL=chunk-R4V5PVU7.mjs.map
42
+ //# sourceMappingURL=chunk-meta.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-meta.mjs","names":[],"sources":["../../dx.config.ts","../../src/meta.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Config2 } from '@dxos/app-framework/config';\nimport { trim } from '@dxos/util';\n\nexport default Config2.make({\n plugin: {\n key: 'org.dxos.plugin.game',\n name: 'Game',\n author: 'DXOS',\n description: trim`\n Generic game host plugin that provides shared infrastructure for local-first,\n multi-player turn-based games inside DXOS Composer. The plugin owns the base\n \\`Game\\` ECHO type — which stores players and a reference to variant-specific\n state — and drives the two-stage game-creation flow (variant picker + optional\n input form).\n\n Game variants (chess, tic-tac-toe, and others) are contributed by separate\n plugins via the \\`GameCapabilities.VariantProvider\\` capability. Each variant supplies\n its own state schema, player roles, create factory, and surface components\n (Article and Card). Plugin-game resolves the correct variant at runtime and\n delegates rendering, keeping the host layer fully decoupled from game logic.\n\n Variant state objects are stored as hidden ECHO objects alongside the top-level\n \\`Game\\`, ensuring they replicate to all peers but do not appear as independent\n items in the user's space graph. The entire creation flow is atomic: if the\n Game write fails, the variant state is rolled back automatically.\n `,\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-game',\n icon: { key: 'ph--sword--regular', hue: 'indigo' },\n spec: 'PLUGIN.mdl',\n screenshots: [\n {\n dark: 'https://customer-5rxcjpyab08avpmn.cloudflarestream.com/2797d56edc9658d018ad75fe48a47f27/iframe?poster=https%3A%2F%2Fcustomer-5rxcjpyab08avpmn.cloudflarestream.com%2F2797d56edc9658d018ad75fe48a47f27%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600',\n },\n ],\n tags: ['alpha'],\n },\n});\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\n\nimport config from '../dx.config';\n\nexport const meta = Plugin.getMetaFromConfig(config);\n"],"mappings":";;;;AAOA,IAAA,oBAAe,QAAQ,KAAK,EAC1B,QAAQ;CACN,KAAK;CACL,MAAM;CACN,QAAQ;CACR,aAAa,IAAI;;;;;;;;;;;;;;;;;;CAkBjB,QAAQ;CACR,MAAM;EAAE,KAAK;EAAsB,KAAK;CAAS;CACjD,MAAM;CACN,aAAa,CACX,EACE,MAAM,8PACR,CACF;CACA,MAAM,CAAC,OAAO;AAChB,EACF,CAAC;;;AChCD,IAAa,OAAO,OAAO,kBAAkB,iBAAM"}
@@ -0,0 +1,29 @@
1
+ import { r as Game } from "./chunk-types.mjs";
2
+ import { Capabilities, Capability } from "@dxos/app-framework";
3
+ import * as Effect from "effect/Effect";
4
+ import { Surface } from "@dxos/app-framework/ui";
5
+ import { AppSurface } from "@dxos/app-toolkit/ui";
6
+ import { GameArticle, GameCard } from "#containers";
7
+ //#region src/capabilities/react-surface.ts
8
+ var react_surface_default = Capability.makeModule(() => Effect.succeed(Capability.contributes(Capabilities.ReactSurface, [Surface.create({
9
+ id: "game",
10
+ filter: AppSurface.oneOf(AppSurface.object(AppSurface.Article, Game), AppSurface.object(AppSurface.Section, Game)),
11
+ component: GameArticle,
12
+ props: ({ role, data: { subject, attendableId } }) => ({
13
+ role,
14
+ subject,
15
+ attendableId
16
+ })
17
+ }), Surface.create({
18
+ id: "gameCard",
19
+ filter: AppSurface.object(AppSurface.CardContent, Game),
20
+ component: GameCard,
21
+ props: ({ role, data: { subject } }) => ({
22
+ role,
23
+ subject
24
+ })
25
+ })])));
26
+ //#endregion
27
+ export { react_surface_default as default };
28
+
29
+ //# sourceMappingURL=chunk-react-surface.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-react-surface.mjs","names":[],"sources":["../../src/capabilities/react-surface.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capabilities, Capability } from '@dxos/app-framework';\nimport { Surface } from '@dxos/app-framework/ui';\nimport { AppSurface } from '@dxos/app-toolkit/ui';\n\nimport { GameArticle, GameCard } from '#containers';\n\nimport { Game } from '../types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contributes(Capabilities.ReactSurface, [\n Surface.create({\n id: 'game',\n filter: AppSurface.oneOf(\n AppSurface.object(AppSurface.Article, Game.Game),\n AppSurface.object(AppSurface.Section, Game.Game),\n ),\n component: GameArticle,\n props: ({ role, data: { subject, attendableId } }) => ({ role, subject, attendableId }),\n }),\n Surface.create({\n id: 'gameCard',\n filter: AppSurface.object(AppSurface.CardContent, Game.Game),\n component: GameCard,\n props: ({ role, data: { subject } }) => ({ role, subject }),\n }),\n ]),\n ),\n);\n"],"mappings":";;;;;;;AAcA,IAAA,wBAAe,WAAW,iBACxB,OAAO,QACL,WAAW,YAAY,aAAa,cAAc,CAChD,QAAQ,OAAO;CACb,IAAI;CACJ,QAAQ,WAAW,MACjB,WAAW,OAAO,WAAW,SAAS,IAAS,GAC/C,WAAW,OAAO,WAAW,SAAS,IAAS,CACjD;CACA,WAAW;CACX,QAAQ,EAAE,MAAM,MAAM,EAAE,SAAS,sBAAsB;EAAE;EAAM;EAAS;CAAa;AACvF,CAAC,GACD,QAAQ,OAAO;CACb,IAAI;CACJ,QAAQ,WAAW,OAAO,WAAW,aAAa,IAAS;CAC3D,WAAW;CACX,QAAQ,EAAE,MAAM,MAAM,EAAE,iBAAiB;EAAE;EAAM;CAAQ;AAC3D,CAAC,CACH,CAAC,CACH,CACF"}
@@ -0,0 +1,83 @@
1
+ import "./chunk-load-game.mjs";
2
+ import { Capability } from "@dxos/app-framework";
3
+ import * as Schema from "effect/Schema";
4
+ import { Annotation, DXN, Obj, Ref, Type } from "@dxos/echo";
5
+ import { FormInputAnnotation, LabelAnnotation } from "@dxos/echo/Annotation";
6
+ import { CardAnnotation } from "@dxos/schema";
7
+ import { meta } from "#meta";
8
+ //#region \0rolldown/runtime.js
9
+ var __defProp = Object.defineProperty;
10
+ var __exportAll = (all, no_symbols) => {
11
+ let target = {};
12
+ for (var name in all) __defProp(target, name, {
13
+ get: all[name],
14
+ enumerable: true
15
+ });
16
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
17
+ return target;
18
+ };
19
+ //#endregion
20
+ //#region src/types/Game.ts
21
+ var Game_exports = /* @__PURE__ */ __exportAll({
22
+ Game: () => Game,
23
+ GameRef: () => GameRef,
24
+ Player: () => Player,
25
+ make: () => make
26
+ });
27
+ /**
28
+ * A player in a game.
29
+ * `role` is variant-defined (e.g. 'white' | 'black' for chess, 'x' | 'o' for tictactoe).
30
+ * `identity` is the optional DID of a human player; absent for AI or empty seats.
31
+ * `name` is an optional display label (useful for AI/guest players).
32
+ */
33
+ var Player = Schema.Struct({
34
+ role: Schema.String.annotations({ description: "Variant-defined player role (e.g. \"white\", \"x\")." }),
35
+ identity: Schema.optional(Schema.String.annotations({ description: "DID of the player; absent for AI or empty seats." })),
36
+ name: Schema.optional(Schema.String.annotations({ description: "Optional display name for the player." }))
37
+ });
38
+ /**
39
+ * Base Game object. Variant-specific state lives in a separate referenced object.
40
+ * Unifies all game variants (chess, tic-tac-toe, ...) under one typename so they share
41
+ * graph node, create flow, and shared surface scaffolding.
42
+ */
43
+ var Game = class extends Type.makeObject(DXN.make("org.dxos.type.game", "0.1.0"))(Schema.Struct({
44
+ name: Schema.optional(Schema.String),
45
+ players: Schema.mutable(Schema.Array(Player)).annotations({ description: "Players in the game." }).pipe(FormInputAnnotation.set(false), Schema.optional),
46
+ variant: Ref.Ref(Obj.Unknown).annotations({ description: "Reference to variant-specific state object." }).pipe(FormInputAnnotation.set(false))
47
+ }).pipe(LabelAnnotation.set(["name"]), Annotation.IconAnnotation.set({
48
+ icon: "ph--sword--regular",
49
+ hue: "indigo"
50
+ }), CardAnnotation.set(true), Annotation.IconFromRefAnnotation.set("variant"))) {};
51
+ var GameRef = (_variantType) => Ref.Ref(Game);
52
+ /**
53
+ * Build a base `Game` object referencing the given variant-state ECHO object.
54
+ *
55
+ * The variant is stored as a `Ref` so the underlying state (e.g. `Chess.State`,
56
+ * `TicTacToe.State`) lives as its own ECHO object alongside the Game.
57
+ *
58
+ * @param name Optional display name shown in the graph node and Properties form.
59
+ * @param variant Variant-specific state object (e.g. `Chess.State`, `TicTacToe.State`).
60
+ * @param players Optional initial players; copied into a mutable array on the Game.
61
+ * @returns A new `Game` object with `variant` stored as a Ref.
62
+ */
63
+ var make = ({ name, players, variant }) => {
64
+ return Obj.make(Game, {
65
+ name,
66
+ players: players ? [...players] : [],
67
+ variant: Ref.make(variant)
68
+ });
69
+ };
70
+ //#endregion
71
+ //#region src/types/GameCapabilities.ts
72
+ var GameCapabilities_exports = /* @__PURE__ */ __exportAll({ VariantProvider: () => VariantProvider });
73
+ /**
74
+ * A game variant contribution. Each variant plugin (chess, tic-tac-toe, ...)
75
+ * contributes one of these via `Capability.contributes(GameCapabilities.VariantProvider, variant)`.
76
+ * Consumers iterate via `Capability.getAll(GameCapabilities.VariantProvider)` (Effect) or
77
+ * `useCapabilities(GameCapabilities.VariantProvider)` (React).
78
+ */
79
+ var VariantProvider = Capability.make(`${meta.profile.key}.capability.variant`);
80
+ //#endregion
81
+ export { make as a, Game_exports as i, VariantProvider as n, Game as r, GameCapabilities_exports as t };
82
+
83
+ //# sourceMappingURL=chunk-types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-types.mjs","names":[],"sources":["../../src/types/Game.ts","../../src/types/GameCapabilities.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { Annotation, DXN, Obj, Ref, Type } from '@dxos/echo';\nimport { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/Annotation';\nimport { CardAnnotation } from '@dxos/schema';\n\n// @import-as-namespace\n\n/**\n * A player in a game.\n * `role` is variant-defined (e.g. 'white' | 'black' for chess, 'x' | 'o' for tictactoe).\n * `identity` is the optional DID of a human player; absent for AI or empty seats.\n * `name` is an optional display label (useful for AI/guest players).\n */\nexport const Player = Schema.Struct({\n role: Schema.String.annotations({\n description: 'Variant-defined player role (e.g. \"white\", \"x\").',\n }),\n identity: Schema.optional(\n Schema.String.annotations({\n description: 'DID of the player; absent for AI or empty seats.',\n }),\n ),\n name: Schema.optional(\n Schema.String.annotations({\n description: 'Optional display name for the player.',\n }),\n ),\n});\n\nexport type Player = Schema.Schema.Type<typeof Player>;\n\n/**\n * Base Game object. Variant-specific state lives in a separate referenced object.\n * Unifies all game variants (chess, tic-tac-toe, ...) under one typename so they share\n * graph node, create flow, and shared surface scaffolding.\n */\nexport class Game extends Type.makeObject<Game>(DXN.make('org.dxos.type.game', '0.1.0'))(\n Schema.Struct({\n name: Schema.optional(Schema.String),\n players: Schema.mutable(Schema.Array(Player))\n .annotations({ description: 'Players in the game.' })\n .pipe(FormInputAnnotation.set(false), Schema.optional),\n variant: Ref.Ref(Obj.Unknown)\n .annotations({ description: 'Reference to variant-specific state object.' })\n .pipe(FormInputAnnotation.set(false)),\n }).pipe(\n LabelAnnotation.set(['name']),\n Annotation.IconAnnotation.set({ icon: 'ph--sword--regular', hue: 'indigo' }),\n CardAnnotation.set(true),\n // Delegate the graph-node icon to the referenced variant state's schema. Falls back to\n // the static `ph--sword--regular` above while the variant ref is still loading.\n Annotation.IconFromRefAnnotation.set('variant'),\n ),\n) {}\n\n/**\n * Variant-narrowed reference to a Game.\n *\n * Encodes — at the type level — that the variant ref points to a specific state type.\n * Runtime narrowing is performed by `loadGame(ref, variantType)` which validates and\n * returns the resolved Game together with its typed variant state.\n *\n * @example\n * ```ts\n * input: Schema.Struct({\n * game: GameRef(Chess.State),\n * }),\n * // handler:\n * const { game, variant } = yield* loadGame(input.game, Chess.State);\n * // `variant` is typed as Chess.State.\n * ```\n */\nexport type GameRef<_V> = Ref.Ref<Game>;\n\nexport const GameRef = <S extends Type.AnyObj>(_variantType: S) =>\n Ref.Ref(Game) as Schema.Schema<GameRef<Type.InstanceType<S>>, any, never>;\n\n/**\n * Build a base `Game` object referencing the given variant-state ECHO object.\n *\n * The variant is stored as a `Ref` so the underlying state (e.g. `Chess.State`,\n * `TicTacToe.State`) lives as its own ECHO object alongside the Game.\n *\n * @param name Optional display name shown in the graph node and Properties form.\n * @param variant Variant-specific state object (e.g. `Chess.State`, `TicTacToe.State`).\n * @param players Optional initial players; copied into a mutable array on the Game.\n * @returns A new `Game` object with `variant` stored as a Ref.\n */\nexport const make = ({\n name,\n players,\n variant,\n}: {\n name?: string;\n players?: ReadonlyArray<Player>;\n variant: Obj.Unknown;\n}): Game => {\n return Obj.make(Game, {\n name,\n players: players ? [...players] : [],\n variant: Ref.make(variant),\n });\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport { Capability } from '@dxos/app-framework';\n\nimport { meta } from '#meta';\n\nimport type { GameVariant } from './types';\n\n/**\n * A game variant contribution. Each variant plugin (chess, tic-tac-toe, ...)\n * contributes one of these via `Capability.contributes(GameCapabilities.VariantProvider, variant)`.\n * Consumers iterate via `Capability.getAll(GameCapabilities.VariantProvider)` (Effect) or\n * `useCapabilities(GameCapabilities.VariantProvider)` (React).\n */\nexport const VariantProvider = Capability.make<GameVariant>(`${meta.profile.key}.capability.variant`);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,IAAa,SAAS,OAAO,OAAO;CAClC,MAAM,OAAO,OAAO,YAAY,EAC9B,aAAa,uDACf,CAAC;CACD,UAAU,OAAO,SACf,OAAO,OAAO,YAAY,EACxB,aAAa,mDACf,CAAC,CACH;CACA,MAAM,OAAO,SACX,OAAO,OAAO,YAAY,EACxB,aAAa,wCACf,CAAC,CACH;AACF,CAAC;;;;;;AASD,IAAa,OAAb,cAA0B,KAAK,WAAiB,IAAI,KAAK,sBAAsB,OAAO,CAAC,CAAC,CACtF,OAAO,OAAO;CACZ,MAAM,OAAO,SAAS,OAAO,MAAM;CACnC,SAAS,OAAO,QAAQ,OAAO,MAAM,MAAM,CAAC,CAAA,CACzC,YAAY,EAAE,aAAa,uBAAuB,CAAC,CAAA,CACnD,KAAK,oBAAoB,IAAI,KAAK,GAAG,OAAO,QAAQ;CACvD,SAAS,IAAI,IAAI,IAAI,OAAO,CAAA,CACzB,YAAY,EAAE,aAAa,8CAA8C,CAAC,CAAA,CAC1E,KAAK,oBAAoB,IAAI,KAAK,CAAC;AACxC,CAAC,CAAC,CAAC,KACD,gBAAgB,IAAI,CAAC,MAAM,CAAC,GAC5B,WAAW,eAAe,IAAI;CAAE,MAAM;CAAsB,KAAK;AAAS,CAAC,GAC3E,eAAe,IAAI,IAAI,GAGvB,WAAW,sBAAsB,IAAI,SAAS,CAChD,CACF,CAAC,CAAC,CAAC;AAqBH,IAAa,WAAkC,iBAC7C,IAAI,IAAI,IAAI;;;;;;;;;;;;AAad,IAAa,QAAQ,EACnB,MACA,SACA,cAKU;CACV,OAAO,IAAI,KAAK,MAAM;EACpB;EACA,SAAS,UAAU,CAAC,GAAG,OAAO,IAAI,CAAC;EACnC,SAAS,IAAI,KAAK,OAAO;CAC3B,CAAC;AACH;;;;;;;;;;ACzFA,IAAa,kBAAkB,WAAW,KAAkB,GAAG,KAAK,QAAQ,IAAI,oBAAoB"}
@@ -0,0 +1,82 @@
1
+ import { Obj } from "@dxos/echo";
2
+ import { meta } from "#meta";
3
+ import { GameCapabilities } from "#types";
4
+ import { useCallback, useMemo, useState } from "react";
5
+ import { useCapabilities } from "@dxos/app-framework/ui";
6
+ import { Column, useTranslation } from "@dxos/react-ui";
7
+ import { Form, omitId } from "@dxos/react-ui-form";
8
+ import { SearchList, useSearchListResults } from "@dxos/react-ui-search";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/components/CreateGamePanel.tsx
11
+ /**
12
+ * Two-stage create panel for games:
13
+ * 1. Variant picker (SearchList over contributed `GameVariant[]`).
14
+ * 2. Variant-specific input form (rendered from variant.inputSchema).
15
+ *
16
+ * On submit, calls `onCreateObject({ variantId, name, input })` where `input` is the
17
+ * variant-specific form values. Plugin-game's CreateObjectEntry.createObject resolves
18
+ * the variantId, builds the variant state object via variant.createVariant, then wraps
19
+ * it in a Game.
20
+ */
21
+ var CreateGamePanel = ({ target, onCreateObject, variants: variantsProp }) => {
22
+ const capabilityVariants = useCapabilities(GameCapabilities.VariantProvider);
23
+ const variants = variantsProp ?? capabilityVariants;
24
+ const [selectedId, setSelectedId] = useState(void 0);
25
+ const selected = useMemo(() => variants.find((v) => v.id === selectedId), [variants, selectedId]);
26
+ const handleSelect = useCallback((id) => {
27
+ const variant = variants.find((v) => v.id === id);
28
+ if (!variant) return;
29
+ if (!variant.inputSchema) {
30
+ onCreateObject({ variantId: id });
31
+ return;
32
+ }
33
+ setSelectedId(id);
34
+ }, [variants, onCreateObject]);
35
+ const handleSubmit = useCallback((input) => {
36
+ if (!selected) return;
37
+ onCreateObject({
38
+ variantId: selected.id,
39
+ input
40
+ });
41
+ }, [selected, onCreateObject]);
42
+ if (!selected) return /* @__PURE__ */ jsx(VariantPicker, {
43
+ variants,
44
+ onSelect: handleSelect
45
+ });
46
+ const schema = selected.inputSchema ? omitId(selected.inputSchema) : void 0;
47
+ if (!schema) return null;
48
+ return /* @__PURE__ */ jsx(Form.Root, {
49
+ autoFocus: true,
50
+ schema,
51
+ defaultValues: {},
52
+ db: Obj.isObject(target) ? Obj.getDatabase(target) : target,
53
+ onSave: handleSubmit,
54
+ testId: "create-game-form",
55
+ children: /* @__PURE__ */ jsx(Column.Center, { children: /* @__PURE__ */ jsxs(Form.Content, { children: [/* @__PURE__ */ jsx(Form.FieldSet, {}), /* @__PURE__ */ jsx(Form.Submit, {})] }) })
56
+ });
57
+ };
58
+ var VariantPicker = ({ variants, onSelect }) => {
59
+ const { t } = useTranslation(meta.profile.key);
60
+ const { results, handleSearch } = useSearchListResults({
61
+ items: useMemo(() => [...variants].sort((a, b) => a.label.localeCompare(b.label)), [variants]),
62
+ extract: (variant) => variant.label
63
+ });
64
+ return /* @__PURE__ */ jsxs(SearchList.Root, {
65
+ onSearch: handleSearch,
66
+ children: [/* @__PURE__ */ jsx(SearchList.Input, {
67
+ classNames: "mb-form-gap",
68
+ autoFocus: true,
69
+ "data-testid": "create-game-panel.variant-input",
70
+ placeholder: t("create-panel.variant.placeholder")
71
+ }), /* @__PURE__ */ jsx(SearchList.Viewport, { children: results.map((variant) => /* @__PURE__ */ jsx(SearchList.Item, {
72
+ value: variant.id,
73
+ label: variant.label,
74
+ icon: variant.icon ?? "ph--sword--regular",
75
+ onSelect: () => onSelect(variant.id)
76
+ }, variant.id)) })]
77
+ });
78
+ };
79
+ //#endregion
80
+ export { CreateGamePanel };
81
+
82
+ //# sourceMappingURL=components.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.mjs","names":[],"sources":["../../src/components/CreateGamePanel.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/ui';\nimport { Obj } from '@dxos/echo';\nimport { type SpaceCapabilities } from '@dxos/plugin-space';\nimport { Column, useTranslation } from '@dxos/react-ui';\nimport { Form, omitId } from '@dxos/react-ui-form';\nimport { SearchList, useSearchListResults } from '@dxos/react-ui-search';\n\nimport { meta } from '#meta';\nimport { GameCapabilities, type GameVariant } from '#types';\n\nexport type CreateGamePanelProps = SpaceCapabilities.CreateObjectCustomPanelProps & {\n /** Optional override (primarily for stories/tests). Defaults to GameCapabilities.VariantProvider. */\n variants?: GameVariant[];\n};\n\n/**\n * Two-stage create panel for games:\n * 1. Variant picker (SearchList over contributed `GameVariant[]`).\n * 2. Variant-specific input form (rendered from variant.inputSchema).\n *\n * On submit, calls `onCreateObject({ variantId, name, input })` where `input` is the\n * variant-specific form values. Plugin-game's CreateObjectEntry.createObject resolves\n * the variantId, builds the variant state object via variant.createVariant, then wraps\n * it in a Game.\n */\nexport const CreateGamePanel = ({ target, onCreateObject, variants: variantsProp }: CreateGamePanelProps) => {\n const capabilityVariants = useCapabilities(GameCapabilities.VariantProvider);\n const variants = variantsProp ?? capabilityVariants;\n const [selectedId, setSelectedId] = useState<string | undefined>(undefined);\n const selected = useMemo(() => variants.find((v) => v.id === selectedId), [variants, selectedId]);\n\n const handleSelect = useCallback(\n (id: string) => {\n const variant = variants.find((v) => v.id === id);\n if (!variant) {\n return;\n }\n if (!variant.inputSchema) {\n void onCreateObject({ variantId: id });\n return;\n }\n setSelectedId(id);\n },\n [variants, onCreateObject],\n );\n\n const handleSubmit = useCallback(\n (input: Record<string, any>) => {\n if (!selected) {\n return;\n }\n void onCreateObject({ variantId: selected.id, input });\n },\n [selected, onCreateObject],\n );\n\n if (!selected) {\n return <VariantPicker variants={variants} onSelect={handleSelect} />;\n }\n\n const schema = selected.inputSchema ? omitId(selected.inputSchema) : undefined;\n if (!schema) {\n return null;\n }\n\n return (\n <Form.Root\n autoFocus\n schema={schema}\n defaultValues={{}}\n db={Obj.isObject(target) ? Obj.getDatabase(target) : target}\n onSave={handleSubmit}\n testId='create-game-form'\n >\n {/* Rendered inside the create dialog's Dialog.Body (which owns the gutter Column); use\n Column.Center to align with the dialog title rather than nesting another Column.Root. */}\n <Column.Center>\n <Form.Content>\n <Form.FieldSet />\n <Form.Submit />\n </Form.Content>\n </Column.Center>\n </Form.Root>\n );\n};\n\ntype VariantPickerProps = {\n variants: GameVariant[];\n onSelect: (id: string) => void;\n};\n\nconst VariantPicker = ({ variants, onSelect }: VariantPickerProps) => {\n const { t } = useTranslation(meta.profile.key);\n const sorted = useMemo(() => [...variants].sort((a, b) => a.label.localeCompare(b.label)), [variants]);\n const { results, handleSearch } = useSearchListResults({\n items: sorted,\n extract: (variant) => variant.label,\n });\n\n return (\n <SearchList.Root onSearch={handleSearch}>\n <SearchList.Input\n classNames='mb-form-gap'\n autoFocus\n data-testid='create-game-panel.variant-input'\n placeholder={t('create-panel.variant.placeholder')}\n />\n <SearchList.Viewport>\n {results.map((variant) => (\n <SearchList.Item\n key={variant.id}\n value={variant.id}\n label={variant.label}\n icon={variant.icon ?? 'ph--sword--regular'}\n onSelect={() => onSelect(variant.id)}\n />\n ))}\n </SearchList.Viewport>\n </SearchList.Root>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+BA,IAAa,mBAAmB,EAAE,QAAQ,gBAAgB,UAAU,mBAAyC;CAC3G,MAAM,qBAAqB,gBAAgB,iBAAiB,eAAe;CAC3E,MAAM,WAAW,gBAAgB;CACjC,MAAM,CAAC,YAAY,iBAAiB,SAA6B,KAAA,CAAS;CAC1E,MAAM,WAAW,cAAc,SAAS,MAAM,MAAM,EAAE,OAAO,UAAU,GAAG,CAAC,UAAU,UAAU,CAAC;CAEhG,MAAM,eAAe,aAClB,OAAe;EACd,MAAM,UAAU,SAAS,MAAM,MAAM,EAAE,OAAO,EAAE;EAChD,IAAI,CAAC,SACH;EAEF,IAAI,CAAC,QAAQ,aAAa;GACxB,eAAoB,EAAE,WAAW,GAAG,CAAC;GACrC;EACF;EACA,cAAc,EAAE;CAClB,GACA,CAAC,UAAU,cAAc,CAC3B;CAEA,MAAM,eAAe,aAClB,UAA+B;EAC9B,IAAI,CAAC,UACH;EAEF,eAAoB;GAAE,WAAW,SAAS;GAAI;EAAM,CAAC;CACvD,GACA,CAAC,UAAU,cAAc,CAC3B;CAEA,IAAI,CAAC,UACH,OAAO,oBAAC,eAAD;EAAyB;EAAU,UAAU;CAAe,CAAA;CAGrE,MAAM,SAAS,SAAS,cAAc,OAAO,SAAS,WAAW,IAAI,KAAA;CACrE,IAAI,CAAC,QACH,OAAO;CAGT,OACE,oBAAC,KAAK,MAAN;EACE,WAAA;EACQ;EACR,eAAe,CAAC;EAChB,IAAI,IAAI,SAAS,MAAM,IAAI,IAAI,YAAY,MAAM,IAAI;EACrD,QAAQ;EACR,QAAO;YAIP,oBAAC,OAAO,QAAR,EAAA,UACE,qBAAC,KAAK,SAAN,EAAA,UAAA,CACE,oBAAC,KAAK,UAAN,CAAgB,CAAA,GAChB,oBAAC,KAAK,QAAN,CAAc,CAAA,CACF,EAAA,CAAA,EACD,CAAA;CACN,CAAA;AAEf;AAOA,IAAM,iBAAiB,EAAE,UAAU,eAAmC;CACpE,MAAM,EAAE,MAAM,eAAe,KAAK,QAAQ,GAAG;CAE7C,MAAM,EAAE,SAAS,iBAAiB,qBAAqB;EACrD,OAFa,cAAc,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAE3F;EACP,UAAU,YAAY,QAAQ;CAChC,CAAC;CAED,OACE,qBAAC,WAAW,MAAZ;EAAiB,UAAU;YAA3B,CACE,oBAAC,WAAW,OAAZ;GACE,YAAW;GACX,WAAA;GACA,eAAY;GACZ,aAAa,EAAE,kCAAkC;EAClD,CAAA,GACD,oBAAC,WAAW,UAAZ,EAAA,UACG,QAAQ,KAAK,YACZ,oBAAC,WAAW,MAAZ;GAEE,OAAO,QAAQ;GACf,OAAO,QAAQ;GACf,MAAM,QAAQ,QAAQ;GACtB,gBAAgB,SAAS,QAAQ,EAAE;EACpC,GALM,QAAQ,EAKd,CACF,EACkB,CAAA,CACN;;AAErB"}
@@ -0,0 +1,8 @@
1
+ import { lazy } from "react";
2
+ //#region src/containers/index.ts
3
+ var GameArticle = lazy(() => import("./chunk-GameArticle.mjs"));
4
+ var GameCard = lazy(() => import("./chunk-GameCard.mjs"));
5
+ //#endregion
6
+ export { GameArticle, GameCard };
7
+
8
+ //# sourceMappingURL=containers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers.mjs","names":[],"sources":["../../src/containers/index.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { type ComponentType, lazy } from 'react';\n\nexport const GameArticle: ComponentType<any> = lazy(() => import('./GameArticle'));\nexport const GameCard: ComponentType<any> = lazy(() => import('./GameCard'));\n"],"mappings":";;AAMA,IAAa,cAAkC,WAAW,OAAO,0BAAgB;AACjF,IAAa,WAA+B,WAAW,OAAO,uBAAa"}
@@ -0,0 +1,4 @@
1
+ import { i as Game_exports, t as GameCapabilities_exports } from "./chunk-types.mjs";
2
+ import { t as meta } from "./chunk-meta.mjs";
3
+ import { n as loadGame, t as GameVariantMismatchError } from "./chunk-load-game.mjs";
4
+ export { Game_exports as Game, GameCapabilities_exports as GameCapabilities, GameVariantMismatchError, loadGame, meta };
@@ -0,0 +1,2 @@
1
+ import { t as meta } from "./chunk-meta.mjs";
2
+ export { meta };
@@ -0,0 +1,8 @@
1
+ import { t as meta } from "./chunk-meta.mjs";
2
+ import { Plugin } from "@dxos/app-framework";
3
+ //#region src/plugin.ts
4
+ var GamePlugin = Plugin.lazy(meta, () => import("#plugin"));
5
+ //#endregion
6
+ export { GamePlugin };
7
+
8
+ //# sourceMappingURL=plugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../src/plugin.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\n\nimport { meta } from './meta';\n\nexport const GamePlugin = Plugin.lazy(meta, () => import('#plugin'));\n"],"mappings":";;;AAQA,IAAa,aAAa,OAAO,KAAK,YAAY,OAAO,UAAU"}