@dreamboard-games/sdk 0.5.0-alpha.2 → 0.5.0-alpha.21

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 (150) hide show
  1. package/README.md +462 -53
  2. package/dist/board-element-CqtxU5VZ.d.ts +13 -0
  3. package/dist/chunk-3RFGPBES.js +1792 -0
  4. package/dist/chunk-3RFGPBES.js.map +1 -0
  5. package/dist/chunk-CZRPUWCT.js +1602 -0
  6. package/dist/chunk-CZRPUWCT.js.map +1 -0
  7. package/dist/chunk-DMSXVMYY.js +7199 -0
  8. package/dist/chunk-DMSXVMYY.js.map +1 -0
  9. package/dist/chunk-U6R7FAH4.js +630 -0
  10. package/dist/chunk-U6R7FAH4.js.map +1 -0
  11. package/dist/chunk-YT3RPO5J.js +635 -0
  12. package/dist/chunk-YT3RPO5J.js.map +1 -0
  13. package/dist/diagnostics-ZAPEBlJP.d.ts +64 -0
  14. package/dist/extract-CwJWDrSD.d.ts +6850 -0
  15. package/dist/index.d.ts +5177 -1
  16. package/dist/index.js +1990 -6
  17. package/dist/index.js.map +1 -1
  18. package/dist/react.d.ts +158 -0
  19. package/dist/react.js +1119 -0
  20. package/dist/react.js.map +1 -0
  21. package/dist/reducer.d.ts +1028 -97
  22. package/dist/reducer.js +4892 -125
  23. package/dist/reducer.js.map +1 -1
  24. package/dist/shortcuts-B_RrufOM.d.ts +822 -0
  25. package/dist/testing.d.ts +529 -569
  26. package/dist/testing.js +2588 -934
  27. package/dist/testing.js.map +1 -1
  28. package/dist/types-BxXRINRF.d.ts +118 -0
  29. package/package.json +39 -144
  30. package/dist/HandView-Bi2lxzQP.d.ts +0 -79
  31. package/dist/ResourceCounter-BFxJknqp.d.ts +0 -98
  32. package/dist/ThemeProvider-CElaL2ik.d.ts +0 -99
  33. package/dist/attributes-DbvyMbXw.d.ts +0 -68
  34. package/dist/browser-interaction.d.ts +0 -910
  35. package/dist/browser-interaction.js +0 -119
  36. package/dist/browser-interaction.js.map +0 -1
  37. package/dist/chunk-32PFKDV7.js +0 -11705
  38. package/dist/chunk-32PFKDV7.js.map +0 -1
  39. package/dist/chunk-3BAD4VC2.js +0 -263
  40. package/dist/chunk-3BAD4VC2.js.map +0 -1
  41. package/dist/chunk-3SKDNDPG.js +0 -104
  42. package/dist/chunk-3SKDNDPG.js.map +0 -1
  43. package/dist/chunk-5YV2WHJ4.js +0 -25
  44. package/dist/chunk-5YV2WHJ4.js.map +0 -1
  45. package/dist/chunk-ANRB4XKA.js +0 -90
  46. package/dist/chunk-ANRB4XKA.js.map +0 -1
  47. package/dist/chunk-BI4G3PM2.js +0 -1864
  48. package/dist/chunk-BI4G3PM2.js.map +0 -1
  49. package/dist/chunk-EVCLTY4Q.js +0 -935
  50. package/dist/chunk-EVCLTY4Q.js.map +0 -1
  51. package/dist/chunk-GDPKTBUR.js +0 -564
  52. package/dist/chunk-GDPKTBUR.js.map +0 -1
  53. package/dist/chunk-H6VDGFL5.js +0 -2903
  54. package/dist/chunk-H6VDGFL5.js.map +0 -1
  55. package/dist/chunk-LR3ZTWQF.js +0 -5960
  56. package/dist/chunk-LR3ZTWQF.js.map +0 -1
  57. package/dist/chunk-PF7L4BMG.js +0 -117
  58. package/dist/chunk-PF7L4BMG.js.map +0 -1
  59. package/dist/chunk-PN5O6GG2.js +0 -32
  60. package/dist/chunk-PN5O6GG2.js.map +0 -1
  61. package/dist/chunk-PZ5AY32C.js +0 -10
  62. package/dist/chunk-PZ5AY32C.js.map +0 -1
  63. package/dist/chunk-S2JEDVWH.js +0 -7165
  64. package/dist/chunk-S2JEDVWH.js.map +0 -1
  65. package/dist/chunk-T3ZKNUZ7.js +0 -1
  66. package/dist/chunk-T3ZKNUZ7.js.map +0 -1
  67. package/dist/chunk-UGH54WZ2.js +0 -223
  68. package/dist/chunk-UGH54WZ2.js.map +0 -1
  69. package/dist/chunk-VCDWP5VL.js +0 -746
  70. package/dist/chunk-VCDWP5VL.js.map +0 -1
  71. package/dist/chunk-VDXOF4FW.js +0 -69
  72. package/dist/chunk-VDXOF4FW.js.map +0 -1
  73. package/dist/chunk-WHR5UW3F.js +0 -1988
  74. package/dist/chunk-WHR5UW3F.js.map +0 -1
  75. package/dist/chunk-Y75CFE77.js +0 -17
  76. package/dist/chunk-Y75CFE77.js.map +0 -1
  77. package/dist/chunk-Z7QCREWI.js +0 -3435
  78. package/dist/chunk-Z7QCREWI.js.map +0 -1
  79. package/dist/chunk-ZZGN2ATS.js +0 -1941
  80. package/dist/chunk-ZZGN2ATS.js.map +0 -1
  81. package/dist/components-gAbIz7hK.d.ts +0 -1284
  82. package/dist/definitions-BgmV_GhC.d.ts +0 -300
  83. package/dist/diagnostics-DIi3ina7.d.ts +0 -50
  84. package/dist/digest.d.ts +0 -8
  85. package/dist/game-CsZScpcn.d.ts +0 -763
  86. package/dist/hex-board-view-aKkblDp6.d.ts +0 -1228
  87. package/dist/index-CcT9Q7N7.d.ts +0 -193
  88. package/dist/index.d-DjzoK7zn.d.ts +0 -2101
  89. package/dist/package-set.d.ts +0 -13
  90. package/dist/package-set.js +0 -12
  91. package/dist/package-set.js.map +0 -1
  92. package/dist/player-state-Cqpyeql0.d.ts +0 -371
  93. package/dist/plugin-runtime-contract.d.ts +0 -17
  94. package/dist/plugin-runtime-contract.js +0 -92
  95. package/dist/plugin-runtime-contract.js.map +0 -1
  96. package/dist/primitive-props-BNHDkgd7.d.ts +0 -16
  97. package/dist/protocol-dYgafTYY.d.ts +0 -314
  98. package/dist/reducer/advanced.d.ts +0 -82
  99. package/dist/reducer/advanced.js +0 -51
  100. package/dist/reducer/advanced.js.map +0 -1
  101. package/dist/reducer-contract.d.ts +0 -11
  102. package/dist/reducer-contract.js +0 -16
  103. package/dist/reducer-contract.js.map +0 -1
  104. package/dist/reference-games/index.d.ts +0 -31
  105. package/dist/reference-games/index.js +0 -48
  106. package/dist/reference-games/index.js.map +0 -1
  107. package/dist/runtime/primitives.d.ts +0 -250
  108. package/dist/runtime/primitives.js +0 -189
  109. package/dist/runtime/primitives.js.map +0 -1
  110. package/dist/runtime/runtime-api.d.ts +0 -2
  111. package/dist/runtime/runtime-api.js +0 -1
  112. package/dist/runtime/runtime-api.js.map +0 -1
  113. package/dist/runtime/workspace-contract.d.ts +0 -392
  114. package/dist/runtime/workspace-contract.js +0 -28
  115. package/dist/runtime/workspace-contract.js.map +0 -1
  116. package/dist/runtime-RJ5orDJU.d.ts +0 -1699
  117. package/dist/runtime-api-Bz5pwNU_.d.ts +0 -296
  118. package/dist/runtime-json-CQ9QbLZ5.d.ts +0 -5
  119. package/dist/runtime.d.ts +0 -83
  120. package/dist/runtime.js +0 -242
  121. package/dist/runtime.js.map +0 -1
  122. package/dist/schema.d.ts +0 -379
  123. package/dist/stale-contract-artifact-error-XLaweZtF.d.ts +0 -18
  124. package/dist/testing-compiler.d.ts +0 -37
  125. package/dist/testing-compiler.js +0 -272
  126. package/dist/testing-compiler.js.map +0 -1
  127. package/dist/testing-runtime.d.ts +0 -119
  128. package/dist/testing-runtime.js +0 -212
  129. package/dist/testing-runtime.js.map +0 -1
  130. package/dist/types-DJj5MJkl.d.ts +0 -256
  131. package/dist/types-DR7DoB1x.d.ts +0 -28
  132. package/dist/types-JWCYHmu7.d.ts +0 -122
  133. package/dist/types.d.ts +0 -1958
  134. package/dist/types.js +0 -14
  135. package/dist/types.js.map +0 -1
  136. package/dist/ui/components.d.ts +0 -17
  137. package/dist/ui/components.js +0 -216
  138. package/dist/ui/components.js.map +0 -1
  139. package/dist/ui/defaults.d.ts +0 -19
  140. package/dist/ui/defaults.js +0 -104
  141. package/dist/ui/defaults.js.map +0 -1
  142. package/dist/ui/player-state.d.ts +0 -2
  143. package/dist/ui/player-state.js +0 -1
  144. package/dist/ui/player-state.js.map +0 -1
  145. package/dist/ui/plugin-styles.css +0 -2
  146. package/dist/ui-contract-GTUPkf8z.d.ts +0 -1168
  147. package/dist/ui.d.ts +0 -317
  148. package/dist/ui.js +0 -277
  149. package/dist/ui.js.map +0 -1
  150. package/dist/views-BpuWcOyN.d.ts +0 -1641
@@ -0,0 +1,822 @@
1
+ import { Store } from '@tanstack/store';
2
+ import { j as BoardSpaceTarget, bh as TopologyDefinitions, h as BoardIdOfTable, bb as TileSpaceId, aZ as SeatSpaceRef, b0 as SpaceIdOfTable, be as TiledBoardIdOfTable, bf as TiledEdgeIdOfTable, bg as TiledVertexIdOfTable, k as BoardStateOfTable, at as PositionTarget, a_ as SeatTileRef, aP as RuntimeJson, aX as SeatBoardTopology, a5 as InteractionInputDescriptor, U as InputDomain, aq as PhaseNamesOfDefinition, a4 as InteractionIdOfDefinitionPhase, s as ClientParamsOfInteractionOfDefinition, T as InputCollectorOfDefinition, bq as ViewOfDefinition, ay as ProjectedTile, aA as ReadonlyRuntimeData, l as BoardTopologyOf, P as HiddenCardId, bk as ViewCard, bl as ViewCardOfTable, I as GameEvent } from './extract-CwJWDrSD.js';
3
+ import { g as SourceSnapshot, h as SourceState, i as SubmitResult, G as GameSource, I as InteractionDescriptor } from './types-BxXRINRF.js';
4
+ import { z } from 'zod';
5
+
6
+ type RuntimeBoardTarget = {
7
+ readonly valueKind: "board-id";
8
+ readonly kind: "space" | "edge" | "vertex";
9
+ readonly boardId: string;
10
+ readonly value: string;
11
+ } | {
12
+ readonly valueKind: "board-space";
13
+ readonly kind: "space";
14
+ readonly value: BoardSpaceTarget;
15
+ };
16
+ type RuntimeSelectionTarget = RuntimeBoardTarget | {
17
+ readonly kind: "card";
18
+ readonly value: string;
19
+ } | {
20
+ readonly kind: "tile";
21
+ readonly value: SeatTileRef;
22
+ };
23
+ type RuntimeTargetOptions = {
24
+ readonly interaction?: undefined;
25
+ readonly input?: never;
26
+ } | {
27
+ readonly interaction: string;
28
+ readonly input?: string;
29
+ };
30
+ type RuntimeBoardDropTarget = RuntimeBoardTarget & {
31
+ readonly interactionKey: string;
32
+ readonly cardInputKey: string;
33
+ readonly inputKey: string;
34
+ };
35
+ interface RuntimeInteractionDropTarget {
36
+ readonly kind: "interaction";
37
+ readonly interactionKey: string;
38
+ readonly cardInputKey: string;
39
+ readonly params?: Readonly<Record<string, RuntimeJson>>;
40
+ }
41
+ /** An insertion point in a zone for an interaction with a position input. */
42
+ interface RuntimePositionDropTarget {
43
+ readonly kind: "position";
44
+ readonly interactionKey: string;
45
+ readonly cardInputKey: string;
46
+ readonly inputKey: string;
47
+ readonly value: PositionTarget;
48
+ }
49
+ type RuntimeDropTarget = RuntimeBoardDropTarget | RuntimeInteractionDropTarget | RuntimePositionDropTarget;
50
+ type SeatSpaceValue<Id> = Id extends TileSpaceId ? SeatSpaceRef : Id;
51
+ type TargetOnBoard<Table, B extends BoardIdOfTable<Table>, Definitions extends TopologyDefinitions> = ({
52
+ readonly valueKind: "board-id";
53
+ readonly boardId: B;
54
+ } & ({
55
+ readonly kind: "space";
56
+ readonly value: SeatSpaceValue<SpaceIdOfTable<Table, B, Definitions>>;
57
+ } | (B extends TiledBoardIdOfTable<Table, Definitions> ? {
58
+ readonly kind: "edge";
59
+ readonly value: TiledEdgeIdOfTable<Table, B, Definitions>;
60
+ } | {
61
+ readonly kind: "vertex";
62
+ readonly value: TiledVertexIdOfTable<Table, B, Definitions>;
63
+ } : never))) | (BoardStateOfTable<Table, B, Definitions> extends {
64
+ scope: "perPlayer";
65
+ baseId: string;
66
+ } ? {
67
+ readonly valueKind: "board-space";
68
+ readonly kind: "space";
69
+ readonly value: BoardSpaceTarget<B, SeatSpaceValue<SpaceIdOfTable<Table, B, Definitions>>>;
70
+ } : never);
71
+ /** One target identity; board-space targets already contain their board identity. */
72
+ type BoardTarget<G> = [TableOfGame<G>] extends [never] ? RuntimeBoardTarget : G extends {
73
+ contract: {
74
+ manifest: infer Definitions extends TopologyDefinitions;
75
+ };
76
+ } ? {
77
+ [B in BoardIdOfTable<TableOfGame<G>>]: TargetOnBoard<TableOfGame<G>, B, Definitions>;
78
+ }[BoardIdOfTable<TableOfGame<G>>] : never;
79
+ type SelectionTarget<G> = BoardTarget<G> | {
80
+ readonly kind: "card";
81
+ readonly value: SeatCardId<G>;
82
+ } | {
83
+ readonly kind: "tile";
84
+ readonly value: SeatTileRef;
85
+ };
86
+ /** Input disambiguation belongs to a particular interaction. */
87
+ type TargetOptions<G> = {
88
+ readonly interaction?: undefined;
89
+ readonly input?: never;
90
+ } | {
91
+ [K in InteractionKey<G>]: {
92
+ readonly interaction: K;
93
+ readonly input?: InputKey<G, K>;
94
+ };
95
+ }[InteractionKey<G>];
96
+ type KeysOfKind<G, K extends InteractionKey<G>, Kind extends string> = unknown extends G ? string : {
97
+ [N in InputKey<G, K>]: InputKind<G, K, N> extends Kind ? N : never;
98
+ }[InputKey<G, K>];
99
+ /** A resolved atomic card/drop route retains both input identities. */
100
+ type BoardDropTarget<G> = BoardTarget<G> & {
101
+ [K in InteractionKey<G>]: {
102
+ readonly interactionKey: K;
103
+ readonly cardInputKey: KeysOfKind<G, K, "card">;
104
+ readonly inputKey: KeysOfKind<G, K, "board-space" | "board-edge" | "board-vertex">;
105
+ };
106
+ }[InteractionKey<G>];
107
+ type DropAreaParams<G, K extends InteractionKey<G>> = Partial<InteractionParams<G, K>> & (unknown extends G ? Record<never, never> : {
108
+ readonly [N in KeysOfKind<G, K, "card">]?: never;
109
+ });
110
+ /** An area that runs an interaction without a board input on the dropped card. */
111
+ type InteractionDropTarget<G> = {
112
+ [K in InteractionKey<G>]: [KeysOfKind<G, K, "card">] extends [never] ? never : {
113
+ readonly kind: "interaction";
114
+ readonly interactionKey: K;
115
+ readonly cardInputKey: KeysOfKind<G, K, "card">;
116
+ readonly params?: DropAreaParams<G, K>;
117
+ };
118
+ }[InteractionKey<G>];
119
+ type PositionValue<G, K extends InteractionKey<G>> = unknown extends G ? PositionTarget : {
120
+ [N in InputKey<G, K>]: InputKind<G, K, N> extends "position" ? InputTarget<G, K, N> : never;
121
+ }[InputKey<G, K>];
122
+ /** A dragged card's insertion point in a zone, as a position input takes it. */
123
+ type PositionDropTarget<G> = {
124
+ [K in InteractionKey<G>]: [KeysOfKind<G, K, "position">] extends [never] ? never : {
125
+ readonly kind: "position";
126
+ readonly interactionKey: K;
127
+ readonly cardInputKey: KeysOfKind<G, K, "card">;
128
+ readonly inputKey: KeysOfKind<G, K, "position">;
129
+ readonly value: PositionValue<G, K>;
130
+ };
131
+ }[InteractionKey<G>];
132
+ type DropTarget<G> = BoardDropTarget<G> | InteractionDropTarget<G> | PositionDropTarget<G>;
133
+ /**
134
+ * Bound inputs accompany the dropped card in one interaction draft. A
135
+ * `position` instead names the insertion point the area offers now.
136
+ */
137
+ type DropAreaBinding<G> = {
138
+ [K in InteractionKey<G>]: {
139
+ readonly interaction: K;
140
+ readonly input?: KeysOfKind<G, K, "card">;
141
+ readonly params?: DropAreaParams<G, K>;
142
+ readonly position?: never;
143
+ } | ([KeysOfKind<G, K, "position">] extends [never] ? never : {
144
+ readonly interaction: K;
145
+ readonly input?: KeysOfKind<G, K, "card">;
146
+ readonly params?: never;
147
+ readonly position: PositionValue<G, K>;
148
+ });
149
+ }[InteractionKey<G>];
150
+
151
+ /** Internal operations over admitted projections; never a game facade widened to unknown. */
152
+ declare const runtimeFeatures: unique symbol;
153
+ interface RuntimeInput {
154
+ readonly key: string;
155
+ readonly kind: InteractionInputDescriptor["kind"];
156
+ getDomain(): InputDomain;
157
+ getIsEligible(value: RuntimeJson): boolean;
158
+ getIsSelected(value: RuntimeJson): boolean;
159
+ getTargetProps(value: RuntimeJson): ActionProps;
160
+ }
161
+ interface RuntimeInteraction {
162
+ readonly key: string;
163
+ getIsAvailable(params?: Readonly<Record<string, RuntimeJson>>): boolean;
164
+ getIsReady(params?: Readonly<Record<string, RuntimeJson>>): boolean;
165
+ getStatus(): "open" | "submitting" | "submitted";
166
+ submit(params?: Readonly<Record<string, RuntimeJson>>): Promise<SubmitResult>;
167
+ getInputs(): readonly RuntimeInput[];
168
+ }
169
+ interface RuntimeFeatureSnapshot {
170
+ readonly view: unknown;
171
+ readonly snapshot: SourceSnapshot | null;
172
+ readonly connection: SourceState["connection"];
173
+ readonly request: SourceState["request"];
174
+ readonly interactions: {
175
+ list(): readonly RuntimeInteraction[];
176
+ };
177
+ readonly zones: {
178
+ find(id: string, hostId: string): {
179
+ readonly count: number;
180
+ } | undefined;
181
+ };
182
+ readonly cards: {
183
+ find(id: string): {
184
+ readonly zone: string;
185
+ readonly hostId: string;
186
+ getInteractions(): readonly RuntimeInteraction[];
187
+ } | undefined;
188
+ };
189
+ }
190
+ interface RuntimeFeatureGame extends RuntimeFeatureSnapshot {
191
+ getSnapshot(): RuntimeFeatureSnapshot;
192
+ getOptions(): {
193
+ readonly source: GameSource;
194
+ };
195
+ subscribe(listener: () => void): () => void;
196
+ }
197
+ interface RuntimeBoard {
198
+ readonly id: string;
199
+ readonly data: SeatBoardTopology;
200
+ readonly game: RuntimeFeatureGame;
201
+ }
202
+ interface RuntimeFeatureContext {
203
+ readonly game: RuntimeFeatureGame;
204
+ getBoards(): Readonly<Record<string, SeatBoardTopology>>;
205
+ createBoard(data: SeatBoardTopology): RuntimeBoard;
206
+ routeTarget(target: RuntimeSelectionTarget, options?: RuntimeTargetOptions): void;
207
+ getCanDropCard(cardId: string, target: RuntimeDropTarget): boolean;
208
+ routeCardDrop(cardId: string, target: RuntimeDropTarget): void;
209
+ getCanDropCardGroup(cardIds: readonly string[], target: RuntimeDropTarget): boolean;
210
+ routeCardGroupDrop(cardIds: readonly string[], target: RuntimeDropTarget): void;
211
+ invalidate(): void;
212
+ }
213
+
214
+ type Domain<Type extends InputDomain["type"]> = Extract<InputDomain, {
215
+ type: Type;
216
+ }>;
217
+ type Editable<Value> = {
218
+ readonly value: Value;
219
+ readonly setValue: (value: Value) => void;
220
+ };
221
+ type Control<Type extends "boundedNumber" | "resourceMap", Value> = {
222
+ readonly type: Type;
223
+ readonly domain: Domain<Type>;
224
+ } & (({
225
+ readonly mode: "single";
226
+ } & Editable<Value | undefined>) | ({
227
+ readonly mode: "many";
228
+ } & Editable<Value[]>));
229
+ interface InputTargetOption<Value = RuntimeJson> {
230
+ readonly value: Value;
231
+ readonly label: string;
232
+ readonly selected: boolean;
233
+ readonly props: ActionProps;
234
+ }
235
+ /** A captured, descriptor-driven editor. Its handlers retain the input's lifetime. */
236
+ type InputControl = {
237
+ readonly key: string;
238
+ readonly disabled: boolean;
239
+ readonly props: {
240
+ readonly disabled: boolean;
241
+ readonly [key: `data-${string}`]: string | number | boolean | undefined;
242
+ };
243
+ } & (Control<"boundedNumber", number> | Control<"resourceMap", Record<string, number>> | {
244
+ readonly type: "targets";
245
+ readonly options: readonly InputTargetOption[];
246
+ });
247
+
248
+ type PhaseName<G> = [PhaseNamesOfDefinition<G>] extends [never] ? string : PhaseNamesOfDefinition<G>;
249
+ type InteractionKey<G> = unknown extends G ? string : [PhaseNamesOfDefinition<G>] extends [never] ? string : {
250
+ [P in PhaseNamesOfDefinition<G>]: `${P}.${InteractionIdOfDefinitionPhase<G, P>}`;
251
+ }[PhaseNamesOfDefinition<G>];
252
+ type InteractionIdentity<G, K> = {
253
+ [P in PhaseNamesOfDefinition<G>]: {
254
+ [I in InteractionIdOfDefinitionPhase<G, P>]: `${P}.${I}` extends K ? {
255
+ phase: P;
256
+ id: I;
257
+ } : never;
258
+ }[InteractionIdOfDefinitionPhase<G, P>];
259
+ }[PhaseNamesOfDefinition<G>];
260
+ type RawInteractionParams<G, K extends InteractionKey<G>> = unknown extends G ? Record<string, RuntimeJson> : [PhaseNamesOfDefinition<G>] extends [never] ? Record<string, RuntimeJson> : InteractionIdentity<G, K> extends infer Identity ? Identity extends {
261
+ phase: infer P extends PhaseNamesOfDefinition<G>;
262
+ id: infer I;
263
+ } ? I extends InteractionIdOfDefinitionPhase<G, P> ? ClientParamsOfInteractionOfDefinition<G, P, I> : never : never : never;
264
+ type UnionKeys<T> = T extends unknown ? keyof T : never;
265
+ type UnionValue<T, Key> = T extends unknown ? Key extends keyof T ? T[Key] : never : never;
266
+ type InteractionParams<G, K extends InteractionKey<G>> = {
267
+ [N in UnionKeys<RawInteractionParams<G, K>>]: UnionValue<RawInteractionParams<G, K>, N>;
268
+ };
269
+ type CollectorOf<G, K, N extends string> = InteractionIdentity<G, K> extends infer Identity ? Identity extends {
270
+ phase: infer P extends PhaseNamesOfDefinition<G>;
271
+ id: infer I;
272
+ } ? I extends InteractionIdOfDefinitionPhase<G, P> ? InputCollectorOfDefinition<G, P, I, N> : never : never : never;
273
+ type InputKind<G, K extends InteractionKey<G>, N extends InputKey<G, K>> = [CollectorOf<G, K, N>] extends [never] ? InteractionInputDescriptor["kind"] : CollectorOf<G, K, N> extends {
274
+ readonly kind: infer Kind extends InteractionInputDescriptor["kind"];
275
+ } ? Kind : InteractionInputDescriptor["kind"];
276
+ type SelectionValue<Collector, Value> = Collector extends {
277
+ readonly selection: {
278
+ readonly mode: "many";
279
+ };
280
+ } | {
281
+ readonly domain: (...args: never[]) => {
282
+ readonly type: "choiceList";
283
+ };
284
+ } ? Value extends readonly (infer Item)[] ? Item : never : Value;
285
+ type InputTarget<G, K extends InteractionKey<G>, N extends InputKey<G, K>> = [CollectorOf<G, K, N>] extends [never] ? Exclude<InteractionParams<G, K>[N], undefined> : SelectionValue<CollectorOf<G, K, N>, Exclude<InteractionParams<G, K>[N], undefined>>;
286
+ type AnyInput<G, F extends Features, K extends InteractionKey<G>> = {
287
+ [N in InputKey<G, K>]: Input<G, F, K, N>;
288
+ }[InputKey<G, K>];
289
+ type AnyInteraction<G, F extends Features = Record<never, never>> = {
290
+ [K in InteractionKey<G>]: Interaction<G, F, K>;
291
+ }[InteractionKey<G>];
292
+ type InputKey<G, K extends InteractionKey<G>> = keyof InteractionParams<G, K> & string;
293
+ type IdOf<G, K extends string> = G extends {
294
+ contract: {
295
+ manifest: {
296
+ ids: Record<K, infer Schema extends z.ZodType>;
297
+ };
298
+ };
299
+ } ? z.output<Schema> & string : string;
300
+ type ViewOf<G> = [ViewOfDefinition<G>] extends [never] ? unknown : ViewOfDefinition<G>;
301
+ type Drafts<G> = Readonly<Partial<{
302
+ [K in InteractionKey<G>]: Readonly<Partial<InteractionParams<G, K>>>;
303
+ }>>;
304
+ interface LocalState<G> {
305
+ readonly drafts: Drafts<G>;
306
+ readonly activeInteraction: InteractionKey<G> | null;
307
+ }
308
+ interface Feature {
309
+ readonly root?: object;
310
+ readonly interaction?: object;
311
+ readonly input?: object;
312
+ readonly zone?: object;
313
+ readonly card?: object;
314
+ readonly board?: object;
315
+ readonly dispose?: () => void;
316
+ }
317
+ type Features = Readonly<Record<string, Feature>>;
318
+ type Intersection<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void ? I : never;
319
+ type Hook<F extends Features, H extends keyof Feature> = keyof F extends never ? Record<never, never> : Intersection<{
320
+ [K in keyof F]: F[K] extends Record<H, infer A> ? A : Record<never, never>;
321
+ }[keyof F]>;
322
+ type TableOfGame<G> = G extends {
323
+ contract: {
324
+ manifest: {
325
+ tableSchema: infer Schema extends z.ZodType;
326
+ };
327
+ };
328
+ } ? z.output<Schema> : never;
329
+ /** Actual host identity admitted for one zone's attachment. */
330
+ type ZoneHostId<G, K extends IdOf<G, "zoneId"> = IdOf<G, "zoneId">> = [
331
+ TableOfGame<G>
332
+ ] extends [never] ? string : TableOfGame<G> extends {
333
+ zones: infer Zones;
334
+ } ? K extends keyof Zones ? Extract<keyof Zones[K], string> : never : never;
335
+ type SeatCell<Cell> = Cell extends {
336
+ readonly id: string;
337
+ readonly tileId: string;
338
+ } ? Omit<Cell, "id" | "tileId"> & {
339
+ readonly id: SeatSpaceRef;
340
+ readonly tileRef: SeatTileRef;
341
+ } : Cell;
342
+ type SeatRelation<Relation> = Relation extends {
343
+ readonly fromSpaceId: string;
344
+ readonly toSpaceId: string;
345
+ } ? Omit<Relation, "fromSpaceId" | "toSpaceId"> & {
346
+ readonly fromSpaceId: SeatSpaceRef;
347
+ readonly toSpaceId: SeatSpaceRef;
348
+ } : Relation;
349
+ type SeatElement<Element> = Element extends {
350
+ readonly spaceIds: readonly string[];
351
+ } ? Omit<Element, "spaceIds"> & {
352
+ readonly spaceIds: readonly SeatSpaceRef[];
353
+ } : Element;
354
+ type TileDefinitionsOf<G> = G extends {
355
+ contract: {
356
+ manifest: {
357
+ tileDefinitions: infer Definitions;
358
+ };
359
+ };
360
+ } ? Definitions : never;
361
+ type VisibleTileData<G, Runtime> = Runtime extends {
362
+ readonly tileTypeId: infer Type extends string;
363
+ readonly properties: infer Properties;
364
+ } ? Type extends keyof TileDefinitionsOf<G> ? TileDefinitionsOf<G>[Type] extends {
365
+ readonly fields: infer Fields;
366
+ } ? Omit<Extract<ProjectedTile, {
367
+ disclosure: "visible";
368
+ }>, "tileTypeId" | "properties" | "fields"> & {
369
+ readonly tileTypeId: Type;
370
+ readonly properties: ReadonlyData<Properties>;
371
+ readonly fields: ReadonlyData<Fields>;
372
+ } : never : never : never;
373
+ /** The seat DTO is canonical; known games refine only disclosed authored face data. */
374
+ type TileDataOf<G> = [TableOfGame<G>] extends [never] ? ProjectedTile : Extract<ProjectedTile, {
375
+ disclosure: "concealed";
376
+ }> | (TableOfGame<G> extends {
377
+ readonly tiles: infer Tiles;
378
+ } ? VisibleTileData<G, Tiles[keyof Tiles]> : never);
379
+ type PlacedTileDataOf<G> = TileDataOf<G> & {
380
+ readonly placement: Extract<SeatBoardTopology, {
381
+ layout: "hex" | "square";
382
+ }>["tiles"][number]["placement"];
383
+ };
384
+ type SeatTopology<Topology, G> = Topology extends {
385
+ readonly layout: "hex" | "square";
386
+ readonly spaces: infer Spaces;
387
+ readonly relations: readonly (infer Relation)[];
388
+ readonly edges: readonly (infer Edge)[];
389
+ readonly vertices: readonly (infer Vertex)[];
390
+ } ? Omit<Topology, "spaces" | "relations" | "edges" | "vertices"> & {
391
+ readonly spaces: Readonly<Record<SeatSpaceRef, SeatCell<Spaces[keyof Spaces]>>>;
392
+ readonly tiles: readonly PlacedTileDataOf<G>[];
393
+ readonly relations: readonly SeatRelation<Relation>[];
394
+ readonly edges: readonly SeatElement<Edge>[];
395
+ readonly vertices: readonly SeatElement<Vertex>[];
396
+ } : Topology;
397
+ type BoardDataOf<G, K extends string> = [TableOfGame<G>] extends [never] ? SeatBoardTopology : G extends {
398
+ contract: {
399
+ manifest: infer Definitions extends TopologyDefinitions;
400
+ };
401
+ } ? TableOfGame<G> extends {
402
+ boards: infer Boards;
403
+ } ? K extends Extract<keyof Boards, string> ? SeatTopology<BoardTopologyOf<TableOfGame<G>, Definitions, K>, G> : never : never : never;
404
+ type BoardSpaceId<G, B extends IdOf<G, "boardId">> = B extends unknown ? BoardDataOf<G, B> extends {
405
+ readonly spaces: infer Spaces;
406
+ } ? keyof Spaces & string : never : never;
407
+ type BoardSpaceData<G, B extends IdOf<G, "boardId">, S extends BoardSpaceId<G, B>> = B extends unknown ? BoardDataOf<G, B> extends {
408
+ readonly spaces: infer Spaces;
409
+ } ? S extends keyof Spaces ? Spaces[S] & {
410
+ readonly id: S;
411
+ } : never : never : never;
412
+ interface BoardSpace<G, F extends Features = Record<never, never>, B extends IdOf<G, "boardId"> = IdOf<G, "boardId">, S extends BoardSpaceId<G, B> = BoardSpaceId<G, B>> {
413
+ readonly id: S;
414
+ readonly data: BoardSpaceData<G, B, S>;
415
+ readonly board: Board<G, F, B>;
416
+ getIsEligible(): boolean;
417
+ getIsSelectable(): boolean;
418
+ getIsSelected(): boolean;
419
+ getSelectHandler(options?: TargetOptions<G>): () => void;
420
+ getTargetProps(options?: TargetOptions<G>): ActionProps;
421
+ }
422
+ interface BoardSpaceCollection<G, F extends Features = Record<never, never>, B extends IdOf<G, "boardId"> = IdOf<G, "boardId">> {
423
+ get<S extends BoardSpaceId<G, B>>(id: S): BoardSpace<G, F, B, S>;
424
+ find<S extends BoardSpaceId<G, B>>(id: S): BoardSpace<G, F, B, S> | undefined;
425
+ getAll(): readonly BoardSpace<G, F, B>[];
426
+ }
427
+ type BoardHooks<G, F extends Features, B extends IdOf<G, "boardId">> = {
428
+ [K in keyof Hook<F, "board">]: Hook<F, "board">[K] extends BoardSpaceCollection<G> ? BoardSpaceCollection<G, F, B> : Hook<F, "board">[K];
429
+ };
430
+ interface BoardBase<G, K extends IdOf<G, "boardId"> = IdOf<G, "boardId">> {
431
+ readonly id: K;
432
+ readonly game: CoreInstance<G>;
433
+ readonly data: BoardDataOf<G, K>;
434
+ }
435
+ type Board<G, F extends Features, K extends IdOf<G, "boardId"> = IdOf<G, "boardId">> = BoardBase<G, K> & BoardHooks<G, F, K> & {
436
+ readonly game: GameInstance<G, F>;
437
+ };
438
+ interface BoardCollection<G, F extends Features = Record<never, never>> {
439
+ get<K extends IdOf<G, "boardId">>(id: K): Board<G, F, K>;
440
+ find<K extends IdOf<G, "boardId">>(id: K): Board<G, F, K> | undefined;
441
+ getAll(): readonly Board<G, F>[];
442
+ }
443
+ type RootHooks<G, F extends Features> = {
444
+ [K in keyof Hook<F, "root">]: Hook<F, "root">[K] extends BoardCollection<G> ? BoardCollection<G, F> : Hook<F, "root">[K];
445
+ };
446
+ interface FeatureContext<G> {
447
+ readonly [runtimeFeatures]: RuntimeFeatureContext;
448
+ createBoard<K extends IdOf<G, "boardId">>(data: BoardDataOf<G, K> & {
449
+ readonly id: K;
450
+ }): BoardBase<G, K>;
451
+ routeTarget(target: SelectionTarget<G>, options?: TargetOptions<G>): void;
452
+ routeCardDrop(cardId: SeatCardId<G>, target: DropTarget<G>): void;
453
+ invalidate(): void;
454
+ }
455
+ interface NativeEvent {
456
+ preventDefault(): void;
457
+ }
458
+ type ActionProps = {
459
+ readonly onClick: (event?: NativeEvent) => void;
460
+ readonly disabled: boolean;
461
+ readonly type: "button";
462
+ readonly [key: `data-${string}`]: string | number | boolean | undefined;
463
+ };
464
+ interface Player<G, K extends IdOf<G, "playerId"> = IdOf<G, "playerId">> {
465
+ readonly id: K;
466
+ readonly index: number;
467
+ readonly name: string;
468
+ readonly color?: string;
469
+ readonly isMe: boolean;
470
+ readonly game: CoreInstance<G>;
471
+ }
472
+ interface Phase<G> {
473
+ readonly current: PhaseName<G> | null;
474
+ is(name: PhaseName<G>): boolean;
475
+ switch<R>(routes: {
476
+ [P in PhaseName<G>]: () => R;
477
+ }): R | null;
478
+ }
479
+ interface Turn<G> {
480
+ readonly activePlayerIds: readonly IdOf<G, "playerId">[];
481
+ readonly currentPlayerId: IdOf<G, "playerId"> | null;
482
+ readonly order: readonly IdOf<G, "playerId">[];
483
+ readonly isMine: boolean;
484
+ }
485
+ type DomainOfCollector<Collector> = Collector extends {
486
+ readonly domain: (...args: never[]) => infer Domain extends InputDomain;
487
+ } ? Domain : InputDomain;
488
+ type InputDomainOf<G, K extends InteractionKey<G>, N extends InputKey<G, K>> = [CollectorOf<G, K, N>] extends [never] ? InputDomain : DomainOfCollector<CollectorOf<G, K, N>>;
489
+ type SelectionModeOfCollector<Collector> = Collector extends {
490
+ readonly selection: {
491
+ readonly mode: "many";
492
+ };
493
+ } | {
494
+ readonly domain: (...args: never[]) => {
495
+ readonly type: "choiceList";
496
+ };
497
+ } ? "many" : "single";
498
+ type InputSelectionMode<G, K extends InteractionKey<G>, N extends InputKey<G, K>> = [CollectorOf<G, K, N>] extends [never] ? "single" | "many" : SelectionModeOfCollector<CollectorOf<G, K, N>>;
499
+ interface InputBase<G, K extends InteractionKey<G>, N extends InputKey<G, K>> {
500
+ readonly key: N;
501
+ readonly kind: InputKind<G, K, N>;
502
+ readonly game: CoreInstance<G>;
503
+ readonly interaction: InteractionBase<G, K>;
504
+ readonly domainType: InputDomainOf<G, K, N>["type"];
505
+ readonly selectionMode: InputSelectionMode<G, K, N>;
506
+ getDomain(): InputDomainOf<G, K, N>;
507
+ getControl(): InputControl;
508
+ getTargetOptions(): readonly InputTargetOption<InputTarget<G, K, N>>[];
509
+ getValue(): InteractionParams<G, K>[N] | undefined;
510
+ readonly setValue: (value: Exclude<InteractionParams<G, K>[N], undefined>) => void;
511
+ clear(): void;
512
+ getIsReady(): boolean;
513
+ getEligibleTargets(): readonly InputTarget<G, K, N>[];
514
+ readonly getIsEligible: (value: InputTarget<G, K, N>) => boolean;
515
+ readonly getIsSelected: (value: InputTarget<G, K, N>) => boolean;
516
+ readonly getSelectHandler: (value: InputTarget<G, K, N>) => () => void;
517
+ readonly getTargetProps: (value: InputTarget<G, K, N>) => ActionProps;
518
+ }
519
+ type Input<G, F extends Features, K extends InteractionKey<G>, N extends InputKey<G, K>> = Omit<InputBase<G, K, N>, "interaction" | "game"> & Hook<F, "input"> & {
520
+ readonly game: GameInstance<G, F>;
521
+ readonly interaction: Interaction<G, F, K>;
522
+ };
523
+ interface InteractionBase<G, K extends InteractionKey<G>> {
524
+ readonly key: K;
525
+ readonly id: [InteractionIdentity<G, K>] extends [never] ? string : InteractionIdentity<G, K>["id"];
526
+ readonly phase: [InteractionIdentity<G, K>] extends [never] ? PhaseName<G> : InteractionIdentity<G, K>["phase"];
527
+ readonly label: string;
528
+ readonly help?: string;
529
+ readonly kind: "inputs" | "steps";
530
+ readonly game: CoreInstance<G>;
531
+ getAvailability(): InteractionDescriptor["availability"];
532
+ getIsAvailable(params?: InteractionParams<G, K>): boolean;
533
+ getUnavailableReason(): string | null;
534
+ getStep(): InteractionDescriptor["step"] | null;
535
+ getStepIndex(): number | null;
536
+ getIsReady(params?: InteractionParams<G, K>): boolean;
537
+ getMissingInputs(): readonly InputKey<G, K>[];
538
+ getStatus(): "open" | "submitting" | "submitted";
539
+ submit(params?: InteractionParams<G, K>): Promise<SubmitResult>;
540
+ cancel(): Promise<SubmitResult>;
541
+ reset(): void;
542
+ activate(): void;
543
+ getSubmitHandler(params?: InteractionParams<G, K>): (event?: NativeEvent) => void;
544
+ getSubmitProps(params?: InteractionParams<G, K>): ActionProps;
545
+ }
546
+ type Interaction<G, F extends Features, K extends InteractionKey<G>> = InteractionBase<G, K> & Hook<F, "interaction"> & {
547
+ readonly game: GameInstance<G, F>;
548
+ getInput<N extends InputKey<G, K>>(key: N): Input<G, F, K, N>;
549
+ findInput<N extends InputKey<G, K>>(key: N): Input<G, F, K, N> | undefined;
550
+ getInputs(): readonly AnyInput<G, F, K>[];
551
+ };
552
+ type ReadonlyData<T> = ReadonlyRuntimeData<T>;
553
+ type CardDataOf<G, K extends string> = [TableOfGame<G>] extends [never] ? ReadonlyData<ViewCard<K>> : TableOfGame<G> extends {
554
+ cards: Record<string, {
555
+ cardType: string;
556
+ properties: Record<string, unknown>;
557
+ }>;
558
+ } ? K extends keyof TableOfGame<G>["cards"] ? ReadonlyData<ViewCardOfTable<TableOfGame<G>, K>> : never : never;
559
+ interface CardEntity<G> {
560
+ readonly zone: IdOf<G, "zoneId">;
561
+ readonly hostId: ZoneHostId<G>;
562
+ readonly index: number;
563
+ readonly game: CoreInstance<G>;
564
+ getInteractions(): readonly AnyInteraction<G>[];
565
+ getIsEligible(): boolean;
566
+ getIsSelected(): boolean;
567
+ getCanSelect(options?: TargetOptions<G>): boolean;
568
+ select(options?: TargetOptions<G>): void;
569
+ getSelectHandler(options?: TargetOptions<G>): () => void;
570
+ getProps(options?: TargetOptions<G>): ActionProps;
571
+ }
572
+ /** The id a seat knows a card by. */
573
+ type SeatCardId<G> = IdOf<G, "cardId"> | HiddenCardId;
574
+ type HiddenCard<K extends HiddenCardId> = {
575
+ readonly hidden: true;
576
+ readonly id: K;
577
+ readonly view: null;
578
+ /** The URL of the card's back image, when it has one. */
579
+ readonly backImage: string | null;
580
+ };
581
+ /** A hidden id is hidden; any other id is visible, or either when it is `string`. */
582
+ type CardVisibility<G, K extends string> = K extends HiddenCardId ? HiddenCard<K> : (HiddenCardId extends K ? HiddenCard<HiddenCardId> : never) | {
583
+ readonly hidden: false;
584
+ readonly id: K;
585
+ readonly view: CardDataOf<G, K>;
586
+ };
587
+ type CardBase<G, K extends SeatCardId<G> = SeatCardId<G>> = CardEntity<G> & CardVisibility<G, K>;
588
+ type Card<G, F extends Features, K extends SeatCardId<G> = SeatCardId<G>> = Omit<CardEntity<G>, "getInteractions" | "game"> & CardVisibility<G, K> & Hook<F, "card"> & {
589
+ readonly game: GameInstance<G, F>;
590
+ getInteractions(): readonly AnyInteraction<G, F>[];
591
+ };
592
+ /** One tile presentation admitted for this seat; its reference expires with its frame. */
593
+ interface Tile<G, F extends Features = Record<never, never>> {
594
+ readonly ref: SeatTileRef;
595
+ readonly data: TileDataOf<G>;
596
+ readonly zone: IdOf<G, "zoneId">;
597
+ readonly hostId: ZoneHostId<G>;
598
+ readonly index: number;
599
+ readonly game: GameInstance<G, F>;
600
+ getInteractions(): readonly AnyInteraction<G, F>[];
601
+ getIsEligible(): boolean;
602
+ getIsSelected(): boolean;
603
+ getCanSelect(options?: TargetOptions<G>): boolean;
604
+ select(options?: TargetOptions<G>): void;
605
+ getSelectHandler(options?: TargetOptions<G>): () => void;
606
+ getTargetProps(options?: TargetOptions<G>): ActionProps;
607
+ }
608
+ interface ZoneBase<G, K extends IdOf<G, "zoneId"> = IdOf<G, "zoneId">> {
609
+ readonly id: K;
610
+ readonly hostId: ZoneHostId<G, K>;
611
+ /** Number of projected cards and tiles; omitted inventory contributes nothing. */
612
+ readonly count: number;
613
+ readonly game: CoreInstance<G>;
614
+ getIsEmpty(): boolean;
615
+ }
616
+ type Zone<G, F extends Features, K extends IdOf<G, "zoneId"> = IdOf<G, "zoneId">> = ZoneBase<G, K> & Hook<F, "zone"> & {
617
+ readonly game: GameInstance<G, F>;
618
+ getCards(options?: {
619
+ sort?: (a: Card<G, F>, b: Card<G, F>) => number;
620
+ }): readonly Card<G, F>[];
621
+ getTiles(): readonly Tile<G, F>[];
622
+ getTile(ref: SeatTileRef): Tile<G, F>;
623
+ findTile(ref: SeatTileRef): Tile<G, F> | undefined;
624
+ getCard<K extends SeatCardId<G>>(id: K): Card<G, F, K>;
625
+ findCard<K extends SeatCardId<G>>(id: K): Card<G, F, K> | undefined;
626
+ };
627
+ interface ReadModel<G, F extends Features = Record<never, never>> {
628
+ readonly snapshot: SourceSnapshot | null;
629
+ readonly view: ViewOf<G> | null;
630
+ readonly version: number | null;
631
+ readonly connection: SourceState["connection"];
632
+ readonly failure: SourceState["failure"];
633
+ readonly request: SourceState["request"];
634
+ readonly state: LocalState<G>;
635
+ readonly phase: Phase<G>;
636
+ readonly turn: Turn<G>;
637
+ readonly me: {
638
+ readonly id: IdOf<G, "playerId">;
639
+ readonly player: Player<G>;
640
+ getCanAct(): boolean;
641
+ } | null;
642
+ readonly players: {
643
+ get<K extends IdOf<G, "playerId">>(id: K): Player<G, K>;
644
+ find<K extends IdOf<G, "playerId">>(id: K): Player<G, K> | undefined;
645
+ getAll(): readonly Player<G>[];
646
+ next(id: IdOf<G, "playerId">): Player<G>;
647
+ readonly order: readonly IdOf<G, "playerId">[];
648
+ };
649
+ readonly interactions: {
650
+ get<K extends InteractionKey<G>>(key: K): Interaction<G, F, K>;
651
+ find<K extends InteractionKey<G>>(key: K): Interaction<G, F, K> | undefined;
652
+ list(): readonly AnyInteraction<G, F>[];
653
+ listAvailable(): readonly AnyInteraction<G, F>[];
654
+ };
655
+ readonly inputs: {
656
+ get<K extends InteractionKey<G>, N extends InputKey<G, K>>(interaction: K, input: N): Input<G, F, K, N>;
657
+ find<K extends InteractionKey<G>, N extends InputKey<G, K>>(interaction: K, input: N): Input<G, F, K, N> | undefined;
658
+ };
659
+ readonly zones: {
660
+ get<K extends IdOf<G, "zoneId">>(id: K, hostId: ZoneHostId<G, NoInfer<K>>): Zone<G, F, K>;
661
+ find<K extends IdOf<G, "zoneId">>(id: K, hostId: ZoneHostId<G, NoInfer<K>>): Zone<G, F, K> | undefined;
662
+ getAll(): readonly Zone<G, F>[];
663
+ };
664
+ readonly cards: {
665
+ get<K extends SeatCardId<G>>(id: K): Card<G, F, K>;
666
+ find<K extends SeatCardId<G>>(id: K): Card<G, F, K> | undefined;
667
+ };
668
+ readonly events: {
669
+ readonly recent: readonly GameEvent[];
670
+ };
671
+ }
672
+ interface InstanceOptions<G, S extends GameSource = GameSource> {
673
+ readonly source: S;
674
+ readonly initialState?: Partial<LocalState<G>>;
675
+ readonly state?: Partial<LocalState<G>>;
676
+ readonly onDraftsChange?: (drafts: Drafts<G>) => void;
677
+ readonly onActiveInteractionChange?: (key: InteractionKey<G> | null) => void;
678
+ readonly onError?: (error: unknown) => void;
679
+ readonly debug?: boolean;
680
+ }
681
+ type CoreInstance<G> = ReadModel<G> & {
682
+ readonly store: Pick<Store<ReadModel<G>>, "get" | "subscribe">;
683
+ getSnapshot(): ReadModel<G>;
684
+ getOptions(): InstanceOptions<G>;
685
+ setOptions(options: InstanceOptions<G>): void;
686
+ subscribe(listener: () => void): () => void;
687
+ dispose(): void;
688
+ assertCoverage(): void;
689
+ };
690
+ type GameSnapshot<G, F extends Features = Record<never, never>> = ReadModel<G, F> & RootHooks<G, F>;
691
+ type GameInstance<G, F extends Features = Record<never, never>, S extends GameSource = GameSource> = Omit<CoreInstance<G>, keyof ReadModel<G> | "store" | "getSnapshot" | "getOptions" | "setOptions"> & ReadModel<G, F> & RootHooks<G, F> & {
692
+ readonly store: Pick<Store<GameSnapshot<G, F>>, "get" | "subscribe">;
693
+ getSnapshot(): GameSnapshot<G, F>;
694
+ getOptions(): InstanceOptions<G, S>;
695
+ setOptions(options: InstanceOptions<G, S>): void;
696
+ } & (S extends {
697
+ apply(action: infer A): infer R;
698
+ } ? {
699
+ apply(action: A): R;
700
+ } : Record<never, never>) & (S extends {
701
+ explore(...args: infer A): infer R;
702
+ } ? {
703
+ explore(...args: A): R;
704
+ } : Record<never, never>);
705
+
706
+ /** A zone control carries the actual admitted attachment, including its host. */
707
+ type ShortcutZoneTarget<G> = {
708
+ [Z in IdOf<G, "zoneId">]: {
709
+ readonly kind: "zone";
710
+ readonly zoneId: Z;
711
+ readonly hostId: ZoneHostId<G, Z>;
712
+ };
713
+ }[IdOf<G, "zoneId">];
714
+ type ShortcutTarget<G> = SelectionTarget<G> | ShortcutZoneTarget<G>;
715
+ type TargetKind = SelectionTarget<unknown>["kind"];
716
+ type CollectorKind<Kind extends TargetKind> = Kind extends "space" ? "board-space" : Kind extends "edge" ? "board-edge" : Kind extends "vertex" ? "board-vertex" : Kind;
717
+ type TargetFor<G, K extends InteractionKey<G>, N extends InputKey<G, K>, Kind extends TargetKind> = Extract<SelectionTarget<G>, {
718
+ readonly kind: Kind;
719
+ }> & {
720
+ readonly value: InputTarget<G, K, N>;
721
+ };
722
+ type Binding<G, K extends InteractionKey<G>, Target, Filter> = Filter & {
723
+ /** Exact browser event.key values; modifiers and held repeats are ignored. */
724
+ readonly keys: readonly string[];
725
+ readonly label: string;
726
+ readonly kind: "interaction";
727
+ readonly interaction: K;
728
+ readonly inputs: (context: {
729
+ readonly key: string;
730
+ readonly target: Target;
731
+ }) => InteractionParams<G, K>;
732
+ };
733
+ type SelectionBinding<G, K extends InteractionKey<G>> = {
734
+ [N in InputKey<G, K>]: {
735
+ [Kind in TargetKind]: [
736
+ Extract<InputKind<G, K, N>, CollectorKind<Kind>>
737
+ ] extends [never] ? never : Binding<G, K, TargetFor<G, K, N, Kind>, {
738
+ readonly target: Kind;
739
+ readonly input: N;
740
+ }>;
741
+ }[TargetKind];
742
+ }[InputKey<G, K>];
743
+ /** Correlated by interaction, input kind, and the selected target's value. */
744
+ type InteractionShortcutBinding<G> = {
745
+ [K in InteractionKey<G>]: SelectionBinding<G, K> | {
746
+ [Z in IdOf<G, "zoneId">]: Binding<G, K, Extract<ShortcutZoneTarget<G>, {
747
+ readonly zoneId: Z;
748
+ }>, {
749
+ readonly target: "zone";
750
+ readonly zoneId: Z;
751
+ }>;
752
+ }[IdOf<G, "zoneId">];
753
+ }[InteractionKey<G>];
754
+ /** Local presentation actions run only from control focus, independent of reducer turns. */
755
+ type LocalShortcutBinding<G> = {
756
+ [Z in IdOf<G, "zoneId">]: {
757
+ readonly kind: "local";
758
+ readonly keys: readonly string[];
759
+ readonly label: string;
760
+ readonly target: "zone";
761
+ readonly zoneId: Z;
762
+ /** Pure applicability predicate, also evaluated for hints. */
763
+ readonly getIsAvailable?: (context: {
764
+ readonly key: string;
765
+ readonly target: Extract<ShortcutZoneTarget<G>, {
766
+ readonly zoneId: Z;
767
+ }>;
768
+ }) => boolean;
769
+ readonly run: (context: {
770
+ readonly key: string;
771
+ readonly target: Extract<ShortcutZoneTarget<G>, {
772
+ readonly zoneId: Z;
773
+ }>;
774
+ }) => void | Promise<void>;
775
+ };
776
+ }[IdOf<G, "zoneId">];
777
+ type ShortcutBinding<G> = InteractionShortcutBinding<G> | LocalShortcutBinding<G>;
778
+ interface ShortcutOptions<G> {
779
+ readonly bindings: readonly ShortcutBinding<G>[];
780
+ }
781
+ type ShortcutHint<G = unknown> = {
782
+ readonly keys: readonly string[];
783
+ readonly label: string;
784
+ } & ({
785
+ readonly kind: "interaction";
786
+ readonly interaction: InteractionKey<G>;
787
+ } | {
788
+ readonly kind: "local";
789
+ });
790
+ type ShortcutResult = {
791
+ readonly kind: "interaction";
792
+ readonly result: SubmitResult;
793
+ } | {
794
+ readonly kind: "local";
795
+ };
796
+ /** Mounted control activity; explicit-target interaction menus need no focus. */
797
+ interface ShortcutActivity<G> {
798
+ readonly focusedTarget: ShortcutTarget<G> | null;
799
+ /** Card press, drag, or submitted drag overlay still settling. */
800
+ readonly pointerActive: boolean;
801
+ }
802
+ interface ShortcutsController<G> {
803
+ /** UI binding configuration has its own subscription, independent of reducer frames. */
804
+ readonly configuration: Pick<Store<ShortcutOptions<G> | null>, "get" | "subscribe">;
805
+ /** Registers one mounted adapter. Cleanup removes both behavior and hints. */
806
+ register(options: ShortcutOptions<G>): {
807
+ update(options: ShortcutOptions<G>): void;
808
+ dispose(): void;
809
+ };
810
+ /** null means unhandled; a handled key runs or submits exactly once. */
811
+ handle(key: string, target: ShortcutTarget<G> | null, activity?: ShortcutActivity<G>): Promise<ShortcutResult> | null;
812
+ getHints(target: ShortcutTarget<G> | null, activity?: ShortcutActivity<G>): readonly ShortcutHint<G>[];
813
+ }
814
+ /** Headless and opt-in: no names, bindings or browser listeners are installed by default. */
815
+ declare function shortcutsFeature<G>(_game: CoreInstance<G>, context: FeatureContext<G>): {
816
+ root: {
817
+ shortcuts: ShortcutsController<G>;
818
+ };
819
+ dispose(): void;
820
+ };
821
+
822
+ export { type RuntimeBoardDropTarget as $, type ActionProps as A, type Board as B, type Card as C, type Drafts as D, type InputTargetOption as E, type Feature as F, type GameInstance as G, type Hook as H, type IdOf as I, type InstanceOptions as J, type Interaction as K, type InteractionBase as L, type InteractionDropTarget as M, type InteractionKey as N, type InteractionParams as O, type InteractionShortcutBinding as P, type LocalShortcutBinding as Q, type LocalState as R, type NativeEvent as S, type Phase as T, type PhaseName as U, type PlacedTileDataOf as V, type Player as W, type PositionDropTarget as X, type ReadModel as Y, type ReadonlyData as Z, type RuntimeBoard as _, type AnyInput as a, type RuntimeBoardTarget as a0, type RuntimeDropTarget as a1, type RuntimeInteractionDropTarget as a2, type RuntimePositionDropTarget as a3, type RuntimeSelectionTarget as a4, type RuntimeTargetOptions as a5, type SeatCardId as a6, type SelectionTarget as a7, type ShortcutActivity as a8, type ShortcutBinding as a9, type ShortcutHint as aa, type ShortcutOptions as ab, type ShortcutResult as ac, type ShortcutTarget as ad, type ShortcutZoneTarget as ae, type ShortcutsController as af, type TableOfGame as ag, type TargetOptions as ah, type Tile as ai, type TileDataOf as aj, type Turn as ak, type ViewOf as al, type Zone as am, type ZoneBase as an, type ZoneHostId as ao, shortcutsFeature as ap, type AnyInteraction as b, type BoardBase as c, type BoardCollection as d, type BoardDataOf as e, type BoardDropTarget as f, type BoardSpace as g, type BoardSpaceCollection as h, type BoardSpaceData as i, type BoardSpaceId as j, type BoardTarget as k, type CardBase as l, type CardDataOf as m, type CoreInstance as n, type DropAreaBinding as o, type DropTarget as p, type FeatureContext as q, type Features as r, type GameSnapshot as s, type Input as t, type InputBase as u, type InputControl as v, type InputDomainOf as w, type InputKey as x, type InputKind as y, type InputTarget as z };