@dreamboard-games/sdk 0.4.0-alpha.1 → 0.4.0-alpha.2

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 (78) hide show
  1. package/REFERENCE.md +1215 -125
  2. package/dist/{ResourceCounter-BTXklCEZ.d.ts → ResourceCounter-BuiNstXs.d.ts} +5 -1
  3. package/dist/{ThemeProvider-DvMl17Ny.d.ts → ThemeProvider-B1sIoBlX.d.ts} +1 -1
  4. package/dist/{attributes-BrZtP9az.d.ts → attributes-DbvyMbXw.d.ts} +17 -2
  5. package/dist/authoring/index.d.ts +66 -0
  6. package/dist/authoring/index.js +560 -0
  7. package/dist/authoring/index.js.map +1 -0
  8. package/dist/browser-interaction.d.ts +205 -5
  9. package/dist/browser-interaction.js +14 -2
  10. package/dist/{chunk-7W6TQO3X.js → chunk-45FI6XII.js} +613 -366
  11. package/dist/chunk-45FI6XII.js.map +1 -0
  12. package/dist/{chunk-3K362ZKR.js → chunk-6JQFGSLD.js} +202 -38
  13. package/dist/chunk-6JQFGSLD.js.map +1 -0
  14. package/dist/{chunk-XXBSIPJX.js → chunk-CP35NPPY.js} +131 -59
  15. package/dist/chunk-CP35NPPY.js.map +1 -0
  16. package/dist/{chunk-XJYUSD5F.js → chunk-FWVV2X74.js} +2 -2
  17. package/dist/{chunk-IUGKW2GS.js → chunk-HWJS3VOJ.js} +6 -2
  18. package/dist/chunk-HWJS3VOJ.js.map +1 -0
  19. package/dist/chunk-K5ZRJTZZ.js +328 -0
  20. package/dist/chunk-K5ZRJTZZ.js.map +1 -0
  21. package/dist/{chunk-7LZZEI25.js → chunk-N6ZDIMRB.js} +1 -1
  22. package/dist/chunk-N6ZDIMRB.js.map +1 -0
  23. package/dist/chunk-O6M6PN4E.js +1225 -0
  24. package/dist/chunk-O6M6PN4E.js.map +1 -0
  25. package/dist/{chunk-AEUXCFGM.js → chunk-PF7L4BMG.js} +1 -8
  26. package/dist/{chunk-AEUXCFGM.js.map → chunk-PF7L4BMG.js.map} +1 -1
  27. package/dist/{chunk-CZMFAS3E.js → chunk-WOWFONLZ.js} +517 -1274
  28. package/dist/chunk-WOWFONLZ.js.map +1 -0
  29. package/dist/{chunk-MALRKLRR.js → chunk-WUIVY2KE.js} +301 -12
  30. package/dist/chunk-WUIVY2KE.js.map +1 -0
  31. package/dist/chunk-ZAS2SENW.js +12 -0
  32. package/dist/chunk-ZAS2SENW.js.map +1 -0
  33. package/dist/codegen.d.ts +11 -3
  34. package/dist/codegen.js +1 -1
  35. package/dist/{components-Dqr_LuZJ.d.ts → components-BbWPnZCF.d.ts} +37 -6
  36. package/dist/{hex-board-view-UCUjMALd.d.ts → hex-board-view-Kz9Q_zsv.d.ts} +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/package-set.d.ts +2 -2
  39. package/dist/package-set.js +2 -1
  40. package/dist/player-state-Cqpyeql0.d.ts +371 -0
  41. package/dist/protocol-BP193lva.d.ts +267 -0
  42. package/dist/reducer/advanced.js +1 -1
  43. package/dist/reducer-contract.js +1 -1
  44. package/dist/reducer.js +2 -2
  45. package/dist/reducer.js.map +1 -1
  46. package/dist/runtime/primitives.d.ts +10 -10
  47. package/dist/runtime/primitives.js +9 -7
  48. package/dist/runtime/runtime-api.d.ts +2 -2
  49. package/dist/runtime/workspace-contract.d.ts +23 -12
  50. package/dist/runtime/workspace-contract.js +7 -6
  51. package/dist/runtime-api-BJharVaj.d.ts +198 -0
  52. package/dist/runtime-api-C6aWo9c0.d.ts +95 -0
  53. package/dist/runtime.d.ts +35 -31
  54. package/dist/runtime.js +87 -797
  55. package/dist/runtime.js.map +1 -1
  56. package/dist/testing.d.ts +254 -140
  57. package/dist/testing.js +964 -149
  58. package/dist/testing.js.map +1 -1
  59. package/dist/types-CYeN0wLK.d.ts +29 -0
  60. package/dist/{types-BqzHkNMA.d.ts → types-DJj5MJkl.d.ts} +32 -5
  61. package/dist/types.d.ts +13 -8
  62. package/dist/ui/components.d.ts +4 -5
  63. package/dist/ui/components.js +19 -1
  64. package/dist/ui/player-state.d.ts +2 -365
  65. package/dist/{ui-contract-W2-kxObe.d.ts → ui-contract-CY7cxsCC.d.ts} +16 -26
  66. package/dist/ui.d.ts +7 -8
  67. package/dist/ui.js +20 -2
  68. package/package.json +25 -19
  69. package/dist/chunk-3K362ZKR.js.map +0 -1
  70. package/dist/chunk-7LZZEI25.js.map +0 -1
  71. package/dist/chunk-7W6TQO3X.js.map +0 -1
  72. package/dist/chunk-CZMFAS3E.js.map +0 -1
  73. package/dist/chunk-IUGKW2GS.js.map +0 -1
  74. package/dist/chunk-MALRKLRR.js.map +0 -1
  75. package/dist/chunk-XXBSIPJX.js.map +0 -1
  76. package/dist/hex-color-MhOyuY-o.d.ts +0 -8
  77. package/dist/runtime-api-BXd70c2e.d.ts +0 -490
  78. /package/dist/{chunk-XJYUSD5F.js.map → chunk-FWVV2X74.js.map} +0 -0
@@ -15,25 +15,38 @@ import {
15
15
  createHexBoardView,
16
16
  surfaceStyle,
17
17
  useChromeSuppression,
18
+ useOverlayInsets,
18
19
  useTheme,
19
20
  useThemeCssVars
20
- } from "./chunk-7W6TQO3X.js";
21
+ } from "./chunk-45FI6XII.js";
21
22
  import {
22
23
  composeEventHandlers,
23
24
  renderPrimitive
24
25
  } from "./chunk-VDXOF4FW.js";
25
26
  import {
26
- BROWSER_INTERACTION_ATTRIBUTES,
27
- DREAMBOARD_BROWSER_INTERACTION_PROTOCOL_VERSION,
28
- GAMEPLAY_BROWSER_INTERACTION_SURFACE,
27
+ defaultRuntimeSnapshotEquality,
28
+ useArmedInteraction,
29
+ useAuthoredPluginGameplayFrameSelector,
30
+ useInteractionDraft,
31
+ useInteractionSubmitting,
32
+ useInteractionUiStore,
33
+ usePendingInteractionKey,
34
+ usePendingInteractionRevision,
35
+ usePluginGameplayFrameSelector,
36
+ usePluginSession,
37
+ usePluginSessionDescriptor,
38
+ useRuntimeContext
39
+ } from "./chunk-O6M6PN4E.js";
40
+ import {
29
41
  createGameplayActuatorAttributes,
30
42
  createGameplayInteractionRootAttributes,
43
+ createGameplayPointerTargetAttributes,
31
44
  gameplayAdjustResourceEffect,
32
45
  gameplayCommitEffect,
33
46
  gameplayInvokeEffect,
34
47
  gameplaySetCandidateEffect,
35
48
  gameplaySetScalarEffect
36
- } from "./chunk-MALRKLRR.js";
49
+ } from "./chunk-WUIVY2KE.js";
37
50
 
38
51
  // src/runtime/primitives/ui.tsx
39
52
  import { Fragment, jsx } from "react/jsx-runtime";
@@ -65,745 +78,7 @@ var UI = {
65
78
  };
66
79
 
67
80
  // src/runtime/primitives/hand-intent-adapter.ts
68
- import { useCallback as useCallback2 } from "react";
69
-
70
- // src/runtime/context/InteractionDraftContext.tsx
71
- import { createContext, useContext, useMemo } from "react";
72
- import { useStore } from "zustand";
73
- import { createStore } from "zustand/vanilla";
74
- import { useShallow } from "zustand/shallow";
75
- import { jsx as jsx2 } from "react/jsx-runtime";
76
- var EMPTY_DRAFT = Object.freeze({});
77
- function omitRecordKey(record, key) {
78
- const next = { ...record };
79
- delete next[key];
80
- return next;
81
- }
82
- function createInteractionUiStore() {
83
- const store = createStore()(() => ({
84
- drafts: {},
85
- arms: {},
86
- submitting: {},
87
- pendingInteractionKey: null,
88
- pendingInteractionRevision: 0
89
- }));
90
- const api = {
91
- getDraft(interactionId) {
92
- return store.getState().drafts[interactionId] ?? EMPTY_DRAFT;
93
- },
94
- setInput(interactionId, key, value) {
95
- store.setState((prev) => {
96
- const current = prev.drafts[interactionId];
97
- if (current && current[key] === value) return prev;
98
- return {
99
- ...prev,
100
- drafts: {
101
- ...prev.drafts,
102
- [interactionId]: { ...current ?? {}, [key]: value }
103
- }
104
- };
105
- });
106
- },
107
- clearInput(interactionId, key) {
108
- store.setState((prev) => {
109
- const current = prev.drafts[interactionId];
110
- if (!current) return prev;
111
- if (key === void 0) {
112
- return { ...prev, drafts: omitRecordKey(prev.drafts, interactionId) };
113
- }
114
- if (!(key in current)) return prev;
115
- const remainingKeys = omitRecordKey(current, key);
116
- if (Object.keys(remainingKeys).length === 0) {
117
- return { ...prev, drafts: omitRecordKey(prev.drafts, interactionId) };
118
- }
119
- return {
120
- ...prev,
121
- drafts: { ...prev.drafts, [interactionId]: remainingKeys }
122
- };
123
- });
124
- },
125
- clearAll() {
126
- store.setState((prev) => {
127
- if (Object.keys(prev.drafts).length === 0 && Object.keys(prev.arms).length === 0 && Object.keys(prev.submitting).length === 0 && prev.pendingInteractionKey === null) {
128
- return prev;
129
- }
130
- return {
131
- drafts: {},
132
- arms: {},
133
- submitting: {},
134
- pendingInteractionKey: null,
135
- pendingInteractionRevision: prev.pendingInteractionRevision + 1
136
- };
137
- });
138
- },
139
- getArmed(surface) {
140
- return store.getState().arms[surface] ?? null;
141
- },
142
- arm(surface, interactionId) {
143
- store.setState((prev) => {
144
- const current = prev.arms[surface] ?? null;
145
- if (current === interactionId) return prev;
146
- if (interactionId === null) {
147
- return { ...prev, arms: omitRecordKey(prev.arms, surface) };
148
- }
149
- return { ...prev, arms: { ...prev.arms, [surface]: interactionId } };
150
- });
151
- },
152
- getPendingInteraction() {
153
- return store.getState().pendingInteractionKey;
154
- },
155
- setPendingInteraction(interactionId) {
156
- store.setState((prev) => {
157
- if (prev.pendingInteractionKey === interactionId) {
158
- return interactionId === null ? prev : {
159
- ...prev,
160
- pendingInteractionRevision: prev.pendingInteractionRevision + 1
161
- };
162
- }
163
- return {
164
- ...prev,
165
- pendingInteractionKey: interactionId,
166
- pendingInteractionRevision: prev.pendingInteractionRevision + 1
167
- };
168
- });
169
- },
170
- getPendingInteractionRevision() {
171
- return store.getState().pendingInteractionRevision;
172
- },
173
- isSubmitting(interactionId) {
174
- return store.getState().submitting[interactionId] === true;
175
- },
176
- claimSubmitting(interactionId) {
177
- let claimed = false;
178
- store.setState((prev) => {
179
- if (prev.submitting[interactionId] === true) return prev;
180
- claimed = true;
181
- return {
182
- ...prev,
183
- submitting: { ...prev.submitting, [interactionId]: true }
184
- };
185
- });
186
- return claimed;
187
- },
188
- setSubmitting(interactionId, submitting) {
189
- store.setState((prev) => {
190
- const current = prev.submitting[interactionId] === true;
191
- if (current === submitting) return prev;
192
- if (!submitting) {
193
- return {
194
- ...prev,
195
- submitting: omitRecordKey(prev.submitting, interactionId)
196
- };
197
- }
198
- return {
199
- ...prev,
200
- submitting: { ...prev.submitting, [interactionId]: true }
201
- };
202
- });
203
- }
204
- };
205
- return Object.assign(store, api);
206
- }
207
- var InteractionUiCtx = createContext(null);
208
- function InteractionUiProvider({
209
- children,
210
- store
211
- }) {
212
- const ownedStore = useMemo(() => createInteractionUiStore(), []);
213
- return /* @__PURE__ */ jsx2(InteractionUiCtx.Provider, { value: store ?? ownedStore, children });
214
- }
215
- function useInteractionUiStore() {
216
- const ctx = useContext(InteractionUiCtx);
217
- const fallback = useMemo(() => createInteractionUiStore(), []);
218
- return ctx ?? fallback;
219
- }
220
- function useInteractionDraft(interactionId) {
221
- const store = useInteractionUiStore();
222
- useStore(
223
- store,
224
- useShallow(
225
- (state) => state.drafts[interactionId] ?? EMPTY_DRAFT
226
- )
227
- );
228
- return store.getDraft(interactionId);
229
- }
230
- function useArmedInteraction(surface) {
231
- const store = useInteractionUiStore();
232
- return useStore(store, (state) => state.arms[surface] ?? null);
233
- }
234
- function usePendingInteractionKey() {
235
- const store = useInteractionUiStore();
236
- const subscribed = useStore(
237
- store,
238
- (state) => state.pendingInteractionKey ?? null
239
- );
240
- return store.getPendingInteraction() ?? subscribed;
241
- }
242
- function usePendingInteractionRevision() {
243
- const store = useInteractionUiStore();
244
- const subscribed = useStore(
245
- store,
246
- (state) => state.pendingInteractionRevision
247
- );
248
- return Math.max(store.getPendingInteractionRevision(), subscribed);
249
- }
250
- function useInteractionSubmitting(interactionId) {
251
- const store = useInteractionUiStore();
252
- return useStore(
253
- store,
254
- (state) => state.submitting[interactionId] === true
255
- );
256
- }
257
-
258
- // src/runtime/context/PluginSessionContext.tsx
259
- import { createContext as createContext2, useContext as useContext2 } from "react";
260
- var PluginSessionContext = createContext2(
261
- null
262
- );
263
- function usePluginSession() {
264
- const context = useContext2(PluginSessionContext);
265
- if (context === null) {
266
- throw new Error(
267
- "usePluginSession must be used within a PluginSessionContext.Provider (provided by RuntimeContext)"
268
- );
269
- }
270
- return context;
271
- }
272
-
273
- // src/runtime/context/PluginStateContext.tsx
274
- import {
275
- createContext as createContext4,
276
- useContext as useContext4,
277
- useMemo as useMemo3,
278
- useSyncExternalStore as useSyncExternalStore2
279
- } from "react";
280
-
281
- // src/runtime/context/RuntimeContext.tsx
282
- import { createContext as createContext3, useContext as useContext3, useState, useEffect } from "react";
283
- import { jsx as jsx3 } from "react/jsx-runtime";
284
- var RuntimeContext = createContext3(null);
285
- function useRuntimeContext() {
286
- const context = useContext3(RuntimeContext);
287
- if (!context) {
288
- throw new Error(
289
- "useRuntimeContext must be used within a RuntimeContext.Provider"
290
- );
291
- }
292
- return context;
293
- }
294
- function RuntimeProvider({
295
- runtime,
296
- children
297
- }) {
298
- const [sessionState, setSessionState] = useState(
299
- () => runtime.getSessionState()
300
- );
301
- useEffect(() => {
302
- const runtimeWithInternal = runtime;
303
- if (runtimeWithInternal._subscribeToSessionState) {
304
- return runtimeWithInternal._subscribeToSessionState((state) => {
305
- setSessionState(state);
306
- });
307
- }
308
- return () => {
309
- };
310
- }, [runtime]);
311
- return /* @__PURE__ */ jsx3(RuntimeContext.Provider, { value: runtime, children: /* @__PURE__ */ jsx3(PluginSessionContext.Provider, { value: sessionState, children }) });
312
- }
313
-
314
- // src/runtime/utils/semantic-projection-digest.ts
315
- var AUTHORIZED_SEAT_PROJECTION_DIGEST_VERSION = "authorized-seat-projection@2";
316
- function semanticProjectionDigestForState(state) {
317
- const actorPlayerId = state.session.controllingPlayerId;
318
- if (!actorPlayerId) {
319
- return null;
320
- }
321
- const seatOrder = state.lobby?.seats.map((seat) => seat.playerId) ?? [];
322
- if (!seatOrder.includes(actorPlayerId)) {
323
- return null;
324
- }
325
- return hashJson(semanticSeatProjection(state, state.gameplay, seatOrder));
326
- }
327
- function semanticSeatProjection(state, gameplay, seatOrder) {
328
- const playerToSeat = new Map(
329
- seatOrder.map((playerId, index) => [playerId, index])
330
- );
331
- const actorPlayerId = state.session.controllingPlayerId;
332
- const actorSeat = actorPlayerId ? playerToSeat.get(actorPlayerId) : void 0;
333
- if (actorSeat === void 0) {
334
- throw new Error(
335
- `authorized projection player ${actorPlayerId ?? "__none__"} is not present in seat order`
336
- );
337
- }
338
- return {
339
- digestVersion: AUTHORIZED_SEAT_PROJECTION_DIGEST_VERSION,
340
- actorSeat,
341
- currentStage: gameplay.currentStage ?? null,
342
- stageSeats: gameplay.activePlayers.map(
343
- (playerId) => canonicalizeSeatReference(playerId, playerToSeat)
344
- ),
345
- view: canonicalizeSemanticProjectionValue(state.view, playerToSeat),
346
- zones: canonicalizeSemanticProjectionValue(
347
- gameplay.zones ?? {},
348
- playerToSeat
349
- ),
350
- availableInteractions: gameplay.availableInteractions.map(
351
- (descriptor) => semanticInteractionDescriptor(descriptor, playerToSeat)
352
- )
353
- };
354
- }
355
- function semanticInteractionDescriptor(descriptor, playerToSeat) {
356
- const inputs = descriptor.inputs.map(
357
- (input) => semanticInteractionInput(input, playerToSeat)
358
- );
359
- const { defaults, defaultProvenance } = collectDefaults(descriptor.inputs);
360
- return {
361
- interactionKey: descriptor.interactionKey,
362
- interactionId: descriptor.interactionId,
363
- stableIdentity: canonicalizeSemanticProjectionValue(
364
- `${descriptor.interactionKey}:${descriptor.interactionId}`,
365
- playerToSeat
366
- ),
367
- kind: descriptor.kind,
368
- surface: descriptor.zoneId ?? descriptor.zoneIds?.find((zoneId) => typeof zoneId === "string") ?? null,
369
- commitMode: descriptor.commit.mode === "autoWhenReady" ? "autoWhenReady" : "manual",
370
- status: descriptor.availability.status ?? null,
371
- available: descriptor.availability.status === "available",
372
- inputs,
373
- defaults: canonicalizeSemanticProjectionValue(defaults, playerToSeat),
374
- defaultProvenance
375
- };
376
- }
377
- function semanticInteractionInput(input, playerToSeat) {
378
- const domain = asRecord(input.domain);
379
- const selection = asRecord(domain.selection);
380
- return {
381
- key: input.key,
382
- kind: input.kind,
383
- domain: canonicalizeSemanticProjectionValue(input.domain, playerToSeat),
384
- defaultValue: input.defaultValue === void 0 ? null : canonicalizeSemanticProjectionValue(input.defaultValue, playerToSeat),
385
- defaultProvenance: input.defaultValue === void 0 ? null : "input",
386
- selectionMode: stringField(selection, "mode"),
387
- min: numberField(domain),
388
- max: numberField(domain, "max")
389
- };
390
- }
391
- function collectDefaults(inputs) {
392
- const defaults = {};
393
- const defaultProvenance = {};
394
- for (const input of inputs) {
395
- if (input.defaultValue !== void 0) {
396
- defaults[input.key] = toCanonicalJson(input.defaultValue);
397
- defaultProvenance[input.key] = "input";
398
- }
399
- }
400
- return { defaults, defaultProvenance };
401
- }
402
- function canonicalizeSemanticProjectionValue(value, playerToSeat) {
403
- if (value === null || typeof value === "boolean" || typeof value === "number") {
404
- return toCanonicalJson(value);
405
- }
406
- if (typeof value === "string") {
407
- return canonicalizeSeatReference(value, playerToSeat);
408
- }
409
- if (Array.isArray(value)) {
410
- return value.map(
411
- (item) => canonicalizeSemanticProjectionValue(item, playerToSeat)
412
- );
413
- }
414
- if (isRecord(value)) {
415
- return Object.fromEntries(
416
- Object.entries(value).filter(
417
- ([key, item]) => item !== void 0 && !SEMANTIC_PROJECTION_TRANSPORT_FIELDS.has(key)
418
- ).map(([key, item]) => [
419
- canonicalizeObjectKey(key, playerToSeat),
420
- canonicalizeSemanticProjectionProperty(key, item, playerToSeat)
421
- ])
422
- );
423
- }
424
- return null;
425
- }
426
- function canonicalizeSemanticProjectionProperty(key, value, playerToSeat) {
427
- const canonicalValue = canonicalizeSemanticProjectionValue(
428
- value,
429
- playerToSeat
430
- );
431
- if ((key === "eligibleTargets" || key === "dependentCases") && Array.isArray(canonicalValue)) {
432
- return [...canonicalValue].sort(
433
- (left, right) => compareJson(canonicalJson(left), canonicalJson(right))
434
- );
435
- }
436
- return canonicalValue;
437
- }
438
- function canonicalizeSeatReference(value, playerToSeat) {
439
- const seat = playerToSeat.get(value);
440
- return seat === void 0 ? value : { $seat: seat };
441
- }
442
- function canonicalizeObjectKey(key, playerToSeat) {
443
- const seat = playerToSeat.get(key);
444
- return seat === void 0 ? key : `$seat:${seat}`;
445
- }
446
- var SEMANTIC_PROJECTION_TRANSPORT_FIELDS = /* @__PURE__ */ new Set([
447
- "availableInteractionRefs",
448
- "board",
449
- "cursor",
450
- "etag",
451
- "hydratedAt",
452
- "hydrationCursor",
453
- "hydrationSequence",
454
- "interactionRef",
455
- "interactionRefs",
456
- "lastEventId",
457
- "receivedAt",
458
- "sequence",
459
- "serverTime",
460
- "snapshotVersion",
461
- "transportSequence",
462
- "transportVersion",
463
- "updatedAt"
464
- ]);
465
- function toCanonicalJson(value) {
466
- if (value === null || typeof value === "boolean" || typeof value === "string") {
467
- return value;
468
- }
469
- if (typeof value === "number") {
470
- return value;
471
- }
472
- if (Array.isArray(value)) {
473
- return value.map((item) => toCanonicalJson(item));
474
- }
475
- if (isRecord(value)) {
476
- return Object.fromEntries(
477
- Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => [key, toCanonicalJson(item)])
478
- );
479
- }
480
- return null;
481
- }
482
- function hashJson(value) {
483
- return `sha256:${sha256Hex(canonicalJson(value))}`;
484
- }
485
- function canonicalJson(value) {
486
- return JSON.stringify(canonicalizeJson(value));
487
- }
488
- function canonicalizeJson(value) {
489
- if (value === null || typeof value === "boolean" || typeof value === "string") {
490
- return value;
491
- }
492
- if (typeof value === "number") {
493
- if (!Number.isFinite(value)) {
494
- throw new Error("canonical JSON contains a non-finite number");
495
- }
496
- return value;
497
- }
498
- if (Array.isArray(value)) {
499
- return value.map((item) => canonicalizeJson(item));
500
- }
501
- return Object.fromEntries(
502
- Object.entries(value).sort(([left], [right]) => compareJson(left, right)).map(([key, item]) => [key, canonicalizeJson(item)])
503
- );
504
- }
505
- function compareJson(left, right) {
506
- return left < right ? -1 : left > right ? 1 : 0;
507
- }
508
- function isRecord(value) {
509
- return !!value && typeof value === "object" && !Array.isArray(value);
510
- }
511
- function asRecord(value) {
512
- return isRecord(value) ? value : {};
513
- }
514
- function stringField(record, key) {
515
- const value = record[key];
516
- return typeof value === "string" && value.trim() ? value : null;
517
- }
518
- function numberField(record, key = "min") {
519
- const value = record[key];
520
- return typeof value === "number" && Number.isFinite(value) ? value : null;
521
- }
522
- var SHA256_K = [
523
- 1116352408,
524
- 1899447441,
525
- 3049323471,
526
- 3921009573,
527
- 961987163,
528
- 1508970993,
529
- 2453635748,
530
- 2870763221,
531
- 3624381080,
532
- 310598401,
533
- 607225278,
534
- 1426881987,
535
- 1925078388,
536
- 2162078206,
537
- 2614888103,
538
- 3248222580,
539
- 3835390401,
540
- 4022224774,
541
- 264347078,
542
- 604807628,
543
- 770255983,
544
- 1249150122,
545
- 1555081692,
546
- 1996064986,
547
- 2554220882,
548
- 2821834349,
549
- 2952996808,
550
- 3210313671,
551
- 3336571891,
552
- 3584528711,
553
- 113926993,
554
- 338241895,
555
- 666307205,
556
- 773529912,
557
- 1294757372,
558
- 1396182291,
559
- 1695183700,
560
- 1986661051,
561
- 2177026350,
562
- 2456956037,
563
- 2730485921,
564
- 2820302411,
565
- 3259730800,
566
- 3345764771,
567
- 3516065817,
568
- 3600352804,
569
- 4094571909,
570
- 275423344,
571
- 430227734,
572
- 506948616,
573
- 659060556,
574
- 883997877,
575
- 958139571,
576
- 1322822218,
577
- 1537002063,
578
- 1747873779,
579
- 1955562222,
580
- 2024104815,
581
- 2227730452,
582
- 2361852424,
583
- 2428436474,
584
- 2756734187,
585
- 3204031479,
586
- 3329325298
587
- ];
588
- function sha256Hex(input) {
589
- const bytes = utf8Bytes(input);
590
- const bitLength = bytes.length * 8;
591
- bytes.push(128);
592
- while (bytes.length % 64 !== 56) {
593
- bytes.push(0);
594
- }
595
- for (let shift = 56; shift >= 0; shift -= 8) {
596
- bytes.push(Math.floor(bitLength / 2 ** shift) & 255);
597
- }
598
- let h0 = 1779033703;
599
- let h1 = 3144134277;
600
- let h2 = 1013904242;
601
- let h3 = 2773480762;
602
- let h4 = 1359893119;
603
- let h5 = 2600822924;
604
- let h6 = 528734635;
605
- let h7 = 1541459225;
606
- const words = new Array(64);
607
- for (let offset = 0; offset < bytes.length; offset += 64) {
608
- for (let index = 0; index < 16; index += 1) {
609
- const base = offset + index * 4;
610
- words[index] = (bytes[base] << 24 | bytes[base + 1] << 16 | bytes[base + 2] << 8 | bytes[base + 3]) >>> 0;
611
- }
612
- for (let index = 16; index < 64; index += 1) {
613
- const s0 = rotateRight(words[index - 15], 7) ^ rotateRight(words[index - 15], 18) ^ words[index - 15] >>> 3;
614
- const s1 = rotateRight(words[index - 2], 17) ^ rotateRight(words[index - 2], 19) ^ words[index - 2] >>> 10;
615
- words[index] = words[index - 16] + s0 + words[index - 7] + s1 >>> 0;
616
- }
617
- let a = h0;
618
- let b = h1;
619
- let c = h2;
620
- let d = h3;
621
- let e = h4;
622
- let f = h5;
623
- let g = h6;
624
- let h = h7;
625
- for (let index = 0; index < 64; index += 1) {
626
- const s1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
627
- const ch2 = e & f ^ ~e & g;
628
- const temp1 = h + s1 + ch2 + SHA256_K[index] + words[index] >>> 0;
629
- const s0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
630
- const maj2 = a & b ^ a & c ^ b & c;
631
- const temp2 = s0 + maj2 >>> 0;
632
- h = g;
633
- g = f;
634
- f = e;
635
- e = d + temp1 >>> 0;
636
- d = c;
637
- c = b;
638
- b = a;
639
- a = temp1 + temp2 >>> 0;
640
- }
641
- h0 = h0 + a >>> 0;
642
- h1 = h1 + b >>> 0;
643
- h2 = h2 + c >>> 0;
644
- h3 = h3 + d >>> 0;
645
- h4 = h4 + e >>> 0;
646
- h5 = h5 + f >>> 0;
647
- h6 = h6 + g >>> 0;
648
- h7 = h7 + h >>> 0;
649
- }
650
- return [h0, h1, h2, h3, h4, h5, h6, h7].map((value) => value.toString(16).padStart(8, "0")).join("");
651
- }
652
- function rotateRight(value, bits) {
653
- return value >>> bits | value << 32 - bits;
654
- }
655
- function utf8Bytes(input) {
656
- return Array.from(new TextEncoder().encode(input));
657
- }
658
-
659
- // src/runtime/hooks/useRuntimeSnapshotSelector.ts
660
- import { useCallback, useMemo as useMemo2, useSyncExternalStore } from "react";
661
- function defaultRuntimeSnapshotEquality(left, right) {
662
- return Object.is(left, right);
663
- }
664
- function useRuntimeSnapshotSelector(subscribe, getSnapshot, getServerSnapshot, selector, equalityFn = defaultRuntimeSnapshotEquality) {
665
- const cache = useMemo2(
666
- () => ({ current: null, selector, equalityFn }),
667
- [equalityFn, selector]
668
- );
669
- const getSelectedFromSnapshot = useCallback(
670
- (snapshot) => {
671
- const cached = cache.current;
672
- if (cached && cached.snapshot === snapshot) {
673
- return cached.selection;
674
- }
675
- const nextSelection = selector(snapshot);
676
- if (cached && equalityFn(cached.selection, nextSelection)) {
677
- cache.current = {
678
- snapshot,
679
- selection: cached.selection
680
- };
681
- return cached.selection;
682
- }
683
- cache.current = {
684
- snapshot,
685
- selection: nextSelection
686
- };
687
- return nextSelection;
688
- },
689
- [cache, equalityFn, selector]
690
- );
691
- const getSelectedSnapshot = useCallback(
692
- () => getSelectedFromSnapshot(getSnapshot()),
693
- [getSelectedFromSnapshot, getSnapshot]
694
- );
695
- const getSelectedServerSnapshot = useCallback(
696
- () => selector(getServerSnapshot()),
697
- [getServerSnapshot, selector]
698
- );
699
- const subscribeSelected = useCallback(
700
- (onStoreChange) => subscribe(() => {
701
- const previous = cache.current;
702
- const nextSelection = getSelectedSnapshot();
703
- if (!previous || !equalityFn(previous.selection, nextSelection)) {
704
- onStoreChange();
705
- }
706
- }),
707
- [cache, equalityFn, getSelectedSnapshot, subscribe]
708
- );
709
- return useSyncExternalStore(
710
- subscribeSelected,
711
- getSelectedSnapshot,
712
- getSelectedServerSnapshot
713
- );
714
- }
715
-
716
- // src/runtime/context/PluginStateContext.tsx
717
- import { Fragment as Fragment2, jsx as jsx4, jsxs } from "react/jsx-runtime";
718
- var PluginStateContext = createContext4(null);
719
- var GAMEPLAY_BROWSER_SCOPE_ID = "runtime";
720
- var BROWSER_PROJECTION_DIGEST_ATTRIBUTE = "data-dreamboard-projection-digest";
721
- function RuntimeSemanticProjectionMarker() {
722
- const state = usePluginState((snapshot) => snapshot);
723
- return /* @__PURE__ */ jsx4(SemanticProjectionMarker, { state });
724
- }
725
- function SemanticProjectionMarker({
726
- state
727
- }) {
728
- const digest = semanticProjectionDigestForState(state);
729
- if (!digest) {
730
- return null;
731
- }
732
- return /* @__PURE__ */ jsx4(
733
- "span",
734
- {
735
- "aria-hidden": "true",
736
- style: { display: "none" },
737
- ...{
738
- [BROWSER_INTERACTION_ATTRIBUTES.protocol]: DREAMBOARD_BROWSER_INTERACTION_PROTOCOL_VERSION,
739
- [BROWSER_INTERACTION_ATTRIBUTES.surface]: GAMEPLAY_BROWSER_INTERACTION_SURFACE,
740
- [BROWSER_INTERACTION_ATTRIBUTES.scope]: GAMEPLAY_BROWSER_SCOPE_ID,
741
- [BROWSER_INTERACTION_ATTRIBUTES.role]: "projection",
742
- [BROWSER_PROJECTION_DIGEST_ATTRIBUTE]: digest
743
- }
744
- }
745
- );
746
- }
747
- function usePluginState(selector, equalityFn = defaultRuntimeSnapshotEquality) {
748
- const runtime = useRuntimeContext();
749
- const storeApi = useMemo3(() => {
750
- const subscribe = (onStoreChange) => {
751
- if (!runtime.subscribeToState) {
752
- return () => {
753
- };
754
- }
755
- return runtime.subscribeToState(() => {
756
- onStoreChange();
757
- });
758
- };
759
- const getSnapshot = () => {
760
- const state = runtime.getSnapshot?.();
761
- if (!state) {
762
- throw new Error(
763
- "usePluginState: No state available. Make sure you have wrapped your app with <PluginStateProvider>."
764
- );
765
- }
766
- return state;
767
- };
768
- return {
769
- subscribe,
770
- getSnapshot,
771
- getServerSnapshot: getSnapshot
772
- };
773
- }, [runtime]);
774
- return useRuntimeSnapshotSelector(
775
- storeApi.subscribe,
776
- storeApi.getSnapshot,
777
- storeApi.getServerSnapshot,
778
- selector,
779
- equalityFn
780
- );
781
- }
782
- function usePluginActions() {
783
- const runtime = useRuntimeContext();
784
- return {
785
- /**
786
- * Mark a notification as read.
787
- * Sends message to host which updates the notification in GameSessionStore.
788
- */
789
- markNotificationRead: (notificationId) => {
790
- window.parent.postMessage(
791
- { type: "mark-notification-read", notificationId },
792
- "*"
793
- );
794
- },
795
- /**
796
- * Switch to a different player (for users controlling multiple seats).
797
- */
798
- switchPlayer: (playerId) => {
799
- runtime.switchPlayer?.(playerId);
800
- },
801
- /**
802
- * Submit a player interaction (action or prompt response).
803
- */
804
- submitInteraction: runtime.submitInteraction
805
- };
806
- }
81
+ import { useCallback } from "react";
807
82
 
808
83
  // src/runtime/utils/interaction-inputs.ts
809
84
  function interactionInputKeys(descriptor) {
@@ -1498,9 +773,9 @@ function projectDraftCardState(availableInteractions, drafts, validate) {
1498
773
  }
1499
774
  return entries;
1500
775
  }
1501
- function selectedCardIdsForZone(store, zone, state) {
776
+ function selectedCardIdsForZone(store, zone, availableInteractions) {
1502
777
  const result = /* @__PURE__ */ new Set();
1503
- for (const descriptor of state.gameplay.availableInteractions) {
778
+ for (const descriptor of availableInteractions) {
1504
779
  const cardInput = descriptor.inputs.find((input) => {
1505
780
  if (!isTargetDomain(input.domain)) return false;
1506
781
  if (input.domain.type !== "cardTarget") return false;
@@ -1541,13 +816,13 @@ function useCardIntentAdapter({
1541
816
  const store = useInteractionUiStore();
1542
817
  const { controllingPlayerId } = usePluginSession();
1543
818
  const runtime = useRuntimeContext();
1544
- const zoneSnapshot = usePluginState(
1545
- (state) => state.gameplay.zones[zone] ?? null
819
+ const zoneSnapshot = useAuthoredPluginGameplayFrameSelector(
820
+ (frame) => frame.zones[zone] ?? null
1546
821
  );
1547
- const availableInteractions = usePluginState(
1548
- (state) => state.gameplay.availableInteractions
822
+ const availableInteractions = useAuthoredPluginGameplayFrameSelector(
823
+ (frame) => frame.availableInteractions
1549
824
  );
1550
- return useCallback2(
825
+ return useCallback(
1551
826
  async (intent) => {
1552
827
  const authored = decodeAuthoredCardIntent(intent);
1553
828
  if (intent.type === "previewStart" || intent.type === "previewEnd") {
@@ -1573,7 +848,6 @@ function useCardIntentAdapter({
1573
848
  zoneSnapshot,
1574
849
  submit: async (descriptor, params) => {
1575
850
  await runtime.submitInteraction(
1576
- controllingPlayerId,
1577
851
  descriptor.interactionId,
1578
852
  params
1579
853
  );
@@ -1600,54 +874,36 @@ function useCardIntentAdapter({
1600
874
  }
1601
875
 
1602
876
  // src/runtime/primitives/game.tsx
1603
- import { createContext as createContext5, useContext as useContext5, useMemo as useMemo7 } from "react";
1604
- import { useStore as useStore2 } from "zustand";
877
+ import {
878
+ createContext,
879
+ useContext,
880
+ useMemo as useMemo3
881
+ } from "react";
882
+ import { useStore } from "zustand";
1605
883
 
1606
884
  // src/runtime/hooks/useActivePlayers.ts
1607
885
  function useActivePlayers() {
1608
- return usePluginState((state) => {
1609
- const simultaneous = state.gameplay.simultaneousPhase;
886
+ return usePluginGameplayFrameSelector((frame) => {
887
+ const simultaneous = frame.flow.simultaneousPhase;
1610
888
  if (simultaneous && simultaneous.pendingPlayerIds.length > 0) {
1611
889
  return simultaneous.pendingPlayerIds;
1612
890
  }
1613
- return state.gameplay.activePlayers;
891
+ return frame.flow.activePlayers;
1614
892
  });
1615
893
  }
1616
894
 
1617
895
  // src/runtime/hooks/useGameSelector.ts
1618
- import { useMemo as useMemo4 } from "react";
1619
- function requireProjectedView(snapshot, message) {
1620
- const view = snapshot?.view;
896
+ function requireProjectedView(frame, message) {
897
+ const view = frame?.view;
1621
898
  if (view === null || typeof view === "undefined") {
1622
899
  throw new Error(message);
1623
900
  }
1624
901
  return view;
1625
902
  }
1626
903
  function useGameSelector(selector, equalityFn = defaultRuntimeSnapshotEquality) {
1627
- const runtime = useRuntimeContext();
1628
904
  const message = "useGameSelector: Projected view not available. Ensure the reducer-native host payload is initialized.";
1629
- const storeApi = useMemo4(() => {
1630
- const subscribe = (onStoreChange) => {
1631
- if (!runtime.subscribeToState) {
1632
- return () => {
1633
- };
1634
- }
1635
- return runtime.subscribeToState(() => {
1636
- onStoreChange();
1637
- });
1638
- };
1639
- const getSnapshot = () => runtime.getSnapshot?.() ?? null;
1640
- return {
1641
- subscribe,
1642
- getSnapshot,
1643
- getServerSnapshot: getSnapshot
1644
- };
1645
- }, [runtime]);
1646
- return useRuntimeSnapshotSelector(
1647
- storeApi.subscribe,
1648
- storeApi.getSnapshot,
1649
- storeApi.getServerSnapshot,
1650
- (snapshot) => selector(requireProjectedView(snapshot, message)),
905
+ return usePluginGameplayFrameSelector(
906
+ (frame) => selector(requireProjectedView(frame, message)),
1651
907
  equalityFn
1652
908
  );
1653
909
  }
@@ -1658,76 +914,34 @@ function useGameView() {
1658
914
  }
1659
915
 
1660
916
  // src/runtime/hooks/usePlayerInfo.ts
1661
- import { useMemo as useMemo5 } from "react";
1662
-
1663
- // src/runtime/hooks/useLobby.ts
1664
- import { useState as useState2, useEffect as useEffect2 } from "react";
1665
- function useLobbyState() {
1666
- const runtime = useRuntimeContext();
1667
- const getStateFromSnapshot = () => {
1668
- if (!runtime.getSnapshot) return null;
1669
- const snapshot = runtime.getSnapshot();
1670
- if (!snapshot?.lobby) return null;
1671
- return snapshot.lobby;
1672
- };
1673
- const [lobbyState, setLobbyState] = useState2(
1674
- getStateFromSnapshot
1675
- );
1676
- useEffect2(() => {
1677
- if (!runtime.subscribeToState) {
1678
- return;
1679
- }
1680
- const initialState = runtime.getSnapshot?.();
1681
- if (initialState?.lobby) {
1682
- setLobbyState(initialState.lobby);
1683
- }
1684
- return runtime.subscribeToState((snapshot) => {
1685
- if (snapshot.lobby) {
1686
- setLobbyState(snapshot.lobby);
1687
- }
1688
- });
1689
- }, [runtime]);
1690
- return lobbyState;
1691
- }
1692
- function useLobby() {
1693
- const lobbyState = useLobbyState();
1694
- if (lobbyState === null) {
1695
- throw new Error(
1696
- "useLobby: Lobby state not available. The host should only render the plugin when lobby state is ready."
1697
- );
1698
- }
1699
- return lobbyState;
1700
- }
1701
-
1702
- // src/runtime/hooks/usePlayerInfo.ts
917
+ import { useMemo } from "react";
1703
918
  function usePlayerInfo() {
1704
- const lobby = useLobbyState();
1705
- return useMemo5(() => {
1706
- if (!lobby) {
1707
- return /* @__PURE__ */ new Map();
1708
- }
919
+ const sessionDescriptor = usePluginSessionDescriptor();
920
+ return useMemo(() => {
1709
921
  const playerMap = /* @__PURE__ */ new Map();
1710
- for (const seat of lobby.seats) {
1711
- const playerId = seat.playerId;
922
+ for (const player of sessionDescriptor.players) {
923
+ const playerId = player.playerId;
1712
924
  playerMap.set(playerId, {
1713
925
  playerId,
1714
- name: seat.displayName,
1715
- isHost: seat.isHost,
1716
- color: seat.playerColor
926
+ name: player.displayName,
927
+ isHost: false,
928
+ color: player.color
1717
929
  });
1718
930
  }
1719
931
  return playerMap;
1720
- }, [lobby]);
932
+ }, [sessionDescriptor]);
1721
933
  }
1722
934
 
1723
935
  // src/runtime/hooks/usePlayerTurnOrder.ts
1724
- import { useMemo as useMemo6 } from "react";
936
+ import { useMemo as useMemo2 } from "react";
1725
937
  function usePlayerTurnOrder() {
1726
- const lobby = useLobby();
1727
- return useMemo6(() => {
1728
- if (!lobby) return [];
1729
- return lobby.seats.map((seat) => seat.playerId);
1730
- }, [lobby]);
938
+ const sessionDescriptor = usePluginSessionDescriptor();
939
+ return useMemo2(
940
+ () => sessionDescriptor.players.map(
941
+ (player) => player.playerId
942
+ ),
943
+ [sessionDescriptor]
944
+ );
1731
945
  }
1732
946
 
1733
947
  // src/runtime/utils/interaction-labels.ts
@@ -1744,12 +958,12 @@ function interactionLabel(descriptor) {
1744
958
  }
1745
959
 
1746
960
  // src/runtime/primitives/game.tsx
1747
- import { Fragment as Fragment3, jsx as jsx5 } from "react/jsx-runtime";
1748
- var GameActionErrorContext = createContext5(
961
+ import { Fragment as Fragment2, jsx as jsx2 } from "react/jsx-runtime";
962
+ var GameActionErrorContext = createContext(
1749
963
  null
1750
964
  );
1751
965
  function useGameActionError() {
1752
- return useContext5(GameActionErrorContext);
966
+ return useContext(GameActionErrorContext);
1753
967
  }
1754
968
  function fallbackPlayer(playerId) {
1755
969
  return {
@@ -1767,11 +981,13 @@ function useGameRenderState() {
1767
981
  const turnOrder = usePlayerTurnOrder().map(
1768
982
  (playerId) => playerId
1769
983
  );
1770
- const phase = usePluginState(
1771
- (state) => state.gameplay.currentPhase
984
+ const phase = useAuthoredPluginGameplayFrameSelector(
985
+ (frame) => frame.flow.currentPhase
1772
986
  );
1773
- const stage = usePluginState((state) => state.gameplay.currentStage);
1774
- const playersById = useMemo7(() => {
987
+ const stage = useAuthoredPluginGameplayFrameSelector(
988
+ (frame) => frame.flow.currentStage
989
+ );
990
+ const playersById = useMemo3(() => {
1775
991
  const next = /* @__PURE__ */ new Map();
1776
992
  playerInfo.forEach((player, key) => {
1777
993
  const playerId = key;
@@ -1783,30 +999,20 @@ function useGameRenderState() {
1783
999
  return next;
1784
1000
  }, [playerInfo]);
1785
1001
  const controllingPlayerId = session.controllingPlayerId == null ? null : session.controllingPlayerId;
1786
- const controllablePlayerIds = session.controllablePlayerIds.map(
1787
- (playerId) => playerId
1788
- );
1789
1002
  const currentPlayerId = activePlayers[0] ?? turnOrder[0] ?? null;
1790
1003
  const currentPlayer = currentPlayerId ? playersById.get(currentPlayerId) ?? fallbackPlayer(currentPlayerId) : null;
1791
1004
  const mePlayer = controllingPlayerId ? playersById.get(controllingPlayerId) ?? fallbackPlayer(controllingPlayerId) : null;
1792
- const entries = useMemo7(
1005
+ const entries = useMemo3(
1793
1006
  () => turnOrder.map((playerId, index) => {
1794
1007
  const player = playersById.get(playerId) ?? fallbackPlayer(playerId);
1795
1008
  return {
1796
1009
  ...player,
1797
1010
  index,
1798
1011
  isActive: activePlayers.includes(playerId),
1799
- isCurrentPlayer: playerId === controllingPlayerId,
1800
- isControllable: controllablePlayerIds.includes(playerId)
1012
+ isCurrentPlayer: playerId === controllingPlayerId
1801
1013
  };
1802
1014
  }),
1803
- [
1804
- activePlayers,
1805
- controllablePlayerIds,
1806
- controllingPlayerId,
1807
- playersById,
1808
- turnOrder
1809
- ]
1015
+ [activePlayers, controllingPlayerId, playersById, turnOrder]
1810
1016
  );
1811
1017
  return {
1812
1018
  view,
@@ -1816,7 +1022,6 @@ function useGameRenderState() {
1816
1022
  me: {
1817
1023
  playerId: controllingPlayerId,
1818
1024
  player: mePlayer,
1819
- controllablePlayerIds,
1820
1025
  canAct: controllingPlayerId != null && activePlayers.includes(controllingPlayerId)
1821
1026
  },
1822
1027
  turn: {
@@ -1841,9 +1046,9 @@ function GameRoot({
1841
1046
  onActionError
1842
1047
  }) {
1843
1048
  const state = useGameRenderState();
1844
- const rendered = /* @__PURE__ */ jsx5(Fragment3, { children: children(state) });
1049
+ const rendered = /* @__PURE__ */ jsx2(Fragment2, { children: children(state) });
1845
1050
  if (!onActionError) return rendered;
1846
- return /* @__PURE__ */ jsx5(GameActionErrorContext.Provider, { value: onActionError, children: rendered });
1051
+ return /* @__PURE__ */ jsx2(GameActionErrorContext.Provider, { value: onActionError, children: rendered });
1847
1052
  }
1848
1053
  function GameChrome({
1849
1054
  children
@@ -1851,13 +1056,13 @@ function GameChrome({
1851
1056
  const renderState = useGameRenderState();
1852
1057
  const store = useInteractionUiStore();
1853
1058
  const pendingInteractionKey = usePendingInteractionKey();
1854
- const draftSnapshot = useStore2(store, (state) => state.drafts);
1855
- const descriptor = usePluginState(
1856
- (state) => pendingInteractionKey ? state.gameplay.availableInteractions.find(
1059
+ const draftSnapshot = useStore(store, (state) => state.drafts);
1060
+ const descriptor = useAuthoredPluginGameplayFrameSelector(
1061
+ (frame) => pendingInteractionKey ? frame.availableInteractions.find(
1857
1062
  (candidate) => candidate.interactionKey === pendingInteractionKey
1858
1063
  ) : void 0
1859
1064
  );
1860
- const activeAction = useMemo7(() => {
1065
+ const activeAction = useMemo3(() => {
1861
1066
  if (!descriptor) return null;
1862
1067
  const draft = draftSnapshot[descriptor.interactionKey] ?? store.getDraft(descriptor.interactionKey);
1863
1068
  const readiness = getInteractionDraftReadiness(descriptor, draft);
@@ -1875,19 +1080,30 @@ function GameChrome({
1875
1080
  pendingInput: pendingInput ? pendingInputState(pendingInput) : null
1876
1081
  };
1877
1082
  }, [descriptor, draftSnapshot, store]);
1878
- const cancel = useMemo7(
1083
+ const cancel = useMemo3(
1879
1084
  () => descriptor ? () => {
1880
1085
  clearInteractionRoute(store, descriptor);
1881
1086
  } : null,
1882
1087
  [descriptor, store]
1883
1088
  );
1884
- return /* @__PURE__ */ jsx5(Fragment3, { children: children({
1089
+ return /* @__PURE__ */ jsx2(Fragment2, { children: children({
1885
1090
  ...renderState,
1886
1091
  activePlayers: renderState.turn.activePlayerIds,
1887
1092
  activeAction,
1888
1093
  cancel
1889
1094
  }) });
1890
1095
  }
1096
+ function GameViewport({ children, style, ...props }) {
1097
+ const { bottom } = useOverlayInsets();
1098
+ const viewportStyle = {
1099
+ "--dreamboard-bottom-overlay-inset": `${bottom}px`,
1100
+ "--dreamboard-safe-area-bottom": "env(safe-area-inset-bottom, 0px)",
1101
+ minHeight: "100dvh",
1102
+ paddingBottom: "calc(var(--dreamboard-bottom-overlay-inset) + var(--dreamboard-safe-area-bottom))",
1103
+ ...style
1104
+ };
1105
+ return /* @__PURE__ */ jsx2("div", { "data-dreamboard-game-viewport": "", ...props, style: viewportStyle, children });
1106
+ }
1891
1107
  function pendingInputState(input) {
1892
1108
  return {
1893
1109
  key: input.key,
@@ -1917,14 +1133,15 @@ function humanizeInputKey(key) {
1917
1133
  }
1918
1134
  var Game = {
1919
1135
  Root: GameRoot,
1920
- Chrome: GameChrome
1136
+ Chrome: GameChrome,
1137
+ Viewport: GameViewport
1921
1138
  };
1922
1139
 
1923
1140
  // src/runtime/primitives/zone.tsx
1924
1141
  import {
1925
- createContext as createContext6,
1926
- useContext as useContext6,
1927
- useMemo as useMemo8
1142
+ createContext as createContext2,
1143
+ useContext as useContext2,
1144
+ useMemo as useMemo4
1928
1145
  } from "react";
1929
1146
 
1930
1147
  // src/runtime/primitives/interaction-submit.ts
@@ -1978,25 +1195,25 @@ function submitInteractionParams(handle, params, callbacks = {}, options = {}) {
1978
1195
  }
1979
1196
 
1980
1197
  // src/runtime/primitives/zone.tsx
1981
- import { Fragment as Fragment4, jsx as jsx6 } from "react/jsx-runtime";
1982
- var ZoneContext = createContext6(null);
1983
- var ZoneCardContext = createContext6(null);
1984
- var ZonePileContext = createContext6(null);
1198
+ import { Fragment as Fragment3, jsx as jsx3 } from "react/jsx-runtime";
1199
+ var ZoneContext = createContext2(null);
1200
+ var ZoneCardContext = createContext2(null);
1201
+ var ZonePileContext = createContext2(null);
1985
1202
  function useZonePrimitiveContext() {
1986
- const value = useContext6(ZoneContext);
1203
+ const value = useContext2(ZoneContext);
1987
1204
  if (!value) {
1988
1205
  throw new Error("Zone primitives must be rendered inside <Zone.Root>.");
1989
1206
  }
1990
1207
  return value;
1991
1208
  }
1992
1209
  function useOptionalZonePrimitiveContext() {
1993
- return useContext6(ZoneContext);
1210
+ return useContext2(ZoneContext);
1994
1211
  }
1995
1212
  function useZoneCardContext() {
1996
- return useContext6(ZoneCardContext);
1213
+ return useContext2(ZoneCardContext);
1997
1214
  }
1998
1215
  function useZonePileContext() {
1999
- const value = useContext6(ZonePileContext);
1216
+ const value = useContext2(ZonePileContext);
2000
1217
  if (!value) {
2001
1218
  throw new Error(
2002
1219
  "Zone pile primitives must be rendered inside <Zone.PileRoot>."
@@ -2009,12 +1226,12 @@ function ZoneRoot({
2009
1226
  children,
2010
1227
  ...props
2011
1228
  }) {
2012
- const snapshot = usePluginState((state) => state.gameplay.zones[zone]) ?? null;
2013
- const value = useMemo8(
1229
+ const snapshot = useAuthoredPluginGameplayFrameSelector((frame) => frame.zones[zone]) ?? null;
1230
+ const value = useMemo4(
2014
1231
  () => ({ zone, snapshot }),
2015
1232
  [snapshot, zone]
2016
1233
  );
2017
- return /* @__PURE__ */ jsx6(ZoneContext.Provider, { value, children: renderPrimitive("div", {
1234
+ return /* @__PURE__ */ jsx3(ZoneContext.Provider, { value, children: renderPrimitive("div", {
2018
1235
  ...props,
2019
1236
  "data-dreamboard-zone-root": "",
2020
1237
  "data-zone": zone,
@@ -2024,7 +1241,7 @@ function ZoneRoot({
2024
1241
  }
2025
1242
  function ZoneList({ children, empty, sort, ...props }) {
2026
1243
  const { zone, items, isEmpty } = useZoneCards({ sort });
2027
- const renderedChildren = typeof children === "function" ? isEmpty ? empty : items.map((item) => /* @__PURE__ */ jsx6(ZoneItem, { card: item, children: children(item) }, item.id)) : isEmpty && empty !== void 0 ? empty : children;
1244
+ const renderedChildren = typeof children === "function" ? isEmpty ? empty : items.map((item) => /* @__PURE__ */ jsx3(ZoneItem, { card: item, children: children(item) }, item.id)) : isEmpty && empty !== void 0 ? empty : children;
2028
1245
  return renderPrimitive("div", {
2029
1246
  ...props,
2030
1247
  role: props.role ?? "list",
@@ -2038,7 +1255,7 @@ function useZoneCards({
2038
1255
  sort
2039
1256
  } = {}) {
2040
1257
  const { zone, snapshot } = useZonePrimitiveContext();
2041
- return useMemo8(() => {
1258
+ return useMemo4(() => {
2042
1259
  const cards = (snapshot?.cardIds ?? []).map(
2043
1260
  (cardId, index) => createZoneCardRenderItem(zone, snapshot, cardId, index)
2044
1261
  );
@@ -2060,11 +1277,11 @@ function ZoneItem({ card, children, ...props }) {
2060
1277
  card,
2061
1278
  indexOfCard(snapshot, card)
2062
1279
  ) : card;
2063
- const cardContext = useMemo8(
1280
+ const cardContext = useMemo4(
2064
1281
  () => ({ zone, cardId: item.id }),
2065
1282
  [item.id, zone]
2066
1283
  );
2067
- return /* @__PURE__ */ jsx6(ZoneCardContext.Provider, { value: cardContext, children: renderPrimitive("div", {
1284
+ return /* @__PURE__ */ jsx3(ZoneCardContext.Provider, { value: cardContext, children: renderPrimitive("div", {
2068
1285
  ...props,
2069
1286
  role: props.role ?? "listitem",
2070
1287
  "data-dreamboard-zone-item": "",
@@ -2085,23 +1302,23 @@ function ZoneCardAtContent({
2085
1302
  }) {
2086
1303
  const { zone, snapshot } = useZonePrimitiveContext();
2087
1304
  const cardIndex = resolveZoneCardIndex(snapshot, index);
2088
- if (cardIndex === null) return /* @__PURE__ */ jsx6(Fragment4, { children: empty });
1305
+ if (cardIndex === null) return /* @__PURE__ */ jsx3(Fragment3, { children: empty });
2089
1306
  const cardId = snapshot?.cardIds[cardIndex];
2090
- if (!cardId) return /* @__PURE__ */ jsx6(Fragment4, { children: empty });
1307
+ if (!cardId) return /* @__PURE__ */ jsx3(Fragment3, { children: empty });
2091
1308
  const card = createZoneCardRenderItem(zone, snapshot, cardId, cardIndex);
2092
- return /* @__PURE__ */ jsx6(ZoneItem, { card, ...props, children: typeof children === "function" ? children(card) : children });
1309
+ return /* @__PURE__ */ jsx3(ZoneItem, { card, ...props, children: typeof children === "function" ? children(card) : children });
2093
1310
  }
2094
1311
  function ZoneCardAt({
2095
1312
  zone,
2096
1313
  ...props
2097
1314
  }) {
2098
1315
  if (zone) {
2099
- return /* @__PURE__ */ jsx6(ZoneRoot, { zone, children: /* @__PURE__ */ jsx6(ZoneCardAtContent, { ...props }) });
1316
+ return /* @__PURE__ */ jsx3(ZoneRoot, { zone, children: /* @__PURE__ */ jsx3(ZoneCardAtContent, { ...props }) });
2100
1317
  }
2101
- return /* @__PURE__ */ jsx6(ZoneCardAtContent, { ...props });
1318
+ return /* @__PURE__ */ jsx3(ZoneCardAtContent, { ...props });
2102
1319
  }
2103
1320
  function ZoneTopCard(props) {
2104
- return /* @__PURE__ */ jsx6(ZoneCardAt, { ...props, index: 0 });
1321
+ return /* @__PURE__ */ jsx3(ZoneCardAt, { ...props, index: 0 });
2105
1322
  }
2106
1323
  function ZoneCardAction({
2107
1324
  card,
@@ -2173,7 +1390,6 @@ function ZoneCardAction({
2173
1390
  }
2174
1391
  try {
2175
1392
  await runtime.submitInteraction(
2176
- controllingPlayerId,
2177
1393
  descriptor.interactionId,
2178
1394
  params
2179
1395
  );
@@ -2204,7 +1420,7 @@ function ZonePileRoot({
2204
1420
  children,
2205
1421
  ...props
2206
1422
  }) {
2207
- return /* @__PURE__ */ jsx6(ZoneRoot, { zone, ...props, children: /* @__PURE__ */ jsx6(
1423
+ return /* @__PURE__ */ jsx3(ZoneRoot, { zone, ...props, children: /* @__PURE__ */ jsx3(
2208
1424
  ZonePileProvider,
2209
1425
  {
2210
1426
  emptyDescription,
@@ -2223,8 +1439,8 @@ function ZonePileProvider({
2223
1439
  children
2224
1440
  }) {
2225
1441
  const { zone, snapshot } = useZonePrimitiveContext();
2226
- const cards = useMemo8(() => snapshot?.cardIds ?? [], [snapshot]);
2227
- const items = useMemo8(
1442
+ const cards = useMemo4(() => snapshot?.cardIds ?? [], [snapshot]);
1443
+ const items = useMemo4(
2228
1444
  () => cards.map(
2229
1445
  (cardId, index) => createZoneCardRenderItem(zone, snapshot, cardId, index)
2230
1446
  ),
@@ -2234,7 +1450,7 @@ function ZonePileProvider({
2234
1450
  const isHidden = snapshot === null;
2235
1451
  const hasVisibleCards = items.length > 0;
2236
1452
  const description = isHidden ? hiddenDescription : hasVisibleCards ? visibleDescription?.(count) ?? null : emptyDescription;
2237
- const value = useMemo8(
1453
+ const value = useMemo4(
2238
1454
  () => ({
2239
1455
  zone,
2240
1456
  label,
@@ -2247,7 +1463,7 @@ function ZonePileProvider({
2247
1463
  }),
2248
1464
  [cards, count, description, hasVisibleCards, isHidden, items, label, zone]
2249
1465
  );
2250
- return /* @__PURE__ */ jsx6(ZonePileContext.Provider, { value, children });
1466
+ return /* @__PURE__ */ jsx3(ZonePileContext.Provider, { value, children });
2251
1467
  }
2252
1468
  function ZonePileTrigger({ children, ...props }) {
2253
1469
  const pile = useZonePileContext();
@@ -2298,7 +1514,7 @@ function ZonePileDescription({
2298
1514
  function ZonePileCards({ renderCard, ...props }) {
2299
1515
  const pile = useZonePileContext();
2300
1516
  if (!pile.hasVisibleCards) return null;
2301
- return /* @__PURE__ */ jsx6(ZoneList, { ...props, children: pile.items.map((card) => /* @__PURE__ */ jsx6(ZoneItem, { card, children: renderCard(card) }, card.id)) });
1517
+ return /* @__PURE__ */ jsx3(ZoneList, { ...props, children: pile.items.map((card) => /* @__PURE__ */ jsx3(ZoneItem, { card, children: renderCard(card) }, card.id)) });
2302
1518
  }
2303
1519
  function indexOfCard(snapshot, cardId) {
2304
1520
  return snapshot?.cardIds.indexOf(cardId) ?? -1;
@@ -2325,7 +1541,7 @@ function createZoneCardRenderItem(zone, snapshot, cardId, index) {
2325
1541
  };
2326
1542
  }
2327
1543
  function useZoneCardActionRoute(cardId, snapshot, interaction, input) {
2328
- return useMemo8(() => {
1544
+ return useMemo4(() => {
2329
1545
  if (!cardId || !snapshot) {
2330
1546
  return { descriptor: null, inputKey: null, ambiguous: false };
2331
1547
  }
@@ -2415,15 +1631,15 @@ var Zone = {
2415
1631
 
2416
1632
  // src/runtime/primitives/hand-surface.tsx
2417
1633
  import {
2418
- Fragment as Fragment5,
2419
- useCallback as useCallback3,
2420
- useEffect as useEffect3,
2421
- useMemo as useMemo9,
1634
+ Fragment as Fragment4,
1635
+ useCallback as useCallback2,
1636
+ useEffect,
1637
+ useMemo as useMemo5,
2422
1638
  useRef
2423
1639
  } from "react";
2424
- import { useStore as useStore3 } from "zustand";
2425
- import { useShallow as useShallow2 } from "zustand/shallow";
2426
- import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
1640
+ import { useStore as useStore2 } from "zustand";
1641
+ import { useShallow } from "zustand/shallow";
1642
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
2427
1643
  function HandSurfaceView({
2428
1644
  zone,
2429
1645
  cards,
@@ -2443,26 +1659,30 @@ function HandSurfaceView({
2443
1659
  }) {
2444
1660
  const route = useCardIntentAdapter({ zone, onResult: onIntentRouted });
2445
1661
  const interactionStore = useInteractionUiStore();
2446
- const drafts = useStore3(
1662
+ const drafts = useStore2(
2447
1663
  interactionStore,
2448
- useShallow2((state) => state.drafts)
1664
+ useShallow((state) => state.drafts)
2449
1665
  );
2450
- const availableInteractions = usePluginState(
2451
- (state) => state.gameplay.availableInteractions
1666
+ const availableInteractions = useAuthoredPluginGameplayFrameSelector(
1667
+ (frame) => frame.availableInteractions
2452
1668
  );
2453
- const selectedIds = usePluginState(
2454
- useCallback3(
2455
- (state) => selectedCardIdsForZone(interactionStore, zone, state),
1669
+ const selectedIds = useAuthoredPluginGameplayFrameSelector(
1670
+ useCallback2(
1671
+ (frame) => selectedCardIdsForZone(
1672
+ interactionStore,
1673
+ zone,
1674
+ frame.availableInteractions
1675
+ ),
2456
1676
  // drafts is part of the store snapshot — useStore handles re-render.
2457
1677
  // eslint-disable-next-line react-hooks/exhaustive-deps
2458
1678
  [interactionStore, zone, drafts]
2459
1679
  )
2460
1680
  );
2461
- const visibleCards = useMemo9(
1681
+ const visibleCards = useMemo5(
2462
1682
  () => cards.filter((card) => !selectedIds.includes(card.id)),
2463
1683
  [cards, selectedIds]
2464
1684
  );
2465
- const viewCards = useMemo9(
1685
+ const viewCards = useMemo5(
2466
1686
  () => visibleCards.map(
2467
1687
  (card) => card.hidden ? {
2468
1688
  id: card.id,
@@ -2473,18 +1693,20 @@ function HandSurfaceView({
2473
1693
  ),
2474
1694
  [visibleCards]
2475
1695
  );
2476
- const cardByViewId = useMemo9(() => {
1696
+ const cardByViewId = useMemo5(() => {
2477
1697
  const index = /* @__PURE__ */ new Map();
2478
1698
  for (const card of visibleCards) {
2479
1699
  index.set(card.id, card);
2480
1700
  }
2481
1701
  return index;
2482
1702
  }, [visibleCards]);
2483
- const cardDescriptorIndex = usePluginState((state) => {
2484
- const snapshot = state.gameplay.zones[zone];
2485
- return snapshot?.playableByCardId ?? {};
2486
- });
2487
- const draftCardProjection = useMemo9(
1703
+ const cardDescriptorIndex = useAuthoredPluginGameplayFrameSelector(
1704
+ (frame) => {
1705
+ const snapshot = frame.zones[zone];
1706
+ return snapshot?.playableByCardId ?? {};
1707
+ }
1708
+ );
1709
+ const draftCardProjection = useMemo5(
2488
1710
  () => projectDraftCardState(
2489
1711
  availableInteractions,
2490
1712
  drafts,
@@ -2492,7 +1714,7 @@ function HandSurfaceView({
2492
1714
  ),
2493
1715
  [availableInteractions, drafts]
2494
1716
  );
2495
- const eligibleCardIds = useMemo9(() => {
1717
+ const eligibleCardIds = useMemo5(() => {
2496
1718
  const set = /* @__PURE__ */ new Set();
2497
1719
  for (const card of visibleCards) {
2498
1720
  const cardId = card.id;
@@ -2507,7 +1729,7 @@ function HandSurfaceView({
2507
1729
  return set;
2508
1730
  }, [visibleCards, cardDescriptorIndex]);
2509
1731
  const allVisibleEligible = visibleCards.length > 1 && eligibleCardIds.size === visibleCards.length;
2510
- const stateForCard = useCallback3(
1732
+ const stateForCard = useCallback2(
2511
1733
  (viewCard) => {
2512
1734
  const cardId = viewCard.id;
2513
1735
  const sourceCard = cardByViewId.get(cardId);
@@ -2530,7 +1752,7 @@ function HandSurfaceView({
2530
1752
  },
2531
1753
  [allVisibleEligible, cardByViewId, draftCardProjection, eligibleCardIds]
2532
1754
  );
2533
- const selectionSummary = useMemo9(() => {
1755
+ const selectionSummary = useMemo5(() => {
2534
1756
  const ids = /* @__PURE__ */ new Set();
2535
1757
  let hasInvalidSelection = false;
2536
1758
  for (const entry of draftCardProjection) {
@@ -2545,12 +1767,12 @@ function HandSurfaceView({
2545
1767
  }, [draftCardProjection]);
2546
1768
  const onSelectionSummaryRef = useRef(onSelectionSummary);
2547
1769
  onSelectionSummaryRef.current = onSelectionSummary;
2548
- useEffect3(() => {
1770
+ useEffect(() => {
2549
1771
  onSelectionSummaryRef.current?.(selectionSummary);
2550
1772
  }, [selectionSummary]);
2551
1773
  const summaryContent = renderSummary ? renderSummary(selectionSummary) : null;
2552
1774
  const actionsNode = renderActions ? renderActions(selectionSummary) : null;
2553
- const actionsContent = actionsNode !== null && actionsNode !== void 0 ? /* @__PURE__ */ jsx7(
1775
+ const actionsContent = actionsNode !== null && actionsNode !== void 0 ? /* @__PURE__ */ jsx4(
2554
1776
  "div",
2555
1777
  {
2556
1778
  "data-dreamboard-hand-actions": "",
@@ -2563,13 +1785,27 @@ function HandSurfaceView({
2563
1785
  children: actionsNode
2564
1786
  }
2565
1787
  ) : null;
2566
- const handleIntent = useCallback3(
1788
+ const handleIntent = useCallback2(
2567
1789
  (intent) => {
2568
1790
  void route(intent);
2569
1791
  },
2570
1792
  [route]
2571
1793
  );
2572
- const handView = /* @__PURE__ */ jsx7(
1794
+ const pointerTargetAttributesById = useMemo5(() => {
1795
+ const map = /* @__PURE__ */ new Map();
1796
+ for (const target of dropTargets ?? []) {
1797
+ const attributes = pointerTargetAttributesForRuntimeDropTarget({
1798
+ target,
1799
+ availableInteractions,
1800
+ drafts
1801
+ });
1802
+ if (attributes) {
1803
+ map.set(target.targetId, attributes);
1804
+ }
1805
+ }
1806
+ return map;
1807
+ }, [availableInteractions, drafts, dropTargets]);
1808
+ const handView = /* @__PURE__ */ jsx4(
2573
1809
  HandView,
2574
1810
  {
2575
1811
  cards: viewCards,
@@ -2592,8 +1828,8 @@ function HandSurfaceView({
2592
1828
  if (summaryContent === null && actionsContent === null) {
2593
1829
  return handView;
2594
1830
  }
2595
- return /* @__PURE__ */ jsxs2(Fragment5, { children: [
2596
- summaryContent !== null ? /* @__PURE__ */ jsx7(
1831
+ return /* @__PURE__ */ jsxs(Fragment4, { children: [
1832
+ summaryContent !== null ? /* @__PURE__ */ jsx4(
2597
1833
  "div",
2598
1834
  {
2599
1835
  "data-dreamboard-runtime-hand-summary": "",
@@ -2607,7 +1843,7 @@ function HandSurfaceView({
2607
1843
  actionsContent
2608
1844
  ] });
2609
1845
  }
2610
- const targets = dropTargets.map((target) => /* @__PURE__ */ jsx7(
1846
+ const targets = dropTargets.map((target) => /* @__PURE__ */ jsx4(
2611
1847
  CardDropTargetView,
2612
1848
  {
2613
1849
  targetId: target.targetId,
@@ -2616,12 +1852,15 @@ function HandSurfaceView({
2616
1852
  role: target.role,
2617
1853
  order: target.order,
2618
1854
  className: target.className,
1855
+ browserInteractionAttributes: pointerTargetAttributesById.get(
1856
+ target.targetId
1857
+ ),
2619
1858
  renderTarget: target.render
2620
1859
  },
2621
1860
  target.targetId
2622
1861
  ));
2623
- return /* @__PURE__ */ jsxs2(CardDragSurface, { onCardIntent: handleIntent, children: [
2624
- summaryContent !== null ? /* @__PURE__ */ jsx7(
1862
+ return /* @__PURE__ */ jsxs(CardDragSurface, { onCardIntent: handleIntent, children: [
1863
+ summaryContent !== null ? /* @__PURE__ */ jsx4(
2625
1864
  "div",
2626
1865
  {
2627
1866
  "data-dreamboard-runtime-hand-summary": "",
@@ -2631,7 +1870,7 @@ function HandSurfaceView({
2631
1870
  children: summaryContent
2632
1871
  }
2633
1872
  ) : null,
2634
- renderDropTargets ? renderDropTargets(/* @__PURE__ */ jsx7(Fragment5, { children: targets })) : /* @__PURE__ */ jsx7("div", { "data-dreamboard-runtime-drop-row": "", className: "flex gap-2 mb-2", children: targets }),
1873
+ renderDropTargets ? renderDropTargets(/* @__PURE__ */ jsx4(Fragment4, { children: targets })) : /* @__PURE__ */ jsx4("div", { "data-dreamboard-runtime-drop-row": "", className: "flex gap-2 mb-2", children: targets }),
2635
1874
  handView,
2636
1875
  actionsContent
2637
1876
  ] });
@@ -2650,6 +1889,49 @@ function manyCardSelectionForZone(availableInteractions, zone) {
2650
1889
  }
2651
1890
  return null;
2652
1891
  }
1892
+ function pointerTargetAttributesForRuntimeDropTarget({
1893
+ target,
1894
+ availableInteractions,
1895
+ drafts
1896
+ }) {
1897
+ const decoded = decodeRuntimeDropTargetId(target.targetId);
1898
+ if (!decoded) return void 0;
1899
+ for (const descriptor of availableInteractions) {
1900
+ if (!isInteractionAvailable(descriptor)) continue;
1901
+ const draft = drafts[descriptor.interactionKey] ?? {};
1902
+ const acceptedEffectPatterns = [];
1903
+ for (const rawInput of descriptor.inputs) {
1904
+ const input = resolveInputDomain(rawInput, draft);
1905
+ if (decoded.mode === "input" && input.key !== decoded.inputKey) {
1906
+ continue;
1907
+ }
1908
+ if (decoded.mode === "kind") {
1909
+ if (!isTargetDomain(input.domain) || decoded.kind === "card" && input.domain.type !== "cardTarget" || decoded.kind !== "card" && (input.domain.type !== "boardTarget" || input.domain.targetKind !== decoded.kind)) {
1910
+ continue;
1911
+ }
1912
+ }
1913
+ if (isResolvedTargetDomain(input.domain) && !input.domain.eligibleTargets.includes(decoded.value)) {
1914
+ continue;
1915
+ }
1916
+ acceptedEffectPatterns.push({
1917
+ kind: "match",
1918
+ effectKind: "setCandidate",
1919
+ fields: { inputKey: input.key, candidateValue: decoded.value }
1920
+ });
1921
+ }
1922
+ if (acceptedEffectPatterns.length === 0) continue;
1923
+ return createGameplayPointerTargetAttributes({
1924
+ scopeId: "runtime",
1925
+ interactionKey: descriptor.interactionKey,
1926
+ interactionId: descriptor.interactionId,
1927
+ targetId: target.targetId,
1928
+ enabled: (target.visualState?.eligible ?? true) && !(target.visualState?.disabled ?? false),
1929
+ ...descriptor.descriptorDigest !== void 0 ? { descriptorDigest: descriptor.descriptorDigest } : {},
1930
+ acceptedEffectPatterns
1931
+ });
1932
+ }
1933
+ return void 0;
1934
+ }
2653
1935
  function HandStagingView({
2654
1936
  zone,
2655
1937
  renderCard,
@@ -2660,44 +1942,48 @@ function HandStagingView({
2660
1942
  className
2661
1943
  }) {
2662
1944
  const interactionStore = useInteractionUiStore();
2663
- const drafts = useStore3(
1945
+ const drafts = useStore2(
2664
1946
  interactionStore,
2665
- useShallow2((state) => state.drafts)
1947
+ useShallow((state) => state.drafts)
2666
1948
  );
2667
- const stagedIds = usePluginState(
2668
- useCallback3(
2669
- (state) => selectedCardIdsForZone(interactionStore, zone, state),
1949
+ const stagedIds = useAuthoredPluginGameplayFrameSelector(
1950
+ useCallback2(
1951
+ (frame) => selectedCardIdsForZone(
1952
+ interactionStore,
1953
+ zone,
1954
+ frame.availableInteractions
1955
+ ),
2670
1956
  // drafts is part of the store snapshot — useStore handles re-render.
2671
1957
  // eslint-disable-next-line react-hooks/exhaustive-deps
2672
1958
  [interactionStore, zone, drafts]
2673
1959
  )
2674
1960
  );
2675
- const zoneSnapshot = usePluginState(
2676
- (state) => state.gameplay.zones[zone] ?? null
1961
+ const zoneSnapshot = useAuthoredPluginGameplayFrameSelector(
1962
+ (frame) => frame.zones[zone] ?? null
2677
1963
  );
2678
- const availableInteractions = usePluginState(
2679
- (state) => state.gameplay.availableInteractions
1964
+ const availableInteractions = useAuthoredPluginGameplayFrameSelector(
1965
+ (frame) => frame.availableInteractions
2680
1966
  );
2681
- const cards = useMemo9(
1967
+ const cards = useMemo5(
2682
1968
  () => stagedIds.map(
2683
1969
  (cardId, index) => createZoneCardRenderItem(zone, zoneSnapshot, cardId, index)
2684
1970
  ).filter((card) => !card.hidden),
2685
1971
  [stagedIds, zone, zoneSnapshot]
2686
1972
  );
2687
- const selection = useMemo9(
1973
+ const selection = useMemo5(
2688
1974
  () => manyCardSelectionForZone(availableInteractions, zone),
2689
1975
  [availableInteractions, zone]
2690
1976
  );
2691
1977
  const slotCount = selection?.max ?? (selection ? Math.max(cards.length, 1) : cards.length);
2692
1978
  const route = useCardIntentAdapter({ zone });
2693
- const onRemove = useCallback3(
1979
+ const onRemove = useCallback2(
2694
1980
  (cardId) => {
2695
1981
  void route({ type: "activate", cardId, source: "tap" });
2696
1982
  },
2697
1983
  [route]
2698
1984
  );
2699
1985
  if (slotCount <= 0 && cards.length === 0) return null;
2700
- return /* @__PURE__ */ jsx7(
1986
+ return /* @__PURE__ */ jsx4(
2701
1987
  StagingZone,
2702
1988
  {
2703
1989
  cards,
@@ -2715,8 +2001,8 @@ function HandStagingView({
2715
2001
  function dropTargetIdFor(kind, value) {
2716
2002
  return encodeRuntimeDropTargetKind(kind, value);
2717
2003
  }
2718
- function descriptorsHaveDestinationInput(state) {
2719
- for (const descriptor of state.gameplay.availableInteractions) {
2004
+ function descriptorsHaveDestinationInput(availableInteractions) {
2005
+ for (const descriptor of availableInteractions) {
2720
2006
  const cardInputs = descriptor.inputs.filter(
2721
2007
  (input) => isTargetDomain(input.domain) && input.domain.type === "cardTarget"
2722
2008
  );
@@ -2730,15 +2016,15 @@ function descriptorsHaveDestinationInput(state) {
2730
2016
 
2731
2017
  // src/runtime/primitives/board.tsx
2732
2018
  import {
2733
- createContext as createContext7,
2734
- useContext as useContext7,
2735
- useMemo as useMemo11
2019
+ createContext as createContext3,
2020
+ useContext as useContext3,
2021
+ useMemo as useMemo7
2736
2022
  } from "react";
2737
- import { useStore as useStore5 } from "zustand";
2023
+ import { useStore as useStore4 } from "zustand";
2738
2024
 
2739
2025
  // src/runtime/hooks/useBoardInteractions.ts
2740
- import { useCallback as useCallback4, useMemo as useMemo10 } from "react";
2741
- import { useStore as useStore4 } from "zustand";
2026
+ import { useCallback as useCallback3, useMemo as useMemo6 } from "react";
2027
+ import { useStore as useStore3 } from "zustand";
2742
2028
 
2743
2029
  // src/ui/errors/ValidationError.ts
2744
2030
  var ValidationError = class extends Error {
@@ -2769,7 +2055,7 @@ function interactionDraftDigestForValues(descriptor, values) {
2769
2055
  interactionKey: descriptor.interactionKey,
2770
2056
  values: {
2771
2057
  ...defaults,
2772
- ...toCanonicalJson2(values)
2058
+ ...toCanonicalJson(values)
2773
2059
  }
2774
2060
  });
2775
2061
  }
@@ -2780,7 +2066,7 @@ function draftDigest({
2780
2066
  interactionKey,
2781
2067
  values
2782
2068
  }) {
2783
- return hashJson2({
2069
+ return hashJson({
2784
2070
  digestVersion: "interaction-draft@2",
2785
2071
  actorSeat,
2786
2072
  descriptorDigest,
@@ -2793,11 +2079,11 @@ function draftDigest({
2793
2079
  function defaultsForDescriptor(descriptor) {
2794
2080
  return Object.fromEntries(
2795
2081
  descriptor.inputs.flatMap(
2796
- (input) => input.defaultValue === void 0 ? [] : [[input.key, toCanonicalJson2(input.defaultValue)]]
2082
+ (input) => input.defaultValue === void 0 ? [] : [[input.key, toCanonicalJson(input.defaultValue)]]
2797
2083
  )
2798
2084
  );
2799
2085
  }
2800
- function toCanonicalJson2(value) {
2086
+ function toCanonicalJson(value) {
2801
2087
  if (value === null || typeof value === "boolean" || typeof value === "string") {
2802
2088
  return value;
2803
2089
  }
@@ -2805,22 +2091,22 @@ function toCanonicalJson2(value) {
2805
2091
  return value;
2806
2092
  }
2807
2093
  if (Array.isArray(value)) {
2808
- return value.map((item) => toCanonicalJson2(item));
2094
+ return value.map((item) => toCanonicalJson(item));
2809
2095
  }
2810
2096
  if (typeof value === "object") {
2811
2097
  return Object.fromEntries(
2812
- Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => [key, toCanonicalJson2(item)])
2098
+ Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => [key, toCanonicalJson(item)])
2813
2099
  );
2814
2100
  }
2815
2101
  return null;
2816
2102
  }
2817
- function hashJson2(value) {
2818
- return `sha256:${sha256Hex2(canonicalJson2(value))}`;
2103
+ function hashJson(value) {
2104
+ return `sha256:${sha256Hex(canonicalJson(value))}`;
2819
2105
  }
2820
- function canonicalJson2(value) {
2821
- return JSON.stringify(canonicalizeJson2(value));
2106
+ function canonicalJson(value) {
2107
+ return JSON.stringify(canonicalizeJson(value));
2822
2108
  }
2823
- function canonicalizeJson2(value) {
2109
+ function canonicalizeJson(value) {
2824
2110
  if (value === null || typeof value === "boolean" || typeof value === "string") {
2825
2111
  return value;
2826
2112
  }
@@ -2831,14 +2117,14 @@ function canonicalizeJson2(value) {
2831
2117
  return value;
2832
2118
  }
2833
2119
  if (Array.isArray(value)) {
2834
- return value.map((item) => canonicalizeJson2(item));
2120
+ return value.map((item) => canonicalizeJson(item));
2835
2121
  }
2836
2122
  return Object.fromEntries(
2837
- Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, canonicalizeJson2(item)])
2123
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, canonicalizeJson(item)])
2838
2124
  );
2839
2125
  }
2840
- function sha256Hex2(input) {
2841
- const bytes = utf8Bytes2(input);
2126
+ function sha256Hex(input) {
2127
+ const bytes = utf8Bytes(input);
2842
2128
  const bitLength = bytes.length * 8;
2843
2129
  bytes.push(128);
2844
2130
  while (bytes.length % 64 !== 56) {
@@ -2894,7 +2180,7 @@ function sha256Hex2(input) {
2894
2180
  }
2895
2181
  return [h0, h1, h2, h3, h4, h5, h6, h7].map((word) => word.toString(16).padStart(8, "0")).join("");
2896
2182
  }
2897
- function utf8Bytes2(input) {
2183
+ function utf8Bytes(input) {
2898
2184
  return Array.from(new TextEncoder().encode(input));
2899
2185
  }
2900
2186
  function rightRotate(value, bits) {
@@ -3149,26 +2435,26 @@ function useBoardInteractions(options = {}) {
3149
2435
  const runtime = useRuntimeContext();
3150
2436
  const { controllingPlayerId } = usePluginSession();
3151
2437
  const store = useInteractionUiStore();
3152
- const subscribedArmedBySurface = useStore4(store, (state) => state.arms);
3153
- const subscribedDrafts = useStore4(store, (state) => state.drafts);
3154
- const pendingInteractionKey = useStore4(
2438
+ const subscribedArmedBySurface = useStore3(store, (state) => state.arms);
2439
+ const subscribedDrafts = useStore3(store, (state) => state.drafts);
2440
+ const pendingInteractionKey = useStore3(
3155
2441
  store,
3156
2442
  (state) => state.pendingInteractionKey
3157
2443
  );
3158
2444
  const armedBySurface = store.getState().arms ?? subscribedArmedBySurface;
3159
2445
  const drafts = store.getState().drafts ?? subscribedDrafts;
3160
- const descriptors = usePluginState(
3161
- (state) => state.gameplay.availableInteractions ?? []
2446
+ const descriptors = usePluginGameplayFrameSelector(
2447
+ (frame) => frame.availableInteractions ?? []
3162
2448
  );
3163
- const targetKindSet = useMemo10(
2449
+ const targetKindSet = useMemo6(
3164
2450
  () => new Set(targetKinds),
3165
2451
  [targetKinds]
3166
2452
  );
3167
- const armedIds = useMemo10(
2453
+ const armedIds = useMemo6(
3168
2454
  () => new Set(Object.values(armedBySurface)),
3169
2455
  [armedBySurface]
3170
2456
  );
3171
- const interactions = useMemo10(() => {
2457
+ const interactions = useMemo6(() => {
3172
2458
  return descriptors.flatMap(
3173
2459
  (descriptor) => {
3174
2460
  if (armedIds.has(descriptor.interactionKey)) {
@@ -3185,7 +2471,7 @@ function useBoardInteractions(options = {}) {
3185
2471
  }
3186
2472
  );
3187
2473
  }, [armedIds, descriptors, targetKindSet, targetKinds]);
3188
- const eligible = useMemo10(() => {
2474
+ const eligible = useMemo6(() => {
3189
2475
  const acc = {
3190
2476
  edge: /* @__PURE__ */ new Set(),
3191
2477
  vertex: /* @__PURE__ */ new Set(),
@@ -3206,7 +2492,7 @@ function useBoardInteractions(options = {}) {
3206
2492
  }
3207
2493
  return acc;
3208
2494
  }, [drafts, interactions]);
3209
- const isEligible = useCallback4(
2495
+ const isEligible = useCallback3(
3210
2496
  (targetId, kind) => {
3211
2497
  if (kind !== void 0) {
3212
2498
  return eligible[kind].has(targetId);
@@ -3218,13 +2504,13 @@ function useBoardInteractions(options = {}) {
3218
2504
  },
3219
2505
  [eligible]
3220
2506
  );
3221
- const clearPendingInteraction = useCallback4(
2507
+ const clearPendingInteraction = useCallback3(
3222
2508
  (descriptor) => {
3223
2509
  clearInteractionRoute(store, descriptor);
3224
2510
  },
3225
2511
  [store]
3226
2512
  );
3227
- const resolveSelection = useCallback4(
2513
+ const resolveSelection = useCallback3(
3228
2514
  async (descriptor, inputKey, targetId, extraInputs) => {
3229
2515
  if (!controllingPlayerId) return { status: "none" };
3230
2516
  const { params, readiness } = routeInteractionTarget(store, descriptor, {
@@ -3251,7 +2537,6 @@ function useBoardInteractions(options = {}) {
3251
2537
  }
3252
2538
  try {
3253
2539
  await runtime.submitInteraction(
3254
- controllingPlayerId,
3255
2540
  descriptor.interactionId,
3256
2541
  submitParams
3257
2542
  );
@@ -3269,7 +2554,7 @@ function useBoardInteractions(options = {}) {
3269
2554
  },
3270
2555
  [clearPendingInteraction, controllingPlayerId, runtime, store]
3271
2556
  );
3272
- const resolveTargetMatches = useCallback4(
2557
+ const resolveTargetMatches = useCallback3(
3273
2558
  (targetKind, targetId, interactionKeys) => {
3274
2559
  const allowedInteractionKeys = interactionKeys ? new Set(interactionKeys) : null;
3275
2560
  const matches = interactions.flatMap((descriptor) => {
@@ -3303,7 +2588,7 @@ function useBoardInteractions(options = {}) {
3303
2588
  },
3304
2589
  [armedIds, drafts, interactions]
3305
2590
  );
3306
- const selectByKind = useCallback4(
2591
+ const selectByKind = useCallback3(
3307
2592
  async (targetKind, targetId, extraInputs, interactionKeys) => {
3308
2593
  if (!controllingPlayerId) return { status: "none" };
3309
2594
  const matches = resolveTargetMatches(
@@ -3320,7 +2605,7 @@ function useBoardInteractions(options = {}) {
3320
2605
  },
3321
2606
  [controllingPlayerId, resolveSelection, resolveTargetMatches]
3322
2607
  );
3323
- const select = useMemo10(
2608
+ const select = useMemo6(
3324
2609
  () => ({
3325
2610
  edge: (targetId, extraInputs) => selectByKind("edge", targetId, extraInputs),
3326
2611
  vertex: (targetId, extraInputs) => selectByKind("vertex", targetId, extraInputs),
@@ -3329,7 +2614,7 @@ function useBoardInteractions(options = {}) {
3329
2614
  }),
3330
2615
  [selectByKind]
3331
2616
  );
3332
- const targetState = useCallback4(
2617
+ const targetState = useCallback3(
3333
2618
  (targetKind, targetId, options2 = {}) => {
3334
2619
  const enabled = options2.enabled !== false;
3335
2620
  const matches = enabled ? resolveTargetMatches(targetKind, targetId, options2.interactionKeys) : [];
@@ -3364,7 +2649,7 @@ function useBoardInteractions(options = {}) {
3364
2649
  },
3365
2650
  [controllingPlayerId, drafts, pendingInteractionKey, resolveTargetMatches]
3366
2651
  );
3367
- const targetLayers = useMemo10(() => {
2652
+ const targetLayers = useMemo6(() => {
3368
2653
  const createLayer = (targetKind) => (layerOptions = {}) => {
3369
2654
  const {
3370
2655
  enabled,
@@ -3421,7 +2706,7 @@ function useBoardInteractions(options = {}) {
3421
2706
  tile: createLayer("tile")
3422
2707
  };
3423
2708
  }, [eligible, selectByKind, targetState]);
3424
- const pendingInteraction = useMemo10(() => {
2709
+ const pendingInteraction = useMemo6(() => {
3425
2710
  if (!pendingInteractionKey) return null;
3426
2711
  const descriptor = interactions.find(
3427
2712
  (candidate) => candidate.interactionKey === pendingInteractionKey
@@ -3437,11 +2722,11 @@ function useBoardInteractions(options = {}) {
3437
2722
  clear: () => clearPendingInteraction(descriptor)
3438
2723
  };
3439
2724
  }, [clearPendingInteraction, drafts, interactions, pendingInteractionKey]);
3440
- const selectTarget = useCallback4(
2725
+ const selectTarget = useCallback3(
3441
2726
  (descriptor, _targetKind, targetId, inputKey, extraInputs) => resolveSelection(descriptor, inputKey, targetId, extraInputs),
3442
2727
  [resolveSelection]
3443
2728
  );
3444
- return useMemo10(
2729
+ return useMemo6(
3445
2730
  () => ({
3446
2731
  interactions,
3447
2732
  eligible,
@@ -3475,7 +2760,7 @@ function isTargetSelectable(input, draft, targetId) {
3475
2760
  function missingInputsForDraft(descriptor, draft) {
3476
2761
  return [...getInteractionDraftReadiness(descriptor, draft).missingInputs];
3477
2762
  }
3478
- var GAMEPLAY_BROWSER_SCOPE_ID2 = "runtime";
2763
+ var GAMEPLAY_BROWSER_SCOPE_ID = "runtime";
3479
2764
  function boardTargetBrowserAttributes({
3480
2765
  descriptor,
3481
2766
  inputKey,
@@ -3485,7 +2770,7 @@ function boardTargetBrowserAttributes({
3485
2770
  draft
3486
2771
  }) {
3487
2772
  return createGameplayActuatorAttributes({
3488
- scopeId: GAMEPLAY_BROWSER_SCOPE_ID2,
2773
+ scopeId: GAMEPLAY_BROWSER_SCOPE_ID,
3489
2774
  interactionKey: descriptor.interactionKey,
3490
2775
  interactionId: descriptor.interactionId,
3491
2776
  intent: "select",
@@ -3535,8 +2820,8 @@ function candidateUnavailableReason(match, conflict) {
3535
2820
  }
3536
2821
 
3537
2822
  // src/runtime/primitives/board.tsx
3538
- import { Fragment as Fragment6, jsx as jsx8 } from "react/jsx-runtime";
3539
- var BoardContext = createContext7(null);
2823
+ import { Fragment as Fragment5, jsx as jsx5 } from "react/jsx-runtime";
2824
+ var BoardContext = createContext3(null);
3540
2825
  var warnedAmbiguousBoardTargets = /* @__PURE__ */ new Set();
3541
2826
  function warnAmbiguousBoardTarget({
3542
2827
  kind,
@@ -3557,7 +2842,7 @@ function warnAmbiguousBoardTarget({
3557
2842
  }
3558
2843
  }
3559
2844
  function useBoardPrimitiveContext() {
3560
- const value = useContext7(BoardContext);
2845
+ const value = useContext3(BoardContext);
3561
2846
  if (!value) {
3562
2847
  throw new Error("Board primitives must be rendered inside <Board.Root>.");
3563
2848
  }
@@ -3565,21 +2850,21 @@ function useBoardPrimitiveContext() {
3565
2850
  }
3566
2851
  function BoardRoot({ children, targetKinds, ...props }) {
3567
2852
  const board = useBoardInteractions({ targetKinds });
3568
- return /* @__PURE__ */ jsx8(BoardContext.Provider, { value: board, children: renderPrimitive("div", {
2853
+ return /* @__PURE__ */ jsx5(BoardContext.Provider, { value: board, children: renderPrimitive("div", {
3569
2854
  ...props,
3570
2855
  "data-dreamboard-board-root": "",
3571
2856
  children
3572
2857
  }) });
3573
2858
  }
3574
2859
  function BoardState({ children }) {
3575
- return /* @__PURE__ */ jsx8(Fragment6, { children: children(useBoardPrimitiveContext()) });
2860
+ return /* @__PURE__ */ jsx5(Fragment5, { children: children(useBoardPrimitiveContext()) });
3576
2861
  }
3577
2862
  function BoardHexView({ board, spaces, children }) {
3578
- const view = useMemo11(
2863
+ const view = useMemo7(
3579
2864
  () => createHexBoardView(board, { spaces }),
3580
2865
  [board, spaces]
3581
2866
  );
3582
- return /* @__PURE__ */ jsx8(Fragment6, { children: children(view) });
2867
+ return /* @__PURE__ */ jsx5(Fragment5, { children: children(view) });
3583
2868
  }
3584
2869
  function BoardHexGrid({
3585
2870
  board,
@@ -3604,7 +2889,7 @@ function BoardHexGrid({
3604
2889
  interactionKeys: interactions === "auto" ? void 0 : interactions.space,
3605
2890
  onError: gameActionError ?? void 0
3606
2891
  });
3607
- return /* @__PURE__ */ jsx8(BoardHexView, { board, spaces, children: (view) => /* @__PURE__ */ jsx8(
2892
+ return /* @__PURE__ */ jsx5(BoardHexView, { board, spaces, children: (view) => /* @__PURE__ */ jsx5(
3608
2893
  HexGrid,
3609
2894
  {
3610
2895
  ...props,
@@ -3620,13 +2905,13 @@ function BoardTarget({
3620
2905
  input,
3621
2906
  ...props
3622
2907
  }) {
3623
- const descriptor = usePluginState(
3624
- (state) => interaction ? state.gameplay.availableInteractions.find(
2908
+ const descriptor = useAuthoredPluginGameplayFrameSelector(
2909
+ (frame) => interaction ? frame.availableInteractions.find(
3625
2910
  (candidate) => candidate.interactionKey === interaction || candidate.interactionId === interaction
3626
2911
  ) : void 0
3627
2912
  );
3628
2913
  if (interaction) {
3629
- return descriptor ? /* @__PURE__ */ jsx8(ExplicitBoardTarget, { descriptor, input, ...props }) : /* @__PURE__ */ jsx8(
2914
+ return descriptor ? /* @__PURE__ */ jsx5(ExplicitBoardTarget, { descriptor, input, ...props }) : /* @__PURE__ */ jsx5(
3630
2915
  UnavailableBoardTarget,
3631
2916
  {
3632
2917
  interaction,
@@ -3635,16 +2920,16 @@ function BoardTarget({
3635
2920
  }
3636
2921
  );
3637
2922
  }
3638
- return /* @__PURE__ */ jsx8(UnambiguousBoardTarget, { input, ...props });
2923
+ return /* @__PURE__ */ jsx5(UnambiguousBoardTarget, { input, ...props });
3639
2924
  }
3640
2925
  function BoardSpaceTarget(props) {
3641
- return /* @__PURE__ */ jsx8(BoardTarget, { kind: "space", ...props });
2926
+ return /* @__PURE__ */ jsx5(BoardTarget, { kind: "space", ...props });
3642
2927
  }
3643
2928
  function BoardEdgeTarget(props) {
3644
- return /* @__PURE__ */ jsx8(BoardTarget, { kind: "edge", ...props });
2929
+ return /* @__PURE__ */ jsx5(BoardTarget, { kind: "edge", ...props });
3645
2930
  }
3646
2931
  function BoardVertexTarget(props) {
3647
- return /* @__PURE__ */ jsx8(BoardTarget, { kind: "vertex", ...props });
2932
+ return /* @__PURE__ */ jsx5(BoardTarget, { kind: "vertex", ...props });
3648
2933
  }
3649
2934
  function UnambiguousBoardTarget({
3650
2935
  kind,
@@ -3719,7 +3004,7 @@ function ExplicitBoardTarget({
3719
3004
  const board = useBoardPrimitiveContext();
3720
3005
  const gameActionError = useGameActionError();
3721
3006
  const store = useInteractionUiStore();
3722
- useStore5(store, (state) => state.drafts[descriptor.interactionKey] ?? {});
3007
+ useStore4(store, (state) => state.drafts[descriptor.interactionKey] ?? {});
3723
3008
  const draft = store.getDraft(descriptor.interactionKey);
3724
3009
  const inputKey = input ?? inputKeyForTarget(descriptor, kind, value, draft);
3725
3010
  const rawInputDescriptor = inputKey ? inputByKey(descriptor, inputKey) : void 0;
@@ -3797,7 +3082,7 @@ function UnavailableBoardTarget({
3797
3082
  function resolveExtraInputs(extraInputs, targetId) {
3798
3083
  return typeof extraInputs === "function" ? extraInputs(targetId) : extraInputs ?? {};
3799
3084
  }
3800
- var GAMEPLAY_BROWSER_SCOPE_ID3 = "runtime";
3085
+ var GAMEPLAY_BROWSER_SCOPE_ID2 = "runtime";
3801
3086
  function boardTargetBrowserAttributes2({
3802
3087
  descriptor,
3803
3088
  inputKey,
@@ -3807,7 +3092,7 @@ function boardTargetBrowserAttributes2({
3807
3092
  draft
3808
3093
  }) {
3809
3094
  return createGameplayActuatorAttributes({
3810
- scopeId: GAMEPLAY_BROWSER_SCOPE_ID3,
3095
+ scopeId: GAMEPLAY_BROWSER_SCOPE_ID2,
3811
3096
  interactionKey: descriptor.interactionKey,
3812
3097
  interactionId: descriptor.interactionId,
3813
3098
  intent: "select",
@@ -3846,23 +3131,23 @@ var Board = {
3846
3131
  };
3847
3132
 
3848
3133
  // src/runtime/primitives/interaction/context.tsx
3849
- import { createContext as createContext9, useContext as useContext9, useMemo as useMemo13 } from "react";
3134
+ import { createContext as createContext5, useContext as useContext5, useMemo as useMemo9 } from "react";
3850
3135
 
3851
3136
  // src/runtime/hooks/useBoundInteractionHandle.ts
3852
- import { useCallback as useCallback5, useEffect as useEffect4, useMemo as useMemo12, useRef as useRef2 } from "react";
3137
+ import { useCallback as useCallback4, useEffect as useEffect2, useMemo as useMemo8, useRef as useRef2 } from "react";
3853
3138
 
3854
3139
  // src/runtime/context/ClientParamSchemaContext.tsx
3855
- import { createContext as createContext8, useContext as useContext8 } from "react";
3856
- import { jsx as jsx9 } from "react/jsx-runtime";
3857
- var ClientParamSchemaContext = createContext8({});
3140
+ import { createContext as createContext4, useContext as useContext4 } from "react";
3141
+ import { jsx as jsx6 } from "react/jsx-runtime";
3142
+ var ClientParamSchemaContext = createContext4({});
3858
3143
  function ClientParamSchemaProvider({
3859
3144
  schemas,
3860
3145
  children
3861
3146
  }) {
3862
- return /* @__PURE__ */ jsx9(ClientParamSchemaContext.Provider, { value: schemas ?? {}, children });
3147
+ return /* @__PURE__ */ jsx6(ClientParamSchemaContext.Provider, { value: schemas ?? {}, children });
3863
3148
  }
3864
3149
  function useClientParamSchema(phaseName, interactionId) {
3865
- const schemas = useContext8(ClientParamSchemaContext);
3150
+ const schemas = useContext4(ClientParamSchemaContext);
3866
3151
  if (!phaseName) return void 0;
3867
3152
  return schemas[phaseName]?.[interactionId];
3868
3153
  }
@@ -3875,20 +3160,20 @@ function useBoundInteractionHandle(descriptor) {
3875
3160
  const { controllingPlayerId } = usePluginSession();
3876
3161
  const store = useInteractionUiStore();
3877
3162
  const autoSubmitSignatureRef = useRef2(null);
3878
- const simultaneousPhase = usePluginState(
3879
- (state) => state.gameplay.simultaneousPhase
3163
+ const simultaneousPhase = usePluginGameplayFrameSelector(
3164
+ (frame) => frame.flow.simultaneousPhase
3880
3165
  );
3881
3166
  const interactionId = descriptor?.interactionId ?? "";
3882
3167
  const interactionKey = descriptor?.interactionKey ?? MISSING_INTERACTION_KEY;
3883
3168
  const phaseName = descriptor?.phaseName;
3884
3169
  const armScope = descriptor ? interactionArmScope(descriptor) : MISSING_INTERACTION_SCOPE;
3885
- const inputKeys = useMemo12(
3170
+ const inputKeys = useMemo8(
3886
3171
  () => descriptor ? interactionInputKeys(descriptor) : [],
3887
3172
  [descriptor]
3888
3173
  );
3889
3174
  const paramsSchema = useClientParamSchema(phaseName, interactionId);
3890
3175
  const draft = useInteractionDraft(interactionKey);
3891
- const values = useMemo12(() => {
3176
+ const values = useMemo8(() => {
3892
3177
  if (!descriptor) {
3893
3178
  return {};
3894
3179
  }
@@ -3899,7 +3184,7 @@ function useBoundInteractionHandle(descriptor) {
3899
3184
  const submitting = useInteractionSubmitting(interactionKey);
3900
3185
  const submitted = descriptor !== null && controllingPlayerId !== null && simultaneousPhase?.phaseName === descriptor.phaseName && simultaneousPhase.interactionId === descriptor.interactionId && simultaneousPhase.sealedPlayerIds.includes(controllingPlayerId);
3901
3186
  const status = submitted ? "submitted" : submitting ? "submitting" : "open";
3902
- const readiness = useMemo12(() => {
3187
+ const readiness = useMemo8(() => {
3903
3188
  if (!descriptor) {
3904
3189
  return null;
3905
3190
  }
@@ -3909,7 +3194,7 @@ function useBoundInteractionHandle(descriptor) {
3909
3194
  );
3910
3195
  }, [descriptor, values]);
3911
3196
  const isReady = readiness?.ready ?? false;
3912
- const requireDescriptor = useCallback5(() => {
3197
+ const requireDescriptor = useCallback4(() => {
3913
3198
  if (!descriptor) {
3914
3199
  throw new Error(
3915
3200
  "useInteractionHandle: interaction descriptor unavailable"
@@ -3917,13 +3202,7 @@ function useBoundInteractionHandle(descriptor) {
3917
3202
  }
3918
3203
  return descriptor;
3919
3204
  }, [descriptor]);
3920
- const requirePlayer = useCallback5(() => {
3921
- if (!controllingPlayerId) {
3922
- throw new Error("useInteractionHandle: no controlling player available");
3923
- }
3924
- return controllingPlayerId;
3925
- }, [controllingPlayerId]);
3926
- const submit = useCallback5(
3205
+ const submit = useCallback4(
3927
3206
  async (params) => {
3928
3207
  const activeDescriptor = requireDescriptor();
3929
3208
  if (status !== "open") {
@@ -3944,7 +3223,6 @@ function useBoundInteractionHandle(descriptor) {
3944
3223
  );
3945
3224
  try {
3946
3225
  await runtime.submitInteraction(
3947
- requirePlayer(),
3948
3226
  activeDescriptor.interactionId,
3949
3227
  finalParams
3950
3228
  );
@@ -3955,9 +3233,9 @@ function useBoundInteractionHandle(descriptor) {
3955
3233
  store.setSubmitting(activeDescriptor.interactionKey, false);
3956
3234
  }
3957
3235
  },
3958
- [requireDescriptor, status, store, values, runtime, requirePlayer]
3236
+ [requireDescriptor, status, store, values, runtime]
3959
3237
  );
3960
- const validate = useCallback5(
3238
+ const validate = useCallback4(
3961
3239
  async (params) => {
3962
3240
  const activeDescriptor = requireDescriptor();
3963
3241
  const finalParams = applyInteractionInputDefaults(
@@ -3965,7 +3243,6 @@ function useBoundInteractionHandle(descriptor) {
3965
3243
  params ?? values
3966
3244
  );
3967
3245
  const result = await runtime.validateInteraction(
3968
- requirePlayer(),
3969
3246
  activeDescriptor.interactionId,
3970
3247
  finalParams
3971
3248
  );
@@ -3973,9 +3250,9 @@ function useBoundInteractionHandle(descriptor) {
3973
3250
  throw new ValidationError(result.errorCode, result.message);
3974
3251
  }
3975
3252
  },
3976
- [requireDescriptor, values, runtime, requirePlayer]
3253
+ [requireDescriptor, values, runtime]
3977
3254
  );
3978
- const validateDraft = useCallback5(() => {
3255
+ const validateDraft = useCallback4(() => {
3979
3256
  const activeDescriptor = requireDescriptor();
3980
3257
  const rawDraft = { ...values };
3981
3258
  const required = inputKeys;
@@ -4042,10 +3319,10 @@ function useBoundInteractionHandle(descriptor) {
4042
3319
  missing
4043
3320
  };
4044
3321
  }, [requireDescriptor, values, inputKeys, paramsSchema]);
4045
- const validateDraftServer = useCallback5(async () => {
3322
+ const validateDraftServer = useCallback4(async () => {
4046
3323
  await validate({ ...values });
4047
3324
  }, [values, validate]);
4048
- const submitDraft = useCallback5(async () => {
3325
+ const submitDraft = useCallback4(async () => {
4049
3326
  const validation = validateDraft();
4050
3327
  if (!validation.ok) {
4051
3328
  const message = validation.formErrors[0] ?? Object.values(validation.fieldErrors).flat()[0] ?? (validation.missing.length > 0 ? "Required inputs are missing" : "Draft validation failed");
@@ -4053,7 +3330,7 @@ function useBoundInteractionHandle(descriptor) {
4053
3330
  }
4054
3331
  await submit(validation.params);
4055
3332
  }, [submit, validateDraft]);
4056
- useEffect4(() => {
3333
+ useEffect2(() => {
4057
3334
  if (!descriptor) {
4058
3335
  autoSubmitSignatureRef.current = null;
4059
3336
  return;
@@ -4086,28 +3363,28 @@ function useBoundInteractionHandle(descriptor) {
4086
3363
  submit,
4087
3364
  validateDraft
4088
3365
  ]);
4089
- const setInput = useCallback5(
3366
+ const setInput = useCallback4(
4090
3367
  (key, value) => {
4091
3368
  const activeDescriptor = requireDescriptor();
4092
3369
  applyInteractionDraftMutation(store, activeDescriptor, [{ key, value }]);
4093
3370
  },
4094
3371
  [store, requireDescriptor]
4095
3372
  );
4096
- const clearInput = useCallback5(
3373
+ const clearInput = useCallback4(
4097
3374
  (key) => {
4098
3375
  const activeDescriptor = requireDescriptor();
4099
3376
  store.clearInput(activeDescriptor.interactionKey, key);
4100
3377
  },
4101
3378
  [store, requireDescriptor]
4102
3379
  );
4103
- const arm = useCallback5(() => {
3380
+ const arm = useCallback4(() => {
4104
3381
  const activeDescriptor = requireDescriptor();
4105
3382
  store.arm(
4106
3383
  interactionArmScope(activeDescriptor),
4107
3384
  activeDescriptor.interactionKey
4108
3385
  );
4109
3386
  }, [store, requireDescriptor]);
4110
- const disarm = useCallback5(() => {
3387
+ const disarm = useCallback4(() => {
4111
3388
  const activeDescriptor = requireDescriptor();
4112
3389
  const activeArmScope = interactionArmScope(activeDescriptor);
4113
3390
  if (store.getArmed(activeArmScope) === activeDescriptor.interactionKey) {
@@ -4145,7 +3422,7 @@ function useInteractionHandle(descriptor) {
4145
3422
  }
4146
3423
 
4147
3424
  // src/runtime/interactions/gameplay-attributes.ts
4148
- var GAMEPLAY_BROWSER_SCOPE_ID4 = "runtime";
3425
+ var GAMEPLAY_BROWSER_SCOPE_ID3 = "runtime";
4149
3426
  function gameplayInteractionRootAttributes({
4150
3427
  descriptor,
4151
3428
  draftDigest: draftDigest2,
@@ -4153,7 +3430,7 @@ function gameplayInteractionRootAttributes({
4153
3430
  available
4154
3431
  }) {
4155
3432
  return createGameplayInteractionRootAttributes({
4156
- scopeId: GAMEPLAY_BROWSER_SCOPE_ID4,
3433
+ scopeId: GAMEPLAY_BROWSER_SCOPE_ID3,
4157
3434
  interactionKey: descriptor.interactionKey,
4158
3435
  interactionId: descriptor.interactionId,
4159
3436
  ...descriptor.descriptorDigest !== void 0 ? { descriptorDigest: descriptor.descriptorDigest } : {},
@@ -4176,7 +3453,7 @@ function gameplayActuatorAttributes({
4176
3453
  actuatorId
4177
3454
  }) {
4178
3455
  return createGameplayActuatorAttributes({
4179
- scopeId: GAMEPLAY_BROWSER_SCOPE_ID4,
3456
+ scopeId: GAMEPLAY_BROWSER_SCOPE_ID3,
4180
3457
  interactionKey: descriptor.interactionKey,
4181
3458
  interactionId: descriptor.interactionId,
4182
3459
  intent,
@@ -4195,15 +3472,15 @@ function gameplayActuatorAttributes({
4195
3472
  }
4196
3473
 
4197
3474
  // src/runtime/primitives/interaction/context.tsx
4198
- import { jsx as jsx10 } from "react/jsx-runtime";
4199
- var InteractionContext = createContext9(null);
3475
+ import { jsx as jsx7 } from "react/jsx-runtime";
3476
+ var InteractionContext = createContext5(null);
4200
3477
  function humanizeInteraction(value) {
4201
3478
  const parts = value.split(".");
4202
3479
  const leaf = parts[parts.length - 1] ?? value;
4203
3480
  return leaf.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\s+/g, " ").trim().replace(/^./, (first) => first.toUpperCase());
4204
3481
  }
4205
3482
  function useInteractionPrimitiveContext() {
4206
- const value = useContext9(InteractionContext);
3483
+ const value = useContext5(InteractionContext);
4207
3484
  if (!value) {
4208
3485
  throw new Error(
4209
3486
  "Interaction primitives must be rendered inside <Interaction.Root>."
@@ -4212,7 +3489,7 @@ function useInteractionPrimitiveContext() {
4212
3489
  return value;
4213
3490
  }
4214
3491
  function useResolvedCardTargetValue() {
4215
- const context = useContext9(InteractionContext);
3492
+ const context = useContext5(InteractionContext);
4216
3493
  const descriptor = context?.descriptor;
4217
3494
  const handle = context?.handle;
4218
3495
  if (!descriptor || !handle) return void 0;
@@ -4223,8 +3500,8 @@ function useResolvedCardTargetValue() {
4223
3500
  return handle.values[cardInput.key];
4224
3501
  }
4225
3502
  function useInteractionDescriptor(interaction) {
4226
- return usePluginState(
4227
- (state) => state.gameplay.availableInteractions.find(
3503
+ return useAuthoredPluginGameplayFrameSelector(
3504
+ (frame) => frame.availableInteractions.find(
4228
3505
  (descriptor) => descriptor.interactionKey === interaction || descriptor.interactionId === interaction
4229
3506
  )
4230
3507
  );
@@ -4235,20 +3512,20 @@ function ResolvedInteractionRoot({
4235
3512
  children
4236
3513
  }) {
4237
3514
  const handle = useInteractionHandle(descriptor);
4238
- const value = useMemo13(
3515
+ const value = useMemo9(
4239
3516
  () => ({ interaction, descriptor, handle }),
4240
3517
  [descriptor, handle, interaction]
4241
3518
  );
4242
3519
  const available = isInteractionAvailable(descriptor);
4243
3520
  const rootAttributes = createGameplayInteractionRootAttributes({
4244
- scopeId: GAMEPLAY_BROWSER_SCOPE_ID4,
3521
+ scopeId: GAMEPLAY_BROWSER_SCOPE_ID3,
4245
3522
  interactionKey: descriptor.interactionKey,
4246
3523
  interactionId: descriptor.interactionId,
4247
3524
  ...descriptor.descriptorDigest !== void 0 ? { descriptorDigest: descriptor.descriptorDigest } : {},
4248
3525
  ...descriptor.draftDigest !== void 0 ? { draftDigest: descriptor.draftDigest } : {},
4249
3526
  readiness: available ? handle.isReady ? "ready" : "blocked" : "unavailable"
4250
3527
  });
4251
- return /* @__PURE__ */ jsx10(InteractionContext.Provider, { value, children: renderPrimitive("span", {
3528
+ return /* @__PURE__ */ jsx7(InteractionContext.Provider, { value, children: renderPrimitive("span", {
4252
3529
  ...rootAttributes,
4253
3530
  style: { display: "contents" },
4254
3531
  children
@@ -4262,7 +3539,7 @@ function InteractionRoot({
4262
3539
  const descriptor = useInteractionDescriptor(interaction);
4263
3540
  if (!descriptor) {
4264
3541
  if (unavailable === "hide") return null;
4265
- return /* @__PURE__ */ jsx10(
3542
+ return /* @__PURE__ */ jsx7(
4266
3543
  InteractionContext.Provider,
4267
3544
  {
4268
3545
  value: {
@@ -4277,12 +3554,12 @@ function InteractionRoot({
4277
3554
  if (!isInteractionAvailable(descriptor) && unavailable === "hide") {
4278
3555
  return null;
4279
3556
  }
4280
- return /* @__PURE__ */ jsx10(ResolvedInteractionRoot, { interaction, descriptor, children });
3557
+ return /* @__PURE__ */ jsx7(ResolvedInteractionRoot, { interaction, descriptor, children });
4281
3558
  }
4282
3559
 
4283
3560
  // src/runtime/components/interaction-form/fields.tsx
4284
3561
  import { useId } from "react";
4285
- import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
3562
+ import { Fragment as Fragment6, jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
4286
3563
  var EMPTY_FIELD_ERRORS = [];
4287
3564
  function InteractionField({
4288
3565
  descriptor,
@@ -4313,8 +3590,8 @@ function InteractionField({
4313
3590
  missing,
4314
3591
  disabled
4315
3592
  };
4316
- if (render) return /* @__PURE__ */ jsx11(Fragment7, { children: render(props) });
4317
- return /* @__PURE__ */ jsx11(DefaultInteractionField, { ...props });
3593
+ if (render) return /* @__PURE__ */ jsx8(Fragment6, { children: render(props) });
3594
+ return /* @__PURE__ */ jsx8(DefaultInteractionField, { ...props });
4318
3595
  }
4319
3596
  function defaultFormInputs(descriptor, values = {}) {
4320
3597
  return resolveInteractionInputs(descriptor, values).filter((input) => {
@@ -4335,7 +3612,7 @@ function DefaultInteractionField(props) {
4335
3612
  switch (input.domain.type) {
4336
3613
  case "choice":
4337
3614
  if (input.domain.selection?.mode === "many") {
4338
- return /* @__PURE__ */ jsx11(
3615
+ return /* @__PURE__ */ jsx8(
4339
3616
  ChoiceListField,
4340
3617
  {
4341
3618
  ...props,
@@ -4349,16 +3626,16 @@ function DefaultInteractionField(props) {
4349
3626
  }
4350
3627
  );
4351
3628
  }
4352
- return /* @__PURE__ */ jsx11(ChoiceField, { ...props, domain: input.domain });
3629
+ return /* @__PURE__ */ jsx8(ChoiceField, { ...props, domain: input.domain });
4353
3630
  case "choiceList":
4354
- return /* @__PURE__ */ jsx11(ChoiceListField, { ...props, domain: input.domain });
3631
+ return /* @__PURE__ */ jsx8(ChoiceListField, { ...props, domain: input.domain });
4355
3632
  case "resourceMap":
4356
- return /* @__PURE__ */ jsx11(ResourceMapField, { ...props, domain: input.domain });
3633
+ return /* @__PURE__ */ jsx8(ResourceMapField, { ...props, domain: input.domain });
4357
3634
  case "boundedNumber":
4358
- return /* @__PURE__ */ jsx11(BoundedNumberField, { ...props, domain: input.domain });
3635
+ return /* @__PURE__ */ jsx8(BoundedNumberField, { ...props, domain: input.domain });
4359
3636
  case "cardTarget":
4360
3637
  case "boardTarget":
4361
- return /* @__PURE__ */ jsx11(TargetSummaryField, { ...props, domain: input.domain });
3638
+ return /* @__PURE__ */ jsx8(TargetSummaryField, { ...props, domain: input.domain });
4362
3639
  }
4363
3640
  }
4364
3641
  function FieldFrame({
@@ -4370,7 +3647,7 @@ function FieldFrame({
4370
3647
  }) {
4371
3648
  const theme = useTheme();
4372
3649
  const messages = errors.length > 0 ? errors : missing ? ["Required"] : [];
4373
- return /* @__PURE__ */ jsxs3(
3650
+ return /* @__PURE__ */ jsxs2(
4374
3651
  "div",
4375
3652
  {
4376
3653
  style: {
@@ -4381,7 +3658,7 @@ function FieldFrame({
4381
3658
  color: theme.semantic.text.primary
4382
3659
  },
4383
3660
  children: [
4384
- /* @__PURE__ */ jsx11(
3661
+ /* @__PURE__ */ jsx8(
4385
3662
  Label,
4386
3663
  {
4387
3664
  htmlFor: controlId,
@@ -4393,7 +3670,7 @@ function FieldFrame({
4393
3670
  }
4394
3671
  ),
4395
3672
  children,
4396
- messages.length > 0 ? /* @__PURE__ */ jsx11(
3673
+ messages.length > 0 ? /* @__PURE__ */ jsx8(
4397
3674
  "span",
4398
3675
  {
4399
3676
  role: "alert",
@@ -4404,7 +3681,7 @@ function FieldFrame({
4404
3681
  color: theme.semantic.intent.danger.solid,
4405
3682
  fontSize: theme.typography.fontSize.xs
4406
3683
  },
4407
- children: messages.map((message) => /* @__PURE__ */ jsx11("span", { children: message }, message))
3684
+ children: messages.map((message) => /* @__PURE__ */ jsx8("span", { children: message }, message))
4408
3685
  }
4409
3686
  ) : null
4410
3687
  ]
@@ -4413,7 +3690,7 @@ function FieldFrame({
4413
3690
  }
4414
3691
  function ChoiceOptionLabel({ choice }) {
4415
3692
  const theme = useTheme();
4416
- return /* @__PURE__ */ jsxs3(
3693
+ return /* @__PURE__ */ jsxs2(
4417
3694
  "span",
4418
3695
  {
4419
3696
  style: {
@@ -4423,7 +3700,7 @@ function ChoiceOptionLabel({ choice }) {
4423
3700
  minWidth: 0
4424
3701
  },
4425
3702
  children: [
4426
- /* @__PURE__ */ jsxs3(
3703
+ /* @__PURE__ */ jsxs2(
4427
3704
  "span",
4428
3705
  {
4429
3706
  style: {
@@ -4433,12 +3710,12 @@ function ChoiceOptionLabel({ choice }) {
4433
3710
  minWidth: 0
4434
3711
  },
4435
3712
  children: [
4436
- choice.icon ? /* @__PURE__ */ jsx11("span", { "aria-hidden": true, style: { fontSize: "1.1em", lineHeight: 1 }, children: choice.icon }) : null,
4437
- /* @__PURE__ */ jsx11("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: choice.label })
3713
+ choice.icon ? /* @__PURE__ */ jsx8("span", { "aria-hidden": true, style: { fontSize: "1.1em", lineHeight: 1 }, children: choice.icon }) : null,
3714
+ /* @__PURE__ */ jsx8("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: choice.label })
4438
3715
  ]
4439
3716
  }
4440
3717
  ),
4441
- choice.badge ? /* @__PURE__ */ jsx11(
3718
+ choice.badge ? /* @__PURE__ */ jsx8(
4442
3719
  "span",
4443
3720
  {
4444
3721
  style: {
@@ -4462,7 +3739,7 @@ function ChoiceDescription({ choice }) {
4462
3739
  const theme = useTheme();
4463
3740
  const message = choice?.disabledReason ?? choice?.description;
4464
3741
  if (!message) return null;
4465
- return /* @__PURE__ */ jsx11(
3742
+ return /* @__PURE__ */ jsx8(
4466
3743
  "span",
4467
3744
  {
4468
3745
  style: {
@@ -4501,13 +3778,13 @@ function ChoiceField({
4501
3778
  const controlId = useId();
4502
3779
  const selectedChoice = typeof value === "string" || value === null ? choices.find((choice) => choice.value === value) : void 0;
4503
3780
  if (choices.length > 0 && choices.length <= 3) {
4504
- return /* @__PURE__ */ jsx11(
3781
+ return /* @__PURE__ */ jsx8(
4505
3782
  FieldFrame,
4506
3783
  {
4507
3784
  label: labelForInput(input),
4508
3785
  errors,
4509
3786
  missing,
4510
- children: /* @__PURE__ */ jsx11(
3787
+ children: /* @__PURE__ */ jsx8(
4511
3788
  "span",
4512
3789
  {
4513
3790
  style: {
@@ -4518,7 +3795,7 @@ function ChoiceField({
4518
3795
  children: choices.map((choice) => {
4519
3796
  const selected = value === choice.value;
4520
3797
  const isDisabled = disabled || choice.disabled;
4521
- return /* @__PURE__ */ jsx11(
3798
+ return /* @__PURE__ */ jsx8(
4522
3799
  ThemedButton,
4523
3800
  {
4524
3801
  type: "button",
@@ -4550,7 +3827,7 @@ function ChoiceField({
4550
3827
  }),
4551
3828
  onClick: () => setValue(choice.value),
4552
3829
  className: "h-8 px-3 text-sm",
4553
- children: /* @__PURE__ */ jsx11(ChoiceOptionLabel, { choice })
3830
+ children: /* @__PURE__ */ jsx8(ChoiceOptionLabel, { choice })
4554
3831
  },
4555
3832
  choiceRenderKey(choice)
4556
3833
  );
@@ -4560,7 +3837,7 @@ function ChoiceField({
4560
3837
  }
4561
3838
  );
4562
3839
  }
4563
- return /* @__PURE__ */ jsxs3(
3840
+ return /* @__PURE__ */ jsxs2(
4564
3841
  FieldFrame,
4565
3842
  {
4566
3843
  label: labelForInput(input),
@@ -4568,14 +3845,14 @@ function ChoiceField({
4568
3845
  errors,
4569
3846
  missing,
4570
3847
  children: [
4571
- /* @__PURE__ */ jsxs3(
3848
+ /* @__PURE__ */ jsxs2(
4572
3849
  Select,
4573
3850
  {
4574
3851
  disabled,
4575
3852
  value: encodeChoiceSelectValue(value),
4576
3853
  onValueChange: (next) => setValue(decodeChoiceSelectValue(next)),
4577
3854
  children: [
4578
- /* @__PURE__ */ jsx11(
3855
+ /* @__PURE__ */ jsx8(
4579
3856
  SelectTrigger,
4580
3857
  {
4581
3858
  id: controlId,
@@ -4597,17 +3874,17 @@ function ChoiceField({
4597
3874
  handle.values
4598
3875
  )
4599
3876
  }),
4600
- children: /* @__PURE__ */ jsx11("span", { "data-slot": "select-value", children: selectedChoice ? /* @__PURE__ */ jsx11(ChoiceOptionLabel, { choice: selectedChoice }) : /* @__PURE__ */ jsx11("span", { style: { color: theme.semantic.text.muted }, children: "Choose..." }) })
3877
+ children: /* @__PURE__ */ jsx8("span", { "data-slot": "select-value", children: selectedChoice ? /* @__PURE__ */ jsx8(ChoiceOptionLabel, { choice: selectedChoice }) : /* @__PURE__ */ jsx8("span", { style: { color: theme.semantic.text.muted }, children: "Choose..." }) })
4601
3878
  }
4602
3879
  ),
4603
- /* @__PURE__ */ jsx11(
3880
+ /* @__PURE__ */ jsx8(
4604
3881
  SelectContent,
4605
3882
  {
4606
3883
  style: {
4607
3884
  ...themeCssVars,
4608
3885
  fontFamily: theme.typography.fontFamily.body
4609
3886
  },
4610
- children: choices.map((choice) => /* @__PURE__ */ jsx11(
3887
+ children: choices.map((choice) => /* @__PURE__ */ jsx8(
4611
3888
  SelectItem,
4612
3889
  {
4613
3890
  value: choiceRenderKey(choice),
@@ -4634,7 +3911,7 @@ function ChoiceField({
4634
3911
  intent: "select"
4635
3912
  }).semanticEffects
4636
3913
  }),
4637
- children: /* @__PURE__ */ jsx11(ChoiceOptionLabel, { choice })
3914
+ children: /* @__PURE__ */ jsx8(ChoiceOptionLabel, { choice })
4638
3915
  },
4639
3916
  choiceRenderKey(choice)
4640
3917
  ))
@@ -4643,7 +3920,7 @@ function ChoiceField({
4643
3920
  ]
4644
3921
  }
4645
3922
  ),
4646
- /* @__PURE__ */ jsx11(ChoiceDescription, { choice: selectedChoice })
3923
+ /* @__PURE__ */ jsx8(ChoiceDescription, { choice: selectedChoice })
4647
3924
  ]
4648
3925
  }
4649
3926
  );
@@ -4670,10 +3947,10 @@ function ChoiceListField({
4670
3947
  setValue([...next]);
4671
3948
  };
4672
3949
  const meta = min || Number.isFinite(max) ? `Pick ${min ?? 0}${Number.isFinite(max) ? `-${max}` : "+"}` : void 0;
4673
- return /* @__PURE__ */ jsx11(
3950
+ return /* @__PURE__ */ jsx8(
4674
3951
  FieldFrame,
4675
3952
  {
4676
- label: /* @__PURE__ */ jsxs3(
3953
+ label: /* @__PURE__ */ jsxs2(
4677
3954
  "span",
4678
3955
  {
4679
3956
  style: {
@@ -4682,18 +3959,18 @@ function ChoiceListField({
4682
3959
  gap: theme.space[2]
4683
3960
  },
4684
3961
  children: [
4685
- /* @__PURE__ */ jsx11("span", { children: labelForInput(input) }),
4686
- meta ? /* @__PURE__ */ jsx11("span", { style: { color: theme.semantic.text.muted }, children: meta }) : null
3962
+ /* @__PURE__ */ jsx8("span", { children: labelForInput(input) }),
3963
+ meta ? /* @__PURE__ */ jsx8("span", { style: { color: theme.semantic.text.muted }, children: meta }) : null
4687
3964
  ]
4688
3965
  }
4689
3966
  ),
4690
3967
  errors,
4691
3968
  missing,
4692
- children: /* @__PURE__ */ jsx11("span", { style: { display: "flex", flexWrap: "wrap", gap: theme.space[1] }, children: (domain.choices ?? []).map((choice) => {
3969
+ children: /* @__PURE__ */ jsx8("span", { style: { display: "flex", flexWrap: "wrap", gap: theme.space[1] }, children: (domain.choices ?? []).map((choice) => {
4693
3970
  const value2 = choice.value;
4694
3971
  const checked = selected.has(value2);
4695
3972
  const isDisabled = disabled || choice.disabled || !checked && selected.size >= max;
4696
- return /* @__PURE__ */ jsx11(
3973
+ return /* @__PURE__ */ jsx8(
4697
3974
  ThemedButton,
4698
3975
  {
4699
3976
  type: "button",
@@ -4725,7 +4002,7 @@ function ChoiceListField({
4725
4002
  }),
4726
4003
  onClick: () => toggle(value2),
4727
4004
  className: "h-8 px-3 text-sm",
4728
- children: /* @__PURE__ */ jsx11(ChoiceOptionLabel, { choice })
4005
+ children: /* @__PURE__ */ jsx8(ChoiceOptionLabel, { choice })
4729
4006
  },
4730
4007
  value2
4731
4008
  );
@@ -4745,13 +4022,13 @@ function ResourceMapField({
4745
4022
  domain
4746
4023
  }) {
4747
4024
  const theme = useTheme();
4748
- const current = isRecord2(value) ? value : {};
4025
+ const current = isRecord(value) ? value : {};
4749
4026
  const update = (resourceId, delta, min, max) => {
4750
4027
  const previous = numberOrZero(current[resourceId]);
4751
4028
  const next = Math.max(min, Math.min(max, previous + delta));
4752
4029
  setValue({ ...current, [resourceId]: next });
4753
4030
  };
4754
- return /* @__PURE__ */ jsx11(FieldFrame, { label: labelForInput(input), errors, missing, children: /* @__PURE__ */ jsx11(
4031
+ return /* @__PURE__ */ jsx8(FieldFrame, { label: labelForInput(input), errors, missing, children: /* @__PURE__ */ jsx8(
4755
4032
  "span",
4756
4033
  {
4757
4034
  style: {
@@ -4763,7 +4040,7 @@ function ResourceMapField({
4763
4040
  const min = resource.min ?? 0;
4764
4041
  const max = resource.max ?? 0;
4765
4042
  const amount = numberOrZero(current[resource.resourceId]);
4766
- return /* @__PURE__ */ jsxs3(
4043
+ return /* @__PURE__ */ jsxs2(
4767
4044
  "span",
4768
4045
  {
4769
4046
  style: {
@@ -4776,7 +4053,7 @@ function ResourceMapField({
4776
4053
  background: theme.semantic.surface.inset
4777
4054
  },
4778
4055
  children: [
4779
- /* @__PURE__ */ jsxs3(
4056
+ /* @__PURE__ */ jsxs2(
4780
4057
  "span",
4781
4058
  {
4782
4059
  style: {
@@ -4786,12 +4063,12 @@ function ResourceMapField({
4786
4063
  gap: theme.space[1]
4787
4064
  },
4788
4065
  children: [
4789
- resource.icon ? /* @__PURE__ */ jsx11("span", { "aria-hidden": true, style: { fontSize: "1.1em" }, children: resource.icon }) : null,
4066
+ resource.icon ? /* @__PURE__ */ jsx8("span", { "aria-hidden": true, style: { fontSize: "1.1em" }, children: resource.icon }) : null,
4790
4067
  resource.label ?? humanize(input.key)
4791
4068
  ]
4792
4069
  }
4793
4070
  ),
4794
- /* @__PURE__ */ jsx11(
4071
+ /* @__PURE__ */ jsx8(
4795
4072
  StepperButton,
4796
4073
  {
4797
4074
  label: `Decrease ${resource.label ?? resource.resourceId}`,
@@ -4818,7 +4095,7 @@ function ResourceMapField({
4818
4095
  children: "-"
4819
4096
  }
4820
4097
  ),
4821
- /* @__PURE__ */ jsx11(
4098
+ /* @__PURE__ */ jsx8(
4822
4099
  "span",
4823
4100
  {
4824
4101
  style: {
@@ -4829,7 +4106,7 @@ function ResourceMapField({
4829
4106
  children: amount
4830
4107
  }
4831
4108
  ),
4832
- /* @__PURE__ */ jsx11(
4109
+ /* @__PURE__ */ jsx8(
4833
4110
  StepperButton,
4834
4111
  {
4835
4112
  label: `Increase ${resource.label ?? resource.resourceId}`,
@@ -4882,14 +4159,14 @@ function BoundedNumberField({
4882
4159
  const current = typeof value === "number" ? value : min;
4883
4160
  const controlId = useId();
4884
4161
  const update = (next) => setValue(Math.max(min, Math.min(max, next)));
4885
- return /* @__PURE__ */ jsx11(
4162
+ return /* @__PURE__ */ jsx8(
4886
4163
  FieldFrame,
4887
4164
  {
4888
4165
  label: labelForInput(input),
4889
4166
  controlId,
4890
4167
  errors,
4891
4168
  missing,
4892
- children: /* @__PURE__ */ jsxs3(
4169
+ children: /* @__PURE__ */ jsxs2(
4893
4170
  "span",
4894
4171
  {
4895
4172
  style: {
@@ -4898,7 +4175,7 @@ function BoundedNumberField({
4898
4175
  gap: theme.space[1]
4899
4176
  },
4900
4177
  children: [
4901
- /* @__PURE__ */ jsx11(
4178
+ /* @__PURE__ */ jsx8(
4902
4179
  StepperButton,
4903
4180
  {
4904
4181
  label: `Decrease ${input.key}`,
@@ -4923,7 +4200,7 @@ function BoundedNumberField({
4923
4200
  children: "-"
4924
4201
  }
4925
4202
  ),
4926
- /* @__PURE__ */ jsx11(
4203
+ /* @__PURE__ */ jsx8(
4927
4204
  Input,
4928
4205
  {
4929
4206
  id: controlId,
@@ -4953,7 +4230,7 @@ function BoundedNumberField({
4953
4230
  className: "h-9 w-[8ch] px-2 text-center text-sm md:text-sm"
4954
4231
  }
4955
4232
  ),
4956
- /* @__PURE__ */ jsx11(
4233
+ /* @__PURE__ */ jsx8(
4957
4234
  StepperButton,
4958
4235
  {
4959
4236
  label: `Increase ${input.key}`,
@@ -4992,7 +4269,7 @@ function TargetSummaryField({
4992
4269
  domain
4993
4270
  }) {
4994
4271
  const target = inputTargetKind(domain) ?? "target";
4995
- return /* @__PURE__ */ jsx11(FieldFrame, { label: labelForInput(input), errors, missing, children: /* @__PURE__ */ jsx11("span", { children: Array.isArray(value) ? value.length > 0 ? `${value.length} selected: ${value.join(", ")}` : `Select ${targetSelectionLabel(domain)}.` : typeof value === "string" ? value : `Select a ${target} on the board.` }) });
4272
+ return /* @__PURE__ */ jsx8(FieldFrame, { label: labelForInput(input), errors, missing, children: /* @__PURE__ */ jsx8("span", { children: Array.isArray(value) ? value.length > 0 ? `${value.length} selected: ${value.join(", ")}` : `Select ${targetSelectionLabel(domain)}.` : typeof value === "string" ? value : `Select a ${target} on the board.` }) });
4996
4273
  }
4997
4274
  function targetSelectionLabel(domain) {
4998
4275
  const target = inputTargetKind(domain) ?? "target";
@@ -5011,7 +4288,7 @@ function StepperButton({
5011
4288
  onClick,
5012
4289
  children
5013
4290
  }) {
5014
- return /* @__PURE__ */ jsx11(
4291
+ return /* @__PURE__ */ jsx8(
5015
4292
  ThemedButton,
5016
4293
  {
5017
4294
  type: "button",
@@ -5038,7 +4315,7 @@ function labelForInput(input) {
5038
4315
  function humanize(key) {
5039
4316
  return key.replace(/Id$/, "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
5040
4317
  }
5041
- function isRecord2(value) {
4318
+ function isRecord(value) {
5042
4319
  return typeof value === "object" && value !== null && !Array.isArray(value);
5043
4320
  }
5044
4321
  function numberOrZero(value) {
@@ -5047,15 +4324,15 @@ function numberOrZero(value) {
5047
4324
 
5048
4325
  // src/runtime/components/interaction-form/InteractionForm.tsx
5049
4326
  import {
5050
- useEffect as useEffect5,
4327
+ useEffect as useEffect3,
5051
4328
  useId as useId2,
5052
- useMemo as useMemo14,
5053
- useState as useState3
4329
+ useMemo as useMemo10,
4330
+ useState
5054
4331
  } from "react";
5055
4332
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
5056
4333
 
5057
4334
  // src/runtime/components/interaction-form/input-slot.tsx
5058
- import { Fragment as Fragment8, jsx as jsx12 } from "react/jsx-runtime";
4335
+ import { Fragment as Fragment7, jsx as jsx9 } from "react/jsx-runtime";
5059
4336
  function createInteractionInputSlot({
5060
4337
  descriptor,
5061
4338
  input,
@@ -5103,7 +4380,7 @@ function createInteractionInputSlot({
5103
4380
  intent: selection?.mode === "many" ? "toggle" : "select"
5104
4381
  }).semanticEffects
5105
4382
  });
5106
- return /* @__PURE__ */ jsx12(
4383
+ return /* @__PURE__ */ jsx9(
5107
4384
  "button",
5108
4385
  {
5109
4386
  type: "button",
@@ -5129,7 +4406,7 @@ function createInteractionInputSlot({
5129
4406
  );
5130
4407
  };
5131
4408
  return {
5132
- Field: () => /* @__PURE__ */ jsx12(
4409
+ Field: () => /* @__PURE__ */ jsx9(
5133
4410
  DefaultInteractionField,
5134
4411
  {
5135
4412
  descriptor,
@@ -5167,7 +4444,7 @@ function createInteractionInputSlot({
5167
4444
  intent: "select"
5168
4445
  }).semanticEffects : void 0
5169
4446
  });
5170
- return /* @__PURE__ */ jsx12(
4447
+ return /* @__PURE__ */ jsx9(
5171
4448
  "button",
5172
4449
  {
5173
4450
  type: "button",
@@ -5190,24 +4467,24 @@ function createInteractionInputSlot({
5190
4467
  Cards: ({ children }) => {
5191
4468
  const domain = resolvedInput.domain;
5192
4469
  const targets = isResolvedTargetDomain(domain) ? domain.eligibleTargets : [];
5193
- return /* @__PURE__ */ jsx12(Fragment8, { children: targets.map((id) => children({ id })) });
4470
+ return /* @__PURE__ */ jsx9(Fragment7, { children: targets.map((id) => children({ id })) });
5194
4471
  },
5195
4472
  Options: ({ children }) => {
5196
4473
  const domain = resolvedInput.domain;
5197
4474
  const choices = domain.type === "choice" || domain.type === "choiceList" ? domain.choices ?? [] : [];
5198
- return /* @__PURE__ */ jsx12(Fragment8, { children: choices.map((choice) => children(choice)) });
4475
+ return /* @__PURE__ */ jsx9(Fragment7, { children: choices.map((choice) => children(choice)) });
5199
4476
  },
5200
- Value: ({ children }) => /* @__PURE__ */ jsx12(Fragment8, { children: children(value) }),
5201
- Label: ({ children }) => /* @__PURE__ */ jsx12(Fragment8, { children: children ?? labelForInput(resolvedInput) }),
4477
+ Value: ({ children }) => /* @__PURE__ */ jsx9(Fragment7, { children: children(value) }),
4478
+ Label: ({ children }) => /* @__PURE__ */ jsx9(Fragment7, { children: children ?? labelForInput(resolvedInput) }),
5202
4479
  Message: ({ children }) => {
5203
4480
  const message = children ?? errors[0] ?? (missing ? "Required" : null);
5204
- return message ? /* @__PURE__ */ jsx12("span", { role: "alert", "data-dreamboard-interaction-message-slot": "", children: message }) : null;
4481
+ return message ? /* @__PURE__ */ jsx9("span", { role: "alert", "data-dreamboard-interaction-message-slot": "", children: message }) : null;
5205
4482
  }
5206
4483
  };
5207
4484
  }
5208
4485
 
5209
4486
  // src/runtime/components/interaction-form/InteractionForm.tsx
5210
- import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs4 } from "react/jsx-runtime";
4487
+ import { Fragment as Fragment8, jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
5211
4488
  function InteractionForm({
5212
4489
  descriptor,
5213
4490
  handle,
@@ -5231,14 +4508,14 @@ function InteractionForm({
5231
4508
  const fallbackLabel = interactionLabel(descriptor);
5232
4509
  const formId = useId2();
5233
4510
  useChromeSuppression(formId, true);
5234
- const [pending, setPending] = useState3(false);
5235
- const [validation, setValidation] = useState3(
4511
+ const [pending, setPending] = useState(false);
4512
+ const [validation, setValidation] = useState(
5236
4513
  null
5237
4514
  );
5238
- const [formError, setFormError] = useState3(null);
5239
- const [accordionOpen, setAccordionOpen] = useState3(defaultOpen);
5240
- const hidden = useMemo14(() => new Set(hiddenFields ?? []), [hiddenFields]);
5241
- const visibleInputs = useMemo14(() => {
4515
+ const [formError, setFormError] = useState(null);
4516
+ const [accordionOpen, setAccordionOpen] = useState(defaultOpen);
4517
+ const hidden = useMemo10(() => new Set(hiddenFields ?? []), [hiddenFields]);
4518
+ const visibleInputs = useMemo10(() => {
5242
4519
  if (inputs) {
5243
4520
  const rendered = new Set(Object.keys(inputs));
5244
4521
  return resolveInteractionInputs(
@@ -5302,7 +4579,7 @@ function InteractionForm({
5302
4579
  actuatorId: "submit",
5303
4580
  semanticEffects: submitMetadata.semanticEffects
5304
4581
  });
5305
- useEffect5(() => {
4582
+ useEffect3(() => {
5306
4583
  setAccordionOpen(defaultOpen);
5307
4584
  }, [defaultOpen, descriptor.interactionId]);
5308
4585
  const containerStyle = {
@@ -5340,8 +4617,8 @@ function InteractionForm({
5340
4617
  setPending(false);
5341
4618
  }
5342
4619
  };
5343
- const header = /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [
5344
- /* @__PURE__ */ jsx13(
4620
+ const header = /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [
4621
+ /* @__PURE__ */ jsx10(
5345
4622
  "strong",
5346
4623
  {
5347
4624
  style: {
@@ -5352,7 +4629,7 @@ function InteractionForm({
5352
4629
  children: title ?? fallbackLabel
5353
4630
  }
5354
4631
  ),
5355
- description ? /* @__PURE__ */ jsx13(
4632
+ description ? /* @__PURE__ */ jsx10(
5356
4633
  "span",
5357
4634
  {
5358
4635
  style: {
@@ -5363,7 +4640,7 @@ function InteractionForm({
5363
4640
  }
5364
4641
  ) : null
5365
4642
  ] });
5366
- const fieldsContent = visibleInputs.length > 0 ? /* @__PURE__ */ jsx13(
4643
+ const fieldsContent = visibleInputs.length > 0 ? /* @__PURE__ */ jsx10(
5367
4644
  "div",
5368
4645
  {
5369
4646
  style: {
@@ -5374,7 +4651,7 @@ function InteractionForm({
5374
4651
  children: visibleInputs.map((input) => {
5375
4652
  const key = input.key;
5376
4653
  const inputRenderer = inputs?.[key];
5377
- return /* @__PURE__ */ jsx13(
4654
+ return /* @__PURE__ */ jsx10(
5378
4655
  InteractionField,
5379
4656
  {
5380
4657
  descriptor,
@@ -5404,7 +4681,7 @@ function InteractionForm({
5404
4681
  `InteractionForm '${descriptor.interactionKey}' has required inputs that cannot be rendered by the default form. Provide renderFields, select on a surface, or use a default-renderable input domain.`
5405
4682
  );
5406
4683
  }
5407
- const formErrorContent = formErrors.length > 0 ? /* @__PURE__ */ jsx13(
4684
+ const formErrorContent = formErrors.length > 0 ? /* @__PURE__ */ jsx10(
5408
4685
  "div",
5409
4686
  {
5410
4687
  role: "alert",
@@ -5415,10 +4692,10 @@ function InteractionForm({
5415
4692
  color: theme.semantic.intent.danger.solid,
5416
4693
  fontSize: theme.typography.fontSize.sm
5417
4694
  },
5418
- children: formErrors.map((error) => /* @__PURE__ */ jsx13("span", { children: error }, error))
4695
+ children: formErrors.map((error) => /* @__PURE__ */ jsx10("span", { children: error }, error))
5419
4696
  }
5420
4697
  ) : null;
5421
- const actions = /* @__PURE__ */ jsxs4(
4698
+ const actions = /* @__PURE__ */ jsxs3(
5422
4699
  "div",
5423
4700
  {
5424
4701
  style: {
@@ -5427,7 +4704,7 @@ function InteractionForm({
5427
4704
  justifyContent: "flex-end"
5428
4705
  },
5429
4706
  children: [
5430
- onCancel ? /* @__PURE__ */ jsx13(
4707
+ onCancel ? /* @__PURE__ */ jsx10(
5431
4708
  ThemedButton,
5432
4709
  {
5433
4710
  type: "button",
@@ -5441,7 +4718,7 @@ function InteractionForm({
5441
4718
  ) : null,
5442
4719
  renderSubmit ? renderSubmit(
5443
4720
  {
5444
- Button: ({ children, ...buttonProps }) => /* @__PURE__ */ jsx13(
4721
+ Button: ({ children, ...buttonProps }) => /* @__PURE__ */ jsx10(
5445
4722
  ThemedButton,
5446
4723
  {
5447
4724
  type: "submit",
@@ -5456,7 +4733,7 @@ function InteractionForm({
5456
4733
  )
5457
4734
  },
5458
4735
  descriptor
5459
- ) : /* @__PURE__ */ jsx13(
4736
+ ) : /* @__PURE__ */ jsx10(
5460
4737
  ThemedButton,
5461
4738
  {
5462
4739
  type: "submit",
@@ -5471,12 +4748,12 @@ function InteractionForm({
5471
4748
  ]
5472
4749
  }
5473
4750
  );
5474
- const body = /* @__PURE__ */ jsxs4(Fragment9, { children: [
4751
+ const body = /* @__PURE__ */ jsxs3(Fragment8, { children: [
5475
4752
  fieldsContent,
5476
4753
  formErrorContent,
5477
4754
  actions
5478
4755
  ] });
5479
- return /* @__PURE__ */ jsx13(
4756
+ return /* @__PURE__ */ jsx10(
5480
4757
  "form",
5481
4758
  {
5482
4759
  "data-interaction-form": true,
@@ -5484,15 +4761,15 @@ function InteractionForm({
5484
4761
  onSubmit: (event) => void submit(event),
5485
4762
  style: containerStyle,
5486
4763
  ...rootBrowserAttributes,
5487
- children: useAccordion ? /* @__PURE__ */ jsx13(
4764
+ children: useAccordion ? /* @__PURE__ */ jsx10(
5488
4765
  AccordionPrimitive.Root,
5489
4766
  {
5490
4767
  type: "single",
5491
4768
  collapsible: true,
5492
4769
  value: accordionOpen ? "fields" : void 0,
5493
4770
  onValueChange: (value) => setAccordionOpen(value === "fields"),
5494
- children: /* @__PURE__ */ jsxs4(AccordionPrimitive.Item, { value: "fields", children: [
5495
- /* @__PURE__ */ jsx13(AccordionPrimitive.Header, { style: { margin: 0 }, children: /* @__PURE__ */ jsxs4(
4771
+ children: /* @__PURE__ */ jsxs3(AccordionPrimitive.Item, { value: "fields", children: [
4772
+ /* @__PURE__ */ jsx10(AccordionPrimitive.Header, { style: { margin: 0 }, children: /* @__PURE__ */ jsxs3(
5496
4773
  AccordionPrimitive.Trigger,
5497
4774
  {
5498
4775
  ...armBrowserAttributes,
@@ -5513,12 +4790,12 @@ function InteractionForm({
5513
4790
  width: "100%"
5514
4791
  },
5515
4792
  children: [
5516
- /* @__PURE__ */ jsx13("span", { children: title ?? fallbackLabel }),
5517
- /* @__PURE__ */ jsx13("span", { "aria-hidden": true, children: accordionOpen ? "\u2212" : "+" })
4793
+ /* @__PURE__ */ jsx10("span", { children: title ?? fallbackLabel }),
4794
+ /* @__PURE__ */ jsx10("span", { "aria-hidden": true, children: accordionOpen ? "\u2212" : "+" })
5518
4795
  ]
5519
4796
  }
5520
4797
  ) }),
5521
- /* @__PURE__ */ jsx13(AccordionPrimitive.Content, { children: /* @__PURE__ */ jsxs4(
4798
+ /* @__PURE__ */ jsx10(AccordionPrimitive.Content, { children: /* @__PURE__ */ jsxs3(
5522
4799
  "div",
5523
4800
  {
5524
4801
  style: {
@@ -5528,7 +4805,7 @@ function InteractionForm({
5528
4805
  marginTop: theme.space[2]
5529
4806
  },
5530
4807
  children: [
5531
- description ? /* @__PURE__ */ jsx13(
4808
+ description ? /* @__PURE__ */ jsx10(
5532
4809
  "span",
5533
4810
  {
5534
4811
  style: {
@@ -5544,7 +4821,7 @@ function InteractionForm({
5544
4821
  ) })
5545
4822
  ] })
5546
4823
  }
5547
- ) : /* @__PURE__ */ jsxs4(Fragment9, { children: [
4824
+ ) : /* @__PURE__ */ jsxs3(Fragment8, { children: [
5548
4825
  header,
5549
4826
  body
5550
4827
  ] })
@@ -5553,7 +4830,7 @@ function InteractionForm({
5553
4830
  }
5554
4831
 
5555
4832
  // src/runtime/primitives/interaction/form.tsx
5556
- import { jsx as jsx14 } from "react/jsx-runtime";
4833
+ import { jsx as jsx11 } from "react/jsx-runtime";
5557
4834
  function castInteractionHandle(handle) {
5558
4835
  return handle;
5559
4836
  }
@@ -5565,7 +4842,7 @@ function BoundInteractionForm({
5565
4842
  handle,
5566
4843
  ...props
5567
4844
  }) {
5568
- return /* @__PURE__ */ jsx14(
4845
+ return /* @__PURE__ */ jsx11(
5569
4846
  InteractionForm,
5570
4847
  {
5571
4848
  descriptor,
@@ -5577,7 +4854,7 @@ function BoundInteractionForm({
5577
4854
  function InteractionFormPrimitive(props) {
5578
4855
  const { descriptor, handle } = useInteractionPrimitiveContext();
5579
4856
  if (!descriptor || !handle) return null;
5580
- return /* @__PURE__ */ jsx14(
4857
+ return /* @__PURE__ */ jsx11(
5581
4858
  BoundInteractionForm,
5582
4859
  {
5583
4860
  descriptor,
@@ -5589,7 +4866,7 @@ function InteractionFormPrimitive(props) {
5589
4866
  function InteractionFieldPrimitive({ input, ...props }) {
5590
4867
  const { descriptor, handle } = useInteractionPrimitiveContext();
5591
4868
  if (!descriptor || !handle) return null;
5592
- return /* @__PURE__ */ jsx14(
4869
+ return /* @__PURE__ */ jsx11(
5593
4870
  InteractionField,
5594
4871
  {
5595
4872
  descriptor,
@@ -5601,12 +4878,12 @@ function InteractionFieldPrimitive({ input, ...props }) {
5601
4878
  }
5602
4879
 
5603
4880
  // src/runtime/primitives/interaction/state.tsx
5604
- import { Fragment as Fragment10, jsx as jsx15 } from "react/jsx-runtime";
4881
+ import { Fragment as Fragment9, jsx as jsx12 } from "react/jsx-runtime";
5605
4882
  function InteractionState({ children, unavailable }) {
5606
4883
  const { interaction, descriptor, handle } = useInteractionPrimitiveContext();
5607
4884
  const store = useInteractionUiStore();
5608
4885
  if (!descriptor || !handle) {
5609
- return /* @__PURE__ */ jsx15(Fragment10, { children: unavailable });
4886
+ return /* @__PURE__ */ jsx12(Fragment9, { children: unavailable });
5610
4887
  }
5611
4888
  const typedHandle = castInteractionHandle(handle);
5612
4889
  const liveDraft = castInteractionDraft(
@@ -5614,7 +4891,7 @@ function InteractionState({ children, unavailable }) {
5614
4891
  );
5615
4892
  const inputKeys = descriptor.inputs.map((input) => input.key);
5616
4893
  const readiness = getInteractionDraftReadiness(descriptor, liveDraft);
5617
- return /* @__PURE__ */ jsx15(Fragment10, { children: children({
4894
+ return /* @__PURE__ */ jsx12(Fragment9, { children: children({
5618
4895
  interaction,
5619
4896
  descriptor,
5620
4897
  handle: typedHandle,
@@ -5633,25 +4910,25 @@ function InteractionState({ children, unavailable }) {
5633
4910
  }
5634
4911
 
5635
4912
  // src/runtime/primitives/interaction/routes.tsx
5636
- import { Fragment as Fragment11, jsx as jsx16 } from "react/jsx-runtime";
4913
+ import { Fragment as Fragment10, jsx as jsx13 } from "react/jsx-runtime";
5637
4914
  function InteractionSwitch({
5638
4915
  interaction,
5639
4916
  routes,
5640
4917
  fallback = null
5641
4918
  }) {
5642
4919
  const pendingInteractionKey = usePendingInteractionKey();
5643
- const descriptors = usePluginState(
5644
- (state) => state.gameplay.availableInteractions
4920
+ const descriptors = useAuthoredPluginGameplayFrameSelector(
4921
+ (frame) => frame.availableInteractions
5645
4922
  );
5646
4923
  const routedInteraction = interaction ?? pendingInteractionKey;
5647
4924
  const descriptor = routedInteraction ? descriptors.find(
5648
4925
  (candidate) => candidate.interactionKey === routedInteraction
5649
4926
  ) : void 0;
5650
- if (!descriptor) return /* @__PURE__ */ jsx16(Fragment11, { children: fallback });
4927
+ if (!descriptor) return /* @__PURE__ */ jsx13(Fragment10, { children: fallback });
5651
4928
  const route = routes[descriptor.interactionKey] ?? null;
5652
- if (!route) return /* @__PURE__ */ jsx16(Fragment11, { children: fallback });
4929
+ if (!route) return /* @__PURE__ */ jsx13(Fragment10, { children: fallback });
5653
4930
  const typedInteraction = descriptor.interactionKey;
5654
- return /* @__PURE__ */ jsx16(InteractionRoot, { interaction: typedInteraction, children: route({
4931
+ return /* @__PURE__ */ jsx13(InteractionRoot, { interaction: typedInteraction, children: route({
5655
4932
  interaction: typedInteraction,
5656
4933
  descriptor
5657
4934
  }) });
@@ -5672,10 +4949,10 @@ function InteractionRoutes({
5672
4949
  includeUnavailable = false
5673
4950
  }) {
5674
4951
  const runtime = useRuntimeContext();
5675
- const descriptors = usePluginState(
5676
- (state) => state.gameplay.availableInteractions
4952
+ const descriptors = useAuthoredPluginGameplayFrameSelector(
4953
+ (frame) => frame.availableInteractions
5677
4954
  );
5678
- if (descriptors.length === 0) return /* @__PURE__ */ jsx16(Fragment11, { children: fallback });
4955
+ if (descriptors.length === 0) return /* @__PURE__ */ jsx13(Fragment10, { children: fallback });
5679
4956
  const routedDescriptors = descriptors.filter(
5680
4957
  (descriptor) => includeUnavailable || isInteractionAvailable(descriptor)
5681
4958
  ).map((descriptor) => {
@@ -5699,39 +4976,39 @@ function InteractionRoutes({
5699
4976
  }
5700
4977
  return descriptor;
5701
4978
  });
5702
- if (routedDescriptors.length === 0) return /* @__PURE__ */ jsx16(Fragment11, { children: fallback });
4979
+ if (routedDescriptors.length === 0) return /* @__PURE__ */ jsx13(Fragment10, { children: fallback });
5703
4980
  return null;
5704
4981
  }
5705
4982
 
5706
4983
  // src/runtime/primitives/interaction/dialog.tsx
5707
- import { useEffect as useEffect6, useMemo as useMemo16, useRef as useRef3 } from "react";
4984
+ import { useEffect as useEffect4, useMemo as useMemo12, useRef as useRef3 } from "react";
5708
4985
 
5709
4986
  // src/ui/primitives/dialog-lifecycle.ts
5710
- import { useCallback as useCallback6, useMemo as useMemo15, useState as useState4 } from "react";
4987
+ import { useCallback as useCallback5, useMemo as useMemo11, useState as useState2 } from "react";
5711
4988
  function useDialogLifecycle({
5712
4989
  defaultOpen = true,
5713
4990
  onStateChange
5714
4991
  }) {
5715
- const [state, setState] = useState4(
4992
+ const [state, setState] = useState2(
5716
4993
  defaultOpen ? "open" : "minimized"
5717
4994
  );
5718
- const updateState = useCallback6(
4995
+ const updateState = useCallback5(
5719
4996
  (nextState) => {
5720
4997
  setState(nextState);
5721
4998
  onStateChange?.(nextState);
5722
4999
  },
5723
5000
  [onStateChange]
5724
5001
  );
5725
- const restore = useCallback6(() => updateState("open"), [updateState]);
5726
- const minimize = useCallback6(() => updateState("minimized"), [updateState]);
5727
- const dismiss = useCallback6(() => updateState("dismissed"), [updateState]);
5728
- const setOpen = useCallback6(
5002
+ const restore = useCallback5(() => updateState("open"), [updateState]);
5003
+ const minimize = useCallback5(() => updateState("minimized"), [updateState]);
5004
+ const dismiss = useCallback5(() => updateState("dismissed"), [updateState]);
5005
+ const setOpen = useCallback5(
5729
5006
  (open) => {
5730
5007
  updateState(open ? "open" : "minimized");
5731
5008
  },
5732
5009
  [updateState]
5733
5010
  );
5734
- return useMemo15(
5011
+ return useMemo11(
5735
5012
  () => ({
5736
5013
  state,
5737
5014
  open: state === "open",
@@ -5747,7 +5024,7 @@ function useDialogLifecycle({
5747
5024
  }
5748
5025
 
5749
5026
  // src/runtime/primitives/interaction/dialog.tsx
5750
- import { Fragment as Fragment12, jsx as jsx17 } from "react/jsx-runtime";
5027
+ import { Fragment as Fragment11, jsx as jsx14 } from "react/jsx-runtime";
5751
5028
  function InteractionDialog({
5752
5029
  defaultOpen = false,
5753
5030
  onStateChange,
@@ -5758,7 +5035,7 @@ function InteractionDialog({
5758
5035
  const pendingInteractionRevision = usePendingInteractionRevision();
5759
5036
  const lifecycle = useDialogLifecycle({ defaultOpen, onStateChange });
5760
5037
  const restoredRevisionRef = useRef3(null);
5761
- useEffect6(() => {
5038
+ useEffect4(() => {
5762
5039
  if (pendingInteractionKey === interaction && restoredRevisionRef.current !== pendingInteractionRevision) {
5763
5040
  restoredRevisionRef.current = pendingInteractionRevision;
5764
5041
  lifecycle.restore();
@@ -5769,14 +5046,14 @@ function InteractionDialog({
5769
5046
  pendingInteractionKey,
5770
5047
  pendingInteractionRevision
5771
5048
  ]);
5772
- const renderState = useMemo16(
5049
+ const renderState = useMemo12(
5773
5050
  () => ({
5774
5051
  interaction,
5775
5052
  ...lifecycle
5776
5053
  }),
5777
5054
  [interaction, lifecycle]
5778
5055
  );
5779
- return /* @__PURE__ */ jsx17(Fragment12, { children: children(renderState) });
5056
+ return /* @__PURE__ */ jsx14(Fragment11, { children: children(renderState) });
5780
5057
  }
5781
5058
 
5782
5059
  // src/runtime/primitives/interaction/controls.tsx
@@ -5967,7 +5244,7 @@ function InteractionValidationMessage({
5967
5244
  }
5968
5245
 
5969
5246
  // src/runtime/primitives/interaction/card-input.tsx
5970
- import { useCallback as useCallback7 } from "react";
5247
+ import { useCallback as useCallback6 } from "react";
5971
5248
  function InteractionCardInput({
5972
5249
  input,
5973
5250
  unsafeCardId,
@@ -5984,12 +5261,12 @@ function InteractionCardInput({
5984
5261
  const zoneContext = useOptionalZonePrimitiveContext();
5985
5262
  const cardId = zoneCard?.cardId ?? unsafeCardId;
5986
5263
  const validationZone = zoneCard?.zone ?? zoneContext?.zone;
5987
- const zoneSnapshot = usePluginState(
5988
- (state) => validationZone ? state.gameplay.zones[validationZone] : void 0
5264
+ const zoneSnapshot = useAuthoredPluginGameplayFrameSelector(
5265
+ (frame) => validationZone ? frame.zones[validationZone] : void 0
5989
5266
  );
5990
- const cardDescriptor = usePluginState((state) => {
5267
+ const cardDescriptor = useAuthoredPluginGameplayFrameSelector((frame) => {
5991
5268
  if (!cardId || !validationZone) return void 0;
5992
- return state.gameplay.zones[validationZone]?.playableByCardId[cardId]?.find(
5269
+ return frame.zones[validationZone]?.playableByCardId[cardId]?.find(
5993
5270
  (candidate) => candidate.interactionKey === descriptor?.interactionKey && candidate.inputs.some((candidateInput) => candidateInput.key === input)
5994
5271
  );
5995
5272
  });
@@ -6025,7 +5302,7 @@ function InteractionCardInput({
6025
5302
  const fieldErrors = validation?.fieldErrors[input] ?? [];
6026
5303
  const isInvalid = fieldErrors.length > 0;
6027
5304
  const isDisabled = disabled === true || !descriptorAvailable || !cardId || !isTargetValid || !isCardAvailable || !isSelectable || !handle;
6028
- const activateCardInput = useCallback7(() => {
5305
+ const activateCardInput = useCallback6(() => {
6029
5306
  if (isDisabled || !descriptor || !cardId || !handle || !inputDescriptor) {
6030
5307
  return;
6031
5308
  }
@@ -6192,7 +5469,7 @@ var Interaction = {
6192
5469
  };
6193
5470
 
6194
5471
  // src/runtime/primitives/phase.tsx
6195
- import { Fragment as Fragment13, jsx as jsx18 } from "react/jsx-runtime";
5472
+ import { Fragment as Fragment12, jsx as jsx15 } from "react/jsx-runtime";
6196
5473
  function hasRoute(routes, phase) {
6197
5474
  return Object.prototype.hasOwnProperty.call(routes, phase);
6198
5475
  }
@@ -6203,11 +5480,13 @@ function PhaseSwitch({
6203
5480
  routes,
6204
5481
  fallback
6205
5482
  }) {
6206
- const phase = usePluginState((state) => state.gameplay.currentPhase);
5483
+ const phase = useAuthoredPluginGameplayFrameSelector(
5484
+ (frame) => frame.flow.currentPhase
5485
+ );
6207
5486
  if (phase && hasRoute(routes, phase)) {
6208
- return /* @__PURE__ */ jsx18(Fragment13, { children: routes[phase]() });
5487
+ return /* @__PURE__ */ jsx15(Fragment12, { children: routes[phase]() });
6209
5488
  }
6210
- return /* @__PURE__ */ jsx18(Fragment13, { children: renderFallback(fallback, phase) });
5489
+ return /* @__PURE__ */ jsx15(Fragment12, { children: renderFallback(fallback, phase) });
6211
5490
  }
6212
5491
  var Phase = {
6213
5492
  Switch: PhaseSwitch
@@ -6215,17 +5494,17 @@ var Phase = {
6215
5494
 
6216
5495
  // src/runtime/primitives/player-roster.tsx
6217
5496
  import {
6218
- createContext as createContext10,
6219
- Fragment as Fragment14,
6220
- useContext as useContext10,
6221
- useMemo as useMemo17
5497
+ createContext as createContext6,
5498
+ Fragment as Fragment13,
5499
+ useContext as useContext6,
5500
+ useMemo as useMemo13
6222
5501
  } from "react";
6223
- import { Fragment as Fragment15, jsx as jsx19, jsxs as jsxs5 } from "react/jsx-runtime";
6224
- var PlayerRosterContext = createContext10(
5502
+ import { Fragment as Fragment14, jsx as jsx16, jsxs as jsxs4 } from "react/jsx-runtime";
5503
+ var PlayerRosterContext = createContext6(
6225
5504
  null
6226
5505
  );
6227
5506
  function usePlayerRosterContext() {
6228
- const value = useContext10(PlayerRosterContext);
5507
+ const value = useContext6(PlayerRosterContext);
6229
5508
  if (!value) {
6230
5509
  throw new Error(
6231
5510
  "PlayerRoster primitives must be rendered inside <PlayerRoster.Root>."
@@ -6250,8 +5529,8 @@ function PlayerRosterRoot({
6250
5529
  const playerInfo = usePlayerInfo();
6251
5530
  const activePlayers = useActivePlayers();
6252
5531
  const turnOrder = usePlayerTurnOrder();
6253
- const { controllingPlayerId, controllablePlayerIds } = usePluginSession();
6254
- const players = useMemo17(() => {
5532
+ const { controllingPlayerId } = usePluginSession();
5533
+ const players = useMemo13(() => {
6255
5534
  const orderedPlayerIds = order === "self-first" && controllingPlayerId ? [
6256
5535
  ...turnOrder.filter((pid) => pid === controllingPlayerId),
6257
5536
  ...turnOrder.filter((pid) => pid !== controllingPlayerId)
@@ -6259,7 +5538,6 @@ function PlayerRosterRoot({
6259
5538
  return orderedPlayerIds.map((playerId, index) => {
6260
5539
  const player = playerInfo.get(playerId);
6261
5540
  const isCurrentPlayer = playerId === controllingPlayerId;
6262
- const isControllable = controllablePlayerIds.includes(playerId);
6263
5541
  const resolvedScoreLabel = typeof scoreLabel === "function" ? scoreLabel(playerId) : scoreLabel;
6264
5542
  return {
6265
5543
  playerId,
@@ -6268,8 +5546,6 @@ function PlayerRosterRoot({
6268
5546
  index,
6269
5547
  isActive: activePlayers.includes(playerId),
6270
5548
  isCurrentPlayer,
6271
- isControllable,
6272
- canSwitchToPlayer: controllablePlayerIds.length > 1 && isControllable && !isCurrentPlayer,
6273
5549
  score: score?.(playerId),
6274
5550
  scoreLabel: resolvedScoreLabel,
6275
5551
  badges: projectBadges(badges, playerId),
@@ -6283,7 +5559,6 @@ function PlayerRosterRoot({
6283
5559
  }, [
6284
5560
  activePlayers,
6285
5561
  badges,
6286
- controllablePlayerIds,
6287
5562
  controllingPlayerId,
6288
5563
  include,
6289
5564
  metadata,
@@ -6293,11 +5568,11 @@ function PlayerRosterRoot({
6293
5568
  scoreLabel,
6294
5569
  turnOrder
6295
5570
  ]);
6296
- const value = useMemo17(
5571
+ const value = useMemo13(
6297
5572
  () => ({ players }),
6298
5573
  [players]
6299
5574
  );
6300
- return /* @__PURE__ */ jsx19(PlayerRosterContext.Provider, { value, children });
5575
+ return /* @__PURE__ */ jsx16(PlayerRosterContext.Provider, { value, children });
6301
5576
  }
6302
5577
  function PlayerRosterList({
6303
5578
  children,
@@ -6307,39 +5582,13 @@ function PlayerRosterList({
6307
5582
  return renderPrimitive("div", {
6308
5583
  ...props,
6309
5584
  "data-dreamboard-player-roster-list": "",
6310
- children: players.map((player) => /* @__PURE__ */ jsx19(Fragment14, { children: children ? children(player) : /* @__PURE__ */ jsx19(PlayerRosterName, { player }) }, player.playerId))
5585
+ children: players.map((player) => /* @__PURE__ */ jsx16(Fragment13, { children: children ? children(player) : /* @__PURE__ */ jsx16(PlayerRosterName, { player }) }, player.playerId))
6311
5586
  });
6312
5587
  }
6313
5588
  function PlayerRosterEmpty({ children }) {
6314
5589
  const { players } = usePlayerRosterContext();
6315
5590
  if (players.length > 0) return null;
6316
- return /* @__PURE__ */ jsx19(Fragment15, { children });
6317
- }
6318
- function PlayerRosterSwitchButton({
6319
- player,
6320
- disabled,
6321
- onClick,
6322
- ...props
6323
- }) {
6324
- const { switchPlayer } = usePluginActions();
6325
- const isDisabled = disabled === true || !player.canSwitchToPlayer;
6326
- return renderPrimitive("button", {
6327
- type: "button",
6328
- ...props,
6329
- disabled: isDisabled,
6330
- "aria-current": player.isCurrentPlayer ? "true" : void 0,
6331
- "aria-disabled": isDisabled,
6332
- "data-dreamboard-player-roster-switch": "",
6333
- "data-player-id": player.playerId,
6334
- "data-active": player.isActive || void 0,
6335
- "data-current": player.isCurrentPlayer || void 0,
6336
- "data-controllable": player.isControllable || void 0,
6337
- "data-switchable": player.canSwitchToPlayer || void 0,
6338
- "data-disabled": isDisabled || void 0,
6339
- onClick: composeEventHandlers(onClick, () => {
6340
- if (!isDisabled) switchPlayer(player.playerId);
6341
- })
6342
- });
5591
+ return /* @__PURE__ */ jsx16(Fragment14, { children });
6343
5592
  }
6344
5593
  function PlayerRosterName({
6345
5594
  player,
@@ -6374,7 +5623,7 @@ function PlayerRosterBadges({
6374
5623
  return renderPrimitive("span", {
6375
5624
  ...props,
6376
5625
  "data-dreamboard-player-roster-badges": "",
6377
- children: children ?? player.badges.map((badge) => /* @__PURE__ */ jsxs5(
5626
+ children: children ?? player.badges.map((badge) => /* @__PURE__ */ jsxs4(
6378
5627
  "span",
6379
5628
  {
6380
5629
  "data-dreamboard-player-roster-badge": "",
@@ -6393,7 +5642,6 @@ var PlayerRoster = {
6393
5642
  Root: PlayerRosterRoot,
6394
5643
  List: PlayerRosterList,
6395
5644
  Empty: PlayerRosterEmpty,
6396
- SwitchButton: PlayerRosterSwitchButton,
6397
5645
  Name: PlayerRosterName,
6398
5646
  Score: PlayerRosterScore,
6399
5647
  Badges: PlayerRosterBadges
@@ -6401,16 +5649,16 @@ var PlayerRoster = {
6401
5649
 
6402
5650
  // src/runtime/primitives/prompt.tsx
6403
5651
  import {
6404
- Fragment as Fragment16,
6405
- createContext as createContext11,
6406
- useContext as useContext11,
6407
- useMemo as useMemo18
5652
+ Fragment as Fragment15,
5653
+ createContext as createContext7,
5654
+ useContext as useContext7,
5655
+ useMemo as useMemo14
6408
5656
  } from "react";
6409
5657
 
6410
5658
  // src/runtime/hooks/useSeatInbox.ts
6411
5659
  function useSeatInbox() {
6412
- const interactions = usePluginState(
6413
- (s) => s.gameplay.availableInteractions ?? []
5660
+ const interactions = usePluginGameplayFrameSelector(
5661
+ (frame) => frame.availableInteractions ?? []
6414
5662
  );
6415
5663
  const bySurface = {};
6416
5664
  const prompts = [];
@@ -6441,21 +5689,21 @@ function bucketForDescriptor(descriptor) {
6441
5689
  }
6442
5690
 
6443
5691
  // src/runtime/primitives/prompt.tsx
6444
- import { Fragment as Fragment17, jsx as jsx20 } from "react/jsx-runtime";
5692
+ import { Fragment as Fragment16, jsx as jsx17 } from "react/jsx-runtime";
6445
5693
  function PromptRoot(props) {
6446
- return /* @__PURE__ */ jsx20(InteractionRoot, { ...props });
5694
+ return /* @__PURE__ */ jsx17(InteractionRoot, { ...props });
6447
5695
  }
6448
5696
  function PromptTitle(props) {
6449
5697
  const { descriptor } = useInteractionPrimitiveContext();
6450
5698
  const context = descriptor?.kind === "prompt" ? descriptor.context : void 0;
6451
- return /* @__PURE__ */ jsx20(InteractionLabel, { ...props, children: props.children ?? context?.title ?? (descriptor ? interactionLabel(descriptor) : void 0) });
5699
+ return /* @__PURE__ */ jsx17(InteractionLabel, { ...props, children: props.children ?? context?.title ?? (descriptor ? interactionLabel(descriptor) : void 0) });
6452
5700
  }
6453
5701
  function PromptMessage(props) {
6454
5702
  const { descriptor } = useInteractionPrimitiveContext();
6455
5703
  const context = descriptor?.kind === "prompt" ? descriptor.context : void 0;
6456
5704
  const message = props.children ?? (typeof context?.payload?.message === "string" ? context.payload.message : void 0);
6457
5705
  if (!message) return null;
6458
- return /* @__PURE__ */ jsx20(InteractionDescription, { ...props, children: message });
5706
+ return /* @__PURE__ */ jsx17(InteractionDescription, { ...props, children: message });
6459
5707
  }
6460
5708
  function PromptOption({
6461
5709
  value,
@@ -6506,7 +5754,7 @@ function PromptOption({
6506
5754
  function PromptOptions({ children }) {
6507
5755
  const { descriptor } = useInteractionPrimitiveContext();
6508
5756
  const options = descriptor?.kind === "prompt" ? descriptor.context.options ?? [] : [];
6509
- return /* @__PURE__ */ jsx20(Fragment17, { children: options.map((option) => /* @__PURE__ */ jsx20(Fragment16, { children: children(option) }, option.id)) });
5757
+ return /* @__PURE__ */ jsx17(Fragment16, { children: options.map((option) => /* @__PURE__ */ jsx17(Fragment15, { children: children(option) }, option.id)) });
6510
5758
  }
6511
5759
  function PromptDialog({
6512
5760
  prompt,
@@ -6515,18 +5763,18 @@ function PromptDialog({
6515
5763
  children
6516
5764
  }) {
6517
5765
  const lifecycle = useDialogLifecycle({ defaultOpen, onStateChange });
6518
- const renderState = useMemo18(
5766
+ const renderState = useMemo14(
6519
5767
  () => ({
6520
5768
  prompt,
6521
5769
  ...lifecycle
6522
5770
  }),
6523
5771
  [lifecycle, prompt]
6524
5772
  );
6525
- return /* @__PURE__ */ jsx20(Fragment17, { children: children(renderState) });
5773
+ return /* @__PURE__ */ jsx17(Fragment16, { children: children(renderState) });
6526
5774
  }
6527
- var PromptInboxContext = createContext11(null);
5775
+ var PromptInboxContext = createContext7(null);
6528
5776
  function usePromptInboxContext() {
6529
- const value = useContext11(PromptInboxContext);
5777
+ const value = useContext7(PromptInboxContext);
6530
5778
  if (!value) {
6531
5779
  throw new Error(
6532
5780
  "PromptInbox primitives must be rendered inside <PromptInbox.Root>."
@@ -6536,16 +5784,16 @@ function usePromptInboxContext() {
6536
5784
  }
6537
5785
  function PromptInboxRoot({ children }) {
6538
5786
  const inbox = useSeatInbox();
6539
- return /* @__PURE__ */ jsx20(PromptInboxContext.Provider, { value: { prompts: inbox.prompts }, children });
5787
+ return /* @__PURE__ */ jsx17(PromptInboxContext.Provider, { value: { prompts: inbox.prompts }, children });
6540
5788
  }
6541
5789
  function PromptInboxEmpty({ children }) {
6542
5790
  const { prompts } = usePromptInboxContext();
6543
5791
  if (prompts.length > 0) return null;
6544
- return /* @__PURE__ */ jsx20(Fragment17, { children });
5792
+ return /* @__PURE__ */ jsx17(Fragment16, { children });
6545
5793
  }
6546
5794
  function PromptInboxItems({ children }) {
6547
5795
  const { prompts } = usePromptInboxContext();
6548
- return /* @__PURE__ */ jsx20(Fragment17, { children: prompts.map((prompt) => children(prompt)) });
5796
+ return /* @__PURE__ */ jsx17(Fragment16, { children: prompts.map((prompt) => children(prompt)) });
6549
5797
  }
6550
5798
  var Prompt = {
6551
5799
  Root: PromptRoot,
@@ -6562,9 +5810,9 @@ var PromptInbox = {
6562
5810
  };
6563
5811
 
6564
5812
  // src/runtime/primitives/dice.tsx
6565
- import { createContext as createContext12, useContext as useContext12 } from "react";
6566
- import { jsx as jsx21 } from "react/jsx-runtime";
6567
- var DiceContext = createContext12(null);
5813
+ import { createContext as createContext8, useContext as useContext8 } from "react";
5814
+ import { jsx as jsx18 } from "react/jsx-runtime";
5815
+ var DiceContext = createContext8(null);
6568
5816
  function normalizeDiceState({
6569
5817
  values,
6570
5818
  count = 2
@@ -6583,10 +5831,10 @@ function normalizeDiceState({
6583
5831
  };
6584
5832
  }
6585
5833
  function DiceRoot({ values, count, children }) {
6586
- return /* @__PURE__ */ jsx21(DiceContext.Provider, { value: normalizeDiceState({ values, count }), children });
5834
+ return /* @__PURE__ */ jsx18(DiceContext.Provider, { value: normalizeDiceState({ values, count }), children });
6587
5835
  }
6588
5836
  function useDicePrimitiveContext() {
6589
- const value = useContext12(DiceContext);
5837
+ const value = useContext8(DiceContext);
6590
5838
  if (!value) {
6591
5839
  throw new Error("Dice primitives must be rendered inside <Dice.Root>.");
6592
5840
  }
@@ -6603,17 +5851,13 @@ var Dice = {
6603
5851
  export {
6604
5852
  UIRoot,
6605
5853
  UI,
6606
- usePluginSession,
6607
- RuntimeProvider,
6608
- RuntimeSemanticProjectionMarker,
6609
- usePluginState,
6610
- InteractionUiProvider,
6611
5854
  isInteractionAvailable,
6612
5855
  decodeAuthoredCardIntent,
6613
5856
  useCardIntentAdapter,
6614
5857
  useGameActionError,
6615
5858
  GameRoot,
6616
5859
  GameChrome,
5860
+ GameViewport,
6617
5861
  Game,
6618
5862
  useZonePrimitiveContext,
6619
5863
  useOptionalZonePrimitiveContext,
@@ -6671,7 +5915,6 @@ export {
6671
5915
  PlayerRosterRoot,
6672
5916
  PlayerRosterList,
6673
5917
  PlayerRosterEmpty,
6674
- PlayerRosterSwitchButton,
6675
5918
  PlayerRosterName,
6676
5919
  PlayerRosterScore,
6677
5920
  PlayerRosterBadges,
@@ -6693,4 +5936,4 @@ export {
6693
5936
  DiceValues,
6694
5937
  Dice
6695
5938
  };
6696
- //# sourceMappingURL=chunk-CZMFAS3E.js.map
5939
+ //# sourceMappingURL=chunk-WOWFONLZ.js.map